Ignore:
File:
1 edited

Legend:

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

    r275bf456 rf123909  
    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 * @}
Note: See TracChangeset for help on using the changeset viewer.