2400 lines · plain
1/*2 * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.3 *4 * Copyright (c) 1994-2001 Justin T. Gibbs.5 * Copyright (c) 2000-2001 Adaptec Inc.6 * All rights reserved.7 *8 * Redistribution and use in source and binary forms, with or without9 * modification, are permitted provided that the following conditions10 * are met:11 * 1. Redistributions of source code must retain the above copyright12 * notice, this list of conditions, and the following disclaimer,13 * without modification.14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer15 * substantially similar to the "NO WARRANTY" disclaimer below16 * ("Disclaimer") and any redistribution must be conditioned upon17 * including a substantially similar Disclaimer requirement for further18 * binary redistribution.19 * 3. Neither the names of the above-listed copyright holders nor the names20 * of any contributors may be used to endorse or promote products derived21 * from this software without specific prior written permission.22 *23 * Alternatively, this software may be distributed under the terms of the24 * GNU General Public License ("GPL") version 2 as published by the Free25 * Software Foundation.26 *27 * NO WARRANTY28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT32 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40 * $FreeBSD$41 */42 43VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"44PATCH_ARG_LIST = "struct ahc_softc *ahc"45PREFIX = "ahc_"46 47#include "aic7xxx.reg"48#include "scsi_message.h"49 50/*51 * A few words on the waiting SCB list:52 * After starting the selection hardware, we check for reconnecting targets53 * as well as for our selection to complete just in case the reselection wins54 * bus arbitration. The problem with this is that we must keep track of the55 * SCB that we've already pulled from the QINFIFO and started the selection56 * on just in case the reselection wins so that we can retry the selection at57 * a later time. This problem cannot be resolved by holding a single entry58 * in scratch ram since a reconnecting target can request sense and this will59 * create yet another SCB waiting for selection. The solution used here is to 60 * use byte 27 of the SCB as a pseudo-next pointer and to thread a list61 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, 62 * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to63 * this list every time a request sense occurs or after completing a non-tagged64 * command for which a second SCB has been queued. The sequencer will65 * automatically consume the entries.66 */67 68bus_free_sel:69 /*70 * Turn off the selection hardware. We need to reset the71 * selection request in order to perform a new selection.72 */73 and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP;74 and SIMODE1, ~ENBUSFREE;75poll_for_work:76 call clear_target_state;77 and SXFRCTL0, ~SPIOEN;78 if ((ahc->features & AHC_ULTRA2) != 0) {79 clr SCSIBUSL;80 }81 test SCSISEQ, ENSELO jnz poll_for_selection;82 if ((ahc->features & AHC_TWIN) != 0) {83 xor SBLKCTL,SELBUSB; /* Toggle to the other bus */84 test SCSISEQ, ENSELO jnz poll_for_selection;85 }86 cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting;87poll_for_work_loop:88 if ((ahc->features & AHC_TWIN) != 0) {89 xor SBLKCTL,SELBUSB; /* Toggle to the other bus */90 }91 test SSTAT0, SELDO|SELDI jnz selection;92test_queue:93 /* Has the driver posted any work for us? */94BEGIN_CRITICAL;95 if ((ahc->features & AHC_QUEUE_REGS) != 0) {96 test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;97 } else {98 mov A, QINPOS;99 cmp KERNEL_QINPOS, A je poll_for_work_loop;100 }101 mov ARG_1, NEXT_QUEUED_SCB;102 103 /*104 * We have at least one queued SCB now and we don't have any 105 * SCBs in the list of SCBs awaiting selection. Allocate a106 * card SCB for the host's SCB and get to work on it.107 */108 if ((ahc->flags & AHC_PAGESCBS) != 0) {109 mov ALLZEROS call get_free_or_disc_scb;110 } else {111 /* In the non-paging case, the SCBID == hardware SCB index */112 mov SCBPTR, ARG_1;113 }114 or SEQ_FLAGS2, SCB_DMA;115END_CRITICAL;116dma_queued_scb:117 /*118 * DMA the SCB from host ram into the current SCB location.119 */120 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;121 mov ARG_1 call dma_scb;122 /*123 * Check one last time to see if this SCB was canceled124 * before we completed the DMA operation. If it was,125 * the QINFIFO next pointer will not match our saved126 * value.127 */128 mov A, ARG_1;129BEGIN_CRITICAL;130 cmp NEXT_QUEUED_SCB, A jne abort_qinscb;131 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {132 cmp SCB_TAG, A je . + 2;133 mvi SCB_MISMATCH call set_seqint;134 }135 mov NEXT_QUEUED_SCB, SCB_NEXT;136 mov SCB_NEXT,WAITING_SCBH;137 mov WAITING_SCBH, SCBPTR;138 if ((ahc->features & AHC_QUEUE_REGS) != 0) {139 mov NONE, SNSCB_QOFF;140 } else {141 inc QINPOS;142 }143 and SEQ_FLAGS2, ~SCB_DMA;144END_CRITICAL;145start_waiting:146 /*147 * Start the first entry on the waiting SCB list.148 */149 mov SCBPTR, WAITING_SCBH;150 call start_selection;151 152poll_for_selection:153 /*154 * Twin channel devices cannot handle things like SELTO155 * interrupts on the "background" channel. So, while156 * selecting, keep polling the current channel until157 * either a selection or reselection occurs.158 */159 test SSTAT0, SELDO|SELDI jz poll_for_selection;160 161selection:162 /*163 * We aren't expecting a bus free, so interrupt164 * the kernel driver if it happens.165 */166 mvi CLRSINT1,CLRBUSFREE;167 if ((ahc->features & AHC_DT) == 0) {168 or SIMODE1, ENBUSFREE;169 }170 171 /*172 * Guard against a bus free after (re)selection173 * but prior to enabling the busfree interrupt. SELDI174 * and SELDO will be cleared in that case.175 */176 test SSTAT0, SELDI|SELDO jz bus_free_sel;177 test SSTAT0,SELDO jnz select_out;178select_in:179 if ((ahc->flags & AHC_TARGETROLE) != 0) {180 if ((ahc->flags & AHC_INITIATORROLE) != 0) {181 test SSTAT0, TARGET jz initiator_reselect;182 }183 mvi CLRSINT0, CLRSELDI;184 185 /*186 * We've just been selected. Assert BSY and187 * setup the phase for receiving messages188 * from the target.189 */190 mvi SCSISIGO, P_MESGOUT|BSYO;191 192 /*193 * Setup the DMA for sending the identify and194 * command information.195 */196 mvi SEQ_FLAGS, CMDPHASE_PENDING;197 198 mov A, TQINPOS;199 if ((ahc->features & AHC_CMD_CHAN) != 0) {200 mvi DINDEX, CCHADDR;201 mvi SHARED_DATA_ADDR call set_32byte_addr;202 mvi CCSCBCTL, CCSCBRESET;203 } else {204 mvi DINDEX, HADDR;205 mvi SHARED_DATA_ADDR call set_32byte_addr;206 mvi DFCNTRL, FIFORESET;207 }208 209 /* Initiator that selected us */210 and SAVED_SCSIID, SELID_MASK, SELID;211 /* The Target ID we were selected at */212 if ((ahc->features & AHC_MULTI_TID) != 0) {213 and A, OID, TARGIDIN;214 } else if ((ahc->features & AHC_ULTRA2) != 0) {215 and A, OID, SCSIID_ULTRA2;216 } else {217 and A, OID, SCSIID;218 }219 or SAVED_SCSIID, A;220 if ((ahc->features & AHC_TWIN) != 0) {221 test SBLKCTL, SELBUSB jz . + 2;222 or SAVED_SCSIID, TWIN_CHNLB;223 }224 if ((ahc->features & AHC_CMD_CHAN) != 0) {225 mov CCSCBRAM, SAVED_SCSIID;226 } else {227 mov DFDAT, SAVED_SCSIID;228 }229 230 /*231 * If ATN isn't asserted, the target isn't interested232 * in talking to us. Go directly to bus free.233 * XXX SCSI-1 may require us to assume lun 0 if234 * ATN is false.235 */236 test SCSISIGI, ATNI jz target_busfree;237 238 /*239 * Watch ATN closely now as we pull in messages from the240 * initiator. We follow the guidlines from section 6.5241 * of the SCSI-2 spec for what messages are allowed when.242 */243 call target_inb;244 245 /*246 * Our first message must be one of IDENTIFY, ABORT, or247 * BUS_DEVICE_RESET.248 */249 test DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop;250 /* Store for host */251 if ((ahc->features & AHC_CMD_CHAN) != 0) {252 mov CCSCBRAM, DINDEX;253 } else {254 mov DFDAT, DINDEX;255 }256 and SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX;257 258 /* Remember for disconnection decision */259 test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;260 /* XXX Honor per target settings too */261 or SEQ_FLAGS, NO_DISCONNECT;262 263 test SCSISIGI, ATNI jz ident_messages_done;264 call target_inb;265 /*266 * If this is a tagged request, the tagged message must267 * immediately follow the identify. We test for a valid268 * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and269 * < MSG_IGN_WIDE_RESIDUE.270 */271 add A, -MSG_SIMPLE_Q_TAG, DINDEX;272 jnc ident_messages_done_msg_pending;273 add A, -MSG_IGN_WIDE_RESIDUE, DINDEX;274 jc ident_messages_done_msg_pending;275 276 /* Store for host */277 if ((ahc->features & AHC_CMD_CHAN) != 0) {278 mov CCSCBRAM, DINDEX;279 } else {280 mov DFDAT, DINDEX;281 }282 283 /*284 * If the initiator doesn't feel like providing a tag number,285 * we've got a failed selection and must transition to bus286 * free.287 */288 test SCSISIGI, ATNI jz target_busfree;289 290 /*291 * Store the tag for the host.292 */293 call target_inb;294 if ((ahc->features & AHC_CMD_CHAN) != 0) {295 mov CCSCBRAM, DINDEX;296 } else {297 mov DFDAT, DINDEX;298 }299 mov INITIATOR_TAG, DINDEX;300 or SEQ_FLAGS, TARGET_CMD_IS_TAGGED;301 302ident_messages_done:303 /* Terminate the ident list */304 if ((ahc->features & AHC_CMD_CHAN) != 0) {305 mvi CCSCBRAM, SCB_LIST_NULL;306 } else {307 mvi DFDAT, SCB_LIST_NULL;308 }309 or SEQ_FLAGS, TARG_CMD_PENDING;310 test SEQ_FLAGS2, TARGET_MSG_PENDING311 jnz target_mesgout_pending;312 test SCSISIGI, ATNI jnz target_mesgout_continue;313 jmp target_ITloop;314 315 316ident_messages_done_msg_pending:317 or SEQ_FLAGS2, TARGET_MSG_PENDING;318 jmp ident_messages_done;319 320 /*321 * Pushed message loop to allow the kernel to322 * run it's own target mode message state engine.323 */324host_target_message_loop:325 mvi HOST_MSG_LOOP call set_seqint;326 cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop;327 test SSTAT0, SPIORDY jz .;328 jmp host_target_message_loop;329 }330 331if ((ahc->flags & AHC_INITIATORROLE) != 0) {332/*333 * Reselection has been initiated by a target. Make a note that we've been334 * reselected, but haven't seen an IDENTIFY message from the target yet.335 */336initiator_reselect:337 /* XXX test for and handle ONE BIT condition */338 or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;339 and SAVED_SCSIID, SELID_MASK, SELID;340 if ((ahc->features & AHC_ULTRA2) != 0) {341 and A, OID, SCSIID_ULTRA2;342 } else {343 and A, OID, SCSIID;344 }345 or SAVED_SCSIID, A;346 if ((ahc->features & AHC_TWIN) != 0) {347 test SBLKCTL, SELBUSB jz . + 2;348 or SAVED_SCSIID, TWIN_CHNLB;349 }350 mvi CLRSINT0, CLRSELDI;351 jmp ITloop;352}353 354abort_qinscb:355 call add_scb_to_free_list;356 jmp poll_for_work_loop;357 358start_selection:359 /*360 * If bus reset interrupts have been disabled (from a previous361 * reset), re-enable them now. Resets are only of interest362 * when we have outstanding transactions, so we can safely363 * defer re-enabling the interrupt until, as an initiator,364 * we start sending out transactions again.365 */366 test SIMODE1, ENSCSIRST jnz . + 3;367 mvi CLRSINT1, CLRSCSIRSTI;368 or SIMODE1, ENSCSIRST;369 if ((ahc->features & AHC_TWIN) != 0) {370 and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */371 test SCB_SCSIID, TWIN_CHNLB jz . + 2;372 or SINDEX, SELBUSB;373 mov SBLKCTL,SINDEX; /* select channel */374 }375initialize_scsiid:376 if ((ahc->features & AHC_ULTRA2) != 0) {377 mov SCSIID_ULTRA2, SCB_SCSIID;378 } else if ((ahc->features & AHC_TWIN) != 0) {379 and SCSIID, TWIN_TID|OID, SCB_SCSIID;380 } else {381 mov SCSIID, SCB_SCSIID;382 }383 if ((ahc->flags & AHC_TARGETROLE) != 0) {384 mov SINDEX, SCSISEQ_TEMPLATE;385 test SCB_CONTROL, TARGET_SCB jz . + 2;386 or SINDEX, TEMODE;387 mov SCSISEQ, SINDEX ret;388 } else {389 mov SCSISEQ, SCSISEQ_TEMPLATE ret;390 }391 392/*393 * Initialize transfer settings with SCB provided settings.394 */395set_transfer_settings:396 if ((ahc->features & AHC_ULTRA) != 0) {397 test SCB_CONTROL, ULTRAENB jz . + 2;398 or SXFRCTL0, FAST20;399 } 400 /*401 * Initialize SCSIRATE with the appropriate value for this target.402 */403 if ((ahc->features & AHC_ULTRA2) != 0) {404 bmov SCSIRATE, SCB_SCSIRATE, 2 ret;405 } else {406 mov SCSIRATE, SCB_SCSIRATE ret;407 }408 409if ((ahc->flags & AHC_TARGETROLE) != 0) {410/*411 * We carefully toggle SPIOEN to allow us to return the 412 * message byte we receive so it can be checked prior to413 * driving REQ on the bus for the next byte.414 */415target_inb:416 /*417 * Drive REQ on the bus by enabling SCSI PIO.418 */419 or SXFRCTL0, SPIOEN;420 /* Wait for the byte */421 test SSTAT0, SPIORDY jz .;422 /* Prevent our read from triggering another REQ */423 and SXFRCTL0, ~SPIOEN;424 /* Save latched contents */425 mov DINDEX, SCSIDATL ret;426}427 428/*429 * After the selection, remove this SCB from the "waiting SCB"430 * list. This is achieved by simply moving our "next" pointer into431 * WAITING_SCBH. Our next pointer will be set to null the next time this432 * SCB is used, so don't bother with it now.433 */434select_out:435 /* Turn off the selection hardware */436 and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ;437 mov SCBPTR, WAITING_SCBH;438 mov WAITING_SCBH,SCB_NEXT;439 mov SAVED_SCSIID, SCB_SCSIID;440 and SAVED_LUN, LID, SCB_LUN;441 call set_transfer_settings;442 if ((ahc->flags & AHC_TARGETROLE) != 0) {443 test SSTAT0, TARGET jz initiator_select;444 445 or SXFRCTL0, CLRSTCNT|CLRCHN;446 447 /*448 * Put tag in connonical location since not449 * all connections have an SCB.450 */451 mov INITIATOR_TAG, SCB_TARGET_ITAG;452 453 /*454 * We've just re-selected an initiator.455 * Assert BSY and setup the phase for456 * sending our identify messages.457 */458 mvi P_MESGIN|BSYO call change_phase;459 mvi CLRSINT0, CLRSELDO;460 461 /*462 * Start out with a simple identify message.463 */464 or SAVED_LUN, MSG_IDENTIFYFLAG call target_outb;465 466 /*467 * If we are the result of a tagged command, send468 * a simple Q tag and the tag id.469 */470 test SCB_CONTROL, TAG_ENB jz . + 3;471 mvi MSG_SIMPLE_Q_TAG call target_outb;472 mov SCB_TARGET_ITAG call target_outb;473target_synccmd:474 /*475 * Now determine what phases the host wants us476 * to go through.477 */478 mov SEQ_FLAGS, SCB_TARGET_PHASES;479 480 test SCB_CONTROL, MK_MESSAGE jz target_ITloop;481 mvi P_MESGIN|BSYO call change_phase;482 jmp host_target_message_loop;483target_ITloop:484 /*485 * Start honoring ATN signals now that486 * we properly identified ourselves.487 */488 test SCSISIGI, ATNI jnz target_mesgout;489 test SEQ_FLAGS, CMDPHASE_PENDING jnz target_cmdphase;490 test SEQ_FLAGS, DPHASE_PENDING jnz target_dphase;491 test SEQ_FLAGS, SPHASE_PENDING jnz target_sphase;492 493 /*494 * No more work to do. Either disconnect or not depending495 * on the state of NO_DISCONNECT.496 */497 test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; 498 mvi TARG_IMMEDIATE_SCB, SCB_LIST_NULL;499 call complete_target_cmd;500 if ((ahc->flags & AHC_PAGESCBS) != 0) {501 mov ALLZEROS call get_free_or_disc_scb;502 }503 cmp TARG_IMMEDIATE_SCB, SCB_LIST_NULL je .;504 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;505 mov TARG_IMMEDIATE_SCB call dma_scb;506 call set_transfer_settings;507 or SXFRCTL0, CLRSTCNT|CLRCHN;508 jmp target_synccmd;509 510target_mesgout:511 mvi SCSISIGO, P_MESGOUT|BSYO;512target_mesgout_continue:513 call target_inb;514target_mesgout_pending:515 and SEQ_FLAGS2, ~TARGET_MSG_PENDING;516 /* Local Processing goes here... */517 jmp host_target_message_loop;518 519target_disconnect:520 mvi P_MESGIN|BSYO call change_phase;521 test SEQ_FLAGS, DPHASE jz . + 2;522 mvi MSG_SAVEDATAPOINTER call target_outb;523 mvi MSG_DISCONNECT call target_outb;524 525target_busfree_wait:526 /* Wait for preceding I/O session to complete. */527 test SCSISIGI, ACKI jnz .;528target_busfree:529 and SIMODE1, ~ENBUSFREE;530 if ((ahc->features & AHC_ULTRA2) != 0) {531 clr SCSIBUSL;532 }533 clr SCSISIGO;534 mvi LASTPHASE, P_BUSFREE;535 call complete_target_cmd;536 jmp poll_for_work;537 538target_cmdphase:539 /*540 * The target has dropped ATN (doesn't want to abort or BDR)541 * and we believe this selection to be valid. If the ring542 * buffer for new commands is full, return busy or queue full.543 */544 if ((ahc->features & AHC_HS_MAILBOX) != 0) {545 and A, HOST_TQINPOS, HS_MAILBOX;546 } else {547 mov A, KERNEL_TQINPOS;548 }549 cmp TQINPOS, A jne tqinfifo_has_space;550 mvi P_STATUS|BSYO call change_phase;551 test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;552 mvi STATUS_QUEUE_FULL call target_outb;553 jmp target_busfree_wait;554 mvi STATUS_BUSY call target_outb;555 jmp target_busfree_wait;556tqinfifo_has_space: 557 mvi P_COMMAND|BSYO call change_phase;558 call target_inb;559 mov A, DINDEX;560 /* Store for host */561 if ((ahc->features & AHC_CMD_CHAN) != 0) {562 mov CCSCBRAM, A;563 } else {564 mov DFDAT, A;565 }566 567 /*568 * Determine the number of bytes to read569 * based on the command group code via table lookup.570 * We reuse the first 8 bytes of the TARG_SCSIRATE571 * BIOS array for this table. Count is one less than572 * the total for the command since we've already fetched573 * the first byte.574 */575 shr A, CMD_GROUP_CODE_SHIFT;576 add SINDEX, CMDSIZE_TABLE, A;577 mov A, SINDIR;578 579 test A, 0xFF jz command_phase_done;580 or SXFRCTL0, SPIOEN;581command_loop:582 test SSTAT0, SPIORDY jz .;583 cmp A, 1 jne . + 2;584 and SXFRCTL0, ~SPIOEN; /* Last Byte */585 if ((ahc->features & AHC_CMD_CHAN) != 0) {586 mov CCSCBRAM, SCSIDATL;587 } else {588 mov DFDAT, SCSIDATL;589 }590 dec A;591 test A, 0xFF jnz command_loop;592 593command_phase_done:594 and SEQ_FLAGS, ~CMDPHASE_PENDING;595 jmp target_ITloop;596 597target_dphase:598 /*599 * Data phases on the bus are from the600 * perspective of the initiator. The dma601 * code looks at LASTPHASE to determine the602 * data direction of the DMA. Toggle it for603 * target transfers.604 */605 xor LASTPHASE, IOI, SCB_TARGET_DATA_DIR;606 or SCB_TARGET_DATA_DIR, BSYO call change_phase;607 jmp p_data;608 609target_sphase:610 mvi P_STATUS|BSYO call change_phase;611 mvi LASTPHASE, P_STATUS;612 mov SCB_SCSI_STATUS call target_outb;613 /* XXX Watch for ATN or parity errors??? */614 mvi SCSISIGO, P_MESGIN|BSYO;615 /* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */616 mov ALLZEROS call target_outb;617 jmp target_busfree_wait;618 619complete_target_cmd:620 test SEQ_FLAGS, TARG_CMD_PENDING jnz . + 2;621 mov SCB_TAG jmp complete_post;622 if ((ahc->features & AHC_CMD_CHAN) != 0) {623 /* Set the valid byte */624 mvi CCSCBADDR, 24;625 mov CCSCBRAM, ALLONES;626 mvi CCHCNT, 28;627 or CCSCBCTL, CCSCBEN|CCSCBRESET;628 test CCSCBCTL, CCSCBDONE jz .;629 clr CCSCBCTL;630 } else {631 /* Set the valid byte */632 or DFCNTRL, FIFORESET;633 mvi DFWADDR, 3; /* Third 64bit word or byte 24 */634 mov DFDAT, ALLONES;635 mvi 28 call set_hcnt;636 or DFCNTRL, HDMAEN|FIFOFLUSH;637 call dma_finish;638 }639 inc TQINPOS;640 mvi INTSTAT,CMDCMPLT ret;641 }642 643if ((ahc->flags & AHC_INITIATORROLE) != 0) {644initiator_select:645 or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;646 /*647 * As soon as we get a successful selection, the target648 * should go into the message out phase since we have ATN649 * asserted.650 */651 mvi MSG_OUT, MSG_IDENTIFYFLAG;652 mvi SEQ_FLAGS, NO_CDB_SENT;653 mvi CLRSINT0, CLRSELDO;654 655 /*656 * Main loop for information transfer phases. Wait for the657 * target to assert REQ before checking MSG, C/D and I/O for658 * the bus phase.659 */660mesgin_phasemis:661ITloop:662 call phase_lock;663 664 mov A, LASTPHASE;665 666 test A, ~P_DATAIN jz p_data;667 cmp A,P_COMMAND je p_command;668 cmp A,P_MESGOUT je p_mesgout;669 cmp A,P_STATUS je p_status;670 cmp A,P_MESGIN je p_mesgin;671 672 mvi BAD_PHASE call set_seqint;673 jmp ITloop; /* Try reading the bus again. */674 675await_busfree:676 and SIMODE1, ~ENBUSFREE;677 mov NONE, SCSIDATL; /* Ack the last byte */678 if ((ahc->features & AHC_ULTRA2) != 0) {679 clr SCSIBUSL; /* Prevent bit leakage durint SELTO */680 }681 and SXFRCTL0, ~SPIOEN;682 mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;683 test SSTAT1,REQINIT|BUSFREE jz .;684 test SSTAT1, BUSFREE jnz poll_for_work;685 mvi MISSED_BUSFREE call set_seqint;686}687 688clear_target_state:689 /*690 * We assume that the kernel driver may reset us691 * at any time, even in the middle of a DMA, so692 * clear DFCNTRL too.693 */694 clr DFCNTRL;695 or SXFRCTL0, CLRSTCNT|CLRCHN;696 697 /*698 * We don't know the target we will connect to,699 * so default to narrow transfers to avoid700 * parity problems.701 */702 if ((ahc->features & AHC_ULTRA2) != 0) {703 bmov SCSIRATE, ALLZEROS, 2;704 } else {705 clr SCSIRATE;706 if ((ahc->features & AHC_ULTRA) != 0) {707 and SXFRCTL0, ~(FAST20);708 }709 }710 mvi LASTPHASE, P_BUSFREE;711 /* clear target specific flags */712 mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;713 714sg_advance:715 clr A; /* add sizeof(struct scatter) */716 add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF;717 adc SCB_RESIDUAL_SGPTR[1],A;718 adc SCB_RESIDUAL_SGPTR[2],A;719 adc SCB_RESIDUAL_SGPTR[3],A ret;720 721if ((ahc->features & AHC_CMD_CHAN) != 0) {722disable_ccsgen:723 test CCSGCTL, CCSGEN jz return;724 test CCSGCTL, CCSGDONE jz .;725disable_ccsgen_fetch_done:726 clr CCSGCTL;727 test CCSGCTL, CCSGEN jnz .;728 ret;729idle_loop:730 /*731 * Do we need any more segments for this transfer?732 */733 test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;734 735 /* Did we just finish fetching segs? */736 cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;737 738 /* Are we actively fetching segments? */739 test CCSGCTL, CCSGEN jnz return;740 741 /*742 * Do we have any prefetch left???743 */744 cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;745 746 /*747 * Need to fetch segments, but we can only do that748 * if the command channel is completely idle. Make749 * sure we don't have an SCB prefetch going on.750 */751 test CCSCBCTL, CCSCBEN jnz return;752 753 /*754 * We fetch a "cacheline aligned" and sized amount of data755 * so we don't end up referencing a non-existent page.756 * Cacheline aligned is in quotes because the kernel will757 * set the prefetch amount to a reasonable level if the758 * cacheline size is unknown.759 */760 mvi CCHCNT, SG_PREFETCH_CNT;761 and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;762 bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;763 mvi CCSGCTL, CCSGEN|CCSGRESET ret;764idle_sgfetch_complete:765 call disable_ccsgen_fetch_done;766 and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;767idle_sg_avail:768 if ((ahc->features & AHC_ULTRA2) != 0) {769 /* Does the hardware have space for another SG entry? */770 test DFSTATUS, PRELOAD_AVAIL jz return;771 bmov HADDR, CCSGRAM, 7;772 bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;773 if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {774 mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;775 }776 call sg_advance;777 mov SINDEX, SCB_RESIDUAL_SGPTR[0];778 test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;779 or SINDEX, LAST_SEG;780 mov SG_CACHE_PRE, SINDEX;781 /* Load the segment */782 or DFCNTRL, PRELOADEN;783 }784 ret;785}786 787if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {788/*789 * Calculate the trailing portion of this S/G segment that cannot790 * be transferred using memory write and invalidate PCI transactions. 791 * XXX Can we optimize this for PCI writes only???792 */793calc_mwi_residual:794 /*795 * If the ending address is on a cacheline boundary,796 * there is no need for an extra segment.797 */798 mov A, HCNT[0];799 add A, A, HADDR[0];800 and A, CACHESIZE_MASK;801 test A, 0xFF jz return;802 803 /*804 * If the transfer is less than a cachline,805 * there is no need for an extra segment.806 */807 test HCNT[1], 0xFF jnz calc_mwi_residual_final;808 test HCNT[2], 0xFF jnz calc_mwi_residual_final;809 add NONE, INVERTED_CACHESIZE_MASK, HCNT[0];810 jnc return;811 812calc_mwi_residual_final:813 mov MWI_RESIDUAL, A;814 not A;815 inc A;816 add HCNT[0], A;817 adc HCNT[1], -1;818 adc HCNT[2], -1 ret;819}820 821p_data:822 test SEQ_FLAGS,NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed;823 mvi PROTO_VIOLATION call set_seqint;824p_data_allowed:825 if ((ahc->features & AHC_ULTRA2) != 0) {826 mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;827 } else {828 mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;829 }830 test LASTPHASE, IOI jnz . + 2;831 or DMAPARAMS, DIRECTION;832 if ((ahc->features & AHC_CMD_CHAN) != 0) {833 /* We don't have any valid S/G elements */834 mvi CCSGADDR, SG_PREFETCH_CNT;835 }836 test SEQ_FLAGS, DPHASE jz data_phase_initialize;837 838 /*839 * If we re-enter the data phase after going through another840 * phase, our transfer location has almost certainly been841 * corrupted by the interveining, non-data, transfers. Ask842 * the host driver to fix us up based on the transfer residual.843 */844 mvi PDATA_REINIT call set_seqint;845 jmp data_phase_loop;846 847data_phase_initialize:848 /* We have seen a data phase for the first time */849 or SEQ_FLAGS, DPHASE;850 851 /*852 * Initialize the DMA address and counter from the SCB.853 * Also set SCB_RESIDUAL_SGPTR, including the LAST_SEG854 * flag in the highest byte of the data count. We cannot855 * modify the saved values in the SCB until we see a save856 * data pointers message.857 */858 if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {859 /* The lowest address byte must be loaded last. */860 mov SCB_DATACNT[3] call set_hhaddr;861 }862 if ((ahc->features & AHC_CMD_CHAN) != 0) {863 bmov HADDR, SCB_DATAPTR, 7;864 bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;865 } else {866 mvi DINDEX, HADDR;867 mvi SCB_DATAPTR call bcopy_7;868 mvi DINDEX, SCB_RESIDUAL_DATACNT + 3;869 mvi SCB_DATACNT + 3 call bcopy_5;870 }871 if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {872 call calc_mwi_residual;873 }874 and SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID;875 876 if ((ahc->features & AHC_ULTRA2) == 0) {877 if ((ahc->features & AHC_CMD_CHAN) != 0) {878 bmov STCNT, HCNT, 3;879 } else {880 call set_stcnt_from_hcnt;881 }882 }883 884data_phase_loop:885 /* Guard against overruns */886 test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_inbounds;887 888 /*889 * Turn on `Bit Bucket' mode, wait until the target takes890 * us to another phase, and then notify the host.891 */892 and DMAPARAMS, DIRECTION;893 mov DFCNTRL, DMAPARAMS;894 or SXFRCTL1,BITBUCKET;895 if ((ahc->features & AHC_DT) == 0) {896 test SSTAT1,PHASEMIS jz .;897 } else {898 test SCSIPHASE, DATA_PHASE_MASK jnz .;899 }900 and SXFRCTL1, ~BITBUCKET;901 mvi DATA_OVERRUN call set_seqint;902 jmp ITloop;903 904data_phase_inbounds:905 if ((ahc->features & AHC_ULTRA2) != 0) {906 mov SINDEX, SCB_RESIDUAL_SGPTR[0];907 test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;908 or SINDEX, LAST_SEG;909 mov SG_CACHE_PRE, SINDEX;910 mov DFCNTRL, DMAPARAMS;911ultra2_dma_loop:912 call idle_loop;913 /*914 * The transfer is complete if either the last segment915 * completes or the target changes phase.916 */917 test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;918 if ((ahc->features & AHC_DT) == 0) {919 if ((ahc->flags & AHC_TARGETROLE) != 0) {920 /*921 * As a target, we control the phases,922 * so ignore PHASEMIS.923 */924 test SSTAT0, TARGET jnz ultra2_dma_loop;925 }926 if ((ahc->flags & AHC_INITIATORROLE) != 0) {927 test SSTAT1,PHASEMIS jz ultra2_dma_loop;928 }929 } else {930 test DFCNTRL, SCSIEN jnz ultra2_dma_loop;931 }932 933ultra2_dmafinish:934 /*935 * The transfer has terminated either due to a phase936 * change, and/or the completion of the last segment.937 * We have two goals here. Do as much other work938 * as possible while the data fifo drains on a read939 * and respond as quickly as possible to the standard940 * messages (save data pointers/disconnect and command941 * complete) that usually follow a data phase.942 */943 if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {944 /*945 * On chips with broken auto-flush, start946 * the flushing process now. We'll poke947 * the chip from time to time to keep the948 * flush process going as we complete the949 * data phase.950 */951 or DFCNTRL, FIFOFLUSH;952 }953 /*954 * We assume that, even though data may still be955 * transferring to the host, that the SCSI side of956 * the DMA engine is now in a static state. This957 * allows us to update our notion of where we are958 * in this transfer.959 *960 * If, by chance, we stopped before being able961 * to fetch additional segments for this transfer,962 * yet the last S/G was completely exhausted,963 * call our idle loop until it is able to load964 * another segment. This will allow us to immediately965 * pickup on the next segment on the next data phase.966 *967 * If we happened to stop on the last segment, then968 * our residual information is still correct from969 * the idle loop and there is no need to perform970 * any fixups.971 */972ultra2_ensure_sg:973 test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;974 /* Record if we've consumed all S/G entries */975 test SSTAT2, SHVALID jnz residuals_correct;976 or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;977 jmp residuals_correct;978 979ultra2_shvalid:980 test SSTAT2, SHVALID jnz sgptr_fixup;981 call idle_loop;982 jmp ultra2_ensure_sg;983 984sgptr_fixup:985 /*986 * Fixup the residual next S/G pointer. The S/G preload987 * feature of the chip allows us to load two elements988 * in addition to the currently active element. We989 * store the bottom byte of the next S/G pointer in990 * the SG_CACEPTR register so we can restore the991 * correct value when the DMA completes. If the next992 * sg ptr value has advanced to the point where higher993 * bytes in the address have been affected, fix them994 * too.995 */996 test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done;997 test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done;998 add SCB_RESIDUAL_SGPTR[1], -1;999 adc SCB_RESIDUAL_SGPTR[2], -1; 1000 adc SCB_RESIDUAL_SGPTR[3], -1;1001sgptr_fixup_done:1002 and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;1003 /* We are not the last seg */1004 and SCB_RESIDUAL_DATACNT[3], ~SG_LAST_SEG;1005residuals_correct:1006 /*1007 * Go ahead and shut down the DMA engine now.1008 * In the future, we'll want to handle end of1009 * transfer messages prior to doing this, but this1010 * requires similar restructuring for pre-ULTRA21011 * controllers.1012 */1013 test DMAPARAMS, DIRECTION jnz ultra2_fifoempty;1014ultra2_fifoflush:1015 if ((ahc->features & AHC_DT) == 0) {1016 if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {1017 /*1018 * On Rev A of the aic7890, the autoflush1019 * feature doesn't function correctly.1020 * Perform an explicit manual flush. During1021 * a manual flush, the FIFOEMP bit becomes1022 * true every time the PCI FIFO empties1023 * regardless of the state of the SCSI FIFO.1024 * It can take up to 4 clock cycles for the1025 * SCSI FIFO to get data into the PCI FIFO1026 * and for FIFOEMP to de-assert. Here we1027 * guard against this condition by making1028 * sure the FIFOEMP bit stays on for 5 full1029 * clock cycles.1030 */1031 or DFCNTRL, FIFOFLUSH;1032 test DFSTATUS, FIFOEMP jz ultra2_fifoflush;1033 test DFSTATUS, FIFOEMP jz ultra2_fifoflush;1034 test DFSTATUS, FIFOEMP jz ultra2_fifoflush;1035 test DFSTATUS, FIFOEMP jz ultra2_fifoflush;1036 }1037 test DFSTATUS, FIFOEMP jz ultra2_fifoflush;1038 } else {1039 /*1040 * We enable the auto-ack feature on DT capable1041 * controllers. This means that the controller may1042 * have already transferred some overrun bytes into1043 * the data FIFO and acked them on the bus. The only1044 * way to detect this situation is to wait for1045 * LAST_SEG_DONE to come true on a completed transfer1046 * and then test to see if the data FIFO is non-empty.1047 */1048 test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL1049 jz ultra2_wait_fifoemp;1050 test SG_CACHE_SHADOW, LAST_SEG_DONE jz .;1051 /*1052 * FIFOEMP can lag LAST_SEG_DONE. Wait a few1053 * clocks before calling this an overrun.1054 */1055 test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;1056 test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;1057 test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;1058 /* Overrun */1059 jmp data_phase_loop;1060ultra2_wait_fifoemp:1061 test DFSTATUS, FIFOEMP jz .;1062 }1063ultra2_fifoempty:1064 /* Don't clobber an inprogress host data transfer */1065 test DFSTATUS, MREQPEND jnz ultra2_fifoempty;1066ultra2_dmahalt:1067 and DFCNTRL, ~(SCSIEN|HDMAEN);1068 test DFCNTRL, SCSIEN|HDMAEN jnz .;1069 if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {1070 /*1071 * Keep HHADDR cleared for future, 32bit addressed1072 * only, DMA operations.1073 *1074 * Due to bayonette style S/G handling, our residual1075 * data must be "fixed up" once the transfer is halted.1076 * Here we fixup the HSHADDR stored in the high byte1077 * of the residual data cnt. By postponing the fixup,1078 * we can batch the clearing of HADDR with the fixup.1079 * If we halted on the last segment, the residual is1080 * already correct. If we are not on the last1081 * segment, copy the high address directly from HSHADDR.1082 * We don't need to worry about maintaining the1083 * SG_LAST_SEG flag as it will always be false in the1084 * case where an update is required.1085 */1086 or DSCOMMAND1, HADDLDSEL0;1087 test SG_CACHE_SHADOW, LAST_SEG jnz . + 2;1088 mov SCB_RESIDUAL_DATACNT[3], SHADDR;1089 clr HADDR;1090 and DSCOMMAND1, ~HADDLDSEL0;1091 }1092 } else {1093 /* If we are the last SG block, tell the hardware. */1094 if ((ahc->bugs & AHC_PCI_MWI_BUG) != 01095 && ahc->pci_cachesize != 0) {1096 test MWI_RESIDUAL, 0xFF jnz dma_mid_sg;1097 }1098 test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;1099 if ((ahc->flags & AHC_TARGETROLE) != 0) {1100 test SSTAT0, TARGET jz dma_last_sg;1101 if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {1102 test DMAPARAMS, DIRECTION jz dma_mid_sg;1103 }1104 }1105dma_last_sg:1106 and DMAPARAMS, ~WIDEODD;1107dma_mid_sg:1108 /* Start DMA data transfer. */1109 mov DFCNTRL, DMAPARAMS;1110dma_loop:1111 if ((ahc->features & AHC_CMD_CHAN) != 0) {1112 call idle_loop;1113 }1114 test SSTAT0,DMADONE jnz dma_dmadone;1115 test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */1116dma_phasemis:1117 /*1118 * We will be "done" DMAing when the transfer count goes to1119 * zero, or the target changes the phase (in light of this,1120 * it makes sense that the DMA circuitry doesn't ACK when1121 * PHASEMIS is active). If we are doing a SCSI->Host transfer,1122 * the data FIFO should be flushed auto-magically on STCNT=01123 * or a phase change, so just wait for FIFO empty status.1124 */1125dma_checkfifo:1126 test DFCNTRL,DIRECTION jnz dma_fifoempty;1127dma_fifoflush:1128 test DFSTATUS,FIFOEMP jz dma_fifoflush;1129dma_fifoempty:1130 /* Don't clobber an inprogress host data transfer */1131 test DFSTATUS, MREQPEND jnz dma_fifoempty;1132 1133 /*1134 * Now shut off the DMA and make sure that the DMA1135 * hardware has actually stopped. Touching the DMA1136 * counters, etc. while a DMA is active will result1137 * in an ILLSADDR exception.1138 */1139dma_dmadone:1140 and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);1141dma_halt:1142 /*1143 * Some revisions of the aic78XX have a problem where, if the1144 * data fifo is full, but the PCI input latch is not empty, 1145 * HDMAEN cannot be cleared. The fix used here is to drain1146 * the prefetched but unused data from the data fifo until1147 * there is space for the input latch to drain.1148 */1149 if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {1150 mov NONE, DFDAT;1151 }1152 test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;1153 1154 /* See if we have completed this last segment */1155 test STCNT[0], 0xff jnz data_phase_finish;1156 test STCNT[1], 0xff jnz data_phase_finish;1157 test STCNT[2], 0xff jnz data_phase_finish;1158 1159 /*1160 * Advance the scatter-gather pointers if needed 1161 */1162 if ((ahc->bugs & AHC_PCI_MWI_BUG) != 01163 && ahc->pci_cachesize != 0) {1164 test MWI_RESIDUAL, 0xFF jz no_mwi_resid;1165 /*1166 * Reload HADDR from SHADDR and setup the1167 * count to be the size of our residual.1168 */1169 if ((ahc->features & AHC_CMD_CHAN) != 0) {1170 bmov HADDR, SHADDR, 4;1171 mov HCNT, MWI_RESIDUAL;1172 bmov HCNT[1], ALLZEROS, 2;1173 } else {1174 mvi DINDEX, HADDR;1175 mvi SHADDR call bcopy_4;1176 mov MWI_RESIDUAL call set_hcnt;1177 }1178 clr MWI_RESIDUAL;1179 jmp sg_load_done;1180no_mwi_resid:1181 }1182 test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz sg_load;1183 or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;1184 jmp data_phase_finish;1185sg_load:1186 /*1187 * Load the next SG element's data address and length1188 * into the DMA engine. If we don't have hardware1189 * to perform a prefetch, we'll have to fetch the1190 * segment from host memory first.1191 */1192 if ((ahc->features & AHC_CMD_CHAN) != 0) {1193 /* Wait for the idle loop to complete */1194 test CCSGCTL, CCSGEN jz . + 3;1195 call idle_loop;1196 test CCSGCTL, CCSGEN jnz . - 1;1197 bmov HADDR, CCSGRAM, 7;1198 /*1199 * Workaround for flaky external SCB RAM1200 * on certain aic7895 setups. It seems1201 * unable to handle direct transfers from1202 * S/G ram to certain SCB locations.1203 */1204 mov SINDEX, CCSGRAM;1205 mov SCB_RESIDUAL_DATACNT[3], SINDEX;1206 } else {1207 if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {1208 mov ALLZEROS call set_hhaddr;1209 }1210 mvi DINDEX, HADDR;1211 mvi SCB_RESIDUAL_SGPTR call bcopy_4;1212 1213 mvi SG_SIZEOF call set_hcnt;1214 1215 or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;1216 1217 call dma_finish;1218 1219 mvi DINDEX, HADDR;1220 call dfdat_in_7;1221 mov SCB_RESIDUAL_DATACNT[3], DFDAT;1222 }1223 1224 if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {1225 mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;1226 1227 /*1228 * The lowest address byte must be loaded1229 * last as it triggers the computation of1230 * some items in the PCI block. The ULTRA21231 * chips do this on PRELOAD.1232 */1233 mov HADDR, HADDR;1234 }1235 if ((ahc->bugs & AHC_PCI_MWI_BUG) != 01236 && ahc->pci_cachesize != 0) {1237 call calc_mwi_residual;1238 }1239 1240 /* Point to the new next sg in memory */1241 call sg_advance;1242 1243sg_load_done:1244 if ((ahc->features & AHC_CMD_CHAN) != 0) {1245 bmov STCNT, HCNT, 3;1246 } else {1247 call set_stcnt_from_hcnt;1248 }1249 1250 if ((ahc->flags & AHC_TARGETROLE) != 0) {1251 test SSTAT0, TARGET jnz data_phase_loop;1252 }1253 }1254data_phase_finish:1255 /*1256 * If the target has left us in data phase, loop through1257 * the dma code again. In the case of ULTRA2 adapters,1258 * we should only loop if there is a data overrun. For1259 * all other adapters, we'll loop after each S/G element1260 * is loaded as well as if there is an overrun.1261 */1262 if ((ahc->flags & AHC_TARGETROLE) != 0) {1263 test SSTAT0, TARGET jnz data_phase_done;1264 }1265 if ((ahc->flags & AHC_INITIATORROLE) != 0) {1266 test SSTAT1, REQINIT jz .;1267 if ((ahc->features & AHC_DT) == 0) {1268 test SSTAT1,PHASEMIS jz data_phase_loop;1269 } else {1270 test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;1271 }1272 }1273 1274data_phase_done:1275 /*1276 * After a DMA finishes, save the SG and STCNT residuals back into1277 * the SCB. We use STCNT instead of HCNT, since it's a reflection1278 * of how many bytes were transferred on the SCSI (as opposed to the1279 * host) bus.1280 */1281 if ((ahc->features & AHC_CMD_CHAN) != 0) {1282 /* Kill off any pending prefetch */1283 call disable_ccsgen;1284 }1285 1286 if ((ahc->features & AHC_ULTRA2) == 0) {1287 /*1288 * Clear the high address byte so that all other DMA1289 * operations, which use 32bit addressing, can assume1290 * HHADDR is 0.1291 */1292 if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {1293 mov ALLZEROS call set_hhaddr;1294 }1295 }1296 1297 /*1298 * Update our residual information before the information is1299 * lost by some other type of SCSI I/O (e.g. PIO). If we have1300 * transferred all data, no update is needed.1301 *1302 */1303 test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done;1304 if ((ahc->bugs & AHC_PCI_MWI_BUG) != 01305 && ahc->pci_cachesize != 0) {1306 if ((ahc->features & AHC_CMD_CHAN) != 0) {1307 test MWI_RESIDUAL, 0xFF jz bmov_resid;1308 }1309 mov A, MWI_RESIDUAL;1310 add SCB_RESIDUAL_DATACNT[0], A, STCNT[0];1311 clr A;1312 adc SCB_RESIDUAL_DATACNT[1], A, STCNT[1];1313 adc SCB_RESIDUAL_DATACNT[2], A, STCNT[2];1314 clr MWI_RESIDUAL;1315 if ((ahc->features & AHC_CMD_CHAN) != 0) {1316 jmp . + 2;1317bmov_resid:1318 bmov SCB_RESIDUAL_DATACNT, STCNT, 3;1319 }1320 } else if ((ahc->features & AHC_CMD_CHAN) != 0) {1321 bmov SCB_RESIDUAL_DATACNT, STCNT, 3;1322 } else {1323 mov SCB_RESIDUAL_DATACNT[0], STCNT[0];1324 mov SCB_RESIDUAL_DATACNT[1], STCNT[1];1325 mov SCB_RESIDUAL_DATACNT[2], STCNT[2];1326 }1327residual_update_done:1328 /*1329 * Since we've been through a data phase, the SCB_RESID* fields1330 * are now initialized. Clear the full residual flag.1331 */1332 and SCB_SGPTR[0], ~SG_FULL_RESID;1333 1334 if ((ahc->features & AHC_ULTRA2) != 0) {1335 /* Clear the channel in case we return to data phase later */1336 or SXFRCTL0, CLRSTCNT|CLRCHN;1337 or SXFRCTL0, CLRSTCNT|CLRCHN;1338 }1339 1340 if ((ahc->flags & AHC_TARGETROLE) != 0) {1341 test SEQ_FLAGS, DPHASE_PENDING jz ITloop;1342 and SEQ_FLAGS, ~DPHASE_PENDING;1343 /*1344 * For data-in phases, wait for any pending acks from the1345 * initiator before changing phase. We only need to1346 * send Ignore Wide Residue messages for data-in phases.1347 */1348 test DFCNTRL, DIRECTION jz target_ITloop;1349 test SSTAT1, REQINIT jnz .;1350 test SCB_LUN, SCB_XFERLEN_ODD jz target_ITloop;1351 test SCSIRATE, WIDEXFER jz target_ITloop;1352 /*1353 * Issue an Ignore Wide Residue Message.1354 */1355 mvi P_MESGIN|BSYO call change_phase;1356 mvi MSG_IGN_WIDE_RESIDUE call target_outb;1357 mvi 1 call target_outb;1358 jmp target_ITloop;1359 } else {1360 jmp ITloop;1361 }1362 1363if ((ahc->flags & AHC_INITIATORROLE) != 0) {1364/*1365 * Command phase. Set up the DMA registers and let 'er rip.1366 */1367p_command:1368 test SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay;1369 mvi PROTO_VIOLATION call set_seqint;1370p_command_okay:1371 1372 if ((ahc->features & AHC_ULTRA2) != 0) {1373 bmov HCNT[0], SCB_CDB_LEN, 1;1374 bmov HCNT[1], ALLZEROS, 2;1375 mvi SG_CACHE_PRE, LAST_SEG;1376 } else if ((ahc->features & AHC_CMD_CHAN) != 0) {1377 bmov STCNT[0], SCB_CDB_LEN, 1;1378 bmov STCNT[1], ALLZEROS, 2;1379 } else {1380 mov STCNT[0], SCB_CDB_LEN;1381 clr STCNT[1];1382 clr STCNT[2];1383 }1384 add NONE, -13, SCB_CDB_LEN;1385 mvi SCB_CDB_STORE jnc p_command_embedded;1386p_command_from_host:1387 if ((ahc->features & AHC_ULTRA2) != 0) {1388 bmov HADDR[0], SCB_CDB_PTR, 4;1389 mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);1390 } else {1391 if ((ahc->features & AHC_CMD_CHAN) != 0) {1392 bmov HADDR[0], SCB_CDB_PTR, 4;1393 bmov HCNT, STCNT, 3;1394 } else {1395 mvi DINDEX, HADDR;1396 mvi SCB_CDB_PTR call bcopy_4;1397 mov SCB_CDB_LEN call set_hcnt;1398 }1399 mvi DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET);1400 }1401 jmp p_command_xfer;1402p_command_embedded:1403 /*1404 * The data fifo seems to require 4 byte aligned1405 * transfers from the sequencer. Force this to1406 * be the case by clearing HADDR[0] even though1407 * we aren't going to touch host memory.1408 */1409 clr HADDR[0];1410 if ((ahc->features & AHC_ULTRA2) != 0) {1411 mvi DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION);1412 bmov DFDAT, SCB_CDB_STORE, 12; 1413 } else if ((ahc->features & AHC_CMD_CHAN) != 0) {1414 if ((ahc->flags & AHC_SCB_BTT) != 0) {1415 /*1416 * On the 7895 the data FIFO will1417 * get corrupted if you try to dump1418 * data from external SCB memory into1419 * the FIFO while it is enabled. So,1420 * fill the fifo and then enable SCSI1421 * transfers.1422 */1423 mvi DFCNTRL, (DIRECTION|FIFORESET);1424 } else {1425 mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);1426 }1427 bmov DFDAT, SCB_CDB_STORE, 12; 1428 if ((ahc->flags & AHC_SCB_BTT) != 0) {1429 mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFOFLUSH);1430 } else {1431 or DFCNTRL, FIFOFLUSH;1432 }1433 } else {1434 mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);1435 call copy_to_fifo_6;1436 call copy_to_fifo_6;1437 or DFCNTRL, FIFOFLUSH;1438 }1439p_command_xfer:1440 and SEQ_FLAGS, ~NO_CDB_SENT;1441 if ((ahc->features & AHC_DT) == 0) {1442 test SSTAT0, SDONE jnz . + 2;1443 test SSTAT1, PHASEMIS jz . - 1;1444 /*1445 * Wait for our ACK to go-away on it's own1446 * instead of being killed by SCSIEN getting cleared.1447 */1448 test SCSISIGI, ACKI jnz .;1449 } else {1450 test DFCNTRL, SCSIEN jnz .;1451 }1452 test SSTAT0, SDONE jnz p_command_successful;1453 /*1454 * Don't allow a data phase if the command1455 * was not fully transferred.1456 */1457 or SEQ_FLAGS, NO_CDB_SENT;1458p_command_successful:1459 and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);1460 test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;1461 jmp ITloop;1462 1463/*1464 * Status phase. Wait for the data byte to appear, then read it1465 * and store it into the SCB.1466 */1467p_status:1468 test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;1469p_status_okay:1470 mov SCB_SCSI_STATUS, SCSIDATL;1471 or SCB_CONTROL, STATUS_RCVD;1472 jmp ITloop;1473 1474/*1475 * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full1476 * indentify message sequence and send it to the target. The host may1477 * override this behavior by setting the MK_MESSAGE bit in the SCB1478 * control byte. This will cause us to interrupt the host and allow1479 * it to handle the message phase completely on its own. If the bit1480 * associated with this target is set, we will also interrupt the host,1481 * thereby allowing it to send a message on the next selection regardless1482 * of the transaction being sent.1483 * 1484 * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.1485 * This is done to allow the host to send messages outside of an identify1486 * sequence while protecting the seqencer from testing the MK_MESSAGE bit1487 * on an SCB that might not be for the current nexus. (For example, a1488 * BDR message in response to a bad reselection would leave us pointed to1489 * an SCB that doesn't have anything to do with the current target).1490 *1491 * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,1492 * bus device reset).1493 *1494 * When there are no messages to send, MSG_OUT should be set to MSG_NOOP,1495 * in case the target decides to put us in this phase for some strange1496 * reason.1497 */1498p_mesgout_retry:1499 /* Turn on ATN for the retry */1500 if ((ahc->features & AHC_DT) == 0) {1501 or SCSISIGO, ATNO, LASTPHASE;1502 } else {1503 mvi SCSISIGO, ATNO;1504 }1505p_mesgout:1506 mov SINDEX, MSG_OUT;1507 cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;1508 test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;1509p_mesgout_identify:1510 or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SAVED_LUN;1511 test SCB_CONTROL, DISCENB jnz . + 2;1512 and SINDEX, ~DISCENB;1513/*1514 * Send a tag message if TAG_ENB is set in the SCB control block.1515 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.1516 */1517p_mesgout_tag:1518 test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte;1519 mov SCSIDATL, SINDEX; /* Send the identify message */1520 call phase_lock;1521 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;1522 and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;1523 call phase_lock;1524 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;1525 mov SCB_TAG jmp p_mesgout_onebyte;1526/*1527 * Interrupt the driver, and allow it to handle this message1528 * phase and any required retries.1529 */1530p_mesgout_from_host:1531 cmp SINDEX, HOST_MSG jne p_mesgout_onebyte;1532 jmp host_message_loop;1533 1534p_mesgout_onebyte:1535 mvi CLRSINT1, CLRATNO;1536 mov SCSIDATL, SINDEX;1537 1538/*1539 * If the next bus phase after ATN drops is message out, it means1540 * that the target is requesting that the last message(s) be resent.1541 */1542 call phase_lock;1543 cmp LASTPHASE, P_MESGOUT je p_mesgout_retry;1544 1545p_mesgout_done:1546 mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */1547 mov LAST_MSG, MSG_OUT;1548 mvi MSG_OUT, MSG_NOOP; /* No message left */1549 jmp ITloop;1550 1551/*1552 * Message in phase. Bytes are read using Automatic PIO mode.1553 */1554p_mesgin:1555 mvi ACCUM call inb_first; /* read the 1st message byte */1556 1557 test A,MSG_IDENTIFYFLAG jnz mesgin_identify;1558 cmp A,MSG_DISCONNECT je mesgin_disconnect;1559 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs;1560 cmp ALLZEROS,A je mesgin_complete;1561 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs;1562 cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue;1563 cmp A,MSG_NOOP je mesgin_done;1564 1565/*1566 * Pushed message loop to allow the kernel to1567 * run it's own message state engine. To avoid an1568 * extra nop instruction after signaling the kernel,1569 * we perform the phase_lock before checking to see1570 * if we should exit the loop and skip the phase_lock1571 * in the ITloop. Performing back to back phase_locks1572 * shouldn't hurt, but why do it twice...1573 */1574host_message_loop:1575 mvi HOST_MSG_LOOP call set_seqint;1576 call phase_lock;1577 cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1;1578 jmp host_message_loop;1579 1580mesgin_ign_wide_residue:1581if ((ahc->features & AHC_WIDE) != 0) {1582 test SCSIRATE, WIDEXFER jz mesgin_reject;1583 /* Pull the residue byte */1584 mvi ARG_1 call inb_next;1585 cmp ARG_1, 0x01 jne mesgin_reject;1586 test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2;1587 test SCB_LUN, SCB_XFERLEN_ODD jnz mesgin_done;1588 mvi IGN_WIDE_RES call set_seqint;1589 jmp mesgin_done;1590}1591 1592mesgin_proto_violation:1593 mvi PROTO_VIOLATION call set_seqint;1594 jmp mesgin_done;1595mesgin_reject:1596 mvi MSG_MESSAGE_REJECT call mk_mesg;1597mesgin_done:1598 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/1599 jmp ITloop;1600 1601/*1602 * We received a "command complete" message. Put the SCB_TAG into the QOUTFIFO,1603 * and trigger a completion interrupt. Before doing so, check to see if there1604 * is a residual or the status byte is something other than STATUS_GOOD (0).1605 * In either of these conditions, we upload the SCB back to the host so it can1606 * process this information. In the case of a non zero status byte, we 1607 * additionally interrupt the kernel driver synchronously, allowing it to1608 * decide if sense should be retrieved. If the kernel driver wishes to request1609 * sense, it will fill the kernel SCB with a request sense command, requeue1610 * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting 1611 * RETURN_1 to SEND_SENSE.1612 */1613mesgin_complete:1614 1615 /*1616 * If ATN is raised, we still want to give the target a message.1617 * Perhaps there was a parity error on this last message byte.1618 * Either way, the target should take us to message out phase1619 * and then attempt to complete the command again. We should use a1620 * critical section here to guard against a timeout triggering1621 * for this command and setting ATN while we are still processing1622 * the completion.1623 test SCSISIGI, ATNI jnz mesgin_done;1624 */1625 1626 /*1627 * If we are identified and have successfully sent the CDB,1628 * any status will do. Optimize this fast path.1629 */1630 test SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation;1631 test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted; 1632 1633 /*1634 * If the target never sent an identify message but instead went1635 * to mesgin to give an invalid message, let the host abort us.1636 */1637 test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;1638 1639 /*1640 * If we recevied good status but never successfully sent the1641 * cdb, abort the command.1642 */1643 test SCB_SCSI_STATUS,0xff jnz complete_accepted;1644 test SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation;1645 1646complete_accepted:1647 /*1648 * See if we attempted to deliver a message but the target ingnored us.1649 */1650 test SCB_CONTROL, MK_MESSAGE jz . + 2;1651 mvi MKMSG_FAILED call set_seqint;1652 1653 /*1654 * Check for residuals1655 */1656 test SCB_SGPTR, SG_LIST_NULL jnz check_status;/* No xfer */1657 test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */1658 test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;1659check_status:1660 test SCB_SCSI_STATUS,0xff jz complete; /* Good Status? */1661upload_scb:1662 or SCB_SGPTR, SG_RESID_VALID;1663 mvi DMAPARAMS, FIFORESET;1664 mov SCB_TAG call dma_scb;1665 test SCB_SCSI_STATUS, 0xff jz complete; /* Just a residual? */1666 mvi BAD_STATUS call set_seqint; /* let driver know */1667 cmp RETURN_1, SEND_SENSE jne complete;1668 call add_scb_to_free_list;1669 jmp await_busfree;1670complete:1671 mov SCB_TAG call complete_post;1672 jmp await_busfree;1673}1674 1675complete_post:1676 /* Post the SCBID in SINDEX and issue an interrupt */1677 call add_scb_to_free_list;1678 mov ARG_1, SINDEX;1679 if ((ahc->features & AHC_QUEUE_REGS) != 0) {1680 mov A, SDSCB_QOFF;1681 } else {1682 mov A, QOUTPOS;1683 }1684 mvi QOUTFIFO_OFFSET call post_byte_setup;1685 mov ARG_1 call post_byte;1686 if ((ahc->features & AHC_QUEUE_REGS) == 0) {1687 inc QOUTPOS;1688 }1689 mvi INTSTAT,CMDCMPLT ret;1690 1691if ((ahc->flags & AHC_INITIATORROLE) != 0) {1692/*1693 * Is it a disconnect message? Set a flag in the SCB to remind us1694 * and await the bus going free. If this is an untagged transaction1695 * store the SCB id for it in our untagged target table for lookup on1696 * a reselection.1697 */1698mesgin_disconnect:1699 /*1700 * If ATN is raised, we still want to give the target a message.1701 * Perhaps there was a parity error on this last message byte1702 * or we want to abort this command. Either way, the target1703 * should take us to message out phase and then attempt to1704 * disconnect again.1705 * XXX - Wait for more testing.1706 test SCSISIGI, ATNI jnz mesgin_done;1707 */1708 test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT1709 jnz mesgin_proto_violation;1710 or SCB_CONTROL,DISCONNECTED;1711 if ((ahc->flags & AHC_PAGESCBS) != 0) {1712 call add_scb_to_disc_list;1713 }1714 test SCB_CONTROL, TAG_ENB jnz await_busfree;1715 mov ARG_1, SCB_TAG;1716 and SAVED_LUN, LID, SCB_LUN;1717 mov SCB_SCSIID call set_busy_target;1718 jmp await_busfree;1719 1720/*1721 * Save data pointers message:1722 * Copying RAM values back to SCB, for Save Data Pointers message, but1723 * only if we've actually been into a data phase to change them. This1724 * protects against bogus data in scratch ram and the residual counts1725 * since they are only initialized when we go into data_in or data_out.1726 * Ack the message as soon as possible. For chips without S/G pipelining,1727 * we can only ack the message after SHADDR has been saved. On these1728 * chips, SHADDR increments with every bus transaction, even PIO.1729 */1730mesgin_sdptrs:1731 if ((ahc->features & AHC_ULTRA2) != 0) {1732 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/1733 test SEQ_FLAGS, DPHASE jz ITloop;1734 } else {1735 test SEQ_FLAGS, DPHASE jz mesgin_done;1736 }1737 1738 /*1739 * If we are asked to save our position at the end of the1740 * transfer, just mark us at the end rather than perform a1741 * full save.1742 */1743 test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full;1744 or SCB_SGPTR, SG_LIST_NULL;1745 if ((ahc->features & AHC_ULTRA2) != 0) {1746 jmp ITloop;1747 } else {1748 jmp mesgin_done;1749 }1750 1751mesgin_sdptrs_full:1752 1753 /*1754 * The SCB_SGPTR becomes the next one we'll download,1755 * and the SCB_DATAPTR becomes the current SHADDR.1756 * Use the residual number since STCNT is corrupted by1757 * any message transfer.1758 */1759 if ((ahc->features & AHC_CMD_CHAN) != 0) {1760 bmov SCB_DATAPTR, SHADDR, 4;1761 if ((ahc->features & AHC_ULTRA2) == 0) {1762 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/1763 }1764 bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;1765 } else {1766 mvi DINDEX, SCB_DATAPTR;1767 mvi SHADDR call bcopy_4;1768 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/1769 mvi SCB_RESIDUAL_DATACNT call bcopy_8;1770 }1771 jmp ITloop;1772 1773/*1774 * Restore pointers message? Data pointers are recopied from the1775 * SCB anytime we enter a data phase for the first time, so all1776 * we need to do is clear the DPHASE flag and let the data phase1777 * code do the rest. We also reset/reallocate the FIFO to make1778 * sure we have a clean start for the next data or command phase.1779 */1780mesgin_rdptrs:1781 and SEQ_FLAGS, ~DPHASE; /*1782 * We'll reload them1783 * the next time through1784 * the dataphase.1785 */1786 or SXFRCTL0, CLRSTCNT|CLRCHN;1787 jmp mesgin_done;1788 1789/*1790 * Index into our Busy Target table. SINDEX and DINDEX are modified1791 * upon return. SCBPTR may be modified by this action.1792 */1793set_busy_target:1794 shr DINDEX, 4, SINDEX;1795 if ((ahc->flags & AHC_SCB_BTT) != 0) {1796 mov SCBPTR, SAVED_LUN;1797 add DINDEX, SCB_64_BTT;1798 } else {1799 add DINDEX, BUSY_TARGETS;1800 }1801 mov DINDIR, ARG_1 ret;1802 1803/*1804 * Identify message? For a reconnecting target, this tells us the lun1805 * that the reconnection is for - find the correct SCB and switch to it,1806 * clearing the "disconnected" bit so we don't "find" it by accident later.1807 */1808mesgin_identify:1809 /*1810 * Determine whether a target is using tagged or non-tagged1811 * transactions by first looking at the transaction stored in1812 * the busy target array. If there is no untagged transaction1813 * for this target or the transaction is for a different lun, then1814 * this must be a tagged transaction.1815 */1816 shr SINDEX, 4, SAVED_SCSIID;1817 and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A;1818 if ((ahc->flags & AHC_SCB_BTT) != 0) {1819 add SINDEX, SCB_64_BTT;1820 mov SCBPTR, SAVED_LUN;1821 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1822 add NONE, -SCB_64_BTT, SINDEX;1823 jc . + 2;1824 mvi INTSTAT, OUT_OF_RANGE;1825 nop;1826 add NONE, -(SCB_64_BTT + 16), SINDEX;1827 jnc . + 2;1828 mvi INTSTAT, OUT_OF_RANGE;1829 nop;1830 }1831 } else {1832 add SINDEX, BUSY_TARGETS;1833 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1834 add NONE, -BUSY_TARGETS, SINDEX;1835 jc . + 2;1836 mvi INTSTAT, OUT_OF_RANGE;1837 nop;1838 add NONE, -(BUSY_TARGETS + 16), SINDEX;1839 jnc . + 2;1840 mvi INTSTAT, OUT_OF_RANGE;1841 nop;1842 }1843 }1844 mov ARG_1, SINDIR;1845 cmp ARG_1, SCB_LIST_NULL je snoop_tag;1846 if ((ahc->flags & AHC_PAGESCBS) != 0) {1847 mov ARG_1 call findSCB;1848 } else {1849 mov SCBPTR, ARG_1;1850 }1851 if ((ahc->flags & AHC_SCB_BTT) != 0) {1852 jmp setup_SCB_id_lun_okay;1853 } else {1854 /*1855 * We only allow one untagged command per-target1856 * at a time. So, if the lun doesn't match, look1857 * for a tag message.1858 */1859 and A, LID, SCB_LUN;1860 cmp SAVED_LUN, A je setup_SCB_id_lun_okay;1861 if ((ahc->flags & AHC_PAGESCBS) != 0) {1862 /*1863 * findSCB removes the SCB from the1864 * disconnected list, so we must replace1865 * it there should this SCB be for another1866 * lun.1867 */1868 call cleanup_scb;1869 }1870 }1871 1872/*1873 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.1874 * If we get one, we use the tag returned to find the proper1875 * SCB. With SCB paging, we must search for non-tagged1876 * transactions since the SCB may exist in any slot. If we're not1877 * using SCB paging, we can use the tag as the direct index to the1878 * SCB.1879 */1880snoop_tag:1881 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1882 or SEQ_FLAGS, 0x80;1883 }1884 mov NONE,SCSIDATL; /* ACK Identify MSG */1885 call phase_lock;1886 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1887 or SEQ_FLAGS, 0x1;1888 }1889 cmp LASTPHASE, P_MESGIN jne not_found;1890 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1891 or SEQ_FLAGS, 0x2;1892 }1893 cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;1894get_tag:1895 if ((ahc->flags & AHC_PAGESCBS) != 0) {1896 mvi ARG_1 call inb_next; /* tag value */1897 mov ARG_1 call findSCB;1898 } else {1899 mvi ARG_1 call inb_next; /* tag value */1900 mov SCBPTR, ARG_1;1901 }1902 1903/*1904 * Ensure that the SCB the tag points to is for1905 * an SCB transaction to the reconnecting target.1906 */1907setup_SCB:1908 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1909 or SEQ_FLAGS, 0x4;1910 }1911 mov A, SCB_SCSIID;1912 cmp SAVED_SCSIID, A jne not_found_cleanup_scb;1913 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1914 or SEQ_FLAGS, 0x8;1915 }1916setup_SCB_id_okay:1917 and A, LID, SCB_LUN;1918 cmp SAVED_LUN, A jne not_found_cleanup_scb;1919setup_SCB_id_lun_okay:1920 if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {1921 or SEQ_FLAGS, 0x10;1922 }1923 test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;1924 and SCB_CONTROL,~DISCONNECTED;1925 test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged;1926 if ((ahc->flags & AHC_SCB_BTT) != 0) {1927 mov A, SCBPTR;1928 }1929 mvi ARG_1, SCB_LIST_NULL;1930 mov SAVED_SCSIID call set_busy_target;1931 if ((ahc->flags & AHC_SCB_BTT) != 0) {1932 mov SCBPTR, A;1933 }1934setup_SCB_tagged:1935 clr SEQ_FLAGS; /* make note of IDENTIFY */1936 call set_transfer_settings;1937 /* See if the host wants to send a message upon reconnection */1938 test SCB_CONTROL, MK_MESSAGE jz mesgin_done;1939 mvi HOST_MSG call mk_mesg;1940 jmp mesgin_done;1941 1942not_found_cleanup_scb:1943 if ((ahc->flags & AHC_PAGESCBS) != 0) {1944 call cleanup_scb;1945 }1946not_found:1947 mvi NO_MATCH call set_seqint;1948 jmp mesgin_done;1949 1950mk_mesg:1951 if ((ahc->features & AHC_DT) == 0) {1952 or SCSISIGO, ATNO, LASTPHASE;1953 } else {1954 mvi SCSISIGO, ATNO;1955 }1956 mov MSG_OUT,SINDEX ret;1957 1958/*1959 * Functions to read data in Automatic PIO mode.1960 *1961 * According to Adaptec's documentation, an ACK is not sent on input from1962 * the target until SCSIDATL is read from. So we wait until SCSIDATL is1963 * latched (the usual way), then read the data byte directly off the bus1964 * using SCSIBUSL. When we have pulled the ATN line, or we just want to1965 * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI1966 * spec guarantees that the target will hold the data byte on the bus until1967 * we send our ACK.1968 *1969 * The assumption here is that these are called in a particular sequence,1970 * and that REQ is already set when inb_first is called. inb_{first,next}1971 * use the same calling convention as inb.1972 */1973inb_next_wait_perr:1974 mvi PERR_DETECTED call set_seqint;1975 jmp inb_next_wait;1976inb_next:1977 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/1978inb_next_wait:1979 /*1980 * If there is a parity error, wait for the kernel to1981 * see the interrupt and prepare our message response1982 * before continuing.1983 */1984 test SSTAT1, REQINIT jz inb_next_wait;1985 test SSTAT1, SCSIPERR jnz inb_next_wait_perr;1986inb_next_check_phase:1987 and LASTPHASE, PHASE_MASK, SCSISIGI;1988 cmp LASTPHASE, P_MESGIN jne mesgin_phasemis;1989inb_first:1990 mov DINDEX,SINDEX;1991 mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/1992inb_last:1993 mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/1994}1995 1996if ((ahc->flags & AHC_TARGETROLE) != 0) {1997/*1998 * Change to a new phase. If we are changing the state of the I/O signal,1999 * from out to in, wait an additional data release delay before continuing.2000 */2001change_phase:2002 /* Wait for preceding I/O session to complete. */2003 test SCSISIGI, ACKI jnz .;2004 2005 /* Change the phase */2006 and DINDEX, IOI, SCSISIGI;2007 mov SCSISIGO, SINDEX;2008 and A, IOI, SINDEX;2009 2010 /*2011 * If the data direction has changed, from2012 * out (initiator driving) to in (target driving),2013 * we must wait at least a data release delay plus2014 * the normal bus settle delay. [SCSI III SPI 10.11.0]2015 */2016 cmp DINDEX, A je change_phase_wait;2017 test SINDEX, IOI jz change_phase_wait;2018 call change_phase_wait;2019change_phase_wait:2020 nop;2021 nop;2022 nop;2023 nop ret;2024 2025/*2026 * Send a byte to an initiator in Automatic PIO mode.2027 */2028target_outb:2029 or SXFRCTL0, SPIOEN;2030 test SSTAT0, SPIORDY jz .;2031 mov SCSIDATL, SINDEX;2032 test SSTAT0, SPIORDY jz .;2033 and SXFRCTL0, ~SPIOEN ret;2034}2035 2036/*2037 * Locate a disconnected SCB by SCBID. Upon return, SCBPTR and SINDEX will2038 * be set to the position of the SCB. If the SCB cannot be found locally,2039 * it will be paged in from host memory. RETURN_2 stores the address of the2040 * preceding SCB in the disconnected list which can be used to speed up2041 * removal of the found SCB from the disconnected list.2042 */2043if ((ahc->flags & AHC_PAGESCBS) != 0) {2044BEGIN_CRITICAL;2045findSCB:2046 mov A, SINDEX; /* Tag passed in SINDEX */2047 cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;2048 mov SCBPTR, DISCONNECTED_SCBH; /* Initialize SCBPTR */2049 mvi ARG_2, SCB_LIST_NULL; /* Head of list */2050 jmp findSCB_loop;2051findSCB_next:2052 cmp SCB_NEXT, SCB_LIST_NULL je findSCB_notFound;2053 mov ARG_2, SCBPTR;2054 mov SCBPTR,SCB_NEXT;2055findSCB_loop:2056 cmp SCB_TAG, A jne findSCB_next;2057rem_scb_from_disc_list:2058 cmp ARG_2, SCB_LIST_NULL je rHead;2059 mov DINDEX, SCB_NEXT;2060 mov SINDEX, SCBPTR;2061 mov SCBPTR, ARG_2;2062 mov SCB_NEXT, DINDEX;2063 mov SCBPTR, SINDEX ret;2064rHead:2065 mov DISCONNECTED_SCBH,SCB_NEXT ret;2066END_CRITICAL;2067findSCB_notFound:2068 /*2069 * We didn't find it. Page in the SCB.2070 */2071 mov ARG_1, A; /* Save tag */2072 mov ALLZEROS call get_free_or_disc_scb;2073 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;2074 mov ARG_1 jmp dma_scb;2075}2076 2077/*2078 * Prepare the hardware to post a byte to host memory given an2079 * index of (A + (256 * SINDEX)) and a base address of SHARED_DATA_ADDR.2080 */2081post_byte_setup:2082 mov ARG_2, SINDEX;2083 if ((ahc->features & AHC_CMD_CHAN) != 0) {2084 mvi DINDEX, CCHADDR;2085 mvi SHARED_DATA_ADDR call set_1byte_addr;2086 mvi CCHCNT, 1;2087 mvi CCSCBCTL, CCSCBRESET ret;2088 } else {2089 mvi DINDEX, HADDR;2090 mvi SHARED_DATA_ADDR call set_1byte_addr;2091 mvi 1 call set_hcnt;2092 mvi DFCNTRL, FIFORESET ret;2093 }2094 2095post_byte:2096 if ((ahc->features & AHC_CMD_CHAN) != 0) {2097 bmov CCSCBRAM, SINDEX, 1;2098 or CCSCBCTL, CCSCBEN|CCSCBRESET;2099 test CCSCBCTL, CCSCBDONE jz .;2100 clr CCSCBCTL ret;2101 } else {2102 mov DFDAT, SINDEX;2103 or DFCNTRL, HDMAEN|FIFOFLUSH;2104 jmp dma_finish;2105 }2106 2107phase_lock_perr:2108 mvi PERR_DETECTED call set_seqint;2109phase_lock: 2110 /*2111 * If there is a parity error, wait for the kernel to2112 * see the interrupt and prepare our message response2113 * before continuing.2114 */2115 test SSTAT1, REQINIT jz phase_lock;2116 test SSTAT1, SCSIPERR jnz phase_lock_perr;2117phase_lock_latch_phase:2118 if ((ahc->features & AHC_DT) == 0) {2119 and SCSISIGO, PHASE_MASK, SCSISIGI;2120 }2121 and LASTPHASE, PHASE_MASK, SCSISIGI ret;2122 2123if ((ahc->features & AHC_CMD_CHAN) == 0) {2124set_hcnt:2125 mov HCNT[0], SINDEX;2126clear_hcnt:2127 clr HCNT[1];2128 clr HCNT[2] ret;2129 2130set_stcnt_from_hcnt:2131 mov STCNT[0], HCNT[0];2132 mov STCNT[1], HCNT[1];2133 mov STCNT[2], HCNT[2] ret;2134 2135bcopy_8:2136 mov DINDIR, SINDIR;2137bcopy_7:2138 mov DINDIR, SINDIR;2139 mov DINDIR, SINDIR;2140bcopy_5:2141 mov DINDIR, SINDIR;2142bcopy_4:2143 mov DINDIR, SINDIR;2144bcopy_3:2145 mov DINDIR, SINDIR;2146 mov DINDIR, SINDIR;2147 mov DINDIR, SINDIR ret;2148}2149 2150if ((ahc->flags & AHC_TARGETROLE) != 0) {2151/*2152 * Setup addr assuming that A is an index into2153 * an array of 32byte objects, SINDEX contains2154 * the base address of that array, and DINDEX2155 * contains the base address of the location2156 * to store the indexed address.2157 */2158set_32byte_addr:2159 shr ARG_2, 3, A;2160 shl A, 5;2161 jmp set_1byte_addr;2162}2163 2164/*2165 * Setup addr assuming that A is an index into2166 * an array of 64byte objects, SINDEX contains2167 * the base address of that array, and DINDEX2168 * contains the base address of the location2169 * to store the indexed address.2170 */2171set_64byte_addr:2172 shr ARG_2, 2, A;2173 shl A, 6;2174 2175/*2176 * Setup addr assuming that A + (ARG_2 * 256) is an2177 * index into an array of 1byte objects, SINDEX contains2178 * the base address of that array, and DINDEX contains2179 * the base address of the location to store the computed2180 * address.2181 */2182set_1byte_addr:2183 add DINDIR, A, SINDIR;2184 mov A, ARG_2;2185 adc DINDIR, A, SINDIR;2186 clr A;2187 adc DINDIR, A, SINDIR;2188 adc DINDIR, A, SINDIR ret;2189 2190/*2191 * Either post or fetch an SCB from host memory based on the2192 * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.2193 */2194dma_scb:2195 mov A, SINDEX;2196 if ((ahc->features & AHC_CMD_CHAN) != 0) {2197 mvi DINDEX, CCHADDR;2198 mvi HSCB_ADDR call set_64byte_addr;2199 mov CCSCBPTR, SCBPTR;2200 test DMAPARAMS, DIRECTION jz dma_scb_tohost;2201 if ((ahc->flags & AHC_SCB_BTT) != 0) {2202 mvi CCHCNT, SCB_DOWNLOAD_SIZE_64;2203 } else {2204 mvi CCHCNT, SCB_DOWNLOAD_SIZE;2205 }2206 mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;2207 cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;2208 jmp dma_scb_finish;2209dma_scb_tohost:2210 mvi CCHCNT, SCB_UPLOAD_SIZE;2211 if ((ahc->features & AHC_ULTRA2) == 0) {2212 mvi CCSCBCTL, CCSCBRESET;2213 bmov CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE;2214 or CCSCBCTL, CCSCBEN|CCSCBRESET;2215 test CCSCBCTL, CCSCBDONE jz .;2216 } else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) {2217 mvi CCSCBCTL, CCARREN|CCSCBRESET;2218 cmp CCSCBCTL, ARRDONE|CCARREN jne .;2219 mvi CCHCNT, SCB_UPLOAD_SIZE;2220 mvi CCSCBCTL, CCSCBEN|CCSCBRESET;2221 cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .;2222 } else {2223 mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;2224 cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;2225 }2226dma_scb_finish:2227 clr CCSCBCTL;2228 test CCSCBCTL, CCARREN|CCSCBEN jnz .;2229 ret;2230 } else {2231 mvi DINDEX, HADDR;2232 mvi HSCB_ADDR call set_64byte_addr;2233 mvi SCB_DOWNLOAD_SIZE call set_hcnt;2234 mov DFCNTRL, DMAPARAMS;2235 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost;2236 /* Fill it with the SCB data */2237copy_scb_tofifo:2238 mvi SINDEX, SCB_BASE;2239 add A, SCB_DOWNLOAD_SIZE, SINDEX;2240copy_scb_tofifo_loop:2241 call copy_to_fifo_8;2242 cmp SINDEX, A jne copy_scb_tofifo_loop;2243 or DFCNTRL, HDMAEN|FIFOFLUSH;2244 jmp dma_finish;2245dma_scb_fromhost:2246 mvi DINDEX, SCB_BASE;2247 if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {2248 /*2249 * The PCI module will only issue a PCI2250 * retry if the data FIFO is empty. If the2251 * host disconnects in the middle of a2252 * transfer, we must empty the fifo of all2253 * available data to force the chip to2254 * continue the transfer. This does not2255 * happen for SCSI transfers as the SCSI module2256 * will drain the FIFO as data are made available.2257 * When the hang occurs, we know that a multiple2258 * of 8 bytes is in the FIFO because the PCI2259 * module has an 8 byte input latch that only2260 * dumps to the FIFO when HCNT == 0 or the2261 * latch is full.2262 */2263 clr A;2264 /* Wait for at least 8 bytes of data to arrive. */2265dma_scb_hang_fifo:2266 test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;2267dma_scb_hang_wait:2268 test DFSTATUS, MREQPEND jnz dma_scb_hang_wait;2269 test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;2270 test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;2271 test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;2272 /*2273 * The PCI module no longer intends to perform2274 * a PCI transaction. Drain the fifo.2275 */2276dma_scb_hang_dma_drain_fifo:2277 not A, HCNT;2278 add A, SCB_DOWNLOAD_SIZE+SCB_BASE+1;2279 and A, ~0x7;2280 mov DINDIR,DFDAT;2281 cmp DINDEX, A jne . - 1;2282 cmp DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE2283 je dma_finish_nowait;2284 /* Restore A as the lines left to transfer. */2285 add A, -SCB_BASE, DINDEX;2286 shr A, 3;2287 jmp dma_scb_hang_fifo;2288dma_scb_hang_dma_done:2289 and DFCNTRL, ~HDMAEN;2290 test DFCNTRL, HDMAEN jnz .;2291 add SEQADDR0, A;2292 } else {2293 call dma_finish;2294 }2295 call dfdat_in_8;2296 call dfdat_in_8;2297 call dfdat_in_8;2298dfdat_in_8:2299 mov DINDIR,DFDAT;2300dfdat_in_7:2301 mov DINDIR,DFDAT;2302 mov DINDIR,DFDAT;2303 mov DINDIR,DFDAT;2304 mov DINDIR,DFDAT;2305 mov DINDIR,DFDAT;2306dfdat_in_2:2307 mov DINDIR,DFDAT;2308 mov DINDIR,DFDAT ret;2309 }2310 2311copy_to_fifo_8:2312 mov DFDAT,SINDIR;2313 mov DFDAT,SINDIR;2314copy_to_fifo_6:2315 mov DFDAT,SINDIR;2316copy_to_fifo_5:2317 mov DFDAT,SINDIR;2318copy_to_fifo_4:2319 mov DFDAT,SINDIR;2320 mov DFDAT,SINDIR;2321 mov DFDAT,SINDIR;2322 mov DFDAT,SINDIR ret;2323 2324/*2325 * Wait for DMA from host memory to data FIFO to complete, then disable2326 * DMA and wait for it to acknowledge that it's off.2327 */2328dma_finish:2329 test DFSTATUS,HDONE jz dma_finish;2330dma_finish_nowait:2331 /* Turn off DMA */2332 and DFCNTRL, ~HDMAEN;2333 test DFCNTRL, HDMAEN jnz .;2334 ret;2335 2336/*2337 * Restore an SCB that failed to match an incoming reselection2338 * to the correct/safe state. If the SCB is for a disconnected2339 * transaction, it must be returned to the disconnected list.2340 * If it is not in the disconnected state, it must be free.2341 */2342cleanup_scb:2343 if ((ahc->flags & AHC_PAGESCBS) != 0) {2344 test SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list;2345 }2346add_scb_to_free_list:2347 if ((ahc->flags & AHC_PAGESCBS) != 0) {2348BEGIN_CRITICAL;2349 mov SCB_NEXT, FREE_SCBH;2350 mvi SCB_TAG, SCB_LIST_NULL;2351 mov FREE_SCBH, SCBPTR ret;2352END_CRITICAL;2353 } else {2354 mvi SCB_TAG, SCB_LIST_NULL ret;2355 }2356 2357if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {2358set_hhaddr:2359 or DSCOMMAND1, HADDLDSEL0;2360 and HADDR, SG_HIGH_ADDR_BITS, SINDEX;2361 and DSCOMMAND1, ~HADDLDSEL0 ret;2362}2363 2364if ((ahc->flags & AHC_PAGESCBS) != 0) {2365get_free_or_disc_scb:2366BEGIN_CRITICAL;2367 cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;2368 cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;2369return_error:2370 mvi NO_FREE_SCB call set_seqint;2371 mvi SINDEX, SCB_LIST_NULL ret;2372dequeue_disc_scb:2373 mov SCBPTR, DISCONNECTED_SCBH;2374 mov DISCONNECTED_SCBH, SCB_NEXT;2375END_CRITICAL;2376 mvi DMAPARAMS, FIFORESET;2377 mov SCB_TAG jmp dma_scb;2378BEGIN_CRITICAL;2379dequeue_free_scb:2380 mov SCBPTR, FREE_SCBH;2381 mov FREE_SCBH, SCB_NEXT ret;2382END_CRITICAL;2383 2384add_scb_to_disc_list:2385/*2386 * Link this SCB into the DISCONNECTED list. This list holds the2387 * candidates for paging out an SCB if one is needed for a new command.2388 * Modifying the disconnected list is a critical(pause dissabled) section.2389 */2390BEGIN_CRITICAL;2391 mov SCB_NEXT, DISCONNECTED_SCBH;2392 mov DISCONNECTED_SCBH, SCBPTR ret;2393END_CRITICAL;2394}2395set_seqint:2396 mov INTSTAT, SINDEX;2397 nop;2398return:2399 ret;2400