From 26f34d1c060c40ce975424e164274177c8f7b4c6 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 27 May 2006 19:33:30 +0000 Subject: [PATCH] * 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 --- .../kernel/bus_managers/usb/BusManager.cpp | 304 +++++++++--------- src/add-ons/kernel/bus_managers/usb/usb_p.h | 63 ++-- src/add-ons/kernel/busses/usb/uhci.cpp | 39 +-- src/add-ons/kernel/busses/usb/uhci.h | 1 - src/add-ons/kernel/busses/usb/uhci_rh.cpp | 10 +- 5 files changed, 210 insertions(+), 207 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp index 7444662709..cab9040bbe 100644 --- a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp +++ b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp @@ -1,186 +1,200 @@ -//------------------------------------------------------------------------------ -// Copyright (c) 2003-2004, Niels S. Reedijk -// -// 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 2003-2006, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Niels S. Reedijk + */ #include "usb_p.h" -/* +++++++++ -This is the 'main' function of the explore thread, which keeps track of -the hub statuses. -+++++++++ */ -int32 usb_explore_thread( void *data ) -{ - 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; -} +#define TRACE_BUSMANAGER +#ifdef TRACE_BUSMANAGER +#define TRACE(x) dprintf(x) +#else +#define TRACE(x) /* nothing */ +#endif BusManager::BusManager() { - m_initok = false; - m_roothub = 0; - - // 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; + fInitOK = false; + fRootHub = NULL; - 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() { } -status_t BusManager::InitCheck() + +status_t +BusManager::InitCheck() { - if ( m_initok == true ) + if (fInitOK) 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; - status_t retval; - usb_device_descriptor device_descriptor; - - //1. Check if there is a free entry in the device map (for the device number) - devicenum = AllocateAddress(); - if ( devicenum < 0 ) - { - dprintf( "usb Busmanager [new device]: could not get a new address\n" ); - return 0; + Hub *rootHub = (Hub *)data; + if (!rootHub) + return B_ERROR; + + while (true) { + rootHub->Explore(); + snooze(1000000); } - - - //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 - 0 , //index - 0 , //length - NULL , //data - 0 , //data_len - 0 ); //actual len - - if ( retval < B_OK ) - { - dprintf( "usb busmanager [new device]: error with commmunicating the right address\n" ); - return 0; + + return B_OK; +} + + +Device * +BusManager::AllocateNewDevice(Device *parent, bool lowSpeed) +{ + // Check if there is a free entry in the device map (for the device number) + int8 deviceNum = AllocateAddress(); + if (deviceNum < 0) { + TRACE(("usb BusManager::AllocateNewDevice(): could not get a new address\n")); + return NULL; } - - //Create a temporary pipe - ControlPipe pipe( this , devicenum , Pipe::Default , Pipe::LowSpeed , 0 ); - - //3. Get the device descriptor + + // Set the address of the device USB 1.1 spec p202 + status_t result = fDefaultPipeLowSpeed->SendRequest( + USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type + 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 // size of any device, plus it is enough, because the device type is in - // there too - - size_t actual_length; - - pipe.SendRequest( USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type - USB_REQUEST_GET_DESCRIPTOR , //Request - ( USB_DESCRIPTOR_DEVICE << 8 ), //Value - 0 , //Index - 8 , //Length - (void *)&device_descriptor , //Buffer - 8 , //Bufferlength - &actual_length ); //length - - if ( actual_length != 8 ) - { - dprintf( "usb busmanager [new device]: error while getting the device descriptor\n" ); - return 0; + // there too + + size_t actualLength = 0; + usb_device_descriptor deviceDescriptor; + + pipe.SendRequest( + USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type + USB_REQUEST_GET_DESCRIPTOR, // request + USB_DESCRIPTOR_DEVICE << 8, // value + 0, // index + 8, // length + (void *)&deviceDescriptor, // buffer + 8, // buffer length + &actualLength); // actual length + + if (actualLength != 8) { + 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); - if ( device_descriptor.device_class == 0x09 ) - { - dprintf( "usb Busmanager [new device]: New hub\n" ); - Device *ret = new Hub( this , parent , device_descriptor , devicenum , lowspeed ); - if ( parent == 0 ) //root hub!! - m_roothub = ret; - return 0; + // Create a new instance based on the type (Hub or Device) + if (deviceDescriptor.device_class == 0x09) { + TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n")); + Device *ret = new Hub(this, parent, deviceDescriptor, deviceNum, + lowSpeed); + + if (parent == NULL) { + // root hub + fRootHub = ret; + } + + return ret; } - - dprintf( "usb Busmanager [new device]: New normal device\n" ); - return new Device( this , parent , device_descriptor , devicenum , lowspeed); + + TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n")); + return new Device(this, parent, deviceDescriptor, deviceNum, lowSpeed); } -int8 BusManager::AllocateAddress() + +int8 +BusManager::AllocateAddress() { - acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 ); - int8 devicenum = -1; - for( int i = 1 ; i < 128 ; i++ ) - { - if ( m_devicemap[i] == false ) - { - devicenum = i; - m_devicemap[i] = true; + acquire_sem_etc(fLock, 1, B_CAN_INTERRUPT, 0); + + int8 deviceNum = -1; + for (int32 i = 1; i < 128; i++) { + if (fDeviceMap[i] == false) { + deviceNum = i; + fDeviceMap[i] = true; 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" ); - if ( InitCheck() != B_OK ) + TRACE(("usb BusManager::Start()\n")); + if (InitCheck() != B_OK) return InitCheck(); - - if ( m_explore_thread == 0 ) - m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" , - B_LOW_PRIORITY , (void *)m_roothub ); - - // Start the 'explore thread' - return resume_thread( m_explore_thread ); + + if (fExploreThread < 0) { + fExploreThread = spawn_kernel_thread(ExploreThread, + "usb busmanager explore", B_LOW_PRIORITY, (void *)fRootHub); + } + + 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; -}; +} diff --git a/src/add-ons/kernel/bus_managers/usb/usb_p.h b/src/add-ons/kernel/bus_managers/usb/usb_p.h index 9d1f41ad6a..dbebce13bf 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -128,37 +128,42 @@ private: * after a host controller gives positive feedback on whether the hardware * is found. */ -class BusManager -{ - friend class Device; - friend class ControlPipe; +class BusManager { public: - 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; -}; + BusManager(); +virtual ~BusManager(); -// Located in the BusManager.cpp -int32 usb_explore_thread( void *data ); +virtual status_t InitCheck(); + + 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\ diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp b/src/add-ons/kernel/busses/usb/uhci.cpp index e921be581d..3f603ba29d 100644 --- a/src/add-ons/kernel/busses/usb/uhci.cpp +++ b/src/add-ons/kernel/busses/usb/uhci.cpp @@ -99,7 +99,7 @@ UHCI::UHCI(pci_info *info, Stack *stack) GlobalReset(); if (Reset() < B_OK) { TRACE(("usb_uhci: host failed to reset\n")); - m_initok = false; + fInitOK = false; return; } @@ -110,7 +110,7 @@ UHCI::UHCI(pci_info *info, Stack *stack) if (fFrameArea < B_OK) { TRACE(("usb_uhci: unable to create an area for the frame pointer list\n")); - m_initok = false; + fInitOK = false; return; } @@ -126,7 +126,7 @@ UHCI::UHCI(pci_info *info, Stack *stack) if (fStack->AllocateChunk((void **)&strayDescriptor, &physicalAddress, 32) != B_OK) { TRACE(("usb_uhci: failed to allocate a stray transfer descriptor\n")); delete_area(fFrameArea); - m_initok = false; + fInitOK = false; return; } @@ -151,7 +151,7 @@ UHCI::UHCI(pci_info *info, Stack *stack) &physicalAddress, 32) != B_OK) { TRACE(("usb_uhci: failed allocation of skeleton queue head %i, aborting\n", i)); delete_area(fFrameArea); - m_initok = false; + fInitOK = false; return; } @@ -246,22 +246,13 @@ UHCI::Start() 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(); fRootHub = new UHCIRootHub(this, fRootHubAddress); 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", 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 // 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. @@ -423,7 +410,8 @@ UHCI::InsertControl(Transfer *transfer) 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 topQueueHead->element_phy = transferDescriptor->this_phy; @@ -470,11 +458,11 @@ UHCI::InsertControl(Transfer *transfer) transfer->GetHostPrivate()->lasttd = statusDescriptor; 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) { // the control queue is empty, make this the first element fQueueHeadControl->element_phy = topQueueHead->this_phy; - fQueueHeadControl->link_log = (void *)topQueueHead; + fQueueHeadControl->link_log = topQueueHead; TRACE(("usb_uhci: first transfer in queue\n")); } else { // there are control transfers linked, append to the queue @@ -483,7 +471,7 @@ UHCI::InsertControl(Transfer *transfer) queueHead = (uhci_qh *)queueHead->link_log; queueHead->link_phy = topQueueHead->this_phy; - queueHead->link_log = (void *)topQueueHead; + queueHead->link_log = topQueueHead; TRACE(("usb_uhci: appended transfer to queue\n")); } @@ -510,7 +498,6 @@ UHCI::AddTo(Stack &stack) TRACE(("usb_uhci: AddTo(): setting up hardware\n")); - // TODO: in the future we might want to support multiple host controllers. bool found = false; pci_info *item = new pci_info; 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->SetupRootHub(); stack.AddBusManager(bus); found = true; - break; } } diff --git a/src/add-ons/kernel/busses/usb/uhci.h b/src/add-ons/kernel/busses/usb/uhci.h index 81769ee96e..6d6ecddc03 100644 --- a/src/add-ons/kernel/busses/usb/uhci.h +++ b/src/add-ons/kernel/busses/usb/uhci.h @@ -22,7 +22,6 @@ public: UHCI(pci_info *info, Stack *stack); status_t Start(); - status_t SetupRootHub(); status_t SubmitTransfer(Transfer *transfer); static bool AddTo(Stack &stack); diff --git a/src/add-ons/kernel/busses/usb/uhci_rh.cpp b/src/add-ons/kernel/busses/usb/uhci_rh.cpp index 74c8189e22..55696bf1b8 100644 --- a/src/add-ons/kernel/busses/usb/uhci_rh.cpp +++ b/src/add-ons/kernel/busses/usb/uhci_rh.cpp @@ -77,7 +77,7 @@ usb_hub_descriptor uhci_hubd = { 0x09, //Including deprecated powerctrlmask USB_DESCRIPTOR_HUB, - 1, //Number of ports + 2, //Number of ports 0x02 | 0x01, //Hub characteristics FIXME 50, //Power on to power good 0, // Current @@ -228,25 +228,25 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer) void UHCIRootHub::UpdatePortStatus() { - for (int32 i = 0; i < 2; i++) { + for (int32 i = 0; i < uhci_hubd.bNbrPorts; i++) { uint16 newStatus = 0; uint16 newChange = 0; 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 if (portStatus & UHCI_PORTSC_CURSTAT) newStatus |= PORT_STATUS_CONNECTION; if (portStatus & UHCI_PORTSC_STATCHA) - newStatus |= PORT_STATUS_CONNECTION; + newChange |= PORT_STATUS_CONNECTION; if (portStatus & UHCI_PORTSC_ENABLED) newStatus |= PORT_STATUS_ENABLE; if (portStatus & UHCI_PORTSC_ENABCHA) - newStatus |= PORT_STATUS_ENABLE; + newChange |= PORT_STATUS_ENABLE; // TODO: work out suspended/resume