Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1185 lines
31 KiB

/*++
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__ */