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:
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,10 @@
|
|||||||
//------------------------------------------------------------------------------
|
/*
|
||||||
// Copyright (c) 2004, Niels S. Reedijk
|
* Copyright 2004-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.
|
|
||||||
|
|
||||||
#ifndef UHCI_H
|
#ifndef UHCI_H
|
||||||
#define UHCI_H
|
#define UHCI_H
|
||||||
@@ -29,84 +16,88 @@ struct pci_info;
|
|||||||
struct pci_module_info;
|
struct pci_module_info;
|
||||||
class UHCIRootHub;
|
class UHCIRootHub;
|
||||||
|
|
||||||
class UHCI : public BusManager
|
|
||||||
{
|
class UHCI : public BusManager {
|
||||||
friend class UHCIRootHub;
|
|
||||||
friend int32 uhci_interrupt_handler( void *data );
|
|
||||||
public:
|
public:
|
||||||
UHCI( pci_info *info , Stack *stack );
|
UHCI(pci_info *info, Stack *stack);
|
||||||
|
|
||||||
//Override from BusManager
|
status_t Start();
|
||||||
status_t Start();
|
status_t SubmitTransfer(Transfer *transfer);
|
||||||
status_t SubmitTransfer( Transfer *t );
|
|
||||||
|
static bool AddTo(Stack &stack);
|
||||||
|
|
||||||
// Global data for the module.
|
|
||||||
static pci_module_info *pci_module;
|
|
||||||
private:
|
private:
|
||||||
//Utility functions
|
friend class UHCIRootHub;
|
||||||
void GlobalReset();
|
|
||||||
status_t Reset();
|
|
||||||
int32 Interrupt();
|
|
||||||
|
|
||||||
//Functions for the actual functioning of transfers
|
// Utility functions
|
||||||
status_t InsertControl( Transfer *t );
|
void GlobalReset();
|
||||||
|
status_t Reset();
|
||||||
|
static int32 InterruptHandler(void *data);
|
||||||
|
int32 Interrupt();
|
||||||
|
|
||||||
uint32 m_reg_base; //Base address of the registers
|
// Register functions
|
||||||
pci_info *m_pcii; //pci-info struct
|
inline void WriteReg16(uint32 reg, uint16 value);
|
||||||
Stack *m_stack; //Pointer to the stack
|
inline void WriteReg32(uint32 reg, uint32 value);
|
||||||
|
inline uint16 ReadReg16(uint32 reg);
|
||||||
|
inline uint32 ReadReg32(uint32 reg);
|
||||||
|
|
||||||
//Frame list memory
|
// Functions for the actual functioning of transfers
|
||||||
area_id m_framearea;
|
status_t InsertControl(Transfer *transfer);
|
||||||
addr_t m_framelist[1024]; //The frame list struct
|
|
||||||
addr_t m_framelist_phy; //The physical pointer to the frame list
|
|
||||||
|
|
||||||
// Virtual frame
|
static pci_module_info *sPCIModule;
|
||||||
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
|
uint32 fRegisterBase;
|
||||||
Vector<Transfer *> m_transfers;
|
pci_info *fPCIInfo;
|
||||||
|
Stack *fStack;
|
||||||
|
|
||||||
//Root hub:
|
// Frame list memory
|
||||||
UHCIRootHub *m_rh; // the root hub
|
area_id fFrameArea;
|
||||||
uint8 m_rh_address; // the address of the root hub
|
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:
|
public:
|
||||||
UHCIRootHub( UHCI *uhci , int8 devicenum );
|
UHCIRootHub(UHCI *uhci, int8 deviceNum);
|
||||||
status_t SubmitTransfer( Transfer *t );
|
|
||||||
void UpdatePortStatus();
|
status_t SubmitTransfer(Transfer *transfer);
|
||||||
|
void UpdatePortStatus();
|
||||||
|
|
||||||
private:
|
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_qh *topqh;
|
||||||
uhci_td *firsttd;
|
uhci_td *firsttd;
|
||||||
uhci_td *lasttd;
|
uhci_td *lasttd;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define UHCI_DEBUG
|
|
||||||
#ifdef UHCI_DEBUG
|
|
||||||
#define TRACE dprintf
|
|
||||||
#else
|
|
||||||
#define TRACE silent
|
|
||||||
void silent( const char * , ... ) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
#define UHCI_USBSTS_HOSTERR 0x8 // Host System Error
|
#define UHCI_USBSTS_HOSTERR 0x8 // Host System Error
|
||||||
#define UHCI_USBSTS_HCPRERR 0x10// Host Controller Process error
|
#define UHCI_USBSTS_HCPRERR 0x10// Host Controller Process error
|
||||||
#define UHCI_USBSTS_HCHALT 0x20 // HCHalted
|
#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
|
//USBINTR
|
||||||
#define UHCI_USBINTR_CRC 0x1 // Timeout/ CRC interrupt enable
|
#define UHCI_USBINTR_CRC 0x1 // Timeout/ CRC interrupt enable
|
||||||
|
|||||||
@@ -1,267 +1,268 @@
|
|||||||
//------------------------------------------------------------------------------
|
/*
|
||||||
// Copyright (c) 2004, Niels S. Reedijk
|
* Copyright 2004-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 "uhci.h"
|
#include "uhci.h"
|
||||||
#include <PCI.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 =
|
usb_device_descriptor uhci_devd =
|
||||||
{
|
{
|
||||||
0x12, //Descriptor size
|
0x12, //Descriptor size
|
||||||
USB_DESCRIPTOR_DEVICE , //Type of descriptor
|
USB_DESCRIPTOR_DEVICE, //Type of descriptor
|
||||||
0x110, //USB 1.1
|
0x110, //USB 1.1
|
||||||
0x09 , //Hub type
|
0x09, //Hub type
|
||||||
0 , //Subclass
|
0, //Subclass
|
||||||
0 , //Protocol
|
0, //Protocol
|
||||||
64 , //Max packet size
|
64, //Max packet size
|
||||||
0 , //Vendor
|
0, //Vendor
|
||||||
0 , //Product
|
0, //Product
|
||||||
0x110 , //Version
|
0x110, //Version
|
||||||
1 , 2 , 0 , //Other data
|
1, 2, 0, //Other data
|
||||||
1 //Number of configurations
|
1 //Number of configurations
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
usb_configuration_descriptor uhci_confd =
|
usb_configuration_descriptor uhci_confd =
|
||||||
{
|
{
|
||||||
0x09, //Size
|
0x09, //Size
|
||||||
USB_DESCRIPTOR_CONFIGURATION ,
|
USB_DESCRIPTOR_CONFIGURATION,
|
||||||
25 , //Total size (taken from BSD source)
|
25, //Total size (taken from BSD source)
|
||||||
1 , //Number interfaces
|
1, //Number interfaces
|
||||||
1 , //Value of configuration
|
1, //Value of configuration
|
||||||
0 , //Number of configuration
|
0, //Number of configuration
|
||||||
0x40 , //Self powered
|
0x40, //Self powered
|
||||||
0 //Max power (0, because of self power)
|
0 //Max power (0, because of self power)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
usb_interface_descriptor uhci_intd =
|
usb_interface_descriptor uhci_intd =
|
||||||
{
|
{
|
||||||
0x09 , //Size
|
0x09, //Size
|
||||||
USB_DESCRIPTOR_INTERFACE ,
|
USB_DESCRIPTOR_INTERFACE,
|
||||||
0 , //Interface number
|
0, //Interface number
|
||||||
0 , //Alternate setting
|
0, //Alternate setting
|
||||||
1 , //Num endpoints
|
1, //Num endpoints
|
||||||
0x09 , //Interface class
|
0x09, //Interface class
|
||||||
0 , //Interface subclass
|
0, //Interface subclass
|
||||||
0 , //Interface protocol
|
0, //Interface protocol
|
||||||
0 , //Interface
|
0, //Interface
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
usb_endpoint_descriptor uhci_endd =
|
usb_endpoint_descriptor uhci_endd =
|
||||||
{
|
{
|
||||||
0x07 , //Size
|
0x07, //Size
|
||||||
USB_DESCRIPTOR_ENDPOINT,
|
USB_DESCRIPTOR_ENDPOINT,
|
||||||
USB_REQTYPE_DEVICE_IN | 1, //1 from freebsd driver
|
USB_REQTYPE_DEVICE_IN | 1, //1 from freebsd driver
|
||||||
0x3 , // Interrupt
|
0x3, // Interrupt
|
||||||
8 , // Max packet size
|
8, // Max packet size
|
||||||
0xFF // Interval 256
|
0xFF // Interval 256
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
usb_hub_descriptor uhci_hubd =
|
usb_hub_descriptor uhci_hubd =
|
||||||
{
|
{
|
||||||
0x09 , //Including deprecated powerctrlmask
|
0x09, //Including deprecated powerctrlmask
|
||||||
USB_DESCRIPTOR_HUB,
|
USB_DESCRIPTOR_HUB,
|
||||||
1, //Number of ports
|
1, //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
|
||||||
0x00 //Both ports are removable
|
0x00 //Both ports are removable
|
||||||
};
|
};
|
||||||
|
|
||||||
//Implementation
|
|
||||||
UHCIRootHub::UHCIRootHub( UHCI *uhci , int8 devicenum )
|
UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
|
||||||
: Hub( uhci , NULL , uhci_devd , devicenum , false )
|
: Hub(uhci, NULL, uhci_devd, devicenum, false)
|
||||||
{
|
{
|
||||||
m_uhci = uhci;
|
fUHCI = uhci;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t UHCIRootHub::SubmitTransfer( Transfer *t )
|
|
||||||
|
status_t
|
||||||
|
UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||||
{
|
{
|
||||||
status_t retval;
|
usb_request_data *request = transfer->GetRequestData();
|
||||||
usb_request_data *request = t->GetRequestData();
|
TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request));
|
||||||
uint16 port; //used in RH_CLEAR/SET_FEATURE
|
|
||||||
|
|
||||||
TRACE( "USB UHCI: rh_submit_packet called. Request: %u\n" , t->GetRequestData()->Request );
|
status_t result = B_ERROR;
|
||||||
|
switch(request->Request) {
|
||||||
switch( request->Request )
|
case RH_GET_STATUS:
|
||||||
{
|
if (request->Index == 0) {
|
||||||
case RH_GET_STATUS:
|
// Get the hub status -- everything as 0 means all-right
|
||||||
if ( request->Index == 0 )
|
memset(transfer->GetBuffer(), 0, sizeof(get_status_buffer));
|
||||||
{
|
result = B_OK;
|
||||||
//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;
|
|
||||||
break;
|
break;
|
||||||
case RH_CONFIG_DESCRIPTOR:
|
} else if (request->Index > uhci_hubd.bNbrPorts) {
|
||||||
memcpy( t->GetBuffer() , (void *)&uhci_confd , t->GetBufferLength());
|
// This port doesn't exist
|
||||||
*(t->GetActualLength()) = t->GetBufferLength();
|
result = EINVAL;
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case RH_SET_CONFIG:
|
// Get port status
|
||||||
retval = B_OK;
|
UpdatePortStatus();
|
||||||
break;
|
memcpy(transfer->GetBuffer(),
|
||||||
|
(void *)&fPortStatus[request->Index - 1],
|
||||||
|
transfer->GetBufferLength());
|
||||||
|
|
||||||
case RH_CLEAR_FEATURE:
|
*(transfer->GetActualLength()) = transfer->GetBufferLength();
|
||||||
if ( request->Index == 0 )
|
result = B_OK;
|
||||||
{
|
|
||||||
//We don't support any hub changes
|
|
||||||
TRACE( "UHCI: RH_CLEAR_FEATURE no hub changes!\n" );
|
|
||||||
retval = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
else if ( request->Index > uhci_hubd.bNbrPorts )
|
|
||||||
{
|
|
||||||
//Invalid port number
|
|
||||||
TRACE( "UHCI: RH_CLEAR_FEATURE invalid port!\n" );
|
|
||||||
retval = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("UHCI: RH_CLEAR_FEATURE called. Feature: %u!\n" , request->Value );
|
case RH_SET_ADDRESS:
|
||||||
switch( request->Value )
|
if (request->Value >= 128) {
|
||||||
{
|
result = EINVAL;
|
||||||
case PORT_RESET:
|
break;
|
||||||
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 );
|
TRACE(("usb_uhci_roothub: rh_submit_packet RH_ADDRESS: %d\n", request->Value));
|
||||||
UHCI::pci_module->write_io_16( m_uhci->m_reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 , port );
|
result = B_OK;
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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:
|
default:
|
||||||
retval = EINVAL;
|
result = EINVAL;
|
||||||
break;
|
break;
|
||||||
} //switch( t->value)
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
retval = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up the transfer - we own it, so we clean it up
|
// Clean up the transfer - we own it, so we clean it up
|
||||||
t->Finish();
|
transfer->Finish();
|
||||||
delete t;
|
delete transfer;
|
||||||
|
return result;
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UHCIRootHub::UpdatePortStatus(void)
|
|
||||||
|
void
|
||||||
|
UHCIRootHub::UpdatePortStatus()
|
||||||
{
|
{
|
||||||
int i;
|
for (int32 i = 0; i < 2; i++) {
|
||||||
for ( i = 0; i <= 1 ; i++ )
|
uint16 newStatus = 0;
|
||||||
{
|
uint16 newChange = 0;
|
||||||
uint16 newstatus = 0;
|
|
||||||
uint16 newchange = 0;
|
|
||||||
|
|
||||||
uint16 portsc = UHCI::pci_module->read_io_16( m_uhci->m_reg_base + UHCI_PORTSC1 + i * 2 );
|
uint16 portStatus = UHCI::sPCIModule->read_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + i * 2);
|
||||||
dprintf( "USB UHCI: port: %x status: 0x%x\n" , UHCI_PORTSC1 + i * 2 , portsc );
|
TRACE(("usb_uhci_roothub: port: %d status: 0x%04x\n", UHCI_PORTSC1 + i * 2, portStatus));
|
||||||
//Set all individual bits
|
|
||||||
if ( portsc & UHCI_PORTSC_CURSTAT )
|
|
||||||
newstatus |= PORT_STATUS_CONNECTION;
|
|
||||||
|
|
||||||
if ( portsc & UHCI_PORTSC_STATCHA )
|
// Set all individual bits
|
||||||
newchange |= PORT_STATUS_CONNECTION;
|
if (portStatus & UHCI_PORTSC_CURSTAT)
|
||||||
|
newStatus |= PORT_STATUS_CONNECTION;
|
||||||
|
|
||||||
if ( portsc & UHCI_PORTSC_ENABLED )
|
if (portStatus & UHCI_PORTSC_STATCHA)
|
||||||
newstatus |= PORT_STATUS_ENABLE;
|
newStatus |= PORT_STATUS_CONNECTION;
|
||||||
|
|
||||||
if ( portsc & UHCI_PORTSC_ENABCHA )
|
if (portStatus & UHCI_PORTSC_ENABLED)
|
||||||
newchange |= PORT_STATUS_ENABLE;
|
newStatus |= PORT_STATUS_ENABLE;
|
||||||
|
|
||||||
|
if (portStatus & UHCI_PORTSC_ENABCHA)
|
||||||
|
newStatus |= PORT_STATUS_ENABLE;
|
||||||
|
|
||||||
// TODO: work out suspended/resume
|
// TODO: work out suspended/resume
|
||||||
|
|
||||||
if ( portsc & UHCI_PORTSC_RESET )
|
if (portStatus & UHCI_PORTSC_RESET)
|
||||||
newstatus |= PORT_STATUS_RESET;
|
newStatus |= PORT_STATUS_RESET;
|
||||||
|
|
||||||
//TODO: work out reset change...
|
//TODO: work out reset change...
|
||||||
|
|
||||||
//The port is automagically powered on
|
//The port is automagically powered on
|
||||||
newstatus |= PORT_POWER;
|
newStatus |= PORT_POWER;
|
||||||
|
|
||||||
if ( portsc & UHCI_PORTSC_LOWSPEED )
|
if (portStatus & UHCI_PORTSC_LOWSPEED)
|
||||||
newstatus |= PORT_STATUS_LOW_SPEED;
|
newStatus |= PORT_STATUS_LOW_SPEED;
|
||||||
|
|
||||||
//Update the stored port status
|
//Update the stored port status
|
||||||
m_hw_port_status[i].status = newstatus;
|
fPortStatus[i].status = newStatus;
|
||||||
m_hw_port_status[i].change = newchange;
|
fPortStatus[i].change = newChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user