* 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

View File

@ -1,67 +1,32 @@
//------------------------------------------------------------------------------
// Copyright (c) 2005, Jan-Rixt Van Hoye
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// 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.
//
// ------------------------------------------------------------------------
/*
* Copyright 2005-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Jan-Rixt Van Hoye
* Salvatore Benedetto <salvatore.benedetto@gmail.com>
*/
// ---------------------------
// OHCI:: Includes
// ---------------------------
#include <module.h>
#include <PCI.h>
#include <USB3.h>
#include <KernelExport.h>
#include <stdlib.h>
// ---------------------------
// OHCI:: Local includes
// ---------------------------
#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
// (Section 3.3.2)
//------------------------------------------------------
static uint8 revbits[OHCI_NO_INTRS] =
static uint8 revbits[OHCI_NUMBER_OF_INTERRUPTS] =
{ 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f };
//------------------------------------------------------------------------
// OHCI:: These are the OHCI operations that can be done.
//
// parameters:
// - op: operation
//------------------------------------------------------------------------
static int32
ohci_std_ops( int32 op , ... )
@ -69,14 +34,15 @@ ohci_std_ops( int32 op , ... )
switch (op)
{
case B_MODULE_INIT:
TRACE(("ohci_module: init the module\n"));
TRACE(("usb_ohci_module: init module\n"));
return B_OK;
case B_MODULE_UNINIT:
TRACE(("ohci_module: uninit the module\n"));
TRACE(("usb_ohci_module: uninit module\n"));
break;
default:
return EINVAL;
}
return B_OK;
}
@ -87,67 +53,82 @@ ohci_std_ops( int32 op , ... )
// - &stack: reference to a stack instance form stack.cpp
//------------------------------------------------------------------------
static status_t
ohci_add_to(Stack *stack)
status_t
OHCI::AddTo(Stack *stack)
{
status_t status;
pci_info *item;
bool found = false;
int i;
#ifdef TRACE_USB
set_dprintf_enabled(true);
load_driver_symbols("ohci");
#endif
//
// Try if the PCI module is loaded
//
if( ( status = get_module( B_PCI_MODULE_NAME, (module_info **)&( OHCI::pci_module ) ) ) != B_OK) {
TRACE(("USB_ OHCI: init_hardware(): Get PCI module failed! %lu \n", status));
return status;
if (!sPCIModule) {
status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
if (status < B_OK) {
TRACE_ERROR(("usb_ohci: AddTo(): getting pci module failed! 0x%08lx\n",
status));
return status;
}
}
TRACE(("usb_ohci init_hardware(): Setting up hardware\n"));
item = new pci_info;
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 )
&& ( item->class_api == PCI_usb_ohci ) )
{
if ((item->u.h0.interrupt_line == 0) || (item->u.h0.interrupt_line == 0xFF)) {
TRACE(("USB OHCI: init_hardware(): found with invalid IRQ - check IRQ assignement\n"));
TRACE(("usb_ohci: AddTo(): setting up hardware\n"));
bool found = false;
pci_info *item = new(std::nothrow) pci_info;
if (!item) {
sPCIModule = NULL;
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;
}
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);
if (!bus) {
delete item;
OHCI::pci_module = NULL;
sPCIModule = NULL;
put_module(B_PCI_MODULE_NAME);
return B_NO_MEMORY;
}
if (bus->InitCheck() != B_OK) {
TRACE(("usb_ohci: bus failed to initialize...\n"));
if (bus->InitCheck() < B_OK) {
TRACE_ERROR(("usb_ohci: AddTo(): InitCheck() failed 0x%08lx\n",
bus->InitCheck()));
delete bus;
continue;
}
bus->Start();
stack->AddBusManager( bus );
// the bus took it away
item = new(std::nothrow) pci_info;
bus->Start();
stack->AddBusManager(bus);
found = true;
}
}
if (!found) {
TRACE(("USB OHCI: init hardware(): no devices found\n"));
free( item );
put_module( B_PCI_MODULE_NAME );
TRACE_ERROR(("usb_ohci: no devices found\n"));
delete item;
put_module(B_PCI_MODULE_NAME);
return ENODEV;
}
return B_OK; //Hardware found
delete item;
return B_OK;
}
//------------------------------------------------------------------------
// OHCI:: Host controller information
//
@ -157,11 +138,11 @@ ohci_add_to(Stack *stack)
host_controller_info ohci_module = {
{
"busses/usb/ohci",
0, // No flag like B_KEEP_LOADED : the usb module does that
0,
ohci_std_ops
},
NULL ,
ohci_add_to
NULL,
OHCI::AddTo
};
//------------------------------------------------------------------------
@ -194,10 +175,10 @@ OHCI::OHCI(pci_info *info, Stack *stack)
fRootHubAddress(0),
fNumPorts(0)
{
fPcii = info;
fPCIInfo = info;
fStack = stack;
int i;
TRACE(("USB OHCI: constructing new BusManager\n"));
TRACE(("usb_ohci: constructing new BusManager\n"));
fInitOK = false;
@ -205,22 +186,22 @@ OHCI::OHCI(pci_info *info, Stack *stack)
fInterruptEndpoints[i] = 0;
// 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_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
//
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);
registeroffset &= PCI_address_memory_32_mask;
TRACE(("OHCI: iospace offset: %lx\n" , 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) {
TRACE(("USB OHCI: error mapping the registers\n"));
TRACE(("usb_ohci: error mapping the registers\n"));
return;
}
@ -230,7 +211,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
// 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" : ""));
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;
}
@ -239,7 +220,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
fHccaArea = fStack->AllocateArea((void**)&fHcca, &hcca_phy,
B_PAGE_SIZE, "OHCI HCCA");
if (fHccaArea < B_OK) {
TRACE(("USB OHCI: Error allocating HCCA block\n"));
TRACE(("usb_ohci: Error allocating HCCA block\n"));
return;
}
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
//
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);
for (int i = 0; i < 100 && (ReadReg(OHCI_CONTROL) & OHCI_IR); i++)
snooze(1000);
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)) {
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)) {
WriteReg(OHCI_CONTROL, OHCI_HCFS_RESUME);
snooze(USB_DELAY_BUS_RESET);
@ -287,9 +268,9 @@ OHCI::OHCI(pci_info *info, Stack *stack)
else
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]] =
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
uint32 frameinterval = ReadReg(OHCI_FM_INTERVAL);
@ -301,7 +282,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
break;
}
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;
}
@ -368,7 +349,7 @@ OHCI::Start()
return B_ERROR;
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;
}
@ -377,17 +358,17 @@ OHCI::Start()
fRootHub = new(std::nothrow) OHCIRootHub(this, fRootHubAddress);
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;
}
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;
}
SetRootHub(fRootHub);
TRACE(("USB OHCI::Start(): Succesful start\n"));
TRACE(("usb_ohci::Start(): Succesful start\n"));
return B_OK;
}
@ -525,7 +506,7 @@ OHCI::AllocateEndpoint()
//Add a NULL list by creating one TransferDescriptor
TransferDescriptor *trans = new(std::nothrow) TransferDescriptor;
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;
}
@ -544,12 +525,12 @@ OHCI::AllocateTransfer()
TRACE(("OHCI::%s()\n", __FUNCTION__));
TransferDescriptor *transfer = new TransferDescriptor;
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"));
return 0;
}
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;
}
@ -557,7 +538,7 @@ void
OHCI::FreeTransfer(TransferDescriptor *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;
}
@ -579,21 +560,21 @@ OHCI::InsertEndpointForPipe(Pipe *p)
uint32 properties = 0;
//Set the device address
properties |= OHCI_ENDPOINT_SET_FA(p->DeviceAddress());
properties |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(p->DeviceAddress());
//Set the endpoint number
properties |= OHCI_ENDPOINT_SET_EN(p->EndpointAddress());
properties |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(p->EndpointAddress());
//Set the direction
switch (p->Direction()) {
case Pipe::In:
properties |= OHCI_ENDPOINT_DIR_IN;
properties |= OHCI_ENDPOINT_DIRECTION_IN;
break;
case Pipe::Out:
properties |= OHCI_ENDPOINT_DIR_OUT;
properties |= OHCI_ENDPOINT_DIRECTION_OUT;
break;
case Pipe::Default:
properties |= OHCI_ENDPOINT_DIR_TD;
properties |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
break;
default:
//TODO: error
@ -616,10 +597,10 @@ OHCI::InsertEndpointForPipe(Pipe *p)
//Assign the format. Isochronous endpoints require this switch
if (p->Type() & USB_OBJECT_ISO_PIPE)
properties |= OHCI_ENDPOINT_FORMAT_ISO;
properties |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
//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;
}
@ -653,18 +634,25 @@ OHCI::InsertEndpointForPipe(Pipe *p)
return B_OK;
}
pci_module_info *OHCI::pci_module = 0;
pci_module_info *sPCIModule = 0;
void
OHCI::WriteReg(uint32 reg, uint32 value)
{
TRACE(("OHCI::%s(%lu, %lu)\n", __FUNCTION__, reg, value));
*(volatile uint32 *)(fRegisters + reg) = value;
*(volatile uint32 *)(fRegisterBase + reg) = value;
}
uint32
OHCI::ReadReg(uint32 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;
}

