PERFORCE change 129926 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Dec 1 16:16:51 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=129926
Change 129926 by hselasky at hselasky_laptop001 on 2007/12/02 00:16:43
This commit finishes change 129799 with regard to
"usb_subr.c".
The "page_cache" now holds the pointer to
the virtual buffer and "usbd_get_page" has
been updated to reflect the latest changes.
Factored out most CPU cache flush / invalidate
calls.
There is a new set of functions added that abstract
the BUS-DMA interface towards USB. The old BUS-DMA
abstraction functions were removed. The NetBSD
specific part of "usb_subr.c" has not been updated
with regard to this. TODO.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#57 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#57 (text+ko) ====
@@ -1783,6 +1783,8 @@
{
struct usbd_page *page;
+ res->buffer = USBD_ADD_BYTES(pc->buffer, offset);
+
offset += pc->page_offset_buf;
if ((offset >= pc->page_offset_end) ||
@@ -1793,7 +1795,6 @@
res->length = 0;
res->buffer = NULL;
res->physaddr = 0;
- res->page = NULL;
return;
}
/* compute destination page */
@@ -1805,9 +1806,7 @@
offset %= USB_PAGE_SIZE;
res->length = USB_PAGE_SIZE - offset;
- res->buffer = USBD_ADD_BYTES(page->buffer, offset);
res->physaddr = page->physaddr + offset;
- res->page = page;
return;
}
@@ -1831,15 +1830,11 @@
if (res.length > len) {
res.length = len;
}
- usbd_page_cpu_invalidate(res.page);
-
bcopy(ptr, res.buffer, res.length);
- usbd_page_cpu_flush(res.page);
-
offset += res.length;
len -= res.length;
- ptr = ((const uint8_t *)ptr) + res.length;
+ ptr = USBD_ADD_BYTES(ptr, res.length);
}
return;
}
@@ -1898,16 +1893,12 @@
if (res.length > len) {
res.length = len;
}
- usbd_page_cpu_invalidate(res.page);
-
/*
* "uiomove()" can sleep so one needs to make a wrapper,
* exiting the mutex and checking things
*/
error = uiomove(res.buffer, len, uio);
- usbd_page_cpu_flush(res.page);
-
if (error) {
break;
}
@@ -1937,12 +1928,8 @@
if (res.length > len) {
res.length = len;
}
- usbd_page_cpu_invalidate(res.page);
-
bcopy(res.buffer, ptr, res.length);
- usbd_page_cpu_flush(res.page);
-
offset += res.length;
len -= res.length;
ptr = USBD_ADD_BYTES(ptr, res.length);
@@ -1969,480 +1956,283 @@
if (res.length > len) {
res.length = len;
}
- usbd_page_cpu_invalidate(res.page);
-
bzero(res.buffer, res.length);
- usbd_page_cpu_flush(res.page);
-
offset += res.length;
len -= res.length;
}
return;
}
+#ifdef __FreeBSD__
+
/*------------------------------------------------------------------------*
- * usbd_page_alloc - allocate multiple DMA-able memory pages
+ * usbd_pc_tag_create - allocate a DMA tag
*
- * Returns:
- * 1: failure
- * 0: success
+ * NOTE: If the "align" parameter has a value of 1 the DMA-tag will
+ * allow multi-segment mappings. Else all mappings are single-segment.
*------------------------------------------------------------------------*/
-uint8_t
-usbd_page_alloc(bus_dma_tag_t tag, struct usbd_page *page,
- uint32_t npages)
+bus_dma_tag_t
+usbd_dma_tag_create(bus_dma_tag_t tag_parent, uint32_t size, uint32_t align)
{
- uint32_t x;
- void *ptr;
+ bus_dma_tag_t tag;
- for (x = 0; x < npages; x++) {
-
-repeat:
-
- ptr = usbd_mem_alloc_sub(tag, page + x,
- USB_PAGE_SIZE, USB_PAGE_SIZE);
- if (ptr == NULL) {
-
- while (x--) {
- usbd_mem_free_sub(page + x);
- }
- return (1); /* failure */
- } else {
-
- if ((page + x)->physaddr == 0) {
-
- /*
- * at least the OHCI controller gives
- * special meaning to physaddr == 0, so
- * discard that page if it gets here:
- */
- printf("%s:%d: Discarded memory "
- "page with physaddr=0!\n",
- __FUNCTION__, __LINE__);
- goto repeat;
- }
- }
+ if (bus_dma_tag_create
+ ( /* parent */ tag_parent,
+ /* alignment */ align,
+ /* boundary */ 0,
+ /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
+ /* highaddr */ BUS_SPACE_MAXADDR,
+ /* filter */ NULL,
+ /* filterarg */ NULL,
+ /* maxsize */ size,
+ /* nsegments */ (align == 1) ?
+ (2 + (size / USB_PAGE_SIZE)) : 1,
+ /* maxsegsz */ USB_PAGE_SIZE,
+ /* flags */ 0,
+ /* lock */ NULL,
+ /* */ NULL,
+ &tag)) {
+ tag = NULL;
}
- return (0); /* success */
+ return (tag);
}
/*------------------------------------------------------------------------*
- * usbd_page_free - free multiple DMA-able memory pages
+ * usbd_dma_tag_free - free a DMA tag
*------------------------------------------------------------------------*/
void
-usbd_page_free(struct usbd_page *page, uint32_t npages)
+usbd_dma_tag_destroy(bus_dma_tag_t tag)
{
- while (npages--) {
- usbd_mem_free_sub(page + npages);
- }
+ bus_dma_tag_destroy(tag);
return;
}
/*------------------------------------------------------------------------*
- * usbd_page_cache_init
+ * usbd_pc_alloc_mem_cb
*------------------------------------------------------------------------*/
-void
-usbd_page_cache_init(struct usbd_page_cache *pc, struct usbd_page *page_ptr,
- uint32_t offset, uint32_t size)
+static void
+usbd_pc_alloc_mem_cb(void *arg, bus_dma_segment_t *segs,
+ int nseg, int error)
{
- pc->page_start = page_ptr + (offset / USB_PAGE_SIZE);
- pc->page_offset_buf = (offset % USB_PAGE_SIZE);
- pc->page_offset_end = pc->page_offset_buf + size;
- return;
-}
+ struct usbd_xfer *xfer;
+ struct usbd_page_cache *pc;
+ struct usbd_page *pg;
+ uint32_t rem;
-/*------------------------------------------------------------------------*
- * usbd_page_fit_obj - fit object function
- *------------------------------------------------------------------------*/
-uint32_t
-usbd_page_fit_obj(uint32_t size, uint32_t obj_len)
-{
- uint32_t adj;
+ xfer = pc->xfer;
- if (obj_len > (USB_PAGE_SIZE - (size & (USB_PAGE_SIZE - 1)))) {
+ /* XXX sometimes recursive locking here */
- if (obj_len > USB_PAGE_SIZE) {
- panic("%s:%d Too large object, %d bytes, will "
- "not fit on a USB page, %d bytes!\n",
- __FUNCTION__, __LINE__, obj_len,
- (int32_t)USB_PAGE_SIZE);
+ if (error) {
+ if (xfer) {
+ mtx_lock(xfer->priv_mtx);
+ xfer->usb_root->dma_error = 1;
+ usbd_bdma_done_event(xfer->usb_root);
+ mtx_unlock(xfer->priv_mtx);
}
- /*
- * adjust offset to the beginning of the next page:
- */
- adj = ((-size) & (USB_PAGE_SIZE - 1));
- } else {
- adj = 0;
+ return;
}
- return (adj);
-}
+ pc = arg;
+ pg = pc->page_start;
+ pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
+ rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
+ pc->page_offset_buf = rem;
+ pc->page_offset_end += rem;
+ nseg--;
-/*------------------------------------------------------------------------*
- * usbd_mem_alloc - allocate DMA-able memory
- *------------------------------------------------------------------------*/
-void *
-usbd_mem_alloc(bus_dma_tag_t parent, struct usbd_page *page, uint32_t size,
- uint8_t align_power)
-{
- bus_dma_tag_t tag;
- uint32_t alignment = (1 << align_power);
- void *ptr;
-
- tag = usbd_dma_tag_alloc(parent, size, alignment, size, 1);
-
- if (tag == NULL) {
- return (NULL);
+ while (nseg > 0) {
+ nseg--;
+ segs++;
+ pg++;
+ pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
}
- ptr = usbd_mem_alloc_sub(tag, page, size, alignment);
- if (ptr == NULL) {
- usbd_dma_tag_free(tag);
- return (NULL);
+ if (xfer) {
+ mtx_lock(xfer->priv_mtx);
+ usbd_bdma_done_event(xfer->usb_root);
+ mtx_unlock(xfer->priv_mtx);
}
- return (ptr);
-}
-
-/*------------------------------------------------------------------------*
- * usbd_mem_free - free DMA-able memory
- *------------------------------------------------------------------------*/
-void
-usbd_mem_free(struct usbd_page *page)
-{
- bus_dma_tag_t tag;
-
- tag = page->tag;
-
- usbd_mem_free_sub(page);
-
- usbd_dma_tag_free(tag);
-
return;
}
-#ifdef __FreeBSD__
/*------------------------------------------------------------------------*
- * bus_dmamap_load_callback
+ * usbd_pc_alloc_mem - allocate DMA'able memory
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
*------------------------------------------------------------------------*/
-static void
-bus_dmamap_load_callback(void *arg, bus_dma_segment_t *segs,
- int nseg, int error)
-{
- __KASSERT(nseg == 1, ("Invalid number of segments, %d!\n", nseg));
- __KASSERT(error == 0, ("Could not load memory into DMA!\n"));
-
- *((bus_size_t *)arg) = segs->ds_addr;
-
- return;
-}
-
-/*------------------------------------------------------------------------*
- * usbd_dma_tag_alloc - allocate a bus-DMA tag
- *------------------------------------------------------------------------*/
-bus_dma_tag_t
-usbd_dma_tag_alloc(bus_dma_tag_t parent, uint32_t seg_size,
- uint32_t alignment, uint32_t max_size, uint8_t single_seg)
+uint8_t
+usbd_pc_alloc_mem(bus_dma_tag_t parent_tag, struct usbd_dma_tag *utag,
+ struct usbd_page_cache *pc, struct usbd_page *pg, uint32_t size,
+ uint32_t align, uint8_t utag_max)
{
bus_dma_tag_t tag;
-
- if (bus_dma_tag_create
- ( /* parent */ parent,
- /* alignment */ alignment,
- /* boundary */ 0,
- /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
- /* highaddr */ BUS_SPACE_MAXADDR,
- /* filter */ NULL,
- /* filterarg */ NULL,
- /* maxsize */ max_size,
- /* nsegments */ (single_seg ? 1 : ((16 * 1024 * 1024) / USB_PAGE_SIZE)),
- /* maxsegsz */ seg_size,
- /* flags */ 0,
- /* lock */ NULL,
- /* */ NULL,
- &tag)) {
- tag = NULL;
- }
- return (tag);
-}
-
-/*------------------------------------------------------------------------*
- * usbd_dma_tag_free - free a bus-DMA tag
- *------------------------------------------------------------------------*/
-void
-usbd_dma_tag_free(bus_dma_tag_t tag)
-{
- bus_dma_tag_destroy(tag);
- return;
-}
-
-/*------------------------------------------------------------------------*
- * usbd_mem_alloc_sub - allocate DMA-able memory
- *------------------------------------------------------------------------*/
-void *
-usbd_mem_alloc_sub(bus_dma_tag_t tag, struct usbd_page *page,
- uint32_t size, uint32_t alignment)
-{
bus_dmamap_t map;
- bus_size_t physaddr = 0;
void *ptr;
+ /* get the correct DMA tag */
+ tag = usbd_dma_tag_setup(parent_tag, utag, size, align, utag_max);
+ if (tag == NULL) {
+ goto error;
+ }
+ /* allocate memory */
if (bus_dmamem_alloc
(tag, &ptr, (BUS_DMA_WAITOK | BUS_DMA_COHERENT), &map)) {
- return (NULL);
+ goto error;
}
+ /* setup page cache */
+ pc->buffer = ptr;
+ pc->page_start = pg;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+ pc->map = map;
+ pc->tag = tag;
+
+ /* load memory into DMA */
if (bus_dmamap_load
- (tag, map, ptr, size, &bus_dmamap_load_callback,
- &physaddr, (BUS_DMA_WAITOK | BUS_DMA_COHERENT))) {
+ (tag, map, ptr, size, &usbd_pc_alloc_mem_cb,
+ pc, (BUS_DMA_WAITOK | BUS_DMA_COHERENT))) {
bus_dmamem_free(tag, ptr, map);
- return (NULL);
+ goto error;
}
- page->tag = tag;
- page->map = map;
- page->physaddr = physaddr;
- page->buffer = ptr;
- page->length = size;
+ bzero(ptr, size);
+
+ usbd_pc_cpu_flush(pc);
- usbd_page_cpu_invalidate(page);
- bzero(ptr, size);
- usbd_page_cpu_flush(page);
+ return (0);
-#ifdef USB_DEBUG
- if (usbdebug > 14) {
- printf("%s: %p, %d bytes, phys=%p\n",
- __FUNCTION__, ptr, size,
- ((char *)0) + physaddr);
- }
-#endif
- return (ptr);
+error:
+ /* reset most of the page cache */
+ pc->buffer = NULL;
+ pc->page_start = NULL;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = 0;
+ pc->map = NULL;
+ pc->tag = NULL;
+ return (1);
}
/*------------------------------------------------------------------------*
- * usbd_mem_free_sub - free DMA-able memory
+ * usbd_pc_free_mem - free DMA memory
+ *
+ * This function is NULL safe.
*------------------------------------------------------------------------*/
void
-usbd_mem_free_sub(struct usbd_page *page)
+usbd_pc_free_mem(struct usbd_page_cache *pc)
{
- /*
- * NOTE: make a copy of "tag", "map", and "buffer" in case "page" is
- * part of the allocated memory:
- */
- bus_dma_tag_t tag = page->tag;
- bus_dmamap_t map = page->map;
- void *ptr = page->buffer;
+ if (pc && pc->buffer) {
- bus_dmamap_unload(tag, map);
+ bus_dmamap_unload(pc->tag, pc->map);
- bus_dmamem_free(tag, ptr, map);
+ bus_dmamem_free(pc->tag, pc->buffer, pc->map);
-#ifdef USB_DEBUG
- if (usbdebug > 14) {
- printf("%s: %p\n",
- __FUNCTION__, ptr);
+ pc->buffer = NULL;
}
-#endif
return;
}
/*------------------------------------------------------------------------*
- * usbd_dma_load_setup - allocate BUS-DMA maps
+ * usbd_pc_load_mem - load virtual memory into DMA
*------------------------------------------------------------------------*/
void
-usbd_dma_load_setup(struct usbd_setup_params *parm)
+usbd_pc_load_mem(struct usbd_page_cache *pc, uint32_t size)
{
- struct usbd_xfer *xfer;
-
- if (parm->buf == NULL) {
+ /* sanity check */
+ if (pc->xfer == NULL) {
+ panic("This page cache is not loadable!\n");
return;
}
- xfer = parm->curr_xfer;
+ /* setup page cache */
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+
+ if (size > 0) {
- if (bus_dmamap_create(xfer->udev->bus->dma_tag_1b, 0,
- &(xfer->dma_tx_map))) {
- xfer->dma_tx_map = NULL;
- parm->err = USBD_NOMEM;
- return;
- }
- if (bus_dmamap_create(xfer->udev->bus->dma_tag_1b, 0,
- &(xfer->dma_rx_map))) {
- xfer->dma_rx_map = NULL;
- parm->err = USBD_NOMEM;
- return;
- }
- return;
-}
+ pc->xfer->usb_root->dma_refcount++;
-/*------------------------------------------------------------------------*
- * usbd_dma_load_unsetup - release BUS-DMA maps
- *------------------------------------------------------------------------*/
-void
-usbd_dma_load_unsetup(struct usbd_xfer *xfer)
-{
- if (xfer->dma_tx_map) {
- bus_dmamap_destroy(xfer->udev->bus->dma_tag_1b,
- xfer->dma_tx_map);
+ /* try to load memory into DMA */
+ if (bus_dmamap_load(
+ pc->tag, pc->map, pc->buffer, size,
+ &usbd_pc_alloc_mem_cb, pc, 0)) {
+ }
}
- if (xfer->dma_rx_map) {
- bus_dmamap_destroy(xfer->udev->bus->dma_tag_1b,
- xfer->dma_rx_map);
- }
return;
}
/*------------------------------------------------------------------------*
- * usbd_dma_load_pre_sync - flush CPU cache, if any
+ * usbd_pc_cpu_invalidate - invalidate CPU cache
*------------------------------------------------------------------------*/
void
-usbd_dma_load_pre_sync(struct usbd_xfer *xfer)
+usbd_pc_cpu_invalidate(struct usbd_page_cache *pc)
{
- bus_dmamap_sync(xfer->udev->bus->dma_tag_1b, xfer->dma_tx_map,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- return;
-}
-
-/*------------------------------------------------------------------------*
- * usbd_dma_load_post_sync - invalidate CPU cache, if any
- *------------------------------------------------------------------------*/
-void
-usbd_dma_load_post_sync(struct usbd_xfer *xfer)
-{
- bus_dmamap_sync(xfer->udev->bus->dma_tag_1b, xfer->dma_rx_map,
+ bus_dmamap_sync(pc->tag, pc->map,
BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
return;
}
/*------------------------------------------------------------------------*
- * usbd_page_cpu_invalidate - invalidate CPU cache
+ * usbd_pc_cpu_flush - flush CPU cache
*------------------------------------------------------------------------*/
void
-usbd_page_cpu_invalidate(struct usbd_page *page)
+usbd_pc_cpu_flush(struct usbd_page_cache *pc)
{
- bus_dmamap_sync(page->tag, page->map,
- BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
- return;
-}
-
-/*------------------------------------------------------------------------*
- * usbd_page_cpu_flush - flush CPU cache
- *------------------------------------------------------------------------*/
-void
-usbd_page_cpu_flush(struct usbd_page *page)
-{
- bus_dmamap_sync(page->tag, page->map,
+ bus_dmamap_sync(pc->tag, pc->map,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return;
}
/*------------------------------------------------------------------------*
- * usbd_dma_load_mem_callback - internal callback
+ * usbd_pc_dmamap_create
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
*------------------------------------------------------------------------*/
-static void
-usbd_dma_load_mem_callback(void *arg, bus_dma_segment_t *segs,
- int nseg, int error)
+uint8_t
+usbd_pc_dmamap_create(struct usbd_page_cache *pc, uint32_t size)
{
- struct usbd_page_cache *pc;
- struct usbd_xfer *xfer;
- struct usbd_page *pg;
- uint32_t rem;
+ struct usbd_memory_info *info;
+ bus_dma_tag_t tag;
- pc = arg;
- xfer = pc->p_xfer;
+ /* sanity check */
+ if (pc->xfer == NULL) {
+ goto error;
+ }
+ info = pc->xfer->usb_root;
+ tag = pc->xfer->udev->bus->dma_tag_parent;
- /* XXX sometimes recursive locking here */
-
- mtx_lock(xfer->priv_mtx);
-
- if (error) {
- printf("%s: %s: error=%d\n",
- __FILE__, __FUNCTION__, error);
-
- xfer->flags_int.bdma_error = 1;
- } else {
- __KASSERT(nseg > 0, ("Invalid number of segments!\n"));
-
- pg = pc->page_start;
- rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
-
- pc->page_offset_buf += rem;
- pc->page_offset_end += rem;
-
- pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
-
- while (1) {
-
- if (--nseg == 0) {
- break;
- }
- pg++;
- segs++;
- pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
- }
+ tag = usbd_dma_tag_setup(tag, info->dma_tag_p,
+ size, 1, info->dma_tag_max);
+ if (tag == NULL) {
+ goto error;
+ }
+ if (bus_dmamap_create(tag, 0, &(pc->map))) {
+ goto error;
}
+ pc->tag = tag;
+ return 0; /* success */
- usbd_bdma_done_event(xfer);
-
- mtx_unlock(xfer->priv_mtx);
- return;
+error:
+ pc->map = NULL;
+ pc->tag = NULL;
+ return 1; /* failure */
}
/*------------------------------------------------------------------------*
- * usbd_dma_load_mem - load DMA memory if any
+ * usbd_pc_dmamap_destroy
+ *
+ * This function is NULL safe.
*------------------------------------------------------------------------*/
void
-usbd_dma_load_mem(struct usbd_xfer *xfer, struct usbd_dma_load_mem_info *info)
+usbd_pc_dmamap_destroy(struct usbd_page_cache *pc)
{
- struct usbd_page_cache *pc;
- struct usbd_page *pg;
- bus_dma_tag_t dma_tag;
- bus_dmamap_t dma_map;
- uint32_t npg;
- int error;
-
- pc = info->page_cache;
-
- if (info->frame_length == 0) {
- /* not used */
- pc->page_start = NULL;
- pc->page_offset_buf = 0;
- pc->page_offset_end = 0;
- return;
- }
- /* select the one byte alignment DMA tag */
-
- dma_tag = xfer->udev->bus->dma_tag_1b;
- if (pc->isread) {
- dma_map = xfer->dma_rx_map;
- } else {
- dma_map = xfer->dma_tx_map;
+ if (pc && pc->tag) {
+ bus_dmamap_destroy(pc->tag, pc->map);
+ pc->tag = NULL;
+ pc->map = NULL;
}
-
- /* increment refcount */
-
- xfer->dma_refcount++;
-
- /* initialize the "usbd_page_cache" structure */
-
- pc->page_start = info->page_ptr;
- pc->page_offset_buf = 0;
- pc->page_offset_end = info->frame_length;
-
- /* initialize the "usbd_page" structure */
-
- npg = (info->frame_length / USB_PAGE_SIZE) + 2;
- pg = info->page_ptr;
-
- while (npg--) {
- pg->tag = dma_tag;
- pg->map = dma_map;
- pg->length = USB_PAGE_SIZE;
- pg++;
- }
-
- /* update "page_ptr" to the next pointer value */
-
- info->page_ptr = pg;
-
- error = bus_dmamap_load(dma_tag, dma_map, pc->p_buffer,
- info->frame_length, usbd_dma_load_mem_callback, pc, 0);
-
return;
}
@@ -2496,9 +2286,7 @@
page->length = size;
usbd_page_cpu_invalidate(page);
-
bzero(ptr, size);
-
usbd_page_cpu_flush(page);
#ifdef USB_DEBUG
@@ -2547,23 +2335,31 @@
}
/*------------------------------------------------------------------------*
- * usbd_page_cpu_invalidate - invalidate CPU cache
+ * usbd_pc_cpu_invalidate - invalidate CPU cache
*------------------------------------------------------------------------*/
void
-usbd_page_cpu_invalidate(struct usbd_page *page)
+usbd_pc_cpu_invalidate(struct usbd_page_cache *pc)
{
- bus_dmamap_sync(page->tag, page->map, 0, page->length,
+ uint32_t len;
+
+ len = pc->page_offset_end - pc->page_offset_buf;
+
+ bus_dmamap_sync(pc->tag, pc->map, 0, len,
BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
return;
}
/*------------------------------------------------------------------------*
- * usbd_page_cpu_flush - flush CPU cache
+ * usbd_pc_cpu_flush - flush CPU cache
*------------------------------------------------------------------------*/
void
-usbd_page_cpu_flush(struct usbd_page *page)
+usbd_pc_cpu_flush(struct usbd_page_cache *pc)
{
- bus_dmamap_sync(page->tag, page->map, 0, page->length,
+ uint32_t len;
+
+ len = pc->page_offset_end - pc->page_offset_buf;
+
+ bus_dmamap_sync(page->tag, page->map, 0, len,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return;
}
@@ -2571,59 +2367,6 @@
#endif
/*------------------------------------------------------------------------*
- * usbd_pio_load_mem - load virtual memory if any
- *------------------------------------------------------------------------*/
-void
-usbd_pio_load_mem(struct usbd_xfer *xfer, struct usbd_dma_load_mem_info *info)
-{
- struct usbd_page_cache *pc;
- struct usbd_page *pg;
- uint32_t npg;
- uint32_t rem;
- uint8_t *ptr;
-
- pc = info->page_cache;
- pg = info->page_ptr;
-
- if (info->frame_length == 0) {
- /* not used */
- pc->page_start = NULL;
- pc->page_offset_buf = 0;
- pc->page_offset_end = 0;
- return;
- }
- ptr = pc->p_buffer;
- rem = POINTER_TO_UNSIGNED(ptr) & (USB_PAGE_SIZE - 1);
- ptr -= rem; /* page align */
- info->frame_length += rem; /* adjust */
-
- pc->page_start = pg;
- pc->page_offset_buf = rem;
- pc->page_offset_end = info->frame_length;
-
- npg = (info->frame_length + (USB_PAGE_SIZE - 1)) / USB_PAGE_SIZE;
-
- while (npg--) {
-
- /*
- * NOTE: We only setup the fields
- * we need for PIO in "struct usbd_page"
- */
- pg->buffer = ptr;
- pg->length = USB_PAGE_SIZE;
-
- ptr += USB_PAGE_SIZE;
- pg++;
- }
-
- /* update page pointer */
-
- info->page_ptr = pg;
-
- return;
-}
-
-/*------------------------------------------------------------------------*
* usbd_make_str_desc - convert an ASCII string into a UNICODE string
*------------------------------------------------------------------------*/
uint8_t
@@ -3121,64 +2864,172 @@
}
/*------------------------------------------------------------------------*
- * usbd_bus_mem_setup - factored out code
- *
- * Return:
- * 0: Success
- * Else: Failure
+ * usbd_bus_tag_setup - factored out code
*------------------------------------------------------------------------*/
-uint8_t
-usbd_bus_mem_setup(struct usbd_bus *bus, bus_dma_tag_t parent_tag,
- uint32_t hw_mem_size, uint8_t hw_addr_lines, uint8_t hw_align_power)
+bus_dma_tag_t
+usbd_dma_tag_setup(bus_dma_tag_t tag_parent, struct usbd_dma_tag *udt,
+ uint32_t size, uint32_t align, uint8_t nudt)
{
+ __KASSERT(align > 0, ("Invalid parameter align = 0!\n"));
+ __KASSERT(size > 0, ("Invalid parameter size = 0!\n"));
+
+ while (nudt--) {
- if (hw_mem_size > 0) {
+ if (udt->align == 0) {
+ udt->tag =
+ usbd_dma_tag_create(tag_parent, size, align);
+ if (udt->tag == NULL) {
+ return (NULL);
+ }
+ udt->align = align;
+ udt->size = size;
+ return (udt->tag);
+ }
+ if ((udt->align == align) && (udt->size == size)) {
+ return (udt->tag);
+ }
+ udt++;
+ }
+ return (NULL);
+}
- bus->hw_ptr.data =
- usbd_mem_alloc(parent_tag, &(bus->hw_page),
- hw_mem_size, hw_align_power);
+/*------------------------------------------------------------------------*
+ * usbd_bus_tag_unsetup - factored out code
+ *------------------------------------------------------------------------*/
+void
+usbd_dma_tag_unsetup(struct usbd_dma_tag *udt, uint8_t nudt)
+{
+ while (nudt--) {
- if (bus->hw_ptr.data == NULL) {
- goto error;
+ if (udt->align) {
+ usbd_dma_tag_destroy(udt->tag);
+ udt->align = 0;
}
+ udt++;
}
- bus->dma_tag_1b =
- usbd_dma_tag_alloc(parent_tag, USB_PAGE_SIZE, 1, 0 - 1, 0);
+ return;
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_bus_mem_flush_all_cb
+ *------------------------------------------------------------------------*/
+static void
+usbd_bus_mem_flush_all_cb(struct usbd_bus *bus, struct usbd_page_cache *pc,
+ struct usbd_page *pg, uint32_t size, uint32_t align)
+{
+ usbd_pc_cpu_flush(pc);
+ return;
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_bus_mem_flush_all - factored out code
+ *------------------------------------------------------------------------*/
+void
+usbd_bus_mem_flush_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb)
+{
+ cb(bus, &usbd_bus_mem_flush_all_cb);
+ return;
+}
- if (bus->dma_tag_1b == NULL) {
- goto error;
+/*------------------------------------------------------------------------*
+ * usbd_bus_mem_alloc_all_cb
+ *------------------------------------------------------------------------*/
+static void
+usbd_bus_mem_alloc_all_cb(struct usbd_bus *bus, struct usbd_page_cache *pc,
+ struct usbd_page *pg, uint32_t size, uint32_t align)
+{
+ if (usbd_pc_alloc_mem(bus->dma_tag_parent,
+ bus->dma_tags, pc, pg, size, align,
+ USB_BUS_DMA_TAG_MAX)) {
+ bus->alloc_failed = 1;
}
- bus->dma_tag_ps =
- usbd_dma_tag_alloc(parent_tag, USB_PAGE_SIZE,
- USB_PAGE_SIZE, USB_PAGE_SIZE, 1);
+ return;
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_bus_mem_alloc_all - factored out code
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usbd_bus_mem_alloc_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb)
+{
+ bus->alloc_failed = 0;
+
+ cb(bus, &usbd_bus_mem_alloc_all_cb);
- if (bus->dma_tag_ps == NULL) {
- goto error;
+ if (bus->alloc_failed) {
+ usbd_bus_mem_free_all(bus, cb);
}
- return (0);
+ return (bus->alloc_failed);
+}
-error:
- usbd_bus_mem_unsetup(bus);
- return (1);
+/*------------------------------------------------------------------------*
+ * usbd_bus_mem_free_all_cb
+ *------------------------------------------------------------------------*/
+static void
+usbd_bus_mem_free_all_cb(struct usbd_bus *bus, struct usbd_page_cache *pc,
+ struct usbd_page *pg, uint32_t size, uint32_t align)
+{
+ usbd_pc_free_mem(pc);
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list