mirror of
https://github.com/reactos/reactos.git
synced 2024-07-05 12:15:46 +00:00
[usb/usbehci]:
- Reorganization code to put hardware related structures and routines in own source files. - Modify ResetPort to correctly reset the port instead of the controller. - Implement allocating chunks of memory from the Common Buffer for use with the rest of source code. svn path=/trunk/; revision=50223
This commit is contained in:
parent
c1d677d16a
commit
4eef1c1925
275
reactos/drivers/usb/usbehci/hardware.c
Normal file
275
reactos/drivers/usb/usbehci/hardware.c
Normal file
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbehci/hardware.c
|
||||
* PURPOSE: Hardware related routines.
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "hardware.h"
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
//FORCEINLINE
|
||||
VOID
|
||||
SetAsyncListQueueRegister(PEHCI_HOST_CONTROLLER hcd, ULONG PhysicalAddr)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_ASYNCLISTBASE), PhysicalAddr);
|
||||
}
|
||||
|
||||
//FORCEINLINE
|
||||
ULONG
|
||||
GetAsyncListQueueRegister(PEHCI_HOST_CONTROLLER hcd)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
return READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_ASYNCLISTBASE));
|
||||
}
|
||||
|
||||
//FORCEINLINE
|
||||
VOID
|
||||
SetPeriodicFrameListRegister(PEHCI_HOST_CONTROLLER hcd, ULONG PhysicalAddr)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_PERIODICLISTBASE), PhysicalAddr);
|
||||
}
|
||||
|
||||
//FORCEINLINE
|
||||
ULONG
|
||||
GetPeriodicFrameListRegister(PEHCI_HOST_CONTROLLER hcd)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
return READ_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_PERIODICLISTBASE));
|
||||
}
|
||||
|
||||
//FORCEINLINE
|
||||
ULONG
|
||||
ReadControllerStatus(PEHCI_HOST_CONTROLLER hcd)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
return READ_REGISTER_ULONG ((PULONG) (OpRegisters + EHCI_USBSTS));
|
||||
}
|
||||
|
||||
//FORCEINLINE
|
||||
VOID
|
||||
ClearControllerStatus(PEHCI_HOST_CONTROLLER hcd, ULONG Status)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
WRITE_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBSTS), Status);
|
||||
}
|
||||
|
||||
VOID
|
||||
ResetPort(PEHCI_HOST_CONTROLLER hcd, UCHAR Port)
|
||||
{
|
||||
ULONG tmp;
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
DPRINT1("Reset Port %x\n", Port);
|
||||
|
||||
tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port)));
|
||||
if (tmp & 0x400)
|
||||
{
|
||||
DPRINT1("Non HighSpeed device connected. Releasing ownership.\n");
|
||||
WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port)), 0x2000);
|
||||
}
|
||||
|
||||
/* Get current port state */
|
||||
tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port)));
|
||||
|
||||
/* Set reset and clear enable */
|
||||
tmp |= 0x100;
|
||||
tmp &= ~0x04;
|
||||
WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port)), tmp);
|
||||
|
||||
/* USB 2.0 Spec 10.2.8.1, more than 50ms */
|
||||
KeStallExecutionProcessor(100);
|
||||
|
||||
/* Clear reset */
|
||||
tmp &= ~0x100;
|
||||
WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port)), tmp);
|
||||
|
||||
KeStallExecutionProcessor(100);
|
||||
|
||||
tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port)));
|
||||
|
||||
if (tmp & 0x100)
|
||||
{
|
||||
DPRINT1("EHCI ERROR: Port Reset did not complete!\n");
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
StopEhci(PEHCI_HOST_CONTROLLER hcd)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
PEHCI_USBCMD_CONTENT UsbCmd;
|
||||
PEHCI_USBSTS_CONTEXT UsbSts;
|
||||
LONG FailSafe;
|
||||
LONG tmp;
|
||||
|
||||
DPRINT1("Stopping Ehci controller\n");
|
||||
|
||||
WRITE_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBINTR), 0);
|
||||
|
||||
tmp = READ_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBCMD));
|
||||
UsbCmd = (PEHCI_USBCMD_CONTENT) & tmp;
|
||||
UsbCmd->Run = FALSE;
|
||||
WRITE_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBCMD), tmp);
|
||||
|
||||
/* Wait for the device to stop */
|
||||
for (FailSafe = 100; FailSafe > 1; FailSafe++)
|
||||
{
|
||||
KeStallExecutionProcessor(10);
|
||||
tmp = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS));
|
||||
UsbSts = (PEHCI_USBSTS_CONTEXT)&tmp;
|
||||
|
||||
if (UsbSts->HCHalted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!UsbSts->HCHalted)
|
||||
DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
StartEhci(PEHCI_HOST_CONTROLLER hcd)
|
||||
{
|
||||
ULONG OpRegisters = hcd->OpRegisters;
|
||||
PEHCI_USBCMD_CONTENT UsbCmd;
|
||||
PEHCI_USBSTS_CONTEXT UsbSts;
|
||||
LONG FailSafe;
|
||||
LONG tmp;
|
||||
LONG tmp2;
|
||||
|
||||
DPRINT("Starting Ehci controller\n");
|
||||
|
||||
tmp = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS));
|
||||
UsbSts = (PEHCI_USBSTS_CONTEXT)&tmp;
|
||||
|
||||
if (!UsbSts->HCHalted)
|
||||
{
|
||||
StopEhci(hcd);
|
||||
}
|
||||
|
||||
tmp = READ_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBCMD));
|
||||
|
||||
/* Reset the device */
|
||||
UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
|
||||
UsbCmd->HCReset = TRUE;
|
||||
WRITE_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBCMD), tmp);
|
||||
|
||||
/* Wait for the device to reset */
|
||||
for (FailSafe = 100; FailSafe > 1; FailSafe++)
|
||||
{
|
||||
KeStallExecutionProcessor(10);
|
||||
tmp = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD));
|
||||
UsbCmd = (PEHCI_USBCMD_CONTENT)&tmp;
|
||||
|
||||
if (!UsbCmd->HCReset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
DPRINT("Waiting for reset, USBCMD: %x\n", READ_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBCMD)));
|
||||
}
|
||||
|
||||
if (UsbCmd->HCReset)
|
||||
{
|
||||
DPRINT1("EHCI ERROR: Controller failed to reset! Will attempt to continue.\n");
|
||||
}
|
||||
|
||||
UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
|
||||
|
||||
/* Disable Interrupts on the device */
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBINTR), 0);
|
||||
/* Clear the Status */
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS), 0x0000001f);
|
||||
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_CTRLDSSEGMENT), 0);
|
||||
|
||||
SetAsyncListQueueRegister(hcd, hcd->AsyncListQueue->PhysicalAddr | QH_TYPE_QH);
|
||||
/* Set the ansync and periodic to disable */
|
||||
UsbCmd->PeriodicEnable = FALSE;
|
||||
UsbCmd->AsyncEnable = TRUE;
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD), tmp);
|
||||
|
||||
/* Set the threshold */
|
||||
UsbCmd->IntThreshold = 1;
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD), tmp);
|
||||
|
||||
/* Turn back on interrupts */
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBINTR),
|
||||
EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
|
||||
/*| EHCI_USBINTR_FLROVR*/ | EHCI_USBINTR_PC);
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBINTR),
|
||||
EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
|
||||
/*| EHCI_USBINTR_FLROVR*/ | EHCI_USBINTR_PC);
|
||||
|
||||
UsbCmd->Run = TRUE;
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD), tmp);
|
||||
|
||||
/* Wait for the device to start */
|
||||
for (;;)
|
||||
{
|
||||
KeStallExecutionProcessor(10);
|
||||
tmp2 = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS));
|
||||
UsbSts = (PEHCI_USBSTS_CONTEXT)&tmp2;
|
||||
|
||||
if (!UsbSts->HCHalted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
DPRINT("Waiting for start, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBSTS)));
|
||||
}
|
||||
|
||||
/* Set all port routing to ECHI controller */
|
||||
WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_CONFIGFLAG), 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
GetCapabilities(PEHCI_CAPS PCap, ULONG CapRegister)
|
||||
{
|
||||
PEHCI_HCS_CONTENT PHCS;
|
||||
LONG i;
|
||||
|
||||
if (!PCap)
|
||||
return;
|
||||
|
||||
PCap->Length = READ_REGISTER_UCHAR((PUCHAR)CapRegister);
|
||||
PCap->Reserved = READ_REGISTER_UCHAR((PUCHAR)(CapRegister + 1));
|
||||
PCap->HCIVersion = READ_REGISTER_USHORT((PUSHORT)(CapRegister + 2));
|
||||
PCap->HCSParamsLong = READ_REGISTER_ULONG((PULONG)(CapRegister + 4));
|
||||
PCap->HCCParams = READ_REGISTER_ULONG((PULONG)(CapRegister + 8));
|
||||
|
||||
DPRINT1("Length %d\n", PCap->Length);
|
||||
DPRINT1("Reserved %d\n", PCap->Reserved);
|
||||
DPRINT1("HCIVersion %x\n", PCap->HCIVersion);
|
||||
DPRINT1("HCSParams %x\n", PCap->HCSParamsLong);
|
||||
DPRINT1("HCCParams %x\n", PCap->HCCParams);
|
||||
|
||||
if (PCap->HCCParams & 0x02)
|
||||
DPRINT1("Frame list size is configurable\n");
|
||||
|
||||
if (PCap->HCCParams & 0x01)
|
||||
DPRINT1("64bit address mode not supported!\n");
|
||||
|
||||
DPRINT1("Number of Ports: %d\n", PCap->HCSParams.PortCount);
|
||||
|
||||
if (PCap->HCSParams.PortPowerControl)
|
||||
DPRINT1("Port Power Control is enabled\n");
|
||||
|
||||
if (!PCap->HCSParams.CHCCount)
|
||||
{
|
||||
DPRINT1("Number of Companion Host controllers %x\n", PCap->HCSParams.CHCCount);
|
||||
DPRINT1("Number of Ports Per CHC: %d\n", PCap->HCSParams.PortPerCHC);
|
||||
}
|
||||
|
||||
PHCS = (PEHCI_HCS_CONTENT)&PCap->HCSParams;
|
||||
if (PHCS->PortRouteRules)
|
||||
{
|
||||
for (i = 0; i < PCap->HCSParams.PortCount; i++)
|
||||
{
|
||||
PCap->PortRoute[i] = READ_REGISTER_UCHAR((PUCHAR) (CapRegister + 12 + i));
|
||||
}
|
||||
}
|
||||
}
|
307
reactos/drivers/usb/usbehci/hardware.h
Normal file
307
reactos/drivers/usb/usbehci/hardware.h
Normal file
|
@ -0,0 +1,307 @@
|
|||
#pragma once
|
||||
|
||||
#include <ntddk.h>
|
||||
|
||||
/* USB Command Register */
|
||||
#define EHCI_USBCMD 0x00
|
||||
#define EHCI_USBSTS 0x04
|
||||
#define EHCI_USBINTR 0x08
|
||||
#define EHCI_FRINDEX 0x0C
|
||||
#define EHCI_CTRLDSSEGMENT 0x10
|
||||
#define EHCI_PERIODICLISTBASE 0x14
|
||||
#define EHCI_ASYNCLISTBASE 0x18
|
||||
#define EHCI_CONFIGFLAG 0x40
|
||||
#define EHCI_PORTSC 0x44
|
||||
|
||||
/* USB Interrupt Register Flags 32 Bits */
|
||||
#define EHCI_USBINTR_INTE 0x01
|
||||
#define EHCI_USBINTR_ERR 0x02
|
||||
#define EHCI_USBINTR_PC 0x04
|
||||
#define EHCI_USBINTR_FLROVR 0x08
|
||||
#define EHCI_USBINTR_HSERR 0x10
|
||||
#define EHCI_USBINTR_ASYNC 0x20
|
||||
/* Bits 6:31 Reserved */
|
||||
|
||||
/* Status Register Flags 32 Bits */
|
||||
#define EHCI_STS_INT 0x01
|
||||
#define EHCI_STS_ERR 0x02
|
||||
#define EHCI_STS_PCD 0x04
|
||||
#define EHCI_STS_FLR 0x08
|
||||
#define EHCI_STS_FATAL 0x10
|
||||
#define EHCI_STS_IAA 0x20
|
||||
/* Bits 11:6 Reserved */
|
||||
#define EHCI_STS_HALT 0x1000
|
||||
#define EHCI_STS_RECL 0x2000
|
||||
#define EHCI_STS_PSS 0x4000
|
||||
#define EHCI_STS_ASS 0x8000
|
||||
#define EHCI_ERROR_INT ( EHCI_STS_FATAL | EHCI_STS_ERR )
|
||||
|
||||
|
||||
/* Last bit in QUEUE ELEMENT TRANSFER DESCRIPTOR Next Pointer */
|
||||
/* Used for Queue Element Transfer Descriptor Pointers
|
||||
and Queue Head Horizontal Link Pointers */
|
||||
#define TERMINATE_POINTER 0x01
|
||||
|
||||
/* QUEUE ELEMENT TRANSFER DESCRIPTOR, Token defines and structs */
|
||||
|
||||
/* PIDCodes for QETD_TOKEN
|
||||
OR with QUEUE_TRANSFER_DESCRIPTOR Token.PIDCode*/
|
||||
#define PID_CODE_OUT_TOKEN 0x00
|
||||
#define PID_CODE_IN_TOKEN 0x01
|
||||
#define PID_CODE_SETUP_TOKEN 0x02
|
||||
|
||||
/* Split Transaction States
|
||||
OR with QUEUE_TRANSFER_DESCRIPTOR Token.SplitTransactionState */
|
||||
#define DO_START_SPLIT 0x00
|
||||
#define DO_COMPLETE_SPLIT 0x01
|
||||
|
||||
/* Ping States, OR with QUEUE_TRANSFER_DESCRIPTOR Token. */
|
||||
#define PING_STATE_DO_OUT 0x00
|
||||
#define PING_STATE_DO_PING 0x01
|
||||
|
||||
typedef struct _PERIODICFRAMELIST
|
||||
{
|
||||
PULONG VirtualAddr;
|
||||
PHYSICAL_ADDRESS PhysicalAddr;
|
||||
ULONG Size;
|
||||
} PERIODICFRAMELIST, *PPERIODICFRAMELIST;
|
||||
|
||||
|
||||
/* QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN */
|
||||
typedef struct _QETD_TOKEN_BITS
|
||||
{
|
||||
ULONG PingState:1;
|
||||
ULONG SplitTransactionState:1;
|
||||
ULONG MissedMicroFrame:1;
|
||||
ULONG TransactionError:1;
|
||||
ULONG BabbleDetected:1;
|
||||
ULONG DataBufferError:1;
|
||||
ULONG Halted:1;
|
||||
ULONG Active:1;
|
||||
ULONG PIDCode:2;
|
||||
ULONG ErrorCounter:2;
|
||||
ULONG CurrentPage:3;
|
||||
ULONG InterruptOnComplete:1;
|
||||
ULONG TotalBytesToTransfer:15;
|
||||
ULONG DataToggle:1;
|
||||
} QETD_TOKEN_BITS, *PQETD_TOKEN_BITS;
|
||||
|
||||
/* QUEUE ELEMENT TRANSFER DESCRIPTOR */
|
||||
typedef struct _QUEUE_TRANSFER_DESCRIPTOR
|
||||
{
|
||||
//Hardware
|
||||
ULONG NextPointer;
|
||||
ULONG AlternateNextPointer;
|
||||
union
|
||||
{
|
||||
QETD_TOKEN_BITS Bits;
|
||||
ULONG DWord;
|
||||
} Token;
|
||||
ULONG BufferPointer[5];
|
||||
|
||||
//Software
|
||||
ULONG PhysicalAddr;
|
||||
struct _QUEUE_TRANSFER_DESCRIPTOR *PreviousDescriptor;
|
||||
struct _QUEUE_TRANSFER_DESCRIPTOR *NextDescriptor;
|
||||
} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
|
||||
|
||||
/* EndPointSpeeds of END_POINT_CHARACTERISTICS */
|
||||
#define QH_ENDPOINT_FULLSPEED 0x00
|
||||
#define QH_ENDPOINT_LOWSPEED 0x01
|
||||
#define QH_ENDPOINT_HIGHSPEED 0x02
|
||||
|
||||
typedef struct _END_POINT_CHARACTERISTICS
|
||||
{
|
||||
ULONG DeviceAddress:7;
|
||||
ULONG InactiveOnNextTransaction:1;
|
||||
ULONG EndPointNumber:4;
|
||||
ULONG EndPointSpeed:2;
|
||||
ULONG QEDTDataToggleControl:1;
|
||||
ULONG HeadOfReclamation:1;
|
||||
ULONG MaximumPacketLength:11;
|
||||
ULONG ControlEndPointFlag:1;
|
||||
ULONG NakCountReload:4;
|
||||
} END_POINT_CHARACTERISTICS, *PEND_POINT_CHARACTERISTICS;
|
||||
|
||||
typedef struct _END_POINT_CAPABILITIES
|
||||
{
|
||||
ULONG InterruptScheduleMask:8;
|
||||
ULONG SplitCompletionMask:8;
|
||||
ULONG HubAddr:6;
|
||||
ULONG PortNumber:6;
|
||||
/* Multi */
|
||||
ULONG NumberOfTransactionPerFrame:2;
|
||||
} END_POINT_CAPABILITIES, *PEND_POINT_CAPABILITIES;
|
||||
|
||||
|
||||
/* QUEUE HEAD defines and structs */
|
||||
|
||||
/* QUEUE HEAD Select Types, OR with QUEUE_HEAD HorizontalLinkPointer */
|
||||
#define QH_TYPE_IDT 0x00
|
||||
#define QH_TYPE_QH 0x02
|
||||
#define QH_TYPE_SITD 0x04
|
||||
#define QH_TYPE_FSTN 0x06
|
||||
|
||||
/* QUEUE HEAD */
|
||||
typedef struct _QUEUE_HEAD
|
||||
{
|
||||
//Hardware
|
||||
ULONG HorizontalLinkPointer;
|
||||
END_POINT_CHARACTERISTICS EndPointCharacteristics;
|
||||
END_POINT_CAPABILITIES EndPointCapabilities;
|
||||
/* TERMINATE_POINTER not valid for this member */
|
||||
ULONG CurrentLinkPointer;
|
||||
/* TERMINATE_POINTER valid */
|
||||
ULONG NextPointer;
|
||||
/* TERMINATE_POINTER valid, bits 1:4 is NAK_COUNTER */
|
||||
ULONG AlternateNextPointer;
|
||||
/* Only DataToggle, InterruptOnComplete, ErrorCounter, PingState valid */
|
||||
union
|
||||
{
|
||||
QETD_TOKEN_BITS Bits;
|
||||
ULONG DWord;
|
||||
} Token;
|
||||
ULONG BufferPointer[5];
|
||||
|
||||
//Software
|
||||
ULONG PhysicalAddr;
|
||||
struct _QUEUE_HEAD *PreviousQueueHead;
|
||||
struct _QUEUE_HEAD *NextQueueHead;
|
||||
PQUEUE_TRANSFER_DESCRIPTOR TransferDescriptor;
|
||||
PIRP IrpToComplete;
|
||||
PMDL MdlToFree;
|
||||
PKEVENT Event;
|
||||
} QUEUE_HEAD, *PQUEUE_HEAD;
|
||||
|
||||
/* USBCMD register 32 bits */
|
||||
typedef struct _EHCI_USBCMD_CONTENT
|
||||
{
|
||||
ULONG Run : 1;
|
||||
ULONG HCReset : 1;
|
||||
ULONG FrameListSize : 2;
|
||||
ULONG PeriodicEnable : 1;
|
||||
ULONG AsyncEnable : 1;
|
||||
ULONG DoorBell : 1;
|
||||
ULONG LightReset : 1;
|
||||
ULONG AsyncParkCount : 2;
|
||||
ULONG Reserved : 1;
|
||||
ULONG AsyncParkEnable : 1;
|
||||
ULONG Reserved1 : 4;
|
||||
ULONG IntThreshold : 8;
|
||||
ULONG Reserved2 : 8;
|
||||
|
||||
} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT;
|
||||
|
||||
typedef struct _EHCI_USBSTS_CONTENT
|
||||
{
|
||||
ULONG USBInterrupt:1;
|
||||
ULONG ErrorInterrupt:1;
|
||||
ULONG DetectChangeInterrupt:1;
|
||||
ULONG FrameListRolloverInterrupt:1;
|
||||
ULONG HostSystemErrorInterrupt:1;
|
||||
ULONG AsyncAdvanceInterrupt:1;
|
||||
ULONG Reserved:6;
|
||||
ULONG HCHalted:1;
|
||||
ULONG Reclamation:1;
|
||||
ULONG PeriodicScheduleStatus:1;
|
||||
ULONG AsynchronousScheduleStatus:1;
|
||||
} EHCI_USBSTS_CONTEXT, *PEHCI_USBSTS_CONTEXT;
|
||||
|
||||
typedef struct _EHCI_USBPORTSC_CONTENT
|
||||
{
|
||||
ULONG CurrentConnectStatus:1;
|
||||
ULONG ConnectStatusChange:1;
|
||||
ULONG PortEnabled:1;
|
||||
ULONG PortEnableChanged:1;
|
||||
ULONG OverCurrentActive:1;
|
||||
ULONG OverCurrentChange:1;
|
||||
ULONG ForcePortResume:1;
|
||||
ULONG Suspend:1;
|
||||
ULONG PortReset:1;
|
||||
ULONG Reserved:1;
|
||||
ULONG LineStatus:2;
|
||||
ULONG PortPower:1;
|
||||
ULONG PortOwner:1;
|
||||
} EHCI_USBPORTSC_CONTENT, *PEHCI_USBPORTSC_CONTENT;
|
||||
|
||||
typedef struct _EHCI_HCS_CONTENT
|
||||
{
|
||||
ULONG PortCount : 4;
|
||||
ULONG PortPowerControl: 1;
|
||||
ULONG Reserved : 2;
|
||||
ULONG PortRouteRules : 1;
|
||||
ULONG PortPerCHC : 4;
|
||||
ULONG CHCCount : 4;
|
||||
ULONG PortIndicator : 1;
|
||||
ULONG Reserved2 : 3;
|
||||
ULONG DbgPortNum : 4;
|
||||
ULONG Reserved3 : 8;
|
||||
|
||||
} EHCI_HCS_CONTENT, *PEHCI_HCS_CONTENT;
|
||||
|
||||
typedef struct _EHCI_HCC_CONTENT
|
||||
{
|
||||
ULONG CurAddrBits : 1;
|
||||
ULONG VarFrameList : 1;
|
||||
ULONG ParkMode : 1;
|
||||
ULONG Reserved : 1;
|
||||
ULONG IsoSchedThreshold : 4;
|
||||
ULONG EECPCapable : 8;
|
||||
ULONG Reserved2 : 16;
|
||||
|
||||
} EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT;
|
||||
|
||||
typedef struct _EHCI_CAPS {
|
||||
UCHAR Length;
|
||||
UCHAR Reserved;
|
||||
USHORT HCIVersion;
|
||||
union
|
||||
{
|
||||
EHCI_HCS_CONTENT HCSParams;
|
||||
ULONG HCSParamsLong;
|
||||
};
|
||||
ULONG HCCParams;
|
||||
UCHAR PortRoute [8];
|
||||
} EHCI_CAPS, *PEHCI_CAPS;
|
||||
|
||||
typedef struct _EHCI_HOST_CONTROLLER
|
||||
{
|
||||
ULONG OpRegisters;
|
||||
EHCI_CAPS ECHICaps;
|
||||
PVOID CommonBufferVA;
|
||||
PHYSICAL_ADDRESS CommonBufferPA;
|
||||
ULONG CommonBufferSize;
|
||||
PQUEUE_HEAD AsyncListQueue;
|
||||
KSPIN_LOCK Lock;
|
||||
} EHCI_HOST_CONTROLLER, *PEHCI_HOST_CONTROLLER;
|
||||
|
||||
ULONG
|
||||
ReadControllerStatus(PEHCI_HOST_CONTROLLER hcd);
|
||||
|
||||
VOID
|
||||
ClearControllerStatus(PEHCI_HOST_CONTROLLER hcd, ULONG Status);
|
||||
|
||||
VOID
|
||||
GetCapabilities(PEHCI_CAPS PCap, ULONG CapRegister);
|
||||
|
||||
VOID
|
||||
ResetPort(PEHCI_HOST_CONTROLLER hcd, UCHAR Port);
|
||||
|
||||
VOID
|
||||
StartEhci(PEHCI_HOST_CONTROLLER hcd);
|
||||
|
||||
VOID
|
||||
StopEhci(PEHCI_HOST_CONTROLLER hcd);
|
||||
|
||||
VOID
|
||||
SetAsyncListQueueRegister(PEHCI_HOST_CONTROLLER hcd, ULONG PhysicalAddr);
|
||||
|
||||
ULONG
|
||||
GetAsyncListQueueRegister(PEHCI_HOST_CONTROLLER hcd);
|
||||
|
||||
VOID
|
||||
SetPeriodicFrameListRegister(PEHCI_HOST_CONTROLLER hcd, ULONG PhysicalAddr);
|
||||
|
||||
ULONG
|
||||
GetPeriodicFrameListRegister(PEHCI_HOST_CONTROLLER hcd);
|
||||
|
94
reactos/drivers/usb/usbehci/physmem.c
Normal file
94
reactos/drivers/usb/usbehci/physmem.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbehci/physmem.c
|
||||
* PURPOSE: Common Buffer routines.
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "physmem.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define SMALL_ALLOCATION_SIZE 32
|
||||
|
||||
VOID
|
||||
DumpPages()
|
||||
{
|
||||
//PMEM_HEADER MemBlock = (PMEM_HEADER)EhciSharedMemory.VirtualAddr;
|
||||
}
|
||||
|
||||
// Returns Virtual Address of Allocated Memory
|
||||
ULONG
|
||||
AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress)
|
||||
{
|
||||
PMEM_HEADER MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA;
|
||||
ULONG PageCount = 0;
|
||||
ULONG NumberOfPages = hcd->CommonBufferSize / PAGE_SIZE;
|
||||
ULONG BlocksNeeded;
|
||||
ULONG i,j, freeCount;
|
||||
ULONG RetAddr = 0;
|
||||
|
||||
Size = ((Size + SMALL_ALLOCATION_SIZE - 1) / SMALL_ALLOCATION_SIZE) * SMALL_ALLOCATION_SIZE;
|
||||
BlocksNeeded = Size / SMALL_ALLOCATION_SIZE;
|
||||
|
||||
do
|
||||
{
|
||||
if (MemoryPage->IsFull)
|
||||
{
|
||||
PageCount++;
|
||||
MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE);
|
||||
continue;
|
||||
}
|
||||
freeCount = 0;
|
||||
for (i = 0; i < sizeof(MemoryPage->Entry); i++)
|
||||
{
|
||||
if (!MemoryPage->Entry[i].InUse)
|
||||
{
|
||||
freeCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
freeCount = 0;
|
||||
}
|
||||
|
||||
if (freeCount == BlocksNeeded)
|
||||
{
|
||||
for (j = 0; j < freeCount; j++)
|
||||
{
|
||||
MemoryPage->Entry[i-j].InUse = 1;
|
||||
MemoryPage->Entry[i-j].Blocks = 0;
|
||||
}
|
||||
|
||||
MemoryPage->Entry[i-freeCount + 1].Blocks = BlocksNeeded;
|
||||
|
||||
RetAddr = (ULONG)MemoryPage + (SMALL_ALLOCATION_SIZE * (i - freeCount + 1)) + sizeof(MEM_HEADER);
|
||||
|
||||
*PhysicalAddress = (ULONG)hcd->CommonBufferPA.LowPart + (RetAddr - (ULONG)hcd->CommonBufferVA);
|
||||
return RetAddr;
|
||||
}
|
||||
}
|
||||
|
||||
PageCount++;
|
||||
MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE);
|
||||
} while (PageCount < NumberOfPages);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
ReleaseMemory(ULONG Address)
|
||||
{
|
||||
PMEM_HEADER MemoryPage;
|
||||
ULONG Index, i;
|
||||
|
||||
MemoryPage = (PMEM_HEADER)(Address & ~(PAGE_SIZE - 1));
|
||||
|
||||
Index = (Address - ((ULONG)MemoryPage + sizeof(MEM_HEADER))) / SMALL_ALLOCATION_SIZE;
|
||||
|
||||
for (i = 0; i < MemoryPage->Entry[Index].Blocks; i++)
|
||||
{
|
||||
MemoryPage->Entry[Index + i].InUse = 0;
|
||||
MemoryPage->Entry[Index + i].Blocks = 0;
|
||||
}
|
||||
}
|
25
reactos/drivers/usb/usbehci/physmem.h
Normal file
25
reactos/drivers/usb/usbehci/physmem.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
typedef struct _MEM_ENTRY
|
||||
{
|
||||
UCHAR InUse:1;
|
||||
UCHAR Blocks:7;
|
||||
} MEM_ENTRY, *PMEM_ENTRY;
|
||||
|
||||
typedef struct _MEM_HEADER
|
||||
{
|
||||
UCHAR IsFull;
|
||||
MEM_ENTRY Entry[127];
|
||||
} MEM_HEADER, *PMEM_HEADER;
|
||||
|
||||
VOID
|
||||
DumpPages();
|
||||
|
||||
ULONG
|
||||
AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress);
|
||||
|
||||
VOID
|
||||
ReleaseMemory(ULONG Address);
|
||||
|
Loading…
Reference in a new issue