
Buen día, querido lector! Me pidieron que escribiera sobre UHCI, bueno, escribo.
Puede encontrar este artículo útil si, por ejemplo, no tiene suficientes habilidades de escritura para los controladores y la lectura de la documentación de un hardware. Un ejemplo simple: desea escribir su sistema operativo para una mini PC, de modo que alguna distribución de Windows u otra distribución de Linux no descargue hardware, y utilice toda su potencia exclusivamente para sus propios fines.
¿Qué es la UHCI?
Creo que, para no volver a rociar sobre el tema de qué y por qué, simplemente deje un enlace a mi artículo anterior sobre EHCI.
Meter aquíUHCI: interfaz de controlador de host universal, funciona como un dispositivo PCI, pero, a diferencia de EHCI, utiliza puertos en lugar de MMIO (Memory-Mapped-IO).

Términos que se utilizarán más adelante
- Controlador USB (USBD): el controlador USB en sí
- HC (Host Controller): un controlador de host, o simplemente nuestro UHCI
- Host Controller Driver (HCD): un controlador que conecta hardware y USBD
- Dispositivo USB: dispositivo USB en sí
Tipos de transferencia de datos
Isócrono: transmisión isosíncrona, que tiene una frecuencia dada de transferencia de datos. Se puede usar, por ejemplo, para micrófonos USB, etc.
Interrupción: pequeñas transferencias de datos espontáneas desde un dispositivo. El tipo de transmisión de interrupción admite dispositivos que requieren un intervalo de servicio predecible pero que no necesariamente proporcionan un flujo de datos predecible. Comúnmente utilizado para dispositivos como teclados y dispositivos señaladores que pueden no proporcionar datos durante períodos prolongados de tiempo, pero requieren una respuesta rápida cuando tienen datos para enviar.
Control: tipo de transmisión de información sobre el estado del dispositivo, el estado y la configuración. El tipo de transferencia de Control se utiliza para proporcionar un canal de control desde el Host a los dispositivos USB. Las transmisiones de control siempre consisten en una fase de configuración y cero o más fases de datos seguidas de una fase de estado. Es imperativo que la transferencia de control a un punto final dado se procese en modo FIFO. Si el control se pasa al mismo punto final, el intercalado puede conducir a un comportamiento impredecible.
Granel: tipo de transferencia de matrices de datos. Usado, por ejemplo, en dispositivos MassStorage.

Así es como se ve la distribución de tiempo de 1 ms: procesamiento de un cuadro.
Distribución del tiempo
El controlador host admite la entrega de datos en tiempo real al generar un paquete de inicio de trama (SOF) cada 1 ms. Se genera un paquete SOF cuando caduca el contador SOF en el controlador host (Figura 3). El controlador host inicializa el contador SOF durante un tiempo de trama de 1 ms. Se pueden hacer pequeños cambios en este valor (y, por lo tanto, en el período de tiempo del cuadro) programando el registro de cambios SOF. Esta característica le permite realizar cambios menores en el período de tiempo del cuadro, si es necesario, para mantener la sincronización en tiempo real en todo el sistema USB.
El controlador de host incluye el número de trama en cada paquete SOF. Este número de trama determina de manera única el período de trama en tiempo real. La condición de fin de trama (EOF) ocurre al final del intervalo de tiempo de 1 ms cuando el controlador host inicia el siguiente tiempo de trama, generando otro paquete SOF con el número de trama correspondiente. Durante el período de trama, los datos se transmiten como paquetes de información. El controlador de host impone estrictamente el período de tiempo de trama, y los paquetes de datos en la trama actual no pueden ir más allá del EOF (consulte el Capítulo 11 en la especificación USB). El controlador host admite la sincronización de la transmisión de datos entre cuadros en tiempo real, vinculando el número de cuadro para realizar una entrada específica en la lista de cuadros. El contador de trama del controlador host genera un número de trama (valor de 11 bits) y lo incluye en cada paquete SOF. El contador se programa a través de registros y cada período de trama se incrementa. El controlador host utiliza los 10 bits inferiores del número de cuadro como índice en la lista de cuadros con 1024 cuadros, que se almacena en la memoria del sistema. Por lo tanto, dado que el contador de cuadros controla la selección de una entrada de la lista de cuadros, el controlador host procesa cada entrada en la lista en un período de cuadro dado. El controlador de host se expande a la siguiente entrada en la lista de cuadros para cada nuevo cuadro. Esto asegura que las transmisiones isócronas se realicen en una trama específica.
Figura 3:

