diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/Jamfile b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/Jamfile index 847602a5eb..7fdcda3f87 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/Jamfile +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/Jamfile @@ -6,6 +6,7 @@ SubDirHdrs [ FDirName $(OBOS_TOP) src add-ons media media-add-ons lala ] ; KernelMergeObject ichaudio_driver.o : ichaudio.c + io.c : -fno-pic -Wno-unused -D_KERNEL_MODE ; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/hardware.h b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/hardware.h index 98b56c8161..97efaecd8c 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/hardware.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/hardware.h @@ -122,7 +122,6 @@ typedef struct { /* PCI Configuration Space */ -#define PCI_PCICMD 0x04 #define PCI_PCICMD_IOS 0x01 #define PCI_PCICMD_MSE 0x02 #define PCI_PCICMD_BME 0x04 diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.c b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.c index 8f6ccfa284..d01f47359e 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.c @@ -1,9 +1,9 @@ #include "lala/lala.h" #include "ichaudio.h" -status_t ichaudio_attach(drv_t *drv, void *cookie); -status_t ichaudio_powerctl(drv_t *drv, void *cookie); -status_t ichaudio_detach(drv_t *drv, void *cookie); +status_t ichaudio_attach(audio_drv_t *drv); +status_t ichaudio_powerctl(audio_drv_t *drv); +status_t ichaudio_detach(audio_drv_t *drv); id_table_t ichaudio_id_table[] = { { 0x8086, 0x7195, -1, -1, -1, -1, -1, "Intel 82443MX AC97 audio" }, @@ -38,31 +38,78 @@ driver_info_t driver_info = { status_t -ichaudio_attach(drv_t *drv, void *_cookie) +ichaudio_attach(audio_drv_t *drv) { - ichaudio_cookie *cookie = (ichaudio_cookie *)_cookie; + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + uint32 value; dprintf("ichaudio_attach\n"); + // For old ICHs enable programmed IO and busmaster access, + // for ICH4 and up enable memory mapped IO and busmaster access + value = drv->pci->read_pci_config(drv->bus, drv->device, drv->function, PCI_command, 2); + value |= PCI_PCICMD_BME | (drv->flags & TYPE_ICH4) ? PCI_PCICMD_MSE : PCI_PCICMD_IOS; + drv->pci->write_pci_config(drv->bus, drv->device, drv->function, PCI_command, 2, value); + + // get IRQ, we can compensate it later if IRQ is not available (hack!) + cookie->irq = drv->pci->read_pci_config(drv->bus, drv->device, drv->function, PCI_interrupt_line, 1); + if (cookie->irq == 0xff) cookie->irq = 0; + if (cookie->irq == 0) dprintf("ichaudio_attach: no interrupt configured\n"); + + if (drv->flags & TYPE_ICH4) { + // memory mapped access + uint32 phy_mmbar = PCI_address_memory_32_mask & drv->pci->read_pci_config(drv->bus, drv->device, drv->function, 0x18, 4); + uint32 phy_mbbar = PCI_address_memory_32_mask & drv->pci->read_pci_config(drv->bus, drv->device, drv->function, 0x1C, 4); + if (!phy_mmbar || !phy_mbbar) { + dprintf("ichaudio_attach: memory mapped io unconfigured\n"); + goto err; + } + // map into memory + cookie->area_mmbar = map_mem(&cookie->mmbar, (void *)phy_mmbar, ICH4_MMBAR_SIZE, 0, "ichaudio mmbar io"); + cookie->area_mbbar = map_mem(&cookie->mbbar, (void *)phy_mbbar, ICH4_MBBAR_SIZE, 0, "ichaudio mbbar io"); + if (cookie->area_mmbar < B_OK || cookie->area_mbbar < B_OK) { + dprintf("ichaudio_attach: mapping io into memory failed\n"); + goto err; + } + } else { + // pio access + cookie->nambar = PCI_address_io_mask & drv->pci->read_pci_config(drv->bus, drv->device, drv->function, 0x10, 4); + cookie->nabmbar = PCI_address_io_mask & drv->pci->read_pci_config(drv->bus, drv->device, drv->function, 0x14, 4); + if (!cookie->nambar || !cookie->nabmbar) { + dprintf("ichaudio_attach: io unconfiugured\n"); + goto err; + } + } + + return B_OK; + +err: + // unmap io memory + if (cookie->area_mmbar > 0) delete_area(cookie->area_mmbar); + if (cookie->area_mbbar > 0) delete_area(cookie->area_mbbar); + return B_ERROR; } status_t -ichaudio_detach(drv_t *drv, void *_cookie) +ichaudio_detach(audio_drv_t *drv) { - ichaudio_cookie *cookie = (ichaudio_cookie *)_cookie; + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; dprintf("ichaudio_detach\n"); + // unmap io memory + if (cookie->area_mmbar > 0) delete_area(cookie->area_mmbar); + if (cookie->area_mbbar > 0) delete_area(cookie->area_mbbar); return B_OK; } status_t -ichaudio_powerctl(drv_t *drv, void *_cookie) +ichaudio_powerctl(audio_drv_t *drv) { - ichaudio_cookie *cookie = (ichaudio_cookie *)_cookie; + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; return B_OK; } diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.h b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.h index 72cfacdf2b..e9e0eed62a 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/ichaudio.h @@ -1,29 +1,23 @@ #include - +#include "hardware.h" typedef struct { - const char *name; + uint32 irq; uint32 nambar; uint32 nabmbar; - uint32 irq; - uint32 type; - uint32 mmbar; // ich4 - uint32 mbbar; // ich4 - void * log_mmbar; // ich4 - void * log_mbbar; // ich4 area_id area_mmbar; // ich4 area_id area_mbbar; // ich4 - uint32 codecoffset; + void * mmbar; // ich4 + void * mbbar; // ich4 + + uint32 codecoffset; uint32 input_rate; uint32 output_rate; - pci_module_info *pci; - } ichaudio_cookie; - #define TYPE_ICH4 0x01 #define TYPE_SIS7012 0x02 diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/io.c b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/io.c new file mode 100644 index 0000000000..80d7919b93 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/io.c @@ -0,0 +1,168 @@ +/* + * BeOS Driver for Intel ICH AC'97 Link interface + * + * Copyright (C) 2002-2004, Marcus Overhagen + * + * All rights reserved. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include "debug.h" +#include "hardware.h" +#include "ichaudio.h" +#include "io.h" + +status_t ich_codec_wait(audio_drv_t *drv); + +uint8 +ich_reg_read_8(audio_drv_t *drv, int regno) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63); + if (drv->flags & TYPE_ICH4) + return *(uint8 *)((char *)cookie->mbbar + regno); + else + return drv->pci->read_io_8(cookie->nabmbar + regno); +} + +uint16 +ich_reg_read_16(audio_drv_t *drv, int regno) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63); + if (drv->flags & TYPE_ICH4) + return *(uint16 *)((char *)cookie->mbbar + regno); + else + return drv->pci->read_io_16(cookie->nabmbar + regno); +} + +uint32 +ich_reg_read_32(audio_drv_t *drv, int regno) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63); + + if (drv->flags & TYPE_ICH4) + return *(uint32 *)((char *)cookie->mbbar + regno); + else + return drv->pci->read_io_32(cookie->nabmbar + regno); +} + +void +ich_reg_write_8(audio_drv_t *drv, int regno, uint8 value) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63); + + if (drv->flags & TYPE_ICH4) + *(uint8 *)((char *)cookie->mbbar + regno) = value; + else + drv->pci->write_io_8(cookie->nabmbar + regno, value); +} + +void +ich_reg_write_16(audio_drv_t *drv, int regno, uint16 value) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63); + + if (drv->flags & TYPE_ICH4) + *(uint16 *)((char *)cookie->mbbar + regno) = value; + else + drv->pci->write_io_16(cookie->nabmbar + regno, value); +} + +void +ich_reg_write_32(audio_drv_t *drv, int regno, uint32 value) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63); + + if (drv->flags & TYPE_ICH4) + *(uint32 *)((char *)cookie->mbbar + regno) = value; + else + drv->pci->write_io_32(cookie->nabmbar + regno, value); +} + +status_t +ich_codec_wait(audio_drv_t *drv) +{ + int i; + for (i = 0; i < 1100; i++) { + if ((ich_reg_read_8(drv, ICH_REG_ACC_SEMA) & 0x01) == 0) + return B_OK; + if (i > 100) + snooze(1); + } + return B_TIMED_OUT; +} + +uint16 +ich_codec_read(audio_drv_t *drv, int regno) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT((regno & 1) == 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255); + + if (regno == 0x54) // intel uses 0x54 for GPIO access, we filter it! + return 0; + if (B_OK != ich_codec_wait(drv)) + PRINT(("semaphore timeout reading register %#x\n", regno)); + if (drv->flags & TYPE_ICH4) + return *(uint16 *)(((char *)cookie->mmbar) + regno); + else + return drv->pci->read_io_16(cookie->nambar + regno); +} + +void +ich_codec_write(audio_drv_t *drv, int regno, uint16 value) +{ + ichaudio_cookie *cookie = (ichaudio_cookie *)drv->cookie; + + ASSERT(regno >= 0); + ASSERT((regno & 1) == 0); + ASSERT(((drv->flags & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255); + + if (regno == 0x54) // intel uses 0x54 for GPIO access, we filter it! + return; + if (B_OK != ich_codec_wait(drv)) + PRINT(("semaphore timeout writing register %#x\n", regno)); + if (drv->flags & TYPE_ICH4) + *(uint16 *)(((char *)cookie->mmbar) + regno) = value; + else + drv->pci->write_io_16(cookie->nambar + regno, value); +} diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/io.h b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/io.h new file mode 100644 index 0000000000..ee0aa51d00 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/io.h @@ -0,0 +1,44 @@ +/* + * BeOS Driver for Intel ICH AC'97 Link interface + * + * Copyright (c) 2002, Marcus Overhagen + * + * All rights reserved. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _IO_H_ +#define _IO_H_ + +#include "lala/lala.h" + +uint8 ich_reg_read_8(audio_drv_t *drv, int regno); +uint16 ich_reg_read_16(audio_drv_t *drv, int regno); +uint32 ich_reg_read_32(audio_drv_t *drv, int regno); + +void ich_reg_write_8(audio_drv_t *drv, int regno, uint8 value); +void ich_reg_write_16(audio_drv_t *drv, int regno, uint16 value); +void ich_reg_write_32(audio_drv_t *drv, int regno, uint32 value); + +uint16 ich_codec_read(audio_drv_t *drv, int regno); +void ich_codec_write(audio_drv_t *drv, int regno, uint16 value); + +#endif diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/Jamfile b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/Jamfile index 0cf8768815..1355ea5efd 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/Jamfile +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/Jamfile @@ -6,6 +6,7 @@ SubDir OBOS_TOP src add-ons kernel drivers audio ac97 ichaudio lala ; KernelMergeObject lala.o : driver.c + util.c : -fno-pic -D_KERNEL_MODE ; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/driver.c b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/driver.c index ed8eedb6ed..26cf0a5ebc 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/driver.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/driver.c @@ -9,14 +9,14 @@ #include "lala.h" -int32 api_version = B_CUR_DRIVER_API_VERSION; - #define MAX_DEVICES 8 -sem_id drv_sem; -char * drv_path[MAX_DEVICES + 1]; -drv_t * drv_data[MAX_DEVICES]; -int drv_count; +int32 api_version = B_CUR_DRIVER_API_VERSION; + +sem_id drv_sem; +char * drv_path[MAX_DEVICES + 1]; +audio_drv_t * drv_data[MAX_DEVICES]; +int drv_count; pci_module_info *pcimodule; @@ -40,7 +40,7 @@ init_driver(void) dprintf("init_driver\n"); dprintf("driver base name '%s'\n", driver_info.basename); - if (get_module(B_PCI_MODULE_NAME,(module_info **)&pcimodule) < 0) { + if (get_module(B_PCI_MODULE_NAME, (module_info **) &pcimodule) < 0) { return B_ERROR; } @@ -76,7 +76,7 @@ init_driver(void) drv_path[drv_count] = (char *) malloc(strlen(driver_info.basename) + 5); sprintf(drv_path[drv_count], "%s/%d", driver_info.basename, drv_count + 1); - drv_data[drv_count] = (drv_t *) malloc(sizeof(drv_t)); + drv_data[drv_count] = (audio_drv_t *) malloc(sizeof(audio_drv_t)); drv_data[drv_count]->pci = pcimodule; drv_data[drv_count]->bus = pciinfo->bus; drv_data[drv_count]->device = pciinfo->device; @@ -132,7 +132,7 @@ ich_open(const char *name, uint32 flags, void** cookie) if (drv_data[index]->open_count == 0) { memset(drv_data[index]->cookie, 0, driver_info.cookie_size); - res = driver_info.attach(drv_data[index], drv_data[index]->cookie); + res = driver_info.attach(drv_data[index]); drv_data[index]->open_count = (res == B_OK) ? 1 : 0; } else { res = B_OK; @@ -166,7 +166,7 @@ ich_free(void* cookie) drv_data[index]->open_count--; if (drv_data[index]->open_count == 0) - res = driver_info.detach(drv_data[index], drv_data[index]->cookie); + res = driver_info.detach(drv_data[index]); else res = B_OK; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/lala.h b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/lala.h index 6cbccc4de8..77bc699f1e 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/lala.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/lala.h @@ -15,10 +15,11 @@ typedef struct const char * name; uint32 flags; + void * cookie; + // private: int32 open_count; - void * cookie; -} drv_t; +} audio_drv_t; typedef void stream_id; typedef void control_id; @@ -35,9 +36,9 @@ typedef struct { uint32 flags; } id_table_t; -typedef status_t (*drv_attach) (drv_t *drv, void *cookie); -typedef status_t (*drv_powerctl) (drv_t *drv, void *cookie); -typedef status_t (*drv_detach) (drv_t *drv, void *cookie); +typedef status_t (*drv_attach) (audio_drv_t *drv); +typedef status_t (*drv_powerctl) (audio_drv_t *drv); +typedef status_t (*drv_detach) (audio_drv_t *drv); typedef struct { @@ -55,10 +56,17 @@ typedef struct extern driver_info_t driver_info; -stream_id create_stream(drv_t *dev, stream_info_t *info); -status_t control_stream(drv_t *dev, stream_info_t *info); +// protection is 0 for kernel only access, or B_READ_AREA, B_WRITE_AREA for user space access +area_id alloc_mem(void **virt, void **phy, size_t size, uint32 protection, const char *name); +area_id map_mem(void **virt, void *phy, size_t size, uint32 protection, const char *name); + +stream_id create_stream(audio_drv_t *dev, stream_info_t *info); +status_t control_stream(audio_drv_t *dev, stream_info_t *info); status_t delete_stream(stream_id stream); -control_id create_control_group(control_id parent, dev_t *dev); +control_id create_control_group(control_id parent, audio_drv_t *dev); control_id create_control(control_id parent, uint32 flags, void *get, void *set, const char *name); + +#define LOG(a) dprintf a +#define PRINT(a) dprintf a diff --git a/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/util.c b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/util.c new file mode 100644 index 0000000000..e7d15332ac --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/ichaudio/lala/util.c @@ -0,0 +1,99 @@ +/* + * BeOS Driver for Intel ICH AC'97 Link interface + * + * Copyright (c) 2002, Marcus Overhagen + * + * All rights reserved. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include + +//#define DEBUG 2 + +#include "lala.h" + +uint32 round_to_pagesize(uint32 size); + +uint32 round_to_pagesize(uint32 size) +{ + return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); +} + +area_id +alloc_mem(void **virt, void **phy, size_t size, uint32 protection, const char *name) +{ + physical_entry pe; + void * virtadr; + area_id areaid; + status_t rv; + + LOG(("allocating %ld bytes for %s\n", size, name)); + + size = round_to_pagesize(size); + areaid = create_area(name, &virtadr, B_ANY_KERNEL_ADDRESS, size, B_FULL_LOCK | B_CONTIGUOUS, protection); + if (areaid < B_OK) { + PRINT(("couldn't allocate area %s\n",name)); + return B_ERROR; + } + rv = get_memory_map(virtadr, size, &pe, 1); + if (rv < B_OK) { + delete_area(areaid); + PRINT(("couldn't map %s\n",name)); + return B_ERROR; + } + memset(virtadr, 0, size); + if (virt) + *virt = virtadr; + if (phy) + *phy = pe.address; + LOG(("area = %ld, size = %ld, virt = %p, phy = %p\n", areaid, size, virtadr, pe.address)); + return areaid; +} + +/* This is not the most advanced method to map physical memory for io access. + * Perhaps using B_ANY_KERNEL_ADDRESS instead of B_ANY_KERNEL_BLOCK_ADDRESS + * makes the whole offset calculation and relocation obsolete. But the code + * below does work, and I can't test if using B_ANY_KERNEL_ADDRESS also works. + */ +area_id +map_mem(void **virt, void *phy, size_t size, uint32 protection, const char *name) +{ + uint32 offset; + void *phyadr; + void *mapadr; + area_id area; + + LOG(("mapping physical address %p with %ld bytes for %s\n", phy, size, name)); + + offset = (uint32)phy & (B_PAGE_SIZE - 1); + phyadr = (char *)phy - offset; + size = round_to_pagesize(size + offset); + area = map_physical_memory(name, phyadr, size, B_ANY_KERNEL_BLOCK_ADDRESS, protection, &mapadr); + *virt = (char *)mapadr + offset; + + LOG(("physical = %p, virtual = %p, offset = %ld, phyadr = %p, mapadr = %p, size = %ld, area = 0x%08lx\n", + phy, *virt, offset, phyadr, mapadr, size, area)); + + return area; +}