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