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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
Reference in New Issue
Block a user