Date: Sun, 2 Dec 2007 00:16:50 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 129926 for review Message-ID: <200712020016.lB20GoED004485@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=129926 Change 129926 by hselasky@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) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712020016.lB20GoED004485>
