Changes in / [34e8bab:b77ce84] in mainline
- Location:
- uspace
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/batch.c
r34e8bab rb77ce84 76 76 * @param[in] func_out function to call on outbound transfer completion 77 77 * @param[in] arg additional parameter to func_in or func_out 78 * @return Valid pointer if all s tructures were successfully created,78 * @return Valid pointer if all substructures were successfully created, 79 79 * NULL otherwise. 80 80 * … … 126 126 127 127 qh_init(uhci_data->qh); 128 qh_set_element_td(uhci_data->qh, uhci_data->tds);128 qh_set_element_td(uhci_data->qh, addr_to_phys(uhci_data->tds)); 129 129 130 130 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); … … 396 396 } 397 397 /*----------------------------------------------------------------------------*/ 398 /** Provides access to QH data structure.399 * @param[in] instance Batch pointer to use.400 * @return Pointer to the QH used by the batch.401 */402 398 qh_t * batch_qh(usb_transfer_batch_t *instance) 403 399 { -
uspace/drv/uhci-hcd/batch.h
r34e8bab rb77ce84 30 30 */ 31 31 /** @file 32 * @brief UHCI driver USB tran fer helper functions32 * @brief UHCI driver USB transaction structure 33 33 */ 34 34 #ifndef DRV_UHCI_BATCH_H -
uspace/drv/uhci-hcd/hc.c
r34e8bab rb77ce84 66 66 static int hc_interrupt_emulator(void *arg); 67 67 static int hc_debug_checker(void *arg); 68 #if 0 69 static bool usb_is_allowed( 70 bool low_speed, usb_transfer_type_t transfer, size_t size); 71 #endif 68 72 /*----------------------------------------------------------------------------*/ 69 73 /** Initialize UHCI hcd driver structure … … 85 89 int ret; 86 90 87 #define CHECK_RET_ RETURN(ret, message...) \91 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \ 88 92 if (ret != EOK) { \ 89 93 usb_log_error(message); \ 94 if (instance->ddf_instance) \ 95 ddf_fun_destroy(instance->ddf_instance); \ 90 96 return ret; \ 91 97 } else (void) 0 … … 93 99 instance->hw_interrupts = interrupts; 94 100 instance->hw_failures = 0; 101 102 /* Setup UHCI function. */ 103 instance->ddf_instance = fun; 95 104 96 105 /* allow access to hc control registers */ 97 106 regs_t *io; 98 107 ret = pio_enable(regs, reg_size, (void**)&io); 99 CHECK_RET_ RETURN(ret,108 CHECK_RET_DEST_FUN_RETURN(ret, 100 109 "Failed(%d) to gain access to registers at %p: %s.\n", 101 ret, io, str_error(ret));110 ret, str_error(ret), io); 102 111 instance->registers = io; 103 112 usb_log_debug("Device registers at %p(%u) accessible.\n", … … 105 114 106 115 ret = hc_init_mem_structures(instance); 107 CHECK_RET_RETURN(ret, 108 "Failed(%d) to initialize UHCI memory structures: %s.\n", 109 ret, str_error(ret)); 116 CHECK_RET_DEST_FUN_RETURN(ret, 117 "Failed to initialize UHCI memory structures.\n"); 110 118 111 119 hc_init_hw(instance); 112 120 if (!interrupts) { 113 instance-> interrupt_emulator =121 instance->cleaner = 114 122 fibril_create(hc_interrupt_emulator, instance); 115 fibril_add_ready(instance->interrupt_emulator); 116 } 117 (void)hc_debug_checker; 123 fibril_add_ready(instance->cleaner); 124 } else { 125 /* TODO: enable interrupts here */ 126 } 127 128 instance->debug_checker = 129 fibril_create(hc_debug_checker, instance); 130 // fibril_add_ready(instance->debug_checker); 118 131 119 132 return EOK; … … 215 228 /* Set all frames to point to the first queue head */ 216 229 const uint32_t queue = 217 LINK_POINTER_QH(addr_to_phys(218 instance->transfers_interrupt.queue_head));230 instance->transfers_interrupt.queue_head_pa 231 | LINK_POINTER_QUEUE_HEAD_FLAG; 219 232 220 233 unsigned i = 0; … … 223 236 } 224 237 225 /* Init device keeper 238 /* Init device keeper*/ 226 239 usb_device_keeper_init(&instance->manager); 227 240 usb_log_debug("Initialized device manager.\n"); … … 466 479 #undef QH 467 480 } 481 /*----------------------------------------------------------------------------*/ 482 /** Check transfers for USB validity 483 * 484 * @param[in] low_speed Transfer speed. 485 * @param[in] transfer Transer type 486 * @param[in] size Size of data packets 487 * @return True if transaction is allowed by USB specs, false otherwise 488 */ 489 #if 0 490 bool usb_is_allowed( 491 bool low_speed, usb_transfer_type_t transfer, size_t size) 492 { 493 /* see USB specification chapter 5.5-5.8 for magic numbers used here */ 494 switch(transfer) 495 { 496 case USB_TRANSFER_ISOCHRONOUS: 497 return (!low_speed && size < 1024); 498 case USB_TRANSFER_INTERRUPT: 499 return size <= (low_speed ? 8 : 64); 500 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 501 return (size <= (low_speed ? 8 : 64)); 502 case USB_TRANSFER_BULK: /* device specifies its own max size */ 503 return (!low_speed && size <= 64); 504 } 505 return false; 506 } 507 #endif 468 508 /** 469 509 * @} -
uspace/drv/uhci-hcd/hc.h
r34e8bab rb77ce84 48 48 #include "transfer_list.h" 49 49 50 /** UHCI I/O registers layout */51 50 typedef struct uhci_regs { 52 /** Command register, controls HC behaviour */53 51 uint16_t usbcmd; 54 52 #define UHCI_CMD_MAX_PACKET (1 << 7) … … 61 59 #define UHCI_CMD_RUN_STOP (1 << 0) 62 60 63 /** Status register, 1 means interrupt is asserted (if enabled) */64 61 uint16_t usbsts; 65 62 #define UHCI_STATUS_HALTED (1 << 5) … … 70 67 #define UHCI_STATUS_INTERRUPT (1 << 0) 71 68 72 /** Interrupt enabled registers */73 69 uint16_t usbintr; 74 70 #define UHCI_INTR_SHORT_PACKET (1 << 3) … … 77 73 #define UHCI_INTR_CRC (1 << 0) 78 74 79 /** Register stores frame number used in SOF packet */80 75 uint16_t frnum; 81 82 /** Pointer(physical) to the Frame List */83 76 uint32_t flbaseadd; 84 85 /** SOF modification to match external timers */86 77 uint8_t sofmod; 87 78 } regs_t; … … 92 83 #define UHCI_ALLOWED_HW_FAIL 5 93 84 94 /* Main HC driver structure */95 85 typedef struct hc { 96 /** USB bus driver, devices and addresses */97 86 usb_device_keeper_t manager; 98 /** USB bus driver, endpoints */99 87 usb_endpoint_manager_t ep_manager; 100 88 101 /** Addresses of I/O registers */102 89 regs_t *registers; 103 90 104 /** Frame List contains 1024 link pointers */105 91 link_pointer_t *frame_list; 106 92 107 /** List and queue of interrupt transfers */ 93 transfer_list_t transfers_bulk_full; 94 transfer_list_t transfers_control_full; 95 transfer_list_t transfers_control_slow; 108 96 transfer_list_t transfers_interrupt; 109 /** List and queue of low speed control transfers */110 transfer_list_t transfers_control_slow;111 /** List and queue of full speed bulk transfers */112 transfer_list_t transfers_bulk_full;113 /** List and queue of full speed control transfers */114 transfer_list_t transfers_control_full;115 97 116 /** Pointer table to the above lists, helps during scheduling */117 98 transfer_list_t *transfers[2][4]; 118 99 119 /** Code to be executed in kernel interrupt handler */120 100 irq_code_t interrupt_code; 121 101 122 /** Fibril periodically checking status register*/ 123 fid_t interrupt_emulator; 102 fid_t cleaner; 103 fid_t debug_checker; 104 bool hw_interrupts; 105 unsigned hw_failures; 124 106 125 /** Indicator of hw interrupts availability */ 126 bool hw_interrupts; 127 128 /** Number of hw failures detected. */ 129 unsigned hw_failures; 107 ddf_fun_t *ddf_instance; 130 108 } hc_t; 131 109 -
uspace/drv/uhci-hcd/hw_struct/queue_head.h
r34e8bab rb77ce84 34 34 #ifndef DRV_UHCI_QH_H 35 35 #define DRV_UHCI_QH_H 36 37 /* libc */ 36 38 #include <assert.h> 37 39 38 40 #include "link_pointer.h" 39 #include "transfer_descriptor.h"40 #include "utils/malloc32.h"41 41 42 /** This structure is defined in UHCI design guide p. 31 */43 42 typedef struct queue_head { 44 /** Pointer to the next entity (another QH or TD */45 43 volatile link_pointer_t next; 46 /** Pointer to the contained entities (execution controlled by vertical flag*/47 44 volatile link_pointer_t element; 48 45 } __attribute__((packed)) qh_t; … … 67 64 * @param[in] pa Physical address of the next queue head. 68 65 * 69 * Adds proper flag. If the pointer is NULL, sets next to terminal NULL. 66 * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal 67 * NULL. 70 68 */ 71 static inline void qh_set_next_qh(qh_t *instance, qh_t *next)69 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa) 72 70 { 73 uint32_t pa = addr_to_phys(next);74 if (pa ) {71 /* Address is valid and not terminal */ 72 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 75 73 instance->next = LINK_POINTER_QH(pa); 76 74 } else { … … 82 80 * 83 81 * @param[in] instance qh_t structure to initialize. 82 * @param[in] pa Physical address of the next queue head. 83 * 84 * Adds proper flag. If the pointer is NULL or terminal, sets element 85 * to terminal NULL. 86 */ 87 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa) 88 { 89 /* Address is valid and not terminal */ 90 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 91 instance->element = LINK_POINTER_QH(pa); 92 } else { 93 instance->element = LINK_POINTER_TERM; 94 } 95 } 96 /*----------------------------------------------------------------------------*/ 97 /** Set queue head element pointer 98 * 99 * @param[in] instance qh_t structure to initialize. 84 100 * @param[in] pa Physical address of the TD structure. 85 101 * 86 * Adds proper flag. If the pointer is NULL, sets element to terminal NULL. 102 * Adds proper flag. If the pointer is NULL or terminal, sets element 103 * to terminal NULL. 87 104 */ 88 static inline void qh_set_element_td(qh_t *instance, td_t *td)105 static inline void qh_set_element_td(qh_t *instance, uint32_t pa) 89 106 { 90 uint32_t pa = addr_to_phys(td); 91 if (pa) { 107 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 92 108 instance->element = LINK_POINTER_TD(pa); 93 109 } else { … … 95 111 } 96 112 } 113 97 114 #endif 98 115 /** -
uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c
r34e8bab rb77ce84 77 77 78 78 instance->status = 0 79 | ((err_count & TD_STATUS_ERROR_COUNT_MASK) 80 << TD_STATUS_ERROR_COUNT_POS) 79 | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS) 81 80 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0) 82 81 | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0) … … 90 89 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS) 91 90 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0) 92 | ((target.address & TD_DEVICE_ADDRESS_MASK) 93 << TD_DEVICE_ADDRESS_POS) 94 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) 95 << TD_DEVICE_ENDPOINT_POS) 91 | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS) 92 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS) 96 93 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS); 97 94 … … 117 114 assert(instance); 118 115 119 /* This is hc internal error it should never be reported.*/116 /* this is hc internal error it should never be reported */ 120 117 if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0) 121 118 return EAGAIN; … … 126 123 return EBADCHECKSUM; 127 124 128 /* HC does not end transactionson these, it should never be reported */125 /* hc does not end transaction on these, it should never be reported */ 129 126 if ((instance->status & TD_STATUS_ERROR_NAK) != 0) 130 127 return EAGAIN; 131 128 132 /* Buffer overrun or underrun */129 /* buffer overrun or underrun */ 133 130 if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0) 134 131 return ERANGE; 135 132 136 /* Device babble is something serious */133 /* device babble is something serious */ 137 134 if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0) 138 135 return EIO; 139 136 140 /* Stall might represent err count reaching zero or stall response from141 * the device . Iferr count reached zero, one of the above is reported*/137 /* stall might represent err count reaching zero or stall response from 138 * the device, is err count reached zero, one of the above is reported*/ 142 139 if ((instance->status & TD_STATUS_ERROR_STALLED) != 0) 143 140 return ESTALL; -
uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h
r34e8bab rb77ce84 40 40 #include "link_pointer.h" 41 41 42 /** Transfer Descriptor, defined in UHCI design guide p. 26*/42 /** UHCI Transfer Descriptor */ 43 43 typedef struct transfer_descriptor { 44 /** Pointer to the next entity (TD or QH) */45 44 link_pointer_t next; 46 45 47 /** Status doubleword */48 46 volatile uint32_t status; 49 47 #define TD_STATUS_RESERVED_MASK 0xc000f800 50 #define TD_STATUS_SPD_FLAG (1 << 29)51 #define TD_STATUS_ERROR_COUNT_POS 2752 #define TD_STATUS_ERROR_COUNT_MASK 0x353 #define TD_STATUS_LOW_SPEED_FLAG (1 << 26)54 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25)55 #define TD_STATUS_IOC_FLAG (1 << 24)48 #define TD_STATUS_SPD_FLAG ( 1 << 29 ) 49 #define TD_STATUS_ERROR_COUNT_POS ( 27 ) 50 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 ) 51 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 ) 52 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 ) 53 #define TD_STATUS_IOC_FLAG ( 1 << 24 ) 56 54 57 #define TD_STATUS_ERROR_ACTIVE (1 << 23)58 #define TD_STATUS_ERROR_STALLED (1 << 22)59 #define TD_STATUS_ERROR_BUFFER (1 << 21)60 #define TD_STATUS_ERROR_BABBLE (1 << 20)61 #define TD_STATUS_ERROR_NAK (1 << 19)62 #define TD_STATUS_ERROR_CRC (1 << 18)63 #define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17)64 #define TD_STATUS_ERROR_RESERVED (1 << 16)55 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23 ) 56 #define TD_STATUS_ERROR_STALLED ( 1 << 22 ) 57 #define TD_STATUS_ERROR_BUFFER ( 1 << 21 ) 58 #define TD_STATUS_ERROR_BABBLE ( 1 << 20 ) 59 #define TD_STATUS_ERROR_NAK ( 1 << 19 ) 60 #define TD_STATUS_ERROR_CRC ( 1 << 18 ) 61 #define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 ) 62 #define TD_STATUS_ERROR_RESERVED ( 1 << 16 ) 65 63 #define TD_STATUS_ERROR_POS 16 66 #define TD_STATUS_ERROR_MASK 0xff64 #define TD_STATUS_ERROR_MASK ( 0xff ) 67 65 68 66 #define TD_STATUS_ACTLEN_POS 0 69 67 #define TD_STATUS_ACTLEN_MASK 0x7ff 70 68 71 /* double word with USB device specific info */72 69 volatile uint32_t device; 73 70 #define TD_DEVICE_MAXLEN_POS 21 74 #define TD_DEVICE_MAXLEN_MASK 0x7ff75 #define TD_DEVICE_RESERVED_FLAG (1 << 20)76 #define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19)71 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff ) 72 #define TD_DEVICE_RESERVED_FLAG ( 1 << 20 ) 73 #define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 ) 77 74 #define TD_DEVICE_ENDPOINT_POS 15 78 #define TD_DEVICE_ENDPOINT_MASK 0xf75 #define TD_DEVICE_ENDPOINT_MASK ( 0xf ) 79 76 #define TD_DEVICE_ADDRESS_POS 8 80 #define TD_DEVICE_ADDRESS_MASK 0x7f77 #define TD_DEVICE_ADDRESS_MASK ( 0x7f ) 81 78 #define TD_DEVICE_PID_POS 0 82 #define TD_DEVICE_PID_MASK 0xff79 #define TD_DEVICE_PID_MASK ( 0xff ) 83 80 84 /** Pointer(physical) to the beginning of the transaction's buffer */85 81 volatile uint32_t buffer_ptr; 86 82 87 /* According to UHCI design guide, there is 16 bytes of 88 * data available here. 89 * According to linux kernel the hardware does not care, 90 * it just needs to be aligned. We don't use it anyway. 83 /* there is 16 bytes of data available here, according to UHCI 84 * Design guide, according to linux kernel the hardware does not care, 85 * it just needs to be aligned, we don't use it anyway 91 86 */ 92 87 } __attribute__((packed)) td_t; -
uspace/drv/uhci-hcd/main.c
r34e8bab rb77ce84 39 39 #include <usb/debug.h> 40 40 41 #include "iface.h" 41 42 #include "uhci.h" 42 43 … … 61 62 int uhci_add_device(ddf_dev_t *device) 62 63 { 63 usb_log_debug 2("uhci_add_device() called\n");64 usb_log_debug("uhci_add_device() called\n"); 64 65 assert(device); 65 66 66 uhci_t *uhci = malloc(sizeof(uhci_t)); 67 67 if (uhci == NULL) { … … 72 72 int ret = uhci_init(uhci, device); 73 73 if (ret != EOK) { 74 usb_log_error("Failed (%d)to initialize UHCI driver: %s.\n",75 ret,str_error(ret));74 usb_log_error("Failed to initialize UHCI driver: %s.\n", 75 str_error(ret)); 76 76 return ret; 77 77 } … … 85 85 /** Initialize global driver structures (NONE). 86 86 * 87 * @param[in] argc N umber of arguments in argv vector (ignored).87 * @param[in] argc Nmber of arguments in argv vector (ignored). 88 88 * @param[in] argv Cmdline argument vector (ignored). 89 89 * @return Error code. … … 94 94 { 95 95 printf(NAME ": HelenOS UHCI driver.\n"); 96 97 sleep(3); /* TODO: remove in final version */ 96 98 usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME); 97 99 -
uspace/drv/uhci-hcd/pci.c
r34e8bab rb77ce84 44 44 #include "pci.h" 45 45 46 /** Get I/Oaddress of registers and IRQ for given device.46 /** Get address of registers and IRQ for given device. 47 47 * 48 48 * @param[in] dev Device asking for the addresses. … … 53 53 */ 54 54 int pci_get_my_registers(ddf_dev_t *dev, 55 uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no) 55 uintptr_t *io_reg_address, size_t *io_reg_size, 56 int *irq_no) 56 57 { 57 58 assert(dev != NULL); 58 59 59 int parent_phone = 60 devman_parent_device_connect(dev->handle,IPC_FLAG_BLOCKING);60 int parent_phone = devman_parent_device_connect(dev->handle, 61 IPC_FLAG_BLOCKING); 61 62 if (parent_phone < 0) { 62 63 return parent_phone; 63 64 } 64 65 66 int rc; 65 67 hw_resource_list_t hw_resources; 66 intrc = hw_res_get_resource_list(parent_phone, &hw_resources);68 rc = hw_res_get_resource_list(parent_phone, &hw_resources); 67 69 if (rc != EOK) { 68 70 goto leave; … … 93 95 res->res.io_range.address, res->res.io_range.size); 94 96 io_found = true; 95 break;96 97 97 98 default: … … 112 113 leave: 113 114 async_hangup(parent_phone); 115 114 116 return rc; 115 117 } … … 143 145 } 144 146 145 /* See UHCI design guide for these values p.45,147 /* See UHCI design guide for these values, 146 148 * write all WC bits in USB legacy register */ 147 149 sysarg_t address = 0xc0; -
uspace/drv/uhci-hcd/root_hub.c
r34e8bab rb77ce84 55 55 int ret = asprintf(&match_str, "usb&uhci&root-hub"); 56 56 if (ret < 0) { 57 usb_log_error( 58 "Failed(%d) to create root hub match string: %s.\n", 59 ret, str_error(ret)); 60 return ret; 57 usb_log_error("Failed to create root hub match string.\n"); 58 return ENOMEM; 61 59 } 62 60 63 61 ret = ddf_fun_add_match_id(fun, match_str, 100); 64 62 if (ret != EOK) { 65 free(match_str);66 63 usb_log_error("Failed(%d) to add root hub match id: %s\n", 67 64 ret, str_error(ret)); … … 69 66 } 70 67 71 /* Initialize resource structure */72 instance->resource_list.count = 1;73 instance->resource_list.resources = &instance->io_regs;74 68 hw_resource_list_t *resource_list = &instance->resource_list; 69 resource_list->count = 1; 70 resource_list->resources = &instance->io_regs; 71 assert(resource_list->resources); 75 72 instance->io_regs.type = IO_RANGE; 76 73 instance->io_regs.res.io_range.address = reg_addr; -
uspace/drv/uhci-hcd/root_hub.h
r34e8bab rb77ce84 39 39 #include <ops/hw_res.h> 40 40 41 /** DDF support structure for uhci-rhd driver, provides I/O resources */42 41 typedef struct rh { 43 /** List of resources available to the root hub. */44 42 hw_resource_list_t resource_list; 45 /** The only resource in the above list */46 43 hw_resource_t io_regs; 47 44 } rh_t; -
uspace/drv/uhci-hcd/transfer_list.c
r34e8bab rb77ce84 57 57 return ENOMEM; 58 58 } 59 uint32_tqueue_head_pa = addr_to_phys(instance->queue_head);59 instance->queue_head_pa = addr_to_phys(instance->queue_head); 60 60 usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n", 61 name, instance->queue_head, queue_head_pa);61 name, instance->queue_head, instance->queue_head_pa); 62 62 63 63 qh_init(instance->queue_head); … … 67 67 } 68 68 /*----------------------------------------------------------------------------*/ 69 /** Dispose transfer list structures.70 *71 * @param[in] instance Memory place to use.72 *73 * Frees memory for internal qh_t structure.74 */75 void transfer_list_fini(transfer_list_t *instance)76 {77 assert(instance);78 free32(instance->queue_head);79 }80 69 /** Set the next list in transfer list chain. 81 70 * … … 92 81 if (!instance->queue_head) 93 82 return; 94 /* Set queue_head.next to point to the follower */95 qh_set_next_qh(instance->queue_head, next->queue_head );96 } 97 /*----------------------------------------------------------------------------*/ 98 /** Addtransfer batch to the list and queue.83 /* Set both queue_head.next to point to the follower */ 84 qh_set_next_qh(instance->queue_head, next->queue_head_pa); 85 } 86 /*----------------------------------------------------------------------------*/ 87 /** Submit transfer batch to the list and queue. 99 88 * 100 89 * @param[in] instance List to use. 101 90 * @param[in] batch Transfer batch to submit. 91 * @return Error code 102 92 * 103 93 * The batch is added to the end of the list and queue. … … 119 109 } else { 120 110 /* There is something scheduled */ 121 usb_transfer_batch_t *last = 122 usb_transfer_batch_from_link(instance->batch_list.prev);111 usb_transfer_batch_t *last = list_get_instance( 112 instance->batch_list.prev, usb_transfer_batch_t, link); 123 113 last_qh = batch_qh(last); 124 114 } … … 128 118 /* keep link */ 129 119 batch_qh(batch)->next = last_qh->next; 130 qh_set_next_qh(last_qh, batch_qh(batch));120 qh_set_next_qh(last_qh, pa); 131 121 132 122 asm volatile ("": : :"memory"); … … 142 132 } 143 133 /*----------------------------------------------------------------------------*/ 144 /** Add completed bantches to the provided list.134 /** Create list for finished batches. 145 135 * 146 136 * @param[in] instance List to use. … … 157 147 link_t *next = current->next; 158 148 usb_transfer_batch_t *batch = 159 usb_transfer_batch_from_link(current);149 list_get_instance(current, usb_transfer_batch_t, link); 160 150 161 151 if (batch_is_complete(batch)) { 162 /* Save for p rocessing */152 /* Save for post-processing */ 163 153 transfer_list_remove_batch(instance, batch); 164 154 list_append(current, done); … … 169 159 } 170 160 /*----------------------------------------------------------------------------*/ 171 /** Walk the list and finish all batches with EINTR.161 /** Walk the list and abort all batches. 172 162 * 173 163 * @param[in] instance List to use. … … 179 169 link_t *current = instance->batch_list.next; 180 170 usb_transfer_batch_t *batch = 181 usb_transfer_batch_from_link(current);171 list_get_instance(current, usb_transfer_batch_t, link); 182 172 transfer_list_remove_batch(instance, batch); 183 usb_transfer_batch_finish_error(batch, EI NTR);173 usb_transfer_batch_finish_error(batch, EIO); 184 174 } 185 175 fibril_mutex_unlock(&instance->guard); … … 190 180 * @param[in] instance List to use. 191 181 * @param[in] batch Transfer batch to remove. 182 * @return Error code 192 183 * 193 184 * Does not lock the transfer list, caller is responsible for that. … … 206 197 207 198 const char *qpos = NULL; 208 qh_t *prev_qh = NULL;209 199 /* Remove from the hardware queue */ 210 200 if (instance->batch_list.next == &batch->link) { 211 201 /* I'm the first one here */ 212 prev_qh = instance->queue_head; 202 assert((instance->queue_head->next & LINK_POINTER_ADDRESS_MASK) 203 == addr_to_phys(batch_qh(batch))); 204 instance->queue_head->next = batch_qh(batch)->next; 213 205 qpos = "FIRST"; 214 206 } else { 215 /* The thing before me is a batch too */216 207 usb_transfer_batch_t *prev = 217 usb_transfer_batch_from_link(batch->link.prev); 218 prev_qh = batch_qh(prev); 208 list_get_instance( 209 batch->link.prev, usb_transfer_batch_t, link); 210 assert((batch_qh(prev)->next & LINK_POINTER_ADDRESS_MASK) 211 == addr_to_phys(batch_qh(batch))); 212 batch_qh(prev)->next = batch_qh(batch)->next; 219 213 qpos = "NOT FIRST"; 220 214 } 221 assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)222 == addr_to_phys(batch_qh(batch)));223 prev_qh->next = batch_qh(batch)->next;224 215 asm volatile ("": : :"memory"); 225 216 /* Remove from the batch list */ 226 217 list_remove(&batch->link); 227 usb_log_debug("Batch(%p) removed (%s) from %s, next :%x.\n",218 usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n", 228 219 batch, qpos, instance->name, batch_qh(batch)->next); 229 220 } -
uspace/drv/uhci-hcd/transfer_list.h
r34e8bab rb77ce84 39 39 #include "batch.h" 40 40 #include "hw_struct/queue_head.h" 41 #include "utils/malloc32.h" 41 42 42 /** Structure maintaining both hw queue and software list43 * of currently executed transfers44 */45 43 typedef struct transfer_list 46 44 { 47 /** Guard against multiple add/remove races */48 45 fibril_mutex_t guard; 49 /** UHCI hw structure represeting this queue */50 46 qh_t *queue_head; 51 /** Assigned name, for nicer debug output */47 uint32_t queue_head_pa; 52 48 const char *name; 53 /** List of all batches in this list */54 49 link_t batch_list; 55 50 } transfer_list_t; 56 51 57 void transfer_list_fini(transfer_list_t *instance); 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 } 63 58 64 int transfer_list_init(transfer_list_t *instance, const char *name); 65 59 66 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next); 60 void transfer_list_add_batch( 61 transfer_list_t *instance, usb_transfer_batch_t *batch); 67 68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch); 69 62 70 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done); 71 63 72 void transfer_list_abort_all(transfer_list_t *instance); 64 73 #endif -
uspace/drv/uhci-hcd/uhci.c
r34e8bab rb77ce84 44 44 #include "pci.h" 45 45 46 /** IRQ handling callback, forward status from call to diver structure.46 /** IRQ handling callback, identifies device 47 47 * 48 48 * @param[in] dev DDF instance of the device to use. 49 49 * @param[in] iid (Unused). 50 * @param[in] call Pointer to the call from kernel.50 * @param[in] call Pointer to the call that represents interrupt. 51 51 */ 52 52 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) … … 61 61 /** Get address of the device identified by handle. 62 62 * 63 * @param[in] fun DDF instance of the functionto use.64 * @param[in] handle DDF handle of the driver seeking its USB address.65 * @param[ out] address Found address.63 * @param[in] dev DDF instance of the device to use. 64 * @param[in] iid (Unused). 65 * @param[in] call Pointer to the call that represents interrupt. 66 66 */ 67 67 static int usb_iface_get_address( … … 69 69 { 70 70 assert(fun); 71 usb_device_keeper_t *manager = 72 &((uhci_t*)fun->dev->driver_data)->hc.manager; 71 usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.manager; 73 72 74 73 usb_address_t addr = usb_device_keeper_find(manager, handle); … … 84 83 } 85 84 /*----------------------------------------------------------------------------*/ 86 /** Gets handle of the respective hc .87 * 88 * @param[in] fun DDF function of uhci device.89 * @param[out] handle Host cotnrollerhandle.85 /** Gets handle of the respective hc (this or parent device). 86 * 87 * @param[in] root_hub_fun Root hub function seeking hc handle. 88 * @param[out] handle Place to write the handle. 90 89 * @return Error code. 91 90 */ … … 101 100 } 102 101 /*----------------------------------------------------------------------------*/ 103 /** USB interface implementation used by RH*/102 /** This iface is generic for both RH and HC. */ 104 103 static usb_iface_t usb_iface = { 105 104 .get_hc_handle = usb_iface_get_hc_handle, … … 107 106 }; 108 107 /*----------------------------------------------------------------------------*/ 109 /** Operations supported by the HC driver */110 108 static ddf_dev_ops_t hc_ops = { 109 // .interfaces[USB_DEV_IFACE] = &usb_iface, 111 110 .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */ 112 111 }; … … 123 122 } 124 123 /*----------------------------------------------------------------------------*/ 125 /** Interface to provide the root hub driver with hw info */126 124 static hw_res_ops_t hw_res_iface = { 127 125 .get_resource_list = get_resource_list, … … 129 127 }; 130 128 /*----------------------------------------------------------------------------*/ 131 /** RH function support for uhci-rhd */132 129 static ddf_dev_ops_t rh_ops = { 133 130 .interfaces[USB_DEV_IFACE] = &usb_iface, … … 135 132 }; 136 133 /*----------------------------------------------------------------------------*/ 137 /** Initialize hc and rh DDFstructures and their respective drivers.134 /** Initialize hc and rh ddf structures and their respective drivers. 138 135 * 139 136 * @param[in] instance UHCI structure to use. … … 141 138 * 142 139 * This function does all the preparatory work for hc and rh drivers: 143 * - gets device 'shw resources144 * - disables UHCI legacy support (PCI config space)140 * - gets device hw resources 141 * - disables UHCI legacy support 145 142 * - asks for interrupt 146 143 * - registers interrupt handler … … 196 193 ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 197 194 CHECK_RET_DEST_FUN_RETURN(ret, 198 "Failed(%d) to create HC function : %s.\n", ret, str_error(ret));195 "Failed(%d) to create HC function.\n", ret); 199 196 200 197 ret = hc_init(&instance->hc, instance->hc_fun, 201 198 (void*)io_reg_base, io_reg_size, interrupts); 202 CHECK_RET_DEST_FUN_RETURN(ret, 203 "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret)); 204 199 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 205 200 instance->hc_fun->ops = &hc_ops; 206 201 instance->hc_fun->driver_data = &instance->hc; … … 226 221 &instance->hc.interrupt_code); 227 222 CHECK_RET_FINI_RETURN(ret, 228 "Failed(%d) to register interrupt handler: %s.\n", 229 ret, str_error(ret)); 223 "Failed(%d) to register interrupt handler.\n", ret); 230 224 231 225 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh"); 232 226 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 233 227 CHECK_RET_FINI_RETURN(ret, 234 "Failed(%d) to create root hub function: %s.\n", 235 ret, str_error(ret)); 228 "Failed(%d) to create root hub function.\n", ret); 236 229 237 230 ret = rh_init(&instance->rh, instance->rh_fun, 238 231 (uintptr_t)instance->hc.registers + 0x10, 4); 239 232 CHECK_RET_FINI_RETURN(ret, 240 "Failed(%d) to setup UHCI root hub : %s.\n", ret, str_error(ret));233 "Failed(%d) to setup UHCI root hub.\n", ret); 241 234 242 235 instance->rh_fun->ops = &rh_ops; … … 244 237 ret = ddf_fun_bind(instance->rh_fun); 245 238 CHECK_RET_FINI_RETURN(ret, 246 "Failed(%d) to register UHCI root hub : %s.\n", ret, str_error(ret));239 "Failed(%d) to register UHCI root hub.\n", ret); 247 240 248 241 return EOK; -
uspace/drv/uhci-hcd/uhci.h
r34e8bab rb77ce84 41 41 #include "root_hub.h" 42 42 43 /** Structure representing both functions of UHCI hc, USB host controller44 * and USB root hub */45 43 typedef struct uhci { 46 /** Pointer to DDF represenation of UHCI host controller */47 44 ddf_fun_t *hc_fun; 48 /** Pointer to DDF represenation of UHCI root hub */49 45 ddf_fun_t *rh_fun; 50 46 51 /** Internal driver's represenation of UHCI host controller */52 47 hc_t hc; 53 /** Internal driver's represenation of UHCI root hub */54 48 rh_t rh; 55 49 } uhci_t; 56 50 57 51 int uhci_init(uhci_t *instance, ddf_dev_t *device); 52 58 53 #endif 59 54 /** -
uspace/lib/usb/src/host/usb_endpoint_manager.c
r34e8bab rb77ce84 211 211 212 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active)214 return EBUSY;215 216 213 instance->free_bw += node->bw; 217 214 hash_table_remove(&instance->ep_table, key, MAX_KEYS);
Note:
See TracChangeset
for help on using the changeset viewer.