Changes in uspace/drv/ohci/hc.c [9ff5ff82:aa9ccf7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/hc.c
r9ff5ff82 raa9ccf7 108 108 ret, str_error(ret)); 109 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 fibril_mutex_initialize(&instance->guard); 116 117 rh_init(&instance->rh, dev, instance->registers); 118 110 119 if (!interrupts) { 111 120 instance->interrupt_emulator = … … 114 123 } 115 124 116 hc_gain_control(instance);117 118 rh_init(&instance->rh, dev, instance->registers);119 120 hc_init_memory(instance);121 hc_init_hw(instance);122 123 /* TODO: implement */124 125 return EOK; 125 126 } … … 135 136 } 136 137 137 transfer_list_add_batch( 138 instance->transfers[batch->transfer_type], batch); 139 138 fibril_mutex_lock(&instance->guard); 140 139 switch (batch->transfer_type) { 141 140 case USB_TRANSFER_CONTROL: 141 instance->registers->control &= ~C_CLE; 142 transfer_list_add_batch( 143 instance->transfers[batch->transfer_type], batch); 142 144 instance->registers->command_status |= CS_CLF; 145 usb_log_debug2("Set CS control transfer filled: %x.\n", 146 instance->registers->command_status); 147 instance->registers->control_current = 0; 148 instance->registers->control |= C_CLE; 143 149 break; 144 150 case USB_TRANSFER_BULK: 151 instance->registers->control &= ~C_BLE; 152 transfer_list_add_batch( 153 instance->transfers[batch->transfer_type], batch); 145 154 instance->registers->command_status |= CS_BLF; 155 usb_log_debug2("Set bulk transfer filled: %x.\n", 156 instance->registers->command_status); 157 instance->registers->control |= C_BLE; 158 break; 159 case USB_TRANSFER_INTERRUPT: 160 case USB_TRANSFER_ISOCHRONOUS: 161 instance->registers->control &= (~C_PLE & ~C_IE); 162 transfer_list_add_batch( 163 instance->transfers[batch->transfer_type], batch); 164 instance->registers->control |= C_PLE | C_IE; 165 usb_log_debug2("Added periodic transfer: %x.\n", 166 instance->registers->periodic_current); 146 167 break; 147 168 default: 148 169 break; 149 170 } 171 fibril_mutex_unlock(&instance->guard); 150 172 return EOK; 151 173 } … … 154 176 { 155 177 assert(instance); 156 if ( status == 0)178 if ((status & ~IS_SF) == 0) /* ignore sof status */ 157 179 return; 158 180 if (status & IS_RHSC) 159 181 rh_interrupt(&instance->rh); 160 182 161 usb_log_info("OHCI interrupt: %x.\n", status); 162 163 LIST_INITIALIZE(done); 164 transfer_list_remove_finished(&instance->transfers_interrupt, &done); 165 transfer_list_remove_finished(&instance->transfers_isochronous, &done); 166 transfer_list_remove_finished(&instance->transfers_control, &done); 167 transfer_list_remove_finished(&instance->transfers_bulk, &done); 168 169 while (!list_empty(&done)) { 170 link_t *item = done.next; 171 list_remove(item); 172 usb_transfer_batch_t *batch = 173 list_get_instance(item, usb_transfer_batch_t, link); 174 usb_transfer_batch_finish(batch); 183 usb_log_debug("OHCI interrupt: %x.\n", status); 184 185 if (status & IS_WDH) { 186 fibril_mutex_lock(&instance->guard); 187 usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca, 188 instance->registers->hcca, addr_to_phys(instance->hcca)); 189 usb_log_debug2("Periodic current: %p.\n", 190 instance->registers->periodic_current); 191 LIST_INITIALIZE(done); 192 transfer_list_remove_finished( 193 &instance->transfers_interrupt, &done); 194 transfer_list_remove_finished( 195 &instance->transfers_isochronous, &done); 196 transfer_list_remove_finished( 197 &instance->transfers_control, &done); 198 transfer_list_remove_finished( 199 &instance->transfers_bulk, &done); 200 201 while (!list_empty(&done)) { 202 link_t *item = done.next; 203 list_remove(item); 204 usb_transfer_batch_t *batch = 205 list_get_instance(item, usb_transfer_batch_t, link); 206 usb_transfer_batch_finish(batch); 207 } 208 fibril_mutex_unlock(&instance->guard); 175 209 } 176 210 } … … 184 218 instance->registers->interrupt_status = status; 185 219 hc_interrupt(instance, status); 186 async_usleep( 1000);220 async_usleep(50000); 187 221 } 188 222 return EOK; … … 192 226 { 193 227 assert(instance); 228 /* Turn off legacy emulation */ 229 volatile uint32_t *ohci_emulation_reg = 230 (uint32_t*)((char*)instance->registers + 0x100); 231 usb_log_debug("OHCI legacy register %p: %x.\n", 232 ohci_emulation_reg, *ohci_emulation_reg); 233 *ohci_emulation_reg = 0; 234 194 235 /* Interrupt routing enabled => smm driver is active */ 195 236 if (instance->registers->control & C_IR) { 196 usb_log_ info("Found SMM driver requestingownership change.\n");237 usb_log_debug("SMM driver: request ownership change.\n"); 197 238 instance->registers->command_status |= CS_OCR; 198 239 while (instance->registers->control & C_IR) { 199 240 async_usleep(1000); 200 241 } 201 usb_log_info(" Ownership taken from SMM driver.\n");242 usb_log_info("SMM driver: Ownership taken.\n"); 202 243 return; 203 244 } … … 207 248 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 208 249 if (hc_status != C_HCFS_RESET) { 209 usb_log_ info("Found BIOS driver.\n");250 usb_log_debug("BIOS driver found.\n"); 210 251 if (hc_status == C_HCFS_OPERATIONAL) { 211 usb_log_info(" HC operational(BIOS).\n");252 usb_log_info("BIOS driver: HC operational.\n"); 212 253 return; 213 254 } … … 215 256 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT); 216 257 async_usleep(20000); 258 usb_log_info("BIOS driver: HC resumed.\n"); 217 259 return; 218 260 } … … 220 262 /* HC is in reset (hw startup) => no other driver 221 263 * maintain reset for at least the time specified in USB spec (50 ms)*/ 264 usb_log_info("HC found in reset.\n"); 222 265 async_usleep(50000); 223 224 /* turn off legacy emulation */225 volatile uint32_t *ohci_emulation_reg =226 (uint32_t*)((char*)instance->registers + 0x100);227 usb_log_info("OHCI legacy register status %p: %x.\n",228 ohci_emulation_reg, *ohci_emulation_reg);229 *ohci_emulation_reg = 0;230 231 266 } 232 267 /*----------------------------------------------------------------------------*/ 233 268 void hc_init_hw(hc_t *instance) 234 269 { 235 assert(instance); 270 /* OHCI guide page 42 */ 271 assert(instance); 272 usb_log_debug2("Started hc initialization routine.\n"); 273 274 /* Save contents of fm_interval register */ 236 275 const uint32_t fm_interval = instance->registers->fm_interval; 237 238 /* reset hc */ 276 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval); 277 278 /* Reset hc */ 279 usb_log_debug2("HC reset.\n"); 280 size_t time = 0; 239 281 instance->registers->command_status = CS_HCR; 240 async_usleep(10); 241 242 /* restore fm_interval */ 282 while (instance->registers->command_status & CS_HCR) { 283 async_usleep(10); 284 time += 10; 285 } 286 usb_log_debug2("HC reset complete in %zu us.\n", time); 287 288 /* Restore fm_interval */ 243 289 instance->registers->fm_interval = fm_interval; 244 290 assert((instance->registers->command_status & CS_HCR) == 0); 245 291 246 292 /* hc is now in suspend state */ 247 248 /* enable queues */ 293 usb_log_debug2("HC should be in suspend state(%x).\n", 294 instance->registers->control); 295 296 /* Use HCCA */ 297 instance->registers->hcca = addr_to_phys(instance->hcca); 298 299 /* Use queues */ 300 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 301 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 302 instance->transfers_bulk.list_head, 303 instance->transfers_bulk.list_head_pa); 304 305 instance->registers->control_head = 306 instance->transfers_control.list_head_pa; 307 usb_log_debug2("Control HEAD set to: %p(%p).\n", 308 instance->transfers_control.list_head, 309 instance->transfers_control.list_head_pa); 310 311 /* Enable queues */ 249 312 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); 250 /* TODO: enable interrupts */ 251 /* set periodic start to 90% */ 252 instance->registers->periodic_start = (fm_interval / 10) * 9; 313 usb_log_debug2("All queues enabled(%x).\n", 314 instance->registers->control); 315 316 /* Disable interrupts */ 317 instance->registers->interrupt_disable = I_SF | I_OC; 318 usb_log_debug2("Disabling interrupts: %x.\n", 319 instance->registers->interrupt_disable); 320 instance->registers->interrupt_disable = I_MI; 321 usb_log_debug2("Enabled interrupts: %x.\n", 322 instance->registers->interrupt_enable); 323 324 /* Set periodic start to 90% */ 325 uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK); 326 instance->registers->periodic_start = (frame_length / 10) * 9; 327 usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n", 328 instance->registers->periodic_start, 329 instance->registers->periodic_start, frame_length); 253 330 254 331 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT); 255 usb_log_info("OHCI HC up and running.\n"); 332 usb_log_info("OHCI HC up and running(%x).\n", 333 instance->registers->control); 256 334 } 257 335 /*----------------------------------------------------------------------------*/ … … 277 355 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 278 356 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 279 357 #undef SETUP_TRANSFER_LIST 280 358 transfer_list_set_next(&instance->transfers_interrupt, 281 359 &instance->transfers_isochronous); … … 292 370 293 371 return EOK; 294 #undef CHECK_RET_CLEAR_RETURN295 372 } 296 373 /*----------------------------------------------------------------------------*/ … … 298 375 { 299 376 assert(instance); 300 /* init queues */377 /* Init queues */ 301 378 hc_init_transfer_lists(instance); 302 379 303 /* init HCCA */380 /*Init HCCA */ 304 381 instance->hcca = malloc32(sizeof(hcca_t)); 305 382 if (instance->hcca == NULL) 306 383 return ENOMEM; 307 384 bzero(instance->hcca, sizeof(hcca_t)); 308 instance->registers->hcca = addr_to_phys(instance->hcca); 309 310 /* use queues */ 311 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 312 instance->registers->control_head = 313 instance->transfers_control.list_head_pa; 385 usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca); 314 386 315 387 unsigned i = 0; … … 318 390 instance->transfers_interrupt.list_head_pa; 319 391 } 392 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 393 instance->transfers_interrupt.list_head, 394 instance->transfers_interrupt.list_head_pa); 320 395 321 396 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.