View File

@ -1,42 +1,52 @@
//------------------------------------------------------------------------------
// Copyright (c) 2005, Jan-Rixt Van Hoye
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// 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.
//-------------------------------------------------------------------------------
/*
* Copyright 2005-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Jan-Rixt Van Hoye
* Salvatore Benedetto <salvatore.benedetto@gmail.com>
*/
#ifndef OHCI_H
#define OHCI_H
// ---------------------------
// OHCI:: Includes
// ---------------------------
#include "usb_p.h"
#include "ohci_software.h"
#include "ohci_hardware.h"
#include <lock.h>
struct pci_info;
struct pci_module_info;
class OHCIRootHub;
struct Endpoint;
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
// from the BusManager
@ -46,31 +56,40 @@ class OHCI : public BusManager
{
friend class OHCIRootHub;
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 ClearPortFeature(uint8 index, uint16 feature);
status_t SetPortFeature(uint8 index, uint16 feature);
uint8 PortCount() { return fNumPorts; };
status_t Start();
virtual status_t SubmitTransfer(Transfer *transfer);
virtual status_t CancelQueuedTransfers(Pipe *pipe);
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:
inline void WriteReg(uint32 reg, uint32 value);
inline uint32 ReadReg(uint32 reg);
// Register functions
inline void WriteReg(uint32 reg, uint32 value);
inline uint32 ReadReg(uint32 reg);
// Global
pci_info *fPcii; // pci-info struct
Stack *fStack; // Pointer to the stack
uint8 *fRegisters; // Base address of the operational registers
area_id fRegisterArea; // Area id of the
static pci_module_info *sPCIModule;
uint32 *fRegisterBase;
pci_info *fPCIInfo;
Stack *fStack;
area_id fRegisterArea;
// HCCA
area_id fHccaArea;
struct ohci_hcca *fHcca; // The HCCA structure for the interupt communication
@ -79,10 +98,6 @@ private:
Endpoint *fDummyControl;
Endpoint *fDummyBulk;
Endpoint *fDummyIsochronous;
// Root Hub
OHCIRootHub *fRootHub; // the root hub
uint8 fRootHubAddress; // the usb address of the roothub
uint8 fNumPorts; // the number of ports
// functions
Endpoint *AllocateEndpoint(); // allocate memory for an endpoint
void FreeEndpoint(Endpoint *end); // Free endpoint
@ -90,6 +105,11 @@ private:
void FreeTransfer(TransferDescriptor *trans); // Free transfer
status_t InsertEndpointForPipe(Pipe *p);
// Root Hub
OHCIRootHub *fRootHub;
uint8 fRootHubAddress;
uint8 fNumPorts;
};
// --------------------------------
@ -132,7 +152,7 @@ struct Endpoint
struct TransferDescriptor
{
addr_t physicaladdress;
ohci_transfer_descriptor *td;
ohci_general_transfer_descriptor *td;
};
#endif // OHCI_H

