Changes in / [c32688d:bb41b85] in mainline


Ignore:
Files:
7 added
4 deleted
49 edited

Legend:

Unmodified
Added
Removed
  • dist/Makefile

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

    rc32688d rbb41b85  
    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        }
    6774        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
    6875        if (rc != EOK) {
  • uspace/app/usbinfo/main.c

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

    rc32688d rbb41b85  
    253253         * @defgroup drvusbuhci UHCI driver
    254254         * @ingroup usb
    255          * @brief Driver for USB host controller UHCI.
    256          */
     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                 */
    257269
    258270        /**
  • uspace/drv/ehci-hcd/main.c

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

    rc32688d rbb41b85  
    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 */
    261260        }
    262261
     
    280279        usb_log_debug2("USBLEGSUP: %x.\n", value);
    281280
    282 /*
    283  * TURN OFF EHCI FOR NOW, REMOVE IF THE DRIVER IS IMPLEMENTED
    284  */
     281        /*
     282         * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT
     283        */
    285284
    286285        /* Get size of capability registers in memory space. */
  • uspace/drv/pciintel/pci.c

    rc32688d rbb41b85  
    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 = 0;
    99 
    100   if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
    101     irc_service = SERVICE_APIC;
     98        int irc_service = -1;
     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 == 0)
     103                irc_service = SERVICE_I8259;
     104        }
     105
     106        if (irc_service == -1) {
    107107                return false;
     108        }
    108109
    109110        irc_phone = service_connect_blocking(irc_service, 0, 0);
    110         if (irc_phone < 0)
     111        if (irc_phone < 0) {
    111112                return false;
     113        }
    112114
    113115        size_t i;
    114   for (i = 0; i < dev_data->hw_resources.count; i++) {
     116        for (i = 0; i < dev_data->hw_resources.count; i++) {
    115117                if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
    116118                        int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
  • uspace/drv/uhci-hcd/Makefile

    rc32688d rbb41b85  
    3535        iface.c \
    3636        main.c \
    37         root_hub.c \
    3837        transfer_list.c \
    3938        uhci.c \
     39        uhci_hc.c \
     40        uhci_rh.c \
    4041        uhci_struct/transfer_descriptor.c \
    4142        utils/device_keeper.c \
  • uspace/drv/uhci-hcd/batch.c

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver USB transaction structure
    3333 */
    3434#include <errno.h>
     
    4040#include "batch.h"
    4141#include "transfer_list.h"
    42 #include "uhci.h"
     42#include "uhci_hc.h"
    4343#include "utils/malloc32.h"
    4444
    4545#define DEFAULT_ERROR_COUNT 3
    46 
    47 static int batch_schedule(batch_t *instance);
    4846
    4947static void batch_control(batch_t *instance,
     
    5452static void batch_call_in_and_dispose(batch_t *instance);
    5553static void batch_call_out_and_dispose(batch_t *instance);
    56 static void batch_dispose(batch_t *instance);
    57 
    58 
    59 /** Allocates memory and initializes internal data structures.
     54
     55
     56/** Allocate memory and initialize internal data structure.
    6057 *
    6158 * @param[in] fun DDF function to pass to callback.
     
    7269 * @param[in] arg additional parameter to func_in or func_out
    7370 * @param[in] manager Pointer to toggle management structure.
    74  * @return False, if there is an active TD, true otherwise.
     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.
    7577 */
    7678batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
     
    100102        bzero(instance, sizeof(batch_t));
    101103
    102         instance->qh = malloc32(sizeof(queue_head_t));
     104        instance->qh = malloc32(sizeof(qh_t));
    103105        CHECK_NULL_DISPOSE_RETURN(instance->qh,
    104106            "Failed to allocate batch queue head.\n");
    105         queue_head_init(instance->qh);
     107        qh_init(instance->qh);
    106108
    107109        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    114116            instance->tds, "Failed to allocate transfer descriptors.\n");
    115117        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 
    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));
     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));
    152149
    153150        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
     
    156153}
    157154/*----------------------------------------------------------------------------*/
    158 /** Checks batch TDs for activity.
     155/** Check batch TDs for activity.
    159156 *
    160157 * @param[in] instance Batch structure to use.
    161158 * @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.
    162163 */
    163164bool batch_is_complete(batch_t *instance)
     
    177178                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    178179                            instance, i, instance->tds[i].status);
     180                        td_print_status(&instance->tds[i]);
    179181
    180182                        device_keeper_set_toggle(instance->manager,
     
    197199 *
    198200 * @param[in] instance Batch structure to use.
     201 *
     202 * Uses genercir control function with pids OUT and IN.
    199203 */
    200204void batch_control_write(batch_t *instance)
    201205{
    202206        assert(instance);
    203         /* we are data out, we are supposed to provide data */
     207        /* We are data out, we are supposed to provide data */
    204208        memcpy(instance->transport_buffer, instance->buffer,
    205209            instance->buffer_size);
     
    207211        instance->next_step = batch_call_out_and_dispose;
    208212        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    209         batch_schedule(instance);
    210213}
    211214/*----------------------------------------------------------------------------*/
     
    213216 *
    214217 * @param[in] instance Batch structure to use.
     218 *
     219 * Uses generic control with pids IN and OUT.
    215220 */
    216221void batch_control_read(batch_t *instance)
     
    220225        instance->next_step = batch_call_in_and_dispose;
    221226        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    222         batch_schedule(instance);
    223 }
    224 /*----------------------------------------------------------------------------*/
    225 /** Prepares interrupt in transaction.
    226  *
    227  * @param[in] instance Batch structure to use.
     227}
     228/*----------------------------------------------------------------------------*/
     229/** Prepare interrupt in transaction.
     230 *
     231 * @param[in] instance Batch structure to use.
     232 *
     233 * Data transaction with PID_IN.
    228234 */
    229235void batch_interrupt_in(batch_t *instance)
     
    233239        instance->next_step = batch_call_in_and_dispose;
    234240        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    235         batch_schedule(instance);
    236 }
    237 /*----------------------------------------------------------------------------*/
    238 /** Prepares interrupt out transaction.
    239  *
    240  * @param[in] instance Batch structure to use.
     241}
     242/*----------------------------------------------------------------------------*/
     243/** Prepare interrupt out transaction.
     244 *
     245 * @param[in] instance Batch structure to use.
     246 *
     247 * Data transaction with PID_OUT.
    241248 */
    242249void batch_interrupt_out(batch_t *instance)
    243250{
    244251        assert(instance);
    245         /* we are data out, we are supposed to provide data */
     252        /* We are data out, we are supposed to provide data */
    246253        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    247254        batch_data(instance, USB_PID_OUT);
    248255        instance->next_step = batch_call_out_and_dispose;
    249256        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    250         batch_schedule(instance);
    251 }
    252 /*----------------------------------------------------------------------------*/
    253 /** Prepares bulk in transaction.
    254  *
    255  * @param[in] instance Batch structure to use.
     257}
     258/*----------------------------------------------------------------------------*/
     259/** Prepare bulk in transaction.
     260 *
     261 * @param[in] instance Batch structure to use.
     262 *
     263 * Data transaction with PID_IN.
    256264 */
    257265void batch_bulk_in(batch_t *instance)
     
    261269        instance->next_step = batch_call_in_and_dispose;
    262270        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    263         batch_schedule(instance);
    264 }
    265 /*----------------------------------------------------------------------------*/
    266 /** Prepares bulk out transaction.
    267  *
    268  * @param[in] instance Batch structure to use.
     271}
     272/*----------------------------------------------------------------------------*/
     273/** Prepare bulk out transaction.
     274 *
     275 * @param[in] instance Batch structure to use.
     276 *
     277 * Data transaction with PID_OUT.
    269278 */
    270279void batch_bulk_out(batch_t *instance)
    271280{
    272281        assert(instance);
     282        /* We are data out, we are supposed to provide data */
    273283        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    274284        batch_data(instance, USB_PID_OUT);
    275285        instance->next_step = batch_call_out_and_dispose;
    276286        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    277         batch_schedule(instance);
    278 }
    279 /*----------------------------------------------------------------------------*/
    280 /** Prepares generic data transaction
     287}
     288/*----------------------------------------------------------------------------*/
     289/** Prepare generic data transaction
    281290 *
    282291 * @param[in] instance Batch structure to use.
    283292 * @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.
    284296 */
    285297void batch_data(batch_t *instance, usb_packet_id pid)
     
    318330                ++packet;
    319331        }
     332        td_set_ioc(&instance->tds[packet - 1]);
    320333        device_keeper_set_toggle(instance->manager, instance->target, toggle);
    321334}
    322335/*----------------------------------------------------------------------------*/
    323 /** Prepares generic control transaction
     336/** Prepare generic control transaction
    324337 *
    325338 * @param[in] instance Batch structure to use.
    326339 * @param[in] data_stage to use for data packets.
    327340 * @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.
    328346 */
    329347void batch_control(batch_t *instance,
     
    369387            0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
    370388
    371 
    372         instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     389        td_set_ioc(&instance->tds[packet]);
    373390        usb_log_debug2("Control last TD status: %x.\n",
    374391            instance->tds[packet].status);
    375392}
    376393/*----------------------------------------------------------------------------*/
    377 /** Prepares data, gets error status and calls callback in.
    378  *
    379  * @param[in] instance Batch structure to use.
     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.
    380399 */
    381400void batch_call_in(batch_t *instance)
     
    384403        assert(instance->callback_in);
    385404
    386         /* we are data in, we need data */
     405        /* We are data in, we need data */
    387406        memcpy(instance->buffer, instance->transport_buffer,
    388407            instance->buffer_size);
     
    397416}
    398417/*----------------------------------------------------------------------------*/
    399 /** Gets error status and calls callback out.
     418/** Get error status and call callback out.
    400419 *
    401420 * @param[in] instance Batch structure to use.
     
    413432}
    414433/*----------------------------------------------------------------------------*/
    415 /** Prepares data, gets error status, calls callback in and dispose.
     434/** Helper function calls callback and correctly disposes of batch structure.
    416435 *
    417436 * @param[in] instance Batch structure to use.
     
    424443}
    425444/*----------------------------------------------------------------------------*/
    426 /** Gets error status, calls callback out and dispose.
     445/** Helper function calls callback and correctly disposes of batch structure.
    427446 *
    428447 * @param[in] instance Batch structure to use.
     
    435454}
    436455/*----------------------------------------------------------------------------*/
    437 /** Correctly disposes all used data structures.
     456/** Correctly dispose all used data structures.
    438457 *
    439458 * @param[in] instance Batch structure to use.
     
    450469        free(instance);
    451470}
    452 /*----------------------------------------------------------------------------*/
    453 int 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 }
    460471/**
    461472 * @}
  • uspace/drv/uhci-hcd/batch.h

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

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver hc interface implementation
    3333 */
    3434#include <ddf/driver.h>
     
    4040
    4141#include "iface.h"
    42 #include "uhci.h"
     42#include "uhci_hc.h"
    4343#include "utils/device_keeper.h"
    4444
     
    5353{
    5454        assert(fun);
    55         uhci_t *hc = fun_to_uhci(fun);
     55        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    5656        assert(hc);
    5757        usb_log_debug("Default address request with speed %d.\n", speed);
     
    6868{
    6969        assert(fun);
    70         uhci_t *hc = fun_to_uhci(fun);
     70        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    7171        assert(hc);
    7272        usb_log_debug("Default address release.\n");
     
    8686{
    8787        assert(fun);
    88         uhci_t *hc = fun_to_uhci(fun);
     88        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    8989        assert(hc);
    9090        assert(address);
     
    109109{
    110110        assert(fun);
    111         uhci_t *hc = fun_to_uhci(fun);
     111        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    112112        assert(hc);
    113113        usb_log_debug("Address bind %d-%d.\n", address, handle);
     
    125125{
    126126        assert(fun);
    127         uhci_t *hc = fun_to_uhci(fun);
     127        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    128128        assert(hc);
    129129        usb_log_debug("Address release %d.\n", address);
     
    148148{
    149149        assert(fun);
    150         uhci_t *hc = fun_to_uhci(fun);
     150        uhci_hc_t *hc = fun_to_uhci_hc(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        }
    163168        return EOK;
    164169}
     
    180185{
    181186        assert(fun);
    182         uhci_t *hc = fun_to_uhci(fun);
     187        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    183188        assert(hc);
    184189        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    192197                return ENOMEM;
    193198        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        }
    194204        return EOK;
    195205}
     
    211221{
    212222        assert(fun);
    213         uhci_t *hc = fun_to_uhci(fun);
     223        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    214224        assert(hc);
    215225        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    224234                return ENOMEM;
    225235        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        }
    226241        return EOK;
    227242}
     
    243258{
    244259        assert(fun);
    245         uhci_t *hc = fun_to_uhci(fun);
     260        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    246261        assert(hc);
    247262        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    255270                return ENOMEM;
    256271        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        }
    257277        return EOK;
    258278}
     
    277297{
    278298        assert(fun);
    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);
     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);
    284304
    285305        if (setup_size != 8)
     
    293313        device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
    294314        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        }
    295320        return EOK;
    296321}
     
    315340{
    316341        assert(fun);
    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);
     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);
    323348        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    324349            max_packet_size, speed, data, size, setup_data, setup_size, callback,
     
    327352                return ENOMEM;
    328353        batch_control_read(batch);
    329         return EOK;
    330 }
    331 /*----------------------------------------------------------------------------*/
    332 usbhc_iface_t uhci_iface = {
     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/*----------------------------------------------------------------------------*/
     362usbhc_iface_t uhci_hc_iface = {
    333363        .reserve_default_address = reserve_default_address,
    334364        .release_default_address = release_default_address,
  • uspace/drv/uhci-hcd/iface.h

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

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver initialization
    3333 */
    3434#include <ddf/driver.h>
    35 #include <ddf/interrupt.h>
    36 #include <device/hw_res.h>
    3735#include <errno.h>
    3836#include <str_error.h>
    3937
    40 #include <usb_iface.h>
    4138#include <usb/ddfiface.h>
    4239#include <usb/debug.h>
    4340
    4441#include "iface.h"
    45 #include "pci.h"
    46 #include "root_hub.h"
    4742#include "uhci.h"
    4843
     
    6055};
    6156/*----------------------------------------------------------------------------*/
    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  */
    68 static 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.
     57/** Initialize a new ddf driver instance for uhci hc and hub.
    7858 *
    7959 * @param[in] device DDF instance of the device to initialize.
    8060 * @return Error code.
    81  *
    82  * Gets and initialies hardware resources, disables any legacy support,
    83  * and reports root hub device.
    8461 */
    8562int uhci_add_device(ddf_dev_t *device)
    8663{
     64        usb_log_info("uhci_add_device() called\n");
    8765        assert(device);
    88         uhci_t *hcd = NULL;
    89 #define CHECK_RET_FREE_HC_RETURN(ret, message...) \
    90 if (ret != EOK) { \
    91         usb_log_error(message); \
    92         if (hcd != NULL) \
    93                 free(hcd); \
    94         return ret; \
    95 }
     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;
     70        }
    9671
    97         usb_log_info("uhci_add_device() called\n");
    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);
     72        int ret = uhci_init(uhci, device);
    11673        if (ret != EOK) {
    117                 usb_log_warning(
    118                     "Failed(%d) to enable interrupts, fall back to polling.\n",
    119                     ret);
     74                usb_log_error("Failed to initialzie UHCI driver.\n");
     75                return ret;
    12076        }
    121 #endif
    122 
    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...) \
    140 if (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 
     77        device->driver_data = uhci;
    16678        return EOK;
    167 #undef CHECK_RET_FINI_FREE_RETURN
    16879}
    16980/*----------------------------------------------------------------------------*/
    170 /** Initializes global driver structures (NONE).
     81/** Initialize global driver structures (NONE).
    17182 *
    17283 * @param[in] argc Nmber of arguments in argv vector (ignored).
     
    17889int main(int argc, char *argv[])
    17990{
    180         sleep(3);
     91        sleep(3); /* TODO: remove in final version */
    18192        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    18293
  • uspace/drv/uhci-hcd/pci.c

    rc32688d rbb41b85  
    2727 */
    2828/**
    29  * @addtogroup drvusbuhci
     29 * @addtogroup drvusbuhcihc
    3030 * @{
    3131 */
     
    117117}
    118118/*----------------------------------------------------------------------------*/
    119 /** Calls the PCI driver with a request to enable interrupts
     119/** Call the PCI driver with a request to enable interrupts
    120120 *
    121121 * @param[in] device Device asking for interrupts
     
    131131}
    132132/*----------------------------------------------------------------------------*/
    133 /** Calls the PCI driver with a request to clear legacy support register
     133/** Call 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

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

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver transfer list implementation
    3333 */
    3434#include <errno.h>
    35 
    3635#include <usb/debug.h>
    3736
     
    4140    transfer_list_t *instance, batch_t *batch);
    4241/*----------------------------------------------------------------------------*/
    43 /** Initializes transfer list structures.
     42/** Initialize transfer list structures.
    4443 *
    4544 * @param[in] instance Memory place to use.
    46  * @param[in] name Name of te new list.
    47  * @return Error code
    48  *
    49  * Allocates memory for internat queue_head_t structure.
     45 * @param[in] name Name of the new list.
     46 * @return Error code
     47 *
     48 * Allocates memory for internal qh_t structure.
    5049 */
    5150int transfer_list_init(transfer_list_t *instance, const char *name)
    5251{
    5352        assert(instance);
    54         instance->next = NULL;
    5553        instance->name = name;
    56         instance->queue_head = malloc32(sizeof(queue_head_t));
     54        instance->queue_head = malloc32(sizeof(qh_t));
    5755        if (!instance->queue_head) {
    5856                usb_log_error("Failed to allocate queue head.\n");
     
    6159        instance->queue_head_pa = addr_to_phys(instance->queue_head);
    6260
    63         queue_head_init(instance->queue_head);
     61        qh_init(instance->queue_head);
    6462        list_initialize(&instance->batch_list);
    6563        fibril_mutex_initialize(&instance->guard);
     
    6765}
    6866/*----------------------------------------------------------------------------*/
    69 /** Set the next list in chain.
     67/** Set the next list in transfer list chain.
    7068 *
    7169 * @param[in] instance List to lead.
    7270 * @param[in] next List to append.
    7371 * @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         queue_head_append_qh(instance->queue_head, next->queue_head_pa);
    82         instance->queue_head->element = instance->queue_head->next_queue;
    83 }
    84 /*----------------------------------------------------------------------------*/
    85 /** Submits a new transfer batch to list and queue.
     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);
     84}
     85/*----------------------------------------------------------------------------*/
     86/** Submit transfer batch to the list and queue.
    8687 *
    8788 * @param[in] instance List to use.
    8889 * @param[in] batch Transfer batch to submit.
    8990 * @return Error code
     91 *
     92 * The batch is added to the end of the list and queue.
    9093 */
    9194void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
     
    9396        assert(instance);
    9497        assert(batch);
    95         usb_log_debug2(
    96             "Adding batch(%p) to queue %s.\n", batch, instance->name);
    97 
    98         uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
     98        usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     99
     100        const uint32_t pa = addr_to_phys(batch->qh);
    99101        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    100         pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
    101 
    102         batch->qh->next_queue = instance->queue_head->next_queue;
     102
     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);
    103106
    104107        fibril_mutex_lock(&instance->guard);
    105108
    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;
    114         }
    115         /* now we can be sure that there is someting scheduled */
    116         assert(!list_empty(&instance->batch_list));
     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);
     120        }
     121        /* Add to the driver list */
     122        list_append(&batch->link, &instance->batch_list);
     123
    117124        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);
    122         list_append(&batch->link, &instance->batch_list);
    123 
    124         usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
     125            instance->batch_list.next, batch_t, link);
     126        usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
    125127                batch, instance->name, first);
    126128        fibril_mutex_unlock(&instance->guard);
    127129}
    128130/*----------------------------------------------------------------------------*/
    129 /** Removes a transfer batch from list and queue.
     131/** Remove a transfer batch from the list and queue.
    130132 *
    131133 * @param[in] instance List to use.
    132134 * @param[in] batch Transfer batch to remove.
    133135 * @return Error code
     136 *
     137 * Does not lock the transfer list, caller is responsible for that.
    134138 */
    135139void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
     
    140144        assert(batch->qh);
    141145        usb_log_debug2(
    142             "Removing batch(%p) from queue %s.\n", batch, instance->name);
    143 
     146            "Queue %s: removing batch(%p).\n", instance->name, batch);
     147
     148        const char * pos = NULL;
     149        /* Remove from the hardware queue */
    144150        if (batch->link.prev == &instance->batch_list) {
    145151                /* I'm the first one here */
    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;
     152                qh_set_element_qh(instance->queue_head, batch->qh->next);
     153                pos = "FIRST";
    150154        } 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);
    154155                batch_t *prev =
    155156                    list_get_instance(batch->link.prev, batch_t, link);
    156                 prev->qh->next_queue = batch->qh->next_queue;
    157         }
     157                qh_set_next_qh(prev->qh, batch->qh->next);
     158                pos = "NOT FIRST";
     159        }
     160        /* Remove from the driver list */
    158161        list_remove(&batch->link);
    159 }
    160 /*----------------------------------------------------------------------------*/
    161 /** Checks list for finished transfers.
     162        usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",
     163            batch, pos, instance->name, batch->qh->next);
     164}
     165/*----------------------------------------------------------------------------*/
     166/** Check list for finished batches.
    162167 *
    163168 * @param[in] instance List to use.
    164169 * @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.
    165174 */
    166175void transfer_list_remove_finished(transfer_list_t *instance)
     
    177186
    178187                if (batch_is_complete(batch)) {
     188                        /* Save for post-processing */
    179189                        transfer_list_remove_batch(instance, batch);
    180190                        list_append(current, &done);
  • uspace/drv/uhci-hcd/transfer_list.h

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver transfer list structure
    3333 */
    3434#ifndef DRV_UHCI_TRANSFER_LIST_H
     
    4444{
    4545        fibril_mutex_t guard;
    46         queue_head_t *queue_head;
     46        qh_t *queue_head;
    4747        uint32_t queue_head_pa;
    48         struct transfer_list *next;
    4948        const char *name;
    5049        link_t batch_list;
    5150} transfer_list_t;
     51
     52/** Dispose transfer list structures.
     53 *
     54 * @param[in] instance Memory place to use.
     55 *
     56 * Frees memory for internal qh_t structure.
     57 */
     58static inline void transfer_list_fini(transfer_list_t *instance)
     59{
     60        assert(instance);
     61        free32(instance->queue_head);
     62}
    5263
    5364int transfer_list_init(transfer_list_t *instance, const char *name);
     
    5566void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    5667
    57 static inline void transfer_list_fini(transfer_list_t *instance)
    58 {
    59         assert(instance);
    60         free32(instance->queue_head);
    61 }
    6268void transfer_list_remove_finished(transfer_list_t *instance);
    6369
  • uspace/drv/uhci-hcd/uhci.c

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28
     29/** @addtogroup drvusbuhci
    2930 * @{
    3031 */
     
    3435#include <errno.h>
    3536#include <str_error.h>
    36 #include <adt/list.h>
    37 #include <libarch/ddi.h>
    38 
     37#include <ddf/interrupt.h>
     38#include <usb_iface.h>
     39#include <usb/ddfiface.h>
    3940#include <usb/debug.h>
    40 #include <usb/usb.h>
    41 #include <usb/ddfiface.h>
    42 #include <usb_iface.h>
    4341
    4442#include "uhci.h"
    4543#include "iface.h"
    46 
    47 static 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.
     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 */
     53static 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.
    6967 */
    7068static int usb_iface_get_address(
     
    7270{
    7371        assert(fun);
    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);
     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);
    7975        if (addr < 0) {
    8076                return addr;
     
    8884}
    8985/*----------------------------------------------------------------------------*/
    90 static usb_iface_t hc_usb_iface = {
    91         .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
     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 */
     92static 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. */
     104static usb_iface_t usb_iface = {
     105        .get_hc_handle = usb_iface_get_hc_handle,
    92106        .get_address = usb_iface_get_address
    93107};
    94108/*----------------------------------------------------------------------------*/
    95 static ddf_dev_ops_t uhci_ops = {
    96         .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
    97         .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    98 };
    99 /*----------------------------------------------------------------------------*/
    100 static int uhci_init_transfer_lists(uhci_t *instance);
    101 static int uhci_init_mem_structures(uhci_t *instance);
    102 static void uhci_init_hw(uhci_t *instance);
    103 
    104 static int uhci_interrupt_emulator(void *arg);
    105 static int uhci_debug_checker(void *arg);
    106 
    107 static 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  */
    119 int 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 
     109static 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 */
     112};
     113/*----------------------------------------------------------------------------*/
     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 */
     119static 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/*----------------------------------------------------------------------------*/
     125static hw_res_ops_t hw_res_iface = {
     126        .get_resource_list = get_resource_list,
     127        .enable_interrupt = NULL
     128};
     129/*----------------------------------------------------------------------------*/
     130static 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 */
     146int uhci_init(uhci_t *instance, ddf_dev_t *device)
     147{
     148        assert(instance);
     149        instance->hc_fun = NULL;
     150        instance->rh_fun = NULL;
    124151#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
    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;
    135         CHECK_RET_DEST_FUN_RETURN(ret,
    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);
     152if (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);
     167        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);
    142198        CHECK_RET_DEST_FUN_RETURN(ret,
    143199            "Failed(%d) to bind UHCI device function: %s.\n",
    144200            ret, str_error(ret));
    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");
     201#undef CHECK_RET_HC_RETURN
     202
     203#define CHECK_RET_FINI_RETURN(ret, message...) \
     204if (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
    169236        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  */
    177 void 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  */
    215 int 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  */
    278 int 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  */
    342 int 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  */
    370 void 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  */
    385 int 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  */
    408 int 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  */
    477 bool 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;
     237#undef CHECK_RET_FINI_RETURN
    493238}
    494239/**
  • uspace/drv/uhci-hcd/uhci.h

    rc32688d rbb41b85  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief UHCI driver
     33 * @brief UHCI driver main structure for both host controller and root-hub.
    3434 */
    3535#ifndef DRV_UHCI_UHCI_H
    3636#define DRV_UHCI_UHCI_H
     37#include <ddi.h>
     38#include <ddf/driver.h>
    3739
    38 #include <fibril.h>
    39 #include <fibril_synch.h>
    40 #include <adt/list.h>
    41 #include <ddi.h>
    42 
    43 #include <usbhc_iface.h>
    44 
    45 #include "batch.h"
    46 #include "transfer_list.h"
    47 #include "utils/device_keeper.h"
    48 
    49 typedef 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
     40#include "uhci_hc.h"
     41#include "uhci_rh.h"
    8242
    8343typedef struct uhci {
    84         device_keeper_t device_manager;
     44        ddf_fun_t *hc_fun;
     45        ddf_fun_t *rh_fun;
    8546
    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;
     47        uhci_hc_t hc;
     48        uhci_rh_t rh;
    10349} uhci_t;
    10450
    105 /* init uhci specifics in device.driver_data */
    106 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size);
    107 
    108 static inline void uhci_fini(uhci_t *instance) {};
    109 
    110 int uhci_schedule(uhci_t *instance, batch_t *batch);
    111 
    112 void uhci_interrupt(uhci_t *instance, uint16_t status);
    113 
    114 static inline uhci_t * dev_to_uhci(ddf_dev_t *dev)
    115         { return (uhci_t*)dev->driver_data; }
    116 
    117 static inline uhci_t * fun_to_uhci(ddf_fun_t *fun)
    118         { return (uhci_t*)fun->driver_data; }
    119 
     51int uhci_init(uhci_t *instance, ddf_dev_t *device);
    12052
    12153#endif
  • uspace/drv/uhci-hcd/uhci_struct/link_pointer.h

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    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
    4851#endif
    4952/**
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    rc32688d rbb41b85  
    1 
    21/*
    32 * Copyright (c) 2010 Jan Vesely
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
    29 /** @addtogroup usb
     28/** @addtogroup drv usbuhcihc
    3029 * @{
    3130 */
     
    4342
    4443typedef struct queue_head {
    45         volatile link_pointer_t next_queue;
     44        volatile link_pointer_t next;
    4645        volatile link_pointer_t element;
    47 } __attribute__((packed)) queue_head_t;
    48 
    49 static inline void queue_head_init(queue_head_t *instance)
     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 */
     54static inline void qh_init(qh_t *instance)
    5055{
    5156        assert(instance);
    5257
    5358        instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    54         instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
     59        instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    5560}
    56 
    57 static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa)
     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 */
     70static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
    5871{
    59         if (pa) {
    60                 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
     72        /* Address is valid and not terminal */
     73        if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     74                instance->next = (pa & LINK_POINTER_ADDRESS_MASK)
    6175                    | LINK_POINTER_QUEUE_HEAD_FLAG;
     76        } else {
     77                instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    6278        }
    6379}
    64 
    65 static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa)
     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 */
     89static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
    6690{
    67         if (pa) {
    68                 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
     91        /* Address is valid and not terminal */
     92        if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     93                instance->element = (pa & LINK_POINTER_ADDRESS_MASK)
    6994                    | LINK_POINTER_QUEUE_HEAD_FLAG;
     95        } else {
     96                instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    7097        }
    7198}
    72 
    73 static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa)
     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 */
     108static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
    74109{
    75         if (pa) {
     110        if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    76111                instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
     112        } else {
     113                instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    77114        }
    78115}
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
     
    3838#include "utils/malloc32.h"
    3939
    40 /** Initializes Transfer Descriptor
     40/** Initialize 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 is for Isochronous transfer.
     46 * @param[in] iso True if TD represents 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.
    5361 */
    5462void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
     
    8896        }
    8997
    90         usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
    91             instance->next, instance->status, instance->device,
     98        usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
     99            instance, instance->next, instance->status, instance->device,
    92100            instance->buffer_ptr, buffer);
     101        td_print_status(instance);
    93102        if (pid == USB_PID_SETUP) {
    94103                usb_log_debug("SETUP BUFFER: %s\n",
    95                         usb_debug_str_buffer(buffer, 8, 8));
     104                    usb_debug_str_buffer(buffer, 8, 8));
    96105        }
    97106}
    98107/*----------------------------------------------------------------------------*/
    99 /** Converts TD status into standard error code
     108/** Convert TD status into standard error code
    100109 *
    101110 * @param[in] instance TD structure to use.
     
    126135        return EOK;
    127136}
     137/*----------------------------------------------------------------------------*/
     138/** Print values in status field (dw1) in a human readable way.
     139 *
     140 * @param[in] instance TD structure to use.
     141 */
     142void 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}
    128164/**
    129165 * @}
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    rc32688d rbb41b85  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
     
    4545
    4646        volatile uint32_t status;
    47 
    4847#define TD_STATUS_RESERVED_MASK 0xc000f800
    4948#define TD_STATUS_SPD_FLAG ( 1 << 29 )
    5049#define TD_STATUS_ERROR_COUNT_POS ( 27 )
    5150#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
    52 #define TD_STATUS_ERROR_COUNT_DEFAULT 3
    5351#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
    5452#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
    55 #define TD_STATUS_COMPLETE_INTERRUPT_FLAG ( 1 << 24 )
     53#define TD_STATUS_IOC_FLAG ( 1 << 24 )
    5654
    5755#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
     
    7068
    7169        volatile uint32_t device;
    72 
    7370#define TD_DEVICE_MAXLEN_POS 21
    7471#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
     
    8582
    8683        /* there is 16 bytes of data available here, according to UHCI
    87          * Design guide, according to linux kernel the hardware does not care
    88          * we don't use it anyway
     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
    8986         */
    9087} __attribute__((packed)) td_t;
    9188
    9289
    93 void 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);
     90void 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);
    9693
    9794int td_status(td_t *instance);
    9895
     96void 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 */
    99103static inline size_t td_act_size(td_t *instance)
    100104{
    101105        assert(instance);
    102         return
    103             ((instance->status >> TD_STATUS_ACTLEN_POS) + 1)
    104             & TD_STATUS_ACTLEN_MASK;
     106        const uint32_t s = instance->status;
     107        return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
    105108}
    106 
     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 */
    107116static inline bool td_is_short(td_t *instance)
    108117{
     
    114123            (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
    115124}
    116 
     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 */
    117131static inline int td_toggle(td_t *instance)
    118132{
    119133        assert(instance);
    120         return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0)
    121             ? 1 : 0;
     134        return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
    122135}
    123 
     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 */
    124142static inline bool td_is_active(td_t *instance)
    125143{
     
    127145        return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
    128146}
     147/*----------------------------------------------------------------------------*/
     148/** Helper function for setting IOC bit.
     149 *
     150 * @param[in] instance TD structure to use.
     151 */
     152static inline void td_set_ioc(td_t *instance)
     153{
     154        assert(instance);
     155        instance->status |= TD_STATUS_IOC_FLAG;
     156}
     157/*----------------------------------------------------------------------------*/
    129158#endif
    130159/**
  • uspace/drv/uhci-hcd/utils/device_keeper.c

    rc32688d rbb41b85  
    2727 */
    2828
    29 /** @addtogroup drvusbuhci
     29/** @addtogroup drvusbuhcihc
    3030 * @{
    3131 */
     
    4040
    4141/*----------------------------------------------------------------------------*/
    42 /** Initializes device keeper structure.
     42/** Initialize device keeper structure.
    4343 *
    4444 * @param[in] instance Memory place to initialize.
     45 *
     46 * Set all values to false/0.
    4547 */
    4648void device_keeper_init(device_keeper_t *instance)
     
    5860}
    5961/*----------------------------------------------------------------------------*/
    60 /** Attempts to obtain address 0, blocks.
     62/** Attempt to obtain address 0, blocks.
    6163 *
    6264 * @param[in] instance Device keeper structure to use.
     
    7678}
    7779/*----------------------------------------------------------------------------*/
    78 /** Attempts to obtain address 0, blocks.
     80/** Attempt to obtain address 0, blocks.
    7981 *
    8082 * @param[in] instance Device keeper structure to use.
     
    9092}
    9193/*----------------------------------------------------------------------------*/
    92 /** Checks setup data for signs of toggle reset.
     94/** Check setup packet data for signs of toggle reset.
    9395 *
    9496 * @param[in] instance Device keeper structure to use.
    9597 * @param[in] target Device to receive setup packet.
    9698 * @param[in] data Setup packet data.
     99 *
     100 * Really ugly one.
    97101 */
    98102void device_keeper_reset_if_need(
     
    105109            || !instance->devices[target.address].occupied) {
    106110                fibril_mutex_unlock(&instance->guard);
     111                usb_log_error("Invalid data when checking for toggle reset.\n");
    107112                return;
    108113        }
     
    130135}
    131136/*----------------------------------------------------------------------------*/
    132 /** Gets current value of endpoint toggle.
     137/** Get current value of endpoint toggle.
    133138 *
    134139 * @param[in] instance Device keeper structure to use.
     
    144149            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    145150            || !instance->devices[target.address].occupied) {
     151                usb_log_error("Invalid data when asking for toggle value.\n");
    146152                ret = EINVAL;
    147153        } else {
    148                 ret =
    149                     (instance->devices[target.address].toggle_status
     154                ret = (instance->devices[target.address].toggle_status
    150155                        >> target.endpoint) & 1;
    151156        }
     
    154159}
    155160/*----------------------------------------------------------------------------*/
    156 /** Sets current value of endpoint toggle.
     161/** Set current value of endpoint toggle.
    157162 *
    158163 * @param[in] instance Device keeper structure to use.
    159164 * @param[in] target Device and endpoint used.
    160  * @param[in] toggle Current toggle value.
     165 * @param[in] toggle Toggle value.
    161166 * @return Error code.
    162167 */
     
    170175            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    171176            || !instance->devices[target.address].occupied) {
     177                usb_log_error("Invalid data when setting toggle value.\n");
    172178                ret = EINVAL;
    173179        } else {
     
    183189}
    184190/*----------------------------------------------------------------------------*/
    185 /** Gets a free USB address
     191/** Get a free USB address
    186192 *
    187193 * @param[in] instance Device keeper structure to use.
     
    216222}
    217223/*----------------------------------------------------------------------------*/
    218 /** Binds USB address to devman handle.
     224/** Bind USB address to devman handle.
    219225 *
    220226 * @param[in] instance Device keeper structure to use.
     
    234240}
    235241/*----------------------------------------------------------------------------*/
    236 /** Releases used USB address.
     242/** Release used USB address.
    237243 *
    238244 * @param[in] instance Device keeper structure to use.
     
    251257}
    252258/*----------------------------------------------------------------------------*/
    253 /** Finds USB address associated with the device
     259/** Find USB address associated with the device
    254260 *
    255261 * @param[in] instance Device keeper structure to use.
     
    274280}
    275281/*----------------------------------------------------------------------------*/
    276 /** Gets speed associated with the address
     282/** Get speed associated with the address
    277283 *
    278284 * @param[in] instance Device keeper structure to use.
  • uspace/drv/uhci-hcd/utils/device_keeper.h

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

    rc32688d rbb41b85  
    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 */
    4550static inline uintptr_t addr_to_phys(void *addr)
    4651{
     
    4853        int ret = as_get_physical_mapping(addr, &result);
    4954
    50         assert(ret == 0);
     55        if (ret != EOK)
     56                return 0;
    5157        return (result | ((uintptr_t)addr & 0xfff));
    5258}
    53 
     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 */
    5465static inline void * malloc32(size_t size)
    5566        { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
    56 
    57 static inline void * get_page()
     67/*----------------------------------------------------------------------------*/
     68/** Physical mallocator simulator
     69 *
     70 * @param[in] addr Address of the place allocated by malloc32
     71 */
     72static 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 */
     79static inline void * get_page(void)
    5880{
    5981        void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
    6082        assert(free_address);
    6183        if (free_address == 0)
    62                 return 0;
     84                return NULL;
    6385        void* ret =
    6486          as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
    6587                  AS_AREA_READ | AS_AREA_WRITE);
    6688        if (ret != free_address)
    67                 return 0;
     89                return NULL;
    6890        return ret;
    6991}
    70 
    71 static inline void free32(void *addr)
    72         { if (addr) free(addr); }
    7392
    7493#endif
  • uspace/drv/uhci-rhd/Makefile

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

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI root hub initialization routines
    3333 */
    3434#include <ddf/driver.h>
     
    4040#include <usb/debug.h>
    4141
    42 
    43 
    4442#include "root_hub.h"
    4543
     
    4745static int hc_get_my_registers(ddf_dev_t *dev,
    4846    uintptr_t *io_reg_address, size_t *io_reg_size);
     47#if 0
    4948/*----------------------------------------------------------------------------*/
    5049static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
     
    6766        .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
    6867};
     68#endif
    6969/*----------------------------------------------------------------------------*/
    70 /** Initializes a new ddf driver instance of UHCI root hub.
     70/** Initialize 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 
    9183        uintptr_t io_regs = 0;
    9284        size_t io_size = 0;
    9385
    9486        int ret = hc_get_my_registers(device, &io_regs, &io_size);
    95         assert(ret == EOK);
     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);
    9692
    97         /* TODO: verify values from hc */
    98         usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size);
     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
    9999        ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
    100100        if (ret != EOK) {
     
    119119};
    120120/*----------------------------------------------------------------------------*/
    121 /** Initializes global driver structures (NONE).
     121/** Initialize global driver structures (NONE).
    122122 *
    123123 * @param[in] argc Nmber of arguments in argv vector (ignored).
  • uspace/drv/uhci-rhd/port.c

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
    33  */
     32 * @brief UHCI root hub port routines
     33 */
     34#include <libarch/ddi.h> /* pio_read and pio_write */
    3435#include <errno.h>
    3536#include <str_error.h>
     
    3738
    3839#include <usb/usb.h>    /* usb_address_t */
    39 #include <usb/usbdevice.h>
    4040#include <usb/hub.h>
    41 #include <usb/request.h>
    4241#include <usb/debug.h>
    43 #include <usb/recognise.h>
    4442
    4543#include "port.h"
    46 #include "port_status.h"
    4744
    4845static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
     
    5148static int uhci_port_check(void *port);
    5249static int uhci_port_reset_enable(int portno, void *arg);
    53 /*----------------------------------------------------------------------------*/
    54 /** Initializes UHCI root hub port instance.
     50static 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 */
     58static 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 */
     70static 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.
    5579 *
    5680 * @param[in] port Memory structure to use.
     
    6185 * @return Error code.
    6286 *
    63  * Starts the polling fibril.
     87 * Creates and starts the polling fibril.
    6488 */
    6589int uhci_port_init(uhci_port_t *port,
     
    6791{
    6892        assert(port);
     93        asprintf(&port->id_string, "Port (%p - %d)", port, number);
     94        if (port->id_string == NULL) {
     95                return ENOMEM;
     96        }
    6997
    7098        port->address = address;
     
    83111        port->checker = fibril_create(uhci_port_check, port);
    84112        if (port->checker == 0) {
    85                 usb_log_error("Port(%p - %d): failed to launch root hub fibril.",
    86                     port->address, port->number);
     113                usb_log_error("%s: failed to create polling fibril.",
     114                    port->id_string);
    87115                return ENOMEM;
    88116        }
    89117
    90118        fibril_add_ready(port->checker);
    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.
     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.
    97125 *
    98126 * @param[in] port Memory structure to use.
     
    102130void uhci_port_fini(uhci_port_t *port)
    103131{
     132        assert(port);
     133        free(port->id_string);
    104134        /* TODO: Kill fibril here */
    105135        return;
     
    108138/** Periodically checks port status and reports new devices.
    109139 *
    110  * @param[in] port Memory structure to use.
     140 * @param[in] port Port structure to use.
    111141 * @return Error code.
    112142 */
     
    116146        assert(instance);
    117147
    118         /* Iteration count, for debug purposes only */
    119         unsigned count = 0;
    120 
    121148        while (1) {
    122149                async_usleep(instance->wait_period_usec);
    123150
    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);
     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);
    135157
    136158                if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
    137159                        continue;
    138160
    139                 usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
    140                     instance->address, instance->number, port_status);
     161                usb_log_debug("%s: Connected change detected: %x.\n",
     162                    instance->id_string, port_status);
    141163
    142164                int rc =
    143165                    usb_hc_connection_open(&instance->hc_connection);
    144166                if (rc != EOK) {
    145                         usb_log_error("Port(%p - %d): Failed to connect to HC.",
    146                             instance->address, instance->number);
     167                        usb_log_error("%s: Failed to connect to HC.",
     168                            instance->id_string);
    147169                        continue;
    148170                }
     
    150172                /* Remove any old device */
    151173                if (instance->attached_device) {
    152                         usb_log_debug2("Port(%p - %d): Removing device.\n",
    153                             instance->address, instance->number);
     174                        usb_log_debug2("%s: Removing device.\n",
     175                            instance->id_string);
    154176                        uhci_port_remove_device(instance);
    155177                }
     
    163185                } else {
    164186                        /* Write one to WC bits, to ack changes */
    165                         port_status_write(instance->address, port_status);
    166                         usb_log_debug("Port(%p - %d): Change status ACK.\n",
    167                             instance->address, instance->number);
     187                        uhci_port_write_status(instance, port_status);
     188                        usb_log_debug("%s: status change ACK.\n",
     189                            instance->id_string);
    168190                }
    169191
    170192                rc = usb_hc_connection_close(&instance->hc_connection);
    171193                if (rc != EOK) {
    172                         usb_log_error("Port(%p - %d): Failed to disconnect.",
    173                             instance->address, instance->number);
     194                        usb_log_error("%s: Failed to disconnect.",
     195                            instance->id_string);
    174196                }
    175197        }
     
    182204 * @param arg Pointer to uhci_port_t of port with the new device.
    183205 * @return Error code.
     206 *
     207 * Resets and enables the ub port.
    184208 */
    185209int uhci_port_reset_enable(int portno, void *arg)
     
    187211        uhci_port_t *port = (uhci_port_t *) arg;
    188212
    189         usb_log_debug2("Port(%p - %d): new_device_enable_port.\n",
    190             port->address, port->number);
     213        usb_log_debug2("%s: new_device_enable_port.\n", port->id_string);
    191214
    192215        /*
     
    196219        async_usleep(100000);
    197220
    198 
    199         /* The hub maintains the reset signal to that port for 10 ms
    200          * (See Section 11.5.1.5)
     221        /*
     222         * Resets from root ports should be nominally 50ms
    201223         */
    202224        {
    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);
     225                usb_log_debug("%s: Reset Signal start.\n", port->id_string);
     226                port_status_t port_status = uhci_port_read_status(port);
    207227                port_status |= STATUS_IN_RESET;
    208                 port_status_write(port->address, port_status);
    209                 async_usleep(10000);
    210                 port_status = port_status_read(port->address);
     228                uhci_port_write_status(port, port_status);
     229                async_usleep(50000);
     230                port_status = uhci_port_read_status(port);
    211231                port_status &= ~STATUS_IN_RESET;
    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         }
     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);
    216238
    217239        /* Enable the port. */
    218240        uhci_port_set_enabled(port, true);
    219         return EOK;
    220 }
    221 /*----------------------------------------------------------------------------*/
    222 /** Initializes and reports connected device.
    223  *
    224  * @param[in] port Memory structure to use.
     241
     242        return EOK;
     243}
     244/*----------------------------------------------------------------------------*/
     245/** Initialize and report connected device.
     246 *
     247 * @param[in] port Port structure to use.
    225248 * @param[in] speed Detected speed.
    226249 * @return Error code.
     
    233256        assert(usb_hc_connection_is_opened(&port->hc_connection));
    234257
    235         usb_log_info("Port(%p-%d): Detected new device.\n",
    236             port->address, port->number);
     258        usb_log_info("%s: Detected new device.\n", port->id_string);
    237259
    238260        usb_address_t dev_addr;
     
    242264
    243265        if (rc != EOK) {
    244                 usb_log_error("Port(%p-%d): Failed(%d) to add device: %s.\n",
    245                     port->address, port->number, rc, str_error(rc));
     266                usb_log_error("%s: Failed(%d) to add device: %s.\n",
     267                    port->id_string, rc, str_error(rc));
    246268                uhci_port_set_enabled(port, false);
    247269                return rc;
    248270        }
    249271
    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.
     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.
    257279 *
    258280 * @param[in] port Memory structure to use.
    259281 * @return Error code.
    260282 *
    261  * Does not work DDF does not support device removal.
     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).
    262286 */
    263287int uhci_port_remove_device(uhci_port_t *port)
    264288{
    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.
     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.
    273298 * @return Error code. (Always EOK)
    274299 */
     
    278303
    279304        /* Read register value */
    280         port_status_t port_status = port_status_read(port->address);
     305        port_status_t port_status = uhci_port_read_status(port);
    281306
    282307        /* Set enabled bit */
     
    288313
    289314        /* Write new value. */
    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 /*----------------------------------------------------------------------------*/
     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 */
     328void 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}
    297346/**
    298347 * @}
  • uspace/drv/uhci-rhd/port.h

    rc32688d rbb41b85  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI port driver
     32 * @brief UHCI root hub port routines
    3333 */
    3434#ifndef DRV_UHCI_PORT_H
    3535#define DRV_UHCI_PORT_H
    3636
    37 #include <assert.h>
     37#include <stdint.h>
     38#include <fibril.h>
    3839#include <ddf/driver.h>
    39 #include <stdint.h>
    40 #include <usb/usbdevice.h>
     40#include <usb/usbdevice.h> /* usb_hc_connection_t */
    4141
    42 #include "port_status.h"
     42typedef 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)
    4355
    4456typedef struct uhci_port
    4557{
     58        char *id_string;
    4659        port_status_t *address;
    4760        unsigned number;
     
    5871
    5972void uhci_port_fini(uhci_port_t *port);
     73
    6074#endif
    6175/**
  • uspace/drv/uhci-rhd/root_hub.c

    rc32688d rbb41b85  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI root hub driver
    3333 */
    3434#include <errno.h>
    35 #include <stdint.h>
    3635#include <ddi.h>
    37 #include <devman.h>
    3836#include <usb/debug.h>
    3937
    4038#include "root_hub.h"
    4139
    42 /** Initializes UHCI root hub instance.
     40/** Initialize UHCI root hub instance.
    4341 *
    4442 * @param[in] instance Driver memory structure to use.
    4543 * @param[in] addr Address of I/O registers.
    4644 * @param[in] size Size of available I/O space.
    47  * @param[in] rh Pointer to ddf instance fo the root hub driver.
     45 * @param[in] rh Pointer to ddf instance of the root hub driver.
    4846 * @return Error code.
    4947 */
     
    6159        if (ret < 0) {
    6260                usb_log_error(
    63                     "Failed to gain access to port registers at %p\n", regs);
     61                    "Failed(%d) to gain access to port registers at %p\n",
     62                    ret, regs);
    6463                return ret;
    6564        }
    6665
    67         /* add fibrils for periodic port checks */
     66        /* Initialize root hub ports */
    6867        unsigned i = 0;
    6968        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
     
    8281}
    8382/*----------------------------------------------------------------------------*/
    84 /** Finishes UHCI root hub instance.
     83/** Cleanup UHCI root hub instance.
    8584 *
    86  * @param[in] instance Driver memory structure to use.
     85 * @param[in] instance Root hub structure to use.
    8786 * @return Error code.
    8887 */
  • uspace/drv/uhci-rhd/root_hub.h

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

    rc32688d rbb41b85  
    411411                return rc;
    412412        }
    413        
     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
    414420        /*
    415421         * Initialize the report parser.
  • uspace/drv/usbhub/usbhub.c

    rc32688d rbb41b85  
    7272int usb_hub_control_loop(void * hub_info_param){
    7373        usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param;
    74         while(true){
    75                 usb_hub_check_hub_changes(hub_info);
     74        int errorCode = EOK;
     75
     76        while(errorCode == EOK){
     77                errorCode = usb_hub_check_hub_changes(hub_info);
    7678                async_usleep(1000 * 1000 );/// \TODO proper number once
    7779        }
     80        dprintf(USB_LOG_LEVEL_ERROR,
     81                                "something in ctrl loop went wrong, errno %d",errorCode);
    7882        return 0;
    7983}
     
    118122                dprintf(USB_LOG_LEVEL_ERROR,
    119123                                "could not initialize connection to device endpoint, errno %d",opResult);
    120         }
    121         return 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;
    122134}
    123135
     
    372384 * @param target
    373385 */
    374 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port) {
     386static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,
     387                bool isLowSpeed) {
    375388        usb_device_request_setup_packet_t request;
    376389        int opResult;
     
    378391        assert(hub->endpoints.control.hc_phone);
    379392        //get default address
    380         //opResult = usb_drv_reserve_default_address(hc);
    381         opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
     393        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
     394        opResult = usb_hc_reserve_default_address(&hub->connection, speed);
    382395       
    383396        if (opResult != EOK) {
     
    430443                        &new_device_pipe,
    431444                        &new_device_connection);
     445        usb_endpoint_pipe_probe_default_control(&new_device_pipe);
    432446        /// \TODO get highspeed info
    433447        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
     
    437451        usb_address_t new_device_address = usb_hc_request_address(
    438452                        &hub->connection,
    439                         speed/// \TODO fullspeed??
     453                        speed
    440454                        );
    441455        if (new_device_address < 0) {
     
    501515static void usb_hub_removed_device(
    502516    usb_hub_info_t * hub,uint16_t port) {
    503         //usb_device_request_setup_packet_t request;
    504         int opResult;
    505        
     517               
    506518        /** \TODO remove device from device manager - not yet implemented in
    507519         * devide manager
     
    510522        //close address
    511523        if(hub->attached_devs[port].address!=0){
    512                 //opResult = usb_drv_release_address(hc,hub->attached_devs[port].address);
     524                /*uncomment this code to use it when DDF allows device removal
    513525                opResult = usb_hc_unregister_device(
    514526                                &hub->connection, hub->attached_devs[port].address);
     
    519531                hub->attached_devs[port].address = 0;
    520532                hub->attached_devs[port].handle = 0;
     533                 */
    521534        }else{
    522535                dprintf(USB_LOG_LEVEL_WARNING, "this is strange, disconnected device had no address");
     
    588601                if (usb_port_dev_connected(&status)) {
    589602                        dprintf(USB_LOG_LEVEL_INFO, "some connection changed");
    590                         usb_hub_init_add_device(hub, port);
     603                        usb_hub_init_add_device(hub, port, usb_port_low_speed(&status));
    591604                } else {
    592605                        usb_hub_removed_device(hub, port);
     
    626639/**
    627640 * Check changes on particular hub
    628  * @param hub_info_param
    629  */
    630 void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
     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 */
     645int usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
    631646        int opResult;
    632647        opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
     
    634649                dprintf(USB_LOG_LEVEL_ERROR,
    635650                                "could not initialize communication for hub; %d", opResult);
    636                 return;
     651                return opResult;
    637652        }
    638653
     
    656671                dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
    657672                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    658                 return;
     673                return opResult;
    659674        }
    660675        unsigned int port;
     
    664679                                opResult);
    665680                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    666                 return;
     681                return opResult;
    667682        }
    668683        opResult = usb_hc_connection_open(&hub_info->connection);
     
    672687                usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
    673688                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    674                 return;
     689                return opResult;
    675690        }
    676691
     
    688703        usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    689704        free(change_bitmap);
     705        return EOK;
    690706}
    691707
  • uspace/drv/usbhub/usbhub.h

    rc32688d rbb41b85  
    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
    9193 */
    92 void usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
     94int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
    9395
    9496
  • uspace/drv/usbmid/usbmid.c

    rc32688d rbb41b85  
    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        }
    118125
    119126        mid->dev = dev;
  • uspace/drv/usbmouse/init.c

    rc32688d rbb41b85  
    4242
    4343/** Mouse polling endpoint description for boot protocol subclass. */
    44 static usb_endpoint_description_t poll_endpoint_description = {
     44usb_endpoint_description_t poll_endpoint_description = {
    4545        .transfer_type = USB_TRANSFER_INTERRUPT,
    4646        .direction = USB_DIRECTION_IN,
     
    5050        .flags = 0
    5151};
    52 
    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  */
    61 static 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 }
    10152
    10253static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
     
    14394 * @return Error code.
    14495 */
    145 int usb_mouse_create(ddf_dev_t *dev)
     96int usb_mouse_create(usb_device_t *dev)
    14697{
    14798        usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
     
    149100                return ENOMEM;
    150101        }
    151         mouse->device = dev;
     102        mouse->dev = dev;
    152103        mouse->console_phone = -1;
    153104
    154105        int rc;
    155106
    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 
    183107        /* Create DDF function. */
    184         mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
     108        mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
    185109        if (mouse->mouse_fun == NULL) {
    186110                rc = ENOMEM;
  • uspace/drv/usbmouse/main.c

    rc32688d rbb41b85  
    4444 * @return Error code.
    4545 */
    46 static int usbmouse_add_device(ddf_dev_t *dev)
     46static int usbmouse_add_device(usb_device_t *dev)
    4747{
    4848        int rc = usb_mouse_create(dev);
     
    5353        }
    5454
    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;
     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;
    6065        }
    6166
    62         fibril_add_ready(poll_fibril);
    63 
    6467        usb_log_info("controlling new mouse (handle %llu).\n",
    65             dev->handle);
     68            dev->ddf_dev->handle);
    6669
    6770        return EOK;
     
    6972
    7073/** USB mouse driver ops. */
    71 static driver_ops_t mouse_driver_ops = {
     74static usb_driver_ops_t mouse_driver_ops = {
    7275        .add_device = usbmouse_add_device,
    7376};
    7477
     78static usb_endpoint_description_t *endpoints[] = {
     79        &poll_endpoint_description,
     80        NULL
     81};
     82
    7583/** USB mouse driver. */
    76 static driver_t mouse_driver = {
     84static usb_driver_t mouse_driver = {
    7785        .name = NAME,
    78         .driver_ops = &mouse_driver_ops
     86        .ops = &mouse_driver_ops,
     87        .endpoints = endpoints
    7988};
    8089
     
    8392        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    8493
    85         return ddf_driver_main(&mouse_driver);
     94        return usb_driver_main(&mouse_driver);
    8695}
    8796
  • uspace/drv/usbmouse/mouse.c

    rc32688d rbb41b85  
    4040#include <ipc/mouse.h>
    4141
    42 /** Fibril function for polling the mouse device.
     42/** Mouse polling callback.
    4343 *
    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.
     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.
    4949 */
    50 int usb_mouse_polling_fibril(void *arg)
     50bool usb_mouse_polling_callback(usb_device_t *dev,
     51    uint8_t *buffer, size_t buffer_size, void *arg)
    5152{
    52         assert(arg != NULL);
    53         ddf_dev_t *dev = (ddf_dev_t *) arg;
    54         usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data;
     53        usb_mouse_t *mouse = (usb_mouse_t *) arg;
    5554
    56         assert(mouse);
     55        usb_log_debug2("got buffer: %s.\n",
     56            usb_debug_str_buffer(buffer, buffer_size, 0));
    5757
    58         size_t buffer_size = mouse->poll_pipe.max_packet_size;
     58        uint8_t butt = buffer[0];
     59        char str_buttons[4] = {
     60                butt & 1 ? '#' : '.',
     61                butt & 2 ? '#' : '.',
     62                butt & 4 ? '#' : '.',
     63                0
     64        };
    5965
    60         if (buffer_size < 4) {
    61                 usb_log_error("Weird mouse, results will be skewed.\n");
    62                 buffer_size = 4;
     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;
    6378        }
    6479
    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;
     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                }
    6994        }
    7095
    71         while (true) {
    72                 async_usleep(mouse->poll_interval_us);
     96        usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
     97            str_buttons, shift_x, shift_y, wheel);
    7398
    74                 size_t actual_size;
    75                 int rc;
     99        /* Guess. */
     100        async_usleep(1000);
    76101
    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                  */
     102        return true;
     103}
    85104
    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                 }
     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 */
     112void 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;
    92116
    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          */
    154117        async_hangup(mouse->console_phone);
    155118        mouse->console_phone = -1;
    156 
    157         usb_log_error("Mouse polling fibril terminated.\n");
    158 
    159         return EOK;
    160119}
    161 
    162120
    163121/**
  • uspace/drv/usbmouse/mouse.h

    rc32688d rbb41b85  
    3737#define USBMOUSE_MOUSE_H_
    3838
    39 #include <ddf/driver.h>
     39#include <usb/devdrv.h>
    4040#include <usb/pipes.h>
    4141#include <time.h>
     
    4646typedef struct {
    4747        /** Generic device container. */
    48         ddf_dev_t *device;
     48        usb_device_t *dev;
    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;
    5751        /** Polling interval in microseconds. */
    5852        suseconds_t poll_interval_us;
     
    6155} usb_mouse_t;
    6256
    63 int usb_mouse_create(ddf_dev_t *);
     57#define POLL_PIPE(dev) ((dev)->pipes[0].pipe)
    6458
    65 int usb_mouse_polling_fibril(void *);
     59extern usb_endpoint_description_t poll_endpoint_description;
     60
     61int usb_mouse_create(usb_device_t *);
     62
     63bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t, void *);
     64void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
    6665
    6766#endif
  • uspace/lib/block/libblock.c

    rc32688d rbb41b85  
    411411        l = hash_table_find(&cache->block_hash, &key);
    412412        if (l) {
     413found:
    413414                /*
    414415                 * We found the block in the cache.
     
    493494                                        fibril_mutex_unlock(&b->lock);
    494495                                        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;
    495510                                }
    496511
  • uspace/lib/drv/generic/remote_usbhc.c

    rc32688d rbb41b85  
    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 *);
     57static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     58static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5759//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5860
     
    7375
    7476        remote_usbhc_control_write,
    75         remote_usbhc_control_read
     77        remote_usbhc_control_read,
     78
     79        remote_usbhc_register_endpoint,
     80        remote_usbhc_unregister_endpoint
    7681};
    7782
     
    522527
    523528
     529void 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
     562void 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
    524582
    525583/**
  • uspace/lib/drv/include/usbhc_iface.h

    rc32688d rbb41b85  
    167167        IPC_M_USBHC_CONTROL_READ,
    168168
    169         /* IPC_M_USB_ */
     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
    170192} usbhc_iface_funcs_t;
    171193
     
    200222        int (*release_address)(ddf_fun_t *, usb_address_t);
    201223
     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
    202229        usbhc_iface_transfer_out_t interrupt_out;
    203230        usbhc_iface_transfer_in_t interrupt_in;
  • uspace/lib/usb/Makefile

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

    rc32688d rbb41b85  
    106106        const usb_endpoint_description_t *description;
    107107        /** Interface number the endpoint must belong to (-1 for any). */
    108         const int interface_no;
     108        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 *);
     131int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *);
    131132int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    132133    size_t, uint8_t *, size_t, usb_device_connection_t *);
    133 
     134int usb_endpoint_pipe_register(usb_endpoint_pipe_t *, unsigned int,
     135    usb_hc_connection_t *);
     136int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *, usb_hc_connection_t *);
    134137
    135138int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
  • uspace/lib/usb/src/hub.c

    rc32688d rbb41b85  
    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        }
    237242
    238243        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
  • uspace/lib/usb/src/pipesinit.c

    rc32688d rbb41b85  
    3737#include <usb/pipes.h>
    3838#include <usb/dp.h>
     39#include <usb/request.h>
     40#include <usbhc_iface.h>
    3941#include <errno.h>
    4042#include <assert.h>
     43
     44#define CTRL_PIPE_MIN_PACKET_SIZE 8
     45#define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
    4146
    4247
     
    369374
    370375        int rc = usb_endpoint_pipe_initialize(pipe, connection,
    371             0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
     376            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
     377            USB_DIRECTION_BOTH);
    372378
    373379        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 */
     392int 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 */
     453int 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 */
     481int 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);
    374494}
    375495
  • uspace/lib/usb/src/recognise.c

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

    rc32688d rbb41b85  
    5454#define NAME  "apic"
    5555
     56static bool apic_found = false;
     57
    5658static int apic_enable_irq(sysarg_t irq)
    5759{
     
    7981                callid = async_get_call(&call);
    8082               
    81                 switch (IPC_GET_IMETHOD(call)) {
     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) {
    8294                case IRC_ENABLE_INTERRUPT:
    8395                        async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call)));
     
    97109 *
    98110 */
    99 static bool apic_init(void)
     111static void apic_init(void)
    100112{
    101113        sysarg_t apic;
    102114       
    103         if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) {
    104                 printf(NAME ": No APIC found\n");
    105                 return false;
     115        apic_found = sysinfo_get_value("apic", &apic) && apic;
     116        if (!apic_found) {
     117                printf(NAME ": Warning: no APIC found\n");
    106118        }
    107119       
    108120        async_set_client_connection(apic_connection);
    109121        service_register(SERVICE_APIC);
    110        
    111         return true;
    112122}
    113123
     
    116126        printf(NAME ": HelenOS APIC driver\n");
    117127       
    118         if (!apic_init())
    119                 return -1;
    120        
     128        apic_init();
     129
    121130        printf(NAME ": Accepting connections\n");
    122131        async_manager();
Note: See TracChangeset for help on using the changeset viewer.