Date: Sun, 2 Dec 2007 00:11:45 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 129925 for review Message-ID: <200712020011.lB20BjmN003859@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=129925 Change 129925 by hselasky@hselasky_laptop001 on 2007/12/02 00:11:06 This commit finishes change 129799 with regard to "usb_subr.h". The USBD_BDMA state has been removed, hence I was able to simplify the statemachine. New bus method "xfer_unsetup". Currently unused. Struct "usbd_page" has been simplified to only contain the physical address. Struct "usbd_page_cache" now contains the BUS-DMA "tag" and "map". New structure "usbd_dma_tag" which is used to cache DMA-tags. "buf_data" field in "struct usbd_xfer" was replaced by "frbuffers + 0". Some new prototypes. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#62 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#62 (text+ko) ==== @@ -73,8 +73,14 @@ #define USBD_GET_STATE(xfer) ((xfer)->usb_state) #define USBD_GET_DATA_ISREAD(xfer) ((xfer)->flags_int.is_dci ? \ -((xfer->endpoint & UE_DIR_IN) ? 0 : 1) : \ - ((xfer->endpoint & UE_DIR_IN) ? 1 : 0)) + ((xfer->endpoint & UE_DIR_IN) ? 0 : 1) : \ + ((xfer->endpoint & UE_DIR_IN) ? 1 : 0)) + +#undef LIST_PREV +#define LIST_PREV(head,elm,field) \ + (((elm) == LIST_FIRST(head)) ? ((__typeof(elm))0) : \ + ((__typeof(elm))(((uint8_t *)((elm)->field.le_prev)) - \ + ((uint8_t *)&LIST_NEXT((__typeof(elm))0,field))))) /* USB transfer states */ @@ -84,20 +90,6 @@ USBD_ST_ERROR, }; -/* - * USB BUS-DMA transfer states - * - * Hence the BUS-DMA framework does not support DMA load abort we need - * to keep track of the BUS-DMA state in the USB transfer. - */ - -enum { - USBD_BDMA_ST_IDLE, - USBD_BDMA_ST_LOADING, - USBD_BDMA_ST_CANCELLING, - USBD_BDMA_ST_CANCEL_AND_LOAD, -}; - struct usbd_xfer; struct usbd_pipe; struct usbd_bus; @@ -115,9 +107,6 @@ struct proc; struct usb_device; /* Linux compat */ struct cdev; -struct ehci_hw_softc; -struct uhci_hw_softc; -struct ohci_hw_softc; typedef uint8_t usbd_status; @@ -139,6 +128,7 @@ void (*pipe_init) (struct usbd_device *udev, usb_endpoint_descriptor_t *edesc, struct usbd_pipe *pipe); void (*do_poll) (struct usbd_bus *); void (*xfer_setup) (struct usbd_setup_params *parm); + void (*xfer_unsetup) (struct usbd_xfer *xfer); }; struct usbd_pipe_methods { @@ -183,8 +173,16 @@ }; struct usbd_page { + bus_size_t physaddr; +}; + +struct usbd_page_search { void *buffer; bus_size_t physaddr; + uint32_t length; +}; + +struct usbd_page_cache { #ifdef __FreeBSD__ bus_dma_tag_t tag; @@ -192,72 +190,62 @@ #endif #ifdef __NetBSD__ + bus_dma_segment_t seg; bus_dma_tag_t tag; bus_dmamap_t map; - bus_dma_segment_t seg; int32_t seg_count; #endif - uint32_t length; -}; - -struct usbd_page_search { - void *buffer; - struct usbd_page *page; - bus_size_t physaddr; - uint32_t length; -}; - -struct usbd_page_cache { struct usbd_page *page_start; - struct usbd_xfer *p_xfer; /* this backpointer to the USB - * transfer is used when loading - * virtual buffers into DMA */ - void *p_buffer; /* virtual buffer to be loaded by - * BUS-DMA */ + struct usbd_xfer *xfer; /* if set, backpointer to USB transfer */ + void *buffer; /* virtual buffer pointer */ uint32_t page_offset_buf; uint32_t page_offset_end; uint8_t isread:1; }; struct usbd_setup_params { - struct usbd_page_cache pc; - + struct usbd_dma_tag *dma_tag_p; struct usbd_page *dma_page_ptr; - struct usbd_page *page_ptr; + struct usbd_page_cache *dma_page_cache_ptr; /* these will be + * auto-freed */ + struct usbd_page_cache *xfer_page_cache_ptr; /* these will not be + * auto-freed */ struct usbd_device *udev; struct usbd_xfer *curr_xfer; const struct usbd_config *curr_setup; const struct usbd_pipe_methods *methods; void *buf; + uint32_t *xfer_length_ptr; - uint32_t size[4]; - uint32_t total_size[3]; + uint32_t size[7]; uint32_t bufsize; + uint32_t bufsize_max; uint32_t hc_max_frame_size; uint16_t hc_max_packet_size; uint8_t hc_max_packet_count; uint8_t speed; + uint8_t dma_tag_max; usbd_status err; }; +struct usbd_dma_tag { + bus_dma_tag_t tag; + uint32_t align; + uint32_t size; +}; + +#define USB_BUS_DMA_TAG_MAX 8 + struct usbd_bus { struct usb_device_stats stats; struct mtx mtx; - struct usbd_page hw_page; + + device_t bdev; /* filled by HC driver */ - union { - struct ehci_hw_softc *ehci; - struct uhci_hw_softc *uhci; - struct ohci_hw_softc *ohci; - void *data; - } hw_ptr; + struct usbd_dma_tag dma_tags[USB_BUS_DMA_TAG_MAX]; + bus_dma_tag_t dma_tag_parent; - device_t bdev; /* filled by HC driver */ - bus_dma_tag_t dma_tag_1b; /* 1 byte aligned DMA-tag, filled by - * HC driver */ - bus_dma_tag_t dma_tag_ps; /* page size aligned DMA-tag, filled - * by HC driver */ eventhandler_tag usb_clone_tag; struct usbd_bus_methods *methods; /* filled by HC driver */ struct usbd_device *devices[USB_MAX_DEVICES]; @@ -269,6 +257,7 @@ uint16_t isoc_time_last; /* ms */ + uint8_t alloc_failed; /* Set if memory allocation failed. */ uint8_t is_exploring; uint8_t wait_explore; uint8_t needs_explore; /* Set if a hub signalled a change. @@ -385,11 +374,6 @@ uint8_t ext_buffer:1; /* uses external DMA buffer */ uint8_t manual_status:1; /* non automatic status stage on * control transfers */ - uint8_t bdma_enable:1; /* setting this flag allows you to - * load buffers directly into DMA for - * the USB transfer the flag belongs - * to. The flag can not be changed - * during operation. */ }; struct usbd_xfer_flags_int { @@ -407,11 +391,11 @@ uint8_t short_frames_ok:1; /* filtered version */ uint8_t short_xfer_ok:1; /* filtered version */ - uint8_t bdma_state:2; /* BUS-DMA state */ - uint8_t bdma_error:1; /* BUS-DMA error flag */ uint8_t bdma_enable:1; /* filtered version (only set if * hardware supports DMA) */ - uint8_t bdma_draining:1; + uint8_t bdma_no_post_sync:1; /* set if the USB callback wrapper + * should not do the BUS-DMA post sync + * operation */ uint8_t isochronous_xfr:1; /* set if isochronous transfer */ uint8_t is_dci:1; /* set if hardware is a device * controller interface */ @@ -437,17 +421,15 @@ struct usbd_xfer { struct usb_callout timeout_handle; - struct usbd_page_cache buf_data;/* buffer page cache */ - struct usbd_page_cache buf_fixup; /* fixup buffer */ + struct usbd_page_cache *buf_fixup; /* fixup buffer(s) */ LIST_ENTRY(usbd_xfer) interrupt_list; /* used by HC driver */ LIST_ENTRY(usbd_xfer) pipe_list; /* used by HC driver */ + LIST_ENTRY(usbd_xfer) dma_list;/* used by BUS-DMA */ - bus_dmamap_t dma_rx_map; - bus_dmamap_t dma_tx_map; struct usbd_page *dma_page_ptr; struct usbd_pipe *pipe; struct usbd_device *udev; - struct mtx *priv_mtx; + struct mtx *priv_mtx; /* cannot be changed during operation */ struct mtx *usb_mtx; /* used by HC driver */ struct usbd_memory_info *usb_root; /* used by HC driver */ struct thread *usb_thread; /* used by HC driver */ @@ -459,11 +441,11 @@ void *td_transfer_cache; /* used by HC driver */ void *priv_sc; void *priv_fifo; + void *local_buffer; uint32_t *frlengths; struct usbd_page_cache *frbuffers; usbd_callback_t *callback; - uint32_t dma_refcount; uint32_t max_usb_frame_size; uint32_t max_data_length; uint32_t sumlen; /* sum of all lengths in bytes */ @@ -496,22 +478,33 @@ struct usbd_xfer_flags_int flags_int; }; -struct usbd_dma_load_mem_info { - struct usbd_page *page_ptr; - struct usbd_page_cache *page_cache; - uint32_t frame_length; -}; +struct usbd_memory_info { + LIST_HEAD(, usbd_xfer) dma_head; -struct usbd_memory_info { void *memory_base; struct mtx *priv_mtx; struct mtx *usb_mtx; - struct usbd_page *page_base; + struct usbd_page_cache *dma_page_cache_start; + struct usbd_page_cache *dma_page_cache_end; + struct usbd_page_cache *xfer_page_cache_start; + struct usbd_page_cache *xfer_page_cache_end; + struct usbd_xfer *dma_curr_xfer; + struct usbd_dma_tag *dma_tag_p; uint32_t memory_size; uint32_t memory_refcount; uint32_t setup_refcount; uint32_t page_size; + uint32_t dma_refcount; + + uint8_t dma_error; /* set if virtual memory could not be + * loaded */ + uint8_t dma_draining; /* set if someone is waiting for a + * BUS-DMA load operation to complete */ + uint8_t dma_no_callback; /* set if callback should not be + * called */ + + uint8_t dma_tag_max; }; struct usbd_mbuf { @@ -667,6 +660,9 @@ #endif #endif +typedef void (usbd_bus_mem_sub_cb_t)(struct usbd_bus *bus, struct usbd_page_cache *pc, struct usbd_page *pg, uint32_t size, uint32_t align); +typedef void (usbd_bus_mem_cb_t)(struct usbd_bus *bus, usbd_bus_mem_sub_cb_t *scb); + void usbd_devinfo(struct usbd_device *udev, char *dst_ptr, uint16_t dst_len); const char *usbd_errstr(usbd_status err); void usb_delay_ms(struct usbd_bus *bus, uint32_t ms); @@ -700,29 +696,20 @@ int usbd_uiomove(struct usbd_page_cache *pc, struct uio *uio, uint32_t pc_offset, uint32_t len); void usbd_copy_out(struct usbd_page_cache *cache, uint32_t offset, void *ptr, uint32_t len); void usbd_bzero(struct usbd_page_cache *cache, uint32_t offset, uint32_t len); -uint8_t usbd_page_alloc(bus_dma_tag_t tag, struct usbd_page *page, uint32_t npages); -void usbd_page_free(struct usbd_page *page, uint32_t npages); -void usbd_page_cache_init(struct usbd_page_cache *pc, struct usbd_page *page_ptr, uint32_t offset, uint32_t size); -uint32_t usbd_page_fit_obj(uint32_t size, uint32_t obj_len); -void *usbd_mem_alloc(bus_dma_tag_t parent, struct usbd_page *page, uint32_t size, uint8_t align_power); -void usbd_mem_free(struct usbd_page *page); -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); -void usbd_dma_tag_free(bus_dma_tag_t tag); -void *usbd_mem_alloc_sub(bus_dma_tag_t tag, struct usbd_page *page, uint32_t size, uint32_t alignment); -void usbd_mem_free_sub(struct usbd_page *page); -void usbd_dma_load_setup(struct usbd_setup_params *parm); -void usbd_dma_load_unsetup(struct usbd_xfer *xfer); -void usbd_dma_load_pre_sync(struct usbd_xfer *xfer); -void usbd_dma_load_post_sync(struct usbd_xfer *xfer); -void usbd_page_cpu_invalidate(struct usbd_page *page); -void usbd_page_cpu_flush(struct usbd_page *page); -void usbd_pio_load_mem(struct usbd_xfer *xfer, struct usbd_dma_load_mem_info *info); +bus_dma_tag_t usbd_dma_tag_create(bus_dma_tag_t tag_parent, uint32_t size, uint32_t align); +void usbd_dma_tag_destroy(bus_dma_tag_t tag); +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); +void usbd_pc_free_mem(struct usbd_page_cache *pc); +void usbd_pc_load_mem(struct usbd_page_cache *pc, uint32_t size); +void usbd_pc_cpu_invalidate(struct usbd_page_cache *pc); +void usbd_pc_cpu_flush(struct usbd_page_cache *pc); +uint8_t usbd_pc_dmamap_create(struct usbd_page_cache *pc, uint32_t size); +void usbd_pc_dmamap_destroy(struct usbd_page_cache *pc); uint8_t usbd_make_str_desc(void *ptr, uint16_t max_len, const char *s); uint32_t mtx_drop_recurse(struct mtx *mtx); void mtx_pickup_recurse(struct mtx *mtx, uint32_t recurse_level); uint8_t usbd_config_td_setup(struct usbd_config_td *ctd, void *priv_sc, struct mtx *priv_mtx, usbd_config_td_end_of_commands_t *p_func_eoc, uint16_t item_size, uint16_t item_count); void usbd_config_td_stop(struct usbd_config_td *ctd); -void usbd_transfer_drain(struct usbd_xfer *xfer); void usbd_config_td_unsetup(struct usbd_config_td *ctd); void usbd_config_td_queue_command(struct usbd_config_td *ctd, usbd_config_td_command_t *pre_func, usbd_config_td_command_t *post_func, uint16_t command_qcount, uint16_t command_ref); uint8_t usbd_config_td_is_gone(struct usbd_config_td *ctd); @@ -730,9 +717,12 @@ struct mbuf *usbd_ether_get_mbuf(void); int32_t device_delete_all_children(device_t dev); uint16_t usbd_isoc_time_expand(struct usbd_bus *bus, uint16_t isoc_time_curr); -void usbd_dma_load_mem(struct usbd_xfer *xfer, struct usbd_dma_load_mem_info *info); -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); -void usbd_bus_mem_unsetup(struct usbd_bus *bus); +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); +void usbd_dma_tag_unsetup(struct usbd_dma_tag *udt, uint8_t nudt); +void usbd_bus_mem_flush_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb); +uint8_t usbd_bus_mem_alloc_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb); +void usbd_bus_mem_free_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb); +uint8_t usbd_transfer_setup_sub_malloc(struct usbd_setup_params *parm, struct usbd_page_search *info, struct usbd_page_cache **ppc, uint32_t size, uint32_t align); /* prototypes from usb.c */ @@ -768,9 +758,12 @@ void usbd_transfer_unsetup(struct usbd_xfer **pxfer, uint16_t n_setup); uint8_t usbd_std_root_transfer(struct usbd_std_root_transfer *std, struct thread *ctd, usbd_std_root_transfer_func_t *func); void usbd_start_hardware(struct usbd_xfer *xfer); -void usbd_bdma_done_event(struct usbd_xfer *xfer); +void usbd_bdma_done_event(struct usbd_memory_info *info); +void usbd_bdma_pre_sync(struct usbd_xfer *xfer); +void usbd_bdma_post_sync(struct usbd_xfer *xfer); void usbd_transfer_start(struct usbd_xfer *xfer); void usbd_transfer_stop(struct usbd_xfer *xfer); +void usbd_transfer_drain(struct usbd_xfer *xfer); void usbd_set_frame_data(struct usbd_xfer *xfer, void *ptr, uint32_t len, uint32_t frindex); void usbd_set_frame_offset(struct usbd_xfer *xfer, uint32_t offset, uint32_t frindex); void usbd_callback_wrapper(struct usbd_xfer *xfer);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712020011.lB20BjmN003859>