aic7xxx.seq revision 19921
1/*+M*********************************************************************** 2 *Adaptec 274x/284x/294x device driver for Linux and FreeBSD. 3 * 4 *Copyright (c) 1994 John Aycock 5 * The University of Calgary Department of Computer Science. 6 * All rights reserved. 7 * 8 *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing, 9 *SCB paging and other optimizations: 10 *Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved. 11 * 12 *Redistribution and use in source and binary forms, with or without 13 *modification, are permitted provided that the following conditions 14 *are met: 15 *1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer. 17 *2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 *3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of Calgary 23 * Department of Computer Science and its contributors. 24 *4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29 *ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 *ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 *SUCH DAMAGE. 39 * 40 *-M************************************************************************/ 41 42VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.50 1996/11/21 06:18:33 gibbs Exp $" 43 44#if defined(__NetBSD__) 45#include "../../../../dev/ic/aic7xxxreg.h" 46#include "../../../../scsi/scsi_message.h" 47#elif defined(__FreeBSD__) 48#include "../../dev/aic7xxx/aic7xxx_reg.h" 49#include "../../scsi/scsi_message.h" 50#endif 51 52/* 53 * We can't just use ACCUM in the sequencer code because it 54 * must be treated specially by the assembler, and it currently 55 * looks for the symbol 'A'. This is the only register defined in 56 * the assembler's symbol space. 57 */ 58A = ACCUM 59 60/* 61 * A few words on the waiting SCB list: 62 * After starting the selection hardware, we check for reconnecting targets 63 * as well as for our selection to complete just in case the reselection wins 64 * bus arbitration. The problem with this is that we must keep track of the 65 * SCB that we've already pulled from the QINFIFO and started the selection 66 * on just in case the reselection wins so that we can retry the selection at 67 * a later time. This problem cannot be resolved by holding a single entry 68 * in scratch ram since a reconnecting target can request sense and this will 69 * create yet another SCB waiting for selection. The solution used here is to 70 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list 71 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, 72 * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to 73 * this list everytime a request sense occurs or after completing a non-tagged 74 * command for which a second SCB has been queued. The sequencer will 75 * automatically consume the entries. 76 */ 77 78/* 79 * We assume that the kernel driver may reset us at any time, even in the 80 * middle of a DMA, so clear DFCNTRL too. 81 */ 82reset: 83 clr DFCNTRL 84 clr SCSISIGO /* De-assert BSY */ 85 86p_busfree: 87 mvi LASTPHASE, P_BUSFREE 88 89start: 90 and FLAGS,0x07 /* clear target specific flags */ 91 mvi SCSISEQ,ENRSELI /* Always allow reselection */ 92 clr SCSIRATE /* 93 * We don't know the target we will 94 * connect to, so default to narrow 95 * transfers to avoid parity problems. 96 */ 97poll_for_work: 98 /* 99 * Are we a twin channel device? 100 * For fairness, we check the other bus first, 101 * since we just finished a transaction on the 102 * current channel. 103 */ 104 test FLAGS,TWIN_BUS jz start2 105 xor SBLKCTL,SELBUSB /* Toggle to the other bus */ 106 test SSTAT0,SELDI jnz reselect 107 xor SBLKCTL,SELBUSB /* Toggle to the original bus */ 108start2: 109 test SSTAT0,SELDI jnz reselect 110 cmp WAITING_SCBH,SCB_LIST_NULL je test_queue 111start_waiting: 112 /* 113 * Pull the first entry off of the waiting SCB list 114 * We don't have to "test_busy" because only transactions that 115 * have passed that test can be in the WAITING_SCB list. 116 */ 117 mov SCBPTR,WAITING_SCBH 118 jmp start_scb2 119test_queue: 120 /* Has the driver posted any work for us? */ 121 mov A, QCNTMASK 122 test QINCNT,A jz poll_for_work 123 124/* 125 * We have at least one queued SCB now and we don't have any 126 * SCBs in the list of SCBs awaiting selection. If we have 127 * any SCBs availible for use, pull the tag from the QINFIFO 128 * and get to work on it. 129 */ 130 test FLAGS, PAGESCBS jz dequeue_scb 131 mov ALLZEROS call get_free_or_disc_scb 132 cmp SINDEX, SCB_LIST_NULL je poll_for_work 133dequeue_scb: 134 mov CUR_SCBID,QINFIFO 135 test FLAGS, PAGESCBS jnz dma_queued_scb 136 /* In the non-paging case, the SCBID == hardware SCB index */ 137 mov SCBPTR, CUR_SCBID 138dma_queued_scb: 139/* 140 * DMA the SCB from host ram into the current SCB location. 141 */ 142 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */ 143 mov CUR_SCBID call dma_scb 144 145/* 146 * See if there is not already an active SCB for this target. This code 147 * locks out on a per target basis instead of target/lun. Although this 148 * is not ideal for devices that have multiple luns active at the same 149 * time, it is faster than looping through all SCB's looking for active 150 * commands. We also don't have enough spare SCB space for us to store the 151 * SCBID of the currently busy transaction for each target/lun making it 152 * impossible to link up the SCBs. 153 */ 154test_busy: 155 test SCB_CONTROL, TAG_ENB jnz start_scb 156 mov SAVED_SCBPTR, SCBPTR 157 mov SCB_TCL call index_untagged_scb 158 mov ARG_1, SINDIR /* 159 * ARG_1 should 160 * now have the SCB ID of 161 * any active, non-tagged, 162 * command for this target. 163 */ 164 cmp ARG_1, SCB_LIST_NULL je make_busy 165 test FLAGS, PAGESCBS jz simple_busy_link 166 /* 167 * Put this SCB back onto the free list. It 168 * may be necessary to satisfy the search for 169 * the active SCB. 170 */ 171 mov SCBPTR, SAVED_SCBPTR 172 call add_scb_to_free_list 173 /* Find the active SCB */ 174 mov ALLZEROS call findSCB 175 /* 176 * If we couldn't find it, tell the kernel. This should 177 * only happen if the parent SCB was aborted and this 178 * one was already here at the time of the abort. 179 */ 180 cmp SINDEX, SCB_LIST_NULL jne paged_busy_link 181 mvi INTSTAT, NO_MATCH_BUSY 182paged_busy_link: 183 /* Link us in */ 184 mov SCB_LINKED_NEXT, CUR_SCBID 185 /* Put it back on the disconnected list */ 186 call add_scb_to_disc_list 187 jmp poll_for_work 188simple_busy_link: 189 mov SCBPTR, ARG_1 190 mov SCB_LINKED_NEXT, CUR_SCBID 191 jmp poll_for_work 192make_busy: 193 mov DINDIR, CUR_SCBID 194 mov SCBPTR, SAVED_SCBPTR 195 196start_scb: 197 /* 198 * Place us on the waiting list in case our selection 199 * doesn't win during bus arbitration. 200 */ 201 mov SCB_NEXT,WAITING_SCBH 202 mov WAITING_SCBH, SCBPTR 203start_scb2: 204 and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */ 205 and A,0x08,SCB_TCL /* Get new channel bit */ 206 or SINDEX,A 207 mov SBLKCTL,SINDEX /* select channel */ 208 mov SCB_TCL call initialize_scsiid 209 210/* 211 * Enable selection phase as an initiator, and do automatic ATN 212 * after the selection. We do this now so that we can overlap the 213 * rest of our work to set up this target with the arbitration and 214 * selection bus phases. 215 */ 216start_selection: 217 mvi SCSISEQ,0x58 /* ENSELO|ENAUTOATNO|ENRSELI */ 218 219/* 220 * As soon as we get a successful selection, the target should go 221 * into the message out phase since we have ATN asserted. Prepare 222 * the message to send. 223 * 224 * Messages are stored in scratch RAM starting with a length byte 225 * followed by the message itself. 226 */ 227 228mk_identify: 229 and MSG0,0x7,SCB_TCL /* lun */ 230 and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */ 231 or MSG0,A /* or in disconnect privledge */ 232 or MSG0,MSG_IDENTIFYFLAG 233 mvi MSG_LEN, 1 234 235/* 236 * Send a tag message if TAG_ENB is set in the SCB control block. 237 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. 238 */ 239mk_tag: 240 test SCB_CONTROL,TAG_ENB jz mk_message 241 and MSG1,0x23,SCB_CONTROL 242 mov MSG2,SCB_TAG 243 add MSG_LEN,2 /* update message length */ 244 245/* 246 * Interrupt the driver, and allow it to tweak the message buffer 247 * if it asks. 248 */ 249mk_message: 250 test SCB_CONTROL,MK_MESSAGE jz wait_for_selection 251 252 mvi INTSTAT,AWAITING_MSG 253 254wait_for_selection: 255 test SSTAT0,SELDO jnz select 256 test SSTAT0,SELDI jz wait_for_selection 257 258/* 259 * Reselection has been initiated by a target. Make a note that we've been 260 * reselected, but haven't seen an IDENTIFY message from the target yet. 261 */ 262reselect: 263 clr MSG_LEN /* Don't have anything in the mesg buffer */ 264 mov SELID call initialize_scsiid 265 or FLAGS,RESELECTED 266 jmp select2 267 268/* 269 * After the selection, remove this SCB from the "waiting SCB" 270 * list. This is achieved by simply moving our "next" pointer into 271 * WAITING_SCBH. Our next pointer will be set to null the next time this 272 * SCB is used, so don't bother with it now. 273 */ 274select: 275 mov WAITING_SCBH,SCB_NEXT 276select2: 277/* 278 * Initialize SCSIRATE with the appropriate value for this target. 279 * The SCSIRATE settings for each target are stored in an array 280 * based at TARG_SCRATCH. 281 */ 282ndx_dtr: 283 shr A,SCSIID,4 284 test SBLKCTL,SELBUSB jz ndx_dtr_2 285 or SAVED_TCL, SELBUSB /* Add the channel bit while we're here */ 286 or A,0x08 /* Channel B entries add 8 */ 287ndx_dtr_2: 288 add SINDEX,TARG_SCRATCH,A 289 mov SCSIRATE,SINDIR 290 291/* 292 * Initialize Ultra mode setting and clear the SCSI channel. 293 */ 294ultra: 295 and DINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */ 296 /* 297 * Set CLRCHN here before the target has entered a data transfer mode - 298 * with synchronous SCSI, if you do it later, you blow away some 299 * data in the SCSI FIFO that the target has already sent to you. 300 */ 301 or DINDEX, CLRCHN 302 mvi SINDEX, ULTRA_ENB_B 303 test SCSIID, 0x80 jnz ultra_2 /* Target ID > 7 */ 304 test SBLKCTL, SELBUSB jnz ultra_2 /* Second channel device */ 305 dec SINDEX 306ultra_2: 307 mov FUNCTION1,SCSIID 308 mov A,FUNCTION1 309 test SINDIR, A jz set_sxfrctl0 310 or DINDEX, ULTRAEN 311 312set_sxfrctl0: 313 mov SXFRCTL0,DINDEX 314 315 mvi SCSISEQ,ENAUTOATNP /* 316 * ATN on parity errors 317 * for "in" phases 318 */ 319 mvi CLRSINT1,CLRBUSFREE 320 mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */ 321 or SIMODE1, ENBUSFREE /* 322 * We aren't expecting a 323 * bus free, so interrupt 324 * the kernel driver if it 325 * happens. 326 */ 327/* 328 * Main loop for information transfer phases. If BSY is false, then 329 * we have a bus free condition, expected or not. Otherwise, wait 330 * for the target to assert REQ before checking MSG, C/D and I/O 331 * for the bus phase. 332 * 333 */ 334ITloop: 335 test SSTAT1,BUSFREE jnz p_busfree 336 test SSTAT1,REQINIT jz ITloop 337 338 and A,PHASE_MASK,SCSISIGI 339 mov LASTPHASE,A 340 mov SCSISIGO,A 341 342 cmp ALLZEROS,A je p_dataout 343 cmp A,P_DATAIN je p_datain 344 cmp A,P_COMMAND je p_command 345 cmp A,P_MESGOUT je p_mesgout 346 cmp A,P_STATUS je p_status 347 cmp A,P_MESGIN je p_mesgin 348 349 mvi INTSTAT,BAD_PHASE /* unknown phase - signal driver */ 350 jmp ITloop /* Try reading the bus again. */ 351 352p_dataout: 353 mvi DMAPARAMS,0x7d /* 354 * WIDEODD|SCSIEN|SDMAEN|HDMAEN| 355 * DIRECTION|FIFORESET 356 */ 357 jmp data_phase_init 358 359/* 360 * If we re-enter the data phase after going through another phase, the 361 * STCNT may have been cleared, so restore it from the residual field. 362 */ 363data_phase_reinit: 364 mvi DINDEX, STCNT0 365 mvi SCB_RESID_DCNT0 call bcopy_3 366 jmp data_phase_loop 367 368p_datain: 369 mvi DMAPARAMS,0x79 /* 370 * WIDEODD|SCSIEN|SDMAEN|HDMAEN| 371 * !DIRECTION|FIFORESET 372 */ 373data_phase_init: 374 call assert /* 375 * Ensure entering a data 376 * phase is okay - seen identify, etc. 377 */ 378 379 test FLAGS, DPHASE jnz data_phase_reinit 380 381 /* 382 * Initialize the DMA address and counter from the SCB. 383 * Also set SG_COUNT and SG_NEXT in memory since we cannot 384 * modify the values in the SCB itself until we see a 385 * save data pointers message. 386 */ 387 mvi DINDEX, HADDR0 388 mvi SCB_DATAPTR call bcopy_7 389 390 call set_stcnt_from_hcnt 391 392 mov SG_COUNT,SCB_SGCOUNT 393 394 mvi DINDEX, SG_NEXT 395 mvi SCB_SGPTR call bcopy_4 396 397 /* We have seen a data phase */ 398 or FLAGS, DPHASE 399 400data_phase_loop: 401/* Guard against overruns */ 402 test SG_COUNT, 0xff jnz data_phase_inbounds 403/* 404 * Turn on 'Bit Bucket' mode, set the transfer count to 405 * 16meg and let the target run until it changes phase. 406 * When the transfer completes, notify the host that we 407 * had an overrun. 408 */ 409 or SXFRCTL1,BITBUCKET 410 and DMAPARAMS, 0xf7 /* Turn off HDMAEN */ 411 mvi STCNT0,0xff 412 mvi STCNT1,0xff 413 mvi STCNT2,0xff 414 415data_phase_inbounds: 416/* If we are the last SG block, ensure wideodd is off. */ 417 cmp SG_COUNT,0x01 jne data_phase_wideodd 418 and DMAPARAMS, 0xbf /* Turn off WIDEODD */ 419data_phase_wideodd: 420 mov DMAPARAMS call dma 421 422/* Go tell the host about any overruns */ 423 test SXFRCTL1,BITBUCKET jnz data_phase_overrun 424 425/* Exit if we had an underrun */ 426 test SSTAT0,SDONE jz data_phase_finish /* underrun STCNT != 0 */ 427 428/* 429 * Advance the scatter-gather pointers if needed 430 */ 431sg_advance: 432 dec SG_COUNT /* one less segment to go */ 433 434 test SG_COUNT, 0xff jz data_phase_finish /* Are we done? */ 435 436 clr A /* add sizeof(struct scatter) */ 437 add SG_NEXT0,SG_SIZEOF,SG_NEXT0 438 adc SG_NEXT1,A,SG_NEXT1 439 440/* 441 * Load a struct scatter and set up the data address and length. 442 * If the working value of the SG count is nonzero, then 443 * we need to load a new set of values. 444 * 445 * This, like all DMA's, assumes little-endian host data storage. 446 */ 447sg_load: 448 clr HCNT2 449 clr HCNT1 450 mvi HCNT0,SG_SIZEOF 451 452 mvi DINDEX, HADDR0 453 mvi SG_NEXT0 call bcopy_4 454 455 or DFCNTRL,0xd /* HDMAEN|DIRECTION|FIFORESET */ 456 457 call dma_finish 458 459/* 460 * Copy data from FIFO into SCB data pointer and data count. This assumes 461 * that the SG segments are of the form: 462 * 463 * struct ahc_dma_seg { 464 * u_int32_t addr; four bytes, little-endian order 465 * u_int32_t len; four bytes, little endian order 466 * }; 467 */ 468 mvi HADDR0 call dfdat_in_7 469 470/* Load STCNT as well. It is a mirror of HCNT */ 471 call set_stcnt_from_hcnt 472 test SSTAT1,PHASEMIS jz data_phase_loop 473 474data_phase_finish: 475/* 476 * After a DMA finishes, save the SG and STCNT residuals back into the SCB 477 * We use STCNT instead of HCNT, since it's a reflection of how many bytes 478 * were transferred on the SCSI (as opposed to the host) bus. 479 */ 480 mov SCB_RESID_DCNT0,STCNT0 481 mov SCB_RESID_DCNT1,STCNT1 482 mov SCB_RESID_DCNT2,STCNT2 483 mov SCB_RESID_SGCNT, SG_COUNT 484 jmp ITloop 485 486data_phase_overrun: 487/* 488 * Turn off BITBUCKET mode and notify the host 489 */ 490 and SXFRCTL1,0x7f /* ~BITBUCKET */ 491 mvi INTSTAT,DATA_OVERRUN 492 jmp ITloop 493 494/* 495 * Command phase. Set up the DMA registers and let 'er rip. 496 */ 497p_command: 498 call assert 499 500/* 501 * Load HADDR and HCNT. 502 */ 503 mvi DINDEX, HADDR0 504 mvi SCB_CMDPTR call bcopy_5 505 clr HCNT1 506 clr HCNT2 507 508 call set_stcnt_from_hcnt 509 510 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN| 511 # DIRECTION|FIFORESET 512 jmp ITloop 513 514/* 515 * Status phase. Wait for the data byte to appear, then read it 516 * and store it into the SCB. 517 */ 518p_status: 519 call assert 520 521 mvi SCB_TARGET_STATUS call inb_first 522 jmp mesgin_done 523 524/* 525 * Message out phase. If there is not an active message, but the target 526 * took us into this phase anyway, build a no-op message and send it. 527 */ 528p_mesgout: 529 test MSG_LEN, 0xff jnz p_mesgout_start 530 mvi MSG_NOOP call mk_mesg /* build NOP message */ 531p_mesgout_start: 532/* 533 * Set up automatic PIO transfer from MSG0. Bit 3 in 534 * SXFRCTL0 (SPIOEN) is already on. 535 */ 536 mvi SINDEX,MSG0 537 mov DINDEX,MSG_LEN 538 539/* 540 * When target asks for a byte, drop ATN if it's the last one in 541 * the message. Otherwise, keep going until the message is exhausted. 542 * 543 * Keep an eye out for a phase change, in case the target issues 544 * a MESSAGE REJECT. 545 */ 546p_mesgout_loop: 547 test SSTAT0,SPIORDY jz p_mesgout_loop 548 test SSTAT1,PHASEMIS jnz p_mesgout_done 549/* 550 * If the next bus phase after ATN drops is a message out, it means 551 * that the target is requesting that the last message(s) be resent. 552 */ 553p_mesgout_dropatn: 554 cmp DINDEX,1 jne p_mesgout_testretry /* last byte? */ 555 mvi CLRSINT1,CLRATNO /* drop ATN */ 556p_mesgout_testretry: 557 test DINDEX,0xff jnz p_mesgout_outb 558 or SCSISIGO,ATNO /* turn on ATN for the retry */ 559 jmp p_mesgout_start 560p_mesgout_outb: 561 dec DINDEX 562 mvi CLRSINT0, CLRSPIORDY 563 mov SCSIDATL,SINDIR 564 jmp p_mesgout_loop 565 566p_mesgout_done: 567 mvi CLRSINT1,CLRATNO /* Be sure to turn ATNO off */ 568 clr MSG_LEN /* no active msg */ 569 jmp ITloop 570 571/* 572 * Message in phase. Bytes are read using Automatic PIO mode. 573 */ 574p_mesgin: 575 mvi A call inb_first /* read the 1st message byte */ 576 mov REJBYTE,A /* save it for the driver */ 577 578 test A,MSG_IDENTIFYFLAG jnz mesgin_identify 579 cmp A,MSG_DISCONNECT je mesgin_disconnect 580 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs 581 cmp ALLZEROS,A je mesgin_complete 582 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs 583 cmp A,MSG_EXTENDED je mesgin_extended 584 cmp A,MSG_MESSAGE_REJECT je mesgin_reject 585 586rej_mesgin: 587/* 588 * We have no idea what this message in is, so we issue a message reject 589 * and hope for the best. In any case, rejection should be a rare 590 * occurrence - signal the driver when it happens. 591 */ 592 mvi INTSTAT,SEND_REJECT /* let driver know */ 593 594 mvi MSG_MESSAGE_REJECT call mk_mesg 595 596mesgin_done: 597 call inb_last /*ack & turn auto PIO back on*/ 598 jmp ITloop 599 600 601mesgin_complete: 602/* 603 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO, 604 * and trigger a completion interrupt. Before doing so, check to see if there 605 * is a residual or the status byte is something other than NO_ERROR (0). In 606 * either of these conditions, we upload the SCB back to the host so it can 607 * process this information. In the case of a non zero status byte, we 608 * additionally interrupt the kernel driver synchronously, allowing it to 609 * decide if sense should be retrieved. If the kernel driver wishes to request 610 * sense, it will fill the kernel SCB with a request sense command and set 611 * RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE we redownload 612 * the SCB, and process it as the next command by adding it to the waiting list. 613 * If the kernel driver does not wish to request sense, it need only clear 614 * RETURN_1, and the command is allowed to complete normally. We don't bother 615 * to post to the QOUTFIFO in the error cases since it would require extra 616 * work in the kernel driver to ensure that the entry was removed before the 617 * command complete code tried processing it. 618 */ 619 620/* 621 * We expect to go to bus free after this message. 622 */ 623 and SIMODE1, 0xf7 /* ~ENBUSFREE */ 624/* 625 * First check for residuals 626 */ 627 test SCB_RESID_SGCNT,0xff jnz upload_scb 628 test SCB_TARGET_STATUS,0xff jz status_ok /* Good Status? */ 629upload_scb: 630 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/ 631 mov SCB_TAG call dma_scb 632check_status: 633 test SCB_TARGET_STATUS,0xff jz status_ok /* Just a residual? */ 634 mvi INTSTAT,BAD_STATUS /* let driver know */ 635 cmp RETURN_1, SEND_SENSE jne status_ok 636 /* This SCB becomes the next to execute as it will retrieve sense */ 637 mov SCB_LINKED_NEXT, SCB_TAG 638 jmp dma_next_scb 639 640status_ok: 641/* First, mark this target as free. */ 642 test SCB_CONTROL,TAG_ENB jnz complete /* 643 * Tagged commands 644 * don't busy the 645 * target. 646 */ 647 mov SAVED_SCBPTR, SCBPTR 648 mov SAVED_LINKPTR, SCB_LINKED_NEXT 649 mov SCB_TCL call index_untagged_scb 650 mov DINDIR, SAVED_LINKPTR 651 mov SCBPTR, SAVED_SCBPTR 652 653complete: 654 test FLAGS, PAGESCBS jz complete_post 655 mov A, QFULLCNT 656complete_poll: 657 cmp QOUTQCNT, A je complete_poll 658 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */ 659 inc QOUTQCNT 660complete_post: 661 /* Post the SCB and issue an interrupt */ 662 mov QOUTFIFO,SCB_TAG 663 mvi SEQCTL,0x10 /* FASTMODE */ 664 mvi INTSTAT,CMDCMPLT 665 666dma_next_scb: 667 cmp SCB_LINKED_NEXT, SCB_LIST_NULL je add_to_free_list 668 test FLAGS, PAGESCBS jnz dma_next_scb2 669 /* Only DMA on top of ourselves if we are the SCB to download */ 670 mov A, SCB_LINKED_NEXT 671 cmp SCB_TAG, A je dma_next_scb2 672 mov SCBPTR, A 673 jmp add_to_waiting_list 674dma_next_scb2: 675 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */ 676 mov SCB_LINKED_NEXT call dma_scb 677add_to_waiting_list: 678 mov SCB_NEXT,WAITING_SCBH 679 mov WAITING_SCBH, SCBPTR 680 jmp mesgin_done 681add_to_free_list: 682 call add_scb_to_free_list 683 jmp mesgin_done 684 685/* 686 * Is it an extended message? Copy the message to our message buffer and 687 * notify the host. The host will tell us whether to reject this message, 688 * respond to it with the message that the host placed in our message buffer, 689 * or simply to do nothing. 690 */ 691mesgin_extended: 692 mvi MSGIN_EXT_LEN call inb_next 693 mov A, MSGIN_EXT_LEN 694mesgin_extended_loop: 695 mov DINDEX call inb_next 696 dec A 697 cmp DINDEX, MSGIN_EXT_LASTBYTE jne mesgin_extended_loop_test 698 dec DINDEX /* dump by repeatedly filling the last byte */ 699mesgin_extended_loop_test: 700 test A, 0xFF jnz mesgin_extended_loop 701mesgin_extended_intr: 702 mvi INTSTAT,EXTENDED_MSG /* let driver know */ 703 cmp RETURN_1,SEND_REJ je rej_mesgin 704 cmp RETURN_1,SEND_MSG jne mesgin_done 705/* The kernel has setup a message to be sent */ 706 or SCSISIGO,ATNO /* turn on ATNO */ 707 jmp mesgin_done 708 709/* 710 * Is it a disconnect message? Set a flag in the SCB to remind us 711 * and await the bus going free. 712 */ 713mesgin_disconnect: 714 and SIMODE1, 0xf7 /* ~ENBUSFREE */ 715 or SCB_CONTROL,DISCONNECTED 716 test FLAGS, PAGESCBS jz mesgin_done 717 call add_scb_to_disc_list 718 jmp mesgin_done 719 720/* 721 * Save data pointers message: 722 * Copying RAM values back to SCB, for Save Data Pointers message, but 723 * only if we've actually been into a data phase to change them. This 724 * protects against bogus data in scratch ram and the residual counts 725 * since they are only initialized when we go into data_in or data_out. 726 */ 727mesgin_sdptrs: 728 test FLAGS, DPHASE jz mesgin_done 729 mov SCB_SGCOUNT,SG_COUNT 730 731 /* The SCB SGPTR becomes the next one we'll download */ 732 mvi DINDEX, SCB_SGPTR 733 mvi SG_NEXT0 call bcopy_4 734 735 /* The SCB DATAPTR0 becomes the current SHADDR */ 736 mvi DINDEX, SCB_DATAPTR0 737 mvi SHADDR0 call bcopy_4 738 739/* 740 * Use the residual number since STCNT is corrupted by any message transfer. 741 */ 742 mvi SCB_RESID_DCNT0 call bcopy_3 743 744 jmp mesgin_done 745 746/* 747 * Restore pointers message? Data pointers are recopied from the 748 * SCB anytime we enter a data phase for the first time, so all 749 * we need to do is clear the DPHASE flag and let the data phase 750 * code do the rest. 751 */ 752mesgin_rdptrs: 753 and FLAGS,0xef /* 754 * !DPHASE we'll reload them 755 * the next time through 756 */ 757 jmp mesgin_done 758 759/* 760 * Identify message? For a reconnecting target, this tells us the lun 761 * that the reconnection is for - find the correct SCB and switch to it, 762 * clearing the "disconnected" bit so we don't "find" it by accident later. 763 */ 764mesgin_identify: 765 test A,0x78 jnz rej_mesgin /*!DiscPriv|!LUNTAR|!Reserved*/ 766 and A,0x07 /* lun in lower three bits */ 767 or SAVED_TCL,A /* SAVED_TCL should be complete now */ 768 call inb_last /* ACK */ 769 770/* 771 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. 772 * If we get one, we use the tag returned to switch to find the proper 773 * SCB. With SCB paging, this requires using findSCB for both tagged 774 * and non-tagged transactions since the SCB may exist in any slot. 775 * If we're not using SCB paging, we can use the tag as the direct 776 * index to the SCB. 777 */ 778 mvi ARG_1,SCB_LIST_NULL /* Default to no-tag */ 779snoop_tag_loop: 780 test SSTAT0,SPIORDY jz snoop_tag_loop 781 test SSTAT1,PHASEMIS jnz use_findSCB 782 mvi A call inb_first 783 cmp A,MSG_SIMPLE_Q_TAG jne use_findSCB 784get_tag: 785 or FLAGS, TAGGED_SCB 786 mvi ARG_1 call inb_next /* tag value */ 787/* 788 * See if the tag is in range. The tag is < SCBCOUNT if we add 789 * the complement of SCBCOUNT to the incomming tag and there is 790 * no carry. 791 */ 792 mov A,COMP_SCBCOUNT 793 add SINDEX,A,ARG_1 794 jc send_abort_msg 795 796/* 797 * Ensure that the SCB the tag points to is for an SCB transaction 798 * to the reconnecting target. 799 */ 800 test FLAGS, PAGESCBS jz index_by_tag 801use_findSCB: 802 mov ALLZEROS call findSCB /* Have to search */ 803 cmp SINDEX, SCB_LIST_NULL, je not_found 804setup_SCB: 805 and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */ 806 or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */ 807 test SCB_CONTROL,TAG_ENB jnz mesgin_done /* Ack Tag */ 808 jmp ITloop 809index_by_tag: 810 mov SCBPTR,ARG_1 811 mov A, SAVED_TCL 812 cmp SCB_TCL,A jne send_abort_msg 813 test SCB_CONTROL,TAG_ENB jz send_abort_msg 814 jmp setup_SCB 815 816not_found: 817 mvi INTSTAT, NO_MATCH 818send_abort_msg: 819 test FLAGS, TAGGED_SCB jnz abort_tag_msg 820 mvi MSG_ABORT call mk_mesg 821 jmp mesgin_done 822abort_tag_msg: 823 mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */ 824 jmp mesgin_done 825 826/* 827 * Message reject? Let the kernel driver handle this. If we have an 828 * outstanding WDTR or SDTR negotiation, assume that it's a response from 829 * the target selecting 8bit or asynchronous transfer, otherwise just ignore 830 * it since we have no clue what it pertains to. 831 */ 832mesgin_reject: 833 mvi INTSTAT, REJECT_MSG 834 jmp mesgin_done 835 836/* 837 * [ ADD MORE MESSAGE HANDLING HERE ] 838 */ 839 840/* 841 * Locking the driver out, build a one-byte message passed in SINDEX 842 * if there is no active message already. SINDEX is returned intact. 843 */ 844mk_mesg: 845 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */ 846 test MSG_LEN,0xff jz mk_mesg1 /* Should always succeed */ 847 848 /* 849 * Hmmm. For some reason the mesg buffer is in use. 850 * Tell the driver. It should look at SINDEX to find 851 * out what we wanted to use the buffer for and resolve 852 * the conflict. 853 */ 854 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */ 855 mvi INTSTAT,MSG_BUFFER_BUSY 856 857mk_mesg1: 858 or SCSISIGO,ATNO /* turn on ATNO */ 859 mvi MSG_LEN,1 /* length = 1 */ 860 mov MSG0,SINDEX /* 1-byte message */ 861 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */ 862 863/* 864 * Functions to read data in Automatic PIO mode. 865 * 866 * According to Adaptec's documentation, an ACK is not sent on input from 867 * the target until SCSIDATL is read from. So we wait until SCSIDATL is 868 * latched (the usual way), then read the data byte directly off the bus 869 * using SCSIBUSL. When we have pulled the ATN line, or we just want to 870 * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI 871 * spec guarantees that the target will hold the data byte on the bus until 872 * we send our ACK. 873 * 874 * The assumption here is that these are called in a particular sequence, 875 * and that REQ is already set when inb_first is called. inb_{first,next} 876 * use the same calling convention as inb. 877 */ 878 879inb_next: 880 call inb_last /* ACK */ 881inb_next_wait: 882 test SSTAT0, SPIORDY jz inb_next_wait 883 test SSTAT1,PHASEMIS jnz mesgin_phasemis 884inb_first: 885 mov DINDEX,SINDEX 886 mov DINDIR,SCSIBUSL ret /*read byte directly from bus*/ 887inb_last: 888 mvi CLRSINT0, CLRSPIORDY 889 mov NONE,SCSIDATL ret /*dummy read from latch to ACK*/ 890 891mesgin_phasemis: 892/* 893 * We expected to receive another byte, but the target changed phase 894 */ 895 mvi INTSTAT, MSGIN_PHASEMIS 896 jmp ITloop 897 898/* 899 * DMA data transfer. HADDR and HCNT must be loaded first, and 900 * SINDEX should contain the value to load DFCNTRL with - 0x3d for 901 * host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared 902 * during initialization. 903 */ 904dma: 905 mov DFCNTRL,SINDEX 906dma1: 907 test SSTAT0,DMADONE jnz dma3 908 test SSTAT1,PHASEMIS jz dma1 /* ie. underrun */ 909 910/* 911 * We will be "done" DMAing when the transfer count goes to zero, or 912 * the target changes the phase (in light of this, it makes sense that 913 * the DMA circuitry doesn't ACK when PHASEMIS is active). If we are 914 * doing a SCSI->Host transfer, the data FIFO should be flushed auto- 915 * magically on STCNT=0 or a phase change, so just wait for FIFO empty 916 * status. 917 */ 918dma3: 919 test SINDEX,DIRECTION jnz dma5 920dma4: 921 test DFSTATUS,FIFOEMP jz dma4 922 923/* 924 * Now shut the DMA enables off and make sure that the DMA enables are 925 * actually off first lest we get an ILLSADDR. 926 */ 927dma5: 928 /* disable DMA, but maintain WIDEODD */ 929 and DFCNTRL,WIDEODD 930dma6: 931 test DFCNTRL,0x38 jnz dma6 /* SCSIENACK|SDMAENACK|HDMAENACK */ 932return: 933 ret 934 935/* 936 * Common SCSI initialization for selection and reselection. Expects 937 * the target SCSI ID to be in the upper four bits of SINDEX, and A's 938 * contents are stomped on return. 939 */ 940initialize_scsiid: 941 and SINDEX,0xf0 /* Get target ID */ 942 mov SAVED_TCL, SINDEX /* Update the target portion of this */ 943 and A,0x0f,SCSIID 944 or SINDEX,A 945 mov SCSIID,SINDEX ret 946 947/* 948 * Assert that if we've been reselected, then we've seen an IDENTIFY 949 * message. 950 */ 951assert: 952 test FLAGS,RESELECTED jz return /* reselected? */ 953 test FLAGS,IDENTIFY_SEEN jnz return /* seen IDENTIFY? */ 954 955 mvi INTSTAT,NO_IDENT ret /* no - tell the kernel */ 956 957/* 958 * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL) 959 * or by the SCBIDn ARG_1. The search begins at the SCB index passed in 960 * via SINDEX. If the SCB cannot be found, SINDEX will be SCB_LIST_NULL, 961 * otherwise, SCBPTR is set to the proper SCB. 962 */ 963findSCB: 964 mov SCBPTR,SINDEX /* switch to next SCB */ 965 test SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/ 966 cmp ARG_1, SCB_LIST_NULL jne findBySCBID 967 mov A, SAVED_TCL 968 cmp SCB_TCL,A je foundSCB /* target ID/channel/lun match? */ 969findSCB1: 970 inc SINDEX 971 mov A,SCBCOUNT 972 cmp SINDEX,A jne findSCB 973/* 974 * We didn't find it. If we're paging, pull an SCB and DMA down the 975 * one we want. If we aren't paging or the SCB we dma down has the 976 * abort flag set, return not found. 977 */ 978 test FLAGS, PAGESCBS jz find_error 979 mov ALLZEROS call get_free_or_disc_scb 980 cmp ARG_1, SCB_LIST_NULL jne find_dma_scb 981 mov SAVED_TCL call index_untagged_scb 982 mov ARG_1, SINDIR /* SCBID of SCB to fetch */ 983find_dma_scb: 984 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */ 985 mov ARG_1 call dma_scb 986 test SCB_CONTROL, ABORT_SCB jz return 987find_error: 988 mvi SINDEX, SCB_LIST_NULL ret 989findBySCBID: 990 mov A, ARG_1 /* Tag passed in ARG_1 */ 991 cmp SCB_TAG,A jne findSCB1 /* Found it? */ 992foundSCB: 993 test SCB_CONTROL, ABORT_SCB jnz find_error 994 test FLAGS,PAGESCBS jz return 995rem_scb_from_disc_list: 996/* Remove this SCB from the disconnection list */ 997 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev 998 mov SAVED_LINKPTR, SCB_PREV 999 mov SCBPTR, SCB_NEXT 1000 mov SCB_PREV, SAVED_LINKPTR 1001 mov SCBPTR, SINDEX 1002unlink_prev: 1003 cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */ 1004 mov SAVED_LINKPTR, SCB_NEXT 1005 mov SCBPTR, SCB_PREV 1006 mov SCB_NEXT, SAVED_LINKPTR 1007 mov SCBPTR, SINDEX ret 1008rHead: 1009 mov DISCONNECTED_SCBH,SCB_NEXT ret 1010 1011set_stcnt_from_hcnt: 1012 mov STCNT0, HCNT0 1013 mov STCNT1, HCNT1 1014 mov STCNT2, HCNT2 ret 1015 1016bcopy_7: 1017 mov DINDIR, SINDIR 1018 mov DINDIR, SINDIR 1019bcopy_5: 1020 mov DINDIR, SINDIR 1021bcopy_4: 1022 mov DINDIR, SINDIR 1023bcopy_3: 1024 mov DINDIR, SINDIR 1025 mov DINDIR, SINDIR 1026 mov DINDIR, SINDIR ret 1027 1028dma_scb: 1029 /* 1030 * SCB index is in SINDEX. Determine the physical address in 1031 * the host where this SCB is located and load HADDR with it. 1032 */ 1033 shr DINDEX, SINDEX, 3 1034 shl A, SINDEX, 5 1035 add HADDR0, A, HSCB_ADDR0 1036 mov A, DINDEX 1037 adc HADDR1, A, HSCB_ADDR1 1038 clr A 1039 adc HADDR2, A, HSCB_ADDR2 1040 adc HADDR3, A, HSCB_ADDR3 1041 /* Setup Count */ 1042 mvi HCNT0, 28 1043 clr HCNT1 1044 clr HCNT2 1045 mov DFCNTRL, DMAPARAMS 1046 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost 1047 /* Fill it with the SCB data */ 1048 call copy_scb_tofifo 1049 mvi DFCNTRL, 0xa /* HDMAEN | FIFOFLUSH */ 1050dma_scb_fromhost: 1051 call dma_finish 1052 /* If we were putting the SCB, we are done */ 1053 test DMAPARAMS, DIRECTION jz return 1054 mvi SCBARRAY call dfdat_in_7 1055 call dfdat_in_7_continued 1056 call dfdat_in_7_continued 1057 jmp dfdat_in_7_continued 1058dfdat_in_7: 1059 mov DINDEX,SINDEX 1060dfdat_in_7_continued: 1061 mov DINDIR,DFDAT 1062 mov DINDIR,DFDAT 1063 mov DINDIR,DFDAT 1064 mov DINDIR,DFDAT 1065 mov DINDIR,DFDAT 1066 mov DINDIR,DFDAT 1067 mov DINDIR,DFDAT ret 1068 1069copy_scb_tofifo: 1070 mvi SCBARRAY call dfdat_out_7 1071 call dfdat_out_7 1072 call dfdat_out_7 1073dfdat_out_7: 1074 mov DFDAT,SINDIR 1075 mov DFDAT,SINDIR 1076 mov DFDAT,SINDIR 1077 mov DFDAT,SINDIR 1078 mov DFDAT,SINDIR 1079 mov DFDAT,SINDIR 1080 mov DFDAT,SINDIR ret 1081 1082/* 1083 * Wait for DMA from host memory to data FIFO to complete, then disable 1084 * DMA and wait for it to acknowledge that it's off. 1085 */ 1086dma_finish: 1087 test DFSTATUS,HDONE jz dma_finish 1088 /* Turn off DMA preserving WIDEODD */ 1089 and DFCNTRL,WIDEODD 1090dma_finish2: 1091 test DFCNTRL,HDMAENACK jnz dma_finish2 1092 ret 1093 1094index_untagged_scb: 1095 mov DINDEX, SINDEX 1096 shr DINDEX, 4 1097 and DINDEX, 0x03 /* Bottom two bits of tid */ 1098 add DINDEX, SCB_ACTIVE0 1099 shr A, SINDEX, 6 /* Target ID divided by 4 */ 1100 test SINDEX, SELBUSB jz index_untagged_scb2 1101 add A, 2 /* Add 2 positions */ 1102index_untagged_scb2: 1103 mov SCBPTR, A /* 1104 * Select the SCB with this 1105 * target's information. 1106 */ 1107 mov SINDEX, DINDEX ret 1108 1109 1110get_free_or_disc_scb: 1111 cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb 1112 cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb 1113return_error: 1114 mvi SINDEX, SCB_LIST_NULL ret 1115dequeue_disc_scb: 1116 mov SCBPTR, DISCONNECTED_SCBH 1117/* 1118 * If we have a residual, then we are in the middle of some I/O 1119 * and we have to send this SCB back up to the kernel so that the 1120 * saved data pointers and residual information isn't lost. 1121 */ 1122 test SCB_RESID_SGCNT,0xff jz unlink_disc_scb 1123 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/ 1124 mov SCB_TAG call dma_scb 1125unlink_disc_scb: 1126 /* jmp instead of call since we want to return anyway */ 1127 mov SCBPTR jmp rem_scb_from_disc_list 1128dequeue_free_scb: 1129 mov SCBPTR, FREE_SCBH 1130 mov FREE_SCBH, SCB_NEXT ret 1131 1132add_scb_to_free_list: 1133 mov SCB_NEXT, FREE_SCBH 1134 mov FREE_SCBH, SCBPTR ret 1135 1136add_scb_to_disc_list: 1137/* 1138 * Link this SCB into the DISCONNECTED list. This list holds the 1139 * candidates for paging out an SCB if one is needed for a new command. 1140 * Modifying the disconnected list is a critical(pause dissabled) section. 1141 */ 1142 mvi SCB_PREV, SCB_LIST_NULL 1143 mov SCB_NEXT, DISCONNECTED_SCBH 1144 mov DISCONNECTED_SCBH, SCBPTR 1145 cmp SCB_NEXT,SCB_LIST_NULL je return 1146 mov SCBPTR,SCB_NEXT 1147 mov SCB_PREV,DISCONNECTED_SCBH 1148 mov SCBPTR,DISCONNECTED_SCBH ret 1149 1150