Picking up work on the USB stack. First of all adapting the style of the UHCI driver. Not yet working any more than until now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17607 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
848b89034e
commit
12b0511534
File diff suppressed because it is too large
Load Diff
@ -1,23 +1,10 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 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 2004-2006, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Niels S. Reedijk
|
||||
*/
|
||||
|
||||
#ifndef UHCI_H
|
||||
#define UHCI_H
|
||||
@ -29,84 +16,88 @@ struct pci_info;
|
||||
struct pci_module_info;
|
||||
class UHCIRootHub;
|
||||
|
||||
class UHCI : public BusManager
|
||||
{
|
||||
friend class UHCIRootHub;
|
||||
friend int32 uhci_interrupt_handler( void *data );
|
||||
public:
|
||||
UHCI( pci_info *info , Stack *stack );
|
||||
|
||||
//Override from BusManager
|
||||
status_t Start();
|
||||
status_t SubmitTransfer( Transfer *t );
|
||||
|
||||
// Global data for the module.
|
||||
static pci_module_info *pci_module;
|
||||
private:
|
||||
//Utility functions
|
||||
void GlobalReset();
|
||||
status_t Reset();
|
||||
int32 Interrupt();
|
||||
|
||||
//Functions for the actual functioning of transfers
|
||||
status_t InsertControl( Transfer *t );
|
||||
|
||||
uint32 m_reg_base; //Base address of the registers
|
||||
pci_info *m_pcii; //pci-info struct
|
||||
Stack *m_stack; //Pointer to the stack
|
||||
|
||||
//Frame list memory
|
||||
area_id m_framearea;
|
||||
addr_t m_framelist[1024]; //The frame list struct
|
||||
addr_t m_framelist_phy; //The physical pointer to the frame list
|
||||
|
||||
// Virtual frame
|
||||
uhci_qh *m_qh_virtual[12]; //
|
||||
#define m_qh_interrupt_256 m_qh_virtual[0]
|
||||
#define m_qh_interrupt_128 m_qh_virtual[1]
|
||||
#define m_qh_interrupt_64 m_qh_virtual[2]
|
||||
#define m_qh_interrupt_32 m_qh_virtual[3]
|
||||
#define m_qh_interrupt_16 m_qh_virtual[4]
|
||||
#define m_qh_interrupt_8 m_qh_virtual[5]
|
||||
#define m_qh_interrupt_4 m_qh_virtual[6]
|
||||
#define m_qh_interrupt_2 m_qh_virtual[7]
|
||||
#define m_qh_interrupt_1 m_qh_virtual[8]
|
||||
#define m_qh_control m_qh_virtual[9]
|
||||
#define m_qh_bulk m_qh_virtual[10]
|
||||
#define m_qh_terminate m_qh_virtual[11]
|
||||
|
||||
//Maintain a list of transfers
|
||||
Vector<Transfer *> m_transfers;
|
||||
|
||||
//Root hub:
|
||||
UHCIRootHub *m_rh; // the root hub
|
||||
uint8 m_rh_address; // the address of the root hub
|
||||
class UHCI : public BusManager {
|
||||
public:
|
||||
UHCI(pci_info *info, Stack *stack);
|
||||
|
||||
status_t Start();
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
|
||||
static bool AddTo(Stack &stack);
|
||||
|
||||
private:
|
||||
friend class UHCIRootHub;
|
||||
|
||||
// Utility functions
|
||||
void GlobalReset();
|
||||
status_t Reset();
|
||||
static int32 InterruptHandler(void *data);
|
||||
int32 Interrupt();
|
||||
|
||||
// Register functions
|
||||
inline void WriteReg16(uint32 reg, uint16 value);
|
||||
inline void WriteReg32(uint32 reg, uint32 value);
|
||||
inline uint16 ReadReg16(uint32 reg);
|
||||
inline uint32 ReadReg32(uint32 reg);
|
||||
|
||||
// Functions for the actual functioning of transfers
|
||||
status_t InsertControl(Transfer *transfer);
|
||||
|
||||
static pci_module_info *sPCIModule;
|
||||
|
||||
uint32 fRegisterBase;
|
||||
pci_info *fPCIInfo;
|
||||
Stack *fStack;
|
||||
|
||||
// Frame list memory
|
||||
area_id fFrameArea;
|
||||
addr_t fFrameList[1024];
|
||||
addr_t fPhysicalFrameList;
|
||||
|
||||
// Virtual frame
|
||||
uhci_qh *fVirtualQueueHead[12];
|
||||
|
||||
#define fQueueHeadInterrupt256 fVirtualQueueHead[0]
|
||||
#define fQueueHeadInterrupt128 fVirtualQueueHead[1]
|
||||
#define fQueueHeadInterrupt64 fVirtualQueueHead[2]
|
||||
#define fQueueHeadInterrupt32 fVirtualQueueHead[3]
|
||||
#define fQueueHeadInterrupt16 fVirtualQueueHead[4]
|
||||
#define fQueueHeadInterrupt8 fVirtualQueueHead[5]
|
||||
#define fQueueHeadInterrupt4 fVirtualQueueHead[6]
|
||||
#define fQueueHeadInterrupt2 fVirtualQueueHead[7]
|
||||
#define fQueueHeadInterrupt1 fVirtualQueueHead[8]
|
||||
#define fQueueHeadControl fVirtualQueueHead[9]
|
||||
#define fQueueHeadBulk fVirtualQueueHead[10]
|
||||
#define fQueueHeadTerminate fVirtualQueueHead[11]
|
||||
|
||||
// Maintain a list of transfers
|
||||
Vector<Transfer *> fTransfers;
|
||||
|
||||
// Root hub
|
||||
UHCIRootHub *fRootHub;
|
||||
uint8 fRootHubAddress;
|
||||
};
|
||||
|
||||
class UHCIRootHub : public Hub
|
||||
{
|
||||
|
||||
class UHCIRootHub : public Hub {
|
||||
public:
|
||||
UHCIRootHub( UHCI *uhci , int8 devicenum );
|
||||
status_t SubmitTransfer( Transfer *t );
|
||||
void UpdatePortStatus();
|
||||
UHCIRootHub(UHCI *uhci, int8 deviceNum);
|
||||
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
void UpdatePortStatus();
|
||||
|
||||
private:
|
||||
usb_port_status m_hw_port_status[2]; // the port status (maximum of two)
|
||||
UHCI *m_uhci; // needed because of internal data
|
||||
|
||||
usb_port_status fPortStatus[2];
|
||||
UHCI *fUHCI;
|
||||
};
|
||||
|
||||
struct hostcontroller_priv
|
||||
{
|
||||
|
||||
struct hostcontroller_priv {
|
||||
uhci_qh *topqh;
|
||||
uhci_td *firsttd;
|
||||
uhci_td *lasttd;
|
||||
};
|
||||
|
||||
#define UHCI_DEBUG
|
||||
#ifdef UHCI_DEBUG
|
||||
#define TRACE dprintf
|
||||
#else
|
||||
#define TRACE silent
|
||||
void silent( const char * , ... ) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -61,7 +61,7 @@
|
||||
#define UHCI_USBSTS_HOSTERR 0x8 // Host System Error
|
||||
#define UHCI_USBSTS_HCPRERR 0x10// Host Controller Process error
|
||||
#define UHCI_USBSTS_HCHALT 0x20 // HCHalted
|
||||
#define UHCI_INTERRUPT_MASK 0x1F //Mask for all the interrupts
|
||||
#define UHCI_INTERRUPT_MASK 0x3F //Mask for all the interrupts
|
||||
|
||||
//USBINTR
|
||||
#define UHCI_USBINTR_CRC 0x1 // Timeout/ CRC interrupt enable
|
||||
|
@ -1,267 +1,268 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 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 2004-2006, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Niels S. Reedijk
|
||||
*/
|
||||
|
||||
#include "uhci.h"
|
||||
#include <PCI.h>
|
||||
|
||||
|
||||
#define TRACE_UHCI_ROOT_HUB
|
||||
#ifdef TRACE_UHCI_ROOT_HUB
|
||||
#define TRACE(x) dprintf x
|
||||
#else
|
||||
#define TRACE(x) /* nothing */
|
||||
#endif
|
||||
|
||||
|
||||
usb_device_descriptor uhci_devd =
|
||||
{
|
||||
0x12, //Descriptor size
|
||||
USB_DESCRIPTOR_DEVICE , //Type of descriptor
|
||||
USB_DESCRIPTOR_DEVICE, //Type of descriptor
|
||||
0x110, //USB 1.1
|
||||
0x09 , //Hub type
|
||||
0 , //Subclass
|
||||
0 , //Protocol
|
||||
64 , //Max packet size
|
||||
0 , //Vendor
|
||||
0 , //Product
|
||||
0x110 , //Version
|
||||
1 , 2 , 0 , //Other data
|
||||
0x09, //Hub type
|
||||
0, //Subclass
|
||||
0, //Protocol
|
||||
64, //Max packet size
|
||||
0, //Vendor
|
||||
0, //Product
|
||||
0x110, //Version
|
||||
1, 2, 0, //Other data
|
||||
1 //Number of configurations
|
||||
};
|
||||
|
||||
|
||||
usb_configuration_descriptor uhci_confd =
|
||||
{
|
||||
0x09, //Size
|
||||
USB_DESCRIPTOR_CONFIGURATION ,
|
||||
25 , //Total size (taken from BSD source)
|
||||
1 , //Number interfaces
|
||||
1 , //Value of configuration
|
||||
0 , //Number of configuration
|
||||
0x40 , //Self powered
|
||||
USB_DESCRIPTOR_CONFIGURATION,
|
||||
25, //Total size (taken from BSD source)
|
||||
1, //Number interfaces
|
||||
1, //Value of configuration
|
||||
0, //Number of configuration
|
||||
0x40, //Self powered
|
||||
0 //Max power (0, because of self power)
|
||||
};
|
||||
|
||||
|
||||
usb_interface_descriptor uhci_intd =
|
||||
{
|
||||
0x09 , //Size
|
||||
USB_DESCRIPTOR_INTERFACE ,
|
||||
0 , //Interface number
|
||||
0 , //Alternate setting
|
||||
1 , //Num endpoints
|
||||
0x09 , //Interface class
|
||||
0 , //Interface subclass
|
||||
0 , //Interface protocol
|
||||
0 , //Interface
|
||||
0x09, //Size
|
||||
USB_DESCRIPTOR_INTERFACE,
|
||||
0, //Interface number
|
||||
0, //Alternate setting
|
||||
1, //Num endpoints
|
||||
0x09, //Interface class
|
||||
0, //Interface subclass
|
||||
0, //Interface protocol
|
||||
0, //Interface
|
||||
};
|
||||
|
||||
|
||||
usb_endpoint_descriptor uhci_endd =
|
||||
{
|
||||
0x07 , //Size
|
||||
0x07, //Size
|
||||
USB_DESCRIPTOR_ENDPOINT,
|
||||
USB_REQTYPE_DEVICE_IN | 1, //1 from freebsd driver
|
||||
0x3 , // Interrupt
|
||||
8 , // Max packet size
|
||||
0x3, // Interrupt
|
||||
8, // Max packet size
|
||||
0xFF // Interval 256
|
||||
};
|
||||
|
||||
|
||||
usb_hub_descriptor uhci_hubd =
|
||||
{
|
||||
0x09 , //Including deprecated powerctrlmask
|
||||
0x09, //Including deprecated powerctrlmask
|
||||
USB_DESCRIPTOR_HUB,
|
||||
1, //Number of ports
|
||||
0x02 | 0x01 , //Hub characteristics FIXME
|
||||
50 , //Power on to power good
|
||||
0x02 | 0x01, //Hub characteristics FIXME
|
||||
50, //Power on to power good
|
||||
0, // Current
|
||||
0x00 //Both ports are removable
|
||||
};
|
||||
|
||||
//Implementation
|
||||
UHCIRootHub::UHCIRootHub( UHCI *uhci , int8 devicenum )
|
||||
: Hub( uhci , NULL , uhci_devd , devicenum , false )
|
||||
|
||||
UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
|
||||
: Hub(uhci, NULL, uhci_devd, devicenum, false)
|
||||
{
|
||||
m_uhci = uhci;
|
||||
fUHCI = uhci;
|
||||
}
|
||||
|
||||
status_t UHCIRootHub::SubmitTransfer( Transfer *t )
|
||||
{
|
||||
status_t retval;
|
||||
usb_request_data *request = t->GetRequestData();
|
||||
uint16 port; //used in RH_CLEAR/SET_FEATURE
|
||||
|
||||
TRACE( "USB UHCI: rh_submit_packet called. Request: %u\n" , t->GetRequestData()->Request );
|
||||
|
||||
switch( request->Request )
|
||||
{
|
||||
case RH_GET_STATUS:
|
||||
if ( request->Index == 0 )
|
||||
{
|
||||
//Get the hub status -- everything as 0 means that it is all-rigth
|
||||
memset( t->GetBuffer() , NULL , sizeof(get_status_buffer) );
|
||||
retval = B_OK;
|
||||
break;
|
||||
}
|
||||
else if (request->Index > uhci_hubd.bNbrPorts )
|
||||
{
|
||||
//This port doesn't exist
|
||||
retval = EINVAL;
|
||||
break;
|
||||
}
|
||||
//Get port status
|
||||
UpdatePortStatus();
|
||||
memcpy( t->GetBuffer() , (void *)&(m_hw_port_status[request->Index - 1]) , t->GetBufferLength());
|
||||
*(t->GetActualLength()) = t->GetBufferLength();
|
||||
retval = B_OK;
|
||||
break;
|
||||
|
||||
case RH_SET_ADDRESS:
|
||||
if ( request->Value >= 128 )
|
||||
{
|
||||
retval = EINVAL;
|
||||
break;
|
||||
}
|
||||
TRACE( "USB UHCI: rh_submit_packet RH_ADDRESS: %d\n" , request->Value );
|
||||
retval = B_OK;
|
||||
break;
|
||||
|
||||
case RH_GET_DESCRIPTOR:
|
||||
{
|
||||
TRACE( "USB UHCI: rh_submit_packet GET_DESC: %d\n" , request->Value );
|
||||
switch ( request->Value )
|
||||
{
|
||||
case RH_DEVICE_DESCRIPTOR:
|
||||
memcpy( t->GetBuffer() , (void *)&uhci_devd , t->GetBufferLength());
|
||||
*(t->GetActualLength()) = t->GetBufferLength();
|
||||
retval = B_OK;
|
||||
status_t
|
||||
UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
{
|
||||
usb_request_data *request = transfer->GetRequestData();
|
||||
TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request));
|
||||
|
||||
status_t result = B_ERROR;
|
||||
switch(request->Request) {
|
||||
case RH_GET_STATUS:
|
||||
if (request->Index == 0) {
|
||||
// Get the hub status -- everything as 0 means all-right
|
||||
memset(transfer->GetBuffer(), 0, sizeof(get_status_buffer));
|
||||
result = B_OK;
|
||||
break;
|
||||
case RH_CONFIG_DESCRIPTOR:
|
||||
memcpy( t->GetBuffer() , (void *)&uhci_confd , t->GetBufferLength());
|
||||
*(t->GetActualLength()) = t->GetBufferLength();
|
||||
retval = B_OK;
|
||||
break;
|
||||
case RH_INTERFACE_DESCRIPTOR:
|
||||
memcpy( t->GetBuffer() , (void *)&uhci_intd , t->GetBufferLength());
|
||||
*(t->GetActualLength()) = t->GetBufferLength();
|
||||
retval = B_OK ;
|
||||
break;
|
||||
case RH_ENDPOINT_DESCRIPTOR:
|
||||
memcpy( t->GetBuffer() , (void *)&uhci_endd , t->GetBufferLength());
|
||||
*(t->GetActualLength()) = t->GetBufferLength();
|
||||
retval = B_OK ;
|
||||
break;
|
||||
case RH_HUB_DESCRIPTOR:
|
||||
memcpy( t->GetBuffer() , (void *)&uhci_hubd , t->GetBufferLength());
|
||||
*(t->GetActualLength()) = t->GetBufferLength();
|
||||
retval = B_OK;
|
||||
break;
|
||||
default:
|
||||
retval = EINVAL;
|
||||
} else if (request->Index > uhci_hubd.bNbrPorts) {
|
||||
// This port doesn't exist
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RH_SET_CONFIG:
|
||||
retval = B_OK;
|
||||
break;
|
||||
// Get port status
|
||||
UpdatePortStatus();
|
||||
memcpy(transfer->GetBuffer(),
|
||||
(void *)&fPortStatus[request->Index - 1],
|
||||
transfer->GetBufferLength());
|
||||
|
||||
case RH_CLEAR_FEATURE:
|
||||
if ( request->Index == 0 )
|
||||
{
|
||||
//We don't support any hub changes
|
||||
TRACE( "UHCI: RH_CLEAR_FEATURE no hub changes!\n" );
|
||||
retval = EINVAL;
|
||||
*(transfer->GetActualLength()) = transfer->GetBufferLength();
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
else if ( request->Index > uhci_hubd.bNbrPorts )
|
||||
{
|
||||
//Invalid port number
|
||||
TRACE( "UHCI: RH_CLEAR_FEATURE invalid port!\n" );
|
||||
retval = EINVAL;
|
||||
|
||||
case RH_SET_ADDRESS:
|
||||
if (request->Value >= 128) {
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci_roothub: rh_submit_packet RH_ADDRESS: %d\n", request->Value));
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE("UHCI: RH_CLEAR_FEATURE called. Feature: %u!\n" , request->Value );
|
||||
switch( request->Value )
|
||||
{
|
||||
case PORT_RESET:
|
||||
port = UHCI::pci_module->read_io_16( m_uhci->m_reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 );
|
||||
port &= ~UHCI_PORTSC_RESET;
|
||||
TRACE( "UHCI rh: port %x Clear RESET\n" , port );
|
||||
UHCI::pci_module->write_io_16( m_uhci->m_reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 , port );
|
||||
case C_PORT_CONNECTION:
|
||||
port = UHCI::pci_module->read_io_16( m_uhci->m_reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 );
|
||||
port = port & UHCI_PORTSC_DATAMASK;
|
||||
port |= UHCI_PORTSC_STATCHA;
|
||||
TRACE( "UHCI rh: port: %x\n" , port );
|
||||
UHCI::pci_module->write_io_16( m_uhci->m_reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 , port );
|
||||
retval = B_OK;
|
||||
|
||||
case RH_GET_DESCRIPTOR:
|
||||
TRACE(("usb_uhci_roothub: rh_submit_packet GET_DESC: %d\n", request->Value));
|
||||
|
||||
switch (request->Value) {
|
||||
case RH_DEVICE_DESCRIPTOR:
|
||||
memcpy(transfer->GetBuffer(), (void *)&uhci_devd,
|
||||
transfer->GetBufferLength());
|
||||
*(transfer->GetActualLength()) = transfer->GetBufferLength();
|
||||
result = B_OK;
|
||||
break;
|
||||
case RH_CONFIG_DESCRIPTOR:
|
||||
memcpy(transfer->GetBuffer(), (void *)&uhci_confd,
|
||||
transfer->GetBufferLength());
|
||||
*(transfer->GetActualLength()) = transfer->GetBufferLength();
|
||||
result = B_OK;
|
||||
break;
|
||||
case RH_INTERFACE_DESCRIPTOR:
|
||||
memcpy(transfer->GetBuffer(), (void *)&uhci_intd,
|
||||
transfer->GetBufferLength());
|
||||
*(transfer->GetActualLength()) = transfer->GetBufferLength();
|
||||
result = B_OK ;
|
||||
break;
|
||||
case RH_ENDPOINT_DESCRIPTOR:
|
||||
memcpy(transfer->GetBuffer(), (void *)&uhci_endd,
|
||||
transfer->GetBufferLength());
|
||||
*(transfer->GetActualLength()) = transfer->GetBufferLength();
|
||||
result = B_OK ;
|
||||
break;
|
||||
case RH_HUB_DESCRIPTOR:
|
||||
memcpy(transfer->GetBuffer(), (void *)&uhci_hubd,
|
||||
transfer->GetBufferLength());
|
||||
*(transfer->GetActualLength()) = transfer->GetBufferLength();
|
||||
result = B_OK;
|
||||
break;
|
||||
default:
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
retval = EINVAL;
|
||||
|
||||
case RH_SET_CONFIG:
|
||||
result = B_OK;
|
||||
break;
|
||||
|
||||
case RH_CLEAR_FEATURE:
|
||||
if (request->Index == 0) {
|
||||
// We don't support any hub changes
|
||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE no hub changes!\n"));
|
||||
result = EINVAL;
|
||||
break;
|
||||
} else if (request->Index > uhci_hubd.bNbrPorts) {
|
||||
// Invalid port number
|
||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE invalid port!\n"));
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE called. Feature: %u!\n", request->Value));
|
||||
uint16 port;
|
||||
switch(request->Value) {
|
||||
case PORT_RESET:
|
||||
port = UHCI::sPCIModule->read_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + (request->Index - 1) * 2);
|
||||
port &= ~UHCI_PORTSC_RESET;
|
||||
TRACE(("usb_uhci_roothub: port %x Clear RESET\n", port));
|
||||
UHCI::sPCIModule->write_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + (request->Index - 1) * 2, port);
|
||||
break;
|
||||
|
||||
case C_PORT_CONNECTION:
|
||||
port = UHCI::sPCIModule->read_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + (request->Index - 1) * 2);
|
||||
port = port & UHCI_PORTSC_DATAMASK;
|
||||
port |= UHCI_PORTSC_STATCHA;
|
||||
TRACE(("usb_uhci_roothub: port: %x\n", port));
|
||||
UHCI::sPCIModule->write_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + (request->Index - 1) * 2, port);
|
||||
result = B_OK;
|
||||
break;
|
||||
default:
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
result = EINVAL;
|
||||
break;
|
||||
} //switch( t->value)
|
||||
break;
|
||||
|
||||
default:
|
||||
retval = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Clean up the transfer - we own it, so we clean it up
|
||||
t->Finish();
|
||||
delete t;
|
||||
|
||||
return retval;
|
||||
transfer->Finish();
|
||||
delete transfer;
|
||||
return result;
|
||||
}
|
||||
|
||||
void UHCIRootHub::UpdatePortStatus(void)
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i <= 1 ; i++ )
|
||||
{
|
||||
uint16 newstatus = 0;
|
||||
uint16 newchange = 0;
|
||||
|
||||
uint16 portsc = UHCI::pci_module->read_io_16( m_uhci->m_reg_base + UHCI_PORTSC1 + i * 2 );
|
||||
dprintf( "USB UHCI: port: %x status: 0x%x\n" , UHCI_PORTSC1 + i * 2 , portsc );
|
||||
//Set all individual bits
|
||||
if ( portsc & UHCI_PORTSC_CURSTAT )
|
||||
newstatus |= PORT_STATUS_CONNECTION;
|
||||
|
||||
if ( portsc & UHCI_PORTSC_STATCHA )
|
||||
newchange |= PORT_STATUS_CONNECTION;
|
||||
|
||||
if ( portsc & UHCI_PORTSC_ENABLED )
|
||||
newstatus |= PORT_STATUS_ENABLE;
|
||||
|
||||
if ( portsc & UHCI_PORTSC_ENABCHA )
|
||||
newchange |= PORT_STATUS_ENABLE;
|
||||
|
||||
void
|
||||
UHCIRootHub::UpdatePortStatus()
|
||||
{
|
||||
for (int32 i = 0; i < 2; 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));
|
||||
|
||||
// Set all individual bits
|
||||
if (portStatus & UHCI_PORTSC_CURSTAT)
|
||||
newStatus |= PORT_STATUS_CONNECTION;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_STATCHA)
|
||||
newStatus |= PORT_STATUS_CONNECTION;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_ENABLED)
|
||||
newStatus |= PORT_STATUS_ENABLE;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_ENABCHA)
|
||||
newStatus |= PORT_STATUS_ENABLE;
|
||||
|
||||
// TODO: work out suspended/resume
|
||||
|
||||
if ( portsc & UHCI_PORTSC_RESET )
|
||||
newstatus |= PORT_STATUS_RESET;
|
||||
|
||||
|
||||
if (portStatus & UHCI_PORTSC_RESET)
|
||||
newStatus |= PORT_STATUS_RESET;
|
||||
|
||||
//TODO: work out reset change...
|
||||
|
||||
|
||||
//The port is automagically powered on
|
||||
newstatus |= PORT_POWER;
|
||||
|
||||
if ( portsc & UHCI_PORTSC_LOWSPEED )
|
||||
newstatus |= PORT_STATUS_LOW_SPEED;
|
||||
|
||||
newStatus |= PORT_POWER;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_LOWSPEED)
|
||||
newStatus |= PORT_STATUS_LOW_SPEED;
|
||||
|
||||
//Update the stored port status
|
||||
m_hw_port_status[i].status = newstatus;
|
||||
m_hw_port_status[i].change = newchange;
|
||||
fPortStatus[i].status = newStatus;
|
||||
fPortStatus[i].change = newChange;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user