From e3964db29123650785d76e4dd083bf6d680ee045 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Fri, 28 May 2004 07:50:37 +0000 Subject: [PATCH] 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 --- src/add-ons/kernel/busses/usb/Jamfile | 1 + .../kernel/busses/usb/host_controller.h | 41 +++++-- src/add-ons/kernel/busses/usb/uhci.c | 76 +++++++----- src/add-ons/kernel/busses/usb/util.c | 113 ++++++++++++++++++ src/add-ons/kernel/busses/usb/util.h | 41 +++++++ 5 files changed, 232 insertions(+), 40 deletions(-) create mode 100644 src/add-ons/kernel/busses/usb/util.c create mode 100644 src/add-ons/kernel/busses/usb/util.h diff --git a/src/add-ons/kernel/busses/usb/Jamfile b/src/add-ons/kernel/busses/usb/Jamfile index e5c3967836..25996a45b9 100644 --- a/src/add-ons/kernel/busses/usb/Jamfile +++ b/src/add-ons/kernel/busses/usb/Jamfile @@ -4,5 +4,6 @@ AddResources uhci : uhci.rdef ; R5KernelAddon uhci : [ FDirName kernel busses usb ] : uhci.c + util.c ; diff --git a/src/add-ons/kernel/busses/usb/host_controller.h b/src/add-ons/kernel/busses/usb/host_controller.h index eecad2a082..677c929232 100644 --- a/src/add-ons/kernel/busses/usb/host_controller.h +++ b/src/add-ons/kernel/busses/usb/host_controller.h @@ -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 diff --git a/src/add-ons/kernel/busses/usb/uhci.c b/src/add-ons/kernel/busses/usb/uhci.c index a299b685f5..93e949ed31 100644 --- a/src/add-ons/kernel/busses/usb/uhci.c +++ b/src/add-ons/kernel/busses/usb/uhci.c @@ -26,6 +26,7 @@ #include #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; diff --git a/src/add-ons/kernel/busses/usb/util.c b/src/add-ons/kernel/busses/usb/util.c new file mode 100644 index 0000000000..4c8de3d577 --- /dev/null +++ b/src/add-ons/kernel/busses/usb/util.c @@ -0,0 +1,113 @@ +/* + * BeOS Driver for Intel ICH AC'97 Link interface + * + * Copyright (c) 2002, Marcus Overhagen + * + * 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 +#include +#include + +//#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; +} diff --git a/src/add-ons/kernel/busses/usb/util.h b/src/add-ons/kernel/busses/usb/util.h new file mode 100644 index 0000000000..2bc87c062f --- /dev/null +++ b/src/add-ons/kernel/busses/usb/util.h @@ -0,0 +1,41 @@ +/* + * BeOS Driver for Intel ICH AC'97 Link interface + * + * Copyright (c) 2002, Marcus Overhagen + * + * 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 + +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