Summary: Merge with development branch

Patches applied:

 * n.reedijk@planet.nl--nielx-2003/usb-busses--development--0.1--patch-7
   Created memory area for the framelist

 * n.reedijk@planet.nl--nielx-2003/usb-busses--development--0.1--patch-8
   Fix the iobase offset, so that the thing actually is correct

 * n.reedijk@planet.nl--nielx-2003/usb-busses--development--0.1--patch-9
   Device Address 0 is reserved. 1 is the one for root hub

 * n.reedijk@planet.nl--nielx-2003/usb-busses--development--0.1--patch-10
   Changed packet to transfer

 * n.reedijk@planet.nl--nielx-2003/usb-busses--development--0.1--patch-11
   Merge with Axels changes


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7669 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Niels Sascha Reedijk 2004-05-28 07:50:37 +00:00
parent 0f6609e85c
commit e3964db291
5 changed files with 232 additions and 40 deletions

View File

@ -4,5 +4,6 @@ AddResources uhci : uhci.rdef ;
R5KernelAddon uhci : [ FDirName kernel busses usb ] :
uhci.c
util.c
;

View File

@ -64,22 +64,41 @@ typedef struct
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;
// Describes the internals of a pipe
enum Direction { In , Out , Default };
enum Speed { LowSpeed , NormalSpeed };
typedef struct usb_pipe_t
{
enum Direction direction;
enum Speed speed;
int8 deviceid;
uint8 endpoint;
} usb_pipe_t;
// Describes the internal organs of an usb packet
typedef struct usb_transfer_t
{
//Data that is related to the transfer
usb_pipe_t *pipe;
uint8 *buffer;
size_t bufferlength;
size_t *actual_length;
bigtime_t timeout;
status_t status;
//For control transfers
usb_request_data *request;
} usb_transfer_t;
//
//
typedef struct host_controller_info
{
module_info info;
status_t (*hwstart)(void);
status_t (*SubmitPacket)(usb_packet_t *);
status_t (*SubmitPacket)(usb_transfer_t *);
} host_controller_info;
#endif //HOST_CONTROLLER_INFO_H

View File

