Changeset 51b46f2 in mainline for uspace/drv/uhci-hcd/uhci.c
- Timestamp:
- 2011-03-01T15:39:52Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e135751
- Parents:
- 0e3505a (diff), cc44f7e (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/uhci.c
r0e3505a r51b46f2 48 48 { 49 49 .cmd = CMD_PIO_READ_16, 50 .addr = (void*)0xc022,50 .addr = NULL, /* patched for every instance */ 51 51 .dstarg = 1 52 52 }, 53 53 { 54 54 .cmd = CMD_PIO_WRITE_16, 55 .addr = (void*)0xc022,55 .addr = NULL, /* pathed for every instance */ 56 56 .value = 0x1f 57 57 }, … … 68 68 assert(hc); 69 69 70 usb_address_t addr = usb_address_keeping_find(&hc->address_manager,70 usb_address_t addr = device_keeper_find(&hc->device_manager, 71 71 handle); 72 72 if (addr < 0) { … … 80 80 return EOK; 81 81 } 82 83 82 /*----------------------------------------------------------------------------*/ 84 83 static usb_iface_t hc_usb_iface = { 85 84 .get_hc_handle = usb_iface_get_hc_handle_hc_impl, … … 89 88 static ddf_dev_ops_t uhci_ops = { 90 89 .interfaces[USB_DEV_IFACE] = &hc_usb_iface, 91 .interfaces[USBHC_DEV_IFACE] = &uhci_iface 90 .interfaces[USBHC_DEV_IFACE] = &uhci_iface, 92 91 }; 93 92 … … 102 101 bool low_speed, usb_transfer_type_t, size_t size); 103 102 104 #define CHECK_RET_RETURN(ret, message...) \ 103 104 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 105 { 106 assert(reg_size >= sizeof(regs_t)); 107 int ret; 108 109 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \ 105 110 if (ret != EOK) { \ 106 111 usb_log_error(message); \ 112 if (instance->ddf_instance) \ 113 ddf_fun_destroy(instance->ddf_instance); \ 107 114 return ret; \ 108 115 } else (void) 0 109 110 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)111 {112 assert(reg_size >= sizeof(regs_t));113 int ret;114 116 115 117 /* … … 117 119 */ 118 120 instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci"); 119 if (instance->ddf_instance == NULL) { 120 usb_log_error("Failed to create UHCI device function.\n"); 121 return ENOMEM; 122 } 121 ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK; 122 CHECK_RET_DEST_FUN_RETURN(ret, "Failed to create UHCI device function.\n"); 123 123 124 instance->ddf_instance->ops = &uhci_ops; 124 125 instance->ddf_instance->driver_data = instance; 125 126 126 127 ret = ddf_fun_bind(instance->ddf_instance); 127 CHECK_RET_ RETURN(ret, "Failedto bind UHCI device function: %s.\n",128 str_error(ret));128 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to bind UHCI device function: %s.\n", 129 ret, str_error(ret)); 129 130 130 131 /* allow access to hc control registers */ 131 132 regs_t *io; 132 133 ret = pio_enable(regs, reg_size, (void**)&io); 133 CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io); 134 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to gain access to registers at %p: %s.\n", 135 ret, str_error(ret), io); 134 136 instance->registers = io; 135 usb_log_debug("Device registers a ccessible.\n");137 usb_log_debug("Device registers at %p(%u) accessible.\n", io, reg_size); 136 138 137 139 ret = uhci_init_mem_structures(instance); 138 CHECK_RET_ RETURN(ret, "Failed to initializememory structures.\n");140 CHECK_RET_DEST_FUN_RETURN(ret, "Failed to initialize UHCI memory structures.\n"); 139 141 140 142 uhci_init_hw(instance); 141 143 142 144 instance->cleaner = fibril_create(uhci_interrupt_emulator, instance); 143 //fibril_add_ready(instance->cleaner);145 fibril_add_ready(instance->cleaner); 144 146 145 147 instance->debug_checker = fibril_create(uhci_debug_checker, instance); 146 148 fibril_add_ready(instance->debug_checker); 147 149 148 return EOK; 150 usb_log_info("Started UHCI driver.\n"); 151 return EOK; 152 #undef CHECK_RET_DEST_FUN_RETURN 149 153 } 150 154 /*----------------------------------------------------------------------------*/ 151 155 void uhci_init_hw(uhci_t *instance) 152 156 { 157 /* reset everything, who knows what touched it before us */ 158 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET); 159 async_usleep(10000); /* 10ms according to USB spec */ 160 pio_write_16(&instance->registers->usbcmd, 0); 161 162 /* reset hc, all states and counters */ 163 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET); 164 while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0) 165 { async_usleep(10); } 153 166 154 167 /* set framelist pointer */ … … 163 176 pio_write_16(&instance->registers->usbcmd, 164 177 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); 165 usb_log_debug("Started UHCI HC.\n");166 178 } 167 179 /*----------------------------------------------------------------------------*/ … … 169 181 { 170 182 assert(instance); 183 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \ 184 if (ret != EOK) { \ 185 usb_log_error(message); \ 186 if (instance->interrupt_code.cmds != NULL) \ 187 free(instance->interrupt_code.cmds); \ 188 return ret; \ 189 } else (void) 0 171 190 172 191 /* init interrupt code */ 173 irq_cmd_t *interrupt_commands = malloc(sizeof(uhci_cmds)); 174 if (interrupt_commands == NULL) { 175 return ENOMEM; 176 } 177 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 178 interrupt_commands[0].addr = (void*)&instance->registers->usbsts; 179 interrupt_commands[1].addr = (void*)&instance->registers->usbsts; 180 instance->interrupt_code.cmds = interrupt_commands; 181 instance->interrupt_code.cmdcount = 182 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 192 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 193 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 194 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n"); 195 196 { 197 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 198 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 199 interrupt_commands[0].addr = (void*)&instance->registers->usbsts; 200 interrupt_commands[1].addr = (void*)&instance->registers->usbsts; 201 instance->interrupt_code.cmdcount = 202 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 203 } 183 204 184 205 /* init transfer lists */ 185 intret = uhci_init_transfer_lists(instance);186 CHECK_RET_ RETURN(ret, "Failed to initialize transfer lists.\n");206 ret = uhci_init_transfer_lists(instance); 207 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n"); 187 208 usb_log_debug("Initialized transfer lists.\n"); 188 209 … … 190 211 instance->frame_list = get_page(); 191 212 ret = instance ? EOK : ENOMEM; 192 CHECK_RET_ RETURN(ret, "Failed to get frame list page.\n");213 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n"); 193 214 usb_log_debug("Initialized frame list.\n"); 194 215 … … 197 218 instance->transfers_interrupt.queue_head_pa 198 219 | LINK_POINTER_QUEUE_HEAD_FLAG; 220 199 221 unsigned i = 0; 200 222 for(; i < UHCI_FRAME_LIST_COUNT; ++i) { … … 203 225 204 226 /* init address keeper(libusb) */ 205 usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX); 206 usb_log_debug("Initialized address manager.\n"); 207 208 return EOK; 227 device_keeper_init(&instance->device_manager); 228 usb_log_debug("Initialized device manager.\n"); 229 230 return EOK; 231 #undef CHECK_RET_DEST_CMDS_RETURN 209 232 } 210 233 /*----------------------------------------------------------------------------*/ … … 212 235 { 213 236 assert(instance); 237 #define CHECK_RET_CLEAR_RETURN(ret, message...) \ 238 if (ret != EOK) { \ 239 usb_log_error(message); \ 240 transfer_list_fini(&instance->transfers_bulk_full); \ 241 transfer_list_fini(&instance->transfers_control_full); \ 242 transfer_list_fini(&instance->transfers_control_slow); \ 243 transfer_list_fini(&instance->transfers_interrupt); \ 244 return ret; \ 245 } else (void) 0 214 246 215 247 /* initialize TODO: check errors */ 216 248 int ret; 217 249 ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL"); 218 assert(ret == EOK);250 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 219 251 ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL"); 220 assert(ret == EOK);252 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 221 253 ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW"); 222 assert(ret == EOK);254 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 223 255 ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT"); 224 assert(ret == EOK);256 CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list."); 225 257 226 258 transfer_list_set_next(&instance->transfers_control_full, … … 249 281 250 282 return EOK; 283 #undef CHECK_RET_CLEAR_RETURN 251 284 } 252 285 /*----------------------------------------------------------------------------*/ … … 255 288 assert(instance); 256 289 assert(batch); 257 const int low_speed = (batch->speed == LOW_SPEED);290 const int low_speed = (batch->speed == USB_SPEED_LOW); 258 291 if (!allowed_usb_packet( 259 292 low_speed, batch->transfer_type, batch->max_packet_size)) { … … 276 309 { 277 310 assert(instance); 278 if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)279 return;280 usb_log_debug("UHCI interrupt: %X.\n", status);281 transfer_list_ check(&instance->transfers_interrupt);282 transfer_list_ check(&instance->transfers_control_slow);283 transfer_list_ check(&instance->transfers_control_full);284 transfer_list_ check(&instance->transfers_bulk_full);311 // if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0) 312 // return; 313 // usb_log_debug2("UHCI interrupt: %X.\n", status); 314 transfer_list_remove_finished(&instance->transfers_interrupt); 315 transfer_list_remove_finished(&instance->transfers_control_slow); 316 transfer_list_remove_finished(&instance->transfers_control_full); 317 transfer_list_remove_finished(&instance->transfers_bulk_full); 285 318 } 286 319 /*----------------------------------------------------------------------------*/ … … 291 324 assert(instance); 292 325 293 while (1) {326 while (1) { 294 327 uint16_t status = pio_read_16(&instance->registers->usbsts); 328 if (status != 0) 329 usb_log_debug2("UHCI status: %x.\n", status); 330 status |= 1; 295 331 uhci_interrupt(instance, status); 296 async_usleep(UHCI_CLEANER_TIMEOUT); 332 pio_write_16(&instance->registers->usbsts, 0x1f); 333 async_usleep(UHCI_CLEANER_TIMEOUT * 5); 297 334 } 298 335 return EOK; … … 307 344 const uint16_t sts = pio_read_16(&instance->registers->usbsts); 308 345 const uint16_t intr = pio_read_16(&instance->registers->usbintr); 309 usb_log_debug("Command: %X Status: %X Interrupts: %x\n", 310 cmd, sts, intr); 311 312 uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd); 346 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) { 347 usb_log_debug2("Command: %X Status: %X Intr: %x\n", 348 cmd, sts, intr); 349 } 350 351 uintptr_t frame_list = 352 pio_read_32(&instance->registers->flbaseadd) & ~0xfff; 313 353 if (frame_list != addr_to_phys(instance->frame_list)) { 314 354 usb_log_debug("Framelist address: %p vs. %p.\n",
Note:
See TracChangeset
for help on using the changeset viewer.