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