[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:
Johannes Anderwald 2012-02-22 14:11:23 +00:00
parent 6d5fb45681
commit a0375291e4
4 changed files with 91 additions and 23 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>