USB -- EHCI
Posted: Sat Apr 16, 2011 8:43 pm
I am trying to make a test EHCI driver and I am having problems. It is resetting and enabling the ports properly but transactions arent working.
Here is the code. The method I am having problems with is DoTransactions(byte port);
Here is the code. The method I am having problems with is DoTransactions(byte port);
Code: Select all
#include "LoadKernel.h"
#include "Bootinfo.h"
#define GetPhysicalAddress(x) (*x & ~0xFFF)
void EHCI();
void Main(Bootinfo::MultibootInfo* bootinfo, dword kernelsize)
{
LoadKernel::InitializeSystems(bootinfo, kernelsize);
EHCI();
Shell::RunShell();
LoadKernel::DeInitializeSystems();
}
void Beep(byte on)
{
OutPort(0x61, on * 163);
}
// /USB Testing -
// /-------------
// /-------------
// /-------------
#include "USB.h"
dword BaseRegister = 0;
dword OperationalRegisterBase = 0;
byte NumberOfPorts = 0;
dword PortBase = 0;
struct CapibilityRegisters
{
byte CAPLENGTH;
byte RESERVED;
word HCIVERSION;
dword HCSPARAMS;
dword HCCPARAMS;
byte HCSPPORTROUTE[8];
};
struct OperationRegisters
{
dword USBCMD;
dword USBSTS;
dword USBINTR;
dword FRINDEX;
dword CTRLDSSEGMENT;
dword PERIODICLISTBASE;
dword ASYNCLISTADDR;
byte Reserved[36];
dword CONFIGFLAG;
};
OperationRegisters* op;
dword ReadPci(byte bus, byte device, byte funct, byte offset)
{
dword address = (bus << 16) | (device << 11) | (funct << 8) | (offset & 0xFC) | (0x80000000);
OutPortDWord(0xCF8, address);
return InPortDWord(0xCFC);
}
void DisplayEHCIPCI()
{
dword classcode = ReadPci(0, 3, 3, 8);
Video::Print("Class code: ");
Video::PrintNumber((classcode >> 24) & 0xFF, 16);
Video::Print(" Sub class code: ");
Video::PrintNumber((classcode >> 16) & 0xFF, 16);
Video::Print(" Programming Interface: ");
Video::PrintNumber((classcode >> 8) & 0xFF, 16);
Video::Print("\n\n");
}
void ReadBaseRegister()
{
dword base = ReadPci(0, 3, 3, 0x10);
Video::Print("Base register address: 0x");
Video::PrintNumber(base, 16);
Video::Print(" - ");
Video::PrintNumber(base, 10);
VirtualMemory::AllocateRandomPage(true, &BaseRegister);
VirtualMemory::FreePage(BaseRegister);
VirtualMemory::MapPage((void*)base, (void*)BaseRegister);
Video::Print("\n\n");
}
void ReadPCIReleaseNumber()
{
dword num = ReadPci(0, 3, 3, 0x60);
Video::Print("Serial Bus Release Number: ");
Video::PrintNumber((byte)num, 16);
Video::Print("\n\n");
}
void CapibilityPortsHCS(dword HCSPARAMS)
{
byte NOPs = (HCSPARAMS & 0xF);
Video::Print("\nNOPs: ");
Video::PrintNumber(NOPs, 10);
NumberOfPorts = NOPs;
byte DebugPortNumber = (HCSPARAMS & 0xFF000000);
Video::Print(" Debug Port: ");
Video::PrintNumber(DebugPortNumber, 10);
byte PortPower = ((HCSPARAMS >> 4) & 1);
Video::Print(" Port Power: ");
Video::PrintNumber(PortPower, 10);
}
void ParseCapibilityRegisters()
{
CapibilityRegisters cap = *((CapibilityRegisters*)BaseRegister);
Video::Print("CAPLENGTH: ");
Video::PrintNumber(cap.CAPLENGTH, 10);
OperationalRegisterBase = (BaseRegister + cap.CAPLENGTH);
Video::Print("\nHCIVERSION: ");
Video::PrintNumber(cap.HCIVERSION, 16);
CapibilityPortsHCS(cap.HCSPARAMS);
Video::Print("\n\n");
}
void OperateRegisters()
{
op = ((OperationRegisters*)OperationalRegisterBase);
op->USBCMD |= 2;
while ((op->USBCMD & 2) == 1) {}
op->PERIODICLISTBASE |= 0xFFFFF000;
op->USBCMD |= 1;
op->CONFIGFLAG |= 1;
PIT::WaitMilliseconds(200);
Video::Print("Host Controller Reset\n\n");
PortBase = OperationalRegisterBase + 0x44;
}
dword* SelectPort(byte portnumber)
{
return (dword*)(PortBase + (portnumber * 4));
}
byte Ports()
{
while (true)
{
for (int i = 0; i < NumberOfPorts; i++)
{
dword* base = SelectPort(i);
dword enable = (((*base) >> 0) & 1);
if (enable)
{
Video::Print("Device has been inserted into port: ");
Video::PrintNumber(i, 10);
Beep(1);
PIT::WaitMilliseconds(50);
*base |= 256;
PIT::WaitMilliseconds(50);
*base &= ~256;
PIT::WaitMilliseconds(10);
Beep(0);
Video::Print(" With data code: ");
Video::PrintNumber(*base, 10);
Video::NewLine();
return i;
}
}
}
}
void DoTransactions(byte port)
{
Keyboard::WaitForKeyDown();
dword qhmem = 0;
VirtualMemory::AllocateRandomPage(true, &qhmem);
QueueHead* qh = (QueueHead*)qhmem;
qh->HorizontalPointer = 0;
qh->HorizontalPointer |= 2;
qh->HorizontalPointer |= qhmem;
qh->StaticEndpoint[0] = 0;
qh->StaticEndpoint[0] |= 0; // DeviceAddress TO BE FILLED IN!!!
qh->StaticEndpoint[0] |= 8192; // EndpointSpeed
qh->StaticEndpoint[0] |= 0x400000; // qMaxPacketSize
qh->StaticEndpoint[0] |= 0xF0000000; // NakReloader
qh->StaticEndpoint[1] = 0;
qh->StaticEndpoint[1] |= 0x40000000; // Multiplyer
qh->CurrentQtd = 0;
memset(&qh->Overlay, 0, 32);
qh->Overlay[0] |= 1;
qh->Overlay[1] |= 1;
op->ASYNCLISTADDR = qhmem;
dword qtdmem = qhmem + 128;
QTD* qtd = (QTD*)qtdmem;
qtd->NextPointer = 0;
qtd->NextPointer |= 1;
qtd->AlternatePointer = 0;
qtd->AlternatePointer |= 1;
qtd->Results = 0;
qtd->Results |= 512;
qtd->Results |= 0x80000;
qtd->Buffers[0] = 0;
dword setupbuffer = 0;
VirtualMemory::AllocateRandomPage(true, &setupbuffer);
qtd->Buffers[0] |= setupbuffer;
byte* sb = (byte*)setupbuffer;
sb[0] = 128;
sb[1] = 6;
sb[2] = 0;
sb[3] = 1;
sb[4] = 0;
sb[5] = 0;
sb[6] = 18;
dword nextqtd = 0;
nextqtd |= qtdmem;
qh->Overlay[0] = nextqtd;
op->USBCMD |= 32;
while (((op->USBSTS >> 15) & 1) == 1)
{
}
Video::Print("Running AsncyList\n");
PIT::WaitMilliseconds(500);
Video::PrintNumber(qh->CurrentQtd, 10);
}
void EHCI()
{
// PCI
DisplayEHCIPCI();
ReadBaseRegister();
ReadPCIReleaseNumber();
//EHCI
ParseCapibilityRegisters();
OperateRegisters();
byte port = Ports();
DoTransactions(port);
Keyboard::WaitForKeyDown();
LoadKernel::DeInitializeSystems();
}