8/02/2014

PXE, iPXE adding a USB bus

It appears the best approach is to make sure the Balaji implementation of a USB bus is working and compiled.

Then move on, this is because the USB to Nic driver will need to use that support to identify and probe to communicate with the USB Host controller.

The gPXE code has the new USB bus code here:

/gpxe/src/drivers/bus/usb

The iPXE code has some bus code in the same plus, but no support for a USB bus:

/ipxe/src/drivers/bus

While the PCI bus files appear to have changed, the ISA.C bus files have identical md5sum hash values and have thus not changed.

This suggests whatever the conventions for enumerating and standing up a bus instance are still valid.

So the /gpxe/src/drivers/bus/usb directory was simply copied over to /ipxe/src/drivers/bus

The USB bus code consists of eight files:

hcd.h - a list of USB Packet IDs, it has an #ifndef _GPXE_HCD_H that probably needs to be translated in some way. (edit: this seems to be related to how the Make files used to work, making decisions on whether to compile and link code modules on whether certain Macro environment variables were set or not, iPXE doesn't use that method any more - I don't think - so its not relevant)

message.c - appears to be some functions for building up some structures and then calling a
[ usb_submit_urb ] function and then monitoring it and [ usb_urb_status ] for completion

the [ usb_start_wait_urb ] function builds on this to provide a polling service that submits an urb and waits for the results

[ usb_control_msg ] uses the [sub_start_wait_urb] and takes arguments to target a device, endpoint on the device, a request type, value, index, data and size

[ usb_get_descriptor] appears to get a device descriptor

[ usb_get_device_descriptor] uses the former to accomplish its task

[ usb_set_configuration] sets a device configuration

[ usb_get_configuration] gets a device configuration

[gpxe/usb.h] is referenced, which in gpxe appears in [ /gpxe/src/include/gpxe/usb.h ] so needs to be copied over - this defines some structures to hold usb device and driver data, and is where the last problem encountered actually exists#define __usb_driver __table (struct usb_driver, usb_drivers, 01)

The prototype for __table in the ipxe code no longer acceptsthree parameters for instantiating a member, it only takes two parameters

It defines a lot of prototypes and then appears to call:

[int usb_probe] to tell the usb core about a discovered USB device, then

The "above" procedure appears to be standard USB bus protocol for initializing the device at the end of a USB cable. It clears the "decks" sets up some Control structures, then gets a "device descriptor" (there can be 'Only One') and then sends a "Configuration" command over to the device to get it ready. "Devices" can have lots of endpoints, and four different ways of addressing called "Pipes" I think they are really "Methods" for communications with varying levels of "Priority" over other types of traffic.. some are "Critical - like setting up the device or Configuring" some are "When you get around to it - like Polling for data" or "Best effort as quick as you can - like Isynchronous" there is something like "Interrupt" but not quite sure where that falls.

Last step is to retrieve the "Configuration" when it comes back you know that its "done" and ready for action.

[gpxe/malloc.h] is referenced, and probably refers to [ /gpxe/src/include/gpxe/malloc.h ]which does exist in [ /ipxe/src/include/ipxe ] but in a different modified form

[gpxe/src/include/gpxe/usb] directory also exists with a single file called ch9.h, these appear to describe USB macros and structures to make it easier to program for USB communications, looks to be lifted direct from Linux code (edit: ch9.h is described in detail in the Book mentioned at the bottom of this blog post, it seems to be a core feature of USB communications described by the Specification itself)

ohci_hcd.c (ohci Host Controller Driver ->ohci_hcd) resets initializes and defines how to use this controller type, it seems to rely on the PCI_ROM function to "find" a pci_device_id that matches something like "OHCI USB Controller" or "OHCI HCD" and if it does then instantiates a "pci device" driver instance to manage this host controller.. and proceed to probe to initialize it

uhci_hcd.h (uhci Intel Inversal Host Controller Type - complex type) appears to do much the same thing, interesting they did not postfix _hcd.h on to the end of the ohci.h filename

uhci_hcd.c (uhci Intel Inversal Host Controller Type -uhci_hcd) more complex, but structured very much the same, has the PCI_ROM find "UHCI USB Controller" or "UHCI HCD" and create an instance of this driver as a PCI bus device and probe and initialize it

usbcore.c - takes a usb_device table and loops over its list of drivers to see if it can find a usb device driver for a device hanging off its bus. Some DBG commands to print the results if debug is turned on.

It "looks like" the use of gpxe/tables.h and gpxe/usb.h et. al. is sufficiently self contained and referenced that they "could" be copied over and used as they are, the code may work without adapting it. The USB host controllers are treated as PCI devices in the same manner as they were originally.

After the USB controller(s) is initialized, the USB device drivers interact with the usbcore but not with any other system. (except through common net driver interfaces)

The USB drivers communicate over the USB bus, but expose common "net driver" interfaces to the rest of the system code. When they invoke "net driver" communcations functions they are handled by the usbcore to communicate with the USB device hanging off the controller.

I had "thought" I saw USB storage support in the ipxe code base, which could complicate things, since the usb controller should be managed only by one pci usb bus driver. But I could be wrong.

In fact after cloning the github ipxe/ipxe project again the only usb file referenced is here:

clone-ipxe-8-02-2014/ipxe/src/arch/i386/prefix/usbdisk.S

Which appears to be a gnu assembler file for "Zip" disk support, possibly part of the bootloader code for bootstraping from that type of media.

The usbdisk.S "might" be a misnomer, "zipdisk.S" may have been the original intent.

So at present there is no pci bus usb host controller support.

Something I had not thought about however, is the usb host controller "pci device driver" needs to interface to the new ipxe pci bus driver.. and its apparent that has changed.

So while the usb host controller driver "might" compile, it might not interface with the pci bus driver code.. I will have to study that.

Useful Links:
http://www.linux-usb.org/USB-guide/book1.html

Very Useful Links:

This book describes the very complex and layered Linux USB bus system, and how its put together, with diagrams. (Thanks to Jan Axelson for pointing out the level of detail available in this book, and the more appropriate use for this kind of software project!)

This book on page 111 begins to describe the Linux USB stack, which is almost verbatim the stack implemented in gPXE, which has been proven to work.

The Chapter 9 describes the major components and functions calls and what they actually do (as opposed to my guessing). Its a very interesting read.

The book is available through Amazon, (correction) it is available as Kindle book, it is also available through O'Reilly's Safari Online if you have a subscription you can immediately access it online.

It has been pointed out (in the reviews, and in the Book itself) much of the information can be obtained by reading the Linux Kernel source and Documentation on the USB stack.. but I find a book with a narrative much easier to orient oneself.