Changeset d7ff048 in mainline for uspace/drv
- Timestamp:
- 2011-10-08T13:08:53Z (14 years ago)
- 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. - Location:
- uspace/drv
- Files:
-
- 6 added
- 4 deleted
- 6 edited
- 5 moved
-
bus/usb/usbhub/Makefile (modified) (2 diffs)
-
bus/usb/usbhub/main.c (modified) (6 diffs)
-
bus/usb/usbhub/port.c (added)
-
bus/usb/usbhub/port.h (moved) (moved from uspace/drv/bus/usb/usbhub/ports.h ) (5 diffs)
-
bus/usb/usbhub/port_status.h (deleted)
-
bus/usb/usbhub/ports.c (deleted)
-
bus/usb/usbhub/status.h (added)
-
bus/usb/usbhub/usbhub.c (modified) (14 diffs)
-
bus/usb/usbhub/usbhub.h (modified) (5 diffs)
-
bus/usb/usbhub/usbhub_private.h (deleted)
-
bus/usb/usbhub/utils.c (deleted)
-
bus/usb/usbmast/main.c (modified) (5 diffs)
-
infrastructure/rootvirt/devices.def (modified) (3 diffs)
-
nic/lo/Makefile (moved) (moved from uspace/lib/packet/Makefile ) (2 diffs)
-
nic/lo/lo.c (added)
-
nic/lo/lo.ma (added)
-
nic/ne2k/Makefile (moved) (moved from uspace/srv/net/netif/lo/Makefile ) (2 diffs)
-
nic/ne2k/dp8390.c (moved) (moved from uspace/srv/hw/netif/ne2000/dp8390.c ) (20 diffs)
-
nic/ne2k/dp8390.h (moved) (moved from uspace/srv/hw/netif/ne2000/dp8390.h ) (6 diffs)
-
nic/ne2k/ne2k.c (added)
-
nic/ne2k/ne2k.ma (added)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/Makefile
r8367d1d rd7ff048 1 1 # 2 2 # Copyright (c) 2010 Vojtech Horky 3 # Copyright (c) 2011 Jan Vesely 3 4 # All rights reserved. 4 5 # … … 43 44 SOURCES = \ 44 45 main.c \ 45 utils.c \46 46 usbhub.c \ 47 port s.c47 port.c 48 48 49 49 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/bus/usb/usbhub/main.c
r8367d1d rd7ff048 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 38 39 #include <usb/dev/driver.h> 39 40 #include <usb/classes/classes.h> 41 #include <usb/debug.h> 40 42 41 43 #include "usbhub.h" 42 #include "usbhub_private.h"43 44 44 45 /** Hub status-change endpoint description. … … 56 57 57 58 /** 58 * usbhub driver operations59 * USB hub driver operations 59 60 * 60 61 * The most important one is add_device, which is set to usb_hub_add_device. … … 64 65 }; 65 66 66 /** 67 * hub endpoints, excluding control endpoint 68 */ 67 /** Hub endpoints, excluding control endpoint. */ 69 68 static usb_endpoint_description_t *usb_hub_endpoints[] = { 70 69 &hub_status_change_endpoint_description, 71 NULL 70 NULL, 72 71 }; 73 74 /** 75 * static usb hub driver information 76 */ 72 /** Static usb hub driver information. */ 77 73 static usb_driver_t usb_hub_driver = { 78 74 .name = NAME, … … 85 81 { 86 82 printf(NAME ": HelenOS USB hub driver.\n"); 87 88 83 usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME); 89 84 … … 94 89 * @} 95 90 */ 96 -
uspace/drv/bus/usb/usbhub/port.h
r8367d1d rd7ff048 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup drvusbhub 30 30 * @{ … … 33 33 * Hub ports related functions. 34 34 */ 35 #ifndef DRV_USBHUB_PORT S_H36 #define DRV_USBHUB_PORT S_H35 #ifndef DRV_USBHUB_PORT_H 36 #define DRV_USBHUB_PORT_H 37 37 38 38 #include <usb/dev/driver.h> 39 39 #include <usb/dev/hub.h> 40 #include <usb/classes/hub.h> 40 41 41 42 typedef struct usb_hub_info_t usb_hub_info_t; … … 43 44 /** Information about single port on a hub. */ 44 45 typedef 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; 47 50 /** CV for waiting to port reset completion. */ 48 51 fibril_condvar_t reset_cv; … … 62 65 * @param port Port to be initialized. 63 66 */ 64 static inline void usb_hub_port_init(usb_hub_port_t *port) { 67 static 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); 65 71 port->attached_device.address = -1; 66 72 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); 68 76 fibril_condvar_initialize(&port->reset_cv); 69 77 } 70 78 71 72 void usb_hub_process_port_interrupt(usb_hub_info_t *hub, 73 uint16_t port); 74 75 79 void usb_hub_port_reset_fail(usb_hub_port_t *port); 80 void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_info_t *hub); 81 int usb_hub_port_clear_feature( 82 usb_hub_port_t *port, usb_hub_class_feature_t feature); 83 int usb_hub_port_set_feature( 84 usb_hub_port_t *port, usb_hub_class_feature_t feature); 76 85 77 86 #endif -
uspace/drv/bus/usb/usbhub/usbhub.c
r8367d1d rd7ff048 1 1 /* 2 2 * Copyright (c) 2010 Matus Dekanek 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 38 39 #include <str_error.h> 39 40 #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> 42 47 #include <usb/ddfiface.h> 43 48 #include <usb/descriptor.h> … … 46 51 #include <usb/classes/hub.h> 47 52 #include <usb/dev/poll.h> 48 #include < stdio.h>53 #include <usb_iface.h> 49 54 50 55 #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 */ 61 static 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 69 static int usb_set_first_configuration(usb_device_t *usb_device); 58 70 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev); 59 60 71 static 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, 72 static void usb_hub_over_current(const usb_hub_info_t *hub_info, 67 73 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 74 static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info); 74 75 static void usb_hub_polling_terminated_callback(usb_device_t *device, 75 76 bool was_error, void *data); 76 77 77 78 //*********************************************79 //80 // hub driver code, initialization81 //82 //*********************************************83 84 78 /** 85 79 * Initialize hub device driver fibril 86 80 * 87 * Creates hub representation and fibril that periodically checks hub `s status.81 * Creates hub representation and fibril that periodically checks hub's status. 88 82 * Hub representation is passed to the fibril. 89 83 * @param usb_dev generic usb device information 90 84 * @return error code 91 85 */ 92 int usb_hub_add_device(usb_device_t *usb_dev) { 93 if (!usb_dev) return EINVAL; 86 int usb_hub_add_device(usb_device_t *usb_dev) 87 { 88 assert(usb_dev); 89 /* Create driver soft-state structure */ 94 90 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 */ 96 97 usb_log_debug("Initializing USB wire abstraction.\n"); 97 98 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 116 116 //get port count and create attached_devs 117 117 opResult = usb_hub_process_hub_specific_info(hub_info); … … 123 123 } 124 124 125 usb_log_debug("Creating 'hub' function in DDF.\n");125 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n"); 126 126 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 } 130 133 131 134 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 /*----------------------------------------------------------------------------*/ 140 159 /** Callback for polling hub for changes. 141 160 * … … 147 166 */ 148 167 bool 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 { 150 170 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 */ 154 175 if (change_bitmap_size == 0) { 155 goto leave;156 } 157 158 bool change;159 c hange = ((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; 160 181 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; 167 189 if (change) { 168 usb_hub_p rocess_port_interrupt(hub, port);190 usb_hub_port_process_interrupt(&hub->ports[port], hub); 169 191 } 170 192 } 171 leave:172 /* FIXME: proper interval. */173 async_usleep(1000 * 250);174 175 193 return true; 176 194 } 177 178 179 //********************************************* 180 // 181 // support functions 182 // 183 //********************************************* 184 195 /*----------------------------------------------------------------------------*/ 185 196 /** 186 197 * create usb_hub_info_t structure … … 190 201 * @return basic usb_hub_info_t structure 191 202 */ 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 203 static 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 /*----------------------------------------------------------------------------*/ 210 221 /** 211 222 * Load hub-specific information into hub_info structure and process if needed 212 223 * 213 * Particularly read port count and initialize structure holding port214 * information. If there arenon-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. 215 226 * 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. 217 228 * @param hub_info hub representation 218 229 * @return error code 219 230 */ 220 int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) 221 { 222 // get hub descriptor 231 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) 232 { 233 assert(hub_info); 234 235 /* Get hub descriptor. */ 223 236 usb_log_debug("Retrieving descriptor\n"); 224 u int8_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; 227 240 size_t received_size; 228 opResult = usb_request_get_descriptor(hub_info->control_pipe,241 int opResult = usb_request_get_descriptor(control_pipe, 229 242 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); 233 245 if (opResult != EOK) { 234 246 usb_log_error("Failed to receive hub descriptor: %s.\n", … … 236 248 return opResult; 237 249 } 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 250 255 hub_info->ports = 251 256 malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1)); … … 256 261 size_t port; 257 262 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); 259 264 } 260 265 261 266 const bool is_power_switched = 262 !(descriptor. hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);267 !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG); 263 268 if (is_power_switched) { 264 269 usb_log_debug("Hub power switched\n"); 265 const bool per_port_power = descriptor. hub_characteristics270 const bool per_port_power = descriptor.characteristics 266 271 & HUB_CHAR_POWER_PER_PORT_FLAG; 267 272 268 273 for (port = 1; port <= hub_info->port_count; ++port) { 269 274 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); 273 277 if (opResult != EOK) { 274 278 usb_log_error("Cannot power on port %zu: %s.\n", … … 283 287 } 284 288 } 285 286 289 } else { 287 usb_log_debug("Power not switched, not going to bepowered\n");290 usb_log_debug("Power not switched, ports always powered\n"); 288 291 } 289 292 return EOK; 290 293 } 291 292 /** 293 * Set configuration of hub294 /*----------------------------------------------------------------------------*/ 295 /** 296 * Set configuration of and USB device 294 297 * 295 298 * Check whether there is at least one configuration and sets the first one. 296 299 * This function should be run prior to running any hub-specific action. 297 * @param hub_info hubrepresentation300 * @param usb_device usb device representation 298 301 * @return error code 299 302 */ 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) { 303 static 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) { 307 312 usb_log_error("There are no configurations available\n"); 308 313 return EINVAL; 309 314 } 310 315 316 // TODO: Make sure that there is enough data and the cast is correct 311 317 usb_standard_configuration_descriptor_t *config_descriptor 312 318 = (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); 320 325 if (opResult != EOK) { 321 326 usb_log_error("Failed to set hub configuration: %s.\n", 322 327 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 366 337 * 367 338 * This means either to power off the hub or power it on. … … 370 341 * @return error code 371 342 */ 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; 343 static 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; 378 354 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); 382 357 if (opResult != EOK) { 383 358 usb_log_warning( 384 "Cannot power off port %d; %s\n", 359 "HUB OVER-CURRENT GONE: Cannot power on " 360 "port %zu; %s\n", 385 361 port, str_error(opResult)); 386 362 } 387 363 } 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. 409 380 * @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 */ 382 static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info) 383 { 384 assert(hub_info); 385 assert(hub_info->usb_device); 434 386 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; 439 390 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); 450 396 if (opResult != EOK) { 451 397 usb_log_error("Could not get hub status: %s\n", … … 453 399 return; 454 400 } 455 if (rcvd_size != sizeof (usb_port_status_t)) {401 if (rcvd_size != sizeof(usb_hub_status_t)) { 456 402 usb_log_error("Received status has incorrect size\n"); 457 403 return; 458 404 } 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 /*----------------------------------------------------------------------------*/ 470 437 /** 471 438 * callback called from hub polling fibril when the fibril terminates … … 477 444 */ 478 445 static 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; 481 449 assert(hub); 482 450 … … 492 460 */ 493 461 if (hub->pending_ops_count > 0) { 494 fibril_mutex_lock(&hub->port_mutex);495 462 size_t port; 496 463 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]); 503 465 } 504 fibril_mutex_unlock(&hub->port_mutex);505 466 } 506 467 /* And now wait for them. */ … … 516 477 free(hub); 517 478 } 518 519 520 521 522 479 /** 523 480 * @} -
uspace/drv/bus/usb/usbhub/usbhub.h
r8367d1d rd7ff048 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Vojtech Horky 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup drvusbhub 30 30 * @{ … … 49 49 #define NAME "usbhub" 50 50 51 #include "port s.h"51 #include "port.h" 52 52 53 53 /** Information about attached hub. */ … … 56 56 size_t port_count; 57 57 58 /** attached device handles, for each port one */58 /** Attached device handles, for each port one */ 59 59 usb_hub_port_t *ports; 60 60 61 fibril_mutex_t port_mutex; 62 63 /** connection to hcd */ 61 /** Connection to hcd */ 64 62 usb_hc_connection_t connection; 65 63 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; 91 66 92 67 /** Number of pending operations on the mutex to prevent shooting … … 101 76 /** Condition variable for pending_ops_count. */ 102 77 fibril_condvar_t pending_ops_cv; 103 104 78 }; 105 79 -
uspace/drv/bus/usb/usbmast/main.c
r8367d1d rd7ff048 94 94 95 95 /* Allocate softstate */ 96 mdev = calloc(1, sizeof(usbmast_dev_t));96 mdev = ddf_dev_data_alloc(dev->ddf_dev, sizeof(usbmast_dev_t)); 97 97 if (mdev == NULL) { 98 98 usb_log_error("Failed allocating softstate.\n"); 99 rc = ENOMEM; 100 goto error; 99 return ENOMEM; 101 100 } 102 101 … … 125 124 error: 126 125 /* XXX Destroy functions */ 127 if (mdev != NULL)128 free(mdev);129 126 return rc; 130 127 } … … 158 155 } 159 156 160 free(fun_name);161 162 157 /* 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)); 164 159 if (mfun == NULL) { 165 160 usb_log_error("Failed allocating softstate.\n"); … … 171 166 mfun->lun = lun; 172 167 173 fun_name = NULL;174 175 168 /* Set up a connection handler. */ 176 169 fun->conn_handler = usbmast_bd_connection; 177 fun->driver_data = mfun;178 170 179 171 usb_log_debug("Inquire...\n"); … … 219 211 goto error; 220 212 } 213 214 free(fun_name); 221 215 222 216 return EOK; -
uspace/drv/infrastructure/rootvirt/devices.def
r8367d1d rd7ff048 4 4 * Unless the list is empty, the last item shall be followed by a comma. 5 5 */ 6 7 /* Loopback network interface */ 8 { 9 .name = "lo", 10 .match_id = "virtual&loopback" 11 }, 12 6 13 #ifdef CONFIG_TEST_DRIVERS 14 7 15 { 8 16 .name = "test1", … … 25 33 .match_id = "virtual&test3" 26 34 }, 35 27 36 #endif 37 28 38 #ifdef CONFIG_RUN_VIRTUAL_USB_HC 39 29 40 /* Virtual USB host controller. */ 30 41 { … … 32 43 .match_id = "usb&hc=vhc" 33 44 }, 45 34 46 #endif -
uspace/drv/nic/lo/Makefile
r8367d1d rd7ff048 1 1 # 2 # Copyright (c) 2005 Martin Decky 3 # Copyright (c) 2007 Jakub Jermar 2 # Copyright (c) 2011 Radim Vansa 4 3 # All rights reserved. 5 4 # … … 28 27 # 29 28 30 USPACE_PREFIX = ../.. 31 EXTRA_CFLAGS = -Iinclude 32 LIBRARY = libpacket 29 USPACE_PREFIX = ../../.. 30 LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a 31 EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include 32 BINARY = lo 33 33 34 34 SOURCES = \ 35 generic/packet_server.c35 lo.c 36 36 37 37 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/nic/ne2k/Makefile
r8367d1d rd7ff048 1 1 # 2 # Copyright (c) 2005 Martin Decky 3 # Copyright (c) 2007 Jakub Jermar 2 # Copyright (c) 2011 Radim Vansa 4 3 # All rights reserved. 5 4 # … … 28 27 # 29 28 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 29 USPACE_PREFIX = ../../.. 30 LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a 31 EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include 32 BINARY = ne2k 42 33 43 34 SOURCES = \ 44 lo.c 35 dp8390.c \ 36 ne2k.c 45 37 46 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/nic/ne2k/dp8390.c
r8367d1d rd7ff048 2 2 * Copyright (c) 2009 Lukas Mejdrech 3 3 * Copyright (c) 2011 Martin Decky 4 * Copyright (c) 2011 Radim Vansa 4 5 * All rights reserved. 5 6 * … … 38 39 */ 39 40 40 /** @addtogroup ne2000 41 * @{ 42 */ 43 44 /** @file 41 /** 42 * @addtogroup drv_ne2k 43 * @{ 44 */ 45 46 /** 47 * @file 48 * @brief NE2000 driver core 45 49 * 46 50 * NE2000 (based on DP8390) network interface core implementation. … … 65 69 #define SQ_PAGES 6 66 70 67 /* NE2000 implementation. */68 69 /** NE2000 Data Register */70 #define NE2K_DATA 0x001071 72 /** NE2000 Reset register */73 #define NE2K_RESET 0x001f74 75 /** NE2000 data start */76 #define NE2K_START 0x400077 78 /** NE2000 data size */79 #define NE2K_SIZE 0x400080 81 /** NE2000 retry count */82 #define NE2K_RETRY 0x100083 84 /** NE2000 error messages rate limiting */85 #define NE2K_ERL 1086 87 /** Minimum Ethernet packet size in bytes */88 #define ETH_MIN_PACK_SIZE 6089 90 /** Maximum Ethernet packet size in bytes */91 #define ETH_MAX_PACK_SIZE_TAGGED 151892 93 71 /** Type definition of the receive header 94 72 * … … 216 194 * 217 195 */ 218 int ne2k_probe(ne2k_t *ne2k , void *port, int irq)196 int ne2k_probe(ne2k_t *ne2k) 219 197 { 220 198 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;228 199 229 200 ne2k_init(ne2k); … … 247 218 248 219 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 252 222 return EOK; 223 } 224 225 void 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); 253 242 } 254 243 … … 304 293 305 294 /* Step 4: */ 306 pio_write_8(ne2k->port + DP_RCR, RCR_AB);295 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 307 296 308 297 /* Step 5: */ … … 324 313 pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP); 325 314 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, 0 xff);334 pio_write_8(ne2k->port + DP_MAR1, 0 xff);335 pio_write_8(ne2k->port + DP_MAR2, 0 xff);336 pio_write_8(ne2k->port + DP_MAR3, 0 xff);337 pio_write_8(ne2k->port + DP_MAR4, 0 xff);338 pio_write_8(ne2k->port + DP_MAR5, 0 xff);339 pio_write_8(ne2k->port + DP_MAR6, 0 xff);340 pio_write_8(ne2k->port + DP_MAR7, 0 xff);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); 341 330 342 331 pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1); … … 372 361 } 373 362 363 static 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 374 402 /** Send a frame. 375 403 * … … 378 406 * 379 407 */ 380 void ne2k_send(ne2k_t *ne2k, packet_t *packet) 381 { 408 void ne2k_send(nic_t *nic_data, packet_t *packet) 409 { 410 ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data); 411 382 412 assert(ne2k->probed); 383 413 assert(ne2k->up); 384 414 385 415 fibril_mutex_lock(&ne2k->sq_mutex); 386 416 387 while (ne2k->sq.dirty) 417 while (ne2k->sq.dirty) { 388 418 fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex); 389 419 } 390 420 void *buf = packet_get_data(packet); 391 421 size_t size = packet_get_data_length(packet); … … 393 423 if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) { 394 424 fibril_mutex_unlock(&ne2k->sq_mutex); 395 fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",396 NAME, size);397 425 return; 398 426 } 399 427 400 428 /* Upload the frame to the ethernet card */ 401 429 ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size); 402 430 ne2k->sq.dirty = true; 403 431 ne2k->sq.size = size; 404 432 405 433 /* Initialize the transfer */ 406 434 pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page); … … 408 436 pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff); 409 437 pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA); 410 411 438 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 444 static 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); 454 450 if (frame == NULL) 455 451 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 }464 452 465 453 void *buf = packet_suffix(frame->packet, length); … … 470 458 size_t left = (ne2k->stop_page - page) * DP_PAGE 471 459 - sizeof(recv_header_t); 472 473 460 ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t), 474 461 left); 475 462 ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE, 476 463 length - left); 477 } else 464 } else { 478 465 ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t), 479 466 length); 480 481 ne2k->stats.receive_packets++; 467 } 482 468 return frame; 483 469 } 484 470 485 static list_t *ne2k_receive(ne2k_t *ne2k) 486 { 471 static void ne2k_receive(nic_t *nic_data) 472 { 473 ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data); 487 474 /* 488 475 * Allocate memory for the list of received frames. … … 490 477 * frames from the network, but they will be lost. 491 478 */ 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? 497 487 uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1; 498 488 … … 503 493 uint8_t current = pio_read_8(ne2k->port + DP_CURR); 504 494 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA); 505 506 495 if (current == boundary) 507 496 /* No more frames to process */ … … 520 509 521 510 pio_read_buf_16(ne2k->data_port, (void *) &header, size); 522 511 523 512 size_t length = 524 513 (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size; … … 527 516 if ((length < ETH_MIN_PACK_SIZE) 528 517 || (length > ETH_MAX_PACK_SIZE_TAGGED)) { 529 fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length);530 518 next = current; 531 519 } else if ((header.next < ne2k->start_page) 532 520 || (header.next > ne2k->stop_page)) { 533 fprintf(stderr, "%s: Malformed next frame %u\n", NAME,534 header.next);535 521 next = current; 536 522 } else if (header.status & RSR_FO) { … … 539 525 * reset the buffers. 540 526 */ 541 fprintf(stderr, "%s: FIFO overrun\n", NAME);542 527 ne2k->overruns++; 543 528 next = current; 544 529 } else if ((header.status & RSR_PRX) && (ne2k->up)) { 545 530 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; 550 541 } 551 542 … … 560 551 else 561 552 next--; 562 563 553 pio_write_8(ne2k->port + DP_BNRY, next); 564 554 } 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 558 void 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 574 562 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); 604 566 } 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 606 587 fibril_mutex_lock(&ne2k->sq_mutex); 607 608 588 if (ne2k->sq.dirty) { 609 589 /* Prepare the buffer for next packet */ … … 615 595 } else { 616 596 ne2k->misses++; 617 if (ne2k->misses < NE2K_ERL)618 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);597 // if (ne2k->misses < NE2K_ERL) { 598 // } 619 599 } 620 621 600 fibril_mutex_unlock(&ne2k->sq_mutex); 622 601 } 623 624 if (isr & ISR_RXE) 625 ne2k->stats.receive_errors++; 626 602 627 603 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 } 639 615 if (isr & ISR_RST) { 640 616 /* … … 648 624 pio_write_8(ne2k->port + DP_IMR, 649 625 IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE); 650 651 return frames; 626 } 627 628 void 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 638 void 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 648 void 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 658 void 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); 652 674 } 653 675 -
uspace/drv/nic/ne2k/dp8390.h
r8367d1d rd7ff048 2 2 * Copyright (c) 2009 Lukas Mejdrech 3 3 * Copyright (c) 2011 Martin Decky 4 * Copyright (c) 2011 Radim Vansa 4 5 * All rights reserved. 5 6 * … … 38 39 */ 39 40 40 /** @addtogroup ne200041 /** @addtogroup drv_ne2k 41 42 * @{ 42 43 */ … … 50 51 51 52 #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> 58 55 59 56 /** Input/output size */ 60 57 #define NE2K_IO_SIZE 0x0020 61 58 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 64 84 65 85 /* National Semiconductor DP8390 Network Interface Controller. */ … … 204 224 typedef struct { 205 225 /* Device configuration */ 226 void *base_port; /**< Port assigned from ISA configuration **/ 206 227 void *port; 207 228 void *data_port; 208 229 int irq; 209 uint8_t mac[ETH_ADDR];230 nic_address_t mac; 210 231 211 232 uint8_t start_page; /**< Ring buffer start page */ … … 224 245 bool probed; 225 246 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 227 254 /* Device statistics */ 228 device_stats_t stats;255 // TODO: shouldn't be these directly in device.h - nic_device_stats? 229 256 uint64_t misses; /**< Receive frame misses */ 230 257 uint64_t underruns; /**< FIFO underruns */ … … 232 259 } ne2k_t; 233 260 234 typedef struct { 235 link_t link; 236 packet_t *packet; 237 } frame_t; 238 239 extern int ne2k_probe(ne2k_t *, void *, int); 261 extern int ne2k_probe(ne2k_t *); 240 262 extern int ne2k_up(ne2k_t *); 241 263 extern 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); 264 extern void ne2k_send(nic_t *, packet_t *); 265 extern void ne2k_interrupt(nic_t *, uint8_t, uint8_t); 266 extern packet_t *ne2k_alloc_packet(nic_t *, size_t); 267 268 extern void ne2k_set_accept_mcast(ne2k_t *, int); 269 extern void ne2k_set_accept_bcast(ne2k_t *, int); 270 extern void ne2k_set_promisc_phys(ne2k_t *, int); 271 extern void ne2k_set_mcast_hash(ne2k_t *, uint64_t); 272 extern void ne2k_set_physical_address(ne2k_t *, const nic_address_t *address); 244 273 245 274 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
