Changes in uspace/drv/ohci/hc.c [aa9ccf7:9ff5ff82] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/hc.c
raa9ccf7 r9ff5ff82 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 119 110 if (!interrupts) { 120 111 instance->interrupt_emulator = … … 123 114 } 124 115 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 */ 125 124 return EOK; 126 125 } … … 136 135 } 137 136 138 fibril_mutex_lock(&instance->guard); 137 transfer_list_add_batch( 138 instance->transfers[batch->transfer_type], batch); 139 139 140 switch (batch->transfer_type) { 140 141 case USB_TRANSFER_CONTROL: 141 instance->registers->control &= ~C_CLE;142 transfer_list_add_batch(143 instance->transfers[batch->transfer_type], batch);144 142 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;149 143 break; 150 144 case USB_TRANSFER_BULK: 151 instance->registers->control &= ~C_BLE;152 transfer_list_add_batch(153 instance->transfers[batch->transfer_type], batch);154 145 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);167 146 break; 168 147 default: 169 148 break; 170 149 } 171 fibril_mutex_unlock(&instance->guard);172 150 return EOK; 173 151 } … … 176 154 { 177 155 assert(instance); 178 if ( (status & ~IS_SF) == 0) /* ignore sof status */156 if (status == 0) 179 157 return; 180 158 if (status & IS_RHSC) 181 159 rh_interrupt(&instance->rh); 182 160 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); 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); 209 175 } 210 176 } … … 218 184 instance->registers->interrupt_status = status; 219 185 hc_interrupt(instance, status); 220 async_usleep( 50000);186 async_usleep(1000); 221 187 } 222 188 return EOK; … … 226 192 { 227 193 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 235 194 /* Interrupt routing enabled => smm driver is active */ 236 195 if (instance->registers->control & C_IR) { 237 usb_log_ debug("SMM driver: requestownership change.\n");196 usb_log_info("Found SMM driver requesting ownership change.\n"); 238 197 instance->registers->command_status |= CS_OCR; 239 198 while (instance->registers->control & C_IR) { 240 199 async_usleep(1000); 241 200 } 242 usb_log_info(" SMM driver: Ownership taken.\n");201 usb_log_info("Ownership taken from SMM driver.\n"); 243 202 return; 244 203 } … … 248 207 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 249 208 if (hc_status != C_HCFS_RESET) { 250 usb_log_ debug("BIOS driver found.\n");209 usb_log_info("Found BIOS driver.\n"); 251 210 if (hc_status == C_HCFS_OPERATIONAL) { 252 usb_log_info(" BIOS driver: HC operational.\n");211 usb_log_info("HC operational(BIOS).\n"); 253 212 return; 254 213 } … … 256 215 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT); 257 216 async_usleep(20000); 258 usb_log_info("BIOS driver: HC resumed.\n");259 217 return; 260 218 } … … 262 220 /* HC is in reset (hw startup) => no other driver 263 221 * maintain reset for at least the time specified in USB spec (50 ms)*/ 264 usb_log_info("HC found in reset.\n");265 222 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 266 231 } 267 232 /*----------------------------------------------------------------------------*/ 268 233 void hc_init_hw(hc_t *instance) 269 234 { 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 */ 235 assert(instance); 275 236 const uint32_t fm_interval = instance->registers->fm_interval; 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; 237 238 /* reset hc */ 281 239 instance->registers->command_status = CS_HCR; 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 */ 240 async_usleep(10); 241 242 /* restore fm_interval */ 289 243 instance->registers->fm_interval = fm_interval; 290 244 assert((instance->registers->command_status & CS_HCR) == 0); 291 245 292 246 /* hc is now in suspend state */ 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 */ 247 248 /* enable queues */ 312 249 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); 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); 250 /* TODO: enable interrupts */ 251 /* set periodic start to 90% */ 252 instance->registers->periodic_start = (fm_interval / 10) * 9; 330 253 331 254 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT); 332 usb_log_info("OHCI HC up and running(%x).\n", 333 instance->registers->control); 255 usb_log_info("OHCI HC up and running.\n"); 334 256 } 335 257 /*----------------------------------------------------------------------------*/ … … 355 277 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 356 278 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 357 #undef SETUP_TRANSFER_LIST 279 358 280 transfer_list_set_next(&instance->transfers_interrupt, 359 281 &instance->transfers_isochronous); … … 370 292 371 293 return EOK; 294 #undef CHECK_RET_CLEAR_RETURN 372 295 } 373 296 /*----------------------------------------------------------------------------*/ … … 375 298 { 376 299 assert(instance); 377 /* Init queues */300 /* init queues */ 378 301 hc_init_transfer_lists(instance); 379 302 380 /* Init HCCA */303 /* init HCCA */ 381 304 instance->hcca = malloc32(sizeof(hcca_t)); 382 305 if (instance->hcca == NULL) 383 306 return ENOMEM; 384 307 bzero(instance->hcca, sizeof(hcca_t)); 385 usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca); 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; 386 314 387 315 unsigned i = 0; … … 390 318 instance->transfers_interrupt.list_head_pa; 391 319 } 392 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",393 instance->transfers_interrupt.list_head,394 instance->transfers_interrupt.list_head_pa);395 320 396 321 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.