View File

@ -1,24 +1,11 @@
//------------------------------------------------------------------------------
// Copyright (c) 2005, Jan-Rixt Van Hoye
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// 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.
//------------------------------------------------------------------------------
/*
* Copyright 2005-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Jan-Rixt Van Hoye
* Salvatore Benedetto <salvatore.benedetto@gmail.com>
*/
#ifndef OHCI_HARD_H
#define OHCI_HARD_H
@ -31,9 +18,9 @@
// Revision register (section 7.1.1)
// --------------------------------
#define OHCI_REVISION 0x00 // OHCI revision
#define OHCI_REV_LO(rev) ((rev)&0x0f)
#define OHCI_REV_HI(rev) (((rev)>>4)&0x03)
#define OHCI_REVISION 0x00
#define OHCI_REV_LO(rev) ((rev) & 0x0f)
#define OHCI_REV_HI(rev) (((rev) >> 4) & 0x03)
#define OHCI_REV_LEGACY(rev) ((rev) & 0x10)
// --------------------------------
@ -71,7 +58,7 @@
#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
@ -273,11 +260,11 @@ typedef uint32 ohci_physaddr_t;
// 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;
addr_t hcca_done_head;
uint8 hcca_reserved_for_hc[116];
@ -297,114 +284,113 @@ struct ohci_hcca
typedef struct ohci_endpoint_descriptor
{
uint32 flags;
addr_t tailp; // Queue tail pointer
addr_t headp; // Queue head pointer
addr_t next_endpoint; // Next endpoint in the list
uint32 tail_pointer; // Queue tail pointer
uint32 head_pointer; // Queue head pointer
uint32 next_endpoint; // Next endpoint in the list
};
#define OHCI_ENDPOINT_GET_FA(s) ((s) & 0x7f)
#define OHCI_ENDPOINT_ADDRMASK 0x0000007f
#define OHCI_ENDPOINT_SET_FA(s) (s)
#define OHCI_ENDPOINT_GET_EN(s) (((s) >> 7) & 0xf)
#define OHCI_ENDPOINT_SET_EN(s) ((s) << 7)
#define OHCI_ENDPOINT_DIR_MASK 0x00001800
#define OHCI_ENDPOINT_DIR_TD 0x00000000
#define OHCI_ENDPOINT_DIR_OUT 0x00000800
#define OHCI_ENDPOINT_DIR_IN 0x00001000
#define OHCI_ENDPOINT_SPEED 0x00002000
#define OHCI_ENDPOINT_SKIP 0x00004000
#define OHCI_ENDPOINT_FORMAT_GEN 0x00000000
#define OHCI_ENDPOINT_FORMAT_ISO 0x00008000
#define OHCI_ENDPOINT_GET_MAXP(s) (((s) >> 16) & 0x07ff)
#define OHCI_ENDPOINT_SET_MAXP(s) ((s) << 16)
#define OHCI_ENDPOINT_MAXPMASK (0x7ff << 16)
#define OHCI_HALTED 0x00000001
#define OHCI_TOGGLECARRY 0x00000002
#define OHCI_HEADMASK 0xfffffffc
#define OHCI_ENDPOINT_ADDRESS_MASK 0x0000007f
#define OHCI_ENDPOINT_GET_DEVICE_ADDRESS(s) ((s) & 0x7f)
#define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s) (s)
#define OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s) (((s) >> 7) & 0xf)
#define OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s) ((s) << 7)
#define OHCI_ENDPOINT_DIRECTION_MASK 0x00001800
#define OHCI_ENDPOINT_DIRECTION_DESCRIPTOR 0x00000000
#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
#define OHCI_ENDPOINT_SPEED 0x00002000
#define OHCI_ENDPOINT_SKIP 0x00004000
#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
#define OHCI_ENDPOINT_MAX_PACKET_SIZE_MASK (0x7ff << 16)
#define OHCI_ENDPOINT_GET_MAX_PACKET_SIZE(s) (((s) >> 16) & 0x07ff)
#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16)
#define OHCI_ENDPOINT_HALTED 0x00000001
#define OHCI_ENDPOINT_TOGGLE_CARRY 0x00000002
#define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc
// --------------------------------
// General transfer descriptor structure (section 4.3.1)
// --------------------------------
typedef struct ohci_transfer_descriptor
typedef struct ohci_general_transfer_descriptor
{
uint32 flags;
addr_t td_cbp; // Current Buffer Pointer
addr_t td_nexttd; // Next Transfer Descriptor
addr_t td_be; // Buffer End
} ;
uint32 buffer_phy; // Physical buffer pointer
uint32 next_descriptor; // Next transfer descriptor
uint32 last_byte_address; // Physical buffer end
};
#define OHCI_TD_R 0x00040000 // Buffer Rounding
#define OHCI_TD_DP_MASK 0x00180000 // Direction / PID
#define OHCI_TD_SETUP 0x00000000
#define OHCI_TD_OUT 0x00080000
#define OHCI_TD_IN 0x00100000
#define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) // Delay Interrupt
#define OHCI_TD_SET_DI(x) ((x) << 21)
#define OHCI_TD_NOINTR 0x00e00000
#define OHCI_TD_INTR_MASK 0x00e00000
#define OHCI_TD_TOGGLE_CARRY 0x00000000
#define OHCI_TD_TOGGLE_0 0x02000000
#define OHCI_TD_TOGGLE_1 0x03000000
#define OHCI_TD_TOGGLE_MASK 0x03000000
#define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) // Error Count
#define OHCI_TD_GET_CC(x) ((x) >> 28) // Condition Code
#define OHCI_TD_NOCC 0xf0000000
#define OHCI_BUFFER_ROUNDING 0x00040000 // Buffer Rounding
#define OHCI_TD_DIRECTION_PID_MASK 0x00180000 // Direction / PID
#define OHCI_TD_DIRECTION_PID_SETUP 0x00000000
#define OHCI_TD_DIRECTION_PID_OUT 0x00080000
#define OHCI_TD_DIRECTION_PID_IN 0x00100000
#define OHCI_TD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7) // Delay Interrupt
#define OHCI_TD_SET_DELAY_INTERRUPT(x) ((x) << 21)
#define OHCI_TD_NO_INTERRUPT 0x00e00000
#define OHCI_TD_INTERRUPT_MASK 0x00e00000
#define OHCI_TD_TOGGLE_CARRY 0x00000000
#define OHCI_TD_TOGGLE_0 0x02000000
#define OHCI_TD_TOGGLE_1 0x03000000
#define OHCI_TD_TOGGLE_MASK 0x03000000
#define OHCI_TD_GET_ERROR_COUNT(x) (((x) >> 26) & 3) // Error Count
#define OHCI_TD_GET_CONDITION_CODE(x) ((x) >> 28) // Condition Code
#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)
// --------------------------------
#define OHCI_ITD_NOFFSET 8
typedef struct hc_itransfer_descriptor
typedef struct ohci_isochronous_transfer_descriptor
{
uint32 itd_flags;
addr_t itd_bp0; // Buffer Page 0
addr_t itd_nextitd; // Next Isochronous Transfer Descriptor
addr_t itd_be; // Buffer End
uint16 itd_offset[OHCI_ITD_NOFFSET]; // Buffer offsets
uint32 flags;
uint32 buffer_page_byte_0; // Physical page number of byte 0
uint32 next_descriptor; // Next isochronous transfer descriptor
uint32 last_byte_address; // Physical buffer end
uint16 offset[OHCI_ITD_NOFFSET]; // Buffer offsets
};
#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff)
#define OHCI_ITD_SET_SF(x) ((x) & 0xffff)
#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) // Delay Interrupt
#define OHCI_ITD_SET_DI(x) ((x) << 21)
#define OHCI_ITD_NOINTR 0x00e00000
#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) // Frame Count
#define OHCI_ITD_SET_FC(x) (((x)-1) << 24)
#define OHCI_ITD_GET_CC(x) ((x) >> 28) // Condition Code
#define OHCI_ITD_NOCC 0xf0000000
#define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff)
#define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff)
#define OHCI_ITD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7)
#define OHCI_ITD_SET_DELAY_INTERRUPT(x) ((x) << 21)
#define OHCI_ITD_NO_INTERRUPT 0x00e00000
#define OHCI_ITD_GET_FRAME_COUNT(x) ((((x) >> 24) & 7) + 1)
#define OHCI_ITD_SET_FRAME_COUNT(x) (((x) - 1) << 24)
#define OHCI_ITD_GET_CONDITION_CODE(x) ((x) >> 28)
#define OHCI_ITD_NO_CONDITION_CODE 0xf0000000
#define itd_pswn itd_offset // Packet Status Word
#define OHCI_ITD_PAGE_SELECT 0x00001000
#define OHCI_ITD_MK_OFFS(len) (0xe000 | ((len) & 0x1fff))
#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) // Transfer length
#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) // Condition Code
// TO FIX
#define itd_pswn itd_offset // Packet Status Word
#define OHCI_ITD_PAGE_SELECT 0x00001000
#define OHCI_ITD_MK_OFFS(len) (0xe000 | ((len) & 0x1fff))
#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)
// --------------------------------
#define OHCI_CC_NO_ERROR 0
#define OHCI_CC_CRC 1
#define OHCI_CC_BIT_STUFFING 2
#define OHCI_CC_DATA_TOGGLE_MISMATCH 3
#define OHCI_CC_STALL 4
#define OHCI_CC_DEVICE_NOT_RESPONDING 5
#define OHCI_CC_PID_CHECK_FAILURE 6
#define OHCI_CC_UNEXPECTED_PID 7
#define OHCI_CC_DATA_OVERRUN 8
#define OHCI_CC_DATA_UNDERRUN 9
#define OHCI_CC_BUFFER_OVERRUN 12
#define OHCI_CC_BUFFER_UNDERRUN 13
#define OHCI_CC_NOT_ACCESSED 15
#define OHCI_NO_ERROR 0
#define OHCI_CRC 1
#define OHCI_BIT_STUFFING 2
#define OHCI_DATA_TOGGLE_MISMATCH 3
#define OHCI_STALL 4
#define OHCI_DEVICE_NOT_RESPONDING 5
#define OHCI_PID_CHECK_FAILURE 6
#define OHCI_UNEXPECTED_PID 7
#define OHCI_DATA_OVERRUN 8
#define OHCI_DATA_UNDERRUN 9
#define OHCI_BUFFER_OVERRUN 12
#define OHCI_BUFFER_UNDERRUN 13
#define OHCI_NOT_ACCESSED 15
// --------------------------------
// Some delay needed when changing