Changeset dc4c19e in mainline for uspace/drv/ohci/hc.c
- Timestamp:
- 2011-04-10T12:18:09Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 60c0573
- Parents:
- a49e171 (diff), 82e8861 (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/ohci/hc.c
ra49e171 rdc4c19e 47 47 static void hc_gain_control(hc_t *instance); 48 48 static void hc_init_hw(hc_t *instance); 49 static int hc_init_transfer_lists(hc_t *instance); 50 static int hc_init_memory(hc_t *instance); 49 51 /*----------------------------------------------------------------------------*/ 50 52 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun) … … 59 61 &instance->manager, hub_address, hub_fun->handle); 60 62 63 endpoint_t *ep = malloc(sizeof(endpoint_t)); 64 assert(ep); 65 int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH, 66 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64); 67 assert(ret == EOK); 68 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0); 69 assert(ret == EOK); 70 61 71 char *match_str = NULL; 62 intret = asprintf(&match_str, "usb&class=hub");63 ret = (match_str == NULL) ? ret : EOK;72 ret = asprintf(&match_str, "usb&class=hub"); 73 // ret = (match_str == NULL) ? ret : EOK; 64 74 if (ret < 0) { 65 usb_log_error("Failed to create root hub match-id string.\n"); 75 usb_log_error( 76 "Failed(%d) to create root hub match-id string.\n", ret); 66 77 return ret; 67 78 } … … 97 108 ret, str_error(ret)); 98 109 110 hc_gain_control(instance); 111 ret = hc_init_memory(instance); 112 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n", 113 ret, str_error(ret)); 114 hc_init_hw(instance); 115 116 rh_init(&instance->rh, dev, instance->registers); 117 99 118 if (!interrupts) { 100 119 instance->interrupt_emulator = … … 103 122 } 104 123 105 hc_gain_control(instance);106 107 rh_init(&instance->rh, dev, instance->registers);108 109 hc_init_hw(instance);110 111 /* TODO: implement */112 124 return EOK; 113 125 } … … 117 129 assert(instance); 118 130 assert(batch); 131 132 /* check for root hub communication */ 119 133 if (batch->target.address == instance->rh.address) { 120 134 return rh_request(&instance->rh, batch); 121 135 } 122 /* TODO: implement */ 123 return ENOTSUP; 136 137 transfer_list_add_batch( 138 instance->transfers[batch->transfer_type], batch); 139 140 switch (batch->transfer_type) { 141 case USB_TRANSFER_CONTROL: 142 instance->registers->control &= ~C_CLE; 143 instance->registers->command_status |= CS_CLF; 144 usb_log_debug2("Set control transfer filled: %x.\n", 145 instance->registers->command_status); 146 instance->registers->control |= C_CLE; 147 break; 148 case USB_TRANSFER_BULK: 149 instance->registers->command_status |= CS_BLF; 150 usb_log_debug2("Set bulk transfer filled: %x.\n", 151 instance->registers->command_status); 152 break; 153 default: 154 break; 155 } 156 return EOK; 124 157 } 125 158 /*----------------------------------------------------------------------------*/ … … 127 160 { 128 161 assert(instance); 129 if ( status == 0)162 if ((status & ~IS_SF) == 0) /* ignore sof status */ 130 163 return; 131 164 if (status & IS_RHSC) … … 134 167 usb_log_info("OHCI interrupt: %x.\n", status); 135 168 136 /* TODO: Check for further interrupt causes */ 137 /* TODO: implement */ 169 170 LIST_INITIALIZE(done); 171 transfer_list_remove_finished(&instance->transfers_interrupt, &done); 172 transfer_list_remove_finished(&instance->transfers_isochronous, &done); 173 transfer_list_remove_finished(&instance->transfers_control, &done); 174 transfer_list_remove_finished(&instance->transfers_bulk, &done); 175 176 while (!list_empty(&done)) { 177 link_t *item = done.next; 178 list_remove(item); 179 usb_transfer_batch_t *batch = 180 list_get_instance(item, usb_transfer_batch_t, link); 181 usb_transfer_batch_finish(batch); 182 } 138 183 } 139 184 /*----------------------------------------------------------------------------*/ … … 154 199 { 155 200 assert(instance); 201 /* Turn off legacy emulation */ 202 volatile uint32_t *ohci_emulation_reg = 203 (uint32_t*)((char*)instance->registers + 0x100); 204 usb_log_debug("OHCI legacy register %p: %x.\n", 205 ohci_emulation_reg, *ohci_emulation_reg); 206 *ohci_emulation_reg = 0; 207 156 208 /* Interrupt routing enabled => smm driver is active */ 157 209 if (instance->registers->control & C_IR) { 158 usb_log_ info("Found SMM driver requestingownership change.\n");210 usb_log_debug("SMM driver: request ownership change.\n"); 159 211 instance->registers->command_status |= CS_OCR; 160 212 while (instance->registers->control & C_IR) { 161 213 async_usleep(1000); 162 214 } 163 usb_log_info(" Ownership taken from SMM driver.\n");215 usb_log_info("SMM driver: Ownership taken.\n"); 164 216 return; 165 217 } … … 169 221 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 170 222 if (hc_status != C_HCFS_RESET) { 171 usb_log_ info("Found BIOS driver.\n");223 usb_log_debug("BIOS driver found.\n"); 172 224 if (hc_status == C_HCFS_OPERATIONAL) { 173 usb_log_info(" HC operational(BIOS).\n");225 usb_log_info("BIOS driver: HC operational.\n"); 174 226 return; 175 227 } … … 177 229 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT); 178 230 async_usleep(20000); 231 usb_log_info("BIOS driver: HC resumed.\n"); 179 232 return; 180 233 } … … 182 235 /* HC is in reset (hw startup) => no other driver 183 236 * maintain reset for at least the time specified in USB spec (50 ms)*/ 237 usb_log_info("HC found in reset.\n"); 184 238 async_usleep(50000); 185 186 /* turn off legacy emulation */187 volatile uint32_t *ohci_emulation_reg =188 (uint32_t*)((char*)instance->registers + 0x100);189 usb_log_info("OHCI legacy register status %p: %x.\n",190 ohci_emulation_reg, *ohci_emulation_reg);191 *ohci_emulation_reg = 0;192 193 239 } 194 240 /*----------------------------------------------------------------------------*/ 195 241 void hc_init_hw(hc_t *instance) 196 242 { 197 assert(instance); 243 /* OHCI guide page 42 */ 244 assert(instance); 245 usb_log_debug2("Started hc initialization routine.\n"); 246 247 /* Save contents of fm_interval register */ 198 248 const uint32_t fm_interval = instance->registers->fm_interval; 249 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval); 250 251 /* Reset hc */ 252 usb_log_debug2("HC reset.\n"); 253 size_t time = 0; 199 254 instance->registers->command_status = CS_HCR; 200 async_usleep(10); 255 while (instance->registers->command_status & CS_HCR) { 256 async_usleep(10); 257 time += 10; 258 } 259 usb_log_debug2("HC reset complete in %zu us.\n", time); 260 261 /* Restore fm_interval */ 201 262 instance->registers->fm_interval = fm_interval; 202 263 assert((instance->registers->command_status & CS_HCR) == 0); 264 203 265 /* hc is now in suspend state */ 204 /* TODO: init HCCA block */ 205 /* TODO: init queues */ 206 /* TODO: enable queues */ 207 /* TODO: enable interrupts */ 208 /* TODO: set periodic start to 90% */ 266 usb_log_debug2("HC should be in suspend state(%x).\n", 267 instance->registers->control); 268 269 /* Enable queues */ 270 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); 271 usb_log_debug2("All queues enabled(%x).\n", 272 instance->registers->control); 273 274 /* Disable interrupts */ 275 instance->registers->interrupt_disable = I_SF | I_OC; 276 usb_log_debug2("Disabling interrupts: %x.\n", 277 instance->registers->interrupt_disable); 278 instance->registers->interrupt_disable = I_MI; 279 usb_log_debug2("Enabled interrupts: %x.\n", 280 instance->registers->interrupt_enable); 281 282 /* Set periodic start to 90% */ 283 uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK); 284 instance->registers->periodic_start = (frame_length / 10) * 9; 285 usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n", 286 instance->registers->periodic_start, 287 instance->registers->periodic_start, frame_length); 209 288 210 289 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT); 211 usb_log_info("OHCI HC up and running.\n"); 290 usb_log_info("OHCI HC up and running(%x).\n", 291 instance->registers->control); 292 } 293 /*----------------------------------------------------------------------------*/ 294 int hc_init_transfer_lists(hc_t *instance) 295 { 296 assert(instance); 297 298 #define SETUP_TRANSFER_LIST(type, name) \ 299 do { \ 300 int ret = transfer_list_init(&instance->type, name); \ 301 if (ret != EOK) { \ 302 usb_log_error("Failed(%d) to setup %s transfer list.\n", \ 303 ret, name); \ 304 transfer_list_fini(&instance->transfers_isochronous); \ 305 transfer_list_fini(&instance->transfers_interrupt); \ 306 transfer_list_fini(&instance->transfers_control); \ 307 transfer_list_fini(&instance->transfers_bulk); \ 308 } \ 309 } while (0) 310 311 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 312 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 313 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 314 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 315 316 transfer_list_set_next(&instance->transfers_interrupt, 317 &instance->transfers_isochronous); 318 319 /* Assign pointers to be used during scheduling */ 320 instance->transfers[USB_TRANSFER_INTERRUPT] = 321 &instance->transfers_interrupt; 322 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 323 &instance->transfers_interrupt; 324 instance->transfers[USB_TRANSFER_CONTROL] = 325 &instance->transfers_control; 326 instance->transfers[USB_TRANSFER_BULK] = 327 &instance->transfers_bulk; 328 329 return EOK; 330 #undef CHECK_RET_CLEAR_RETURN 331 } 332 /*----------------------------------------------------------------------------*/ 333 int hc_init_memory(hc_t *instance) 334 { 335 assert(instance); 336 /* Init queues */ 337 hc_init_transfer_lists(instance); 338 339 /*Init HCCA */ 340 instance->hcca = malloc32(sizeof(hcca_t)); 341 if (instance->hcca == NULL) 342 return ENOMEM; 343 bzero(instance->hcca, sizeof(hcca_t)); 344 instance->registers->hcca = addr_to_phys(instance->hcca); 345 usb_log_debug2("OHCI HCCA initialized at %p(%p).\n", 346 instance->hcca, instance->registers->hcca); 347 348 /* Use queues */ 349 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 350 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 351 instance->transfers_bulk.list_head, 352 instance->transfers_bulk.list_head_pa); 353 354 instance->registers->control_head = 355 instance->transfers_control.list_head_pa; 356 usb_log_debug2("Control HEAD set to: %p(%p).\n", 357 instance->transfers_control.list_head, 358 instance->transfers_control.list_head_pa); 359 360 unsigned i = 0; 361 for (; i < 32; ++i) { 362 instance->hcca->int_ep[i] = 363 instance->transfers_interrupt.list_head_pa; 364 } 365 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 366 instance->transfers_interrupt.list_head, 367 instance->transfers_interrupt.list_head_pa); 368 369 return EOK; 212 370 } 213 371 /**
Note:
See TracChangeset
for help on using the changeset viewer.