mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 11:35:58 +00:00
226 lines
8 KiB
C
226 lines
8 KiB
C
/*
|
|
* PROJECT: ReactOS USB UHCI Miniport Driver
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: USBUHCI hardware declarations
|
|
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
|
|
*/
|
|
|
|
#define UHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List
|
|
#define UHCI_NUM_ROOT_HUB_PORTS 2
|
|
|
|
/* UHCI HC I/O Registers offset (PUSHORT) */
|
|
#define UHCI_USBCMD 0 // USB Command R/W
|
|
#define UHCI_USBSTS 1 // USB Status R/WC
|
|
#define UHCI_USBINTR 2 // USB Interrupt Enable R/W
|
|
#define UHCI_FRNUM 3 // Frame Number R/W WORD writeable only
|
|
#define UHCI_FRBASEADD 4 // Frame List Base Address R/W // 32 bit
|
|
#define UHCI_SOFMOD 6 // Start Of Frame Modify R/W // 8 bit
|
|
#define UHCI_PORTSC1 8 // Port 1 Status/Control R/WC WORD writeable only
|
|
#define UHCI_PORTSC2 9 // Port 2 Status/Control R/WC WORD writeable only
|
|
|
|
/* PCI Legacy Support */
|
|
#define PCI_LEGSUP 0xC0 // Legacy Support register offset. R/WC
|
|
#define PCI_LEGSUP_USBPIRQDEN 0x2000
|
|
#define PCI_LEGSUP_CLEAR_SMI 0x8F00
|
|
|
|
/* LEGSUP Legacy support register (PCI Configuration - Function 2) */
|
|
typedef union _UHCI_PCI_LEGSUP {
|
|
struct {
|
|
USHORT Smi60Read : 1; // (60REN) Trap/SMI On 60h Read Enable. R/W.
|
|
USHORT Smi60Write : 1; // (60WEN) Trap/SMI On 60h Write Enable. R/W.
|
|
USHORT Smi64Read : 1; // (64REN) Trap/SMI On 64h Read Enable. R/W.
|
|
USHORT Smi64Write : 1; // (64WEN) Trap/SMI On 64h Write Enable. R/W.
|
|
USHORT SmiIrq : 1; // (USBSMIEN) Trap/SMI ON IRQ Enable. R/W.
|
|
USHORT A20Gate : 1; // (A20PTEN) A20Gate Pass Through Enable. R/W.
|
|
USHORT PassThroughStatus : 1; // (PSS) Pass Through Status. RO.
|
|
USHORT SmiEndPassThrough : 1; // (SMIEPTE) SMI At End Of Pass Through Enable. R/W.
|
|
USHORT TrapBy60ReadStatus : 1; // (TBY60R) Trap By 60h Read Status. R/WC.
|
|
USHORT TrapBy60WriteStatus : 1; // (TBY60W) Trap By 60h Write Status. R/WC.
|
|
USHORT TrapBy64ReadStatus : 1; // (TBY64R) Trap By 64h Read Status. R/WC.
|
|
USHORT TrapBy64WriteStatus : 1; // (TBY64W) Trap By 64h Write Status. R/WC.
|
|
USHORT UsbIrqStatus : 1; // (USBIRQS) USB IRQ Status. RO.
|
|
USHORT UsbPIRQ : 1; // (USBPIRQDEN) USB PIRQ Enable. R/W.
|
|
USHORT Reserved : 1;
|
|
USHORT EndA20GateStatus : 1; // (A20PTS) End OF A20GATE Pass Through Status. R/WC.
|
|
};
|
|
USHORT AsUSHORT;
|
|
} UHCI_PCI_LEGSUP;
|
|
|
|
C_ASSERT(sizeof(UHCI_PCI_LEGSUP) == sizeof(USHORT));
|
|
|
|
/* USBCMD Command register */
|
|
typedef union _UHCI_USB_COMMAND {
|
|
struct {
|
|
USHORT Run : 1;
|
|
USHORT HcReset : 1;
|
|
USHORT GlobalReset : 1;
|
|
USHORT GlobalSuspend : 1;
|
|
USHORT GlobalResume : 1; // Force Global Resume
|
|
USHORT SoftwareDebug : 1; // 0 - Normal Mode, 1 - Debug mode
|
|
USHORT ConfigureFlag : 1; // no effect on the hardware
|
|
USHORT MaxPacket : 1; // 0 = 32, 1 = 64
|
|
USHORT Reserved : 8;
|
|
};
|
|
USHORT AsUSHORT;
|
|
} UHCI_USB_COMMAND;
|
|
|
|
C_ASSERT(sizeof(UHCI_USB_COMMAND) == sizeof(USHORT));
|
|
|
|
/* USBSTS Status register */
|
|
#define UHCI_USB_STATUS_MASK 0x3F
|
|
|
|
typedef union _UHCI_USB_STATUS {
|
|
struct {
|
|
USHORT Interrupt : 1; // due to IOC (Interrupt On Complete)
|
|
USHORT ErrorInterrupt : 1; // due to error
|
|
USHORT ResumeDetect : 1;
|
|
USHORT HostSystemError : 1; // PCI problems
|
|
USHORT HcProcessError : 1; // Schedule is buggy
|
|
USHORT HcHalted : 1;
|
|
USHORT Reserved : 10;
|
|
};
|
|
USHORT AsUSHORT;
|
|
} UHCI_USB_STATUS;
|
|
|
|
C_ASSERT(sizeof(UHCI_USB_STATUS) == sizeof(USHORT));
|
|
|
|
/* USBINTR Interrupt enable register */
|
|
typedef union _UHCI_INTERRUPT_ENABLE {
|
|
struct {
|
|
USHORT TimeoutCRC : 1; // Timeout/CRC error enable
|
|
USHORT ResumeInterrupt : 1;
|
|
USHORT InterruptOnComplete : 1;
|
|
USHORT ShortPacket : 1;
|
|
USHORT Reserved : 12;
|
|
};
|
|
USHORT AsUSHORT;
|
|
} UHCI_INTERRUPT_ENABLE;
|
|
|
|
C_ASSERT(sizeof(UHCI_INTERRUPT_ENABLE) == sizeof(USHORT));
|
|
|
|
/* FRNUM Frame Number register */
|
|
#define UHCI_FRNUM_FRAME_MASK 0x7FF
|
|
#define UHCI_FRNUM_INDEX_MASK 0x3FF
|
|
#define UHCI_FRNUM_OVERFLOW_LIST 0x400
|
|
|
|
/* PORTSC(1|2) USB port status and control registers */
|
|
typedef union _UHCI_PORT_STATUS_CONTROL {
|
|
struct {
|
|
USHORT CurrentConnectStatus : 1;
|
|
USHORT ConnectStatusChange : 1;
|
|
USHORT PortEnabledDisabled : 1;
|
|
USHORT PortEnableDisableChange : 1;
|
|
USHORT LineStatus : 2; // D+ and D-
|
|
USHORT ResumeDetect : 1;
|
|
USHORT Reserved1 : 1; // always 1
|
|
USHORT LowSpeedDevice : 1; // LS device Attached
|
|
USHORT PortReset : 1;
|
|
USHORT Reserved2 : 2; // Intel use it (not UHCI 1.1d spec)
|
|
USHORT Suspend : 1;
|
|
USHORT Reserved3 : 3; // write zeroes
|
|
};
|
|
USHORT AsUSHORT;
|
|
} UHCI_PORT_STATUS_CONTROL;
|
|
|
|
C_ASSERT(sizeof(UHCI_PORT_STATUS_CONTROL) == sizeof(USHORT));
|
|
|
|
typedef struct _UHCI_HW_REGISTERS {
|
|
UHCI_USB_COMMAND HcCommand; // R/W
|
|
UHCI_USB_STATUS HcStatus; // R/WC
|
|
UHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W
|
|
USHORT FrameNumber; // R/W WORD writeable only
|
|
ULONG FrameAddress; // R/W
|
|
UCHAR SOF_Modify; // R/W
|
|
UCHAR Reserved[3];
|
|
UHCI_PORT_STATUS_CONTROL PortControl[UHCI_NUM_ROOT_HUB_PORTS]; // R/WC WORD writeable only
|
|
} UHCI_HW_REGISTERS, *PUHCI_HW_REGISTERS;
|
|
|
|
/* Transfer Descriptor (TD) */
|
|
#define UHCI_TD_STS_ACTIVE (1 << 7)
|
|
#define UHCI_TD_STS_STALLED (1 << 6)
|
|
#define UHCI_TD_STS_DATA_BUFFER_ERROR (1 << 5)
|
|
#define UHCI_TD_STS_BABBLE_DETECTED (1 << 4)
|
|
#define UHCI_TD_STS_NAK_RECEIVED (1 << 3)
|
|
#define UHCI_TD_STS_TIMEOUT_CRC_ERROR (1 << 2)
|
|
#define UHCI_TD_STS_BITSTUFF_ERROR (1 << 1)
|
|
//#define UHCI_TD_STS_Reserved (1 << 0)
|
|
|
|
#define UHCI_TD_VALID_LENGTH 0x4FF
|
|
#define UHCI_TD_LENGTH_INVALID 0x7FE
|
|
#define UHCI_TD_LENGTH_NULL 0x7FF
|
|
|
|
typedef union _UHCI_CONTROL_STATUS {
|
|
struct {
|
|
ULONG ActualLength : 11; // encoded as n - 1
|
|
ULONG Reserved1 : 5;
|
|
ULONG Status : 8; // UHCI_TD_STS_ xxx
|
|
ULONG InterruptOnComplete : 1;
|
|
ULONG IsochronousType : 1;
|
|
ULONG LowSpeedDevice : 1;
|
|
ULONG ErrorCounter : 2;
|
|
ULONG ShortPacketDetect : 1;
|
|
ULONG Reserved2 : 2;
|
|
};
|
|
ULONG AsULONG;
|
|
} UHCI_CONTROL_STATUS;
|
|
|
|
C_ASSERT(sizeof(UHCI_CONTROL_STATUS) == sizeof(ULONG));
|
|
|
|
#define UHCI_TD_PID_IN 0x69
|
|
#define UHCI_TD_PID_OUT 0xE1
|
|
#define UHCI_TD_PID_SETUP 0x2D
|
|
|
|
#define UHCI_TD_PID_DATA0 0
|
|
#define UHCI_TD_PID_DATA1 1
|
|
|
|
typedef union _UHCI_TD_TOKEN {
|
|
struct {
|
|
ULONG PIDCode : 8;
|
|
ULONG DeviceAddress : 7;
|
|
ULONG Endpoint : 4;
|
|
ULONG DataToggle : 1;
|
|
ULONG Reserved : 1;
|
|
ULONG MaximumLength : 11;
|
|
};
|
|
ULONG AsULONG;
|
|
} UHCI_TD_TOKEN;
|
|
|
|
C_ASSERT(sizeof(UHCI_TD_TOKEN) == sizeof(ULONG));
|
|
|
|
#define UHCI_TD_LINK_PTR_VALID (0 << 0)
|
|
#define UHCI_TD_LINK_PTR_TERMINATE (1 << 0)
|
|
#define UHCI_TD_LINK_PTR_TD (0 << 1)
|
|
#define UHCI_TD_LINK_PTR_QH (1 << 1)
|
|
#define UHCI_TD_LINK_PTR_BREADTH_FIRST (0 << 2)
|
|
#define UHCI_TD_LINK_PTR_DEPTH_FIRST (1 << 2)
|
|
#define UHCI_TD_LINK_POINTER_MASK 0xFFFFFFF0
|
|
|
|
typedef struct _UHCI_TD { // Transfer Descriptors always aligned on 16-byte boundaries
|
|
ULONG NextElement;
|
|
UHCI_CONTROL_STATUS ControlStatus;
|
|
UHCI_TD_TOKEN Token;
|
|
ULONG Buffer;
|
|
} UHCI_TD, *PUHCI_TD;
|
|
|
|
C_ASSERT(sizeof(UHCI_TD) == 16);
|
|
|
|
/* Queue Header (QH) */
|
|
#define UHCI_QH_HEAD_LINK_PTR_VALID (0 << 0)
|
|
#define UHCI_QH_HEAD_LINK_PTR_TERMINATE (1 << 0)
|
|
#define UHCI_QH_HEAD_LINK_PTR_TD (0 << 1)
|
|
#define UHCI_QH_HEAD_LINK_PTR_QH (1 << 1)
|
|
#define UHCI_QH_HEAD_LINK_POINTER_MASK 0xFFFFFFF0
|
|
|
|
#define UHCI_QH_ELEMENT_LINK_PTR_VALID (0 << 0)
|
|
#define UHCI_QH_ELEMENT_LINK_PTR_TERMINATE (1 << 0)
|
|
#define UHCI_QH_ELEMENT_LINK_PTR_TD (0 << 1)
|
|
#define UHCI_QH_ELEMENT_LINK_PTR_QH (1 << 1)
|
|
#define UHCI_QH_ELEMENT_LINK_POINTER_MASK 0xFFFFFFF0
|
|
|
|
typedef struct _UHCI_QH { // Queue Heads must be aligned on a 16-byte boundary
|
|
ULONG NextQH;
|
|
ULONG NextElement;
|
|
} UHCI_QH, *PUHCI_QH;
|
|
|
|
C_ASSERT(sizeof(UHCI_QH) == 8);
|