Changeset d7ff048 in mainline for uspace/drv


Ignore:
Timestamp:
2011-10-08T13:08:53Z (14 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bf08ff0
Parents:
8367d1d (diff), 80099c19 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

Location:
uspace/drv
Files:
6 added
4 deleted
6 edited
5 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbhub/Makefile

    r8367d1d rd7ff048  
    11#
    22# Copyright (c) 2010 Vojtech Horky
     3# Copyright (c) 2011 Jan Vesely
    34# All rights reserved.
    45#
     
    4344SOURCES = \
    4445        main.c \
    45         utils.c \
    4646        usbhub.c \
    47         ports.c
     47        port.c
    4848
    4949include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/bus/usb/usbhub/main.c

    r8367d1d rd7ff048  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    3839#include <usb/dev/driver.h>
    3940#include <usb/classes/classes.h>
     41#include <usb/debug.h>
    4042
    4143#include "usbhub.h"
    42 #include "usbhub_private.h"
    4344
    4445/** Hub status-change endpoint description.
     
    5657
    5758/**
    58  * usb hub driver operations
     59 * USB hub driver operations
    5960 *
    6061 * The most important one is add_device, which is set to usb_hub_add_device.
     
    6465};
    6566
    66 /**
    67  * hub endpoints, excluding control endpoint
    68  */
     67/** Hub endpoints, excluding control endpoint. */
    6968static usb_endpoint_description_t *usb_hub_endpoints[] = {
    7069        &hub_status_change_endpoint_description,
    71         NULL
     70        NULL,
    7271};
    73 
    74 /**
    75  * static usb hub driver information
    76  */
     72/** Static usb hub driver information. */
    7773static usb_driver_t usb_hub_driver = {
    7874        .name = NAME,
     
    8581{
    8682        printf(NAME ": HelenOS USB hub driver.\n");
    87 
    8883        usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
    8984
     
    9489 * @}
    9590 */
    96 
  • uspace/drv/bus/usb/usbhub/port.h

    r8367d1d rd7ff048  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    2627 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2728 */
    28 
    2929/** @addtogroup drvusbhub
    3030 * @{
     
    3333 * Hub ports related functions.
    3434 */
    35 #ifndef DRV_USBHUB_PORTS_H
    36 #define DRV_USBHUB_PORTS_H
     35#ifndef DRV_USBHUB_PORT_H
     36#define DRV_USBHUB_PORT_H
    3737
    3838#include <usb/dev/driver.h>
    3939#include <usb/dev/hub.h>
     40#include <usb/classes/hub.h>
    4041
    4142typedef struct usb_hub_info_t usb_hub_info_t;
     
    4344/** Information about single port on a hub. */
    4445typedef struct {
    45         /** Mutex needed by CV for checking port reset. */
    46         fibril_mutex_t reset_mutex;
     46        size_t port_number;
     47        usb_pipe_t *control_pipe;
     48        /** Mutex needed not only by CV for checking port reset. */
     49        fibril_mutex_t mutex;
    4750        /** CV for waiting to port reset completion. */
    4851        fibril_condvar_t reset_cv;
     
    6265 * @param port Port to be initialized.
    6366 */
    64 static inline void usb_hub_port_init(usb_hub_port_t *port) {
     67static inline void usb_hub_port_init(usb_hub_port_t *port, size_t port_number,
     68    usb_pipe_t *control_pipe)
     69{
     70        assert(port);
    6571        port->attached_device.address = -1;
    6672        port->attached_device.handle = 0;
    67         fibril_mutex_initialize(&port->reset_mutex);
     73        port->port_number = port_number;
     74        port->control_pipe = control_pipe;
     75        fibril_mutex_initialize(&port->mutex);
    6876        fibril_condvar_initialize(&port->reset_cv);
    6977}
    7078
    71 
    72 void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
    73         uint16_t port);
    74 
    75 
     79void usb_hub_port_reset_fail(usb_hub_port_t *port);
     80void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_info_t *hub);
     81int usb_hub_port_clear_feature(
     82    usb_hub_port_t *port, usb_hub_class_feature_t feature);
     83int usb_hub_port_set_feature(
     84    usb_hub_port_t *port, usb_hub_class_feature_t feature);
    7685
    7786#endif
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r8367d1d rd7ff048  
    11/*
    22 * Copyright (c) 2010 Matus Dekanek
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    3839#include <str_error.h>
    3940#include <inttypes.h>
    40 
    41 #include <usb_iface.h>
     41#include <stdio.h>
     42
     43#include <usb/usb.h>
     44#include <usb/debug.h>
     45#include <usb/dev/pipes.h>
     46#include <usb/classes/classes.h>
    4247#include <usb/ddfiface.h>
    4348#include <usb/descriptor.h>
     
    4651#include <usb/classes/hub.h>
    4752#include <usb/dev/poll.h>
    48 #include <stdio.h>
     53#include <usb_iface.h>
    4954
    5055#include "usbhub.h"
    51 #include "usbhub_private.h"
    52 #include "port_status.h"
    53 #include <usb/usb.h>
    54 #include <usb/dev/pipes.h>
    55 #include <usb/classes/classes.h>
    56 
    57 
     56#include "status.h"
     57
     58#define HUB_FNC_NAME "hub"
     59
     60/** Standard get hub global status request */
     61static const usb_device_request_setup_packet_t get_hub_status_request = {
     62        .request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS,
     63        .request = USB_HUB_REQUEST_GET_STATUS,
     64        .index = 0,
     65        .value = 0,
     66        .length = sizeof(usb_hub_status_t),
     67};
     68
     69static int usb_set_first_configuration(usb_device_t *usb_device);
    5870static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
    59 
    6071static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
    61 
    62 static int usb_hub_set_configuration(usb_hub_info_t *hub_info);
    63 
    64 static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info);
    65 
    66 static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
     72static void usb_hub_over_current(const usb_hub_info_t *hub_info,
    6773    usb_hub_status_t status);
    68 
    69 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
    70     usb_hub_status_t status);
    71 
    72 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info);
    73 
     74static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info);
    7475static void usb_hub_polling_terminated_callback(usb_device_t *device,
    7576    bool was_error, void *data);
    7677
    77 
    78 //*********************************************
    79 //
    80 //  hub driver code, initialization
    81 //
    82 //*********************************************
    83 
    8478/**
    8579 * Initialize hub device driver fibril
    8680 *
    87  * Creates hub representation and fibril that periodically checks hub`s status.
     81 * Creates hub representation and fibril that periodically checks hub's status.
    8882 * Hub representation is passed to the fibril.
    8983 * @param usb_dev generic usb device information
    9084 * @return error code
    9185 */
    92 int usb_hub_add_device(usb_device_t *usb_dev) {
    93         if (!usb_dev) return EINVAL;
     86int usb_hub_add_device(usb_device_t *usb_dev)
     87{
     88        assert(usb_dev);
     89        /* Create driver soft-state structure */
    9490        usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev);
    95         //create hc connection
     91        if (hub_info == NULL) {
     92                usb_log_error("Failed to create hun driver structure.\n");
     93                return ENOMEM;
     94        }
     95
     96        /* Create hc connection */
    9697        usb_log_debug("Initializing USB wire abstraction.\n");
    9798        int opResult = usb_hc_connection_initialize_from_device(
    98             &hub_info->connection,
    99             hub_info->usb_device->ddf_dev);
    100         if (opResult != EOK) {
    101                 usb_log_error("Could not initialize connection to device, "
    102                     " %s\n",
    103                     str_error(opResult));
    104                 free(hub_info);
    105                 return opResult;
    106         }
    107 
    108         //set hub configuration
    109         opResult = usb_hub_set_configuration(hub_info);
    110         if (opResult != EOK) {
    111                 usb_log_error("Could not set hub configuration, %s\n",
    112                     str_error(opResult));
    113                 free(hub_info);
    114                 return opResult;
    115         }
     99            &hub_info->connection, hub_info->usb_device->ddf_dev);
     100        if (opResult != EOK) {
     101                usb_log_error("Could not initialize connection to device: %s\n",
     102                    str_error(opResult));
     103                free(hub_info);
     104                return opResult;
     105        }
     106
     107        /* Set hub's first configuration. (There should be only one) */
     108        opResult = usb_set_first_configuration(usb_dev);
     109        if (opResult != EOK) {
     110                usb_log_error("Could not set hub configuration: %s\n",
     111                    str_error(opResult));
     112                free(hub_info);
     113                return opResult;
     114        }
     115
    116116        //get port count and create attached_devs
    117117        opResult = usb_hub_process_hub_specific_info(hub_info);
     
    123123        }
    124124
    125         usb_log_debug("Creating 'hub' function in DDF.\n");
     125        usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
    126126        ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
    127             fun_exposed, "hub");
    128         assert(hub_fun != NULL);
    129         hub_fun->ops = NULL;
     127            fun_exposed, HUB_FNC_NAME);
     128        if (hub_fun == NULL) {
     129                usb_log_error("Failed to create hub function.\n");
     130                free(hub_info);
     131                return ENOMEM;
     132        }
    130133
    131134        opResult = ddf_fun_bind(hub_fun);
    132         assert(opResult == EOK);
    133 
    134         opResult = usb_hub_start_hub_fibril(hub_info);
    135         if (opResult != EOK)
    136                 free(hub_info);
    137         return opResult;
    138 }
    139 
     135        if (opResult != EOK) {
     136                usb_log_error("Failed to bind hub function: %s.\n",
     137                   str_error(opResult));
     138                free(hub_info);
     139                ddf_fun_destroy(hub_fun);
     140                return opResult;
     141        }
     142
     143        opResult = usb_device_auto_poll(hub_info->usb_device, 0,
     144            hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
     145            usb_hub_polling_terminated_callback, hub_info);
     146        if (opResult != EOK) {
     147                ddf_fun_destroy(hub_fun);
     148                free(hub_info);
     149                usb_log_error("Failed to create polling fibril: %s.\n",
     150                    str_error(opResult));
     151                return opResult;
     152        }
     153        usb_log_info("Controlling hub '%s' (%zu ports).\n",
     154            hub_info->usb_device->ddf_dev->name, hub_info->port_count);
     155
     156        return EOK;
     157}
     158/*----------------------------------------------------------------------------*/
    140159/** Callback for polling hub for changes.
    141160 *
     
    147166 */
    148167bool hub_port_changes_callback(usb_device_t *dev,
    149     uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
     168    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg)
     169{
    150170        usb_log_debug("hub_port_changes_callback\n");
    151         usb_hub_info_t *hub = (usb_hub_info_t *) arg;
    152 
    153         /* FIXME: check that we received enough bytes. */
     171        usb_hub_info_t *hub = arg;
     172        assert(hub);
     173
     174        /* It is an error condition if we didn't receive enough data */
    154175        if (change_bitmap_size == 0) {
    155                 goto leave;
    156         }
    157 
    158         bool change;
    159         change = ((uint8_t*) change_bitmap)[0] & 1;
     176                return false;
     177        }
     178
     179        /* Lowest bit indicates global change */
     180        const bool change = change_bitmap[0] & 1;
    160181        if (change) {
    161                 usb_hub_process_global_interrupt(hub);
    162         }
    163 
    164         size_t port;
    165         for (port = 1; port < hub->port_count + 1; port++) {
    166                 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
     182                usb_hub_global_interrupt(hub);
     183        }
     184
     185        /* N + 1 bit indicates change on port N */
     186        size_t port = 1;
     187        for (; port < hub->port_count + 1; port++) {
     188                const bool change = (change_bitmap[port / 8] >> (port % 8)) & 1;
    167189                if (change) {
    168                         usb_hub_process_port_interrupt(hub, port);
     190                        usb_hub_port_process_interrupt(&hub->ports[port], hub);
    169191                }
    170192        }
    171 leave:
    172         /* FIXME: proper interval. */
    173         async_usleep(1000 * 250);
    174 
    175193        return true;
    176194}
    177 
    178 
    179 //*********************************************
    180 //
    181 //  support functions
    182 //
    183 //*********************************************
    184 
     195/*----------------------------------------------------------------------------*/
    185196/**
    186197 * create usb_hub_info_t structure
     
    190201 * @return basic usb_hub_info_t structure
    191202 */
    192 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) {
    193         usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t));
    194         if (!result) return NULL;
    195         result->usb_device = usb_dev;
    196         result->status_change_pipe = usb_dev->pipes[0].pipe;
    197         result->control_pipe = &usb_dev->ctrl_pipe;
    198         result->is_default_address_used = false;
    199 
    200         result->ports = NULL;
    201         result->port_count = (size_t) - 1;
    202         fibril_mutex_initialize(&result->port_mutex);
    203 
    204         fibril_mutex_initialize(&result->pending_ops_mutex);
    205         fibril_condvar_initialize(&result->pending_ops_cv);
    206         result->pending_ops_count = 0;
    207         return result;
    208 }
    209 
     203static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev)
     204{
     205        assert(usb_dev);
     206        usb_hub_info_t *info = malloc(sizeof(usb_hub_info_t));
     207        if (!info)
     208            return NULL;
     209
     210        info->usb_device = usb_dev;
     211
     212        info->ports = NULL;
     213        info->port_count = -1;
     214        fibril_mutex_initialize(&info->pending_ops_mutex);
     215        fibril_condvar_initialize(&info->pending_ops_cv);
     216        info->pending_ops_count = 0;
     217
     218        return info;
     219}
     220/*----------------------------------------------------------------------------*/
    210221/**
    211222 * Load hub-specific information into hub_info structure and process if needed
    212223 *
    213  * Particularly read port count and initialize structure holding port
    214  * information. If there are non-removable devices, start initializing them.
     224 * Read port count and initialize structures holding per port information.
     225 * If there are any non-removable devices, start initializing them.
    215226 * This function is hub-specific and should be run only after the hub is
    216  * configured using usb_hub_set_configuration function.
     227 * configured using usb_set_first_configuration function.
    217228 * @param hub_info hub representation
    218229 * @return error code
    219230 */
    220 int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
    221 {
    222         // get hub descriptor
     231static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
     232{
     233        assert(hub_info);
     234
     235        /* Get hub descriptor. */
    223236        usb_log_debug("Retrieving descriptor\n");
    224         uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
    225         int opResult;
    226 
     237        usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe;
     238
     239        usb_hub_descriptor_header_t descriptor;
    227240        size_t received_size;
    228         opResult = usb_request_get_descriptor(hub_info->control_pipe,
     241        int opResult = usb_request_get_descriptor(control_pipe,
    229242            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
    230             USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
    231             USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
    232 
     243            USB_DESCTYPE_HUB, 0, 0, &descriptor,
     244            sizeof(usb_hub_descriptor_t), &received_size);
    233245        if (opResult != EOK) {
    234246                usb_log_error("Failed to receive hub descriptor: %s.\n",
     
    236248                return opResult;
    237249        }
    238         usb_log_debug2("Parsing descriptor\n");
    239         usb_hub_descriptor_t descriptor;
    240         opResult = usb_deserialize_hub_desriptor(
    241                 serialized_descriptor, received_size, &descriptor);
    242         if (opResult != EOK) {
    243                 usb_log_error("Could not parse descriptor: %s\n",
    244                     str_error(opResult));
    245                 return opResult;
    246         }
    247         usb_log_debug("Setting port count to %d.\n", descriptor.ports_count);
    248         hub_info->port_count = descriptor.ports_count;
    249 
     250
     251        usb_log_debug("Setting port count to %d.\n", descriptor.port_count);
     252        hub_info->port_count = descriptor.port_count;
     253
     254        // TODO: +1 hack is no longer necessary
    250255        hub_info->ports =
    251256            malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1));
     
    256261        size_t port;
    257262        for (port = 0; port < hub_info->port_count + 1; ++port) {
    258                 usb_hub_port_init(&hub_info->ports[port]);
     263                usb_hub_port_init(&hub_info->ports[port], port, control_pipe);
    259264        }
    260265
    261266        const bool is_power_switched =
    262             !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
     267            !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
    263268        if (is_power_switched) {
    264269                usb_log_debug("Hub power switched\n");
    265                 const bool per_port_power = descriptor.hub_characteristics
     270                const bool per_port_power = descriptor.characteristics
    266271                    & HUB_CHAR_POWER_PER_PORT_FLAG;
    267272
    268273                for (port = 1; port <= hub_info->port_count; ++port) {
    269274                        usb_log_debug("Powering port %zu.\n", port);
    270                         opResult = usb_hub_set_port_feature(
    271                             hub_info->control_pipe,
    272                             port, USB_HUB_FEATURE_PORT_POWER);
     275                        opResult = usb_hub_port_set_feature(
     276                            &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER);
    273277                        if (opResult != EOK) {
    274278                                usb_log_error("Cannot power on port %zu: %s.\n",
     
    283287                        }
    284288                }
    285 
    286289        } else {
    287                 usb_log_debug("Power not switched, not going to be powered\n");
     290                usb_log_debug("Power not switched, ports always powered\n");
    288291        }
    289292        return EOK;
    290293}
    291 
    292 /**
    293  * Set configuration of hub
     294/*----------------------------------------------------------------------------*/
     295/**
     296 * Set configuration of and USB device
    294297 *
    295298 * Check whether there is at least one configuration and sets the first one.
    296299 * This function should be run prior to running any hub-specific action.
    297  * @param hub_info hub representation
     300 * @param usb_device usb device representation
    298301 * @return error code
    299302 */
    300 static int usb_hub_set_configuration(usb_hub_info_t *hub_info) {
    301         //device descriptor
    302         usb_standard_device_descriptor_t *std_descriptor
    303             = &hub_info->usb_device->descriptors.device;
    304         usb_log_debug("Hub has %d configurations\n",
    305             std_descriptor->configuration_count);
    306         if (std_descriptor->configuration_count < 1) {
     303static int usb_set_first_configuration(usb_device_t *usb_device)
     304{
     305        assert(usb_device);
     306        /* Get number of possible configurations from device descriptor */
     307        const size_t configuration_count =
     308            usb_device->descriptors.device.configuration_count;
     309        usb_log_debug("Hub has %zu configurations.\n", configuration_count);
     310
     311        if (configuration_count < 1) {
    307312                usb_log_error("There are no configurations available\n");
    308313                return EINVAL;
    309314        }
    310315
     316        // TODO: Make sure that there is enough data and the cast is correct
    311317        usb_standard_configuration_descriptor_t *config_descriptor
    312318            = (usb_standard_configuration_descriptor_t *)
    313             hub_info->usb_device->descriptors.configuration;
    314 
    315         /* Set configuration. */
    316         int opResult = usb_request_set_configuration(
    317             &hub_info->usb_device->ctrl_pipe,
    318             config_descriptor->configuration_number);
    319 
     319            usb_device->descriptors.configuration;
     320
     321        /* Set configuration. Use the configuration that was in
     322         * usb_device->descriptors.configuration i.e. The first one. */
     323        const int opResult = usb_request_set_configuration(
     324            &usb_device->ctrl_pipe, config_descriptor->configuration_number);
    320325        if (opResult != EOK) {
    321326                usb_log_error("Failed to set hub configuration: %s.\n",
    322327                    str_error(opResult));
    323                 return opResult;
    324         }
    325         usb_log_debug("\tUsed configuration %d\n",
    326             config_descriptor->configuration_number);
    327 
    328         return EOK;
    329 }
    330 
    331 /**
    332  * create and start fibril with hub control loop
    333  *
    334  * Before the fibril is started, the control pipe and host controller
    335  * connection of the hub is open.
    336  *
    337  * @param hub_info hub representing structure
    338  * @return error code
    339  */
    340 static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info) {
    341         int rc;
    342 
    343         rc = usb_device_auto_poll(hub_info->usb_device, 0,
    344             hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
    345             usb_hub_polling_terminated_callback, hub_info);
    346         if (rc != EOK) {
    347                 usb_log_error("Failed to create polling fibril: %s.\n",
    348                     str_error(rc));
    349                 free(hub_info);
    350                 return rc;
    351         }
    352 
    353         usb_log_info("Controlling hub `%s' (%zu ports).\n",
    354             hub_info->usb_device->ddf_dev->name, hub_info->port_count);
    355         return EOK;
    356 }
    357 
    358 //*********************************************
    359 //
    360 //  change handling functions
    361 //
    362 //*********************************************
    363 
    364 /**
    365  * process hub over current change
     328        } else {
     329                usb_log_debug("\tUsed configuration %d\n",
     330                    config_descriptor->configuration_number);
     331        }
     332        return opResult;
     333}
     334/*----------------------------------------------------------------------------*/
     335/**
     336 * Process hub over current change
    366337 *
    367338 * This means either to power off the hub or power it on.
     
    370341 * @return error code
    371342 */
    372 static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
    373     usb_hub_status_t status) {
    374         int opResult;
    375         if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) {
    376                 //poweroff all ports
    377                 unsigned int port;
     343static void usb_hub_over_current(const usb_hub_info_t *hub_info,
     344    usb_hub_status_t status)
     345{
     346        if (status & USB_HUB_STATUS_OVER_CURRENT) {
     347                /* Hub should remove power from all ports if it detects OC */
     348                usb_log_warning("Detected hub over-current condition, "
     349                    "all ports should be powered off.");
     350        } else {
     351                /* Over-current condition is gone, it is safe to turn the
     352                 * ports on. */
     353                size_t port;
    378354                for (port = 1; port <= hub_info->port_count; ++port) {
    379                         opResult = usb_hub_clear_port_feature(
    380                             hub_info->control_pipe, port,
    381                             USB_HUB_FEATURE_PORT_POWER);
     355                        const int opResult = usb_hub_port_set_feature(
     356                            &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER);
    382357                        if (opResult != EOK) {
    383358                                usb_log_warning(
    384                                     "Cannot power off port %d;  %s\n",
     359                                    "HUB OVER-CURRENT GONE: Cannot power on "
     360                                    "port %zu;  %s\n",
    385361                                    port, str_error(opResult));
    386362                        }
    387363                }
    388         } else {
    389                 //power all ports
    390                 unsigned int port;
    391                 for (port = 1; port <= hub_info->port_count; ++port) {
    392                         opResult = usb_hub_set_port_feature(
    393                             hub_info->control_pipe, port,
    394                             USB_HUB_FEATURE_PORT_POWER);
    395                         if (opResult != EOK) {
    396                                 usb_log_warning(
    397                                     "Cannot power off port %d;  %s\n",
    398                                     port, str_error(opResult));
    399                         }
    400                 }
    401         }
    402         return opResult;
    403 }
    404 
    405 /**
    406  * process hub local power change
    407  *
    408  * This change is ignored.
     364        }
     365        const int opResult = usb_request_clear_feature(
     366            &hub_info->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
     367            USB_REQUEST_RECIPIENT_DEVICE,
     368            USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
     369        if (opResult != EOK) {
     370                usb_log_error(
     371                    "Failed to clear hub over-current change flag: %s.\n",
     372                    str_error(opResult));
     373        }
     374}
     375/*----------------------------------------------------------------------------*/
     376/**
     377 * Process hub interrupts.
     378 *
     379 * The change can be either in the over-current condition or local-power change.
    409380 * @param hub_info hub instance
    410  * @param status hub status bitmask
    411  * @return error code
    412  */
    413 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
    414     usb_hub_status_t status) {
    415         int opResult = EOK;
    416         opResult = usb_hub_clear_feature(hub_info->control_pipe,
    417             USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    418         if (opResult != EOK) {
    419                 usb_log_error("Cannnot clear hub power change flag: "
    420                     "%s\n",
    421                     str_error(opResult));
    422         }
    423         return opResult;
    424 }
    425 
    426 /**
    427  * process hub interrupts
    428  *
    429  * The change can be either in the over-current condition or
    430  * local-power change.
    431  * @param hub_info hub instance
    432  */
    433 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) {
     381 */
     382static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info)
     383{
     384        assert(hub_info);
     385        assert(hub_info->usb_device);
    434386        usb_log_debug("Global interrupt on a hub\n");
    435         usb_pipe_t *pipe = hub_info->control_pipe;
    436         int opResult;
    437 
    438         usb_port_status_t status;
     387        usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe;
     388
     389        usb_hub_status_t status;
    439390        size_t rcvd_size;
    440         usb_device_request_setup_packet_t request;
    441         //int opResult;
    442         usb_hub_set_hub_status_request(&request);
    443         //endpoint 0
    444 
    445         opResult = usb_pipe_control_read(
    446             pipe,
    447             &request, sizeof (usb_device_request_setup_packet_t),
    448             &status, 4, &rcvd_size
    449             );
     391        /* NOTE: We can't use standard USB GET_STATUS request, because
     392         * hubs reply is 4byte instead of 2 */
     393        const int opResult = usb_pipe_control_read(control_pipe,
     394            &get_hub_status_request, sizeof(get_hub_status_request),
     395            &status, sizeof(usb_hub_status_t), &rcvd_size);
    450396        if (opResult != EOK) {
    451397                usb_log_error("Could not get hub status: %s\n",
     
    453399                return;
    454400        }
    455         if (rcvd_size != sizeof (usb_port_status_t)) {
     401        if (rcvd_size != sizeof(usb_hub_status_t)) {
    456402                usb_log_error("Received status has incorrect size\n");
    457403                return;
    458404        }
    459         //port reset
    460         if (
    461             usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
    462                 usb_process_hub_over_current(hub_info, status);
    463         }
    464         if (
    465             usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
    466                 usb_process_hub_local_power_change(hub_info, status);
    467         }
    468 }
    469 
     405
     406        /* Handle status changes */
     407        if (status & USB_HUB_STATUS_C_OVER_CURRENT) {
     408                usb_hub_over_current(hub_info, status);
     409        }
     410
     411        if (status & USB_HUB_STATUS_C_LOCAL_POWER) {
     412                /* NOTE: Handling this is more complicated.
     413                 * If the transition is from bus power to local power, all
     414                 * is good and we may signal the parent hub that we don't
     415                 * need the power.
     416                 * If the transition is from local power to bus power
     417                 * the hub should turn off all the ports and devices need
     418                 * to be reinitialized taking into account the limited power
     419                 * that is now available.
     420                 * There is no support for power distribution in HelenOS,
     421                 * (or other OSes/hub devices that I've seen) so this is not
     422                 * implemented.
     423                 * Just ACK the change.
     424                 */
     425                const int opResult = usb_request_clear_feature(
     426                    control_pipe, USB_REQUEST_TYPE_CLASS,
     427                    USB_REQUEST_RECIPIENT_DEVICE,
     428                    USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
     429                if (opResult != EOK) {
     430                        usb_log_error(
     431                            "Failed to clear hub power change flag: %s.\n",
     432                            str_error(opResult));
     433                }
     434        }
     435}
     436/*----------------------------------------------------------------------------*/
    470437/**
    471438 * callback called from hub polling fibril when the fibril terminates
     
    477444 */
    478445static void usb_hub_polling_terminated_callback(usb_device_t *device,
    479     bool was_error, void *data) {
    480         usb_hub_info_t * hub = data;
     446    bool was_error, void *data)
     447{
     448        usb_hub_info_t *hub = data;
    481449        assert(hub);
    482450
     
    492460         */
    493461        if (hub->pending_ops_count > 0) {
    494                 fibril_mutex_lock(&hub->port_mutex);
    495462                size_t port;
    496463                for (port = 0; port < hub->port_count; port++) {
    497                         usb_hub_port_t *the_port = hub->ports + port;
    498                         fibril_mutex_lock(&the_port->reset_mutex);
    499                         the_port->reset_completed = true;
    500                         the_port->reset_okay = false;
    501                         fibril_condvar_broadcast(&the_port->reset_cv);
    502                         fibril_mutex_unlock(&the_port->reset_mutex);
     464                        usb_hub_port_reset_fail(&hub->ports[port]);
    503465                }
    504                 fibril_mutex_unlock(&hub->port_mutex);
    505466        }
    506467        /* And now wait for them. */
     
    516477        free(hub);
    517478}
    518 
    519 
    520 
    521 
    522479/**
    523480 * @}
  • uspace/drv/bus/usb/usbhub/usbhub.h

    r8367d1d rd7ff048  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
     3 * Copyright (c) 2011 Vojtech Horky
    34 * All rights reserved.
    45 *
     
    2627 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2728 */
    28 
    2929/** @addtogroup drvusbhub
    3030 * @{
     
    4949#define NAME "usbhub"
    5050
    51 #include "ports.h"
     51#include "port.h"
    5252
    5353/** Information about attached hub. */
     
    5656        size_t port_count;
    5757
    58         /** attached device handles, for each port one */
     58        /** Attached device handles, for each port one */
    5959        usb_hub_port_t *ports;
    6060
    61         fibril_mutex_t port_mutex;
    62 
    63         /** connection to hcd */
     61        /** Connection to hcd */
    6462        usb_hc_connection_t connection;
    6563
    66         /** default address is used indicator
    67          *
    68          * If default address is requested by this device, it cannot
    69          * be requested by the same hub again, otherwise a deadlock will occur.
    70          */
    71         bool is_default_address_used;
    72 
    73         /** convenience pointer to status change pipe
    74          *
    75          * Status change pipe is initialized in usb_device structure. This is
    76          * pointer into this structure, so that it does not have to be
    77          * searched again and again for the 'right pipe'.
    78          */
    79         usb_pipe_t * status_change_pipe;
    80 
    81         /** convenience pointer to control pipe
    82          *
    83          * Control pipe is initialized in usb_device structure. This is
    84          * pointer into this structure, so that it does not have to be
    85          * searched again and again for the 'right pipe'.
    86          */
    87         usb_pipe_t * control_pipe;
    88 
    89         /** generic usb device data*/
    90         usb_device_t * usb_device;
     64        /** Generic usb device data*/
     65        usb_device_t *usb_device;
    9166
    9267        /** Number of pending operations on the mutex to prevent shooting
     
    10176        /** Condition variable for pending_ops_count. */
    10277        fibril_condvar_t pending_ops_cv;
    103 
    10478};
    10579
  • uspace/drv/bus/usb/usbmast/main.c

    r8367d1d rd7ff048  
    9494
    9595        /* Allocate softstate */
    96         mdev = calloc(1, sizeof(usbmast_dev_t));
     96        mdev = ddf_dev_data_alloc(dev->ddf_dev, sizeof(usbmast_dev_t));
    9797        if (mdev == NULL) {
    9898                usb_log_error("Failed allocating softstate.\n");
    99                 rc = ENOMEM;
    100                 goto error;
     99                return ENOMEM;
    101100        }
    102101
     
    125124error:
    126125        /* XXX Destroy functions */
    127         if (mdev != NULL)
    128                 free(mdev);
    129126        return rc;
    130127}
     
    158155        }
    159156
    160         free(fun_name);
    161 
    162157        /* Allocate soft state */
    163         mfun = ddf_dev_data_alloc(mdev->ddf_dev, sizeof(usbmast_fun_t));
     158        mfun = ddf_fun_data_alloc(fun, sizeof(usbmast_fun_t));
    164159        if (mfun == NULL) {
    165160                usb_log_error("Failed allocating softstate.\n");
     
    171166        mfun->lun = lun;
    172167
    173         fun_name = NULL;
    174 
    175168        /* Set up a connection handler. */
    176169        fun->conn_handler = usbmast_bd_connection;
    177         fun->driver_data = mfun;
    178170
    179171        usb_log_debug("Inquire...\n");
     
    219211                goto error;
    220212        }
     213
     214        free(fun_name);
    221215
    222216        return EOK;
  • uspace/drv/infrastructure/rootvirt/devices.def

    r8367d1d rd7ff048  
    44 * Unless the list is empty, the last item shall be followed by a comma.
    55 */
     6
     7/* Loopback network interface */
     8{
     9    .name = "lo",
     10    .match_id = "virtual&loopback"
     11},
     12
    613#ifdef CONFIG_TEST_DRIVERS
     14
    715{
    816        .name = "test1",
     
    2533        .match_id = "virtual&test3"
    2634},
     35
    2736#endif
     37
    2838#ifdef CONFIG_RUN_VIRTUAL_USB_HC
     39
    2940/* Virtual USB host controller. */
    3041{
     
    3243        .match_id = "usb&hc=vhc"
    3344},
     45
    3446#endif
  • uspace/drv/nic/lo/Makefile

    r8367d1d rd7ff048  
    11#
    2 # Copyright (c) 2005 Martin Decky
    3 # Copyright (c) 2007 Jakub Jermar
     2# Copyright (c) 2011 Radim Vansa
    43# All rights reserved.
    54#
     
    2827#
    2928
    30 USPACE_PREFIX = ../..
    31 EXTRA_CFLAGS = -Iinclude
    32 LIBRARY = libpacket
     29USPACE_PREFIX = ../../..
     30LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a
     31EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include
     32BINARY = lo
    3333
    3434SOURCES = \
    35         generic/packet_server.c
     35        lo.c
    3636
    3737include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/nic/ne2k/Makefile

    r8367d1d rd7ff048  
    11#
    2 # Copyright (c) 2005 Martin Decky
    3 # Copyright (c) 2007 Jakub Jermar
     2# Copyright (c) 2011 Radim Vansa
    43# All rights reserved.
    54#
     
    2827#
    2928
    30 USPACE_PREFIX = ../../../..
    31 ROOT_PATH = $(USPACE_PREFIX)/..
    32 LIBS = $(LIBNET_PREFIX)/libnet.a
    33 EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
    34 
    35 COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
    36 CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
    37 
    38 -include $(COMMON_MAKEFILE)
    39 -include $(CONFIG_MAKEFILE)
    40 
    41 BINARY = lo
     29USPACE_PREFIX = ../../..
     30LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a
     31EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include
     32BINARY = ne2k
    4233
    4334SOURCES = \
    44         lo.c
     35        dp8390.c \
     36        ne2k.c
    4537
    4638include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/nic/ne2k/dp8390.c

    r8367d1d rd7ff048  
    22 * Copyright (c) 2009 Lukas Mejdrech
    33 * Copyright (c) 2011 Martin Decky
     4 * Copyright (c) 2011 Radim Vansa
    45 * All rights reserved.
    56 *
     
    3839 */
    3940
    40 /** @addtogroup ne2000
    41  *  @{
    42  */
    43 
    44 /** @file
     41/**
     42 * @addtogroup drv_ne2k
     43 * @{
     44 */
     45
     46/**
     47 * @file
     48 * @brief NE2000 driver core
    4549 *
    4650 * NE2000 (based on DP8390) network interface core implementation.
     
    6569#define SQ_PAGES  6
    6670
    67 /* NE2000 implementation. */
    68 
    69 /** NE2000 Data Register */
    70 #define NE2K_DATA  0x0010
    71 
    72 /** NE2000 Reset register */
    73 #define NE2K_RESET  0x001f
    74 
    75 /** NE2000 data start */
    76 #define NE2K_START  0x4000
    77 
    78 /** NE2000 data size */
    79 #define NE2K_SIZE  0x4000
    80 
    81 /** NE2000 retry count */
    82 #define NE2K_RETRY  0x1000
    83 
    84 /** NE2000 error messages rate limiting */
    85 #define NE2K_ERL  10
    86 
    87 /** Minimum Ethernet packet size in bytes */
    88 #define ETH_MIN_PACK_SIZE  60
    89 
    90 /** Maximum Ethernet packet size in bytes */
    91 #define ETH_MAX_PACK_SIZE_TAGGED  1518
    92 
    9371/** Type definition of the receive header
    9472 *
     
    216194 *
    217195 */
    218 int ne2k_probe(ne2k_t *ne2k, void *port, int irq)
     196int ne2k_probe(ne2k_t *ne2k)
    219197{
    220198        unsigned int i;
    221        
    222         /* General initialization */
    223         ne2k->port = port;
    224         ne2k->data_port = ne2k->port + NE2K_DATA;
    225         ne2k->irq = irq;
    226         ne2k->probed = false;
    227         ne2k->up = false;
    228199       
    229200        ne2k_init(ne2k);
     
    247218       
    248219        for (i = 0; i < ETH_ADDR; i++)
    249                 ne2k->mac[i] = pio_read_16(ne2k->data_port);
    250        
    251         ne2k->probed = true;
     220                ne2k->mac.address[i] = pio_read_16(ne2k->data_port);
     221       
    252222        return EOK;
     223}
     224
     225void ne2k_set_physical_address(ne2k_t *ne2k, const nic_address_t *address)
     226{
     227        memcpy(&ne2k->mac, address, sizeof(nic_address_t));
     228       
     229        pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STP);
     230       
     231        pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1);
     232        pio_write_8(ne2k->port + DP_RBCR1, 0);
     233        pio_write_8(ne2k->port + DP_RSAR0, 0);
     234        pio_write_8(ne2k->port + DP_RSAR1, 0);
     235        pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
     236
     237        size_t i;
     238        for (i = 0; i < ETH_ADDR; i++)
     239                pio_write_16(ne2k->data_port, ne2k->mac.address[i]);
     240
     241        //pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA);
    253242}
    254243
     
    304293       
    305294        /* Step 4: */
    306         pio_write_8(ne2k->port + DP_RCR, RCR_AB);
     295        pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration);
    307296       
    308297        /* Step 5: */
     
    324313        pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
    325314       
    326         pio_write_8(ne2k->port + DP_PAR0, ne2k->mac[0]);
    327         pio_write_8(ne2k->port + DP_PAR1, ne2k->mac[1]);
    328         pio_write_8(ne2k->port + DP_PAR2, ne2k->mac[2]);
    329         pio_write_8(ne2k->port + DP_PAR3, ne2k->mac[3]);
    330         pio_write_8(ne2k->port + DP_PAR4, ne2k->mac[4]);
    331         pio_write_8(ne2k->port + DP_PAR5, ne2k->mac[5]);
    332        
    333         pio_write_8(ne2k->port + DP_MAR0, 0xff);
    334         pio_write_8(ne2k->port + DP_MAR1, 0xff);
    335         pio_write_8(ne2k->port + DP_MAR2, 0xff);
    336         pio_write_8(ne2k->port + DP_MAR3, 0xff);
    337         pio_write_8(ne2k->port + DP_MAR4, 0xff);
    338         pio_write_8(ne2k->port + DP_MAR5, 0xff);
    339         pio_write_8(ne2k->port + DP_MAR6, 0xff);
    340         pio_write_8(ne2k->port + DP_MAR7, 0xff);
     315        pio_write_8(ne2k->port + DP_PAR0, ne2k->mac.address[0]);
     316        pio_write_8(ne2k->port + DP_PAR1, ne2k->mac.address[1]);
     317        pio_write_8(ne2k->port + DP_PAR2, ne2k->mac.address[2]);
     318        pio_write_8(ne2k->port + DP_PAR3, ne2k->mac.address[3]);
     319        pio_write_8(ne2k->port + DP_PAR4, ne2k->mac.address[4]);
     320        pio_write_8(ne2k->port + DP_PAR5, ne2k->mac.address[5]);
     321       
     322        pio_write_8(ne2k->port + DP_MAR0, 0);
     323        pio_write_8(ne2k->port + DP_MAR1, 0);
     324        pio_write_8(ne2k->port + DP_MAR2, 0);
     325        pio_write_8(ne2k->port + DP_MAR3, 0);
     326        pio_write_8(ne2k->port + DP_MAR4, 0);
     327        pio_write_8(ne2k->port + DP_MAR5, 0);
     328        pio_write_8(ne2k->port + DP_MAR6, 0);
     329        pio_write_8(ne2k->port + DP_MAR7, 0);
    341330       
    342331        pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1);
     
    372361}
    373362
     363static void ne2k_reset(ne2k_t *ne2k)
     364{
     365        unsigned int i;
     366
     367        fibril_mutex_lock(&ne2k->sq_mutex);
     368
     369        /* Stop the chip */
     370        pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
     371        pio_write_8(ne2k->port + DP_RBCR0, 0);
     372        pio_write_8(ne2k->port + DP_RBCR1, 0);
     373
     374        for (i = 0; i < NE2K_RETRY; i++) {
     375                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
     376                        break;
     377        }
     378
     379        pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST);
     380        pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT);
     381        pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
     382
     383        /* Acknowledge the ISR_RDC (remote DMA) interrupt */
     384        for (i = 0; i < NE2K_RETRY; i++) {
     385                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
     386                        break;
     387        }
     388
     389        uint8_t val = pio_read_8(ne2k->port + DP_ISR);
     390        pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC);
     391
     392        /*
     393         * Reset the transmit ring. If we were transmitting a frame,
     394         * we pretend that the packet is processed. Higher layers will
     395         * retransmit if the packet wasn't actually sent.
     396         */
     397        ne2k->sq.dirty = false;
     398
     399        fibril_mutex_unlock(&ne2k->sq_mutex);
     400}
     401
    374402/** Send a frame.
    375403 *
     
    378406 *
    379407 */
    380 void ne2k_send(ne2k_t *ne2k, packet_t *packet)
    381 {
     408void ne2k_send(nic_t *nic_data, packet_t *packet)
     409{
     410        ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
     411
    382412        assert(ne2k->probed);
    383413        assert(ne2k->up);
    384        
     414
    385415        fibril_mutex_lock(&ne2k->sq_mutex);
    386416       
    387         while (ne2k->sq.dirty)
     417        while (ne2k->sq.dirty) {
    388418                fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex);
    389        
     419        }
    390420        void *buf = packet_get_data(packet);
    391421        size_t size = packet_get_data_length(packet);
     
    393423        if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) {
    394424                fibril_mutex_unlock(&ne2k->sq_mutex);
    395                 fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",
    396                     NAME, size);
    397425                return;
    398426        }
    399        
     427
    400428        /* Upload the frame to the ethernet card */
    401429        ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size);
    402430        ne2k->sq.dirty = true;
    403431        ne2k->sq.size = size;
    404        
     432
    405433        /* Initialize the transfer */
    406434        pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page);
     
    408436        pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff);
    409437        pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA);
    410        
    411438        fibril_mutex_unlock(&ne2k->sq_mutex);
    412 }
    413 
    414 static void ne2k_reset(ne2k_t *ne2k)
    415 {
    416         unsigned int i;
    417        
    418         /* Stop the chip */
    419         pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
    420         pio_write_8(ne2k->port + DP_RBCR0, 0);
    421         pio_write_8(ne2k->port + DP_RBCR1, 0);
    422        
    423         for (i = 0; i < NE2K_RETRY; i++) {
    424                 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
    425                         break;
    426         }
    427        
    428         pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST);
    429         pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT);
    430         pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
    431        
    432         /* Acknowledge the ISR_RDC (remote DMA) interrupt */
    433         for (i = 0; i < NE2K_RETRY; i++) {
    434                 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
    435                         break;
    436         }
    437        
    438         uint8_t val = pio_read_8(ne2k->port + DP_ISR);
    439         pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC);
    440        
    441         /*
    442          * Reset the transmit ring. If we were transmitting a frame,
    443          * we pretend that the packet is processed. Higher layers will
    444          * retransmit if the packet wasn't actually sent.
    445          */
    446         fibril_mutex_lock(&ne2k->sq_mutex);
    447         ne2k->sq.dirty = false;
    448         fibril_mutex_unlock(&ne2k->sq_mutex);
    449 }
    450 
    451 static frame_t *ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length)
    452 {
    453         frame_t *frame = (frame_t *) malloc(sizeof(frame_t));
     439
     440        /* Relase packet */
     441        nic_release_packet(nic_data, packet);
     442}
     443
     444static nic_frame_t *ne2k_receive_frame(nic_t *nic_data, uint8_t page,
     445        size_t length)
     446{
     447        ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
     448
     449        nic_frame_t *frame = nic_alloc_frame(nic_data, length);
    454450        if (frame == NULL)
    455451                return NULL;
    456        
    457         link_initialize(&frame->link);
    458        
    459         frame->packet = netif_packet_get_1(length);
    460         if (frame->packet == NULL) {
    461                 free(frame);
    462                 return NULL;
    463         }
    464452       
    465453        void *buf = packet_suffix(frame->packet, length);
     
    470458                size_t left = (ne2k->stop_page - page) * DP_PAGE
    471459                    - sizeof(recv_header_t);
    472                
    473460                ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
    474461                    left);
    475462                ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE,
    476463                    length - left);
    477         } else
     464        } else {
    478465                ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
    479466                    length);
    480        
    481         ne2k->stats.receive_packets++;
     467        }
    482468        return frame;
    483469}
    484470
    485 static list_t *ne2k_receive(ne2k_t *ne2k)
    486 {
     471static void ne2k_receive(nic_t *nic_data)
     472{
     473        ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
    487474        /*
    488475         * Allocate memory for the list of received frames.
     
    490477         * frames from the network, but they will be lost.
    491478         */
    492         list_t *frames = (list_t *) malloc(sizeof(list_t));
    493         if (frames != NULL)
    494                 list_initialize(frames);
    495        
    496         while (true) {
     479        nic_frame_list_t *frames = nic_alloc_frame_list();
     480        size_t frames_count = 0;
     481
     482        /* We may block sending in this loop - after so many received frames there
     483         * must be some interrupt pending (for the frames not yet downloaded) and
     484         * we will continue in its handler. */
     485        while (frames_count < 16) {
     486                //TODO: isn't some locking necessary here?
    497487                uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
    498488               
     
    503493                uint8_t current = pio_read_8(ne2k->port + DP_CURR);
    504494                pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
    505                
    506495                if (current == boundary)
    507496                        /* No more frames to process */
     
    520509               
    521510                pio_read_buf_16(ne2k->data_port, (void *) &header, size);
    522                
     511
    523512                size_t length =
    524513                    (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size;
     
    527516                if ((length < ETH_MIN_PACK_SIZE)
    528517                    || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
    529                         fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length);
    530518                        next = current;
    531519                } else if ((header.next < ne2k->start_page)
    532520                    || (header.next > ne2k->stop_page)) {
    533                         fprintf(stderr, "%s: Malformed next frame %u\n", NAME,
    534                             header.next);
    535521                        next = current;
    536522                } else if (header.status & RSR_FO) {
     
    539525                         * reset the buffers.
    540526                         */
    541                         fprintf(stderr, "%s: FIFO overrun\n", NAME);
    542527                        ne2k->overruns++;
    543528                        next = current;
    544529                } else if ((header.status & RSR_PRX) && (ne2k->up)) {
    545530                        if (frames != NULL) {
    546                                 frame_t *frame = ne2k_receive_frame(ne2k, boundary, length);
    547                                 if (frame != NULL)
    548                                         list_append(&frame->link, frames);
    549                         }
     531                                nic_frame_t *frame =
     532                                        ne2k_receive_frame(nic_data, boundary, length);
     533                                if (frame != NULL) {
     534                                        nic_frame_list_append(frames, frame);
     535                                        frames_count++;
     536                                } else {
     537                                        break;
     538                                }
     539                        } else
     540                                break;
    550541                }
    551542               
     
    560551                else
    561552                        next--;
    562                
    563553                pio_write_8(ne2k->port + DP_BNRY, next);
    564554        }
    565        
    566         return frames;
    567 }
    568 
    569 list_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
    570 {
    571         /* List of received frames */
    572         list_t *frames = NULL;
    573        
     555        nic_received_frame_list(nic_data, frames);
     556}
     557
     558void ne2k_interrupt(nic_t *nic_data, uint8_t isr, uint8_t tsr)
     559{
     560        ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
     561
    574562        if (isr & (ISR_PTX | ISR_TXE)) {
    575                 if (isr & ISR_TXE)
    576                         ne2k->stats.send_errors++;
    577                 else {
    578                         if (tsr & TSR_PTX)
    579                                 ne2k->stats.send_packets++;
    580                        
    581                         if (tsr & TSR_COL)
    582                                 ne2k->stats.collisions++;
    583                        
    584                         if (tsr & TSR_ABT)
    585                                 ne2k->stats.send_aborted_errors++;
    586                        
    587                         if (tsr & TSR_CRS)
    588                                 ne2k->stats.send_carrier_errors++;
    589                        
    590                         if (tsr & TSR_FU) {
    591                                 ne2k->underruns++;
    592                                 if (ne2k->underruns < NE2K_ERL)
    593                                         fprintf(stderr, "%s: FIFO underrun\n", NAME);
    594                         }
    595                        
    596                         if (tsr & TSR_CDH) {
    597                                 ne2k->stats.send_heartbeat_errors++;
    598                                 if (ne2k->stats.send_heartbeat_errors < NE2K_ERL)
    599                                         fprintf(stderr, "%s: CD heartbeat failure\n", NAME);
    600                         }
    601                        
    602                         if (tsr & TSR_OWC)
    603                                 ne2k->stats.send_window_errors++;
     563                if (tsr & TSR_COL) {
     564                        nic_report_collisions(nic_data,
     565                                pio_read_8(ne2k->port + DP_NCR) & 15);
    604566                }
    605                
     567
     568                if (tsr & TSR_PTX) {
     569                        // TODO: fix number of sent bytes (but how?)
     570                        nic_report_send_ok(nic_data, 1, 0);
     571                } else if (tsr & TSR_ABT) {
     572                        nic_report_send_error(nic_data, NIC_SEC_ABORTED, 1);
     573                } else if (tsr & TSR_CRS) {
     574                        nic_report_send_error(nic_data, NIC_SEC_CARRIER_LOST, 1);
     575                } else if (tsr & TSR_FU) {
     576                        ne2k->underruns++;
     577                        // if (ne2k->underruns < NE2K_ERL) {
     578                        // }
     579                } else if (tsr & TSR_CDH) {
     580                        nic_report_send_error(nic_data, NIC_SEC_HEARTBEAT, 1);
     581                        // if (nic_data->stats.send_heartbeat_errors < NE2K_ERL) {
     582                        // }
     583                } else if (tsr & TSR_OWC) {
     584                        nic_report_send_error(nic_data, NIC_SEC_WINDOW_ERROR, 1);
     585                }
     586
    606587                fibril_mutex_lock(&ne2k->sq_mutex);
    607                
    608588                if (ne2k->sq.dirty) {
    609589                        /* Prepare the buffer for next packet */
     
    615595                } else {
    616596                        ne2k->misses++;
    617                         if (ne2k->misses < NE2K_ERL)
    618                                 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
     597                        // if (ne2k->misses < NE2K_ERL) {
     598                        // }
    619599                }
    620                
    621600                fibril_mutex_unlock(&ne2k->sq_mutex);
    622601        }
    623        
    624         if (isr & ISR_RXE)
    625                 ne2k->stats.receive_errors++;
    626        
     602
    627603        if (isr & ISR_CNT) {
    628                 ne2k->stats.receive_crc_errors +=
    629                     pio_read_8(ne2k->port + DP_CNTR0);
    630                 ne2k->stats.receive_frame_errors +=
    631                     pio_read_8(ne2k->port + DP_CNTR1);
    632                 ne2k->stats.receive_missed_errors +=
    633                     pio_read_8(ne2k->port + DP_CNTR2);
    634         }
    635        
    636         if (isr & ISR_PRX)
    637                 frames = ne2k_receive(ne2k);
    638        
     604                unsigned int errors;
     605                for (errors = pio_read_8(ne2k->port + DP_CNTR0); errors > 0; --errors)
     606                        nic_report_receive_error(nic_data, NIC_REC_CRC, 1);
     607                for (errors = pio_read_8(ne2k->port + DP_CNTR1); errors > 0; --errors)
     608                        nic_report_receive_error(nic_data, NIC_REC_FRAME_ALIGNMENT, 1);
     609                for (errors = pio_read_8(ne2k->port + DP_CNTR2); errors > 0; --errors)
     610                        nic_report_receive_error(nic_data, NIC_REC_MISSED, 1);
     611        }
     612        if (isr & ISR_PRX) {
     613                ne2k_receive(nic_data);
     614        }
    639615        if (isr & ISR_RST) {
    640616                /*
     
    648624        pio_write_8(ne2k->port + DP_IMR,
    649625            IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
    650        
    651         return frames;
     626}
     627
     628void ne2k_set_accept_bcast(ne2k_t *ne2k, int accept)
     629{
     630        if (accept)
     631                ne2k->receive_configuration |= RCR_AB;
     632        else
     633                ne2k->receive_configuration &= ~RCR_AB;
     634       
     635        pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration);
     636}
     637
     638void ne2k_set_accept_mcast(ne2k_t *ne2k, int accept)
     639{
     640        if (accept)
     641                ne2k->receive_configuration |= RCR_AM;
     642        else
     643                ne2k->receive_configuration &= ~RCR_AM;
     644       
     645        pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration);
     646}
     647
     648void ne2k_set_promisc_phys(ne2k_t *ne2k, int promisc)
     649{
     650        if (promisc)
     651                ne2k->receive_configuration |= RCR_PRO;
     652        else
     653                ne2k->receive_configuration &= ~RCR_PRO;
     654       
     655        pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration);
     656}
     657
     658void ne2k_set_mcast_hash(ne2k_t *ne2k, uint64_t hash)
     659{
     660        /* Select Page 1 and stop all transfers */
     661        pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
     662       
     663        pio_write_8(ne2k->port + DP_MAR0, (uint8_t) hash);
     664        pio_write_8(ne2k->port + DP_MAR1, (uint8_t) (hash >> 8));
     665        pio_write_8(ne2k->port + DP_MAR2, (uint8_t) (hash >> 16));
     666        pio_write_8(ne2k->port + DP_MAR3, (uint8_t) (hash >> 24));
     667        pio_write_8(ne2k->port + DP_MAR4, (uint8_t) (hash >> 32));
     668        pio_write_8(ne2k->port + DP_MAR5, (uint8_t) (hash >> 40));
     669        pio_write_8(ne2k->port + DP_MAR6, (uint8_t) (hash >> 48));
     670        pio_write_8(ne2k->port + DP_MAR7, (uint8_t) (hash >> 56));
     671       
     672        /* Select Page 0 and resume transfers */
     673        pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA);
    652674}
    653675
  • uspace/drv/nic/ne2k/dp8390.h

    r8367d1d rd7ff048  
    22 * Copyright (c) 2009 Lukas Mejdrech
    33 * Copyright (c) 2011 Martin Decky
     4 * Copyright (c) 2011 Radim Vansa
    45 * All rights reserved.
    56 *
     
    3839 */
    3940
    40 /** @addtogroup ne2000
     41/** @addtogroup drv_ne2k
    4142 *  @{
    4243 */
     
    5051
    5152#include <fibril_synch.h>
    52 #include <adt/list.h>
    53 #include <net/packet.h>
    54 #include <netif_skel.h>
    55 
    56 /** Module name */
    57 #define NAME  "ne2000"
     53#include <nic.h>
     54#include <ddf/interrupt.h>
    5855
    5956/** Input/output size */
    6057#define NE2K_IO_SIZE  0x0020
    6158
    62 /** Ethernet address length */
    63 #define ETH_ADDR  6
     59/* NE2000 implementation. */
     60
     61/** NE2000 Data Register */
     62#define NE2K_DATA  0x0010
     63
     64/** NE2000 Reset register */
     65#define NE2K_RESET  0x001f
     66
     67/** NE2000 data start */
     68#define NE2K_START  0x4000
     69
     70/** NE2000 data size */
     71#define NE2K_SIZE  0x4000
     72
     73/** NE2000 retry count */
     74#define NE2K_RETRY  0x1000
     75
     76/** NE2000 error messages rate limiting */
     77#define NE2K_ERL  10
     78
     79/** Minimum Ethernet packet size in bytes */
     80#define ETH_MIN_PACK_SIZE  60
     81
     82/** Maximum Ethernet packet size in bytes */
     83#define ETH_MAX_PACK_SIZE_TAGGED  1518
    6484
    6585/* National Semiconductor DP8390 Network Interface Controller. */
     
    204224typedef struct {
    205225        /* Device configuration */
     226        void *base_port; /**< Port assigned from ISA configuration **/
    206227        void *port;
    207228        void *data_port;
    208229        int irq;
    209         uint8_t mac[ETH_ADDR];
     230        nic_address_t mac;
    210231       
    211232        uint8_t start_page;  /**< Ring buffer start page */
     
    224245        bool probed;
    225246        bool up;
    226        
     247
     248        /* Irq code with assigned addresses for this device */
     249        irq_code_t code;
     250
     251        /* Copy of the receive configuration register */
     252        uint8_t receive_configuration;
     253
    227254        /* Device statistics */
    228         device_stats_t stats;
     255        // TODO: shouldn't be these directly in device.h - nic_device_stats?
    229256        uint64_t misses;     /**< Receive frame misses */
    230257        uint64_t underruns;  /**< FIFO underruns */
     
    232259} ne2k_t;
    233260
    234 typedef struct {
    235         link_t link;
    236         packet_t *packet;
    237 } frame_t;
    238 
    239 extern int ne2k_probe(ne2k_t *, void *, int);
     261extern int ne2k_probe(ne2k_t *);
    240262extern int ne2k_up(ne2k_t *);
    241263extern void ne2k_down(ne2k_t *);
    242 extern void ne2k_send(ne2k_t *, packet_t *);
    243 extern list_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
     264extern void ne2k_send(nic_t *, packet_t *);
     265extern void ne2k_interrupt(nic_t *, uint8_t, uint8_t);
     266extern packet_t *ne2k_alloc_packet(nic_t *, size_t);
     267
     268extern void ne2k_set_accept_mcast(ne2k_t *, int);
     269extern void ne2k_set_accept_bcast(ne2k_t *, int);
     270extern void ne2k_set_promisc_phys(ne2k_t *, int);
     271extern void ne2k_set_mcast_hash(ne2k_t *, uint64_t);
     272extern void ne2k_set_physical_address(ne2k_t *, const nic_address_t *address);
    244273
    245274#endif
Note: See TracChangeset for help on using the changeset viewer.