Estructura UHCI
Todo es exactamente igual que con EHCI. Ejemplo de solicitudes a HC:

Configurar y acceder a UHCI
Y así, como dije antes, UHCI funciona a través de puertos, por lo que desde PCI necesitamos encontrar la base de los registros UHCI.

En el desplazamiento 0x20 hay 4 bytes: IO Base. Con respecto a IO Base, podemos usar los siguientes registros:

Registros UHCI
- USBCMD es un registro para controlar HC. Bits
- El bit 6 es un indicador de que el dispositivo está configurado e inicializado con éxito.
- Bit 1 - Reinicio HC. Establecer para restablecer HC.
- Bit 0 - Ejecutar / Parar. Muestra el estado de HC. 1 - funciona, 0 - no.
- USBSTS - Registro de estado. Bits
- Bit 5 - HC detenido. Se ha producido un error o el controlador ha completado con éxito el restablecimiento de HC.
- Bit 4: error de proceso del controlador host. El bit se establece en 1 cuando se produce un error crítico y HC no puede continuar haciendo cola y TD.
- Bit 3: error del sistema host. Error de PCI.
- Bit 1 - Interrupción de error. Indica que se ha producido un error y que el HC generó una interrupción.
- Bit 0 - Interrupción. Indica que HC generó una interrupción.
- USBINTR - Registro de configuraciones de interrupción. Bits
- Bit 2 - IOC - Interrupción al completar - genera una interrupción al final de la transacción.
- FRNUM - Número del cuadro actual (Tómelo y 0x3FF para el valor correcto).
- FLBASEADD - Dirección base de la lista de cuadros - dirección de la lista de cuadros.
- PORTSC - Estado y control de puertos - registro de estado y control de puertos. Bits
- Bit 9 - Restablecimiento de puerto - 1 - puerto para restablecer.
- Bit 8: indica que un dispositivo de baja velocidad está conectado al puerto
- Bit 3: indica que el puerto en estado ha cambiado
- Bit 2: indica si el puerto está habilitado
- Bit 1: indica que el estado del dispositivo está conectado al puerto
- Bit 0: indica que el dispositivo está conectado al puerto.
Estructuras
Puntero de lista de cuadros

Descriptor de transferencia

TD CONTROL Y ESTADO
. Bits
- Bits 28-27 - contador de errores, similar a EHCI.
- Bit 26 - 1 = Dispositivo de baja velocidad, 0 = Dispositivo de velocidad completa.
- Bit 25-1 = TD isosíncrono
- Bit 24 - COI
- Bits 23-16 - Estado:
- Bit 23: indica que es un TD activo
- Bit 22 - Atascado
- Bit 21 - Error de búfer de datos
- Bit 20: balbuceo detectado
- Bit 19 - NAK
- Bits 10–0: el número de bytes transmitidos por el controlador de host.
Token TD
- Bits 31:21 - Max Packet Len, similar a EHCI
- Bit 19: alternancia de datos, similar a EHCI
- Bits 18:15 - Número de punto final
- Bits 18:14 - dirección del dispositivo
- Bits 7: 0 - PID. In = 0x69, Out = 0xE1, Setup = 0x2D
Cabeza de la cola

Código
Inicializar y configurar HC:
PciBar bar; PciGetBar(&bar, id, 4); if (~bar.flags & PCI_BAR_IO) {
Puntos finales y solicitudes de control: