2078 lines
47 KiB
C
2078 lines
47 KiB
C
/*++
|
|
|
|
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__ */
|
|
|