Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-rhd/port.c

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