Changes in / [bb41b85:c32688d] in mainline


Ignore:
Files:
4 added
7 deleted
49 edited

Legend:

Unmodified
Added
Removed
  • dist/Makefile

    rbb41b85 rc32688d  
    4343
    4444SUFFIX = $(suffix $(IMGFILE))
    45 
    46 ifdef PROFILE
    47         DISTFILE = Helenos-$(shell echo $(PROFILE) | tr '/' '-')$(SUFFIX)
    48 else
    49         DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX)
    50 endif
     45DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX)
    5146
    5247.PHONY: all clean dist distfile
     
    5853        cp $< $@
    5954
    60 $(IMGFILE):
    61         $(MAKE) -C ..
    62 
    6355dist:
    6456        for profile in $(PROFILES); do \
  • uspace/app/usbinfo/info.c

    rbb41b85 rc32688d  
    6565                goto leave;
    6666        }
    67         rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
    68         if (rc != EOK) {
    69                 fprintf(stderr,
    70                     NAME ": probing default control pipe failed: %s.\n",
    71                     str_error(rc));
    72                 goto leave;
    73         }
    7467        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
    7568        if (rc != EOK) {
  • uspace/app/usbinfo/main.c

    rbb41b85 rc32688d  
    8282
    8383        if (str_cmp(path, "uhci") == 0) {
    84                 path = "/hw/pci0/00:01.2/uhci-hc";
     84                path = "/hw/pci0/00:01.2/uhci";
    8585        }
    8686
  • uspace/doc/doxygroups.h

    rbb41b85 rc32688d  
    253253         * @defgroup drvusbuhci UHCI driver
    254254         * @ingroup usb
    255          * @brief Drivers for USB UHCI host controller and root hub.
    256          */
    257 
    258                 /**
    259                  * @defgroup drvusbuhcirh UHCI root hub driver
    260                  * @ingroup drvusbuhci
    261                  * @brief Driver for UHCI complaint root hub.
    262                  */
    263 
    264                 /**
    265                  * @defgroup drvusbuhcihc UHCI host controller driver
    266                  * @ingroup drvusbuhci
    267                  * @brief Driver for UHCI complaint USB host controller.
    268                  */
     255         * @brief Driver for USB host controller UHCI.
     256         */
    269257
    270258        /**
  • uspace/drv/ehci-hcd/main.c

    rbb41b85 rc32688d  
    2727 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2828 */
    29 /** @addtogroup drvusbehci
     29/** @addtogroup usbdrvehci
    3030 * @{
    3131 */
  • uspace/drv/ehci-hcd/pci.c

    rbb41b85 rc32688d  
    247247
    248248
    249         if ((value & USBLEGSUP_BIOS_CONTROL) == 0) {
     249        if ((value & USBLEGSUP_BIOS_CONTROL) != 0) {
    250250                usb_log_info("BIOS released control after %d usec.\n", wait);
    251251        } else {
    252252                /* BIOS failed to hand over control, this should not happen. */
    253                 usb_log_warning( "BIOS failed to release control after "
     253                usb_log_warning( "BIOS failed to release control after"
    254254                    "%d usecs, force it.\n", wait);
    255255                ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     
    258258                CHECK_RET_HANGUP_RETURN(ret,
    259259                    "Failed(%d) to force OS EHCI control.\n", ret);
     260                /* TODO: This does not seem to work on my machine */
    260261        }
    261262
     
    279280        usb_log_debug2("USBLEGSUP: %x.\n", value);
    280281
    281         /*
    282          * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT
    283         */
     282/*
     283 * TURN OFF EHCI FOR NOW, REMOVE IF THE DRIVER IS IMPLEMENTED
     284 */
    284285
    285286        /* Get size of capability registers in memory space. */
  • uspace/drv/pciintel/pci.c

    rbb41b85 rc32688d  
    9292        pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
    9393
    94         sysarg_t apic;
    95         sysarg_t i8259;
     94  sysarg_t apic;
     95  sysarg_t i8259;
    9696
    9797        int irc_phone = -1;
    98         int irc_service = -1;
    99 
    100         if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
    101                 irc_service = SERVICE_APIC;
     98        int irc_service = 0;
     99
     100  if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
     101    irc_service = SERVICE_APIC;
    102102        } else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) {
    103                 irc_service = SERVICE_I8259;
    104         }
    105 
    106         if (irc_service == -1) {
     103    irc_service = SERVICE_I8259;
     104        }
     105
     106  if (irc_service == 0)
    107107                return false;
    108         }
    109108
    110109        irc_phone = service_connect_blocking(irc_service, 0, 0);
    111         if (irc_phone < 0) {
     110        if (irc_phone < 0)
    112111                return false;
    113         }
    114112
    115113        size_t i;
    116         for (i = 0; i < dev_data->hw_resources.count; i++) {
     114  for (i = 0; i < dev_data->hw_resources.count; i++) {
    117115                if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
    118116                        int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
  • uspace/drv/uhci-hcd/Makefile

    rbb41b85 rc32688d  
    3535        iface.c \
    3636        main.c \
     37        root_hub.c \
    3738        transfer_list.c \
    3839        uhci.c \
    39         uhci_hc.c \
    40         uhci_rh.c \
    4140        uhci_struct/transfer_descriptor.c \
    4241        utils/device_keeper.c \
  • uspace/drv/uhci-hcd/batch.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver
    3333 */
    3434#include <errno.h>
     
    4040#include "batch.h"
    4141#include "transfer_list.h"
    42 #include "uhci_hc.h"
     42#include "uhci.h"
    4343#include "utils/malloc32.h"
    4444
    4545#define DEFAULT_ERROR_COUNT 3
     46
     47static int batch_schedule(batch_t *instance);
    4648
    4749static void batch_control(batch_t *instance,
     
    5254static void batch_call_in_and_dispose(batch_t *instance);
    5355static void batch_call_out_and_dispose(batch_t *instance);
    54 
    55 
    56 /** Allocate memory and initialize internal data structure.
     56static void batch_dispose(batch_t *instance);
     57
     58
     59/** Allocates memory and initializes internal data structures.
    5760 *
    5861 * @param[in] fun DDF function to pass to callback.
     
    6972 * @param[in] arg additional parameter to func_in or func_out
    7073 * @param[in] manager Pointer to toggle management structure.
    71  * @return Valid pointer if all substructures were successfully created,
    72  * NULL otherwise.
    73  *
    74  * Determines the number of needed packets (TDs). Prepares a transport buffer
    75  * (that is accessible by the hardware). Initializes parameters needed for the
    76  * transaction and callback.
     74 * @return False, if there is an active TD, true otherwise.
    7775 */
    7876batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
     
    102100        bzero(instance, sizeof(batch_t));
    103101
    104         instance->qh = malloc32(sizeof(qh_t));
     102        instance->qh = malloc32(sizeof(queue_head_t));
    105103        CHECK_NULL_DISPOSE_RETURN(instance->qh,
    106104            "Failed to allocate batch queue head.\n");
    107         qh_init(instance->qh);
     105        queue_head_init(instance->qh);
    108106
    109107        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    116114            instance->tds, "Failed to allocate transfer descriptors.\n");
    117115        bzero(instance->tds, sizeof(td_t) * instance->packets);
     116
     117//      const size_t transport_size = max_packet_size * instance->packets;
    118118
    119119        if (size > 0) {
     
    143143        instance->speed = speed;
    144144        instance->manager = manager;
    145         instance->callback_out = func_out;
    146         instance->callback_in = func_in;
    147 
    148         qh_set_element_td(instance->qh, addr_to_phys(instance->tds));
     145
     146        if (func_out)
     147                instance->callback_out = func_out;
     148        if (func_in)
     149                instance->callback_in = func_in;
     150
     151        queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds));
    149152
    150153        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
     
    153156}
    154157/*----------------------------------------------------------------------------*/
    155 /** Check batch TDs for activity.
     158/** Checks batch TDs for activity.
    156159 *
    157160 * @param[in] instance Batch structure to use.
    158161 * @return False, if there is an active TD, true otherwise.
    159  *
    160  * Walk all TDs. Stop with false if there is an active one (it is to be
    161  * processed). Stop with true if an error is found. Return true if the last TS
    162  * is reached.
    163162 */
    164163bool batch_is_complete(batch_t *instance)
     
    178177                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    179178                            instance, i, instance->tds[i].status);
    180                         td_print_status(&instance->tds[i]);
    181179
    182180                        device_keeper_set_toggle(instance->manager,
     
    199197 *
    200198 * @param[in] instance Batch structure to use.
    201  *
    202  * Uses genercir control function with pids OUT and IN.
    203199 */
    204200void batch_control_write(batch_t *instance)
    205201{
    206202        assert(instance);
    207         /* We are data out, we are supposed to provide data */
     203        /* we are data out, we are supposed to provide data */
    208204        memcpy(instance->transport_buffer, instance->buffer,
    209205            instance->buffer_size);
     
    211207        instance->next_step = batch_call_out_and_dispose;
    212208        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     209        batch_schedule(instance);
    213210}
    214211/*----------------------------------------------------------------------------*/
     
    216213 *
    217214 * @param[in] instance Batch structure to use.
    218  *
    219  * Uses generic control with pids IN and OUT.
    220215 */
    221216void batch_control_read(batch_t *instance)
     
    225220        instance->next_step = batch_call_in_and_dispose;
    226221        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    227 }
    228 /*----------------------------------------------------------------------------*/
    229 /** Prepare interrupt in transaction.
    230  *
    231  * @param[in] instance Batch structure to use.
    232  *
    233  * Data transaction with PID_IN.
     222        batch_schedule(instance);
     223}
     224/*----------------------------------------------------------------------------*/
     225/** Prepares interrupt in transaction.
     226 *
     227 * @param[in] instance Batch structure to use.
    234228 */
    235229void batch_interrupt_in(batch_t *instance)
     
    239233        instance->next_step = batch_call_in_and_dispose;
    240234        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    241 }
    242 /*----------------------------------------------------------------------------*/
    243 /** Prepare interrupt out transaction.
    244  *
    245  * @param[in] instance Batch structure to use.
    246  *
    247  * Data transaction with PID_OUT.
     235        batch_schedule(instance);
     236}
     237/*----------------------------------------------------------------------------*/
     238/** Prepares interrupt out transaction.
     239 *
     240 * @param[in] instance Batch structure to use.
    248241 */
    249242void batch_interrupt_out(batch_t *instance)
    250243{
    251244        assert(instance);
    252         /* We are data out, we are supposed to provide data */
     245        /* we are data out, we are supposed to provide data */
    253246        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    254247        batch_data(instance, USB_PID_OUT);
    255248        instance->next_step = batch_call_out_and_dispose;
    256249        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    257 }
    258 /*----------------------------------------------------------------------------*/
    259 /** Prepare bulk in transaction.
    260  *
    261  * @param[in] instance Batch structure to use.
    262  *
    263  * Data transaction with PID_IN.
     250        batch_schedule(instance);
     251}
     252/*----------------------------------------------------------------------------*/
     253/** Prepares bulk in transaction.
     254 *
     255 * @param[in] instance Batch structure to use.
    264256 */
    265257void batch_bulk_in(batch_t *instance)
     
    269261        instance->next_step = batch_call_in_and_dispose;
    270262        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    271 }
    272 /*----------------------------------------------------------------------------*/
    273 /** Prepare bulk out transaction.
    274  *
    275  * @param[in] instance Batch structure to use.
    276  *
    277  * Data transaction with PID_OUT.
     263        batch_schedule(instance);
     264}
     265/*----------------------------------------------------------------------------*/
     266/** Prepares bulk out transaction.
     267 *
     268 * @param[in] instance Batch structure to use.
    278269 */
    279270void batch_bulk_out(batch_t *instance)
    280271{
    281272        assert(instance);
    282         /* We are data out, we are supposed to provide data */
    283273        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    284274        batch_data(instance, USB_PID_OUT);
    285275        instance->next_step = batch_call_out_and_dispose;
    286276        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    287 }
    288 /*----------------------------------------------------------------------------*/
    289 /** Prepare generic data transaction
     277        batch_schedule(instance);
     278}
     279/*----------------------------------------------------------------------------*/
     280/** Prepares generic data transaction
    290281 *
    291282 * @param[in] instance Batch structure to use.
    292283 * @param[in] pid to use for data packets.
    293  *
    294  * Packets with alternating toggle bit and supplied pid value.
    295  * The last packet is marked with IOC flag.
    296284 */
    297285void batch_data(batch_t *instance, usb_packet_id pid)
     
    330318                ++packet;
    331319        }
    332         td_set_ioc(&instance->tds[packet - 1]);
    333320        device_keeper_set_toggle(instance->manager, instance->target, toggle);
    334321}
    335322/*----------------------------------------------------------------------------*/
    336 /** Prepare generic control transaction
     323/** Prepares generic control transaction
    337324 *
    338325 * @param[in] instance Batch structure to use.
    339326 * @param[in] data_stage to use for data packets.
    340327 * @param[in] status_stage to use for data packets.
    341  *
    342  * Setup stage with toggle 0 and USB_PID_SETUP.
    343  * Data stage with alternating toggle and pid supplied by parameter.
    344  * Status stage with toggle 1 and pid supplied by parameter.
    345  * The last packet is marked with IOC.
    346328 */
    347329void batch_control(batch_t *instance,
     
    387369            0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
    388370
    389         td_set_ioc(&instance->tds[packet]);
     371
     372        instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    390373        usb_log_debug2("Control last TD status: %x.\n",
    391374            instance->tds[packet].status);
    392375}
    393376/*----------------------------------------------------------------------------*/
    394 /** Prepare data, get error status and call callback in.
    395  *
    396  * @param[in] instance Batch structure to use.
    397  * Copies data from transport buffer, and calls callback with appropriate
    398  * parameters.
     377/** Prepares data, gets error status and calls callback in.
     378 *
     379 * @param[in] instance Batch structure to use.
    399380 */
    400381void batch_call_in(batch_t *instance)
     
    403384        assert(instance->callback_in);
    404385
    405         /* We are data in, we need data */
     386        /* we are data in, we need data */
    406387        memcpy(instance->buffer, instance->transport_buffer,
    407388            instance->buffer_size);
     
    416397}
    417398/*----------------------------------------------------------------------------*/
    418 /** Get error status and call callback out.
     399/** Gets error status and calls callback out.
    419400 *
    420401 * @param[in] instance Batch structure to use.
     
    432413}
    433414/*----------------------------------------------------------------------------*/
    434 /** Helper function calls callback and correctly disposes of batch structure.
     415/** Prepares data, gets error status, calls callback in and dispose.
    435416 *
    436417 * @param[in] instance Batch structure to use.
     
    443424}
    444425/*----------------------------------------------------------------------------*/
    445 /** Helper function calls callback and correctly disposes of batch structure.
     426/** Gets error status, calls callback out and dispose.
    446427 *
    447428 * @param[in] instance Batch structure to use.
     
    454435}
    455436/*----------------------------------------------------------------------------*/
    456 /** Correctly dispose all used data structures.
     437/** Correctly disposes all used data structures.
    457438 *
    458439 * @param[in] instance Batch structure to use.
     
    469450        free(instance);
    470451}
     452/*----------------------------------------------------------------------------*/
     453int batch_schedule(batch_t *instance)
     454{
     455        assert(instance);
     456        uhci_t *hc = fun_to_uhci(instance->fun);
     457        assert(hc);
     458        return uhci_schedule(hc, instance);
     459}
    471460/**
    472461 * @}
  • uspace/drv/uhci-hcd/batch.h

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver
    3333 */
    3434#ifndef DRV_UHCI_BATCH_H
     
    5050        usb_target_t target;
    5151        usb_transfer_type_t transfer_type;
    52         usbhc_iface_transfer_in_callback_t callback_in;
    53         usbhc_iface_transfer_out_callback_t callback_out;
     52        union {
     53                usbhc_iface_transfer_in_callback_t callback_in;
     54                usbhc_iface_transfer_out_callback_t callback_out;
     55        };
    5456        void *arg;
    5557        char *transport_buffer;
     
    6365        int error;
    6466        ddf_fun_t *fun;
    65         qh_t *qh;
     67        queue_head_t *qh;
    6668        td_t *tds;
    6769        void (*next_step)(struct batch*);
     
    7779                device_keeper_t *manager
    7880                );
    79 
    80 void batch_dispose(batch_t *instance);
    8181
    8282bool batch_is_complete(batch_t *instance);
  • uspace/drv/uhci-hcd/iface.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver hc interface implementation
     32 * @brief UHCI driver
    3333 */
    3434#include <ddf/driver.h>
     
    4040
    4141#include "iface.h"
    42 #include "uhci_hc.h"
     42#include "uhci.h"
    4343#include "utils/device_keeper.h"
    4444
     
    5353{
    5454        assert(fun);
    55         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     55        uhci_t *hc = fun_to_uhci(fun);
    5656        assert(hc);
    5757        usb_log_debug("Default address request with speed %d.\n", speed);
     
    6868{
    6969        assert(fun);
    70         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     70        uhci_t *hc = fun_to_uhci(fun);
    7171        assert(hc);
    7272        usb_log_debug("Default address release.\n");
     
    8686{
    8787        assert(fun);
    88         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     88        uhci_t *hc = fun_to_uhci(fun);
    8989        assert(hc);
    9090        assert(address);
     
    109109{
    110110        assert(fun);
    111         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     111        uhci_t *hc = fun_to_uhci(fun);
    112112        assert(hc);
    113113        usb_log_debug("Address bind %d-%d.\n", address, handle);
     
    125125{
    126126        assert(fun);
    127         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     127        uhci_t *hc = fun_to_uhci(fun);
    128128        assert(hc);
    129129        usb_log_debug("Address release %d.\n", address);
     
    148148{
    149149        assert(fun);
    150         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     150        uhci_t *hc = fun_to_uhci(fun);
    151151        assert(hc);
    152152        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    161161                return ENOMEM;
    162162        batch_interrupt_out(batch);
    163         const int ret = uhci_hc_schedule(hc, batch);
    164         if (ret != EOK) {
    165                 batch_dispose(batch);
    166                 return ret;
    167         }
    168163        return EOK;
    169164}
     
    185180{
    186181        assert(fun);
    187         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     182        uhci_t *hc = fun_to_uhci(fun);
    188183        assert(hc);
    189184        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    197192                return ENOMEM;
    198193        batch_interrupt_in(batch);
    199         const int ret = uhci_hc_schedule(hc, batch);
    200         if (ret != EOK) {
    201                 batch_dispose(batch);
    202                 return ret;
    203         }
    204194        return EOK;
    205195}
     
    221211{
    222212        assert(fun);
    223         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     213        uhci_t *hc = fun_to_uhci(fun);
    224214        assert(hc);
    225215        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    234224                return ENOMEM;
    235225        batch_bulk_out(batch);
    236         const int ret = uhci_hc_schedule(hc, batch);
    237         if (ret != EOK) {
    238                 batch_dispose(batch);
    239                 return ret;
    240         }
    241226        return EOK;
    242227}
     
    258243{
    259244        assert(fun);
    260         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     245        uhci_t *hc = fun_to_uhci(fun);
    261246        assert(hc);
    262247        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    270255                return ENOMEM;
    271256        batch_bulk_in(batch);
    272         const int ret = uhci_hc_schedule(hc, batch);
    273         if (ret != EOK) {
    274                 batch_dispose(batch);
    275                 return ret;
    276         }
    277257        return EOK;
    278258}
     
    297277{
    298278        assert(fun);
    299         uhci_hc_t *hc = fun_to_uhci_hc(fun);
    300         assert(hc);
    301         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    302         usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
    303             speed, target.address, target.endpoint, size, max_packet_size);
     279        uhci_t *hc = fun_to_uhci(fun);
     280        assert(hc);
     281        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     282        usb_log_debug("Control WRITE %d:%d %zu(%zu).\n",
     283            target.address, target.endpoint, size, max_packet_size);
    304284
    305285        if (setup_size != 8)
     
    313293        device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
    314294        batch_control_write(batch);
    315         const int ret = uhci_hc_schedule(hc, batch);
    316         if (ret != EOK) {
    317                 batch_dispose(batch);
    318                 return ret;
    319         }
    320295        return EOK;
    321296}
     
    340315{
    341316        assert(fun);
    342         uhci_hc_t *hc = fun_to_uhci_hc(fun);
    343         assert(hc);
    344         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    345 
    346         usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
    347             speed, target.address, target.endpoint, size, max_packet_size);
     317        uhci_t *hc = fun_to_uhci(fun);
     318        assert(hc);
     319        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     320
     321        usb_log_debug("Control READ %d:%d %zu(%zu).\n",
     322            target.address, target.endpoint, size, max_packet_size);
    348323        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    349324            max_packet_size, speed, data, size, setup_data, setup_size, callback,
     
    352327                return ENOMEM;
    353328        batch_control_read(batch);
    354         const int ret = uhci_hc_schedule(hc, batch);
    355         if (ret != EOK) {
    356                 batch_dispose(batch);
    357                 return ret;
    358         }
    359         return EOK;
    360 }
    361 /*----------------------------------------------------------------------------*/
    362 usbhc_iface_t uhci_hc_iface = {
     329        return EOK;
     330}
     331/*----------------------------------------------------------------------------*/
     332usbhc_iface_t uhci_iface = {
    363333        .reserve_default_address = reserve_default_address,
    364334        .release_default_address = release_default_address,
  • uspace/drv/uhci-hcd/iface.h

    rbb41b85 rc32688d  
    2727 */
    2828
    29 /** @addtogroup drvusbuhcihc
     29/** @addtogroup usb
    3030 * @{
    3131 */
    3232/** @file
    33  * @brief UHCI driver iface
     33 * @brief UHCI driver
    3434 */
    3535#ifndef DRV_UHCI_IFACE_H
     
    3838#include <usbhc_iface.h>
    3939
    40 extern usbhc_iface_t uhci_hc_iface;
     40extern usbhc_iface_t uhci_iface;
    4141
    4242#endif
  • uspace/drv/uhci-hcd/main.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver initialization
     32 * @brief UHCI driver
    3333 */
    3434#include <ddf/driver.h>
     35#include <ddf/interrupt.h>
     36#include <device/hw_res.h>
    3537#include <errno.h>
    3638#include <str_error.h>
    3739
     40#include <usb_iface.h>
    3841#include <usb/ddfiface.h>
    3942#include <usb/debug.h>
    4043
    4144#include "iface.h"
     45#include "pci.h"
     46#include "root_hub.h"
    4247#include "uhci.h"
    4348
     
    5560};
    5661/*----------------------------------------------------------------------------*/
    57 /** Initialize a new ddf driver instance for uhci hc and hub.
     62/** IRQ handling callback, identifies devic
     63 *
     64 * @param[in] dev DDF instance of the device to use.
     65 * @param[in] iid (Unused).
     66 * @param[in] call Pointer to the call that represents interrupt.
     67 */
     68static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
     69{
     70        assert(dev);
     71        uhci_t *hc = dev_to_uhci(dev);
     72        uint16_t status = IPC_GET_ARG1(*call);
     73        assert(hc);
     74        uhci_interrupt(hc, status);
     75}
     76/*----------------------------------------------------------------------------*/
     77/** Initializes a new ddf driver instance of UHCI hcd.
    5878 *
    5979 * @param[in] device DDF instance of the device to initialize.
    6080 * @return Error code.
     81 *
     82 * Gets and initialies hardware resources, disables any legacy support,
     83 * and reports root hub device.
    6184 */
    6285int uhci_add_device(ddf_dev_t *device)
    6386{
     87        assert(device);
     88        uhci_t *hcd = NULL;
     89#define CHECK_RET_FREE_HC_RETURN(ret, message...) \
     90if (ret != EOK) { \
     91        usb_log_error(message); \
     92        if (hcd != NULL) \
     93                free(hcd); \
     94        return ret; \
     95}
     96
    6497        usb_log_info("uhci_add_device() called\n");
    65         assert(device);
    66         uhci_t *uhci = malloc(sizeof(uhci_t));
    67         if (uhci == NULL) {
    68                 usb_log_error("Failed to allocate UHCI driver.\n");
    69                 return ENOMEM;
     98
     99        uintptr_t io_reg_base = 0;
     100        size_t io_reg_size = 0;
     101        int irq = 0;
     102
     103        int ret =
     104            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
     105        CHECK_RET_FREE_HC_RETURN(ret,
     106            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
     107        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
     108            io_reg_base, io_reg_size, irq);
     109
     110        ret = pci_disable_legacy(device);
     111        CHECK_RET_FREE_HC_RETURN(ret,
     112            "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
     113
     114#if 0
     115        ret = pci_enable_interrupts(device);
     116        if (ret != EOK) {
     117                usb_log_warning(
     118                    "Failed(%d) to enable interrupts, fall back to polling.\n",
     119                    ret);
    70120        }
     121#endif
    71122
    72         int ret = uhci_init(uhci, device);
    73         if (ret != EOK) {
    74                 usb_log_error("Failed to initialzie UHCI driver.\n");
    75                 return ret;
    76         }
    77         device->driver_data = uhci;
     123        hcd = malloc(sizeof(uhci_t));
     124        ret = (hcd != NULL) ? EOK : ENOMEM;
     125        CHECK_RET_FREE_HC_RETURN(ret,
     126            "Failed(%d) to allocate memory for uhci hcd.\n", ret);
     127
     128        ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
     129        CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
     130#undef CHECK_RET_FREE_HC_RETURN
     131
     132        /*
     133         * We might free hcd, but that does not matter since no one
     134         * else would access driver_data anyway.
     135         */
     136        device->driver_data = hcd;
     137
     138        ddf_fun_t *rh = NULL;
     139#define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
     140if (ret != EOK) { \
     141        usb_log_error(message); \
     142        if (hcd != NULL) {\
     143                uhci_fini(hcd); \
     144                free(hcd); \
     145        } \
     146        if (rh != NULL) \
     147                free(rh); \
     148        return ret; \
     149}
     150
     151        /* It does no harm if we register this on polling */
     152        ret = register_interrupt_handler(device, irq, irq_handler,
     153            &hcd->interrupt_code);
     154        CHECK_RET_FINI_FREE_RETURN(ret,
     155            "Failed(%d) to register interrupt handler.\n", ret);
     156
     157        ret = setup_root_hub(&rh, device);
     158        CHECK_RET_FINI_FREE_RETURN(ret,
     159            "Failed(%d) to setup UHCI root hub.\n", ret);
     160        rh->driver_data = hcd->ddf_instance;
     161
     162        ret = ddf_fun_bind(rh);
     163        CHECK_RET_FINI_FREE_RETURN(ret,
     164            "Failed(%d) to register UHCI root hub.\n", ret);
     165
    78166        return EOK;
     167#undef CHECK_RET_FINI_FREE_RETURN
    79168}
    80169/*----------------------------------------------------------------------------*/
    81 /** Initialize global driver structures (NONE).
     170/** Initializes global driver structures (NONE).
    82171 *
    83172 * @param[in] argc Nmber of arguments in argv vector (ignored).
     
    89178int main(int argc, char *argv[])
    90179{
    91         sleep(3); /* TODO: remove in final version */
     180        sleep(3);
    92181        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    93182
  • uspace/drv/uhci-hcd/pci.c

    rbb41b85 rc32688d  
    2727 */
    2828/**
    29  * @addtogroup drvusbuhcihc
     29 * @addtogroup drvusbuhci
    3030 * @{
    3131 */
     
    117117}
    118118/*----------------------------------------------------------------------------*/
    119 /** Call the PCI driver with a request to enable interrupts
     119/** Calls the PCI driver with a request to enable interrupts
    120120 *
    121121 * @param[in] device Device asking for interrupts
     
    131131}
    132132/*----------------------------------------------------------------------------*/
    133 /** Call the PCI driver with a request to clear legacy support register
     133/** Calls the PCI driver with a request to clear legacy support register
    134134 *
    135135 * @param[in] device Device asking to disable interrupts
  • uspace/drv/uhci-hcd/pci.h

    rbb41b85 rc32688d  
    2727 */
    2828
    29 /** @addtogroup drvusbuhcihc
     29/** @addtogroup drvusbuhci
    3030 * @{
    3131 */
    3232/** @file
    33  * @brief UHCI driver PCI helper functions
     33 * @brief UHCI driver
    3434 */
    3535#ifndef DRV_UHCI_PCI_H
  • uspace/drv/uhci-hcd/transfer_list.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver transfer list implementation
     32 * @brief UHCI driver
    3333 */
    3434#include <errno.h>
     35
    3536#include <usb/debug.h>
    3637
     
    4041    transfer_list_t *instance, batch_t *batch);
    4142/*----------------------------------------------------------------------------*/
    42 /** Initialize transfer list structures.
     43/** Initializes transfer list structures.
    4344 *
    4445 * @param[in] instance Memory place to use.
    45  * @param[in] name Name of the new list.
     46 * @param[in] name Name of te new list.
    4647 * @return Error code
    4748 *
    48  * Allocates memory for internal qh_t structure.
     49 * Allocates memory for internat queue_head_t structure.
    4950 */
    5051int transfer_list_init(transfer_list_t *instance, const char *name)
    5152{
    5253        assert(instance);
     54        instance->next = NULL;
    5355        instance->name = name;
    54         instance->queue_head = malloc32(sizeof(qh_t));
     56        instance->queue_head = malloc32(sizeof(queue_head_t));
    5557        if (!instance->queue_head) {
    5658                usb_log_error("Failed to allocate queue head.\n");
     
    5961        instance->queue_head_pa = addr_to_phys(instance->queue_head);
    6062
    61         qh_init(instance->queue_head);
     63        queue_head_init(instance->queue_head);
    6264        list_initialize(&instance->batch_list);
    6365        fibril_mutex_initialize(&instance->guard);
     
    6567}
    6668/*----------------------------------------------------------------------------*/
    67 /** Set the next list in transfer list chain.
     69/** Set the next list in chain.
    6870 *
    6971 * @param[in] instance List to lead.
    7072 * @param[in] next List to append.
    7173 * @return Error code
    72  *
    73  * Does not check whether this replaces an existing list .
    7474 */
    7575void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
     
    7979        if (!instance->queue_head)
    8080                return;
    81         /* Set both next and element to point to the same QH */
    82         qh_set_next_qh(instance->queue_head, next->queue_head_pa);
    83         qh_set_element_qh(instance->queue_head, next->queue_head_pa);
     81        queue_head_append_qh(instance->queue_head, next->queue_head_pa);
     82        instance->queue_head->element = instance->queue_head->next_queue;
    8483}
    8584/*----------------------------------------------------------------------------*/
    86 /** Submit transfer batch to the list and queue.
     85/** Submits a new transfer batch to list and queue.
    8786 *
    8887 * @param[in] instance List to use.
    8988 * @param[in] batch Transfer batch to submit.
    9089 * @return Error code
    91  *
    92  * The batch is added to the end of the list and queue.
    9390 */
    9491void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
     
    9693        assert(instance);
    9794        assert(batch);
    98         usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     95        usb_log_debug2(
     96            "Adding batch(%p) to queue %s.\n", batch, instance->name);
    9997
    100         const uint32_t pa = addr_to_phys(batch->qh);
     98        uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
    10199        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
     100        pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
    102101
    103         /* New batch will be added to the end of the current list
    104          * so set the link accordingly */
    105         qh_set_next_qh(batch->qh, instance->queue_head->next);
     102        batch->qh->next_queue = instance->queue_head->next_queue;
    106103
    107104        fibril_mutex_lock(&instance->guard);
    108105
    109         /* Add to the hardware queue. */
    110         if (list_empty(&instance->batch_list)) {
    111                 /* There is nothing scheduled */
    112                 qh_t *qh = instance->queue_head;
    113                 assert(qh->element == qh->next);
    114                 qh_set_element_qh(qh, pa);
    115         } else {
    116                 /* There is something scheduled */
    117                 batch_t *last = list_get_instance(
    118                     instance->batch_list.prev, batch_t, link);
    119                 qh_set_next_qh(last->qh, pa);
     106        if (instance->queue_head->element == instance->queue_head->next_queue) {
     107                /* there is nothing scheduled */
     108                list_append(&batch->link, &instance->batch_list);
     109                instance->queue_head->element = pa;
     110                usb_log_debug("Batch(%p) added to queue %s first.\n",
     111                        batch, instance->name);
     112                fibril_mutex_unlock(&instance->guard);
     113                return;
    120114        }
    121         /* Add to the driver list */
     115        /* now we can be sure that there is someting scheduled */
     116        assert(!list_empty(&instance->batch_list));
     117        batch_t *first = list_get_instance(
     118                  instance->batch_list.next, batch_t, link);
     119        batch_t *last = list_get_instance(
     120            instance->batch_list.prev, batch_t, link);
     121        queue_head_append_qh(last->qh, pa);
    122122        list_append(&batch->link, &instance->batch_list);
    123123
    124         batch_t *first = list_get_instance(
    125             instance->batch_list.next, batch_t, link);
    126         usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
     124        usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
    127125                batch, instance->name, first);
    128126        fibril_mutex_unlock(&instance->guard);
    129127}
    130128/*----------------------------------------------------------------------------*/
    131 /** Remove a transfer batch from the list and queue.
     129/** Removes a transfer batch from list and queue.
    132130 *
    133131 * @param[in] instance List to use.
    134132 * @param[in] batch Transfer batch to remove.
    135133 * @return Error code
    136  *
    137  * Does not lock the transfer list, caller is responsible for that.
    138134 */
    139135void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
     
    144140        assert(batch->qh);
    145141        usb_log_debug2(
    146             "Queue %s: removing batch(%p).\n", instance->name, batch);
     142            "Removing batch(%p) from queue %s.\n", batch, instance->name);
    147143
    148         const char * pos = NULL;
    149         /* Remove from the hardware queue */
    150144        if (batch->link.prev == &instance->batch_list) {
    151145                /* I'm the first one here */
    152                 qh_set_element_qh(instance->queue_head, batch->qh->next);
    153                 pos = "FIRST";
     146                usb_log_debug(
     147                    "Batch(%p) removed (FIRST) from %s, next element %x.\n",
     148                    batch, instance->name, batch->qh->next_queue);
     149                instance->queue_head->element = batch->qh->next_queue;
    154150        } else {
     151                usb_log_debug(
     152                    "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",
     153                    batch, instance->name, batch->qh->next_queue);
    155154                batch_t *prev =
    156155                    list_get_instance(batch->link.prev, batch_t, link);
    157                 qh_set_next_qh(prev->qh, batch->qh->next);
    158                 pos = "NOT FIRST";
     156                prev->qh->next_queue = batch->qh->next_queue;
    159157        }
    160         /* Remove from the driver list */
    161158        list_remove(&batch->link);
    162         usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",
    163             batch, pos, instance->name, batch->qh->next);
    164159}
    165160/*----------------------------------------------------------------------------*/
    166 /** Check list for finished batches.
     161/** Checks list for finished transfers.
    167162 *
    168163 * @param[in] instance List to use.
    169164 * @return Error code
    170  *
    171  * Creates a local list of finished batches and calls next_step on each and
    172  * every one. This is safer because next_step may theoretically access
    173  * this transfer list leading to the deadlock if its done inline.
    174165 */
    175166void transfer_list_remove_finished(transfer_list_t *instance)
     
    186177
    187178                if (batch_is_complete(batch)) {
    188                         /* Save for post-processing */
    189179                        transfer_list_remove_batch(instance, batch);
    190180                        list_append(current, &done);
  • uspace/drv/uhci-hcd/transfer_list.h

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver transfer list structure
     32 * @brief UHCI driver
    3333 */
    3434#ifndef DRV_UHCI_TRANSFER_LIST_H
     
    4444{
    4545        fibril_mutex_t guard;
    46         qh_t *queue_head;
     46        queue_head_t *queue_head;
    4747        uint32_t queue_head_pa;
     48        struct transfer_list *next;
    4849        const char *name;
    4950        link_t batch_list;
    5051} transfer_list_t;
    5152
    52 /** Dispose transfer list structures.
    53  *
    54  * @param[in] instance Memory place to use.
    55  *
    56  * Frees memory for internal qh_t structure.
    57  */
     53int transfer_list_init(transfer_list_t *instance, const char *name);
     54
     55void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
     56
    5857static inline void transfer_list_fini(transfer_list_t *instance)
    5958{
     
    6160        free32(instance->queue_head);
    6261}
    63 
    64 int transfer_list_init(transfer_list_t *instance, const char *name);
    65 
    66 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    67 
    6862void transfer_list_remove_finished(transfer_list_t *instance);
    6963
  • uspace/drv/uhci-hcd/uhci.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup drvusbuhci
     28/** @addtogroup usb
    3029 * @{
    3130 */
     
    3534#include <errno.h>
    3635#include <str_error.h>
    37 #include <ddf/interrupt.h>
     36#include <adt/list.h>
     37#include <libarch/ddi.h>
     38
     39#include <usb/debug.h>
     40#include <usb/usb.h>
     41#include <usb/ddfiface.h>
    3842#include <usb_iface.h>
    39 #include <usb/ddfiface.h>
    40 #include <usb/debug.h>
    4143
    4244#include "uhci.h"
    4345#include "iface.h"
    44 #include "pci.h"
    45 
    46 
    47 /** IRQ handling callback, identifies device
    48  *
    49  * @param[in] dev DDF instance of the device to use.
    50  * @param[in] iid (Unused).
    51  * @param[in] call Pointer to the call that represents interrupt.
    52  */
    53 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    54 {
    55         assert(dev);
    56         uhci_hc_t *hc = &((uhci_t*)dev->driver_data)->hc;
    57         uint16_t status = IPC_GET_ARG1(*call);
    58         assert(hc);
    59         uhci_hc_interrupt(hc, status);
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 /** Get address of the device identified by handle.
    63  *
    64  * @param[in] dev DDF instance of the device to use.
    65  * @param[in] iid (Unused).
    66  * @param[in] call Pointer to the call that represents interrupt.
     46
     47static irq_cmd_t uhci_cmds[] = {
     48        {
     49                .cmd = CMD_PIO_READ_16,
     50                .addr = NULL, /* patched for every instance */
     51                .dstarg = 1
     52        },
     53        {
     54                .cmd = CMD_PIO_WRITE_16,
     55                .addr = NULL, /* pathed for every instance */
     56                .value = 0x1f
     57        },
     58        {
     59                .cmd = CMD_ACCEPT
     60        }
     61};
     62
     63/** Gets USB address of the calling device.
     64 *
     65 * @param[in] fun UHCI hc function.
     66 * @param[in] handle Handle of the device seeking address.
     67 * @param[out] address Place to store found address.
     68 * @return Error code.
    6769 */
    6870static int usb_iface_get_address(
     
    7072{
    7173        assert(fun);
    72         device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.device_manager;
    73 
    74         usb_address_t addr = device_keeper_find(manager, handle);
     74        uhci_t *hc = fun_to_uhci(fun);
     75        assert(hc);
     76
     77        usb_address_t addr = device_keeper_find(&hc->device_manager,
     78            handle);
    7579        if (addr < 0) {
    7680                return addr;
     
    8488}
    8589/*----------------------------------------------------------------------------*/
    86 /** Gets handle of the respective hc (this or parent device).
    87  *
    88  * @param[in] root_hub_fun Root hub function seeking hc handle.
    89  * @param[out] handle Place to write the handle.
    90  * @return Error code.
    91  */
    92 static int usb_iface_get_hc_handle(
    93     ddf_fun_t *fun, devman_handle_t *handle)
    94 {
    95         assert(handle);
    96         ddf_fun_t *hc_fun = ((uhci_t*)fun->dev->driver_data)->hc_fun;
    97         assert(hc_fun != NULL);
    98 
    99         *handle = hc_fun->handle;
    100         return EOK;
    101 }
    102 /*----------------------------------------------------------------------------*/
    103 /** This iface is generic for both RH and HC. */
    104 static usb_iface_t usb_iface = {
    105         .get_hc_handle = usb_iface_get_hc_handle,
     90static usb_iface_t hc_usb_iface = {
     91        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
    10692        .get_address = usb_iface_get_address
    10793};
    10894/*----------------------------------------------------------------------------*/
    109 static ddf_dev_ops_t uhci_hc_ops = {
    110         .interfaces[USB_DEV_IFACE] = &usb_iface,
    111         .interfaces[USBHC_DEV_IFACE] = &uhci_hc_iface, /* see iface.h/c */
     95static ddf_dev_ops_t uhci_ops = {
     96        .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
     97        .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    11298};
    11399/*----------------------------------------------------------------------------*/
    114 /** Get root hub hw resources (I/O registers).
    115  *
    116  * @param[in] fun Root hub function.
    117  * @return Pointer to the resource list used by the root hub.
    118  */
    119 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
    120 {
    121         assert(fun);
    122         return &((uhci_rh_t*)fun->driver_data)->resource_list;
    123 }
    124 /*----------------------------------------------------------------------------*/
    125 static hw_res_ops_t hw_res_iface = {
    126         .get_resource_list = get_resource_list,
    127         .enable_interrupt = NULL
    128 };
    129 /*----------------------------------------------------------------------------*/
    130 static ddf_dev_ops_t uhci_rh_ops = {
    131         .interfaces[USB_DEV_IFACE] = &usb_iface,
    132         .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
    133 };
    134 /*----------------------------------------------------------------------------*/
    135 /** Initialize hc and rh ddf structures and their respective drivers.
    136  *
    137  * @param[in] instance UHCI structure to use.
    138  * @param[in] device DDF instance of the device to use.
    139  *
    140  * This function does all the preparatory work for hc and rh drivers:
    141  *  - gets device hw resources
    142  *  - disables UHCI legacy support
    143  *  - asks for interrupt
    144  *  - registers interrupt handler
    145  */
    146 int uhci_init(uhci_t *instance, ddf_dev_t *device)
    147 {
    148         assert(instance);
    149         instance->hc_fun = NULL;
    150         instance->rh_fun = NULL;
     100static int uhci_init_transfer_lists(uhci_t *instance);
     101static int uhci_init_mem_structures(uhci_t *instance);
     102static void uhci_init_hw(uhci_t *instance);
     103
     104static int uhci_interrupt_emulator(void *arg);
     105static int uhci_debug_checker(void *arg);
     106
     107static bool allowed_usb_packet(
     108    bool low_speed, usb_transfer_type_t transfer, size_t size);
     109/*----------------------------------------------------------------------------*/
     110/** Initializes UHCI hcd driver structure
     111 *
     112 * @param[in] instance Memory place to initialize.
     113 * @param[in] dev DDF device.
     114 * @param[in] regs Address of I/O control registers.
     115 * @param[in] size Size of I/O control registers.
     116 * @return Error code.
     117 * @note Should be called only once on any structure.
     118 */
     119int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
     120{
     121        assert(reg_size >= sizeof(regs_t));
     122        int ret;
     123
    151124#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
    152 if (ret != EOK) { \
    153         usb_log_error(message); \
    154         if (instance->hc_fun) \
    155                 ddf_fun_destroy(instance->hc_fun); \
    156         if (instance->rh_fun) \
    157                 ddf_fun_destroy(instance->rh_fun); \
    158         return ret; \
    159 }
    160 
    161         uintptr_t io_reg_base = 0;
    162         size_t io_reg_size = 0;
    163         int irq = 0;
    164 
    165         int ret =
    166             pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
     125        if (ret != EOK) { \
     126                usb_log_error(message); \
     127                if (instance->ddf_instance) \
     128                        ddf_fun_destroy(instance->ddf_instance); \
     129                return ret; \
     130        } else (void) 0
     131
     132        /* Create UHCI function. */
     133        instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
     134        ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
    167135        CHECK_RET_DEST_FUN_RETURN(ret,
    168             "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
    169         usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
    170             io_reg_base, io_reg_size, irq);
    171 
    172         ret = pci_disable_legacy(device);
    173         CHECK_RET_DEST_FUN_RETURN(ret,
    174             "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
    175 
    176         bool interrupts = false;
    177         ret = pci_enable_interrupts(device);
    178         if (ret != EOK) {
    179                 usb_log_warning(
    180                     "Failed(%d) to enable interrupts, fall back to polling.\n",
    181                     ret);
    182         } else {
    183                 usb_log_debug("Hw interrupts enabled.\n");
    184                 interrupts = true;
    185         }
    186 
    187         instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc");
    188         ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
    189         CHECK_RET_DEST_FUN_RETURN(ret,
    190             "Failed(%d) to create HC function.\n", ret);
    191 
    192         ret = uhci_hc_init(&instance->hc, instance->hc_fun,
    193             (void*)io_reg_base, io_reg_size, interrupts);
    194         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
    195         instance->hc_fun->ops = &uhci_hc_ops;
    196         instance->hc_fun->driver_data = &instance->hc;
    197         ret = ddf_fun_bind(instance->hc_fun);
     136            "Failed to create UHCI device function.\n");
     137
     138        instance->ddf_instance->ops = &uhci_ops;
     139        instance->ddf_instance->driver_data = instance;
     140
     141        ret = ddf_fun_bind(instance->ddf_instance);
    198142        CHECK_RET_DEST_FUN_RETURN(ret,
    199143            "Failed(%d) to bind UHCI device function: %s.\n",
    200144            ret, str_error(ret));
    201 #undef CHECK_RET_HC_RETURN
    202 
    203 #define CHECK_RET_FINI_RETURN(ret, message...) \
    204 if (ret != EOK) { \
    205         usb_log_error(message); \
    206         if (instance->hc_fun) \
    207                 ddf_fun_destroy(instance->hc_fun); \
    208         if (instance->rh_fun) \
    209                 ddf_fun_destroy(instance->rh_fun); \
    210         uhci_hc_fini(&instance->hc); \
    211         return ret; \
    212 }
    213 
    214         /* It does no harm if we register this on polling */
    215         ret = register_interrupt_handler(device, irq, irq_handler,
    216             &instance->hc.interrupt_code);
    217         CHECK_RET_FINI_RETURN(ret,
    218             "Failed(%d) to register interrupt handler.\n", ret);
    219 
    220         instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
    221         ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
    222         CHECK_RET_FINI_RETURN(ret,
    223             "Failed(%d) to create root hub function.\n", ret);
    224 
    225         ret = uhci_rh_init(&instance->rh, instance->rh_fun,
    226             (uintptr_t)instance->hc.registers + 0x10, 4);
    227         CHECK_RET_FINI_RETURN(ret,
    228             "Failed(%d) to setup UHCI root hub.\n", ret);
    229 
    230         instance->rh_fun->ops = &uhci_rh_ops;
    231         instance->rh_fun->driver_data = &instance->rh;
    232         ret = ddf_fun_bind(instance->rh_fun);
    233         CHECK_RET_FINI_RETURN(ret,
    234             "Failed(%d) to register UHCI root hub.\n", ret);
    235 
    236         return EOK;
    237 #undef CHECK_RET_FINI_RETURN
     145
     146        /* allow access to hc control registers */
     147        regs_t *io;
     148        ret = pio_enable(regs, reg_size, (void**)&io);
     149        CHECK_RET_DEST_FUN_RETURN(ret,
     150            "Failed(%d) to gain access to registers at %p: %s.\n",
     151            ret, str_error(ret), io);
     152        instance->registers = io;
     153        usb_log_debug("Device registers at %p(%u) accessible.\n",
     154            io, reg_size);
     155
     156        ret = uhci_init_mem_structures(instance);
     157        CHECK_RET_DEST_FUN_RETURN(ret,
     158            "Failed to initialize UHCI memory structures.\n");
     159
     160        uhci_init_hw(instance);
     161        instance->cleaner =
     162            fibril_create(uhci_interrupt_emulator, instance);
     163        fibril_add_ready(instance->cleaner);
     164
     165        instance->debug_checker = fibril_create(uhci_debug_checker, instance);
     166        fibril_add_ready(instance->debug_checker);
     167
     168        usb_log_info("Started UHCI driver.\n");
     169        return EOK;
     170#undef CHECK_RET_DEST_FUN_RETURN
     171}
     172/*----------------------------------------------------------------------------*/
     173/** Initializes UHCI hcd hw resources.
     174 *
     175 * @param[in] instance UHCI structure to use.
     176 */
     177void uhci_init_hw(uhci_t *instance)
     178{
     179        assert(instance);
     180        regs_t *registers = instance->registers;
     181
     182        /* Reset everything, who knows what touched it before us */
     183        pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
     184        async_usleep(10000); /* 10ms according to USB spec */
     185        pio_write_16(&registers->usbcmd, 0);
     186
     187        /* Reset hc, all states and counters */
     188        pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
     189        do { async_usleep(10); }
     190        while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
     191
     192        /* Set framelist pointer */
     193        const uint32_t pa = addr_to_phys(instance->frame_list);
     194        pio_write_32(&registers->flbaseadd, pa);
     195
     196        /* Enable all interrupts, but resume interrupt */
     197//      pio_write_16(&instance->registers->usbintr,
     198//          UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     199
     200        uint16_t status = pio_read_16(&registers->usbcmd);
     201        if (status != 0)
     202                usb_log_warning("Previous command value: %x.\n", status);
     203
     204        /* Start the hc with large(64B) packet FSBR */
     205        pio_write_16(&registers->usbcmd,
     206            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
     207}
     208/*----------------------------------------------------------------------------*/
     209/** Initializes UHCI hcd memory structures.
     210 *
     211 * @param[in] instance UHCI structure to use.
     212 * @return Error code
     213 * @note Should be called only once on any structure.
     214 */
     215int uhci_init_mem_structures(uhci_t *instance)
     216{
     217        assert(instance);
     218#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
     219        if (ret != EOK) { \
     220                usb_log_error(message); \
     221                if (instance->interrupt_code.cmds != NULL) \
     222                        free(instance->interrupt_code.cmds); \
     223                return ret; \
     224        } else (void) 0
     225
     226        /* Init interrupt code */
     227        instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
     228        int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
     229        CHECK_RET_DEST_CMDS_RETURN(ret,
     230            "Failed to allocate interrupt cmds space.\n");
     231
     232        {
     233                irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
     234                memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
     235                interrupt_commands[0].addr =
     236                    (void*)&instance->registers->usbsts;
     237                interrupt_commands[1].addr =
     238                    (void*)&instance->registers->usbsts;
     239                instance->interrupt_code.cmdcount =
     240                    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     241        }
     242
     243        /* Init transfer lists */
     244        ret = uhci_init_transfer_lists(instance);
     245        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
     246        usb_log_debug("Initialized transfer lists.\n");
     247
     248        /* Init USB frame list page*/
     249        instance->frame_list = get_page();
     250        ret = instance ? EOK : ENOMEM;
     251        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
     252        usb_log_debug("Initialized frame list.\n");
     253
     254        /* Set all frames to point to the first queue head */
     255        const uint32_t queue =
     256          instance->transfers_interrupt.queue_head_pa
     257          | LINK_POINTER_QUEUE_HEAD_FLAG;
     258
     259        unsigned i = 0;
     260        for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
     261                instance->frame_list[i] = queue;
     262        }
     263
     264        /* Init device keeper*/
     265        device_keeper_init(&instance->device_manager);
     266        usb_log_debug("Initialized device manager.\n");
     267
     268        return EOK;
     269#undef CHECK_RET_DEST_CMDS_RETURN
     270}
     271/*----------------------------------------------------------------------------*/
     272/** Initializes UHCI hcd transfer lists.
     273 *
     274 * @param[in] instance UHCI structure to use.
     275 * @return Error code
     276 * @note Should be called only once on any structure.
     277 */
     278int uhci_init_transfer_lists(uhci_t *instance)
     279{
     280        assert(instance);
     281#define CHECK_RET_CLEAR_RETURN(ret, message...) \
     282        if (ret != EOK) { \
     283                usb_log_error(message); \
     284                transfer_list_fini(&instance->transfers_bulk_full); \
     285                transfer_list_fini(&instance->transfers_control_full); \
     286                transfer_list_fini(&instance->transfers_control_slow); \
     287                transfer_list_fini(&instance->transfers_interrupt); \
     288                return ret; \
     289        } else (void) 0
     290
     291        /* initialize TODO: check errors */
     292        int ret;
     293        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
     294        CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
     295
     296        ret = transfer_list_init(
     297            &instance->transfers_control_full, "CONTROL_FULL");
     298        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
     299
     300        ret = transfer_list_init(
     301            &instance->transfers_control_slow, "CONTROL_SLOW");
     302        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
     303
     304        ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
     305        CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
     306
     307        transfer_list_set_next(&instance->transfers_control_full,
     308                &instance->transfers_bulk_full);
     309        transfer_list_set_next(&instance->transfers_control_slow,
     310                &instance->transfers_control_full);
     311        transfer_list_set_next(&instance->transfers_interrupt,
     312                &instance->transfers_control_slow);
     313
     314        /*FSBR*/
     315#ifdef FSBR
     316        transfer_list_set_next(&instance->transfers_bulk_full,
     317                &instance->transfers_control_full);
     318#endif
     319
     320        /* Assign pointers to be used during scheduling */
     321        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
     322          &instance->transfers_interrupt;
     323        instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
     324          &instance->transfers_interrupt;
     325        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
     326          &instance->transfers_control_full;
     327        instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
     328          &instance->transfers_control_slow;
     329        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
     330          &instance->transfers_bulk_full;
     331
     332        return EOK;
     333#undef CHECK_RET_CLEAR_RETURN
     334}
     335/*----------------------------------------------------------------------------*/
     336/** Schedules batch for execution.
     337 *
     338 * @param[in] instance UHCI structure to use.
     339 * @param[in] batch Transfer batch to schedule.
     340 * @return Error code
     341 */
     342int uhci_schedule(uhci_t *instance, batch_t *batch)
     343{
     344        assert(instance);
     345        assert(batch);
     346        const int low_speed = (batch->speed == USB_SPEED_LOW);
     347        if (!allowed_usb_packet(
     348            low_speed, batch->transfer_type, batch->max_packet_size)) {
     349                usb_log_warning(
     350                    "Invalid USB packet specified %s SPEED %d %zu.\n",
     351                    low_speed ? "LOW" : "FULL" , batch->transfer_type,
     352                    batch->max_packet_size);
     353                return ENOTSUP;
     354        }
     355        /* TODO: check available bandwith here */
     356
     357        transfer_list_t *list =
     358            instance->transfers[low_speed][batch->transfer_type];
     359        assert(list);
     360        transfer_list_add_batch(list, batch);
     361
     362        return EOK;
     363}
     364/*----------------------------------------------------------------------------*/
     365/** Takes action based on the interrupt cause.
     366 *
     367 * @param[in] instance UHCI structure to use.
     368 * @param[in] status Value of the stsatus regiser at the time of interrupt.
     369 */
     370void uhci_interrupt(uhci_t *instance, uint16_t status)
     371{
     372        assert(instance);
     373        /* TODO: Check interrupt cause here */
     374        transfer_list_remove_finished(&instance->transfers_interrupt);
     375        transfer_list_remove_finished(&instance->transfers_control_slow);
     376        transfer_list_remove_finished(&instance->transfers_control_full);
     377        transfer_list_remove_finished(&instance->transfers_bulk_full);
     378}
     379/*----------------------------------------------------------------------------*/
     380/** Polling function, emulates interrupts.
     381 *
     382 * @param[in] arg UHCI structure to use.
     383 * @return EOK
     384 */
     385int uhci_interrupt_emulator(void* arg)
     386{
     387        usb_log_debug("Started interrupt emulator.\n");
     388        uhci_t *instance = (uhci_t*)arg;
     389        assert(instance);
     390
     391        while (1) {
     392                uint16_t status = pio_read_16(&instance->registers->usbsts);
     393                if (status != 0)
     394                        usb_log_debug2("UHCI status: %x.\n", status);
     395                status |= 1;
     396                uhci_interrupt(instance, status);
     397                pio_write_16(&instance->registers->usbsts, 0x1f);
     398                async_usleep(UHCI_CLEANER_TIMEOUT);
     399        }
     400        return EOK;
     401}
     402/*---------------------------------------------------------------------------*/
     403/** Debug function, checks consistency of memory structures.
     404 *
     405 * @param[in] arg UHCI structure to use.
     406 * @return EOK
     407 */
     408int uhci_debug_checker(void *arg)
     409{
     410        uhci_t *instance = (uhci_t*)arg;
     411        assert(instance);
     412
     413#define QH(queue) \
     414        instance->transfers_##queue.queue_head
     415
     416        while (1) {
     417                const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
     418                const uint16_t sts = pio_read_16(&instance->registers->usbsts);
     419                const uint16_t intr =
     420                    pio_read_16(&instance->registers->usbintr);
     421
     422                if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
     423                        usb_log_debug2("Command: %X Status: %X Intr: %x\n",
     424                            cmd, sts, intr);
     425                }
     426
     427                uintptr_t frame_list =
     428                    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
     429                if (frame_list != addr_to_phys(instance->frame_list)) {
     430                        usb_log_debug("Framelist address: %p vs. %p.\n",
     431                            frame_list, addr_to_phys(instance->frame_list));
     432                }
     433
     434                int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
     435                usb_log_debug2("Framelist item: %d \n", frnum );
     436
     437                uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf);
     438                uintptr_t real_pa = addr_to_phys(QH(interrupt));
     439                if (expected_pa != real_pa) {
     440                        usb_log_debug("Interrupt QH: %p vs. %p.\n",
     441                            expected_pa, real_pa);
     442                }
     443
     444                expected_pa = QH(interrupt)->next_queue & (~0xf);
     445                real_pa = addr_to_phys(QH(control_slow));
     446                if (expected_pa != real_pa) {
     447                        usb_log_debug("Control Slow QH: %p vs. %p.\n",
     448                            expected_pa, real_pa);
     449                }
     450
     451                expected_pa = QH(control_slow)->next_queue & (~0xf);
     452                real_pa = addr_to_phys(QH(control_full));
     453                if (expected_pa != real_pa) {
     454                        usb_log_debug("Control Full QH: %p vs. %p.\n",
     455                            expected_pa, real_pa);
     456                }
     457
     458                expected_pa = QH(control_full)->next_queue & (~0xf);
     459                real_pa = addr_to_phys(QH(bulk_full));
     460                if (expected_pa != real_pa ) {
     461                        usb_log_debug("Bulk QH: %p vs. %p.\n",
     462                            expected_pa, real_pa);
     463                }
     464                async_usleep(UHCI_DEBUGER_TIMEOUT);
     465        }
     466        return EOK;
     467#undef QH
     468}
     469/*----------------------------------------------------------------------------*/
     470/** Checks transfer packets, for USB validity
     471 *
     472 * @param[in] low_speed Transfer speed.
     473 * @param[in] transfer Transer type
     474 * @param[in] size Maximum size of used packets
     475 * @return EOK
     476 */
     477bool allowed_usb_packet(
     478    bool low_speed, usb_transfer_type_t transfer, size_t size)
     479{
     480        /* see USB specification chapter 5.5-5.8 for magic numbers used here */
     481        switch(transfer)
     482        {
     483        case USB_TRANSFER_ISOCHRONOUS:
     484                return (!low_speed && size < 1024);
     485        case USB_TRANSFER_INTERRUPT:
     486                return size <= (low_speed ? 8 : 64);
     487        case USB_TRANSFER_CONTROL: /* device specifies its own max size */
     488                return (size <= (low_speed ? 8 : 64));
     489        case USB_TRANSFER_BULK: /* device specifies its own max size */
     490                return (!low_speed && size <= 64);
     491        }
     492        return false;
    238493}
    239494/**
  • uspace/drv/uhci-hcd/uhci.h

    rbb41b85 rc32688d  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2010 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief UHCI driver main structure for both host controller and root-hub.
     33 * @brief UHCI driver
    3434 */
    3535#ifndef DRV_UHCI_UHCI_H
    3636#define DRV_UHCI_UHCI_H
     37
     38#include <fibril.h>
     39#include <fibril_synch.h>
     40#include <adt/list.h>
    3741#include <ddi.h>
    38 #include <ddf/driver.h>
    3942
    40 #include "uhci_hc.h"
    41 #include "uhci_rh.h"
     43#include <usbhc_iface.h>
     44
     45#include "batch.h"
     46#include "transfer_list.h"
     47#include "utils/device_keeper.h"
     48
     49typedef struct uhci_regs {
     50        uint16_t usbcmd;
     51#define UHCI_CMD_MAX_PACKET (1 << 7)
     52#define UHCI_CMD_CONFIGURE  (1 << 6)
     53#define UHCI_CMD_DEBUG  (1 << 5)
     54#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
     55#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
     56#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
     57#define UHCI_CMD_HCRESET  (1 << 1)
     58#define UHCI_CMD_RUN_STOP  (1 << 0)
     59
     60        uint16_t usbsts;
     61#define UHCI_STATUS_HALTED (1 << 5)
     62#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
     63#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
     64#define UHCI_STATUS_RESUME (1 << 2)
     65#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
     66#define UHCI_STATUS_INTERRUPT (1 << 0)
     67
     68        uint16_t usbintr;
     69#define UHCI_INTR_SHORT_PACKET (1 << 3)
     70#define UHCI_INTR_COMPLETE (1 << 2)
     71#define UHCI_INTR_RESUME (1 << 1)
     72#define UHCI_INTR_CRC (1 << 0)
     73
     74        uint16_t frnum;
     75        uint32_t flbaseadd;
     76        uint8_t sofmod;
     77} regs_t;
     78
     79#define UHCI_FRAME_LIST_COUNT 1024
     80#define UHCI_CLEANER_TIMEOUT 10000
     81#define UHCI_DEBUGER_TIMEOUT 5000000
    4282
    4383typedef struct uhci {
    44         ddf_fun_t *hc_fun;
    45         ddf_fun_t *rh_fun;
     84        device_keeper_t device_manager;
    4685
    47         uhci_hc_t hc;
    48         uhci_rh_t rh;
     86        regs_t *registers;
     87
     88        link_pointer_t *frame_list;
     89
     90        transfer_list_t transfers_bulk_full;
     91        transfer_list_t transfers_control_full;
     92        transfer_list_t transfers_control_slow;
     93        transfer_list_t transfers_interrupt;
     94
     95        transfer_list_t *transfers[2][4];
     96
     97        irq_code_t interrupt_code;
     98
     99        fid_t cleaner;
     100        fid_t debug_checker;
     101
     102        ddf_fun_t *ddf_instance;
    49103} uhci_t;
    50104
    51 int uhci_init(uhci_t *instance, ddf_dev_t *device);
     105/* init uhci specifics in device.driver_data */
     106int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size);
     107
     108static inline void uhci_fini(uhci_t *instance) {};
     109
     110int uhci_schedule(uhci_t *instance, batch_t *batch);
     111
     112void uhci_interrupt(uhci_t *instance, uint16_t status);
     113
     114static inline uhci_t * dev_to_uhci(ddf_dev_t *dev)
     115        { return (uhci_t*)dev->driver_data; }
     116
     117static inline uhci_t * fun_to_uhci(ddf_fun_t *fun)
     118        { return (uhci_t*)fun->driver_data; }
     119
    52120
    53121#endif
  • uspace/drv/uhci-hcd/uhci_struct/link_pointer.h

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
     
    4646#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
    4747
    48 #define LINK_POINTER_QH(address) \
    49         ((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG)
    50 
    5148#endif
    5249/**
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    rbb41b85 rc32688d  
     1
    12/*
    23 * Copyright (c) 2010 Jan Vesely
     
    2627 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2728 */
    28 /** @addtogroup drv usbuhcihc
     29/** @addtogroup usb
    2930 * @{
    3031 */
     
    4243
    4344typedef struct queue_head {
    44         volatile link_pointer_t next;
     45        volatile link_pointer_t next_queue;
    4546        volatile link_pointer_t element;
    46 } __attribute__((packed)) qh_t;
    47 /*----------------------------------------------------------------------------*/
    48 /** Initialize queue head structure
    49  *
    50  * @param[in] instance qh_t structure to initialize.
    51  *
    52  * Sets both pointer to terminal NULL.
    53  */
    54 static inline void qh_init(qh_t *instance)
     47} __attribute__((packed)) queue_head_t;
     48
     49static inline void queue_head_init(queue_head_t *instance)
    5550{
    5651        assert(instance);
    5752
    5853        instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    59         instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
     54        instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
    6055}
    61 /*----------------------------------------------------------------------------*/
    62 /** Set queue head next pointer
    63  *
    64  * @param[in] instance qh_t structure to use.
    65  * @param[in] pa Physical address of the next queue head.
    66  *
    67  * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal
    68  * NULL.
    69  */
    70 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
     56
     57static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa)
    7158{
    72         /* Address is valid and not terminal */
    73         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    74                 instance->next = (pa & LINK_POINTER_ADDRESS_MASK)
     59        if (pa) {
     60                instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
    7561                    | LINK_POINTER_QUEUE_HEAD_FLAG;
    76         } else {
    77                 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    7862        }
    7963}
    80 /*----------------------------------------------------------------------------*/
    81 /** Set queue head element pointer
    82  *
    83  * @param[in] instance qh_t structure to initialize.
    84  * @param[in] pa Physical address of the next queue head.
    85  *
    86  * Adds proper flag. If the pointer is NULL or terminal, sets element
    87  * to terminal NULL.
    88  */
    89 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
     64
     65static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa)
    9066{
    91         /* Address is valid and not terminal */
    92         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    93                 instance->element = (pa & LINK_POINTER_ADDRESS_MASK)
     67        if (pa) {
     68                instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
    9469                    | LINK_POINTER_QUEUE_HEAD_FLAG;
    95         } else {
    96                 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    9770        }
    9871}
    99 /*----------------------------------------------------------------------------*/
    100 /** Set queue head element pointer
    101  *
    102  * @param[in] instance qh_t structure to initialize.
    103  * @param[in] pa Physical address of the TD structure.
    104  *
    105  * Adds proper flag. If the pointer is NULL or terminal, sets element
    106  * to terminal NULL.
    107  */
    108 static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
     72
     73static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa)
    10974{
    110         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     75        if (pa) {
    11176                instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
    112         } else {
    113                 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    11477        }
    11578}
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
     
    3838#include "utils/malloc32.h"
    3939
    40 /** Initialize Transfer Descriptor
     40/** Initializes Transfer Descriptor
    4141 *
    4242 * @param[in] instance Memory place to initialize.
     
    4444 * @param[in] size Size of data source.
    4545 * @param[in] toggle Value of toggle bit.
    46  * @param[in] iso True if TD represents Isochronous transfer.
     46 * @param[in] iso True if TD is for Isochronous transfer.
    4747 * @param[in] low_speed Target device's speed.
    4848 * @param[in] target Address and endpoint receiving the transfer.
     
    5151 * @param[in] next Net TD in transaction.
    5252 * @return Error code.
    53  *
    54  * Uses a mix of supplied and default values.
    55  * Implicit values:
    56  *  - all TDs have vertical flag set (makes transfers to endpoints atomic)
    57  *  - in the error field only active it is set
    58  *  - if the packet uses PID_IN and is not isochronous SPD is set
    59  *
    60  * Dumps 8 bytes of buffer if PID_SETUP is used.
    6153 */
    6254void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
     
    9688        }
    9789
    98         usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
    99             instance, instance->next, instance->status, instance->device,
     90        usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
     91            instance->next, instance->status, instance->device,
    10092            instance->buffer_ptr, buffer);
    101         td_print_status(instance);
    10293        if (pid == USB_PID_SETUP) {
    10394                usb_log_debug("SETUP BUFFER: %s\n",
    104                     usb_debug_str_buffer(buffer, 8, 8));
     95                        usb_debug_str_buffer(buffer, 8, 8));
    10596        }
    10697}
    10798/*----------------------------------------------------------------------------*/
    108 /** Convert TD status into standard error code
     99/** Converts TD status into standard error code
    109100 *
    110101 * @param[in] instance TD structure to use.
     
    135126        return EOK;
    136127}
    137 /*----------------------------------------------------------------------------*/
    138 /** Print values in status field (dw1) in a human readable way.
    139  *
    140  * @param[in] instance TD structure to use.
    141  */
    142 void td_print_status(td_t *instance)
    143 {
    144         assert(instance);
    145         const uint32_t s = instance->status;
    146         usb_log_debug2("TD(%p) status(%#x):%s %d,%s%s%s%s%s%s%s%s%s%s%s %d.\n",
    147             instance, instance->status,
    148             (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
    149             (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
    150             (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
    151             (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
    152             (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
    153             (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
    154             (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
    155             (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
    156             (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
    157             (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
    158             (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
    159             (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
    160             (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
    161             (s >> TD_STATUS_ACTLEN_POS) & TD_STATUS_ACTLEN_MASK
    162         );
    163 }
    164128/**
    165129 * @}
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    rbb41b85 rc32688d  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2010 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
     
    4545
    4646        volatile uint32_t status;
     47
    4748#define TD_STATUS_RESERVED_MASK 0xc000f800
    4849#define TD_STATUS_SPD_FLAG ( 1 << 29 )
    4950#define TD_STATUS_ERROR_COUNT_POS ( 27 )
    5051#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
     52#define TD_STATUS_ERROR_COUNT_DEFAULT 3
    5153#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
    5254#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
    53 #define TD_STATUS_IOC_FLAG ( 1 << 24 )
     55#define TD_STATUS_COMPLETE_INTERRUPT_FLAG ( 1 << 24 )
    5456
    5557#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
     
    6870
    6971        volatile uint32_t device;
     72
    7073#define TD_DEVICE_MAXLEN_POS 21
    7174#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
     
    8285
    8386        /* there is 16 bytes of data available here, according to UHCI
    84          * Design guide, according to linux kernel the hardware does not care,
    85          * it just needs to be aligned, we don't use it anyway
     87         * Design guide, according to linux kernel the hardware does not care
     88         * we don't use it anyway
    8689         */
    8790} __attribute__((packed)) td_t;
    8891
    8992
    90 void td_init(td_t *instance, int error_count, size_t size, bool toggle,
    91     bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
    92     void *buffer, td_t *next);
     93void td_init(td_t *instance, int error_count, size_t size, bool toggle, bool iso,
     94    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
     95    td_t *next);
    9396
    9497int td_status(td_t *instance);
    9598
    96 void td_print_status(td_t *instance);
    97 /*----------------------------------------------------------------------------*/
    98 /** Helper function for parsing actual size out of TD.
    99  *
    100  * @param[in] instance TD structure to use.
    101  * @return Parsed actual size.
    102  */
    10399static inline size_t td_act_size(td_t *instance)
    104100{
    105101        assert(instance);
    106         const uint32_t s = instance->status;
    107         return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
     102        return
     103            ((instance->status >> TD_STATUS_ACTLEN_POS) + 1)
     104            & TD_STATUS_ACTLEN_MASK;
    108105}
    109 /*----------------------------------------------------------------------------*/
    110 /** Check whether less than max data were recieved and packet is marked as SPD.
    111  *
    112  * @param[in] instance TD structure to use.
    113  * @return True if packet is short (less than max bytes and SPD set), false
    114  *     otherwise.
    115  */
     106
    116107static inline bool td_is_short(td_t *instance)
    117108{
     
    123114            (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
    124115}
    125 /*----------------------------------------------------------------------------*/
    126 /** Helper function for parsing value of toggle bit.
    127  *
    128  * @param[in] instance TD structure to use.
    129  * @return Toggle bit value.
    130  */
     116
    131117static inline int td_toggle(td_t *instance)
    132118{
    133119        assert(instance);
    134         return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
     120        return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0)
     121            ? 1 : 0;
    135122}
    136 /*----------------------------------------------------------------------------*/
    137 /** Helper function for parsing value of active bit
    138  *
    139  * @param[in] instance TD structure to use.
    140  * @return Active bit value.
    141  */
     123
    142124static inline bool td_is_active(td_t *instance)
    143125{
     
    145127        return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
    146128}
    147 /*----------------------------------------------------------------------------*/
    148 /** Helper function for setting IOC bit.
    149  *
    150  * @param[in] instance TD structure to use.
    151  */
    152 static inline void td_set_ioc(td_t *instance)
    153 {
    154         assert(instance);
    155         instance->status |= TD_STATUS_IOC_FLAG;
    156 }
    157 /*----------------------------------------------------------------------------*/
    158129#endif
    159130/**
  • uspace/drv/uhci-hcd/utils/device_keeper.c

    rbb41b85 rc32688d  
    2727 */
    2828
    29 /** @addtogroup drvusbuhcihc
     29/** @addtogroup drvusbuhci
    3030 * @{
    3131 */
     
    4040
    4141/*----------------------------------------------------------------------------*/
    42 /** Initialize device keeper structure.
     42/** Initializes device keeper structure.
    4343 *
    4444 * @param[in] instance Memory place to initialize.
    45  *
    46  * Set all values to false/0.
    4745 */
    4846void device_keeper_init(device_keeper_t *instance)
     
    6058}
    6159/*----------------------------------------------------------------------------*/
    62 /** Attempt to obtain address 0, blocks.
     60/** Attempts to obtain address 0, blocks.
    6361 *
    6462 * @param[in] instance Device keeper structure to use.
     
    7876}
    7977/*----------------------------------------------------------------------------*/
    80 /** Attempt to obtain address 0, blocks.
     78/** Attempts to obtain address 0, blocks.
    8179 *
    8280 * @param[in] instance Device keeper structure to use.
     
    9290}
    9391/*----------------------------------------------------------------------------*/
    94 /** Check setup packet data for signs of toggle reset.
     92/** Checks setup data for signs of toggle reset.
    9593 *
    9694 * @param[in] instance Device keeper structure to use.
    9795 * @param[in] target Device to receive setup packet.
    9896 * @param[in] data Setup packet data.
    99  *
    100  * Really ugly one.
    10197 */
    10298void device_keeper_reset_if_need(
     
    109105            || !instance->devices[target.address].occupied) {
    110106                fibril_mutex_unlock(&instance->guard);
    111                 usb_log_error("Invalid data when checking for toggle reset.\n");
    112107                return;
    113108        }
     
    135130}
    136131/*----------------------------------------------------------------------------*/
    137 /** Get current value of endpoint toggle.
     132/** Gets current value of endpoint toggle.
    138133 *
    139134 * @param[in] instance Device keeper structure to use.
     
    149144            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    150145            || !instance->devices[target.address].occupied) {
    151                 usb_log_error("Invalid data when asking for toggle value.\n");
    152146                ret = EINVAL;
    153147        } else {
    154                 ret = (instance->devices[target.address].toggle_status
     148                ret =
     149                    (instance->devices[target.address].toggle_status
    155150                        >> target.endpoint) & 1;
    156151        }
     
    159154}
    160155/*----------------------------------------------------------------------------*/
    161 /** Set current value of endpoint toggle.
     156/** Sets current value of endpoint toggle.
    162157 *
    163158 * @param[in] instance Device keeper structure to use.
    164159 * @param[in] target Device and endpoint used.
    165  * @param[in] toggle Toggle value.
     160 * @param[in] toggle Current toggle value.
    166161 * @return Error code.
    167162 */
     
    175170            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    176171            || !instance->devices[target.address].occupied) {
    177                 usb_log_error("Invalid data when setting toggle value.\n");
    178172                ret = EINVAL;
    179173        } else {
     
    189183}
    190184/*----------------------------------------------------------------------------*/
    191 /** Get a free USB address
     185/** Gets a free USB address
    192186 *
    193187 * @param[in] instance Device keeper structure to use.
     
    222216}
    223217/*----------------------------------------------------------------------------*/
    224 /** Bind USB address to devman handle.
     218/** Binds USB address to devman handle.
    225219 *
    226220 * @param[in] instance Device keeper structure to use.
     
    240234}
    241235/*----------------------------------------------------------------------------*/
    242 /** Release used USB address.
     236/** Releases used USB address.
    243237 *
    244238 * @param[in] instance Device keeper structure to use.
     
    257251}
    258252/*----------------------------------------------------------------------------*/
    259 /** Find USB address associated with the device
     253/** Finds USB address associated with the device
    260254 *
    261255 * @param[in] instance Device keeper structure to use.
     
    280274}
    281275/*----------------------------------------------------------------------------*/
    282 /** Get speed associated with the address
     276/** Gets speed associated with the address
    283277 *
    284278 * @param[in] instance Device keeper structure to use.
  • uspace/drv/uhci-hcd/utils/device_keeper.h

    rbb41b85 rc32688d  
    2727 */
    2828
    29 /** @addtogroup drvusbuhcihc
     29/** @addtogroup drvusbuhci
    3030 * @{
    3131 */
  • uspace/drv/uhci-hcd/utils/malloc32.h

    rbb41b85 rc32688d  
    4343#define UHCI_REQUIRED_PAGE_SIZE 4096
    4444
    45 /** Get physical address translation
    46  *
    47  * @param[in] addr Virtual address to translate
    48  * @return Physical address if exists, NULL otherwise.
    49  */
    5045static inline uintptr_t addr_to_phys(void *addr)
    5146{
     
    5348        int ret = as_get_physical_mapping(addr, &result);
    5449
    55         if (ret != EOK)
    56                 return 0;
     50        assert(ret == 0);
    5751        return (result | ((uintptr_t)addr & 0xfff));
    5852}
    59 /*----------------------------------------------------------------------------*/
    60 /** Physical mallocator simulator
    61  *
    62  * @param[in] size Size of the required memory space
    63  * @return Address of the alligned and big enough memory place, NULL on failure.
    64  */
     53
    6554static inline void * malloc32(size_t size)
    6655        { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
    67 /*----------------------------------------------------------------------------*/
    68 /** Physical mallocator simulator
    69  *
    70  * @param[in] addr Address of the place allocated by malloc32
    71  */
    72 static inline void free32(void *addr)
    73         { if (addr) free(addr); }
    74 /*----------------------------------------------------------------------------*/
    75 /** Create 4KB page mapping
    76  *
    77  * @return Address of the mapped page, NULL on failure.
    78  */
    79 static inline void * get_page(void)
     56
     57static inline void * get_page()
    8058{
    8159        void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
    8260        assert(free_address);
    8361        if (free_address == 0)
    84                 return NULL;
     62                return 0;
    8563        void* ret =
    8664          as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
    8765                  AS_AREA_READ | AS_AREA_WRITE);
    8866        if (ret != free_address)
    89                 return NULL;
     67                return 0;
    9068        return ret;
    9169}
     70
     71static inline void free32(void *addr)
     72        { if (addr) free(addr); }
    9273
    9374#endif
  • uspace/drv/uhci-rhd/Makefile

    rbb41b85 rc32688d  
    3535        main.c \
    3636        port.c \
     37        port_status.c \
    3738        root_hub.c
    3839
  • uspace/drv/uhci-rhd/main.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub initialization routines
     32 * @brief UHCI driver
    3333 */
    3434#include <ddf/driver.h>
     
    4040#include <usb/debug.h>
    4141
     42
     43
    4244#include "root_hub.h"
    4345
     
    4547static int hc_get_my_registers(ddf_dev_t *dev,
    4648    uintptr_t *io_reg_address, size_t *io_reg_size);
    47 #if 0
    4849/*----------------------------------------------------------------------------*/
    4950static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
     
    6667        .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
    6768};
    68 #endif
    6969/*----------------------------------------------------------------------------*/
    70 /** Initialize a new ddf driver instance of UHCI root hub.
     70/** Initializes a new ddf driver instance of UHCI root hub.
    7171 *
    7272 * @param[in] device DDF instance of the device to initialize.
     
    8181
    8282        //device->ops = &uhci_rh_ops;
     83        (void) uhci_rh_ops;
     84
     85        uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
     86        if (!rh) {
     87                usb_log_error("Failed to allocate memory for driver instance.\n");
     88                return ENOMEM;
     89        }
     90
    8391        uintptr_t io_regs = 0;
    8492        size_t io_size = 0;
    8593
    8694        int ret = hc_get_my_registers(device, &io_regs, &io_size);
    87         if (ret != EOK) {
    88                 usb_log_error("Failed(%d) to get registers from parent hc.",
    89                     ret);
    90         }
    91         usb_log_info("I/O regs at %#X (size %zu).\n", io_regs, io_size);
     95        assert(ret == EOK);
    9296
    93         uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
    94         if (!rh) {
    95                 usb_log_error("Failed to allocate driver instance.\n");
    96                 return ENOMEM;
    97         }
    98 
     97        /* TODO: verify values from hc */
     98        usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size);
    9999        ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
    100100        if (ret != EOK) {
     
    119119};
    120120/*----------------------------------------------------------------------------*/
    121 /** Initialize global driver structures (NONE).
     121/** Initializes global driver structures (NONE).
    122122 *
    123123 * @param[in] argc Nmber of arguments in argv vector (ignored).
  • uspace/drv/uhci-rhd/port.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub port routines
    33  */
    34 #include <libarch/ddi.h> /* pio_read and pio_write */
     32 * @brief UHCI driver
     33 */
    3534#include <errno.h>
    3635#include <str_error.h>
     
    3837
    3938#include <usb/usb.h>    /* usb_address_t */
     39#include <usb/usbdevice.h>
    4040#include <usb/hub.h>
     41#include <usb/request.h>
    4142#include <usb/debug.h>
     43#include <usb/recognise.h>
    4244
    4345#include "port.h"
     46#include "port_status.h"
    4447
    4548static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
     
    4851static int uhci_port_check(void *port);
    4952static int uhci_port_reset_enable(int portno, void *arg);
    50 static void uhci_port_print_status(
    51     uhci_port_t *port, const port_status_t value);
    52 
    53 /** Register reading helper function.
    54  *
    55  * @param[in] port Structure to use.
    56  * @return Error code. (Always EOK)
    57  */
    58 static inline port_status_t uhci_port_read_status(uhci_port_t *port)
    59 {
    60         assert(port);
    61         return pio_read_16(port->address);
    62 }
    63 /*----------------------------------------------------------------------------*/
    64 /** Register writing helper function.
    65  *
    66  * @param[in] port Structure to use.
    67  * @param[in] value New register value.
    68  * @return Error code. (Always EOK)
    69  */
    70 static inline void uhci_port_write_status(
    71     uhci_port_t *port, port_status_t value)
    72 {
    73         assert(port);
    74         pio_write_16(port->address, value);
    75 }
    76 
    77 /*----------------------------------------------------------------------------*/
    78 /** Initialize UHCI root hub port instance.
     53/*----------------------------------------------------------------------------*/
     54/** Initializes UHCI root hub port instance.
    7955 *
    8056 * @param[in] port Memory structure to use.
     
    8561 * @return Error code.
    8662 *
    87  * Creates and starts the polling fibril.
     63 * Starts the polling fibril.
    8864 */
    8965int uhci_port_init(uhci_port_t *port,
     
    9167{
    9268        assert(port);
    93         asprintf(&port->id_string, "Port (%p - %d)", port, number);
    94         if (port->id_string == NULL) {
    95                 return ENOMEM;
    96         }
    9769
    9870        port->address = address;
     
    11183        port->checker = fibril_create(uhci_port_check, port);
    11284        if (port->checker == 0) {
    113                 usb_log_error("%s: failed to create polling fibril.",
    114                     port->id_string);
     85                usb_log_error("Port(%p - %d): failed to launch root hub fibril.",
     86                    port->address, port->number);
    11587                return ENOMEM;
    11688        }
    11789
    11890        fibril_add_ready(port->checker);
    119         usb_log_debug("%s: Started polling fibril(%x).\n",
    120             port->id_string, port->checker);
    121         return EOK;
    122 }
    123 /*----------------------------------------------------------------------------*/
    124 /** Cleanup UHCI root hub port instance.
     91        usb_log_debug("Port(%p - %d): Added fibril. %x\n",
     92            port->address, port->number, port->checker);
     93        return EOK;
     94}
     95/*----------------------------------------------------------------------------*/
     96/** Finishes UHCI root hub port instance.
    12597 *
    12698 * @param[in] port Memory structure to use.
     
    130102void uhci_port_fini(uhci_port_t *port)
    131103{
    132         assert(port);
    133         free(port->id_string);
    134104        /* TODO: Kill fibril here */
    135105        return;
     
    138108/** Periodically checks port status and reports new devices.
    139109 *
    140  * @param[in] port Port structure to use.
     110 * @param[in] port Memory structure to use.
    141111 * @return Error code.
    142112 */
     
    146116        assert(instance);
    147117
     118        /* Iteration count, for debug purposes only */
     119        unsigned count = 0;
     120
    148121        while (1) {
    149122                async_usleep(instance->wait_period_usec);
    150123
    151                 /* Read register value */
    152                 port_status_t port_status = uhci_port_read_status(instance);
    153 
    154                 /* Print the value if it's interesting */
    155                 if (port_status & ~STATUS_ALWAYS_ONE)
    156                         uhci_port_print_status(instance, port_status);
     124                /* read register value */
     125                port_status_t port_status = port_status_read(instance->address);
     126
     127                /* debug print mutex */
     128                static fibril_mutex_t dbg_mtx =
     129                    FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
     130                fibril_mutex_lock(&dbg_mtx);
     131                usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n",
     132                  instance->address, instance->number, port_status, count++);
     133//              print_port_status(port_status);
     134                fibril_mutex_unlock(&dbg_mtx);
    157135
    158136                if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
    159137                        continue;
    160138
    161                 usb_log_debug("%s: Connected change detected: %x.\n",
    162                     instance->id_string, port_status);
     139                usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
     140                    instance->address, instance->number, port_status);
    163141
    164142                int rc =
    165143                    usb_hc_connection_open(&instance->hc_connection);
    166144                if (rc != EOK) {
    167                         usb_log_error("%s: Failed to connect to HC.",
    168                             instance->id_string);
     145                        usb_log_error("Port(%p - %d): Failed to connect to HC.",
     146                            instance->address, instance->number);
    169147                        continue;
    170148                }
     
    172150                /* Remove any old device */
    173151                if (instance->attached_device) {
    174                         usb_log_debug2("%s: Removing device.\n",
    175                             instance->id_string);
     152                        usb_log_debug2("Port(%p - %d): Removing device.\n",
     153                            instance->address, instance->number);
    176154                        uhci_port_remove_device(instance);
    177155                }
     
    185163                } else {
    186164                        /* Write one to WC bits, to ack changes */
    187                         uhci_port_write_status(instance, port_status);
    188                         usb_log_debug("%s: status change ACK.\n",
    189                             instance->id_string);
     165                        port_status_write(instance->address, port_status);
     166                        usb_log_debug("Port(%p - %d): Change status ACK.\n",
     167                            instance->address, instance->number);
    190168                }
    191169
    192170                rc = usb_hc_connection_close(&instance->hc_connection);
    193171                if (rc != EOK) {
    194                         usb_log_error("%s: Failed to disconnect.",
    195                             instance->id_string);
     172                        usb_log_error("Port(%p - %d): Failed to disconnect.",
     173                            instance->address, instance->number);
    196174                }
    197175        }
     
    204182 * @param arg Pointer to uhci_port_t of port with the new device.
    205183 * @return Error code.
    206  *
    207  * Resets and enables the ub port.
    208184 */
    209185int uhci_port_reset_enable(int portno, void *arg)
     
    211187        uhci_port_t *port = (uhci_port_t *) arg;
    212188
    213         usb_log_debug2("%s: new_device_enable_port.\n", port->id_string);
     189        usb_log_debug2("Port(%p - %d): new_device_enable_port.\n",
     190            port->address, port->number);
    214191
    215192        /*
     
    219196        async_usleep(100000);
    220197
    221         /*
    222          * Resets from root ports should be nominally 50ms
     198
     199        /* The hub maintains the reset signal to that port for 10 ms
     200         * (See Section 11.5.1.5)
    223201         */
    224202        {
    225                 usb_log_debug("%s: Reset Signal start.\n", port->id_string);
    226                 port_status_t port_status = uhci_port_read_status(port);
     203                usb_log_debug("Port(%p - %d): Reset Signal start.\n",
     204                    port->address, port->number);
     205                port_status_t port_status =
     206                        port_status_read(port->address);
    227207                port_status |= STATUS_IN_RESET;
    228                 uhci_port_write_status(port, port_status);
    229                 async_usleep(50000);
    230                 port_status = uhci_port_read_status(port);
     208                port_status_write(port->address, port_status);
     209                async_usleep(10000);
     210                port_status = port_status_read(port->address);
    231211                port_status &= ~STATUS_IN_RESET;
    232                 uhci_port_write_status(port, port_status);
    233                 usb_log_debug("%s: Reset Signal stop.\n", port->id_string);
    234         }
    235 
    236         /* the reset recovery time 10ms */
    237         async_usleep(10000);
     212                port_status_write(port->address, port_status);
     213                usb_log_debug("Port(%p - %d): Reset Signal stop.\n",
     214                    port->address, port->number);
     215        }
    238216
    239217        /* Enable the port. */
    240218        uhci_port_set_enabled(port, true);
    241 
    242         return EOK;
    243 }
    244 /*----------------------------------------------------------------------------*/
    245 /** Initialize and report connected device.
    246  *
    247  * @param[in] port Port structure to use.
     219        return EOK;
     220}
     221/*----------------------------------------------------------------------------*/
     222/** Initializes and reports connected device.
     223 *
     224 * @param[in] port Memory structure to use.
    248225 * @param[in] speed Detected speed.
    249226 * @return Error code.
     
    256233        assert(usb_hc_connection_is_opened(&port->hc_connection));
    257234
    258         usb_log_info("%s: Detected new device.\n", port->id_string);
     235        usb_log_info("Port(%p-%d): Detected new device.\n",
     236            port->address, port->number);
    259237
    260238        usb_address_t dev_addr;
     
    264242
    265243        if (rc != EOK) {
    266                 usb_log_error("%s: Failed(%d) to add device: %s.\n",
    267                     port->id_string, rc, str_error(rc));
     244                usb_log_error("Port(%p-%d): Failed(%d) to add device: %s.\n",
     245                    port->address, port->number, rc, str_error(rc));
    268246                uhci_port_set_enabled(port, false);
    269247                return rc;
    270248        }
    271249
    272         usb_log_info("%s: New device has address %d (handle %zu).\n",
    273             port->id_string, dev_addr, port->attached_device);
    274 
    275         return EOK;
    276 }
    277 /*----------------------------------------------------------------------------*/
    278 /** Remove device.
    279  *
    280  * @param[in] port Memory structure to use.
    281  * @return Error code.
    282  *
    283  * Does not work, DDF does not support device removal.
    284  * Does not even free used USB address (it would be dangerous if tis driver
    285  * is still running).
     250        usb_log_info("Port(%p-%d): New device has address %d (handle %zu).\n",
     251            port->address, port->number, dev_addr, port->attached_device);
     252
     253        return EOK;
     254}
     255/*----------------------------------------------------------------------------*/
     256/** Removes device.
     257 *
     258 * @param[in] port Memory structure to use.
     259 * @return Error code.
     260 *
     261 * Does not work DDF does not support device removal.
    286262 */
    287263int uhci_port_remove_device(uhci_port_t *port)
    288264{
    289         usb_log_error("%s: Don't know how to remove device %d.\n",
    290             port->id_string, (unsigned int)port->attached_device);
    291         return EOK;
    292 }
    293 /*----------------------------------------------------------------------------*/
    294 /** Enable or disable root hub port.
    295  *
    296  * @param[in] port Port structure to use.
    297  * @param[in] enabled Port status to set.
     265        usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n",
     266            port->address, port->number, (unsigned int)port->attached_device);
     267        return EOK;
     268}
     269/*----------------------------------------------------------------------------*/
     270/** Enables and disables port.
     271 *
     272 * @param[in] port Memory structure to use.
    298273 * @return Error code. (Always EOK)
    299274 */
     
    303278
    304279        /* Read register value */
    305         port_status_t port_status = uhci_port_read_status(port);
     280        port_status_t port_status = port_status_read(port->address);
    306281
    307282        /* Set enabled bit */
     
    313288
    314289        /* Write new value. */
    315         uhci_port_write_status(port, port_status);
    316 
    317         usb_log_info("%s: %sabled port.\n",
    318                 port->id_string, enabled ? "En" : "Dis");
    319         return EOK;
    320 }
    321 /*----------------------------------------------------------------------------*/
    322 /** Print the port status value in a human friendly way
    323  *
    324  * @param[in] port Port structure to use.
    325  * @param[in] value Port register value to print.
    326  * @return Error code. (Always EOK)
    327  */
    328 void uhci_port_print_status(uhci_port_t *port, const port_status_t value)
    329 {
    330         assert(port);
    331         usb_log_debug2("%s Port status(%#x):%s%s%s%s%s%s%s%s%s%s%s.\n",
    332             port->id_string, value,
    333             (value & STATUS_SUSPEND) ? " SUSPENDED," : "",
    334             (value & STATUS_RESUME) ? " IN RESUME," : "",
    335             (value & STATUS_IN_RESET) ? " IN RESET," : "",
    336             (value & STATUS_LINE_D_MINUS) ? " VD-," : "",
    337             (value & STATUS_LINE_D_PLUS) ? " VD+," : "",
    338             (value & STATUS_LOW_SPEED) ? " LOWSPEED," : "",
    339             (value & STATUS_ENABLED_CHANGED) ? " ENABLED-CHANGE," : "",
    340             (value & STATUS_ENABLED) ? " ENABLED," : "",
    341             (value & STATUS_CONNECTED_CHANGED) ? " CONNECTED-CHANGE," : "",
    342             (value & STATUS_CONNECTED) ? " CONNECTED," : "",
    343             (value & STATUS_ALWAYS_ONE) ? " ALWAYS ONE" : " ERROR: NO ALWAYS ONE"
    344         );
    345 }
     290        port_status_write(port->address, port_status);
     291
     292        usb_log_info("Port(%p-%d): %sabled port.\n",
     293                port->address, port->number, enabled ? "En" : "Dis");
     294        return EOK;
     295}
     296/*----------------------------------------------------------------------------*/
    346297/**
    347298 * @}
  • uspace/drv/uhci-rhd/port.h

    rbb41b85 rc32688d  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2010 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub port routines
     32 * @brief UHCI port driver
    3333 */
    3434#ifndef DRV_UHCI_PORT_H
    3535#define DRV_UHCI_PORT_H
    3636
     37#include <assert.h>
     38#include <ddf/driver.h>
    3739#include <stdint.h>
    38 #include <fibril.h>
    39 #include <ddf/driver.h>
    40 #include <usb/usbdevice.h> /* usb_hc_connection_t */
     40#include <usb/usbdevice.h>
    4141
    42 typedef uint16_t port_status_t;
    43 #define STATUS_CONNECTED         (1 << 0)
    44 #define STATUS_CONNECTED_CHANGED (1 << 1)
    45 #define STATUS_ENABLED           (1 << 2)
    46 #define STATUS_ENABLED_CHANGED   (1 << 3)
    47 #define STATUS_LINE_D_PLUS       (1 << 4)
    48 #define STATUS_LINE_D_MINUS      (1 << 5)
    49 #define STATUS_RESUME            (1 << 6)
    50 #define STATUS_ALWAYS_ONE        (1 << 7)
    51 
    52 #define STATUS_LOW_SPEED (1 <<  8)
    53 #define STATUS_IN_RESET  (1 <<  9)
    54 #define STATUS_SUSPEND   (1 << 12)
     42#include "port_status.h"
    5543
    5644typedef struct uhci_port
    5745{
    58         char *id_string;
    5946        port_status_t *address;
    6047        unsigned number;
     
    7158
    7259void uhci_port_fini(uhci_port_t *port);
    73 
    7460#endif
    7561/**
  • uspace/drv/uhci-rhd/root_hub.c

    rbb41b85 rc32688d  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub driver
     32 * @brief UHCI driver
    3333 */
    3434#include <errno.h>
     35#include <stdint.h>
    3536#include <ddi.h>
     37#include <devman.h>
    3638#include <usb/debug.h>
    3739
    3840#include "root_hub.h"
    3941
    40 /** Initialize UHCI root hub instance.
     42/** Initializes UHCI root hub instance.
    4143 *
    4244 * @param[in] instance Driver memory structure to use.
    4345 * @param[in] addr Address of I/O registers.
    4446 * @param[in] size Size of available I/O space.
    45  * @param[in] rh Pointer to ddf instance of the root hub driver.
     47 * @param[in] rh Pointer to ddf instance fo the root hub driver.
    4648 * @return Error code.
    4749 */
     
    5961        if (ret < 0) {
    6062                usb_log_error(
    61                     "Failed(%d) to gain access to port registers at %p\n",
    62                     ret, regs);
     63                    "Failed to gain access to port registers at %p\n", regs);
    6364                return ret;
    6465        }
    6566
    66         /* Initialize root hub ports */
     67        /* add fibrils for periodic port checks */
    6768        unsigned i = 0;
    6869        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
     
    8182}
    8283/*----------------------------------------------------------------------------*/
    83 /** Cleanup UHCI root hub instance.
     84/** Finishes UHCI root hub instance.
    8485 *
    85  * @param[in] instance Root hub structure to use.
     86 * @param[in] instance Driver memory structure to use.
    8687 * @return Error code.
    8788 */
  • uspace/drv/uhci-rhd/root_hub.h

    rbb41b85 rc32688d  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2010 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
     
    3535#define DRV_UHCI_ROOT_HUB_H
    3636
     37#include <fibril.h>
    3738#include <ddf/driver.h>
    3839
  • uspace/drv/usbhid/hiddev.c

    rbb41b85 rc32688d  
    411411                return rc;
    412412        }
    413         rc = usb_endpoint_pipe_probe_default_control(&hid_dev->ctrl_pipe);
    414         if (rc != EOK) {
    415                 usb_log_error("Probing default control pipe failed: %s.\n",
    416                     str_error(rc));
    417                 return rc;
    418         }
    419 
     413       
    420414        /*
    421415         * Initialize the report parser.
  • uspace/drv/usbhub/usbhub.c

    rbb41b85 rc32688d  
    7272int usb_hub_control_loop(void * hub_info_param){
    7373        usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param;
    74         int errorCode = EOK;
    75 
    76         while(errorCode == EOK){
    77                 errorCode = usb_hub_check_hub_changes(hub_info);
     74        while(true){
     75                usb_hub_check_hub_changes(hub_info);
    7876                async_usleep(1000 * 1000 );/// \TODO proper number once
    7977        }
    80         dprintf(USB_LOG_LEVEL_ERROR,
    81                                 "something in ctrl loop went wrong, errno %d",errorCode);
    8278        return 0;
    8379}
     
    122118                dprintf(USB_LOG_LEVEL_ERROR,
    123119                                "could not initialize connection to device endpoint, errno %d",opResult);
    124                 return opResult;
    125         }
    126 
    127         opResult = usb_endpoint_pipe_probe_default_control(&hub->endpoints.control);
    128         if (opResult != EOK) {
    129                 dprintf(USB_LOG_LEVEL_ERROR, "failed probing endpoint 0, %d", opResult);
    130                 return opResult;
    131         }
    132 
    133         return EOK;
     120        }
     121        return opResult;
    134122}
    135123
     
    384372 * @param target
    385373 */
    386 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,
    387                 bool isLowSpeed) {
     374static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port) {
    388375        usb_device_request_setup_packet_t request;
    389376        int opResult;
     
    391378        assert(hub->endpoints.control.hc_phone);
    392379        //get default address
    393         usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
    394         opResult = usb_hc_reserve_default_address(&hub->connection, speed);
     380        //opResult = usb_drv_reserve_default_address(hc);
     381        opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
    395382       
    396383        if (opResult != EOK) {
     
    443430                        &new_device_pipe,
    444431                        &new_device_connection);
    445         usb_endpoint_pipe_probe_default_control(&new_device_pipe);
    446432        /// \TODO get highspeed info
    447433        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
     
    451437        usb_address_t new_device_address = usb_hc_request_address(
    452438                        &hub->connection,
    453                         speed
     439                        speed/// \TODO fullspeed??
    454440                        );
    455441        if (new_device_address < 0) {
     
    515501static void usb_hub_removed_device(
    516502    usb_hub_info_t * hub,uint16_t port) {
    517                
     503        //usb_device_request_setup_packet_t request;
     504        int opResult;
     505       
    518506        /** \TODO remove device from device manager - not yet implemented in
    519507         * devide manager
     
    522510        //close address
    523511        if(hub->attached_devs[port].address!=0){
    524                 /*uncomment this code to use it when DDF allows device removal
     512                //opResult = usb_drv_release_address(hc,hub->attached_devs[port].address);
    525513                opResult = usb_hc_unregister_device(
    526514                                &hub->connection, hub->attached_devs[port].address);
     
    531519                hub->attached_devs[port].address = 0;
    532520                hub->attached_devs[port].handle = 0;
    533                  */
    534521        }else{
    535522                dprintf(USB_LOG_LEVEL_WARNING, "this is strange, disconnected device had no address");
     
    601588                if (usb_port_dev_connected(&status)) {
    602589                        dprintf(USB_LOG_LEVEL_INFO, "some connection changed");
    603                         usb_hub_init_add_device(hub, port, usb_port_low_speed(&status));
     590                        usb_hub_init_add_device(hub, port);
    604591                } else {
    605592                        usb_hub_removed_device(hub, port);
     
    639626/**
    640627 * Check changes on particular hub
    641  * @param hub_info_param pointer to usb_hub_info_t structure
    642  * @return error code if there is problem when initializing communication with
    643  * hub, EOK otherwise
    644  */
    645 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
     628 * @param hub_info_param
     629 */
     630void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
    646631        int opResult;
    647632        opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
     
    649634                dprintf(USB_LOG_LEVEL_ERROR,
    650635                                "could not initialize communication for hub; %d", opResult);
    651                 return opResult;
     636                return;
    652637        }
    653638
     
    671656                dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
    672657                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    673                 return opResult;
     658                return;
    674659        }
    675660        unsigned int port;
     
    679664                                opResult);
    680665                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    681                 return opResult;
     666                return;
    682667        }
    683668        opResult = usb_hc_connection_open(&hub_info->connection);
     
    687672                usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
    688673                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    689                 return opResult;
     674                return;
    690675        }
    691676
     
    703688        usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    704689        free(change_bitmap);
    705         return EOK;
    706690}
    707691
  • uspace/drv/usbhub/usbhub.h

    rbb41b85 rc32688d  
    8787
    8888/**
    89  * Check changes on specified hub
     89 * check changes on specified hub
    9090 * @param hub_info_param pointer to usb_hub_info_t structure
    91  * @return error code if there is problem when initializing communication with
    92  * hub, EOK otherwise
    9391 */
    94 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
     92void usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
    9593
    9694
  • uspace/drv/usbmid/usbmid.c

    rbb41b85 rc32688d  
    116116                return NULL;
    117117        }
    118         rc = usb_endpoint_pipe_probe_default_control(&mid->ctrl_pipe);
    119         if (rc != EOK) {
    120                 usb_log_error("Probing default control pipe failed: %s.\n",
    121                     str_error(rc));
    122                 free(mid);
    123                 return NULL;
    124         }
    125118
    126119        mid->dev = dev;
  • uspace/drv/usbmouse/init.c

    rbb41b85 rc32688d  
    4242
    4343/** Mouse polling endpoint description for boot protocol subclass. */
    44 usb_endpoint_description_t poll_endpoint_description = {
     44static usb_endpoint_description_t poll_endpoint_description = {
    4545        .transfer_type = USB_TRANSFER_INTERRUPT,
    4646        .direction = USB_DIRECTION_IN,
     
    5151};
    5252
     53/** Initialize poll pipe.
     54 *
     55 * Expects that session is already started on control pipe zero.
     56 *
     57 * @param mouse Mouse device.
     58 * @param my_interface Interface number.
     59 * @return Error code.
     60 */
     61static int intialize_poll_pipe(usb_mouse_t *mouse, int my_interface)
     62{
     63        assert(usb_endpoint_pipe_is_session_started(&mouse->ctrl_pipe));
     64
     65        int rc;
     66
     67        void *config_descriptor;
     68        size_t config_descriptor_size;
     69
     70        rc = usb_request_get_full_configuration_descriptor_alloc(
     71            &mouse->ctrl_pipe, 0, &config_descriptor, &config_descriptor_size);
     72        if (rc != EOK) {
     73                return rc;
     74        }
     75
     76        usb_endpoint_mapping_t endpoint_mapping[1] = {
     77                {
     78                        .pipe = &mouse->poll_pipe,
     79                        .description = &poll_endpoint_description,
     80                        .interface_no = my_interface
     81                }
     82        };
     83
     84        rc = usb_endpoint_pipe_initialize_from_configuration(endpoint_mapping,
     85            1, config_descriptor, config_descriptor_size, &mouse->wire);
     86        if (rc != EOK) {
     87                return rc;
     88        }
     89
     90        if (!endpoint_mapping[0].present) {
     91                return ENOENT;
     92        }
     93
     94        mouse->poll_interval_us = 1000 * endpoint_mapping[0].descriptor->poll_interval;
     95
     96        usb_log_debug("prepared polling endpoint %d (interval %zu).\n",
     97            mouse->poll_pipe.endpoint_no, mouse->poll_interval_us);
     98
     99        return EOK;
     100}
     101
    53102static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    54103/** Device ops for USB mouse. */
     
    94143 * @return Error code.
    95144 */
    96 int usb_mouse_create(usb_device_t *dev)
     145int usb_mouse_create(ddf_dev_t *dev)
    97146{
    98147        usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
     
    100149                return ENOMEM;
    101150        }
    102         mouse->dev = dev;
     151        mouse->device = dev;
    103152        mouse->console_phone = -1;
    104153
    105154        int rc;
    106155
     156        /* Initialize the backing connection. */
     157        rc = usb_device_connection_initialize_from_device(&mouse->wire, dev);
     158        if (rc != EOK) {
     159                goto leave;
     160        }
     161
     162        /* Initialize the default control pipe. */
     163        rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe,
     164            &mouse->wire);
     165        if (rc != EOK) {
     166                goto leave;
     167        }
     168
     169        rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe);
     170        if (rc != EOK) {
     171                goto leave;
     172        }
     173
     174        rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev));
     175
     176        /* We can ignore error here. */
     177        usb_endpoint_pipe_end_session(&mouse->ctrl_pipe);
     178
     179        if (rc != EOK) {
     180                goto leave;
     181        }
     182
    107183        /* Create DDF function. */
    108         mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
     184        mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
    109185        if (mouse->mouse_fun == NULL) {
    110186                rc = ENOMEM;
  • uspace/drv/usbmouse/main.c

    rbb41b85 rc32688d  
    4444 * @return Error code.
    4545 */
    46 static int usbmouse_add_device(usb_device_t *dev)
     46static int usbmouse_add_device(ddf_dev_t *dev)
    4747{
    4848        int rc = usb_mouse_create(dev);
     
    5353        }
    5454
    55         usb_log_debug("Polling pipe at endpoint %d.\n", dev->pipes[0].pipe->endpoint_no);
    56 
    57         rc = usb_device_auto_poll(dev, 0,
    58             usb_mouse_polling_callback, dev->pipes[0].pipe->max_packet_size,
    59             usb_mouse_polling_ended_callback, dev->driver_data);
    60 
    61         if (rc != EOK) {
    62                 usb_log_error("Failed to start polling fibril: %s.\n",
    63                     str_error(rc));
    64                 return rc;
     55        fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev);
     56        if (poll_fibril == 0) {
     57                usb_log_error("Failed to initialize polling fibril.\n");
     58                /* FIXME: free allocated resources. */
     59                return ENOMEM;
    6560        }
    6661
     62        fibril_add_ready(poll_fibril);
     63
    6764        usb_log_info("controlling new mouse (handle %llu).\n",
    68             dev->ddf_dev->handle);
     65            dev->handle);
    6966
    7067        return EOK;
     
    7269
    7370/** USB mouse driver ops. */
    74 static usb_driver_ops_t mouse_driver_ops = {
     71static driver_ops_t mouse_driver_ops = {
    7572        .add_device = usbmouse_add_device,
    7673};
    7774
    78 static usb_endpoint_description_t *endpoints[] = {
    79         &poll_endpoint_description,
    80         NULL
    81 };
    82 
    8375/** USB mouse driver. */
    84 static usb_driver_t mouse_driver = {
     76static driver_t mouse_driver = {
    8577        .name = NAME,
    86         .ops = &mouse_driver_ops,
    87         .endpoints = endpoints
     78        .driver_ops = &mouse_driver_ops
    8879};
    8980
     
    9283        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    9384
    94         return usb_driver_main(&mouse_driver);
     85        return ddf_driver_main(&mouse_driver);
    9586}
    9687
  • uspace/drv/usbmouse/mouse.c

    rbb41b85 rc32688d  
    4040#include <ipc/mouse.h>
    4141
    42 /** Mouse polling callback.
     42/** Fibril function for polling the mouse device.
    4343 *
    44  * @param dev Device that is being polled.
    45  * @param buffer Data buffer.
    46  * @param buffer_size Buffer size in bytes.
    47  * @param arg Custom argument - points to usb_mouse_t.
    48  * @return Always true.
     44 * This function shall not terminate unless the device breaks and fails
     45 * to send data (e.g. stalls on data request).
     46 *
     47 * @param arg ddf_dev_t type representing the mouse device.
     48 * @return EOK Always.
    4949 */
    50 bool usb_mouse_polling_callback(usb_device_t *dev,
    51     uint8_t *buffer, size_t buffer_size, void *arg)
     50int usb_mouse_polling_fibril(void *arg)
    5251{
    53         usb_mouse_t *mouse = (usb_mouse_t *) arg;
     52        assert(arg != NULL);
     53        ddf_dev_t *dev = (ddf_dev_t *) arg;
     54        usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data;
    5455
    55         usb_log_debug2("got buffer: %s.\n",
    56             usb_debug_str_buffer(buffer, buffer_size, 0));
     56        assert(mouse);
    5757
    58         uint8_t butt = buffer[0];
    59         char str_buttons[4] = {
    60                 butt & 1 ? '#' : '.',
    61                 butt & 2 ? '#' : '.',
    62                 butt & 4 ? '#' : '.',
    63                 0
    64         };
     58        size_t buffer_size = mouse->poll_pipe.max_packet_size;
    6559
    66         int shift_x = ((int) buffer[1]) - 127;
    67         int shift_y = ((int) buffer[2]) - 127;
    68         int wheel = ((int) buffer[3]) - 127;
    69 
    70         if (buffer[1] == 0) {
    71                 shift_x = 0;
    72         }
    73         if (buffer[2] == 0) {
    74                 shift_y = 0;
    75         }
    76         if (buffer[3] == 0) {
    77                 wheel = 0;
     60        if (buffer_size < 4) {
     61                usb_log_error("Weird mouse, results will be skewed.\n");
     62                buffer_size = 4;
    7863        }
    7964
    80         if (mouse->console_phone >= 0) {
    81                 if ((shift_x != 0) || (shift_y != 0)) {
    82                         /* FIXME: guessed for QEMU */
    83                         async_req_2_0(mouse->console_phone,
    84                             MEVENT_MOVE,
    85                             - shift_x / 10,  - shift_y / 10);
    86                 }
    87                 if (butt) {
    88                         /* FIXME: proper button clicking. */
    89                         async_req_2_0(mouse->console_phone,
    90                             MEVENT_BUTTON, 1, 1);
    91                         async_req_2_0(mouse->console_phone,
    92                             MEVENT_BUTTON, 1, 0);
    93                 }
     65        uint8_t *buffer = malloc(buffer_size);
     66        if (buffer == NULL) {
     67                usb_log_error("Out of memory, poll fibril aborted.\n");
     68                return ENOMEM;
    9469        }
    9570
    96         usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
    97             str_buttons, shift_x, shift_y, wheel);
     71        while (true) {
     72                async_usleep(mouse->poll_interval_us);
    9873
    99         /* Guess. */
    100         async_usleep(1000);
     74                size_t actual_size;
     75                int rc;
    10176
    102         return true;
     77                /*
     78                 * Error checking note:
     79                 * - failure when starting a session is considered
     80                 *   temporary (e.g. out of phones, next try might succeed)
     81                 * - failure of transfer considered fatal (probably the
     82                 *   device was unplugged)
     83                 * - session closing not checked (shall not fail anyway)
     84                 */
     85
     86                rc = usb_endpoint_pipe_start_session(&mouse->poll_pipe);
     87                if (rc != EOK) {
     88                        usb_log_warning("Failed to start session, will try again: %s.\n",
     89                            str_error(rc));
     90                        continue;
     91                }
     92
     93                rc = usb_endpoint_pipe_read(&mouse->poll_pipe,
     94                    buffer, buffer_size, &actual_size);
     95
     96                usb_endpoint_pipe_end_session(&mouse->poll_pipe);
     97
     98                if (rc != EOK) {
     99                        usb_log_error("Failed reading mouse input: %s.\n",
     100                            str_error(rc));
     101                        break;
     102                }
     103
     104                usb_log_debug2("got buffer: %s.\n",
     105                    usb_debug_str_buffer(buffer, buffer_size, 0));
     106
     107                uint8_t butt = buffer[0];
     108                char str_buttons[4] = {
     109                        butt & 1 ? '#' : '.',
     110                        butt & 2 ? '#' : '.',
     111                        butt & 4 ? '#' : '.',
     112                        0
     113                };
     114
     115                int shift_x = ((int) buffer[1]) - 127;
     116                int shift_y = ((int) buffer[2]) - 127;
     117                int wheel = ((int) buffer[3]) - 127;
     118
     119                if (buffer[1] == 0) {
     120                        shift_x = 0;
     121                }
     122                if (buffer[2] == 0) {
     123                        shift_y = 0;
     124                }
     125                if (buffer[3] == 0) {
     126                        wheel = 0;
     127                }
     128
     129                if (mouse->console_phone >= 0) {
     130                        if ((shift_x != 0) || (shift_y != 0)) {
     131                                /* FIXME: guessed for QEMU */
     132                                async_req_2_0(mouse->console_phone,
     133                                    MEVENT_MOVE,
     134                                    - shift_x / 10,  - shift_y / 10);
     135                        }
     136                        if (butt) {
     137                                /* FIXME: proper button clicking. */
     138                                async_req_2_0(mouse->console_phone,
     139                                    MEVENT_BUTTON, 1, 1);
     140                                async_req_2_0(mouse->console_phone,
     141                                    MEVENT_BUTTON, 1, 0);
     142                        }
     143                }
     144
     145                usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
     146                   str_buttons, shift_x, shift_y, wheel);
     147        }
     148
     149        /*
     150         * Device was probably unplugged.
     151         * Hang-up the phone to the console.
     152         * FIXME: release allocated memory.
     153         */
     154        async_hangup(mouse->console_phone);
     155        mouse->console_phone = -1;
     156
     157        usb_log_error("Mouse polling fibril terminated.\n");
     158
     159        return EOK;
    103160}
    104161
    105 /** Callback when polling is terminated.
    106  *
    107  * @param dev Device where the polling terminated.
    108  * @param recurring_errors Whether the polling was terminated due to
    109  *      recurring errors.
    110  * @param arg Custom argument - points to usb_mouse_t.
    111  */
    112 void usb_mouse_polling_ended_callback(usb_device_t *dev,
    113     bool recurring_errors, void *arg)
    114 {
    115         usb_mouse_t *mouse = (usb_mouse_t *) arg;
    116 
    117         async_hangup(mouse->console_phone);
    118         mouse->console_phone = -1;
    119 }
    120162
    121163/**
  • uspace/drv/usbmouse/mouse.h

    rbb41b85 rc32688d  
    3737#define USBMOUSE_MOUSE_H_
    3838
    39 #include <usb/devdrv.h>
     39#include <ddf/driver.h>
    4040#include <usb/pipes.h>
    4141#include <time.h>
     
    4646typedef struct {
    4747        /** Generic device container. */
    48         usb_device_t *dev;
     48        ddf_dev_t *device;
    4949        /** Function representing the device. */
    5050        ddf_fun_t *mouse_fun;
     51        /** Representation of connection to the device. */
     52        usb_device_connection_t wire;
     53        /** Default (zero) control pipe. */
     54        usb_endpoint_pipe_t ctrl_pipe;
     55        /** Polling (in) pipe. */
     56        usb_endpoint_pipe_t poll_pipe;
    5157        /** Polling interval in microseconds. */
    5258        suseconds_t poll_interval_us;
     
    5561} usb_mouse_t;
    5662
    57 #define POLL_PIPE(dev) ((dev)->pipes[0].pipe)
     63int usb_mouse_create(ddf_dev_t *);
    5864
    59 extern usb_endpoint_description_t poll_endpoint_description;
    60 
    61 int usb_mouse_create(usb_device_t *);
    62 
    63 bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t, void *);
    64 void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
     65int usb_mouse_polling_fibril(void *);
    6566
    6667#endif
  • uspace/lib/block/libblock.c

    rbb41b85 rc32688d  
    411411        l = hash_table_find(&cache->block_hash, &key);
    412412        if (l) {
    413 found:
    414413                /*
    415414                 * We found the block in the cache.
     
    494493                                        fibril_mutex_unlock(&b->lock);
    495494                                        goto retry;
    496                                 }
    497                                 l = hash_table_find(&cache->block_hash, &key);
    498                                 if (l) {
    499                                         /*
    500                                          * Someone else must have already
    501                                          * instantiated the block while we were
    502                                          * not holding the cache lock.
    503                                          * Leave the recycled block on the
    504                                          * freelist and continue as if we
    505                                          * found the block of interest during
    506                                          * the first try.
    507                                          */
    508                                         fibril_mutex_unlock(&b->lock);
    509                                         goto found;
    510495                                }
    511496
  • uspace/lib/drv/generic/remote_usbhc.c

    rbb41b85 rc32688d  
    5555static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5656static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    57 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    58 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5957//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    6058
     
    7573
    7674        remote_usbhc_control_write,
    77         remote_usbhc_control_read,
    78 
    79         remote_usbhc_register_endpoint,
    80         remote_usbhc_unregister_endpoint
     75        remote_usbhc_control_read
    8176};
    8277
     
    527522
    528523
    529 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
    530     ipc_callid_t callid, ipc_call_t *call)
    531 {
    532         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    533 
    534         if (!usb_iface->register_endpoint) {
    535                 async_answer_0(callid, ENOTSUP);
    536                 return;
    537         }
    538 
    539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \
    540         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256
    541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \
    542         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256
    543 
    544         INIT_FROM_HIGH_DATA(usb_address_t, address, 1);
    545         INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1);
    546         INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2);
    547         INIT_FROM_LOW_DATA(usb_direction_t, direction, 2);
    548 
    549 #undef INIT_FROM_HIGH_DATA
    550 #undef INIT_FROM_LOW_DATA
    551 
    552         size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call);
    553         unsigned int interval  = (unsigned int) DEV_IPC_GET_ARG4(*call);
    554 
    555         int rc = usb_iface->register_endpoint(fun, address, endpoint,
    556             transfer_type, direction, max_packet_size, interval);
    557 
    558         async_answer_0(callid, rc);
    559 }
    560 
    561 
    562 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
    563     ipc_callid_t callid, ipc_call_t *call)
    564 {
    565         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    566 
    567         if (!usb_iface->unregister_endpoint) {
    568                 async_answer_0(callid, ENOTSUP);
    569                 return;
    570         }
    571 
    572         usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    573         usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);
    574         usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);
    575 
    576         int rc = usb_iface->unregister_endpoint(fun,
    577             address, endpoint, direction);
    578 
    579         async_answer_0(callid, rc);
    580 }
    581 
    582524
    583525/**
  • uspace/lib/drv/include/usbhc_iface.h

    rbb41b85 rc32688d  
    167167        IPC_M_USBHC_CONTROL_READ,
    168168
    169         /** Register endpoint attributes at host controller.
    170          * This is used to reserve portion of USB bandwidth.
    171          * Parameters:
    172          * - USB address + endpoint number (ADDR * 256 + EP)
    173          * - transfer type + direction (TYPE * 256 + DIR)
    174          * - maximum packet size
    175          * - interval (in milliseconds)
    176          * Answer:
    177          * - EOK - reservation successful
    178          * - ELIMIT - not enough bandwidth to satisfy the request
    179          */
    180         IPC_M_USBHC_REGISTER_ENDPOINT,
    181 
    182         /** Revert endpoint registration.
    183          * Parameters:
    184          * - USB address
    185          * - endpoint number
    186          * - data direction
    187          * Answer:
    188          * - EOK - endpoint unregistered
    189          * - ENOENT - unknown endpoint
    190          */
    191         IPC_M_USBHC_UNREGISTER_ENDPOINT
     169        /* IPC_M_USB_ */
    192170} usbhc_iface_funcs_t;
    193171
     
    222200        int (*release_address)(ddf_fun_t *, usb_address_t);
    223201
    224         int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
    225             usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    226         int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
    227             usb_direction_t);
    228 
    229202        usbhc_iface_transfer_out_t interrupt_out;
    230203        usbhc_iface_transfer_in_t interrupt_in;
  • uspace/lib/usb/Makefile

    rbb41b85 rc32688d  
    3737        src/ddfiface.c \
    3838        src/debug.c \
    39         src/devdrv.c \
    40         src/devpoll.c \
    4139        src/dp.c \
    4240        src/dump.c \
  • uspace/lib/usb/include/usb/pipes.h

    rbb41b85 rc32688d  
    106106        const usb_endpoint_description_t *description;
    107107        /** Interface number the endpoint must belong to (-1 for any). */
    108         int interface_no;
     108        const int interface_no;
    109109        /** Found descriptor fitting the description. */
    110110        usb_standard_endpoint_descriptor_t *descriptor;
     
    129129int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *,
    130130    usb_device_connection_t *);
    131 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *);
    132131int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    133132    size_t, uint8_t *, size_t, usb_device_connection_t *);
    134 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *, unsigned int,
    135     usb_hc_connection_t *);
    136 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *, usb_hc_connection_t *);
     133
    137134
    138135int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
  • uspace/lib/usb/src/hub.c

    rbb41b85 rc32688d  
    235235                goto leave_release_default_address;
    236236        }
    237         rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
    238         if (rc != EOK) {
    239                 rc = ENOTCONN;
    240                 goto leave_release_default_address;
    241         }
    242237
    243238        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
  • uspace/lib/usb/src/pipesinit.c

    rbb41b85 rc32688d  
    3737#include <usb/pipes.h>
    3838#include <usb/dp.h>
    39 #include <usb/request.h>
    40 #include <usbhc_iface.h>
    4139#include <errno.h>
    4240#include <assert.h>
    43 
    44 #define CTRL_PIPE_MIN_PACKET_SIZE 8
    45 #define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
    4641
    4742
     
    374369
    375370        int rc = usb_endpoint_pipe_initialize(pipe, connection,
    376             0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
    377             USB_DIRECTION_BOTH);
     371            0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
    378372
    379373        return rc;
    380 }
    381 
    382 /** Probe default control pipe for max packet size.
    383  *
    384  * The function tries to get the correct value of max packet size several
    385  * time before giving up.
    386  *
    387  * The session on the pipe shall not be started.
    388  *
    389  * @param pipe Default control pipe.
    390  * @return Error code.
    391  */
    392 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *pipe)
    393 {
    394         assert(pipe);
    395         assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
    396 
    397         if ((pipe->direction != USB_DIRECTION_BOTH) ||
    398             (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
    399             (pipe->endpoint_no != 0)) {
    400                 return EINVAL;
    401         }
    402 
    403 #define TRY_LOOP(attempt_var) \
    404         for (attempt_var = 0; attempt_var < 3; attempt_var++)
    405 
    406         size_t failed_attempts;
    407         int rc;
    408 
    409         TRY_LOOP(failed_attempts) {
    410                 rc = usb_endpoint_pipe_start_session(pipe);
    411                 if (rc == EOK) {
    412                         break;
    413                 }
    414         }
    415         if (rc != EOK) {
    416                 return rc;
    417         }
    418 
    419 
    420         uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
    421         size_t transferred_size;
    422         TRY_LOOP(failed_attempts) {
    423                 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
    424                     USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
    425                     0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,
    426                     &transferred_size);
    427                 if (rc == EOK) {
    428                         if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {
    429                                 rc = ELIMIT;
    430                                 continue;
    431                         }
    432                         break;
    433                 }
    434         }
    435         usb_endpoint_pipe_end_session(pipe);
    436         if (rc != EOK) {
    437                 return rc;
    438         }
    439 
    440         pipe->max_packet_size
    441             = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
    442 
    443         return EOK;
    444 }
    445 
    446 /** Register endpoint with the host controller.
    447  *
    448  * @param pipe Pipe to be registered.
    449  * @param interval Polling interval.
    450  * @param hc_connection Connection to the host controller (must be opened).
    451  * @return Error code.
    452  */
    453 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *pipe,
    454     unsigned int interval,
    455     usb_hc_connection_t *hc_connection)
    456 {
    457         assert(pipe);
    458         assert(hc_connection);
    459 
    460         if (!usb_hc_connection_is_opened(hc_connection)) {
    461                 return EBADF;
    462         }
    463 
    464 #define _PACK(high, low) ((high) * 256 + (low))
    465 
    466         return async_req_5_0(hc_connection->hc_phone,
    467             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
    468             _PACK(pipe->wire->address, pipe->endpoint_no),
    469             _PACK(pipe->transfer_type, pipe->direction),
    470             pipe->max_packet_size, interval);
    471 
    472 #undef _PACK
    473 }
    474 
    475 /** Revert endpoint registration with the host controller.
    476  *
    477  * @param pipe Pipe to be unregistered.
    478  * @param hc_connection Connection to the host controller (must be opened).
    479  * @return Error code.
    480  */
    481 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *pipe,
    482     usb_hc_connection_t *hc_connection)
    483 {
    484         assert(pipe);
    485         assert(hc_connection);
    486 
    487         if (!usb_hc_connection_is_opened(hc_connection)) {
    488                 return EBADF;
    489         }
    490 
    491         return async_req_4_0(hc_connection->hc_phone,
    492             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT,
    493             pipe->wire->address, pipe->endpoint_no, pipe->direction);
    494374}
    495375
  • uspace/lib/usb/src/recognise.c

    rbb41b85 rc32688d  
    369369                goto failure;
    370370        }
    371         rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
    372         if (rc != EOK) {
    373                 goto failure;
    374         }
    375371
    376372        /*
     
    378374         * naming etc., something more descriptive could be created.
    379375         */
    380         rc = asprintf(&child_name, "usb%02zu_a%d",
    381             this_device_name_index, address);
     376        rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
    382377        if (rc < 0) {
    383378                goto failure;
  • uspace/srv/hw/irc/apic/apic.c

    rbb41b85 rc32688d  
    5454#define NAME  "apic"
    5555
    56 static bool apic_found = false;
    57 
    5856static int apic_enable_irq(sysarg_t irq)
    5957{
     
    8179                callid = async_get_call(&call);
    8280               
    83                 sysarg_t method = IPC_GET_IMETHOD(call);
    84                 if (method == IPC_M_PHONE_HUNGUP) {
    85                         return;
    86                 }
    87 
    88                 if (!apic_found) {
    89                         async_answer_0(callid, ENOTSUP);
    90                         break;
    91                 }
    92 
    93                 switch (method) {
     81                switch (IPC_GET_IMETHOD(call)) {
    9482                case IRC_ENABLE_INTERRUPT:
    9583                        async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call)));
     
    10997 *
    11098 */
    111 static void apic_init(void)
     99static bool apic_init(void)
    112100{
    113101        sysarg_t apic;
    114102       
    115         apic_found = sysinfo_get_value("apic", &apic) && apic;
    116         if (!apic_found) {
    117                 printf(NAME ": Warning: no APIC found\n");
     103        if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) {
     104                printf(NAME ": No APIC found\n");
     105                return false;
    118106        }
    119107       
    120108        async_set_client_connection(apic_connection);
    121109        service_register(SERVICE_APIC);
     110       
     111        return true;
    122112}
    123113
     
    126116        printf(NAME ": HelenOS APIC driver\n");
    127117       
    128         apic_init();
    129 
     118        if (!apic_init())
     119                return -1;
     120       
    130121        printf(NAME ": Accepting connections\n");
    131122        async_manager();
Note: See TracChangeset for help on using the changeset viewer.