1139749Simp/*- 226997Sgibbs * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. 313177Sgibbs * 495378Sgibbs * Copyright (c) 1994-2001 Justin T. Gibbs. 595378Sgibbs * Copyright (c) 2000-2001 Adaptec Inc. 626997Sgibbs * All rights reserved. 713177Sgibbs * 826997Sgibbs * Redistribution and use in source and binary forms, with or without 926997Sgibbs * modification, are permitted provided that the following conditions 1026997Sgibbs * are met: 1126997Sgibbs * 1. Redistributions of source code must retain the above copyright 1226997Sgibbs * notice, this list of conditions, and the following disclaimer, 1354211Sgibbs * without modification. 1495378Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1595378Sgibbs * substantially similar to the "NO WARRANTY" disclaimer below 1695378Sgibbs * ("Disclaimer") and any redistribution must be conditioned upon 1795378Sgibbs * including a substantially similar Disclaimer requirement for further 1895378Sgibbs * binary redistribution. 1995378Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names 2095378Sgibbs * of any contributors may be used to endorse or promote products derived 2195378Sgibbs * from this software without specific prior written permission. 2213177Sgibbs * 2354211Sgibbs * Alternatively, this software may be distributed under the terms of the 2495378Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free 2595378Sgibbs * Software Foundation. 2613177Sgibbs * 2795378Sgibbs * NO WARRANTY 2895378Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2995378Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3095378Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3195378Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3295378Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3326997Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3426997Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3595378Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3695378Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3795378Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3895378Sgibbs * POSSIBILITY OF SUCH DAMAGES. 3913177Sgibbs * 4050477Speter * $FreeBSD: releng/10.2/sys/dev/aic7xxx/aic7xxx.seq 165628 2006-12-29 13:08:46Z yar $ 4126997Sgibbs */ 424568Sgibbs 43123579SgibbsVERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $" 4495378SgibbsPATCH_ARG_LIST = "struct ahc_softc *ahc" 45102673SgibbsPREFIX = "ahc_" 4679874Sgibbs 4766268Sgibbs#include "aic7xxx.reg" 4866268Sgibbs#include "scsi_message.h" 495647Sgibbs 5013177Sgibbs/* 5119164Sgibbs * A few words on the waiting SCB list: 5219164Sgibbs * After starting the selection hardware, we check for reconnecting targets 5313690Sgibbs * as well as for our selection to complete just in case the reselection wins 5413690Sgibbs * bus arbitration. The problem with this is that we must keep track of the 5513690Sgibbs * SCB that we've already pulled from the QINFIFO and started the selection 5613690Sgibbs * on just in case the reselection wins so that we can retry the selection at 5713690Sgibbs * a later time. This problem cannot be resolved by holding a single entry 5813690Sgibbs * in scratch ram since a reconnecting target can request sense and this will 5913690Sgibbs * create yet another SCB waiting for selection. The solution used here is to 6013690Sgibbs * use byte 27 of the SCB as a psuedo-next pointer and to thread a list 6119164Sgibbs * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, 6219164Sgibbs * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to 6319164Sgibbs * this list everytime a request sense occurs or after completing a non-tagged 6419164Sgibbs * command for which a second SCB has been queued. The sequencer will 6519164Sgibbs * automatically consume the entries. 6613177Sgibbs */ 674568Sgibbs 6871390Sgibbsbus_free_sel: 6971390Sgibbs /* 7071390Sgibbs * Turn off the selection hardware. We need to reset the 7171390Sgibbs * selection request in order to perform a new selection. 7271390Sgibbs */ 73109590Sgibbs and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP; 7471390Sgibbs and SIMODE1, ~ENBUSFREE; 7544507Sgibbspoll_for_work: 7623925Sgibbs call clear_target_state; 7739220Sgibbs and SXFRCTL0, ~SPIOEN; 7868623Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 7968623Sgibbs clr SCSIBUSL; 8068623Sgibbs } 8172811Sgibbs test SCSISEQ, ENSELO jnz poll_for_selection; 8272811Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 8372811Sgibbs xor SBLKCTL,SELBUSB; /* Toggle to the other bus */ 8472811Sgibbs test SCSISEQ, ENSELO jnz poll_for_selection; 8572811Sgibbs } 86133670SgibbsBEGIN_CRITICAL; 8772811Sgibbs cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting; 88133670SgibbsEND_CRITICAL; 8939220Sgibbspoll_for_work_loop: 9039220Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 9139220Sgibbs xor SBLKCTL,SELBUSB; /* Toggle to the other bus */ 9239220Sgibbs } 9372811Sgibbs test SSTAT0, SELDO|SELDI jnz selection; 9419164Sgibbstest_queue: 9519164Sgibbs /* Has the driver posted any work for us? */ 9695378SgibbsBEGIN_CRITICAL; 9739220Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 9839220Sgibbs test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop; 9939220Sgibbs } else { 10068087Sgibbs mov A, QINPOS; 10139220Sgibbs cmp KERNEL_QINPOS, A je poll_for_work_loop; 10239220Sgibbs } 10366647Sgibbs mov ARG_1, NEXT_QUEUED_SCB; 1044568Sgibbs 10563457Sgibbs /* 10663457Sgibbs * We have at least one queued SCB now and we don't have any 10766647Sgibbs * SCBs in the list of SCBs awaiting selection. Allocate a 10866647Sgibbs * card SCB for the host's SCB and get to work on it. 10963457Sgibbs */ 11039220Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 11139220Sgibbs mov ALLZEROS call get_free_or_disc_scb; 11266647Sgibbs } else { 11339220Sgibbs /* In the non-paging case, the SCBID == hardware SCB index */ 11466647Sgibbs mov SCBPTR, ARG_1; 11539220Sgibbs } 11674094Sgibbs or SEQ_FLAGS2, SCB_DMA; 11795378SgibbsEND_CRITICAL; 11819164Sgibbsdma_queued_scb: 11963457Sgibbs /* 12063457Sgibbs * DMA the SCB from host ram into the current SCB location. 12163457Sgibbs */ 12223925Sgibbs mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; 12366647Sgibbs mov ARG_1 call dma_scb; 12419164Sgibbs /* 12566647Sgibbs * Check one last time to see if this SCB was canceled 12666647Sgibbs * before we completed the DMA operation. If it was, 12766647Sgibbs * the QINFIFO next pointer will not match our saved 12866647Sgibbs * value. 12919164Sgibbs */ 13066647Sgibbs mov A, ARG_1; 13195378SgibbsBEGIN_CRITICAL; 13266647Sgibbs cmp NEXT_QUEUED_SCB, A jne abort_qinscb; 13368087Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 13468087Sgibbs cmp SCB_TAG, A je . + 2; 13568402Sgibbs mvi SCB_MISMATCH call set_seqint; 13668087Sgibbs } 13766647Sgibbs mov NEXT_QUEUED_SCB, SCB_NEXT; 13823925Sgibbs mov SCB_NEXT,WAITING_SCBH; 13923925Sgibbs mov WAITING_SCBH, SCBPTR; 14068402Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 14168402Sgibbs mov NONE, SNSCB_QOFF; 14268402Sgibbs } else { 14368402Sgibbs inc QINPOS; 14468402Sgibbs } 14574094Sgibbs and SEQ_FLAGS2, ~SCB_DMA; 14623925Sgibbsstart_waiting: 14723925Sgibbs /* 14863457Sgibbs * Start the first entry on the waiting SCB list. 14923925Sgibbs */ 15023925Sgibbs mov SCBPTR, WAITING_SCBH; 15123925Sgibbs call start_selection; 152133670SgibbsEND_CRITICAL; 1538104Sgibbs 15472811Sgibbspoll_for_selection: 15568579Sgibbs /* 15672811Sgibbs * Twin channel devices cannot handle things like SELTO 15772811Sgibbs * interrupts on the "background" channel. So, while 15872811Sgibbs * selecting, keep polling the current channel until 15972811Sgibbs * either a selection or reselection occurs. 16068579Sgibbs */ 16172811Sgibbs test SSTAT0, SELDO|SELDI jz poll_for_selection; 16239220Sgibbs 16339220Sgibbsselection: 16463457Sgibbs /* 16563457Sgibbs * We aren't expecting a bus free, so interrupt 16663457Sgibbs * the kernel driver if it happens. 16763457Sgibbs */ 16863457Sgibbs mvi CLRSINT1,CLRBUSFREE; 16976634Sgibbs if ((ahc->features & AHC_DT) == 0) { 17076634Sgibbs or SIMODE1, ENBUSFREE; 17176634Sgibbs } 17263457Sgibbs 17368579Sgibbs /* 17468579Sgibbs * Guard against a bus free after (re)selection 17568579Sgibbs * but prior to enabling the busfree interrupt. SELDI 17668579Sgibbs * and SELDO will be cleared in that case. 17768579Sgibbs */ 17871390Sgibbs test SSTAT0, SELDI|SELDO jz bus_free_sel; 17939220Sgibbs test SSTAT0,SELDO jnz select_out; 18039220Sgibbsselect_in: 18168087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 18268087Sgibbs if ((ahc->flags & AHC_INITIATORROLE) != 0) { 18341646Sgibbs test SSTAT0, TARGET jz initiator_reselect; 18441646Sgibbs } 18571390Sgibbs mvi CLRSINT0, CLRSELDI; 18642652Sgibbs 18739220Sgibbs /* 18839220Sgibbs * We've just been selected. Assert BSY and 18939220Sgibbs * setup the phase for receiving messages 19039220Sgibbs * from the target. 19139220Sgibbs */ 19239220Sgibbs mvi SCSISIGO, P_MESGOUT|BSYO; 19339220Sgibbs 19439220Sgibbs /* 19539220Sgibbs * Setup the DMA for sending the identify and 19641299Sgibbs * command information. 19739220Sgibbs */ 198109590Sgibbs mvi SEQ_FLAGS, CMDPHASE_PENDING; 19941299Sgibbs 20041299Sgibbs mov A, TQINPOS; 20139220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 20239220Sgibbs mvi DINDEX, CCHADDR; 20363457Sgibbs mvi SHARED_DATA_ADDR call set_32byte_addr; 20439220Sgibbs mvi CCSCBCTL, CCSCBRESET; 20539220Sgibbs } else { 20639220Sgibbs mvi DINDEX, HADDR; 20763457Sgibbs mvi SHARED_DATA_ADDR call set_32byte_addr; 20839220Sgibbs mvi DFCNTRL, FIFORESET; 20939220Sgibbs } 21039220Sgibbs 21139220Sgibbs /* Initiator that selected us */ 21263457Sgibbs and SAVED_SCSIID, SELID_MASK, SELID; 21363457Sgibbs /* The Target ID we were selected at */ 21463457Sgibbs if ((ahc->features & AHC_MULTI_TID) != 0) { 21563457Sgibbs and A, OID, TARGIDIN; 21663457Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 21763457Sgibbs and A, OID, SCSIID_ULTRA2; 21839220Sgibbs } else { 21963457Sgibbs and A, OID, SCSIID; 22039220Sgibbs } 22163457Sgibbs or SAVED_SCSIID, A; 22263457Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 22363457Sgibbs test SBLKCTL, SELBUSB jz . + 2; 22463457Sgibbs or SAVED_SCSIID, TWIN_CHNLB; 22563457Sgibbs } 22644507Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 22763457Sgibbs mov CCSCBRAM, SAVED_SCSIID; 22839220Sgibbs } else { 22963457Sgibbs mov DFDAT, SAVED_SCSIID; 23039220Sgibbs } 23139220Sgibbs 23239220Sgibbs /* 23339220Sgibbs * If ATN isn't asserted, the target isn't interested 23439220Sgibbs * in talking to us. Go directly to bus free. 23563457Sgibbs * XXX SCSI-1 may require us to assume lun 0 if 23663457Sgibbs * ATN is false. 23739220Sgibbs */ 23839220Sgibbs test SCSISIGI, ATNI jz target_busfree; 23939220Sgibbs 24039220Sgibbs /* 24139220Sgibbs * Watch ATN closely now as we pull in messages from the 24239220Sgibbs * initiator. We follow the guidlines from section 6.5 24339220Sgibbs * of the SCSI-2 spec for what messages are allowed when. 24439220Sgibbs */ 24541646Sgibbs call target_inb; 24639220Sgibbs 24739220Sgibbs /* 24839220Sgibbs * Our first message must be one of IDENTIFY, ABORT, or 24939220Sgibbs * BUS_DEVICE_RESET. 25039220Sgibbs */ 25142652Sgibbs test DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop; 25239220Sgibbs /* Store for host */ 25339220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 25439220Sgibbs mov CCSCBRAM, DINDEX; 25539220Sgibbs } else { 25639220Sgibbs mov DFDAT, DINDEX; 25739220Sgibbs } 25895378Sgibbs and SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX; 25939220Sgibbs 26039220Sgibbs /* Remember for disconnection decision */ 26139220Sgibbs test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2; 26239220Sgibbs /* XXX Honor per target settings too */ 26339220Sgibbs or SEQ_FLAGS, NO_DISCONNECT; 26439220Sgibbs 26539220Sgibbs test SCSISIGI, ATNI jz ident_messages_done; 26641646Sgibbs call target_inb; 26739220Sgibbs /* 26839220Sgibbs * If this is a tagged request, the tagged message must 26939220Sgibbs * immediately follow the identify. We test for a valid 27039220Sgibbs * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and 27139220Sgibbs * < MSG_IGN_WIDE_RESIDUE. 27239220Sgibbs */ 27339220Sgibbs add A, -MSG_SIMPLE_Q_TAG, DINDEX; 27495378Sgibbs jnc ident_messages_done_msg_pending; 27539220Sgibbs add A, -MSG_IGN_WIDE_RESIDUE, DINDEX; 27695378Sgibbs jc ident_messages_done_msg_pending; 27795378Sgibbs 27839220Sgibbs /* Store for host */ 27939220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 28039220Sgibbs mov CCSCBRAM, DINDEX; 28139220Sgibbs } else { 28239220Sgibbs mov DFDAT, DINDEX; 28339220Sgibbs } 28439220Sgibbs 28539220Sgibbs /* 28639220Sgibbs * If the initiator doesn't feel like providing a tag number, 28739220Sgibbs * we've got a failed selection and must transition to bus 28839220Sgibbs * free. 28939220Sgibbs */ 29039220Sgibbs test SCSISIGI, ATNI jz target_busfree; 29142652Sgibbs 29239220Sgibbs /* 29339220Sgibbs * Store the tag for the host. 29439220Sgibbs */ 29541646Sgibbs call target_inb; 29639220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 29739220Sgibbs mov CCSCBRAM, DINDEX; 29839220Sgibbs } else { 29939220Sgibbs mov DFDAT, DINDEX; 30039220Sgibbs } 30142652Sgibbs mov INITIATOR_TAG, DINDEX; 30263457Sgibbs or SEQ_FLAGS, TARGET_CMD_IS_TAGGED; 30395378Sgibbs 30495378Sgibbsident_messages_done: 30595378Sgibbs /* Terminate the ident list */ 30695378Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 30795378Sgibbs mvi CCSCBRAM, SCB_LIST_NULL; 30895378Sgibbs } else { 30995378Sgibbs mvi DFDAT, SCB_LIST_NULL; 31095378Sgibbs } 311109590Sgibbs or SEQ_FLAGS, TARG_CMD_PENDING; 31295378Sgibbs test SEQ_FLAGS2, TARGET_MSG_PENDING 31395378Sgibbs jnz target_mesgout_pending; 31495378Sgibbs test SCSISIGI, ATNI jnz target_mesgout_continue; 31595378Sgibbs jmp target_ITloop; 31695378Sgibbs 31795378Sgibbs 31895378Sgibbsident_messages_done_msg_pending: 31995378Sgibbs or SEQ_FLAGS2, TARGET_MSG_PENDING; 32039220Sgibbs jmp ident_messages_done; 32139220Sgibbs 32241646Sgibbs /* 32341646Sgibbs * Pushed message loop to allow the kernel to 32442652Sgibbs * run it's own target mode message state engine. 32541646Sgibbs */ 32641646Sgibbshost_target_message_loop: 32768402Sgibbs mvi HOST_MSG_LOOP call set_seqint; 32841646Sgibbs cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop; 32941646Sgibbs test SSTAT0, SPIORDY jz .; 33041646Sgibbs jmp host_target_message_loop; 33139220Sgibbs } 33239220Sgibbs 33368087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) { 33439220Sgibbs/* 33523925Sgibbs * Reselection has been initiated by a target. Make a note that we've been 33623925Sgibbs * reselected, but haven't seen an IDENTIFY message from the target yet. 33713177Sgibbs */ 33839220Sgibbsinitiator_reselect: 33923925Sgibbs /* XXX test for and handle ONE BIT condition */ 34071390Sgibbs or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN; 34163457Sgibbs and SAVED_SCSIID, SELID_MASK, SELID; 34263457Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 34363457Sgibbs and A, OID, SCSIID_ULTRA2; 34463457Sgibbs } else { 34563457Sgibbs and A, OID, SCSIID; 34663457Sgibbs } 34763457Sgibbs or SAVED_SCSIID, A; 34839545Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 34939545Sgibbs test SBLKCTL, SELBUSB jz . + 2; 35063457Sgibbs or SAVED_SCSIID, TWIN_CHNLB; 35139545Sgibbs } 35271390Sgibbs mvi CLRSINT0, CLRSELDI; 35339220Sgibbs jmp ITloop; 35441646Sgibbs} 3554568Sgibbs 35672811Sgibbsabort_qinscb: 35772811Sgibbs call add_scb_to_free_list; 35872811Sgibbs jmp poll_for_work_loop; 35972811Sgibbs 360133670SgibbsBEGIN_CRITICAL; 36172811Sgibbsstart_selection: 36272811Sgibbs /* 36372811Sgibbs * If bus reset interrupts have been disabled (from a previous 36472811Sgibbs * reset), re-enable them now. Resets are only of interest 36572811Sgibbs * when we have outstanding transactions, so we can safely 36672811Sgibbs * defer re-enabling the interrupt until, as an initiator, 36772811Sgibbs * we start sending out transactions again. 36872811Sgibbs */ 36972811Sgibbs test SIMODE1, ENSCSIRST jnz . + 3; 37072811Sgibbs mvi CLRSINT1, CLRSCSIRSTI; 37172811Sgibbs or SIMODE1, ENSCSIRST; 37272811Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 37372811Sgibbs and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */ 37472811Sgibbs test SCB_SCSIID, TWIN_CHNLB jz . + 2; 37572811Sgibbs or SINDEX, SELBUSB; 37672811Sgibbs mov SBLKCTL,SINDEX; /* select channel */ 37772811Sgibbs } 37872811Sgibbsinitialize_scsiid: 37972811Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 38072811Sgibbs mov SCSIID_ULTRA2, SCB_SCSIID; 38172811Sgibbs } else if ((ahc->features & AHC_TWIN) != 0) { 38272811Sgibbs and SCSIID, TWIN_TID|OID, SCB_SCSIID; 38372811Sgibbs } else { 38472811Sgibbs mov SCSIID, SCB_SCSIID; 38572811Sgibbs } 38672811Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 38772811Sgibbs mov SINDEX, SCSISEQ_TEMPLATE; 38872811Sgibbs test SCB_CONTROL, TARGET_SCB jz . + 2; 38972811Sgibbs or SINDEX, TEMODE; 39072811Sgibbs mov SCSISEQ, SINDEX ret; 39172811Sgibbs } else { 39272811Sgibbs mov SCSISEQ, SCSISEQ_TEMPLATE ret; 39372811Sgibbs } 394133670SgibbsEND_CRITICAL; 39572811Sgibbs 39613177Sgibbs/* 397102673Sgibbs * Initialize transfer settings with SCB provided settings. 39872811Sgibbs */ 39972811Sgibbsset_transfer_settings: 40072811Sgibbs if ((ahc->features & AHC_ULTRA) != 0) { 40172811Sgibbs test SCB_CONTROL, ULTRAENB jz . + 2; 40272811Sgibbs or SXFRCTL0, FAST20; 40372811Sgibbs } 40472811Sgibbs /* 40572811Sgibbs * Initialize SCSIRATE with the appropriate value for this target. 40672811Sgibbs */ 40772811Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 40872811Sgibbs bmov SCSIRATE, SCB_SCSIRATE, 2 ret; 40972811Sgibbs } else { 41072811Sgibbs mov SCSIRATE, SCB_SCSIRATE ret; 41172811Sgibbs } 41272811Sgibbs 41372811Sgibbsif ((ahc->flags & AHC_TARGETROLE) != 0) { 41472811Sgibbs/* 41572811Sgibbs * We carefully toggle SPIOEN to allow us to return the 41672811Sgibbs * message byte we receive so it can be checked prior to 41772811Sgibbs * driving REQ on the bus for the next byte. 41872811Sgibbs */ 41972811Sgibbstarget_inb: 42072811Sgibbs /* 42172811Sgibbs * Drive REQ on the bus by enabling SCSI PIO. 42272811Sgibbs */ 42372811Sgibbs or SXFRCTL0, SPIOEN; 42472811Sgibbs /* Wait for the byte */ 42572811Sgibbs test SSTAT0, SPIORDY jz .; 42672811Sgibbs /* Prevent our read from triggering another REQ */ 42772811Sgibbs and SXFRCTL0, ~SPIOEN; 42872811Sgibbs /* Save latched contents */ 42972811Sgibbs mov DINDEX, SCSIDATL ret; 43072811Sgibbs} 43172811Sgibbs 43272811Sgibbs/* 43323925Sgibbs * After the selection, remove this SCB from the "waiting SCB" 43423925Sgibbs * list. This is achieved by simply moving our "next" pointer into 43523925Sgibbs * WAITING_SCBH. Our next pointer will be set to null the next time this 43623925Sgibbs * SCB is used, so don't bother with it now. 43723925Sgibbs */ 43839220Sgibbsselect_out: 43925005Sgibbs /* Turn off the selection hardware */ 44058258Sgibbs and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ; 44125005Sgibbs mov SCBPTR, WAITING_SCBH; 44224914Sgibbs mov WAITING_SCBH,SCB_NEXT; 44363457Sgibbs mov SAVED_SCSIID, SCB_SCSIID; 444115333Sgibbs and SAVED_LUN, LID, SCB_LUN; 445102673Sgibbs call set_transfer_settings; 44668087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 44739220Sgibbs test SSTAT0, TARGET jz initiator_select; 4488567Sdg 449102673Sgibbs or SXFRCTL0, CLRSTCNT|CLRCHN; 450102673Sgibbs 45139220Sgibbs /* 452102673Sgibbs * Put tag in connonical location since not 453102673Sgibbs * all connections have an SCB. 454102673Sgibbs */ 455102673Sgibbs mov INITIATOR_TAG, SCB_TARGET_ITAG; 456102673Sgibbs 457102673Sgibbs /* 45839220Sgibbs * We've just re-selected an initiator. 45939220Sgibbs * Assert BSY and setup the phase for 46039220Sgibbs * sending our identify messages. 46139220Sgibbs */ 46241646Sgibbs mvi P_MESGIN|BSYO call change_phase; 463102673Sgibbs mvi CLRSINT0, CLRSELDO; 4644568Sgibbs 46539220Sgibbs /* 46639220Sgibbs * Start out with a simple identify message. 46739220Sgibbs */ 468115333Sgibbs or SAVED_LUN, MSG_IDENTIFYFLAG call target_outb; 4696608Sgibbs 47039220Sgibbs /* 47139220Sgibbs * If we are the result of a tagged command, send 47239220Sgibbs * a simple Q tag and the tag id. 47339220Sgibbs */ 47439220Sgibbs test SCB_CONTROL, TAG_ENB jz . + 3; 47539220Sgibbs mvi MSG_SIMPLE_Q_TAG call target_outb; 47695378Sgibbs mov SCB_TARGET_ITAG call target_outb; 47739220Sgibbstarget_synccmd: 47839220Sgibbs /* 47939220Sgibbs * Now determine what phases the host wants us 48039220Sgibbs * to go through. 48139220Sgibbs */ 48295378Sgibbs mov SEQ_FLAGS, SCB_TARGET_PHASES; 48342652Sgibbs 48474972Sgibbs test SCB_CONTROL, MK_MESSAGE jz target_ITloop; 48574972Sgibbs mvi P_MESGIN|BSYO call change_phase; 48674972Sgibbs jmp host_target_message_loop; 48739220Sgibbstarget_ITloop: 48839220Sgibbs /* 48941646Sgibbs * Start honoring ATN signals now that 49044507Sgibbs * we properly identified ourselves. 49139220Sgibbs */ 49241646Sgibbs test SCSISIGI, ATNI jnz target_mesgout; 49339220Sgibbs test SEQ_FLAGS, CMDPHASE_PENDING jnz target_cmdphase; 49439220Sgibbs test SEQ_FLAGS, DPHASE_PENDING jnz target_dphase; 49539220Sgibbs test SEQ_FLAGS, SPHASE_PENDING jnz target_sphase; 49639220Sgibbs 49739220Sgibbs /* 49839220Sgibbs * No more work to do. Either disconnect or not depending 49939220Sgibbs * on the state of NO_DISCONNECT. 50039220Sgibbs */ 50139220Sgibbs test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; 502102673Sgibbs mvi TARG_IMMEDIATE_SCB, SCB_LIST_NULL; 50374972Sgibbs call complete_target_cmd; 50439220Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 50539220Sgibbs mov ALLZEROS call get_free_or_disc_scb; 50639220Sgibbs } 507102673Sgibbs cmp TARG_IMMEDIATE_SCB, SCB_LIST_NULL je .; 50839220Sgibbs mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; 509102673Sgibbs mov TARG_IMMEDIATE_SCB call dma_scb; 51095378Sgibbs call set_transfer_settings; 511102673Sgibbs or SXFRCTL0, CLRSTCNT|CLRCHN; 51239220Sgibbs jmp target_synccmd; 51339220Sgibbs 51441646Sgibbstarget_mesgout: 51541646Sgibbs mvi SCSISIGO, P_MESGOUT|BSYO; 51663457Sgibbstarget_mesgout_continue: 51741646Sgibbs call target_inb; 51863457Sgibbstarget_mesgout_pending: 519109590Sgibbs and SEQ_FLAGS2, ~TARGET_MSG_PENDING; 52041646Sgibbs /* Local Processing goes here... */ 52141646Sgibbs jmp host_target_message_loop; 52241646Sgibbs 52339220Sgibbstarget_disconnect: 52441646Sgibbs mvi P_MESGIN|BSYO call change_phase; 52541816Sgibbs test SEQ_FLAGS, DPHASE jz . + 2; 52641816Sgibbs mvi MSG_SAVEDATAPOINTER call target_outb; 52739220Sgibbs mvi MSG_DISCONNECT call target_outb; 52839220Sgibbs 52943880Sgibbstarget_busfree_wait: 53072640Sasmodai /* Wait for preceding I/O session to complete. */ 53143880Sgibbs test SCSISIGI, ACKI jnz .; 53239220Sgibbstarget_busfree: 53363457Sgibbs and SIMODE1, ~ENBUSFREE; 53468623Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 53568623Sgibbs clr SCSIBUSL; 53668623Sgibbs } 53739220Sgibbs clr SCSISIGO; 53857099Sgibbs mvi LASTPHASE, P_BUSFREE; 53939220Sgibbs call complete_target_cmd; 54039220Sgibbs jmp poll_for_work; 54139220Sgibbs 54239220Sgibbstarget_cmdphase: 54395378Sgibbs /* 54495378Sgibbs * The target has dropped ATN (doesn't want to abort or BDR) 54595378Sgibbs * and we believe this selection to be valid. If the ring 54695378Sgibbs * buffer for new commands is full, return busy or queue full. 54795378Sgibbs */ 54895378Sgibbs if ((ahc->features & AHC_HS_MAILBOX) != 0) { 54995378Sgibbs and A, HOST_TQINPOS, HS_MAILBOX; 55095378Sgibbs } else { 55195378Sgibbs mov A, KERNEL_TQINPOS; 55295378Sgibbs } 55395378Sgibbs cmp TQINPOS, A jne tqinfifo_has_space; 55495378Sgibbs mvi P_STATUS|BSYO call change_phase; 55595378Sgibbs test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3; 55695378Sgibbs mvi STATUS_QUEUE_FULL call target_outb; 55795378Sgibbs jmp target_busfree_wait; 55895378Sgibbs mvi STATUS_BUSY call target_outb; 55995378Sgibbs jmp target_busfree_wait; 56095378Sgibbstqinfifo_has_space: 56141646Sgibbs mvi P_COMMAND|BSYO call change_phase; 56241646Sgibbs call target_inb; 56339220Sgibbs mov A, DINDEX; 56439220Sgibbs /* Store for host */ 56539220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 56639220Sgibbs mov CCSCBRAM, A; 56739220Sgibbs } else { 56839220Sgibbs mov DFDAT, A; 56939220Sgibbs } 57039220Sgibbs 57139220Sgibbs /* 57239220Sgibbs * Determine the number of bytes to read 57341299Sgibbs * based on the command group code via table lookup. 57441299Sgibbs * We reuse the first 8 bytes of the TARG_SCSIRATE 57541299Sgibbs * BIOS array for this table. Count is one less than 57641299Sgibbs * the total for the command since we've already fetched 57741299Sgibbs * the first byte. 57839220Sgibbs */ 57939220Sgibbs shr A, CMD_GROUP_CODE_SHIFT; 58068087Sgibbs add SINDEX, CMDSIZE_TABLE, A; 58139220Sgibbs mov A, SINDIR; 58239220Sgibbs 58339220Sgibbs test A, 0xFF jz command_phase_done; 58471390Sgibbs or SXFRCTL0, SPIOEN; 58539220Sgibbscommand_loop: 58639220Sgibbs test SSTAT0, SPIORDY jz .; 58739220Sgibbs cmp A, 1 jne . + 2; 58839220Sgibbs and SXFRCTL0, ~SPIOEN; /* Last Byte */ 58939220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 59039220Sgibbs mov CCSCBRAM, SCSIDATL; 59139220Sgibbs } else { 59239220Sgibbs mov DFDAT, SCSIDATL; 59339220Sgibbs } 59439220Sgibbs dec A; 59539220Sgibbs test A, 0xFF jnz command_loop; 59639220Sgibbs 59739220Sgibbscommand_phase_done: 59839220Sgibbs and SEQ_FLAGS, ~CMDPHASE_PENDING; 59939220Sgibbs jmp target_ITloop; 60039220Sgibbs 60139220Sgibbstarget_dphase: 60239220Sgibbs /* 60363457Sgibbs * Data phases on the bus are from the 60463457Sgibbs * perspective of the initiator. The dma 60563457Sgibbs * code looks at LASTPHASE to determine the 60663457Sgibbs * data direction of the DMA. Toggle it for 60763457Sgibbs * target transfers. 60839220Sgibbs */ 60995378Sgibbs xor LASTPHASE, IOI, SCB_TARGET_DATA_DIR; 61095378Sgibbs or SCB_TARGET_DATA_DIR, BSYO call change_phase; 61139220Sgibbs jmp p_data; 61239220Sgibbs 61339220Sgibbstarget_sphase: 61441646Sgibbs mvi P_STATUS|BSYO call change_phase; 61541646Sgibbs mvi LASTPHASE, P_STATUS; 61695378Sgibbs mov SCB_SCSI_STATUS call target_outb; 61741646Sgibbs /* XXX Watch for ATN or parity errors??? */ 61839220Sgibbs mvi SCSISIGO, P_MESGIN|BSYO; 61939220Sgibbs /* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */ 62039220Sgibbs mov ALLZEROS call target_outb; 62143880Sgibbs jmp target_busfree_wait; 62239220Sgibbs 62339220Sgibbscomplete_target_cmd: 62439220Sgibbs test SEQ_FLAGS, TARG_CMD_PENDING jnz . + 2; 62539220Sgibbs mov SCB_TAG jmp complete_post; 62639220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 62741299Sgibbs /* Set the valid byte */ 62841299Sgibbs mvi CCSCBADDR, 24; 62941299Sgibbs mov CCSCBRAM, ALLONES; 63041299Sgibbs mvi CCHCNT, 28; 63139220Sgibbs or CCSCBCTL, CCSCBEN|CCSCBRESET; 63239220Sgibbs test CCSCBCTL, CCSCBDONE jz .; 63339220Sgibbs clr CCSCBCTL; 63439220Sgibbs } else { 63541299Sgibbs /* Set the valid byte */ 63641299Sgibbs or DFCNTRL, FIFORESET; 63741299Sgibbs mvi DFWADDR, 3; /* Third 64bit word or byte 24 */ 63841299Sgibbs mov DFDAT, ALLONES; 63963457Sgibbs mvi 28 call set_hcnt; 64039220Sgibbs or DFCNTRL, HDMAEN|FIFOFLUSH; 64139220Sgibbs call dma_finish; 64239220Sgibbs } 64341299Sgibbs inc TQINPOS; 64441299Sgibbs mvi INTSTAT,CMDCMPLT ret; 64539220Sgibbs } 64641646Sgibbs 64768087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) { 64839220Sgibbsinitiator_select: 649102673Sgibbs or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN; 65041646Sgibbs /* 65141646Sgibbs * As soon as we get a successful selection, the target 65241646Sgibbs * should go into the message out phase since we have ATN 65341646Sgibbs * asserted. 65441646Sgibbs */ 65539220Sgibbs mvi MSG_OUT, MSG_IDENTIFYFLAG; 656107420Sscottl mvi SEQ_FLAGS, NO_CDB_SENT; 657102673Sgibbs mvi CLRSINT0, CLRSELDO; 65813177Sgibbs 65941646Sgibbs /* 66041646Sgibbs * Main loop for information transfer phases. Wait for the 66141646Sgibbs * target to assert REQ before checking MSG, C/D and I/O for 66241646Sgibbs * the bus phase. 66341646Sgibbs */ 66463457Sgibbsmesgin_phasemis: 6654568SgibbsITloop: 66639220Sgibbs call phase_lock; 6674568Sgibbs 66839220Sgibbs mov A, LASTPHASE; 6694568Sgibbs 67039220Sgibbs test A, ~P_DATAIN jz p_data; 67123925Sgibbs cmp A,P_COMMAND je p_command; 67223925Sgibbs cmp A,P_MESGOUT je p_mesgout; 67323925Sgibbs cmp A,P_STATUS je p_status; 67423925Sgibbs cmp A,P_MESGIN je p_mesgin; 6754568Sgibbs 67668402Sgibbs mvi BAD_PHASE call set_seqint; 67723925Sgibbs jmp ITloop; /* Try reading the bus again. */ 6784568Sgibbs 67923925Sgibbsawait_busfree: 68023925Sgibbs and SIMODE1, ~ENBUSFREE; 68123925Sgibbs mov NONE, SCSIDATL; /* Ack the last byte */ 68268623Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 68368623Sgibbs clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ 68468623Sgibbs } 68539220Sgibbs and SXFRCTL0, ~SPIOEN; 686123579Sgibbs mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; 68723925Sgibbs test SSTAT1,REQINIT|BUSFREE jz .; 68823925Sgibbs test SSTAT1, BUSFREE jnz poll_for_work; 68968579Sgibbs mvi MISSED_BUSFREE call set_seqint; 69041646Sgibbs} 69123925Sgibbs 69223925Sgibbsclear_target_state: 69341646Sgibbs /* 69441646Sgibbs * We assume that the kernel driver may reset us 69541646Sgibbs * at any time, even in the middle of a DMA, so 69641646Sgibbs * clear DFCNTRL too. 69741646Sgibbs */ 69841646Sgibbs clr DFCNTRL; 69968087Sgibbs or SXFRCTL0, CLRSTCNT|CLRCHN; 70041646Sgibbs 70141646Sgibbs /* 70241646Sgibbs * We don't know the target we will connect to, 70341646Sgibbs * so default to narrow transfers to avoid 70441646Sgibbs * parity problems. 70541646Sgibbs */ 70641646Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 70741646Sgibbs bmov SCSIRATE, ALLZEROS, 2; 70841646Sgibbs } else { 70941646Sgibbs clr SCSIRATE; 71063457Sgibbs if ((ahc->features & AHC_ULTRA) != 0) { 71163457Sgibbs and SXFRCTL0, ~(FAST20); 71263457Sgibbs } 71341646Sgibbs } 71423925Sgibbs mvi LASTPHASE, P_BUSFREE; 71523925Sgibbs /* clear target specific flags */ 716107420Sscottl mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; 71723925Sgibbs 71863457Sgibbssg_advance: 71963457Sgibbs clr A; /* add sizeof(struct scatter) */ 72063457Sgibbs add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF; 72163457Sgibbs adc SCB_RESIDUAL_SGPTR[1],A; 72263457Sgibbs adc SCB_RESIDUAL_SGPTR[2],A; 72363457Sgibbs adc SCB_RESIDUAL_SGPTR[3],A ret; 72463457Sgibbs 72574094Sgibbsif ((ahc->features & AHC_CMD_CHAN) != 0) { 72674094Sgibbsdisable_ccsgen: 72774094Sgibbs test CCSGCTL, CCSGEN jz return; 72874094Sgibbs test CCSGCTL, CCSGDONE jz .; 72974094Sgibbsdisable_ccsgen_fetch_done: 73074094Sgibbs clr CCSGCTL; 73174094Sgibbs test CCSGCTL, CCSGEN jnz .; 73274094Sgibbs ret; 73363457Sgibbsidle_loop: 73476634Sgibbs /* 73576634Sgibbs * Do we need any more segments for this transfer? 73676634Sgibbs */ 73776634Sgibbs test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return; 73876634Sgibbs 73974094Sgibbs /* Did we just finish fetching segs? */ 74074094Sgibbs cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete; 74163457Sgibbs 74274094Sgibbs /* Are we actively fetching segments? */ 74374094Sgibbs test CCSGCTL, CCSGEN jnz return; 74463457Sgibbs 74574094Sgibbs /* 74674094Sgibbs * Do we have any prefetch left??? 74774094Sgibbs */ 74874094Sgibbs cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail; 74963457Sgibbs 75074094Sgibbs /* 75174094Sgibbs * Need to fetch segments, but we can only do that 75274094Sgibbs * if the command channel is completely idle. Make 75374094Sgibbs * sure we don't have an SCB prefetch going on. 75474094Sgibbs */ 75574094Sgibbs test CCSCBCTL, CCSCBEN jnz return; 75663457Sgibbs 75774094Sgibbs /* 75874094Sgibbs * We fetch a "cacheline aligned" and sized amount of data 75974094Sgibbs * so we don't end up referencing a non-existant page. 76074094Sgibbs * Cacheline aligned is in quotes because the kernel will 76174094Sgibbs * set the prefetch amount to a reasonable level if the 76274094Sgibbs * cacheline size is unknown. 76374094Sgibbs */ 76474094Sgibbs mvi CCHCNT, SG_PREFETCH_CNT; 76574094Sgibbs and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR; 76674094Sgibbs bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3; 76774094Sgibbs mvi CCSGCTL, CCSGEN|CCSGRESET ret; 76863457Sgibbsidle_sgfetch_complete: 76974094Sgibbs call disable_ccsgen_fetch_done; 77074094Sgibbs and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR; 77163457Sgibbsidle_sg_avail: 77274094Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 77374094Sgibbs /* Does the hardware have space for another SG entry? */ 77474094Sgibbs test DFSTATUS, PRELOAD_AVAIL jz return; 77579874Sgibbs bmov HADDR, CCSGRAM, 7; 77674094Sgibbs bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1; 77779874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 77879874Sgibbs mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr; 77979874Sgibbs } 78074094Sgibbs call sg_advance; 78174094Sgibbs mov SINDEX, SCB_RESIDUAL_SGPTR[0]; 78274094Sgibbs test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2; 78374094Sgibbs or SINDEX, LAST_SEG; 78474094Sgibbs mov SG_CACHE_PRE, SINDEX; 78574507Sgibbs /* Load the segment */ 78674507Sgibbs or DFCNTRL, PRELOADEN; 78763457Sgibbs } 78874094Sgibbs ret; 78974094Sgibbs} 79063457Sgibbs 79165942Sgibbsif ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) { 79213177Sgibbs/* 79365942Sgibbs * Calculate the trailing portion of this S/G segment that cannot 79465942Sgibbs * be transferred using memory write and invalidate PCI transactions. 79565942Sgibbs * XXX Can we optimize this for PCI writes only??? 79665942Sgibbs */ 79765942Sgibbscalc_mwi_residual: 79865942Sgibbs /* 79965942Sgibbs * If the ending address is on a cacheline boundary, 80065942Sgibbs * there is no need for an extra segment. 80165942Sgibbs */ 80265942Sgibbs mov A, HCNT[0]; 80365942Sgibbs add A, A, HADDR[0]; 80465942Sgibbs and A, CACHESIZE_MASK; 80565942Sgibbs test A, 0xFF jz return; 80665942Sgibbs 80765942Sgibbs /* 80865942Sgibbs * If the transfer is less than a cachline, 80965942Sgibbs * there is no need for an extra segment. 81065942Sgibbs */ 81165942Sgibbs test HCNT[1], 0xFF jnz calc_mwi_residual_final; 81265942Sgibbs test HCNT[2], 0xFF jnz calc_mwi_residual_final; 81365942Sgibbs add NONE, INVERTED_CACHESIZE_MASK, HCNT[0]; 81465942Sgibbs jnc return; 81565942Sgibbs 81665942Sgibbscalc_mwi_residual_final: 81765942Sgibbs mov MWI_RESIDUAL, A; 81865942Sgibbs not A; 81965942Sgibbs inc A; 82065942Sgibbs add HCNT[0], A; 82165942Sgibbs adc HCNT[1], -1; 82265942Sgibbs adc HCNT[2], -1 ret; 82365942Sgibbs} 82465942Sgibbs 82539220Sgibbsp_data: 826107420Sscottl test SEQ_FLAGS,NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed; 827107420Sscottl mvi PROTO_VIOLATION call set_seqint; 828107420Sscottlp_data_allowed: 82939220Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 83039220Sgibbs mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN; 83139220Sgibbs } else { 83239220Sgibbs mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET; 83339220Sgibbs } 83439220Sgibbs test LASTPHASE, IOI jnz . + 2; 83539220Sgibbs or DMAPARAMS, DIRECTION; 83639220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 83763457Sgibbs /* We don't have any valid S/G elements */ 83866647Sgibbs mvi CCSGADDR, SG_PREFETCH_CNT; 83939220Sgibbs } 84079874Sgibbs test SEQ_FLAGS, DPHASE jz data_phase_initialize; 8414568Sgibbs 84279874Sgibbs /* 84379874Sgibbs * If we re-enter the data phase after going through another 84479874Sgibbs * phase, our transfer location has almost certainly been 84579874Sgibbs * corrupted by the interveining, non-data, transfers. Ask 84679874Sgibbs * the host driver to fix us up based on the transfer residual. 84779874Sgibbs */ 84879874Sgibbs mvi PDATA_REINIT call set_seqint; 84979874Sgibbs jmp data_phase_loop; 85079874Sgibbs 85179874Sgibbsdata_phase_initialize: 85279874Sgibbs /* We have seen a data phase for the first time */ 85339220Sgibbs or SEQ_FLAGS, DPHASE; 85439220Sgibbs 85519164Sgibbs /* 85619164Sgibbs * Initialize the DMA address and counter from the SCB. 85763457Sgibbs * Also set SCB_RESIDUAL_SGPTR, including the LAST_SEG 85863457Sgibbs * flag in the highest byte of the data count. We cannot 85963457Sgibbs * modify the saved values in the SCB until we see a save 86063457Sgibbs * data pointers message. 86119164Sgibbs */ 86279874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 86379874Sgibbs /* The lowest address byte must be loaded last. */ 86479874Sgibbs mov SCB_DATACNT[3] call set_hhaddr; 86579874Sgibbs } 86639220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 86739220Sgibbs bmov HADDR, SCB_DATAPTR, 7; 86863457Sgibbs bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5; 86939220Sgibbs } else { 87039220Sgibbs mvi DINDEX, HADDR; 87139220Sgibbs mvi SCB_DATAPTR call bcopy_7; 87263457Sgibbs mvi DINDEX, SCB_RESIDUAL_DATACNT + 3; 87363457Sgibbs mvi SCB_DATACNT + 3 call bcopy_5; 87439220Sgibbs } 87565942Sgibbs if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) { 87665942Sgibbs call calc_mwi_residual; 87765942Sgibbs } 87863457Sgibbs and SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID; 87919164Sgibbs 88039220Sgibbs if ((ahc->features & AHC_ULTRA2) == 0) { 88139220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 88239220Sgibbs bmov STCNT, HCNT, 3; 88339220Sgibbs } else { 88439220Sgibbs call set_stcnt_from_hcnt; 88539220Sgibbs } 88639220Sgibbs } 88719164Sgibbs 88863457Sgibbsdata_phase_loop: 88963457Sgibbs /* Guard against overruns */ 89063457Sgibbs test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_inbounds; 89119164Sgibbs 89263457Sgibbs /* 89368087Sgibbs * Turn on `Bit Bucket' mode, wait until the target takes 89468087Sgibbs * us to another phase, and then notify the host. 89563457Sgibbs */ 89668087Sgibbs and DMAPARAMS, DIRECTION; 89768087Sgibbs mov DFCNTRL, DMAPARAMS; 89823925Sgibbs or SXFRCTL1,BITBUCKET; 89976634Sgibbs if ((ahc->features & AHC_DT) == 0) { 90076634Sgibbs test SSTAT1,PHASEMIS jz .; 90176634Sgibbs } else { 90276634Sgibbs test SCSIPHASE, DATA_PHASE_MASK jnz .; 90376634Sgibbs } 90468087Sgibbs and SXFRCTL1, ~BITBUCKET; 90568402Sgibbs mvi DATA_OVERRUN call set_seqint; 90668087Sgibbs jmp ITloop; 90768087Sgibbs 90816260Sgibbsdata_phase_inbounds: 90939220Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 91063457Sgibbs mov SINDEX, SCB_RESIDUAL_SGPTR[0]; 91163457Sgibbs test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2; 91263457Sgibbs or SINDEX, LAST_SEG; 91363457Sgibbs mov SG_CACHE_PRE, SINDEX; 91463457Sgibbs mov DFCNTRL, DMAPARAMS; 91563457Sgibbsultra2_dma_loop: 91663457Sgibbs call idle_loop; 91763457Sgibbs /* 91863457Sgibbs * The transfer is complete if either the last segment 91963457Sgibbs * completes or the target changes phase. 92063457Sgibbs */ 92163457Sgibbs test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish; 92276634Sgibbs if ((ahc->features & AHC_DT) == 0) { 92376634Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 92476634Sgibbs /* 92576634Sgibbs * As a target, we control the phases, 92676634Sgibbs * so ignore PHASEMIS. 92776634Sgibbs */ 92876634Sgibbs test SSTAT0, TARGET jnz ultra2_dma_loop; 92976634Sgibbs } 93076634Sgibbs if ((ahc->flags & AHC_INITIATORROLE) != 0) { 93176634Sgibbs test SSTAT1,PHASEMIS jz ultra2_dma_loop; 93276634Sgibbs } 93376634Sgibbs } else { 93476634Sgibbs test DFCNTRL, SCSIEN jnz ultra2_dma_loop; 93570204Sgibbs } 93663457Sgibbs 93763457Sgibbsultra2_dmafinish: 93876634Sgibbs /* 93976634Sgibbs * The transfer has terminated either due to a phase 94076634Sgibbs * change, and/or the completion of the last segment. 94176634Sgibbs * We have two goals here. Do as much other work 94276634Sgibbs * as possible while the data fifo drains on a read 94376634Sgibbs * and respond as quickly as possible to the standard 94476634Sgibbs * messages (save data pointers/disconnect and command 94576634Sgibbs * complete) that usually follow a data phase. 94676634Sgibbs */ 94763457Sgibbs if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) { 94863457Sgibbs /* 94976634Sgibbs * On chips with broken auto-flush, start 95076634Sgibbs * the flushing process now. We'll poke 95176634Sgibbs * the chip from time to time to keep the 95276634Sgibbs * flush process going as we complete the 95376634Sgibbs * data phase. 95463457Sgibbs */ 95563457Sgibbs or DFCNTRL, FIFOFLUSH; 95663457Sgibbs } 95763457Sgibbs /* 95876634Sgibbs * We assume that, even though data may still be 95976634Sgibbs * transferring to the host, that the SCSI side of 96076634Sgibbs * the DMA engine is now in a static state. This 96176634Sgibbs * allows us to update our notion of where we are 96276634Sgibbs * in this transfer. 96376634Sgibbs * 96463944Sgibbs * If, by chance, we stopped before being able 96563944Sgibbs * to fetch additional segments for this transfer, 96663944Sgibbs * yet the last S/G was completely exhausted, 96763944Sgibbs * call our idle loop until it is able to load 96863944Sgibbs * another segment. This will allow us to immediately 96963944Sgibbs * pickup on the next segment on the next data phase. 97063944Sgibbs * 97163944Sgibbs * If we happened to stop on the last segment, then 97263944Sgibbs * our residual information is still correct from 97363944Sgibbs * the idle loop and there is no need to perform 97476634Sgibbs * any fixups. 97563944Sgibbs */ 97663944Sgibbsultra2_ensure_sg: 97763944Sgibbs test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid; 97863944Sgibbs /* Record if we've consumed all S/G entries */ 97995378Sgibbs test SSTAT2, SHVALID jnz residuals_correct; 98063944Sgibbs or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL; 98176634Sgibbs jmp residuals_correct; 98263944Sgibbs 98363944Sgibbsultra2_shvalid: 98495378Sgibbs test SSTAT2, SHVALID jnz sgptr_fixup; 98563944Sgibbs call idle_loop; 98663944Sgibbs jmp ultra2_ensure_sg; 98763944Sgibbs 98863944Sgibbssgptr_fixup: 98963944Sgibbs /* 99063457Sgibbs * Fixup the residual next S/G pointer. The S/G preload 99163457Sgibbs * feature of the chip allows us to load two elements 99263457Sgibbs * in addition to the currently active element. We 99363457Sgibbs * store the bottom byte of the next S/G pointer in 99463457Sgibbs * the SG_CACEPTR register so we can restore the 99563457Sgibbs * correct value when the DMA completes. If the next 99663457Sgibbs * sg ptr value has advanced to the point where higher 99763457Sgibbs * bytes in the address have been affected, fix them 99863457Sgibbs * too. 99963457Sgibbs */ 100063457Sgibbs test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done; 100163457Sgibbs test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done; 100263457Sgibbs add SCB_RESIDUAL_SGPTR[1], -1; 100363457Sgibbs adc SCB_RESIDUAL_SGPTR[2], -1; 100463457Sgibbs adc SCB_RESIDUAL_SGPTR[3], -1; 100563457Sgibbssgptr_fixup_done: 100663457Sgibbs and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW; 1007115333Sgibbs /* We are not the last seg */ 1008115333Sgibbs and SCB_RESIDUAL_DATACNT[3], ~SG_LAST_SEG; 100976634Sgibbsresiduals_correct: 101076634Sgibbs /* 101176634Sgibbs * Go ahead and shut down the DMA engine now. 101276634Sgibbs * In the future, we'll want to handle end of 101376634Sgibbs * transfer messages prior to doing this, but this 101476634Sgibbs * requires similar restructuring for pre-ULTRA2 101576634Sgibbs * controllers. 101676634Sgibbs */ 101776634Sgibbs test DMAPARAMS, DIRECTION jnz ultra2_fifoempty; 101876634Sgibbsultra2_fifoflush: 101976634Sgibbs if ((ahc->features & AHC_DT) == 0) { 102076634Sgibbs if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) { 102176634Sgibbs /* 102276634Sgibbs * On Rev A of the aic7890, the autoflush 102376634Sgibbs * feature doesn't function correctly. 102476634Sgibbs * Perform an explicit manual flush. During 102576634Sgibbs * a manual flush, the FIFOEMP bit becomes 102676634Sgibbs * true every time the PCI FIFO empties 102776634Sgibbs * regardless of the state of the SCSI FIFO. 102876634Sgibbs * It can take up to 4 clock cycles for the 102976634Sgibbs * SCSI FIFO to get data into the PCI FIFO 103076634Sgibbs * and for FIFOEMP to de-assert. Here we 103176634Sgibbs * guard against this condition by making 103276634Sgibbs * sure the FIFOEMP bit stays on for 5 full 103376634Sgibbs * clock cycles. 103476634Sgibbs */ 103576634Sgibbs or DFCNTRL, FIFOFLUSH; 103676634Sgibbs test DFSTATUS, FIFOEMP jz ultra2_fifoflush; 103776634Sgibbs test DFSTATUS, FIFOEMP jz ultra2_fifoflush; 103876634Sgibbs test DFSTATUS, FIFOEMP jz ultra2_fifoflush; 103976634Sgibbs test DFSTATUS, FIFOEMP jz ultra2_fifoflush; 104076634Sgibbs } 104176634Sgibbs test DFSTATUS, FIFOEMP jz ultra2_fifoflush; 104276634Sgibbs } else { 104376634Sgibbs /* 104476634Sgibbs * We enable the auto-ack feature on DT capable 104576634Sgibbs * controllers. This means that the controller may 104676634Sgibbs * have already transferred some overrun bytes into 104776634Sgibbs * the data FIFO and acked them on the bus. The only 104876634Sgibbs * way to detect this situation is to wait for 104976634Sgibbs * LAST_SEG_DONE to come true on a completed transfer 105076634Sgibbs * and then test to see if the data FIFO is non-empty. 105176634Sgibbs */ 1052115334Sgibbs test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL 1053115334Sgibbs jz ultra2_wait_fifoemp; 105476634Sgibbs test SG_CACHE_SHADOW, LAST_SEG_DONE jz .; 1055115334Sgibbs /* 1056115334Sgibbs * FIFOEMP can lag LAST_SEG_DONE. Wait a few 1057115334Sgibbs * clocks before calling this an overrun. 1058115334Sgibbs */ 105976634Sgibbs test DFSTATUS, FIFOEMP jnz ultra2_fifoempty; 1060115334Sgibbs test DFSTATUS, FIFOEMP jnz ultra2_fifoempty; 1061115334Sgibbs test DFSTATUS, FIFOEMP jnz ultra2_fifoempty; 106276634Sgibbs /* Overrun */ 106376634Sgibbs jmp data_phase_loop; 1064115334Sgibbsultra2_wait_fifoemp: 106576634Sgibbs test DFSTATUS, FIFOEMP jz .; 106676634Sgibbs } 106776634Sgibbsultra2_fifoempty: 106876634Sgibbs /* Don't clobber an inprogress host data transfer */ 106976634Sgibbs test DFSTATUS, MREQPEND jnz ultra2_fifoempty; 107076634Sgibbsultra2_dmahalt: 107176634Sgibbs and DFCNTRL, ~(SCSIEN|HDMAEN); 107276634Sgibbs test DFCNTRL, SCSIEN|HDMAEN jnz .; 107379874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 107479874Sgibbs /* 107579874Sgibbs * Keep HHADDR cleared for future, 32bit addressed 107679874Sgibbs * only, DMA operations. 107779874Sgibbs * 107879874Sgibbs * Due to bayonette style S/G handling, our residual 107979874Sgibbs * data must be "fixed up" once the transfer is halted. 108079874Sgibbs * Here we fixup the HSHADDR stored in the high byte 108179874Sgibbs * of the residual data cnt. By postponing the fixup, 108279874Sgibbs * we can batch the clearing of HADDR with the fixup. 108379874Sgibbs * If we halted on the last segment, the residual is 108479874Sgibbs * already correct. If we are not on the last 108579874Sgibbs * segment, copy the high address directly from HSHADDR. 108679874Sgibbs * We don't need to worry about maintaining the 108779874Sgibbs * SG_LAST_SEG flag as it will always be false in the 108879874Sgibbs * case where an update is required. 108979874Sgibbs */ 109079874Sgibbs or DSCOMMAND1, HADDLDSEL0; 109179874Sgibbs test SG_CACHE_SHADOW, LAST_SEG jnz . + 2; 109279874Sgibbs mov SCB_RESIDUAL_DATACNT[3], SHADDR; 109379874Sgibbs clr HADDR; 109479874Sgibbs and DSCOMMAND1, ~HADDLDSEL0; 109579874Sgibbs } 109639220Sgibbs } else { 109763457Sgibbs /* If we are the last SG block, tell the hardware. */ 109865942Sgibbs if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 109965942Sgibbs && ahc->pci_cachesize != 0) { 110065942Sgibbs test MWI_RESIDUAL, 0xFF jnz dma_mid_sg; 110165942Sgibbs } 110263457Sgibbs test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; 110368087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 110463944Sgibbs test SSTAT0, TARGET jz dma_last_sg; 1105123579Sgibbs if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) { 110663944Sgibbs test DMAPARAMS, DIRECTION jz dma_mid_sg; 110763944Sgibbs } 110857099Sgibbs } 110963944Sgibbsdma_last_sg: 111039220Sgibbs and DMAPARAMS, ~WIDEODD; 111163457Sgibbsdma_mid_sg: 111263457Sgibbs /* Start DMA data transfer. */ 111339220Sgibbs mov DFCNTRL, DMAPARAMS; 111463457Sgibbsdma_loop: 111563457Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 111663457Sgibbs call idle_loop; 111763457Sgibbs } 111863457Sgibbs test SSTAT0,DMADONE jnz dma_dmadone; 111963457Sgibbs test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */ 112063457Sgibbsdma_phasemis: 112139220Sgibbs /* 112263457Sgibbs * We will be "done" DMAing when the transfer count goes to 112363457Sgibbs * zero, or the target changes the phase (in light of this, 112463457Sgibbs * it makes sense that the DMA circuitry doesn't ACK when 112563457Sgibbs * PHASEMIS is active). If we are doing a SCSI->Host transfer, 112663457Sgibbs * the data FIFO should be flushed auto-magically on STCNT=0 112763457Sgibbs * or a phase change, so just wait for FIFO empty status. 112839220Sgibbs */ 112963457Sgibbsdma_checkfifo: 113063457Sgibbs test DFCNTRL,DIRECTION jnz dma_fifoempty; 113163457Sgibbsdma_fifoflush: 113263457Sgibbs test DFSTATUS,FIFOEMP jz dma_fifoflush; 113363457Sgibbsdma_fifoempty: 113463457Sgibbs /* Don't clobber an inprogress host data transfer */ 113563457Sgibbs test DFSTATUS, MREQPEND jnz dma_fifoempty; 11364568Sgibbs 113739220Sgibbs /* 113863457Sgibbs * Now shut off the DMA and make sure that the DMA 113963457Sgibbs * hardware has actually stopped. Touching the DMA 114063457Sgibbs * counters, etc. while a DMA is active will result 114163457Sgibbs * in an ILLSADDR exception. 114239220Sgibbs */ 114363457Sgibbsdma_dmadone: 114463457Sgibbs and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN); 114563457Sgibbsdma_halt: 114663457Sgibbs /* 114765942Sgibbs * Some revisions of the aic78XX have a problem where, if the 114863457Sgibbs * data fifo is full, but the PCI input latch is not empty, 114963457Sgibbs * HDMAEN cannot be cleared. The fix used here is to drain 115063457Sgibbs * the prefetched but unused data from the data fifo until 115163457Sgibbs * there is space for the input latch to drain. 115263457Sgibbs */ 115365942Sgibbs if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) { 115465942Sgibbs mov NONE, DFDAT; 115565942Sgibbs } 115663457Sgibbs test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt; 115722568Sgibbs 115863457Sgibbs /* See if we have completed this last segment */ 115963457Sgibbs test STCNT[0], 0xff jnz data_phase_finish; 116063457Sgibbs test STCNT[1], 0xff jnz data_phase_finish; 116163457Sgibbs test STCNT[2], 0xff jnz data_phase_finish; 11629928Sgibbs 116339220Sgibbs /* 116463457Sgibbs * Advance the scatter-gather pointers if needed 116539220Sgibbs */ 116665942Sgibbs if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 116765942Sgibbs && ahc->pci_cachesize != 0) { 116865942Sgibbs test MWI_RESIDUAL, 0xFF jz no_mwi_resid; 116965942Sgibbs /* 117065942Sgibbs * Reload HADDR from SHADDR and setup the 117165942Sgibbs * count to be the size of our residual. 117265942Sgibbs */ 117365942Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 117465942Sgibbs bmov HADDR, SHADDR, 4; 117565942Sgibbs mov HCNT, MWI_RESIDUAL; 117665942Sgibbs bmov HCNT[1], ALLZEROS, 2; 117765942Sgibbs } else { 117865942Sgibbs mvi DINDEX, HADDR; 117965942Sgibbs mvi SHADDR call bcopy_4; 118065942Sgibbs mov MWI_RESIDUAL call set_hcnt; 118165942Sgibbs } 118265942Sgibbs clr MWI_RESIDUAL; 118365942Sgibbs jmp sg_load_done; 118465942Sgibbsno_mwi_resid: 118565942Sgibbs } 118663457Sgibbs test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz sg_load; 118763457Sgibbs or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL; 118863457Sgibbs jmp data_phase_finish; 118963457Sgibbssg_load: 119063457Sgibbs /* 119163457Sgibbs * Load the next SG element's data address and length 119263457Sgibbs * into the DMA engine. If we don't have hardware 119363457Sgibbs * to perform a prefetch, we'll have to fetch the 119463457Sgibbs * segment from host memory first. 119563457Sgibbs */ 119639220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 119763457Sgibbs /* Wait for the idle loop to complete */ 119863457Sgibbs test CCSGCTL, CCSGEN jz . + 3; 119963457Sgibbs call idle_loop; 120063457Sgibbs test CCSGCTL, CCSGEN jnz . - 1; 120163457Sgibbs bmov HADDR, CCSGRAM, 7; 120279874Sgibbs /* 120379874Sgibbs * Workaround for flaky external SCB RAM 120479874Sgibbs * on certain aic7895 setups. It seems 120579874Sgibbs * unable to handle direct transfers from 120679874Sgibbs * S/G ram to certain SCB locations. 120779874Sgibbs */ 120879874Sgibbs mov SINDEX, CCSGRAM; 120979874Sgibbs mov SCB_RESIDUAL_DATACNT[3], SINDEX; 121039220Sgibbs } else { 121179874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 121279874Sgibbs mov ALLZEROS call set_hhaddr; 121379874Sgibbs } 121463457Sgibbs mvi DINDEX, HADDR; 121563457Sgibbs mvi SCB_RESIDUAL_SGPTR call bcopy_4; 121663457Sgibbs 121763457Sgibbs mvi SG_SIZEOF call set_hcnt; 121863457Sgibbs 121963457Sgibbs or DFCNTRL, HDMAEN|DIRECTION|FIFORESET; 122063457Sgibbs 122163457Sgibbs call dma_finish; 122263457Sgibbs 122365942Sgibbs mvi DINDEX, HADDR; 122465942Sgibbs call dfdat_in_7; 122563457Sgibbs mov SCB_RESIDUAL_DATACNT[3], DFDAT; 122665942Sgibbs } 122765942Sgibbs 122879874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 122979874Sgibbs mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr; 123079874Sgibbs 123179874Sgibbs /* 123279874Sgibbs * The lowest address byte must be loaded 123379874Sgibbs * last as it triggers the computation of 123479874Sgibbs * some items in the PCI block. The ULTRA2 123579874Sgibbs * chips do this on PRELOAD. 123679874Sgibbs */ 123779874Sgibbs mov HADDR, HADDR; 123879874Sgibbs } 123965942Sgibbs if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 124065942Sgibbs && ahc->pci_cachesize != 0) { 124165942Sgibbs call calc_mwi_residual; 124265942Sgibbs } 124365942Sgibbs 124465942Sgibbs /* Point to the new next sg in memory */ 124565942Sgibbs call sg_advance; 124665942Sgibbs 124765942Sgibbssg_load_done: 124865942Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 124965942Sgibbs bmov STCNT, HCNT, 3; 125065942Sgibbs } else { 125139220Sgibbs call set_stcnt_from_hcnt; 125239220Sgibbs } 125339220Sgibbs 125468087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 125563457Sgibbs test SSTAT0, TARGET jnz data_phase_loop; 125663457Sgibbs } 125763457Sgibbs } 125863457Sgibbsdata_phase_finish: 125963457Sgibbs /* 126063457Sgibbs * If the target has left us in data phase, loop through 126163457Sgibbs * the dma code again. In the case of ULTRA2 adapters, 126263457Sgibbs * we should only loop if there is a data overrun. For 126363457Sgibbs * all other adapters, we'll loop after each S/G element 126463457Sgibbs * is loaded as well as if there is an overrun. 126563457Sgibbs */ 126668087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 126763457Sgibbs test SSTAT0, TARGET jnz data_phase_done; 126841646Sgibbs } 126968087Sgibbs if ((ahc->flags & AHC_INITIATORROLE) != 0) { 127063457Sgibbs test SSTAT1, REQINIT jz .; 127176634Sgibbs if ((ahc->features & AHC_DT) == 0) { 127276634Sgibbs test SSTAT1,PHASEMIS jz data_phase_loop; 127376634Sgibbs } else { 127476634Sgibbs test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop; 127576634Sgibbs } 127639220Sgibbs } 12774568Sgibbs 127863457Sgibbsdata_phase_done: 127963457Sgibbs /* 128063457Sgibbs * After a DMA finishes, save the SG and STCNT residuals back into 128163457Sgibbs * the SCB. We use STCNT instead of HCNT, since it's a reflection 128263457Sgibbs * of how many bytes were transferred on the SCSI (as opposed to the 128363457Sgibbs * host) bus. 128463457Sgibbs */ 128539220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 128663457Sgibbs /* Kill off any pending prefetch */ 128774094Sgibbs call disable_ccsgen; 128865942Sgibbs } 128963457Sgibbs 129079874Sgibbs if ((ahc->features & AHC_ULTRA2) == 0) { 129179874Sgibbs /* 129279874Sgibbs * Clear the high address byte so that all other DMA 129379874Sgibbs * operations, which use 32bit addressing, can assume 129479874Sgibbs * HHADDR is 0. 129579874Sgibbs */ 129679874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 129779874Sgibbs mov ALLZEROS call set_hhaddr; 129879874Sgibbs } 129979874Sgibbs } 130079874Sgibbs 130179874Sgibbs /* 130279874Sgibbs * Update our residual information before the information is 130379874Sgibbs * lost by some other type of SCSI I/O (e.g. PIO). If we have 130479874Sgibbs * transferred all data, no update is needed. 130579874Sgibbs * 130679874Sgibbs */ 130779874Sgibbs test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done; 130865942Sgibbs if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 130965942Sgibbs && ahc->pci_cachesize != 0) { 131065942Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 131165942Sgibbs test MWI_RESIDUAL, 0xFF jz bmov_resid; 131265942Sgibbs } 131365942Sgibbs mov A, MWI_RESIDUAL; 131465942Sgibbs add SCB_RESIDUAL_DATACNT[0], A, STCNT[0]; 131565942Sgibbs clr A; 131665942Sgibbs adc SCB_RESIDUAL_DATACNT[1], A, STCNT[1]; 131765942Sgibbs adc SCB_RESIDUAL_DATACNT[2], A, STCNT[2]; 131865942Sgibbs clr MWI_RESIDUAL; 131965942Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 132065942Sgibbs jmp . + 2; 132165942Sgibbsbmov_resid: 132265942Sgibbs bmov SCB_RESIDUAL_DATACNT, STCNT, 3; 132365942Sgibbs } 132465942Sgibbs } else if ((ahc->features & AHC_CMD_CHAN) != 0) { 132563457Sgibbs bmov SCB_RESIDUAL_DATACNT, STCNT, 3; 132639220Sgibbs } else { 132765942Sgibbs mov SCB_RESIDUAL_DATACNT[0], STCNT[0]; 132865942Sgibbs mov SCB_RESIDUAL_DATACNT[1], STCNT[1]; 132965942Sgibbs mov SCB_RESIDUAL_DATACNT[2], STCNT[2]; 133039220Sgibbs } 133179874Sgibbsresidual_update_done: 133263457Sgibbs /* 133363457Sgibbs * Since we've been through a data phase, the SCB_RESID* fields 133463457Sgibbs * are now initialized. Clear the full residual flag. 133563457Sgibbs */ 133663457Sgibbs and SCB_SGPTR[0], ~SG_FULL_RESID; 133763457Sgibbs 133839220Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 133963457Sgibbs /* Clear the channel in case we return to data phase later */ 134039220Sgibbs or SXFRCTL0, CLRSTCNT|CLRCHN; 134168402Sgibbs or SXFRCTL0, CLRSTCNT|CLRCHN; 134239220Sgibbs } 134322568Sgibbs 134468087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 134541646Sgibbs test SEQ_FLAGS, DPHASE_PENDING jz ITloop; 134639220Sgibbs and SEQ_FLAGS, ~DPHASE_PENDING; 134742652Sgibbs /* 134842652Sgibbs * For data-in phases, wait for any pending acks from the 134995378Sgibbs * initiator before changing phase. We only need to 135095378Sgibbs * send Ignore Wide Residue messages for data-in phases. 135142652Sgibbs */ 135242652Sgibbs test DFCNTRL, DIRECTION jz target_ITloop; 135342652Sgibbs test SSTAT1, REQINIT jnz .; 1354115333Sgibbs test SCB_LUN, SCB_XFERLEN_ODD jz target_ITloop; 135595378Sgibbs test SCSIRATE, WIDEXFER jz target_ITloop; 135695378Sgibbs /* 135795378Sgibbs * Issue an Ignore Wide Residue Message. 135895378Sgibbs */ 135995378Sgibbs mvi P_MESGIN|BSYO call change_phase; 136095378Sgibbs mvi MSG_IGN_WIDE_RESIDUE call target_outb; 136195378Sgibbs mvi 1 call target_outb; 136239220Sgibbs jmp target_ITloop; 136363457Sgibbs } else { 136463457Sgibbs jmp ITloop; 136539220Sgibbs } 13664568Sgibbs 136768087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) { 136816260Sgibbs/* 136915328Sgibbs * Command phase. Set up the DMA registers and let 'er rip. 137013177Sgibbs */ 13714568Sgibbsp_command: 1372107420Sscottl test SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay; 1373107420Sscottl mvi PROTO_VIOLATION call set_seqint; 137479874Sgibbsp_command_okay: 13754568Sgibbs 137663457Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 137763457Sgibbs bmov HCNT[0], SCB_CDB_LEN, 1; 137839220Sgibbs bmov HCNT[1], ALLZEROS, 2; 137963944Sgibbs mvi SG_CACHE_PRE, LAST_SEG; 138063457Sgibbs } else if ((ahc->features & AHC_CMD_CHAN) != 0) { 138163457Sgibbs bmov STCNT[0], SCB_CDB_LEN, 1; 138263457Sgibbs bmov STCNT[1], ALLZEROS, 2; 138339220Sgibbs } else { 138463457Sgibbs mov STCNT[0], SCB_CDB_LEN; 138563457Sgibbs clr STCNT[1]; 138663457Sgibbs clr STCNT[2]; 138739220Sgibbs } 138863457Sgibbs add NONE, -13, SCB_CDB_LEN; 138965942Sgibbs mvi SCB_CDB_STORE jnc p_command_embedded; 139063457Sgibbsp_command_from_host: 139163457Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 139263457Sgibbs bmov HADDR[0], SCB_CDB_PTR, 4; 139363457Sgibbs mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION); 139463457Sgibbs } else { 139563457Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 139663457Sgibbs bmov HADDR[0], SCB_CDB_PTR, 4; 139765942Sgibbs bmov HCNT, STCNT, 3; 139863457Sgibbs } else { 139963457Sgibbs mvi DINDEX, HADDR; 140068087Sgibbs mvi SCB_CDB_PTR call bcopy_4; 140168087Sgibbs mov SCB_CDB_LEN call set_hcnt; 140239220Sgibbs } 140339220Sgibbs mvi DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET); 140463457Sgibbs } 1405107420Sscottl jmp p_command_xfer; 140663457Sgibbsp_command_embedded: 140763457Sgibbs /* 140876634Sgibbs * The data fifo seems to require 4 byte aligned 140963457Sgibbs * transfers from the sequencer. Force this to 141063457Sgibbs * be the case by clearing HADDR[0] even though 141195378Sgibbs * we aren't going to touch host memory. 141263457Sgibbs */ 141363457Sgibbs clr HADDR[0]; 141463457Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 141563457Sgibbs mvi DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION); 141663457Sgibbs bmov DFDAT, SCB_CDB_STORE, 12; 141765942Sgibbs } else if ((ahc->features & AHC_CMD_CHAN) != 0) { 141871390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 141965942Sgibbs /* 142065942Sgibbs * On the 7895 the data FIFO will 142165942Sgibbs * get corrupted if you try to dump 142265942Sgibbs * data from external SCB memory into 142365942Sgibbs * the FIFO while it is enabled. So, 142465942Sgibbs * fill the fifo and then enable SCSI 142565942Sgibbs * transfers. 142665942Sgibbs */ 142765942Sgibbs mvi DFCNTRL, (DIRECTION|FIFORESET); 142865942Sgibbs } else { 142965942Sgibbs mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET); 143065942Sgibbs } 143165942Sgibbs bmov DFDAT, SCB_CDB_STORE, 12; 143271390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 143365942Sgibbs mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFOFLUSH); 143465942Sgibbs } else { 143563821Sgibbs or DFCNTRL, FIFOFLUSH; 143663821Sgibbs } 143763457Sgibbs } else { 143865942Sgibbs mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET); 143963821Sgibbs call copy_to_fifo_6; 144063821Sgibbs call copy_to_fifo_6; 144163821Sgibbs or DFCNTRL, FIFOFLUSH; 144263457Sgibbs } 1443107420Sscottlp_command_xfer: 1444107420Sscottl and SEQ_FLAGS, ~NO_CDB_SENT; 144576634Sgibbs if ((ahc->features & AHC_DT) == 0) { 144676634Sgibbs test SSTAT0, SDONE jnz . + 2; 1447107420Sscottl test SSTAT1, PHASEMIS jz . - 1; 144876634Sgibbs /* 144976634Sgibbs * Wait for our ACK to go-away on it's own 145076634Sgibbs * instead of being killed by SCSIEN getting cleared. 145176634Sgibbs */ 145276634Sgibbs test SCSISIGI, ACKI jnz .; 145376634Sgibbs } else { 1454107420Sscottl test DFCNTRL, SCSIEN jnz .; 145576634Sgibbs } 1456107420Sscottl test SSTAT0, SDONE jnz p_command_successful; 1457107420Sscottl /* 1458107420Sscottl * Don't allow a data phase if the command 1459107420Sscottl * was not fully transferred. 1460107420Sscottl */ 1461107420Sscottl or SEQ_FLAGS, NO_CDB_SENT; 1462107420Sscottlp_command_successful: 146355581Sgibbs and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN); 146439220Sgibbs test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .; 146523925Sgibbs jmp ITloop; 14664568Sgibbs 146713177Sgibbs/* 146813177Sgibbs * Status phase. Wait for the data byte to appear, then read it 146913177Sgibbs * and store it into the SCB. 147013177Sgibbs */ 14714568Sgibbsp_status: 1472107420Sscottl test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation; 147379874Sgibbsp_status_okay: 147463457Sgibbs mov SCB_SCSI_STATUS, SCSIDATL; 1475107420Sscottl or SCB_CONTROL, STATUS_RCVD; 147623925Sgibbs jmp ITloop; 14774568Sgibbs 147813177Sgibbs/* 147941646Sgibbs * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full 148041646Sgibbs * indentify message sequence and send it to the target. The host may 148141646Sgibbs * override this behavior by setting the MK_MESSAGE bit in the SCB 148241646Sgibbs * control byte. This will cause us to interrupt the host and allow 148341646Sgibbs * it to handle the message phase completely on its own. If the bit 148441646Sgibbs * associated with this target is set, we will also interrupt the host, 148541646Sgibbs * thereby allowing it to send a message on the next selection regardless 148641646Sgibbs * of the transaction being sent. 148739220Sgibbs * 148839220Sgibbs * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. 148941646Sgibbs * This is done to allow the host to send messages outside of an identify 149039220Sgibbs * sequence while protecting the seqencer from testing the MK_MESSAGE bit 149139220Sgibbs * on an SCB that might not be for the current nexus. (For example, a 149239220Sgibbs * BDR message in responce to a bad reselection would leave us pointed to 149339220Sgibbs * an SCB that doesn't have anything to do with the current target). 149441646Sgibbs * 149539220Sgibbs * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, 149639220Sgibbs * bus device reset). 149739220Sgibbs * 149839220Sgibbs * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, 149939220Sgibbs * in case the target decides to put us in this phase for some strange 150039220Sgibbs * reason. 150113177Sgibbs */ 150241646Sgibbsp_mesgout_retry: 150376634Sgibbs /* Turn on ATN for the retry */ 150476634Sgibbs if ((ahc->features & AHC_DT) == 0) { 150576634Sgibbs or SCSISIGO, ATNO, LASTPHASE; 150676634Sgibbs } else { 150776634Sgibbs mvi SCSISIGO, ATNO; 150876634Sgibbs } 15094568Sgibbsp_mesgout: 151039220Sgibbs mov SINDEX, MSG_OUT; 151139220Sgibbs cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; 151241646Sgibbs test SCB_CONTROL,MK_MESSAGE jnz host_message_loop; 151339220Sgibbsp_mesgout_identify: 1514115333Sgibbs or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SAVED_LUN; 151563457Sgibbs test SCB_CONTROL, DISCENB jnz . + 2; 151663457Sgibbs and SINDEX, ~DISCENB; 151713177Sgibbs/* 151839220Sgibbs * Send a tag message if TAG_ENB is set in the SCB control block. 151939220Sgibbs * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. 152013177Sgibbs */ 152139220Sgibbsp_mesgout_tag: 152239220Sgibbs test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte; 152339220Sgibbs mov SCSIDATL, SINDEX; /* Send the identify message */ 152439220Sgibbs call phase_lock; 152539220Sgibbs cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; 152639220Sgibbs and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL; 152739220Sgibbs call phase_lock; 152839220Sgibbs cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; 152939220Sgibbs mov SCB_TAG jmp p_mesgout_onebyte; 153013177Sgibbs/* 153141646Sgibbs * Interrupt the driver, and allow it to handle this message 153241646Sgibbs * phase and any required retries. 153313177Sgibbs */ 153439220Sgibbsp_mesgout_from_host: 153539220Sgibbs cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; 153641646Sgibbs jmp host_message_loop; 153739220Sgibbs 153839220Sgibbsp_mesgout_onebyte: 153939220Sgibbs mvi CLRSINT1, CLRATNO; 154039220Sgibbs mov SCSIDATL, SINDEX; 154139220Sgibbs 154213177Sgibbs/* 154341646Sgibbs * If the next bus phase after ATN drops is message out, it means 154413177Sgibbs * that the target is requesting that the last message(s) be resent. 154513177Sgibbs */ 154639220Sgibbs call phase_lock; 154741646Sgibbs cmp LASTPHASE, P_MESGOUT je p_mesgout_retry; 15484568Sgibbs 154919906Sgibbsp_mesgout_done: 155023925Sgibbs mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ 155139220Sgibbs mov LAST_MSG, MSG_OUT; 155239220Sgibbs mvi MSG_OUT, MSG_NOOP; /* No message left */ 155323925Sgibbs jmp ITloop; 15544568Sgibbs 155513177Sgibbs/* 155613177Sgibbs * Message in phase. Bytes are read using Automatic PIO mode. 155713177Sgibbs */ 15584568Sgibbsp_mesgin: 155923925Sgibbs mvi ACCUM call inb_first; /* read the 1st message byte */ 15604568Sgibbs 156123925Sgibbs test A,MSG_IDENTIFYFLAG jnz mesgin_identify; 156223925Sgibbs cmp A,MSG_DISCONNECT je mesgin_disconnect; 156323925Sgibbs cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; 156423925Sgibbs cmp ALLZEROS,A je mesgin_complete; 156523925Sgibbs cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; 156663457Sgibbs cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue; 156723925Sgibbs cmp A,MSG_NOOP je mesgin_done; 15684568Sgibbs 156913177Sgibbs/* 157041887Sgibbs * Pushed message loop to allow the kernel to 157157099Sgibbs * run it's own message state engine. To avoid an 157241887Sgibbs * extra nop instruction after signaling the kernel, 157341887Sgibbs * we perform the phase_lock before checking to see 157441887Sgibbs * if we should exit the loop and skip the phase_lock 157541887Sgibbs * in the ITloop. Performing back to back phase_locks 157641887Sgibbs * shouldn't hurt, but why do it twice... 157713177Sgibbs */ 157841887Sgibbshost_message_loop: 157968402Sgibbs mvi HOST_MSG_LOOP call set_seqint; 158041887Sgibbs call phase_lock; 158141887Sgibbs cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1; 158241887Sgibbs jmp host_message_loop; 15839954Sgibbs 158463457Sgibbsmesgin_ign_wide_residue: 158563457Sgibbsif ((ahc->features & AHC_WIDE) != 0) { 158663457Sgibbs test SCSIRATE, WIDEXFER jz mesgin_reject; 158763457Sgibbs /* Pull the residue byte */ 158863457Sgibbs mvi ARG_1 call inb_next; 158963457Sgibbs cmp ARG_1, 0x01 jne mesgin_reject; 159063457Sgibbs test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2; 1591115333Sgibbs test SCB_LUN, SCB_XFERLEN_ODD jnz mesgin_done; 159268402Sgibbs mvi IGN_WIDE_RES call set_seqint; 159363457Sgibbs jmp mesgin_done; 159463457Sgibbs} 159563457Sgibbs 1596107420Sscottlmesgin_proto_violation: 1597107420Sscottl mvi PROTO_VIOLATION call set_seqint; 1598107420Sscottl jmp mesgin_done; 159963457Sgibbsmesgin_reject: 160063457Sgibbs mvi MSG_MESSAGE_REJECT call mk_mesg; 16019954Sgibbsmesgin_done: 160223925Sgibbs mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ 160323925Sgibbs jmp ITloop; 16049954Sgibbs 160513177Sgibbs/* 160663457Sgibbs * We received a "command complete" message. Put the SCB_TAG into the QOUTFIFO, 160719164Sgibbs * and trigger a completion interrupt. Before doing so, check to see if there 160839220Sgibbs * is a residual or the status byte is something other than STATUS_GOOD (0). 160939220Sgibbs * In either of these conditions, we upload the SCB back to the host so it can 161019164Sgibbs * process this information. In the case of a non zero status byte, we 161119164Sgibbs * additionally interrupt the kernel driver synchronously, allowing it to 161219164Sgibbs * decide if sense should be retrieved. If the kernel driver wishes to request 161368087Sgibbs * sense, it will fill the kernel SCB with a request sense command, requeue 161468087Sgibbs * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting 161568087Sgibbs * RETURN_1 to SEND_SENSE. 161613177Sgibbs */ 1617107420Sscottlmesgin_complete: 161819164Sgibbs 1619107420Sscottl /* 1620107420Sscottl * If ATN is raised, we still want to give the target a message. 1621107420Sscottl * Perhaps there was a parity error on this last message byte. 1622107420Sscottl * Either way, the target should take us to message out phase 1623107420Sscottl * and then attempt to complete the command again. We should use a 1624107420Sscottl * critical section here to guard against a timeout triggering 1625107420Sscottl * for this command and setting ATN while we are still processing 1626107420Sscottl * the completion. 162768579Sgibbs test SCSISIGI, ATNI jnz mesgin_done; 1628107420Sscottl */ 162968579Sgibbs 1630107420Sscottl /* 1631107420Sscottl * If we are identified and have successfully sent the CDB, 1632107420Sscottl * any status will do. Optimize this fast path. 1633107420Sscottl */ 1634107420Sscottl test SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation; 1635107420Sscottl test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted; 1636107420Sscottl 1637107420Sscottl /* 1638107420Sscottl * If the target never sent an identify message but instead went 1639107420Sscottl * to mesgin to give an invalid message, let the host abort us. 1640107420Sscottl */ 1641107420Sscottl test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation; 1642107420Sscottl 1643107420Sscottl /* 1644107420Sscottl * If we recevied good status but never successfully sent the 1645107420Sscottl * cdb, abort the command. 1646107420Sscottl */ 1647107420Sscottl test SCB_SCSI_STATUS,0xff jnz complete_accepted; 1648107420Sscottl test SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation; 1649107420Sscottl 1650107420Sscottlcomplete_accepted: 1651107420Sscottl /* 1652107420Sscottl * See if we attempted to deliver a message but the target ingnored us. 1653107420Sscottl */ 165468402Sgibbs test SCB_CONTROL, MK_MESSAGE jz . + 2; 165568402Sgibbs mvi MKMSG_FAILED call set_seqint; 165668402Sgibbs 1657107420Sscottl /* 1658107420Sscottl * Check for residuals 1659107420Sscottl */ 166063457Sgibbs test SCB_SGPTR, SG_LIST_NULL jnz check_status;/* No xfer */ 166163457Sgibbs test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ 166263457Sgibbs test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; 166363457Sgibbscheck_status: 166463457Sgibbs test SCB_SCSI_STATUS,0xff jz complete; /* Good Status? */ 166519164Sgibbsupload_scb: 166663457Sgibbs or SCB_SGPTR, SG_RESID_VALID; 166723925Sgibbs mvi DMAPARAMS, FIFORESET; 166823925Sgibbs mov SCB_TAG call dma_scb; 166963457Sgibbs test SCB_SCSI_STATUS, 0xff jz complete; /* Just a residual? */ 167068402Sgibbs mvi BAD_STATUS call set_seqint; /* let driver know */ 167139220Sgibbs cmp RETURN_1, SEND_SENSE jne complete; 167268087Sgibbs call add_scb_to_free_list; 167323925Sgibbs jmp await_busfree; 167439220Sgibbscomplete: 167539220Sgibbs mov SCB_TAG call complete_post; 167623925Sgibbs jmp await_busfree; 167741646Sgibbs} 16784568Sgibbs 167939220Sgibbscomplete_post: 168039220Sgibbs /* Post the SCBID in SINDEX and issue an interrupt */ 168144507Sgibbs call add_scb_to_free_list; 168239220Sgibbs mov ARG_1, SINDEX; 168339220Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 168439220Sgibbs mov A, SDSCB_QOFF; 168539220Sgibbs } else { 168639220Sgibbs mov A, QOUTPOS; 168739220Sgibbs } 168839220Sgibbs mvi QOUTFIFO_OFFSET call post_byte_setup; 168939220Sgibbs mov ARG_1 call post_byte; 169039220Sgibbs if ((ahc->features & AHC_QUEUE_REGS) == 0) { 169139220Sgibbs inc QOUTPOS; 169239220Sgibbs } 169339220Sgibbs mvi INTSTAT,CMDCMPLT ret; 169439220Sgibbs 169568087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) { 169613177Sgibbs/* 169713177Sgibbs * Is it a disconnect message? Set a flag in the SCB to remind us 169863457Sgibbs * and await the bus going free. If this is an untagged transaction 169963457Sgibbs * store the SCB id for it in our untagged target table for lookup on 170063457Sgibbs * a reselction. 170113177Sgibbs */ 17029954Sgibbsmesgin_disconnect: 170368579Sgibbs /* 170468579Sgibbs * If ATN is raised, we still want to give the target a message. 170568579Sgibbs * Perhaps there was a parity error on this last message byte 170668579Sgibbs * or we want to abort this command. Either way, the target 170768579Sgibbs * should take us to message out phase and then attempt to 170868579Sgibbs * disconnect again. 170968579Sgibbs * XXX - Wait for more testing. 171068579Sgibbs test SCSISIGI, ATNI jnz mesgin_done; 171168579Sgibbs */ 1712107420Sscottl test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT 1713107420Sscottl jnz mesgin_proto_violation; 171423925Sgibbs or SCB_CONTROL,DISCONNECTED; 171563457Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 171663457Sgibbs call add_scb_to_disc_list; 171763457Sgibbs } 171863457Sgibbs test SCB_CONTROL, TAG_ENB jnz await_busfree; 171963457Sgibbs mov ARG_1, SCB_TAG; 1720115333Sgibbs and SAVED_LUN, LID, SCB_LUN; 172168087Sgibbs mov SCB_SCSIID call set_busy_target; 172223925Sgibbs jmp await_busfree; 172319164Sgibbs 172415328Sgibbs/* 172519164Sgibbs * Save data pointers message: 172619164Sgibbs * Copying RAM values back to SCB, for Save Data Pointers message, but 172719164Sgibbs * only if we've actually been into a data phase to change them. This 172819164Sgibbs * protects against bogus data in scratch ram and the residual counts 172919164Sgibbs * since they are only initialized when we go into data_in or data_out. 173076634Sgibbs * Ack the message as soon as possible. For chips without S/G pipelining, 173176634Sgibbs * we can only ack the message after SHADDR has been saved. On these 173276634Sgibbs * chips, SHADDR increments with every bus transaction, even PIO. 173315328Sgibbs */ 173419164Sgibbsmesgin_sdptrs: 173576634Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 173676634Sgibbs mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ 173776634Sgibbs test SEQ_FLAGS, DPHASE jz ITloop; 173876634Sgibbs } else { 173976634Sgibbs test SEQ_FLAGS, DPHASE jz mesgin_done; 174076634Sgibbs } 174179874Sgibbs 174239220Sgibbs /* 174379874Sgibbs * If we are asked to save our position at the end of the 174479874Sgibbs * transfer, just mark us at the end rather than perform a 174579874Sgibbs * full save. 174679874Sgibbs */ 174779874Sgibbs test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full; 174879874Sgibbs or SCB_SGPTR, SG_LIST_NULL; 174981170Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 175081170Sgibbs jmp ITloop; 175181170Sgibbs } else { 175281170Sgibbs jmp mesgin_done; 175381170Sgibbs } 175479874Sgibbs 175579874Sgibbsmesgin_sdptrs_full: 175679874Sgibbs 175779874Sgibbs /* 175863457Sgibbs * The SCB_SGPTR becomes the next one we'll download, 175963457Sgibbs * and the SCB_DATAPTR becomes the current SHADDR. 176039220Sgibbs * Use the residual number since STCNT is corrupted by 176139220Sgibbs * any message transfer. 176239220Sgibbs */ 176339220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 176439220Sgibbs bmov SCB_DATAPTR, SHADDR, 4; 176576634Sgibbs if ((ahc->features & AHC_ULTRA2) == 0) { 176676634Sgibbs mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ 176776634Sgibbs } 176863457Sgibbs bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8; 176939220Sgibbs } else { 177039220Sgibbs mvi DINDEX, SCB_DATAPTR; 177163457Sgibbs mvi SHADDR call bcopy_4; 177276634Sgibbs mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ 177363457Sgibbs mvi SCB_RESIDUAL_DATACNT call bcopy_8; 177439220Sgibbs } 177576634Sgibbs jmp ITloop; 17764568Sgibbs 177713177Sgibbs/* 177813177Sgibbs * Restore pointers message? Data pointers are recopied from the 177913177Sgibbs * SCB anytime we enter a data phase for the first time, so all 178013177Sgibbs * we need to do is clear the DPHASE flag and let the data phase 1781107420Sscottl * code do the rest. We also reset/reallocate the FIFO to make 1782107420Sscottl * sure we have a clean start for the next data or command phase. 178313177Sgibbs */ 17849954Sgibbsmesgin_rdptrs: 178523925Sgibbs and SEQ_FLAGS, ~DPHASE; /* 178623925Sgibbs * We'll reload them 178713177Sgibbs * the next time through 178823925Sgibbs * the dataphase. 178913177Sgibbs */ 1790107420Sscottl or SXFRCTL0, CLRSTCNT|CLRCHN; 179123925Sgibbs jmp mesgin_done; 17924568Sgibbs 179313177Sgibbs/* 179463457Sgibbs * Index into our Busy Target table. SINDEX and DINDEX are modified 179563457Sgibbs * upon return. SCBPTR may be modified by this action. 179663457Sgibbs */ 179768087Sgibbsset_busy_target: 179868087Sgibbs shr DINDEX, 4, SINDEX; 179971390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 180063457Sgibbs mov SCBPTR, SAVED_LUN; 180168087Sgibbs add DINDEX, SCB_64_BTT; 180263457Sgibbs } else { 180368087Sgibbs add DINDEX, BUSY_TARGETS; 180463457Sgibbs } 180568087Sgibbs mov DINDIR, ARG_1 ret; 180663457Sgibbs 180763457Sgibbs/* 180813177Sgibbs * Identify message? For a reconnecting target, this tells us the lun 180913177Sgibbs * that the reconnection is for - find the correct SCB and switch to it, 181013177Sgibbs * clearing the "disconnected" bit so we don't "find" it by accident later. 181113177Sgibbs */ 18129954Sgibbsmesgin_identify: 181363457Sgibbs /* 181463457Sgibbs * Determine whether a target is using tagged or non-tagged 181563457Sgibbs * transactions by first looking at the transaction stored in 181663457Sgibbs * the busy target array. If there is no untagged transaction 181763457Sgibbs * for this target or the transaction is for a different lun, then 1818102673Sgibbs * this must be a tagged transaction. 181963457Sgibbs */ 182072325Sgibbs shr SINDEX, 4, SAVED_SCSIID; 182171390Sgibbs and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A; 182271390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 182371390Sgibbs add SINDEX, SCB_64_BTT; 182468087Sgibbs mov SCBPTR, SAVED_LUN; 182571390Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 182671390Sgibbs add NONE, -SCB_64_BTT, SINDEX; 182771390Sgibbs jc . + 2; 182871390Sgibbs mvi INTSTAT, OUT_OF_RANGE; 182971390Sgibbs nop; 183071390Sgibbs add NONE, -(SCB_64_BTT + 16), SINDEX; 183171390Sgibbs jnc . + 2; 183271390Sgibbs mvi INTSTAT, OUT_OF_RANGE; 183371390Sgibbs nop; 183471390Sgibbs } 183568087Sgibbs } else { 183671390Sgibbs add SINDEX, BUSY_TARGETS; 183768087Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 183871390Sgibbs add NONE, -BUSY_TARGETS, SINDEX; 183968087Sgibbs jc . + 2; 184068087Sgibbs mvi INTSTAT, OUT_OF_RANGE; 184168402Sgibbs nop; 184271390Sgibbs add NONE, -(BUSY_TARGETS + 16), SINDEX; 184368087Sgibbs jnc . + 2; 184468087Sgibbs mvi INTSTAT, OUT_OF_RANGE; 184568402Sgibbs nop; 184668087Sgibbs } 184768087Sgibbs } 184868087Sgibbs mov ARG_1, SINDIR; 184968087Sgibbs cmp ARG_1, SCB_LIST_NULL je snoop_tag; 185063457Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 185168579Sgibbs mov ARG_1 call findSCB; 185239220Sgibbs } else { 185374094Sgibbs mov SCBPTR, ARG_1; 185439220Sgibbs } 185571390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 185663457Sgibbs jmp setup_SCB_id_lun_okay; 185763457Sgibbs } else { 185874094Sgibbs /* 185974094Sgibbs * We only allow one untagged command per-target 186074094Sgibbs * at a time. So, if the lun doesn't match, look 186174094Sgibbs * for a tag message. 186274094Sgibbs */ 1863115333Sgibbs and A, LID, SCB_LUN; 186474094Sgibbs cmp SAVED_LUN, A je setup_SCB_id_lun_okay; 186574094Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 186674094Sgibbs /* 186774094Sgibbs * findSCB removes the SCB from the 186874094Sgibbs * disconnected list, so we must replace 186974094Sgibbs * it there should this SCB be for another 187074094Sgibbs * lun. 187174094Sgibbs */ 187274094Sgibbs call cleanup_scb; 187374094Sgibbs } 187463457Sgibbs } 187539220Sgibbs 187613177Sgibbs/* 187713177Sgibbs * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. 187823168Sgibbs * If we get one, we use the tag returned to find the proper 187963457Sgibbs * SCB. With SCB paging, we must search for non-tagged 188063457Sgibbs * transactions since the SCB may exist in any slot. If we're not 188163457Sgibbs * using SCB paging, we can use the tag as the direct index to the 188263457Sgibbs * SCB. 188313177Sgibbs */ 188424608Sgibbssnoop_tag: 188571390Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 188671390Sgibbs or SEQ_FLAGS, 0x80; 188771390Sgibbs } 188823925Sgibbs mov NONE,SCSIDATL; /* ACK Identify MSG */ 188939220Sgibbs call phase_lock; 189068087Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 189168087Sgibbs or SEQ_FLAGS, 0x1; 189268087Sgibbs } 189323925Sgibbs cmp LASTPHASE, P_MESGIN jne not_found; 189468087Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 189568087Sgibbs or SEQ_FLAGS, 0x2; 189668087Sgibbs } 189723925Sgibbs cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found; 18986608Sgibbsget_tag: 189963457Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 190063457Sgibbs mvi ARG_1 call inb_next; /* tag value */ 190163457Sgibbs mov ARG_1 call findSCB; 190263457Sgibbs } else { 190368087Sgibbs mvi ARG_1 call inb_next; /* tag value */ 190468087Sgibbs mov SCBPTR, ARG_1; 190563457Sgibbs } 190613177Sgibbs 190763457Sgibbs/* 190863457Sgibbs * Ensure that the SCB the tag points to is for 190963457Sgibbs * an SCB transaction to the reconnecting target. 191063457Sgibbs */ 191139220Sgibbssetup_SCB: 191268087Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 191368087Sgibbs or SEQ_FLAGS, 0x4; 191468087Sgibbs } 191571390Sgibbs mov A, SCB_SCSIID; 191671390Sgibbs cmp SAVED_SCSIID, A jne not_found_cleanup_scb; 191768087Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 191868087Sgibbs or SEQ_FLAGS, 0x8; 191968087Sgibbs } 192071390Sgibbssetup_SCB_id_okay: 1921115333Sgibbs and A, LID, SCB_LUN; 192271390Sgibbs cmp SAVED_LUN, A jne not_found_cleanup_scb; 192363457Sgibbssetup_SCB_id_lun_okay: 192468087Sgibbs if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) { 192568087Sgibbs or SEQ_FLAGS, 0x10; 192663457Sgibbs } 192768087Sgibbs test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb; 192823925Sgibbs and SCB_CONTROL,~DISCONNECTED; 192963457Sgibbs test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged; 193074094Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 193174094Sgibbs mov A, SCBPTR; 193274094Sgibbs } 193368087Sgibbs mvi ARG_1, SCB_LIST_NULL; 193468087Sgibbs mov SAVED_SCSIID call set_busy_target; 193574094Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 193674094Sgibbs mov SCBPTR, A; 193774094Sgibbs } 193863457Sgibbssetup_SCB_tagged: 1939107420Sscottl clr SEQ_FLAGS; /* make note of IDENTIFY */ 194039220Sgibbs call set_transfer_settings; 194139220Sgibbs /* See if the host wants to send a message upon reconnection */ 194239220Sgibbs test SCB_CONTROL, MK_MESSAGE jz mesgin_done; 194339220Sgibbs mvi HOST_MSG call mk_mesg; 194423925Sgibbs jmp mesgin_done; 194515328Sgibbs 194668087Sgibbsnot_found_cleanup_scb: 194768087Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 194874094Sgibbs call cleanup_scb; 194968087Sgibbs } 195019218Sgibbsnot_found: 195168402Sgibbs mvi NO_MATCH call set_seqint; 195223925Sgibbs jmp mesgin_done; 19536608Sgibbs 19544568Sgibbsmk_mesg: 195576634Sgibbs if ((ahc->features & AHC_DT) == 0) { 195676634Sgibbs or SCSISIGO, ATNO, LASTPHASE; 195776634Sgibbs } else { 195876634Sgibbs mvi SCSISIGO, ATNO; 195976634Sgibbs } 196039220Sgibbs mov MSG_OUT,SINDEX ret; 19614568Sgibbs 196213177Sgibbs/* 196313177Sgibbs * Functions to read data in Automatic PIO mode. 196413177Sgibbs * 196513177Sgibbs * According to Adaptec's documentation, an ACK is not sent on input from 196613177Sgibbs * the target until SCSIDATL is read from. So we wait until SCSIDATL is 196713177Sgibbs * latched (the usual way), then read the data byte directly off the bus 196813177Sgibbs * using SCSIBUSL. When we have pulled the ATN line, or we just want to 196913177Sgibbs * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI 197013177Sgibbs * spec guarantees that the target will hold the data byte on the bus until 197113177Sgibbs * we send our ACK. 197213177Sgibbs * 197313177Sgibbs * The assumption here is that these are called in a particular sequence, 197413177Sgibbs * and that REQ is already set when inb_first is called. inb_{first,next} 197513177Sgibbs * use the same calling convention as inb. 197613177Sgibbs */ 197757099Sgibbsinb_next_wait_perr: 197868402Sgibbs mvi PERR_DETECTED call set_seqint; 197957099Sgibbs jmp inb_next_wait; 198013177Sgibbsinb_next: 198123925Sgibbs mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ 198213360Sgibbsinb_next_wait: 198321947Sgibbs /* 198421947Sgibbs * If there is a parity error, wait for the kernel to 198521947Sgibbs * see the interrupt and prepare our message response 198621947Sgibbs * before continuing. 198721947Sgibbs */ 198823925Sgibbs test SSTAT1, REQINIT jz inb_next_wait; 198957099Sgibbs test SSTAT1, SCSIPERR jnz inb_next_wait_perr; 199057099Sgibbsinb_next_check_phase: 199123925Sgibbs and LASTPHASE, PHASE_MASK, SCSISIGI; 199223925Sgibbs cmp LASTPHASE, P_MESGIN jne mesgin_phasemis; 199319623Sgibbsinb_first: 199423925Sgibbs mov DINDEX,SINDEX; 199523925Sgibbs mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/ 199613177Sgibbsinb_last: 199723925Sgibbs mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/ 199841646Sgibbs} 19994568Sgibbs 200068087Sgibbsif ((ahc->flags & AHC_TARGETROLE) != 0) { 200141646Sgibbs/* 200241646Sgibbs * Change to a new phase. If we are changing the state of the I/O signal, 200341646Sgibbs * from out to in, wait an additional data release delay before continuing. 200441646Sgibbs */ 200541646Sgibbschange_phase: 2006165628Syar /* Wait for preceding I/O session to complete. */ 200743880Sgibbs test SCSISIGI, ACKI jnz .; 200843880Sgibbs 200943880Sgibbs /* Change the phase */ 201041646Sgibbs and DINDEX, IOI, SCSISIGI; 201141646Sgibbs mov SCSISIGO, SINDEX; 201241646Sgibbs and A, IOI, SINDEX; 201343880Sgibbs 201443880Sgibbs /* 201543880Sgibbs * If the data direction has changed, from 201643880Sgibbs * out (initiator driving) to in (target driving), 201763457Sgibbs * we must wait at least a data release delay plus 201843880Sgibbs * the normal bus settle delay. [SCSI III SPI 10.11.0] 201943880Sgibbs */ 202041646Sgibbs cmp DINDEX, A je change_phase_wait; 202141646Sgibbs test SINDEX, IOI jz change_phase_wait; 202241646Sgibbs call change_phase_wait; 202341646Sgibbschange_phase_wait: 202441646Sgibbs nop; 202541646Sgibbs nop; 202641646Sgibbs nop; 202741646Sgibbs nop ret; 202841646Sgibbs 202941646Sgibbs/* 203041646Sgibbs * Send a byte to an initiator in Automatic PIO mode. 203141646Sgibbs */ 203239220Sgibbstarget_outb: 203339220Sgibbs or SXFRCTL0, SPIOEN; 203439220Sgibbs test SSTAT0, SPIORDY jz .; 203539220Sgibbs mov SCSIDATL, SINDEX; 203639220Sgibbs test SSTAT0, SPIORDY jz .; 203741646Sgibbs and SXFRCTL0, ~SPIOEN ret; 203839220Sgibbs} 203939220Sgibbs 204013177Sgibbs/* 204163457Sgibbs * Locate a disconnected SCB by SCBID. Upon return, SCBPTR and SINDEX will 204263457Sgibbs * be set to the position of the SCB. If the SCB cannot be found locally, 204363457Sgibbs * it will be paged in from host memory. RETURN_2 stores the address of the 204463457Sgibbs * preceding SCB in the disconnected list which can be used to speed up 204563457Sgibbs * removal of the found SCB from the disconnected list. 204613177Sgibbs */ 204765942Sgibbsif ((ahc->flags & AHC_PAGESCBS) != 0) { 204895378SgibbsBEGIN_CRITICAL; 20494568SgibbsfindSCB: 205068087Sgibbs mov A, SINDEX; /* Tag passed in SINDEX */ 205168087Sgibbs cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound; 205263457Sgibbs mov SCBPTR, DISCONNECTED_SCBH; /* Initialize SCBPTR */ 205368087Sgibbs mvi ARG_2, SCB_LIST_NULL; /* Head of list */ 205463457Sgibbs jmp findSCB_loop; 205539220SgibbsfindSCB_next: 205663457Sgibbs cmp SCB_NEXT, SCB_LIST_NULL je findSCB_notFound; 205768087Sgibbs mov ARG_2, SCBPTR; 205839220Sgibbs mov SCBPTR,SCB_NEXT; 205923168SgibbsfindSCB_loop: 206063457Sgibbs cmp SCB_TAG, A jne findSCB_next; 206119164Sgibbsrem_scb_from_disc_list: 206239220Sgibbs cmp ARG_2, SCB_LIST_NULL je rHead; 206339220Sgibbs mov DINDEX, SCB_NEXT; 206468087Sgibbs mov SINDEX, SCBPTR; 206539220Sgibbs mov SCBPTR, ARG_2; 206639220Sgibbs mov SCB_NEXT, DINDEX; 206723925Sgibbs mov SCBPTR, SINDEX ret; 206815328SgibbsrHead: 206923925Sgibbs mov DISCONNECTED_SCBH,SCB_NEXT ret; 207095378SgibbsEND_CRITICAL; 207168087SgibbsfindSCB_notFound: 207268087Sgibbs /* 207368087Sgibbs * We didn't find it. Page in the SCB. 207468087Sgibbs */ 207568087Sgibbs mov ARG_1, A; /* Save tag */ 207668087Sgibbs mov ALLZEROS call get_free_or_disc_scb; 207768087Sgibbs mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; 207868087Sgibbs mov ARG_1 jmp dma_scb; 207968087Sgibbs} 20804568Sgibbs 208139220Sgibbs/* 208239220Sgibbs * Prepare the hardware to post a byte to host memory given an 208363457Sgibbs * index of (A + (256 * SINDEX)) and a base address of SHARED_DATA_ADDR. 208439220Sgibbs */ 208539220Sgibbspost_byte_setup: 208639220Sgibbs mov ARG_2, SINDEX; 208739220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 208839220Sgibbs mvi DINDEX, CCHADDR; 208963457Sgibbs mvi SHARED_DATA_ADDR call set_1byte_addr; 209039220Sgibbs mvi CCHCNT, 1; 209139220Sgibbs mvi CCSCBCTL, CCSCBRESET ret; 209239220Sgibbs } else { 209339220Sgibbs mvi DINDEX, HADDR; 209463457Sgibbs mvi SHARED_DATA_ADDR call set_1byte_addr; 209563457Sgibbs mvi 1 call set_hcnt; 209639220Sgibbs mvi DFCNTRL, FIFORESET ret; 209739220Sgibbs } 209839220Sgibbs 209939220Sgibbspost_byte: 210039220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 210139220Sgibbs bmov CCSCBRAM, SINDEX, 1; 210239220Sgibbs or CCSCBCTL, CCSCBEN|CCSCBRESET; 210339220Sgibbs test CCSCBCTL, CCSCBDONE jz .; 210439220Sgibbs clr CCSCBCTL ret; 210539220Sgibbs } else { 210639220Sgibbs mov DFDAT, SINDEX; 210739220Sgibbs or DFCNTRL, HDMAEN|FIFOFLUSH; 210839220Sgibbs jmp dma_finish; 210939220Sgibbs } 211039220Sgibbs 211157099Sgibbsphase_lock_perr: 211268402Sgibbs mvi PERR_DETECTED call set_seqint; 211339220Sgibbsphase_lock: 211457099Sgibbs /* 211557099Sgibbs * If there is a parity error, wait for the kernel to 211657099Sgibbs * see the interrupt and prepare our message response 211757099Sgibbs * before continuing. 211857099Sgibbs */ 211939220Sgibbs test SSTAT1, REQINIT jz phase_lock; 212057099Sgibbs test SSTAT1, SCSIPERR jnz phase_lock_perr; 212157099Sgibbsphase_lock_latch_phase: 212276634Sgibbs if ((ahc->features & AHC_DT) == 0) { 212376634Sgibbs and SCSISIGO, PHASE_MASK, SCSISIGI; 212476634Sgibbs } 212541646Sgibbs and LASTPHASE, PHASE_MASK, SCSISIGI ret; 212639220Sgibbs 212739220Sgibbsif ((ahc->features & AHC_CMD_CHAN) == 0) { 212863457Sgibbsset_hcnt: 212963457Sgibbs mov HCNT[0], SINDEX; 213063457Sgibbsclear_hcnt: 213163457Sgibbs clr HCNT[1]; 213263457Sgibbs clr HCNT[2] ret; 213363457Sgibbs 213419164Sgibbsset_stcnt_from_hcnt: 213523925Sgibbs mov STCNT[0], HCNT[0]; 213623925Sgibbs mov STCNT[1], HCNT[1]; 213723925Sgibbs mov STCNT[2], HCNT[2] ret; 21384568Sgibbs 213963457Sgibbsbcopy_8: 214063457Sgibbs mov DINDIR, SINDIR; 214119164Sgibbsbcopy_7: 214223925Sgibbs mov DINDIR, SINDIR; 214323925Sgibbs mov DINDIR, SINDIR; 214419164Sgibbsbcopy_5: 214523925Sgibbs mov DINDIR, SINDIR; 214619164Sgibbsbcopy_4: 214723925Sgibbs mov DINDIR, SINDIR; 214819164Sgibbsbcopy_3: 214923925Sgibbs mov DINDIR, SINDIR; 215023925Sgibbs mov DINDIR, SINDIR; 215123925Sgibbs mov DINDIR, SINDIR ret; 215239220Sgibbs} 21534568Sgibbs 215468087Sgibbsif ((ahc->flags & AHC_TARGETROLE) != 0) { 215539220Sgibbs/* 215639220Sgibbs * Setup addr assuming that A is an index into 215739220Sgibbs * an array of 32byte objects, SINDEX contains 215839220Sgibbs * the base address of that array, and DINDEX 215939220Sgibbs * contains the base address of the location 216039220Sgibbs * to store the indexed address. 216139220Sgibbs */ 216239220Sgibbsset_32byte_addr: 216339220Sgibbs shr ARG_2, 3, A; 216439220Sgibbs shl A, 5; 216539220Sgibbs jmp set_1byte_addr; 216639220Sgibbs} 216739220Sgibbs 216839220Sgibbs/* 216939220Sgibbs * Setup addr assuming that A is an index into 217039220Sgibbs * an array of 64byte objects, SINDEX contains 217139220Sgibbs * the base address of that array, and DINDEX 217239220Sgibbs * contains the base address of the location 217339220Sgibbs * to store the indexed address. 217439220Sgibbs */ 217539220Sgibbsset_64byte_addr: 217639220Sgibbs shr ARG_2, 2, A; 217739220Sgibbs shl A, 6; 217839220Sgibbs 217939220Sgibbs/* 218063457Sgibbs * Setup addr assuming that A + (ARG_2 * 256) is an 218139220Sgibbs * index into an array of 1byte objects, SINDEX contains 218239220Sgibbs * the base address of that array, and DINDEX contains 218339220Sgibbs * the base address of the location to store the computed 218439220Sgibbs * address. 218539220Sgibbs */ 218639220Sgibbsset_1byte_addr: 218739220Sgibbs add DINDIR, A, SINDIR; 218839220Sgibbs mov A, ARG_2; 218939220Sgibbs adc DINDIR, A, SINDIR; 219039220Sgibbs clr A; 219139220Sgibbs adc DINDIR, A, SINDIR; 219239220Sgibbs adc DINDIR, A, SINDIR ret; 219339220Sgibbs 219439220Sgibbs/* 219595378Sgibbs * Either post or fetch an SCB from host memory based on the 219639220Sgibbs * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX. 219739220Sgibbs */ 219819164Sgibbsdma_scb: 219939220Sgibbs mov A, SINDEX; 220039220Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 220139220Sgibbs mvi DINDEX, CCHADDR; 220239220Sgibbs mvi HSCB_ADDR call set_64byte_addr; 220339220Sgibbs mov CCSCBPTR, SCBPTR; 220439220Sgibbs test DMAPARAMS, DIRECTION jz dma_scb_tohost; 220571390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 220665942Sgibbs mvi CCHCNT, SCB_DOWNLOAD_SIZE_64; 220765942Sgibbs } else { 220865942Sgibbs mvi CCHCNT, SCB_DOWNLOAD_SIZE; 220965942Sgibbs } 221039220Sgibbs mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET; 221139220Sgibbs cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .; 221239220Sgibbs jmp dma_scb_finish; 221339220Sgibbsdma_scb_tohost: 221465942Sgibbs mvi CCHCNT, SCB_UPLOAD_SIZE; 221565942Sgibbs if ((ahc->features & AHC_ULTRA2) == 0) { 221639220Sgibbs mvi CCSCBCTL, CCSCBRESET; 221765942Sgibbs bmov CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE; 221839220Sgibbs or CCSCBCTL, CCSCBEN|CCSCBRESET; 221968579Sgibbs test CCSCBCTL, CCSCBDONE jz .; 222065942Sgibbs } else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) { 222165942Sgibbs mvi CCSCBCTL, CCARREN|CCSCBRESET; 222265942Sgibbs cmp CCSCBCTL, ARRDONE|CCARREN jne .; 222365942Sgibbs mvi CCHCNT, SCB_UPLOAD_SIZE; 222465942Sgibbs mvi CCSCBCTL, CCSCBEN|CCSCBRESET; 222565942Sgibbs cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .; 222639220Sgibbs } else { 222739220Sgibbs mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET; 222839220Sgibbs cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .; 222939220Sgibbs } 223039220Sgibbsdma_scb_finish: 223139220Sgibbs clr CCSCBCTL; 223239220Sgibbs test CCSCBCTL, CCARREN|CCSCBEN jnz .; 223339220Sgibbs ret; 223439220Sgibbs } else { 223539220Sgibbs mvi DINDEX, HADDR; 223639220Sgibbs mvi HSCB_ADDR call set_64byte_addr; 223765942Sgibbs mvi SCB_DOWNLOAD_SIZE call set_hcnt; 223839220Sgibbs mov DFCNTRL, DMAPARAMS; 223939220Sgibbs test DMAPARAMS, DIRECTION jnz dma_scb_fromhost; 224039220Sgibbs /* Fill it with the SCB data */ 224124175Sgibbscopy_scb_tofifo: 224265942Sgibbs mvi SINDEX, SCB_BASE; 224365942Sgibbs add A, SCB_DOWNLOAD_SIZE, SINDEX; 224424175Sgibbscopy_scb_tofifo_loop: 224565942Sgibbs call copy_to_fifo_8; 224639220Sgibbs cmp SINDEX, A jne copy_scb_tofifo_loop; 224739220Sgibbs or DFCNTRL, HDMAEN|FIFOFLUSH; 224865942Sgibbs jmp dma_finish; 224919164Sgibbsdma_scb_fromhost: 225065942Sgibbs mvi DINDEX, SCB_BASE; 225165942Sgibbs if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) { 225265942Sgibbs /* 225365942Sgibbs * The PCI module will only issue a PCI 225465942Sgibbs * retry if the data FIFO is empty. If the 225565942Sgibbs * host disconnects in the middle of a 225665942Sgibbs * transfer, we must empty the fifo of all 225765942Sgibbs * available data to force the chip to 225865942Sgibbs * continue the transfer. This does not 225965942Sgibbs * happen for SCSI transfers as the SCSI module 2260102673Sgibbs * will drain the FIFO as data are made available. 226172325Sgibbs * When the hang occurs, we know that a multiple 2262102673Sgibbs * of 8 bytes is in the FIFO because the PCI 226365942Sgibbs * module has an 8 byte input latch that only 226465942Sgibbs * dumps to the FIFO when HCNT == 0 or the 226565942Sgibbs * latch is full. 226665942Sgibbs */ 226772325Sgibbs clr A; 226874507Sgibbs /* Wait for at least 8 bytes of data to arrive. */ 226965942Sgibbsdma_scb_hang_fifo: 227074434Sgibbs test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo; 227165942Sgibbsdma_scb_hang_wait: 227265942Sgibbs test DFSTATUS, MREQPEND jnz dma_scb_hang_wait; 227365942Sgibbs test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; 227465942Sgibbs test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; 227565942Sgibbs test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; 227665942Sgibbs /* 227772325Sgibbs * The PCI module no longer intends to perform 227874507Sgibbs * a PCI transaction. Drain the fifo. 227965942Sgibbs */ 228081170Sgibbsdma_scb_hang_dma_drain_fifo: 228181170Sgibbs not A, HCNT; 228281170Sgibbs add A, SCB_DOWNLOAD_SIZE+SCB_BASE+1; 228381170Sgibbs and A, ~0x7; 228481170Sgibbs mov DINDIR,DFDAT; 228581170Sgibbs cmp DINDEX, A jne . - 1; 228681170Sgibbs cmp DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE 228781170Sgibbs je dma_finish_nowait; 228881170Sgibbs /* Restore A as the lines left to transfer. */ 228981170Sgibbs add A, -SCB_BASE, DINDEX; 229081170Sgibbs shr A, 3; 229165942Sgibbs jmp dma_scb_hang_fifo; 229265942Sgibbsdma_scb_hang_dma_done: 229365942Sgibbs and DFCNTRL, ~HDMAEN; 229465942Sgibbs test DFCNTRL, HDMAEN jnz .; 229572325Sgibbs add SEQADDR0, A; 229665942Sgibbs } else { 229765942Sgibbs call dma_finish; 229865942Sgibbs } 229972325Sgibbs call dfdat_in_8; 230072325Sgibbs call dfdat_in_8; 230172325Sgibbs call dfdat_in_8; 230265942Sgibbsdfdat_in_8: 230365942Sgibbs mov DINDIR,DFDAT; 230419164Sgibbsdfdat_in_7: 230539220Sgibbs mov DINDIR,DFDAT; 230639220Sgibbs mov DINDIR,DFDAT; 230739220Sgibbs mov DINDIR,DFDAT; 230839220Sgibbs mov DINDIR,DFDAT; 230939220Sgibbs mov DINDIR,DFDAT; 231065942Sgibbsdfdat_in_2: 231139220Sgibbs mov DINDIR,DFDAT; 231239220Sgibbs mov DINDIR,DFDAT ret; 231339220Sgibbs } 231419164Sgibbs 231565942Sgibbscopy_to_fifo_8: 231665942Sgibbs mov DFDAT,SINDIR; 231765942Sgibbs mov DFDAT,SINDIR; 231863457Sgibbscopy_to_fifo_6: 231963457Sgibbs mov DFDAT,SINDIR; 232063457Sgibbscopy_to_fifo_5: 232163457Sgibbs mov DFDAT,SINDIR; 232263457Sgibbscopy_to_fifo_4: 232363457Sgibbs mov DFDAT,SINDIR; 232463457Sgibbs mov DFDAT,SINDIR; 232563457Sgibbs mov DFDAT,SINDIR; 232663457Sgibbs mov DFDAT,SINDIR ret; 232739220Sgibbs 232813177Sgibbs/* 232919164Sgibbs * Wait for DMA from host memory to data FIFO to complete, then disable 233019164Sgibbs * DMA and wait for it to acknowledge that it's off. 233113177Sgibbs */ 233219164Sgibbsdma_finish: 233323925Sgibbs test DFSTATUS,HDONE jz dma_finish; 233474434Sgibbsdma_finish_nowait: 233522234Sgibbs /* Turn off DMA */ 233623925Sgibbs and DFCNTRL, ~HDMAEN; 233723925Sgibbs test DFCNTRL, HDMAEN jnz .; 233823925Sgibbs ret; 23399928Sgibbs 234074094Sgibbs/* 234174094Sgibbs * Restore an SCB that failed to match an incoming reselection 234274094Sgibbs * to the correct/safe state. If the SCB is for a disconnected 234374094Sgibbs * transaction, it must be returned to the disconnected list. 234474094Sgibbs * If it is not in the disconnected state, it must be free. 234574094Sgibbs */ 234674094Sgibbscleanup_scb: 234774094Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 234874094Sgibbs test SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list; 234974094Sgibbs } 235023925Sgibbsadd_scb_to_free_list: 235139220Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 235295378SgibbsBEGIN_CRITICAL; 235339220Sgibbs mov SCB_NEXT, FREE_SCBH; 235457099Sgibbs mvi SCB_TAG, SCB_LIST_NULL; 235557099Sgibbs mov FREE_SCBH, SCBPTR ret; 235695378SgibbsEND_CRITICAL; 235757099Sgibbs } else { 235857099Sgibbs mvi SCB_TAG, SCB_LIST_NULL ret; 235939220Sgibbs } 23604568Sgibbs 236179874Sgibbsif ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 236279874Sgibbsset_hhaddr: 236379874Sgibbs or DSCOMMAND1, HADDLDSEL0; 236479874Sgibbs and HADDR, SG_HIGH_ADDR_BITS, SINDEX; 236579874Sgibbs and DSCOMMAND1, ~HADDLDSEL0 ret; 236679874Sgibbs} 236779874Sgibbs 236839220Sgibbsif ((ahc->flags & AHC_PAGESCBS) != 0) { 236919164Sgibbsget_free_or_disc_scb: 237095378SgibbsBEGIN_CRITICAL; 237123925Sgibbs cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb; 237223925Sgibbs cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb; 237319623Sgibbsreturn_error: 237468402Sgibbs mvi NO_FREE_SCB call set_seqint; 237523925Sgibbs mvi SINDEX, SCB_LIST_NULL ret; 237619623Sgibbsdequeue_disc_scb: 237723925Sgibbs mov SCBPTR, DISCONNECTED_SCBH; 237868579Sgibbs mov DISCONNECTED_SCBH, SCB_NEXT; 237995378SgibbsEND_CRITICAL; 238023925Sgibbs mvi DMAPARAMS, FIFORESET; 238168579Sgibbs mov SCB_TAG jmp dma_scb; 238295378SgibbsBEGIN_CRITICAL; 238319164Sgibbsdequeue_free_scb: 238423925Sgibbs mov SCBPTR, FREE_SCBH; 238523925Sgibbs mov FREE_SCBH, SCB_NEXT ret; 238695378SgibbsEND_CRITICAL; 23874568Sgibbs 238819164Sgibbsadd_scb_to_disc_list: 238913177Sgibbs/* 239019164Sgibbs * Link this SCB into the DISCONNECTED list. This list holds the 239119164Sgibbs * candidates for paging out an SCB if one is needed for a new command. 239219164Sgibbs * Modifying the disconnected list is a critical(pause dissabled) section. 239313177Sgibbs */ 239495378SgibbsBEGIN_CRITICAL; 239523925Sgibbs mov SCB_NEXT, DISCONNECTED_SCBH; 239639220Sgibbs mov DISCONNECTED_SCBH, SCBPTR ret; 239795378SgibbsEND_CRITICAL; 239865942Sgibbs} 239968402Sgibbsset_seqint: 240068402Sgibbs mov INTSTAT, SINDEX; 240168402Sgibbs nop; 240263457Sgibbsreturn: 240363457Sgibbs ret; 2404