* Cleaned up / applied style to the BusManager class
* Fixed some copy&paste errors I introduced earlier * Removed the "one UHCI bus only" limit * Other fixes The hub now sees when a new device is connected but failes when getting its descriptor. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17611 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
76e69839f7
commit
26f34d1c06
@ -1,186 +1,200 @@
|
|||||||
//------------------------------------------------------------------------------
|
/*
|
||||||
// Copyright (c) 2003-2004, Niels S. Reedijk
|
* Copyright 2003-2006, 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
|
* Niels S. Reedijk
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
|
|
||||||
|
|
||||||
/* +++++++++
|
#define TRACE_BUSMANAGER
|
||||||
This is the 'main' function of the explore thread, which keeps track of
|
#ifdef TRACE_BUSMANAGER
|
||||||
the hub statuses.
|
#define TRACE(x) dprintf(x)
|
||||||
+++++++++ */
|
#else
|
||||||
int32 usb_explore_thread( void *data )
|
#define TRACE(x) /* nothing */
|
||||||
{
|
#endif
|
||||||
Hub *roothub = (Hub *)data;
|
|
||||||
|
|
||||||
if ( roothub == 0 )
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
//Go to the hubs
|
|
||||||
roothub->Explore();
|
|
||||||
snooze(1000000); //Wait one second before continueing
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BusManager::BusManager()
|
BusManager::BusManager()
|
||||||
{
|
{
|
||||||
m_initok = false;
|
fInitOK = false;
|
||||||
m_roothub = 0;
|
fRootHub = NULL;
|
||||||
|
|
||||||
// Set up the semaphore
|
|
||||||
m_lock = create_sem( 1 , "buslock" );
|
|
||||||
if( m_lock < B_OK )
|
|
||||||
return;
|
|
||||||
set_sem_owner( B_SYSTEM_TEAM , m_lock );
|
|
||||||
|
|
||||||
// Clear the device map
|
|
||||||
memset( &m_devicemap , 0 , 128 );
|
|
||||||
|
|
||||||
// Set up the default pipes
|
|
||||||
m_defaultPipe = new ControlPipe( this , 0 , Pipe::Default , Pipe::NormalSpeed , 0 );
|
|
||||||
m_defaultLowSpeedPipe = new ControlPipe( this , 0 , Pipe::Default , Pipe::LowSpeed , 0 );
|
|
||||||
|
|
||||||
// Clear the 'explore thread'
|
|
||||||
m_explore_thread = 0;
|
|
||||||
|
|
||||||
m_initok = true;
|
// Set up the semaphore
|
||||||
|
fLock = create_sem(1, "bus manager lock");
|
||||||
|
if (fLock < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
set_sem_owner(B_SYSTEM_TEAM, fLock);
|
||||||
|
|
||||||
|
// Clear the device map
|
||||||
|
for (int32 i = 0; i < 128; i++)
|
||||||
|
fDeviceMap[i] = false;
|
||||||
|
|
||||||
|
// Set up the default pipes
|
||||||
|
fDefaultPipe = new ControlPipe(this, 0, Pipe::Default, Pipe::NormalSpeed, 0);
|
||||||
|
fDefaultPipeLowSpeed = new ControlPipe(this, 0, Pipe::Default,
|
||||||
|
Pipe::LowSpeed, 0);
|
||||||
|
|
||||||
|
fExploreThread = -1;
|
||||||
|
fInitOK = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BusManager::~BusManager()
|
BusManager::~BusManager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BusManager::InitCheck()
|
|
||||||
|
status_t
|
||||||
|
BusManager::InitCheck()
|
||||||
{
|
{
|
||||||
if ( m_initok == true )
|
if (fInitOK)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
else
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Device * BusManager::AllocateNewDevice( Device *parent , bool lowspeed )
|
|
||||||
|
/*
|
||||||
|
This is the 'main' function of the explore thread, which keeps track of
|
||||||
|
the hub states.
|
||||||
|
*/
|
||||||
|
int32
|
||||||
|
BusManager::ExploreThread(void *data)
|
||||||
{
|
{
|
||||||
int8 devicenum;
|
Hub *rootHub = (Hub *)data;
|
||||||
status_t retval;
|
if (!rootHub)
|
||||||
usb_device_descriptor device_descriptor;
|
return B_ERROR;
|
||||||
|
|
||||||
//1. Check if there is a free entry in the device map (for the device number)
|
while (true) {
|
||||||
devicenum = AllocateAddress();
|
rootHub->Explore();
|
||||||
if ( devicenum < 0 )
|
snooze(1000000);
|
||||||
{
|
|
||||||
dprintf( "usb Busmanager [new device]: could not get a new address\n" );
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
//2. Set the address of the device USB 1.1 spec p202 (bepdf)
|
}
|
||||||
retval = m_defaultPipe->SendRequest( USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //host->device
|
|
||||||
USB_REQUEST_SET_ADDRESS , //request
|
|
||||||
devicenum , //value
|
Device *
|
||||||
0 , //index
|
BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
|
||||||
0 , //length
|
{
|
||||||
NULL , //data
|
// Check if there is a free entry in the device map (for the device number)
|
||||||
0 , //data_len
|
int8 deviceNum = AllocateAddress();
|
||||||
0 ); //actual len
|
if (deviceNum < 0) {
|
||||||
|
TRACE(("usb BusManager::AllocateNewDevice(): could not get a new address\n"));
|
||||||
if ( retval < B_OK )
|
return NULL;
|
||||||
{
|
|
||||||
dprintf( "usb busmanager [new device]: error with commmunicating the right address\n" );
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create a temporary pipe
|
// Set the address of the device USB 1.1 spec p202
|
||||||
ControlPipe pipe( this , devicenum , Pipe::Default , Pipe::LowSpeed , 0 );
|
status_t result = fDefaultPipeLowSpeed->SendRequest(
|
||||||
|
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
||||||
//3. Get the device descriptor
|
USB_REQUEST_SET_ADDRESS, // request
|
||||||
|
deviceNum, // value
|
||||||
|
0, // index
|
||||||
|
0, // length
|
||||||
|
NULL, // buffer
|
||||||
|
0, // buffer length
|
||||||
|
NULL); // actual length
|
||||||
|
|
||||||
|
if (result < B_OK) {
|
||||||
|
TRACE(("usb BusManager::AllocateNewDevice(): error while setting device address\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary pipe
|
||||||
|
ControlPipe pipe(this, deviceNum, Pipe::Default, Pipe::LowSpeed, 0);
|
||||||
|
|
||||||
|
// Get the device descriptor
|
||||||
// Just retrieve the first 8 bytes of the descriptor -> minimum supported
|
// Just retrieve the first 8 bytes of the descriptor -> minimum supported
|
||||||
// size of any device, plus it is enough, because the device type is in
|
// size of any device, plus it is enough, because the device type is in
|
||||||
// there too
|
// there too
|
||||||
|
|
||||||
size_t actual_length;
|
size_t actualLength = 0;
|
||||||
|
usb_device_descriptor deviceDescriptor;
|
||||||
pipe.SendRequest( USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type
|
|
||||||
USB_REQUEST_GET_DESCRIPTOR , //Request
|
pipe.SendRequest(
|
||||||
( USB_DESCRIPTOR_DEVICE << 8 ), //Value
|
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
|
||||||
0 , //Index
|
USB_REQUEST_GET_DESCRIPTOR, // request
|
||||||
8 , //Length
|
USB_DESCRIPTOR_DEVICE << 8, // value
|
||||||
(void *)&device_descriptor , //Buffer
|
0, // index
|
||||||
8 , //Bufferlength
|
8, // length
|
||||||
&actual_length ); //length
|
(void *)&deviceDescriptor, // buffer
|
||||||
|
8, // buffer length
|
||||||
if ( actual_length != 8 )
|
&actualLength); // actual length
|
||||||
{
|
|
||||||
dprintf( "usb busmanager [new device]: error while getting the device descriptor\n" );
|
if (actualLength != 8) {
|
||||||
return 0;
|
TRACE(("usb BusManager::AllocateNewDevice(): error while getting the device descriptor\n"));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//4. Create a new instant based on the type (Hub or Device);
|
// Create a new instance based on the type (Hub or Device)
|
||||||
if ( device_descriptor.device_class == 0x09 )
|
if (deviceDescriptor.device_class == 0x09) {
|
||||||
{
|
TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n"));
|
||||||
dprintf( "usb Busmanager [new device]: New hub\n" );
|
Device *ret = new Hub(this, parent, deviceDescriptor, deviceNum,
|
||||||
Device *ret = new Hub( this , parent , device_descriptor , devicenum , lowspeed );
|
lowSpeed);
|
||||||
if ( parent == 0 ) //root hub!!
|
|
||||||
m_roothub = ret;
|
if (parent == NULL) {
|
||||||
return 0;
|
// root hub
|
||||||
|
fRootHub = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf( "usb Busmanager [new device]: New normal device\n" );
|
TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n"));
|
||||||
return new Device( this , parent , device_descriptor , devicenum , lowspeed);
|
return new Device(this, parent, deviceDescriptor, deviceNum, lowSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
int8 BusManager::AllocateAddress()
|
|
||||||
|
int8
|
||||||
|
BusManager::AllocateAddress()
|
||||||
{
|
{
|
||||||
acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 );
|
acquire_sem_etc(fLock, 1, B_CAN_INTERRUPT, 0);
|
||||||
int8 devicenum = -1;
|
|
||||||
for( int i = 1 ; i < 128 ; i++ )
|
int8 deviceNum = -1;
|
||||||
{
|
for (int32 i = 1; i < 128; i++) {
|
||||||
if ( m_devicemap[i] == false )
|
if (fDeviceMap[i] == false) {
|
||||||
{
|
deviceNum = i;
|
||||||
devicenum = i;
|
fDeviceMap[i] = true;
|
||||||
m_devicemap[i] = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
release_sem( m_lock );
|
|
||||||
return devicenum;
|
release_sem(fLock);
|
||||||
|
return deviceNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BusManager::Start()
|
|
||||||
|
status_t
|
||||||
|
BusManager::Start()
|
||||||
{
|
{
|
||||||
dprintf( "USB: BusManager::Start()\n" );
|
TRACE(("usb BusManager::Start()\n"));
|
||||||
if ( InitCheck() != B_OK )
|
if (InitCheck() != B_OK)
|
||||||
return InitCheck();
|
return InitCheck();
|
||||||
|
|
||||||
if ( m_explore_thread == 0 )
|
if (fExploreThread < 0) {
|
||||||
m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" ,
|
fExploreThread = spawn_kernel_thread(ExploreThread,
|
||||||
B_LOW_PRIORITY , (void *)m_roothub );
|
"usb busmanager explore", B_LOW_PRIORITY, (void *)fRootHub);
|
||||||
|
}
|
||||||
// Start the 'explore thread'
|
|
||||||
return resume_thread( m_explore_thread );
|
return resume_thread(fExploreThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BusManager::SubmitTransfer( Transfer *t )
|
|
||||||
|
status_t
|
||||||
|
BusManager::Stop()
|
||||||
{
|
{
|
||||||
|
// ToDo: implement (should end the explore thread)
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BusManager::SubmitTransfer(Transfer *transfer)
|
||||||
|
{
|
||||||
|
// virtual function to be overridden
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
};
|
}
|
||||||
|
@ -128,37 +128,42 @@ private:
|
|||||||
* after a host controller gives positive feedback on whether the hardware
|
* after a host controller gives positive feedback on whether the hardware
|
||||||
* is found.
|
* is found.
|
||||||
*/
|
*/
|
||||||
class BusManager
|
class BusManager {
|
||||||
{
|
|
||||||
friend class Device;
|
|
||||||
friend class ControlPipe;
|
|
||||||
public:
|
public:
|
||||||
BusManager();
|
BusManager();
|
||||||
virtual ~BusManager();
|
virtual ~BusManager();
|
||||||
|
|
||||||
virtual status_t InitCheck();
|
|
||||||
|
|
||||||
Device *AllocateNewDevice( Device *parent , bool speed );
|
|
||||||
int8 AllocateAddress();
|
|
||||||
|
|
||||||
virtual status_t Start();
|
|
||||||
// virtual status_t Stop();
|
|
||||||
virtual status_t SubmitTransfer( Transfer *t );
|
|
||||||
protected:
|
|
||||||
void SetRootHub( Hub *hub ) { m_roothub = hub; };
|
|
||||||
Device* GetRootHub() { return m_roothub; };
|
|
||||||
bool m_initok;
|
|
||||||
private:
|
|
||||||
bool m_devicemap[128];
|
|
||||||
ControlPipe *m_defaultLowSpeedPipe;
|
|
||||||
ControlPipe *m_defaultPipe;
|
|
||||||
sem_id m_lock;
|
|
||||||
Device *m_roothub;
|
|
||||||
thread_id m_explore_thread;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Located in the BusManager.cpp
|
virtual status_t InitCheck();
|
||||||
int32 usb_explore_thread( void *data );
|
|
||||||
|
Device *AllocateNewDevice(Device *parent,
|
||||||
|
bool lowSpeed);
|
||||||
|
|
||||||
|
int8 AllocateAddress();
|
||||||
|
|
||||||
|
virtual status_t Start();
|
||||||
|
virtual status_t Stop();
|
||||||
|
|
||||||
|
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetRootHub(Hub *hub) { fRootHub = hub; };
|
||||||
|
Device *GetRootHub() { return fRootHub; };
|
||||||
|
|
||||||
|
bool fInitOK;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class Device;
|
||||||
|
friend class ControlPipe;
|
||||||
|
|
||||||
|
static int32 ExploreThread(void *data);
|
||||||
|
|
||||||
|
sem_id fLock;
|
||||||
|
bool fDeviceMap[128];
|
||||||
|
ControlPipe *fDefaultPipe;
|
||||||
|
ControlPipe *fDefaultPipeLowSpeed;
|
||||||
|
Device *fRootHub;
|
||||||
|
thread_id fExploreThread;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Pipe class is the communication management between the hardware and\
|
* The Pipe class is the communication management between the hardware and\
|
||||||
|
@ -99,7 +99,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
|||||||
GlobalReset();
|
GlobalReset();
|
||||||
if (Reset() < B_OK) {
|
if (Reset() < B_OK) {
|
||||||
TRACE(("usb_uhci: host failed to reset\n"));
|
TRACE(("usb_uhci: host failed to reset\n"));
|
||||||
m_initok = false;
|
fInitOK = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
|||||||
|
|
||||||
if (fFrameArea < B_OK) {
|
if (fFrameArea < B_OK) {
|
||||||
TRACE(("usb_uhci: unable to create an area for the frame pointer list\n"));
|
TRACE(("usb_uhci: unable to create an area for the frame pointer list\n"));
|
||||||
m_initok = false;
|
fInitOK = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
|||||||
if (fStack->AllocateChunk((void **)&strayDescriptor, &physicalAddress, 32) != B_OK) {
|
if (fStack->AllocateChunk((void **)&strayDescriptor, &physicalAddress, 32) != B_OK) {
|
||||||
TRACE(("usb_uhci: failed to allocate a stray transfer descriptor\n"));
|
TRACE(("usb_uhci: failed to allocate a stray transfer descriptor\n"));
|
||||||
delete_area(fFrameArea);
|
delete_area(fFrameArea);
|
||||||
m_initok = false;
|
fInitOK = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
|||||||
&physicalAddress, 32) != B_OK) {
|
&physicalAddress, 32) != B_OK) {
|
||||||
TRACE(("usb_uhci: failed allocation of skeleton queue head %i, aborting\n", i));
|
TRACE(("usb_uhci: failed allocation of skeleton queue head %i, aborting\n", i));
|
||||||
delete_area(fFrameArea);
|
delete_area(fFrameArea);
|
||||||
m_initok = false;
|
fInitOK = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,22 +246,13 @@ UHCI::Start()
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("usb_uhci: controller is started. status: %u curframe: %u\n",
|
|
||||||
ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)));
|
|
||||||
return BusManager::Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
UHCI::SetupRootHub()
|
|
||||||
{
|
|
||||||
TRACE(("usb_uhci: setting up root hub\n"));
|
|
||||||
|
|
||||||
fRootHubAddress = AllocateAddress();
|
fRootHubAddress = AllocateAddress();
|
||||||
fRootHub = new UHCIRootHub(this, fRootHubAddress);
|
fRootHub = new UHCIRootHub(this, fRootHubAddress);
|
||||||
SetRootHub(fRootHub);
|
SetRootHub(fRootHub);
|
||||||
|
|
||||||
return B_OK;
|
TRACE(("usb_uhci: controller is started. status: %u curframe: %u\n",
|
||||||
|
ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)));
|
||||||
|
return BusManager::Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -377,10 +368,6 @@ UHCI::InsertControl(Transfer *transfer)
|
|||||||
TRACE(("usb_uhci: InsertControl() frnum %u, usbsts reg %u\n",
|
TRACE(("usb_uhci: InsertControl() frnum %u, usbsts reg %u\n",
|
||||||
ReadReg16(UHCI_FRNUM), ReadReg16(UHCI_USBSTS)));
|
ReadReg16(UHCI_FRNUM), ReadReg16(UHCI_USBSTS)));
|
||||||
|
|
||||||
// HACK: this one is to prevent rogue transfers from happening
|
|
||||||
if (!transfer->GetBuffer())
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
// Please note that any data structures must be aligned on a 16 byte boundary
|
// Please note that any data structures must be aligned on a 16 byte boundary
|
||||||
// Also, due to the strange ways of C++' void* handling, this code is much messier
|
// Also, due to the strange ways of C++' void* handling, this code is much messier
|
||||||
// than it actually should be. Forgive me. Or blame the compiler.
|
// than it actually should be. Forgive me. Or blame the compiler.
|
||||||
@ -423,7 +410,8 @@ UHCI::InsertControl(Transfer *transfer)
|
|||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(transferDescriptor->buffer_log, transfer->GetRequestData(), sizeof(usb_request_data));
|
memcpy(transferDescriptor->buffer_log, transfer->GetRequestData(),
|
||||||
|
sizeof(usb_request_data));
|
||||||
|
|
||||||
// Link this to the queue head
|
// Link this to the queue head
|
||||||
topQueueHead->element_phy = transferDescriptor->this_phy;
|
topQueueHead->element_phy = transferDescriptor->this_phy;
|
||||||
@ -470,11 +458,11 @@ UHCI::InsertControl(Transfer *transfer)
|
|||||||
transfer->GetHostPrivate()->lasttd = statusDescriptor;
|
transfer->GetHostPrivate()->lasttd = statusDescriptor;
|
||||||
fTransfers.PushBack(transfer);
|
fTransfers.PushBack(transfer);
|
||||||
|
|
||||||
// Secondly, append the qh to the control list
|
// Secondly, append the queue head to the control list
|
||||||
if (fQueueHeadControl->element_phy & QH_TERMINATE) {
|
if (fQueueHeadControl->element_phy & QH_TERMINATE) {
|
||||||
// the control queue is empty, make this the first element
|
// the control queue is empty, make this the first element
|
||||||
fQueueHeadControl->element_phy = topQueueHead->this_phy;
|
fQueueHeadControl->element_phy = topQueueHead->this_phy;
|
||||||
fQueueHeadControl->link_log = (void *)topQueueHead;
|
fQueueHeadControl->link_log = topQueueHead;
|
||||||
TRACE(("usb_uhci: first transfer in queue\n"));
|
TRACE(("usb_uhci: first transfer in queue\n"));
|
||||||
} else {
|
} else {
|
||||||
// there are control transfers linked, append to the queue
|
// there are control transfers linked, append to the queue
|
||||||
@ -483,7 +471,7 @@ UHCI::InsertControl(Transfer *transfer)
|
|||||||
queueHead = (uhci_qh *)queueHead->link_log;
|
queueHead = (uhci_qh *)queueHead->link_log;
|
||||||
|
|
||||||
queueHead->link_phy = topQueueHead->this_phy;
|
queueHead->link_phy = topQueueHead->this_phy;
|
||||||
queueHead->link_log = (void *)topQueueHead;
|
queueHead->link_log = topQueueHead;
|
||||||
TRACE(("usb_uhci: appended transfer to queue\n"));
|
TRACE(("usb_uhci: appended transfer to queue\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,7 +498,6 @@ UHCI::AddTo(Stack &stack)
|
|||||||
|
|
||||||
TRACE(("usb_uhci: AddTo(): setting up hardware\n"));
|
TRACE(("usb_uhci: AddTo(): setting up hardware\n"));
|
||||||
|
|
||||||
// TODO: in the future we might want to support multiple host controllers.
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
pci_info *item = new pci_info;
|
pci_info *item = new pci_info;
|
||||||
for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
|
for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
|
||||||
@ -532,10 +519,8 @@ UHCI::AddTo(Stack &stack)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bus->Start();
|
bus->Start();
|
||||||
bus->SetupRootHub();
|
|
||||||
stack.AddBusManager(bus);
|
stack.AddBusManager(bus);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ public:
|
|||||||
UHCI(pci_info *info, Stack *stack);
|
UHCI(pci_info *info, Stack *stack);
|
||||||
|
|
||||||
status_t Start();
|
status_t Start();
|
||||||
status_t SetupRootHub();
|
|
||||||
status_t SubmitTransfer(Transfer *transfer);
|
status_t SubmitTransfer(Transfer *transfer);
|
||||||
|
|
||||||
static bool AddTo(Stack &stack);
|
static bool AddTo(Stack &stack);
|
||||||
|
@ -77,7 +77,7 @@ usb_hub_descriptor uhci_hubd =
|
|||||||
{
|
{
|
||||||
0x09, //Including deprecated powerctrlmask
|
0x09, //Including deprecated powerctrlmask
|
||||||
USB_DESCRIPTOR_HUB,
|
USB_DESCRIPTOR_HUB,
|
||||||
1, //Number of ports
|
2, //Number of ports
|
||||||
0x02 | 0x01, //Hub characteristics FIXME
|
0x02 | 0x01, //Hub characteristics FIXME
|
||||||
50, //Power on to power good
|
50, //Power on to power good
|
||||||
0, // Current
|
0, // Current
|
||||||
@ -228,25 +228,25 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
void
|
void
|
||||||
UHCIRootHub::UpdatePortStatus()
|
UHCIRootHub::UpdatePortStatus()
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < 2; i++) {
|
for (int32 i = 0; i < uhci_hubd.bNbrPorts; i++) {
|
||||||
uint16 newStatus = 0;
|
uint16 newStatus = 0;
|
||||||
uint16 newChange = 0;
|
uint16 newChange = 0;
|
||||||
|
|
||||||
uint16 portStatus = UHCI::sPCIModule->read_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + i * 2);
|
uint16 portStatus = UHCI::sPCIModule->read_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + i * 2);
|
||||||
TRACE(("usb_uhci_roothub: port: %d status: 0x%04x\n", UHCI_PORTSC1 + i * 2, portStatus));
|
TRACE(("usb_uhci_roothub: port: %d status: 0x%04x\n", i, portStatus));
|
||||||
|
|
||||||
// Set all individual bits
|
// Set all individual bits
|
||||||
if (portStatus & UHCI_PORTSC_CURSTAT)
|
if (portStatus & UHCI_PORTSC_CURSTAT)
|
||||||
newStatus |= PORT_STATUS_CONNECTION;
|
newStatus |= PORT_STATUS_CONNECTION;
|
||||||
|
|
||||||
if (portStatus & UHCI_PORTSC_STATCHA)
|
if (portStatus & UHCI_PORTSC_STATCHA)
|
||||||
newStatus |= PORT_STATUS_CONNECTION;
|
newChange |= PORT_STATUS_CONNECTION;
|
||||||
|
|
||||||
if (portStatus & UHCI_PORTSC_ENABLED)
|
if (portStatus & UHCI_PORTSC_ENABLED)
|
||||||
newStatus |= PORT_STATUS_ENABLE;
|
newStatus |= PORT_STATUS_ENABLE;
|
||||||
|
|
||||||
if (portStatus & UHCI_PORTSC_ENABCHA)
|
if (portStatus & UHCI_PORTSC_ENABCHA)
|
||||||
newStatus |= PORT_STATUS_ENABLE;
|
newChange |= PORT_STATUS_ENABLE;
|
||||||
|
|
||||||
// TODO: work out suspended/resume
|
// TODO: work out suspended/resume
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user