📄 nuhci_spec.html
字号:
Return value is a pointer to the allocated URB, 0 if allocation failed.The parameter isoframes specifies the number of isochronous transfer framesyou want to schedule. For CTRL/BULK/INT, use 0.<p>To free an URB, use<p><center><b> void free_urb(purb_t purb)</b></center><p>This call also may free internal (host controller specific) memory in thefuture.<p><b>2.4. What has to be filled in?</b><p>Depending on the type of transaction, there are some macros (FILL_CONTROL_URB, FILL_BULK_URB, and FILL_INT_URB, defined in uhci.h)that simplify the URB creation. In general, all macros need the usbdevice pointer, the pipe (usual format), the transfer buffer, the desired transfer length, the completion handler, and its context. Take a look at the uhci_control_msg-function that convert the old API into an URB.<p>Flags:<p>For ISO there are two startup behaviors: Specified start_frame or ASAP.For ASAP set USB_ISO_ASAP in transfer_flags.<p>If short packets should NOT be tolerated, set USB_DISABLE_SPD in transfer_flags.<p>Usually, (to reduce restart time) the completion handler is calledAFTER the URB re-submission. You can get the other way by settingUSB_URB_EARLY_COMPLETE in transfer_flags. This is implicite forINT transfers.<p><b>2.5. How to submit an URB?</b><p>Just call<center><b> int submit_urb(purb_t purb)</b></center><p>It immediately returns, either with status 0 (request queued) or someerror code, usually caused by the following:<p><ul><li> Out of memory (-ENOMEM)<li> Wrong pipe handle (-ENXIO)<li> Unplugged device (-ENODEV)<li> Stalled endpoint (-EPIPE)<li> Too many queued ISO transfers (-EAGAIN)<li> Too many requested ISO frames (-EFBIG)<li> Invalid INT interval (-EINVAL)<li> More than one packet for INT (-EINVAL)</ul>After submission, urb->status is USB_ST_URB_PENDING.<p>For isochronous endpoints, subsequent submitting of URBs to the same endpointwith the ASAP flag result in a seamless ISO streaming. Exception: The execution cannot be scheduled later than 900 frames from the 'now'-time. The same applies to INT transfers, but here the seamless continuation is independent of the transfer flags (implicitely ASAP).<p><b>2.6. How to cancel an already running URB?</b><p>Call<center><b> int unlink_urb(purb_t purb)</b></center><p>It removes the urb from the internal list and frees all allocatedHW descriptors. The status is changed to USB_ST_URB_KILLED. After unlink_urb() returns, you can safely free the URB with free_urb(urb)and all other possibly associated data (urb->context etc.)<p><b>2.7. What about the completion handler?</b><p>The completion handler is optional, but useful for fast data processingor wakeup of a sleeping process (as shown in the compatibility wrapper's completion handler).<p>The handler is of the following type:<p><center><b> typedef void (*usb_complete_t)(struct urb *) </b></center><p>i.e. it gets just the URB that caused the completion call.In the completion handler, you should have a look at urb->status todetect any USB errors. Since the context parameter is included in the URB,you can pass information to the completion handler. <p><b>2.8. How to do isochronous (ISO) transfers?</b><p>For ISO transfers you have to append the iso_packet_descriptor_t structure to the URB for each frame you want to schedule. When using alloc_urb(n)(recommended), the isoframe-parameter n can be used to allocate thestructures for n frames.<p>For each entry you have to specify the data offset for this frame (base istransfer_buffer), and the length you want to write/expect to read.After completion, actual_length contains the actual transfered length and status contains the resulting USB-status for the ISO transfer for this frame.It is allowed to specify a varying length from frame to frame (e.g. foraudio synchronisation/adaptive transfer rates). You can also use the length 0 to omit one or more frames (striping).<p>As can be concluded from above, the UHCI-driver does not care for continousdata in case of short packet ISO reads! There's no fixup_isoc() like in the old driver. There may be a common routine to do this in the future, but this has nothing to do with the UHCI-driver!<p>For scheduling you can choose your own start frame or ASAP. As written above,queuing more than one ISO frame with ASAP to the same device&endpoint result in seamless ISO streaming. For continous streaming you have to use URBlinking. <p><b>2.9. How to start interrupt (INT) transfers?</b><p>INT transfers are currently implemented with 8 different queues for intervals for 1, 2, 4,... 128ms. Only one TD is allocated for each interrupt. Aftercalling the completion handler, the TD is recycled.With the submission of one URB, the interrupt is scheduled until it iscanceled by unlink_urb.<p>The submit_urb()-call modifies urb->interval to the rounded value.<p><hr><h1>3. Internal structure and mechanisms</h1>To get quickly familiar with the internal structures, here's a shortdescription how the new UHCI driver works. However, the ultimate source oftruth is only uhci.c!<p><b>3.1. Descriptor structure (QHs and TDs)</b><p>During initialization, the following skeleton is allocated in init_skel:<p><IMG SRC="skeleton.gif"><p>For each CTRL or BULK transfer a new QH is allocated and the containing datatransfers are appended as (vertical) TDs. After building the whole QH with itsdangling TDs, the QH is inserted before the BULK Chain QH (for CTRL) orbefore the End Chain QH (for BULK). Since only the QH->next pointers areaffected, no atomic memory operation is required. The three QHs in thecommon chain are never equipped with TDs!<p>For ISO or INT, the TD for each frame is simply inserted into the apropriateISO/INT-TD-chain for the desired frame. The 7 skeleton INT-TDs are scatteredamong the 1024 frames similar to the old UHCI driver.<p>For CTRL/BULK/ISO, the last TD in the transfer has the IOC-bit set. For INT,every TD (there is only one...) has the IOC-bit set.<p>Besides the data for the UHCI controller (2 or 4 32bit words), the descriptorsare double-linked through the .vertical and .horizontal elements in the SW data of the descriptor (using the double-linked list structures and operations), but SW-linking occurs only in closed domains, i.e. for each ofthe 1024 ISO-chains and the 8 INT-chains there is a closed cycle. This simplifies all insertions and unlinking operations and avoids costly bus_to_virt()-calls.<p><b>3.2. URB structure and linking to QH/TDs</b><p>During assembly of the QH and TDs of the requested action, these descriptorsare stored in urb->urb_list, so the allocated QH/TD descriptors are bound tothis URB.<p>If the assembly was successful and the descriptors were added to the HW chain,the corresponding URB is inserted into a global URB list for this controller.This list stores all pending URBs.<p><b>3.3. Interrupt processing</b><p>Since UHCI provides no means to directly detect completed transactions, thefollowing is done in each UHCI interrupt (uhci_interrupt()):<p>For each URB in the pending queue (process_urb()), the ACTIVE-flag of the associated TDs are processed (depending on the transfer type process_{transfer|interrupt|iso}()). If the TDs are not active anymore, they indicate the completion of the transaction and the status is calculated. Inactive QH/TDs are removed from the HW chain (since the host controlleralready removed the TDs from the QH, no atomic access is needed) and eventually the URB is marked as completed (OK or errors) and removed from the pending queue. Then the next linked URB is submitted. After (or immediately before) that, the completion handler is called.<p><b>3.4. Unlinking URBs</b><p>First, all QH/TDs stored in the URB are unlinked from the HW chain. To ensure that the host controller really left a vertical TD chain, we wait for one frame. After that, the TDs are physically destroyed.<p><b>3.5. URB linking and the consequences</b><p>Since URBs can be linked and the corresponding submit_urb is called inthe UHCI-interrupt, all work associated with URB/QH/TD assembly has to beinterrupt save. This forces kmalloc to use GFP_ATOMIC in the interrupt.<hr> <address><a href="mailto:usb@in.tum.de">USB-Team</a></address><!-- Created: Fri Nov 5 13:58:11 CET 1999 --><!-- hhmts start -->Last modified: Mon Nov 8 18:21:42 CET 1999<!-- hhmts end --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -