|
|
/*++
Copyright (c) 1993 Microsoft Corporation :ts=4
Module Name:
uhcd.h
Abstract:
This module contains the PRIVATE definitions for the code that implements the UHC device driver for USB.
Environment:
Kernel & user mode
Revision History:
10-27-95 : created
--*/
#ifndef __UHCD_H__
#define __UHCD_H__
//enable pageable code
#ifndef PAGE_CODE
#define PAGE_CODE
#endif
#if !defined(max)
#define max(a, b) (a > b ? a : b)
#endif // !defined(max)
/*
Registry Keys */
// Disables selective suspend for the root hub ports.
// this behavior is the default for the PIIX3 or PIIX4 because
// of hardware bugs -- it is off (ie sel suspend enabled)
// for all other UHCI controllers unless this key is set
#define DISABLE_SELECTIVE_SUSPEND L"DisableSelectiveSuspend"
// used to overide the default clock timing in the host controller
// hardware.
// Some motherboard designs use a cheap clock crystal -- if so there
// is an adjustment that must be made to the SOF clock.
// This system BIOS should do this but if it does not there is a
// utility that can be run to determine the correct value which can
// then be set with these registry keys
#define CLOCKS_PER_FRAME L"timingClocksPerFrame"
#define REC_CLOCKS_PER_FRAME L"recommendedClocksPerFrame"
#define DEBUG_LEVEL L"debuglevel"
#define DEBUG_WIN9X L"debugWin9x"
/*****/
#define LEGSUP_HCD_MODE 0x2000 // value to put in LEGSUP reg for normal HCD use JMD
#define LEGSUP_BIOS_MODE 0x00BF // value to put in LEGSUP reg for BIOS/SMI use JMD
#define LEGSUP_USBPIRQD_EN 0x2000 // bit 13
//
// Defines for enabling certian host controller driver features
#define VIA_HC // enable support for the VIA version of the
// Universal Host Controller
#define ENABLE_B0_FEATURES // enable B0 optimizations
#define RECLAIM_BW // enable bandwidth reclimation for bulk
#include "usbdlibi.h"
#include "usbdlib.h"
#include "roothub.h"
//
// total bandwidth in bits/ms
//
#define UHCD_TOTAL_USB_BW 12000
//
// 10% reserved for bulk and control
//
#define UHCD_BULK_CONTROL_BW (UHCD_TOTAL_USB_BW/10)
//
// Number of times to try and get controller out of hung frame counter
// state before giving up (approx. 4ms per shot)
//
#define UHCD_MAX_KICK_STARTS 3
//
// enable USB BIOS support
//
#define USB_BIOS
//
// enable root hub support
//
#define ROOT_HUB
// flag to enable debug timing code
#if DBG
//#define DBG_TIMING
#define DEBUG_LOG
#endif
#define FRAME_LIST_SIZE 1024
// number of bit times in a USB frame based on a 12MHZ SOF clock
#define UHCD_12MHZ_SOF 11936
//
// we keep a list of TDs for use as interrupt triggers,
// frame rollover detection and error recovery
// TDs 0,1 are used for frame rollover
// TD 2 is used for error recovery
// TD 3,4 reserved for PIIX4 hack
// TDs 5+ are used as triggers
//
#define UHCD_FIRST_TRIGGER_TD 5
#include "dbg.h"
//
// This is (on average) how many ms we can expect it to take for us to get an
// iso request in to the schedule.
//
#define UHCD_ASAP_LATENCY 5
//
// UHCD pending status values
//
// Urb is the current urb being serviced for the endpoint
#define UHCD_STATUS_PENDING_CURRENT \
(((USBD_STATUS)0x00000001L) | USBD_STATUS_PENDING)
// Urb is queued to the endpoint
#define UHCD_STATUS_PENDING_QUEUED \
(((USBD_STATUS)0x00000002L) | USBD_STATUS_PENDING)
// Urb is being canceled in hardware
#define UHCD_STATUS_PENDING_CANCELING \
(((USBD_STATUS)0x00000003L) | USBD_STATUS_PENDING)
// Urb in hardware needs to be canceled
#define UHCD_STATUS_PENDING_XXX \
(((USBD_STATUS)0x00000004L) | USBD_STATUS_PENDING)
// the Urb is queued to the startio routine
#define UHCD_STATUS_PENDING_STARTIO \
(((USBD_STATUS)0x00000005L) | USBD_STATUS_PENDING) //
// Macros used to keep track of how many pending urbs are
// associated with an endpoint.
//
#define DECREMENT_PENDING_URB_COUNT(irp) \
(((LONG)(ULONG_PTR)(IoGetCurrentIrpStackLocation(irp))->\ Parameters.Others.Argument2)--) #define INCREMENT_PENDING_URB_COUNT(irp) \
(((LONG)(ULONG_PTR)(IoGetCurrentIrpStackLocation(irp))->\ Parameters.Others.Argument2)++) #define PENDING_URB_COUNT(irp) \
(((LONG)(ULONG_PTR)(IoGetCurrentIrpStackLocation(irp))->\ Parameters.Others.Argument2))
#define URB_HEADER(u) ((u)->UrbHeader)
#define HCD_AREA(u) ((u)->HcdUrbCommonTransfer.hca)
//
// number of bytes to allocate for a frame list
//
#define FRAME_LIST_LENGTH (FRAME_LIST_SIZE * \
sizeof(HW_DESCRIPTOR_PHYSICAL_ADDRESS))
//
// Stepping Versions of the UHCI host controller
//
#define UHCD_A1_STEP 0
#define UHCD_B0_STEP 1
#define UHCI_HW_VERSION_UNKNOWN 0
#define UHCI_HW_VERSION_PIIX3 1
#define UHCI_HW_VERSION_PIIX4 2
#define UHCI_HW_VERSION_82460GXPIIX6 3 // IA64 PowerOn
//
// values for the HCD_EXTENSION flags field
//
#define UHCD_TRANSFER_ACTIVE 0x01
#define UHCD_TRANSFER_INITIALIZED 0x02
#define UHCD_MAPPED_LOCKED_PAGES 0x04
#define UHCD_TRANSFER_MAPPED 0x08
#define UHCD_TRANSFER_DEFER 0x10
#define UHCD_TOGGLE_READY 0x20
#define LOCK_ENDPOINT_PENDING_LIST(ep, irql, sig) \
KeAcquireSpinLock(&(ep)->PendingListSpin, &(irql)); \ LOGENTRY(LOG_MISC, sig, ep, irql, 0);\ UHCD_LockAccess(&(ep)->AccessPendingList);
#define UNLOCK_ENDPOINT_PENDING_LIST(ep, irql, sig) \
UHCD_UnLockAccess(&(ep)->AccessPendingList); \ LOGENTRY(LOG_MISC, sig, ep, irql, 0);\ KeReleaseSpinLock(&(ep)->PendingListSpin, irql);
#define LOCK_ENDPOINT_ACTIVE_LIST(ep, irql) \
KeAcquireSpinLock(&ep->ActiveListSpin, &irql); \ UHCD_LockAccess(&(ep)->AccessActiveList);
#define UNLOCK_ENDPOINT_ACTIVE_LIST(ep, irql) \
UHCD_UnLockAccess(&(ep)->AccessActiveList); \ KeReleaseSpinLock(&(ep)->ActiveListSpin, irql);
#define LOCK_ENDPOINT_LIST(de, irql) \
KeAcquireSpinLock(&(de)->EndpointListSpin, &irql);
#define UNLOCK_ENDPOINT_LIST(de, irql) \
KeReleaseSpinLock(&(de)->EndpointListSpin, irql);
//
// Maximum Polling Interval we support (ms)
//
//BUGBUG should be 32
#define MAX_INTERVAL 32
//
// Definitions for Common Buffer sizes,
// these are the buffers we use for TDs and
// double buffering packets.
//
//
// Needs to be big enough for all the TDs plus a queue header
// and a scratch buffer
//
#define UHCD_LARGE_COMMON_BUFFER_SIZE \
((MAX_TDS_PER_ENDPOINT+2) * UHCD_HW_DESCRIPTOR_SIZE) //#define UHCD_LARGE_COMMON_BUFFER_SIZE 1023
// size of largest packet (iso)
//
// Big enough for 8 TDs plus queue head plus scratch buffer
//
#define UHCD_MEDIUM_COMMON_BUFFER_SIZE \
((MIN_TDS_PER_ENDPOINT+2) * UHCD_HW_DESCRIPTOR_SIZE)
#define UHCD_SMALL_COMMON_BUFFER_SIZE 128
//
// This is the number of buffers we hold in reserve -- we grow the free pool
// whenever we allocate at passive to maintain the reserve pool. The idea
// here is to minimize the frequency that we have to call
// HalAllocateCommonBuffer from DPC level.
//
// buffers needed during DPC time will be typically packet buffers
// (needed to double buffer packets that cross page boundries)
//
// BUGBUG
// Currently NTKERN will fail any calls to HalAllocateCommonBuffer at DPC
// level so these values are unususally large.
//
#define UHCD_RESERVE_LARGE_BUFFERS 16
#define UHCD_RESERVE_MEDIUM_BUFFERS 32
#define UHCD_RESERVE_SMALL_BUFFERS 32
#define UHCD_MAX_ACTIVE_TRANSFERS 4
//
// The last four bits of a descriptor ptr are defined as control
// flag bits.
//
#define UHCD_CF_TERMINATE_BIT 0
#define UHCD_CF_TERMINATE (1<<UHCD_CF_TERMINATE_BIT)
#define UHCD_CF_QUEUE_BIT 1
#define UHCD_CF_QUEUE (1<<UHCD_CF_QUEUE_BIT)
#define UHCD_CF_VERTICAL_FIRST_BIT 2
#define UHCD_CF_VERTICAL_FIRST (1<<UHCD_CF_VERTICAL_FIRST_BIT)
#define UHCD_CF_RESERVED_BIT 3
#define UHCD_CF_RESERVED (1<<UHCD_CF_RESERVED_BIT)
#define SET_T_BIT(x) (x |= UHCD_CF_TERMINATE)
#define SET_Q_BIT(x) (x |= UHCD_CF_QUEUE)
#define CLEAR_T_BIT(x) (x &= ~UHCD_CF_TERMINATE)
#define UHCD_DESCRIPTOR_PTR_MASK 0xfffffff0
#define UHCD_DESCRIPTOR_FLAGS_MASK 0x0000000f
//
// Macros for manipulating descriptors
//
#define TD_PTR(descriptor) ((PHW_TRANSFER_DESCRIPTOR) descriptor)
#define QH_PTR(descriptor) ((PHW_QUEUE_HEAD) descriptor)
#define LIST_END (UHCD_CF_TERMINATE)
//
// MACROS for USB controller registers
//
#define COMMAND_REG(deviceExtension) \
((PUSHORT) (deviceExtension->DeviceRegisters[0])) #define STATUS_REG(deviceExtension) \
((PUSHORT) (deviceExtension->DeviceRegisters[0] + 0x02)) #define INTERRUPT_MASK_REG(deviceExtension) \
((PUSHORT) (deviceExtension->DeviceRegisters[0] + 0x04)) #define FRAME_LIST_CURRENT_INDEX_REG(deviceExtension) \
((PUSHORT) (deviceExtension->DeviceRegisters[0] + 0x06)) #define FRAME_LIST_BASE_REG(deviceExtension) \
((PULONG) (deviceExtension->DeviceRegisters[0] + 0x08)) #define SOF_MODIFY_REG(deviceExtension) \
((PUCHAR) (deviceExtension->DeviceRegisters[0] + 0x0C)) #define PORT1_REG(deviceExtension) \
((PUSHORT) (deviceExtension->DeviceRegisters[0] + 0x10)) #define PORT2_REG(deviceExtension) \
((PUSHORT) (deviceExtension->DeviceRegisters[0] + 0x12))
//
// Interrupt Mask register bits
//
#define UHCD_INT_MASK_SHORT_BIT 3
#define UHCD_INT_MASK_SHORT (1<<UHCD_INT_MASK_SHORT_BIT)
#define UHCD_INT_MASK_IOC_BIT 2
#define UHCD_INT_MASK_IOC (1<<UHCD_INT_MASK_IOC_BIT)
#define UHCD_INT_MASK_RESUME_BIT 1
#define UHCD_INT_MASK_RESUME (1<<UHCD_INT_MASK_RESUME_BIT)
#define UHCD_INT_MASK_TIMEOUT_BIT 0
#define UHCD_INT_MASK_TIMEOUT (1<<UHCD_INT_MASK_TIMEOUT_BIT)
//
// Port Register Bits
//
// BUGBUG these are for hub port control
#define UHCD_PORT_ENABLE_BIT 2
#define UHCD_PORT_ENABLE (1<<UHCD_PORT_ENABLE_BIT)
//
// Command Register Bits
//
#define UHCD_CMD_RUN_BIT 0
#define UHCD_CMD_RUN (USHORT)(1<<UHCD_CMD_RUN_BIT)
#define UHCD_CMD_RESET_BIT 1
#define UHCD_CMD_RESET (USHORT)(1<<UHCD_CMD_RESET_BIT)
#define UHCD_CMD_GLOBAL_RESET_BIT 2
#define UHCD_CMD_GLOBAL_RESET (USHORT)(1<<UHCD_CMD_GLOBAL_RESET_BIT)
#define UHCD_CMD_SUSPEND_BIT 3
#define UHCD_CMD_SUSPEND (USHORT)(1<<UHCD_CMD_SUSPEND_BIT)
#define UHCD_CMD_FORCE_RESUME_BIT 4
#define UHCD_CMD_FORCE_RESUME (USHORT)(1<<UHCD_CMD_FORCE_RESUME_BIT)
#define UHCD_CMD_SW_DEBUG_BIT 5
#define UHCD_CMD_SW_DEBUG (USHORT)(1<<UHCD_CMD_SW_DEBUG_BIT)
#define UHCD_CMD_SW_CONFIGURED_BIT 6
#define UHCD_CMD_SW_CONFIGURED (USHORT)(1<<UHCD_CMD_SW_CONFIGURED_BIT)
#define UHCD_CMD_MAXPKT_64_BIT 7
#define UHCD_CMD_MAXPKT_64 (USHORT)(1<<UHCD_CMD_MAXPKT_64_BIT)
//
// Status Register Bits
//
#define UHCD_STATUS_USBINT_BIT 0
#define UHCD_STATUS_USBINT (1<<UHCD_STATUS_USBINT_BIT)
#define UHCD_STATUS_USBERR_BIT 1
#define UHCD_STATUS_USBERR (1<<UHCD_STATUS_USBERR_BIT)
#define UHCD_STATUS_RESUME_BIT 2
#define UHCD_STATUS_RESUME (1<<UHCD_STATUS_RESUME_BIT)
#define UHCD_STATUS_PCIERR_BIT 3
#define UHCD_STATUS_PCIERR (1<<UHCD_STATUS_PCIERR_BIT)
#define UHCD_STATUS_HCERR_BIT 4
#define UHCD_STATUS_HCERR (1<<UHCD_STATUS_HCERR_BIT)
#define UHCD_STATUS_HCHALT_BIT 5
#define UHCD_STATUS_HCHALT (1<<UHCD_STATUS_HCHALT_BIT)
//
// opcodes for Create/Allocate/Free Descriptor functions
//
#define QUEUE_HEAD 0
#define TRANSFER_DESCRIPTOR_LIST 1
#define UHCD_INTEL_VENDOR_ID 0x8086
#define UHCD_PIIX3_DEVICE_ID 0x7020
#define UHCD_PIIX4_DEVICE_ID 0x7112
#define UHCD_82460GXPIIX6_DEVICE_ID 0x7602 //IA64 PowerOn
#define MAX_TDS_PER_ENDPOINT 64
#define MIN_TDS_PER_ENDPOINT 8
// computes the size of a common buffer needed for an endpoint
// with n TDs.
// plus one for scratch buffer and one for queue head (+2)
#define TD_LIST_SIZE(n) (((n)+2)*UHCD_HW_DESCRIPTOR_SIZE)
//bugbug change to UHCD to HC
typedef PVOID HW_DESCRIPTOR_PTR; typedef ULONG HW_DESCRIPTOR_PHYSICAL_ADDRESS;
//
// bit values for StatusField
//
#define TD_STATUS_BITSTUFF_BIT 0
#define TD_STATUS_BITSTUFF (1<<TD_STATUS_BITSTUFF_BIT)
#define TD_STATUS_CRC_TIMEOUT_BIT 1
#define TD_STATUS_CRC_TIMEOUT (1<<TD_STATUS_CRC_TIMEOUT_BIT)
#define TD_STATUS_NAK_BIT 2
#define TD_STATUS_NAK (1<<TD_STATUS_NAK_BIT)
#define TD_STATUS_BABBLE_BIT 3
#define TD_STATUS_BABBLE (1<<TD_STATUS_BABBLE_BIT)
#define TD_STATUS_FIFO_BIT 4
#define TD_STATUS_FIFO (1<<TD_STATUS_FIFO_BIT)
#define TD_STATUS_STALL_BIT 5
#define TD_STATUS_STALL (1<<TD_STATUS_STALL_BIT)
typedef struct _UHCD_BUFFER_POOL { SINGLE_LIST_ENTRY MemoryDescriptorFreePool; //
// BUGBUG is it worth padding here to make space
// between the spinlock and the list?
//
ULONG Sig; ULONG MaximumFreeBuffers; ULONG CommonBufferLength; KSPIN_LOCK MemoryDescriptorFreePoolSpin; } UHCD_BUFFER_POOL, *PUHCD_BUFFER_POOL;
//
// To figure out padding for multiple architectures, we use
// this macro; if we wanted to be fancy we could do bitwise rounding,
// but this is obfuscated enough. Let the compiler do the math for us.
//
#define UHCD_SPAD(T, align) \
((align) - (sizeof(T) % (align)) + sizeof(T)) //
// Take advantage of the fact that the MS compiler supports
// variant structs and unions so that we can get the proper padding
// for our structures. Put in lots of C_ASSERT()s just to be sure
// nothing goes really really bad.
//
//
// Structure for tracking blocks of memory containing HW
// descriptors or packet buffers
//
struct _UHCD_MEMORY_DESCRIPTOR_INTERNAL { ULONG Sig; PUCHAR VirtualAddress; // virtual address for the start of this
// block
HW_DESCRIPTOR_PHYSICAL_ADDRESS LogicalAddress; // Address we can give the HC.
ULONG Length; // length in bytes
ULONG InUse; // in use count, bummped when we alloc
SINGLE_LIST_ENTRY SingleListEntry; PUHCD_BUFFER_POOL BufferPool; // buffer pool that owns this MD
ULONG Pad; };
struct _HW_QUEUE_HEAD_INTERNAL { HW_DESCRIPTOR_PHYSICAL_ADDRESS HW_HLink; // used by host controller hardware
HW_DESCRIPTOR_PHYSICAL_ADDRESS HW_VLink; // used by host controller hardware
//
// These fields are for software use
//
ULONG Sig; HW_DESCRIPTOR_PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this QH
struct _HW_QUEUE_HEAD *Next; struct _HW_QUEUE_HEAD *Prev; // used for keeping track of where it is in
// the schedule
struct _UHCD_ENDPOINT *Endpoint; ULONG Flags; };
//
//
// This structure aligns to 16 bytes
//
struct _HW_TRANSFER_DESCRIPTOR_INTERNAL { HW_DESCRIPTOR_PHYSICAL_ADDRESS HW_Link;
ULONG ActualLength:11; /* 0 ..10 */ ULONG Reserved_1:6; /* 11..16 */ ULONG StatusField:6; /* 17..22 */ ULONG Active:1; /* 23 */ ULONG InterruptOnComplete:1; /* 24 */ ULONG Isochronous:1; /* 25 */ ULONG LowSpeedControl:1; /* 26 */ ULONG ErrorCounter:2; /* 27..28 */ ULONG ShortPacketDetect:1; /* 29 */ ULONG ReservedMBZ:2; /* 30..31 */
ULONG PID:8; /* 0..7 */ ULONG Address:7; /* 8..14 */ ULONG Endpoint:4; /* 15..18 */ ULONG RetryToggle:1; /* 19 */ ULONG Reserved_2:1; /* 20 */ ULONG MaxLength:11; /* 21..31 */
HW_DESCRIPTOR_PHYSICAL_ADDRESS PacketBuffer;
//
// These fields are for software use
//
ULONG Sig; HW_DESCRIPTOR_PHYSICAL_ADDRESS PhysicalAddress; ULONG Frame; //BUGBUG used to preprocess isoch Urbs
PHCD_URB Urb; };
typedef struct _HW_TRANSFER_DESCRIPTOR { union { //
// For addressing
//
struct _HW_TRANSFER_DESCRIPTOR_INTERNAL;
//
// The compiler will pick the biggest as aligned to a multiple of 16
//
UCHAR _ReservedPad1[UHCD_SPAD(struct _UHCD_MEMORY_DESCRIPTOR_INTERNAL, 16)]; UCHAR _ReservedPad2[UHCD_SPAD(struct _HW_TRANSFER_DESCRIPTOR_INTERNAL, 16)]; UCHAR _ReservedPad3[UHCD_SPAD(struct _HW_QUEUE_HEAD_INTERNAL, 16)]; };
} HW_TRANSFER_DESCRIPTOR, *PHW_TRANSFER_DESCRIPTOR;
//
// Hardware requires that all descriptors have 16 byte HW-specific section and
// have a software-use section so that the descriptor as a whole is 16-byte
// aligned
//
C_ASSERT(((sizeof(HW_TRANSFER_DESCRIPTOR) % 16) == 0));
#define UHCD_HW_DESCRIPTOR_SIZE (sizeof(HW_TRANSFER_DESCRIPTOR))
//
// values for Flags field in queue head
//
#define UHCD_QUEUE_IN_USE 0x00000001
typedef struct _HW_QUEUE_HEAD { union { //
// For addressing
//
struct _HW_QUEUE_HEAD_INTERNAL;
//
// The compiler will pick the biggest as aligned to a multiple of 16
//
UCHAR _ReservedPad1[UHCD_SPAD(struct _UHCD_MEMORY_DESCRIPTOR_INTERNAL, 16)]; UCHAR _ReservedPad2[UHCD_SPAD(struct _HW_TRANSFER_DESCRIPTOR_INTERNAL, 16)]; UCHAR _ReservedPad3[UHCD_SPAD(struct _HW_QUEUE_HEAD_INTERNAL, 16)]; }; } HW_QUEUE_HEAD, *PHW_QUEUE_HEAD;
//
// Hardware requires that all descriptors have 16 byte HW-specific section and
// have a software-use section so that the descriptor as a whole is 16-byte
// aligned
//
C_ASSERT(((sizeof(HW_TRANSFER_DESCRIPTOR) % 16) == 0));
C_ASSERT(((sizeof(HW_QUEUE_HEAD) % 16) == 0)); C_ASSERT(sizeof(HW_TRANSFER_DESCRIPTOR) == sizeof(HW_QUEUE_HEAD));
//
// TD list structure
//
typedef struct _UHCD_TD_LIST { HW_TRANSFER_DESCRIPTOR TDs[1]; } UHCD_TD_LIST, *PUHCD_TD_LIST;
typedef struct _UHCD_MEMORY_DESCRIPTOR { union {
//
// For addressing
//
struct _UHCD_MEMORY_DESCRIPTOR_INTERNAL;
//
// The compiler will pick the biggest as aligned to a multiple of 16
//
UCHAR _ReservedPad1[UHCD_SPAD(struct _UHCD_MEMORY_DESCRIPTOR_INTERNAL, 16)]; UCHAR _ReservedPad2[UHCD_SPAD(struct _HW_TRANSFER_DESCRIPTOR_INTERNAL, 16)]; UCHAR _ReservedPad3[UHCD_SPAD(struct _HW_QUEUE_HEAD_INTERNAL, 16)]; };
} UHCD_MEMORY_DESCRIPTOR, *PUHCD_MEMORY_DESCRIPTOR;
C_ASSERT(sizeof(UHCD_MEMORY_DESCRIPTOR) == sizeof(HW_TRANSFER_DESCRIPTOR));
//
// A descriptor list contains a Queue head descriptor
// plus one or more transfer descriptors
//
typedef struct _UHCD_HARDWARE_DESCRIPTOR_LIST { // includes queue head
ULONG NumberOfHWDescriptors;
// memory descriptor points to common buffer
// containing descriptors
PUHCD_MEMORY_DESCRIPTOR MemoryDescriptor;
// 32 byte scratch buffer, we use this for the setup
// packet
HW_DESCRIPTOR_PHYSICAL_ADDRESS ScratchBufferLogicalAddress; PVOID ScratchBufferVirtualAddress; } UHCD_HRADWARE_DESCRIPTOR_LIST, *PUHCD_HARDWARE_DESCRIPTOR_LIST;
//
// UHCD Endpoint Structure
//
// We create one of these for every endpoint we open.
//
//
// values for EndpointFlags field
//
// set to if the root hub code owns this ep
#define EPFLAG_ROOT_HUB 0x00000001
// set when client issues an abort endpoint
// request -- causes all queued transfers for
// the endpoint to be completed.
#define EPFLAG_ABORT_PENDING_TRANSFERS 0x00000002
// causes all currently active transfers for an
// endpoint to be aborted.
#define EPFLAG_ABORT_ACTIVE_TRANSFERS 0x00000004
// endpoint is in the halted (AKA stalled) state
#define EPFLAG_HOST_HALTED 0x00000008
// endpoint belongs to a lowspeed device
#define EPFLAG_LOWSPEED 0x00000010
// endpoint has had no transfers submitted,
// restored on reset
#define EPFLAG_VIRGIN 0x00000020
// endpoint will not enter the 'halted' state
#define EPFLAG_NO_HALT 0x00000040
// need attention
#define EPFLAG_HAVE_WORK 0x00000080
// idle state
#define EPFLAG_IDLE 0x00000100
// ed is in th eschedule
#define EPFLAG_ED_IN_SCHEDULE 0x00000200
// ed is closed
#define EPFLAG_EP_CLOSED 0x00000400
// inicates we need to double buffer
// transfers for this endpoint
#define EPFLAG_DBL_BUFFER 0x00000800
#define EPFLAG_NODMA_ON 0x00001000
// indicates we need to use the 'fast iso path'
// for transfers to the EP
#define EPFLAG_FAST_ISO 0x00002000
// indicates we have initialized the ED
#define EPFLAG_INIT 0x00004000
typedef struct _FAST_ISO_DATA {
PDEVICE_OBJECT DeviceObject;
PULONG FastIsoFrameList;
PUCHAR IsoTDListVa; HW_DESCRIPTOR_PHYSICAL_ADDRESS IsoTDListPhys;
PUCHAR DataBufferStartVa; HW_DESCRIPTOR_PHYSICAL_ADDRESS DataBufferStartPhys;
} FAST_ISO_DATA, *PFAST_ISO_DATA;
#define SET_EPFLAG(ep, flag) ((ep)->EndpointFlags |= (flag))
#define CLR_EPFLAG(ep, flag) ((ep)->EndpointFlags &= ~(flag))
typedef struct _UHCD_ENDPOINT { ULONG Sig; // signature field
UCHAR Type; // type of endpoint we are dealing with
UCHAR EndpointAddress; USHORT MaxPacketSize;
UCHAR Interval; UCHAR DeviceAddress; USHORT TDCount; // number of TDS in TDList
PUHCD_TD_LIST TDList; PUHCD_TD_LIST SlotTDList[UHCD_MAX_ACTIVE_TRANSFERS];
PUHCD_HARDWARE_DESCRIPTOR_LIST HardwareDescriptorList[UHCD_MAX_ACTIVE_TRANSFERS]; // Pointer to queue head associated with this endpoint
PHW_QUEUE_HEAD QueueHead; // Urbs currently being processed
PHCD_URB ActiveTransfers[UHCD_MAX_ACTIVE_TRANSFERS]; // List Urbs waiting to be processed
LIST_ENTRY PendingTransferList; // Field for linking endpoints
LIST_ENTRY ListEntry;
// BUGBUG move some of this to
// the urb work space
SHORT LastTDPreparedIdx[UHCD_MAX_ACTIVE_TRANSFERS]; SHORT CurrentTDIdx[UHCD_MAX_ACTIVE_TRANSFERS];
SHORT LastTDInTransferIdx[UHCD_MAX_ACTIVE_TRANSFERS]; UCHAR MaxRequests; UCHAR DataToggle;
ULONG MaxTransferSize; ULONG CurrentFrame;
PUCHAR NoDMABuffer; ULONG NoDMABufferLength;
HW_DESCRIPTOR_PHYSICAL_ADDRESS NoDMAPhysicalAddress;
#if DBG
ULONG AccessPendingList; // access flag, incremented when we HOLD
// the endpoint
// decremented when we RELEASE the endpoint
ULONG AccessActiveList; #endif
ULONG FrameToClose; // Frame number when the close request was
// processed
ULONG EndpointFlags;
KSPIN_LOCK ActiveListSpin;
KSPIN_LOCK PendingListSpin;
USHORT TdsScheduled[UHCD_MAX_ACTIVE_TRANSFERS]; USHORT Offset;
LONG IdleTime; LARGE_INTEGER LastIdleTime;
FAST_ISO_DATA FastIsoData;
UCHAR LastPacketDataToggle; UCHAR CurrentXferId; UCHAR NextXferId; UCHAR Pad[1];
} UHCD_ENDPOINT, *PUHCD_ENDPOINT;
struct _UHCD_PAGE_LIST_ENTRY_INTERNAL { LIST_ENTRY ListEntry; PHYSICAL_ADDRESS LogicalAddress; ULONG Length; ULONG Flags; };
//
// Take advantage of the fact that the MS compiler supports
// variant structs and unions so that we can get the proper padding
// for our structures. Put in lots of C_ASSERT()s just to be sure
// nothing goes really really bad
//
//
// Thist structure must be a multiple of 32 bytes
// to maintain proper alignemnt of the HW descriptors
// it is the first entry in the blocks of memory we allocate
// Host controller HW descriptors from
//
typedef struct _UHCD_PAGE_LIST_ENTRY { union { struct _UHCD_PAGE_LIST_ENTRY_INTERNAL; UCHAR _ReservedPad[UHCD_SPAD(struct _UHCD_PAGE_LIST_ENTRY_INTERNAL, 32)]; }; } UHCD_PAGE_LIST_ENTRY, *PUHCD_PAGE_LIST_ENTRY;
C_ASSERT(((sizeof(UHCD_PAGE_LIST_ENTRY) % 32) == 0));
//
//typedef struct _UHCD_WORKER_CONTEXT {
// WORK_QUEUE_ITEM WorkQueueItem;
// PIRP Irp;
// PDEVICE_OBJECT DeviceObject;
//} UHCD_WORKER_CONTEXT, *PUHCD_WORKER_CONTEXT;
//
// A structure representing the instance information associated with
// a particular device
//
typedef struct _DEVICE_EXTENSION {
UCHAR UsbdWorkArea[sizeof(USBD_EXTENSION)];
//
// Device object that the bus extender created for me.
//
PDEVICE_OBJECT PhysicalDeviceObject;
//
// Device object of the first guy on the stack
// -- the guy we pass our Irps on to.
//
PDEVICE_OBJECT TopOfStackDeviceObject;
//
// Pointer to interrupt object.
//
PKINTERRUPT InterruptObject;
//
// Pointer to the virtual base address for the USB frame list
//
PVOID FrameListVirtualAddress;
//
// Logical address of frame list returned from
// HalAllocateCommonBuffer
//
PHYSICAL_ADDRESS FrameListLogicalAddress;
//
// BUGBUG keep a copy to remove isoch descriptors
// Pointer to the virtual base address for the USB frame list
//
PVOID FrameListCopyVirtualAddress;
//
// DPC Object for processing frames with completed transfers
//
KDPC IsrDpc;
//
// Base queue head that we link all control/bulk transfer
// queues to.
//
PHW_QUEUE_HEAD PersistantQueueHead;
//
// Descriptor List for the PersistantQueueHead
//
PUHCD_HARDWARE_DESCRIPTOR_LIST PQH_DescriptorList;
//
// Queue of active endpoints
//
// BUGBUG we'll probably have a separate queue for each
// transfer type eventually
LIST_ENTRY EndpointList; LIST_ENTRY EndpointLookAsideList;
// lists for fast iso
LIST_ENTRY FastIsoEndpointList; LIST_ENTRY FastIsoTransferList;
//
// List of closed endpoints who's resources need to be
// released.
//
LIST_ENTRY ClosedEndpointList;
// Virtual Addresses for the interrupt queue heads in the
// schedule.
PHW_QUEUE_HEAD InterruptSchedule[MAX_INTERVAL];
// list of common buffer pages allocated
LIST_ENTRY PageList;
//
// Table where we keep track of the available bw on the usb
// for iso and interrupt, entries are in bits/ms
//
ULONG BwTable[MAX_INTERVAL];
//
// 12 bit counter, contains the frame value from the previous
// interrupt
//
ULONG LastFrame;
//
// High part of USB frame counter
//
ULONG FrameHighPart;
LARGE_INTEGER LastIdleTime;
LARGE_INTEGER LastXferIdleTime;
LONG IdleTime;
LONG XferIdleTime;
//
// TDs we are using as interrupt triggers
//
PUHCD_TD_LIST TriggerTDList;
UHCD_BUFFER_POOL LargeBufferPool; UHCD_BUFFER_POOL MediumBufferPool; UHCD_BUFFER_POOL SmallBufferPool;
//
// ROOT HUB VARIABLES
//
//
// device address assigned to root hub
//
ULONG RootHubDeviceAddress;
//
// context pointer passed to root hub
//
PROOTHUB RootHub;
//
// counter for the number of root hub timers
// that are currently scheduled
//
ULONG RootHubTimersActive;
//
// Timer and Dpc for polling the root hub interrupt
// endpoint
//
KDPC RootHubPollDpc;
KTIMER RootHubPollTimer;
//
// non-zero if timer was initialized
//
ULONG RootHubPollTimerInitialized;
KSPIN_LOCK EndpointListSpin;
PUHCD_ENDPOINT RootHubInterruptEndpoint;
// BUGBUG
// isoch stuff
ULONG LastFrameProcessed;
//
// DMA adapter object representing this instance
// of the UHCI controller.
//
PDMA_ADAPTER AdapterObject;
ULONG NumberOfMapRegisters;
PHW_TRANSFER_DESCRIPTOR FrameBabbleRecoverTD;
ULONG DeviceNameHandle;
//
// save registers for BIOS
//
USHORT BiosCmd; USHORT BiosIntMask;
ULONG BiosFrameListBase;
USHORT LegacySupportRegister; USHORT Pad;
PUCHAR DeviceRegisters[1];
//
// saved state information for no power resume
//
USHORT SavedInterruptEnable; USHORT SavedCommandReg;
DEVICE_POWER_STATE CurrentDevicePowerState;
ULONG HcFlags;
USHORT SavedFRNUM; USHORT SavedUnused; ULONG SavedFRBASEADD; ULONG Port; LONG HcDma;
ULONG RegRecClocksPerFrame;
PVOID Piix4EP;
KSPIN_LOCK HcFlagSpin; KSPIN_LOCK HcDmaSpin; KSPIN_LOCK HcScheduleSpin;
//
// Busy flag set when the ISRDPC routine is
// processing the endpoint list
//
BOOLEAN EndpointListBusy;
//
// Stepping Version of the Host Controller
//
UCHAR SteppingVersion;
CHAR SavedSofModify;
UCHAR ControllerType;
//
// statistic counters, used for debugging and interfacing with
// sysmon.
//
HCD_STAT_COUNTERS Stats; HCD_ISO_STAT_COUNTERS IsoStats; ULONG LastFrameInterrupt;
#if DBG
// ptr to list of dwords containing the number of iso bytes
// scheduled for a particular frame
PULONG IsoList; #endif
//
// Status we returned last time we were asked to power up the
// controller. We check this to see if we can touch the
// hardware when the hub is powered up.
//
NTSTATUS LastPowerUpStatus;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
//
// values for HcFlags
//
// Set to indicate port resources were assigned
#define HCFLAG_GOT_IO 0x00000001
// Set at initialization to indicate that the base register
// address must be unmapped when the driver is unloaded.
#define HCFLAG_UNMAP_REGISTERS 0x00000002
// Set if we have a USB BIOS on this system
#define HCFLAG_USBBIOS 0x00000004
// Current state of BW reclimation
#define HCFLAG_BWRECLIMATION_ENABLED 0x00000008
// This flag indicates if the driver needs to cleanup resources
// allocated in start_device.
#define HCFLAG_NEED_CLEANUP 0x00000010
// HC is idle
#define HCFLAG_IDLE 0x00000020
// set when the rollover int is disabled
#define HCFLAG_ROLLOVER_IDLE 0x00000040
// set when the controller is stopped
#define HCFLAG_HCD_STOPPED 0x00000080
// turn off idle check
#define HCFLAG_DISABLE_IDLE 0x00000100
// work item queued
#define HCFLAG_WORK_ITEM_QUEUED 0x00000200
// hcd has shut down
#define HCFLAG_HCD_SHUTDOWN 0x00000400
// indicates we need to restore HC from hibernate
#define HCFLAG_LOST_POWER 0x00000800
// set when root hub turns off the HC
#define HCFLAG_RH_OFF 0x00001000
#define HCFLAG_MAP_SX_TO_D3 0x00002000
// set if we will be suspending in this D3
#define HCFLAG_SUSPEND_NEXT_D3 0x00004000
typedef struct _UHCD_RESOURCES { ULONG InterruptVector; KIRQL InterruptLevel; KAFFINITY Affinity; BOOLEAN ShareIRQ; KINTERRUPT_MODE InterruptMode; } UHCD_RESOURCES, *PUHCD_RESOURCES;
// Macros used by the transfer modules
#define NEXT_TD(idx, ep) ((idx+1) % ep->TDCount)
#define DATA_DIRECTION_IN(u) \
((BOOLEAN)((u)->HcdUrbCommonTransfer.TransferFlags & \ USBD_TRANSFER_DIRECTION_IN))
#define DATA_DIRECTION_OUT(u) \
((BOOLEAN)!((u)->HcdUrbCommonTransfer.TransferFlags & \ USBD_TRANSFER_DIRECTION_IN))
typedef struct _UHCD_LOGICAL_ADDRESS { HW_DESCRIPTOR_PHYSICAL_ADDRESS LogicalAddress; ULONG Length; // if this block caintained a USB packet that crossed a
// page boundry and needed to be double
// buffered then this is the offset of that packet.
ULONG PacketOffset; PUHCD_MEMORY_DESCRIPTOR PacketMemoryDescriptor; // block of memory
// used to double buffer
// packet
} UHCD_LOGICAL_ADDRESS, *PUHCD_LOGICAL_ADDRESS;
//
// Private definition for urb work area
// used by HCD for each transfer URB.
//
typedef struct _HCD_EXTENSION { ULONG CurrentPacketIdx; ULONG BytesTransferred; ULONG TransferOffset; ULONG Status;
ULONG PacketsProcessed;
UCHAR Slot; UCHAR Flags; UCHAR ErrorCount; UCHAR XferId;
UCHAR DataToggle; UCHAR Reserved[3];
//
// list of logical addresses we can give
// to the HC
//
PVOID SystemAddressForMdl; ULONG NumberOfMapRegisters; PVOID MapRegisterBase; ULONG NumberOfLogicalAddresses; UHCD_LOGICAL_ADDRESS LogicalAddressList[1]; } HCD_EXTENSION, *PHCD_EXTENSION;
typedef struct _UHCD_WORKITEM { WORK_QUEUE_ITEM WorkQueueItem; PDEVICE_OBJECT DeviceObject; } UHCD_WORKITEM, *PUHCD_WORKITEM;
//
// some USB constants
//
#define USB_IN_PID 0x69
#define USB_OUT_PID 0xe1
#define USB_SETUP_PID 0x2d
#define NULL_PACKET_LENGTH 0x7ff
#define UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(len) \
((len+1) & NULL_PACKET_LENGTH) #define UHCD_SYSTEM_TO_USB_BUFFER_LENGTH(len) \
((len-1) & NULL_PACKET_LENGTH)
//
// Function Prototypes
//
NTSTATUS UHCD_PnPAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject );
NTSTATUS UHCD_Dispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_Unload( IN PDRIVER_OBJECT DriverObject );
NTSTATUS UHCD_CreateDeviceObject( IN PDRIVER_OBJECT DriverObject, IN OUT PDEVICE_OBJECT *DeviceObject, IN PUNICODE_STRING DeviceNameUnicodeString );
NTSTATUS UHCD_StartDevice( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_RESOURCES Resources );
NTSTATUS UHCD_GetResources( IN PDEVICE_OBJECT DeviceObject, IN PCM_RESOURCE_LIST ResourceList, IN OUT PUHCD_RESOURCES Resources );
VOID UHCD_CompleteIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN NTSTATUS ntStatus, IN ULONG Information, IN PHCD_URB Urb );
VOID UHCD_StartIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS UHCD_URB_Dispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_OpenEndpoint_StartIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_Transfer_StartIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
BOOLEAN UHCD_InterruptService( IN PKINTERRUPT Interrupt, IN PVOID Context );
VOID UHCD_IsrDpc( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
VOID UHCD_OpenEndpoint_StartIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_CloseEndpoint_StartIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_GetDoneTransfer( IN PVOID Context );
NTSTATUS UHCD_GetResourceList( IN PDRIVER_OBJECT DriverOject, IN PDEVICE_OBJECT DeviceObject, IN PCM_RESOURCE_LIST *ResourceList, IN PUNICODE_STRING RegistryPath );
NTSTATUS UHCD_MakeInterrupt( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_StopDevice( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_InitializeSchedule( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_StartGlobalReset( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_CompleteGlobalReset( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_InsertQueueHeadInSchedule( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PHW_QUEUE_HEAD QueueHead, IN ULONG Offset );
VOID UHCD_InitializeTransferDescriptor( IN PDEVICE_OBJECT DeviceObject, IN PHW_TRANSFER_DESCRIPTOR Transfer );
VOID UHCD_InitializeQueueHead( IN PDEVICE_OBJECT DeviceObject, IN PHW_QUEUE_HEAD QueueHead );
BOOLEAN UHCD_AllocateHardwareDescriptors( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_HARDWARE_DESCRIPTOR_LIST *HardwareDescriptorList, IN ULONG NumberOfTransferDescriptors );
VOID UHCD_FreeHardwareDescriptors( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_HARDWARE_DESCRIPTOR_LIST HardwareDescriptorList );
VOID UHCD_CompleteTransferDPC( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN LONG Slot );
BOOLEAN UHCD_RemoveQueueHeadFromSchedule( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PHW_QUEUE_HEAD QueueHead, IN BOOLEAN RemoveFromEPList );
ULONG UHCD_GetCurrentFrame( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_CopyInterruptScheduleToFrameList( IN PDEVICE_OBJECT DeviceObject );
__inline VOID UHCD_InitializeAsyncTD( IN PUHCD_ENDPOINT Endpoint, IN PHW_TRANSFER_DESCRIPTOR TransferDescriptor );
VOID UHCD_GlobalResetDpc( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
VOID UHCD_PrepareStatusPacket( IN PHW_TRANSFER_DESCRIPTOR TransferDescriptor, IN PUHCD_ENDPOINT Endpoint, IN PHCD_URB Urb );
VOID UHCD_PrepareSetupPacket( IN PHW_TRANSFER_DESCRIPTOR TransferDescriptor, IN PUHCD_ENDPOINT Endpoint, IN PHCD_URB Urb );
USBD_STATUS UHCD_PrepareMoreAsyncTDs( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PHCD_URB Urb, IN BOOLEAN Busy );
NTSTATUS UHCD_RootHub_OpenEndpoint( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PHCD_URB Urb );
NTSTATUS UHCD_RootHub_CloseEndpoint( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PHCD_URB Urb );
NTSTATUS UHCD_RootHub_ControlTransfer( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PHCD_URB Urb );
NTSTATUS UHCD_RootHub_InterruptTransfer( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PHCD_URB Urb );
VOID UHCD_RootHubPoll( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
VOID UHCD_ScheduleIsochTransfer( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PHCD_URB Urb );
VOID UHCD_RootHubTimerDpc( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
NTSTATUS UHCD_PnPIrp_Complete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
NTSTATUS UHCD_PowerIrp_Complete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
VOID UHCD_RootHub_InterruptTransferCancel( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
IO_ALLOCATION_ACTION UHCD_StartDmaTransfer( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context );
VOID UHCD_InitializeDmaTransfer( IN PDEVICE_OBJECT DeviceObject, IN PHCD_URB Urb, IN PUHCD_ENDPOINT Endpoint, IN LONG Slot, IN UCHAR XferId );
PUHCD_MEMORY_DESCRIPTOR UHCD_AllocateCommonBuffer( IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfBytes );
VOID UHCD_FreeCommonBuffer( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_MEMORY_DESCRIPTOR MemoryDescriptor );
VOID UHCD_InitializeCommonBufferPool( IN PDEVICE_OBJECT DeviceObject, IN OUT PUHCD_BUFFER_POOL BufferPool, IN ULONG CommonBufferLength, IN ULONG MaximumFreeBuffers );
HW_DESCRIPTOR_PHYSICAL_ADDRESS UHCD_GetPacketBuffer( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PHCD_URB Urb, IN PHCD_EXTENSION urbWork, IN ULONG Offset, IN ULONG PacketSize );
VOID UHCD_RequestInterrupt( IN PDEVICE_OBJECT DeviceObject, IN LONG FrameNumber );
VOID UHCD_TransferCancel( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_BeginTransfer( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PHCD_URB Urb, IN ULONG Slot );
PHCD_URB UHCD_RemoveQueuedUrbs( IN PDEVICE_OBJECT DeviceObject, IN PHCD_URB Urb, IN PIRP Irp );
#if DBG
VOID UHCD_LockAccess( IN PULONG c );
VOID UHCD_UnLockAccess( IN PULONG c ); #else
#define UHCD_UnLockAccess(c)
#define UHCD_LockAccess(c)
#endif
VOID UHCD_StartIoCancel( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_EndpointWorker( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
VOID UHCD_InsertIsochDescriptor( IN PDEVICE_OBJECT DeviceObject, IN PHW_TRANSFER_DESCRIPTOR TransferDescriptor, IN ULONG FrameNumber );
VOID UHCD_GetSetEndpointState_StartIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
#define UHCD_AllocateBandwidth(DeviceObject, Endpoint, Offset) \
UHCD_ManageBandwidth((DeviceObject), \ (Endpoint), \ (Offset),\ TRUE)
#define UHCD_FreeBandwidth(DeviceObject, Endpoint, Offset) \
UHCD_ManageBandwidth((DeviceObject), \ (Endpoint), \ (Offset),\ FALSE)
BOOLEAN UHCD_ManageBandwidth( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN ULONG Offset, IN BOOLEAN AllocateFlag );
NTSTATUS UHCD_GetDeviceName( IN PDEVICE_OBJECT DeviceObject, IN OUT PUNICODE_STRING DeviceNameUnicodeString, IN BOOLEAN DeviceLink );
USBD_STATUS UHCD_MapTDError( PDEVICE_EXTENSION DeviceExtension, ULONG Td_Status, ULONG ActualLength );
VOID UHCD_RootHubPollDpc( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
NTSTATUS UHCD_Suspend( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN SuspendBus );
NTSTATUS UHCD_Resume( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN DoResumeSignaling );
NTSTATUS UHCD_SaveHCstate( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_RestoreHCstate( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_FinishInitializeEndpoint( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN PHCD_URB Urb );
VOID UHCD_CleanupDevice( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_BufferPoolCheck( IN PDEVICE_OBJECT DeviceObject );
ULONG UHCD_GrowBufferPool( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_BUFFER_POOL BufferPool, IN ULONG Length, IN PUCHAR VirtualAddress, IN PUCHAR EndVirtualAddress, IN HW_DESCRIPTOR_PHYSICAL_ADDRESS HwLogicalAddress );
VOID UHCD_InitBandwidthTable( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_StopBIOS( IN PDEVICE_OBJECT DeviceObject );
USHORT UHCD_GetNumTDsPerEndoint( IN UCHAR EndpointType );
VOID UHCD_BW_Reclimation( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Enable );
NTSTATUS UHCD_SetDevicePowerState( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN DEVICE_POWER_STATE DeviceState );
VOID UHCD_ReadWriteConfig( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Read, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length );
NTSTATUS UHCD_QueryCapabilities( IN PDEVICE_OBJECT PdoDeviceObject, IN PDEVICE_CAPABILITIES DeviceCapabilities );
ULONG UHCD_FreePoolSize( IN PUHCD_BUFFER_POOL BufferPool, IN OUT PULONG ByteCount );
NTSTATUS UHCD_GetClassGlobalRegistryParameters( IN OUT PULONG ForceLowPowerState );
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
NTSTATUS UHCD_DeferPoRequestCompletion( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE DeviceState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus );
NTSTATUS UHCD_DeferIrpCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
NTSTATUS UHCD_FixPIIX4( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_InitializeHardwareQueueHeadDescriptor( IN PDEVICE_OBJECT DeviceObject, IN PHW_QUEUE_HEAD QueueHead, IN HW_DESCRIPTOR_PHYSICAL_ADDRESS LogicalAddress );
VOID UHCD_MoreCommonBuffers( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_AllocateCommonBufferBlock( IN PDEVICE_OBJECT DeviceObject, IN ULONG CommonBufferLength, IN ULONG NumberOfPages );
ULONG UHCD_CheckCommonBufferPool( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_BUFFER_POOL BufferPool, IN BOOLEAN Allocate );
NTSTATUS UHCD_StartBIOS( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_RootHubPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS UHCD_ProcessPowerIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS UHCD_ProcessPowerPnP( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS UHCD_DeferredStartDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UHCD_CheckIdle( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_DisableIdleCheck( IN PDEVICE_EXTENSION DeviceExtension );
VOID UHCD_WakeIdle( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_GrowPoolWorker( IN PVOID Context );
NTSTATUS UHCD_GetSOFRegModifyValue( IN PDEVICE_OBJECT DeviceObject, IN OUT PULONG SofModifyValue );
NTSTATUS UHCD_GetGlobalRegistryParameters( IN OUT PULONG DisableController );
NTSTATUS UHCD_ExternalGetCurrentFrame( IN PDEVICE_OBJECT DeviceObject, IN PULONG CurrentFrame );
UCHAR MAX_REQUESTS( IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG EpFlags );
VOID UHCD_FixupDataToggle( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PHCD_URB Urb );
VOID UHCD_SetControllerD0( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_EndpointWakeup( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
VOID UHCD_EndpointIdle( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
ULONG UHCD_ExternalGetConsumedBW( IN PDEVICE_OBJECT DeviceObject );
VOID UHCD_EndpointDMAWorker( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
VOID UHCD_EndpointNoDMAWorker( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
NTSTATUS UHCD_InitializeNoDMAEndpoint( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
VOID UHCD_Free_NoDMA_Buffer( IN PDEVICE_OBJECT DeviceObject, IN PUCHAR NoDMABuffer );
PUCHAR UHCD_Alloc_NoDMA_Buffer( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN ULONG Length );
NTSTATUS UHCD_UnInitializeNoDMAEndpoint( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
VOID UHCD_StopNoDMATransfer( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
NTSTATUS UHCD_InitializeFastIsoEndpoint( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
NTSTATUS UHCD_UnInitializeFastIsoEndpoint( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint );
NTSTATUS UHCD_ProcessFastIsoTransfer( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN PIRP Irp, IN PHCD_URB Urb );
PUHCD_ENDPOINT UHCD_GetLastFastIsoEndpoint( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS UHCD_GetClassGlobalDebugRegistryParameters( );
PHW_TRANSFER_DESCRIPTOR UHCD_CleanupFastIsoTD( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN ULONG RelativeFrame, IN BOOLEAN Count );
VOID UhcdKickStartController(IN PDEVICE_OBJECT PDevObj);
NTSTATUS UHCD_SubmitFastIsoUrb( IN PDEVICE_OBJECT DeviceObject, IN PURB Urb );
VOID UHCD_ValidateIsoUrb( IN PDEVICE_OBJECT DeviceObject, IN PUHCD_ENDPOINT Endpoint, IN OUT PHCD_URB Urb );
#endif /* __UHCD_H__ */
|