mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
[USBUHCI]
- Write the configure bit - Clear connection change and port suspend bit when set after controller initialization - Queue work item after the reset port is complete - Disable port before reseting it - Wait time for reset is 50ms, not 25ms - Clear reset change bit when clearing reset feature - Implement enabling port feature svn path=/trunk/; revision=55806
This commit is contained in:
parent
6d5fb45681
commit
a0375291e4
4 changed files with 91 additions and 23 deletions
|
@ -289,7 +289,7 @@ CUSBHardwareDevice::PnpStart(
|
||||||
// Store Resource base
|
// Store Resource base
|
||||||
//
|
//
|
||||||
m_Base = (PULONG)ResourceDescriptor->u.Port.Start.LowPart; //FIXME
|
m_Base = (PULONG)ResourceDescriptor->u.Port.Start.LowPart; //FIXME
|
||||||
DPRINT1("UHCI Base %p\n", m_Base);
|
DPRINT1("UHCI Base %p Length %x\n", m_Base, ResourceDescriptor->u.Port.Length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,6 +499,9 @@ CUSBHardwareDevice::StartController(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINT1("[USBUHCI] USBCMD: %x USBSTS %x\n", ReadRegister16(UHCI_USBCMD), ReadRegister16(UHCI_USBSTS));
|
||||||
|
|
||||||
|
|
||||||
if ((Status & UHCI_USBSTS_HCHALT))
|
if ((Status & UHCI_USBSTS_HCHALT))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -509,9 +512,31 @@ CUSBHardwareDevice::StartController(void)
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set the configure bit
|
||||||
|
//
|
||||||
|
WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) | UHCI_USBCMD_CF);
|
||||||
|
|
||||||
|
for(Index = 0; Index < 2; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get port status
|
||||||
|
//
|
||||||
|
Status = ReadRegister16(UHCI_PORTSC1 + Index * 2);
|
||||||
|
|
||||||
|
//
|
||||||
|
// clear connection change and port suspend
|
||||||
|
//
|
||||||
|
WriteRegister16(UHCI_PORTSC1 + Index * 2, Status & ~(UHCI_PORTSC_STATCHA | UHCI_PORTSC_SUSPEND));
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT1("[USBUHCI] Controller Started\n");
|
DPRINT1("[USBUHCI] Controller Started\n");
|
||||||
DPRINT1("[USBUHCI] Controller Status %x\n", ReadRegister16(UHCI_USBSTS));
|
DPRINT1("[USBUHCI] Controller Status %x\n", ReadRegister16(UHCI_USBSTS));
|
||||||
|
DPRINT1("[USBUHCI] Controller Cmd Status %x\n", ReadRegister16(UHCI_USBCMD));
|
||||||
|
DPRINT1("[USBUHCI] Controller Interrupt Status %x\n", ReadRegister16(UHCI_USBINTR));
|
||||||
DPRINT1("[USBUHCI] Controller Frame %x\n", ReadRegister16(UHCI_FRNUM));
|
DPRINT1("[USBUHCI] Controller Frame %x\n", ReadRegister16(UHCI_FRNUM));
|
||||||
|
DPRINT1("[USBUHCI] Controller Port Status 0 %x\n", ReadRegister16(UHCI_PORTSC1));
|
||||||
|
DPRINT1("[USBUHCI] Controller Port Status 1 %x\n", ReadRegister16(UHCI_PORTSC1 + 2));
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
|
@ -533,12 +558,15 @@ CUSBHardwareDevice::GlobalReset()
|
||||||
//
|
//
|
||||||
WRITE_PORT_USHORT((PUSHORT)((ULONG)m_Base + UHCI_USBCMD), UHCI_USBCMD_GRESET);
|
WRITE_PORT_USHORT((PUSHORT)((ULONG)m_Base + UHCI_USBCMD), UHCI_USBCMD_GRESET);
|
||||||
|
|
||||||
|
KeStallExecutionProcessor(100);
|
||||||
|
|
||||||
//
|
//
|
||||||
// clear command register
|
// clear command register
|
||||||
//
|
//
|
||||||
WRITE_PORT_USHORT((PUSHORT)((ULONG)m_Base + UHCI_USBCMD), 0);
|
WRITE_PORT_USHORT((PUSHORT)((ULONG)m_Base + UHCI_USBCMD), 0);
|
||||||
|
|
||||||
KeStallExecutionProcessor(1000);
|
KeStallExecutionProcessor(10);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// restore start of modify register
|
// restore start of modify register
|
||||||
|
@ -557,6 +585,12 @@ CUSBHardwareDevice::InitializeController()
|
||||||
|
|
||||||
DPRINT1("[USBUHCI] InitializeController\n");
|
DPRINT1("[USBUHCI] InitializeController\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// now disable all interrupts
|
||||||
|
//
|
||||||
|
WriteRegister16(UHCI_USBINTR, 0);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// UHCI has two ports
|
// UHCI has two ports
|
||||||
//
|
//
|
||||||
|
@ -580,10 +614,6 @@ CUSBHardwareDevice::InitializeController()
|
||||||
|
|
||||||
DPRINT1("[USBUHCI] Acquired ownership\n");
|
DPRINT1("[USBUHCI] Acquired ownership\n");
|
||||||
|
|
||||||
//
|
|
||||||
// now disable all interrupts
|
|
||||||
//
|
|
||||||
WriteRegister16(UHCI_USBINTR, 0);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// perform global reset
|
// perform global reset
|
||||||
|
@ -682,14 +712,15 @@ CUSBHardwareDevice::InitializeController()
|
||||||
//
|
//
|
||||||
// init stray descriptor
|
// init stray descriptor
|
||||||
//
|
//
|
||||||
m_StrayDescriptor->PhysicalAddress = m_StrayDescriptorPhysicalAddress;
|
m_StrayDescriptor->PhysicalAddress = m_StrayDescriptorPhysicalAddress.LowPart;
|
||||||
m_StrayDescriptor->LinkPhysical = TD_TERMINATE;
|
m_StrayDescriptor->LinkPhysical = TD_TERMINATE;
|
||||||
m_StrayDescriptor->Token = TD_TOKEN_NULL_DATA | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | TD_TOKEN_IN;
|
m_StrayDescriptor->Token = TD_TOKEN_NULL_DATA | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | TD_TOKEN_IN;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// link to last queue head
|
// link to last queue head
|
||||||
//
|
//
|
||||||
m_QueueHead[4]->LinkPhysical = m_StrayDescriptor->PhysicalAddress.LowPart;
|
m_QueueHead[4]->LinkPhysical = m_StrayDescriptor->PhysicalAddress;
|
||||||
m_QueueHead[4]->NextLogicalDescriptor = m_StrayDescriptor;
|
m_QueueHead[4]->NextLogicalDescriptor = m_StrayDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
@ -804,6 +835,17 @@ CUSBHardwareDevice::ResetPort(
|
||||||
//
|
//
|
||||||
Status = ReadRegister16(Port);
|
Status = ReadRegister16(Port);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Before port reset, disable the port
|
||||||
|
//
|
||||||
|
WriteRegister16(Port, ReadRegister16(Port) & ~UHCI_PORTSC_ENABLED);
|
||||||
|
while(ReadRegister16(Port) & UHCI_PORTSC_ENABLED)
|
||||||
|
{
|
||||||
|
DPRINT1("Port %x Status %x\n", PortIndex, ReadRegister16(Port));
|
||||||
|
KeStallExecutionProcessor(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// remove unwanted bits
|
// remove unwanted bits
|
||||||
//
|
//
|
||||||
|
@ -817,7 +859,7 @@ CUSBHardwareDevice::ResetPort(
|
||||||
//
|
//
|
||||||
// now wait a bit
|
// now wait a bit
|
||||||
//
|
//
|
||||||
KeStallExecutionProcessor(25);
|
KeStallExecutionProcessor(50);
|
||||||
|
|
||||||
//
|
//
|
||||||
// re-read status
|
// re-read status
|
||||||
|
@ -832,12 +874,17 @@ CUSBHardwareDevice::ResetPort(
|
||||||
//
|
//
|
||||||
// clear reset port
|
// clear reset port
|
||||||
//
|
//
|
||||||
WriteRegister16(Port, Status & ~UHCI_PORTSC_RESET);
|
WriteRegister16(Port, (Status & ~UHCI_PORTSC_RESET));
|
||||||
|
|
||||||
|
//
|
||||||
|
// set enabled bit
|
||||||
|
//
|
||||||
|
WriteRegister16(Port, ReadRegister16(Port) | UHCI_PORTSC_ENABLED);
|
||||||
|
|
||||||
//
|
//
|
||||||
// now wait a bit
|
// now wait a bit
|
||||||
//
|
//
|
||||||
KeStallExecutionProcessor(25);
|
KeStallExecutionProcessor(10);
|
||||||
|
|
||||||
for (Index = 0; Index < 10; Index++)
|
for (Index = 0; Index < 10; Index++)
|
||||||
{
|
{
|
||||||
|
@ -854,7 +901,7 @@ CUSBHardwareDevice::ResetPort(
|
||||||
//
|
//
|
||||||
// enable port
|
// enable port
|
||||||
//
|
//
|
||||||
WriteRegister16(Port, Status | UHCI_PORTSC_ENABLED);
|
WriteRegister16(Port, Status);
|
||||||
|
|
||||||
//
|
//
|
||||||
// wait a bit
|
// wait a bit
|
||||||
|
@ -891,6 +938,16 @@ CUSBHardwareDevice::ResetPort(
|
||||||
|
|
||||||
m_PortResetChange |= (1 << PortIndex);
|
m_PortResetChange |= (1 << PortIndex);
|
||||||
DPRINT1("[USBOHCI] Port Index %x Status after reset %x\n", PortIndex, ReadRegister16(Port));
|
DPRINT1("[USBOHCI] Port Index %x Status after reset %x\n", PortIndex, ReadRegister16(Port));
|
||||||
|
|
||||||
|
if (Status & UHCI_PORTSC_CURSTAT)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// queue work item
|
||||||
|
//
|
||||||
|
DPRINT1("Queueing work item\n");
|
||||||
|
ExQueueWorkItem(&m_StatusChangeWorkItem, DelayedWorkQueue);
|
||||||
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,7 +1060,7 @@ CUSBHardwareDevice::ClearPortStatus(
|
||||||
//
|
//
|
||||||
// UHCI is not supporting port reset register bit
|
// UHCI is not supporting port reset register bit
|
||||||
//
|
//
|
||||||
m_PortResetChange &= (1 << PortId);
|
m_PortResetChange &= ~(1 << PortId);
|
||||||
}
|
}
|
||||||
else if (Feature == C_PORT_CONNECTION)
|
else if (Feature == C_PORT_CONNECTION)
|
||||||
{
|
{
|
||||||
|
@ -1029,6 +1086,8 @@ CUSBHardwareDevice::SetPortFeature(
|
||||||
ULONG PortId,
|
ULONG PortId,
|
||||||
ULONG Feature)
|
ULONG Feature)
|
||||||
{
|
{
|
||||||
|
ULONG PortRegister;
|
||||||
|
|
||||||
DPRINT1("[UHCI] SetPortFeature PortId %x Feature %x\n", PortId, Feature);
|
DPRINT1("[UHCI] SetPortFeature PortId %x Feature %x\n", PortId, Feature);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1043,6 +1102,8 @@ CUSBHardwareDevice::SetPortFeature(
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PortRegister = UHCI_PORTSC1 + PortId * 2;
|
||||||
|
|
||||||
if (Feature == PORT_RESET)
|
if (Feature == PORT_RESET)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1050,6 +1111,13 @@ CUSBHardwareDevice::SetPortFeature(
|
||||||
//
|
//
|
||||||
return ResetPort(PortId);
|
return ResetPort(PortId);
|
||||||
}
|
}
|
||||||
|
else if (Feature == PORT_ENABLE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reset port
|
||||||
|
//
|
||||||
|
WriteRegister16(PortRegister, ReadRegister16(PortRegister) | UHCI_PORTSC_ENABLED);
|
||||||
|
}
|
||||||
else if (Feature == PORT_POWER)
|
else if (Feature == PORT_POWER)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1107,12 +1175,12 @@ InterruptServiceRoutine(
|
||||||
// get context
|
// get context
|
||||||
//
|
//
|
||||||
This = (CUSBHardwareDevice*) ServiceContext;
|
This = (CUSBHardwareDevice*) ServiceContext;
|
||||||
DPRINT("InterruptServiceRoutine\n");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// read register
|
// read register
|
||||||
//
|
//
|
||||||
Status = This->ReadRegister16(UHCI_USBSTS);
|
Status = This->ReadRegister16(UHCI_USBSTS);
|
||||||
|
DPRINT("InterruptServiceRoutine %x\n", Status);
|
||||||
|
|
||||||
//
|
//
|
||||||
// check if the interrupt signaled are from us
|
// check if the interrupt signaled are from us
|
||||||
|
|
|
@ -92,7 +92,7 @@ typedef struct _UHCI_TRANSFER_DESCRIPTOR
|
||||||
ULONG BufferPhysical; // pointer to the buffer
|
ULONG BufferPhysical; // pointer to the buffer
|
||||||
|
|
||||||
// Software part
|
// Software part
|
||||||
PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor
|
ULONG PhysicalAddress; // Physical address of this descriptor
|
||||||
PVOID NextLogicalDescriptor;
|
PVOID NextLogicalDescriptor;
|
||||||
ULONG BufferSize; // Size of the buffer
|
ULONG BufferSize; // Size of the buffer
|
||||||
PVOID BufferLogical; // Logical pointer to the buffer
|
PVOID BufferLogical; // Logical pointer to the buffer
|
||||||
|
|
|
@ -718,7 +718,7 @@ CUSBRequest::CreateDescriptor(
|
||||||
//
|
//
|
||||||
// init descriptor
|
// init descriptor
|
||||||
//
|
//
|
||||||
Descriptor->PhysicalAddress = Address;
|
Descriptor->PhysicalAddress = Address.LowPart;
|
||||||
Descriptor->Status = TD_STATUS_ACTIVE;
|
Descriptor->Status = TD_STATUS_ACTIVE;
|
||||||
|
|
||||||
if (InternalGetTransferType() == USB_ENDPOINT_TYPE_ISOCHRONOUS)
|
if (InternalGetTransferType() == USB_ENDPOINT_TYPE_ISOCHRONOUS)
|
||||||
|
@ -829,7 +829,7 @@ CUSBRequest::BuildTransferDescriptorChain(
|
||||||
//
|
//
|
||||||
// FIXME FIXME FIXME FIXME FIXME
|
// FIXME FIXME FIXME FIXME FIXME
|
||||||
//
|
//
|
||||||
MaxPacketSize = 64;
|
MaxPacketSize = 1280;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -872,7 +872,7 @@ CUSBRequest::BuildTransferDescriptorChain(
|
||||||
//
|
//
|
||||||
// link descriptor
|
// link descriptor
|
||||||
//
|
//
|
||||||
LastDescriptor->LinkPhysical = CurrentDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
|
LastDescriptor->LinkPhysical = CurrentDescriptor->PhysicalAddress | TD_DEPTH_FIRST;
|
||||||
LastDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
|
LastDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,13 +1095,13 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
//
|
//
|
||||||
// link setup descriptor to first data descriptor
|
// link setup descriptor to first data descriptor
|
||||||
//
|
//
|
||||||
SetupDescriptor->LinkPhysical = FirstDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
|
SetupDescriptor->LinkPhysical = FirstDescriptor->PhysicalAddress | TD_DEPTH_FIRST;
|
||||||
SetupDescriptor->NextLogicalDescriptor = (PVOID)FirstDescriptor;
|
SetupDescriptor->NextLogicalDescriptor = (PVOID)FirstDescriptor;
|
||||||
|
|
||||||
//
|
//
|
||||||
// link last data descriptor to status descriptor
|
// link last data descriptor to status descriptor
|
||||||
//
|
//
|
||||||
LastDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
|
LastDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress | TD_DEPTH_FIRST;
|
||||||
LastDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor;
|
LastDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1109,7 +1109,7 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
//
|
//
|
||||||
// directly link setup to status descriptor
|
// directly link setup to status descriptor
|
||||||
//
|
//
|
||||||
SetupDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
|
SetupDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress | TD_DEPTH_FIRST;
|
||||||
SetupDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor;
|
SetupDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1117,7 +1117,7 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
// link queue head with setup descriptor
|
// link queue head with setup descriptor
|
||||||
//
|
//
|
||||||
QueueHead->NextElementDescriptor = (PVOID)SetupDescriptor;
|
QueueHead->NextElementDescriptor = (PVOID)SetupDescriptor;
|
||||||
QueueHead->ElementPhysical = SetupDescriptor->PhysicalAddress.LowPart;
|
QueueHead->ElementPhysical = SetupDescriptor->PhysicalAddress;
|
||||||
|
|
||||||
//
|
//
|
||||||
// store result
|
// store result
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define USBOHCI_H__
|
#define USBOHCI_H__
|
||||||
|
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#define NDEBUG
|
#define YDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <hubbusif.h>
|
#include <hubbusif.h>
|
||||||
#include <usbbusif.h>
|
#include <usbbusif.h>
|
||||||
|
|
Loading…
Reference in a new issue