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