Changeset 178 for trunk/src/os2ahci/ctxhook.c
- Timestamp:
- Nov 29, 2016, 5:30:22 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/os2ahci/ctxhook.c
r161 r178 4 4 * Copyright (c) 2011 thi.guten Software Development 5 5 * Copyright (c) 2011 Mensys B.V. 6 * Copyright (c) 2013-2016 David Azarewicz 6 7 * 7 8 * Authors: Christian Mueller, Markus Thielen … … 87 88 * in the interrupt and error handlers. 88 89 */ 89 void restart_ctxhook(ULONG parm)90 void _Syscall restart_ctxhook(ULONG parm) 90 91 { 91 92 IORB_QUEUE done_queue; 92 93 AD_INFO *ai; 93 IORBH _far *problem_iorb;94 IORBH _far *iorb;95 IORBH _far *next = NULL;96 u8 _far*port_mmio;94 IORBH FAR16DATA *vProblemIorb; 95 IORBH FAR16DATA *vIorb; 96 IORBH FAR16DATA *vNext = NULL; 97 u8 *port_mmio; 97 98 int rearm_ctx_hook = 0; 98 99 int need_reset; … … 101 102 int p; 102 103 103 dprintf("restart_ctxhook() started\n");104 DPRINTF(2,"restart_ctxhook() started\n"); 104 105 memset(&done_queue, 0x00, sizeof(done_queue)); 105 106 106 107 spin_lock(drv_lock); 107 108 108 for (a = 0; a < ad_info_cnt; a++) { 109 for (a = 0; a < ad_info_cnt; a++) 110 { 109 111 ai = ad_infos + a; 110 112 111 if (ai->busy) { 113 if (ai->busy) 114 { 112 115 /* this adapter is busy; leave it alone for now */ 113 116 rearm_ctx_hook = 1; … … 115 118 } 116 119 117 for (p = 0; p <= ai->port_max; p++) { 118 if (ports_to_restart[a] & (1UL << p)) { 120 for (p = 0; p <= ai->port_max; p++) 121 { 122 if (ports_to_restart[a] & (1UL << p)) 123 { 119 124 ports_to_restart[a] &= ~(1UL << p); 120 125 121 126 /* restart this port */ 122 127 port_mmio = port_base(ai, p); 123 problem_iorb = NULL;128 vProblemIorb = NULL; 124 129 need_reset = 0; 125 130 126 dprintf("port %d, TF_DATA: 0x%lx\n", p, readl(port_mmio + PORT_TFDATA));131 DPRINTF(2,"port %d, TF_DATA: 0x%x\n", p, readl(port_mmio + PORT_TFDATA)); 127 132 128 133 /* get "current command slot"; only valid if there are no NCQ cmds */ 129 134 ccs = (int) ((readl(port_mmio + PORT_CMD) >> 8) & 0x1f); 130 ddprintf(" PORT_CMD = 0x%x\n", ccs); 131 132 for (iorb = ai->ports[p].iorb_queue.root; iorb != NULL; iorb = next) { 133 ADD_WORKSPACE _far *aws = add_workspace(iorb); 134 next = iorb->pNxtIORB; 135 136 if (aws->queued_hw) { 137 if (ai->ports[p].ncq_cmds & (1UL << aws->cmd_slot)) { 135 DPRINTF(3," PORT_CMD = 0x%x\n", ccs); 136 137 for (vIorb = ai->ports[p].iorb_queue.vRoot; vIorb != NULL; vIorb = vNext) 138 { 139 IORBH *pIorb = Far16ToFlat(vIorb); 140 ADD_WORKSPACE *aws = add_workspace(pIorb); 141 vNext = pIorb->pNxtIORB; 142 143 if (aws->queued_hw) 144 { 145 if (ai->ports[p].ncq_cmds & (1UL << aws->cmd_slot)) 146 { 138 147 /* NCQ command; force non-NCQ mode and trigger port reset */ 139 148 ai->ports[p].ncq_cmds &= ~(1UL << aws->cmd_slot); 140 149 aws->no_ncq = 1; 141 150 need_reset = 1; 142 } else { 151 } 152 else 153 { 143 154 /* regular command; clear cmd bit and identify problem IORB */ 144 155 ai->ports[p].reg_cmds &= ~(1UL << aws->cmd_slot); 145 if (aws->cmd_slot == ccs) { 156 if (aws->cmd_slot == ccs) 157 { 146 158 /* this is the non-NCQ command that failed */ 147 ddprintf("failing IORB: %Fp\n", iorb);148 problem_iorb = iorb;159 DPRINTF(0,"failing IORB: %x\n", vIorb); 160 vProblemIorb = vIorb; 149 161 } 150 162 } 151 163 /* we can requeue all IORBs unconditionally (see function comment) */ 152 if (aws->retries++ < MAX_RETRIES) { 153 iorb_requeue(iorb); 154 155 } else { 164 if (aws->retries++ < MAX_RETRIES) 165 { 166 iorb_requeue(pIorb); 167 } 168 else 169 { 156 170 /* retry count exceeded; consider IORB aborted */ 157 iorb_seterr(iorb, IOERR_CMD_ABORTED); 158 iorb_queue_del(&ai->ports[p].iorb_queue, iorb); 159 iorb_queue_add(&done_queue, iorb); 160 if (iorb == problem_iorb) { 171 iorb_seterr(pIorb, IOERR_CMD_ABORTED); 172 iorb_queue_del(&ai->ports[p].iorb_queue, vIorb); 173 iorb_queue_add(&done_queue, vIorb, pIorb); 174 if (vIorb == vProblemIorb) 175 { 161 176 /* no further analysis -- we're done with this one */ 162 problem_iorb = NULL;177 vProblemIorb = NULL; 163 178 } 164 179 } … … 167 182 168 183 /* sanity check: issued command bitmaps should be 0 now */ 169 if (ai->ports[p].ncq_cmds != 0 || ai->ports[p].reg_cmds != 0) { 170 dprintf("warning: commands issued not 0 (%08lx/%08lx); resetting...\n", 184 if (ai->ports[p].ncq_cmds != 0 || ai->ports[p].reg_cmds != 0) 185 { 186 DPRINTF(0,"warning: commands issued not 0 (%08lx/%08lx); resetting...\n", 171 187 ai->ports[p].ncq_cmds, ai->ports[p].reg_cmds); 172 188 need_reset = 1; 173 189 } 174 190 175 if (!need_reset) { 176 if ((readl(port_mmio + PORT_TFDATA) & 0x88) != 0) { 191 if (!need_reset) 192 { 193 if ((readl(port_mmio + PORT_TFDATA) & 0x88) != 0) 194 { 177 195 /* device is not in an idle state */ 178 196 need_reset = 1; … … 183 201 ai->busy = 1; 184 202 spin_unlock(drv_lock); 185 if (need_reset) { 203 if (need_reset) 204 { 186 205 ahci_reset_port(ai, p, 1); 187 } else { 206 } 207 else 208 { 188 209 ahci_stop_port(ai, p); 189 210 ahci_start_port(ai, p, 1); … … 197 218 ai->ports[p].cmd_slot = 0; 198 219 199 if (problem_iorb != NULL) { 220 if (vProblemIorb != NULL) 221 { 222 IORBH *pProblemIorb = Far16ToFlat(vProblemIorb); 200 223 /* get details about the error that caused this IORB to fail */ 201 if (need_reset) { 224 if (need_reset) 225 { 202 226 /* no way to retrieve error details after a reset */ 203 iorb_seterr(problem_iorb, IOERR_DEVICE_NONSPECIFIC); 204 iorb_queue_del(&ai->ports[p].iorb_queue, problem_iorb); 205 iorb_queue_add(&done_queue, problem_iorb); 206 207 } else { 227 iorb_seterr(pProblemIorb, IOERR_DEVICE_NONSPECIFIC); 228 iorb_queue_del(&ai->ports[p].iorb_queue, vProblemIorb); 229 iorb_queue_add(&done_queue, vProblemIorb, pProblemIorb); 230 231 } 232 else 233 { 208 234 /* get sense information */ 209 ADD_WORKSPACE _far *aws = add_workspace(problem_iorb);210 int d = iorb_unit_device(p roblem_iorb);211 int (*req_sense)(IORBH _far*, int) = (ai->ports[p].devs[d].atapi) ?235 ADD_WORKSPACE *aws = add_workspace(pProblemIorb); 236 int d = iorb_unit_device(pProblemIorb); 237 int (*req_sense)(IORBH FAR16DATA *, IORBH *, int) = (ai->ports[p].devs[d].atapi) ? 212 238 atapi_req_sense : ata_req_sense; 213 239 … … 215 241 aws->queued_hw = 1; 216 242 217 if (req_sense(problem_iorb, 0) == 0) { 243 if (req_sense(vProblemIorb, pProblemIorb, 0) == 0) 244 { 218 245 /* execute request sense on slot #0 before anything else comes along */ 219 ADD_StartTimerMS(&aws->timer, 5000, (PFN) timeout_callback, 220 problem_iorb, 0); 246 Timer_StartTimerMS(&aws->timer, 5000, timeout_callback, CastFar16ToULONG(vProblemIorb)); 221 247 aws->cmd_slot = 0; 222 248 ai->ports[p].reg_cmds = 1; … … 224 250 readl(port_mmio); /* flush */ 225 251 226 } else { 252 } 253 else 254 { 227 255 /* IORB is expected to contain the error code; just move to done queue */ 228 iorb_queue_del(&ai->ports[p].iorb_queue, problem_iorb);229 iorb_queue_add(&done_queue, problem_iorb);256 iorb_queue_del(&ai->ports[p].iorb_queue, vProblemIorb); 257 iorb_queue_add(&done_queue, vProblemIorb, pProblemIorb); 230 258 } 231 259 } … … 238 266 239 267 /* call notification routine on all IORBs which have completed */ 240 for (iorb = done_queue.root; iorb != NULL; iorb = next) { 241 next = iorb->pNxtIORB; 268 for (vIorb = done_queue.vRoot; vIorb != NULL; vIorb = vNext) 269 { 270 IORBH *pIorb = Far16ToFlat(vIorb); 271 vNext = pIorb->pNxtIORB; 242 272 243 273 spin_lock(drv_lock); 244 aws_free(add_workspace( iorb));274 aws_free(add_workspace(pIorb)); 245 275 spin_unlock(drv_lock); 246 276 247 iorb_complete( iorb);277 iorb_complete(vIorb, pIorb); 248 278 } 249 279 … … 253 283 spin_unlock(drv_lock); 254 284 255 dprintf("restart_ctxhook() completed\n");285 DPRINTF(2,"restart_ctxhook() completed\n"); 256 286 257 287 /* Check whether we have to rearm ourselves because some adapters were busy 258 288 * when we wanted to restart ports on them. 259 289 */ 260 if (rearm_ctx_hook) { 290 if (rearm_ctx_hook) 291 { 261 292 msleep(250); 262 DevHelp_ArmCtxHook(0, restart_ctxhook_h);293 KernArmHook(restart_ctxhook_h, 0, 0); 263 294 } 264 295 } … … 290 321 * the upstream code might reuse the IORBs before we're done with them. 291 322 */ 292 void reset_ctxhook(ULONG parm)323 void _Syscall reset_ctxhook(ULONG parm) 293 324 { 294 325 IORB_QUEUE done_queue; 295 326 AD_INFO *ai; 296 IORBH _far *iorb;297 IORBH _far *next = NULL;327 IORBH FAR16DATA *vIorb; 328 IORBH FAR16DATA *vNext = NULL; 298 329 int rearm_ctx_hook = 0; 299 330 int a; 300 331 int p; 301 332 302 dprintf("reset_ctxhook() started\n");333 DPRINTF(2,"reset_ctxhook() started\n"); 303 334 memset(&done_queue, 0x00, sizeof(done_queue)); 304 335 305 336 spin_lock(drv_lock); 306 337 307 if (th_reset_watchdog != 0) { 338 if (th_reset_watchdog != 0) 339 { 308 340 /* watchdog timer still active -- just reset it */ 309 ADD_CancelTimer(th_reset_watchdog);341 Timer_CancelTimer(th_reset_watchdog); 310 342 th_reset_watchdog = 0; 311 343 } 312 344 313 345 /* add ports of active IORBs from the abort queue to ports_to_reset[] */ 314 for (iorb = abort_queue.root; iorb != NULL; iorb = next) { 315 next = iorb->pNxtIORB; 316 a = iorb_unit_adapter(iorb); 317 p = iorb_unit_port(iorb); 346 for (vIorb = abort_queue.vRoot; vIorb != NULL; vIorb = vNext) 347 { 348 IORBH *pIorb = Far16ToFlat(vIorb); 349 vNext = pIorb->pNxtIORB; 350 a = iorb_unit_adapter(pIorb); 351 p = iorb_unit_port(pIorb); 318 352 ai = ad_infos + a; 319 353 320 if (ai->busy) { 354 if (ai->busy) 355 { 321 356 /* this adapter is busy; leave it alone for now */ 322 357 rearm_ctx_hook = 1; … … 325 360 326 361 /* move IORB to the local 'done' queue */ 327 iorb_queue_del(&abort_queue, iorb);328 iorb_queue_add(&done_queue, iorb);362 iorb_queue_del(&abort_queue, vIorb); 363 iorb_queue_add(&done_queue, vIorb, pIorb); 329 364 330 365 /* reset port if the IORB has already been queued to hardware */ 331 if (add_workspace(iorb)->queued_hw) { 366 if (add_workspace(pIorb)->queued_hw) 367 { 332 368 /* prepare port reset */ 333 369 ports_to_reset[a] |= (1UL << p); … … 336 372 337 373 /* reset all ports in 'ports_to_reset[]' */ 338 for (a = 0; a < ad_info_cnt; a++) { 374 for (a = 0; a < ad_info_cnt; a++) 375 { 339 376 ai = ad_infos + a; 340 377 341 if (ai->busy) { 378 if (ai->busy) 379 { 342 380 /* this adapter is busy; leave it alone for now */ 343 381 rearm_ctx_hook = 1; … … 345 383 } 346 384 347 for (p = 0; p <= ai->port_max; p++) { 348 if (ports_to_reset[a] & (1UL << p)) { 385 for (p = 0; p <= ai->port_max; p++) 386 { 387 if (ports_to_reset[a] & (1UL << p)) 388 { 349 389 ports_to_reset[a] &= ~(1UL << p); 350 390 … … 366 406 367 407 /* retry or abort all remaining active commands on this port */ 368 for (iorb = ai->ports[p].iorb_queue.root; iorb != NULL; iorb = next) { 369 ADD_WORKSPACE _far *aws = add_workspace(iorb); 370 next = iorb->pNxtIORB; 371 372 if (aws->queued_hw) { 408 for (vIorb = ai->ports[p].iorb_queue.vRoot; vIorb != NULL; vIorb = vNext) 409 { 410 IORBH *pIorb = Far16ToFlat(vIorb); 411 ADD_WORKSPACE *aws = add_workspace(pIorb); 412 vNext = pIorb->pNxtIORB; 413 414 if (aws->queued_hw) 415 { 373 416 /* this IORB had already been queued to HW when we reset the port */ 374 if (aws->idempotent && aws->retries++ < MAX_RETRIES) { 417 if (aws->idempotent && aws->retries++ < MAX_RETRIES) 418 { 375 419 /* we can retry this IORB */ 376 iorb_requeue(iorb); 377 378 } else { 420 iorb_requeue(pIorb); 421 422 } 423 else 424 { 379 425 /* we cannot retry this IORB; consider it aborted */ 380 iorb->ErrorCode = IOERR_CMD_ABORTED;381 iorb_queue_del(&ai->ports[p].iorb_queue, iorb);382 iorb_queue_add(&done_queue, iorb);426 pIorb->ErrorCode = IOERR_CMD_ABORTED; 427 iorb_queue_del(&ai->ports[p].iorb_queue, vIorb); 428 iorb_queue_add(&done_queue, vIorb, pIorb); 383 429 } 384 430 } … … 391 437 392 438 /* complete all aborted IORBs */ 393 for (iorb = done_queue.root; iorb != NULL; iorb = next) { 394 next = iorb->pNxtIORB; 439 for (vIorb = done_queue.vRoot; vIorb != NULL; vIorb = vNext) 440 { 441 IORBH *pIorb = Far16ToFlat(vIorb); 442 vNext = pIorb->pNxtIORB; 395 443 396 444 spin_lock(drv_lock); 397 aws_free(add_workspace( iorb));445 aws_free(add_workspace(pIorb)); 398 446 spin_unlock(drv_lock); 399 447 400 iorb->Status |= IORB_ERROR;401 iorb_complete( iorb);448 pIorb->Status |= IORB_ERROR; 449 iorb_complete(vIorb, pIorb); 402 450 } 403 451 … … 407 455 spin_unlock(drv_lock); 408 456 409 dprintf("reset_ctxhook() completed\n");457 DPRINTF(2,"reset_ctxhook() completed\n"); 410 458 411 459 /* Check whether we have to rearm ourselves because some adapters were busy 412 460 * when we wanted to reset ports on them. 413 461 */ 414 if (rearm_ctx_hook) { 462 if (rearm_ctx_hook) 463 { 415 464 msleep(250); 416 DevHelp_ArmCtxHook(0, reset_ctxhook_h);465 KernArmHook(reset_ctxhook_h, 0, 0); 417 466 } 418 467 } … … 424 473 * busy system. Either way, this requires some task-time help. 425 474 */ 426 void engine_ctxhook(ULONG parm)475 void _Syscall engine_ctxhook(ULONG parm) 427 476 { 428 477 int iorbs_sent; 429 478 int i; 430 479 431 dprintf("engine_ctxhook() started\n"); 432 if (resume_sleep_flag) { 480 DPRINTF(2,"engine_ctxhook() started\n"); 481 if (resume_sleep_flag) 482 { 433 483 msleep(resume_sleep_flag); 434 484 resume_sleep_flag = 0; … … 436 486 437 487 spin_lock(drv_lock); 438 for (i = 0; i < 10; i++) { 439 if ((iorbs_sent = trigger_engine_1()) == 0) { 440 break; 441 } 488 for (i = 0; i < 10; i++) 489 { 490 if ((iorbs_sent = trigger_engine_1()) == 0) break; 442 491 } 443 492 spin_unlock(drv_lock); 444 493 445 dprintf("engine_ctxhook() completed\n"); 446 447 if (iorbs_sent != 0) { 494 DPRINTF(2,"engine_ctxhook() completed\n"); 495 496 if (iorbs_sent != 0) 497 { 448 498 /* need to rearm ourselves for another run */ 449 499 msleep(250); 450 DevHelp_ArmCtxHook(0, engine_ctxhook_h);500 KernArmHook(engine_ctxhook_h, 0, 0); 451 501 } 452 502 }
Note:
See TracChangeset
for help on using the changeset viewer.