Subject: bus_dmamem question
To: None <tech-kern@netbsd.org>
From: Hans Petter Selasky <hselasky@c2i.net>
List: tech-kern
Date: 02/19/2006 19:32:38
Hi,
Can someone here help get the following BUS-DMA code right? Currently
"usb_alloc_mem()" works, but "usb_free_mem()" will cause a "uvm_fault()":
uvm_fault(0xc07b08a0, 0xcb6bd000, 0, 1) -> 0xe
kernel: page fault trap, code=0
Stopped in pid 1257.1 (modload) at 0xcbbf146c: movl 0(%ebx),%eax
struct usb_dma {
bus_dma_tag_t tag;
bus_dmamap_t map;
bus_dma_segment_t seg;
int seg_count;
} __packed;
void *
usb_alloc_mem(bus_dma_tag_t dma_tag, u_int32_t size, u_int8_t align_power)
{
caddr_t ptr = NULL;
struct usb_dma temp;
bzero(&temp, sizeof(temp));
temp.tag = dma_tag;
temp.seg_count = 1;
size += sizeof(struct usb_dma);
if(bus_dmamem_alloc(temp.tag, size, (1 << align_power), 0,
&temp.seg, 1,
&temp.seg_count, BUS_DMA_NOWAIT))
{
goto done_4;
}
if(bus_dmamem_map(temp.tag, &temp.seg, temp.seg_count, size,
&ptr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT))
{
goto done_3;
}
if(bus_dmamap_create(temp.tag, size, 1, size,
0, BUS_DMA_NOWAIT, &temp.map))
{
goto done_2;
}
if(bus_dmamap_load(temp.tag, temp.map, ptr, size, NULL,
BUS_DMA_NOWAIT))
{
goto done_1;
}
size -= sizeof(temp);
bcopy(&temp, ((u_int8_t *)ptr) + size, sizeof(temp));
return ptr;
done_1:
bus_dmamap_destroy(temp.tag, temp.map);
done_2:
bus_dmamem_unmap(temp.tag, ptr, size);
done_3:
bus_dmamem_free(temp.tag, &temp.seg, temp.seg_count);
done_4:
return NULL;
}
u_int32_t
usb_vtophys(void *ptr, u_int32_t size)
{
struct usb_dma *arg = (void *)(((u_int8_t *)ptr) + size);
return arg->seg.ds_addr;
}
void
usb_free_mem(void *ptr, u_int32_t size)
{
struct usb_dma *arg = (void *)(((u_int8_t *)ptr) + size);
bus_dmamap_unload(arg->tag, arg->map);
bus_dmamap_destroy(arg->tag, arg->map);
bus_dmamem_unmap(arg->tag, ptr, size);
bus_dmamem_free(arg->tag, &arg->seg, arg->seg_count);
return;
}
--HPS