The framelist was allocated in the object which caused the host controller to fail. Also the root hub is now setup after the host controller is started since new devices are created which use transfers to discover their parameters. The controller should now be correctly initialized and stay up.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17610 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2006-05-27 16:02:54 +00:00
parent 5430d867b4
commit 76e69839f7
2 changed files with 57 additions and 38 deletions

View File

@ -105,8 +105,8 @@ UHCI::UHCI(pci_info *info, Stack *stack)
// Setup the frame list
void *physicalAddress;
fFrameArea = fStack->AllocateArea((void **)&fFrameList[0],
(void **)&fPhysicalFrameList, 4096, "USB UHCI framelist");
fFrameArea = fStack->AllocateArea((void **)&fFrameList,
(void **)&physicalAddress, 4096, "USB UHCI framelist");
if (fFrameArea < B_OK) {
TRACE(("usb_uhci: unable to create an area for the frame pointer list\n"));
@ -115,7 +115,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
}
// Set base pointer and reset frame number
WriteReg32(UHCI_FRBASEADD, (uint32)fPhysicalFrameList);
WriteReg32(UHCI_FRBASEADD, (uint32)physicalAddress);
WriteReg16(UHCI_FRNUM, 0);
/*
@ -204,36 +204,37 @@ UHCI::UHCI(pci_info *info, Stack *stack)
fFrameList[i] = fQueueHeadInterrupt1->this_phy | FRAMELIST_NEXT_IS_QH;
}
// Set up the root hub
fRootHubAddress = AllocateAddress();
fRootHub = new UHCIRootHub(this, fRootHubAddress);
SetRootHub(fRootHub);
TRACE(("usb_uhci: installing interrupt handler\n"));
// Install the interrupt handler
install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
InterruptHandler, (void *)this, 0);
// Acknowledge any possible pending interrupts
WriteReg16(UHCI_USBSTS, 0xffff);
// Enable interrupts
WriteReg16(UHCI_USBINTR, UHCI_USBINTR_CRC | UHCI_USBINTR_RESUME
| UHCI_USBINTR_IOC | UHCI_USBINTR_SHORT);
TRACE(("usb_uhci: UHCI BusManager constructed\n"));
}
status_t
UHCI::Start()
{
//Start the host controller, then start the Busmanager
TRACE(("usb_uhci: usbcmd reg %u, usbsts reg %u\n", ReadReg16(UHCI_USBCMD),
ReadReg16(UHCI_USBSTS)));
// Start the host controller, then start the Busmanager
TRACE(("usb_uhci: starting UHCI BusManager\n"));
TRACE(("usb_uhci: usbcmd reg 0x%04x, usbsts reg 0x%04x\n",
ReadReg16(UHCI_USBCMD), ReadReg16(UHCI_USBSTS)));
// Set the run bit in the command register
WriteReg16(UHCI_USBCMD, ReadReg16(UHCI_USBCMD) | UHCI_USBCMD_RS);
bool running = false;
for (int32 i = 0; i < 10; i++) {
uint16 status = ReadReg16(UHCI_USBSTS);
TRACE(("usb_uhci: current loop %u, status %u\n", i, status));
TRACE(("usb_uhci: current loop %u, status 0x%04x\n", i, status));
if (status & UHCI_USBSTS_HCHALT)
snooze(1000);
snooze(10000);
else {
running = true;
break;
@ -245,16 +246,25 @@ UHCI::Start()
return B_ERROR;
}
// Enable interrupts
WriteReg16(UHCI_USBINTR, UHCI_USBINTR_CRC | UHCI_USBINTR_RESUME
| UHCI_USBINTR_IOC | UHCI_USBINTR_SHORT);
TRACE(("usb_uhci: controller is started. status: %u curframe: %u\n",
ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)));
return BusManager::Start();
}
status_t
UHCI::SetupRootHub()
{
TRACE(("usb_uhci: setting up root hub\n"));
fRootHubAddress = AllocateAddress();
fRootHub = new UHCIRootHub(this, fRootHubAddress);
SetRootHub(fRootHub);
return B_OK;
}
status_t
UHCI::SubmitTransfer(Transfer *transfer)
{
@ -315,15 +325,15 @@ UHCI::InterruptHandler(void *data)
int32
UHCI::Interrupt()
{
TRACE(("usb_uhci: Interrupt()\n"));
uint16 status = ReadReg16(UHCI_USBSTS);
uint16 acknowledge = 0;
TRACE(("usb_uhci: status: 0x%04x\n", status));
// Check if we really had an interrupt
if (status & UHCI_INTERRUPT_MASK == 0)
uint16 status = ReadReg16(UHCI_USBSTS);
if ((status & UHCI_INTERRUPT_MASK) == 0)
return B_UNHANDLED_INTERRUPT;
TRACE(("usb_uhci: Interrupt()\n"));
TRACE(("usb_uhci: status: 0x%04x\n", status));
uint16 acknowledge = 0;
if (status & UHCI_USBSTS_USBINT) {
TRACE(("usb_uhci: transfer finished\n"));
acknowledge |= UHCI_USBSTS_USBINT;
@ -354,7 +364,9 @@ UHCI::Interrupt()
// acknowledge not needed
}
if (acknowledge)
WriteReg16(UHCI_USBSTS, acknowledge);
return B_HANDLED_INTERRUPT;
}
@ -405,8 +417,9 @@ UHCI::InsertControl(Transfer *transfer)
if (fStack->AllocateChunk(&transferDescriptor->buffer_log,
&transferDescriptor->buffer_phy, sizeof(usb_request_data)) < B_OK) {
TRACE(("usb_uhci: unable to allocate space for the setup buffer\n"));
fStack->FreeChunk(transferDescriptor,
(void *)transferDescriptor->this_phy, 32);
fStack->FreeChunk(topQueueHead, (void *)topQueueHead->this_phy, 32);
fStack->FreeChunk(transferDescriptor, (void *)transferDescriptor->this_phy, 32);
return ENOMEM;
}
@ -422,8 +435,10 @@ UHCI::InsertControl(Transfer *transfer)
uhci_td *statusDescriptor;
if (fStack->AllocateChunk((void **)&statusDescriptor, &physicalAddress, 32) < B_OK) {
TRACE(("usb_uhci: failed to allocate the status descriptor\n"));
fStack->FreeChunk(transferDescriptor->buffer_log, (void *)transferDescriptor->buffer_phy, sizeof(usb_request_data));
fStack->FreeChunk(transferDescriptor, (void *)transferDescriptor->this_phy, 32);
fStack->FreeChunk(transferDescriptor->buffer_log,
(void *)transferDescriptor->buffer_phy, sizeof(usb_request_data));
fStack->FreeChunk(transferDescriptor,
(void *)transferDescriptor->this_phy, 32);
fStack->FreeChunk(topQueueHead, (void *)topQueueHead->this_phy, 32);
return ENOMEM;
}
@ -464,7 +479,7 @@ UHCI::InsertControl(Transfer *transfer)
} else {
// there are control transfers linked, append to the queue
uhci_qh *queueHead = (uhci_qh *)fQueueHeadControl->link_log;
while (queueHead->link_phy & QH_TERMINATE == 0)
while ((queueHead->link_phy & QH_TERMINATE) == 0)
queueHead = (uhci_qh *)queueHead->link_log;
queueHead->link_phy = topQueueHead->this_phy;
@ -484,12 +499,14 @@ UHCI::AddTo(Stack &stack)
load_driver_symbols("uhci");
#endif
if (!sPCIModule) {
status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
if (status < B_OK) {
TRACE(("usb_uhci: AddTo(): getting pci module failed! 0x%08x\n",
status));
return status;
}
}
TRACE(("usb_uhci: AddTo(): setting up hardware\n"));
@ -514,8 +531,9 @@ UHCI::AddTo(Stack &stack)
continue;
}
stack.AddBusManager(bus);
bus->Start();
bus->SetupRootHub();
stack.AddBusManager(bus);
found = true;
break;
}
@ -524,6 +542,7 @@ UHCI::AddTo(Stack &stack)
if (!found) {
TRACE(("usb_uhci: AddTo(): no devices found\n"));
delete item;
sPCIModule = NULL;
put_module(B_PCI_MODULE_NAME);
return ENODEV;
}

View File

@ -22,6 +22,7 @@ public:
UHCI(pci_info *info, Stack *stack);
status_t Start();
status_t SetupRootHub();
status_t SubmitTransfer(Transfer *transfer);
static bool AddTo(Stack &stack);
@ -52,8 +53,7 @@ static pci_module_info *sPCIModule;
// Frame list memory
area_id fFrameArea;
addr_t fFrameList[1024];
addr_t fPhysicalFrameList;
addr_t *fFrameList;
// Virtual frame
uhci_qh *fVirtualQueueHead[12];