Universal Host Controller Interface

From OSDev Wiki
(Redirected from UHCI)
Jump to navigation Jump to search

Universal Host Controller Interface (UHCI) was created by Intel as an implementation of the USB 1.0 host controller interface. Along with OHCI, it makes up the USB 1.0 standard.

Technical Details

The UHCI specification defines a set of I/O mapped registers that allow communication between the controller and the operating system. The base address for these registers can be found by searching the PCI controller for a specific VendorID/DeviceID combination, or for a specific ClassID/SubclassID/Interface combination. All UHCI PCI controllers will have a Class ID of 0x0C, a Subclass ID of 0x03, and an Interface value of 0x00. The PCI Configuration space for this device will contain the I/O port address information in BAR4.

I/O Registers

Offset (Hex) Name Description Lenght
00 USBCMD Usb Command 2 bytes
02 USBSTS Usb Status 2 bytes
04 USBINTR Usb Interrupt Enable 2 bytes
06 FRNUM Frame Number 2 bytes
08 FRBASEADD Frame List Base Address 4 bytes
0C SOFMOD Start Of Frame Modify 1 byte
10 PORTSC1 Port 1 Status/Control 2 bytes
12 PORTSC2 Port 2 Status/Control 2 bytes

Command Register

Bits Name Description
15-8 Reserved
7 Max Packet Size 0 = Max Size is 32 bits 1 = Max Size is 64 bits
6 Configure Flag
5 Software Debug
4 Global Resume
3 Global Suspend
2 Global Reset
1 Host Controller Reset This bit will clear after reset is done
0 Run 1 = Controller execute Frame List Entries

Status Register

You can clear those bits by writing 1 to them.

Bits Name Description
15-6 Reserved
5 Halted Indicates status of Frame List execution
4 Process Error
3 System Error
2 Resume Detected
1 Error Interrupt
0 Interrupt

Interrupt Enable Register

If bit is set, it mean that this interrupt will be generated

Bits Name Description
15-4 Reserved
3 Short Packet Interrupt when short packet was transferred
2 Complete Transfer Interrupt after transfer of packet with IOC
1 Resume
0 Timeout CRC

Frame Number

Number of processed entry of Frame List.

Frame List Base Address

32-bit physical adress of Frame List. Address has to be aligned to 4 Kb (first 12 bits are zero). The Frame List must contain 1024 entries.

Start Of Frame

This port sets timing of frame. Should be 0x40.

Port 1/2 Status/Control Registers

Bits Name Description
15-13 Reserved
12 Suspend
11-10 Reserved
9 Reset
8 Low Speed Device 0 = Full Speed Device 1 = Low Speed Device
7 Reserved Always set, used to detect number of ports
6 Resume Detected
5-4 Line Status
3 Port Enable Changed Bit 2 was changed, write-clear bit
2 Device Enable
1 Connection Status Change Bit 0 was changed, write-clear bit
0 Connection Status

Memory structures

Frame List Entry

Bits Name Description
31-4 Physical Address to Memory Structure
3-2 Reserved
1 Memory Structure Type 0 = Transfer Descriptor 1 = Queue Head
0 Frame Enable 0 = Frame Is Valid 1 = Empty Frame

UHCI Queue Head

Offset (Hex) Name Description
00 Horizontal Pointer Same structure as Frame List Entry
04 Vertical Pointer Same structure as Frame List Entry

UHCI Transfer Descriptor

Offset (Hex) Name Description
00 Next Descriptor See below
04 Status See below
08 Packet Header See below
12 Buffer Address 32-bit address of data buffer
16 System Use 128-bit area reserved for use by the system

UHCI Transfer Descriptor Next Descriptor

Bits Name Description
31:4 Physical Address of Memory Structure
3 Reserved
2 Depth First Controller will continue execution to next TD pointed by this TD
1 Memory Structure Type 0 = Transfer Descriptor 1 = Queue Head
0 Terminate 0 = Pointer is valid 1 = This TD do not point do anything

UHCI Transfer Descriptor Status

Bits Name Description
31-30 Reserved
29 Short Packet Detect 1 = If SPD, continue execution from horizontal QH pointer
28-27 Error Counter
26 Low Speed 1 = This is transfer to Low speed device
25 Is Isochronous
24 Interrupt On Complete
23 Active This packet waits to be transferred by UHCI controller
22 Stalled
21 Data Buffer Error
20 Babble Detected
19 Non-Acknowledged
18 Timeout CRC
17 Bit Stuff Error
16-11 Reserved
10-0 Actual Length Length of transferred bytes-1

UHCI Transfer Descriptor Packet Header

Bits Name Description
31-21 Maximum Length (Length - 1) so 7 for low speed, 63 for full speed
20 Reserved
19 Data Toggle
18-15 Endpoint
14-8 Device
7-0 Packet Type 0x69 = IN, 0xE1 = OUT, 0x2D = SETUP, other values are invalid

Initalization

When you find UHCI controller, you need to initalize it by following steps:

  • Disable BIOS Legacy USB Emulation by writing value 0x2000 to PCI register 0xC0
  • Set I/O busmastering in PCI
  • Reset controller by Host Controller Reset (bit will self-clear) and Global Reset (you need to clear bit after 10ms)
  • Allocate memory for Frame List, fill it with empty Frame Entries (every entry will have bit 0 set) and write it's physical address to FRBASEADD
  • Enable interrupts by setting bits in USBINTR
  • Find out number of ports on controller. This value is not saved anywhere, so you need to continue to access new port registers, and check if they have bit 7 set and their value is not 0xFFFF. If those conditions are met, it means that you find valid port register.
  • Start controller by setting bit 0 and bit 7 (to enable transfers with 64 bytes) in USBCMD

When you initalized controller, you can start periodically check Connection Status Change of ports. If it is set, it means, that device was either connected, or disconnected. So you need to check Connection Status to determine what happened. In both cases, you will need to clear Connection Status Change. You have to do it in separate write beside any other action, so for example, you can not clear Connection Status Change and set Reset of port in same write. Then if there is connected new device, you need to enable it by following sequence:

  • Set Reset bit
  • Wait 100 ms
  • Clear Reset bit
  • Wait 50 ms
  • Set Device Enable bit
  • Wait until this bit becomes set

When Device Enable bit is set, it means that you have successfully enabled device that is in zero address mode, so you can start transfers to it. At first you would want to read USB Device Descriptor, and then Set Address to something other than 0. If Device Enable bit is not set after 100 ms, you can assume that there happened some error.

If you want to disable device (for example because it do not responds to transfers), you simply need to clear Device Enable bit.

See Also

External Links