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