@ -26,6 +26,7 @@
#include <stdlib.h>
#include "uhci.h"
#include "util.h"
#include "host_controller.h"
#define UHCI_DEBUG
@ -38,8 +39,8 @@ void silent( const char * , ... ) {}
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 );
static status_t submit_packet( usb_transfer_t *transfer );
static status_t rh_submit_packet( usb_transfer_t *transfer );
static void rh_update_port_status(void);
//static int32 uhci_interrupt( void *d );
@ -172,7 +173,8 @@ init_hardware(void)
//Initialise the host controller
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->reg_base = m_pcimodule->read_pci_config(m_data->pcii->bus, m_data->pcii->device, m_data->pcii->function, 0x20 , 4 ) ^ 1;
TRACE( "USB UHCI: iospace offset: %lx\n" , m_data->reg_base );
m_data->rh_address = 255; //Invalidate the RH address
{
/* enable pci address access */
@ -198,12 +200,22 @@ init_hardware(void)
m_data->port_status[0].status , m_data->port_status[1].status );
//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 );
m_data->framearea = alloc_mem( &(m_data->framelist[0]) , &(m_data->framelist_phy) ,
4096 , "uhci framelist" );
if ( m_data->framearea < B_OK )
{
TRACE( "USB UHCI: init_hardware(): unable to create an area for the frame pointer list\n" );
free( item );
put_module( B_PCI_MODULE_NAME );
return ENODEV;
}
//!!!!!!!!!!!!!! Check the area
*/
//Make all frame list entries invalid
for( i = 0 ; i < 1024 ; i++ )
(int32)(m_data->framelist[i]) = 0x1;
//Set base pointer
m_pcimodule->write_io_32( m_data->reg_base + UHCI_FRBASEADD , (int32)(m_data->framelist_phy) );
// Install the interrupt handler
//install_io_interrupt_handler( m_data->pcii->h0.interrupt_line ,
@ -215,23 +227,24 @@ init_hardware(void)
}
/* ++++++++++
Inserting packets in the queue
Inserting transfers in the queue
++++++++++ */
status_t submit_packet( usb_packet_t *packet )
status_t submit_packet( usb_transfer_t *transfer )
{
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
if ( transfer->pipe->deviceid == 1 ) //First device of a bus has address 1 per definition
{
rh_submit_packet( packet );
rh_submit_packet( transfer );
goto out;
}
//4. Determine the type of transfer and send it to the proper function
//5. Release the spinlock
out:
return B_OK;
}
/* ++++++++++
@ -300,9 +313,9 @@ usb_hub_descriptor uhci_hubd =
};
status_t
rh_submit_packet( usb_packet_t *packet )
rh_submit_packet( usb_transfer_t *transfer )
{
usb_request_data *request = (usb_request_data *)packet->requestdata;
usb_request_data *request = transfer->request;
status_t retval;
uint16 port; //used in RH_CLEAR/SET_FEATURE
@ -315,7 +328,7 @@ rh_submit_packet( usb_packet_t *packet )
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) );
memset( transfer->buffer , NULL , sizeof(get_status_buffer) );
retval = B_OK;
break;
}
@ -327,8 +340,8 @@ rh_submit_packet( usb_packet_t *packet )
}
//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;
memcpy( transfer->buffer , (void *)&(m_data->port_status[request->Index - 1]) , transfer->bufferlength );
*(transfer->actual_length) = transfer->bufferlength;
retval = B_OK;
break;
@ -349,28 +362,28 @@ rh_submit_packet( usb_packet_t *packet )
switch ( request->Value )
{
case RH_DEVICE_DESCRIPTOR:
memcpy( packet->buffer , (void *)&uhci_devd , packet->bufferlength );
*(packet->actual_length) = packet->bufferlength;
memcpy( transfer->buffer , (void *)&uhci_devd , transfer->bufferlength );
*(transfer->actual_length) = transfer->bufferlength;
retval = B_OK;
break;
case RH_CONFIG_DESCRIPTOR:
memcpy( packet->buffer , (void *)&uhci_confd , packet->bufferlength );
*(packet->actual_length) = packet->bufferlength;
memcpy( transfer->buffer , (void *)&uhci_confd , transfer->bufferlength );
*(transfer->actual_length) = transfer->bufferlength;
retval = B_OK;
break;
case RH_INTERFACE_DESCRIPTOR:
memcpy( packet->buffer , (void *)&uhci_intd , packet->bufferlength );
*(packet->actual_length) = packet->bufferlength;
memcpy( transfer->buffer , (void *)&uhci_intd , transfer->bufferlength );
*(transfer->actual_length) = transfer->bufferlength;
retval = B_OK ;
break;
case RH_ENDPOINT_DESCRIPTOR:
memcpy( packet->buffer , (void *)&uhci_endd , packet->bufferlength );
*(packet->actual_length) = packet->bufferlength;
memcpy( transfer->buffer , (void *)&uhci_endd , transfer->bufferlength );
*(transfer->actual_length) = transfer->bufferlength;
retval = B_OK ;
break;
case RH_HUB_DESCRIPTOR:
memcpy( packet->buffer , (void *)&uhci_hubd , packet->bufferlength );
*(packet->actual_length) = packet->bufferlength;
memcpy( transfer->buffer , (void *)&uhci_hubd , transfer->bufferlength );
*(transfer->actual_length) = transfer->bufferlength;
retval = B_OK;
break;
default:
@ -403,6 +416,11 @@ rh_submit_packet( usb_packet_t *packet )
TRACE("UHCI: RH_CLEAR_FEATURE called. Feature: %u!\n" , request->Value );
switch( request->Value )
{
case PORT_RESET:
port = m_pcimodule->read_io_16( m_data->reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 );
port &= ~UHCI_PORTSC_RESET;
TRACE( "UHCI rh: port %x Clear RESET\n" , port );
m_pcimodule->write_io_16( m_data->reg_base + UHCI_PORTSC1 + (request->Index - 1 ) * 2 , port );
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;
@ -414,7 +432,7 @@ rh_submit_packet( usb_packet_t *packet )
default:
retval = EINVAL;
break;
} //switch( packet->value)
} //switch( transfer->value)
break;
default:
@ -435,7 +453,7 @@ rh_update_port_status(void)
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 );
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;

View File

@ -0,0 +1,113 @@
/*
* BeOS Driver for Intel ICH AC'97 Link interface
*
* Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <Errors.h>
#include <OS.h>
#include <string.h>
//#define DEBUG 2
//#include "debug.h"
#include "util.h"
spinlock slock = 0;
uint32 round_to_pagesize(uint32 size);
cpu_status lock(void)
{
cpu_status status = disable_interrupts();
acquire_spinlock(&slock);
return status;
}
void unlock(cpu_status status)
{
release_spinlock(&slock);
restore_interrupts(status);
}
uint32 round_to_pagesize(uint32 size)
{
return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
}
area_id alloc_mem(void **log, void **phy, size_t size, const char *name)
{
physical_entry pe;
void * logadr;
area_id areaid;
status_t rv;
dprintf("allocating %ld bytes for %s\n",size,name);
size = round_to_pagesize(size);
areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS,size,B_FULL_LOCK | B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
if (areaid < B_OK) {
dprintf("couldn't allocate area %s\n",name);
return B_ERROR;
}
rv = get_memory_map(logadr,size,&pe,1);
if (rv < B_OK) {
delete_area(areaid);
dprintf("couldn't map %s\n",name);
return B_ERROR;
}
memset(logadr,0,size);
if (log)
*log = logadr;
if (phy)
*phy = pe.address;
dprintf("area = %ld, size = %ld, log = %#08lX, phy = %#08lX\n",areaid,size,(uint32)logadr,(uint32)(pe.address));
return areaid;
}
/* This is not the most advanced method to map physical memory for io access.
* Perhaps using B_ANY_KERNEL_ADDRESS instead of B_ANY_KERNEL_BLOCK_ADDRESS
* makes the whole offset calculation and relocation obsolete. But the code
* below does work, and I can't test if using B_ANY_KERNEL_ADDRESS also works.
*/
area_id map_mem(void **log, void *phy, size_t size, const char *name)
{
uint32 offset;
void *phyadr;
void *mapadr;
area_id area;
dprintf("mapping physical address %p with %#lx bytes for %s\n",phy,size,name);
offset = (uint32)phy & (B_PAGE_SIZE - 1);
phyadr = (char *)phy - offset;
size = round_to_pagesize(size + offset);
area = map_physical_memory(name, phyadr, size, B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, &mapadr);
*log = (char *)mapadr + offset;
dprintf("physical = %p, logical = %p, offset = %#lx, phyadr = %p, mapadr = %p, size = %#lx, area = %#lx\n",
phy, *log, offset, phyadr, mapadr, size, area);
return area;
}

View File

@ -0,0 +1,41 @@
/*
* BeOS Driver for Intel ICH AC'97 Link interface
*
* Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _UTIL_H_
#define _UTIL_H_
#include <KernelExport.h>
area_id alloc_mem(void **log, void **phy, size_t size, const char *name);
area_id map_mem(void **log, void *phy, size_t size, const char *name);
cpu_status lock(void);
void unlock(cpu_status status);
extern spinlock slock;
#endif