* Clean up (removing unneeded comment)

* Renaming, fixing coding guidelines
* Re-writing AddTo method
* Removing ohci_software.h file (its content has been moved to ohci.h) but it will probably be deleted in the future.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22522 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Salvatore Benedetto
2007-10-12 22:17:27 +00:00
parent 0eb5e06eef
commit 46a41c432c
3 changed files with 271 additions and 277 deletions
+106 -118
View File
@@ -1,67 +1,32 @@
//------------------------------------------------------------------------------ /*
// Copyright (c) 2005, Jan-Rixt Van Hoye * Copyright 2005-2008, Haiku Inc. All rights reserved.
// * Distributed under the terms of the MIT License.
// Permission is hereby granted, free of charge, to any person obtaining a *
// copy of this software and associated documentation files (the "Software"), * Authors:
// to deal in the Software without restriction, including without limitation * Jan-Rixt Van Hoye
// the rights to use, copy, modify, merge, publish, distribute, sublicense, * Salvatore Benedetto <[email protected]>
// and/or sell copies of the Software, and to permit persons to whom the */
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// explanation of this file:
// -------------------------
//
// This is the implementation of the OHCI module for the Haiku USB stack
// It is bases on the hcir1_0a documentation that can be found on www.usb.org
// Some parts are derive from source-files from openbsd, netbsd and linux.
//
// ------------------------------------------------------------------------
// ---------------------------
// OHCI:: Includes
// ---------------------------
#include <module.h> #include <module.h>
#include <PCI.h> #include <PCI.h>
#include <USB3.h> #include <USB3.h>
#include <KernelExport.h> #include <KernelExport.h>
#include <stdlib.h> #include <stdlib.h>
// ---------------------------
// OHCI:: Local includes
// ---------------------------
#include "ohci.h" #include "ohci.h"
#include "ohci_hardware.h"
#include "usb_p.h" pci_module_info *OHCI::sPCIModule = NULL;
//------------------------------------------------------ //------------------------------------------------------
// OHCI:: Reverse the bits in a value between 0 and 31 // OHCI:: Reverse the bits in a value between 0 and 31
// (Section 3.3.2) // (Section 3.3.2)
//------------------------------------------------------ //------------------------------------------------------
static uint8 revbits[OHCI_NUMBER_OF_INTERRUPTS] =
static uint8 revbits[OHCI_NO_INTRS] =
{ 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e, 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d, 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f }; 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f };
//------------------------------------------------------------------------
// OHCI:: These are the OHCI operations that can be done.
//
// parameters:
// - op: operation
//------------------------------------------------------------------------
static int32 static int32
ohci_std_ops( int32 op , ... ) ohci_std_ops( int32 op , ... )
@@ -69,14 +34,15 @@ ohci_std_ops( int32 op , ... )
switch (op) switch (op)
{ {
case B_MODULE_INIT: case B_MODULE_INIT:
TRACE(("ohci_module: init the module\n")); TRACE(("usb_ohci_module: init module\n"));
return B_OK; return B_OK;
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
TRACE(("ohci_module: uninit the module\n")); TRACE(("usb_ohci_module: uninit module\n"));
break; break;
default: default:
return EINVAL; return EINVAL;
} }
return B_OK; return B_OK;
} }
@@ -87,67 +53,82 @@ ohci_std_ops( int32 op , ... )
// - &stack: reference to a stack instance form stack.cpp // - &stack: reference to a stack instance form stack.cpp
//------------------------------------------------------------------------ //------------------------------------------------------------------------
static status_t status_t
ohci_add_to(Stack *stack) OHCI::AddTo(Stack *stack)
{ {
status_t status;
pci_info *item;
bool found = false;
int i;
#ifdef TRACE_USB #ifdef TRACE_USB
set_dprintf_enabled(true); set_dprintf_enabled(true);
load_driver_symbols("ohci"); load_driver_symbols("ohci");
#endif #endif
// if (!sPCIModule) {
// Try if the PCI module is loaded status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
// if (status < B_OK) {
if( ( status = get_module( B_PCI_MODULE_NAME, (module_info **)&( OHCI::pci_module ) ) ) != B_OK) { TRACE_ERROR(("usb_ohci: AddTo(): getting pci module failed! 0x%08lx\n",
TRACE(("USB_ OHCI: init_hardware(): Get PCI module failed! %lu \n", status)); status));
return status; return status;
}
} }
TRACE(("usb_ohci init_hardware(): Setting up hardware\n"));
item = new pci_info; TRACE(("usb_ohci: AddTo(): setting up hardware\n"));
for ( i = 0 ; OHCI::pci_module->get_nth_pci_info( i , item ) == B_OK ; i++ ) {
if ( ( item->class_base == PCI_serial_bus ) && ( item->class_sub == PCI_usb ) bool found = false;
&& ( item->class_api == PCI_usb_ohci ) ) pci_info *item = new(std::nothrow) pci_info;
{ if (!item) {
if ((item->u.h0.interrupt_line == 0) || (item->u.h0.interrupt_line == 0xFF)) { sPCIModule = NULL;
TRACE(("USB OHCI: init_hardware(): found with invalid IRQ - check IRQ assignement\n")); put_module(B_PCI_MODULE_NAME);
return B_NO_MEMORY;
}
for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
&& item->class_api == PCI_usb_ohci) {
if (item->u.h0.interrupt_line == 0
|| item->u.h0.interrupt_line == 0xFF) {
TRACE_ERROR(("usb_ohci: AddTo(): found with invalid IRQ -"
" check IRQ assignement\n"));
continue; continue;
} }
TRACE(("USB OHCI: init_hardware(): found at IRQ %u \n", item->u.h0.interrupt_line));
TRACE(("usb_ohci: AddTo(): found at IRQ %u\n",
item->u.h0.interrupt_line));
OHCI *bus = new(std::nothrow) OHCI(item, stack); OHCI *bus = new(std::nothrow) OHCI(item, stack);
if (!bus) { if (!bus) {
delete item; delete item;
OHCI::pci_module = NULL; sPCIModule = NULL;
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
return B_NO_MEMORY; return B_NO_MEMORY;
} }
if (bus->InitCheck() != B_OK) { if (bus->InitCheck() < B_OK) {
TRACE(("usb_ohci: bus failed to initialize...\n")); TRACE_ERROR(("usb_ohci: AddTo(): InitCheck() failed 0x%08lx\n",
bus->InitCheck()));
delete bus; delete bus;
continue; continue;
} }
bus->Start(); // the bus took it away
stack->AddBusManager( bus ); item = new(std::nothrow) pci_info;
bus->Start();
stack->AddBusManager(bus);
found = true; found = true;
} }
} }
if (!found) { if (!found) {
TRACE(("USB OHCI: init hardware(): no devices found\n")); TRACE_ERROR(("usb_ohci: no devices found\n"));
free( item ); delete item;
put_module( B_PCI_MODULE_NAME ); put_module(B_PCI_MODULE_NAME);
return ENODEV; return ENODEV;
} }
return B_OK; //Hardware found
delete item;
return B_OK;
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// OHCI:: Host controller information // OHCI:: Host controller information
// //
@@ -157,11 +138,11 @@ ohci_add_to(Stack *stack)
host_controller_info ohci_module = { host_controller_info ohci_module = {
{ {
"busses/usb/ohci", "busses/usb/ohci",
0, // No flag like B_KEEP_LOADED : the usb module does that 0,
ohci_std_ops ohci_std_ops
}, },
NULL , NULL,
ohci_add_to OHCI::AddTo
}; };
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@@ -194,10 +175,10 @@ OHCI::OHCI(pci_info *info, Stack *stack)
fRootHubAddress(0), fRootHubAddress(0),
fNumPorts(0) fNumPorts(0)
{ {
fPcii = info; fPCIInfo = info;
fStack = stack; fStack = stack;
int i; int i;
TRACE(("USB OHCI: constructing new BusManager\n")); TRACE(("usb_ohci: constructing new BusManager\n"));
fInitOK = false; fInitOK = false;
@@ -205,22 +186,22 @@ OHCI::OHCI(pci_info *info, Stack *stack)
fInterruptEndpoints[i] = 0; fInterruptEndpoints[i] = 0;
// enable busmaster and memory mapped access // enable busmaster and memory mapped access
uint16 cmd = OHCI::pci_module->read_pci_config(fPcii->bus, fPcii->device, fPcii->function, PCI_command, 2); uint16 cmd = sPCIModule->read_pci_config(fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
cmd &= ~PCI_command_io; cmd &= ~PCI_command_io;
cmd |= PCI_command_master | PCI_command_memory; cmd |= PCI_command_master | PCI_command_memory;
OHCI::pci_module->write_pci_config(fPcii->bus, fPcii->device, fPcii->function, PCI_command, 2, cmd ); sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function, PCI_command, 2, cmd );
// //
// 5.1.1.2 map the registers // 5.1.1.2 map the registers
// //
addr_t registeroffset = pci_module->read_pci_config(info->bus, addr_t registeroffset = sPCIModule->read_pci_config(info->bus,
info->device, info->function, PCI_base_registers, 4); info->device, info->function, PCI_base_registers, 4);
registeroffset &= PCI_address_memory_32_mask; registeroffset &= PCI_address_memory_32_mask;
TRACE(("OHCI: iospace offset: %lx\n" , registeroffset)); TRACE(("OHCI: iospace offset: %lx\n" , registeroffset));
fRegisterArea = map_physical_memory("OHCI base registers", (void *)registeroffset, fRegisterArea = map_physical_memory("OHCI base registers", (void *)registeroffset,
B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA, (void **)&fRegisters); B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA, (void **)&fRegisterBase);
if (fRegisterArea < B_OK) { if (fRegisterArea < B_OK) {
TRACE(("USB OHCI: error mapping the registers\n")); TRACE(("usb_ohci: error mapping the registers\n"));
return; return;
} }
@@ -230,7 +211,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
// Check the revision of the controller. The revision should be 10xh // Check the revision of the controller. The revision should be 10xh
TRACE((" OHCI: Version %ld.%ld%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),OHCI_REV_LEGACY(rev) ? ", legacy support" : "")); TRACE((" OHCI: Version %ld.%ld%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),OHCI_REV_LEGACY(rev) ? ", legacy support" : ""));
if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) { if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
TRACE(("USB OHCI: Unsupported OHCI revision of the ohci device\n")); TRACE(("usb_ohci: Unsupported OHCI revision of the ohci device\n"));
return; return;
} }
@@ -239,7 +220,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
fHccaArea = fStack->AllocateArea((void**)&fHcca, &hcca_phy, fHccaArea = fStack->AllocateArea((void**)&fHcca, &hcca_phy,
B_PAGE_SIZE, "OHCI HCCA"); B_PAGE_SIZE, "OHCI HCCA");
if (fHccaArea < B_OK) { if (fHccaArea < B_OK) {
TRACE(("USB OHCI: Error allocating HCCA block\n")); TRACE(("usb_ohci: Error allocating HCCA block\n"));
return; return;
} }
memset((void*)fHcca, 0, sizeof(ohci_hcca)); memset((void*)fHcca, 0, sizeof(ohci_hcca));
@@ -248,14 +229,14 @@ OHCI::OHCI(pci_info *info, Stack *stack)
// 5.1.1.3 Take control of the host controller // 5.1.1.3 Take control of the host controller
// //
if (ReadReg(OHCI_CONTROL) & OHCI_IR) { if (ReadReg(OHCI_CONTROL) & OHCI_IR) {
TRACE(("USB OHCI: SMM is in control of the host controller\n")); TRACE(("usb_ohci: SMM is in control of the host controller\n"));
WriteReg(OHCI_COMMAND_STATUS, OHCI_OCR); WriteReg(OHCI_COMMAND_STATUS, OHCI_OCR);
for (int i = 0; i < 100 && (ReadReg(OHCI_CONTROL) & OHCI_IR); i++) for (int i = 0; i < 100 && (ReadReg(OHCI_CONTROL) & OHCI_IR); i++)
snooze(1000); snooze(1000);
if (ReadReg(OHCI_CONTROL) & OHCI_IR) if (ReadReg(OHCI_CONTROL) & OHCI_IR)
TRACE(("USB OHCI: SMM doesn't respond... continueing anyway...\n")); TRACE(("usb_ohci: SMM doesn't respond... continueing anyway...\n"));
} else if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_RESET)) { } else if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_RESET)) {
TRACE(("USB OHCI: BIOS is in control of the host controller\n")); TRACE(("usb_ohci: BIOS is in control of the host controller\n"));
if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_OPERATIONAL)) { if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_OPERATIONAL)) {
WriteReg(OHCI_CONTROL, OHCI_HCFS_RESUME); WriteReg(OHCI_CONTROL, OHCI_HCFS_RESUME);
snooze(USB_DELAY_BUS_RESET); snooze(USB_DELAY_BUS_RESET);
@@ -287,9 +268,9 @@ OHCI::OHCI(pci_info *info, Stack *stack)
else else
fInterruptEndpoints[i]->SetNext(fDummyIsochronous); fInterruptEndpoints[i]->SetNext(fDummyIsochronous);
} }
for (i = 0; i < OHCI_NO_INTRS; i++) for (i = 0; i < OHCI_NUMBER_OF_INTERRUPTS; i++)
fHcca->hcca_interrupt_table[revbits[i]] = fHcca->hcca_interrupt_table[revbits[i]] =
fInterruptEndpoints[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physicaladdress; fInterruptEndpoints[OHCI_NO_EDS-OHCI_NUMBER_OF_INTERRUPTS+i]->physicaladdress;
//Go to the hardware part of the initialisation //Go to the hardware part of the initialisation
uint32 frameinterval = ReadReg(OHCI_FM_INTERVAL); uint32 frameinterval = ReadReg(OHCI_FM_INTERVAL);
@@ -301,7 +282,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
break; break;
} }
if (ReadReg(OHCI_COMMAND_STATUS) & OHCI_HCR) { if (ReadReg(OHCI_COMMAND_STATUS) & OHCI_HCR) {
TRACE(("USB OHCI: Error resetting the host controller\n")); TRACE(("usb_ohci: Error resetting the host controller\n"));
return; return;
} }
@@ -368,7 +349,7 @@ OHCI::Start()
return B_ERROR; return B_ERROR;
if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_OPERATIONAL)) { if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_OPERATIONAL)) {
TRACE(("USB OHCI::Start(): Controller not started. TODO: find out what happens.\n")); TRACE(("usb_ohci::Start(): Controller not started. TODO: find out what happens.\n"));
return B_ERROR; return B_ERROR;
} }
@@ -377,17 +358,17 @@ OHCI::Start()
fRootHub = new(std::nothrow) OHCIRootHub(this, fRootHubAddress); fRootHub = new(std::nothrow) OHCIRootHub(this, fRootHubAddress);
if (!fRootHub) { if (!fRootHub) {
TRACE_ERROR(("USB OHCI::Start(): no memory to allocate root hub\n")); TRACE_ERROR(("usb_ohci::Start(): no memory to allocate root hub\n"));
return B_NO_MEMORY; return B_NO_MEMORY;
} }
if (fRootHub->InitCheck() < B_OK) { if (fRootHub->InitCheck() < B_OK) {
TRACE_ERROR(("USB OHCI::Start(): root hub failed init check\n")); TRACE_ERROR(("usb_ohci::Start(): root hub failed init check\n"));
return B_ERROR; return B_ERROR;
} }
SetRootHub(fRootHub); SetRootHub(fRootHub);
TRACE(("USB OHCI::Start(): Succesful start\n")); TRACE(("usb_ohci::Start(): Succesful start\n"));
return B_OK; return B_OK;
} }
@@ -525,7 +506,7 @@ OHCI::AllocateEndpoint()
//Add a NULL list by creating one TransferDescriptor //Add a NULL list by creating one TransferDescriptor
TransferDescriptor *trans = new(std::nothrow) TransferDescriptor; TransferDescriptor *trans = new(std::nothrow) TransferDescriptor;
endpoint->head = endpoint->tail = trans; endpoint->head = endpoint->tail = trans;
endpoint->ed->headp = endpoint->ed->tailp = trans->physicaladdress; endpoint->ed->head_pointer = endpoint->ed->tail_pointer = trans->physicaladdress;
return endpoint; return endpoint;
} }
@@ -544,12 +525,12 @@ OHCI::AllocateTransfer()
TRACE(("OHCI::%s()\n", __FUNCTION__)); TRACE(("OHCI::%s()\n", __FUNCTION__));
TransferDescriptor *transfer = new TransferDescriptor; TransferDescriptor *transfer = new TransferDescriptor;
void *phy; void *phy;
if (fStack->AllocateChunk((void **)&transfer->td, &phy, sizeof(ohci_transfer_descriptor)) != B_OK) { if (fStack->AllocateChunk((void **)&transfer->td, &phy, sizeof(ohci_general_transfer_descriptor)) != B_OK) {
TRACE(("OHCI::AllocateTransfer(): Error Allocating Transfer\n")); TRACE(("OHCI::AllocateTransfer(): Error Allocating Transfer\n"));
return 0; return 0;
} }
transfer->physicaladdress = (addr_t)phy; transfer->physicaladdress = (addr_t)phy;
memset((void *)transfer->td, 0, sizeof(ohci_transfer_descriptor)); memset((void *)transfer->td, 0, sizeof(ohci_general_transfer_descriptor));
return transfer; return transfer;
} }
@@ -557,7 +538,7 @@ void
OHCI::FreeTransfer(TransferDescriptor *trans) OHCI::FreeTransfer(TransferDescriptor *trans)
{ {
TRACE(("OHCI::%s(%p)\n", __FUNCTION__, trans)); TRACE(("OHCI::%s(%p)\n", __FUNCTION__, trans));
fStack->FreeChunk((void *)trans->td, (void *) trans->physicaladdress, sizeof(ohci_transfer_descriptor)); fStack->FreeChunk((void *)trans->td, (void *) trans->physicaladdress, sizeof(ohci_general_transfer_descriptor));
delete trans; delete trans;
} }
@@ -579,21 +560,21 @@ OHCI::InsertEndpointForPipe(Pipe *p)
uint32 properties = 0; uint32 properties = 0;
//Set the device address //Set the device address
properties |= OHCI_ENDPOINT_SET_FA(p->DeviceAddress()); properties |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(p->DeviceAddress());
//Set the endpoint number //Set the endpoint number
properties |= OHCI_ENDPOINT_SET_EN(p->EndpointAddress()); properties |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(p->EndpointAddress());
//Set the direction //Set the direction
switch (p->Direction()) { switch (p->Direction()) {
case Pipe::In: case Pipe::In:
properties |= OHCI_ENDPOINT_DIR_IN; properties |= OHCI_ENDPOINT_DIRECTION_IN;
break; break;
case Pipe::Out: case Pipe::Out:
properties |= OHCI_ENDPOINT_DIR_OUT; properties |= OHCI_ENDPOINT_DIRECTION_OUT;
break; break;
case Pipe::Default: case Pipe::Default:
properties |= OHCI_ENDPOINT_DIR_TD; properties |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
break; break;
default: default:
//TODO: error //TODO: error
@@ -616,10 +597,10 @@ OHCI::InsertEndpointForPipe(Pipe *p)
//Assign the format. Isochronous endpoints require this switch //Assign the format. Isochronous endpoints require this switch
if (p->Type() & USB_OBJECT_ISO_PIPE) if (p->Type() & USB_OBJECT_ISO_PIPE)
properties |= OHCI_ENDPOINT_FORMAT_ISO; properties |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
//Set the maximum packet size //Set the maximum packet size
properties |= OHCI_ENDPOINT_SET_MAXP(p->MaxPacketSize()); properties |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(p->MaxPacketSize());
endpoint->ed->flags = properties; endpoint->ed->flags = properties;
} }
@@ -653,18 +634,25 @@ OHCI::InsertEndpointForPipe(Pipe *p)
return B_OK; return B_OK;
} }
pci_module_info *OHCI::pci_module = 0; pci_module_info *sPCIModule = 0;
void void
OHCI::WriteReg(uint32 reg, uint32 value) OHCI::WriteReg(uint32 reg, uint32 value)
{ {
TRACE(("OHCI::%s(%lu, %lu)\n", __FUNCTION__, reg, value)); TRACE(("OHCI::%s(%lu, %lu)\n", __FUNCTION__, reg, value));
*(volatile uint32 *)(fRegisters + reg) = value; *(volatile uint32 *)(fRegisterBase + reg) = value;
} }
uint32 uint32
OHCI::ReadReg(uint32 reg) OHCI::ReadReg(uint32 reg)
{ {
TRACE(("OHCI::%s(%lu)\n", __FUNCTION__, reg)); TRACE(("OHCI::%s(%lu)\n", __FUNCTION__, reg));
return *(volatile uint32 *)(fRegisters + reg); return *(volatile uint32 *)(fRegisterBase + reg);
} }
status_t
OHCI::CancelQueuedTransfers(Pipe *pipe)
{
return B_ERROR;
}
+71 -51
View File
@@ -1,42 +1,52 @@
//------------------------------------------------------------------------------ /*
// Copyright (c) 2005, Jan-Rixt Van Hoye * Copyright 2005-2008, Haiku Inc. All rights reserved.
// * Distributed under the terms of the MIT License.
// Permission is hereby granted, free of charge, to any person obtaining a *
// copy of this software and associated documentation files (the "Software"), * Authors:
// to deal in the Software without restriction, including without limitation * Jan-Rixt Van Hoye
// the rights to use, copy, modify, merge, publish, distribute, sublicense, * Salvatore Benedetto <[email protected]>
// and/or sell copies of the Software, and to permit persons to whom the */
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//-------------------------------------------------------------------------------
#ifndef OHCI_H #ifndef OHCI_H
#define OHCI_H #define OHCI_H
// ---------------------------
// OHCI:: Includes
// ---------------------------
#include "usb_p.h" #include "usb_p.h"
#include "ohci_software.h" #include "ohci_hardware.h"
#include <lock.h>
struct pci_info; struct pci_info;
struct pci_module_info; struct pci_module_info;
class OHCIRootHub; class OHCIRootHub;
struct Endpoint; struct Endpoint;
struct TransferDescriptor; struct TransferDescriptor;
// --------------------------------------
// OHCI:: Software isonchronous
// transfer descriptor
// --------------------------------------
typedef struct hcd_soft_itransfer
{
ohci_isochronous_transfer_descriptor itd;
struct hcd_soft_itransfer *nextitd; // mirrors nexttd in ITD
struct hcd_soft_itransfer *dnext; // next in done list
addr_t physaddr; // physical address to the host controller isonchronous transfer
//LIST_ENTRY(hcd_soft_itransfer) hnext;
uint16 flags; // flags
#ifdef DIAGNOSTIC
char isdone; // is the transfer done?
#endif
}hcd_soft_itransfer;
#define OHCI_SITD_SIZE ((sizeof (struct hcd_soft_itransfer) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN)
#define OHCI_SITD_CHUNK 64
// ------------------------------------------
// OHCI:: Number of enpoint descriptors (63)
// ------------------------------------------
#define OHCI_NO_EDS (2 * OHCI_NUMBER_OF_INTERRUPTS - 1)
// -------------------------------- // --------------------------------
// OHCI: The OHCI class derived // OHCI: The OHCI class derived
// from the BusManager // from the BusManager
@@ -46,31 +56,40 @@ class OHCI : public BusManager
{ {
friend class OHCIRootHub; friend class OHCIRootHub;
public: public:
OHCI(pci_info *info, Stack *stack);
~OHCI();
status_t Start();
status_t SubmitTransfer(Transfer *t); //Override from BusManager.
status_t NotifyPipeChange(Pipe *pipe, //Override from BusManager.
usb_change change);
static pci_module_info *pci_module; // Global data for the module. OHCI(pci_info *info, Stack *stack);
~OHCI();
status_t GetPortStatus(uint8 index, usb_port_status *status); status_t Start();
status_t ClearPortFeature(uint8 index, uint16 feature); virtual status_t SubmitTransfer(Transfer *transfer);
status_t SetPortFeature(uint8 index, uint16 feature); virtual status_t CancelQueuedTransfers(Pipe *pipe);
uint8 PortCount() { return fNumPorts; }; virtual status_t NotifyPipeChange(Pipe *pipe,
usb_change change);
static status_t AddTo(Stack *stack);
// Port operations
status_t GetPortStatus(uint8 index, usb_port_status *status);
status_t SetPortFeature(uint8 index, uint16 feature);
status_t ClearPortFeature(uint8 index, uint16 feature);
uint8 PortCount() { return fNumPorts; };
private: private:
inline void WriteReg(uint32 reg, uint32 value); // Register functions
inline uint32 ReadReg(uint32 reg); inline void WriteReg(uint32 reg, uint32 value);
inline uint32 ReadReg(uint32 reg);
// Global // Global
pci_info *fPcii; // pci-info struct static pci_module_info *sPCIModule;
Stack *fStack; // Pointer to the stack
uint8 *fRegisters; // Base address of the operational registers uint32 *fRegisterBase;
area_id fRegisterArea; // Area id of the pci_info *fPCIInfo;
Stack *fStack;
area_id fRegisterArea;
// HCCA // HCCA
area_id fHccaArea; area_id fHccaArea;
struct ohci_hcca *fHcca; // The HCCA structure for the interupt communication struct ohci_hcca *fHcca; // The HCCA structure for the interupt communication
@@ -79,10 +98,6 @@ private:
Endpoint *fDummyControl; Endpoint *fDummyControl;
Endpoint *fDummyBulk; Endpoint *fDummyBulk;
Endpoint *fDummyIsochronous; Endpoint *fDummyIsochronous;
// Root Hub
OHCIRootHub *fRootHub; // the root hub
uint8 fRootHubAddress; // the usb address of the roothub
uint8 fNumPorts; // the number of ports
// functions // functions
Endpoint *AllocateEndpoint(); // allocate memory for an endpoint Endpoint *AllocateEndpoint(); // allocate memory for an endpoint
void FreeEndpoint(Endpoint *end); // Free endpoint void FreeEndpoint(Endpoint *end); // Free endpoint
@@ -90,6 +105,11 @@ private:
void FreeTransfer(TransferDescriptor *trans); // Free transfer void FreeTransfer(TransferDescriptor *trans); // Free transfer
status_t InsertEndpointForPipe(Pipe *p); status_t InsertEndpointForPipe(Pipe *p);
// Root Hub
OHCIRootHub *fRootHub;
uint8 fRootHubAddress;
uint8 fNumPorts;
}; };
// -------------------------------- // --------------------------------
@@ -132,7 +152,7 @@ struct Endpoint
struct TransferDescriptor struct TransferDescriptor
{ {
addr_t physicaladdress; addr_t physicaladdress;
ohci_transfer_descriptor *td; ohci_general_transfer_descriptor *td;
}; };
#endif // OHCI_H #endif // OHCI_H
+94 -108
View File
@@ -1,24 +1,11 @@
//------------------------------------------------------------------------------ /*
// Copyright (c) 2005, Jan-Rixt Van Hoye * Copyright 2005-2008, Haiku Inc. All rights reserved.
// * Distributed under the terms of the MIT License.
// Permission is hereby granted, free of charge, to any person obtaining a *
// copy of this software and associated documentation files (the "Software"), * Authors:
// to deal in the Software without restriction, including without limitation * Jan-Rixt Van Hoye
// the rights to use, copy, modify, merge, publish, distribute, sublicense, * Salvatore Benedetto <[email protected]>
// and/or sell copies of the Software, and to permit persons to whom the */
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//------------------------------------------------------------------------------
#ifndef OHCI_HARD_H #ifndef OHCI_HARD_H
#define OHCI_HARD_H #define OHCI_HARD_H
@@ -31,9 +18,9 @@
// Revision register (section 7.1.1) // Revision register (section 7.1.1)
// -------------------------------- // --------------------------------
#define OHCI_REVISION 0x00 // OHCI revision #define OHCI_REVISION 0x00
#define OHCI_REV_LO(rev) ((rev)&0x0f) #define OHCI_REV_LO(rev) ((rev) & 0x0f)
#define OHCI_REV_HI(rev) (((rev)>>4)&0x03) #define OHCI_REV_HI(rev) (((rev) >> 4) & 0x03)
#define OHCI_REV_LEGACY(rev) ((rev) & 0x10) #define OHCI_REV_LEGACY(rev) ((rev) & 0x10)
// -------------------------------- // --------------------------------
@@ -71,7 +58,7 @@
#define OHCI_SOC_MASK 0x00030000 // Scheduling Overrun Count #define OHCI_SOC_MASK 0x00030000 // Scheduling Overrun Count
// -------------------------------- // --------------------------------
// Interupt status register (section 7.1.4) // Interrupt status register (section 7.1.4)
// -------------------------------- // --------------------------------
#define OHCI_INTERRUPT_STATUS 0x0c #define OHCI_INTERRUPT_STATUS 0x0c
@@ -273,11 +260,11 @@ typedef uint32 ohci_physaddr_t;
// HCCA structure (section 4.4) // HCCA structure (section 4.4)
// -------------------------------- // --------------------------------
#define OHCI_NO_INTRS 32 #define OHCI_NUMBER_OF_INTERRUPTS 32
struct ohci_hcca typedef struct ohci_hcca
{ {
addr_t hcca_interrupt_table[OHCI_NO_INTRS]; addr_t hcca_interrupt_table[OHCI_NUMBER_OF_INTERRUPTS];
uint32 hcca_frame_number; uint32 hcca_frame_number;
addr_t hcca_done_head; addr_t hcca_done_head;
uint8 hcca_reserved_for_hc[116]; uint8 hcca_reserved_for_hc[116];
@@ -297,114 +284,113 @@ struct ohci_hcca
typedef struct ohci_endpoint_descriptor typedef struct ohci_endpoint_descriptor
{ {
uint32 flags; uint32 flags;
addr_t tailp; // Queue tail pointer uint32 tail_pointer; // Queue tail pointer
addr_t headp; // Queue head pointer uint32 head_pointer; // Queue head pointer
addr_t next_endpoint; // Next endpoint in the list uint32 next_endpoint; // Next endpoint in the list
}; };
#define OHCI_ENDPOINT_GET_FA(s) ((s) & 0x7f) #define OHCI_ENDPOINT_ADDRESS_MASK 0x0000007f
#define OHCI_ENDPOINT_ADDRMASK 0x0000007f #define OHCI_ENDPOINT_GET_DEVICE_ADDRESS(s) ((s) & 0x7f)
#define OHCI_ENDPOINT_SET_FA(s) (s) #define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s) (s)
#define OHCI_ENDPOINT_GET_EN(s) (((s) >> 7) & 0xf) #define OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s) (((s) >> 7) & 0xf)
#define OHCI_ENDPOINT_SET_EN(s) ((s) << 7) #define OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s) ((s) << 7)
#define OHCI_ENDPOINT_DIR_MASK 0x00001800 #define OHCI_ENDPOINT_DIRECTION_MASK 0x00001800
#define OHCI_ENDPOINT_DIR_TD 0x00000000 #define OHCI_ENDPOINT_DIRECTION_DESCRIPTOR 0x00000000
#define OHCI_ENDPOINT_DIR_OUT 0x00000800 #define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800
#define OHCI_ENDPOINT_DIR_IN 0x00001000 #define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
#define OHCI_ENDPOINT_SPEED 0x00002000 #define OHCI_ENDPOINT_SPEED 0x00002000
#define OHCI_ENDPOINT_SKIP 0x00004000 #define OHCI_ENDPOINT_SKIP 0x00004000
#define OHCI_ENDPOINT_FORMAT_GEN 0x00000000 #define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
#define OHCI_ENDPOINT_FORMAT_ISO 0x00008000 #define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
#define OHCI_ENDPOINT_GET_MAXP(s) (((s) >> 16) & 0x07ff) #define OHCI_ENDPOINT_MAX_PACKET_SIZE_MASK (0x7ff << 16)
#define OHCI_ENDPOINT_SET_MAXP(s) ((s) << 16) #define OHCI_ENDPOINT_GET_MAX_PACKET_SIZE(s) (((s) >> 16) & 0x07ff)
#define OHCI_ENDPOINT_MAXPMASK (0x7ff << 16) #define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16)
#define OHCI_ENDPOINT_HALTED 0x00000001
#define OHCI_HALTED 0x00000001 #define OHCI_ENDPOINT_TOGGLE_CARRY 0x00000002
#define OHCI_TOGGLECARRY 0x00000002 #define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc
#define OHCI_HEADMASK 0xfffffffc
// -------------------------------- // --------------------------------
// General transfer descriptor structure (section 4.3.1) // General transfer descriptor structure (section 4.3.1)
// -------------------------------- // --------------------------------
typedef struct ohci_transfer_descriptor typedef struct ohci_general_transfer_descriptor
{ {
uint32 flags; uint32 flags;
addr_t td_cbp; // Current Buffer Pointer uint32 buffer_phy; // Physical buffer pointer
addr_t td_nexttd; // Next Transfer Descriptor uint32 next_descriptor; // Next transfer descriptor
addr_t td_be; // Buffer End uint32 last_byte_address; // Physical buffer end
} ; };
#define OHCI_TD_R 0x00040000 // Buffer Rounding #define OHCI_BUFFER_ROUNDING 0x00040000 // Buffer Rounding
#define OHCI_TD_DP_MASK 0x00180000 // Direction / PID #define OHCI_TD_DIRECTION_PID_MASK 0x00180000 // Direction / PID
#define OHCI_TD_SETUP 0x00000000 #define OHCI_TD_DIRECTION_PID_SETUP 0x00000000
#define OHCI_TD_OUT 0x00080000 #define OHCI_TD_DIRECTION_PID_OUT 0x00080000
#define OHCI_TD_IN 0x00100000 #define OHCI_TD_DIRECTION_PID_IN 0x00100000
#define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) // Delay Interrupt #define OHCI_TD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7) // Delay Interrupt
#define OHCI_TD_SET_DI(x) ((x) << 21) #define OHCI_TD_SET_DELAY_INTERRUPT(x) ((x) << 21)
#define OHCI_TD_NOINTR 0x00e00000 #define OHCI_TD_NO_INTERRUPT 0x00e00000
#define OHCI_TD_INTR_MASK 0x00e00000 #define OHCI_TD_INTERRUPT_MASK 0x00e00000
#define OHCI_TD_TOGGLE_CARRY 0x00000000 #define OHCI_TD_TOGGLE_CARRY 0x00000000
#define OHCI_TD_TOGGLE_0 0x02000000 #define OHCI_TD_TOGGLE_0 0x02000000
#define OHCI_TD_TOGGLE_1 0x03000000 #define OHCI_TD_TOGGLE_1 0x03000000
#define OHCI_TD_TOGGLE_MASK 0x03000000 #define OHCI_TD_TOGGLE_MASK 0x03000000
#define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) // Error Count #define OHCI_TD_GET_ERROR_COUNT(x) (((x) >> 26) & 3) // Error Count
#define OHCI_TD_GET_CC(x) ((x) >> 28) // Condition Code #define OHCI_TD_GET_CONDITION_CODE(x) ((x) >> 28) // Condition Code
#define OHCI_TD_NOCC 0xf0000000 #define OHCI_TD_NO_CONDITION_CODE 0xf0000000
#define OHCI_TD_ALIGN 16 #define OHCI_GENERAL_TD_ALIGN 16
// -------------------------------- // --------------------------------
// Isonchronous transfer descriptor structure (section 4.3.2) // Isonchronous transfer descriptor structure (section 4.3.2)
// -------------------------------- // --------------------------------
#define OHCI_ITD_NOFFSET 8 #define OHCI_ITD_NOFFSET 8
typedef struct hc_itransfer_descriptor typedef struct ohci_isochronous_transfer_descriptor
{ {
uint32 itd_flags; uint32 flags;
addr_t itd_bp0; // Buffer Page 0 uint32 buffer_page_byte_0; // Physical page number of byte 0
addr_t itd_nextitd; // Next Isochronous Transfer Descriptor uint32 next_descriptor; // Next isochronous transfer descriptor
addr_t itd_be; // Buffer End uint32 last_byte_address; // Physical buffer end
uint16 itd_offset[OHCI_ITD_NOFFSET]; // Buffer offsets uint16 offset[OHCI_ITD_NOFFSET]; // Buffer offsets
}; };
#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff) #define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff)
#define OHCI_ITD_SET_SF(x) ((x) & 0xffff) #define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff)
#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) // Delay Interrupt #define OHCI_ITD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7)
#define OHCI_ITD_SET_DI(x) ((x) << 21) #define OHCI_ITD_SET_DELAY_INTERRUPT(x) ((x) << 21)
#define OHCI_ITD_NOINTR 0x00e00000 #define OHCI_ITD_NO_INTERRUPT 0x00e00000
#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) // Frame Count #define OHCI_ITD_GET_FRAME_COUNT(x) ((((x) >> 24) & 7) + 1)
#define OHCI_ITD_SET_FC(x) (((x)-1) << 24) #define OHCI_ITD_SET_FRAME_COUNT(x) (((x) - 1) << 24)
#define OHCI_ITD_GET_CC(x) ((x) >> 28) // Condition Code #define OHCI_ITD_GET_CONDITION_CODE(x) ((x) >> 28)
#define OHCI_ITD_NOCC 0xf0000000 #define OHCI_ITD_NO_CONDITION_CODE 0xf0000000
#define itd_pswn itd_offset // Packet Status Word // TO FIX
#define OHCI_ITD_PAGE_SELECT 0x00001000 #define itd_pswn itd_offset // Packet Status Word
#define OHCI_ITD_MK_OFFS(len) (0xe000 | ((len) & 0x1fff)) #define OHCI_ITD_PAGE_SELECT 0x00001000
#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) // Transfer length #define OHCI_ITD_MK_OFFS(len) (0xe000 | ((len) & 0x1fff))
#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) // Condition Code #define OHCI_ITD_GET_BUFFER_LENGTH(x) ((x) & 0xfff) // Transfer length
#define OHCI_ITD_GET_BUFFER_CONDITION_CODE(x) ((x) >> 12) // Condition Code
#define OHCI_ITD_ALIGN 32 #define OHCI_ISOCHRONOUS_TD_ALIGN 32
// -------------------------------- // --------------------------------
// Completion Codes (section 4.3.3) // Completion Codes (section 4.3.3)
// -------------------------------- // --------------------------------
#define OHCI_CC_NO_ERROR 0 #define OHCI_NO_ERROR 0
#define OHCI_CC_CRC 1 #define OHCI_CRC 1
#define OHCI_CC_BIT_STUFFING 2 #define OHCI_BIT_STUFFING 2
#define OHCI_CC_DATA_TOGGLE_MISMATCH 3 #define OHCI_DATA_TOGGLE_MISMATCH 3
#define OHCI_CC_STALL 4 #define OHCI_STALL 4
#define OHCI_CC_DEVICE_NOT_RESPONDING 5 #define OHCI_DEVICE_NOT_RESPONDING 5
#define OHCI_CC_PID_CHECK_FAILURE 6 #define OHCI_PID_CHECK_FAILURE 6
#define OHCI_CC_UNEXPECTED_PID 7 #define OHCI_UNEXPECTED_PID 7
#define OHCI_CC_DATA_OVERRUN 8 #define OHCI_DATA_OVERRUN 8
#define OHCI_CC_DATA_UNDERRUN 9 #define OHCI_DATA_UNDERRUN 9
#define OHCI_CC_BUFFER_OVERRUN 12 #define OHCI_BUFFER_OVERRUN 12
#define OHCI_CC_BUFFER_UNDERRUN 13 #define OHCI_BUFFER_UNDERRUN 13
#define OHCI_CC_NOT_ACCESSED 15 #define OHCI_NOT_ACCESSED 15
// -------------------------------- // --------------------------------
// Some delay needed when changing // Some delay needed when changing