Summary: Several changes to the root hub managing code
Keywords: Patches applied: * [email protected]/usb-busses--development--0.1--patch-4 Commit because of switch of development machines * [email protected]/usb-busses--development--0.1--patch-5 Support for hub descriptors * [email protected]/usb-busses--development--0.1--patch-6 Some more hub-management code git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7192 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
SubDir OBOS_TOP src add-ons kernel busses usb ;
|
SubDir OBOS_TOP src add-ons kernel busses usb ;
|
||||||
|
|
||||||
|
AddResources uhci : uhci.rdef ;
|
||||||
|
|
||||||
R5KernelAddon uhci : [ FDirName kernel busses usb ] :
|
R5KernelAddon uhci : [ FDirName kernel busses usb ] :
|
||||||
uhci.c
|
uhci.c
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,6 +1,55 @@
|
|||||||
#ifndef HOST_CONTROLLER_INFO_H
|
#ifndef HOST_CONTROLLER_INFO_H
|
||||||
#define HOST_CONTROLLER_INFO_H
|
#define HOST_CONTROLLER_INFO_H
|
||||||
|
|
||||||
|
/* +++++++++
|
||||||
|
USB Spec definitions (not interesting for the outside world
|
||||||
|
+++++++++ */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8 bDescLength;
|
||||||
|
uint8 bDescriptorType;
|
||||||
|
uint8 bNbrPorts;
|
||||||
|
uint16 wHubCharacteristics;
|
||||||
|
uint8 bPwrOn2PwrGood;
|
||||||
|
uint8 bHucContrCurrent;
|
||||||
|
uint8 DeviceRemovable; //Should be variable!!!
|
||||||
|
uint8 PortPwrCtrlMask; //Deprecated
|
||||||
|
} usb_hub_descriptor;
|
||||||
|
|
||||||
|
#define USB_DESCRIPTOR_HUB 0x29
|
||||||
|
|
||||||
|
// USB Spec 1.1 page 273
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16 status;
|
||||||
|
uint16 change;
|
||||||
|
} usb_port_status;
|
||||||
|
|
||||||
|
//The bits in the usb_port_status struct
|
||||||
|
// USB 1.1 spec page 274
|
||||||
|
#define PORT_STATUS_CONNECTION 0x1
|
||||||
|
#define PORT_STATUS_ENABLE 0x2
|
||||||
|
#define PORT_STATUS_SUSPEND 0x4
|
||||||
|
#define PORT_STATUS_OVER_CURRENT 0x8
|
||||||
|
#define PORT_STATUS_RESET 0x10
|
||||||
|
#define PORT_STATUS_POWER 0x100
|
||||||
|
#define PORT_STATUS_LOW_SPEED 0x200
|
||||||
|
|
||||||
|
//The feature requests with ports
|
||||||
|
// USB 1.1 spec page 268
|
||||||
|
#define PORT_CONNECTION 0
|
||||||
|
#define PORT_ENABLE 1
|
||||||
|
#define PORT_SUSPEND 2
|
||||||
|
#define PORT_OVER_CURRENT 3
|
||||||
|
#define PORT_RESET 4
|
||||||
|
#define PORT_POWER 8
|
||||||
|
#define PORT_LOW_SPEED 9
|
||||||
|
#define C_PORT_CONNECTION 16
|
||||||
|
#define C_PORT_ENABLE 17
|
||||||
|
#define C_PORT_SUSPEND 18
|
||||||
|
#define C_PORT_OVER_CURRENT 19
|
||||||
|
#define C_PORT_RESET 20
|
||||||
|
|
||||||
/* ++++++++++
|
/* ++++++++++
|
||||||
Internally used types
|
Internally used types
|
||||||
++++++++++ */
|
++++++++++ */
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ void silent( const char * , ... ) {}
|
|||||||
static status_t init_hardware(void);
|
static status_t init_hardware(void);
|
||||||
static status_t submit_packet( usb_packet_t *packet );
|
static status_t submit_packet( usb_packet_t *packet );
|
||||||
static status_t rh_submit_packet( usb_packet_t *packet );
|
static status_t rh_submit_packet( usb_packet_t *packet );
|
||||||
|
static void rh_update_port_status(void);
|
||||||
|
//static int32 uhci_interrupt( void *d );
|
||||||
|
|
||||||
/* ++++++++++
|
/* ++++++++++
|
||||||
This is the implementation of the UHCI controller for the OpenBeOS USB stack
|
This is the implementation of the UHCI controller for the OpenBeOS USB stack
|
||||||
@@ -92,6 +94,7 @@ typedef struct uhci_properties
|
|||||||
|
|
||||||
//Root hub:
|
//Root hub:
|
||||||
uint8 rh_address; // the address of the root hub
|
uint8 rh_address; // the address of the root hub
|
||||||
|
usb_port_status port_status[2]; // the port status (maximum of two)
|
||||||
} uhci_properties_t;
|
} uhci_properties_t;
|
||||||
|
|
||||||
static pci_module_info *m_pcimodule = 0;
|
static pci_module_info *m_pcimodule = 0;
|
||||||
@@ -189,12 +192,23 @@ init_hardware(void)
|
|||||||
return ENODEV;
|
return ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Poll the status of the two ports
|
||||||
|
rh_update_port_status();
|
||||||
|
TRACE( "USB UHCI: init_hardware(): port1: %x port2: %x\n",
|
||||||
|
m_data->port_status[0].status , m_data->port_status[1].status );
|
||||||
|
|
||||||
//Set up the frame list
|
//Set up the frame list
|
||||||
m_data->framearea = map_physical_memory( "uhci framelist" , m_data->framelist_phy ,
|
/*m_data->framearea = map_physical_memory( "uhci framelist" , m_data->framelist_phy ,
|
||||||
4096 , B_ANY_KERNEL_BLOCK_ADDRESS ,
|
4096 , B_ANY_KERNEL_BLOCK_ADDRESS ,
|
||||||
B_WRITE_AREA , m_data->framelist );
|
B_WRITE_AREA , m_data->framelist );
|
||||||
|
|
||||||
//!!!!!!!!!!!!!! Check the area
|
//!!!!!!!!!!!!!! Check the area
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Install the interrupt handler
|
||||||
|
//install_io_interrupt_handler( m_data->pcii->h0.interrupt_line ,
|
||||||
|
// uhci_interrupt , m_data , NULL );
|
||||||
|
//m_pcimodule->write_io_16( m_data->reg_base + USBINTR ,
|
||||||
|
|
||||||
//This is enough for now, the most time consuming hardware tasks have been done now
|
//This is enough for now, the most time consuming hardware tasks have been done now
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -271,20 +285,53 @@ usb_endpoint_descriptor uhci_endd =
|
|||||||
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
|
0xFF // Interval 256
|
||||||
};
|
};
|
||||||
|
|
||||||
|
usb_hub_descriptor uhci_hubd =
|
||||||
|
{
|
||||||
|
0x09 , //Including deprecated powerctrlmask
|
||||||
|
USB_DESCRIPTOR_HUB,
|
||||||
|
1, //Number of ports
|
||||||
|
0x02 | 0x01 , //Hub characteristics FIXME
|
||||||
|
50 , //Power on to power good
|
||||||
|
0, // Current
|
||||||
|
0x00 //Both ports are removable
|
||||||
|
};
|
||||||
|
|
||||||
|
status_t
|
||||||
status_t rh_submit_packet( usb_packet_t *packet )
|
rh_submit_packet( usb_packet_t *packet )
|
||||||
{
|
{
|
||||||
usb_request_data *request = (usb_request_data *)packet->requestdata;
|
usb_request_data *request = (usb_request_data *)packet->requestdata;
|
||||||
status_t retval;
|
status_t retval;
|
||||||
|
|
||||||
TRACE( "USB UHCI: rh_submit_packet called\n" );
|
uint16 port; //used in RH_CLEAR/SET_FEATURE
|
||||||
|
|
||||||
|
TRACE( "USB UHCI: rh_submit_packet called. Request: %u\n" , request->Request );
|
||||||
|
|
||||||
switch( request->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( packet->buffer , 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
|
||||||
|
rh_update_port_status();
|
||||||
|
memcpy( packet->buffer , (void *)&(m_data->port_status[request->Index - 1]) , packet->bufferlength );
|
||||||
|
*(packet->actual_length) = packet->bufferlength;
|
||||||
|
retval = B_OK;
|
||||||
|
break;
|
||||||
|
|
||||||
case RH_SET_ADDRESS:
|
case RH_SET_ADDRESS:
|
||||||
if ( request->Value >= 128 )
|
if ( request->Value >= 128 )
|
||||||
{
|
{
|
||||||
@@ -295,6 +342,7 @@ status_t rh_submit_packet( usb_packet_t *packet )
|
|||||||
m_data->rh_address = request->Value;
|
m_data->rh_address = request->Value;
|
||||||
retval = B_OK;
|
retval = B_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RH_GET_DESCRIPTOR:
|
case RH_GET_DESCRIPTOR:
|
||||||
{
|
{
|
||||||
TRACE( "USB UHCI: rh_submit_packet GET_DESC: %d\n" , request->Value );
|
TRACE( "USB UHCI: rh_submit_packet GET_DESC: %d\n" , request->Value );
|
||||||
@@ -310,7 +358,19 @@ status_t rh_submit_packet( usb_packet_t *packet )
|
|||||||
*(packet->actual_length) = packet->bufferlength;
|
*(packet->actual_length) = packet->bufferlength;
|
||||||
retval = B_OK;
|
retval = B_OK;
|
||||||
break;
|
break;
|
||||||
case RH_SET_CONFIG:
|
case RH_INTERFACE_DESCRIPTOR:
|
||||||
|
memcpy( packet->buffer , (void *)&uhci_intd , packet->bufferlength );
|
||||||
|
*(packet->actual_length) = packet->bufferlength;
|
||||||
|
retval = B_OK ;
|
||||||
|
break;
|
||||||
|
case RH_ENDPOINT_DESCRIPTOR:
|
||||||
|
memcpy( packet->buffer , (void *)&uhci_endd , packet->bufferlength );
|
||||||
|
*(packet->actual_length) = packet->bufferlength;
|
||||||
|
retval = B_OK ;
|
||||||
|
break;
|
||||||
|
case RH_HUB_DESCRIPTOR:
|
||||||
|
memcpy( packet->buffer , (void *)&uhci_hubd , packet->bufferlength );
|
||||||
|
*(packet->actual_length) = packet->bufferlength;
|
||||||
retval = B_OK;
|
retval = B_OK;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -319,6 +379,44 @@ status_t rh_submit_packet( usb_packet_t *packet )
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case RH_SET_CONFIG:
|
||||||
|
retval = B_OK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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 );
|
||||||
|
switch( request->Value )
|
||||||
|
{
|
||||||
|
case C_PORT_CONNECTION:
|
||||||
|
port = m_pcimodule->read_io_16( m_data->reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 );
|
||||||
|
port = port & UHCI_PORTSC_DATAMASK;
|
||||||
|
port |= UHCI_PORTSC_STATCHA;
|
||||||
|
TRACE( "UHCI rh: port: %x\n" , port );
|
||||||
|
m_pcimodule->write_io_16( m_data->reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 , port );
|
||||||
|
retval = B_OK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
retval = EINVAL;
|
||||||
|
break;
|
||||||
|
} //switch( packet->value)
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
retval = EINVAL;
|
retval = EINVAL;
|
||||||
break;
|
break;
|
||||||
@@ -327,4 +425,45 @@ status_t rh_submit_packet( usb_packet_t *packet )
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rh_update_port_status(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for ( i = 0; i <= 1 ; i++ )
|
||||||
|
{
|
||||||
|
uint16 newstatus = 0;
|
||||||
|
uint16 newchange = 0;
|
||||||
|
|
||||||
|
uint16 portsc = m_pcimodule->read_io_16( m_data->reg_base + UHCI_PORTSC1 + i * 2 );
|
||||||
|
dprintf( "USB UHCI: port status: 0x%x\n" , 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;
|
||||||
|
|
||||||
|
// TODO: work out suspended/resume
|
||||||
|
|
||||||
|
if ( portsc & 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_LOW_SPEED;
|
||||||
|
|
||||||
|
//Update the stored port status
|
||||||
|
m_data->port_status[i].status = newstatus;
|
||||||
|
m_data->port_status[i].change = newchange;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,9 +66,18 @@
|
|||||||
#define UHCI_USBINTR_SHORT 0x8 // Short packet interrupt enable
|
#define UHCI_USBINTR_SHORT 0x8 // Short packet interrupt enable
|
||||||
|
|
||||||
//PORTSC
|
//PORTSC
|
||||||
#define UHCI_PORTSC_CURSTAT 0x1 // Current connect status
|
#define UHCI_PORTSC_CURSTAT 0x1 // Current connect status
|
||||||
#define UHCI_PORTSC_STATCHA 0x2 // Current connect status change
|
#define UHCI_PORTSC_STATCHA 0x2 // Current connect status change
|
||||||
#define UHCI_PORTSC_ENABLED 0x4 // Port enabled/disabled
|
#define UHCI_PORTSC_ENABLED 0x4 // Port enabled/disabled
|
||||||
|
#define UHCI_PORTSC_ENABCHA 0x8 // Change in enabled/disabled
|
||||||
|
#define UHCI_PORTSC_LINE_0 0x10 // The status of D+ /D-
|
||||||
|
#define UHCI_PORTSC_LINE_1 0x20
|
||||||
|
#define UHCI_PORTSC_RESUME 0x40 // Something with the suspend state ???
|
||||||
|
#define UHCI_PORTSC_LOWSPEED 0x100// Low speed device attached?
|
||||||
|
#define UHCI_PORTSC_RESET 0x200// Port is in reset
|
||||||
|
#define UHCI_PORTSC_SUSPEND 0x1000//Set port in suspend state
|
||||||
|
|
||||||
|
#define UHCI_PORTSC_DATAMASK 0x13F5 //Mask that excludes the change bits of portsc
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Hardware structs *
|
* Hardware structs *
|
||||||
@@ -95,12 +104,25 @@ struct uhci_qh
|
|||||||
/************************************************************
|
/************************************************************
|
||||||
* Roothub Emulation *
|
* Roothub Emulation *
|
||||||
************************************************************/
|
************************************************************/
|
||||||
#define RH_GET_DESCRIPTOR 6
|
#define RH_GET_STATUS 0
|
||||||
|
#define RH_CLEAR_FEATURE 1
|
||||||
|
#define RH_SET_FEATURE 3
|
||||||
#define RH_SET_ADDRESS 5
|
#define RH_SET_ADDRESS 5
|
||||||
|
#define RH_GET_DESCRIPTOR 6
|
||||||
#define RH_SET_CONFIG 9
|
#define RH_SET_CONFIG 9
|
||||||
|
|
||||||
//Descriptors (in usb_request_data->Value)
|
//Descriptors (in usb_request_data->Value)
|
||||||
#define RH_DEVICE_DESCRIPTOR ( 1 << 8 )
|
#define RH_DEVICE_DESCRIPTOR ( 1 << 8 )
|
||||||
#define RH_CONFIG_DESCRIPTOR ( 2 << 8 )
|
#define RH_CONFIG_DESCRIPTOR ( 2 << 8 )
|
||||||
|
#define RH_INTERFACE_DESCRIPTOR ( 4 << 8 )
|
||||||
|
#define RH_ENDPOINT_DESCRIPTOR ( 5 << 8 )
|
||||||
|
#define RH_HUB_DESCRIPTOR ( 0x29 << 8 )
|
||||||
|
|
||||||
|
//Hub/Portstatus buffer
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16 status;
|
||||||
|
uint16 change;
|
||||||
|
} get_status_buffer;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user