Changeset 4f66cc7b in mainline
- Timestamp:
- 2011-03-17T12:45:23Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4fec9ee, 6e3b9a58
- Parents:
- 45dd8bf (diff), 039c66c (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. - Files:
-
- 5 added
- 2 deleted
- 50 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
dist/Makefile
r45dd8bf r4f66cc7b 43 43 44 44 SUFFIX = $(suffix $(IMGFILE)) 45 DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX) 45 46 ifdef PROFILE 47 DISTFILE = Helenos-$(shell echo $(PROFILE) | tr '/' '-')$(SUFFIX) 48 else 49 DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX) 50 endif 46 51 47 52 .PHONY: all clean dist distfile … … 53 58 cp $< $@ 54 59 60 $(IMGFILE): 61 $(MAKE) -C .. 62 55 63 dist: 56 64 for profile in $(PROFILES); do \ -
uspace/app/usbinfo/info.c
r45dd8bf r4f66cc7b 65 65 goto leave; 66 66 } 67 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe); 68 if (rc != EOK) { 69 fprintf(stderr, 70 NAME ": probing default control pipe failed: %s.\n", 71 str_error(rc)); 72 goto leave; 73 } 67 74 rc = usb_endpoint_pipe_start_session(&ctrl_pipe); 68 75 if (rc != EOK) { -
uspace/app/usbinfo/main.c
r45dd8bf r4f66cc7b 82 82 83 83 if (str_cmp(path, "uhci") == 0) { 84 path = "/hw/pci0/00:01.2/uhci ";84 path = "/hw/pci0/00:01.2/uhci-hc"; 85 85 } 86 86 -
uspace/doc/doxygroups.h
r45dd8bf r4f66cc7b 253 253 * @defgroup drvusbuhci UHCI driver 254 254 * @ingroup usb 255 * @brief Driver for USB host controller UHCI. 256 */ 255 * @brief Drivers for USB UHCI host controller and root hub. 256 */ 257 258 /** 259 * @defgroup drvusbuhcirh UHCI root hub driver 260 * @ingroup drvusbuhci 261 * @brief Driver for UHCI complaint root hub. 262 */ 263 264 /** 265 * @defgroup drvusbuhcihc UHCI host controller driver 266 * @ingroup drvusbuhci 267 * @brief Driver for UHCI complaint USB host controller. 268 */ 257 269 258 270 /** -
uspace/drv/ehci-hcd/main.c
r45dd8bf r4f66cc7b 27 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 28 */ 29 /** @addtogroup usbdrvehci29 /** @addtogroup drvusbehci 30 30 * @{ 31 31 */ -
uspace/drv/ehci-hcd/pci.c
r45dd8bf r4f66cc7b 247 247 248 248 249 if ((value & USBLEGSUP_BIOS_CONTROL) != 0) {249 if ((value & USBLEGSUP_BIOS_CONTROL) == 0) { 250 250 usb_log_info("BIOS released control after %d usec.\n", wait); 251 251 } else { 252 252 /* BIOS failed to hand over control, this should not happen. */ 253 usb_log_warning( "BIOS failed to release control after "253 usb_log_warning( "BIOS failed to release control after " 254 254 "%d usecs, force it.\n", wait); 255 255 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), … … 258 258 CHECK_RET_HANGUP_RETURN(ret, 259 259 "Failed(%d) to force OS EHCI control.\n", ret); 260 /* TODO: This does not seem to work on my machine */261 260 } 262 261 … … 280 279 usb_log_debug2("USBLEGSUP: %x.\n", value); 281 280 282 /*283 * TURN OFF EHCI FOR NOW, REMOVE IF THE DRIVER IS IMPLEMENTED 284 */281 /* 282 * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT 283 */ 285 284 286 285 /* Get size of capability registers in memory space. */ -
uspace/drv/pciintel/pci.c
r45dd8bf r4f66cc7b 92 92 pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data; 93 93 94 95 94 sysarg_t apic; 95 sysarg_t i8259; 96 96 97 97 int irc_phone = -1; 98 int irc_service = 0;99 100 101 98 int irc_service = -1; 99 100 if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) { 101 irc_service = SERVICE_APIC; 102 102 } else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) { 103 104 } 105 106 if (irc_service == 0) 103 irc_service = SERVICE_I8259; 104 } 105 106 if (irc_service == -1) { 107 107 return false; 108 } 108 109 109 110 irc_phone = service_connect_blocking(irc_service, 0, 0); 110 if (irc_phone < 0) 111 if (irc_phone < 0) { 111 112 return false; 113 } 112 114 113 115 size_t i; 114 116 for (i = 0; i < dev_data->hw_resources.count; i++) { 115 117 if (dev_data->hw_resources.resources[i].type == INTERRUPT) { 116 118 int irq = dev_data->hw_resources.resources[i].res.interrupt.irq; -
uspace/drv/uhci-hcd/Makefile
r45dd8bf r4f66cc7b 35 35 iface.c \ 36 36 main.c \ 37 root_hub.c \38 37 transfer_list.c \ 39 38 uhci.c \ 39 uhci_hc.c \ 40 uhci_rh.c \ 40 41 uhci_struct/transfer_descriptor.c \ 41 42 utils/device_keeper.c \ -
uspace/drv/uhci-hcd/batch.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver USB transaction structure 33 33 */ 34 34 #include <errno.h> … … 40 40 #include "batch.h" 41 41 #include "transfer_list.h" 42 #include "uhci .h"42 #include "uhci_hc.h" 43 43 #include "utils/malloc32.h" 44 44 45 45 #define DEFAULT_ERROR_COUNT 3 46 47 static int batch_schedule(batch_t *instance);48 46 49 47 static void batch_control(batch_t *instance, … … 54 52 static void batch_call_in_and_dispose(batch_t *instance); 55 53 static void batch_call_out_and_dispose(batch_t *instance); 56 static void batch_dispose(batch_t *instance); 57 58 59 /** Allocates memory and initializes internal data structures. 54 55 56 /** Allocate memory and initialize internal data structure. 60 57 * 61 58 * @param[in] fun DDF function to pass to callback. … … 72 69 * @param[in] arg additional parameter to func_in or func_out 73 70 * @param[in] manager Pointer to toggle management structure. 74 * @return False, if there is an active TD, true otherwise. 71 * @return Valid pointer if all substructures were successfully created, 72 * NULL otherwise. 73 * 74 * Determines the number of needed packets (TDs). Prepares a transport buffer 75 * (that is accessible by the hardware). Initializes parameters needed for the 76 * transaction and callback. 75 77 */ 76 78 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, … … 100 102 bzero(instance, sizeof(batch_t)); 101 103 102 instance->qh = malloc32(sizeof(q ueue_head_t));104 instance->qh = malloc32(sizeof(qh_t)); 103 105 CHECK_NULL_DISPOSE_RETURN(instance->qh, 104 106 "Failed to allocate batch queue head.\n"); 105 q ueue_head_init(instance->qh);107 qh_init(instance->qh); 106 108 107 109 instance->packets = (size + max_packet_size - 1) / max_packet_size; … … 114 116 instance->tds, "Failed to allocate transfer descriptors.\n"); 115 117 bzero(instance->tds, sizeof(td_t) * instance->packets); 116 117 // const size_t transport_size = max_packet_size * instance->packets;118 118 119 119 if (size > 0) { … … 143 143 instance->speed = speed; 144 144 instance->manager = manager; 145 146 if (func_out) 147 instance->callback_out = func_out; 148 if (func_in) 149 instance->callback_in = func_in; 150 151 queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds)); 145 instance->callback_out = func_out; 146 instance->callback_in = func_in; 147 148 qh_set_element_td(instance->qh, addr_to_phys(instance->tds)); 152 149 153 150 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", … … 156 153 } 157 154 /*----------------------------------------------------------------------------*/ 158 /** Check sbatch TDs for activity.155 /** Check batch TDs for activity. 159 156 * 160 157 * @param[in] instance Batch structure to use. 161 158 * @return False, if there is an active TD, true otherwise. 159 * 160 * Walk all TDs. Stop with false if there is an active one (it is to be 161 * processed). Stop with true if an error is found. Return true if the last TS 162 * is reached. 162 163 */ 163 164 bool batch_is_complete(batch_t *instance) … … 177 178 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 178 179 instance, i, instance->tds[i].status); 180 td_print_status(&instance->tds[i]); 179 181 180 182 device_keeper_set_toggle(instance->manager, … … 197 199 * 198 200 * @param[in] instance Batch structure to use. 201 * 202 * Uses genercir control function with pids OUT and IN. 199 203 */ 200 204 void batch_control_write(batch_t *instance) 201 205 { 202 206 assert(instance); 203 /* we are data out, we are supposed to provide data */207 /* We are data out, we are supposed to provide data */ 204 208 memcpy(instance->transport_buffer, instance->buffer, 205 209 instance->buffer_size); … … 207 211 instance->next_step = batch_call_out_and_dispose; 208 212 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 209 batch_schedule(instance);210 213 } 211 214 /*----------------------------------------------------------------------------*/ … … 213 216 * 214 217 * @param[in] instance Batch structure to use. 218 * 219 * Uses generic control with pids IN and OUT. 215 220 */ 216 221 void batch_control_read(batch_t *instance) … … 220 225 instance->next_step = batch_call_in_and_dispose; 221 226 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 222 batch_schedule(instance); 223 } 224 /*----------------------------------------------------------------------------*/ 225 /** Prepares interrupt in transaction. 226 * 227 * @param[in] instance Batch structure to use. 227 } 228 /*----------------------------------------------------------------------------*/ 229 /** Prepare interrupt in transaction. 230 * 231 * @param[in] instance Batch structure to use. 232 * 233 * Data transaction with PID_IN. 228 234 */ 229 235 void batch_interrupt_in(batch_t *instance) … … 233 239 instance->next_step = batch_call_in_and_dispose; 234 240 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 235 batch_schedule(instance); 236 } 237 /*----------------------------------------------------------------------------*/ 238 /** Prepares interrupt out transaction. 239 * 240 * @param[in] instance Batch structure to use. 241 } 242 /*----------------------------------------------------------------------------*/ 243 /** Prepare interrupt out transaction. 244 * 245 * @param[in] instance Batch structure to use. 246 * 247 * Data transaction with PID_OUT. 241 248 */ 242 249 void batch_interrupt_out(batch_t *instance) 243 250 { 244 251 assert(instance); 245 /* we are data out, we are supposed to provide data */252 /* We are data out, we are supposed to provide data */ 246 253 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 247 254 batch_data(instance, USB_PID_OUT); 248 255 instance->next_step = batch_call_out_and_dispose; 249 256 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 250 batch_schedule(instance); 251 } 252 /*----------------------------------------------------------------------------*/ 253 /** Prepares bulk in transaction. 254 * 255 * @param[in] instance Batch structure to use. 257 } 258 /*----------------------------------------------------------------------------*/ 259 /** Prepare bulk in transaction. 260 * 261 * @param[in] instance Batch structure to use. 262 * 263 * Data transaction with PID_IN. 256 264 */ 257 265 void batch_bulk_in(batch_t *instance) … … 261 269 instance->next_step = batch_call_in_and_dispose; 262 270 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 263 batch_schedule(instance); 264 } 265 /*----------------------------------------------------------------------------*/ 266 /** Prepares bulk out transaction. 267 * 268 * @param[in] instance Batch structure to use. 271 } 272 /*----------------------------------------------------------------------------*/ 273 /** Prepare bulk out transaction. 274 * 275 * @param[in] instance Batch structure to use. 276 * 277 * Data transaction with PID_OUT. 269 278 */ 270 279 void batch_bulk_out(batch_t *instance) 271 280 { 272 281 assert(instance); 282 /* We are data out, we are supposed to provide data */ 273 283 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 274 284 batch_data(instance, USB_PID_OUT); 275 285 instance->next_step = batch_call_out_and_dispose; 276 286 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 277 batch_schedule(instance); 278 } 279 /*----------------------------------------------------------------------------*/ 280 /** Prepares generic data transaction 287 } 288 /*----------------------------------------------------------------------------*/ 289 /** Prepare generic data transaction 281 290 * 282 291 * @param[in] instance Batch structure to use. 283 292 * @param[in] pid to use for data packets. 293 * 294 * Packets with alternating toggle bit and supplied pid value. 295 * The last packet is marked with IOC flag. 284 296 */ 285 297 void batch_data(batch_t *instance, usb_packet_id pid) … … 318 330 ++packet; 319 331 } 332 td_set_ioc(&instance->tds[packet - 1]); 320 333 device_keeper_set_toggle(instance->manager, instance->target, toggle); 321 334 } 322 335 /*----------------------------------------------------------------------------*/ 323 /** Prepare sgeneric control transaction336 /** Prepare generic control transaction 324 337 * 325 338 * @param[in] instance Batch structure to use. 326 339 * @param[in] data_stage to use for data packets. 327 340 * @param[in] status_stage to use for data packets. 341 * 342 * Setup stage with toggle 0 and USB_PID_SETUP. 343 * Data stage with alternating toggle and pid supplied by parameter. 344 * Status stage with toggle 1 and pid supplied by parameter. 345 * The last packet is marked with IOC. 328 346 */ 329 347 void batch_control(batch_t *instance, … … 369 387 0, 1, false, low_speed, instance->target, status_stage, NULL, NULL); 370 388 371 372 instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 389 td_set_ioc(&instance->tds[packet]); 373 390 usb_log_debug2("Control last TD status: %x.\n", 374 391 instance->tds[packet].status); 375 392 } 376 393 /*----------------------------------------------------------------------------*/ 377 /** Prepares data, gets error status and calls callback in. 378 * 379 * @param[in] instance Batch structure to use. 394 /** Prepare data, get error status and call callback in. 395 * 396 * @param[in] instance Batch structure to use. 397 * Copies data from transport buffer, and calls callback with appropriate 398 * parameters. 380 399 */ 381 400 void batch_call_in(batch_t *instance) … … 384 403 assert(instance->callback_in); 385 404 386 /* we are data in, we need data */405 /* We are data in, we need data */ 387 406 memcpy(instance->buffer, instance->transport_buffer, 388 407 instance->buffer_size); … … 397 416 } 398 417 /*----------------------------------------------------------------------------*/ 399 /** Get s error status and callscallback out.418 /** Get error status and call callback out. 400 419 * 401 420 * @param[in] instance Batch structure to use. … … 413 432 } 414 433 /*----------------------------------------------------------------------------*/ 415 /** Prepares data, gets error status, calls callback in and dispose.434 /** Helper function calls callback and correctly disposes of batch structure. 416 435 * 417 436 * @param[in] instance Batch structure to use. … … 424 443 } 425 444 /*----------------------------------------------------------------------------*/ 426 /** Gets error status, calls callback out and dispose.445 /** Helper function calls callback and correctly disposes of batch structure. 427 446 * 428 447 * @param[in] instance Batch structure to use. … … 435 454 } 436 455 /*----------------------------------------------------------------------------*/ 437 /** Correctly dispose sall used data structures.456 /** Correctly dispose all used data structures. 438 457 * 439 458 * @param[in] instance Batch structure to use. … … 450 469 free(instance); 451 470 } 452 /*----------------------------------------------------------------------------*/453 int batch_schedule(batch_t *instance)454 {455 assert(instance);456 uhci_t *hc = fun_to_uhci(instance->fun);457 assert(hc);458 return uhci_schedule(hc, instance);459 }460 471 /** 461 472 * @} -
uspace/drv/uhci-hcd/batch.h
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver USB transaction structure 33 33 */ 34 34 #ifndef DRV_UHCI_BATCH_H … … 50 50 usb_target_t target; 51 51 usb_transfer_type_t transfer_type; 52 union { 53 usbhc_iface_transfer_in_callback_t callback_in; 54 usbhc_iface_transfer_out_callback_t callback_out; 55 }; 52 usbhc_iface_transfer_in_callback_t callback_in; 53 usbhc_iface_transfer_out_callback_t callback_out; 56 54 void *arg; 57 55 char *transport_buffer; … … 65 63 int error; 66 64 ddf_fun_t *fun; 67 q ueue_head_t *qh;65 qh_t *qh; 68 66 td_t *tds; 69 67 void (*next_step)(struct batch*); … … 79 77 device_keeper_t *manager 80 78 ); 79 80 void batch_dispose(batch_t *instance); 81 81 82 82 bool batch_is_complete(batch_t *instance); -
uspace/drv/uhci-hcd/iface.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver hc interface implementation 33 33 */ 34 34 #include <ddf/driver.h> … … 40 40 41 41 #include "iface.h" 42 #include "uhci .h"42 #include "uhci_hc.h" 43 43 #include "utils/device_keeper.h" 44 44 … … 53 53 { 54 54 assert(fun); 55 uhci_ t *hc = fun_to_uhci(fun);55 uhci_hc_t *hc = fun_to_uhci_hc(fun); 56 56 assert(hc); 57 57 usb_log_debug("Default address request with speed %d.\n", speed); … … 68 68 { 69 69 assert(fun); 70 uhci_ t *hc = fun_to_uhci(fun);70 uhci_hc_t *hc = fun_to_uhci_hc(fun); 71 71 assert(hc); 72 72 usb_log_debug("Default address release.\n"); … … 86 86 { 87 87 assert(fun); 88 uhci_ t *hc = fun_to_uhci(fun);88 uhci_hc_t *hc = fun_to_uhci_hc(fun); 89 89 assert(hc); 90 90 assert(address); … … 109 109 { 110 110 assert(fun); 111 uhci_ t *hc = fun_to_uhci(fun);111 uhci_hc_t *hc = fun_to_uhci_hc(fun); 112 112 assert(hc); 113 113 usb_log_debug("Address bind %d-%d.\n", address, handle); … … 125 125 { 126 126 assert(fun); 127 uhci_ t *hc = fun_to_uhci(fun);127 uhci_hc_t *hc = fun_to_uhci_hc(fun); 128 128 assert(hc); 129 129 usb_log_debug("Address release %d.\n", address); … … 148 148 { 149 149 assert(fun); 150 uhci_ t *hc = fun_to_uhci(fun);150 uhci_hc_t *hc = fun_to_uhci_hc(fun); 151 151 assert(hc); 152 152 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 161 161 return ENOMEM; 162 162 batch_interrupt_out(batch); 163 const int ret = uhci_hc_schedule(hc, batch); 164 if (ret != EOK) { 165 batch_dispose(batch); 166 return ret; 167 } 163 168 return EOK; 164 169 } … … 180 185 { 181 186 assert(fun); 182 uhci_ t *hc = fun_to_uhci(fun);187 uhci_hc_t *hc = fun_to_uhci_hc(fun); 183 188 assert(hc); 184 189 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 192 197 return ENOMEM; 193 198 batch_interrupt_in(batch); 199 const int ret = uhci_hc_schedule(hc, batch); 200 if (ret != EOK) { 201 batch_dispose(batch); 202 return ret; 203 } 194 204 return EOK; 195 205 } … … 211 221 { 212 222 assert(fun); 213 uhci_ t *hc = fun_to_uhci(fun);223 uhci_hc_t *hc = fun_to_uhci_hc(fun); 214 224 assert(hc); 215 225 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 224 234 return ENOMEM; 225 235 batch_bulk_out(batch); 236 const int ret = uhci_hc_schedule(hc, batch); 237 if (ret != EOK) { 238 batch_dispose(batch); 239 return ret; 240 } 226 241 return EOK; 227 242 } … … 243 258 { 244 259 assert(fun); 245 uhci_ t *hc = fun_to_uhci(fun);260 uhci_hc_t *hc = fun_to_uhci_hc(fun); 246 261 assert(hc); 247 262 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 255 270 return ENOMEM; 256 271 batch_bulk_in(batch); 272 const int ret = uhci_hc_schedule(hc, batch); 273 if (ret != EOK) { 274 batch_dispose(batch); 275 return ret; 276 } 257 277 return EOK; 258 278 } … … 277 297 { 278 298 assert(fun); 279 uhci_ t *hc = fun_to_uhci(fun);280 assert(hc); 281 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 282 usb_log_debug("Control WRITE %d:%d %zu(%zu).\n",283 target.address, target.endpoint, size, max_packet_size);299 uhci_hc_t *hc = fun_to_uhci_hc(fun); 300 assert(hc); 301 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 302 usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n", 303 speed, target.address, target.endpoint, size, max_packet_size); 284 304 285 305 if (setup_size != 8) … … 293 313 device_keeper_reset_if_need(&hc->device_manager, target, setup_data); 294 314 batch_control_write(batch); 315 const int ret = uhci_hc_schedule(hc, batch); 316 if (ret != EOK) { 317 batch_dispose(batch); 318 return ret; 319 } 295 320 return EOK; 296 321 } … … 315 340 { 316 341 assert(fun); 317 uhci_ t *hc = fun_to_uhci(fun);318 assert(hc); 319 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 320 321 usb_log_debug("Control READ %d:%d %zu(%zu).\n",322 target.address, target.endpoint, size, max_packet_size);342 uhci_hc_t *hc = fun_to_uhci_hc(fun); 343 assert(hc); 344 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 345 346 usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n", 347 speed, target.address, target.endpoint, size, max_packet_size); 323 348 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, 324 349 max_packet_size, speed, data, size, setup_data, setup_size, callback, … … 327 352 return ENOMEM; 328 353 batch_control_read(batch); 329 return EOK; 330 } 331 /*----------------------------------------------------------------------------*/ 332 usbhc_iface_t uhci_iface = { 354 const int ret = uhci_hc_schedule(hc, batch); 355 if (ret != EOK) { 356 batch_dispose(batch); 357 return ret; 358 } 359 return EOK; 360 } 361 /*----------------------------------------------------------------------------*/ 362 usbhc_iface_t uhci_hc_iface = { 333 363 .reserve_default_address = reserve_default_address, 334 364 .release_default_address = release_default_address, -
uspace/drv/uhci-hcd/iface.h
r45dd8bf r4f66cc7b 27 27 */ 28 28 29 /** @addtogroup usb29 /** @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief UHCI driver 33 * @brief UHCI driver iface 34 34 */ 35 35 #ifndef DRV_UHCI_IFACE_H … … 38 38 #include <usbhc_iface.h> 39 39 40 extern usbhc_iface_t uhci_ iface;40 extern usbhc_iface_t uhci_hc_iface; 41 41 42 42 #endif -
uspace/drv/uhci-hcd/main.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver initialization 33 33 */ 34 34 #include <ddf/driver.h> 35 #include <ddf/interrupt.h>36 #include <device/hw_res.h>37 35 #include <errno.h> 38 36 #include <str_error.h> 39 37 40 #include <usb_iface.h>41 38 #include <usb/ddfiface.h> 42 39 #include <usb/debug.h> 43 40 44 41 #include "iface.h" 45 #include "pci.h"46 #include "root_hub.h"47 42 #include "uhci.h" 48 43 … … 60 55 }; 61 56 /*----------------------------------------------------------------------------*/ 62 /** IRQ handling callback, identifies devic 63 * 64 * @param[in] dev DDF instance of the device to use. 65 * @param[in] iid (Unused). 66 * @param[in] call Pointer to the call that represents interrupt. 67 */ 68 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 69 { 70 assert(dev); 71 uhci_t *hc = dev_to_uhci(dev); 72 uint16_t status = IPC_GET_ARG1(*call); 73 assert(hc); 74 uhci_interrupt(hc, status); 75 } 76 /*----------------------------------------------------------------------------*/ 77 /** Initializes a new ddf driver instance of UHCI hcd. 57 /** Initialize a new ddf driver instance for uhci hc and hub. 78 58 * 79 59 * @param[in] device DDF instance of the device to initialize. 80 60 * @return Error code. 81 *82 * Gets and initialies hardware resources, disables any legacy support,83 * and reports root hub device.84 61 */ 85 62 int uhci_add_device(ddf_dev_t *device) 86 63 { 64 usb_log_info("uhci_add_device() called\n"); 87 65 assert(device); 88 uhci_t *hcd = NULL; 89 #define CHECK_RET_FREE_HC_RETURN(ret, message...) \ 90 if (ret != EOK) { \ 91 usb_log_error(message); \ 92 if (hcd != NULL) \ 93 free(hcd); \ 94 return ret; \ 95 } 66 uhci_t *uhci = malloc(sizeof(uhci_t)); 67 if (uhci == NULL) { 68 usb_log_error("Failed to allocate UHCI driver.\n"); 69 return ENOMEM; 70 } 96 71 97 usb_log_info("uhci_add_device() called\n"); 98 99 uintptr_t io_reg_base = 0; 100 size_t io_reg_size = 0; 101 int irq = 0; 102 103 int ret = 104 pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq); 105 CHECK_RET_FREE_HC_RETURN(ret, 106 "Failed(%d) to get I/O addresses:.\n", ret, device->handle); 107 usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n", 108 io_reg_base, io_reg_size, irq); 109 110 ret = pci_disable_legacy(device); 111 CHECK_RET_FREE_HC_RETURN(ret, 112 "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret)); 113 114 #if 0 115 ret = pci_enable_interrupts(device); 72 int ret = uhci_init(uhci, device); 116 73 if (ret != EOK) { 117 usb_log_warning( 118 "Failed(%d) to enable interrupts, fall back to polling.\n", 119 ret); 74 usb_log_error("Failed to initialzie UHCI driver.\n"); 75 return ret; 120 76 } 121 #endif 122 123 hcd = malloc(sizeof(uhci_t)); 124 ret = (hcd != NULL) ? EOK : ENOMEM; 125 CHECK_RET_FREE_HC_RETURN(ret, 126 "Failed(%d) to allocate memory for uhci hcd.\n", ret); 127 128 ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size); 129 CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 130 #undef CHECK_RET_FREE_HC_RETURN 131 132 /* 133 * We might free hcd, but that does not matter since no one 134 * else would access driver_data anyway. 135 */ 136 device->driver_data = hcd; 137 138 ddf_fun_t *rh = NULL; 139 #define CHECK_RET_FINI_FREE_RETURN(ret, message...) \ 140 if (ret != EOK) { \ 141 usb_log_error(message); \ 142 if (hcd != NULL) {\ 143 uhci_fini(hcd); \ 144 free(hcd); \ 145 } \ 146 if (rh != NULL) \ 147 free(rh); \ 148 return ret; \ 149 } 150 151 /* It does no harm if we register this on polling */ 152 ret = register_interrupt_handler(device, irq, irq_handler, 153 &hcd->interrupt_code); 154 CHECK_RET_FINI_FREE_RETURN(ret, 155 "Failed(%d) to register interrupt handler.\n", ret); 156 157 ret = setup_root_hub(&rh, device); 158 CHECK_RET_FINI_FREE_RETURN(ret, 159 "Failed(%d) to setup UHCI root hub.\n", ret); 160 rh->driver_data = hcd->ddf_instance; 161 162 ret = ddf_fun_bind(rh); 163 CHECK_RET_FINI_FREE_RETURN(ret, 164 "Failed(%d) to register UHCI root hub.\n", ret); 165 77 device->driver_data = uhci; 166 78 return EOK; 167 #undef CHECK_RET_FINI_FREE_RETURN168 79 } 169 80 /*----------------------------------------------------------------------------*/ 170 /** Initialize sglobal driver structures (NONE).81 /** Initialize global driver structures (NONE). 171 82 * 172 83 * @param[in] argc Nmber of arguments in argv vector (ignored). … … 178 89 int main(int argc, char *argv[]) 179 90 { 180 sleep(3); 91 sleep(3); /* TODO: remove in final version */ 181 92 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 182 93 -
uspace/drv/uhci-hcd/pci.c
r45dd8bf r4f66cc7b 27 27 */ 28 28 /** 29 * @addtogroup drvusbuhci 29 * @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ … … 117 117 } 118 118 /*----------------------------------------------------------------------------*/ 119 /** Call sthe PCI driver with a request to enable interrupts119 /** Call the PCI driver with a request to enable interrupts 120 120 * 121 121 * @param[in] device Device asking for interrupts … … 131 131 } 132 132 /*----------------------------------------------------------------------------*/ 133 /** Call sthe PCI driver with a request to clear legacy support register133 /** Call the PCI driver with a request to clear legacy support register 134 134 * 135 135 * @param[in] device Device asking to disable interrupts -
uspace/drv/uhci-hcd/pci.h
r45dd8bf r4f66cc7b 27 27 */ 28 28 29 /** @addtogroup drvusbuhci 29 /** @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief UHCI driver 33 * @brief UHCI driver PCI helper functions 34 34 */ 35 35 #ifndef DRV_UHCI_PCI_H -
uspace/drv/uhci-hcd/transfer_list.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver transfer list implementation 33 33 */ 34 34 #include <errno.h> 35 36 35 #include <usb/debug.h> 37 36 … … 41 40 transfer_list_t *instance, batch_t *batch); 42 41 /*----------------------------------------------------------------------------*/ 43 /** Initialize stransfer list structures.42 /** Initialize transfer list structures. 44 43 * 45 44 * @param[in] instance Memory place to use. 46 * @param[in] name Name of t e new list.47 * @return Error code 48 * 49 * Allocates memory for interna t queue_head_t structure.45 * @param[in] name Name of the new list. 46 * @return Error code 47 * 48 * Allocates memory for internal qh_t structure. 50 49 */ 51 50 int transfer_list_init(transfer_list_t *instance, const char *name) 52 51 { 53 52 assert(instance); 54 instance->next = NULL;55 53 instance->name = name; 56 instance->queue_head = malloc32(sizeof(q ueue_head_t));54 instance->queue_head = malloc32(sizeof(qh_t)); 57 55 if (!instance->queue_head) { 58 56 usb_log_error("Failed to allocate queue head.\n"); … … 61 59 instance->queue_head_pa = addr_to_phys(instance->queue_head); 62 60 63 q ueue_head_init(instance->queue_head);61 qh_init(instance->queue_head); 64 62 list_initialize(&instance->batch_list); 65 63 fibril_mutex_initialize(&instance->guard); … … 67 65 } 68 66 /*----------------------------------------------------------------------------*/ 69 /** Set the next list in chain.67 /** Set the next list in transfer list chain. 70 68 * 71 69 * @param[in] instance List to lead. 72 70 * @param[in] next List to append. 73 71 * @return Error code 72 * 73 * Does not check whether this replaces an existing list . 74 74 */ 75 75 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next) … … 79 79 if (!instance->queue_head) 80 80 return; 81 queue_head_append_qh(instance->queue_head, next->queue_head_pa); 82 instance->queue_head->element = instance->queue_head->next_queue; 83 } 84 /*----------------------------------------------------------------------------*/ 85 /** Submits a new transfer batch to list and queue. 81 /* Set both next and element to point to the same QH */ 82 qh_set_next_qh(instance->queue_head, next->queue_head_pa); 83 qh_set_element_qh(instance->queue_head, next->queue_head_pa); 84 } 85 /*----------------------------------------------------------------------------*/ 86 /** Submit transfer batch to the list and queue. 86 87 * 87 88 * @param[in] instance List to use. 88 89 * @param[in] batch Transfer batch to submit. 89 90 * @return Error code 91 * 92 * The batch is added to the end of the list and queue. 90 93 */ 91 94 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch) … … 93 96 assert(instance); 94 97 assert(batch); 95 usb_log_debug2( 96 "Adding batch(%p) to queue %s.\n", batch, instance->name); 97 98 uint32_t pa = (uintptr_t)addr_to_phys(batch->qh); 98 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch); 99 100 const uint32_t pa = addr_to_phys(batch->qh); 99 101 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa); 100 pa |= LINK_POINTER_QUEUE_HEAD_FLAG; 101 102 batch->qh->next_queue = instance->queue_head->next_queue; 102 103 /* New batch will be added to the end of the current list 104 * so set the link accordingly */ 105 qh_set_next_qh(batch->qh, instance->queue_head->next); 103 106 104 107 fibril_mutex_lock(&instance->guard); 105 108 106 if (instance->queue_head->element == instance->queue_head->next_queue) { 107 /* there is nothing scheduled */ 108 list_append(&batch->link, &instance->batch_list); 109 instance->queue_head->element = pa; 110 usb_log_debug("Batch(%p) added to queue %s first.\n", 111 batch, instance->name); 112 fibril_mutex_unlock(&instance->guard); 113 return; 114 } 115 /* now we can be sure that there is someting scheduled */ 116 assert(!list_empty(&instance->batch_list)); 109 /* Add to the hardware queue. */ 110 if (list_empty(&instance->batch_list)) { 111 /* There is nothing scheduled */ 112 qh_t *qh = instance->queue_head; 113 assert(qh->element == qh->next); 114 qh_set_element_qh(qh, pa); 115 } else { 116 /* There is something scheduled */ 117 batch_t *last = list_get_instance( 118 instance->batch_list.prev, batch_t, link); 119 qh_set_next_qh(last->qh, pa); 120 } 121 /* Add to the driver list */ 122 list_append(&batch->link, &instance->batch_list); 123 117 124 batch_t *first = list_get_instance( 118 instance->batch_list.next, batch_t, link); 119 batch_t *last = list_get_instance( 120 instance->batch_list.prev, batch_t, link); 121 queue_head_append_qh(last->qh, pa); 122 list_append(&batch->link, &instance->batch_list); 123 124 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 125 instance->batch_list.next, batch_t, link); 126 usb_log_debug("Batch(%p) added to queue %s, first is %p.\n", 125 127 batch, instance->name, first); 126 128 fibril_mutex_unlock(&instance->guard); 127 129 } 128 130 /*----------------------------------------------------------------------------*/ 129 /** Remove s a transfer batch fromlist and queue.131 /** Remove a transfer batch from the list and queue. 130 132 * 131 133 * @param[in] instance List to use. 132 134 * @param[in] batch Transfer batch to remove. 133 135 * @return Error code 136 * 137 * Does not lock the transfer list, caller is responsible for that. 134 138 */ 135 139 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) … … 140 144 assert(batch->qh); 141 145 usb_log_debug2( 142 "Removing batch(%p) from queue %s.\n", batch, instance->name); 143 146 "Queue %s: removing batch(%p).\n", instance->name, batch); 147 148 const char * pos = NULL; 149 /* Remove from the hardware queue */ 144 150 if (batch->link.prev == &instance->batch_list) { 145 151 /* I'm the first one here */ 146 usb_log_debug( 147 "Batch(%p) removed (FIRST) from %s, next element %x.\n", 148 batch, instance->name, batch->qh->next_queue); 149 instance->queue_head->element = batch->qh->next_queue; 152 qh_set_element_qh(instance->queue_head, batch->qh->next); 153 pos = "FIRST"; 150 154 } else { 151 usb_log_debug(152 "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",153 batch, instance->name, batch->qh->next_queue);154 155 batch_t *prev = 155 156 list_get_instance(batch->link.prev, batch_t, link); 156 prev->qh->next_queue = batch->qh->next_queue; 157 } 157 qh_set_next_qh(prev->qh, batch->qh->next); 158 pos = "NOT FIRST"; 159 } 160 /* Remove from the driver list */ 158 161 list_remove(&batch->link); 159 } 160 /*----------------------------------------------------------------------------*/ 161 /** Checks list for finished transfers. 162 usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n", 163 batch, pos, instance->name, batch->qh->next); 164 } 165 /*----------------------------------------------------------------------------*/ 166 /** Check list for finished batches. 162 167 * 163 168 * @param[in] instance List to use. 164 169 * @return Error code 170 * 171 * Creates a local list of finished batches and calls next_step on each and 172 * every one. This is safer because next_step may theoretically access 173 * this transfer list leading to the deadlock if its done inline. 165 174 */ 166 175 void transfer_list_remove_finished(transfer_list_t *instance) … … 177 186 178 187 if (batch_is_complete(batch)) { 188 /* Save for post-processing */ 179 189 transfer_list_remove_batch(instance, batch); 180 190 list_append(current, &done); -
uspace/drv/uhci-hcd/transfer_list.h
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver transfer list structure 33 33 */ 34 34 #ifndef DRV_UHCI_TRANSFER_LIST_H … … 44 44 { 45 45 fibril_mutex_t guard; 46 q ueue_head_t *queue_head;46 qh_t *queue_head; 47 47 uint32_t queue_head_pa; 48 struct transfer_list *next;49 48 const char *name; 50 49 link_t batch_list; 51 50 } transfer_list_t; 51 52 /** Dispose transfer list structures. 53 * 54 * @param[in] instance Memory place to use. 55 * 56 * Frees memory for internal qh_t structure. 57 */ 58 static inline void transfer_list_fini(transfer_list_t *instance) 59 { 60 assert(instance); 61 free32(instance->queue_head); 62 } 52 63 53 64 int transfer_list_init(transfer_list_t *instance, const char *name); … … 55 66 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next); 56 67 57 static inline void transfer_list_fini(transfer_list_t *instance)58 {59 assert(instance);60 free32(instance->queue_head);61 }62 68 void transfer_list_remove_finished(transfer_list_t *instance); 63 69 -
uspace/drv/uhci-hcd/uhci.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb 28 29 /** @addtogroup drvusbuhci 29 30 * @{ 30 31 */ … … 34 35 #include <errno.h> 35 36 #include <str_error.h> 36 #include < adt/list.h>37 #include < libarch/ddi.h>38 37 #include <ddf/interrupt.h> 38 #include <usb_iface.h> 39 #include <usb/ddfiface.h> 39 40 #include <usb/debug.h> 40 #include <usb/usb.h>41 #include <usb/ddfiface.h>42 #include <usb_iface.h>43 41 44 42 #include "uhci.h" 45 43 #include "iface.h" 46 47 static irq_cmd_t uhci_cmds[] = { 48 { 49 .cmd = CMD_PIO_READ_16, 50 .addr = NULL, /* patched for every instance */ 51 .dstarg = 1 52 }, 53 { 54 .cmd = CMD_PIO_WRITE_16, 55 .addr = NULL, /* pathed for every instance */ 56 .value = 0x1f 57 },58 {59 .cmd = CMD_ACCEPT60 }61 };62 63 /* * Gets USB address of the calling device.64 * 65 * @param[in] fun UHCI hc function.66 * @param[in] handle Handle of the device seeking address.67 * @param[ out] address Place to store found address.68 * @ return Error code.44 #include "pci.h" 45 46 47 /** IRQ handling callback, identifies device 48 * 49 * @param[in] dev DDF instance of the device to use. 50 * @param[in] iid (Unused). 51 * @param[in] call Pointer to the call that represents interrupt. 52 */ 53 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 54 { 55 assert(dev); 56 uhci_hc_t *hc = &((uhci_t*)dev->driver_data)->hc; 57 uint16_t status = IPC_GET_ARG1(*call); 58 assert(hc); 59 uhci_hc_interrupt(hc, status); 60 } 61 /*----------------------------------------------------------------------------*/ 62 /** Get address of the device identified by handle. 63 * 64 * @param[in] dev DDF instance of the device to use. 65 * @param[in] iid (Unused). 66 * @param[in] call Pointer to the call that represents interrupt. 69 67 */ 70 68 static int usb_iface_get_address( … … 72 70 { 73 71 assert(fun); 74 uhci_t *hc = fun_to_uhci(fun); 75 assert(hc); 76 77 usb_address_t addr = device_keeper_find(&hc->device_manager, 78 handle); 72 device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.device_manager; 73 74 usb_address_t addr = device_keeper_find(manager, handle); 79 75 if (addr < 0) { 80 76 return addr; … … 88 84 } 89 85 /*----------------------------------------------------------------------------*/ 90 static usb_iface_t hc_usb_iface = { 91 .get_hc_handle = usb_iface_get_hc_handle_hc_impl, 86 /** Gets handle of the respective hc (this or parent device). 87 * 88 * @param[in] root_hub_fun Root hub function seeking hc handle. 89 * @param[out] handle Place to write the handle. 90 * @return Error code. 91 */ 92 static int usb_iface_get_hc_handle( 93 ddf_fun_t *fun, devman_handle_t *handle) 94 { 95 assert(handle); 96 ddf_fun_t *hc_fun = ((uhci_t*)fun->dev->driver_data)->hc_fun; 97 assert(hc_fun != NULL); 98 99 *handle = hc_fun->handle; 100 return EOK; 101 } 102 /*----------------------------------------------------------------------------*/ 103 /** This iface is generic for both RH and HC. */ 104 static usb_iface_t usb_iface = { 105 .get_hc_handle = usb_iface_get_hc_handle, 92 106 .get_address = usb_iface_get_address 93 107 }; 94 108 /*----------------------------------------------------------------------------*/ 95 static ddf_dev_ops_t uhci_ops = { 96 .interfaces[USB_DEV_IFACE] = &hc_usb_iface, 97 .interfaces[USBHC_DEV_IFACE] = &uhci_iface, 98 }; 99 /*----------------------------------------------------------------------------*/ 100 static int uhci_init_transfer_lists(uhci_t *instance); 101 static int uhci_init_mem_structures(uhci_t *instance); 102 static void uhci_init_hw(uhci_t *instance); 103 104 static int uhci_interrupt_emulator(void *arg); 105 static int uhci_debug_checker(void *arg); 106 107 static bool allowed_usb_packet( 108 bool low_speed, usb_transfer_type_t transfer, size_t size); 109 /*----------------------------------------------------------------------------*/ 110 /** Initializes UHCI hcd driver structure 111 * 112 * @param[in] instance Memory place to initialize. 113 * @param[in] dev DDF device. 114 * @param[in] regs Address of I/O control registers. 115 * @param[in] size Size of I/O control registers. 116 * @return Error code. 117 * @note Should be called only once on any structure. 118 */ 119 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 120 { 121 assert(reg_size >= sizeof(regs_t)); 122 int ret; 123 109 static ddf_dev_ops_t uhci_hc_ops = { 110 .interfaces[USB_DEV_IFACE] = &usb_iface, 111 .interfaces[USBHC_DEV_IFACE] = &uhci_hc_iface, /* see iface.h/c */ 112 }; 113 /*----------------------------------------------------------------------------*/ 114 /** Get root hub hw resources (I/O registers). 115 * 116 * @param[in] fun Root hub function. 117 * @return Pointer to the resource list used by the root hub. 118 */ 119 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun) 120 { 121 assert(fun); 122 return &((uhci_rh_t*)fun->driver_data)->resource_list; 123 } 124 /*----------------------------------------------------------------------------*/ 125 static hw_res_ops_t hw_res_iface = { 126 .get_resource_list = get_resource_list, 127 .enable_interrupt = NULL 128 }; 129 /*----------------------------------------------------------------------------*/ 130 static ddf_dev_ops_t uhci_rh_ops = { 131 .interfaces[USB_DEV_IFACE] = &usb_iface, 132 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 133 }; 134 /*----------------------------------------------------------------------------*/ 135 /** Initialize hc and rh ddf structures and their respective drivers. 136 * 137 * @param[in] instance UHCI structure to use. 138 * @param[in] device DDF instance of the device to use. 139 * 140 * This function does all the preparatory work for hc and rh drivers: 141 * - gets device hw resources 142 * - disables UHCI legacy support 143 * - asks for interrupt 144 * - registers interrupt handler 145 */ 146 int uhci_init(uhci_t *instance, ddf_dev_t *device) 147 { 148 assert(instance); 149 instance->hc_fun = NULL; 150 instance->rh_fun = NULL; 124 151 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \ 125 if (ret != EOK) { \ 126 usb_log_error(message); \ 127 if (instance->ddf_instance) \ 128 ddf_fun_destroy(instance->ddf_instance); \ 129 return ret; \ 130 } else (void) 0 131 132 /* Create UHCI function. */ 133 instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci"); 134 ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK; 135 CHECK_RET_DEST_FUN_RETURN(ret, 136 "Failed to create UHCI device function.\n"); 137 138 instance->ddf_instance->ops = &uhci_ops; 139 instance->ddf_instance->driver_data = instance; 140 141 ret = ddf_fun_bind(instance->ddf_instance); 152 if (ret != EOK) { \ 153 usb_log_error(message); \ 154 if (instance->hc_fun) \ 155 ddf_fun_destroy(instance->hc_fun); \ 156 if (instance->rh_fun) \ 157 ddf_fun_destroy(instance->rh_fun); \ 158 return ret; \ 159 } 160 161 uintptr_t io_reg_base = 0; 162 size_t io_reg_size = 0; 163 int irq = 0; 164 165 int ret = 166 pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq); 167 CHECK_RET_DEST_FUN_RETURN(ret, 168 "Failed(%d) to get I/O addresses:.\n", ret, device->handle); 169 usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n", 170 io_reg_base, io_reg_size, irq); 171 172 ret = pci_disable_legacy(device); 173 CHECK_RET_DEST_FUN_RETURN(ret, 174 "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret)); 175 176 bool interrupts = false; 177 ret = pci_enable_interrupts(device); 178 if (ret != EOK) { 179 usb_log_warning( 180 "Failed(%d) to enable interrupts, fall back to polling.\n", 181 ret); 182 } else { 183 usb_log_debug("Hw interrupts enabled.\n"); 184 interrupts = true; 185 } 186 187 instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc"); 188 ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 189 CHECK_RET_DEST_FUN_RETURN(ret, 190 "Failed(%d) to create HC function.\n", ret); 191 192 ret = uhci_hc_init(&instance->hc, instance->hc_fun, 193 (void*)io_reg_base, io_reg_size, interrupts); 194 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 195 instance->hc_fun->ops = &uhci_hc_ops; 196 instance->hc_fun->driver_data = &instance->hc; 197 ret = ddf_fun_bind(instance->hc_fun); 142 198 CHECK_RET_DEST_FUN_RETURN(ret, 143 199 "Failed(%d) to bind UHCI device function: %s.\n", 144 200 ret, str_error(ret)); 145 146 /* allow access to hc control registers */ 147 regs_t *io; 148 ret = pio_enable(regs, reg_size, (void**)&io); 149 CHECK_RET_DEST_FUN_RETURN(ret, 150 "Failed(%d) to gain access to registers at %p: %s.\n", 151 ret, str_error(ret), io); 152 instance->registers = io; 153 usb_log_debug("Device registers at %p(%u) accessible.\n", 154 io, reg_size); 155 156 ret = uhci_init_mem_structures(instance); 157 CHECK_RET_DEST_FUN_RETURN(ret, 158 "Failed to initialize UHCI memory structures.\n"); 159 160 uhci_init_hw(instance); 161 instance->cleaner = 162 fibril_create(uhci_interrupt_emulator, instance); 163 fibril_add_ready(instance->cleaner); 164 165 instance->debug_checker = fibril_create(uhci_debug_checker, instance); 166 fibril_add_ready(instance->debug_checker); 167 168 usb_log_info("Started UHCI driver.\n"); 201 #undef CHECK_RET_HC_RETURN 202 203 #define CHECK_RET_FINI_RETURN(ret, message...) \ 204 if (ret != EOK) { \ 205 usb_log_error(message); \ 206 if (instance->hc_fun) \ 207 ddf_fun_destroy(instance->hc_fun); \ 208 if (instance->rh_fun) \ 209 ddf_fun_destroy(instance->rh_fun); \ 210 uhci_hc_fini(&instance->hc); \ 211 return ret; \ 212 } 213 214 /* It does no harm if we register this on polling */ 215 ret = register_interrupt_handler(device, irq, irq_handler, 216 &instance->hc.interrupt_code); 217 CHECK_RET_FINI_RETURN(ret, 218 "Failed(%d) to register interrupt handler.\n", ret); 219 220 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh"); 221 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 222 CHECK_RET_FINI_RETURN(ret, 223 "Failed(%d) to create root hub function.\n", ret); 224 225 ret = uhci_rh_init(&instance->rh, instance->rh_fun, 226 (uintptr_t)instance->hc.registers + 0x10, 4); 227 CHECK_RET_FINI_RETURN(ret, 228 "Failed(%d) to setup UHCI root hub.\n", ret); 229 230 instance->rh_fun->ops = &uhci_rh_ops; 231 instance->rh_fun->driver_data = &instance->rh; 232 ret = ddf_fun_bind(instance->rh_fun); 233 CHECK_RET_FINI_RETURN(ret, 234 "Failed(%d) to register UHCI root hub.\n", ret); 235 169 236 return EOK; 170 #undef CHECK_RET_DEST_FUN_RETURN 171 } 172 /*----------------------------------------------------------------------------*/ 173 /** Initializes UHCI hcd hw resources. 174 * 175 * @param[in] instance UHCI structure to use. 176 */ 177 void uhci_init_hw(uhci_t *instance) 178 { 179 assert(instance); 180 regs_t *registers = instance->registers; 181 182 /* Reset everything, who knows what touched it before us */ 183 pio_write_16(®isters->usbcmd, UHCI_CMD_GLOBAL_RESET); 184 async_usleep(10000); /* 10ms according to USB spec */ 185 pio_write_16(®isters->usbcmd, 0); 186 187 /* Reset hc, all states and counters */ 188 pio_write_16(®isters->usbcmd, UHCI_CMD_HCRESET); 189 do { async_usleep(10); } 190 while ((pio_read_16(®isters->usbcmd) & UHCI_CMD_HCRESET) != 0); 191 192 /* Set framelist pointer */ 193 const uint32_t pa = addr_to_phys(instance->frame_list); 194 pio_write_32(®isters->flbaseadd, pa); 195 196 /* Enable all interrupts, but resume interrupt */ 197 // pio_write_16(&instance->registers->usbintr, 198 // UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET); 199 200 uint16_t status = pio_read_16(®isters->usbcmd); 201 if (status != 0) 202 usb_log_warning("Previous command value: %x.\n", status); 203 204 /* Start the hc with large(64B) packet FSBR */ 205 pio_write_16(®isters->usbcmd, 206 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); 207 } 208 /*----------------------------------------------------------------------------*/ 209 /** Initializes UHCI hcd memory structures. 210 * 211 * @param[in] instance UHCI structure to use. 212 * @return Error code 213 * @note Should be called only once on any structure. 214 */ 215 int uhci_init_mem_structures(uhci_t *instance) 216 { 217 assert(instance); 218 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \ 219 if (ret != EOK) { \ 220 usb_log_error(message); \ 221 if (instance->interrupt_code.cmds != NULL) \ 222 free(instance->interrupt_code.cmds); \ 223 return ret; \ 224 } else (void) 0 225 226 /* Init interrupt code */ 227 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 228 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 229 CHECK_RET_DEST_CMDS_RETURN(ret, 230 "Failed to allocate interrupt cmds space.\n"); 231 232 { 233 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 234 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 235 interrupt_commands[0].addr = 236 (void*)&instance->registers->usbsts; 237 interrupt_commands[1].addr = 238 (void*)&instance->registers->usbsts; 239 instance->interrupt_code.cmdcount = 240 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 241 } 242 243 /* Init transfer lists */ 244 ret = uhci_init_transfer_lists(instance); 245 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n"); 246 usb_log_debug("Initialized transfer lists.\n"); 247 248 /* Init USB frame list page*/ 249 instance->frame_list = get_page(); 250 ret = instance ? EOK : ENOMEM; 251 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n"); 252 usb_log_debug("Initialized frame list.\n"); 253 254 /* Set all frames to point to the first queue head */ 255 const uint32_t queue = 256 instance->transfers_interrupt.queue_head_pa 257 | LINK_POINTER_QUEUE_HEAD_FLAG; 258 259 unsigned i = 0; 260 for(; i < UHCI_FRAME_LIST_COUNT; ++i) { 261 instance->frame_list[i] = queue; 262 } 263 264 /* Init device keeper*/ 265 device_keeper_init(&instance->device_manager); 266 usb_log_debug("Initialized device manager.\n"); 267 268 return EOK; 269 #undef CHECK_RET_DEST_CMDS_RETURN 270 } 271 /*----------------------------------------------------------------------------*/ 272 /** Initializes UHCI hcd transfer lists. 273 * 274 * @param[in] instance UHCI structure to use. 275 * @return Error code 276 * @note Should be called only once on any structure. 277 */ 278 int uhci_init_transfer_lists(uhci_t *instance) 279 { 280 assert(instance); 281 #define CHECK_RET_CLEAR_RETURN(ret, message...) \ 282 if (ret != EOK) { \ 283 usb_log_error(message); \ 284 transfer_list_fini(&instance->transfers_bulk_full); \ 285 transfer_list_fini(&instance->transfers_control_full); \ 286 transfer_list_fini(&instance->transfers_control_slow); \ 287 transfer_list_fini(&instance->transfers_interrupt); \ 288 return ret; \ 289 } else (void) 0 290 291 /* initialize TODO: check errors */ 292 int ret; 293 ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL"); 294 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 295 296 ret = transfer_list_init( 297 &instance->transfers_control_full, "CONTROL_FULL"); 298 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 299 300 ret = transfer_list_init( 301 &instance->transfers_control_slow, "CONTROL_SLOW"); 302 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 303 304 ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT"); 305 CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list."); 306 307 transfer_list_set_next(&instance->transfers_control_full, 308 &instance->transfers_bulk_full); 309 transfer_list_set_next(&instance->transfers_control_slow, 310 &instance->transfers_control_full); 311 transfer_list_set_next(&instance->transfers_interrupt, 312 &instance->transfers_control_slow); 313 314 /*FSBR*/ 315 #ifdef FSBR 316 transfer_list_set_next(&instance->transfers_bulk_full, 317 &instance->transfers_control_full); 318 #endif 319 320 /* Assign pointers to be used during scheduling */ 321 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] = 322 &instance->transfers_interrupt; 323 instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] = 324 &instance->transfers_interrupt; 325 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] = 326 &instance->transfers_control_full; 327 instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] = 328 &instance->transfers_control_slow; 329 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] = 330 &instance->transfers_bulk_full; 331 332 return EOK; 333 #undef CHECK_RET_CLEAR_RETURN 334 } 335 /*----------------------------------------------------------------------------*/ 336 /** Schedules batch for execution. 337 * 338 * @param[in] instance UHCI structure to use. 339 * @param[in] batch Transfer batch to schedule. 340 * @return Error code 341 */ 342 int uhci_schedule(uhci_t *instance, batch_t *batch) 343 { 344 assert(instance); 345 assert(batch); 346 const int low_speed = (batch->speed == USB_SPEED_LOW); 347 if (!allowed_usb_packet( 348 low_speed, batch->transfer_type, batch->max_packet_size)) { 349 usb_log_warning( 350 "Invalid USB packet specified %s SPEED %d %zu.\n", 351 low_speed ? "LOW" : "FULL" , batch->transfer_type, 352 batch->max_packet_size); 353 return ENOTSUP; 354 } 355 /* TODO: check available bandwith here */ 356 357 transfer_list_t *list = 358 instance->transfers[low_speed][batch->transfer_type]; 359 assert(list); 360 transfer_list_add_batch(list, batch); 361 362 return EOK; 363 } 364 /*----------------------------------------------------------------------------*/ 365 /** Takes action based on the interrupt cause. 366 * 367 * @param[in] instance UHCI structure to use. 368 * @param[in] status Value of the stsatus regiser at the time of interrupt. 369 */ 370 void uhci_interrupt(uhci_t *instance, uint16_t status) 371 { 372 assert(instance); 373 /* TODO: Check interrupt cause here */ 374 transfer_list_remove_finished(&instance->transfers_interrupt); 375 transfer_list_remove_finished(&instance->transfers_control_slow); 376 transfer_list_remove_finished(&instance->transfers_control_full); 377 transfer_list_remove_finished(&instance->transfers_bulk_full); 378 } 379 /*----------------------------------------------------------------------------*/ 380 /** Polling function, emulates interrupts. 381 * 382 * @param[in] arg UHCI structure to use. 383 * @return EOK 384 */ 385 int uhci_interrupt_emulator(void* arg) 386 { 387 usb_log_debug("Started interrupt emulator.\n"); 388 uhci_t *instance = (uhci_t*)arg; 389 assert(instance); 390 391 while (1) { 392 uint16_t status = pio_read_16(&instance->registers->usbsts); 393 if (status != 0) 394 usb_log_debug2("UHCI status: %x.\n", status); 395 status |= 1; 396 uhci_interrupt(instance, status); 397 pio_write_16(&instance->registers->usbsts, 0x1f); 398 async_usleep(UHCI_CLEANER_TIMEOUT); 399 } 400 return EOK; 401 } 402 /*---------------------------------------------------------------------------*/ 403 /** Debug function, checks consistency of memory structures. 404 * 405 * @param[in] arg UHCI structure to use. 406 * @return EOK 407 */ 408 int uhci_debug_checker(void *arg) 409 { 410 uhci_t *instance = (uhci_t*)arg; 411 assert(instance); 412 413 #define QH(queue) \ 414 instance->transfers_##queue.queue_head 415 416 while (1) { 417 const uint16_t cmd = pio_read_16(&instance->registers->usbcmd); 418 const uint16_t sts = pio_read_16(&instance->registers->usbsts); 419 const uint16_t intr = 420 pio_read_16(&instance->registers->usbintr); 421 422 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) { 423 usb_log_debug2("Command: %X Status: %X Intr: %x\n", 424 cmd, sts, intr); 425 } 426 427 uintptr_t frame_list = 428 pio_read_32(&instance->registers->flbaseadd) & ~0xfff; 429 if (frame_list != addr_to_phys(instance->frame_list)) { 430 usb_log_debug("Framelist address: %p vs. %p.\n", 431 frame_list, addr_to_phys(instance->frame_list)); 432 } 433 434 int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff; 435 usb_log_debug2("Framelist item: %d \n", frnum ); 436 437 uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf); 438 uintptr_t real_pa = addr_to_phys(QH(interrupt)); 439 if (expected_pa != real_pa) { 440 usb_log_debug("Interrupt QH: %p vs. %p.\n", 441 expected_pa, real_pa); 442 } 443 444 expected_pa = QH(interrupt)->next_queue & (~0xf); 445 real_pa = addr_to_phys(QH(control_slow)); 446 if (expected_pa != real_pa) { 447 usb_log_debug("Control Slow QH: %p vs. %p.\n", 448 expected_pa, real_pa); 449 } 450 451 expected_pa = QH(control_slow)->next_queue & (~0xf); 452 real_pa = addr_to_phys(QH(control_full)); 453 if (expected_pa != real_pa) { 454 usb_log_debug("Control Full QH: %p vs. %p.\n", 455 expected_pa, real_pa); 456 } 457 458 expected_pa = QH(control_full)->next_queue & (~0xf); 459 real_pa = addr_to_phys(QH(bulk_full)); 460 if (expected_pa != real_pa ) { 461 usb_log_debug("Bulk QH: %p vs. %p.\n", 462 expected_pa, real_pa); 463 } 464 async_usleep(UHCI_DEBUGER_TIMEOUT); 465 } 466 return EOK; 467 #undef QH 468 } 469 /*----------------------------------------------------------------------------*/ 470 /** Checks transfer packets, for USB validity 471 * 472 * @param[in] low_speed Transfer speed. 473 * @param[in] transfer Transer type 474 * @param[in] size Maximum size of used packets 475 * @return EOK 476 */ 477 bool allowed_usb_packet( 478 bool low_speed, usb_transfer_type_t transfer, size_t size) 479 { 480 /* see USB specification chapter 5.5-5.8 for magic numbers used here */ 481 switch(transfer) 482 { 483 case USB_TRANSFER_ISOCHRONOUS: 484 return (!low_speed && size < 1024); 485 case USB_TRANSFER_INTERRUPT: 486 return size <= (low_speed ? 8 : 64); 487 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 488 return (size <= (low_speed ? 8 : 64)); 489 case USB_TRANSFER_BULK: /* device specifies its own max size */ 490 return (!low_speed && size <= 64); 491 } 492 return false; 237 #undef CHECK_RET_FINI_RETURN 493 238 } 494 239 /** -
uspace/drv/uhci-hcd/uhci.h
r45dd8bf r4f66cc7b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief UHCI driver 33 * @brief UHCI driver main structure for both host controller and root-hub. 34 34 */ 35 35 #ifndef DRV_UHCI_UHCI_H 36 36 #define DRV_UHCI_UHCI_H 37 #include <ddi.h> 38 #include <ddf/driver.h> 37 39 38 #include <fibril.h> 39 #include <fibril_synch.h> 40 #include <adt/list.h> 41 #include <ddi.h> 42 43 #include <usbhc_iface.h> 44 45 #include "batch.h" 46 #include "transfer_list.h" 47 #include "utils/device_keeper.h" 48 49 typedef struct uhci_regs { 50 uint16_t usbcmd; 51 #define UHCI_CMD_MAX_PACKET (1 << 7) 52 #define UHCI_CMD_CONFIGURE (1 << 6) 53 #define UHCI_CMD_DEBUG (1 << 5) 54 #define UHCI_CMD_FORCE_GLOBAL_RESUME (1 << 4) 55 #define UHCI_CMD_FORCE_GLOBAL_SUSPEND (1 << 3) 56 #define UHCI_CMD_GLOBAL_RESET (1 << 2) 57 #define UHCI_CMD_HCRESET (1 << 1) 58 #define UHCI_CMD_RUN_STOP (1 << 0) 59 60 uint16_t usbsts; 61 #define UHCI_STATUS_HALTED (1 << 5) 62 #define UHCI_STATUS_PROCESS_ERROR (1 << 4) 63 #define UHCI_STATUS_SYSTEM_ERROR (1 << 3) 64 #define UHCI_STATUS_RESUME (1 << 2) 65 #define UHCI_STATUS_ERROR_INTERRUPT (1 << 1) 66 #define UHCI_STATUS_INTERRUPT (1 << 0) 67 68 uint16_t usbintr; 69 #define UHCI_INTR_SHORT_PACKET (1 << 3) 70 #define UHCI_INTR_COMPLETE (1 << 2) 71 #define UHCI_INTR_RESUME (1 << 1) 72 #define UHCI_INTR_CRC (1 << 0) 73 74 uint16_t frnum; 75 uint32_t flbaseadd; 76 uint8_t sofmod; 77 } regs_t; 78 79 #define UHCI_FRAME_LIST_COUNT 1024 80 #define UHCI_CLEANER_TIMEOUT 10000 81 #define UHCI_DEBUGER_TIMEOUT 5000000 40 #include "uhci_hc.h" 41 #include "uhci_rh.h" 82 42 83 43 typedef struct uhci { 84 device_keeper_t device_manager; 44 ddf_fun_t *hc_fun; 45 ddf_fun_t *rh_fun; 85 46 86 regs_t *registers; 87 88 link_pointer_t *frame_list; 89 90 transfer_list_t transfers_bulk_full; 91 transfer_list_t transfers_control_full; 92 transfer_list_t transfers_control_slow; 93 transfer_list_t transfers_interrupt; 94 95 transfer_list_t *transfers[2][4]; 96 97 irq_code_t interrupt_code; 98 99 fid_t cleaner; 100 fid_t debug_checker; 101 102 ddf_fun_t *ddf_instance; 47 uhci_hc_t hc; 48 uhci_rh_t rh; 103 49 } uhci_t; 104 50 105 /* init uhci specifics in device.driver_data */ 106 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size); 107 108 static inline void uhci_fini(uhci_t *instance) {}; 109 110 int uhci_schedule(uhci_t *instance, batch_t *batch); 111 112 void uhci_interrupt(uhci_t *instance, uint16_t status); 113 114 static inline uhci_t * dev_to_uhci(ddf_dev_t *dev) 115 { return (uhci_t*)dev->driver_data; } 116 117 static inline uhci_t * fun_to_uhci(ddf_fun_t *fun) 118 { return (uhci_t*)fun->driver_data; } 119 51 int uhci_init(uhci_t *instance, ddf_dev_t *device); 120 52 121 53 #endif -
uspace/drv/uhci-hcd/uhci_rh.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhci 29 29 * @{ 30 30 */ … … 33 33 */ 34 34 #include <assert.h> 35 #include <errno.h> 36 #include <str_error.h> 35 37 #include <stdio.h> 36 38 37 39 #include <usb/debug.h> 38 40 39 #include "port_status.h" 41 #include "uhci_rh.h" 42 #include "uhci_hc.h" 40 43 41 struct flag_name 42 { 43 uint16_t flag; 44 const char *name; 45 }; 46 47 static const struct flag_name flags[] = 48 { 49 { STATUS_SUSPEND, "suspended" }, 50 { STATUS_IN_RESET, "in reset" }, 51 { STATUS_LOW_SPEED, "low speed device" }, 52 { STATUS_ALWAYS_ONE, "always 1 bit" }, 53 { STATUS_RESUME, "resume" }, 54 { STATUS_LINE_D_MINUS, "line D- value" }, 55 { STATUS_LINE_D_PLUS, "line D+ value" }, 56 { STATUS_ENABLED_CHANGED, "enabled changed" }, 57 { STATUS_ENABLED, "enabled" }, 58 { STATUS_CONNECTED_CHANGED, "connected changed" }, 59 { STATUS_CONNECTED, "connected" } 60 }; 61 62 /** Prints portr status in a human readable way. 63 * 64 * @param[in] value Port value to print. 44 /** Root hub initialization 45 * @param[in] instance RH structure to initialize 46 * @param[in] fun DDF function representing UHCI root hub 47 * @param[in] reg_addr Address of root hub status and control registers. 48 * @param[in] reg_size Size of accessible address space. 65 49 * @return Error code. 66 50 */ 67 void print_port_status(port_status_t value) 51 int uhci_rh_init( 52 uhci_rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size) 68 53 { 69 unsigned i = 0; 70 for (;i < sizeof(flags)/sizeof(struct flag_name); ++i) { 71 usb_log_debug2("\t%s status: %s.\n", flags[i].name, 72 ((value & flags[i].flag) != 0) ? "YES" : "NO"); 54 assert(fun); 55 56 char *match_str = NULL; 57 int ret = asprintf(&match_str, "usb&uhci&root-hub"); 58 if (ret < 0) { 59 usb_log_error("Failed to create root hub match string.\n"); 60 return ENOMEM; 73 61 } 62 63 ret = ddf_fun_add_match_id(fun, match_str, 100); 64 if (ret != EOK) { 65 usb_log_error("Failed(%d) to add root hub match id: %s\n", 66 ret, str_error(ret)); 67 return ret; 68 } 69 70 hw_resource_list_t *resource_list = &instance->resource_list; 71 resource_list->count = 1; 72 resource_list->resources = &instance->io_regs; 73 assert(resource_list->resources); 74 instance->io_regs.type = IO_RANGE; 75 instance->io_regs.res.io_range.address = reg_addr; 76 instance->io_regs.res.io_range.size = reg_size; 77 instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN; 78 79 return EOK; 74 80 } 75 81 /** -
uspace/drv/uhci-hcd/uhci_rh.h
r45dd8bf r4f66cc7b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 33 33 * @brief UHCI driver 34 34 */ 35 #ifndef DRV_UHCI_ ROOT_HUB_H36 #define DRV_UHCI_ ROOT_HUB_H35 #ifndef DRV_UHCI_UHCI_RH_H 36 #define DRV_UHCI_UHCI_RH_H 37 37 38 38 #include <ddf/driver.h> 39 #include <ops/hw_res.h> 39 40 40 int setup_root_hub(ddf_fun_t **device, ddf_dev_t *hc); 41 typedef struct uhci_rh { 42 hw_resource_list_t resource_list; 43 hw_resource_t io_regs; 44 } uhci_rh_t; 45 46 int uhci_rh_init( 47 uhci_rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size); 41 48 42 49 #endif -
uspace/drv/uhci-hcd/uhci_struct/link_pointer.h
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ … … 46 46 #define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */ 47 47 48 #define LINK_POINTER_QH(address) \ 49 ((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG) 50 48 51 #endif 49 52 /** -
uspace/drv/uhci-hcd/uhci_struct/queue_head.h
r45dd8bf r4f66cc7b 1 2 1 /* 3 2 * Copyright (c) 2010 Jan Vesely … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 29 /** @addtogroup usb28 /** @addtogroup drv usbuhcihc 30 29 * @{ 31 30 */ … … 43 42 44 43 typedef struct queue_head { 45 volatile link_pointer_t next _queue;44 volatile link_pointer_t next; 46 45 volatile link_pointer_t element; 47 } __attribute__((packed)) queue_head_t; 48 49 static inline void queue_head_init(queue_head_t *instance) 46 } __attribute__((packed)) qh_t; 47 /*----------------------------------------------------------------------------*/ 48 /** Initialize queue head structure 49 * 50 * @param[in] instance qh_t structure to initialize. 51 * 52 * Sets both pointer to terminal NULL. 53 */ 54 static inline void qh_init(qh_t *instance) 50 55 { 51 56 assert(instance); 52 57 53 58 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG; 54 instance->next _queue= 0 | LINK_POINTER_TERMINATE_FLAG;59 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG; 55 60 } 56 57 static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa) 61 /*----------------------------------------------------------------------------*/ 62 /** Set queue head next pointer 63 * 64 * @param[in] instance qh_t structure to use. 65 * @param[in] pa Physical address of the next queue head. 66 * 67 * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal 68 * NULL. 69 */ 70 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa) 58 71 { 59 if (pa) { 60 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK) 72 /* Address is valid and not terminal */ 73 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 74 instance->next = (pa & LINK_POINTER_ADDRESS_MASK) 61 75 | LINK_POINTER_QUEUE_HEAD_FLAG; 76 } else { 77 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG; 62 78 } 63 79 } 64 65 static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa) 80 /*----------------------------------------------------------------------------*/ 81 /** Set queue head element pointer 82 * 83 * @param[in] instance qh_t structure to initialize. 84 * @param[in] pa Physical address of the next queue head. 85 * 86 * Adds proper flag. If the pointer is NULL or terminal, sets element 87 * to terminal NULL. 88 */ 89 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa) 66 90 { 67 if (pa) { 68 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK) 91 /* Address is valid and not terminal */ 92 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 93 instance->element = (pa & LINK_POINTER_ADDRESS_MASK) 69 94 | LINK_POINTER_QUEUE_HEAD_FLAG; 95 } else { 96 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG; 70 97 } 71 98 } 72 73 static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa) 99 /*----------------------------------------------------------------------------*/ 100 /** Set queue head element pointer 101 * 102 * @param[in] instance qh_t structure to initialize. 103 * @param[in] pa Physical address of the TD structure. 104 * 105 * Adds proper flag. If the pointer is NULL or terminal, sets element 106 * to terminal NULL. 107 */ 108 static inline void qh_set_element_td(qh_t *instance, uint32_t pa) 74 109 { 75 if (pa ) {110 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 76 111 instance->element = (pa & LINK_POINTER_ADDRESS_MASK); 112 } else { 113 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG; 77 114 } 78 115 } -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ … … 38 38 #include "utils/malloc32.h" 39 39 40 /** Initialize sTransfer Descriptor40 /** Initialize Transfer Descriptor 41 41 * 42 42 * @param[in] instance Memory place to initialize. … … 44 44 * @param[in] size Size of data source. 45 45 * @param[in] toggle Value of toggle bit. 46 * @param[in] iso True if TD is forIsochronous transfer.46 * @param[in] iso True if TD represents Isochronous transfer. 47 47 * @param[in] low_speed Target device's speed. 48 48 * @param[in] target Address and endpoint receiving the transfer. … … 51 51 * @param[in] next Net TD in transaction. 52 52 * @return Error code. 53 * 54 * Uses a mix of supplied and default values. 55 * Implicit values: 56 * - all TDs have vertical flag set (makes transfers to endpoints atomic) 57 * - in the error field only active it is set 58 * - if the packet uses PID_IN and is not isochronous SPD is set 59 * 60 * Dumps 8 bytes of buffer if PID_SETUP is used. 53 61 */ 54 62 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso, … … 88 96 } 89 97 90 usb_log_debug2("Created TD : %X:%X:%X:%X(%p).\n",91 instance ->next, instance->status, instance->device,98 usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n", 99 instance, instance->next, instance->status, instance->device, 92 100 instance->buffer_ptr, buffer); 101 td_print_status(instance); 93 102 if (pid == USB_PID_SETUP) { 94 103 usb_log_debug("SETUP BUFFER: %s\n", 95 104 usb_debug_str_buffer(buffer, 8, 8)); 96 105 } 97 106 } 98 107 /*----------------------------------------------------------------------------*/ 99 /** Convert sTD status into standard error code108 /** Convert TD status into standard error code 100 109 * 101 110 * @param[in] instance TD structure to use. … … 126 135 return EOK; 127 136 } 137 /*----------------------------------------------------------------------------*/ 138 /** Print values in status field (dw1) in a human readable way. 139 * 140 * @param[in] instance TD structure to use. 141 */ 142 void td_print_status(td_t *instance) 143 { 144 assert(instance); 145 const uint32_t s = instance->status; 146 usb_log_debug2("TD(%p) status(%#x):%s %d,%s%s%s%s%s%s%s%s%s%s%s %d.\n", 147 instance, instance->status, 148 (s & TD_STATUS_SPD_FLAG) ? " SPD," : "", 149 (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK, 150 (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "", 151 (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "", 152 (s & TD_STATUS_IOC_FLAG) ? " IOC," : "", 153 (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "", 154 (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "", 155 (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "", 156 (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "", 157 (s & TD_STATUS_ERROR_NAK) ? " NAK," : "", 158 (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "", 159 (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "", 160 (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "", 161 (s >> TD_STATUS_ACTLEN_POS) & TD_STATUS_ACTLEN_MASK 162 ); 163 } 128 164 /** 129 165 * @} -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
r45dd8bf r4f66cc7b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ … … 45 45 46 46 volatile uint32_t status; 47 48 47 #define TD_STATUS_RESERVED_MASK 0xc000f800 49 48 #define TD_STATUS_SPD_FLAG ( 1 << 29 ) 50 49 #define TD_STATUS_ERROR_COUNT_POS ( 27 ) 51 50 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 ) 52 #define TD_STATUS_ERROR_COUNT_DEFAULT 353 51 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 ) 54 52 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 ) 55 #define TD_STATUS_ COMPLETE_INTERRUPT_FLAG ( 1 << 24 )53 #define TD_STATUS_IOC_FLAG ( 1 << 24 ) 56 54 57 55 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23 ) … … 70 68 71 69 volatile uint32_t device; 72 73 70 #define TD_DEVICE_MAXLEN_POS 21 74 71 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff ) … … 85 82 86 83 /* there is 16 bytes of data available here, according to UHCI 87 * Design guide, according to linux kernel the hardware does not care 88 * we don't use it anyway84 * Design guide, according to linux kernel the hardware does not care, 85 * it just needs to be aligned, we don't use it anyway 89 86 */ 90 87 } __attribute__((packed)) td_t; 91 88 92 89 93 void td_init(td_t *instance, int error_count, size_t size, bool toggle, bool iso,94 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,95 td_t *next);90 void td_init(td_t *instance, int error_count, size_t size, bool toggle, 91 bool iso, bool low_speed, usb_target_t target, usb_packet_id pid, 92 void *buffer, td_t *next); 96 93 97 94 int td_status(td_t *instance); 98 95 96 void td_print_status(td_t *instance); 97 /*----------------------------------------------------------------------------*/ 98 /** Helper function for parsing actual size out of TD. 99 * 100 * @param[in] instance TD structure to use. 101 * @return Parsed actual size. 102 */ 99 103 static inline size_t td_act_size(td_t *instance) 100 104 { 101 105 assert(instance); 102 return 103 ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) 104 & TD_STATUS_ACTLEN_MASK; 106 const uint32_t s = instance->status; 107 return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK; 105 108 } 106 109 /*----------------------------------------------------------------------------*/ 110 /** Check whether less than max data were recieved and packet is marked as SPD. 111 * 112 * @param[in] instance TD structure to use. 113 * @return True if packet is short (less than max bytes and SPD set), false 114 * otherwise. 115 */ 107 116 static inline bool td_is_short(td_t *instance) 108 117 { … … 114 123 (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size; 115 124 } 116 125 /*----------------------------------------------------------------------------*/ 126 /** Helper function for parsing value of toggle bit. 127 * 128 * @param[in] instance TD structure to use. 129 * @return Toggle bit value. 130 */ 117 131 static inline int td_toggle(td_t *instance) 118 132 { 119 133 assert(instance); 120 return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0) 121 ? 1 : 0; 134 return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0; 122 135 } 123 136 /*----------------------------------------------------------------------------*/ 137 /** Helper function for parsing value of active bit 138 * 139 * @param[in] instance TD structure to use. 140 * @return Active bit value. 141 */ 124 142 static inline bool td_is_active(td_t *instance) 125 143 { … … 127 145 return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0; 128 146 } 147 /*----------------------------------------------------------------------------*/ 148 /** Helper function for setting IOC bit. 149 * 150 * @param[in] instance TD structure to use. 151 */ 152 static inline void td_set_ioc(td_t *instance) 153 { 154 assert(instance); 155 instance->status |= TD_STATUS_IOC_FLAG; 156 } 157 /*----------------------------------------------------------------------------*/ 129 158 #endif 130 159 /** -
uspace/drv/uhci-hcd/utils/device_keeper.c
r45dd8bf r4f66cc7b 27 27 */ 28 28 29 /** @addtogroup drvusbuhci 29 /** @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ … … 40 40 41 41 /*----------------------------------------------------------------------------*/ 42 /** Initialize sdevice keeper structure.42 /** Initialize device keeper structure. 43 43 * 44 44 * @param[in] instance Memory place to initialize. 45 * 46 * Set all values to false/0. 45 47 */ 46 48 void device_keeper_init(device_keeper_t *instance) … … 58 60 } 59 61 /*----------------------------------------------------------------------------*/ 60 /** Attempt sto obtain address 0, blocks.62 /** Attempt to obtain address 0, blocks. 61 63 * 62 64 * @param[in] instance Device keeper structure to use. … … 76 78 } 77 79 /*----------------------------------------------------------------------------*/ 78 /** Attempt sto obtain address 0, blocks.80 /** Attempt to obtain address 0, blocks. 79 81 * 80 82 * @param[in] instance Device keeper structure to use. … … 90 92 } 91 93 /*----------------------------------------------------------------------------*/ 92 /** Check s setupdata for signs of toggle reset.94 /** Check setup packet data for signs of toggle reset. 93 95 * 94 96 * @param[in] instance Device keeper structure to use. 95 97 * @param[in] target Device to receive setup packet. 96 98 * @param[in] data Setup packet data. 99 * 100 * Really ugly one. 97 101 */ 98 102 void device_keeper_reset_if_need( … … 105 109 || !instance->devices[target.address].occupied) { 106 110 fibril_mutex_unlock(&instance->guard); 111 usb_log_error("Invalid data when checking for toggle reset.\n"); 107 112 return; 108 113 } … … 130 135 } 131 136 /*----------------------------------------------------------------------------*/ 132 /** Get scurrent value of endpoint toggle.137 /** Get current value of endpoint toggle. 133 138 * 134 139 * @param[in] instance Device keeper structure to use. … … 144 149 || target.address >= USB_ADDRESS_COUNT || target.address < 0 145 150 || !instance->devices[target.address].occupied) { 151 usb_log_error("Invalid data when asking for toggle value.\n"); 146 152 ret = EINVAL; 147 153 } else { 148 ret = 149 (instance->devices[target.address].toggle_status 154 ret = (instance->devices[target.address].toggle_status 150 155 >> target.endpoint) & 1; 151 156 } … … 154 159 } 155 160 /*----------------------------------------------------------------------------*/ 156 /** Set scurrent value of endpoint toggle.161 /** Set current value of endpoint toggle. 157 162 * 158 163 * @param[in] instance Device keeper structure to use. 159 164 * @param[in] target Device and endpoint used. 160 * @param[in] toggle Current toggle value.165 * @param[in] toggle Toggle value. 161 166 * @return Error code. 162 167 */ … … 170 175 || target.address >= USB_ADDRESS_COUNT || target.address < 0 171 176 || !instance->devices[target.address].occupied) { 177 usb_log_error("Invalid data when setting toggle value.\n"); 172 178 ret = EINVAL; 173 179 } else { … … 183 189 } 184 190 /*----------------------------------------------------------------------------*/ 185 /** Get sa free USB address191 /** Get a free USB address 186 192 * 187 193 * @param[in] instance Device keeper structure to use. … … 216 222 } 217 223 /*----------------------------------------------------------------------------*/ 218 /** Bind sUSB address to devman handle.224 /** Bind USB address to devman handle. 219 225 * 220 226 * @param[in] instance Device keeper structure to use. … … 234 240 } 235 241 /*----------------------------------------------------------------------------*/ 236 /** Release sused USB address.242 /** Release used USB address. 237 243 * 238 244 * @param[in] instance Device keeper structure to use. … … 251 257 } 252 258 /*----------------------------------------------------------------------------*/ 253 /** Find sUSB address associated with the device259 /** Find USB address associated with the device 254 260 * 255 261 * @param[in] instance Device keeper structure to use. … … 274 280 } 275 281 /*----------------------------------------------------------------------------*/ 276 /** Get sspeed associated with the address282 /** Get speed associated with the address 277 283 * 278 284 * @param[in] instance Device keeper structure to use. -
uspace/drv/uhci-hcd/utils/device_keeper.h
r45dd8bf r4f66cc7b 27 27 */ 28 28 29 /** @addtogroup drvusbuhci 29 /** @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ -
uspace/drv/uhci-hcd/utils/malloc32.h
r45dd8bf r4f66cc7b 43 43 #define UHCI_REQUIRED_PAGE_SIZE 4096 44 44 45 /** Get physical address translation 46 * 47 * @param[in] addr Virtual address to translate 48 * @return Physical address if exists, NULL otherwise. 49 */ 45 50 static inline uintptr_t addr_to_phys(void *addr) 46 51 { … … 48 53 int ret = as_get_physical_mapping(addr, &result); 49 54 50 assert(ret == 0); 55 if (ret != EOK) 56 return 0; 51 57 return (result | ((uintptr_t)addr & 0xfff)); 52 58 } 53 59 /*----------------------------------------------------------------------------*/ 60 /** Physical mallocator simulator 61 * 62 * @param[in] size Size of the required memory space 63 * @return Address of the alligned and big enough memory place, NULL on failure. 64 */ 54 65 static inline void * malloc32(size_t size) 55 66 { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); } 56 57 static inline void * get_page() 67 /*----------------------------------------------------------------------------*/ 68 /** Physical mallocator simulator 69 * 70 * @param[in] addr Address of the place allocated by malloc32 71 */ 72 static inline void free32(void *addr) 73 { if (addr) free(addr); } 74 /*----------------------------------------------------------------------------*/ 75 /** Create 4KB page mapping 76 * 77 * @return Address of the mapped page, NULL on failure. 78 */ 79 static inline void * get_page(void) 58 80 { 59 81 void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE); 60 82 assert(free_address); 61 83 if (free_address == 0) 62 return 0;84 return NULL; 63 85 void* ret = 64 86 as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE, 65 87 AS_AREA_READ | AS_AREA_WRITE); 66 88 if (ret != free_address) 67 return 0;89 return NULL; 68 90 return ret; 69 91 } 70 71 static inline void free32(void *addr)72 { if (addr) free(addr); }73 92 74 93 #endif -
uspace/drv/uhci-rhd/Makefile
r45dd8bf r4f66cc7b 35 35 main.c \ 36 36 port.c \ 37 port_status.c \38 37 root_hub.c 39 38 -
uspace/drv/uhci-rhd/main.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver32 * @brief UHCI root hub initialization routines 33 33 */ 34 34 #include <ddf/driver.h> … … 40 40 #include <usb/debug.h> 41 41 42 43 44 42 #include "root_hub.h" 45 43 … … 47 45 static int hc_get_my_registers(ddf_dev_t *dev, 48 46 uintptr_t *io_reg_address, size_t *io_reg_size); 47 #if 0 49 48 /*----------------------------------------------------------------------------*/ 50 49 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) … … 67 66 .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface, 68 67 }; 68 #endif 69 69 /*----------------------------------------------------------------------------*/ 70 /** Initialize sa new ddf driver instance of UHCI root hub.70 /** Initialize a new ddf driver instance of UHCI root hub. 71 71 * 72 72 * @param[in] device DDF instance of the device to initialize. … … 81 81 82 82 //device->ops = &uhci_rh_ops; 83 (void) uhci_rh_ops;84 85 uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));86 if (!rh) {87 usb_log_error("Failed to allocate memory for driver instance.\n");88 return ENOMEM;89 }90 91 83 uintptr_t io_regs = 0; 92 84 size_t io_size = 0; 93 85 94 86 int ret = hc_get_my_registers(device, &io_regs, &io_size); 95 assert(ret == EOK); 87 if (ret != EOK) { 88 usb_log_error("Failed(%d) to get registers from parent hc.", 89 ret); 90 } 91 usb_log_info("I/O regs at %#X (size %zu).\n", io_regs, io_size); 96 92 97 /* TODO: verify values from hc */ 98 usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size); 93 uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t)); 94 if (!rh) { 95 usb_log_error("Failed to allocate driver instance.\n"); 96 return ENOMEM; 97 } 98 99 99 ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device); 100 100 if (ret != EOK) { … … 119 119 }; 120 120 /*----------------------------------------------------------------------------*/ 121 /** Initialize sglobal driver structures (NONE).121 /** Initialize global driver structures (NONE). 122 122 * 123 123 * @param[in] argc Nmber of arguments in argv vector (ignored). -
uspace/drv/uhci-rhd/port.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 33 */ 32 * @brief UHCI root hub port routines 33 */ 34 #include <libarch/ddi.h> /* pio_read and pio_write */ 34 35 #include <errno.h> 35 36 #include <str_error.h> … … 37 38 38 39 #include <usb/usb.h> /* usb_address_t */ 39 #include <usb/usbdevice.h>40 40 #include <usb/hub.h> 41 #include <usb/request.h>42 41 #include <usb/debug.h> 43 #include <usb/recognise.h>44 42 45 43 #include "port.h" 46 #include "port_status.h"47 44 48 45 static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed); … … 51 48 static int uhci_port_check(void *port); 52 49 static int uhci_port_reset_enable(int portno, void *arg); 53 /*----------------------------------------------------------------------------*/ 54 /** Initializes UHCI root hub port instance. 50 static void uhci_port_print_status( 51 uhci_port_t *port, const port_status_t value); 52 53 /** Register reading helper function. 54 * 55 * @param[in] port Structure to use. 56 * @return Error code. (Always EOK) 57 */ 58 static inline port_status_t uhci_port_read_status(uhci_port_t *port) 59 { 60 assert(port); 61 return pio_read_16(port->address); 62 } 63 /*----------------------------------------------------------------------------*/ 64 /** Register writing helper function. 65 * 66 * @param[in] port Structure to use. 67 * @param[in] value New register value. 68 * @return Error code. (Always EOK) 69 */ 70 static inline void uhci_port_write_status( 71 uhci_port_t *port, port_status_t value) 72 { 73 assert(port); 74 pio_write_16(port->address, value); 75 } 76 77 /*----------------------------------------------------------------------------*/ 78 /** Initialize UHCI root hub port instance. 55 79 * 56 80 * @param[in] port Memory structure to use. … … 61 85 * @return Error code. 62 86 * 63 * Starts the polling fibril.87 * Creates and starts the polling fibril. 64 88 */ 65 89 int uhci_port_init(uhci_port_t *port, … … 67 91 { 68 92 assert(port); 93 asprintf(&port->id_string, "Port (%p - %d)", port, number); 94 if (port->id_string == NULL) { 95 return ENOMEM; 96 } 69 97 70 98 port->address = address; … … 83 111 port->checker = fibril_create(uhci_port_check, port); 84 112 if (port->checker == 0) { 85 usb_log_error(" Port(%p - %d): failed to launch root hubfibril.",86 port-> address, port->number);113 usb_log_error("%s: failed to create polling fibril.", 114 port->id_string); 87 115 return ENOMEM; 88 116 } 89 117 90 118 fibril_add_ready(port->checker); 91 usb_log_debug(" Port(%p - %d): Added fibril. %x\n",92 port-> address, port->number, port->checker);93 return EOK; 94 } 95 /*----------------------------------------------------------------------------*/ 96 /** FinishesUHCI root hub port instance.119 usb_log_debug("%s: Started polling fibril(%x).\n", 120 port->id_string, port->checker); 121 return EOK; 122 } 123 /*----------------------------------------------------------------------------*/ 124 /** Cleanup UHCI root hub port instance. 97 125 * 98 126 * @param[in] port Memory structure to use. … … 102 130 void uhci_port_fini(uhci_port_t *port) 103 131 { 132 assert(port); 133 free(port->id_string); 104 134 /* TODO: Kill fibril here */ 105 135 return; … … 108 138 /** Periodically checks port status and reports new devices. 109 139 * 110 * @param[in] port Memorystructure to use.140 * @param[in] port Port structure to use. 111 141 * @return Error code. 112 142 */ … … 116 146 assert(instance); 117 147 118 /* Iteration count, for debug purposes only */119 unsigned count = 0;120 121 148 while (1) { 122 149 async_usleep(instance->wait_period_usec); 123 150 124 /* read register value */ 125 port_status_t port_status = port_status_read(instance->address); 126 127 /* debug print mutex */ 128 static fibril_mutex_t dbg_mtx = 129 FIBRIL_MUTEX_INITIALIZER(dbg_mtx); 130 fibril_mutex_lock(&dbg_mtx); 131 usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n", 132 instance->address, instance->number, port_status, count++); 133 // print_port_status(port_status); 134 fibril_mutex_unlock(&dbg_mtx); 151 /* Read register value */ 152 port_status_t port_status = uhci_port_read_status(instance); 153 154 /* Print the value if it's interesting */ 155 if (port_status & ~STATUS_ALWAYS_ONE) 156 uhci_port_print_status(instance, port_status); 135 157 136 158 if ((port_status & STATUS_CONNECTED_CHANGED) == 0) 137 159 continue; 138 160 139 usb_log_debug(" Port(%p - %d): Connected change detected: %x.\n",140 instance-> address, instance->number, port_status);161 usb_log_debug("%s: Connected change detected: %x.\n", 162 instance->id_string, port_status); 141 163 142 164 int rc = 143 165 usb_hc_connection_open(&instance->hc_connection); 144 166 if (rc != EOK) { 145 usb_log_error(" Port(%p - %d): Failed to connect to HC.",146 instance-> address, instance->number);167 usb_log_error("%s: Failed to connect to HC.", 168 instance->id_string); 147 169 continue; 148 170 } … … 150 172 /* Remove any old device */ 151 173 if (instance->attached_device) { 152 usb_log_debug2(" Port(%p - %d): Removing device.\n",153 instance-> address, instance->number);174 usb_log_debug2("%s: Removing device.\n", 175 instance->id_string); 154 176 uhci_port_remove_device(instance); 155 177 } … … 163 185 } else { 164 186 /* Write one to WC bits, to ack changes */ 165 port_status_write(instance->address, port_status);166 usb_log_debug(" Port(%p - %d): Change statusACK.\n",167 instance-> address, instance->number);187 uhci_port_write_status(instance, port_status); 188 usb_log_debug("%s: status change ACK.\n", 189 instance->id_string); 168 190 } 169 191 170 192 rc = usb_hc_connection_close(&instance->hc_connection); 171 193 if (rc != EOK) { 172 usb_log_error(" Port(%p - %d): Failed to disconnect.",173 instance-> address, instance->number);194 usb_log_error("%s: Failed to disconnect.", 195 instance->id_string); 174 196 } 175 197 } … … 182 204 * @param arg Pointer to uhci_port_t of port with the new device. 183 205 * @return Error code. 206 * 207 * Resets and enables the ub port. 184 208 */ 185 209 int uhci_port_reset_enable(int portno, void *arg) … … 187 211 uhci_port_t *port = (uhci_port_t *) arg; 188 212 189 usb_log_debug2("Port(%p - %d): new_device_enable_port.\n", 190 port->address, port->number); 213 usb_log_debug2("%s: new_device_enable_port.\n", port->id_string); 191 214 192 215 /* … … 196 219 async_usleep(100000); 197 220 198 199 /* The hub maintains the reset signal to that port for 10 ms 200 * (See Section 11.5.1.5) 221 /* 222 * Resets from root ports should be nominally 50ms 201 223 */ 202 224 { 203 usb_log_debug("Port(%p - %d): Reset Signal start.\n", 204 port->address, port->number); 205 port_status_t port_status = 206 port_status_read(port->address); 225 usb_log_debug("%s: Reset Signal start.\n", port->id_string); 226 port_status_t port_status = uhci_port_read_status(port); 207 227 port_status |= STATUS_IN_RESET; 208 port_status_write(port->address, port_status);209 async_usleep( 10000);210 port_status = port_status_read(port->address);228 uhci_port_write_status(port, port_status); 229 async_usleep(50000); 230 port_status = uhci_port_read_status(port); 211 231 port_status &= ~STATUS_IN_RESET; 212 port_status_write(port->address, port_status); 213 usb_log_debug("Port(%p - %d): Reset Signal stop.\n", 214 port->address, port->number); 215 } 232 uhci_port_write_status(port, port_status); 233 usb_log_debug("%s: Reset Signal stop.\n", port->id_string); 234 } 235 236 /* the reset recovery time 10ms */ 237 async_usleep(10000); 216 238 217 239 /* Enable the port. */ 218 240 uhci_port_set_enabled(port, true); 219 return EOK; 220 } 221 /*----------------------------------------------------------------------------*/ 222 /** Initializes and reports connected device. 223 * 224 * @param[in] port Memory structure to use. 241 242 return EOK; 243 } 244 /*----------------------------------------------------------------------------*/ 245 /** Initialize and report connected device. 246 * 247 * @param[in] port Port structure to use. 225 248 * @param[in] speed Detected speed. 226 249 * @return Error code. … … 233 256 assert(usb_hc_connection_is_opened(&port->hc_connection)); 234 257 235 usb_log_info("Port(%p-%d): Detected new device.\n", 236 port->address, port->number); 258 usb_log_info("%s: Detected new device.\n", port->id_string); 237 259 238 260 usb_address_t dev_addr; … … 242 264 243 265 if (rc != EOK) { 244 usb_log_error(" Port(%p-%d): Failed(%d) to add device: %s.\n",245 port-> address, port->number, rc, str_error(rc));266 usb_log_error("%s: Failed(%d) to add device: %s.\n", 267 port->id_string, rc, str_error(rc)); 246 268 uhci_port_set_enabled(port, false); 247 269 return rc; 248 270 } 249 271 250 usb_log_info(" Port(%p-%d): New device has address %d (handle %zu).\n",251 port-> address, port->number, dev_addr, port->attached_device);252 253 return EOK; 254 } 255 /*----------------------------------------------------------------------------*/ 256 /** Remove sdevice.272 usb_log_info("%s: New device has address %d (handle %zu).\n", 273 port->id_string, dev_addr, port->attached_device); 274 275 return EOK; 276 } 277 /*----------------------------------------------------------------------------*/ 278 /** Remove device. 257 279 * 258 280 * @param[in] port Memory structure to use. 259 281 * @return Error code. 260 282 * 261 * Does not work DDF does not support device removal. 283 * Does not work, DDF does not support device removal. 284 * Does not even free used USB address (it would be dangerous if tis driver 285 * is still running). 262 286 */ 263 287 int uhci_port_remove_device(uhci_port_t *port) 264 288 { 265 usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n", 266 port->address, port->number, (unsigned int)port->attached_device); 267 return EOK; 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** Enables and disables port. 271 * 272 * @param[in] port Memory structure to use. 289 usb_log_error("%s: Don't know how to remove device %d.\n", 290 port->id_string, (unsigned int)port->attached_device); 291 return EOK; 292 } 293 /*----------------------------------------------------------------------------*/ 294 /** Enable or disable root hub port. 295 * 296 * @param[in] port Port structure to use. 297 * @param[in] enabled Port status to set. 273 298 * @return Error code. (Always EOK) 274 299 */ … … 278 303 279 304 /* Read register value */ 280 port_status_t port_status = port_status_read(port->address);305 port_status_t port_status = uhci_port_read_status(port); 281 306 282 307 /* Set enabled bit */ … … 288 313 289 314 /* Write new value. */ 290 port_status_write(port->address, port_status); 291 292 usb_log_info("Port(%p-%d): %sabled port.\n", 293 port->address, port->number, enabled ? "En" : "Dis"); 294 return EOK; 295 } 296 /*----------------------------------------------------------------------------*/ 315 uhci_port_write_status(port, port_status); 316 317 usb_log_info("%s: %sabled port.\n", 318 port->id_string, enabled ? "En" : "Dis"); 319 return EOK; 320 } 321 /*----------------------------------------------------------------------------*/ 322 /** Print the port status value in a human friendly way 323 * 324 * @param[in] port Port structure to use. 325 * @param[in] value Port register value to print. 326 * @return Error code. (Always EOK) 327 */ 328 void uhci_port_print_status(uhci_port_t *port, const port_status_t value) 329 { 330 assert(port); 331 usb_log_debug2("%s Port status(%#x):%s%s%s%s%s%s%s%s%s%s%s.\n", 332 port->id_string, value, 333 (value & STATUS_SUSPEND) ? " SUSPENDED," : "", 334 (value & STATUS_RESUME) ? " IN RESUME," : "", 335 (value & STATUS_IN_RESET) ? " IN RESET," : "", 336 (value & STATUS_LINE_D_MINUS) ? " VD-," : "", 337 (value & STATUS_LINE_D_PLUS) ? " VD+," : "", 338 (value & STATUS_LOW_SPEED) ? " LOWSPEED," : "", 339 (value & STATUS_ENABLED_CHANGED) ? " ENABLED-CHANGE," : "", 340 (value & STATUS_ENABLED) ? " ENABLED," : "", 341 (value & STATUS_CONNECTED_CHANGED) ? " CONNECTED-CHANGE," : "", 342 (value & STATUS_CONNECTED) ? " CONNECTED," : "", 343 (value & STATUS_ALWAYS_ONE) ? " ALWAYS ONE" : " ERROR: NO ALWAYS ONE" 344 ); 345 } 297 346 /** 298 347 * @} -
uspace/drv/uhci-rhd/port.h
r45dd8bf r4f66cc7b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI port driver32 * @brief UHCI root hub port routines 33 33 */ 34 34 #ifndef DRV_UHCI_PORT_H 35 35 #define DRV_UHCI_PORT_H 36 36 37 #include <assert.h> 37 #include <stdint.h> 38 #include <fibril.h> 38 39 #include <ddf/driver.h> 39 #include <stdint.h> 40 #include <usb/usbdevice.h> 40 #include <usb/usbdevice.h> /* usb_hc_connection_t */ 41 41 42 #include "port_status.h" 42 typedef uint16_t port_status_t; 43 #define STATUS_CONNECTED (1 << 0) 44 #define STATUS_CONNECTED_CHANGED (1 << 1) 45 #define STATUS_ENABLED (1 << 2) 46 #define STATUS_ENABLED_CHANGED (1 << 3) 47 #define STATUS_LINE_D_PLUS (1 << 4) 48 #define STATUS_LINE_D_MINUS (1 << 5) 49 #define STATUS_RESUME (1 << 6) 50 #define STATUS_ALWAYS_ONE (1 << 7) 51 52 #define STATUS_LOW_SPEED (1 << 8) 53 #define STATUS_IN_RESET (1 << 9) 54 #define STATUS_SUSPEND (1 << 12) 43 55 44 56 typedef struct uhci_port 45 57 { 58 char *id_string; 46 59 port_status_t *address; 47 60 unsigned number; … … 58 71 59 72 void uhci_port_fini(uhci_port_t *port); 73 60 74 #endif 61 75 /** -
uspace/drv/uhci-rhd/root_hub.c
r45dd8bf r4f66cc7b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver32 * @brief UHCI root hub driver 33 33 */ 34 34 #include <errno.h> 35 #include <stdint.h>36 35 #include <ddi.h> 37 #include <devman.h>38 36 #include <usb/debug.h> 39 37 40 38 #include "root_hub.h" 41 39 42 /** Initialize sUHCI root hub instance.40 /** Initialize UHCI root hub instance. 43 41 * 44 42 * @param[in] instance Driver memory structure to use. 45 43 * @param[in] addr Address of I/O registers. 46 44 * @param[in] size Size of available I/O space. 47 * @param[in] rh Pointer to ddf instance fothe root hub driver.45 * @param[in] rh Pointer to ddf instance of the root hub driver. 48 46 * @return Error code. 49 47 */ … … 61 59 if (ret < 0) { 62 60 usb_log_error( 63 "Failed to gain access to port registers at %p\n", regs); 61 "Failed(%d) to gain access to port registers at %p\n", 62 ret, regs); 64 63 return ret; 65 64 } 66 65 67 /* add fibrils for periodic port checks */66 /* Initialize root hub ports */ 68 67 unsigned i = 0; 69 68 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { … … 82 81 } 83 82 /*----------------------------------------------------------------------------*/ 84 /** FinishesUHCI root hub instance.83 /** Cleanup UHCI root hub instance. 85 84 * 86 * @param[in] instance Driver memorystructure to use.85 * @param[in] instance Root hub structure to use. 87 86 * @return Error code. 88 87 */ -
uspace/drv/uhci-rhd/root_hub.h
r45dd8bf r4f66cc7b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ … … 35 35 #define DRV_UHCI_ROOT_HUB_H 36 36 37 #include <fibril.h>38 37 #include <ddf/driver.h> 39 38 -
uspace/drv/usbhid/hiddev.c
r45dd8bf r4f66cc7b 391 391 return rc; 392 392 } 393 rc = usb_endpoint_pipe_probe_default_control(&hid_dev->ctrl_pipe); 394 if (rc != EOK) { 395 usb_log_error("Probing default control pipe failed: %s.\n", 396 str_error(rc)); 397 return rc; 398 } 393 399 394 400 /* -
uspace/drv/usbhid/kbddev.c
r45dd8bf r4f66cc7b 459 459 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 460 460 usbhid_kbd_repeat_start(kbd_dev, key); 461 } else { size_t461 } else { 462 462 // found, nothing happens 463 463 } -
uspace/drv/usbhub/usbhub.c
r45dd8bf r4f66cc7b 72 72 int usb_hub_control_loop(void * hub_info_param){ 73 73 usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param; 74 while(true){ 75 usb_hub_check_hub_changes(hub_info); 74 int errorCode = EOK; 75 76 while(errorCode == EOK){ 77 errorCode = usb_hub_check_hub_changes(hub_info); 76 78 async_usleep(1000 * 1000 );/// \TODO proper number once 77 79 } 80 dprintf(USB_LOG_LEVEL_ERROR, 81 "something in ctrl loop went wrong, errno %d",errorCode); 78 82 return 0; 79 83 } … … 118 122 dprintf(USB_LOG_LEVEL_ERROR, 119 123 "could not initialize connection to device endpoint, errno %d",opResult); 120 } 121 return opResult; 124 return opResult; 125 } 126 127 opResult = usb_endpoint_pipe_probe_default_control(&hub->endpoints.control); 128 if (opResult != EOK) { 129 dprintf(USB_LOG_LEVEL_ERROR, "failed probing endpoint 0, %d", opResult); 130 return opResult; 131 } 132 133 return EOK; 122 134 } 123 135 … … 372 384 * @param target 373 385 */ 374 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port) { 386 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port, 387 bool isLowSpeed) { 375 388 usb_device_request_setup_packet_t request; 376 389 int opResult; … … 378 391 assert(hub->endpoints.control.hc_phone); 379 392 //get default address 380 //opResult = usb_drv_reserve_default_address(hc);381 opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);393 usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL; 394 opResult = usb_hc_reserve_default_address(&hub->connection, speed); 382 395 383 396 if (opResult != EOK) { … … 430 443 &new_device_pipe, 431 444 &new_device_connection); 445 usb_endpoint_pipe_probe_default_control(&new_device_pipe); 432 446 /// \TODO get highspeed info 433 447 usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL; … … 437 451 usb_address_t new_device_address = usb_hc_request_address( 438 452 &hub->connection, 439 speed /// \TODO fullspeed??453 speed 440 454 ); 441 455 if (new_device_address < 0) { … … 501 515 static void usb_hub_removed_device( 502 516 usb_hub_info_t * hub,uint16_t port) { 503 //usb_device_request_setup_packet_t request; 504 int opResult; 505 517 506 518 /** \TODO remove device from device manager - not yet implemented in 507 519 * devide manager … … 510 522 //close address 511 523 if(hub->attached_devs[port].address!=0){ 512 / /opResult = usb_drv_release_address(hc,hub->attached_devs[port].address);524 /*uncomment this code to use it when DDF allows device removal 513 525 opResult = usb_hc_unregister_device( 514 526 &hub->connection, hub->attached_devs[port].address); … … 519 531 hub->attached_devs[port].address = 0; 520 532 hub->attached_devs[port].handle = 0; 533 */ 521 534 }else{ 522 535 dprintf(USB_LOG_LEVEL_WARNING, "this is strange, disconnected device had no address"); … … 588 601 if (usb_port_dev_connected(&status)) { 589 602 dprintf(USB_LOG_LEVEL_INFO, "some connection changed"); 590 usb_hub_init_add_device(hub, port );603 usb_hub_init_add_device(hub, port, usb_port_low_speed(&status)); 591 604 } else { 592 605 usb_hub_removed_device(hub, port); … … 626 639 /** 627 640 * Check changes on particular hub 628 * @param hub_info_param 629 */ 630 void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){ 641 * @param hub_info_param pointer to usb_hub_info_t structure 642 * @return error code if there is problem when initializing communication with 643 * hub, EOK otherwise 644 */ 645 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info){ 631 646 int opResult; 632 647 opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change); … … 634 649 dprintf(USB_LOG_LEVEL_ERROR, 635 650 "could not initialize communication for hub; %d", opResult); 636 return ;651 return opResult; 637 652 } 638 653 … … 656 671 dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub"); 657 672 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change); 658 return ;673 return opResult; 659 674 } 660 675 unsigned int port; … … 664 679 opResult); 665 680 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change); 666 return ;681 return opResult; 667 682 } 668 683 opResult = usb_hc_connection_open(&hub_info->connection); … … 672 687 usb_endpoint_pipe_end_session(&hub_info->endpoints.control); 673 688 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change); 674 return ;689 return opResult; 675 690 } 676 691 … … 688 703 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change); 689 704 free(change_bitmap); 705 return EOK; 690 706 } 691 707 -
uspace/drv/usbhub/usbhub.h
r45dd8bf r4f66cc7b 87 87 88 88 /** 89 * check changes on specified hub89 * Check changes on specified hub 90 90 * @param hub_info_param pointer to usb_hub_info_t structure 91 * @return error code if there is problem when initializing communication with 92 * hub, EOK otherwise 91 93 */ 92 voidusb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);94 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param); 93 95 94 96 -
uspace/drv/usbmid/usbmid.c
r45dd8bf r4f66cc7b 116 116 return NULL; 117 117 } 118 rc = usb_endpoint_pipe_probe_default_control(&mid->ctrl_pipe); 119 if (rc != EOK) { 120 usb_log_error("Probing default control pipe failed: %s.\n", 121 str_error(rc)); 122 free(mid); 123 return NULL; 124 } 118 125 119 126 mid->dev = dev; -
uspace/drv/usbmouse/init.c
r45dd8bf r4f66cc7b 42 42 43 43 /** Mouse polling endpoint description for boot protocol subclass. */ 44 staticusb_endpoint_description_t poll_endpoint_description = {44 usb_endpoint_description_t poll_endpoint_description = { 45 45 .transfer_type = USB_TRANSFER_INTERRUPT, 46 46 .direction = USB_DIRECTION_IN, … … 50 50 .flags = 0 51 51 }; 52 53 /** Initialize poll pipe.54 *55 * Expects that session is already started on control pipe zero.56 *57 * @param mouse Mouse device.58 * @param my_interface Interface number.59 * @return Error code.60 */61 static int intialize_poll_pipe(usb_mouse_t *mouse, int my_interface)62 {63 assert(usb_endpoint_pipe_is_session_started(&mouse->ctrl_pipe));64 65 int rc;66 67 void *config_descriptor;68 size_t config_descriptor_size;69 70 rc = usb_request_get_full_configuration_descriptor_alloc(71 &mouse->ctrl_pipe, 0, &config_descriptor, &config_descriptor_size);72 if (rc != EOK) {73 return rc;74 }75 76 usb_endpoint_mapping_t endpoint_mapping[1] = {77 {78 .pipe = &mouse->poll_pipe,79 .description = &poll_endpoint_description,80 .interface_no = my_interface81 }82 };83 84 rc = usb_endpoint_pipe_initialize_from_configuration(endpoint_mapping,85 1, config_descriptor, config_descriptor_size, &mouse->wire);86 if (rc != EOK) {87 return rc;88 }89 90 if (!endpoint_mapping[0].present) {91 return ENOENT;92 }93 94 mouse->poll_interval_us = 1000 * endpoint_mapping[0].descriptor->poll_interval;95 96 usb_log_debug("prepared polling endpoint %d (interval %zu).\n",97 mouse->poll_pipe.endpoint_no, mouse->poll_interval_us);98 99 return EOK;100 }101 52 102 53 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); … … 143 94 * @return Error code. 144 95 */ 145 int usb_mouse_create( ddf_dev_t *dev)96 int usb_mouse_create(usb_device_t *dev) 146 97 { 147 98 usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t)); … … 149 100 return ENOMEM; 150 101 } 151 mouse->dev ice= dev;102 mouse->dev = dev; 152 103 mouse->console_phone = -1; 153 104 154 105 int rc; 155 106 156 /* Initialize the backing connection. */157 rc = usb_device_connection_initialize_from_device(&mouse->wire, dev);158 if (rc != EOK) {159 goto leave;160 }161 162 /* Initialize the default control pipe. */163 rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe,164 &mouse->wire);165 if (rc != EOK) {166 goto leave;167 }168 169 rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe);170 if (rc != EOK) {171 goto leave;172 }173 174 rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev));175 176 /* We can ignore error here. */177 usb_endpoint_pipe_end_session(&mouse->ctrl_pipe);178 179 if (rc != EOK) {180 goto leave;181 }182 183 107 /* Create DDF function. */ 184 mouse->mouse_fun = ddf_fun_create(dev , fun_exposed, "mouse");108 mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse"); 185 109 if (mouse->mouse_fun == NULL) { 186 110 rc = ENOMEM; -
uspace/drv/usbmouse/main.c
r45dd8bf r4f66cc7b 44 44 * @return Error code. 45 45 */ 46 static int usbmouse_add_device( ddf_dev_t *dev)46 static int usbmouse_add_device(usb_device_t *dev) 47 47 { 48 48 int rc = usb_mouse_create(dev); … … 53 53 } 54 54 55 fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev); 56 if (poll_fibril == 0) { 57 usb_log_error("Failed to initialize polling fibril.\n"); 58 /* FIXME: free allocated resources. */ 59 return ENOMEM; 55 usb_log_debug("Polling pipe at endpoint %d.\n", dev->pipes[0].pipe->endpoint_no); 56 57 rc = usb_device_auto_poll(dev, 0, 58 usb_mouse_polling_callback, dev->pipes[0].pipe->max_packet_size, 59 usb_mouse_polling_ended_callback, dev->driver_data); 60 61 if (rc != EOK) { 62 usb_log_error("Failed to start polling fibril: %s.\n", 63 str_error(rc)); 64 return rc; 60 65 } 61 66 62 fibril_add_ready(poll_fibril);63 64 67 usb_log_info("controlling new mouse (handle %llu).\n", 65 dev-> handle);68 dev->ddf_dev->handle); 66 69 67 70 return EOK; … … 69 72 70 73 /** USB mouse driver ops. */ 71 static driver_ops_t mouse_driver_ops = {74 static usb_driver_ops_t mouse_driver_ops = { 72 75 .add_device = usbmouse_add_device, 73 76 }; 74 77 78 static usb_endpoint_description_t *endpoints[] = { 79 &poll_endpoint_description, 80 NULL 81 }; 82 75 83 /** USB mouse driver. */ 76 static driver_t mouse_driver = {84 static usb_driver_t mouse_driver = { 77 85 .name = NAME, 78 .driver_ops = &mouse_driver_ops 86 .ops = &mouse_driver_ops, 87 .endpoints = endpoints 79 88 }; 80 89 … … 83 92 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 84 93 85 return ddf_driver_main(&mouse_driver);94 return usb_driver_main(&mouse_driver); 86 95 } 87 96 -
uspace/drv/usbmouse/mouse.c
r45dd8bf r4f66cc7b 40 40 #include <ipc/mouse.h> 41 41 42 /** Fibril function for polling the mouse device.42 /** Mouse polling callback. 43 43 * 44 * This function shall not terminate unless the device breaks and fails45 * to send data (e.g. stalls on data request).46 * 47 * @param arg ddf_dev_t type representing the mouse device.48 * @return EOK Always.44 * @param dev Device that is being polled. 45 * @param buffer Data buffer. 46 * @param buffer_size Buffer size in bytes. 47 * @param arg Custom argument - points to usb_mouse_t. 48 * @return Always true. 49 49 */ 50 int usb_mouse_polling_fibril(void *arg) 50 bool usb_mouse_polling_callback(usb_device_t *dev, 51 uint8_t *buffer, size_t buffer_size, void *arg) 51 52 { 52 assert(arg != NULL); 53 ddf_dev_t *dev = (ddf_dev_t *) arg; 54 usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data; 53 usb_mouse_t *mouse = (usb_mouse_t *) arg; 55 54 56 assert(mouse); 55 usb_log_debug2("got buffer: %s.\n", 56 usb_debug_str_buffer(buffer, buffer_size, 0)); 57 57 58 size_t buffer_size = mouse->poll_pipe.max_packet_size; 58 uint8_t butt = buffer[0]; 59 char str_buttons[4] = { 60 butt & 1 ? '#' : '.', 61 butt & 2 ? '#' : '.', 62 butt & 4 ? '#' : '.', 63 0 64 }; 59 65 60 if (buffer_size < 4) { 61 usb_log_error("Weird mouse, results will be skewed.\n"); 62 buffer_size = 4; 66 int shift_x = ((int) buffer[1]) - 127; 67 int shift_y = ((int) buffer[2]) - 127; 68 int wheel = ((int) buffer[3]) - 127; 69 70 if (buffer[1] == 0) { 71 shift_x = 0; 72 } 73 if (buffer[2] == 0) { 74 shift_y = 0; 75 } 76 if (buffer[3] == 0) { 77 wheel = 0; 63 78 } 64 79 65 uint8_t *buffer = malloc(buffer_size); 66 if (buffer == NULL) { 67 usb_log_error("Out of memory, poll fibril aborted.\n"); 68 return ENOMEM; 80 if (mouse->console_phone >= 0) { 81 if ((shift_x != 0) || (shift_y != 0)) { 82 /* FIXME: guessed for QEMU */ 83 async_req_2_0(mouse->console_phone, 84 MEVENT_MOVE, 85 - shift_x / 10, - shift_y / 10); 86 } 87 if (butt) { 88 /* FIXME: proper button clicking. */ 89 async_req_2_0(mouse->console_phone, 90 MEVENT_BUTTON, 1, 1); 91 async_req_2_0(mouse->console_phone, 92 MEVENT_BUTTON, 1, 0); 93 } 69 94 } 70 95 71 while (true) {72 async_usleep(mouse->poll_interval_us);96 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n", 97 str_buttons, shift_x, shift_y, wheel); 73 98 74 size_t actual_size;75 int rc;99 /* Guess. */ 100 async_usleep(1000); 76 101 77 /* 78 * Error checking note: 79 * - failure when starting a session is considered 80 * temporary (e.g. out of phones, next try might succeed) 81 * - failure of transfer considered fatal (probably the 82 * device was unplugged) 83 * - session closing not checked (shall not fail anyway) 84 */ 102 return true; 103 } 85 104 86 rc = usb_endpoint_pipe_start_session(&mouse->poll_pipe); 87 if (rc != EOK) { 88 usb_log_warning("Failed to start session, will try again: %s.\n", 89 str_error(rc)); 90 continue; 91 } 105 /** Callback when polling is terminated. 106 * 107 * @param dev Device where the polling terminated. 108 * @param recurring_errors Whether the polling was terminated due to 109 * recurring errors. 110 * @param arg Custom argument - points to usb_mouse_t. 111 */ 112 void usb_mouse_polling_ended_callback(usb_device_t *dev, 113 bool recurring_errors, void *arg) 114 { 115 usb_mouse_t *mouse = (usb_mouse_t *) arg; 92 116 93 rc = usb_endpoint_pipe_read(&mouse->poll_pipe,94 buffer, buffer_size, &actual_size);95 96 usb_endpoint_pipe_end_session(&mouse->poll_pipe);97 98 if (rc != EOK) {99 usb_log_error("Failed reading mouse input: %s.\n",100 str_error(rc));101 break;102 }103 104 usb_log_debug2("got buffer: %s.\n",105 usb_debug_str_buffer(buffer, buffer_size, 0));106 107 uint8_t butt = buffer[0];108 char str_buttons[4] = {109 butt & 1 ? '#' : '.',110 butt & 2 ? '#' : '.',111 butt & 4 ? '#' : '.',112 0113 };114 115 int shift_x = ((int) buffer[1]) - 127;116 int shift_y = ((int) buffer[2]) - 127;117 int wheel = ((int) buffer[3]) - 127;118 119 if (buffer[1] == 0) {120 shift_x = 0;121 }122 if (buffer[2] == 0) {123 shift_y = 0;124 }125 if (buffer[3] == 0) {126 wheel = 0;127 }128 129 if (mouse->console_phone >= 0) {130 if ((shift_x != 0) || (shift_y != 0)) {131 /* FIXME: guessed for QEMU */132 async_req_2_0(mouse->console_phone,133 MEVENT_MOVE,134 - shift_x / 10, - shift_y / 10);135 }136 if (butt) {137 /* FIXME: proper button clicking. */138 async_req_2_0(mouse->console_phone,139 MEVENT_BUTTON, 1, 1);140 async_req_2_0(mouse->console_phone,141 MEVENT_BUTTON, 1, 0);142 }143 }144 145 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n",146 str_buttons, shift_x, shift_y, wheel);147 }148 149 /*150 * Device was probably unplugged.151 * Hang-up the phone to the console.152 * FIXME: release allocated memory.153 */154 117 async_hangup(mouse->console_phone); 155 118 mouse->console_phone = -1; 156 157 usb_log_error("Mouse polling fibril terminated.\n");158 159 return EOK;160 119 } 161 162 120 163 121 /** -
uspace/drv/usbmouse/mouse.h
r45dd8bf r4f66cc7b 37 37 #define USBMOUSE_MOUSE_H_ 38 38 39 #include < ddf/driver.h>39 #include <usb/devdrv.h> 40 40 #include <usb/pipes.h> 41 41 #include <time.h> … … 46 46 typedef struct { 47 47 /** Generic device container. */ 48 ddf_dev_t *device;48 usb_device_t *dev; 49 49 /** Function representing the device. */ 50 50 ddf_fun_t *mouse_fun; 51 /** Representation of connection to the device. */52 usb_device_connection_t wire;53 /** Default (zero) control pipe. */54 usb_endpoint_pipe_t ctrl_pipe;55 /** Polling (in) pipe. */56 usb_endpoint_pipe_t poll_pipe;57 51 /** Polling interval in microseconds. */ 58 52 suseconds_t poll_interval_us; … … 61 55 } usb_mouse_t; 62 56 63 int usb_mouse_create(ddf_dev_t *); 57 #define POLL_PIPE(dev) ((dev)->pipes[0].pipe) 64 58 65 int usb_mouse_polling_fibril(void *); 59 extern usb_endpoint_description_t poll_endpoint_description; 60 61 int usb_mouse_create(usb_device_t *); 62 63 bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t, void *); 64 void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *); 66 65 67 66 #endif -
uspace/lib/block/libblock.c
r45dd8bf r4f66cc7b 411 411 l = hash_table_find(&cache->block_hash, &key); 412 412 if (l) { 413 found: 413 414 /* 414 415 * We found the block in the cache. … … 493 494 fibril_mutex_unlock(&b->lock); 494 495 goto retry; 496 } 497 l = hash_table_find(&cache->block_hash, &key); 498 if (l) { 499 /* 500 * Someone else must have already 501 * instantiated the block while we were 502 * not holding the cache lock. 503 * Leave the recycled block on the 504 * freelist and continue as if we 505 * found the block of interest during 506 * the first try. 507 */ 508 fibril_mutex_unlock(&b->lock); 509 goto found; 495 510 } 496 511 -
uspace/lib/drv/generic/remote_usbhc.c
r45dd8bf r4f66cc7b 55 55 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 56 56 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 58 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 59 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 58 60 … … 73 75 74 76 remote_usbhc_control_write, 75 remote_usbhc_control_read 77 remote_usbhc_control_read, 78 79 remote_usbhc_register_endpoint, 80 remote_usbhc_unregister_endpoint 76 81 }; 77 82 … … 522 527 523 528 529 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 530 ipc_callid_t callid, ipc_call_t *call) 531 { 532 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 533 534 if (!usb_iface->register_endpoint) { 535 async_answer_0(callid, ENOTSUP); 536 return; 537 } 538 539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \ 540 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256 541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \ 542 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256 543 544 INIT_FROM_HIGH_DATA(usb_address_t, address, 1); 545 INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1); 546 INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2); 547 INIT_FROM_LOW_DATA(usb_direction_t, direction, 2); 548 549 #undef INIT_FROM_HIGH_DATA 550 #undef INIT_FROM_LOW_DATA 551 552 size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call); 553 unsigned int interval = (unsigned int) DEV_IPC_GET_ARG4(*call); 554 555 int rc = usb_iface->register_endpoint(fun, address, endpoint, 556 transfer_type, direction, max_packet_size, interval); 557 558 async_answer_0(callid, rc); 559 } 560 561 562 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, 563 ipc_callid_t callid, ipc_call_t *call) 564 { 565 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 566 567 if (!usb_iface->unregister_endpoint) { 568 async_answer_0(callid, ENOTSUP); 569 return; 570 } 571 572 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 573 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call); 574 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call); 575 576 int rc = usb_iface->unregister_endpoint(fun, 577 address, endpoint, direction); 578 579 async_answer_0(callid, rc); 580 } 581 524 582 525 583 /** -
uspace/lib/drv/include/usbhc_iface.h
r45dd8bf r4f66cc7b 167 167 IPC_M_USBHC_CONTROL_READ, 168 168 169 /* IPC_M_USB_ */ 169 /** Register endpoint attributes at host controller. 170 * This is used to reserve portion of USB bandwidth. 171 * Parameters: 172 * - USB address + endpoint number (ADDR * 256 + EP) 173 * - transfer type + direction (TYPE * 256 + DIR) 174 * - maximum packet size 175 * - interval (in milliseconds) 176 * Answer: 177 * - EOK - reservation successful 178 * - ELIMIT - not enough bandwidth to satisfy the request 179 */ 180 IPC_M_USBHC_REGISTER_ENDPOINT, 181 182 /** Revert endpoint registration. 183 * Parameters: 184 * - USB address 185 * - endpoint number 186 * - data direction 187 * Answer: 188 * - EOK - endpoint unregistered 189 * - ENOENT - unknown endpoint 190 */ 191 IPC_M_USBHC_UNREGISTER_ENDPOINT 170 192 } usbhc_iface_funcs_t; 171 193 … … 200 222 int (*release_address)(ddf_fun_t *, usb_address_t); 201 223 224 int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, 225 usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 226 int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, 227 usb_direction_t); 228 202 229 usbhc_iface_transfer_out_t interrupt_out; 203 230 usbhc_iface_transfer_in_t interrupt_in; -
uspace/lib/usb/Makefile
r45dd8bf r4f66cc7b 37 37 src/ddfiface.c \ 38 38 src/debug.c \ 39 src/devdrv.c \ 40 src/devpoll.c \ 39 41 src/dp.c \ 40 42 src/dump.c \ -
uspace/lib/usb/include/usb/pipes.h
r45dd8bf r4f66cc7b 106 106 const usb_endpoint_description_t *description; 107 107 /** Interface number the endpoint must belong to (-1 for any). */ 108 constint interface_no;108 int interface_no; 109 109 /** Found descriptor fitting the description. */ 110 110 usb_standard_endpoint_descriptor_t *descriptor; … … 129 129 int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *, 130 130 usb_device_connection_t *); 131 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *); 131 132 int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 132 133 size_t, uint8_t *, size_t, usb_device_connection_t *); 133 134 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *, unsigned int, 135 usb_hc_connection_t *); 136 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *, usb_hc_connection_t *); 134 137 135 138 int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *); -
uspace/lib/usb/src/hub.c
r45dd8bf r4f66cc7b 235 235 goto leave_release_default_address; 236 236 } 237 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe); 238 if (rc != EOK) { 239 rc = ENOTCONN; 240 goto leave_release_default_address; 241 } 237 242 238 243 rc = usb_endpoint_pipe_start_session(&ctrl_pipe); -
uspace/lib/usb/src/pipesinit.c
r45dd8bf r4f66cc7b 37 37 #include <usb/pipes.h> 38 38 #include <usb/dp.h> 39 #include <usb/request.h> 40 #include <usbhc_iface.h> 39 41 #include <errno.h> 40 42 #include <assert.h> 43 44 #define CTRL_PIPE_MIN_PACKET_SIZE 8 45 #define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7 41 46 42 47 … … 369 374 370 375 int rc = usb_endpoint_pipe_initialize(pipe, connection, 371 0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH); 376 0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, 377 USB_DIRECTION_BOTH); 372 378 373 379 return rc; 380 } 381 382 /** Probe default control pipe for max packet size. 383 * 384 * The function tries to get the correct value of max packet size several 385 * time before giving up. 386 * 387 * The session on the pipe shall not be started. 388 * 389 * @param pipe Default control pipe. 390 * @return Error code. 391 */ 392 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *pipe) 393 { 394 assert(pipe); 395 assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE); 396 397 if ((pipe->direction != USB_DIRECTION_BOTH) || 398 (pipe->transfer_type != USB_TRANSFER_CONTROL) || 399 (pipe->endpoint_no != 0)) { 400 return EINVAL; 401 } 402 403 #define TRY_LOOP(attempt_var) \ 404 for (attempt_var = 0; attempt_var < 3; attempt_var++) 405 406 size_t failed_attempts; 407 int rc; 408 409 TRY_LOOP(failed_attempts) { 410 rc = usb_endpoint_pipe_start_session(pipe); 411 if (rc == EOK) { 412 break; 413 } 414 } 415 if (rc != EOK) { 416 return rc; 417 } 418 419 420 uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE]; 421 size_t transferred_size; 422 TRY_LOOP(failed_attempts) { 423 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD, 424 USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE, 425 0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE, 426 &transferred_size); 427 if (rc == EOK) { 428 if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) { 429 rc = ELIMIT; 430 continue; 431 } 432 break; 433 } 434 } 435 usb_endpoint_pipe_end_session(pipe); 436 if (rc != EOK) { 437 return rc; 438 } 439 440 pipe->max_packet_size 441 = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET]; 442 443 return EOK; 444 } 445 446 /** Register endpoint with the host controller. 447 * 448 * @param pipe Pipe to be registered. 449 * @param interval Polling interval. 450 * @param hc_connection Connection to the host controller (must be opened). 451 * @return Error code. 452 */ 453 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *pipe, 454 unsigned int interval, 455 usb_hc_connection_t *hc_connection) 456 { 457 assert(pipe); 458 assert(hc_connection); 459 460 if (!usb_hc_connection_is_opened(hc_connection)) { 461 return EBADF; 462 } 463 464 #define _PACK(high, low) ((high) * 256 + (low)) 465 466 return async_req_5_0(hc_connection->hc_phone, 467 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT, 468 _PACK(pipe->wire->address, pipe->endpoint_no), 469 _PACK(pipe->transfer_type, pipe->direction), 470 pipe->max_packet_size, interval); 471 472 #undef _PACK 473 } 474 475 /** Revert endpoint registration with the host controller. 476 * 477 * @param pipe Pipe to be unregistered. 478 * @param hc_connection Connection to the host controller (must be opened). 479 * @return Error code. 480 */ 481 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *pipe, 482 usb_hc_connection_t *hc_connection) 483 { 484 assert(pipe); 485 assert(hc_connection); 486 487 if (!usb_hc_connection_is_opened(hc_connection)) { 488 return EBADF; 489 } 490 491 return async_req_4_0(hc_connection->hc_phone, 492 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT, 493 pipe->wire->address, pipe->endpoint_no, pipe->direction); 374 494 } 375 495 -
uspace/lib/usb/src/recognise.c
r45dd8bf r4f66cc7b 369 369 goto failure; 370 370 } 371 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe); 372 if (rc != EOK) { 373 goto failure; 374 } 371 375 372 376 /* … … 374 378 * naming etc., something more descriptive could be created. 375 379 */ 376 rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index); 380 rc = asprintf(&child_name, "usb%02zu_a%d", 381 this_device_name_index, address); 377 382 if (rc < 0) { 378 383 goto failure; -
uspace/srv/hw/irc/apic/apic.c
r45dd8bf r4f66cc7b 54 54 #define NAME "apic" 55 55 56 static bool apic_found = false; 57 56 58 static int apic_enable_irq(sysarg_t irq) 57 59 { … … 79 81 callid = async_get_call(&call); 80 82 81 switch (IPC_GET_IMETHOD(call)) { 83 sysarg_t method = IPC_GET_IMETHOD(call); 84 if (method == IPC_M_PHONE_HUNGUP) { 85 return; 86 } 87 88 if (!apic_found) { 89 async_answer_0(callid, ENOTSUP); 90 break; 91 } 92 93 switch (method) { 82 94 case IRC_ENABLE_INTERRUPT: 83 95 async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call))); … … 97 109 * 98 110 */ 99 static boolapic_init(void)111 static void apic_init(void) 100 112 { 101 113 sysarg_t apic; 102 114 103 if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) {104 printf(NAME ": No APIC found\n");105 return false;115 apic_found = sysinfo_get_value("apic", &apic) && apic; 116 if (!apic_found) { 117 printf(NAME ": Warning: no APIC found\n"); 106 118 } 107 119 108 120 async_set_client_connection(apic_connection); 109 121 service_register(SERVICE_APIC); 110 111 return true;112 122 } 113 123 … … 116 126 printf(NAME ": HelenOS APIC driver\n"); 117 127 118 if (!apic_init()) 119 return -1; 120 128 apic_init(); 129 121 130 printf(NAME ": Accepting connections\n"); 122 131 async_manager();
Note:
See TracChangeset
for help on using the changeset viewer.