|
|
/*++
Copyright (c) 1999, 2000 Microsoft Corporation
Module Name:
usbuhci.h
Abstract:
Environment:
Kernel & user mode
Revision History:
1-1-00 : created
--*/
#ifndef __USBUHCI_H__
#define __USBUHCI_H__
#define FIXPIIX4
#define SOF_TD_COUNT 8
#define ANY_VIA(dd) ((dd)->ControllerFlavor >= UHCI_VIA)
#define MASK_CHANGE_BITS(p)\
do {\ (p).PortEnableChange = 0;\ (p).PortConnectChange = 0;\ } while (0);
/*
define resource consumption for endpoints types */
#define T_64K 0x10000
#define T_16K 0x4000
#define T_4K 0x1000
// Control:
// largest possible transfer for control is 64k
// therefore we support up to 2 transfers of this
// size in HW. Most control transfers are much
// smaller than this.
// NOTE: we MUST support at least one 64k transfer in
// HW since a single control transfer cannot be
// broken up.
//#define MAX_CONTROL_TRANSFER_SIZE T_4K
#define MAX_ASYNC_PACKET_SIZE 64
//#define MAX_CONTROL_DOUBLE_BUFFERS MAX_CONTROL_TRANSFER_SIZE/PAGE_SIZE
//#define TDS_PER_CONTROL_ENDPOINT (MAX_CONTROL_TRANSFER_SIZE/MAX_CONTROL_PACKET_SIZE+2) // 2 EXTRA FOR SETUP AND STATUS
// Bulk:
// bugbug temprarily set to 64k
#define MAX_BULK_TRANSFER_SIZE T_4K
//#define MAX_BULK_TRANSFER_SIZE T_4K // T_16K // T_64K
//#define MAX_BULK_PACKET_SIZE 64
#define MAX_BULK_DOUBLE_BUFFERS MAX_BULK_TRANSFER_SIZE/PAGE_SIZE
#define TDS_PER_BULK_ENDPOINT (MAX_BULK_TRANSFER_SIZE/MAX_BULK_PACKET_SIZE)
// Interrupt:
//#define MAX_INTERRUPT_TRANSFER_SIZE T_4K // T_16K
//#define MAX_INTERRUPT_PACKET_SIZE 64
//#define MAX_INTERRUPT_DOUBLE_BUFFERS MAX_INTERRUPT_TRANSFER_SIZE/PAGE_SIZE
//#define TDS_PER_INTERRUPT_ENDPOINT (MAX_INTERRUPT_TRANSFER_SIZE/MAX_INTERRUPT_PACKET_SIZE)
#define MAX_INTERRUPT_TDS_PER_TRANSFER 8
// Isochronous:
#define MAX_ISOCH_TRANSFER_SIZE T_64K
#define MAX_ISOCH_PACKET_SIZE 1023
//#define MAX_ISOCH_DOUBLE_BUFFERS MAX_ISOCH_TRANSFER_SIZE/PAGE_SIZE
//#define TDS_PER_ISOCH_ENDPOINT 1024
// Maximum Polling Interval we support for interrupt (ms)
#define MAX_INTERVAL 32
#define MAX_INTERVAL_MASK(i) (i&0x1f)
// default size of frame list
#define UHCI_MAX_FRAME 1024
#define ACTUAL_FRAME(f) ((f)&0x000003FF)
//
// These values index in to the interrupt QH list
//
#define QH_INTERRUPT_1ms 0
#define QH_INTERRUPT_2ms 1
#define QH_INTERRUPT_4ms 3
#define QH_INTERRUPT_8ms 7
#define QH_INTERRUPT_16ms 15
#define QH_INTERRUPT_32ms 31
#define QH_INTERRUPT_INDEX(x) (x)-1
#define NO_INTERRUPT_INTERVALS 6
#define NO_INTERRUPT_QH_LISTS 63
// debug signatures
#define SIG_HCD_IQH 'qi01'
#define SIG_HCD_CQH 'qa01'
#define SIG_HCD_BQH 'qb01'
#define SIG_HCD_QH 'hq01'
#define SIG_HCD_DQH 'qd01'
#define SIG_HCD_TD 'dt01'
#define SIG_HCD_RTD 'dtlr'
#define SIG_HCD_SOFTD 'dtos'
#define SIG_HCD_ADB 'bd01'
#define SIG_HCD_IDB 'id01'
#define SIG_EP_DATA 'pe01'
#define SIG_UHCI_TRANSFER 'rt01'
#define SIG_UHCI_DD 'ichu'
// What gets returned by READ_PORT_USHORT when hardware is surprise removed.
#define UHCI_HARDWARE_GONE 0xffff
#undef PDEVICE_DATA
typedef struct _TRANSFER_CONTEXT {
ULONG Sig; ULONG PendingTds; PTRANSFER_PARAMETERS TransferParameters; USBD_STATUS UsbdStatus; ULONG BytesTransferred; struct _ENDPOINT_DATA *EndpointData; PMINIPORT_ISO_TRANSFER IsoTransfer;
} TRANSFER_CONTEXT, *PTRANSFER_CONTEXT;
// HCD Endpoint Descriptor (contains the HW descriptor)
// values for HCD_QUEUEHEAD_DESCRIPTOR.Flags
#define UHCI_QH_FLAG_IN_SCHEDULE 0x00000001
#define UHCI_QH_FLAG_QH_REMOVED 0x00000002
struct _ENDPOINT_DATA;
typedef struct _HCD_QUEUEHEAD_DESCRIPTOR { HW_QUEUE_HEAD HwQH; // 2 dwords
HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress; ULONG Sig; ULONG QhFlags; struct _HCD_QUEUEHEAD_DESCRIPTOR *NextQh; struct _HCD_QUEUEHEAD_DESCRIPTOR *PrevQh; struct _ENDPOINT_DATA *EndpointData;
#ifdef _WIN64
ULONG PadTo64[4]; #else
ULONG PadTo64[8]; #endif
} HCD_QUEUEHEAD_DESCRIPTOR, *PHCD_QUEUEHEAD_DESCRIPTOR;
C_ASSERT((sizeof(HCD_QUEUEHEAD_DESCRIPTOR) == 64));
//
// HCD Transfer Descriptor (contains the HW descriptor)
//
#define ENDPOINT_DATA_PTR(p) ((struct _ENDPOINT_DATA *) (p).Pointer)
#define TRANSFER_CONTEXT_PTR(p) ((struct _TRANSFER_CONTEXT *) (p).Pointer)
#define TRANSFER_DESCRIPTOR_PTR(p) ((struct _HCD_TRANSFER_DESCRIPTOR *) (p).Pointer)
#define QH_DESCRIPTOR_PTR(p) ((struct _HCD_QUEUEHEAD_DESCRIPTOR *) (p).Pointer)
#define HW_PTR(p) ((UCHAR * ) (p).Pointer)
#define DB_FLAG_BUSY 0x00000001
typedef struct _TRANSFER_BUFFER_HEADER { HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress; PUCHAR SystemAddress; ULONG Sig; ULONG Flags; ULONG Size; #ifdef _WIN64
ULONG PadTo32[1]; #else
ULONG PadTo32[3]; #endif
} TRANSFER_BUFFER_HEADER, *PTRANSFER_BUFFER_HEADER;
C_ASSERT((sizeof(TRANSFER_BUFFER_HEADER) == 32));
//
// NOTE: The buffer must go first, since the physical address
// depends on it. If not, you must change the init code.
//
typedef struct _ASYNC_TRANSFER_BUFFER { UCHAR Buffer[MAX_ASYNC_PACKET_SIZE]; TRANSFER_BUFFER_HEADER; } ASYNC_TRANSFER_BUFFER, *PASYNC_TRANSFER_BUFFER;
C_ASSERT((sizeof(ASYNC_TRANSFER_BUFFER) == 64+32));
typedef struct _ISOCH_TRANSFER_BUFFER { UCHAR Buffer[MAX_ISOCH_PACKET_SIZE+1]; // bump it to 1024
TRANSFER_BUFFER_HEADER; } ISOCH_TRANSFER_BUFFER, *PISOCH_TRANSFER_BUFFER;
C_ASSERT((sizeof(ISOCH_TRANSFER_BUFFER) == 1024+32));
typedef union _TRANSFER_BUFFER { ISOCH_TRANSFER_BUFFER Isoch; ASYNC_TRANSFER_BUFFER Async; } TRANSFER_BUFFER, *PTRANSFER_BUFFER;
typedef struct _DOUBLE_BUFFER_LIST { union { ASYNC_TRANSFER_BUFFER Async[1]; ISOCH_TRANSFER_BUFFER Isoch[1]; }; } DOUBLE_BUFFER_LIST, *PDOUBLE_BUFFER_LIST;
// values for HCD_TRANSFER_DESCRIPTOR.Flags
#define TD_FLAG_BUSY 0x00000001
#define TD_FLAG_XFER 0x00000002
//#define TD_FLAG_CONTROL_STATUS 0x00000004
#define TD_FLAG_DONE 0x00000008
#define TD_FLAG_SKIP 0x00000010
#define TD_FLAG_DOUBLE_BUFFERED 0x00000020
#define TD_FLAG_ISO_QUEUED 0x00000040
#define TD_FLAG_SETUP_TD 0x00000100
#define TD_FLAG_DATA_TD 0x00000200
#define TD_FLAG_STATUS_TD 0x00000400
#define TD_FLAG_TIMEOUT_ERROR 0x00000800
typedef struct _HCD_TRANSFER_DESCRIPTOR { HW_QUEUE_ELEMENT_TD HwTD; HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress; ULONG Sig; union { PTRANSFER_CONTEXT TransferContext; ULONG RequestFrame; }; PMINIPORT_ISO_PACKET IsoPacket; ULONG Flags; struct _HCD_TRANSFER_DESCRIPTOR *NextTd; PTRANSFER_BUFFER DoubleBuffer; LIST_ENTRY DoneLink; #ifdef _WIN64
ULONG PadTo128[12]; #else
ULONG PadTo64[3]; #endif
} HCD_TRANSFER_DESCRIPTOR, *PHCD_TRANSFER_DESCRIPTOR;
#ifdef _WIN64
C_ASSERT((sizeof(HCD_TRANSFER_DESCRIPTOR) == 128)); #else
C_ASSERT((sizeof(HCD_TRANSFER_DESCRIPTOR) == 64)); #endif
typedef struct _HCD_TD_LIST { HCD_TRANSFER_DESCRIPTOR Td[1]; } HCD_TD_LIST, *PHCD_TD_LIST;
#define UHCI_EDFLAG_HALTED 0x00000001
#define UHCI_EDFLAG_SHORT_PACKET 0x00000002
#define UHCI_EDFLAG_NOHALT 0x00000004
typedef struct _ENDPOINT_DATA {
ULONG Sig; ULONG Flags; ENDPOINT_PARAMETERS Parameters; PHCD_QUEUEHEAD_DESCRIPTOR QueueHead; ULONG PendingTransfers; ULONG MaxPendingTransfers;
PHCD_TRANSFER_DESCRIPTOR TailTd; PHCD_TRANSFER_DESCRIPTOR HeadTd;
//
// Transfer descriptor cache.
//
PHCD_TD_LIST TdList; ULONG TdCount; ULONG TdLastAllocced; ULONG TdsUsed;
//
// Double buffer cache.
//
PDOUBLE_BUFFER_LIST DbList; ULONG DbCount; ULONG DbLastAllocced; ULONG DbsUsed;
ULONG MaxErrorCount;
ULONG Toggle;
LIST_ENTRY DoneTdList; } ENDPOINT_DATA, *PENDPOINT_DATA;
#define UHCI_NUMBER_PORTS 2
#define UHCI_DDFLAG_USBBIOS 0x00000001
#define UHCI_DDFLAG_SUSPENDED 0x00000002
#define UHCI_HC_MAX_ERRORS 0x10
typedef struct _DEVICE_DATA {
ULONG Sig; ULONG Flags; PHC_REGISTER Registers; ULONG HCErrorCount;
// Save the command register thru power downs
USBCMD SuspendCommandReg; FRNUM SuspendFrameNumber; FRBASEADD SuspendFrameListBasePhys; USBINTR SuspendInterruptEnable;
USBINTR EnabledInterrupts; ULONG IsoPendingTransfers;
//
// Base queue head that we link all control/bulk transfer
// queues to.
//
USB_CONTROLLER_FLAVOR ControllerFlavor;
// ULONG LastFrameCounter;
ULONG FrameNumberHighPart; ULONG LastFrameProcessed; ULONG SynchronizeIsoCleanup;
ULONG PortInReset; ULONG PortResetChange; ULONG PortSuspendChange; ULONG PortOvercurrentChange; BOOLEAN PortResuming[UHCI_NUMBER_PORTS];
USHORT IrqStatus;
USHORT PortPowerControl;
PHW_32BIT_PHYSICAL_ADDRESS FrameListVA; HW_32BIT_PHYSICAL_ADDRESS FrameListPA;
// Virtual Addresses for the control and bulk queue heads in the
// schedule.
PHCD_QUEUEHEAD_DESCRIPTOR ControlQueueHead; PHCD_QUEUEHEAD_DESCRIPTOR BulkQueueHead; PHCD_QUEUEHEAD_DESCRIPTOR LastBulkQueueHead;
// Virtual Addresses for the interrupt queue heads in the
// schedule.
PHCD_QUEUEHEAD_DESCRIPTOR InterruptQueueHeads[NO_INTERRUPT_QH_LISTS];
// Virtual Address for the TD that gives us an interrupt at the end
// of every frame, so that things don't get stuck in the schedule.
PHCD_TRANSFER_DESCRIPTOR RollOverTd;
UCHAR SavedSOFModify;
PHCD_TD_LIST SofTdList;
} DEVICE_DATA, *PDEVICE_DATA;
/*
Callouts to port driver services */ extern USBPORT_REGISTRATION_PACKET RegistrationPacket;
#define USBPORT_DBGPRINT(dd, l, f, arg0, arg1, arg2, arg3, arg4, arg5) \
RegistrationPacket.USBPORTSVC_DbgPrint((dd), (l), (f), (arg0), (arg1), \ (arg2), (arg3), (arg4), (arg5))
#define USBPORT_GET_REGISTRY_KEY_VALUE(dd, branch, keystring, keylen, data, datalen) \
RegistrationPacket.USBPORTSVC_GetMiniportRegistryKeyValue((dd), (branch), \ (keystring), (keylen), (data), (datalen))
#define USBPORT_INVALIDATE_ROOTHUB(dd) \
RegistrationPacket.USBPORTSVC_InvalidateRootHub((dd))
#define USBPORT_COMPLETE_TRANSFER(dd, ep, tp, status, length) \
RegistrationPacket.USBPORTSVC_CompleteTransfer((dd), (ep), (tp), \ (status), (length))
#define USBPORT_COMPLETE_ISOCH_TRANSFER(dd, ep, tp, iso) \
RegistrationPacket.USBPORTSVC_CompleteIsoTransfer((dd), (ep), (tp), (iso))
#define USBPORT_INVALIDATE_ENDPOINT(dd, ep) \
RegistrationPacket.USBPORTSVC_InvalidateEndpoint((dd), (ep))
#define USBPORT_PHYSICAL_TO_VIRTUAL(addr, dd, ep) \
RegistrationPacket.USBPORTSVC_MapHwPhysicalToVirtual((addr), (dd), (ep))
#define USBPORT_REQUEST_ASYNC_CALLBACK(dd, t, c, cl, f) \
RegistrationPacket.USBPORTSVC_RequestAsyncCallback((dd), (t), \ (c), (cl), (f))
#define USBPORT_READ_CONFIG_SPACE(dd, b, o, l) \
RegistrationPacket.USBPORTSVC_ReadWriteConfigSpace((dd), TRUE, \ (b), (o), (l))
#define USBPORT_WRITE_CONFIG_SPACE(dd, b, o, l) \
RegistrationPacket.USBPORTSVC_ReadWriteConfigSpace((dd), FALSE, \ (b), (o), (l))
#define USBPORT_INVALIDATE_CONTROLLER(dd, s) \
RegistrationPacket.USBPORTSVC_InvalidateController((dd), (s))
#define USBPORT_WAIT(dd, t) \
RegistrationPacket.USBPORTSVC_Wait((dd), (t))
#define USBPORT_NOTIFY_DOUBLEBUFFER(dd, tp, addr, length) \
RegistrationPacket.USBPORTSVC_NotifyDoubleBuffer((dd), (tp), \ (addr), (length))
#ifdef _WIN64
#define DUMMY_TD_CONTEXT ((PVOID) 0xABADBABEABADBABE)
#else
#define DUMMY_TD_CONTEXT ((PVOID) 0xABADBABE)
#endif
#define UhciCheckIsochTransferInsertion(dd, r, df) {\
ULONG cf = UhciGet32BitFrameNumber((dd));\ if ((df) > (cf)) {\ if ((df) < (dd)->LastFrameProcessed + UHCI_MAX_FRAME) \ r = USBD_STATUS_SUCCESS;\ else\ r = USBD_STATUS_PENDING;\ } else {\ if ((df)-(cf) < UHCI_MAX_FRAME )\ r = USBD_STATUS_SUCCESS;\ else \ r = USBD_STATUS_BAD_START_FRAME;}}
//
// This macro is protected from double queueing the TD, by using
// interlocked function. Unless the HwAddress is NULL, it won't
// replace the value.
//
#define INSERT_ISOCH_TD(dd, td, fn) \
(td)->Flags |= TD_FLAG_ISO_QUEUED;\ InterlockedCompareExchange(&(td)->HwTD.LinkPointer.HwAddress,\ *( ((PULONG) ((dd)->FrameListVA)+ACTUAL_FRAME(fn)) ), 0);\ *( ((PULONG) ((dd)->FrameListVA)+ACTUAL_FRAME(fn)) ) = \ (td)->PhysicalAddress;
//
// Must account for both the regular and overflow cases:
//
/*#define CAN_INSERT_ISOCH_TD(fr, cfr) \
((fr - cfr < USBUHCI_MAX_FRAME) ||\ ((fr + cfr < USBUHCI_MAX_FRAME) && fr < USBUHCI_MAX_FRAME))
#define INSERT_ISOCH_TD(dd, td, ep) \
(td)->PrevTd = (PHCD_TRANSFER_DESCRIPTOR)((PULONG) ((dd)->FrameListVA) + \ ACTUAL_FRAME((td)->IsoPacket->FrameNumber)); \ (td)->HwTD.LinkPointer.HwAddress = (td)->PrevTd->HwTD.LinkPointer.HwAddress; \ if (!(td)->HwTD.LinkPointer.QHTDSelect) {\ PHCD_TRANSFER_DESCRIPTOR rtd = (PHCD_TRANSFER_DESCRIPTOR)\ USBPORT_PHYSICAL_TO_VIRTUAL((td)->HwTD.LinkPointer.HwAddress, \ (dd), \ (ep));\ rtd->PrevTd = (td);\ }\ (td)->PrevTd->HwTD.LinkPointer.HwAddress = td->PhysicalAddress;
#define REMOVE_ISOCH_TD(td) \
(td)->PrevTd->HwTD.LinkPointer.HwAddress = (td)->HwTD.LinkPointer.HwAddress; */
// We must set the frame to the highest ULONG prior to setting the
// TD_FLAG_XFER flag, so that this TD doesn't get completed before
// we've had chance to queue it.
#define INITIALIZE_TD_FOR_TRANSFER(td, tc) \
(td)->TransferContext = (tc);\ (td)->Flags |= TD_FLAG_XFER; \ (td)->HwTD.LinkPointer.HwAddress = 0;\ (td)->HwTD.Control.ul = 0;\ (td)->HwTD.Control.LowSpeedDevice = ((tc)->EndpointData->Parameters.DeviceSpeed == LowSpeed);\ (td)->HwTD.Control.Active = 1;\ (td)->HwTD.Control.ErrorCount = 3;\ (td)->HwTD.Token.ul = 0;\ (td)->HwTD.Token.Endpoint = (tc)->EndpointData->Parameters.EndpointAddress;\ (td)->HwTD.Token.DeviceAddress = (tc)->EndpointData->Parameters.DeviceAddress;\ (td)->NextTd = NULL;
#define SET_QH_TD(dd, ed, td) {\
TD_LINK_POINTER newLink;\ if ((td)) {\ (ed)->HeadTd = (td);\ } else {\ (ed)->HeadTd = (ed)->TailTd = NULL;\ }\ if (!(td) || TEST_FLAG((ed)->Flags, UHCI_EDFLAG_HALTED)) {\ newLink.HwAddress = 0;\ newLink.Terminate = 1;\ } else {\ newLink.HwAddress = (td)->PhysicalAddress;\ newLink.Terminate = 0;\ }\ newLink.QHTDSelect = 0;\ LOGENTRY((dd), G, '_sqt', (td), (ed), 0);\ (ed)->QueueHead->HwQH.VLink = newLink;}
/*#define SET_QH_TD_NULL(qh) \
{ TD_LINK_POINTER newLink;\ newLink.HwAddress = 0;\ newLink.Terminate = 1;\ newLink.QHTDSelect = 0;\ (qh)->HwQH.VLink = newLink;\ } */ #define SET_NEXT_TD(linkTd, nextTd) \
(linkTd)->HwTD.LinkPointer.HwAddress = (nextTd)->PhysicalAddress;\ (linkTd)->HwTD.LinkPointer.Terminate = 0;\ (linkTd)->HwTD.LinkPointer.QHTDSelect = 0;\ (linkTd)->HwTD.LinkPointer.DepthBreadthSelect = 0;\ (linkTd)->NextTd = (nextTd);
#define SET_NEXT_TD_NULL(linkTd) \
(linkTd)->NextTd = NULL;\ (linkTd)->HwTD.LinkPointer.HwAddress = 0;\ (linkTd)->HwTD.LinkPointer.Terminate = 1;
#define PAGE_CROSSING(PhysicalAddress, length) \
((PhysicalAddress+length)%PAGE_SIZE < length && (PhysicalAddress+length)%PAGE_SIZE != 0)
#ifdef _WIN64
#define UHCI_BAD_POINTER ((PVOID) 0xDEADFACEDEADFACE)
#else
#define UHCI_BAD_POINTER ((PVOID) 0xDEADFACE)
#endif
#define UHCI_BAD_HW_POINTER 0x0BADF00D
// Note how we free any double buffering in here instead of relying
// on the c code to do it.
#define UHCI_FREE_TD(dd, ep, td) \
if (TEST_FLAG((td)->Flags, TD_FLAG_DOUBLE_BUFFERED)) { \ UHCI_FREE_DB((dd), (ep), (td)->DoubleBuffer);}\ (ep)->TdsUsed--;\ (td)->HwTD.LinkPointer.HwAddress = UHCI_BAD_HW_POINTER;\ LOGENTRY((dd), G, '_fTD', (td), (ep), 0);\ (td)->TransferContext = UHCI_BAD_POINTER;\ (td)->Flags = 0;
#define UHCI_ALLOC_TD(dd, ep) UhciAllocTd((dd), (ep));
#define UHCI_FREE_DB(dd, ep, db) \
LOGENTRY((dd), G, '_fDB', (db), (ep), 0);\ (ep)->DbsUsed--;\ if ((ep)->Parameters.TransferType == Isochronous) { (db)->Isoch.Flags = 0; }\ else { (db)->Async.Flags = 0; }
#define UHCI_ALLOC_DB(dd, ep, i) UhciAllocDb((dd), (ep), (i));
// bugbug UHCI_ASSERT((dd), (ed)->PendingTransfers);
#define DecPendingTransfers(dd, ed) \
InterlockedDecrement(&(ed)->PendingTransfers);\ if ((ed)->Parameters.TransferType == Isochronous)\ InterlockedDecrement(&(dd)->IsoPendingTransfers);
#define ActivateRolloverTd(dd) \
*( ((PULONG) ((dd)->FrameListVA)) ) = (dd)->RollOverTd->PhysicalAddress;
//#define IncPendingTransfers(dd, ed) \ // InterlockedIncrement(&(ed)->PendingTransfers);\ // if ((ed)->Parameters.TransferType == Isochronous) {\ // if (1 == InterlockedIncrement(&(dd)->IsoPendingTransfers)) {\ // //*( ((PULONG) ((dd)->FrameListVA)) ) = (dd)->RollOverTd->PhysicalAddress; \
// (dd)->LastFrameProcessed = UhciGet32BitFrameNumber((dd));\ // }}
// bugbug UHCI_ASSERT((dd), (ed)->PendingTransfers);
#define IncPendingTransfers(dd, ed) \
InterlockedIncrement(&(ed)->PendingTransfers);\ if ((ed)->Parameters.TransferType == Isochronous) {\ if (1 == InterlockedIncrement(&(dd)->IsoPendingTransfers)) {\ (dd)->LastFrameProcessed = UhciGet32BitFrameNumber((dd));\ }} // bugbug UHCI_ASSERT((dd), (ed)->PendingTransfers);
#define UhciCleanFrameOfIsochTds(dd, i)\
if ((i) == 0) {\ *( ((PULONG) ((dd)->FrameListVA)) ) = (dd)->RollOverTd->PhysicalAddress;\ } else {\ QH_LINK_POINTER newLink;\ newLink.HwAddress = (dd)->InterruptQueueHeads[QH_INTERRUPT_32ms + MAX_INTERVAL_MASK((i))]->PhysicalAddress;\ newLink.QHTDSelect = 1;\ *( ((PULONG) ((dd)->FrameListVA)+(i)) ) = newLink.HwAddress;\ }
#define TEST_BIT(value, bitNumber) ((value) & (1<<(bitNumber))) ? TRUE : FALSE
#define SET_BIT(value, bitNumber) ((value) |= (1<<(bitNumber)))
#define CLEAR_BIT(value, bitNumber) ((value) &= ~(1<<(bitNumber)))
//
// Controller functions
//
USB_MINIPORT_STATUS USBMPFN UhciStartController( IN PDEVICE_DATA DeviceData, IN PHC_RESOURCES HcResources );
VOID USBMPFN UhciStopController( IN PDEVICE_DATA DeviceData, IN BOOLEAN HwPresent );
VOID USBMPFN UhciSuspendController( IN PDEVICE_DATA DeviceData );
USB_MINIPORT_STATUS USBMPFN UhciResumeController( IN PDEVICE_DATA DeviceData );
VOID USBMPFN UhciPollController( IN PDEVICE_DATA DeviceData );
ULONG USBMPFN UhciGet32BitFrameNumber( IN PDEVICE_DATA DeviceData );
VOID USBMPFN UhciInterruptNextSOF( IN PDEVICE_DATA DeviceData );
VOID UhciUpdateCounter( IN PDEVICE_DATA DeviceData );
VOID UhciDisableAsyncList( IN PDEVICE_DATA DeviceData );
VOID UhciInitailizeInterruptSchedule( IN PDEVICE_DATA DeviceData );
VOID UhciEnableAsyncList( IN PDEVICE_DATA DeviceData );
USB_MINIPORT_STATUS USBMPFN UhciPassThru ( IN PDEVICE_DATA DeviceData, IN GUID *FunctionGuid, IN ULONG ParameterLength, IN OUT PVOID Parameters );
//
// Root hub functions
//
VOID USBMPFN UhciRHGetRootHubData( IN PDEVICE_DATA DeviceData, OUT PROOTHUB_DATA HubData );
USB_MINIPORT_STATUS USBMPFN UhciRHGetStatus( IN PDEVICE_DATA DeviceData, OUT PUSHORT Status );
USB_MINIPORT_STATUS USBMPFN UhciRHGetHubStatus( IN PDEVICE_DATA DeviceData, OUT PRH_HUB_STATUS HubStatus );
VOID USBMPFN UhciRHDisableIrq( IN PDEVICE_DATA DeviceData );
VOID USBMPFN UhciRHEnableIrq( IN PDEVICE_DATA DeviceData );
//
// Root hub port functions
//
USB_MINIPORT_STATUS USBMPFN UhciRHSetFeaturePortReset( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHSetFeaturePortSuspend( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortSuspend( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHSetFeaturePortPower( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortPower( IN PDEVICE_DATA DeviceData, IN USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHSetFeaturePortEnable( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortEnable( IN PDEVICE_DATA DeviceData, IN USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHGetPortStatus( PDEVICE_DATA DeviceData, USHORT PortNumber, PRH_PORT_STATUS portStatus );
//
// Clear change bits for hub ports
//
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortConnectChange( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortResetChange( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortSuspendChange( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortOvercurrentChange( PDEVICE_DATA DeviceData, USHORT PortNumber );
USB_MINIPORT_STATUS USBMPFN UhciRHClearFeaturePortEnableChange( PDEVICE_DATA DeviceData, USHORT PortNumber );
//
// Interrupt functions
//
BOOLEAN USBMPFN UhciInterruptService ( IN PDEVICE_DATA DeviceData );
VOID USBMPFN UhciEnableInterrupts( IN PDEVICE_DATA DeviceData );
VOID USBMPFN UhciInterruptDpc ( IN PDEVICE_DATA DeviceData, IN BOOLEAN EnableInterrupts );
VOID USBMPFN UhciDisableInterrupts( IN PDEVICE_DATA DeviceData );
//
// Endpoint functions
//
USB_MINIPORT_STATUS USBMPFN UhciOpenEndpoint( IN PDEVICE_DATA DeviceData, IN PENDPOINT_PARAMETERS EndpointParameters, OUT PENDPOINT_DATA EndpointData );
USB_MINIPORT_STATUS USBMPFN UhciPokeEndpoint( IN PDEVICE_DATA DeviceData, IN PENDPOINT_PARAMETERS EndpointParameters, OUT PENDPOINT_DATA EndpointData );
USB_MINIPORT_STATUS USBMPFN UhciQueryEndpointRequirements( IN PDEVICE_DATA DeviceData, IN PENDPOINT_PARAMETERS EndpointParameters, OUT PENDPOINT_REQUIREMENTS EndpointRequirements );
VOID USBMPFN UhciCloseEndpoint( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData );
VOID USBMPFN UhciAbortTransfer( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PTRANSFER_CONTEXT TransferContext, OUT PULONG BytesTransferred );
USB_MINIPORT_STATUS USBMPFN UhciStartSendOnePacket( IN PDEVICE_DATA DeviceData, IN PMP_PACKET_PARAMETERS PacketParameters, IN PUCHAR PacketData, IN PULONG PacketLength, IN PUCHAR WorkspaceVirtualAddress, IN HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress, IN ULONG WorkSpaceLength, IN OUT USBD_STATUS *UsbdStatus );
USB_MINIPORT_STATUS USBMPFN UhciEndSendOnePacket( IN PDEVICE_DATA DeviceData, IN PMP_PACKET_PARAMETERS PacketParameters, IN PUCHAR PacketData, IN PULONG PacketLength, IN PUCHAR WorkspaceVirtualAddress, IN HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress, IN ULONG WorkSpaceLength, IN OUT USBD_STATUS *UsbdStatus );
VOID USBMPFN UhciSetEndpointStatus( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN MP_ENDPOINT_STATUS Status );
MP_ENDPOINT_STATUS USBMPFN UhciGetEndpointStatus( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData );
PHCD_QUEUEHEAD_DESCRIPTOR UhciInitializeQH( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PHCD_QUEUEHEAD_DESCRIPTOR Qh, IN HW_32BIT_PHYSICAL_ADDRESS HwPhysAddress );
VOID USBMPFN UhciSetEndpointDataToggle( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN ULONG Toggle );
VOID USBMPFN UhciPollEndpoint( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData );
MP_ENDPOINT_STATE USBMPFN UhciGetEndpointState( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData );
VOID USBMPFN UhciSetEndpointState( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN MP_ENDPOINT_STATE State );
VOID UhciSetAsyncEndpointState( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN MP_ENDPOINT_STATE State );
USB_MINIPORT_STATUS USBMPFN UhciSubmitTransfer( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PTRANSFER_PARAMETERS TransferUrb, IN PTRANSFER_CONTEXT TransferContext, IN PTRANSFER_SG_LIST TransferSGList );
//
// Async
//
VOID UhciProcessDoneAsyncTd( PDEVICE_DATA DeviceData, PHCD_TRANSFER_DESCRIPTOR Td );
VOID UhciPollAsyncEndpoint( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData );
USB_MINIPORT_STATUS UhciBulkOrInterruptTransfer( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PTRANSFER_PARAMETERS TransferParameters, IN PTRANSFER_CONTEXT TransferContext, IN PTRANSFER_SG_LIST TransferSGList );
VOID UhciUnlinkQh( IN PDEVICE_DATA DeviceData, IN PHCD_QUEUEHEAD_DESCRIPTOR Qh );
VOID UhciAbortAsyncTransfer( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PTRANSFER_CONTEXT TransferContext, OUT PULONG BytesTransferred );
VOID UhciInsertQh( IN PDEVICE_DATA DeviceData, IN PHCD_QUEUEHEAD_DESCRIPTOR FirstQh, IN PHCD_QUEUEHEAD_DESCRIPTOR LinkQh );
USB_MINIPORT_STATUS UhciControlTransfer( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PTRANSFER_PARAMETERS TransferUrb, IN PTRANSFER_CONTEXT TransferContext, IN PTRANSFER_SG_LIST TransferSGList );
//
// Isoch
//
USB_MINIPORT_STATUS USBMPFN UhciIsochTransfer( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PTRANSFER_PARAMETERS TransferParameters, IN PTRANSFER_CONTEXT TransferContext, IN PMINIPORT_ISO_TRANSFER IsoTransfer );
VOID UhciPollIsochEndpoint( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData );
VOID UhciAbortIsochTransfer( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN PTRANSFER_CONTEXT TransferContext );
VOID UhciSetIsochEndpointState( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN MP_ENDPOINT_STATE State );
VOID UhciCleanOutIsoch( IN PDEVICE_DATA DeviceData, IN BOOLEAN ForceClean );
//
// Utility
//
USBD_STATUS UhciGetErrorFromTD( PDEVICE_DATA DeviceData, PHCD_TRANSFER_DESCRIPTOR Td );
PHCD_TRANSFER_DESCRIPTOR UhciAllocTd( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData );
PTRANSFER_BUFFER UhciAllocDb( IN PDEVICE_DATA DeviceData, IN PENDPOINT_DATA EndpointData, IN BOOLEAN Isoch );
//
// Bios handoff and handback
//
USB_MINIPORT_STATUS UhciStopBIOS( IN PDEVICE_DATA DeviceData, IN PHC_RESOURCES HcResources );
ULONG UhciQueryControlRequirements( IN PDEVICE_DATA DeviceData, IN PENDPOINT_PARAMETERS EndpointParameters, IN OUT PULONG NumberOfTDs, IN OUT PULONG NumberOfDoubleBuffers );
ULONG UhciQueryBulkRequirements( IN PDEVICE_DATA DeviceData, IN PENDPOINT_PARAMETERS EndpointParameters, IN OUT PULONG NumberOfTDs, IN OUT PULONG NumberOfDoubleBuffers );
ULONG UhciQueryIsoRequirements( IN PDEVICE_DATA DeviceData, IN PENDPOINT_PARAMETERS EndpointParameters, IN OUT PULONG NumberOfTDs, IN OUT PULONG NumberOfDoubleBuffers );
ULONG UhciQueryInterruptRequirements( IN PDEVICE_DATA DeviceData, IN PENDPOINT_PARAMETERS EndpointParameters, IN OUT PULONG NumberOfTDs, IN OUT PULONG NumberOfDoubleBuffers );
BOOLEAN UhciHardwarePresent( PDEVICE_DATA DeviceData );
VOID UhciCheckController( PDEVICE_DATA DeviceData );
VOID UhciFlushInterrupts( IN PDEVICE_DATA DeviceData ); /*
USB_MINIPORT_STATUS UhciStartBIOS( IN PDEVICE_DATA DeviceData ); */
#endif /* __USBUHCI_H__ */
|