162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Adaptec U320 device driver firmware for Linux and FreeBSD. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 1994-2001, 2004 Justin T. Gibbs. 562306a36Sopenharmony_ci * Copyright (c) 2000-2002 Adaptec Inc. 662306a36Sopenharmony_ci * All rights reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 962306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1062306a36Sopenharmony_ci * are met: 1162306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1262306a36Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 1362306a36Sopenharmony_ci * without modification. 1462306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1562306a36Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 1662306a36Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 1762306a36Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 1862306a36Sopenharmony_ci * binary redistribution. 1962306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 2062306a36Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 2162306a36Sopenharmony_ci * from this software without specific prior written permission. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 2462306a36Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 2562306a36Sopenharmony_ci * Software Foundation. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * NO WARRANTY 2862306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2962306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3062306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3162306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3262306a36Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3362306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3462306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3562306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3662306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3762306a36Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3862306a36Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * $FreeBSD$ 4162306a36Sopenharmony_ci */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciVERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $" 4462306a36Sopenharmony_ciPATCH_ARG_LIST = "struct ahd_softc *ahd" 4562306a36Sopenharmony_ciPREFIX = "ahd_" 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#include "aic79xx.reg" 4862306a36Sopenharmony_ci#include "scsi_message.h" 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cirestart: 5162306a36Sopenharmony_ciif ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { 5262306a36Sopenharmony_ci test SEQINTCODE, 0xFF jz idle_loop; 5362306a36Sopenharmony_ci SET_SEQINTCODE(NO_SEQINT) 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciidle_loop: 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { 5962306a36Sopenharmony_ci /* 6062306a36Sopenharmony_ci * Convert ERROR status into a sequencer 6162306a36Sopenharmony_ci * interrupt to handle the case of an 6262306a36Sopenharmony_ci * interrupt collision on the hardware 6362306a36Sopenharmony_ci * setting of HWERR. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci test ERROR, 0xFF jz no_error_set; 6662306a36Sopenharmony_ci SET_SEQINTCODE(SAW_HWERR) 6762306a36Sopenharmony_cino_error_set: 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 7062306a36Sopenharmony_ci test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; 7162306a36Sopenharmony_ci test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list; 7262306a36Sopenharmony_ci /* 7362306a36Sopenharmony_ci * If the kernel has caught up with us, thaw the queue. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci mov A, KERNEL_QFREEZE_COUNT; 7662306a36Sopenharmony_ci cmp QFREEZE_COUNT, A jne check_frozen_completions; 7762306a36Sopenharmony_ci mov A, KERNEL_QFREEZE_COUNT[1]; 7862306a36Sopenharmony_ci cmp QFREEZE_COUNT[1], A jne check_frozen_completions; 7962306a36Sopenharmony_ci and SEQ_FLAGS2, ~SELECTOUT_QFROZEN; 8062306a36Sopenharmony_ci jmp check_waiting_list; 8162306a36Sopenharmony_cicheck_frozen_completions: 8262306a36Sopenharmony_ci test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus; 8362306a36Sopenharmony_ciBEGIN_CRITICAL; 8462306a36Sopenharmony_ci /* 8562306a36Sopenharmony_ci * If we have completions stalled waiting for the qfreeze 8662306a36Sopenharmony_ci * to take effect, move them over to the complete_scb list 8762306a36Sopenharmony_ci * now that no selections are pending. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus; 9062306a36Sopenharmony_ci /* 9162306a36Sopenharmony_ci * Find the end of the qfreeze list. The first element has 9262306a36Sopenharmony_ci * to be treated specially. 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_ci bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2; 9562306a36Sopenharmony_ci cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists; 9662306a36Sopenharmony_ci /* 9762306a36Sopenharmony_ci * Now the normal loop. 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci bmov SCBPTR, SCB_NEXT_COMPLETE, 2; 10062306a36Sopenharmony_ci cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1; 10162306a36Sopenharmony_cijoin_lists: 10262306a36Sopenharmony_ci bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; 10362306a36Sopenharmony_ci bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2; 10462306a36Sopenharmony_ci mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL; 10562306a36Sopenharmony_ci jmp idle_loop_checkbus; 10662306a36Sopenharmony_cicheck_waiting_list: 10762306a36Sopenharmony_ci cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; 10862306a36Sopenharmony_ci /* 10962306a36Sopenharmony_ci * ENSELO is cleared by a SELDO, so we must test for SELDO 11062306a36Sopenharmony_ci * one last time. 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_ci test SSTAT0, SELDO jnz select_out; 11362306a36Sopenharmony_ci call start_selection; 11462306a36Sopenharmony_ciidle_loop_checkbus: 11562306a36Sopenharmony_ci test SSTAT0, SELDO jnz select_out; 11662306a36Sopenharmony_ciEND_CRITICAL; 11762306a36Sopenharmony_ci test SSTAT0, SELDI jnz select_in; 11862306a36Sopenharmony_ci test SCSIPHASE, ~DATA_PHASE_MASK jz idle_loop_check_nonpackreq; 11962306a36Sopenharmony_ci test SCSISIGO, ATNO jz idle_loop_check_nonpackreq; 12062306a36Sopenharmony_ci call unexpected_nonpkt_phase_find_ctxt; 12162306a36Sopenharmony_ciidle_loop_check_nonpackreq: 12262306a36Sopenharmony_ci test SSTAT2, NONPACKREQ jz . + 2; 12362306a36Sopenharmony_ci call unexpected_nonpkt_phase_find_ctxt; 12462306a36Sopenharmony_ci if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { 12562306a36Sopenharmony_ci /* 12662306a36Sopenharmony_ci * On Rev A. hardware, the busy LED is only 12762306a36Sopenharmony_ci * turned on automaically during selections 12862306a36Sopenharmony_ci * and re-selections. Make the LED status 12962306a36Sopenharmony_ci * more useful by forcing it to be on so 13062306a36Sopenharmony_ci * long as one of our data FIFOs is active. 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci and A, FIFO0FREE|FIFO1FREE, DFFSTAT; 13362306a36Sopenharmony_ci cmp A, FIFO0FREE|FIFO1FREE jne . + 3; 13462306a36Sopenharmony_ci and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; 13562306a36Sopenharmony_ci jmp . + 2; 13662306a36Sopenharmony_ci or SBLKCTL, DIAGLEDEN|DIAGLEDON; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci call idle_loop_gsfifo_in_scsi_mode; 13962306a36Sopenharmony_ci call idle_loop_service_fifos; 14062306a36Sopenharmony_ci call idle_loop_cchan; 14162306a36Sopenharmony_ci jmp idle_loop; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ciidle_loop_gsfifo: 14462306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 14562306a36Sopenharmony_ciBEGIN_CRITICAL; 14662306a36Sopenharmony_ciidle_loop_gsfifo_in_scsi_mode: 14762306a36Sopenharmony_ci test LQISTAT2, LQIGSAVAIL jz return; 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * We have received good status for this transaction. There may 15062306a36Sopenharmony_ci * still be data in our FIFOs draining to the host. Complete 15162306a36Sopenharmony_ci * the SCB only if all data has transferred to the host. 15262306a36Sopenharmony_ci */ 15362306a36Sopenharmony_cigood_status_IU_done: 15462306a36Sopenharmony_ci bmov SCBPTR, GSFIFO, 2; 15562306a36Sopenharmony_ci clr SCB_SCSI_STATUS; 15662306a36Sopenharmony_ci /* 15762306a36Sopenharmony_ci * If a command completed before an attempted task management 15862306a36Sopenharmony_ci * function completed, notify the host after disabling any 15962306a36Sopenharmony_ci * pending select-outs. 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci test SCB_TASK_MANAGEMENT, 0xFF jz gsfifo_complete_normally; 16262306a36Sopenharmony_ci test SSTAT0, SELDO|SELINGO jnz . + 2; 16362306a36Sopenharmony_ci and SCSISEQ0, ~ENSELO; 16462306a36Sopenharmony_ci SET_SEQINTCODE(TASKMGMT_CMD_CMPLT_OKAY) 16562306a36Sopenharmony_cigsfifo_complete_normally: 16662306a36Sopenharmony_ci or SCB_CONTROL, STATUS_RCVD; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* 16962306a36Sopenharmony_ci * Since this status did not consume a FIFO, we have to 17062306a36Sopenharmony_ci * be a bit more dilligent in how we check for FIFOs pertaining 17162306a36Sopenharmony_ci * to this transaction. There are two states that a FIFO still 17262306a36Sopenharmony_ci * transferring data may be in. 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * 1) Configured and draining to the host, with a FIFO handler. 17562306a36Sopenharmony_ci * 2) Pending cfg4data, fifo not empty. 17662306a36Sopenharmony_ci * 17762306a36Sopenharmony_ci * Case 1 can be detected by noticing a non-zero FIFO active 17862306a36Sopenharmony_ci * count in the SCB. In this case, we allow the routine servicing 17962306a36Sopenharmony_ci * the FIFO to complete the SCB. 18062306a36Sopenharmony_ci * 18162306a36Sopenharmony_ci * Case 2 implies either a pending or yet to occur save data 18262306a36Sopenharmony_ci * pointers for this same context in the other FIFO. So, if 18362306a36Sopenharmony_ci * we detect case 1, we will properly defer the post of the SCB 18462306a36Sopenharmony_ci * and achieve the desired result. The pending cfg4data will 18562306a36Sopenharmony_ci * notice that status has been received and complete the SCB. 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_ci test SCB_FIFO_USE_COUNT, 0xFF jnz idle_loop_gsfifo_in_scsi_mode; 18862306a36Sopenharmony_ci call complete; 18962306a36Sopenharmony_ciEND_CRITICAL; 19062306a36Sopenharmony_ci jmp idle_loop_gsfifo_in_scsi_mode; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ciidle_loop_service_fifos: 19362306a36Sopenharmony_ci SET_MODE(M_DFF0, M_DFF0) 19462306a36Sopenharmony_ciBEGIN_CRITICAL; 19562306a36Sopenharmony_ci test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; 19662306a36Sopenharmony_ci call longjmp; 19762306a36Sopenharmony_ciEND_CRITICAL; 19862306a36Sopenharmony_ciidle_loop_next_fifo: 19962306a36Sopenharmony_ci SET_MODE(M_DFF1, M_DFF1) 20062306a36Sopenharmony_ciBEGIN_CRITICAL; 20162306a36Sopenharmony_ci test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; 20262306a36Sopenharmony_ciEND_CRITICAL; 20362306a36Sopenharmony_cireturn: 20462306a36Sopenharmony_ci ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ciidle_loop_cchan: 20762306a36Sopenharmony_ci SET_MODE(M_CCHAN, M_CCHAN) 20862306a36Sopenharmony_ci test QOFF_CTLSTA, HS_MAILBOX_ACT jz hs_mailbox_empty; 20962306a36Sopenharmony_ci or QOFF_CTLSTA, HS_MAILBOX_ACT; 21062306a36Sopenharmony_ci mov LOCAL_HS_MAILBOX, HS_MAILBOX; 21162306a36Sopenharmony_cihs_mailbox_empty: 21262306a36Sopenharmony_ciBEGIN_CRITICAL; 21362306a36Sopenharmony_ci test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; 21462306a36Sopenharmony_ci test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; 21562306a36Sopenharmony_ci test CCSCBCTL, CCSCBDONE jz return; 21662306a36Sopenharmony_ci /* FALLTHROUGH */ 21762306a36Sopenharmony_ciscbdma_tohost_done: 21862306a36Sopenharmony_ci test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; 21962306a36Sopenharmony_ci /* 22062306a36Sopenharmony_ci * An SCB has been successfully uploaded to the host. 22162306a36Sopenharmony_ci * If the SCB was uploaded for some reason other than 22262306a36Sopenharmony_ci * bad SCSI status (currently only for underruns), we 22362306a36Sopenharmony_ci * queue the SCB for normal completion. Otherwise, we 22462306a36Sopenharmony_ci * wait until any select-out activity has halted, and 22562306a36Sopenharmony_ci * then queue the completion. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci and CCSCBCTL, ~(CCARREN|CCSCBEN); 22862306a36Sopenharmony_ci bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; 22962306a36Sopenharmony_ci cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2; 23062306a36Sopenharmony_ci mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL; 23162306a36Sopenharmony_ci test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion; 23262306a36Sopenharmony_ci bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2; 23362306a36Sopenharmony_ci bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret; 23462306a36Sopenharmony_ciscbdma_queue_completion: 23562306a36Sopenharmony_ci bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; 23662306a36Sopenharmony_ci bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; 23762306a36Sopenharmony_cifill_qoutfifo_dmadone: 23862306a36Sopenharmony_ci and CCSCBCTL, ~(CCARREN|CCSCBEN); 23962306a36Sopenharmony_ci call qoutfifo_updated; 24062306a36Sopenharmony_ci mvi COMPLETE_SCB_DMAINPROG_HEAD[1], SCB_LIST_NULL; 24162306a36Sopenharmony_ci bmov QOUTFIFO_NEXT_ADDR, SCBHADDR, 4; 24262306a36Sopenharmony_ci test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; 24362306a36Sopenharmony_ci bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; 24462306a36Sopenharmony_ci xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; 24562306a36Sopenharmony_ciEND_CRITICAL; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciqoutfifo_updated: 24862306a36Sopenharmony_ci /* 24962306a36Sopenharmony_ci * If there are more commands waiting to be dma'ed 25062306a36Sopenharmony_ci * to the host, always coalesce. Otherwise honor the 25162306a36Sopenharmony_ci * host's wishes. 25262306a36Sopenharmony_ci */ 25362306a36Sopenharmony_ci cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne coalesce_by_count; 25462306a36Sopenharmony_ci cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL jne coalesce_by_count; 25562306a36Sopenharmony_ci test LOCAL_HS_MAILBOX, ENINT_COALESCE jz issue_cmdcmplt; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * If we have relatively few commands outstanding, don't 25962306a36Sopenharmony_ci * bother waiting for another command to complete. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_ci test CMDS_PENDING[1], 0xFF jnz coalesce_by_count; 26262306a36Sopenharmony_ci /* Add -1 so that jnc means <= not just < */ 26362306a36Sopenharmony_ci add A, -1, INT_COALESCING_MINCMDS; 26462306a36Sopenharmony_ci add NONE, A, CMDS_PENDING; 26562306a36Sopenharmony_ci jnc issue_cmdcmplt; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* 26862306a36Sopenharmony_ci * If coalescing, only coalesce up to the limit 26962306a36Sopenharmony_ci * provided by the host driver. 27062306a36Sopenharmony_ci */ 27162306a36Sopenharmony_cicoalesce_by_count: 27262306a36Sopenharmony_ci mov A, INT_COALESCING_MAXCMDS; 27362306a36Sopenharmony_ci add NONE, A, INT_COALESCING_CMDCOUNT; 27462306a36Sopenharmony_ci jc issue_cmdcmplt; 27562306a36Sopenharmony_ci /* 27662306a36Sopenharmony_ci * If the timer is not currently active, 27762306a36Sopenharmony_ci * fire it up. 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci test INTCTL, SWTMINTMASK jz return; 28062306a36Sopenharmony_ci bmov SWTIMER, INT_COALESCING_TIMER, 2; 28162306a36Sopenharmony_ci mvi CLRSEQINTSTAT, CLRSEQ_SWTMRTO; 28262306a36Sopenharmony_ci or INTCTL, SWTMINTEN|SWTIMER_START; 28362306a36Sopenharmony_ci and INTCTL, ~SWTMINTMASK ret; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ciissue_cmdcmplt: 28662306a36Sopenharmony_ci mvi INTSTAT, CMDCMPLT; 28762306a36Sopenharmony_ci clr INT_COALESCING_CMDCOUNT; 28862306a36Sopenharmony_ci or INTCTL, SWTMINTMASK ret; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ciBEGIN_CRITICAL; 29162306a36Sopenharmony_cifetch_new_scb_inprog: 29262306a36Sopenharmony_ci test CCSCBCTL, ARRDONE jz return; 29362306a36Sopenharmony_cifetch_new_scb_done: 29462306a36Sopenharmony_ci and CCSCBCTL, ~(CCARREN|CCSCBEN); 29562306a36Sopenharmony_ci clr A; 29662306a36Sopenharmony_ci add CMDS_PENDING, 1; 29762306a36Sopenharmony_ci adc CMDS_PENDING[1], A; 29862306a36Sopenharmony_ci if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) { 29962306a36Sopenharmony_ci /* 30062306a36Sopenharmony_ci * "Short Luns" are not placed into outgoing LQ 30162306a36Sopenharmony_ci * packets in the correct byte order. Use a full 30262306a36Sopenharmony_ci * sized lun field instead and fill it with the 30362306a36Sopenharmony_ci * one byte of lun information we support. 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ci mov SCB_PKT_LUN[6], SCB_LUN; 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci /* 30862306a36Sopenharmony_ci * The FIFO use count field is shared with the 30962306a36Sopenharmony_ci * tag set by the host so that our SCB dma engine 31062306a36Sopenharmony_ci * knows the correct location to store the SCB. 31162306a36Sopenharmony_ci * Set it to zero before processing the SCB. 31262306a36Sopenharmony_ci */ 31362306a36Sopenharmony_ci clr SCB_FIFO_USE_COUNT; 31462306a36Sopenharmony_ci /* Update the next SCB address to download. */ 31562306a36Sopenharmony_ci bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4; 31662306a36Sopenharmony_ci /* 31762306a36Sopenharmony_ci * NULL out the SCB links since these fields 31862306a36Sopenharmony_ci * occupy the same location as SCB_NEXT_SCB_BUSADDR. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_ci mvi SCB_NEXT[1], SCB_LIST_NULL; 32162306a36Sopenharmony_ci mvi SCB_NEXT2[1], SCB_LIST_NULL; 32262306a36Sopenharmony_ci /* Increment our position in the QINFIFO. */ 32362306a36Sopenharmony_ci mov NONE, SNSCB_QOFF; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* 32662306a36Sopenharmony_ci * Save SCBID of this SCB in REG0 since 32762306a36Sopenharmony_ci * SCBPTR will be clobbered during target 32862306a36Sopenharmony_ci * list updates. We also record the SCB's 32962306a36Sopenharmony_ci * flags so that we can refer to them even 33062306a36Sopenharmony_ci * after SCBPTR has been changed. 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_ci bmov REG0, SCBPTR, 2; 33362306a36Sopenharmony_ci mov A, SCB_CONTROL; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* 33662306a36Sopenharmony_ci * Find the tail SCB of the execution queue 33762306a36Sopenharmony_ci * for this target. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci shr SINDEX, 3, SCB_SCSIID; 34062306a36Sopenharmony_ci and SINDEX, ~0x1; 34162306a36Sopenharmony_ci mvi SINDEX[1], (WAITING_SCB_TAILS >> 8); 34262306a36Sopenharmony_ci bmov DINDEX, SINDEX, 2; 34362306a36Sopenharmony_ci bmov SCBPTR, SINDIR, 2; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* 34662306a36Sopenharmony_ci * Update the tail to point to the new SCB. 34762306a36Sopenharmony_ci */ 34862306a36Sopenharmony_ci bmov DINDIR, REG0, 2; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* 35162306a36Sopenharmony_ci * If the queue was empty, queue this SCB as 35262306a36Sopenharmony_ci * the first for this target. 35362306a36Sopenharmony_ci */ 35462306a36Sopenharmony_ci cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* 35762306a36Sopenharmony_ci * SCBs that want to send messages must always be 35862306a36Sopenharmony_ci * at the head of their per-target queue so that 35962306a36Sopenharmony_ci * ATN can be asserted even if the current 36062306a36Sopenharmony_ci * negotiation agreement is packetized. If the 36162306a36Sopenharmony_ci * target queue is empty, the SCB can be queued 36262306a36Sopenharmony_ci * immediately. If the queue is not empty, we must 36362306a36Sopenharmony_ci * wait for it to empty before entering this SCB 36462306a36Sopenharmony_ci * into the waiting for selection queue. Otherwise 36562306a36Sopenharmony_ci * our batching and round-robin selection scheme 36662306a36Sopenharmony_ci * could allow commands to be queued out of order. 36762306a36Sopenharmony_ci * To simplify the implementation, we stop pulling 36862306a36Sopenharmony_ci * new commands from the host until the MK_MESSAGE 36962306a36Sopenharmony_ci * SCB can be queued to the waiting for selection 37062306a36Sopenharmony_ci * list. 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_ci test A, MK_MESSAGE jz batch_scb; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* 37562306a36Sopenharmony_ci * If the last SCB is also a MK_MESSAGE SCB, then 37662306a36Sopenharmony_ci * order is preserved even if we batch. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci test SCB_CONTROL, MK_MESSAGE jz batch_scb; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* 38162306a36Sopenharmony_ci * Defer this SCB and stop fetching new SCBs until 38262306a36Sopenharmony_ci * it can be queued. Since the SCB_SCSIID of the 38362306a36Sopenharmony_ci * tail SCB must be the same as that of the newly 38462306a36Sopenharmony_ci * queued SCB, there is no need to restore the SCBID 38562306a36Sopenharmony_ci * here. 38662306a36Sopenharmony_ci */ 38762306a36Sopenharmony_ci or SEQ_FLAGS2, PENDING_MK_MESSAGE; 38862306a36Sopenharmony_ci bmov MK_MESSAGE_SCB, REG0, 2; 38962306a36Sopenharmony_ci mov MK_MESSAGE_SCSIID, SCB_SCSIID ret; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cibatch_scb: 39262306a36Sopenharmony_ci /* 39362306a36Sopenharmony_ci * Otherwise just update the previous tail SCB to 39462306a36Sopenharmony_ci * point to the new tail. 39562306a36Sopenharmony_ci */ 39662306a36Sopenharmony_ci bmov SCB_NEXT, REG0, 2 ret; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cifirst_new_target_scb: 39962306a36Sopenharmony_ci /* 40062306a36Sopenharmony_ci * Append SCB to the tail of the waiting for 40162306a36Sopenharmony_ci * selection list. 40262306a36Sopenharmony_ci */ 40362306a36Sopenharmony_ci cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb; 40462306a36Sopenharmony_ci bmov SCBPTR, WAITING_TID_TAIL, 2; 40562306a36Sopenharmony_ci bmov SCB_NEXT2, REG0, 2; 40662306a36Sopenharmony_ci bmov WAITING_TID_TAIL, REG0, 2 ret; 40762306a36Sopenharmony_cifirst_new_scb: 40862306a36Sopenharmony_ci /* 40962306a36Sopenharmony_ci * Whole list is empty, so the head of 41062306a36Sopenharmony_ci * the list must be initialized too. 41162306a36Sopenharmony_ci */ 41262306a36Sopenharmony_ci bmov WAITING_TID_HEAD, REG0, 2; 41362306a36Sopenharmony_ci bmov WAITING_TID_TAIL, REG0, 2 ret; 41462306a36Sopenharmony_ciEND_CRITICAL; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ciscbdma_idle: 41762306a36Sopenharmony_ci /* 41862306a36Sopenharmony_ci * Don't bother downloading new SCBs to execute 41962306a36Sopenharmony_ci * if select-outs are currently frozen or we have 42062306a36Sopenharmony_ci * a MK_MESSAGE SCB waiting to enter the queue. 42162306a36Sopenharmony_ci */ 42262306a36Sopenharmony_ci test SEQ_FLAGS2, SELECTOUT_QFROZEN|PENDING_MK_MESSAGE 42362306a36Sopenharmony_ci jnz scbdma_no_new_scbs; 42462306a36Sopenharmony_ciBEGIN_CRITICAL; 42562306a36Sopenharmony_ci test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb; 42662306a36Sopenharmony_ciscbdma_no_new_scbs: 42762306a36Sopenharmony_ci cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb; 42862306a36Sopenharmony_ci cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return; 42962306a36Sopenharmony_ci /* FALLTHROUGH */ 43062306a36Sopenharmony_cifill_qoutfifo: 43162306a36Sopenharmony_ci /* 43262306a36Sopenharmony_ci * Keep track of the SCBs we are dmaing just 43362306a36Sopenharmony_ci * in case the DMA fails or is aborted. 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_ci bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; 43662306a36Sopenharmony_ci mvi CCSCBCTL, CCSCBRESET; 43762306a36Sopenharmony_ci bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; 43862306a36Sopenharmony_ci mov A, QOUTFIFO_NEXT_ADDR; 43962306a36Sopenharmony_ci bmov SCBPTR, COMPLETE_SCB_HEAD, 2; 44062306a36Sopenharmony_cifill_qoutfifo_loop: 44162306a36Sopenharmony_ci bmov CCSCBRAM, SCBPTR, 2; 44262306a36Sopenharmony_ci mov CCSCBRAM, SCB_SGPTR[0]; 44362306a36Sopenharmony_ci mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG; 44462306a36Sopenharmony_ci mov NONE, SDSCB_QOFF; 44562306a36Sopenharmony_ci inc INT_COALESCING_CMDCOUNT; 44662306a36Sopenharmony_ci add CMDS_PENDING, -1; 44762306a36Sopenharmony_ci adc CMDS_PENDING[1], -1; 44862306a36Sopenharmony_ci cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; 44962306a36Sopenharmony_ci cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; 45062306a36Sopenharmony_ci test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done; 45162306a36Sopenharmony_ci /* 45262306a36Sopenharmony_ci * Don't cross an ADB or Cachline boundary when DMA'ing 45362306a36Sopenharmony_ci * completion entries. In PCI mode, at least in 32/33 45462306a36Sopenharmony_ci * configurations, the SCB DMA engine may lose its place 45562306a36Sopenharmony_ci * in the data-stream should the target force a retry on 45662306a36Sopenharmony_ci * something other than an 8byte aligned boundary. In 45762306a36Sopenharmony_ci * PCI-X mode, we do this to avoid split transactions since 45862306a36Sopenharmony_ci * many chipsets seem to be unable to format proper split 45962306a36Sopenharmony_ci * completions to continue the data transfer. 46062306a36Sopenharmony_ci */ 46162306a36Sopenharmony_ci add SINDEX, A, CCSCBADDR; 46262306a36Sopenharmony_ci test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done; 46362306a36Sopenharmony_ci bmov SCBPTR, SCB_NEXT_COMPLETE, 2; 46462306a36Sopenharmony_ci jmp fill_qoutfifo_loop; 46562306a36Sopenharmony_cifill_qoutfifo_done: 46662306a36Sopenharmony_ci mov SCBHCNT, CCSCBADDR; 46762306a36Sopenharmony_ci mvi CCSCBCTL, CCSCBEN|CCSCBRESET; 46862306a36Sopenharmony_ci bmov COMPLETE_SCB_HEAD, SCB_NEXT_COMPLETE, 2; 46962306a36Sopenharmony_ci mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL ret; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cifetch_new_scb: 47262306a36Sopenharmony_ci bmov SCBHADDR, NEXT_QUEUED_SCB_ADDR, 4; 47362306a36Sopenharmony_ci mvi CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET jmp dma_scb; 47462306a36Sopenharmony_cidma_complete_scb: 47562306a36Sopenharmony_ci bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; 47662306a36Sopenharmony_ci bmov SCBHADDR, SCB_BUSADDR, 4; 47762306a36Sopenharmony_ci mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci/* 48062306a36Sopenharmony_ci * Either post or fetch an SCB from host memory. The caller 48162306a36Sopenharmony_ci * is responsible for polling for transfer completion. 48262306a36Sopenharmony_ci * 48362306a36Sopenharmony_ci * Prerequisits: Mode == M_CCHAN 48462306a36Sopenharmony_ci * SINDEX contains CCSCBCTL flags 48562306a36Sopenharmony_ci * SCBHADDR set to Host SCB address 48662306a36Sopenharmony_ci * SCBPTR set to SCB src location on "push" operations 48762306a36Sopenharmony_ci */ 48862306a36Sopenharmony_ciSET_SRC_MODE M_CCHAN; 48962306a36Sopenharmony_ciSET_DST_MODE M_CCHAN; 49062306a36Sopenharmony_cidma_scb: 49162306a36Sopenharmony_ci mvi SCBHCNT, SCB_TRANSFER_SIZE; 49262306a36Sopenharmony_ci mov CCSCBCTL, SINDEX ret; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_cisetjmp: 49562306a36Sopenharmony_ci /* 49662306a36Sopenharmony_ci * At least on the A, a return in the same 49762306a36Sopenharmony_ci * instruction as the bmov results in a return 49862306a36Sopenharmony_ci * to the caller, not to the new address at the 49962306a36Sopenharmony_ci * top of the stack. Since we want the latter 50062306a36Sopenharmony_ci * (we use setjmp to register a handler from an 50162306a36Sopenharmony_ci * interrupt context but not invoke that handler 50262306a36Sopenharmony_ci * until we return to our idle loop), use a 50362306a36Sopenharmony_ci * separate ret instruction. 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_ci bmov LONGJMP_ADDR, STACK, 2; 50662306a36Sopenharmony_ci ret; 50762306a36Sopenharmony_cisetjmp_inline: 50862306a36Sopenharmony_ci bmov LONGJMP_ADDR, STACK, 2; 50962306a36Sopenharmony_cilongjmp: 51062306a36Sopenharmony_ci bmov STACK, LONGJMP_ADDR, 2 ret; 51162306a36Sopenharmony_ciEND_CRITICAL; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci/*************************** Chip Bug Work Arounds ****************************/ 51462306a36Sopenharmony_ci/* 51562306a36Sopenharmony_ci * Must disable interrupts when setting the mode pointer 51662306a36Sopenharmony_ci * register as an interrupt occurring mid update will 51762306a36Sopenharmony_ci * fail to store the new mode value for restoration on 51862306a36Sopenharmony_ci * an iret. 51962306a36Sopenharmony_ci */ 52062306a36Sopenharmony_ciif ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { 52162306a36Sopenharmony_ciset_mode_work_around: 52262306a36Sopenharmony_ci mvi SEQINTCTL, INTVEC1DSL; 52362306a36Sopenharmony_ci mov MODE_PTR, SINDEX; 52462306a36Sopenharmony_ci clr SEQINTCTL ret; 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ciif ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { 52962306a36Sopenharmony_ciset_seqint_work_around: 53062306a36Sopenharmony_ci mov SEQINTCODE, SINDEX; 53162306a36Sopenharmony_ci mvi SEQINTCODE, NO_SEQINT ret; 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci/************************ Packetized LongJmp Routines *************************/ 53562306a36Sopenharmony_ciSET_SRC_MODE M_SCSI; 53662306a36Sopenharmony_ciSET_DST_MODE M_SCSI; 53762306a36Sopenharmony_cistart_selection: 53862306a36Sopenharmony_ciBEGIN_CRITICAL; 53962306a36Sopenharmony_ci if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { 54062306a36Sopenharmony_ci /* 54162306a36Sopenharmony_ci * Razor #494 54262306a36Sopenharmony_ci * Rev A hardware fails to update LAST/CURR/NEXTSCB 54362306a36Sopenharmony_ci * correctly after a packetized selection in several 54462306a36Sopenharmony_ci * situations: 54562306a36Sopenharmony_ci * 54662306a36Sopenharmony_ci * 1) If only one command existed in the queue, the 54762306a36Sopenharmony_ci * LAST/CURR/NEXTSCB are unchanged. 54862306a36Sopenharmony_ci * 54962306a36Sopenharmony_ci * 2) In a non QAS, protocol allowed phase change, 55062306a36Sopenharmony_ci * the queue is shifted 1 too far. LASTSCB is 55162306a36Sopenharmony_ci * the last SCB that was correctly processed. 55262306a36Sopenharmony_ci * 55362306a36Sopenharmony_ci * 3) In the QAS case, if the full list of commands 55462306a36Sopenharmony_ci * was successfully sent, NEXTSCB is NULL and neither 55562306a36Sopenharmony_ci * CURRSCB nor LASTSCB can be trusted. We must 55662306a36Sopenharmony_ci * manually walk the list counting MAXCMDCNT elements 55762306a36Sopenharmony_ci * to find the last SCB that was sent correctly. 55862306a36Sopenharmony_ci * 55962306a36Sopenharmony_ci * To simplify the workaround for this bug in SELDO 56062306a36Sopenharmony_ci * handling, we initialize LASTSCB prior to enabling 56162306a36Sopenharmony_ci * selection so we can rely on it even for case #1 above. 56262306a36Sopenharmony_ci */ 56362306a36Sopenharmony_ci bmov LASTSCB, WAITING_TID_HEAD, 2; 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci bmov CURRSCB, WAITING_TID_HEAD, 2; 56662306a36Sopenharmony_ci bmov SCBPTR, WAITING_TID_HEAD, 2; 56762306a36Sopenharmony_ci shr SELOID, 4, SCB_SCSIID; 56862306a36Sopenharmony_ci /* 56962306a36Sopenharmony_ci * If we want to send a message to the device, ensure 57062306a36Sopenharmony_ci * we are selecting with atn regardless of our packetized 57162306a36Sopenharmony_ci * agreement. Since SPI4 only allows target reset or PPR 57262306a36Sopenharmony_ci * messages if this is a packetized connection, the change 57362306a36Sopenharmony_ci * to our negotiation table entry for this selection will 57462306a36Sopenharmony_ci * be cleared when the message is acted on. 57562306a36Sopenharmony_ci */ 57662306a36Sopenharmony_ci test SCB_CONTROL, MK_MESSAGE jz . + 3; 57762306a36Sopenharmony_ci mov NEGOADDR, SELOID; 57862306a36Sopenharmony_ci or NEGCONOPTS, ENAUTOATNO; 57962306a36Sopenharmony_ci or SCSISEQ0, ENSELO ret; 58062306a36Sopenharmony_ciEND_CRITICAL; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci/* 58362306a36Sopenharmony_ci * Allocate a FIFO for a non-packetized transaction. 58462306a36Sopenharmony_ci * In RevA hardware, both FIFOs must be free before we 58562306a36Sopenharmony_ci * can allocate a FIFO for a non-packetized transaction. 58662306a36Sopenharmony_ci */ 58762306a36Sopenharmony_ciallocate_fifo_loop: 58862306a36Sopenharmony_ci /* 58962306a36Sopenharmony_ci * Do whatever work is required to free a FIFO. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci call idle_loop_service_fifos; 59262306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 59362306a36Sopenharmony_ciallocate_fifo: 59462306a36Sopenharmony_ci if ((ahd->bugs & AHD_NONPACKFIFO_BUG) != 0) { 59562306a36Sopenharmony_ci and A, FIFO0FREE|FIFO1FREE, DFFSTAT; 59662306a36Sopenharmony_ci cmp A, FIFO0FREE|FIFO1FREE jne allocate_fifo_loop; 59762306a36Sopenharmony_ci } else { 59862306a36Sopenharmony_ci test DFFSTAT, FIFO1FREE jnz allocate_fifo1; 59962306a36Sopenharmony_ci test DFFSTAT, FIFO0FREE jz allocate_fifo_loop; 60062306a36Sopenharmony_ci mvi DFFSTAT, B_CURRFIFO_0; 60162306a36Sopenharmony_ci SET_MODE(M_DFF0, M_DFF0) 60262306a36Sopenharmony_ci bmov SCBPTR, ALLOCFIFO_SCBPTR, 2 ret; 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ciSET_SRC_MODE M_SCSI; 60562306a36Sopenharmony_ciSET_DST_MODE M_SCSI; 60662306a36Sopenharmony_ciallocate_fifo1: 60762306a36Sopenharmony_ci mvi DFFSTAT, CURRFIFO_1; 60862306a36Sopenharmony_ci SET_MODE(M_DFF1, M_DFF1) 60962306a36Sopenharmony_ci bmov SCBPTR, ALLOCFIFO_SCBPTR, 2 ret; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci/* 61262306a36Sopenharmony_ci * We have been reselected as an initiator 61362306a36Sopenharmony_ci * or selected as a target. 61462306a36Sopenharmony_ci */ 61562306a36Sopenharmony_ciSET_SRC_MODE M_SCSI; 61662306a36Sopenharmony_ciSET_DST_MODE M_SCSI; 61762306a36Sopenharmony_ciselect_in: 61862306a36Sopenharmony_ci if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { 61962306a36Sopenharmony_ci /* 62062306a36Sopenharmony_ci * On Rev A. hardware, the busy LED is only 62162306a36Sopenharmony_ci * turned on automaically during selections 62262306a36Sopenharmony_ci * and re-selections. Make the LED status 62362306a36Sopenharmony_ci * more useful by forcing it to be on from 62462306a36Sopenharmony_ci * the point of selection until our idle 62562306a36Sopenharmony_ci * loop determines that neither of our FIFOs 62662306a36Sopenharmony_ci * are busy. This handles the non-packetized 62762306a36Sopenharmony_ci * case nicely as we will not return to the 62862306a36Sopenharmony_ci * idle loop until the busfree at the end of 62962306a36Sopenharmony_ci * each transaction. 63062306a36Sopenharmony_ci */ 63162306a36Sopenharmony_ci or SBLKCTL, DIAGLEDEN|DIAGLEDON; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { 63462306a36Sopenharmony_ci /* 63562306a36Sopenharmony_ci * Test to ensure that the bus has not 63662306a36Sopenharmony_ci * already gone free prior to clearing 63762306a36Sopenharmony_ci * any stale busfree status. This avoids 63862306a36Sopenharmony_ci * a window whereby a busfree just after 63962306a36Sopenharmony_ci * a selection could be missed. 64062306a36Sopenharmony_ci */ 64162306a36Sopenharmony_ci test SCSISIGI, BSYI jz . + 2; 64262306a36Sopenharmony_ci mvi CLRSINT1,CLRBUSFREE; 64362306a36Sopenharmony_ci or SIMODE1, ENBUSFREE; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci or SXFRCTL0, SPIOEN; 64662306a36Sopenharmony_ci and SAVED_SCSIID, SELID_MASK, SELID; 64762306a36Sopenharmony_ci and A, OID, IOWNID; 64862306a36Sopenharmony_ci or SAVED_SCSIID, A; 64962306a36Sopenharmony_ci mvi CLRSINT0, CLRSELDI; 65062306a36Sopenharmony_ci jmp ITloop; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci/* 65362306a36Sopenharmony_ci * We have successfully selected out. 65462306a36Sopenharmony_ci * 65562306a36Sopenharmony_ci * Clear SELDO. 65662306a36Sopenharmony_ci * Dequeue all SCBs sent from the waiting queue 65762306a36Sopenharmony_ci * Requeue all SCBs *not* sent to the tail of the waiting queue 65862306a36Sopenharmony_ci * Take Razor #494 into account for above. 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * In Packetized Mode: 66162306a36Sopenharmony_ci * Return to the idle loop. Our interrupt handler will take 66262306a36Sopenharmony_ci * care of any incoming L_Qs. 66362306a36Sopenharmony_ci * 66462306a36Sopenharmony_ci * In Non-Packetize Mode: 66562306a36Sopenharmony_ci * Continue to our normal state machine. 66662306a36Sopenharmony_ci */ 66762306a36Sopenharmony_ciSET_SRC_MODE M_SCSI; 66862306a36Sopenharmony_ciSET_DST_MODE M_SCSI; 66962306a36Sopenharmony_ciselect_out: 67062306a36Sopenharmony_ciBEGIN_CRITICAL; 67162306a36Sopenharmony_ci if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { 67262306a36Sopenharmony_ci /* 67362306a36Sopenharmony_ci * On Rev A. hardware, the busy LED is only 67462306a36Sopenharmony_ci * turned on automaically during selections 67562306a36Sopenharmony_ci * and re-selections. Make the LED status 67662306a36Sopenharmony_ci * more useful by forcing it to be on from 67762306a36Sopenharmony_ci * the point of re-selection until our idle 67862306a36Sopenharmony_ci * loop determines that neither of our FIFOs 67962306a36Sopenharmony_ci * are busy. This handles the non-packetized 68062306a36Sopenharmony_ci * case nicely as we will not return to the 68162306a36Sopenharmony_ci * idle loop until the busfree at the end of 68262306a36Sopenharmony_ci * each transaction. 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_ci or SBLKCTL, DIAGLEDEN|DIAGLEDON; 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci /* Clear out all SCBs that have been successfully sent. */ 68762306a36Sopenharmony_ci if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { 68862306a36Sopenharmony_ci /* 68962306a36Sopenharmony_ci * For packetized, the LQO manager clears ENSELO on 69062306a36Sopenharmony_ci * the assertion of SELDO. If we are non-packetized, 69162306a36Sopenharmony_ci * LASTSCB and CURRSCB are accurate. 69262306a36Sopenharmony_ci */ 69362306a36Sopenharmony_ci test SCSISEQ0, ENSELO jnz use_lastscb; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* 69662306a36Sopenharmony_ci * The update is correct for LQOSTAT1 errors. All 69762306a36Sopenharmony_ci * but LQOBUSFREE are handled by kernel interrupts. 69862306a36Sopenharmony_ci * If we see LQOBUSFREE, return to the idle loop. 69962306a36Sopenharmony_ci * Once we are out of the select_out critical section, 70062306a36Sopenharmony_ci * the kernel will cleanup the LQOBUSFREE and we will 70162306a36Sopenharmony_ci * eventually restart the selection if appropriate. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ci test LQOSTAT1, LQOBUSFREE jnz idle_loop; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci /* 70662306a36Sopenharmony_ci * On a phase change oustside of packet boundaries, 70762306a36Sopenharmony_ci * LASTSCB points to the currently active SCB context 70862306a36Sopenharmony_ci * on the bus. 70962306a36Sopenharmony_ci */ 71062306a36Sopenharmony_ci test LQOSTAT2, LQOPHACHGOUTPKT jnz use_lastscb; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci /* 71362306a36Sopenharmony_ci * If the hardware has traversed the whole list, NEXTSCB 71462306a36Sopenharmony_ci * will be NULL, CURRSCB and LASTSCB cannot be trusted, 71562306a36Sopenharmony_ci * but MAXCMDCNT is accurate. If we stop part way through 71662306a36Sopenharmony_ci * the list or only had one command to issue, NEXTSCB[1] is 71762306a36Sopenharmony_ci * not NULL and LASTSCB is the last command to go out. 71862306a36Sopenharmony_ci */ 71962306a36Sopenharmony_ci cmp NEXTSCB[1], SCB_LIST_NULL jne use_lastscb; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci /* 72262306a36Sopenharmony_ci * Brute force walk. 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ci bmov SCBPTR, WAITING_TID_HEAD, 2; 72562306a36Sopenharmony_ci mvi SEQINTCTL, INTVEC1DSL; 72662306a36Sopenharmony_ci mvi MODE_PTR, MK_MODE(M_CFG, M_CFG); 72762306a36Sopenharmony_ci mov A, MAXCMDCNT; 72862306a36Sopenharmony_ci mvi MODE_PTR, MK_MODE(M_SCSI, M_SCSI); 72962306a36Sopenharmony_ci clr SEQINTCTL; 73062306a36Sopenharmony_cifind_lastscb_loop: 73162306a36Sopenharmony_ci dec A; 73262306a36Sopenharmony_ci test A, 0xFF jz found_last_sent_scb; 73362306a36Sopenharmony_ci bmov SCBPTR, SCB_NEXT, 2; 73462306a36Sopenharmony_ci jmp find_lastscb_loop; 73562306a36Sopenharmony_ciuse_lastscb: 73662306a36Sopenharmony_ci bmov SCBPTR, LASTSCB, 2; 73762306a36Sopenharmony_cifound_last_sent_scb: 73862306a36Sopenharmony_ci bmov CURRSCB, SCBPTR, 2; 73962306a36Sopenharmony_cicurscb_ww_done: 74062306a36Sopenharmony_ci } else { 74162306a36Sopenharmony_ci bmov SCBPTR, CURRSCB, 2; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci /* 74562306a36Sopenharmony_ci * The whole list made it. Clear our tail pointer to indicate 74662306a36Sopenharmony_ci * that the per-target selection queue is now empty. 74762306a36Sopenharmony_ci */ 74862306a36Sopenharmony_ci cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_clear_tail; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci /* 75162306a36Sopenharmony_ci * Requeue any SCBs not sent, to the tail of the waiting Q. 75262306a36Sopenharmony_ci * We know that neither the per-TID list nor the list of 75362306a36Sopenharmony_ci * TIDs is empty. Use this knowledge to our advantage and 75462306a36Sopenharmony_ci * queue the remainder to the tail of the global execution 75562306a36Sopenharmony_ci * queue. 75662306a36Sopenharmony_ci */ 75762306a36Sopenharmony_ci bmov REG0, SCB_NEXT, 2; 75862306a36Sopenharmony_ciselect_out_queue_remainder: 75962306a36Sopenharmony_ci bmov SCBPTR, WAITING_TID_TAIL, 2; 76062306a36Sopenharmony_ci bmov SCB_NEXT2, REG0, 2; 76162306a36Sopenharmony_ci bmov WAITING_TID_TAIL, REG0, 2; 76262306a36Sopenharmony_ci jmp select_out_inc_tid_q; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ciselect_out_clear_tail: 76562306a36Sopenharmony_ci /* 76662306a36Sopenharmony_ci * Queue any pending MK_MESSAGE SCB for this target now 76762306a36Sopenharmony_ci * that the queue is empty. 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_ci test SEQ_FLAGS2, PENDING_MK_MESSAGE jz select_out_no_mk_message_scb; 77062306a36Sopenharmony_ci mov A, MK_MESSAGE_SCSIID; 77162306a36Sopenharmony_ci cmp SCB_SCSIID, A jne select_out_no_mk_message_scb; 77262306a36Sopenharmony_ci and SEQ_FLAGS2, ~PENDING_MK_MESSAGE; 77362306a36Sopenharmony_ci bmov REG0, MK_MESSAGE_SCB, 2; 77462306a36Sopenharmony_ci jmp select_out_queue_remainder; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ciselect_out_no_mk_message_scb: 77762306a36Sopenharmony_ci /* 77862306a36Sopenharmony_ci * Clear this target's execution tail and increment the queue. 77962306a36Sopenharmony_ci */ 78062306a36Sopenharmony_ci shr DINDEX, 3, SCB_SCSIID; 78162306a36Sopenharmony_ci or DINDEX, 1; /* Want only the second byte */ 78262306a36Sopenharmony_ci mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8); 78362306a36Sopenharmony_ci mvi DINDIR, SCB_LIST_NULL; 78462306a36Sopenharmony_ciselect_out_inc_tid_q: 78562306a36Sopenharmony_ci bmov SCBPTR, WAITING_TID_HEAD, 2; 78662306a36Sopenharmony_ci bmov WAITING_TID_HEAD, SCB_NEXT2, 2; 78762306a36Sopenharmony_ci cmp WAITING_TID_HEAD[1], SCB_LIST_NULL jne . + 2; 78862306a36Sopenharmony_ci mvi WAITING_TID_TAIL[1], SCB_LIST_NULL; 78962306a36Sopenharmony_ci bmov SCBPTR, CURRSCB, 2; 79062306a36Sopenharmony_ci mvi CLRSINT0, CLRSELDO; 79162306a36Sopenharmony_ci test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_mode_cleared; 79262306a36Sopenharmony_ci test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_mode_cleared; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* 79562306a36Sopenharmony_ci * If this is a packetized connection, return to our 79662306a36Sopenharmony_ci * idle_loop and let our interrupt handler deal with 79762306a36Sopenharmony_ci * any connection setup/teardown issues. The only 79862306a36Sopenharmony_ci * exceptions are the case of MK_MESSAGE and task management 79962306a36Sopenharmony_ci * SCBs. 80062306a36Sopenharmony_ci */ 80162306a36Sopenharmony_ci if ((ahd->bugs & AHD_LQO_ATNO_BUG) != 0) { 80262306a36Sopenharmony_ci /* 80362306a36Sopenharmony_ci * In the A, the LQO manager transitions to LQOSTOP0 even if 80462306a36Sopenharmony_ci * we have selected out with ATN asserted and the target 80562306a36Sopenharmony_ci * REQs in a non-packet phase. 80662306a36Sopenharmony_ci */ 80762306a36Sopenharmony_ci test SCB_CONTROL, MK_MESSAGE jz select_out_no_message; 80862306a36Sopenharmony_ci test SCSISIGO, ATNO jnz select_out_non_packetized; 80962306a36Sopenharmony_ciselect_out_no_message: 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci test LQOSTAT2, LQOSTOP0 jz select_out_non_packetized; 81262306a36Sopenharmony_ci test SCB_TASK_MANAGEMENT, 0xFF jz idle_loop; 81362306a36Sopenharmony_ci SET_SEQINTCODE(TASKMGMT_FUNC_COMPLETE) 81462306a36Sopenharmony_ci jmp idle_loop; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ciselect_out_non_packetized: 81762306a36Sopenharmony_ci /* Non packetized request. */ 81862306a36Sopenharmony_ci and SCSISEQ0, ~ENSELO; 81962306a36Sopenharmony_ci if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { 82062306a36Sopenharmony_ci /* 82162306a36Sopenharmony_ci * Test to ensure that the bus has not 82262306a36Sopenharmony_ci * already gone free prior to clearing 82362306a36Sopenharmony_ci * any stale busfree status. This avoids 82462306a36Sopenharmony_ci * a window whereby a busfree just after 82562306a36Sopenharmony_ci * a selection could be missed. 82662306a36Sopenharmony_ci */ 82762306a36Sopenharmony_ci test SCSISIGI, BSYI jz . + 2; 82862306a36Sopenharmony_ci mvi CLRSINT1,CLRBUSFREE; 82962306a36Sopenharmony_ci or SIMODE1, ENBUSFREE; 83062306a36Sopenharmony_ci } 83162306a36Sopenharmony_ci mov SAVED_SCSIID, SCB_SCSIID; 83262306a36Sopenharmony_ci mov SAVED_LUN, SCB_LUN; 83362306a36Sopenharmony_ci mvi SEQ_FLAGS, NO_CDB_SENT; 83462306a36Sopenharmony_ciEND_CRITICAL; 83562306a36Sopenharmony_ci or SXFRCTL0, SPIOEN; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci /* 83862306a36Sopenharmony_ci * As soon as we get a successful selection, the target 83962306a36Sopenharmony_ci * should go into the message out phase since we have ATN 84062306a36Sopenharmony_ci * asserted. 84162306a36Sopenharmony_ci */ 84262306a36Sopenharmony_ci mvi MSG_OUT, MSG_IDENTIFYFLAG; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci /* 84562306a36Sopenharmony_ci * Main loop for information transfer phases. Wait for the 84662306a36Sopenharmony_ci * target to assert REQ before checking MSG, C/D and I/O for 84762306a36Sopenharmony_ci * the bus phase. 84862306a36Sopenharmony_ci */ 84962306a36Sopenharmony_cimesgin_phasemis: 85062306a36Sopenharmony_ciITloop: 85162306a36Sopenharmony_ci call phase_lock; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci mov A, LASTPHASE; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci test A, ~P_DATAIN_DT jz p_data; 85662306a36Sopenharmony_ci cmp A,P_COMMAND je p_command; 85762306a36Sopenharmony_ci cmp A,P_MESGOUT je p_mesgout; 85862306a36Sopenharmony_ci cmp A,P_STATUS je p_status; 85962306a36Sopenharmony_ci cmp A,P_MESGIN je p_mesgin; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci SET_SEQINTCODE(BAD_PHASE) 86262306a36Sopenharmony_ci jmp ITloop; /* Try reading the bus again. */ 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci/* 86562306a36Sopenharmony_ci * Command phase. Set up the DMA registers and let 'er rip. 86662306a36Sopenharmony_ci */ 86762306a36Sopenharmony_cip_command: 86862306a36Sopenharmony_ci test SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay; 86962306a36Sopenharmony_ci SET_SEQINTCODE(PROTO_VIOLATION) 87062306a36Sopenharmony_cip_command_okay: 87162306a36Sopenharmony_ci test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) 87262306a36Sopenharmony_ci jnz p_command_allocate_fifo; 87362306a36Sopenharmony_ci /* 87462306a36Sopenharmony_ci * Command retry. Free our current FIFO and 87562306a36Sopenharmony_ci * re-allocate a FIFO so transfer state is 87662306a36Sopenharmony_ci * reset. 87762306a36Sopenharmony_ci */ 87862306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 87962306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 88062306a36Sopenharmony_ci mvi DFFSXFRCTL, RSTCHN|CLRSHCNT; 88162306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 88262306a36Sopenharmony_cip_command_allocate_fifo: 88362306a36Sopenharmony_ci bmov ALLOCFIFO_SCBPTR, SCBPTR, 2; 88462306a36Sopenharmony_ci call allocate_fifo; 88562306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 88662306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 88762306a36Sopenharmony_ci add NONE, -17, SCB_CDB_LEN; 88862306a36Sopenharmony_ci jnc p_command_embedded; 88962306a36Sopenharmony_cip_command_from_host: 89062306a36Sopenharmony_ci bmov HADDR[0], SCB_HOST_CDB_PTR, 9; 89162306a36Sopenharmony_ci mvi SG_CACHE_PRE, LAST_SEG; 89262306a36Sopenharmony_ci mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN); 89362306a36Sopenharmony_ci jmp p_command_xfer; 89462306a36Sopenharmony_cip_command_embedded: 89562306a36Sopenharmony_ci bmov SHCNT[0], SCB_CDB_LEN, 1; 89662306a36Sopenharmony_ci bmov DFDAT, SCB_CDB_STORE, 16; 89762306a36Sopenharmony_ci mvi DFCNTRL, SCSIEN; 89862306a36Sopenharmony_cip_command_xfer: 89962306a36Sopenharmony_ci and SEQ_FLAGS, ~NO_CDB_SENT; 90062306a36Sopenharmony_ci if ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0) { 90162306a36Sopenharmony_ci /* 90262306a36Sopenharmony_ci * To speed up CDB delivery in Rev B, all CDB acks 90362306a36Sopenharmony_ci * are "released" to the output sync as soon as the 90462306a36Sopenharmony_ci * command phase starts. There is only one problem 90562306a36Sopenharmony_ci * with this approach. If the target changes phase 90662306a36Sopenharmony_ci * before all data are sent, we have left over acks 90762306a36Sopenharmony_ci * that can go out on the bus in a data phase. Due 90862306a36Sopenharmony_ci * to other chip contraints, this only happens if 90962306a36Sopenharmony_ci * the target goes to data-in, but if the acks go 91062306a36Sopenharmony_ci * out before we can test SDONE, we'll think that 91162306a36Sopenharmony_ci * the transfer has completed successfully. Work 91262306a36Sopenharmony_ci * around this by taking advantage of the 400ns or 91362306a36Sopenharmony_ci * 800ns dead time between command phase and the REQ 91462306a36Sopenharmony_ci * of the new phase. If the transfer has completed 91562306a36Sopenharmony_ci * successfully, SCSIEN should fall *long* before we 91662306a36Sopenharmony_ci * see a phase change. We thus treat any phasemiss 91762306a36Sopenharmony_ci * that occurs before SCSIEN falls as an incomplete 91862306a36Sopenharmony_ci * transfer. 91962306a36Sopenharmony_ci */ 92062306a36Sopenharmony_ci test SSTAT1, PHASEMIS jnz p_command_xfer_failed; 92162306a36Sopenharmony_ci test DFCNTRL, SCSIEN jnz . - 1; 92262306a36Sopenharmony_ci } else { 92362306a36Sopenharmony_ci test DFCNTRL, SCSIEN jnz .; 92462306a36Sopenharmony_ci } 92562306a36Sopenharmony_ci /* 92662306a36Sopenharmony_ci * DMA Channel automatically disabled. 92762306a36Sopenharmony_ci * Don't allow a data phase if the command 92862306a36Sopenharmony_ci * was not fully transferred. 92962306a36Sopenharmony_ci */ 93062306a36Sopenharmony_ci test SSTAT2, SDONE jnz ITloop; 93162306a36Sopenharmony_cip_command_xfer_failed: 93262306a36Sopenharmony_ci or SEQ_FLAGS, NO_CDB_SENT; 93362306a36Sopenharmony_ci jmp ITloop; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci/* 93762306a36Sopenharmony_ci * Status phase. Wait for the data byte to appear, then read it 93862306a36Sopenharmony_ci * and store it into the SCB. 93962306a36Sopenharmony_ci */ 94062306a36Sopenharmony_ciSET_SRC_MODE M_SCSI; 94162306a36Sopenharmony_ciSET_DST_MODE M_SCSI; 94262306a36Sopenharmony_cip_status: 94362306a36Sopenharmony_ci test SEQ_FLAGS,NOT_IDENTIFIED jnz mesgin_proto_violation; 94462306a36Sopenharmony_cip_status_okay: 94562306a36Sopenharmony_ci mov SCB_SCSI_STATUS, SCSIDAT; 94662306a36Sopenharmony_ci or SCB_CONTROL, STATUS_RCVD; 94762306a36Sopenharmony_ci jmp ITloop; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci/* 95062306a36Sopenharmony_ci * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full 95162306a36Sopenharmony_ci * indentify message sequence and send it to the target. The host may 95262306a36Sopenharmony_ci * override this behavior by setting the MK_MESSAGE bit in the SCB 95362306a36Sopenharmony_ci * control byte. This will cause us to interrupt the host and allow 95462306a36Sopenharmony_ci * it to handle the message phase completely on its own. If the bit 95562306a36Sopenharmony_ci * associated with this target is set, we will also interrupt the host, 95662306a36Sopenharmony_ci * thereby allowing it to send a message on the next selection regardless 95762306a36Sopenharmony_ci * of the transaction being sent. 95862306a36Sopenharmony_ci * 95962306a36Sopenharmony_ci * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. 96062306a36Sopenharmony_ci * This is done to allow the host to send messages outside of an identify 96162306a36Sopenharmony_ci * sequence while protecting the seqencer from testing the MK_MESSAGE bit 96262306a36Sopenharmony_ci * on an SCB that might not be for the current nexus. (For example, a 96362306a36Sopenharmony_ci * BDR message in response to a bad reselection would leave us pointed to 96462306a36Sopenharmony_ci * an SCB that doesn't have anything to do with the current target). 96562306a36Sopenharmony_ci * 96662306a36Sopenharmony_ci * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, 96762306a36Sopenharmony_ci * bus device reset). 96862306a36Sopenharmony_ci * 96962306a36Sopenharmony_ci * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, 97062306a36Sopenharmony_ci * in case the target decides to put us in this phase for some strange 97162306a36Sopenharmony_ci * reason. 97262306a36Sopenharmony_ci */ 97362306a36Sopenharmony_cip_mesgout_retry: 97462306a36Sopenharmony_ci /* Turn on ATN for the retry */ 97562306a36Sopenharmony_ci mvi SCSISIGO, ATNO; 97662306a36Sopenharmony_cip_mesgout: 97762306a36Sopenharmony_ci mov SINDEX, MSG_OUT; 97862306a36Sopenharmony_ci cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; 97962306a36Sopenharmony_ci test SCB_CONTROL,MK_MESSAGE jnz host_message_loop; 98062306a36Sopenharmony_cip_mesgout_identify: 98162306a36Sopenharmony_ci or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN; 98262306a36Sopenharmony_ci test SCB_CONTROL, DISCENB jnz . + 2; 98362306a36Sopenharmony_ci and SINDEX, ~DISCENB; 98462306a36Sopenharmony_ci/* 98562306a36Sopenharmony_ci * Send a tag message if TAG_ENB is set in the SCB control block. 98662306a36Sopenharmony_ci * Use SCB_NONPACKET_TAG as the tag value. 98762306a36Sopenharmony_ci */ 98862306a36Sopenharmony_cip_mesgout_tag: 98962306a36Sopenharmony_ci test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte; 99062306a36Sopenharmony_ci mov SCSIDAT, SINDEX; /* Send the identify message */ 99162306a36Sopenharmony_ci call phase_lock; 99262306a36Sopenharmony_ci cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; 99362306a36Sopenharmony_ci and SCSIDAT,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL; 99462306a36Sopenharmony_ci call phase_lock; 99562306a36Sopenharmony_ci cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; 99662306a36Sopenharmony_ci mov SCBPTR jmp p_mesgout_onebyte; 99762306a36Sopenharmony_ci/* 99862306a36Sopenharmony_ci * Interrupt the driver, and allow it to handle this message 99962306a36Sopenharmony_ci * phase and any required retries. 100062306a36Sopenharmony_ci */ 100162306a36Sopenharmony_cip_mesgout_from_host: 100262306a36Sopenharmony_ci cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; 100362306a36Sopenharmony_ci jmp host_message_loop; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cip_mesgout_onebyte: 100662306a36Sopenharmony_ci mvi CLRSINT1, CLRATNO; 100762306a36Sopenharmony_ci mov SCSIDAT, SINDEX; 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci/* 101062306a36Sopenharmony_ci * If the next bus phase after ATN drops is message out, it means 101162306a36Sopenharmony_ci * that the target is requesting that the last message(s) be resent. 101262306a36Sopenharmony_ci */ 101362306a36Sopenharmony_ci call phase_lock; 101462306a36Sopenharmony_ci cmp LASTPHASE, P_MESGOUT je p_mesgout_retry; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_cip_mesgout_done: 101762306a36Sopenharmony_ci mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ 101862306a36Sopenharmony_ci mov LAST_MSG, MSG_OUT; 101962306a36Sopenharmony_ci mvi MSG_OUT, MSG_NOOP; /* No message left */ 102062306a36Sopenharmony_ci jmp ITloop; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci/* 102362306a36Sopenharmony_ci * Message in phase. Bytes are read using Automatic PIO mode. 102462306a36Sopenharmony_ci */ 102562306a36Sopenharmony_cip_mesgin: 102662306a36Sopenharmony_ci /* read the 1st message byte */ 102762306a36Sopenharmony_ci mvi ACCUM call inb_first; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci test A,MSG_IDENTIFYFLAG jnz mesgin_identify; 103062306a36Sopenharmony_ci cmp A,MSG_DISCONNECT je mesgin_disconnect; 103162306a36Sopenharmony_ci cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; 103262306a36Sopenharmony_ci cmp ALLZEROS,A je mesgin_complete; 103362306a36Sopenharmony_ci cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; 103462306a36Sopenharmony_ci cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue; 103562306a36Sopenharmony_ci cmp A,MSG_NOOP je mesgin_done; 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci/* 103862306a36Sopenharmony_ci * Pushed message loop to allow the kernel to 103962306a36Sopenharmony_ci * run it's own message state engine. To avoid an 104062306a36Sopenharmony_ci * extra nop instruction after signaling the kernel, 104162306a36Sopenharmony_ci * we perform the phase_lock before checking to see 104262306a36Sopenharmony_ci * if we should exit the loop and skip the phase_lock 104362306a36Sopenharmony_ci * in the ITloop. Performing back to back phase_locks 104462306a36Sopenharmony_ci * shouldn't hurt, but why do it twice... 104562306a36Sopenharmony_ci */ 104662306a36Sopenharmony_cihost_message_loop: 104762306a36Sopenharmony_ci call phase_lock; /* Benign the first time through. */ 104862306a36Sopenharmony_ci SET_SEQINTCODE(HOST_MSG_LOOP) 104962306a36Sopenharmony_ci cmp RETURN_1, EXIT_MSG_LOOP je ITloop; 105062306a36Sopenharmony_ci cmp RETURN_1, CONT_MSG_LOOP_WRITE jne . + 3; 105162306a36Sopenharmony_ci mov SCSIDAT, RETURN_2; 105262306a36Sopenharmony_ci jmp host_message_loop; 105362306a36Sopenharmony_ci /* Must be CONT_MSG_LOOP_READ */ 105462306a36Sopenharmony_ci mov NONE, SCSIDAT; /* ACK Byte */ 105562306a36Sopenharmony_ci jmp host_message_loop; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_cimesgin_ign_wide_residue: 105862306a36Sopenharmony_ci mov SAVED_MODE, MODE_PTR; 105962306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 106062306a36Sopenharmony_ci shr NEGOADDR, 4, SAVED_SCSIID; 106162306a36Sopenharmony_ci mov A, NEGCONOPTS; 106262306a36Sopenharmony_ci RESTORE_MODE(SAVED_MODE) 106362306a36Sopenharmony_ci test A, WIDEXFER jz mesgin_reject; 106462306a36Sopenharmony_ci /* Pull the residue byte */ 106562306a36Sopenharmony_ci mvi REG0 call inb_next; 106662306a36Sopenharmony_ci cmp REG0, 0x01 jne mesgin_reject; 106762306a36Sopenharmony_ci test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2; 106862306a36Sopenharmony_ci test SCB_TASK_ATTRIBUTE, SCB_XFERLEN_ODD jnz mesgin_done; 106962306a36Sopenharmony_ci SET_SEQINTCODE(IGN_WIDE_RES) 107062306a36Sopenharmony_ci jmp mesgin_done; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cimesgin_proto_violation: 107362306a36Sopenharmony_ci SET_SEQINTCODE(PROTO_VIOLATION) 107462306a36Sopenharmony_ci jmp mesgin_done; 107562306a36Sopenharmony_cimesgin_reject: 107662306a36Sopenharmony_ci mvi MSG_MESSAGE_REJECT call mk_mesg; 107762306a36Sopenharmony_cimesgin_done: 107862306a36Sopenharmony_ci mov NONE,SCSIDAT; /*dummy read from latch to ACK*/ 107962306a36Sopenharmony_ci jmp ITloop; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci#define INDEX_DISC_LIST(scsiid, lun) \ 108262306a36Sopenharmony_ci and A, 0xC0, scsiid; \ 108362306a36Sopenharmony_ci or SCBPTR, A, lun; \ 108462306a36Sopenharmony_ci clr SCBPTR[1]; \ 108562306a36Sopenharmony_ci and SINDEX, 0x30, scsiid; \ 108662306a36Sopenharmony_ci shr SINDEX, 3; /* Multiply by 2 */ \ 108762306a36Sopenharmony_ci add SINDEX, (SCB_DISCONNECTED_LISTS & 0xFF); \ 108862306a36Sopenharmony_ci mvi SINDEX[1], ((SCB_DISCONNECTED_LISTS >> 8) & 0xFF) 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_cimesgin_identify: 109162306a36Sopenharmony_ci /* 109262306a36Sopenharmony_ci * Determine whether a target is using tagged or non-tagged 109362306a36Sopenharmony_ci * transactions by first looking at the transaction stored in 109462306a36Sopenharmony_ci * the per-device, disconnected array. If there is no untagged 109562306a36Sopenharmony_ci * transaction for this target, this must be a tagged transaction. 109662306a36Sopenharmony_ci */ 109762306a36Sopenharmony_ci and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A; 109862306a36Sopenharmony_ci INDEX_DISC_LIST(SAVED_SCSIID, SAVED_LUN); 109962306a36Sopenharmony_ci bmov DINDEX, SINDEX, 2; 110062306a36Sopenharmony_ci bmov REG0, SINDIR, 2; 110162306a36Sopenharmony_ci cmp REG0[1], SCB_LIST_NULL je snoop_tag; 110262306a36Sopenharmony_ci /* Untagged. Clear the busy table entry and setup the SCB. */ 110362306a36Sopenharmony_ci bmov DINDIR, ALLONES, 2; 110462306a36Sopenharmony_ci bmov SCBPTR, REG0, 2; 110562306a36Sopenharmony_ci jmp setup_SCB; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci/* 110862306a36Sopenharmony_ci * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. 110962306a36Sopenharmony_ci * If we get one, we use the tag returned to find the proper 111062306a36Sopenharmony_ci * SCB. After receiving the tag, look for the SCB at SCB locations tag and 111162306a36Sopenharmony_ci * tag + 256. 111262306a36Sopenharmony_ci */ 111362306a36Sopenharmony_cisnoop_tag: 111462306a36Sopenharmony_ci if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { 111562306a36Sopenharmony_ci or SEQ_FLAGS, 0x80; 111662306a36Sopenharmony_ci } 111762306a36Sopenharmony_ci mov NONE, SCSIDAT; /* ACK Identify MSG */ 111862306a36Sopenharmony_ci call phase_lock; 111962306a36Sopenharmony_ci if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { 112062306a36Sopenharmony_ci or SEQ_FLAGS, 0x1; 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci cmp LASTPHASE, P_MESGIN jne not_found_ITloop; 112362306a36Sopenharmony_ci if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { 112462306a36Sopenharmony_ci or SEQ_FLAGS, 0x2; 112562306a36Sopenharmony_ci } 112662306a36Sopenharmony_ci cmp SCSIBUS, MSG_SIMPLE_Q_TAG jne not_found; 112762306a36Sopenharmony_ciget_tag: 112862306a36Sopenharmony_ci clr SCBPTR[1]; 112962306a36Sopenharmony_ci mvi SCBPTR call inb_next; /* tag value */ 113062306a36Sopenharmony_civerify_scb: 113162306a36Sopenharmony_ci test SCB_CONTROL,DISCONNECTED jz verify_other_scb; 113262306a36Sopenharmony_ci mov A, SAVED_SCSIID; 113362306a36Sopenharmony_ci cmp SCB_SCSIID, A jne verify_other_scb; 113462306a36Sopenharmony_ci mov A, SAVED_LUN; 113562306a36Sopenharmony_ci cmp SCB_LUN, A je setup_SCB_disconnected; 113662306a36Sopenharmony_civerify_other_scb: 113762306a36Sopenharmony_ci xor SCBPTR[1], 1; 113862306a36Sopenharmony_ci test SCBPTR[1], 0xFF jnz verify_scb; 113962306a36Sopenharmony_ci jmp not_found; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci/* 114262306a36Sopenharmony_ci * Ensure that the SCB the tag points to is for 114362306a36Sopenharmony_ci * an SCB transaction to the reconnecting target. 114462306a36Sopenharmony_ci */ 114562306a36Sopenharmony_cisetup_SCB: 114662306a36Sopenharmony_ci if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { 114762306a36Sopenharmony_ci or SEQ_FLAGS, 0x10; 114862306a36Sopenharmony_ci } 114962306a36Sopenharmony_ci test SCB_CONTROL,DISCONNECTED jz not_found; 115062306a36Sopenharmony_cisetup_SCB_disconnected: 115162306a36Sopenharmony_ci and SCB_CONTROL,~DISCONNECTED; 115262306a36Sopenharmony_ci clr SEQ_FLAGS; /* make note of IDENTIFY */ 115362306a36Sopenharmony_ci test SCB_SGPTR, SG_LIST_NULL jnz . + 3; 115462306a36Sopenharmony_ci bmov ALLOCFIFO_SCBPTR, SCBPTR, 2; 115562306a36Sopenharmony_ci call allocate_fifo; 115662306a36Sopenharmony_ci /* See if the host wants to send a message upon reconnection */ 115762306a36Sopenharmony_ci test SCB_CONTROL, MK_MESSAGE jz mesgin_done; 115862306a36Sopenharmony_ci mvi HOST_MSG call mk_mesg; 115962306a36Sopenharmony_ci jmp mesgin_done; 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_cinot_found: 116262306a36Sopenharmony_ci SET_SEQINTCODE(NO_MATCH) 116362306a36Sopenharmony_ci jmp mesgin_done; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_cinot_found_ITloop: 116662306a36Sopenharmony_ci SET_SEQINTCODE(NO_MATCH) 116762306a36Sopenharmony_ci jmp ITloop; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci/* 117062306a36Sopenharmony_ci * We received a "command complete" message. Put the SCB on the complete 117162306a36Sopenharmony_ci * queue and trigger a completion interrupt via the idle loop. Before doing 117262306a36Sopenharmony_ci * so, check to see if there is a residual or the status byte is something 117362306a36Sopenharmony_ci * other than STATUS_GOOD (0). In either of these conditions, we upload the 117462306a36Sopenharmony_ci * SCB back to the host so it can process this information. 117562306a36Sopenharmony_ci */ 117662306a36Sopenharmony_cimesgin_complete: 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci /* 117962306a36Sopenharmony_ci * If ATN is raised, we still want to give the target a message. 118062306a36Sopenharmony_ci * Perhaps there was a parity error on this last message byte. 118162306a36Sopenharmony_ci * Either way, the target should take us to message out phase 118262306a36Sopenharmony_ci * and then attempt to complete the command again. We should use a 118362306a36Sopenharmony_ci * critical section here to guard against a timeout triggering 118462306a36Sopenharmony_ci * for this command and setting ATN while we are still processing 118562306a36Sopenharmony_ci * the completion. 118662306a36Sopenharmony_ci test SCSISIGI, ATNI jnz mesgin_done; 118762306a36Sopenharmony_ci */ 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci /* 119062306a36Sopenharmony_ci * If we are identified and have successfully sent the CDB, 119162306a36Sopenharmony_ci * any status will do. Optimize this fast path. 119262306a36Sopenharmony_ci */ 119362306a36Sopenharmony_ci test SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation; 119462306a36Sopenharmony_ci test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci /* 119762306a36Sopenharmony_ci * If the target never sent an identify message but instead went 119862306a36Sopenharmony_ci * to mesgin to give an invalid message, let the host abort us. 119962306a36Sopenharmony_ci */ 120062306a36Sopenharmony_ci test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci /* 120362306a36Sopenharmony_ci * If we recevied good status but never successfully sent the 120462306a36Sopenharmony_ci * cdb, abort the command. 120562306a36Sopenharmony_ci */ 120662306a36Sopenharmony_ci test SCB_SCSI_STATUS,0xff jnz complete_accepted; 120762306a36Sopenharmony_ci test SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation; 120862306a36Sopenharmony_cicomplete_accepted: 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci /* 121162306a36Sopenharmony_ci * See if we attempted to deliver a message but the target ingnored us. 121262306a36Sopenharmony_ci */ 121362306a36Sopenharmony_ci test SCB_CONTROL, MK_MESSAGE jz complete_nomsg; 121462306a36Sopenharmony_ci SET_SEQINTCODE(MKMSG_FAILED) 121562306a36Sopenharmony_cicomplete_nomsg: 121662306a36Sopenharmony_ci call queue_scb_completion; 121762306a36Sopenharmony_ci jmp await_busfree; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ciBEGIN_CRITICAL; 122062306a36Sopenharmony_cifreeze_queue: 122162306a36Sopenharmony_ci /* Cancel any pending select-out. */ 122262306a36Sopenharmony_ci test SSTAT0, SELDO|SELINGO jnz . + 2; 122362306a36Sopenharmony_ci and SCSISEQ0, ~ENSELO; 122462306a36Sopenharmony_ci mov ACCUM_SAVE, A; 122562306a36Sopenharmony_ci clr A; 122662306a36Sopenharmony_ci add QFREEZE_COUNT, 1; 122762306a36Sopenharmony_ci adc QFREEZE_COUNT[1], A; 122862306a36Sopenharmony_ci or SEQ_FLAGS2, SELECTOUT_QFROZEN; 122962306a36Sopenharmony_ci mov A, ACCUM_SAVE ret; 123062306a36Sopenharmony_ciEND_CRITICAL; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci/* 123362306a36Sopenharmony_ci * Complete the current FIFO's SCB if data for this same 123462306a36Sopenharmony_ci * SCB is not transferring in the other FIFO. 123562306a36Sopenharmony_ci */ 123662306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 123762306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 123862306a36Sopenharmony_cipkt_complete_scb_if_fifos_idle: 123962306a36Sopenharmony_ci bmov ARG_1, SCBPTR, 2; 124062306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN; 124162306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 124262306a36Sopenharmony_ci bmov SCBPTR, ARG_1, 2; 124362306a36Sopenharmony_ci test SCB_FIFO_USE_COUNT, 0xFF jnz return; 124462306a36Sopenharmony_ciqueue_scb_completion: 124562306a36Sopenharmony_ci test SCB_SCSI_STATUS,0xff jnz bad_status; 124662306a36Sopenharmony_ci /* 124762306a36Sopenharmony_ci * Check for residuals 124862306a36Sopenharmony_ci */ 124962306a36Sopenharmony_ci test SCB_SGPTR, SG_LIST_NULL jnz complete; /* No xfer */ 125062306a36Sopenharmony_ci test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ 125162306a36Sopenharmony_ci test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; 125262306a36Sopenharmony_cicomplete: 125362306a36Sopenharmony_ciBEGIN_CRITICAL; 125462306a36Sopenharmony_ci bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; 125562306a36Sopenharmony_ci bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; 125662306a36Sopenharmony_ciEND_CRITICAL; 125762306a36Sopenharmony_cibad_status: 125862306a36Sopenharmony_ci cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; 125962306a36Sopenharmony_ci call freeze_queue; 126062306a36Sopenharmony_ciupload_scb: 126162306a36Sopenharmony_ci /* 126262306a36Sopenharmony_ci * Restore SCB TAG since we reuse this field 126362306a36Sopenharmony_ci * in the sequencer. We don't want to corrupt 126462306a36Sopenharmony_ci * it on the host. 126562306a36Sopenharmony_ci */ 126662306a36Sopenharmony_ci bmov SCB_TAG, SCBPTR, 2; 126762306a36Sopenharmony_ciBEGIN_CRITICAL; 126862306a36Sopenharmony_ci or SCB_SGPTR, SG_STATUS_VALID; 126962306a36Sopenharmony_ci mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL; 127062306a36Sopenharmony_ci cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail; 127162306a36Sopenharmony_ci bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; 127262306a36Sopenharmony_ci bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret; 127362306a36Sopenharmony_ciadd_dma_scb_tail: 127462306a36Sopenharmony_ci bmov REG0, SCBPTR, 2; 127562306a36Sopenharmony_ci bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2; 127662306a36Sopenharmony_ci bmov SCB_NEXT_COMPLETE, REG0, 2; 127762306a36Sopenharmony_ci bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret; 127862306a36Sopenharmony_ciEND_CRITICAL; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci/* 128162306a36Sopenharmony_ci * Is it a disconnect message? Set a flag in the SCB to remind us 128262306a36Sopenharmony_ci * and await the bus going free. If this is an untagged transaction 128362306a36Sopenharmony_ci * store the SCB id for it in our untagged target table for lookup on 128462306a36Sopenharmony_ci * a reselection. 128562306a36Sopenharmony_ci */ 128662306a36Sopenharmony_cimesgin_disconnect: 128762306a36Sopenharmony_ci /* 128862306a36Sopenharmony_ci * If ATN is raised, we still want to give the target a message. 128962306a36Sopenharmony_ci * Perhaps there was a parity error on this last message byte 129062306a36Sopenharmony_ci * or we want to abort this command. Either way, the target 129162306a36Sopenharmony_ci * should take us to message out phase and then attempt to 129262306a36Sopenharmony_ci * disconnect again. 129362306a36Sopenharmony_ci * XXX - Wait for more testing. 129462306a36Sopenharmony_ci test SCSISIGI, ATNI jnz mesgin_done; 129562306a36Sopenharmony_ci */ 129662306a36Sopenharmony_ci test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT 129762306a36Sopenharmony_ci jnz mesgin_proto_violation; 129862306a36Sopenharmony_ci or SCB_CONTROL,DISCONNECTED; 129962306a36Sopenharmony_ci test SCB_CONTROL, TAG_ENB jnz await_busfree; 130062306a36Sopenharmony_ciqueue_disc_scb: 130162306a36Sopenharmony_ci bmov REG0, SCBPTR, 2; 130262306a36Sopenharmony_ci INDEX_DISC_LIST(SAVED_SCSIID, SAVED_LUN); 130362306a36Sopenharmony_ci bmov DINDEX, SINDEX, 2; 130462306a36Sopenharmony_ci bmov DINDIR, REG0, 2; 130562306a36Sopenharmony_ci bmov SCBPTR, REG0, 2; 130662306a36Sopenharmony_ci /* FALLTHROUGH */ 130762306a36Sopenharmony_ciawait_busfree: 130862306a36Sopenharmony_ci and SIMODE1, ~ENBUSFREE; 130962306a36Sopenharmony_ci if ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0) { 131062306a36Sopenharmony_ci /* 131162306a36Sopenharmony_ci * In the BUSFREEREV_BUG case, the 131262306a36Sopenharmony_ci * busfree status was cleared at the 131362306a36Sopenharmony_ci * beginning of the connection. 131462306a36Sopenharmony_ci */ 131562306a36Sopenharmony_ci mvi CLRSINT1,CLRBUSFREE; 131662306a36Sopenharmony_ci } 131762306a36Sopenharmony_ci mov NONE, SCSIDAT; /* Ack the last byte */ 131862306a36Sopenharmony_ci test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) 131962306a36Sopenharmony_ci jnz await_busfree_not_m_dff; 132062306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 132162306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 132262306a36Sopenharmony_ciawait_busfree_clrchn: 132362306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN; 132462306a36Sopenharmony_ciawait_busfree_not_m_dff: 132562306a36Sopenharmony_ci /* clear target specific flags */ 132662306a36Sopenharmony_ci mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; 132762306a36Sopenharmony_ci test SSTAT1,REQINIT|BUSFREE jz .; 132862306a36Sopenharmony_ci /* 132962306a36Sopenharmony_ci * We only set BUSFREE status once either a new 133062306a36Sopenharmony_ci * phase has been detected or we are really 133162306a36Sopenharmony_ci * BUSFREE. This allows the driver to know 133262306a36Sopenharmony_ci * that we are active on the bus even though 133362306a36Sopenharmony_ci * no identified transaction exists should a 133462306a36Sopenharmony_ci * timeout occur while awaiting busfree. 133562306a36Sopenharmony_ci */ 133662306a36Sopenharmony_ci mvi LASTPHASE, P_BUSFREE; 133762306a36Sopenharmony_ci test SSTAT1, BUSFREE jnz idle_loop; 133862306a36Sopenharmony_ci SET_SEQINTCODE(MISSED_BUSFREE) 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci/* 134262306a36Sopenharmony_ci * Save data pointers message: 134362306a36Sopenharmony_ci * Copying RAM values back to SCB, for Save Data Pointers message, but 134462306a36Sopenharmony_ci * only if we've actually been into a data phase to change them. This 134562306a36Sopenharmony_ci * protects against bogus data in scratch ram and the residual counts 134662306a36Sopenharmony_ci * since they are only initialized when we go into data_in or data_out. 134762306a36Sopenharmony_ci * Ack the message as soon as possible. 134862306a36Sopenharmony_ci */ 134962306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 135062306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 135162306a36Sopenharmony_cimesgin_sdptrs: 135262306a36Sopenharmony_ci mov NONE,SCSIDAT; /*dummy read from latch to ACK*/ 135362306a36Sopenharmony_ci test SEQ_FLAGS, DPHASE jz ITloop; 135462306a36Sopenharmony_ci call save_pointers; 135562306a36Sopenharmony_ci jmp ITloop; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_cisave_pointers: 135862306a36Sopenharmony_ci /* 135962306a36Sopenharmony_ci * If we are asked to save our position at the end of the 136062306a36Sopenharmony_ci * transfer, just mark us at the end rather than perform a 136162306a36Sopenharmony_ci * full save. 136262306a36Sopenharmony_ci */ 136362306a36Sopenharmony_ci test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz save_pointers_full; 136462306a36Sopenharmony_ci or SCB_SGPTR, SG_LIST_NULL ret; 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_cisave_pointers_full: 136762306a36Sopenharmony_ci /* 136862306a36Sopenharmony_ci * The SCB_DATAPTR becomes the current SHADDR. 136962306a36Sopenharmony_ci * All other information comes directly from our residual 137062306a36Sopenharmony_ci * state. 137162306a36Sopenharmony_ci */ 137262306a36Sopenharmony_ci bmov SCB_DATAPTR, SHADDR, 8; 137362306a36Sopenharmony_ci bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8 ret; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci/* 137662306a36Sopenharmony_ci * Restore pointers message? Data pointers are recopied from the 137762306a36Sopenharmony_ci * SCB anytime we enter a data phase for the first time, so all 137862306a36Sopenharmony_ci * we need to do is clear the DPHASE flag and let the data phase 137962306a36Sopenharmony_ci * code do the rest. We also reset/reallocate the FIFO to make 138062306a36Sopenharmony_ci * sure we have a clean start for the next data or command phase. 138162306a36Sopenharmony_ci */ 138262306a36Sopenharmony_cimesgin_rdptrs: 138362306a36Sopenharmony_ci and SEQ_FLAGS, ~DPHASE; 138462306a36Sopenharmony_ci test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz msgin_rdptrs_get_fifo; 138562306a36Sopenharmony_ci mvi DFFSXFRCTL, RSTCHN|CLRSHCNT; 138662306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 138762306a36Sopenharmony_cimsgin_rdptrs_get_fifo: 138862306a36Sopenharmony_ci call allocate_fifo; 138962306a36Sopenharmony_ci jmp mesgin_done; 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ciphase_lock: 139262306a36Sopenharmony_ci if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { 139362306a36Sopenharmony_ci /* 139462306a36Sopenharmony_ci * Don't ignore persistent REQ assertions just because 139562306a36Sopenharmony_ci * they were asserted within the bus settle delay window. 139662306a36Sopenharmony_ci * This allows us to tolerate devices like the GEM318 139762306a36Sopenharmony_ci * that violate the SCSI spec. We are careful not to 139862306a36Sopenharmony_ci * count REQ while we are waiting for it to fall during 139962306a36Sopenharmony_ci * an async phase due to our asserted ACK. Each 140062306a36Sopenharmony_ci * sequencer instruction takes ~25ns, so the REQ must 140162306a36Sopenharmony_ci * last at least 100ns in order to be counted as a true 140262306a36Sopenharmony_ci * REQ. 140362306a36Sopenharmony_ci */ 140462306a36Sopenharmony_ci test SCSIPHASE, 0xFF jnz phase_locked; 140562306a36Sopenharmony_ci test SCSISIGI, ACKI jnz phase_lock; 140662306a36Sopenharmony_ci test SCSISIGI, REQI jz phase_lock; 140762306a36Sopenharmony_ci test SCSIPHASE, 0xFF jnz phase_locked; 140862306a36Sopenharmony_ci test SCSISIGI, ACKI jnz phase_lock; 140962306a36Sopenharmony_ci test SCSISIGI, REQI jz phase_lock; 141062306a36Sopenharmony_ciphase_locked: 141162306a36Sopenharmony_ci } else { 141262306a36Sopenharmony_ci test SCSIPHASE, 0xFF jz .; 141362306a36Sopenharmony_ci } 141462306a36Sopenharmony_ci test SSTAT1, SCSIPERR jnz phase_lock; 141562306a36Sopenharmony_ciphase_lock_latch_phase: 141662306a36Sopenharmony_ci and LASTPHASE, PHASE_MASK, SCSISIGI ret; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci/* 141962306a36Sopenharmony_ci * Functions to read data in Automatic PIO mode. 142062306a36Sopenharmony_ci * 142162306a36Sopenharmony_ci * An ACK is not sent on input from the target until SCSIDATL is read from. 142262306a36Sopenharmony_ci * So we wait until SCSIDATL is latched (the usual way), then read the data 142362306a36Sopenharmony_ci * byte directly off the bus using SCSIBUSL. When we have pulled the ATN 142462306a36Sopenharmony_ci * line, or we just want to acknowledge the byte, then we do a dummy read 142562306a36Sopenharmony_ci * from SCISDATL. The SCSI spec guarantees that the target will hold the 142662306a36Sopenharmony_ci * data byte on the bus until we send our ACK. 142762306a36Sopenharmony_ci * 142862306a36Sopenharmony_ci * The assumption here is that these are called in a particular sequence, 142962306a36Sopenharmony_ci * and that REQ is already set when inb_first is called. inb_{first,next} 143062306a36Sopenharmony_ci * use the same calling convention as inb. 143162306a36Sopenharmony_ci */ 143262306a36Sopenharmony_ciinb_next: 143362306a36Sopenharmony_ci mov NONE,SCSIDAT; /*dummy read from latch to ACK*/ 143462306a36Sopenharmony_ciinb_next_wait: 143562306a36Sopenharmony_ci /* 143662306a36Sopenharmony_ci * If there is a parity error, wait for the kernel to 143762306a36Sopenharmony_ci * see the interrupt and prepare our message response 143862306a36Sopenharmony_ci * before continuing. 143962306a36Sopenharmony_ci */ 144062306a36Sopenharmony_ci test SCSIPHASE, 0xFF jz .; 144162306a36Sopenharmony_ci test SSTAT1, SCSIPERR jnz inb_next_wait; 144262306a36Sopenharmony_ciinb_next_check_phase: 144362306a36Sopenharmony_ci and LASTPHASE, PHASE_MASK, SCSISIGI; 144462306a36Sopenharmony_ci cmp LASTPHASE, P_MESGIN jne mesgin_phasemis; 144562306a36Sopenharmony_ciinb_first: 144662306a36Sopenharmony_ci clr DINDEX[1]; 144762306a36Sopenharmony_ci mov DINDEX,SINDEX; 144862306a36Sopenharmony_ci mov DINDIR,SCSIBUS ret; /*read byte directly from bus*/ 144962306a36Sopenharmony_ciinb_last: 145062306a36Sopenharmony_ci mov NONE,SCSIDAT ret; /*dummy read from latch to ACK*/ 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_cimk_mesg: 145362306a36Sopenharmony_ci mvi SCSISIGO, ATNO; 145462306a36Sopenharmony_ci mov MSG_OUT,SINDEX ret; 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 145762306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 145862306a36Sopenharmony_cidisable_ccsgen: 145962306a36Sopenharmony_ci test SG_STATE, FETCH_INPROG jz disable_ccsgen_fetch_done; 146062306a36Sopenharmony_ci clr CCSGCTL; 146162306a36Sopenharmony_cidisable_ccsgen_fetch_done: 146262306a36Sopenharmony_ci clr SG_STATE ret; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ciservice_fifo: 146562306a36Sopenharmony_ci /* 146662306a36Sopenharmony_ci * Do we have any prefetch left??? 146762306a36Sopenharmony_ci */ 146862306a36Sopenharmony_ci test SG_STATE, SEGS_AVAIL jnz idle_sg_avail; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci /* 147162306a36Sopenharmony_ci * Can this FIFO have access to the S/G cache yet? 147262306a36Sopenharmony_ci */ 147362306a36Sopenharmony_ci test CCSGCTL, SG_CACHE_AVAIL jz return; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci /* Did we just finish fetching segs? */ 147662306a36Sopenharmony_ci test CCSGCTL, CCSGDONE jnz idle_sgfetch_complete; 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci /* Are we actively fetching segments? */ 147962306a36Sopenharmony_ci test CCSGCTL, CCSGENACK jnz return; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci /* 148262306a36Sopenharmony_ci * Should the other FIFO get the S/G cache first? If 148362306a36Sopenharmony_ci * both FIFOs have been allocated since we last checked 148462306a36Sopenharmony_ci * any FIFO, it is important that we service a FIFO 148562306a36Sopenharmony_ci * that is not actively on the bus first. This guarantees 148662306a36Sopenharmony_ci * that a FIFO will be freed to handle snapshot requests for 148762306a36Sopenharmony_ci * any FIFO that is still on the bus. Chips with RTI do not 148862306a36Sopenharmony_ci * perform snapshots, so don't bother with this test there. 148962306a36Sopenharmony_ci */ 149062306a36Sopenharmony_ci if ((ahd->features & AHD_RTI) == 0) { 149162306a36Sopenharmony_ci /* 149262306a36Sopenharmony_ci * If we're not still receiving SCSI data, 149362306a36Sopenharmony_ci * it is safe to allocate the S/G cache to 149462306a36Sopenharmony_ci * this FIFO. 149562306a36Sopenharmony_ci */ 149662306a36Sopenharmony_ci test DFCNTRL, SCSIEN jz idle_sgfetch_start; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci /* 149962306a36Sopenharmony_ci * Switch to the other FIFO. Non-RTI chips 150062306a36Sopenharmony_ci * also have the "set mode" bug, so we must 150162306a36Sopenharmony_ci * disable interrupts during the switch. 150262306a36Sopenharmony_ci */ 150362306a36Sopenharmony_ci mvi SEQINTCTL, INTVEC1DSL; 150462306a36Sopenharmony_ci xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci /* 150762306a36Sopenharmony_ci * If the other FIFO needs loading, then it 150862306a36Sopenharmony_ci * must not have claimed the S/G cache yet 150962306a36Sopenharmony_ci * (SG_CACHE_AVAIL would have been cleared in 151062306a36Sopenharmony_ci * the original FIFO mode and we test this above). 151162306a36Sopenharmony_ci * Return to the idle loop so we can process the 151262306a36Sopenharmony_ci * FIFO not currently on the bus first. 151362306a36Sopenharmony_ci */ 151462306a36Sopenharmony_ci test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay; 151562306a36Sopenharmony_ci clr SEQINTCTL ret; 151662306a36Sopenharmony_ciidle_sgfetch_okay: 151762306a36Sopenharmony_ci xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); 151862306a36Sopenharmony_ci clr SEQINTCTL; 151962306a36Sopenharmony_ci } 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ciidle_sgfetch_start: 152262306a36Sopenharmony_ci /* 152362306a36Sopenharmony_ci * We fetch a "cacheline aligned" and sized amount of data 152462306a36Sopenharmony_ci * so we don't end up referencing a non-existent page. 152562306a36Sopenharmony_ci * Cacheline aligned is in quotes because the kernel will 152662306a36Sopenharmony_ci * set the prefetch amount to a reasonable level if the 152762306a36Sopenharmony_ci * cacheline size is unknown. 152862306a36Sopenharmony_ci */ 152962306a36Sopenharmony_ci bmov SGHADDR, SCB_RESIDUAL_SGPTR, 4; 153062306a36Sopenharmony_ci mvi SGHCNT, SG_PREFETCH_CNT; 153162306a36Sopenharmony_ci if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { 153262306a36Sopenharmony_ci /* 153362306a36Sopenharmony_ci * Need two instructions between "touches" of SGHADDR. 153462306a36Sopenharmony_ci */ 153562306a36Sopenharmony_ci nop; 153662306a36Sopenharmony_ci } 153762306a36Sopenharmony_ci and SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR; 153862306a36Sopenharmony_ci mvi CCSGCTL, CCSGEN|CCSGRESET; 153962306a36Sopenharmony_ci or SG_STATE, FETCH_INPROG ret; 154062306a36Sopenharmony_ciidle_sgfetch_complete: 154162306a36Sopenharmony_ci /* 154262306a36Sopenharmony_ci * Guard against SG_CACHE_AVAIL activating during sg fetch 154362306a36Sopenharmony_ci * request in the other FIFO. 154462306a36Sopenharmony_ci */ 154562306a36Sopenharmony_ci test SG_STATE, FETCH_INPROG jz return; 154662306a36Sopenharmony_ci clr CCSGCTL; 154762306a36Sopenharmony_ci and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR; 154862306a36Sopenharmony_ci mvi SG_STATE, SEGS_AVAIL|LOADING_NEEDED; 154962306a36Sopenharmony_ciidle_sg_avail: 155062306a36Sopenharmony_ci /* Does the hardware have space for another SG entry? */ 155162306a36Sopenharmony_ci test DFSTATUS, PRELOAD_AVAIL jz return; 155262306a36Sopenharmony_ci /* 155362306a36Sopenharmony_ci * On the A, preloading a segment before HDMAENACK 155462306a36Sopenharmony_ci * comes true can clobber the shadow address of the 155562306a36Sopenharmony_ci * first segment in the S/G FIFO. Wait until it is 155662306a36Sopenharmony_ci * safe to proceed. 155762306a36Sopenharmony_ci */ 155862306a36Sopenharmony_ci if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0) { 155962306a36Sopenharmony_ci test DFCNTRL, HDMAENACK jz return; 156062306a36Sopenharmony_ci } 156162306a36Sopenharmony_ci if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { 156262306a36Sopenharmony_ci bmov HADDR, CCSGRAM, 8; 156362306a36Sopenharmony_ci } else { 156462306a36Sopenharmony_ci bmov HADDR, CCSGRAM, 4; 156562306a36Sopenharmony_ci } 156662306a36Sopenharmony_ci bmov HCNT, CCSGRAM, 3; 156762306a36Sopenharmony_ci bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1; 156862306a36Sopenharmony_ci if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { 156962306a36Sopenharmony_ci and HADDR[4], SG_HIGH_ADDR_BITS, SCB_RESIDUAL_DATACNT[3]; 157062306a36Sopenharmony_ci } 157162306a36Sopenharmony_ci if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { 157262306a36Sopenharmony_ci /* Skip 4 bytes of pad. */ 157362306a36Sopenharmony_ci add CCSGADDR, 4; 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_cisg_advance: 157662306a36Sopenharmony_ci clr A; /* add sizeof(struct scatter) */ 157762306a36Sopenharmony_ci add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF; 157862306a36Sopenharmony_ci adc SCB_RESIDUAL_SGPTR[1],A; 157962306a36Sopenharmony_ci adc SCB_RESIDUAL_SGPTR[2],A; 158062306a36Sopenharmony_ci adc SCB_RESIDUAL_SGPTR[3],A; 158162306a36Sopenharmony_ci mov SINDEX, SCB_RESIDUAL_SGPTR[0]; 158262306a36Sopenharmony_ci test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 3; 158362306a36Sopenharmony_ci or SINDEX, LAST_SEG; 158462306a36Sopenharmony_ci clr SG_STATE; 158562306a36Sopenharmony_ci mov SG_CACHE_PRE, SINDEX; 158662306a36Sopenharmony_ci if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { 158762306a36Sopenharmony_ci /* 158862306a36Sopenharmony_ci * Use SCSIENWRDIS so that SCSIEN is never 158962306a36Sopenharmony_ci * modified by this operation. 159062306a36Sopenharmony_ci */ 159162306a36Sopenharmony_ci or DFCNTRL, PRELOADEN|HDMAEN|SCSIENWRDIS; 159262306a36Sopenharmony_ci } else { 159362306a36Sopenharmony_ci or DFCNTRL, PRELOADEN|HDMAEN; 159462306a36Sopenharmony_ci } 159562306a36Sopenharmony_ci /* 159662306a36Sopenharmony_ci * Do we have another segment in the cache? 159762306a36Sopenharmony_ci */ 159862306a36Sopenharmony_ci add NONE, SG_PREFETCH_CNT_LIMIT, CCSGADDR; 159962306a36Sopenharmony_ci jnc return; 160062306a36Sopenharmony_ci and SG_STATE, ~SEGS_AVAIL ret; 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci/* 160362306a36Sopenharmony_ci * Initialize the DMA address and counter from the SCB. 160462306a36Sopenharmony_ci */ 160562306a36Sopenharmony_ciload_first_seg: 160662306a36Sopenharmony_ci bmov HADDR, SCB_DATAPTR, 11; 160762306a36Sopenharmony_ci and REG_ISR, ~SG_FULL_RESID, SCB_SGPTR[0]; 160862306a36Sopenharmony_ci test SCB_DATACNT[3], SG_LAST_SEG jz . + 2; 160962306a36Sopenharmony_ci or REG_ISR, LAST_SEG; 161062306a36Sopenharmony_ci mov SG_CACHE_PRE, REG_ISR; 161162306a36Sopenharmony_ci mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN); 161262306a36Sopenharmony_ci /* 161362306a36Sopenharmony_ci * Since we've are entering a data phase, we will 161462306a36Sopenharmony_ci * rely on the SCB_RESID* fields. Initialize the 161562306a36Sopenharmony_ci * residual and clear the full residual flag. 161662306a36Sopenharmony_ci */ 161762306a36Sopenharmony_ci and SCB_SGPTR[0], ~SG_FULL_RESID; 161862306a36Sopenharmony_ci bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5; 161962306a36Sopenharmony_ci /* If we need more S/G elements, tell the idle loop */ 162062306a36Sopenharmony_ci test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz . + 2; 162162306a36Sopenharmony_ci mvi SG_STATE, LOADING_NEEDED ret; 162262306a36Sopenharmony_ci clr SG_STATE ret; 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_cip_data_handle_xfer: 162562306a36Sopenharmony_ci call setjmp; 162662306a36Sopenharmony_ci test SG_STATE, LOADING_NEEDED jnz service_fifo; 162762306a36Sopenharmony_cip_data_clear_handler: 162862306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR ret; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_cip_data: 163162306a36Sopenharmony_ci test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed; 163262306a36Sopenharmony_ci SET_SEQINTCODE(PROTO_VIOLATION) 163362306a36Sopenharmony_cip_data_allowed: 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci test SEQ_FLAGS, DPHASE jz data_phase_initialize; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci /* 163862306a36Sopenharmony_ci * If we re-enter the data phase after going through another 163962306a36Sopenharmony_ci * phase, our transfer location has almost certainly been 164062306a36Sopenharmony_ci * corrupted by the interveining, non-data, transfers. Ask 164162306a36Sopenharmony_ci * the host driver to fix us up based on the transfer residual 164262306a36Sopenharmony_ci * unless we already know that we should be bitbucketing. 164362306a36Sopenharmony_ci */ 164462306a36Sopenharmony_ci test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket; 164562306a36Sopenharmony_ci SET_SEQINTCODE(PDATA_REINIT) 164662306a36Sopenharmony_ci jmp data_phase_inbounds; 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_cip_data_bitbucket: 164962306a36Sopenharmony_ci /* 165062306a36Sopenharmony_ci * Turn on `Bit Bucket' mode, wait until the target takes 165162306a36Sopenharmony_ci * us to another phase, and then notify the host. 165262306a36Sopenharmony_ci */ 165362306a36Sopenharmony_ci mov SAVED_MODE, MODE_PTR; 165462306a36Sopenharmony_ci test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) 165562306a36Sopenharmony_ci jnz bitbucket_not_m_dff; 165662306a36Sopenharmony_ci /* 165762306a36Sopenharmony_ci * Ensure that any FIFO contents are cleared out and the 165862306a36Sopenharmony_ci * FIFO free'd prior to starting the BITBUCKET. BITBUCKET 165962306a36Sopenharmony_ci * doesn't discard data already in the FIFO. 166062306a36Sopenharmony_ci */ 166162306a36Sopenharmony_ci mvi DFFSXFRCTL, RSTCHN|CLRSHCNT; 166262306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 166362306a36Sopenharmony_cibitbucket_not_m_dff: 166462306a36Sopenharmony_ci or SXFRCTL1,BITBUCKET; 166562306a36Sopenharmony_ci /* Wait for non-data phase. */ 166662306a36Sopenharmony_ci test SCSIPHASE, ~DATA_PHASE_MASK jz .; 166762306a36Sopenharmony_ci and SXFRCTL1, ~BITBUCKET; 166862306a36Sopenharmony_ci RESTORE_MODE(SAVED_MODE) 166962306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 167062306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 167162306a36Sopenharmony_ci SET_SEQINTCODE(DATA_OVERRUN) 167262306a36Sopenharmony_ci jmp ITloop; 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_cidata_phase_initialize: 167562306a36Sopenharmony_ci test SCB_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket; 167662306a36Sopenharmony_ci call load_first_seg; 167762306a36Sopenharmony_cidata_phase_inbounds: 167862306a36Sopenharmony_ci /* We have seen a data phase at least once. */ 167962306a36Sopenharmony_ci or SEQ_FLAGS, DPHASE; 168062306a36Sopenharmony_ci mov SAVED_MODE, MODE_PTR; 168162306a36Sopenharmony_ci test SG_STATE, LOADING_NEEDED jz data_group_dma_loop; 168262306a36Sopenharmony_ci call p_data_handle_xfer; 168362306a36Sopenharmony_cidata_group_dma_loop: 168462306a36Sopenharmony_ci /* 168562306a36Sopenharmony_ci * The transfer is complete if either the last segment 168662306a36Sopenharmony_ci * completes or the target changes phase. Both conditions 168762306a36Sopenharmony_ci * will clear SCSIEN. 168862306a36Sopenharmony_ci */ 168962306a36Sopenharmony_ci call idle_loop_service_fifos; 169062306a36Sopenharmony_ci call idle_loop_cchan; 169162306a36Sopenharmony_ci call idle_loop_gsfifo; 169262306a36Sopenharmony_ci RESTORE_MODE(SAVED_MODE) 169362306a36Sopenharmony_ci test DFCNTRL, SCSIEN jnz data_group_dma_loop; 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_cidata_group_dmafinish: 169662306a36Sopenharmony_ci /* 169762306a36Sopenharmony_ci * The transfer has terminated either due to a phase 169862306a36Sopenharmony_ci * change, and/or the completion of the last segment. 169962306a36Sopenharmony_ci * We have two goals here. Do as much other work 170062306a36Sopenharmony_ci * as possible while the data fifo drains on a read 170162306a36Sopenharmony_ci * and respond as quickly as possible to the standard 170262306a36Sopenharmony_ci * messages (save data pointers/disconnect and command 170362306a36Sopenharmony_ci * complete) that usually follow a data phase. 170462306a36Sopenharmony_ci */ 170562306a36Sopenharmony_ci call calc_residual; 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci /* 170862306a36Sopenharmony_ci * Go ahead and shut down the DMA engine now. 170962306a36Sopenharmony_ci */ 171062306a36Sopenharmony_ci test DFCNTRL, DIRECTION jnz data_phase_finish; 171162306a36Sopenharmony_cidata_group_fifoflush: 171262306a36Sopenharmony_ci if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { 171362306a36Sopenharmony_ci or DFCNTRL, FIFOFLUSH; 171462306a36Sopenharmony_ci } 171562306a36Sopenharmony_ci /* 171662306a36Sopenharmony_ci * We have enabled the auto-ack feature. This means 171762306a36Sopenharmony_ci * that the controller may have already transferred 171862306a36Sopenharmony_ci * some overrun bytes into the data FIFO and acked them 171962306a36Sopenharmony_ci * on the bus. The only way to detect this situation is 172062306a36Sopenharmony_ci * to wait for LAST_SEG_DONE to come true on a completed 172162306a36Sopenharmony_ci * transfer and then test to see if the data FIFO is 172262306a36Sopenharmony_ci * non-empty. We know there is more data yet to transfer 172362306a36Sopenharmony_ci * if SG_LIST_NULL is not yet set, thus there cannot be 172462306a36Sopenharmony_ci * an overrun. 172562306a36Sopenharmony_ci */ 172662306a36Sopenharmony_ci test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_finish; 172762306a36Sopenharmony_ci test SG_CACHE_SHADOW, LAST_SEG_DONE jz .; 172862306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jnz data_phase_finish; 172962306a36Sopenharmony_ci /* Overrun */ 173062306a36Sopenharmony_ci jmp p_data; 173162306a36Sopenharmony_cidata_phase_finish: 173262306a36Sopenharmony_ci /* 173362306a36Sopenharmony_ci * If the target has left us in data phase, loop through 173462306a36Sopenharmony_ci * the dma code again. We will only loop if there is a 173562306a36Sopenharmony_ci * data overrun. 173662306a36Sopenharmony_ci */ 173762306a36Sopenharmony_ci if ((ahd->flags & AHD_TARGETROLE) != 0) { 173862306a36Sopenharmony_ci test SSTAT0, TARGET jnz data_phase_done; 173962306a36Sopenharmony_ci } 174062306a36Sopenharmony_ci if ((ahd->flags & AHD_INITIATORROLE) != 0) { 174162306a36Sopenharmony_ci test SSTAT1, REQINIT jz .; 174262306a36Sopenharmony_ci test SCSIPHASE, DATA_PHASE_MASK jnz p_data; 174362306a36Sopenharmony_ci } 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_cidata_phase_done: 174662306a36Sopenharmony_ci /* Kill off any pending prefetch */ 174762306a36Sopenharmony_ci call disable_ccsgen; 174862306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR; 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci if ((ahd->flags & AHD_TARGETROLE) != 0) { 175162306a36Sopenharmony_ci test SEQ_FLAGS, DPHASE_PENDING jz ITloop; 175262306a36Sopenharmony_ci /* 175362306a36Sopenharmony_ci and SEQ_FLAGS, ~DPHASE_PENDING; 175462306a36Sopenharmony_ci * For data-in phases, wait for any pending acks from the 175562306a36Sopenharmony_ci * initiator before changing phase. We only need to 175662306a36Sopenharmony_ci * send Ignore Wide Residue messages for data-in phases. 175762306a36Sopenharmony_ci test DFCNTRL, DIRECTION jz target_ITloop; 175862306a36Sopenharmony_ci test SSTAT1, REQINIT jnz .; 175962306a36Sopenharmony_ci test SCB_TASK_ATTRIBUTE, SCB_XFERLEN_ODD jz target_ITloop; 176062306a36Sopenharmony_ci SET_MODE(M_SCSI, M_SCSI) 176162306a36Sopenharmony_ci test NEGCONOPTS, WIDEXFER jz target_ITloop; 176262306a36Sopenharmony_ci */ 176362306a36Sopenharmony_ci /* 176462306a36Sopenharmony_ci * Issue an Ignore Wide Residue Message. 176562306a36Sopenharmony_ci mvi P_MESGIN|BSYO call change_phase; 176662306a36Sopenharmony_ci mvi MSG_IGN_WIDE_RESIDUE call target_outb; 176762306a36Sopenharmony_ci mvi 1 call target_outb; 176862306a36Sopenharmony_ci jmp target_ITloop; 176962306a36Sopenharmony_ci */ 177062306a36Sopenharmony_ci } else { 177162306a36Sopenharmony_ci jmp ITloop; 177262306a36Sopenharmony_ci } 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci/* 177562306a36Sopenharmony_ci * We assume that, even though data may still be 177662306a36Sopenharmony_ci * transferring to the host, that the SCSI side of 177762306a36Sopenharmony_ci * the DMA engine is now in a static state. This 177862306a36Sopenharmony_ci * allows us to update our notion of where we are 177962306a36Sopenharmony_ci * in this transfer. 178062306a36Sopenharmony_ci * 178162306a36Sopenharmony_ci * If, by chance, we stopped before being able 178262306a36Sopenharmony_ci * to fetch additional segments for this transfer, 178362306a36Sopenharmony_ci * yet the last S/G was completely exhausted, 178462306a36Sopenharmony_ci * call our idle loop until it is able to load 178562306a36Sopenharmony_ci * another segment. This will allow us to immediately 178662306a36Sopenharmony_ci * pickup on the next segment on the next data phase. 178762306a36Sopenharmony_ci * 178862306a36Sopenharmony_ci * If we happened to stop on the last segment, then 178962306a36Sopenharmony_ci * our residual information is still correct from 179062306a36Sopenharmony_ci * the idle loop and there is no need to perform 179162306a36Sopenharmony_ci * any fixups. 179262306a36Sopenharmony_ci */ 179362306a36Sopenharmony_ciresidual_before_last_seg: 179462306a36Sopenharmony_ci test MDFFSTAT, SHVALID jnz sgptr_fixup; 179562306a36Sopenharmony_ci /* 179662306a36Sopenharmony_ci * Can never happen from an interrupt as the packetized 179762306a36Sopenharmony_ci * hardware will only interrupt us once SHVALID or 179862306a36Sopenharmony_ci * LAST_SEG_DONE. 179962306a36Sopenharmony_ci */ 180062306a36Sopenharmony_ci call idle_loop_service_fifos; 180162306a36Sopenharmony_ci RESTORE_MODE(SAVED_MODE) 180262306a36Sopenharmony_ci /* FALLTHROUGH */ 180362306a36Sopenharmony_cicalc_residual: 180462306a36Sopenharmony_ci test SG_CACHE_SHADOW, LAST_SEG jz residual_before_last_seg; 180562306a36Sopenharmony_ci /* Record if we've consumed all S/G entries */ 180662306a36Sopenharmony_ci test MDFFSTAT, SHVALID jz . + 2; 180762306a36Sopenharmony_ci bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret; 180862306a36Sopenharmony_ci or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL ret; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_cisgptr_fixup: 181162306a36Sopenharmony_ci /* 181262306a36Sopenharmony_ci * Fixup the residual next S/G pointer. The S/G preload 181362306a36Sopenharmony_ci * feature of the chip allows us to load two elements 181462306a36Sopenharmony_ci * in addition to the currently active element. We 181562306a36Sopenharmony_ci * store the bottom byte of the next S/G pointer in 181662306a36Sopenharmony_ci * the SG_CACHE_PTR register so we can restore the 181762306a36Sopenharmony_ci * correct value when the DMA completes. If the next 181862306a36Sopenharmony_ci * sg ptr value has advanced to the point where higher 181962306a36Sopenharmony_ci * bytes in the address have been affected, fix them 182062306a36Sopenharmony_ci * too. 182162306a36Sopenharmony_ci */ 182262306a36Sopenharmony_ci test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done; 182362306a36Sopenharmony_ci test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done; 182462306a36Sopenharmony_ci add SCB_RESIDUAL_SGPTR[1], -1; 182562306a36Sopenharmony_ci adc SCB_RESIDUAL_SGPTR[2], -1; 182662306a36Sopenharmony_ci adc SCB_RESIDUAL_SGPTR[3], -1; 182762306a36Sopenharmony_cisgptr_fixup_done: 182862306a36Sopenharmony_ci and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW; 182962306a36Sopenharmony_ci clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */ 183062306a36Sopenharmony_ci bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ciexport timer_isr: 183362306a36Sopenharmony_ci call issue_cmdcmplt; 183462306a36Sopenharmony_ci mvi CLRSEQINTSTAT, CLRSEQ_SWTMRTO; 183562306a36Sopenharmony_ci if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { 183662306a36Sopenharmony_ci /* 183762306a36Sopenharmony_ci * In H2A4, the mode pointer is not saved 183862306a36Sopenharmony_ci * for intvec2, but is restored on iret. 183962306a36Sopenharmony_ci * This can lead to the restoration of a 184062306a36Sopenharmony_ci * bogus mode ptr. Manually clear the 184162306a36Sopenharmony_ci * intmask bits and do a normal return 184262306a36Sopenharmony_ci * to compensate. 184362306a36Sopenharmony_ci */ 184462306a36Sopenharmony_ci and SEQINTCTL, ~(INTMASK2|INTMASK1) ret; 184562306a36Sopenharmony_ci } else { 184662306a36Sopenharmony_ci or SEQINTCTL, IRET ret; 184762306a36Sopenharmony_ci } 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ciexport seq_isr: 185062306a36Sopenharmony_ci if ((ahd->features & AHD_RTI) == 0) { 185162306a36Sopenharmony_ci /* 185262306a36Sopenharmony_ci * On RevA Silicon, if the target returns us to data-out 185362306a36Sopenharmony_ci * after we have already trained for data-out, it is 185462306a36Sopenharmony_ci * possible for us to transition the free running clock to 185562306a36Sopenharmony_ci * data-valid before the required 100ns P1 setup time (8 P1 185662306a36Sopenharmony_ci * assertions in fast-160 mode). This will only happen if 185762306a36Sopenharmony_ci * this L-Q is a continuation of a data transfer for which 185862306a36Sopenharmony_ci * we have already prefetched data into our FIFO (LQ/Data 185962306a36Sopenharmony_ci * followed by LQ/Data for the same write transaction). 186062306a36Sopenharmony_ci * This can cause some target implementations to miss the 186162306a36Sopenharmony_ci * first few data transfers on the bus. We detect this 186262306a36Sopenharmony_ci * situation by noticing that this is the first data transfer 186362306a36Sopenharmony_ci * after an LQ (LQIWORKONLQ true), that the data transfer is 186462306a36Sopenharmony_ci * a continuation of a transfer already setup in our FIFO 186562306a36Sopenharmony_ci * (SAVEPTRS interrupt), and that the transaction is a write 186662306a36Sopenharmony_ci * (DIRECTION set in DFCNTRL). The delay is performed by 186762306a36Sopenharmony_ci * disabling SCSIEN until we see the first REQ from the 186862306a36Sopenharmony_ci * target. 186962306a36Sopenharmony_ci * 187062306a36Sopenharmony_ci * First instruction in an ISR cannot be a branch on 187162306a36Sopenharmony_ci * Rev A. Snapshot LQISTAT2 so the status is not missed 187262306a36Sopenharmony_ci * and deffer the test by one instruction. 187362306a36Sopenharmony_ci */ 187462306a36Sopenharmony_ci mov REG_ISR, LQISTAT2; 187562306a36Sopenharmony_ci test REG_ISR, LQIWORKONLQ jz main_isr; 187662306a36Sopenharmony_ci test SEQINTSRC, SAVEPTRS jz main_isr; 187762306a36Sopenharmony_ci test LONGJMP_ADDR[1], INVALID_ADDR jz saveptr_active_fifo; 187862306a36Sopenharmony_ci /* 187962306a36Sopenharmony_ci * Switch to the active FIFO after clearing the snapshot 188062306a36Sopenharmony_ci * savepointer in the current FIFO. We do this so that 188162306a36Sopenharmony_ci * a pending CTXTDONE or SAVEPTR is visible in the active 188262306a36Sopenharmony_ci * FIFO. This status is the only way we can detect if we 188362306a36Sopenharmony_ci * have lost the race (e.g. host paused us) and our attempts 188462306a36Sopenharmony_ci * to disable the channel occurred after all REQs were 188562306a36Sopenharmony_ci * already seen and acked (REQINIT never comes true). 188662306a36Sopenharmony_ci */ 188762306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN; 188862306a36Sopenharmony_ci xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); 188962306a36Sopenharmony_ci test DFCNTRL, DIRECTION jz interrupt_return; 189062306a36Sopenharmony_ci and DFCNTRL, ~SCSIEN; 189162306a36Sopenharmony_cisnapshot_wait_data_valid: 189262306a36Sopenharmony_ci test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return; 189362306a36Sopenharmony_ci test SSTAT1, REQINIT jz snapshot_wait_data_valid; 189462306a36Sopenharmony_cisnapshot_data_valid: 189562306a36Sopenharmony_ci or DFCNTRL, SCSIEN; 189662306a36Sopenharmony_ci or SEQINTCTL, IRET ret; 189762306a36Sopenharmony_cisnapshot_saveptr: 189862306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN; 189962306a36Sopenharmony_ci or SEQINTCTL, IRET ret; 190062306a36Sopenharmony_cimain_isr: 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci test SEQINTSRC, CFG4DATA jnz cfg4data_intr; 190362306a36Sopenharmony_ci test SEQINTSRC, CFG4ISTAT jnz cfg4istat_intr; 190462306a36Sopenharmony_ci test SEQINTSRC, SAVEPTRS jnz saveptr_intr; 190562306a36Sopenharmony_ci test SEQINTSRC, CFG4ICMD jnz cfg4icmd_intr; 190662306a36Sopenharmony_ci SET_SEQINTCODE(INVALID_SEQINT) 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci/* 190962306a36Sopenharmony_ci * There are two types of save pointers interrupts: 191062306a36Sopenharmony_ci * The first is a snapshot save pointers where the current FIFO is not 191162306a36Sopenharmony_ci * active and contains a snapshot of the current poniter information. 191262306a36Sopenharmony_ci * This happens between packets in a stream for a single L_Q. Since we 191362306a36Sopenharmony_ci * are not performing a pointer save, we can safely clear the channel 191462306a36Sopenharmony_ci * so it can be used for other transactions. On RTI capable controllers, 191562306a36Sopenharmony_ci * where snapshots can, and are, disabled, the code to handle this type 191662306a36Sopenharmony_ci * of snapshot is not active. 191762306a36Sopenharmony_ci * 191862306a36Sopenharmony_ci * The second case is a save pointers on an active FIFO which occurs 191962306a36Sopenharmony_ci * if the target changes to a new L_Q or busfrees/QASes and the transfer 192062306a36Sopenharmony_ci * has a residual. This should occur coincident with a ctxtdone. We 192162306a36Sopenharmony_ci * disable the interrupt and allow our active routine to handle the 192262306a36Sopenharmony_ci * save. 192362306a36Sopenharmony_ci */ 192462306a36Sopenharmony_cisaveptr_intr: 192562306a36Sopenharmony_ci if ((ahd->features & AHD_RTI) == 0) { 192662306a36Sopenharmony_ci test LONGJMP_ADDR[1], INVALID_ADDR jnz snapshot_saveptr; 192762306a36Sopenharmony_ci } 192862306a36Sopenharmony_cisaveptr_active_fifo: 192962306a36Sopenharmony_ci and SEQIMODE, ~ENSAVEPTRS; 193062306a36Sopenharmony_ci or SEQINTCTL, IRET ret; 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_cicfg4data_intr: 193362306a36Sopenharmony_ci test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun_inc_use_count; 193462306a36Sopenharmony_ci call load_first_seg; 193562306a36Sopenharmony_ci call pkt_handle_xfer; 193662306a36Sopenharmony_ci inc SCB_FIFO_USE_COUNT; 193762306a36Sopenharmony_ciinterrupt_return: 193862306a36Sopenharmony_ci or SEQINTCTL, IRET ret; 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_cicfg4istat_intr: 194162306a36Sopenharmony_ci call freeze_queue; 194262306a36Sopenharmony_ci add NONE, -13, SCB_CDB_LEN; 194362306a36Sopenharmony_ci jnc cfg4istat_have_sense_addr; 194462306a36Sopenharmony_ci test SCB_CDB_LEN, SCB_CDB_LEN_PTR jnz cfg4istat_have_sense_addr; 194562306a36Sopenharmony_ci /* 194662306a36Sopenharmony_ci * Host sets up address/count and enables transfer. 194762306a36Sopenharmony_ci */ 194862306a36Sopenharmony_ci SET_SEQINTCODE(CFG4ISTAT_INTR) 194962306a36Sopenharmony_ci jmp cfg4istat_setup_handler; 195062306a36Sopenharmony_cicfg4istat_have_sense_addr: 195162306a36Sopenharmony_ci bmov HADDR, SCB_SENSE_BUSADDR, 4; 195262306a36Sopenharmony_ci mvi HCNT[1], (AHD_SENSE_BUFSIZE >> 8); 195362306a36Sopenharmony_ci mvi SG_CACHE_PRE, LAST_SEG; 195462306a36Sopenharmony_ci mvi DFCNTRL, PRELOADEN|SCSIEN|HDMAEN; 195562306a36Sopenharmony_cicfg4istat_setup_handler: 195662306a36Sopenharmony_ci /* 195762306a36Sopenharmony_ci * Status pkt is transferring to host. 195862306a36Sopenharmony_ci * Wait in idle loop for transfer to complete. 195962306a36Sopenharmony_ci * If a command completed before an attempted 196062306a36Sopenharmony_ci * task management function completed, notify the host. 196162306a36Sopenharmony_ci */ 196262306a36Sopenharmony_ci test SCB_TASK_MANAGEMENT, 0xFF jz cfg4istat_no_taskmgmt_func; 196362306a36Sopenharmony_ci SET_SEQINTCODE(TASKMGMT_CMD_CMPLT_OKAY) 196462306a36Sopenharmony_cicfg4istat_no_taskmgmt_func: 196562306a36Sopenharmony_ci call pkt_handle_status; 196662306a36Sopenharmony_ci or SEQINTCTL, IRET ret; 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_cicfg4icmd_intr: 196962306a36Sopenharmony_ci /* 197062306a36Sopenharmony_ci * In the case of DMAing a CDB from the host, the normal 197162306a36Sopenharmony_ci * CDB buffer is formatted with an 8 byte address followed 197262306a36Sopenharmony_ci * by a 1 byte count. 197362306a36Sopenharmony_ci */ 197462306a36Sopenharmony_ci bmov HADDR[0], SCB_HOST_CDB_PTR, 9; 197562306a36Sopenharmony_ci mvi SG_CACHE_PRE, LAST_SEG; 197662306a36Sopenharmony_ci mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN); 197762306a36Sopenharmony_ci call pkt_handle_cdb; 197862306a36Sopenharmony_ci or SEQINTCTL, IRET ret; 197962306a36Sopenharmony_ci 198062306a36Sopenharmony_ci/* 198162306a36Sopenharmony_ci * See if the target has gone on in this context creating an 198262306a36Sopenharmony_ci * overrun condition. For the write case, the hardware cannot 198362306a36Sopenharmony_ci * ack bytes until data are provided. So, if the target begins 198462306a36Sopenharmony_ci * another packet without changing contexts, implying we are 198562306a36Sopenharmony_ci * not sitting on a packet boundary, we are in an overrun 198662306a36Sopenharmony_ci * situation. For the read case, the hardware will continue to 198762306a36Sopenharmony_ci * ack bytes into the FIFO, and may even ack the last overrun packet 198862306a36Sopenharmony_ci * into the FIFO. If the FIFO should become non-empty, we are in 198962306a36Sopenharmony_ci * a read overrun case. 199062306a36Sopenharmony_ci */ 199162306a36Sopenharmony_ci#define check_overrun \ 199262306a36Sopenharmony_ci /* Not on a packet boundary. */ \ 199362306a36Sopenharmony_ci test MDFFSTAT, DLZERO jz pkt_handle_overrun; \ 199462306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jz pkt_handle_overrun 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_cipkt_handle_xfer: 199762306a36Sopenharmony_ci test SG_STATE, LOADING_NEEDED jz pkt_last_seg; 199862306a36Sopenharmony_ci call setjmp; 199962306a36Sopenharmony_ci test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs; 200062306a36Sopenharmony_ci test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2; 200162306a36Sopenharmony_ci test SCSISIGO, ATNO jnz . + 2; 200262306a36Sopenharmony_ci test SSTAT2, NONPACKREQ jz pkt_service_fifo; 200362306a36Sopenharmony_ci /* 200462306a36Sopenharmony_ci * Defer handling of this NONPACKREQ until we 200562306a36Sopenharmony_ci * can be sure it pertains to this FIFO. SAVEPTRS 200662306a36Sopenharmony_ci * will not be asserted if the NONPACKREQ is for us, 200762306a36Sopenharmony_ci * so we must simulate it if shadow is valid. If 200862306a36Sopenharmony_ci * shadow is not valid, keep running this FIFO until we 200962306a36Sopenharmony_ci * have satisfied the transfer by loading segments and 201062306a36Sopenharmony_ci * waiting for either shadow valid or last_seg_done. 201162306a36Sopenharmony_ci */ 201262306a36Sopenharmony_ci test MDFFSTAT, SHVALID jnz pkt_saveptrs; 201362306a36Sopenharmony_cipkt_service_fifo: 201462306a36Sopenharmony_ci test SG_STATE, LOADING_NEEDED jnz service_fifo; 201562306a36Sopenharmony_cipkt_last_seg: 201662306a36Sopenharmony_ci call setjmp; 201762306a36Sopenharmony_ci test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs; 201862306a36Sopenharmony_ci test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_last_seg_done; 201962306a36Sopenharmony_ci test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2; 202062306a36Sopenharmony_ci test SCSISIGO, ATNO jnz . + 2; 202162306a36Sopenharmony_ci test SSTAT2, NONPACKREQ jz return; 202262306a36Sopenharmony_ci test MDFFSTAT, SHVALID jz return; 202362306a36Sopenharmony_ci /* FALLTHROUGH */ 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci/* 202662306a36Sopenharmony_ci * Either a SAVEPTRS interrupt condition is pending for this FIFO 202762306a36Sopenharmony_ci * or we have a pending NONPACKREQ for this FIFO. We differentiate 202862306a36Sopenharmony_ci * between the two by capturing the state of the SAVEPTRS interrupt 202962306a36Sopenharmony_ci * prior to clearing this status and executing the common code for 203062306a36Sopenharmony_ci * these two cases. 203162306a36Sopenharmony_ci */ 203262306a36Sopenharmony_cipkt_saveptrs: 203362306a36Sopenharmony_ciBEGIN_CRITICAL; 203462306a36Sopenharmony_ci if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { 203562306a36Sopenharmony_ci or DFCNTRL, FIFOFLUSH; 203662306a36Sopenharmony_ci } 203762306a36Sopenharmony_ci mov REG0, SEQINTSRC; 203862306a36Sopenharmony_ci call calc_residual; 203962306a36Sopenharmony_ci call save_pointers; 204062306a36Sopenharmony_ci mvi CLRSEQINTSRC, CLRSAVEPTRS; 204162306a36Sopenharmony_ci call disable_ccsgen; 204262306a36Sopenharmony_ci or SEQIMODE, ENSAVEPTRS; 204362306a36Sopenharmony_ci test DFCNTRL, DIRECTION jnz pkt_saveptrs_check_status; 204462306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jnz pkt_saveptrs_check_status; 204562306a36Sopenharmony_ci /* 204662306a36Sopenharmony_ci * Keep a handler around for this FIFO until it drains 204762306a36Sopenharmony_ci * to the host to guarantee that we don't complete the 204862306a36Sopenharmony_ci * command to the host before the data arrives. 204962306a36Sopenharmony_ci */ 205062306a36Sopenharmony_cipkt_saveptrs_wait_fifoemp: 205162306a36Sopenharmony_ci call setjmp; 205262306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jz return; 205362306a36Sopenharmony_cipkt_saveptrs_check_status: 205462306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR; 205562306a36Sopenharmony_ci test REG0, SAVEPTRS jz unexpected_nonpkt_phase; 205662306a36Sopenharmony_ci dec SCB_FIFO_USE_COUNT; 205762306a36Sopenharmony_ci test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; 205862306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN ret; 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci/* 206162306a36Sopenharmony_ci * LAST_SEG_DONE status has been seen in the current FIFO. 206262306a36Sopenharmony_ci * This indicates that all of the allowed data for this 206362306a36Sopenharmony_ci * command has transferred across the SCSI and host buses. 206462306a36Sopenharmony_ci * Check for overrun and see if we can complete this command. 206562306a36Sopenharmony_ci */ 206662306a36Sopenharmony_cipkt_last_seg_done: 206762306a36Sopenharmony_ci /* 206862306a36Sopenharmony_ci * Mark transfer as completed. 206962306a36Sopenharmony_ci */ 207062306a36Sopenharmony_ci or SCB_SGPTR, SG_LIST_NULL; 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci /* 207362306a36Sopenharmony_ci * Wait for the current context to finish to verify that 207462306a36Sopenharmony_ci * no overrun condition has occurred. 207562306a36Sopenharmony_ci */ 207662306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done; 207762306a36Sopenharmony_ci call setjmp; 207862306a36Sopenharmony_cipkt_wait_ctxt_done_loop: 207962306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done; 208062306a36Sopenharmony_ci /* 208162306a36Sopenharmony_ci * A sufficiently large overrun or a NONPACKREQ may 208262306a36Sopenharmony_ci * prevent CTXTDONE from ever asserting, so we must 208362306a36Sopenharmony_ci * poll for these statuses too. 208462306a36Sopenharmony_ci */ 208562306a36Sopenharmony_ci check_overrun; 208662306a36Sopenharmony_ci test SSTAT2, NONPACKREQ jz return; 208762306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase; 208862306a36Sopenharmony_ci /* FALLTHROUGH */ 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_cipkt_ctxt_done: 209162306a36Sopenharmony_ci check_overrun; 209262306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR; 209362306a36Sopenharmony_ci /* 209462306a36Sopenharmony_ci * If status has been received, it is safe to skip 209562306a36Sopenharmony_ci * the check to see if another FIFO is active because 209662306a36Sopenharmony_ci * LAST_SEG_DONE has been observed. However, we check 209762306a36Sopenharmony_ci * the FIFO anyway since it costs us only one extra 209862306a36Sopenharmony_ci * instruction to leverage common code to perform the 209962306a36Sopenharmony_ci * SCB completion. 210062306a36Sopenharmony_ci */ 210162306a36Sopenharmony_ci dec SCB_FIFO_USE_COUNT; 210262306a36Sopenharmony_ci test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; 210362306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN ret; 210462306a36Sopenharmony_ciEND_CRITICAL; 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci/* 210762306a36Sopenharmony_ci * Must wait until CDB xfer is over before issuing the 210862306a36Sopenharmony_ci * clear channel. 210962306a36Sopenharmony_ci */ 211062306a36Sopenharmony_cipkt_handle_cdb: 211162306a36Sopenharmony_ci call setjmp; 211262306a36Sopenharmony_ci test SG_CACHE_SHADOW, LAST_SEG_DONE jz return; 211362306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR; 211462306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN ret; 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci/* 211762306a36Sopenharmony_ci * Watch over the status transfer. Our host sense buffer is 211862306a36Sopenharmony_ci * large enough to take the maximum allowed status packet. 211962306a36Sopenharmony_ci * None-the-less, we must still catch and report overruns to 212062306a36Sopenharmony_ci * the host. Additionally, properly catch unexpected non-packet 212162306a36Sopenharmony_ci * phases that are typically caused by CRC errors in status packet 212262306a36Sopenharmony_ci * transmission. 212362306a36Sopenharmony_ci */ 212462306a36Sopenharmony_cipkt_handle_status: 212562306a36Sopenharmony_ci call setjmp; 212662306a36Sopenharmony_ci test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun; 212762306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jz pkt_status_check_nonpackreq; 212862306a36Sopenharmony_ci test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun; 212962306a36Sopenharmony_cipkt_status_IU_done: 213062306a36Sopenharmony_ci if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { 213162306a36Sopenharmony_ci or DFCNTRL, FIFOFLUSH; 213262306a36Sopenharmony_ci } 213362306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jz return; 213462306a36Sopenharmony_ciBEGIN_CRITICAL; 213562306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR; 213662306a36Sopenharmony_ci mvi SCB_SCSI_STATUS, STATUS_PKT_SENSE; 213762306a36Sopenharmony_ci or SCB_CONTROL, STATUS_RCVD; 213862306a36Sopenharmony_ci jmp pkt_complete_scb_if_fifos_idle; 213962306a36Sopenharmony_ciEND_CRITICAL; 214062306a36Sopenharmony_cipkt_status_check_overrun: 214162306a36Sopenharmony_ci /* 214262306a36Sopenharmony_ci * Status PKT overruns are uncerimoniously recovered with a 214362306a36Sopenharmony_ci * bus reset. If we've overrun, let the host know so that 214462306a36Sopenharmony_ci * recovery can be performed. 214562306a36Sopenharmony_ci * 214662306a36Sopenharmony_ci * LAST_SEG_DONE has been observed. If either CTXTDONE or 214762306a36Sopenharmony_ci * a NONPACKREQ phase change have occurred and the FIFO is 214862306a36Sopenharmony_ci * empty, there is no overrun. 214962306a36Sopenharmony_ci */ 215062306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jz pkt_status_report_overrun; 215162306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jz . + 2; 215262306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jnz pkt_status_IU_done; 215362306a36Sopenharmony_ci test SCSIPHASE, ~DATA_PHASE_MASK jz return; 215462306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jnz pkt_status_check_nonpackreq; 215562306a36Sopenharmony_cipkt_status_report_overrun: 215662306a36Sopenharmony_ci SET_SEQINTCODE(STATUS_OVERRUN) 215762306a36Sopenharmony_ci /* SEQUENCER RESTARTED */ 215862306a36Sopenharmony_cipkt_status_check_nonpackreq: 215962306a36Sopenharmony_ci /* 216062306a36Sopenharmony_ci * CTXTDONE may be held off if a NONPACKREQ is associated with 216162306a36Sopenharmony_ci * the current context. If a NONPACKREQ is observed, decide 216262306a36Sopenharmony_ci * if it is for the current context. If it is for the current 216362306a36Sopenharmony_ci * context, we must defer NONPACKREQ processing until all data 216462306a36Sopenharmony_ci * has transferred to the host. 216562306a36Sopenharmony_ci */ 216662306a36Sopenharmony_ci test SCSIPHASE, ~DATA_PHASE_MASK jz return; 216762306a36Sopenharmony_ci test SCSISIGO, ATNO jnz . + 2; 216862306a36Sopenharmony_ci test SSTAT2, NONPACKREQ jz return; 216962306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jnz pkt_status_IU_done; 217062306a36Sopenharmony_ci test DFSTATUS, FIFOEMP jz return; 217162306a36Sopenharmony_ci /* 217262306a36Sopenharmony_ci * The unexpected nonpkt phase handler assumes that any 217362306a36Sopenharmony_ci * data channel use will have a FIFO reference count. It 217462306a36Sopenharmony_ci * turns out that the status handler doesn't need a references 217562306a36Sopenharmony_ci * count since the status received flag, and thus completion 217662306a36Sopenharmony_ci * processing, cannot be set until the handler is finished. 217762306a36Sopenharmony_ci * We increment the count here to make the nonpkt handler 217862306a36Sopenharmony_ci * happy. 217962306a36Sopenharmony_ci */ 218062306a36Sopenharmony_ci inc SCB_FIFO_USE_COUNT; 218162306a36Sopenharmony_ci /* FALLTHROUGH */ 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci/* 218462306a36Sopenharmony_ci * Nonpackreq is a polled status. It can come true in three situations: 218562306a36Sopenharmony_ci * we have received an L_Q, we have sent one or more L_Qs, or there is no 218662306a36Sopenharmony_ci * L_Q context associated with this REQ (REQ occurs immediately after a 218762306a36Sopenharmony_ci * (re)selection). Routines that know that the context responsible for this 218862306a36Sopenharmony_ci * nonpackreq call directly into unexpected_nonpkt_phase. In the case of the 218962306a36Sopenharmony_ci * top level idle loop, we exhaust all active contexts prior to determining that 219062306a36Sopenharmony_ci * we simply do not have the full I_T_L_Q for this phase. 219162306a36Sopenharmony_ci */ 219262306a36Sopenharmony_ciunexpected_nonpkt_phase_find_ctxt: 219362306a36Sopenharmony_ci /* 219462306a36Sopenharmony_ci * This nonpackreq is most likely associated with one of the tags 219562306a36Sopenharmony_ci * in a FIFO or an outgoing LQ. Only treat it as an I_T only 219662306a36Sopenharmony_ci * nonpackreq if we've cleared out the FIFOs and handled any 219762306a36Sopenharmony_ci * pending SELDO. 219862306a36Sopenharmony_ci */ 219962306a36Sopenharmony_ciSET_SRC_MODE M_SCSI; 220062306a36Sopenharmony_ciSET_DST_MODE M_SCSI; 220162306a36Sopenharmony_ci and A, FIFO1FREE|FIFO0FREE, DFFSTAT; 220262306a36Sopenharmony_ci cmp A, FIFO1FREE|FIFO0FREE jne return; 220362306a36Sopenharmony_ci test SSTAT0, SELDO jnz return; 220462306a36Sopenharmony_ci mvi SCBPTR[1], SCB_LIST_NULL; 220562306a36Sopenharmony_ciunexpected_nonpkt_phase: 220662306a36Sopenharmony_ci test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) 220762306a36Sopenharmony_ci jnz unexpected_nonpkt_mode_cleared; 220862306a36Sopenharmony_ciSET_SRC_MODE M_DFF0; 220962306a36Sopenharmony_ciSET_DST_MODE M_DFF0; 221062306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR; 221162306a36Sopenharmony_ci dec SCB_FIFO_USE_COUNT; 221262306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN; 221362306a36Sopenharmony_ciunexpected_nonpkt_mode_cleared: 221462306a36Sopenharmony_ci mvi CLRSINT2, CLRNONPACKREQ; 221562306a36Sopenharmony_ci if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { 221662306a36Sopenharmony_ci /* 221762306a36Sopenharmony_ci * Test to ensure that the bus has not 221862306a36Sopenharmony_ci * already gone free prior to clearing 221962306a36Sopenharmony_ci * any stale busfree status. This avoids 222062306a36Sopenharmony_ci * a window whereby a busfree just after 222162306a36Sopenharmony_ci * a selection could be missed. 222262306a36Sopenharmony_ci */ 222362306a36Sopenharmony_ci test SCSISIGI, BSYI jz . + 2; 222462306a36Sopenharmony_ci mvi CLRSINT1,CLRBUSFREE; 222562306a36Sopenharmony_ci or SIMODE1, ENBUSFREE; 222662306a36Sopenharmony_ci } 222762306a36Sopenharmony_ci test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; 222862306a36Sopenharmony_ci SET_SEQINTCODE(ENTERING_NONPACK) 222962306a36Sopenharmony_ci jmp ITloop; 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ciillegal_phase: 223262306a36Sopenharmony_ci SET_SEQINTCODE(ILLEGAL_PHASE) 223362306a36Sopenharmony_ci jmp ITloop; 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci/* 223662306a36Sopenharmony_ci * We have entered an overrun situation. If we have working 223762306a36Sopenharmony_ci * BITBUCKET, flip that on and let the hardware eat any overrun 223862306a36Sopenharmony_ci * data. Otherwise use an overrun buffer in the host to simulate 223962306a36Sopenharmony_ci * BITBUCKET. 224062306a36Sopenharmony_ci */ 224162306a36Sopenharmony_cipkt_handle_overrun_inc_use_count: 224262306a36Sopenharmony_ci inc SCB_FIFO_USE_COUNT; 224362306a36Sopenharmony_cipkt_handle_overrun: 224462306a36Sopenharmony_ci SET_SEQINTCODE(CFG4OVERRUN) 224562306a36Sopenharmony_ci call freeze_queue; 224662306a36Sopenharmony_ci if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0) { 224762306a36Sopenharmony_ci or DFFSXFRCTL, DFFBITBUCKET; 224862306a36Sopenharmony_ciSET_SRC_MODE M_DFF1; 224962306a36Sopenharmony_ciSET_DST_MODE M_DFF1; 225062306a36Sopenharmony_ci } else { 225162306a36Sopenharmony_ci call load_overrun_buf; 225262306a36Sopenharmony_ci mvi DFCNTRL, (HDMAEN|SCSIEN|PRELOADEN); 225362306a36Sopenharmony_ci } 225462306a36Sopenharmony_ci call setjmp; 225562306a36Sopenharmony_ci if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) { 225662306a36Sopenharmony_ci test DFSTATUS, PRELOAD_AVAIL jz overrun_load_done; 225762306a36Sopenharmony_ci call load_overrun_buf; 225862306a36Sopenharmony_ci or DFCNTRL, PRELOADEN; 225962306a36Sopenharmony_cioverrun_load_done: 226062306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jnz pkt_overrun_end; 226162306a36Sopenharmony_ci } else { 226262306a36Sopenharmony_ci test DFFSXFRCTL, DFFBITBUCKET jz pkt_overrun_end; 226362306a36Sopenharmony_ci } 226462306a36Sopenharmony_ci test SSTAT2, NONPACKREQ jz return; 226562306a36Sopenharmony_cipkt_overrun_end: 226662306a36Sopenharmony_ci or SCB_RESIDUAL_SGPTR, SG_OVERRUN_RESID; 226762306a36Sopenharmony_ci test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase; 226862306a36Sopenharmony_ci dec SCB_FIFO_USE_COUNT; 226962306a36Sopenharmony_ci or LONGJMP_ADDR[1], INVALID_ADDR; 227062306a36Sopenharmony_ci test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; 227162306a36Sopenharmony_ci mvi DFFSXFRCTL, CLRCHN ret; 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ciif ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) { 227462306a36Sopenharmony_ciload_overrun_buf: 227562306a36Sopenharmony_ci /* 227662306a36Sopenharmony_ci * Load a dummy segment if preload space is available. 227762306a36Sopenharmony_ci */ 227862306a36Sopenharmony_ci mov HADDR[0], SHARED_DATA_ADDR; 227962306a36Sopenharmony_ci add HADDR[1], PKT_OVERRUN_BUFOFFSET, SHARED_DATA_ADDR[1]; 228062306a36Sopenharmony_ci mov ACCUM_SAVE, A; 228162306a36Sopenharmony_ci clr A; 228262306a36Sopenharmony_ci adc HADDR[2], A, SHARED_DATA_ADDR[2]; 228362306a36Sopenharmony_ci adc HADDR[3], A, SHARED_DATA_ADDR[3]; 228462306a36Sopenharmony_ci mov A, ACCUM_SAVE; 228562306a36Sopenharmony_ci bmov HADDR[4], ALLZEROS, 4; 228662306a36Sopenharmony_ci /* PKT_OVERRUN_BUFSIZE is a multiple of 256 */ 228762306a36Sopenharmony_ci clr HCNT[0]; 228862306a36Sopenharmony_ci mvi HCNT[1], ((PKT_OVERRUN_BUFSIZE >> 8) & 0xFF); 228962306a36Sopenharmony_ci clr HCNT[2] ret; 229062306a36Sopenharmony_ci} 2291