* [email protected]/usb-busses--development--0.1--patch-1

Fix things up before big changes
 * [email protected]/usb-busses--development--0.1--patch-2
   Continued development on device initialisation
 * [email protected]/usb-busses--development--0.1--patch-3
   Finished Driver initialisation


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5831 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Niels Sascha Reedijk
2003-12-30 14:53:24 +00:00
parent f2777ca181
commit 07b15fef0c
4 changed files with 273 additions and 29 deletions
-3
View File
@@ -4,6 +4,3 @@ R5KernelAddon uhci : [ FDirName kernel busses usb ] :
uhci.c
;
R5KernelAddon ehci : [ FDirName kernel busses usb ] :
ehci.c
;
@@ -0,0 +1,36 @@
#ifndef HOST_CONTROLLER_INFO_H
#define HOST_CONTROLLER_INFO_H
/* ++++++++++
Internally used types
++++++++++ */
//This embodies a request that can be send
typedef struct
{
uint8 RequestType;
uint8 Request;
uint16 Value;
uint16 Index;
uint16 Length;
} usb_request_data;
// Describes the internal organs of an usb packet
typedef struct usb_packet_t
{
uint16 pipe;
uint8 *requestdata;
uint8 *buffer;
int16 bufferlength;
size_t *actual_length;
int16 address; //!!!! TEMPORARY ... or is it?
} usb_packet_t;
typedef struct host_controller_info
{
module_info info;
status_t (*hwstart)(void);
status_t (*SubmitPacket)(usb_packet_t *);
} host_controller_info;
#endif //HOST_CONTROLLER_INFO_H
+199 -26
View File
@@ -21,8 +21,12 @@
#include <module.h>
#include <PCI.h>
#include <USB.h>
#include <KernelExport.h>
#include <stdlib.h>
#include "uhci.h"
#include "host_controller.h"
#define UHCI_DEBUG
#ifdef UHCI_DEBUG
@@ -33,8 +37,9 @@ void silent( const char * , ... ) {}
#endif
static status_t init_hardware();
static status_t init_hardware(void);
static status_t submit_packet( usb_packet_t *packet );
static status_t rh_submit_packet( usb_packet_t *packet );
/* ++++++++++
This is the implementation of the UHCI controller for the OpenBeOS USB stack
@@ -56,15 +61,20 @@ uhci_std_ops( int32 op , ... )
return B_OK;
}
struct module_info uhci_module = {
"busses/usb/uhci/nielx",
NULL, // No flag like B_KEEP_LOADED : the usb module does that
uhci_std_ops
host_controller_info uhci_module = {
{
"busses/usb/uhci/nielx",
NULL, // No flag like B_KEEP_LOADED : the usb module does that
uhci_std_ops
},
NULL ,
submit_packet
};
module_info *modules[] = {
(module_info *)&uhci_module ,
NULL
module_info *modules[] =
{
(module_info *) &uhci_module,
NULL
};
/* ++++++++++
@@ -74,6 +84,14 @@ typedef struct uhci_properties
{
uint32 reg_base; //Base address of the registers
pci_info *pcii; //pci-info struct
//Frame list memory
area_id framearea;
void *framelist[1024]; //The frame list struct
void *framelist_phy; //The physical pointer to the frame list
//Root hub:
uint8 rh_address; // the address of the root hub
} uhci_properties_t;
static pci_module_info *m_pcimodule = 0;
@@ -81,23 +99,32 @@ static pci_info *m_device = 0;
static uhci_properties_t*m_data = 0;
/* ++++++++++
Register/Bit constants
Utility functions
++++++++++ */
enum {
USBCMD = 0x0 //Command register (2byte)
};
static void
uhci_globalreset( uhci_properties_t *data )
{
m_pcimodule->write_io_16( data->reg_base + UHCI_USBCMD , UHCI_USBCMD_GRESET );
spin( 100 );
m_pcimodule->write_io_16( data->reg_base + UHCI_USBCMD , 0 );
}
enum USBCMD_commands {
RS = 0x1 , //Run=1 Stop=0
HCRESET = 0x2 //Host controller reset
};
static status_t
uhci_reset( uhci_properties_t *data )
{
m_pcimodule->write_io_16( data->reg_base + UHCI_USBCMD , UHCI_USBCMD_HCRESET );
spin( 100 );
if ( m_pcimodule->read_io_16( data->reg_base + UHCI_USBCMD ) & UHCI_USBCMD_HCRESET )
return B_ERROR;
return B_OK;
}
/* ++++++++++
The hardware management functions
++++++++++ */
static status_t
init_hardware()
init_hardware(void)
{
status_t status;
pci_info *item;
@@ -106,10 +133,12 @@ init_hardware()
// Try if the PCI module is loaded (it would be weird if it wouldn't, but alas)
if( ( status = get_module( B_PCI_MODULE_NAME, (module_info **)&m_pcimodule )) != B_OK)
{
TRACE( "uhci_nielx init_hardware(): Get PCI module failed! %lu \n", status);
TRACE( "USB_ UHCI: init_hardware(): Get PCI module failed! %lu \n", status);
return status;
}
TRACE( "usb_uhci init_hardware(): Setting up hardware\n" );
// TODO: in the future we might want to support multiple host controllers.
item = (pci_info *)malloc( sizeof( pci_info ) );
for ( i = 0 ; m_pcimodule->get_nth_pci_info( i , item ) == B_OK ; i++ )
@@ -120,10 +149,10 @@ init_hardware()
{
if ((item->u.h0.interrupt_line == 0) || (item->u.h0.interrupt_line == 0xFF))
{
TRACE( "uhci_nielx init_hardware(): found with invalid IRQ - check IRQ assignement\n");
TRACE( "USB UHCI: init_hardware(): found with invalid IRQ - check IRQ assignement\n");
continue;
}
TRACE("uhci_nielx init_hardware(): found at IRQ %u \n", item->u.h0.interrupt_line);
TRACE("USB UHCI: init_hardware(): found at IRQ %u \n", item->u.h0.interrupt_line);
m_device = item;
break;
}
@@ -131,7 +160,8 @@ init_hardware()
if ( m_device == 0 )
{
TRACE( "uhci_nielx init hardware(): no devices found\n" );
TRACE( "USB UHCI: init hardware(): no devices found\n" );
free( item );
put_module( B_PCI_MODULE_NAME );
return ENODEV;
}
@@ -140,7 +170,7 @@ init_hardware()
m_data = (uhci_properties_t *)malloc( sizeof( uhci_properties_t ) );
m_data->pcii = m_device;
m_data->reg_base = m_device->u.h0.base_registers[0];
m_data->rh_address = 255; //Invalidate the RH address
{
/* enable pci address access */
unsigned char cmd;
@@ -150,8 +180,151 @@ init_hardware()
}
//Do a host reset
// m_pcimodule->write_io_16( m_data->reg_base + UHCI_USBCMD , UHCI_USBCMD_HCRESET );
// spin(50);
uhci_globalreset( m_data );
if ( uhci_reset( m_data ) == B_ERROR )
{
TRACE( "USB UHCI: init_hardare(): host failed to reset\n" );
free( item );
put_module( B_PCI_MODULE_NAME );
return ENODEV;
}
//Set up the frame list
m_data->framearea = map_physical_memory( "uhci framelist" , m_data->framelist_phy ,
4096 , B_ANY_KERNEL_BLOCK_ADDRESS ,
B_WRITE_AREA , m_data->framelist );
//!!!!!!!!!!!!!! Check the area
//This is enough for now, the most time consuming hardware tasks have been done now
return B_OK;
}
/* ++++++++++
Inserting packets in the queue
++++++++++ */
status_t submit_packet( usb_packet_t *packet )
{
dprintf( "uhci submit_packet(): CALLED\n");
//Do the following:
//1. Check if the packet really belongs to this bus -- no way of doing that now
//2. Acquire the spinlock of the packet -- still needs to be fixed
if ( packet->address == 0 ) //First device of a bus has address 0 per definition
{
rh_submit_packet( packet );
goto out;
}
//4. Determine the type of transfer and send it to the proper function
//5. Release the spinlock
out:
}
/* ++++++++++
Root hub emulation
++++++++++ */
usb_device_descriptor uhci_devd =
{
0x12, //Descriptor size
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
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
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
};
usb_endpoint_descriptor uhci_endd =
{
0x07 , //Size
USB_DESCRIPTOR_ENDPOINT,
USB_REQTYPE_DEVICE_IN | 1, //1 from freebsd driver
0x3 , // Interrupt
8 , // Max packet size
0xFF // Interval
};
status_t rh_submit_packet( usb_packet_t *packet )
{
usb_request_data *request = (usb_request_data *)packet->requestdata;
status_t retval;
TRACE( "USB UHCI: rh_submit_packet called\n" );
switch( request->Request )
{
case RH_SET_ADDRESS:
if ( request->Value >= 128 )
{
retval = EINVAL;
break;
}
TRACE( "USB UHCI: rh_submit_packet RH_ADDRESS: %d\n" , request->Value );
m_data->rh_address = 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( packet->buffer , (void *)&uhci_devd , packet->bufferlength );
*(packet->actual_length) = packet->bufferlength;
retval = B_OK;
break;
case RH_CONFIG_DESCRIPTOR:
memcpy( packet->buffer , (void *)&uhci_confd , packet->bufferlength );
*(packet->actual_length) = packet->bufferlength;
retval = B_OK;
break;
case RH_SET_CONFIG:
retval = B_OK;
break;
default:
retval = EINVAL;
break;
}
break;
}
default:
retval = EINVAL;
break;
}
return retval;
}
+38
View File
@@ -22,6 +22,11 @@
#ifndef UHCI_H
#define UHCI_H
/************************************************************
* The Registers *
************************************************************/
// R/W -- Read/Write
// R/WC -- Read/Write Clear
// ** -- Only writable with words!
@@ -65,4 +70,37 @@
#define UHCI_PORTSC_STATCHA 0x2 // Current connect status change
#define UHCI_PORTSC_ENABLED 0x4 // Port enabled/disabled
/************************************************************
* Hardware structs *
************************************************************/
//Represents a Transfer Descriptor (TD)
struct uhci_td
{
void * link; // Link to the next TD/QH
uint32 status; // Status field
uint32 token; // Contains the packet header (where it needs to be sent)
void * buffer; // A pointer to the buffer with the actual packet
};
//Represents a Queue Head (QH)
struct uhci_qh
{
void * link; //Link to the next TD/QH
void * element; //Link to the first element pointer in the queue
};
/************************************************************
* Roothub Emulation *
************************************************************/
#define RH_GET_DESCRIPTOR 6
#define RH_SET_ADDRESS 5
#define RH_SET_CONFIG 9
//Descriptors (in usb_request_data->Value)
#define RH_DEVICE_DESCRIPTOR ( 1 << 8 )
#define RH_CONFIG_DESCRIPTOR ( 2 << 8 )
#endif