* Adding skeleton EHCI driver. Some parts filled from the specs and the UHCI driver.
* Corrected some errors I found while reading UHCI. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18626 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -133,7 +133,7 @@ Stack::Stack()
|
||||
if (get_module(moduleName, (module_info **)&module) != B_OK)
|
||||
continue;
|
||||
|
||||
if (module->add_to(*this) != B_OK)
|
||||
if (module->add_to(this) < B_OK)
|
||||
continue;
|
||||
|
||||
TRACE(("usb stack: module %s successfully loaded\n", moduleName));
|
||||
|
||||
@@ -37,7 +37,7 @@ class Object;
|
||||
struct host_controller_info {
|
||||
module_info info;
|
||||
status_t (*control)(uint32 op, void *data, size_t length);
|
||||
bool (*add_to)(Stack &stack);
|
||||
status_t (*add_to)(Stack *stack);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -24,3 +24,9 @@ KernelAddon <usb>ohci : [ FDirName kernel busses usb ] :
|
||||
: ohci.rdef
|
||||
;
|
||||
|
||||
KernelAddon <usb>ehci : [ FDirName kernel busses usb ] :
|
||||
ehci.cpp
|
||||
ehci_rh.cpp
|
||||
: libusb.a
|
||||
: ehci.rdef
|
||||
;
|
||||
|
||||
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <module.h>
|
||||
#include <PCI.h>
|
||||
#include <USB3.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include "ehci.h"
|
||||
|
||||
pci_module_info *EHCI::sPCIModule = NULL;
|
||||
|
||||
|
||||
static int32
|
||||
ehci_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
TRACE(("usb_ehci_module: init module\n"));
|
||||
return B_OK;
|
||||
case B_MODULE_UNINIT:
|
||||
TRACE(("usb_ehci_module: uninit module\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
|
||||
host_controller_info ehci_module = {
|
||||
{
|
||||
"busses/usb/ehci",
|
||||
NULL,
|
||||
ehci_std_ops
|
||||
},
|
||||
NULL,
|
||||
EHCI::AddTo
|
||||
};
|
||||
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&ehci_module,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// #pragma mark -
|
||||
//
|
||||
|
||||
|
||||
EHCI::EHCI(pci_info *info, Stack *stack)
|
||||
: BusManager(stack),
|
||||
fPCIInfo(info),
|
||||
fStack(stack),
|
||||
fPeriodicFrameListArea(-1),
|
||||
fPeriodicFrameList(NULL),
|
||||
fAsyncFrameListArea(-1),
|
||||
fAsyncFrameList(NULL),
|
||||
fFirstTransfer(NULL),
|
||||
fLastTransfer(NULL),
|
||||
fFinishTransfers(false),
|
||||
fFinishThread(-1),
|
||||
fStopFinishThread(false),
|
||||
fRootHub(NULL),
|
||||
fRootHubAddress(0)
|
||||
{
|
||||
if (!fInitOK) {
|
||||
TRACE_ERROR(("usb_ehci: bus manager failed to init\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE(("usb_ehci: constructing new EHCI Host Controller Driver\n"));
|
||||
fInitOK = false;
|
||||
|
||||
fRegisterBase = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function, PCI_memory_base, 4);
|
||||
fRegisterBase &= PCI_address_io_mask;
|
||||
TRACE(("usb_ehci: register base: 0x%08x\n", fRegisterBase));
|
||||
|
||||
// enable pci address access
|
||||
uint16 command = PCI_command_io | PCI_command_master | PCI_command_memory;
|
||||
command |= sPCIModule->read_pci_config(fPCIInfo->bus, fPCIInfo->device,
|
||||
fPCIInfo->function, PCI_command, 2);
|
||||
|
||||
sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
|
||||
fPCIInfo->function, PCI_command, 2, command);
|
||||
|
||||
// make sure we take the controller away from BIOS
|
||||
sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, 2,
|
||||
PCI_LEGSUP, 2, PCI_LEGSUP_USBPIRQDEN);
|
||||
|
||||
// disable interrupts
|
||||
WriteReg16(EHCI_USBINTR, 0);
|
||||
|
||||
// reset the host controller
|
||||
// ToDo...
|
||||
|
||||
// allocate the periodic frame list
|
||||
void *physicalAddress;
|
||||
fPeriodicFrameListArea = fStack->AllocateArea((void **)&fPeriodicFrameList,
|
||||
&physicalAddress, B_PAGE_SIZE, "USB EHCI Periodic Framelist");
|
||||
if (fPeriodicFrameListArea < B_OK) {
|
||||
TRACE_ERROR(("usb_ehci: unable to allocate periodic framelist\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
WriteReg32(EHCI_PERIODICLISTBASE, (uint32)physicalAddress);
|
||||
|
||||
// allocate the async frame list
|
||||
fAsyncFrameListArea = fStack->AllocateArea((void **)&fAsyncFrameList,
|
||||
&physicalAddress, B_PAGE_SIZE, "USB EHCI Async Framelist");
|
||||
if (fAsyncFrameListArea < B_OK) {
|
||||
TRACE_ERROR(("usb_ehci: unable to allocate async framelist\n"));
|
||||
}
|
||||
|
||||
WriteReg32(EHCI_ASYNCLISTADDR, (uint32)physicalAddress);
|
||||
|
||||
// create finisher service thread
|
||||
fFinishThread = spawn_kernel_thread(FinishThread, "ehci finish thread",
|
||||
B_NORMAL_PRIORITY, (void *)this);
|
||||
resume_thread(fFinishThread);
|
||||
|
||||
// install the interrupt handler and enable interrupts
|
||||
install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
|
||||
InterruptHandler, (void *)this, 0);
|
||||
WriteReg16(EHCI_USBINTR, EHCI_USBINTR_HOSTSYSERR
|
||||
| EHCI_USBINTR_USBERRINT | EHCI_USBINTR_USBINT);
|
||||
|
||||
TRACE(("usb_ehci: EHCI Host Controller Driver constructed\n"));
|
||||
fInitOK = true;
|
||||
}
|
||||
|
||||
|
||||
EHCI::~EHCI()
|
||||
{
|
||||
TRACE(("usb_ehci: tear down EHCI Host Controller Driver\n"));
|
||||
|
||||
int32 result = 0;
|
||||
fStopFinishThread = true;
|
||||
wait_for_thread(fFinishThread, &result);
|
||||
|
||||
CancelAllPendingTransfers();
|
||||
|
||||
delete fRootHub;
|
||||
delete_area(fPeriodicFrameListArea);
|
||||
delete_area(fAsyncFrameListArea);
|
||||
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::Start()
|
||||
{
|
||||
TRACE(("usb_ehci: starting EHCI Host Controller\n"));
|
||||
TRACE(("usb_ehci: usbcmd: 0x%08x; usbsts: 0x%08x\n", ReadReg32(EHCI_USBCMD), ReadReg32(EHCI_USBSTS)));
|
||||
|
||||
WriteReg32(EHCI_USBCMD, ReadReg32(EHCI_USBCMD) | EHCI_USBCMD_RUNSTOP);
|
||||
|
||||
bool running = false;
|
||||
for (int32 i = 0; i < 10; i++) {
|
||||
uint32 status = ReadReg32(EHCI_USBSTS);
|
||||
TRACE(("usb_ehci: try %ld: status 0x%08x\n", i, status));
|
||||
|
||||
if (status & EHCI_USBSTS_HCHALTED) {
|
||||
snooze(10000);
|
||||
} else {
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!running) {
|
||||
TRACE(("usb_ehci: Host Controller didn't start\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fRootHubAddress = AllocateAddress();
|
||||
fRootHub = new(std::nothrow) EHCIRootHub(this, fRootHubAddress);
|
||||
if (!fRootHub) {
|
||||
TRACE_ERROR(("usb_ehci: no memory to allocate root hub\n"));
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (fRootHub->InitCheck() < B_OK) {
|
||||
TRACE_ERROR(("usb_ehci: root hub failed init check\n"));
|
||||
return fRootHub->InitCheck();
|
||||
}
|
||||
|
||||
SetRootHub(fRootHub);
|
||||
TRACE(("usb_ehci: Host Controller started\n"));
|
||||
return BusManager::Start();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::SubmitTransfer(Transfer *transfer)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::SubmitRequest(Transfer *transfer)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::AddTo(Stack *stack)
|
||||
{
|
||||
#ifdef TRACE_USB
|
||||
set_dprintf_enabled(true);
|
||||
load_driver_symbols("ehci");
|
||||
#endif
|
||||
|
||||
if (!sPCIModule) {
|
||||
status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
|
||||
if (status < B_OK) {
|
||||
TRACE_ERROR(("usb_ehci: getting pci module failed! 0x%08lx\n", status));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE(("usb_ehci: searching devices\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 (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
|
||||
// class_base: 0C (Serial Bus); class_sub: 03 (USB); class_api: 20 (EHCI)
|
||||
if (item->class_base == 0x0C && item->class_sub == 0x03
|
||||
&& item->class_api == 0x20) {
|
||||
if (item->u.h0.interrupt_line == 0
|
||||
|| item->u.h0.interrupt_line == 0xFF) {
|
||||
TRACE_ERROR(("usb_ehci: found device with invalid IRQ - check IRQ assignement\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
TRACE(("usb_ehci: found device at IRQ %u\n", item->u.h0.interrupt_line));
|
||||
EHCI *bus = new(std::nothrow) EHCI(item, stack);
|
||||
if (!bus) {
|
||||
delete item;
|
||||
sPCIModule = NULL;
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (bus->InitCheck() < B_OK) {
|
||||
TRACE_ERROR(("usb_ehci: bus failed init check\n"));
|
||||
delete bus;
|
||||
continue;
|
||||
}
|
||||
|
||||
// the bus took it away
|
||||
item = new(std::nothrow) pci_info;
|
||||
|
||||
bus->Start();
|
||||
stack->AddBusManager(bus);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
TRACE_ERROR(("usb_ehci: no devices found\n"));
|
||||
delete item;
|
||||
sPCIModule = NULL;
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
delete item;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::ResetPort(int32 index)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::ControllerReset()
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::LightReset()
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
EHCI::InterruptHandler(void *data)
|
||||
{
|
||||
cpu_status status = disable_interrupts();
|
||||
spinlock lock = 0;
|
||||
acquire_spinlock(&lock);
|
||||
|
||||
int32 result = ((EHCI *)data)->Interrupt();
|
||||
|
||||
release_spinlock(&lock);
|
||||
restore_interrupts(status);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
EHCI::Interrupt()
|
||||
{
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
|
||||
ehci_qtd *firstDescriptor, ehci_qtd *dataDescriptor,
|
||||
ehci_qtd *lastDescriptor, bool directionIn)
|
||||
{
|
||||
transfer_data *data = new(std::nothrow) transfer_data();
|
||||
if (!data)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
data->transfer = transfer;
|
||||
data->queue_head = queueHead;
|
||||
data->first_descriptor = firstDescriptor;
|
||||
data->data_descriptor = dataDescriptor;
|
||||
data->last_descriptor = lastDescriptor;
|
||||
data->incoming = directionIn;
|
||||
data->link = NULL;
|
||||
|
||||
if (!Lock()) {
|
||||
delete data;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (fLastTransfer)
|
||||
fLastTransfer->link = data;
|
||||
else
|
||||
fFirstTransfer = data;
|
||||
|
||||
fLastTransfer = data;
|
||||
Unlock();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::CancelPendingTransfer(Transfer *transfer)
|
||||
{
|
||||
if (!Lock())
|
||||
return B_ERROR;
|
||||
|
||||
transfer_data *last = NULL;
|
||||
transfer_data *current = fFirstTransfer;
|
||||
while (current) {
|
||||
if (current->transfer == transfer) {
|
||||
current->transfer->Finished(B_USB_STATUS_IRP_CANCELLED_BY_REQUEST, 0);
|
||||
delete current->transfer;
|
||||
|
||||
if (last)
|
||||
last->link = current->link;
|
||||
else
|
||||
fFirstTransfer = current->link;
|
||||
|
||||
if (fLastTransfer == current)
|
||||
fLastTransfer = last;
|
||||
|
||||
delete current;
|
||||
Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
last = current;
|
||||
current = current->link;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::CancelAllPendingTransfers()
|
||||
{
|
||||
if (!Lock())
|
||||
return B_ERROR;
|
||||
|
||||
transfer_data *transfer = fFirstTransfer;
|
||||
while (transfer) {
|
||||
transfer->transfer->Finished(B_USB_STATUS_IRP_CANCELLED_BY_REQUEST, 0);
|
||||
delete transfer->transfer;
|
||||
|
||||
transfer_data *next = transfer->link;
|
||||
delete transfer;
|
||||
transfer = next;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
EHCI::FinishThread(void *data)
|
||||
{
|
||||
((EHCI *)data)->FinishTransfers();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EHCI::FinishTransfers()
|
||||
{
|
||||
while (!fStopFinishThread) {
|
||||
while (!fFinishTransfers) {
|
||||
if (fStopFinishThread)
|
||||
return;
|
||||
snooze(1000);
|
||||
}
|
||||
|
||||
fFinishTransfers = false;
|
||||
if (!Lock())
|
||||
continue;
|
||||
|
||||
TRACE(("usb_ehci: finishing transfers\n"));
|
||||
transfer_data *lastTransfer = NULL;
|
||||
transfer_data *transfer = fFirstTransfer;
|
||||
Unlock();
|
||||
|
||||
while (transfer) {
|
||||
bool transferDone = false;
|
||||
|
||||
// ToDo...
|
||||
|
||||
if (transferDone) {
|
||||
if (Lock()) {
|
||||
if (lastTransfer)
|
||||
lastTransfer->link = transfer->link;
|
||||
|
||||
if (transfer == fFirstTransfer)
|
||||
fFirstTransfer = transfer->link;
|
||||
if (transfer == fLastTransfer)
|
||||
fLastTransfer = lastTransfer;
|
||||
|
||||
transfer_data *next = transfer->link;
|
||||
delete transfer->transfer;
|
||||
delete transfer;
|
||||
transfer = next;
|
||||
Unlock();
|
||||
}
|
||||
} else {
|
||||
lastTransfer = transfer;
|
||||
transfer = transfer->link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ehci_qtd *
|
||||
EHCI::CreateDescriptor(Pipe *pipe, size_t bufferSize)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **firstDescriptor,
|
||||
ehci_qtd **lastDescriptor, size_t bufferSize)
|
||||
{
|
||||
*firstDescriptor = NULL;
|
||||
*lastDescriptor = NULL;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EHCI::FreeDescriptor(ehci_qtd *descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
|
||||
size_t vectorCount)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
|
||||
size_t vectorCount, uint8 *lastDataToggle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
EHCI::ReadActualLength(ehci_qtd *topDescriptor, uint8 *lastDataToggle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
EHCI::WriteReg8(uint32 reg, uint8 value)
|
||||
{
|
||||
sPCIModule->write_io_8(fRegisterBase + reg, value);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
EHCI::WriteReg16(uint32 reg, uint16 value)
|
||||
{
|
||||
sPCIModule->write_io_16(fRegisterBase + reg, value);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
EHCI::WriteReg32(uint32 reg, uint32 value)
|
||||
{
|
||||
sPCIModule->write_io_32(fRegisterBase + reg, value);
|
||||
}
|
||||
|
||||
|
||||
inline uint8
|
||||
EHCI::ReadReg8(uint32 reg)
|
||||
{
|
||||
return sPCIModule->read_io_8(fRegisterBase + reg);
|
||||
}
|
||||
|
||||
|
||||
inline uint16
|
||||
EHCI::ReadReg16(uint32 reg)
|
||||
{
|
||||
return sPCIModule->read_io_16(fRegisterBase + reg);
|
||||
}
|
||||
|
||||
|
||||
inline uint32
|
||||
EHCI::ReadReg32(uint32 reg)
|
||||
{
|
||||
return sPCIModule->read_io_32(fRegisterBase + reg);
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef EHCI_H
|
||||
#define EHCI_H
|
||||
|
||||
#include "usb_p.h"
|
||||
#include "ehci_hardware.h"
|
||||
|
||||
|
||||
struct pci_info;
|
||||
struct pci_module_info;
|
||||
class EHCIRootHub;
|
||||
|
||||
|
||||
typedef struct transfer_data_s {
|
||||
Transfer *transfer;
|
||||
ehci_qh *queue_head;
|
||||
ehci_qtd *first_descriptor;
|
||||
ehci_qtd *data_descriptor;
|
||||
ehci_qtd *last_descriptor;
|
||||
bool incoming;
|
||||
transfer_data_s *link;
|
||||
} transfer_data;
|
||||
|
||||
|
||||
class EHCI : public BusManager {
|
||||
public:
|
||||
EHCI(pci_info *info, Stack *stack);
|
||||
~EHCI();
|
||||
|
||||
status_t Start();
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
virtual status_t SubmitRequest(Transfer *transfer);
|
||||
|
||||
static status_t AddTo(Stack *stack);
|
||||
|
||||
// Port operations for root hub
|
||||
status_t ResetPort(int32 index);
|
||||
|
||||
private:
|
||||
// Controller resets
|
||||
status_t ControllerReset();
|
||||
status_t LightReset();
|
||||
|
||||
// Interrupt functions
|
||||
static int32 InterruptHandler(void *data);
|
||||
int32 Interrupt();
|
||||
|
||||
// Transfer management
|
||||
status_t AddPendingTransfer(Transfer *transfer,
|
||||
ehci_qh *queueHead,
|
||||
ehci_qtd *firstDescriptor,
|
||||
ehci_qtd *dataDescriptor,
|
||||
ehci_qtd *lastDescriptor,
|
||||
bool directionIn);
|
||||
status_t CancelPendingTransfer(Transfer *transfer);
|
||||
status_t CancelAllPendingTransfers();
|
||||
|
||||
static int32 FinishThread(void *data);
|
||||
void FinishTransfers();
|
||||
|
||||
// Descriptor functions
|
||||
ehci_qtd *CreateDescriptor(Pipe *pipe,
|
||||
size_t bufferSizeToAllocate);
|
||||
status_t CreateDescriptorChain(Pipe *pipe,
|
||||
ehci_qtd **firstDescriptor,
|
||||
ehci_qtd **lastDescriptor,
|
||||
size_t bufferSizeToAllocate);
|
||||
|
||||
void FreeDescriptor(ehci_qtd *descriptor);
|
||||
void FreeDescriptorChain(ehci_qtd *topDescriptor);
|
||||
|
||||
void LinkDescriptors(ehci_qtd *first,
|
||||
ehci_qtd *last);
|
||||
|
||||
size_t WriteDescriptorChain(ehci_qtd *topDescriptor,
|
||||
iovec *vector, size_t vectorCount);
|
||||
size_t ReadDescriptorChain(ehci_qtd *topDescriptor,
|
||||
iovec *vector, size_t vectorCount,
|
||||
uint8 *lastDataToggle);
|
||||
size_t ReadActualLength(ehci_qtd *topDescriptor,
|
||||
uint8 *lastDataToggle);
|
||||
|
||||
// Register functions
|
||||
inline void WriteReg8(uint32 reg, uint8 value);
|
||||
inline void WriteReg16(uint32 reg, uint16 value);
|
||||
inline void WriteReg32(uint32 reg, uint32 value);
|
||||
inline uint8 ReadReg8(uint32 reg);
|
||||
inline uint16 ReadReg16(uint32 reg);
|
||||
inline uint32 ReadReg32(uint32 reg);
|
||||
|
||||
static pci_module_info *sPCIModule;
|
||||
|
||||
uint32 fRegisterBase;
|
||||
pci_info *fPCIInfo;
|
||||
Stack *fStack;
|
||||
|
||||
// Framelist memory
|
||||
area_id fPeriodicFrameListArea;
|
||||
addr_t *fPeriodicFrameList;
|
||||
area_id fAsyncFrameListArea;
|
||||
addr_t *fAsyncFrameList;
|
||||
|
||||
// Maintain a linked list of transfers
|
||||
transfer_data *fFirstTransfer;
|
||||
transfer_data *fLastTransfer;
|
||||
bool fFinishTransfers;
|
||||
thread_id fFinishThread;
|
||||
bool fStopFinishThread;
|
||||
|
||||
// Root Hub
|
||||
EHCIRootHub *fRootHub;
|
||||
uint8 fRootHubAddress;
|
||||
};
|
||||
|
||||
|
||||
class EHCIRootHub : public Hub {
|
||||
public:
|
||||
EHCIRootHub(EHCI *ehci, int8 deviceAddress);
|
||||
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
void UpdatePortStatus();
|
||||
|
||||
private:
|
||||
usb_port_status fPortStatus[2];
|
||||
EHCI *fEHCI;
|
||||
};
|
||||
|
||||
|
||||
#endif // !EHCI_H
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* ehci.rdef
|
||||
*/
|
||||
|
||||
resource app_signature "application/x-vnd.haiku-ehci";
|
||||
|
||||
resource app_version {
|
||||
major = 0,
|
||||
middle = 0,
|
||||
minor = 1,
|
||||
variety = 0,
|
||||
internal = 0,
|
||||
short_info = "EHCI host controller driver",
|
||||
long_info = "Haiku EHCI HCD - Copyright 2006, Haiku Inc."
|
||||
};
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef EHCI_HARDWARE_H
|
||||
#define EHCI_HARDWARE_H
|
||||
|
||||
// Host Controller Operational Registers (EHCI Spec 2.3)
|
||||
#define EHCI_USBCMD 0x00 // USB Command
|
||||
#define EHCI_USBSTS 0x04 // USB Status
|
||||
#define EHCI_USBINTR 0x08 // USB Interrupt Enable
|
||||
#define EHCI_FRINDEX 0x0c // USB Frame Index
|
||||
#define EHCI_CTRDSSEGMENT 0x10 // 4GB Segment Selector
|
||||
#define EHCI_PERIODICLISTBASE 0x14 // Frame List Base Address
|
||||
#define EHCI_ASYNCLISTADDR 0x18 // Next Asynchronous List Address
|
||||
#define EHCI_CONFIGFLAG 0x40 // Configured Flag Register
|
||||
#define EHCI_PORTSC 0x44 // Port Status/Control
|
||||
|
||||
|
||||
// USB Command Register (EHCI Spec 2.3.1)
|
||||
#define EHCI_USBCMD_ITC_SHIFT 16 // Interrupt Threshold Control
|
||||
#define EHCI_USBCMD_ITC_MASK 0xff
|
||||
#define EHCI_USBCMD_ASPME (1 << 11) // Async Schedule Park Mode Enable
|
||||
#define EHCI_USBCMD_ASPMC_SHIFT 8 // Async Schedule Park Mode Count
|
||||
#define EHCI_USBCMD_ASPMC_MASK 0x03
|
||||
#define EHCI_USBCMD_LHCRESET (1 << 7) // Light Host Controller Reset
|
||||
#define EHCI_USBCMD_INTONAAD (1 << 6) // Interrupt on Async Advance Dorbell
|
||||
#define EHCI_USBCMD_ASENABLE (1 << 5) // Asynchronous Schedule Enable
|
||||
#define EHCI_USBCMD_PSENABLE (1 << 4) // Periodic Schedule Enable
|
||||
#define EHCI_USBCMD_FLS_SHIFT 2 // Frame List Size
|
||||
#define EHCI_USBCMD_FLS_MASK 0x03
|
||||
#define EHCI_USBCMD_HCRESET (1 << 1) // Host Controller Reset
|
||||
#define EHCI_USBCMD_RUNSTOP (1 << 0) // Run/Stop
|
||||
|
||||
|
||||
// USB Status Register (EHCI Spec 2.3.2)
|
||||
#define EHCI_USBSTS_ASSTATUS (1 << 15) // Asynchronous Schedule Status
|
||||
#define EHCI_USBSTS_PSSTATUS (1 << 14) // Periodic Schedule Status
|
||||
#define EHCI_USBSTS_RECLAMATION (1 << 13) // Reclamation
|
||||
#define EHCI_USBSTS_HCHALTED (1 << 12) // Host Controller Halted
|
||||
#define EHCI_USBSTS_INTONAA (1 << 5) // Interrupt on Async Advance
|
||||
#define EHCI_USBSTS_HOSTSYSERR (1 << 4) // Host System Error
|
||||
#define EHCI_USBSTS_FLROLLOVER (1 << 3) // Frame List Rollover
|
||||
#define EHCI_USBSTS_PORTCHANGE (1 << 2) // Port Change Detected
|
||||
#define EHCI_USBSTS_USBERRINT (1 << 1) // USB Error Interrupt
|
||||
#define EHCI_USBSTS_USBINT (1 << 0) // USB Interrupt
|
||||
|
||||
|
||||
// USB Interrupt Enable Register (EHCI Spec 2.3.3)
|
||||
#define EHCI_USBINTR_INTONAA (1 << 5) // Interrupt on Async Advance Enable
|
||||
#define EHCI_USBINTR_HOSTSYSERR (1 << 4) // Host System Error Enable
|
||||
#define EHCI_USBINTR_FLROLLOVER (1 << 3) // Frame List Rollover Enable
|
||||
#define EHCI_USBINTR_PORTCHANGE (1 << 2) // Port Change Interrupt Enable
|
||||
#define EHCI_USBINTR_USBERRINT (1 << 1) // USB Error Interrupt Enable
|
||||
#define EHCI_USBINTR_USBINT (1 << 0) // USB Interrupt Enable
|
||||
|
||||
|
||||
// Configure Flag Register (EHCI Spec 2.3.8)
|
||||
#define EHCI_CONFIGFLAG_FLAG (1 << 0) // Configure Flag
|
||||
|
||||
|
||||
// Port Status and Control (EHCI Spec 2.3.9)
|
||||
#define EHCI_PORTSC_WAKEOVERCUR (1 << 22) // Wake on Over-Current Enable
|
||||
#define EHCI_PORTSC_WAKEDISCON (1 << 21) // Wake on Disconnect Enable
|
||||
#define EHCI_PORTSC_WAKECONNECT (1 << 20) // Wake on Connect Enable
|
||||
#define EHCI_PORTSC_PTC_SHIFT 16 // Port Test Control
|
||||
#define EHCI_PORTSC_PTC_MASK 0x07
|
||||
#define EHCI_PORTSC_PIC_SHIFT 14 // Port Indicator Control
|
||||
#define EHCI_PORTSC_PIC_MASK 0x03
|
||||
#define EHCI_PORTSC_PORTOWNER (1 << 13) // Port Owner
|
||||
#define EHCI_PORTSC_PORTPOWER (1 << 12) // Port Power
|
||||
#define EHCI_PORTSC_DPLUS (1 << 11) // Logical Level of D+
|
||||
#define EHCI_PORTSC_DMINUS (1 << 10) // Logical Level of D-
|
||||
#define EHCI_PORTSC_PORTRESET (1 << 8) // Port Reset
|
||||
#define EHCI_PORTSC_SUSPEND (1 << 7) // Suspend
|
||||
#define EHCI_PORTSC_FORCERESUME (1 << 6) // Force Port Resume
|
||||
#define EHCI_PORTSC_OCCHANGE (1 << 5) // Over-Current Change
|
||||
#define EHCI_PORTSC_OCACTIVE (1 << 4) // Over-Current Active
|
||||
#define EHCI_PORTSC_ENDISCHANGE (1 << 3) // Port Enable/Disable Change
|
||||
#define EHCI_PORTSC_ENDIS (1 << 2) // Port Enabled/Disabled
|
||||
#define EHCI_PORTSC_CONNCHANGE (1 << 1) // Connect Status Change
|
||||
#define EHCI_PORTSC_CONNSTATUS (1 << 0) // Current Connect Status
|
||||
|
||||
|
||||
// PCI Registers
|
||||
#define PCI_LEGSUP 0xc0 // PCI Legacy Support
|
||||
#define PCI_LEGSUP_USBPIRQDEN 0x2000 // USBP IRQ Deny
|
||||
|
||||
|
||||
// Data Structures (EHCI Spec 3)
|
||||
|
||||
// Periodic Frame List Element Flags (EHCI Spec 3.1)
|
||||
#define EHCI_PFRAMELIST_ITD 0x00 // Isochronous Transfer Descriptor
|
||||
#define EHCI_PFRAMELIST_QH 0x01 // Queue Head
|
||||
#define EHCI_PFRAMELIST_SITD 0x10 // Split Transaction Isochronous TD
|
||||
#define EHCI_PFRAMELIST_FSTN 0x11 // Frame Span Traversal Node
|
||||
|
||||
|
||||
// ToDo: Isochronous (High-Speed) Transfer Descriptors (iTD, EHCI Spec 3.2)
|
||||
// ToDo: Split Transaction Isochronous Transfer Descriptors (siTD, EHCI Spec 3.3)
|
||||
|
||||
// Queue Element Transfer Descriptors (qTD, EHCI Spec 3.5)
|
||||
typedef struct {
|
||||
// Hardware Part
|
||||
addr_t next_phy;
|
||||
addr_t alt_next_phy;
|
||||
uint32 status_token;
|
||||
addr_t buffer_phy[5];
|
||||
|
||||
// Software Part
|
||||
addr_t this_phy;
|
||||
void *next_log;
|
||||
void *alt_next_log;
|
||||
size_t buffer_size;
|
||||
void *buffer_log;
|
||||
} ehci_qtd;
|
||||
|
||||
|
||||
#define EHCI_QTD_TERMINATE (1 << 0)
|
||||
#define EHCI_QTD_BYTES_SHIFT 16
|
||||
#define EHCI_QTD_BYTES_MASK 0xffff
|
||||
#define EHCI_QTD_IOC (1 << 15)
|
||||
#define EHCI_QTD_PAGE_SHIFT 12
|
||||
#define EHCI_QTD_PAGE_MASK 0x07
|
||||
#define EHCI_QTD_ERRCOUNT_SHIFT 10
|
||||
#define EHCI_QTD_ERRCOUNT_MASK 0x03
|
||||
#define EHCI_QTD_PID_SHIFT 8
|
||||
#define EHCI_QTD_PID_MASK 0x03
|
||||
#define EHCI_QTD_STATUS_SHIFT 0
|
||||
#define EHCI_QTD_STATUS_MASK 0x7f
|
||||
#define EHCI_QTD_STATUS_ACTIVE (1 << 7) // Active
|
||||
#define EHCI_QTD_STATUS_HALTED (1 << 6) // Halted
|
||||
#define EHCI_QTD_STATUS_BUFFER (1 << 5) // Data Buffer Error
|
||||
#define EHCI_QTD_STATUS_BABBLE (1 << 4) // Babble Detected
|
||||
#define EHCI_QTD_STATUS_TERROR (1 << 3) // Transaction Error
|
||||
#define EHCI_QTD_STATUS_MISSED (1 << 2) // Missed Micro-Frame
|
||||
#define EHCI_QTD_STATUS_SPLIT (1 << 1) // Split Transaction State
|
||||
#define EHCI_QTD_STATUS_PING (1 << 0) // Ping State
|
||||
|
||||
|
||||
// Queue Head (QH, EHCI Spec 3.6)
|
||||
typedef struct {
|
||||
// Hardware Part
|
||||
addr_t link_phy;
|
||||
uint32 endpoint_chars;
|
||||
uint32 endpoint_caps;
|
||||
addr_t current_qtd_phy;
|
||||
uint32 overlay[8];
|
||||
// Software Part
|
||||
addr_t this_phy;
|
||||
void *link_log;
|
||||
void *element_log;
|
||||
} ehci_qh;
|
||||
|
||||
|
||||
// Applies to ehci_qh.link_phy
|
||||
#define EHCI_QH_TYPE_ITD (0 << 1)
|
||||
#define EHCI_QH_TYPE_QH (1 << 1)
|
||||
#define EHCI_QH_TYPE_SITD (2 << 1)
|
||||
#define EHCI_QH_TYPE_FSTN (3 << 1)
|
||||
#define EHCI_QH_TERMINATE (1 << 0)
|
||||
|
||||
// Applies to ehci_qh.endpoint_chars
|
||||
#define EHCI_QH_CHARS_RL_SHIFT 28 // NAK Count Reload
|
||||
#define EHCI_QH_CHARS_RL_MASK 0x07
|
||||
#define EHCI_QH_CHARS_CONTROL (1 << 27) // Control Endpoint Flag
|
||||
#define EHCI_QH_CHARS_MPL_SHIFT 16 // Max Packet Length
|
||||
#define EHCI_QH_CHARS_MPL_MASK 0x03ff
|
||||
#define EHCI_QH_CHARS_RECHEAD (1 << 15) // Head of Reclamation List Flag
|
||||
#define EHCI_QH_CHARS_TOGGLE (1 << 14) // Data Toggle Control
|
||||
#define EHCI_QH_CHARS_EPS_FULL (0 << 12) // Endpoint is Full-Speed
|
||||
#define EHCI_QH_CHARS_EPS_LOW (1 << 12) // Endpoint is Low-Speed
|
||||
#define EHCI_QH_CHARS_EPS_HIGH (2 << 12) // Endpoint is High-Speed
|
||||
#define EHCI_QH_CHARS_EPT_SHIFT 8 // Endpoint Number
|
||||
#define EHCI_QH_CHARS_EPT_MASK 0x0f
|
||||
#define EHCI_QH_CHARS_INACTIVE (1 << 7) // Inactive on Next Transaction
|
||||
#define EHCI_QH_CHARS_DEV_SHIFT 0 // Device Address
|
||||
#define EHCI_QH_CHARS_DEV_MASK 0x7f
|
||||
|
||||
|
||||
// Applies to ehci_qh.endpoint_caps
|
||||
#define EHCI_QH_CAPS_MULT_SHIFT 30 // Transactions per Micro-Frame
|
||||
#define EHCI_QH_CAPS_MULT_MASK 0x03
|
||||
#define EHCI_QH_CAPS_PORT_SHIFT 23 // Port Number
|
||||
#define EHCI_QH_CAPS_PORT_MASK 0x7f
|
||||
#define EHCI_QH_CAPS_HUB_SHIFT 16 // Hub Address
|
||||
#define EHCI_QH_CAPS_HUB_MASK 0x7f
|
||||
#define EHCI_QH_CAPS_SCM_SHIFT 8 // Split Completion Mask
|
||||
#define EHCI_QH_CAPS_SCM_MASK 0xff
|
||||
#define EHCI_QH_CAPS_ISM_SHIFT 0 // Interrupt Schedule Mask
|
||||
#define EHCI_QH_CAPS_ISM_MASK 0xff
|
||||
|
||||
|
||||
// Applies to ehci_qh.overlay[EHCI_QH_OL_*_INDEX]
|
||||
#define EHCI_QH_OL_NAK_INDEX 1 // NAK Counter
|
||||
#define EHCI_QH_OL_NAK_SHIFT 1
|
||||
#define EHCI_QH_OL_NAK_MASK 0x0f
|
||||
#define EHCI_QH_OL_TOGGLE_INDEX 2 // Data Toggle
|
||||
#define EHCI_QH_OL_TOGGLE (1 << 31)
|
||||
#define EHCI_QH_OL_IOC_INDEX 2 // Interrupt on Complete
|
||||
#define EHCI_QH_OL_IOC (1 << 15)
|
||||
#define EHCI_QH_OL_ERRC_INDEX 2 // Error Counter
|
||||
#define EHCI_QH_OL_ERRC_SHIFT 10
|
||||
#define EHCI_QH_OL_ERRC_MASK 0x03
|
||||
#define EHCI_QH_OL_PING_INDEX 2 // Ping State
|
||||
#define EHCI_QH_OL_PING (1 << 0)
|
||||
#define EHCI_QH_OL_CPROG_INDEX 4 // Split-Transaction Complete-Split Progress
|
||||
#define EHCI_QH_OL_CPROG_SHIFT 0
|
||||
#define EHCI_QH_OL_CPROG_MASK 0xff
|
||||
#define EHCI_QH_OL_FTAG_INDEX 5 // Split-Transaction Frame Tag
|
||||
#define EHCI_QH_OL_FTAG_SHIFT 0
|
||||
#define EHCI_QH_OL_FTAG_MASK 0x0f
|
||||
#define EHCI_QH_OL_BYTES_INDEX 5 // Transfered Bytes
|
||||
#define EHCI_QH_OL_BYTES_SHIFT 5
|
||||
#define EHCI_QH_OL_BYTES_MASK 0x7f
|
||||
|
||||
|
||||
// ToDo: Periodic Frame Span Traversal Node (FSTN, EHCI Spec 3.7)
|
||||
|
||||
|
||||
#endif // !EHCI_HARDWARE_H
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include "ehci.h"
|
||||
|
||||
|
||||
static usb_device_descriptor sEHCIRootHubDevice =
|
||||
{
|
||||
18, // Descriptor length
|
||||
USB_DESCRIPTOR_DEVICE, // Descriptor type
|
||||
0x200, // USB 2.0
|
||||
0x09, // Class (9 = Hub)
|
||||
0, // Subclass
|
||||
0, // Protocol
|
||||
64, // Max packet size on endpoint 0
|
||||
0, // Vendor ID
|
||||
0, // Product ID
|
||||
0x200, // Version
|
||||
1, // Index of manufacturer string
|
||||
2, // Index of product string
|
||||
0, // Index of serial number string
|
||||
1 // Number of configurations
|
||||
};
|
||||
|
||||
|
||||
struct ehci_root_hub_configuration_s {
|
||||
usb_configuration_descriptor configuration;
|
||||
usb_interface_descriptor interface;
|
||||
usb_endpoint_descriptor endpoint;
|
||||
usb_hub_descriptor hub;
|
||||
} _PACKED;
|
||||
|
||||
|
||||
static ehci_root_hub_configuration_s sEHCIRootHubConfig =
|
||||
{
|
||||
{ // configuration descriptor
|
||||
9, // Descriptor length
|
||||
USB_DESCRIPTOR_CONFIGURATION, // Descriptor type
|
||||
34, // Total length of configuration (including
|
||||
// interface, endpoint and hub descriptors)
|
||||
1, // Number of interfaces
|
||||
1, // Value of this configuration
|
||||
0, // Index of configuration string
|
||||
0x40, // Attributes (0x40 = self powered)
|
||||
0 // Max power (0, since self powered)
|
||||
},
|
||||
|
||||
{ // interface descriptor
|
||||
9, // Descriptor length
|
||||
USB_DESCRIPTOR_INTERFACE, // Descriptor type
|
||||
0, // Interface number
|
||||
0, // Alternate setting
|
||||
1, // Number of endpoints
|
||||
0x09, // Interface class (9 = Hub)
|
||||
0, // Interface subclass
|
||||
0, // Interface protocol
|
||||
0, // Index of interface string
|
||||
},
|
||||
|
||||
{ // endpoint descriptor
|
||||
7, // Descriptor length
|
||||
USB_DESCRIPTOR_ENDPOINT, // Descriptor type
|
||||
USB_REQTYPE_DEVICE_IN | 1, // Endpoint address (first in IN endpoint)
|
||||
0x03, // Attributes (0x03 = interrupt endpoint)
|
||||
8, // Max packet size
|
||||
0xFF // Interval
|
||||
},
|
||||
|
||||
{ // hub descriptor
|
||||
9, // Descriptor length (including
|
||||
// deprecated power control mask)
|
||||
USB_DESCRIPTOR_HUB, // Descriptor type
|
||||
2, // Number of ports
|
||||
0x0000, // Hub characteristics
|
||||
50, // Power on to power good (in 2ms units)
|
||||
0, // Maximum current (in mA)
|
||||
0x00, // Both ports are removable
|
||||
0xff // Depricated power control mask
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct ehci_root_hub_string_s {
|
||||
uint8 length;
|
||||
uint8 descriptor_type;
|
||||
uint16 unicode_string[12];
|
||||
} _PACKED;
|
||||
|
||||
|
||||
static ehci_root_hub_string_s sEHCIRootHubStrings[3] = {
|
||||
{
|
||||
4, // Descriptor length
|
||||
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||
0x0409 // Supported language IDs (English US)
|
||||
},
|
||||
|
||||
{
|
||||
12, // Descriptor length
|
||||
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||
'H', 'A', 'I', 'K', 'U', ' ', // Characters
|
||||
'I', 'n', 'c', '.'
|
||||
},
|
||||
|
||||
{
|
||||
26, // Descriptor length
|
||||
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||
'E', 'H', 'C', 'I', ' ', 'R', // Characters
|
||||
'o', 'o', 't', 'H', 'u', 'b'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
EHCIRootHub::EHCIRootHub(EHCI *ehci, int8 deviceAddress)
|
||||
: Hub(ehci, NULL, sEHCIRootHubDevice, deviceAddress, false)
|
||||
{
|
||||
fEHCI = ehci;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EHCIRootHub::UpdatePortStatus()
|
||||
{
|
||||
for (int32 i = 0; i < sEHCIRootHubConfig.hub.num_ports; i++) {
|
||||
fPortStatus[i].status = 0;
|
||||
fPortStatus[i].change = 0;
|
||||
}
|
||||
}
|
||||
@@ -87,8 +87,8 @@ ohci_std_ops( int32 op , ... )
|
||||
// - &stack: reference to a stack instance form stack.cpp
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
static bool
|
||||
ohci_add_to( Stack &stack )
|
||||
static status_t
|
||||
ohci_add_to( Stack *stack )
|
||||
{
|
||||
status_t status;
|
||||
pci_info *item;
|
||||
@@ -126,14 +126,14 @@ ohci_add_to( Stack &stack )
|
||||
continue;
|
||||
}
|
||||
TRACE("USB OHCI: init_hardware(): found at IRQ %u \n", item->u.h0.interrupt_line);
|
||||
OHCI *bus = new OHCI( item , &stack );
|
||||
OHCI *bus = new OHCI( item , stack );
|
||||
if ( bus->InitCheck() != B_OK )
|
||||
{
|
||||
delete bus;
|
||||
break;
|
||||
}
|
||||
|
||||
stack.AddBusManager( bus );
|
||||
stack->AddBusManager( bus );
|
||||
bus->Start();
|
||||
found = true;
|
||||
break;
|
||||
|
||||
@@ -792,8 +792,6 @@ UHCI::FinishTransfers()
|
||||
transfer = transfer->link;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -988,8 +986,8 @@ UHCI::Interrupt()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
UHCI::AddTo(Stack &stack)
|
||||
status_t
|
||||
UHCI::AddTo(Stack *stack)
|
||||
{
|
||||
#ifdef TRACE_USB
|
||||
set_dprintf_enabled(true);
|
||||
@@ -1026,7 +1024,7 @@ UHCI::AddTo(Stack &stack)
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci: AddTo(): found at IRQ %u\n", item->u.h0.interrupt_line));
|
||||
UHCI *bus = new(std::nothrow) UHCI(item, &stack);
|
||||
UHCI *bus = new(std::nothrow) UHCI(item, stack);
|
||||
if (!bus) {
|
||||
delete item;
|
||||
sPCIModule = NULL;
|
||||
@@ -1040,8 +1038,11 @@ UHCI::AddTo(Stack &stack)
|
||||
continue;
|
||||
}
|
||||
|
||||
// the bus took it away
|
||||
item = new(std::nothrow) pci_info;
|
||||
|
||||
bus->Start();
|
||||
stack.AddBusManager(bus);
|
||||
stack->AddBusManager(bus);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
@@ -1054,6 +1055,7 @@ UHCI::AddTo(Stack &stack)
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
delete item;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
virtual status_t SubmitRequest(Transfer *transfer);
|
||||
|
||||
static bool AddTo(Stack &stack);
|
||||
static status_t AddTo(Stack *stack);
|
||||
|
||||
// Port operations
|
||||
uint16 PortStatus(int32 index);
|
||||
@@ -161,22 +161,15 @@ static pci_module_info *sPCIModule;
|
||||
|
||||
class UHCIRootHub : public Hub {
|
||||
public:
|
||||
UHCIRootHub(UHCI *uhci, int8 deviceNum);
|
||||
UHCIRootHub(UHCI *uhci, int8 deviceAddress);
|
||||
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
void UpdatePortStatus();
|
||||
|
||||
private:
|
||||
|
||||
usb_port_status fPortStatus[2];
|
||||
UHCI *fUHCI;
|
||||
};
|
||||
|
||||
|
||||
struct hostcontroller_priv {
|
||||
uhci_qh *topqh;
|
||||
uhci_td *firsttd;
|
||||
uhci_td *lasttd;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
* Hardware structs *
|
||||
************************************************************/
|
||||
|
||||
//A framelist thingie
|
||||
// Framelist flags
|
||||
#define FRAMELIST_TERMINATE 0x1
|
||||
#define FRAMELIST_NEXT_IS_QH 0x2
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
// Represents a Transfer Descriptor (TD)
|
||||
typedef struct
|
||||
{
|
||||
//Hardware part
|
||||
// Hardware part
|
||||
addr_t link_phy; // Link to the next TD/QH
|
||||
uint32 status; // Status field
|
||||
uint32 token; // Contains the packet header (where it needs to be sent)
|
||||
|
||||
@@ -91,7 +91,7 @@ struct uhci_root_hub_string_s {
|
||||
uint8 length;
|
||||
uint8 descriptor_type;
|
||||
uint16 unicode_string[12];
|
||||
};
|
||||
} _PACKED;
|
||||
|
||||
|
||||
static uhci_root_hub_string_s sUHCIRootHubStrings[3] = {
|
||||
@@ -117,8 +117,8 @@ static uhci_root_hub_string_s sUHCIRootHubStrings[3] = {
|
||||
};
|
||||
|
||||
|
||||
UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
|
||||
: Hub(uhci, NULL, sUHCIRootHubDevice, devicenum, false)
|
||||
UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 deviceAddress)
|
||||
: Hub(uhci, NULL, sUHCIRootHubDevice, deviceAddress, false)
|
||||
{
|
||||
fUHCI = uhci;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user