aic7xxx.seq revision 43880
1/* 2 * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. 3 * 4 * Copyright (c) 1994-1999 Justin Gibbs. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer, 12 * without modification, immediately at the beginning of the file. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * Where this Software is combined with software released under the terms of 17 * the GNU Public License (GPL) and the terms of the GPL would require the 18 * combined work to also be released under the terms of the GPL, the terms 19 * and conditions of this License will apply in addition to those of the 20 * GPL with the exception of any terms or conditions of this License that 21 * conflict with, or are expressly prohibited by, the GPL. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $Id: aic7xxx.seq,v 1.84 1999/01/14 06:14:15 gibbs Exp $ 36 */ 37 38#include <dev/aic7xxx/aic7xxx.reg> 39#include <cam/scsi/scsi_message.h> 40 41/* 42 * A few words on the waiting SCB list: 43 * After starting the selection hardware, we check for reconnecting targets 44 * as well as for our selection to complete just in case the reselection wins 45 * bus arbitration. The problem with this is that we must keep track of the 46 * SCB that we've already pulled from the QINFIFO and started the selection 47 * on just in case the reselection wins so that we can retry the selection at 48 * a later time. This problem cannot be resolved by holding a single entry 49 * in scratch ram since a reconnecting target can request sense and this will 50 * create yet another SCB waiting for selection. The solution used here is to 51 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list 52 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, 53 * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to 54 * this list everytime a request sense occurs or after completing a non-tagged 55 * command for which a second SCB has been queued. The sequencer will 56 * automatically consume the entries. 57 */ 58 59reset: 60 clr SCSISIGO; /* De-assert BSY */ 61 and SXFRCTL1, ~BITBUCKET; 62 /* Always allow reselection */ 63 and SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE; 64 65 if ((ahc->features & AHC_CMD_CHAN) != 0) { 66 /* Ensure that no DMA operations are in progress */ 67 clr CCSGCTL; 68 clr CCSCBCTL; 69 } 70 71 call clear_target_state; 72poll_for_work: 73 and SXFRCTL0, ~SPIOEN; 74 if ((ahc->features & AHC_QUEUE_REGS) == 0) { 75 mov A, QINPOS; 76 } 77poll_for_work_loop: 78 if ((ahc->features & AHC_QUEUE_REGS) == 0) { 79 and SEQCTL, ~PAUSEDIS; 80 } 81 test SSTAT0, SELDO|SELDI jnz selection; 82 test SCSISEQ, ENSELO jnz poll_for_work; 83 if ((ahc->features & AHC_TWIN) != 0) { 84 /* 85 * Twin channel devices cannot handle things like SELTO 86 * interrupts on the "background" channel. So, if we 87 * are selecting, keep polling the current channel util 88 * either a selection or reselection occurs. 89 */ 90 xor SBLKCTL,SELBUSB; /* Toggle to the other bus */ 91 test SSTAT0, SELDO|SELDI jnz selection; 92 test SCSISEQ, ENSELO jnz poll_for_work; 93 xor SBLKCTL,SELBUSB; /* Toggle back */ 94 } 95 cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting; 96test_queue: 97 /* Has the driver posted any work for us? */ 98 if ((ahc->features & AHC_QUEUE_REGS) != 0) { 99 test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop; 100 mov NONE, SNSCB_QOFF; 101 inc QINPOS; 102 } else { 103 or SEQCTL, PAUSEDIS; 104 cmp KERNEL_QINPOS, A je poll_for_work_loop; 105 inc QINPOS; 106 and SEQCTL, ~PAUSEDIS; 107 } 108 109/* 110 * We have at least one queued SCB now and we don't have any 111 * SCBs in the list of SCBs awaiting selection. If we have 112 * any SCBs available for use, pull the tag from the QINFIFO 113 * and get to work on it. 114 */ 115 if ((ahc->flags & AHC_PAGESCBS) != 0) { 116 mov ALLZEROS call get_free_or_disc_scb; 117 } 118 119dequeue_scb: 120 add A, -1, QINPOS; 121 mvi QINFIFO_OFFSET call fetch_byte; 122 123 if ((ahc->flags & AHC_PAGESCBS) == 0) { 124 /* In the non-paging case, the SCBID == hardware SCB index */ 125 mov SCBPTR, RETURN_2; 126 } 127dma_queued_scb: 128/* 129 * DMA the SCB from host ram into the current SCB location. 130 */ 131 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; 132 mov RETURN_2 call dma_scb; 133 134/* 135 * Preset the residual fields in case we never go through a data phase. 136 * This isn't done by the host so we can avoid a DMA to clear these 137 * fields for the normal case of I/O that completes without underrun 138 * or overrun conditions. 139 */ 140 if ((ahc->features & AHC_CMD_CHAN) != 0) { 141 bmov SCB_RESID_DCNT, SCB_DATACNT, 3; 142 } else { 143 mov SCB_RESID_DCNT[0],SCB_DATACNT[0]; 144 mov SCB_RESID_DCNT[1],SCB_DATACNT[1]; 145 mov SCB_RESID_DCNT[2],SCB_DATACNT[2]; 146 } 147 mov SCB_RESID_SGCNT, SCB_SGCOUNT; 148 149start_scb: 150 /* 151 * Place us on the waiting list in case our selection 152 * doesn't win during bus arbitration. 153 */ 154 mov SCB_NEXT,WAITING_SCBH; 155 mov WAITING_SCBH, SCBPTR; 156start_waiting: 157 /* 158 * Pull the first entry off of the waiting SCB list. 159 */ 160 mov SCBPTR, WAITING_SCBH; 161 call start_selection; 162 jmp poll_for_work; 163 164start_selection: 165 if ((ahc->features & AHC_TWIN) != 0) { 166 and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */ 167 and A,SELBUSB,SCB_TCL; /* Get new channel bit */ 168 or SINDEX,A; 169 mov SBLKCTL,SINDEX; /* select channel */ 170 } 171initialize_scsiid: 172 if ((ahc->features & AHC_ULTRA2) != 0) { 173 and A, TID, SCB_TCL; /* Get target ID */ 174 and SCSIID_ULTRA2, OID; /* Clear old target */ 175 or SCSIID_ULTRA2, A; 176 } else { 177 and A, TID, SCB_TCL; /* Get target ID */ 178 and SCSIID, OID; /* Clear old target */ 179 or SCSIID, A; 180 } 181 mov SINDEX, SCSISEQ_TEMPLATE; 182 if ((ahc->flags & AHC_TARGETMODE) != 0) { 183 test SCB_CONTROL, TARGET_SCB jz . + 2; 184 or SINDEX, TEMODE; 185 } 186 mov SCSISEQ, SINDEX ret; 187 188/* 189 * Initialize transfer settings and clear the SCSI channel. 190 * SINDEX should contain any additional bit's the client wants 191 * set in SXFRCTL0. We also assume that the current SCB is 192 * a valid SCB for the target we wish to talk to. 193 */ 194initialize_channel: 195 or SXFRCTL0, CLRSTCNT|CLRCHN, SINDEX; 196set_transfer_settings: 197 if ((ahc->features & AHC_ULTRA) != 0) { 198 test SCB_CONTROL, ULTRAENB jz . + 2; 199 or SXFRCTL0, FAST20; 200 } 201/* 202 * Initialize SCSIRATE with the appropriate value for this target. 203 */ 204 if ((ahc->features & AHC_ULTRA2) != 0) { 205 bmov SCSIRATE, SCB_SCSIRATE, 2 ret; 206 } else { 207 mov SCSIRATE, SCB_SCSIRATE ret; 208 } 209 210selection: 211 test SSTAT0,SELDO jnz select_out; 212 mvi CLRSINT0, CLRSELDI; 213select_in: 214 if ((ahc->flags & AHC_TARGETMODE) != 0) { 215 if ((ahc->flags & AHC_INITIATORMODE) != 0) { 216 test SSTAT0, TARGET jz initiator_reselect; 217 } 218 219 /* 220 * We've just been selected. Assert BSY and 221 * setup the phase for receiving messages 222 * from the target. 223 */ 224 mvi SCSISIGO, P_MESGOUT|BSYO; 225 mvi CLRSINT1, CLRBUSFREE; 226 227 /* 228 * Setup the DMA for sending the identify and 229 * command information. 230 */ 231 or SEQ_FLAGS, CMDPHASE_PENDING; 232 233 /* XXX If ring buffer is full, return busy or queue full */ 234 mov A, TQINPOS; 235 if ((ahc->features & AHC_CMD_CHAN) != 0) { 236 mvi DINDEX, CCHADDR; 237 mvi TMODE_CMDADDR call set_32byte_addr; 238 mvi CCSCBCTL, CCSCBRESET; 239 } else { 240 mvi DINDEX, HADDR; 241 mvi TMODE_CMDADDR call set_32byte_addr; 242 mvi DFCNTRL, FIFORESET; 243 } 244 245 /* Initiator that selected us */ 246 and SAVED_TCL, SELID_MASK, SELID; 247 if ((ahc->features & AHC_CMD_CHAN) != 0) { 248 mov CCSCBRAM, SAVED_TCL; 249 } else { 250 mov DFDAT, SAVED_TCL; 251 } 252 253 /* The Target ID we were selected at */ 254 if ((ahc->features & AHC_MULTI_TID) != 0) { 255 if ((ahc->features & AHC_CMD_CHAN) != 0) { 256 and CCSCBRAM, 0x0f, TARGIDIN; 257 } else { 258 and DFDAT, 0x0f, TARGIDIN; 259 } 260 } else { 261 if ((ahc->features & AHC_CMD_CHAN) != 0) { 262 and CCSCBRAM, OID, SCSIID; 263 } else { 264 and DFDAT, OID, SCSIID; 265 } 266 } 267 268 /* No tag yet */ 269 mvi INITIATOR_TAG, SCB_LIST_NULL; 270 271 /* 272 * If ATN isn't asserted, the target isn't interested 273 * in talking to us. Go directly to bus free. 274 */ 275 test SCSISIGI, ATNI jz target_busfree; 276 277 /* 278 * Watch ATN closely now as we pull in messages from the 279 * initiator. We follow the guidlines from section 6.5 280 * of the SCSI-2 spec for what messages are allowed when. 281 */ 282 call target_inb; 283 284 /* 285 * Our first message must be one of IDENTIFY, ABORT, or 286 * BUS_DEVICE_RESET. 287 */ 288 /* XXX May need to be more lax here for older initiators... */ 289 test DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop; 290 /* Store for host */ 291 if ((ahc->features & AHC_CMD_CHAN) != 0) { 292 mov CCSCBRAM, DINDEX; 293 } else { 294 mov DFDAT, DINDEX; 295 } 296 297 /* Remember for disconnection decision */ 298 test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2; 299 /* XXX Honor per target settings too */ 300 or SEQ_FLAGS, NO_DISCONNECT; 301 302 test SCSISIGI, ATNI jz ident_messages_done; 303 call target_inb; 304 /* 305 * If this is a tagged request, the tagged message must 306 * immediately follow the identify. We test for a valid 307 * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and 308 * < MSG_IGN_WIDE_RESIDUE. 309 */ 310 add A, -MSG_SIMPLE_Q_TAG, DINDEX; 311 jnc ident_messages_done; 312 add A, -MSG_IGN_WIDE_RESIDUE, DINDEX; 313 jc ident_messages_done; 314 /* Store for host */ 315 if ((ahc->features & AHC_CMD_CHAN) != 0) { 316 mov CCSCBRAM, DINDEX; 317 } else { 318 mov DFDAT, DINDEX; 319 } 320 321 /* 322 * If the initiator doesn't feel like providing a tag number, 323 * we've got a failed selection and must transition to bus 324 * free. 325 */ 326 test SCSISIGI, ATNI jz target_busfree; 327 328 /* 329 * Store the tag for the host. 330 */ 331 call target_inb; 332 if ((ahc->features & AHC_CMD_CHAN) != 0) { 333 mov CCSCBRAM, DINDEX; 334 } else { 335 mov DFDAT, DINDEX; 336 } 337 mov INITIATOR_TAG, DINDEX; 338 jmp ident_messages_done; 339 340 /* 341 * Pushed message loop to allow the kernel to 342 * run it's own target mode message state engine. 343 */ 344host_target_message_loop: 345 mvi INTSTAT, HOST_MSG_LOOP; 346 nop; 347 cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop; 348 test SSTAT0, SPIORDY jz .; 349 jmp host_target_message_loop; 350 351ident_messages_done: 352 /* Terminate the ident list */ 353 if ((ahc->features & AHC_CMD_CHAN) != 0) { 354 mvi CCSCBRAM, SCB_LIST_NULL; 355 } else { 356 mvi DFDAT, SCB_LIST_NULL; 357 } 358 or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN; 359 test SCSISIGI, ATNI jnz target_mesgout_pending_msg; 360 jmp target_ITloop; 361 362/* 363 * We carefully toggle SPIOEN to allow us to return the 364 * message byte we receive so it can be checked prior to 365 * driving REQ on the bus for the next byte. 366 */ 367target_inb: 368 /* 369 * Drive REQ on the bus by enabling SCSI PIO. 370 */ 371 or SXFRCTL0, SPIOEN; 372 /* Wait for the byte */ 373 test SSTAT0, SPIORDY jz .; 374 /* Prevent our read from triggering another REQ */ 375 and SXFRCTL0, ~SPIOEN; 376 /* Save latched contents */ 377 mov DINDEX, SCSIDATL ret; 378 } 379 380if ((ahc->flags & AHC_INITIATORMODE) != 0) { 381/* 382 * Reselection has been initiated by a target. Make a note that we've been 383 * reselected, but haven't seen an IDENTIFY message from the target yet. 384 */ 385initiator_reselect: 386 /* XXX test for and handle ONE BIT condition */ 387 and SAVED_TCL, SELID_MASK, SELID; 388 if ((ahc->features & AHC_TWIN) != 0) { 389 test SBLKCTL, SELBUSB jz . + 2; 390 or SAVED_TCL, SELBUSB; 391 } 392 or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN; 393 mvi CLRSINT1,CLRBUSFREE; 394 or SIMODE1, ENBUSFREE; /* 395 * We aren't expecting a 396 * bus free, so interrupt 397 * the kernel driver if it 398 * happens. 399 */ 400 mvi MSG_OUT, MSG_NOOP; /* No message to send */ 401 jmp ITloop; 402} 403 404/* 405 * After the selection, remove this SCB from the "waiting SCB" 406 * list. This is achieved by simply moving our "next" pointer into 407 * WAITING_SCBH. Our next pointer will be set to null the next time this 408 * SCB is used, so don't bother with it now. 409 */ 410select_out: 411 /* Turn off the selection hardware */ 412 and SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE; 413 mvi CLRSINT0, CLRSELDO; 414 mov SCBPTR, WAITING_SCBH; 415 mov WAITING_SCBH,SCB_NEXT; 416 mov SAVED_TCL, SCB_TCL; 417 if ((ahc->flags & AHC_TARGETMODE) != 0) { 418 test SSTAT0, TARGET jz initiator_select; 419 420 /* 421 * We've just re-selected an initiator. 422 * Assert BSY and setup the phase for 423 * sending our identify messages. 424 */ 425 mvi P_MESGIN|BSYO call change_phase; 426 mvi CLRSINT1,CLRBUSFREE; 427 428 /* 429 * Start out with a simple identify message. 430 */ 431 and A, LID, SCB_TCL; 432 or A, MSG_IDENTIFYFLAG call target_outb; 433 434 /* 435 * If we are the result of a tagged command, send 436 * a simple Q tag and the tag id. 437 */ 438 test SCB_CONTROL, TAG_ENB jz . + 3; 439 mvi MSG_SIMPLE_Q_TAG call target_outb; 440 mov SCB_INITIATOR_TAG call target_outb; 441 mov INITIATOR_TAG, SCB_INITIATOR_TAG; 442target_synccmd: 443 /* 444 * Now determine what phases the host wants us 445 * to go through. 446 */ 447 mov SEQ_FLAGS, SCB_TARGET_PHASES; 448 449 450target_ITloop: 451 /* 452 * Start honoring ATN signals now that 453 * we properly identified ourself. 454 */ 455 test SCSISIGI, ATNI jnz target_mesgout; 456 test SEQ_FLAGS, CMDPHASE_PENDING jnz target_cmdphase; 457 test SEQ_FLAGS, DPHASE_PENDING jnz target_dphase; 458 test SEQ_FLAGS, SPHASE_PENDING jnz target_sphase; 459 460 /* 461 * No more work to do. Either disconnect or not depending 462 * on the state of NO_DISCONNECT. 463 */ 464 test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; 465 if ((ahc->flags & AHC_PAGESCBS) != 0) { 466 mov ALLZEROS call get_free_or_disc_scb; 467 } 468 mov RETURN_1, ALLZEROS; 469 call complete_target_cmd; 470 cmp RETURN_1, CONT_MSG_LOOP jne .; 471 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; 472 mov SCB_TAG call dma_scb; 473 jmp target_synccmd; 474 475target_mesgout: 476 mvi SCSISIGO, P_MESGOUT|BSYO; 477 call target_inb; 478 /* Local Processing goes here... */ 479target_mesgout_pending_msg: 480 jmp host_target_message_loop; 481 482target_disconnect: 483 mvi P_MESGIN|BSYO call change_phase; 484 test SEQ_FLAGS, DPHASE jz . + 2; 485 mvi MSG_SAVEDATAPOINTER call target_outb; 486 mvi MSG_DISCONNECT call target_outb; 487 488target_busfree_wait: 489 /* Wait for preceeding I/O session to complete. */ 490 test SCSISIGI, ACKI jnz .; 491target_busfree: 492 clr SCSISIGO; 493 call complete_target_cmd; 494 call clear_target_state; 495 jmp poll_for_work; 496 497target_cmdphase: 498 mvi P_COMMAND|BSYO call change_phase; 499 call target_inb; 500 mov A, DINDEX; 501 /* Store for host */ 502 if ((ahc->features & AHC_CMD_CHAN) != 0) { 503 mov CCSCBRAM, A; 504 } else { 505 mov DFDAT, A; 506 } 507 508 /* 509 * Determine the number of bytes to read 510 * based on the command group code via table lookup. 511 * We reuse the first 8 bytes of the TARG_SCSIRATE 512 * BIOS array for this table. Count is one less than 513 * the total for the command since we've already fetched 514 * the first byte. 515 */ 516 shr A, CMD_GROUP_CODE_SHIFT; 517 add SINDEX, TARG_SCSIRATE, A; 518 mov A, SINDIR; 519 520 test A, 0xFF jz command_phase_done; 521command_loop: 522 or SXFRCTL0, SPIOEN; 523 test SSTAT0, SPIORDY jz .; 524 cmp A, 1 jne . + 2; 525 and SXFRCTL0, ~SPIOEN; /* Last Byte */ 526 if ((ahc->features & AHC_CMD_CHAN) != 0) { 527 mov CCSCBRAM, SCSIDATL; 528 } else { 529 mov DFDAT, SCSIDATL; 530 } 531 dec A; 532 test A, 0xFF jnz command_loop; 533 534command_phase_done: 535 and SEQ_FLAGS, ~CMDPHASE_PENDING; 536 jmp target_ITloop; 537 538target_dphase: 539 /* 540 * Data direction flags are from the 541 * perspective of the initiator. 542 */ 543 test SCB_TARGET_PHASES[1], TARGET_DATA_IN jz . + 4; 544 mvi LASTPHASE, P_DATAOUT; 545 mvi P_DATAIN|BSYO call change_phase; 546 jmp . + 3; 547 mvi LASTPHASE, P_DATAIN; 548 mvi P_DATAOUT|BSYO call change_phase; 549 mov ALLZEROS call initialize_channel; 550 jmp p_data; 551 552target_sphase: 553 mvi P_STATUS|BSYO call change_phase; 554 mvi LASTPHASE, P_STATUS; 555 mov SCB_TARGET_STATUS call target_outb; 556 /* XXX Watch for ATN or parity errors??? */ 557 mvi SCSISIGO, P_MESGIN|BSYO; 558 /* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */ 559 mov ALLZEROS call target_outb; 560 jmp target_busfree_wait; 561 562complete_target_cmd: 563 test SEQ_FLAGS, TARG_CMD_PENDING jnz . + 2; 564 mov SCB_TAG jmp complete_post; 565 if ((ahc->features & AHC_CMD_CHAN) != 0) { 566 /* Set the valid byte */ 567 mvi CCSCBADDR, 24; 568 mov CCSCBRAM, ALLONES; 569 mvi CCHCNT, 28; 570 or CCSCBCTL, CCSCBEN|CCSCBRESET; 571 test CCSCBCTL, CCSCBDONE jz .; 572 clr CCSCBCTL; 573 } else { 574 /* Set the valid byte */ 575 or DFCNTRL, FIFORESET; 576 mvi DFWADDR, 3; /* Third 64bit word or byte 24 */ 577 mov DFDAT, ALLONES; 578 mvi HCNT[0], 28; 579 clr HCNT[1]; 580 clr HCNT[2]; 581 or DFCNTRL, HDMAEN|FIFOFLUSH; 582 call dma_finish; 583 } 584 inc TQINPOS; 585 mvi INTSTAT,CMDCMPLT ret; 586 } 587 588if ((ahc->flags & AHC_INITIATORMODE) != 0) { 589initiator_select: 590 mvi SPIOEN call initialize_channel; 591 592 /* 593 * We aren't expecting a bus free, so interrupt 594 * the kernel driver if it happens. 595 */ 596 mvi CLRSINT1,CLRBUSFREE; 597 or SIMODE1, ENBUSFREE; 598 599 /* 600 * As soon as we get a successful selection, the target 601 * should go into the message out phase since we have ATN 602 * asserted. 603 */ 604 mvi MSG_OUT, MSG_IDENTIFYFLAG; 605 or SEQ_FLAGS, IDENTIFY_SEEN; 606 607 /* 608 * Main loop for information transfer phases. Wait for the 609 * target to assert REQ before checking MSG, C/D and I/O for 610 * the bus phase. 611 */ 612ITloop: 613 call phase_lock; 614 615 mov A, LASTPHASE; 616 617 test A, ~P_DATAIN jz p_data; 618 cmp A,P_COMMAND je p_command; 619 cmp A,P_MESGOUT je p_mesgout; 620 cmp A,P_STATUS je p_status; 621 cmp A,P_MESGIN je p_mesgin; 622 623 mvi INTSTAT,BAD_PHASE; 624 jmp ITloop; /* Try reading the bus again. */ 625 626await_busfree: 627 and SIMODE1, ~ENBUSFREE; 628 call clear_target_state; 629 mov NONE, SCSIDATL; /* Ack the last byte */ 630 and SXFRCTL0, ~SPIOEN; 631 test SSTAT1,REQINIT|BUSFREE jz .; 632 test SSTAT1, BUSFREE jnz poll_for_work; 633 mvi INTSTAT, BAD_PHASE; 634} 635 636clear_target_state: 637 /* 638 * We assume that the kernel driver may reset us 639 * at any time, even in the middle of a DMA, so 640 * clear DFCNTRL too. 641 */ 642 clr DFCNTRL; 643 644 /* 645 * We don't know the target we will connect to, 646 * so default to narrow transfers to avoid 647 * parity problems. 648 */ 649 if ((ahc->features & AHC_ULTRA2) != 0) { 650 bmov SCSIRATE, ALLZEROS, 2; 651 } else { 652 clr SCSIRATE; 653 and SXFRCTL0, ~(FAST20); 654 } 655 mvi LASTPHASE, P_BUSFREE; 656 /* clear target specific flags */ 657 clr SEQ_FLAGS ret; 658 659/* 660 * If we re-enter the data phase after going through another phase, the 661 * STCNT may have been cleared, so restore it from the residual field. 662 */ 663data_phase_reinit: 664 if ((ahc->features & AHC_CMD_CHAN) != 0) { 665 bmov STCNT, SCB_RESID_DCNT, 3; 666 } else { 667 mvi DINDEX, STCNT; 668 mvi SCB_RESID_DCNT call bcopy_3; 669 } 670 and DATA_COUNT_ODD, 0x1, SCB_RESID_DCNT[0]; 671 jmp data_phase_loop; 672 673p_data: 674 if ((ahc->features & AHC_ULTRA2) != 0) { 675 mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN; 676 } else { 677 mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET; 678 } 679 test LASTPHASE, IOI jnz . + 2; 680 or DMAPARAMS, DIRECTION; 681 call assert; /* 682 * Ensure entering a data 683 * phase is okay - seen identify, etc. 684 */ 685 if ((ahc->features & AHC_CMD_CHAN) != 0) { 686 mvi CCSGADDR, CCSGADDR_MAX; 687 } 688 test SEQ_FLAGS, DPHASE jnz data_phase_reinit; 689 690 /* We have seen a data phase */ 691 or SEQ_FLAGS, DPHASE; 692 693 /* 694 * Initialize the DMA address and counter from the SCB. 695 * Also set SG_COUNT and SG_NEXT in memory since we cannot 696 * modify the values in the SCB itself until we see a 697 * save data pointers message. 698 */ 699 if ((ahc->features & AHC_CMD_CHAN) != 0) { 700 bmov HADDR, SCB_DATAPTR, 7; 701 } else { 702 mvi DINDEX, HADDR; 703 mvi SCB_DATAPTR call bcopy_7; 704 } 705 and DATA_COUNT_ODD, 0x1, SCB_DATACNT[0]; 706 707 if ((ahc->features & AHC_ULTRA2) == 0) { 708 if ((ahc->features & AHC_CMD_CHAN) != 0) { 709 bmov STCNT, HCNT, 3; 710 } else { 711 call set_stcnt_from_hcnt; 712 } 713 } 714 715 if ((ahc->features & AHC_CMD_CHAN) != 0) { 716 bmov SG_COUNT, SCB_SGCOUNT, 5; 717 } else { 718 mvi DINDEX, SG_COUNT; 719 mvi SCB_SGCOUNT call bcopy_5; 720 } 721 722data_phase_loop: 723/* Guard against overruns */ 724 test SG_COUNT, 0xff jnz data_phase_inbounds; 725/* 726 * Turn on 'Bit Bucket' mode, set the transfer count to 727 * 16meg and let the target run until it changes phase. 728 * When the transfer completes, notify the host that we 729 * had an overrun. 730 */ 731 or SXFRCTL1,BITBUCKET; 732 and DMAPARAMS, ~(HDMAEN|SDMAEN); 733 if ((ahc->features & AHC_ULTRA2) != 0) { 734 bmov HCNT, ALLONES, 3; 735 } else if ((ahc->features & AHC_CMD_CHAN) != 0) { 736 bmov STCNT, ALLONES, 3; 737 } else { 738 mvi STCNT[0], 0xFF; 739 mvi STCNT[1], 0xFF; 740 mvi STCNT[2], 0xFF; 741 } 742data_phase_inbounds: 743/* If we are the last SG block, tell the hardware. */ 744 cmp SG_COUNT,0x01 jne data_phase_wideodd; 745 if ((ahc->features & AHC_ULTRA2) != 0) { 746 or SG_CACHEPTR, LAST_SEG; 747 } else { 748 and DMAPARAMS, ~WIDEODD; 749 } 750data_phase_wideodd: 751 if ((ahc->features & AHC_ULTRA2) != 0) { 752 mov SINDEX, ALLONES; 753 mov DFCNTRL, DMAPARAMS; 754 test SSTAT0, SDONE jnz .;/* Wait for preload to complete */ 755data_phase_dma_loop: 756 test SSTAT0, SDONE jnz data_phase_dma_done; 757 test SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */ 758data_phase_dma_phasemis: 759 test SSTAT0,SDONE jnz . + 2; 760 mov SINDEX,ALLZEROS; /* Remeber the phasemiss */ 761 } else { 762 mov DMAPARAMS call dma; 763 } 764 765data_phase_dma_done: 766/* Go tell the host about any overruns */ 767 test SXFRCTL1,BITBUCKET jnz data_phase_overrun; 768 769/* Exit if we had an underrun. dma clears SINDEX in this case. */ 770 test SINDEX,0xff jz data_phase_finish; 771 772/* 773 * Advance the scatter-gather pointers if needed 774 */ 775sg_advance: 776 dec SG_COUNT; /* one less segment to go */ 777 778 test SG_COUNT, 0xff jz data_phase_finish; /* Are we done? */ 779/* 780 * Load a struct scatter and set up the data address and length. 781 * If the working value of the SG count is nonzero, then 782 * we need to load a new set of values. 783 * 784 * This, like all DMA's, assumes little-endian host data storage. 785 */ 786sg_load: 787 if ((ahc->features & AHC_CMD_CHAN) != 0) { 788 /* 789 * Do we have any prefetch left??? 790 */ 791 cmp CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail; 792 793 /* 794 * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes. 795 */ 796 add A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT; 797 mvi A, CCSGADDR_MAX; 798 jc . + 2; 799 shl A, 3, SG_COUNT; 800 mov CCHCNT, A; 801 bmov CCHADDR, SG_NEXT, 4; 802 mvi CCSGCTL, CCSGEN|CCSGRESET; 803 test CCSGCTL, CCSGDONE jz .; 804 and CCSGCTL, ~CCSGEN; 805 test CCSGCTL, CCSGEN jnz .; 806 mvi CCSGCTL, CCSGRESET; 807prefetched_segs_avail: 808 bmov HADDR, CCSGRAM, 8; 809 } else { 810 mvi DINDEX, HADDR; 811 mvi SG_NEXT call bcopy_4; 812 813 mvi HCNT[0],SG_SIZEOF; 814 clr HCNT[1]; 815 clr HCNT[2]; 816 817 or DFCNTRL, HDMAEN|DIRECTION|FIFORESET; 818 819 call dma_finish; 820 821 /* 822 * Copy data from FIFO into SCB data pointer and data count. 823 * This assumes that the SG segments are of the form: 824 * struct ahc_dma_seg { 825 * u_int32_t addr; four bytes, little-endian order 826 * u_int32_t len; four bytes, little endian order 827 * }; 828 */ 829 mvi HADDR call dfdat_in_7; 830 } 831 832 /* Track odd'ness */ 833 test HCNT[0], 0x1 jz . + 2; 834 xor DATA_COUNT_ODD, 0x1; 835 836 if ((ahc->features & AHC_ULTRA2) == 0) { 837 /* Load STCNT as well. It is a mirror of HCNT */ 838 if ((ahc->features & AHC_CMD_CHAN) != 0) { 839 bmov STCNT, HCNT, 3; 840 } else { 841 call set_stcnt_from_hcnt; 842 } 843 } 844 845/* Advance the SG pointer */ 846 clr A; /* add sizeof(struct scatter) */ 847 add SG_NEXT[0],SG_SIZEOF; 848 adc SG_NEXT[1],A; 849 850 if ((ahc->flags & AHC_TARGETMODE) != 0) { 851 test SSTAT0, TARGET jnz data_phase_loop; 852 } 853 test SSTAT1, REQINIT jz .; 854 test SSTAT1,PHASEMIS jz data_phase_loop; 855 856 /* Ensure the last seg is visable at the shaddow layer */ 857 if ((ahc->features & AHC_ULTRA2) != 0) { 858 or DFCNTRL, PRELOADEN; 859 } 860 861data_phase_finish: 862 if ((ahc->features & AHC_ULTRA2) != 0) { 863 call ultra2_dmafinish; 864 } 865/* 866 * After a DMA finishes, save the SG and STCNT residuals back into the SCB 867 * We use STCNT instead of HCNT, since it's a reflection of how many bytes 868 * were transferred on the SCSI (as opposed to the host) bus. 869 */ 870 if ((ahc->features & AHC_CMD_CHAN) != 0) { 871 bmov SCB_RESID_DCNT, STCNT, 3; 872 } else { 873 mov SCB_RESID_DCNT[0],STCNT[0]; 874 mov SCB_RESID_DCNT[1],STCNT[1]; 875 mov SCB_RESID_DCNT[2],STCNT[2]; 876 } 877 mov SCB_RESID_SGCNT, SG_COUNT; 878 879 if ((ahc->features & AHC_ULTRA2) != 0) { 880 or SXFRCTL0, CLRSTCNT|CLRCHN; 881 } 882 883 if ((ahc->flags & AHC_TARGETMODE) != 0) { 884 test SEQ_FLAGS, DPHASE_PENDING jz ITloop; 885 and SEQ_FLAGS, ~DPHASE_PENDING; 886 /* 887 * For data-in phases, wait for any pending acks from the 888 * initiator before changing phase. 889 */ 890 test DFCNTRL, DIRECTION jz target_ITloop; 891 test SSTAT1, REQINIT jnz .; 892 jmp target_ITloop; 893 } 894 jmp ITloop; 895 896data_phase_overrun: 897 if ((ahc->features & AHC_ULTRA2) != 0) { 898 call ultra2_dmafinish; 899 or SXFRCTL0, CLRSTCNT|CLRCHN; 900 } 901/* 902 * Turn off BITBUCKET mode and notify the host 903 */ 904 and SXFRCTL1, ~BITBUCKET; 905 mvi INTSTAT,DATA_OVERRUN; 906 jmp ITloop; 907 908ultra2_dmafinish: 909 if ((ahc->features & AHC_ULTRA2) != 0) { 910 test DFCNTRL, DIRECTION jnz ultra2_dmahalt; 911 and DFCNTRL, ~SCSIEN; 912 test DFCNTRL, SCSIEN jnz .; 913 or DFCNTRL, FIFOFLUSH; 914 test DFSTATUS, FIFOEMP jz . - 1; 915ultra2_dmahalt: 916 and DFCNTRL, ~(SCSIEN|HDMAEN); 917 test DFCNTRL, HDMAEN jnz .; 918 ret; 919 } 920 921if ((ahc->flags & AHC_INITIATORMODE) != 0) { 922/* 923 * Command phase. Set up the DMA registers and let 'er rip. 924 */ 925p_command: 926 call assert; 927 928 if ((ahc->features & AHC_CMD_CHAN) != 0) { 929 mov HCNT[0], SCB_CMDLEN; 930 bmov HCNT[1], ALLZEROS, 2; 931 if ((ahc->features & AHC_ULTRA2) == 0) { 932 bmov STCNT, HCNT, 3; 933 } 934 add NONE, -17, SCB_CMDLEN; 935 jc dma_cmd_data; 936 if ((ahc->features & AHC_ULTRA2) != 0) { 937 mvi DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION); 938 } else { 939 mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET); 940 } 941 bmov DFDAT, SCB_CMDSTORE, 16; 942 jmp cmd_loop; 943dma_cmd_data: 944 bmov HADDR, SCB_CMDPTR, 4; 945 } else { 946 mvi DINDEX, HADDR; 947 mvi SCB_CMDPTR call bcopy_5; 948 clr HCNT[1]; 949 clr HCNT[2]; 950 } 951 952 if ((ahc->features & AHC_ULTRA2) == 0) { 953 if ((ahc->features & AHC_CMD_CHAN) == 0) { 954 call set_stcnt_from_hcnt; 955 } 956 mvi DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET); 957 } else { 958 mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION); 959 } 960cmd_loop: 961 test SSTAT0, SDONE jnz . + 2; 962 test SSTAT1, PHASEMIS jz cmd_loop; 963 and DFCNTRL, ~(SCSIEN|HDMAEN|SDMAEN); 964 test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .; 965 jmp ITloop; 966 967/* 968 * Status phase. Wait for the data byte to appear, then read it 969 * and store it into the SCB. 970 */ 971p_status: 972 call assert; 973 974 mov SCB_TARGET_STATUS, SCSIDATL; 975 jmp ITloop; 976 977/* 978 * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full 979 * indentify message sequence and send it to the target. The host may 980 * override this behavior by setting the MK_MESSAGE bit in the SCB 981 * control byte. This will cause us to interrupt the host and allow 982 * it to handle the message phase completely on its own. If the bit 983 * associated with this target is set, we will also interrupt the host, 984 * thereby allowing it to send a message on the next selection regardless 985 * of the transaction being sent. 986 * 987 * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. 988 * This is done to allow the host to send messages outside of an identify 989 * sequence while protecting the seqencer from testing the MK_MESSAGE bit 990 * on an SCB that might not be for the current nexus. (For example, a 991 * BDR message in responce to a bad reselection would leave us pointed to 992 * an SCB that doesn't have anything to do with the current target). 993 * 994 * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, 995 * bus device reset). 996 * 997 * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, 998 * in case the target decides to put us in this phase for some strange 999 * reason. 1000 */ 1001p_mesgout_retry: 1002 or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */ 1003p_mesgout: 1004 mov SINDEX, MSG_OUT; 1005 cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; 1006 test SCB_CONTROL,MK_MESSAGE jnz host_message_loop; 1007 mov FUNCTION1, SCB_TCL; 1008 mov A, FUNCTION1; 1009 mov SINDEX, TARGET_MSG_REQUEST[0]; 1010 if ((ahc->features & AHC_TWIN) != 0) { 1011 /* Second Channel uses high byte bits */ 1012 test SCB_TCL, SELBUSB jz . + 2; 1013 mov SINDEX, TARGET_MSG_REQUEST[1]; 1014 } else if ((ahc->features & AHC_WIDE) != 0) { 1015 test SCB_TCL, 0x80 jz . + 2; /* target > 7 */ 1016 mov SINDEX, TARGET_MSG_REQUEST[1]; 1017 } 1018 test SINDEX, A jnz host_message_loop; 1019p_mesgout_identify: 1020 and SINDEX,LID,SCB_TCL; /* lun */ 1021 and A,DISCENB,SCB_CONTROL; /* mask off disconnect privledge */ 1022 or SINDEX,A; /* or in disconnect privledge */ 1023 or SINDEX,MSG_IDENTIFYFLAG; 1024/* 1025 * Send a tag message if TAG_ENB is set in the SCB control block. 1026 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. 1027 */ 1028p_mesgout_tag: 1029 test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte; 1030 mov SCSIDATL, SINDEX; /* Send the identify message */ 1031 call phase_lock; 1032 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; 1033 and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL; 1034 call phase_lock; 1035 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; 1036 mov SCB_TAG jmp p_mesgout_onebyte; 1037/* 1038 * Interrupt the driver, and allow it to handle this message 1039 * phase and any required retries. 1040 */ 1041p_mesgout_from_host: 1042 cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; 1043 jmp host_message_loop; 1044 1045p_mesgout_onebyte: 1046 mvi CLRSINT1, CLRATNO; 1047 mov SCSIDATL, SINDEX; 1048 1049/* 1050 * If the next bus phase after ATN drops is message out, it means 1051 * that the target is requesting that the last message(s) be resent. 1052 */ 1053 call phase_lock; 1054 cmp LASTPHASE, P_MESGOUT je p_mesgout_retry; 1055 1056p_mesgout_done: 1057 mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ 1058 mov LAST_MSG, MSG_OUT; 1059 mvi MSG_OUT, MSG_NOOP; /* No message left */ 1060 jmp ITloop; 1061 1062/* 1063 * Message in phase. Bytes are read using Automatic PIO mode. 1064 */ 1065p_mesgin: 1066 mvi ACCUM call inb_first; /* read the 1st message byte */ 1067 1068 test A,MSG_IDENTIFYFLAG jnz mesgin_identify; 1069 cmp A,MSG_DISCONNECT je mesgin_disconnect; 1070 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; 1071 cmp ALLZEROS,A je mesgin_complete; 1072 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; 1073 cmp A,MSG_NOOP je mesgin_done; 1074 1075/* 1076 * Pushed message loop to allow the kernel to 1077 * RUN IT's own message state engine. To avoid an 1078 * extra nop instruction after signaling the kernel, 1079 * we perform the phase_lock before checking to see 1080 * if we should exit the loop and skip the phase_lock 1081 * in the ITloop. Performing back to back phase_locks 1082 * shouldn't hurt, but why do it twice... 1083 */ 1084host_message_loop: 1085 mvi INTSTAT, HOST_MSG_LOOP; 1086 call phase_lock; 1087 cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1; 1088 jmp host_message_loop; 1089 1090mesgin_done: 1091 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ 1092 jmp ITloop; 1093 1094 1095mesgin_complete: 1096/* 1097 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO, 1098 * and trigger a completion interrupt. Before doing so, check to see if there 1099 * is a residual or the status byte is something other than STATUS_GOOD (0). 1100 * In either of these conditions, we upload the SCB back to the host so it can 1101 * process this information. In the case of a non zero status byte, we 1102 * additionally interrupt the kernel driver synchronously, allowing it to 1103 * decide if sense should be retrieved. If the kernel driver wishes to request 1104 * sense, it will fill the kernel SCB with a request sense command and set 1105 * RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE we redownload 1106 * the SCB, and process it as the next command by adding it to the waiting list. 1107 * If the kernel driver does not wish to request sense, it need only clear 1108 * RETURN_1, and the command is allowed to complete normally. We don't bother 1109 * to post to the QOUTFIFO in the error cases since it would require extra 1110 * work in the kernel driver to ensure that the entry was removed before the 1111 * command complete code tried processing it. 1112 */ 1113 1114/* 1115 * First check for residuals 1116 */ 1117 test SCB_RESID_SGCNT,0xff jnz upload_scb; 1118 test SCB_TARGET_STATUS,0xff jz complete; /* Good Status? */ 1119upload_scb: 1120 mvi DMAPARAMS, FIFORESET; 1121 mov SCB_TAG call dma_scb; 1122check_status: 1123 test SCB_TARGET_STATUS,0xff jz complete; /* Just a residual? */ 1124 mvi INTSTAT,BAD_STATUS; /* let driver know */ 1125 nop; 1126 cmp RETURN_1, SEND_SENSE jne complete; 1127 /* This SCB becomes the next to execute as it will retrieve sense */ 1128 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; 1129 mov SCB_TAG call dma_scb; 1130add_to_waiting_list: 1131 mov SCB_NEXT,WAITING_SCBH; 1132 mov WAITING_SCBH, SCBPTR; 1133 /* 1134 * Prepare our selection hardware before the busfree so we have a 1135 * high probability of winning arbitration. 1136 */ 1137 call start_selection; 1138 jmp await_busfree; 1139 1140complete: 1141 /* If we are untagged, clear our address up in host ram */ 1142 test SCB_CONTROL, TAG_ENB jnz complete_queue; 1143 mov A, SAVED_TCL; 1144 mvi UNTAGGEDSCB_OFFSET call post_byte_setup; 1145 mvi SCB_LIST_NULL call post_byte; 1146 1147complete_queue: 1148 mov SCB_TAG call complete_post; 1149 1150add_to_free_list: 1151 call add_scb_to_free_list; 1152 jmp await_busfree; 1153} 1154 1155complete_post: 1156 /* Post the SCBID in SINDEX and issue an interrupt */ 1157 mov ARG_1, SINDEX; 1158 if ((ahc->features & AHC_QUEUE_REGS) != 0) { 1159 mov A, SDSCB_QOFF; 1160 } else { 1161 mov A, QOUTPOS; 1162 } 1163 mvi QOUTFIFO_OFFSET call post_byte_setup; 1164 mov ARG_1 call post_byte; 1165 if ((ahc->features & AHC_QUEUE_REGS) == 0) { 1166 inc QOUTPOS; 1167 } 1168 mvi INTSTAT,CMDCMPLT ret; 1169 1170if ((ahc->flags & AHC_INITIATORMODE) != 0) { 1171/* 1172 * Is it a disconnect message? Set a flag in the SCB to remind us 1173 * and await the bus going free. 1174 */ 1175mesgin_disconnect: 1176 or SCB_CONTROL,DISCONNECTED; 1177 call add_scb_to_disc_list; 1178 jmp await_busfree; 1179 1180/* 1181 * Save data pointers message: 1182 * Copying RAM values back to SCB, for Save Data Pointers message, but 1183 * only if we've actually been into a data phase to change them. This 1184 * protects against bogus data in scratch ram and the residual counts 1185 * since they are only initialized when we go into data_in or data_out. 1186 */ 1187mesgin_sdptrs: 1188 test SEQ_FLAGS, DPHASE jz mesgin_done; 1189 1190 /* 1191 * The SCB SGPTR becomes the next one we'll download, 1192 * and the SCB DATAPTR becomes the current SHADDR. 1193 * Use the residual number since STCNT is corrupted by 1194 * any message transfer. 1195 */ 1196 if ((ahc->features & AHC_CMD_CHAN) != 0) { 1197 bmov SCB_SGCOUNT, SG_COUNT, 5; 1198 bmov SCB_DATAPTR, SHADDR, 4; 1199 bmov SCB_DATACNT, SCB_RESID_DCNT, 3; 1200 } else { 1201 mvi DINDEX, SCB_SGCOUNT; 1202 mvi SG_COUNT call bcopy_5; 1203 1204 mvi DINDEX, SCB_DATAPTR; 1205 mvi SHADDR call bcopy_4; 1206 mvi SCB_RESID_DCNT call bcopy_3; 1207 } 1208 jmp mesgin_done; 1209 1210/* 1211 * Restore pointers message? Data pointers are recopied from the 1212 * SCB anytime we enter a data phase for the first time, so all 1213 * we need to do is clear the DPHASE flag and let the data phase 1214 * code do the rest. 1215 */ 1216mesgin_rdptrs: 1217 and SEQ_FLAGS, ~DPHASE; /* 1218 * We'll reload them 1219 * the next time through 1220 * the dataphase. 1221 */ 1222 jmp mesgin_done; 1223 1224/* 1225 * Identify message? For a reconnecting target, this tells us the lun 1226 * that the reconnection is for - find the correct SCB and switch to it, 1227 * clearing the "disconnected" bit so we don't "find" it by accident later. 1228 */ 1229mesgin_identify: 1230 1231 if ((ahc->features & AHC_WIDE) != 0) { 1232 and A,0x0f; /* lun in lower four bits */ 1233 } else { 1234 and A,0x07; /* lun in lower three bits */ 1235 } 1236 or SAVED_TCL,A; /* SAVED_TCL should be complete now */ 1237 1238 mvi ARG_2, SCB_LIST_NULL; /* SCBID of prev SCB in disc List */ 1239 call get_untagged_SCBID; 1240 cmp ARG_1, SCB_LIST_NULL je snoop_tag; 1241 if ((ahc->flags & AHC_PAGESCBS) != 0) { 1242 test SEQ_FLAGS, SCBPTR_VALID jz use_retrieveSCB; 1243 } 1244 /* 1245 * If the SCB was found in the disconnected list (as is 1246 * always the case in non-paging scenarios), SCBPTR is already 1247 * set to the correct SCB. So, simply setup the SCB and get 1248 * on with things. 1249 */ 1250 call rem_scb_from_disc_list; 1251 jmp setup_SCB; 1252/* 1253 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. 1254 * If we get one, we use the tag returned to find the proper 1255 * SCB. With SCB paging, this requires using search for both tagged 1256 * and non-tagged transactions since the SCB may exist in any slot. 1257 * If we're not using SCB paging, we can use the tag as the direct 1258 * index to the SCB. 1259 */ 1260snoop_tag: 1261 mov NONE,SCSIDATL; /* ACK Identify MSG */ 1262snoop_tag_loop: 1263 call phase_lock; 1264 cmp LASTPHASE, P_MESGIN jne not_found; 1265 cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found; 1266get_tag: 1267 mvi ARG_1 call inb_next; /* tag value */ 1268 1269 /* 1270 * Ensure that the SCB the tag points to is for 1271 * an SCB transaction to the reconnecting target. 1272 */ 1273use_retrieveSCB: 1274 call retrieveSCB; 1275setup_SCB: 1276 mov A, SAVED_TCL; 1277 cmp SCB_TCL, A jne not_found_cleanup_scb; 1278 test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb; 1279 and SCB_CONTROL,~DISCONNECTED; 1280 or SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */ 1281 call set_transfer_settings; 1282 /* See if the host wants to send a message upon reconnection */ 1283 test SCB_CONTROL, MK_MESSAGE jz mesgin_done; 1284 and SCB_CONTROL, ~MK_MESSAGE; 1285 mvi HOST_MSG call mk_mesg; 1286 jmp mesgin_done; 1287 1288not_found_cleanup_scb: 1289 test SCB_CONTROL, DISCONNECTED jz . + 3; 1290 call add_scb_to_disc_list; 1291 jmp not_found; 1292 call add_scb_to_free_list; 1293not_found: 1294 mvi INTSTAT, NO_MATCH; 1295 mvi MSG_BUS_DEV_RESET call mk_mesg; 1296 jmp mesgin_done; 1297 1298/* 1299 * [ ADD MORE MESSAGE HANDLING HERE ] 1300 */ 1301 1302/* 1303 * Locking the driver out, build a one-byte message passed in SINDEX 1304 * if there is no active message already. SINDEX is returned intact. 1305 */ 1306mk_mesg: 1307 or SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */ 1308 mov MSG_OUT,SINDEX ret; 1309 1310/* 1311 * Functions to read data in Automatic PIO mode. 1312 * 1313 * According to Adaptec's documentation, an ACK is not sent on input from 1314 * the target until SCSIDATL is read from. So we wait until SCSIDATL is 1315 * latched (the usual way), then read the data byte directly off the bus 1316 * using SCSIBUSL. When we have pulled the ATN line, or we just want to 1317 * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI 1318 * spec guarantees that the target will hold the data byte on the bus until 1319 * we send our ACK. 1320 * 1321 * The assumption here is that these are called in a particular sequence, 1322 * and that REQ is already set when inb_first is called. inb_{first,next} 1323 * use the same calling convention as inb. 1324 */ 1325 1326inb_next: 1327 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ 1328inb_next_wait: 1329 /* 1330 * If there is a parity error, wait for the kernel to 1331 * see the interrupt and prepare our message response 1332 * before continuing. 1333 */ 1334 test SSTAT1, REQINIT jz inb_next_wait; 1335 test SSTAT1, SCSIPERR jnz inb_next_wait; 1336 and LASTPHASE, PHASE_MASK, SCSISIGI; 1337 cmp LASTPHASE, P_MESGIN jne mesgin_phasemis; 1338inb_first: 1339 mov DINDEX,SINDEX; 1340 mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/ 1341inb_last: 1342 mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/ 1343} 1344 1345if ((ahc->flags & AHC_TARGETMODE) != 0) { 1346/* 1347 * Change to a new phase. If we are changing the state of the I/O signal, 1348 * from out to in, wait an additional data release delay before continuing. 1349 */ 1350change_phase: 1351 /* Wait for preceeding I/O session to complete. */ 1352 test SCSISIGI, ACKI jnz .; 1353 1354 /* Change the phase */ 1355 and DINDEX, IOI, SCSISIGI; 1356 mov SCSISIGO, SINDEX; 1357 and A, IOI, SINDEX; 1358 1359 /* 1360 * If the data direction has changed, from 1361 * out (initiator driving) to in (target driving), 1362 * we must waitat least a data release delay plus 1363 * the normal bus settle delay. [SCSI III SPI 10.11.0] 1364 */ 1365 cmp DINDEX, A je change_phase_wait; 1366 test SINDEX, IOI jz change_phase_wait; 1367 call change_phase_wait; 1368change_phase_wait: 1369 nop; 1370 nop; 1371 nop; 1372 nop ret; 1373 1374/* 1375 * Send a byte to an initiator in Automatic PIO mode. 1376 */ 1377target_outb: 1378 or SXFRCTL0, SPIOEN; 1379 test SSTAT0, SPIORDY jz .; 1380 mov SCSIDATL, SINDEX; 1381 test SSTAT0, SPIORDY jz .; 1382 and SXFRCTL0, ~SPIOEN ret; 1383} 1384 1385mesgin_phasemis: 1386/* 1387 * We expected to receive another byte, but the target changed phase 1388 */ 1389 mvi INTSTAT, MSGIN_PHASEMIS; 1390 jmp ITloop; 1391 1392/* 1393 * DMA data transfer. HADDR and HCNT must be loaded first, and 1394 * SINDEX should contain the value to load DFCNTRL with - 0x3d for 1395 * host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared 1396 * during initialization. 1397 */ 1398dma: 1399 mov DFCNTRL,SINDEX; 1400dma_loop: 1401 test SSTAT0,DMADONE jnz dma_dmadone; 1402 test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */ 1403dma_phasemis: 1404 test SSTAT0,SDONE jnz dma_checkfifo; 1405 mov SINDEX,ALLZEROS; /* Notify caller of phasemiss */ 1406 1407/* 1408 * We will be "done" DMAing when the transfer count goes to zero, or 1409 * the target changes the phase (in light of this, it makes sense that 1410 * the DMA circuitry doesn't ACK when PHASEMIS is active). If we are 1411 * doing a SCSI->Host transfer, the data FIFO should be flushed auto- 1412 * magically on STCNT=0 or a phase change, so just wait for FIFO empty 1413 * status. 1414 */ 1415dma_checkfifo: 1416 test DFCNTRL,DIRECTION jnz dma_fifoempty; 1417dma_fifoflush: 1418 test DFSTATUS,FIFOEMP jz dma_fifoflush; 1419 1420dma_fifoempty: 1421 /* Don't clobber an inprogress host data transfer */ 1422 test DFSTATUS, MREQPEND jnz dma_fifoempty; 1423/* 1424 * Now shut the DMA enables off and make sure that the DMA enables are 1425 * actually off first lest we get an ILLSADDR. 1426 */ 1427dma_dmadone: 1428 and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN); 1429dma_halt: 1430 /* 1431 * Some revisions of the aic7880 have a problem where, if the 1432 * data fifo is full, but the PCI input latch is not empty, 1433 * HDMAEN cannot be cleared. The fix used here is to attempt 1434 * to drain the data fifo until there is space for the input 1435 * latch to drain and HDMAEN de-asserts. 1436 */ 1437 if ((ahc->features & AHC_ULTRA2) == 0) { 1438 mov NONE, DFDAT; 1439 } 1440 test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt; 1441return: 1442 ret; 1443 1444/* 1445 * Assert that if we've been reselected, then we've seen an IDENTIFY 1446 * message. 1447 */ 1448assert: 1449 test SEQ_FLAGS,IDENTIFY_SEEN jnz return; /* seen IDENTIFY? */ 1450 1451 mvi INTSTAT,NO_IDENT ret; /* no - tell the kernel */ 1452 1453/* 1454 * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL) 1455 * or by the SCBID ARG_1. The search begins at the SCB index passed in 1456 * via SINDEX which is an SCB that must be on the disconnected list. If 1457 * the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR 1458 * is set to the proper SCB. 1459 */ 1460findSCB: 1461 mov SCBPTR,SINDEX; /* Initialize SCBPTR */ 1462 cmp ARG_1, SCB_LIST_NULL jne findSCB_by_SCBID; 1463 mov A, SAVED_TCL; 1464 mvi SCB_TCL jmp findSCB_loop; /* &SCB_TCL -> SINDEX */ 1465findSCB_by_SCBID: 1466 mov A, ARG_1; /* Tag passed in ARG_1 */ 1467 mvi SCB_TAG jmp findSCB_loop; /* &SCB_TAG -> SINDEX */ 1468findSCB_next: 1469 mov ARG_2, SCBPTR; 1470 cmp SCB_NEXT, SCB_LIST_NULL je notFound; 1471 mov SCBPTR,SCB_NEXT; 1472 dec SINDEX; /* Last comparison moved us too far */ 1473findSCB_loop: 1474 cmp SINDIR, A jne findSCB_next; 1475 mov SINDEX, SCBPTR ret; 1476notFound: 1477 mvi SINDEX, SCB_LIST_NULL ret; 1478 1479/* 1480 * Retrieve an SCB by SCBID first searching the disconnected list falling 1481 * back to DMA'ing the SCB down from the host. This routine assumes that 1482 * ARG_1 is the SCBID of interrest and that SINDEX is the position in the 1483 * disconnected list to start the search from. If SINDEX is SCB_LIST_NULL, 1484 * we go directly to the host for the SCB. 1485 */ 1486retrieveSCB: 1487 test SEQ_FLAGS, SCBPTR_VALID jz retrieve_from_host; 1488 mov SCBPTR call findSCB; /* Continue the search */ 1489 cmp SINDEX, SCB_LIST_NULL je retrieve_from_host; 1490 1491/* 1492 * This routine expects SINDEX to contain the index of the SCB to be 1493 * removed, SCBPTR to be pointing to that SCB, and ARG_2 to be the 1494 * SCBID of the SCB just previous to this one in the list or SCB_LIST_NULL 1495 * if it is at the head. 1496 */ 1497rem_scb_from_disc_list: 1498/* Remove this SCB from the disconnection list */ 1499 cmp ARG_2, SCB_LIST_NULL je rHead; 1500 mov DINDEX, SCB_NEXT; 1501 mov SCBPTR, ARG_2; 1502 mov SCB_NEXT, DINDEX; 1503 mov SCBPTR, SINDEX ret; 1504rHead: 1505 mov DISCONNECTED_SCBH,SCB_NEXT ret; 1506 1507retrieve_from_host: 1508/* 1509 * We didn't find it. Pull an SCB and DMA down the one we want. 1510 * We should never get here in the non-paging case. 1511 */ 1512 mov ALLZEROS call get_free_or_disc_scb; 1513 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; 1514 /* Jump instead of call as we want to return anyway */ 1515 mov ARG_1 jmp dma_scb; 1516 1517/* 1518 * Determine whether a target is using tagged or non-tagged transactions 1519 * by first looking for a matching transaction based on the TCL and if 1520 * that fails, looking up this device in the host's untagged SCB array. 1521 * The TCL to search for is assumed to be in SAVED_TCL. The value is 1522 * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged). 1523 * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information 1524 * in an SCB instead of having to go to the host. 1525 */ 1526get_untagged_SCBID: 1527 cmp DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host; 1528 mvi ARG_1, SCB_LIST_NULL; 1529 mov DISCONNECTED_SCBH call findSCB; 1530 cmp SINDEX, SCB_LIST_NULL je get_SCBID_from_host; 1531 or SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */ 1532 test SCB_CONTROL, TAG_ENB jnz . + 2; 1533 mov ARG_1, SCB_TAG ret; 1534 mvi ARG_1, SCB_LIST_NULL ret; 1535 1536/* 1537 * Fetch a byte from host memory given an index of (A + (256 * SINDEX)) 1538 * and a base address of SCBID_ADDR. The byte is returned in RETURN_2. 1539 */ 1540fetch_byte: 1541 mov ARG_2, SINDEX; 1542 if ((ahc->features & AHC_CMD_CHAN) != 0) { 1543 mvi DINDEX, CCHADDR; 1544 mvi SCBID_ADDR call set_1byte_addr; 1545 mvi CCHCNT, 1; 1546 mvi CCSGCTL, CCSGEN|CCSGRESET; 1547 test CCSGCTL, CCSGDONE jz .; 1548 mvi CCSGCTL, CCSGRESET; 1549 bmov RETURN_2, CCSGRAM, 1 ret; 1550 } else { 1551 mvi DINDEX, HADDR; 1552 mvi SCBID_ADDR call set_1byte_addr; 1553 mvi HCNT[0], 1; 1554 clr HCNT[1]; 1555 clr HCNT[2]; 1556 mvi DFCNTRL, HDMAEN|DIRECTION|FIFORESET; 1557 call dma_finish; 1558 mov RETURN_2, DFDAT ret; 1559 } 1560 1561/* 1562 * Prepare the hardware to post a byte to host memory given an 1563 * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR. 1564 */ 1565post_byte_setup: 1566 mov ARG_2, SINDEX; 1567 if ((ahc->features & AHC_CMD_CHAN) != 0) { 1568 mvi DINDEX, CCHADDR; 1569 mvi SCBID_ADDR call set_1byte_addr; 1570 mvi CCHCNT, 1; 1571 mvi CCSCBCTL, CCSCBRESET ret; 1572 } else { 1573 mvi DINDEX, HADDR; 1574 mvi SCBID_ADDR call set_1byte_addr; 1575 mvi HCNT[0], 1; 1576 clr HCNT[1]; 1577 clr HCNT[2]; 1578 mvi DFCNTRL, FIFORESET ret; 1579 } 1580 1581post_byte: 1582 if ((ahc->features & AHC_CMD_CHAN) != 0) { 1583 bmov CCSCBRAM, SINDEX, 1; 1584 or CCSCBCTL, CCSCBEN|CCSCBRESET; 1585 test CCSCBCTL, CCSCBDONE jz .; 1586 clr CCSCBCTL ret; 1587 } else { 1588 mov DFDAT, SINDEX; 1589 or DFCNTRL, HDMAEN|FIFOFLUSH; 1590 jmp dma_finish; 1591 } 1592 1593get_SCBID_from_host: 1594 mov A, SAVED_TCL; 1595 mvi UNTAGGEDSCB_OFFSET call fetch_byte; 1596 mov RETURN_1, RETURN_2 ret; 1597 1598phase_lock: 1599 test SSTAT1, REQINIT jz phase_lock; 1600 test SSTAT1, SCSIPERR jnz phase_lock; 1601 and SCSISIGO, PHASE_MASK, SCSISIGI; 1602 and LASTPHASE, PHASE_MASK, SCSISIGI ret; 1603 1604if ((ahc->features & AHC_CMD_CHAN) == 0) { 1605set_stcnt_from_hcnt: 1606 mov STCNT[0], HCNT[0]; 1607 mov STCNT[1], HCNT[1]; 1608 mov STCNT[2], HCNT[2] ret; 1609 1610bcopy_7: 1611 mov DINDIR, SINDIR; 1612 mov DINDIR, SINDIR; 1613bcopy_5: 1614 mov DINDIR, SINDIR; 1615bcopy_4: 1616 mov DINDIR, SINDIR; 1617bcopy_3: 1618 mov DINDIR, SINDIR; 1619 mov DINDIR, SINDIR; 1620 mov DINDIR, SINDIR ret; 1621} 1622 1623if ((ahc->flags & AHC_TARGETMODE) != 0) { 1624/* 1625 * Setup addr assuming that A is an index into 1626 * an array of 32byte objects, SINDEX contains 1627 * the base address of that array, and DINDEX 1628 * contains the base address of the location 1629 * to store the indexed address. 1630 */ 1631set_32byte_addr: 1632 shr ARG_2, 3, A; 1633 shl A, 5; 1634 jmp set_1byte_addr; 1635} 1636 1637/* 1638 * Setup addr assuming that A is an index into 1639 * an array of 64byte objects, SINDEX contains 1640 * the base address of that array, and DINDEX 1641 * contains the base address of the location 1642 * to store the indexed address. 1643 */ 1644set_64byte_addr: 1645 shr ARG_2, 2, A; 1646 shl A, 6; 1647 1648/* 1649 * Setup addr assuming that A + (ARG_1 * 256) is an 1650 * index into an array of 1byte objects, SINDEX contains 1651 * the base address of that array, and DINDEX contains 1652 * the base address of the location to store the computed 1653 * address. 1654 */ 1655set_1byte_addr: 1656 add DINDIR, A, SINDIR; 1657 mov A, ARG_2; 1658 adc DINDIR, A, SINDIR; 1659 clr A; 1660 adc DINDIR, A, SINDIR; 1661 adc DINDIR, A, SINDIR ret; 1662 1663/* 1664 * Either post or fetch and SCB from host memory based on the 1665 * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX. 1666 */ 1667dma_scb: 1668 mov A, SINDEX; 1669 if ((ahc->features & AHC_CMD_CHAN) != 0) { 1670 mvi DINDEX, CCHADDR; 1671 mvi HSCB_ADDR call set_64byte_addr; 1672 mov CCSCBPTR, SCBPTR; 1673 test DMAPARAMS, DIRECTION jz dma_scb_tohost; 1674 mvi CCHCNT, SCB_64BYTE_SIZE; 1675 mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET; 1676 cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .; 1677 jmp dma_scb_finish; 1678dma_scb_tohost: 1679 mvi CCHCNT, SCB_32BYTE_SIZE; 1680 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 1681 mvi CCSCBCTL, CCSCBRESET; 1682 bmov CCSCBRAM, SCB_CONTROL, SCB_32BYTE_SIZE; 1683 or CCSCBCTL, CCSCBEN|CCSCBRESET; 1684 test CCSCBCTL, CCSCBDONE jz .; 1685 } else { 1686 mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET; 1687 cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .; 1688 } 1689dma_scb_finish: 1690 clr CCSCBCTL; 1691 test CCSCBCTL, CCARREN|CCSCBEN jnz .; 1692 ret; 1693 } else { 1694 mvi DINDEX, HADDR; 1695 mvi HSCB_ADDR call set_64byte_addr; 1696 mvi HCNT[0], SCB_32BYTE_SIZE; 1697 clr HCNT[1]; 1698 clr HCNT[2]; 1699 mov DFCNTRL, DMAPARAMS; 1700 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost; 1701 /* Fill it with the SCB data */ 1702copy_scb_tofifo: 1703 mvi SINDEX, SCB_CONTROL; 1704 add A, SCB_32BYTE_SIZE, SINDEX; 1705copy_scb_tofifo_loop: 1706 mov DFDAT,SINDIR; 1707 mov DFDAT,SINDIR; 1708 mov DFDAT,SINDIR; 1709 mov DFDAT,SINDIR; 1710 mov DFDAT,SINDIR; 1711 mov DFDAT,SINDIR; 1712 mov DFDAT,SINDIR; 1713 cmp SINDEX, A jne copy_scb_tofifo_loop; 1714 or DFCNTRL, HDMAEN|FIFOFLUSH; 1715dma_scb_fromhost: 1716 call dma_finish; 1717 /* If we were putting the SCB, we are done */ 1718 test DMAPARAMS, DIRECTION jz return; 1719 mvi SCB_CONTROL call dfdat_in_7; 1720 call dfdat_in_7_continued; 1721 call dfdat_in_7_continued; 1722 jmp dfdat_in_7_continued; 1723dfdat_in_7: 1724 mov DINDEX,SINDEX; 1725dfdat_in_7_continued: 1726 mov DINDIR,DFDAT; 1727 mov DINDIR,DFDAT; 1728 mov DINDIR,DFDAT; 1729 mov DINDIR,DFDAT; 1730 mov DINDIR,DFDAT; 1731 mov DINDIR,DFDAT; 1732 mov DINDIR,DFDAT ret; 1733 } 1734 1735 1736/* 1737 * Wait for DMA from host memory to data FIFO to complete, then disable 1738 * DMA and wait for it to acknowledge that it's off. 1739 */ 1740dma_finish: 1741 test DFSTATUS,HDONE jz dma_finish; 1742 /* Turn off DMA */ 1743 and DFCNTRL, ~HDMAEN; 1744 test DFCNTRL, HDMAEN jnz .; 1745 ret; 1746 1747add_scb_to_free_list: 1748 if ((ahc->flags & AHC_PAGESCBS) != 0) { 1749 mov SCB_NEXT, FREE_SCBH; 1750 mov FREE_SCBH, SCBPTR; 1751 } 1752 mvi SCB_TAG, SCB_LIST_NULL ret; 1753 1754if ((ahc->flags & AHC_PAGESCBS) != 0) { 1755get_free_or_disc_scb: 1756 cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb; 1757 cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb; 1758return_error: 1759 mvi SINDEX, SCB_LIST_NULL ret; 1760dequeue_disc_scb: 1761 mov SCBPTR, DISCONNECTED_SCBH; 1762dma_up_scb: 1763 mvi DMAPARAMS, FIFORESET; 1764 mov SCB_TAG call dma_scb; 1765unlink_disc_scb: 1766 mov DISCONNECTED_SCBH, SCB_NEXT ret; 1767dequeue_free_scb: 1768 mov SCBPTR, FREE_SCBH; 1769 mov FREE_SCBH, SCB_NEXT ret; 1770} 1771 1772add_scb_to_disc_list: 1773/* 1774 * Link this SCB into the DISCONNECTED list. This list holds the 1775 * candidates for paging out an SCB if one is needed for a new command. 1776 * Modifying the disconnected list is a critical(pause dissabled) section. 1777 */ 1778 mov SCB_NEXT, DISCONNECTED_SCBH; 1779 mov DISCONNECTED_SCBH, SCBPTR ret; 1780