1139749Simp/*- 265942Sgibbs * Core routines and tables shareable across OS platforms. 339220Sgibbs * 4102670Sgibbs * Copyright (c) 1994-2002 Justin T. Gibbs. 5102670Sgibbs * Copyright (c) 2000-2002 Adaptec Inc. 639220Sgibbs * All rights reserved. 739220Sgibbs * 839220Sgibbs * Redistribution and use in source and binary forms, with or without 939220Sgibbs * modification, are permitted provided that the following conditions 1039220Sgibbs * are met: 1139220Sgibbs * 1. Redistributions of source code must retain the above copyright 1239220Sgibbs * notice, this list of conditions, and the following disclaimer, 1354211Sgibbs * without modification. 1495378Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1595378Sgibbs * substantially similar to the "NO WARRANTY" disclaimer below 1695378Sgibbs * ("Disclaimer") and any redistribution must be conditioned upon 1795378Sgibbs * including a substantially similar Disclaimer requirement for further 1895378Sgibbs * binary redistribution. 1995378Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names 2095378Sgibbs * of any contributors may be used to endorse or promote products derived 2195378Sgibbs * from this software without specific prior written permission. 2239220Sgibbs * 2354211Sgibbs * Alternatively, this software may be distributed under the terms of the 2495378Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free 2595378Sgibbs * Software Foundation. 2639220Sgibbs * 2795378Sgibbs * NO WARRANTY 2895378Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2995378Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3095378Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3195378Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3295378Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3339220Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3439220Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3595378Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3695378Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3795378Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3895378Sgibbs * POSSIBILITY OF SUCH DAMAGES. 3939220Sgibbs * 40129133Sgibbs * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#155 $ 4139220Sgibbs */ 4239220Sgibbs 4395378Sgibbs#ifdef __linux__ 4495378Sgibbs#include "aic7xxx_osm.h" 4595378Sgibbs#include "aic7xxx_inline.h" 4695378Sgibbs#include "aicasm/aicasm_insformat.h" 4795378Sgibbs#else 48123579Sgibbs#include <sys/cdefs.h> 49123579Sgibbs__FBSDID("$FreeBSD$"); 5095378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h> 5165942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 5265942Sgibbs#include <dev/aic7xxx/aicasm/aicasm_insformat.h> 5395378Sgibbs#endif 5439220Sgibbs 5565942Sgibbs/****************************** Softc Data ************************************/ 5665942Sgibbsstruct ahc_softc_tailq ahc_tailq = TAILQ_HEAD_INITIALIZER(ahc_tailq); 5739220Sgibbs 5865942Sgibbs/***************************** Lookup Tables **********************************/ 5955581Sgibbschar *ahc_chip_names[] = 6055581Sgibbs{ 6155581Sgibbs "NONE", 6255581Sgibbs "aic7770", 6355581Sgibbs "aic7850", 6455581Sgibbs "aic7855", 6555581Sgibbs "aic7859", 6655581Sgibbs "aic7860", 6755581Sgibbs "aic7870", 6855581Sgibbs "aic7880", 6963457Sgibbs "aic7895", 7065942Sgibbs "aic7895C", 7155581Sgibbs "aic7890/91", 7263457Sgibbs "aic7896/97", 7355581Sgibbs "aic7892", 7455581Sgibbs "aic7899" 7555581Sgibbs}; 7674094Sgibbsstatic const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names); 7755581Sgibbs 7874094Sgibbs/* 7974094Sgibbs * Hardware error codes. 8074094Sgibbs */ 8174094Sgibbsstruct ahc_hard_error_entry { 8274094Sgibbs uint8_t errno; 8374094Sgibbs char *errmesg; 8474094Sgibbs}; 8574094Sgibbs 8674094Sgibbsstatic struct ahc_hard_error_entry ahc_hard_errors[] = { 8765942Sgibbs { ILLHADDR, "Illegal Host Access" }, 8865942Sgibbs { ILLSADDR, "Illegal Sequencer Address referrenced" }, 8965942Sgibbs { ILLOPCODE, "Illegal Opcode in sequencer program" }, 9065942Sgibbs { SQPARERR, "Sequencer Parity Error" }, 9165942Sgibbs { DPARERR, "Data-path Parity Error" }, 9265942Sgibbs { MPARERR, "Scratch or SCB Memory Parity Error" }, 9365942Sgibbs { PCIERRSTAT, "PCI Error detected" }, 9465942Sgibbs { CIOPARERR, "CIOBUS Parity Error" }, 9565942Sgibbs}; 9674094Sgibbsstatic const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors); 9741646Sgibbs 9874094Sgibbsstatic struct ahc_phase_table_entry ahc_phase_table[] = 9965942Sgibbs{ 10065942Sgibbs { P_DATAOUT, MSG_NOOP, "in Data-out phase" }, 10165942Sgibbs { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" }, 10265942Sgibbs { P_DATAOUT_DT, MSG_NOOP, "in DT Data-out phase" }, 10365942Sgibbs { P_DATAIN_DT, MSG_INITIATOR_DET_ERR, "in DT Data-in phase" }, 10465942Sgibbs { P_COMMAND, MSG_NOOP, "in Command phase" }, 10565942Sgibbs { P_MESGOUT, MSG_NOOP, "in Message-out phase" }, 10665942Sgibbs { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" }, 10765942Sgibbs { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" }, 10865942Sgibbs { P_BUSFREE, MSG_NOOP, "while idle" }, 10965942Sgibbs { 0, MSG_NOOP, "in unknown phase" } 11039220Sgibbs}; 11139220Sgibbs 11265942Sgibbs/* 11365942Sgibbs * In most cases we only wish to itterate over real phases, so 11465942Sgibbs * exclude the last element from the count. 11565942Sgibbs */ 11674094Sgibbsstatic const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1; 11739220Sgibbs 11865942Sgibbs/* 11965942Sgibbs * Valid SCSIRATE values. (p. 3-17) 12065942Sgibbs * Provides a mapping of tranfer periods in ns to the proper value to 12165942Sgibbs * stick in the scsixfer reg. 12265942Sgibbs */ 12374094Sgibbsstatic struct ahc_syncrate ahc_syncrates[] = 12465942Sgibbs{ 12565942Sgibbs /* ultra2 fast/ultra period rate */ 12665942Sgibbs { 0x42, 0x000, 9, "80.0" }, 12765942Sgibbs { 0x03, 0x000, 10, "40.0" }, 12865942Sgibbs { 0x04, 0x000, 11, "33.0" }, 12965942Sgibbs { 0x05, 0x100, 12, "20.0" }, 13065942Sgibbs { 0x06, 0x110, 15, "16.0" }, 13165942Sgibbs { 0x07, 0x120, 18, "13.4" }, 13265942Sgibbs { 0x08, 0x000, 25, "10.0" }, 13365942Sgibbs { 0x19, 0x010, 31, "8.0" }, 13465942Sgibbs { 0x1a, 0x020, 37, "6.67" }, 13565942Sgibbs { 0x1b, 0x030, 43, "5.7" }, 13665942Sgibbs { 0x1c, 0x040, 50, "5.0" }, 13765942Sgibbs { 0x00, 0x050, 56, "4.4" }, 13865942Sgibbs { 0x00, 0x060, 62, "4.0" }, 13965942Sgibbs { 0x00, 0x070, 68, "3.6" }, 14065942Sgibbs { 0x00, 0x000, 0, NULL } 14165942Sgibbs}; 14239220Sgibbs 14365942Sgibbs/* Our Sequencer Program */ 14465942Sgibbs#include "aic7xxx_seq.h" 14539220Sgibbs 14665942Sgibbs/**************************** Function Declarations ***************************/ 147114621Sgibbsstatic void ahc_force_renegotiation(struct ahc_softc *ahc, 148114621Sgibbs struct ahc_devinfo *devinfo); 14974972Sgibbsstatic struct ahc_tmode_tstate* 15065942Sgibbs ahc_alloc_tstate(struct ahc_softc *ahc, 15165942Sgibbs u_int scsi_id, char channel); 15270204Sgibbs#ifdef AHC_TARGET_MODE 15365942Sgibbsstatic void ahc_free_tstate(struct ahc_softc *ahc, 15465942Sgibbs u_int scsi_id, char channel, int force); 15570204Sgibbs#endif 15665942Sgibbsstatic struct ahc_syncrate* 15765942Sgibbs ahc_devlimited_syncrate(struct ahc_softc *ahc, 15868087Sgibbs struct ahc_initiator_tinfo *, 15965942Sgibbs u_int *period, 16068087Sgibbs u_int *ppr_options, 16168087Sgibbs role_t role); 16274972Sgibbsstatic void ahc_update_pending_scbs(struct ahc_softc *ahc); 16365942Sgibbsstatic void ahc_fetch_devinfo(struct ahc_softc *ahc, 16465942Sgibbs struct ahc_devinfo *devinfo); 16565942Sgibbsstatic void ahc_scb_devinfo(struct ahc_softc *ahc, 16665942Sgibbs struct ahc_devinfo *devinfo, 16765942Sgibbs struct scb *scb); 16876634Sgibbsstatic void ahc_assert_atn(struct ahc_softc *ahc); 16965942Sgibbsstatic void ahc_setup_initiator_msgout(struct ahc_softc *ahc, 17065942Sgibbs struct ahc_devinfo *devinfo, 17165942Sgibbs struct scb *scb); 17265942Sgibbsstatic void ahc_build_transfer_msg(struct ahc_softc *ahc, 17365942Sgibbs struct ahc_devinfo *devinfo); 17465942Sgibbsstatic void ahc_construct_sdtr(struct ahc_softc *ahc, 17566647Sgibbs struct ahc_devinfo *devinfo, 17665942Sgibbs u_int period, u_int offset); 17765942Sgibbsstatic void ahc_construct_wdtr(struct ahc_softc *ahc, 17866647Sgibbs struct ahc_devinfo *devinfo, 17965942Sgibbs u_int bus_width); 18065942Sgibbsstatic void ahc_construct_ppr(struct ahc_softc *ahc, 18166647Sgibbs struct ahc_devinfo *devinfo, 18265942Sgibbs u_int period, u_int offset, 18365942Sgibbs u_int bus_width, u_int ppr_options); 18465942Sgibbsstatic void ahc_clear_msg_state(struct ahc_softc *ahc); 185107420Sscottlstatic void ahc_handle_proto_violation(struct ahc_softc *ahc); 18665942Sgibbsstatic void ahc_handle_message_phase(struct ahc_softc *ahc); 18770204Sgibbstypedef enum { 18870204Sgibbs AHCMSG_1B, 18970204Sgibbs AHCMSG_2B, 19070204Sgibbs AHCMSG_EXT 19170204Sgibbs} ahc_msgtype; 19270204Sgibbsstatic int ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, 19370204Sgibbs u_int msgval, int full); 19465942Sgibbsstatic int ahc_parse_msg(struct ahc_softc *ahc, 19565942Sgibbs struct ahc_devinfo *devinfo); 19665942Sgibbsstatic int ahc_handle_msg_reject(struct ahc_softc *ahc, 19765942Sgibbs struct ahc_devinfo *devinfo); 19865942Sgibbsstatic void ahc_handle_ign_wide_residue(struct ahc_softc *ahc, 19965942Sgibbs struct ahc_devinfo *devinfo); 20079874Sgibbsstatic void ahc_reinitialize_dataptrs(struct ahc_softc *ahc); 20165942Sgibbsstatic void ahc_handle_devreset(struct ahc_softc *ahc, 20265942Sgibbs struct ahc_devinfo *devinfo, 20365942Sgibbs cam_status status, char *message, 20465942Sgibbs int verbose_level); 205115337Sgibbs#ifdef AHC_TARGET_MODE 20674972Sgibbsstatic void ahc_setup_target_msgin(struct ahc_softc *ahc, 20774972Sgibbs struct ahc_devinfo *devinfo, 20874972Sgibbs struct scb *scb); 20976634Sgibbs#endif 21039220Sgibbs 21165942Sgibbsstatic bus_dmamap_callback_t ahc_dmamap_cb; 21270204Sgibbsstatic void ahc_build_free_scb_list(struct ahc_softc *ahc); 21365942Sgibbsstatic int ahc_init_scbdata(struct ahc_softc *ahc); 21465942Sgibbsstatic void ahc_fini_scbdata(struct ahc_softc *ahc); 21568087Sgibbsstatic void ahc_qinfifo_requeue(struct ahc_softc *ahc, 21668087Sgibbs struct scb *prev_scb, 21768087Sgibbs struct scb *scb); 21868087Sgibbsstatic int ahc_qinfifo_count(struct ahc_softc *ahc); 21965942Sgibbsstatic u_int ahc_rem_scb_from_disc_list(struct ahc_softc *ahc, 22065942Sgibbs u_int prev, u_int scbptr); 22165942Sgibbsstatic void ahc_add_curscb_to_free_list(struct ahc_softc *ahc); 22265942Sgibbsstatic u_int ahc_rem_wscb(struct ahc_softc *ahc, 22365942Sgibbs u_int scbpos, u_int prev); 22465942Sgibbsstatic void ahc_reset_current_bus(struct ahc_softc *ahc); 22565942Sgibbs#ifdef AHC_DUMP_SEQ 22665942Sgibbsstatic void ahc_dumpseq(struct ahc_softc *ahc); 22765942Sgibbs#endif 228114621Sgibbsstatic int ahc_loadseq(struct ahc_softc *ahc); 22965942Sgibbsstatic int ahc_check_patch(struct ahc_softc *ahc, 23065942Sgibbs struct patch **start_patch, 23165942Sgibbs u_int start_instr, u_int *skip_addr); 23265942Sgibbsstatic void ahc_download_instr(struct ahc_softc *ahc, 23365942Sgibbs u_int instrptr, uint8_t *dconsts); 234129133Sgibbsstatic int ahc_other_scb_timeout(struct ahc_softc *ahc, 235129133Sgibbs struct scb *scb, 236129133Sgibbs struct scb *other_scb); 23765942Sgibbs#ifdef AHC_TARGET_MODE 23865942Sgibbsstatic void ahc_queue_lstate_event(struct ahc_softc *ahc, 23974972Sgibbs struct ahc_tmode_lstate *lstate, 24065942Sgibbs u_int initiator_id, 24165942Sgibbs u_int event_type, 24265942Sgibbs u_int event_arg); 24365942Sgibbsstatic void ahc_update_scsiid(struct ahc_softc *ahc, 24465942Sgibbs u_int targid_mask); 24565942Sgibbsstatic int ahc_handle_target_cmd(struct ahc_softc *ahc, 24665942Sgibbs struct target_cmd *cmd); 24765942Sgibbs#endif 24865942Sgibbs/************************* Sequencer Execution Control ************************/ 24939220Sgibbs/* 25039220Sgibbs * Restart the sequencer program from address zero 25139220Sgibbs */ 25265942Sgibbsvoid 25374094Sgibbsahc_restart(struct ahc_softc *ahc) 25439220Sgibbs{ 25568087Sgibbs 25674094Sgibbs ahc_pause(ahc); 25774094Sgibbs 25895378Sgibbs /* No more pending messages. */ 25995378Sgibbs ahc_clear_msg_state(ahc); 26095378Sgibbs 26165942Sgibbs ahc_outb(ahc, SCSISIGO, 0); /* De-assert BSY */ 26265942Sgibbs ahc_outb(ahc, MSG_OUT, MSG_NOOP); /* No message to send */ 26365942Sgibbs ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); 26495378Sgibbs ahc_outb(ahc, LASTPHASE, P_BUSFREE); 26595378Sgibbs ahc_outb(ahc, SAVED_SCSIID, 0xFF); 26695378Sgibbs ahc_outb(ahc, SAVED_LUN, 0xFF); 26768087Sgibbs 26866845Sgibbs /* 26966845Sgibbs * Ensure that the sequencer's idea of TQINPOS 27066845Sgibbs * matches our own. The sequencer increments TQINPOS 27166845Sgibbs * only after it sees a DMA complete and a reset could 27266845Sgibbs * occur before the increment leaving the kernel to believe 27366845Sgibbs * the command arrived but the sequencer to not. 27466845Sgibbs */ 27566845Sgibbs ahc_outb(ahc, TQINPOS, ahc->tqinfifonext); 27666845Sgibbs 27765942Sgibbs /* Always allow reselection */ 27865942Sgibbs ahc_outb(ahc, SCSISEQ, 27965942Sgibbs ahc_inb(ahc, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); 28065942Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 28165942Sgibbs /* Ensure that no DMA operations are in progress */ 28268402Sgibbs ahc_outb(ahc, CCSCBCNT, 0); 28365942Sgibbs ahc_outb(ahc, CCSGCTL, 0); 28465942Sgibbs ahc_outb(ahc, CCSCBCTL, 0); 28565942Sgibbs } 28674094Sgibbs /* 28774094Sgibbs * If we were in the process of DMA'ing SCB data into 28874094Sgibbs * an SCB, replace that SCB on the free list. This prevents 28974094Sgibbs * an SCB leak. 29074094Sgibbs */ 29174094Sgibbs if ((ahc_inb(ahc, SEQ_FLAGS2) & SCB_DMA) != 0) { 29274094Sgibbs ahc_add_curscb_to_free_list(ahc); 29374094Sgibbs ahc_outb(ahc, SEQ_FLAGS2, 29474094Sgibbs ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA); 29574094Sgibbs } 296129133Sgibbs 297129133Sgibbs /* 298129133Sgibbs * Clear any pending sequencer interrupt. It is no 299129133Sgibbs * longer relevant since we're resetting the Program 300129133Sgibbs * Counter. 301129133Sgibbs */ 302129133Sgibbs ahc_outb(ahc, CLRINT, CLRSEQINT); 303129133Sgibbs 30465942Sgibbs ahc_outb(ahc, MWI_RESIDUAL, 0); 305115332Sgibbs ahc_outb(ahc, SEQCTL, ahc->seqctl); 30668087Sgibbs ahc_outb(ahc, SEQADDR0, 0); 30768087Sgibbs ahc_outb(ahc, SEQADDR1, 0); 308129133Sgibbs 30974094Sgibbs ahc_unpause(ahc); 31039220Sgibbs} 31139220Sgibbs 31265942Sgibbs/************************* Input/Output Queues ********************************/ 31365942Sgibbsvoid 31449933Sgibbsahc_run_qoutfifo(struct ahc_softc *ahc) 31549933Sgibbs{ 31649933Sgibbs struct scb *scb; 31749933Sgibbs u_int scb_index; 31849933Sgibbs 31979874Sgibbs ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); 32049933Sgibbs while (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) { 32165942Sgibbs 32249933Sgibbs scb_index = ahc->qoutfifo[ahc->qoutfifonext]; 32365942Sgibbs if ((ahc->qoutfifonext & 0x03) == 0x03) { 32465942Sgibbs u_int modnext; 32549933Sgibbs 32665942Sgibbs /* 32765942Sgibbs * Clear 32bits of QOUTFIFO at a time 32876634Sgibbs * so that we don't clobber an incoming 32965942Sgibbs * byte DMA to the array on architectures 33065942Sgibbs * that only support 32bit load and store 33165942Sgibbs * operations. 33265942Sgibbs */ 33365942Sgibbs modnext = ahc->qoutfifonext & ~0x3; 33465942Sgibbs *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL; 335123579Sgibbs aic_dmamap_sync(ahc, ahc->shared_data_dmat, 33679874Sgibbs ahc->shared_data_dmamap, 33779874Sgibbs /*offset*/modnext, /*len*/4, 33879874Sgibbs BUS_DMASYNC_PREREAD); 33965942Sgibbs } 34065942Sgibbs ahc->qoutfifonext++; 34165942Sgibbs 34266647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 34366647Sgibbs if (scb == NULL) { 34449933Sgibbs printf("%s: WARNING no command for scb %d " 34549933Sgibbs "(cmdcmplt)\nQOUTPOS = %d\n", 34649933Sgibbs ahc_name(ahc), scb_index, 347102670Sgibbs (ahc->qoutfifonext - 1) & 0xFF); 34849933Sgibbs continue; 34949933Sgibbs } 35049933Sgibbs 35149933Sgibbs /* 35249933Sgibbs * Save off the residual 35349933Sgibbs * if there is one. 35449933Sgibbs */ 35595378Sgibbs ahc_update_residual(ahc, scb); 35649933Sgibbs ahc_done(ahc, scb); 35749933Sgibbs } 35849933Sgibbs} 35949933Sgibbs 36065942Sgibbsvoid 36165942Sgibbsahc_run_untagged_queues(struct ahc_softc *ahc) 36245965Sgibbs{ 36363457Sgibbs int i; 36463457Sgibbs 36565942Sgibbs for (i = 0; i < 16; i++) 36665942Sgibbs ahc_run_untagged_queue(ahc, &ahc->untagged_queues[i]); 36739220Sgibbs} 36839220Sgibbs 36963457Sgibbsvoid 37065942Sgibbsahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue) 37163457Sgibbs{ 37265942Sgibbs struct scb *scb; 37363457Sgibbs 37465942Sgibbs if (ahc->untagged_queue_lock != 0) 37565942Sgibbs return; 37639220Sgibbs 37765942Sgibbs if ((scb = TAILQ_FIRST(queue)) != NULL 37865942Sgibbs && (scb->flags & SCB_ACTIVE) == 0) { 37965942Sgibbs scb->flags |= SCB_ACTIVE; 380133911Sgibbs /* 381133911Sgibbs * Timers are disabled while recovery is in progress. 382133911Sgibbs */ 383129133Sgibbs aic_scb_timer_start(scb); 38465942Sgibbs ahc_queue_scb(ahc, scb); 38539220Sgibbs } 38639220Sgibbs} 38739220Sgibbs 38865942Sgibbs/************************* Interrupt Handling *********************************/ 38939220Sgibbsvoid 39065942Sgibbsahc_handle_brkadrint(struct ahc_softc *ahc) 39139220Sgibbs{ 39245965Sgibbs /* 39365942Sgibbs * We upset the sequencer :-( 39465942Sgibbs * Lookup the error message 39545965Sgibbs */ 39674094Sgibbs int i; 39774094Sgibbs int error; 39845965Sgibbs 39965942Sgibbs error = ahc_inb(ahc, ERROR); 40065942Sgibbs for (i = 0; error != 1 && i < num_errors; i++) 40165942Sgibbs error >>= 1; 40268087Sgibbs printf("%s: brkadrint, %s at seqaddr = 0x%x\n", 40374094Sgibbs ahc_name(ahc), ahc_hard_errors[i].errmesg, 40468087Sgibbs ahc_inb(ahc, SEQADDR0) | 40568087Sgibbs (ahc_inb(ahc, SEQADDR1) << 8)); 40645965Sgibbs 40768087Sgibbs ahc_dump_card_state(ahc); 40868087Sgibbs 409114621Sgibbs /* Tell everyone that this HBA is no longer available */ 41065942Sgibbs ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS, 41165942Sgibbs CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN, 41265942Sgibbs CAM_NO_HBA); 41368623Sgibbs 41468623Sgibbs /* Disable all interrupt sources by resetting the controller */ 41568623Sgibbs ahc_shutdown(ahc); 41645965Sgibbs} 41745965Sgibbs 41839220Sgibbsvoid 41939506Sgibbsahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) 42039220Sgibbs{ 42139220Sgibbs struct scb *scb; 42239220Sgibbs struct ahc_devinfo devinfo; 42339220Sgibbs 42439220Sgibbs ahc_fetch_devinfo(ahc, &devinfo); 42539220Sgibbs 42639220Sgibbs /* 42739220Sgibbs * Clear the upper byte that holds SEQINT status 42839220Sgibbs * codes and clear the SEQINT bit. We will unpause 42939220Sgibbs * the sequencer, if appropriate, after servicing 43039220Sgibbs * the request. 43139220Sgibbs */ 43239220Sgibbs ahc_outb(ahc, CLRINT, CLRSEQINT); 43339220Sgibbs switch (intstat & SEQINT_MASK) { 43439220Sgibbs case BAD_STATUS: 43539220Sgibbs { 43639506Sgibbs u_int scb_index; 43739506Sgibbs struct hardware_scb *hscb; 43866647Sgibbs 43939220Sgibbs /* 44066647Sgibbs * Set the default return value to 0 (don't 44166647Sgibbs * send sense). The sense code will change 44266647Sgibbs * this if needed. 44366647Sgibbs */ 44466647Sgibbs ahc_outb(ahc, RETURN_1, 0); 44566647Sgibbs 44666647Sgibbs /* 44739220Sgibbs * The sequencer will notify us when a command 44839220Sgibbs * has an error that would be of interest to 44939220Sgibbs * the kernel. This allows us to leave the sequencer 45039220Sgibbs * running in the common case of command completes 45139220Sgibbs * without error. The sequencer will already have 45239220Sgibbs * dma'd the SCB back up to us, so we can reference 45339220Sgibbs * the in kernel copy directly. 45439220Sgibbs */ 45539220Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 45666647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 45766647Sgibbs if (scb == NULL) { 458102670Sgibbs ahc_print_devinfo(ahc, &devinfo); 459102670Sgibbs printf("ahc_intr - referenced scb " 46039220Sgibbs "not valid during seqint 0x%x scb(%d)\n", 461102670Sgibbs intstat, scb_index); 46268087Sgibbs ahc_dump_card_state(ahc); 46368087Sgibbs panic("for safety"); 46439220Sgibbs goto unpause; 46539220Sgibbs } 46639220Sgibbs 46747433Sgibbs hscb = scb->hscb; 46847433Sgibbs 46939220Sgibbs /* Don't want to clobber the original sense code */ 47039220Sgibbs if ((scb->flags & SCB_SENSE) != 0) { 47139220Sgibbs /* 47239220Sgibbs * Clear the SCB_SENSE Flag and have 47339220Sgibbs * the sequencer do a normal command 47439220Sgibbs * complete. 47539220Sgibbs */ 47639220Sgibbs scb->flags &= ~SCB_SENSE; 477123579Sgibbs aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); 47839220Sgibbs break; 47939220Sgibbs } 480123579Sgibbs aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); 48163457Sgibbs /* Freeze the queue until the client sees the error. */ 48265942Sgibbs ahc_freeze_devq(ahc, scb); 483123579Sgibbs aic_freeze_scb(scb); 484123579Sgibbs aic_set_scsi_status(scb, hscb->shared_data.status.scsi_status); 48565942Sgibbs switch (hscb->shared_data.status.scsi_status) { 48639220Sgibbs case SCSI_STATUS_OK: 48739220Sgibbs printf("%s: Interrupted for staus of 0???\n", 48839220Sgibbs ahc_name(ahc)); 48939220Sgibbs break; 49039220Sgibbs case SCSI_STATUS_CMD_TERMINATED: 49139220Sgibbs case SCSI_STATUS_CHECK_COND: 49274972Sgibbs { 49374972Sgibbs struct ahc_dma_seg *sg; 49474972Sgibbs struct scsi_sense *sc; 49574972Sgibbs struct ahc_initiator_tinfo *targ_info; 49674972Sgibbs struct ahc_tmode_tstate *tstate; 49774972Sgibbs struct ahc_transinfo *tinfo; 49839220Sgibbs#ifdef AHC_DEBUG 499102670Sgibbs if (ahc_debug & AHC_SHOW_SENSE) { 50065942Sgibbs ahc_print_path(ahc, scb); 50139220Sgibbs printf("SCB %d: requests Check Status\n", 50239220Sgibbs scb->hscb->tag); 50339220Sgibbs } 50439220Sgibbs#endif 50565942Sgibbs 506123579Sgibbs if (aic_perform_autosense(scb) == 0) 50774972Sgibbs break; 50839220Sgibbs 50974972Sgibbs targ_info = ahc_fetch_transinfo(ahc, 51063457Sgibbs devinfo.channel, 51163457Sgibbs devinfo.our_scsiid, 51263457Sgibbs devinfo.target, 51363457Sgibbs &tstate); 51476634Sgibbs tinfo = &targ_info->curr; 51574972Sgibbs sg = scb->sg_list; 51674972Sgibbs sc = (struct scsi_sense *)(&hscb->shared_data.cdb); 51774972Sgibbs /* 51874972Sgibbs * Save off the residual if there is one. 51974972Sgibbs */ 52095378Sgibbs ahc_update_residual(ahc, scb); 52139220Sgibbs#ifdef AHC_DEBUG 522102670Sgibbs if (ahc_debug & AHC_SHOW_SENSE) { 52374972Sgibbs ahc_print_path(ahc, scb); 52474972Sgibbs printf("Sending Sense\n"); 52574972Sgibbs } 52639220Sgibbs#endif 52774972Sgibbs sg->addr = ahc_get_sense_bufaddr(ahc, scb); 528123579Sgibbs sg->len = aic_get_sense_bufsize(ahc, scb); 52974972Sgibbs sg->len |= AHC_DMA_LAST_SEG; 53045965Sgibbs 53174972Sgibbs /* Fixup byte order */ 532123579Sgibbs sg->addr = aic_htole32(sg->addr); 533123579Sgibbs sg->len = aic_htole32(sg->len); 53470693Sgibbs 53574972Sgibbs sc->opcode = REQUEST_SENSE; 53674972Sgibbs sc->byte2 = 0; 53774972Sgibbs if (tinfo->protocol_version <= SCSI_REV_2 53874972Sgibbs && SCB_GET_LUN(scb) < 8) 53974972Sgibbs sc->byte2 = SCB_GET_LUN(scb) << 5; 54074972Sgibbs sc->unused[0] = 0; 54174972Sgibbs sc->unused[1] = 0; 54274972Sgibbs sc->length = sg->len; 54374972Sgibbs sc->control = 0; 54439220Sgibbs 54574972Sgibbs /* 54674972Sgibbs * We can't allow the target to disconnect. 54774972Sgibbs * This will be an untagged transaction and 54874972Sgibbs * having the target disconnect will make this 54974972Sgibbs * transaction indestinguishable from outstanding 55074972Sgibbs * tagged transactions. 55174972Sgibbs */ 55274972Sgibbs hscb->control = 0; 55341646Sgibbs 55474972Sgibbs /* 55574972Sgibbs * This request sense could be because the 55674972Sgibbs * the device lost power or in some other 55774972Sgibbs * way has lost our transfer negotiations. 55874972Sgibbs * Renegotiate if appropriate. Unit attention 55974972Sgibbs * errors will be reported before any data 56074972Sgibbs * phases occur. 56174972Sgibbs */ 562123579Sgibbs if (aic_get_residual(scb) 563123579Sgibbs == aic_get_transfer_length(scb)) { 56474972Sgibbs ahc_update_neg_request(ahc, &devinfo, 56574972Sgibbs tstate, targ_info, 566107420Sscottl AHC_NEG_IF_NON_ASYNC); 56774972Sgibbs } 56874972Sgibbs if (tstate->auto_negotiate & devinfo.target_mask) { 56974972Sgibbs hscb->control |= MK_MESSAGE; 57074972Sgibbs scb->flags &= ~SCB_NEGOTIATE; 57174972Sgibbs scb->flags |= SCB_AUTO_NEGOTIATE; 57274972Sgibbs } 57374972Sgibbs hscb->cdb_len = sizeof(*sc); 57474972Sgibbs hscb->dataptr = sg->addr; 57574972Sgibbs hscb->datacnt = sg->len; 57674972Sgibbs hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; 577123579Sgibbs hscb->sgptr = aic_htole32(hscb->sgptr); 57874972Sgibbs scb->sg_count = 1; 57974972Sgibbs scb->flags |= SCB_SENSE; 58074972Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 58174972Sgibbs ahc_outb(ahc, RETURN_1, SEND_SENSE); 58274972Sgibbs /* 58374972Sgibbs * Ensure we have enough time to actually 584133911Sgibbs * retrieve the sense, but only schedule 585133911Sgibbs * the timer if we are not in recovery or 586133911Sgibbs * this is a recovery SCB that is allowed 587133911Sgibbs * to have an active timer. 58874972Sgibbs */ 589133911Sgibbs if (ahc->scb_data->recovery_scbs == 0 590133911Sgibbs || (scb->flags & SCB_RECOVERY_SCB) != 0) 591137870Sgibbs aic_scb_timer_reset(scb, 5 * 1000); 59239220Sgibbs break; 59374972Sgibbs } 59463457Sgibbs default: 59539220Sgibbs break; 59639220Sgibbs } 59739220Sgibbs break; 59839220Sgibbs } 59963457Sgibbs case NO_MATCH: 60042652Sgibbs { 60163457Sgibbs /* Ensure we don't leave the selection hardware on */ 60263457Sgibbs ahc_outb(ahc, SCSISEQ, 60363457Sgibbs ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); 60463457Sgibbs 60563457Sgibbs printf("%s:%c:%d: no active SCB for reconnecting " 60663457Sgibbs "target - issuing BUS DEVICE RESET\n", 60763457Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target); 60863457Sgibbs printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " 60968087Sgibbs "ARG_1 == 0x%x ACCUM = 0x%x\n", 61063457Sgibbs ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), 61168087Sgibbs ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); 61268087Sgibbs printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " 61368087Sgibbs "SINDEX == 0x%x\n", 61468087Sgibbs ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), 61568087Sgibbs ahc_index_busy_tcl(ahc, 61668087Sgibbs BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID), 61770204Sgibbs ahc_inb(ahc, SAVED_LUN))), 61870204Sgibbs ahc_inb(ahc, SINDEX)); 61968087Sgibbs printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " 62068087Sgibbs "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", 62168087Sgibbs ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), 62268087Sgibbs ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), 62368087Sgibbs ahc_inb(ahc, SCB_CONTROL)); 62471390Sgibbs printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", 62571390Sgibbs ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); 62671390Sgibbs printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); 62771390Sgibbs printf("SEQCTL == 0x%x\n", ahc_inb(ahc, SEQCTL)); 62868087Sgibbs ahc_dump_card_state(ahc); 62963457Sgibbs ahc->msgout_buf[0] = MSG_BUS_DEV_RESET; 63063457Sgibbs ahc->msgout_len = 1; 63163457Sgibbs ahc->msgout_index = 0; 63263457Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 63363457Sgibbs ahc_outb(ahc, MSG_OUT, HOST_MSG); 63476634Sgibbs ahc_assert_atn(ahc); 63542652Sgibbs break; 63642652Sgibbs } 63763457Sgibbs case SEND_REJECT: 63863457Sgibbs { 63963457Sgibbs u_int rejbyte = ahc_inb(ahc, ACCUM); 64063457Sgibbs printf("%s:%c:%d: Warning - unknown message received from " 64163457Sgibbs "target (0x%x). Rejecting\n", 64263457Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, rejbyte); 64363457Sgibbs break; 64463457Sgibbs } 645107420Sscottl case PROTO_VIOLATION: 64663457Sgibbs { 647107420Sscottl ahc_handle_proto_violation(ahc); 648107420Sscottl break; 64963457Sgibbs } 65063457Sgibbs case IGN_WIDE_RES: 65163457Sgibbs ahc_handle_ign_wide_residue(ahc, &devinfo); 65263457Sgibbs break; 65379874Sgibbs case PDATA_REINIT: 65479874Sgibbs ahc_reinitialize_dataptrs(ahc); 65579874Sgibbs break; 65663457Sgibbs case BAD_PHASE: 65763457Sgibbs { 65863457Sgibbs u_int lastphase; 65963457Sgibbs 66063457Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 66168579Sgibbs printf("%s:%c:%d: unknown scsi bus phase %x, " 66268579Sgibbs "lastphase = 0x%x. Attempting to continue\n", 66368579Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, 66468579Sgibbs lastphase, ahc_inb(ahc, SCSISIGI)); 66568579Sgibbs break; 66663457Sgibbs } 66768579Sgibbs case MISSED_BUSFREE: 66868579Sgibbs { 66968579Sgibbs u_int lastphase; 67068579Sgibbs 67168579Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 67268579Sgibbs printf("%s:%c:%d: Missed busfree. " 67368579Sgibbs "Lastphase = 0x%x, Curphase = 0x%x\n", 67468579Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, 67568579Sgibbs lastphase, ahc_inb(ahc, SCSISIGI)); 67674094Sgibbs ahc_restart(ahc); 67768579Sgibbs return; 67868579Sgibbs } 67941646Sgibbs case HOST_MSG_LOOP: 68039220Sgibbs { 68139220Sgibbs /* 68241646Sgibbs * The sequencer has encountered a message phase 68341646Sgibbs * that requires host assistance for completion. 68441646Sgibbs * While handling the message phase(s), we will be 68541646Sgibbs * notified by the sequencer after each byte is 68663457Sgibbs * transfered so we can track bus phase changes. 68741646Sgibbs * 68863457Sgibbs * If this is the first time we've seen a HOST_MSG_LOOP 68963457Sgibbs * interrupt, initialize the state of the host message 69063457Sgibbs * loop. 69139220Sgibbs */ 69241646Sgibbs if (ahc->msg_type == MSG_TYPE_NONE) { 69374972Sgibbs struct scb *scb; 69474972Sgibbs u_int scb_index; 69541646Sgibbs u_int bus_phase; 69639220Sgibbs 69741646Sgibbs bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 69849933Sgibbs if (bus_phase != P_MESGIN 69949933Sgibbs && bus_phase != P_MESGOUT) { 70049933Sgibbs printf("ahc_intr: HOST_MSG_LOOP bad " 70149933Sgibbs "phase 0x%x\n", 70241646Sgibbs bus_phase); 70349933Sgibbs /* 70449933Sgibbs * Probably transitioned to bus free before 70549933Sgibbs * we got here. Just punt the message. 70649933Sgibbs */ 70749933Sgibbs ahc_clear_intstat(ahc); 70874094Sgibbs ahc_restart(ahc); 70963457Sgibbs return; 71049933Sgibbs } 71139220Sgibbs 71274972Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 71374972Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 71441646Sgibbs if (devinfo.role == ROLE_INITIATOR) { 71566647Sgibbs if (scb == NULL) 71666647Sgibbs panic("HOST_MSG_LOOP with " 71766647Sgibbs "invalid SCB %x\n", scb_index); 71866647Sgibbs 71941646Sgibbs if (bus_phase == P_MESGOUT) 72041646Sgibbs ahc_setup_initiator_msgout(ahc, 72141646Sgibbs &devinfo, 72241646Sgibbs scb); 72341646Sgibbs else { 72441646Sgibbs ahc->msg_type = 72541646Sgibbs MSG_TYPE_INITIATOR_MSGIN; 72641646Sgibbs ahc->msgin_index = 0; 72739220Sgibbs } 72895378Sgibbs } 729115337Sgibbs#ifdef AHC_TARGET_MODE 73095378Sgibbs else { 73141646Sgibbs if (bus_phase == P_MESGOUT) { 73241646Sgibbs ahc->msg_type = 73341646Sgibbs MSG_TYPE_TARGET_MSGOUT; 73441646Sgibbs ahc->msgin_index = 0; 73565942Sgibbs } 73665942Sgibbs else 73774972Sgibbs ahc_setup_target_msgin(ahc, 73874972Sgibbs &devinfo, 73974972Sgibbs scb); 74095378Sgibbs } 74165942Sgibbs#endif 74239220Sgibbs } 74339220Sgibbs 74465942Sgibbs ahc_handle_message_phase(ahc); 74541646Sgibbs break; 74639220Sgibbs } 74757099Sgibbs case PERR_DETECTED: 74857099Sgibbs { 74957099Sgibbs /* 75057099Sgibbs * If we've cleared the parity error interrupt 75157099Sgibbs * but the sequencer still believes that SCSIPERR 75257099Sgibbs * is true, it must be that the parity error is 75357099Sgibbs * for the currently presented byte on the bus, 75457099Sgibbs * and we are not in a phase (data-in) where we will 75557099Sgibbs * eventually ack this byte. Ack the byte and 75657099Sgibbs * throw it away in the hope that the target will 75757099Sgibbs * take us to message out to deliver the appropriate 75857099Sgibbs * error message. 75957099Sgibbs */ 76057099Sgibbs if ((intstat & SCSIINT) == 0 76157099Sgibbs && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) { 76257099Sgibbs 76376634Sgibbs if ((ahc->features & AHC_DT) == 0) { 76476634Sgibbs u_int curphase; 76576634Sgibbs 76676634Sgibbs /* 76776634Sgibbs * The hardware will only let you ack bytes 76876634Sgibbs * if the expected phase in SCSISIGO matches 76976634Sgibbs * the current phase. Make sure this is 77076634Sgibbs * currently the case. 77176634Sgibbs */ 77276634Sgibbs curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 77376634Sgibbs ahc_outb(ahc, LASTPHASE, curphase); 77476634Sgibbs ahc_outb(ahc, SCSISIGO, curphase); 77576634Sgibbs } 776107420Sscottl if ((ahc_inb(ahc, SCSISIGI) & (CDI|MSGI)) == 0) { 777107420Sscottl int wait; 778107420Sscottl 779107420Sscottl /* 780107420Sscottl * In a data phase. Faster to bitbucket 781107420Sscottl * the data than to individually ack each 782107420Sscottl * byte. This is also the only strategy 783107420Sscottl * that will work with AUTOACK enabled. 784107420Sscottl */ 785107420Sscottl ahc_outb(ahc, SXFRCTL1, 786107420Sscottl ahc_inb(ahc, SXFRCTL1) | BITBUCKET); 787107420Sscottl wait = 5000; 788107420Sscottl while (--wait != 0) { 789107420Sscottl if ((ahc_inb(ahc, SCSISIGI) 790107420Sscottl & (CDI|MSGI)) != 0) 791107420Sscottl break; 792123579Sgibbs aic_delay(100); 793107420Sscottl } 794107420Sscottl ahc_outb(ahc, SXFRCTL1, 795107420Sscottl ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); 796107420Sscottl if (wait == 0) { 797107420Sscottl struct scb *scb; 798107420Sscottl u_int scb_index; 799107420Sscottl 800107420Sscottl ahc_print_devinfo(ahc, &devinfo); 801107420Sscottl printf("Unable to clear parity error. " 802107420Sscottl "Resetting bus.\n"); 803107420Sscottl scb_index = ahc_inb(ahc, SCB_TAG); 804107420Sscottl scb = ahc_lookup_scb(ahc, scb_index); 805107420Sscottl if (scb != NULL) 806123579Sgibbs aic_set_transaction_status(scb, 807107420Sscottl CAM_UNCOR_PARITY); 808107420Sscottl ahc_reset_channel(ahc, devinfo.channel, 809107420Sscottl /*init reset*/TRUE); 810107420Sscottl } 811107420Sscottl } else { 812107420Sscottl ahc_inb(ahc, SCSIDATL); 813107420Sscottl } 81457099Sgibbs } 81557099Sgibbs break; 81657099Sgibbs } 81739220Sgibbs case DATA_OVERRUN: 81839220Sgibbs { 81939220Sgibbs /* 82039220Sgibbs * When the sequencer detects an overrun, it 82139220Sgibbs * places the controller in "BITBUCKET" mode 82239220Sgibbs * and allows the target to complete its transfer. 82339220Sgibbs * Unfortunately, none of the counters get updated 82439220Sgibbs * when the controller is in this mode, so we have 82539220Sgibbs * no way of knowing how large the overrun was. 82639220Sgibbs */ 82739506Sgibbs u_int scbindex = ahc_inb(ahc, SCB_TAG); 82839506Sgibbs u_int lastphase = ahc_inb(ahc, LASTPHASE); 82963457Sgibbs u_int i; 83039220Sgibbs 83166647Sgibbs scb = ahc_lookup_scb(ahc, scbindex); 83255581Sgibbs for (i = 0; i < num_phases; i++) { 83374094Sgibbs if (lastphase == ahc_phase_table[i].phase) 83455581Sgibbs break; 83555581Sgibbs } 83665942Sgibbs ahc_print_path(ahc, scb); 83755581Sgibbs printf("data overrun detected %s." 83839220Sgibbs " Tag == 0x%x.\n", 83974094Sgibbs ahc_phase_table[i].phasemsg, 84055581Sgibbs scb->hscb->tag); 84165942Sgibbs ahc_print_path(ahc, scb); 84265942Sgibbs printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", 84339220Sgibbs ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", 844123579Sgibbs aic_get_transfer_length(scb), scb->sg_count); 84544507Sgibbs if (scb->sg_count > 0) { 84655581Sgibbs for (i = 0; i < scb->sg_count; i++) { 84779874Sgibbs 84879874Sgibbs printf("sg[%d] - Addr 0x%x%x : Length %d\n", 84944507Sgibbs i, 850123579Sgibbs (aic_le32toh(scb->sg_list[i].len) >> 24 85179874Sgibbs & SG_HIGH_ADDR_BITS), 852123579Sgibbs aic_le32toh(scb->sg_list[i].addr), 853123579Sgibbs aic_le32toh(scb->sg_list[i].len) 85470693Sgibbs & AHC_SG_LEN_MASK); 85544507Sgibbs } 85639220Sgibbs } 85739220Sgibbs /* 85863457Sgibbs * Set this and it will take effect when the 85939220Sgibbs * target does a command complete. 86039220Sgibbs */ 86165942Sgibbs ahc_freeze_devq(ahc, scb); 86295378Sgibbs if ((scb->flags & SCB_SENSE) == 0) { 863123579Sgibbs aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); 86495378Sgibbs } else { 86595378Sgibbs scb->flags &= ~SCB_SENSE; 866123579Sgibbs aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); 86795378Sgibbs } 868123579Sgibbs aic_freeze_scb(scb); 86979874Sgibbs 87079874Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 87179874Sgibbs /* 87279874Sgibbs * Clear the channel in case we return 87379874Sgibbs * to data phase later. 87479874Sgibbs */ 87579874Sgibbs ahc_outb(ahc, SXFRCTL0, 87679874Sgibbs ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); 87779874Sgibbs ahc_outb(ahc, SXFRCTL0, 87879874Sgibbs ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); 87979874Sgibbs } 88079874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 88179874Sgibbs u_int dscommand1; 88279874Sgibbs 88379874Sgibbs /* Ensure HHADDR is 0 for future DMA operations. */ 88479874Sgibbs dscommand1 = ahc_inb(ahc, DSCOMMAND1); 88579874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); 88679874Sgibbs ahc_outb(ahc, HADDR, 0); 88779874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1); 88879874Sgibbs } 88939220Sgibbs break; 89039220Sgibbs } 89168402Sgibbs case MKMSG_FAILED: 89239220Sgibbs { 89368402Sgibbs u_int scbindex; 89468402Sgibbs 89568402Sgibbs printf("%s:%c:%d:%d: Attempt to issue message failed\n", 89668402Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, 89768402Sgibbs devinfo.lun); 89868402Sgibbs scbindex = ahc_inb(ahc, SCB_TAG); 89968402Sgibbs scb = ahc_lookup_scb(ahc, scbindex); 90068402Sgibbs if (scb != NULL 90168402Sgibbs && (scb->flags & SCB_RECOVERY_SCB) != 0) 90268402Sgibbs /* 90368402Sgibbs * Ensure that we didn't put a second instance of this 90468402Sgibbs * SCB into the QINFIFO. 90568402Sgibbs */ 90668402Sgibbs ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), 90768402Sgibbs SCB_GET_CHANNEL(ahc, scb), 90868402Sgibbs SCB_GET_LUN(scb), scb->hscb->tag, 90968402Sgibbs ROLE_INITIATOR, /*status*/0, 91068402Sgibbs SEARCH_REMOVE); 91163457Sgibbs break; 91263457Sgibbs } 91368087Sgibbs case NO_FREE_SCB: 91468087Sgibbs { 91568087Sgibbs printf("%s: No free or disconnected SCBs\n", ahc_name(ahc)); 91668087Sgibbs ahc_dump_card_state(ahc); 91768087Sgibbs panic("for safety"); 91868087Sgibbs break; 91968087Sgibbs } 92068087Sgibbs case SCB_MISMATCH: 92168087Sgibbs { 92268087Sgibbs u_int scbptr; 92368087Sgibbs 92468087Sgibbs scbptr = ahc_inb(ahc, SCBPTR); 92568087Sgibbs printf("Bogus TAG after DMA. SCBPTR %d, tag %d, our tag %d\n", 92668087Sgibbs scbptr, ahc_inb(ahc, ARG_1), 92768087Sgibbs ahc->scb_data->hscbs[scbptr].tag); 92868087Sgibbs ahc_dump_card_state(ahc); 92968087Sgibbs panic("for saftey"); 93068087Sgibbs break; 93168087Sgibbs } 93268087Sgibbs case OUT_OF_RANGE: 93368087Sgibbs { 93468087Sgibbs printf("%s: BTT calculation out of range\n", ahc_name(ahc)); 93568087Sgibbs printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " 93668087Sgibbs "ARG_1 == 0x%x ACCUM = 0x%x\n", 93768087Sgibbs ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), 93868087Sgibbs ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); 93968087Sgibbs printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " 94068087Sgibbs "SINDEX == 0x%x\n, A == 0x%x\n", 94168087Sgibbs ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), 94268087Sgibbs ahc_index_busy_tcl(ahc, 94368087Sgibbs BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID), 94470204Sgibbs ahc_inb(ahc, SAVED_LUN))), 94570204Sgibbs ahc_inb(ahc, SINDEX), 94668087Sgibbs ahc_inb(ahc, ACCUM)); 94768087Sgibbs printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " 94868087Sgibbs "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", 94968087Sgibbs ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), 95068087Sgibbs ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), 95168087Sgibbs ahc_inb(ahc, SCB_CONTROL)); 95271390Sgibbs printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", 95371390Sgibbs ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); 95471390Sgibbs ahc_dump_card_state(ahc); 95568087Sgibbs panic("for safety"); 95668087Sgibbs break; 95768087Sgibbs } 95839220Sgibbs default: 95939220Sgibbs printf("ahc_intr: seqint, " 96039220Sgibbs "intstat == 0x%x, scsisigi = 0x%x\n", 96139220Sgibbs intstat, ahc_inb(ahc, SCSISIGI)); 96239220Sgibbs break; 96339220Sgibbs } 96439220Sgibbsunpause: 96539220Sgibbs /* 96639220Sgibbs * The sequencer is paused immediately on 96739220Sgibbs * a SEQINT, so we should restart it when 96839220Sgibbs * we're done. 96939220Sgibbs */ 97074094Sgibbs ahc_unpause(ahc); 97139220Sgibbs} 97239220Sgibbs 97365942Sgibbsvoid 97439506Sgibbsahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) 97539220Sgibbs{ 97639506Sgibbs u_int scb_index; 97768579Sgibbs u_int status0; 97839506Sgibbs u_int status; 97939506Sgibbs struct scb *scb; 98040421Sgibbs char cur_channel; 98140421Sgibbs char intr_channel; 98239220Sgibbs 98340421Sgibbs if ((ahc->features & AHC_TWIN) != 0 98440421Sgibbs && ((ahc_inb(ahc, SBLKCTL) & SELBUSB) != 0)) 98540421Sgibbs cur_channel = 'B'; 98640421Sgibbs else 98740421Sgibbs cur_channel = 'A'; 98840421Sgibbs intr_channel = cur_channel; 98940421Sgibbs 99068579Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 99168579Sgibbs status0 = ahc_inb(ahc, SSTAT0) & IOERR; 99268579Sgibbs else 99368579Sgibbs status0 = 0; 99470204Sgibbs status = ahc_inb(ahc, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR); 99568579Sgibbs if (status == 0 && status0 == 0) { 99640421Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 99740421Sgibbs /* Try the other channel */ 99840421Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); 99972811Sgibbs status = ahc_inb(ahc, SSTAT1) 100072811Sgibbs & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR); 100140421Sgibbs intr_channel = (cur_channel == 'A') ? 'B' : 'A'; 100240421Sgibbs } 100340421Sgibbs if (status == 0) { 100440421Sgibbs printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc)); 100566269Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 100674094Sgibbs ahc_unpause(ahc); 100740421Sgibbs return; 100840421Sgibbs } 100940421Sgibbs } 101039220Sgibbs 1011107420Sscottl /* Make sure the sequencer is in a safe location. */ 1012107420Sscottl ahc_clear_critical_section(ahc); 1013107420Sscottl 101440421Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 101566647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 101666647Sgibbs if (scb != NULL 1017107420Sscottl && (ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) 101839220Sgibbs scb = NULL; 101939220Sgibbs 102068579Sgibbs if ((ahc->features & AHC_ULTRA2) != 0 102172325Sgibbs && (status0 & IOERR) != 0) { 102268579Sgibbs int now_lvd; 102368579Sgibbs 102468579Sgibbs now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40; 102568579Sgibbs printf("%s: Transceiver State Has Changed to %s mode\n", 102668579Sgibbs ahc_name(ahc), now_lvd ? "LVD" : "SE"); 102768579Sgibbs ahc_outb(ahc, CLRSINT0, CLRIOERR); 102868579Sgibbs /* 102968579Sgibbs * When transitioning to SE mode, the reset line 103068579Sgibbs * glitches, triggering an arbitration bug in some 103168579Sgibbs * Ultra2 controllers. This bug is cleared when we 103268579Sgibbs * assert the reset line. Since a reset glitch has 103368579Sgibbs * already occurred with this transition and a 103468579Sgibbs * transceiver state change is handled just like 103568579Sgibbs * a bus reset anyway, asserting the reset line 103668579Sgibbs * ourselves is safe. 103768579Sgibbs */ 103868579Sgibbs ahc_reset_channel(ahc, intr_channel, 103968579Sgibbs /*Initiate Reset*/now_lvd == 0); 104068579Sgibbs } else if ((status & SCSIRSTI) != 0) { 104139220Sgibbs printf("%s: Someone reset channel %c\n", 104240421Sgibbs ahc_name(ahc), intr_channel); 104372811Sgibbs if (intr_channel != cur_channel) 104472811Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); 104568579Sgibbs ahc_reset_channel(ahc, intr_channel, /*Initiate Reset*/FALSE); 104657099Sgibbs } else if ((status & SCSIPERR) != 0) { 104739220Sgibbs /* 104857099Sgibbs * Determine the bus phase and queue an appropriate message. 104957099Sgibbs * SCSIPERR is latched true as soon as a parity error 105057099Sgibbs * occurs. If the sequencer acked the transfer that 105157099Sgibbs * caused the parity error and the currently presented 105257099Sgibbs * transfer on the bus has correct parity, SCSIPERR will 105357099Sgibbs * be cleared by CLRSCSIPERR. Use this to determine if 105457099Sgibbs * we should look at the last phase the sequencer recorded, 105557099Sgibbs * or the current phase presented on the bus. 105657099Sgibbs */ 1057114621Sgibbs struct ahc_devinfo devinfo; 1058114621Sgibbs u_int mesg_out; 1059114621Sgibbs u_int curphase; 1060114621Sgibbs u_int errorphase; 1061114621Sgibbs u_int lastphase; 1062114621Sgibbs u_int scsirate; 1063114621Sgibbs u_int i; 1064114621Sgibbs u_int sstat2; 1065114621Sgibbs int silent; 106657099Sgibbs 106757099Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 106857099Sgibbs curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 106965942Sgibbs sstat2 = ahc_inb(ahc, SSTAT2); 107057099Sgibbs ahc_outb(ahc, CLRSINT1, CLRSCSIPERR); 107157099Sgibbs /* 107257099Sgibbs * For all phases save DATA, the sequencer won't 107357099Sgibbs * automatically ack a byte that has a parity error 107457099Sgibbs * in it. So the only way that the current phase 107557099Sgibbs * could be 'data-in' is if the parity error is for 107657099Sgibbs * an already acked byte in the data phase. During 107757099Sgibbs * synchronous data-in transfers, we may actually 107857099Sgibbs * ack bytes before latching the current phase in 107957099Sgibbs * LASTPHASE, leading to the discrepancy between 108057099Sgibbs * curphase and lastphase. 108157099Sgibbs */ 108257099Sgibbs if ((ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0 108365942Sgibbs || curphase == P_DATAIN || curphase == P_DATAIN_DT) 108457099Sgibbs errorphase = curphase; 108557099Sgibbs else 108657099Sgibbs errorphase = lastphase; 108757099Sgibbs 108857099Sgibbs for (i = 0; i < num_phases; i++) { 108974094Sgibbs if (errorphase == ahc_phase_table[i].phase) 109057099Sgibbs break; 109157099Sgibbs } 109274094Sgibbs mesg_out = ahc_phase_table[i].mesg_out; 1093109590Sgibbs silent = FALSE; 1094107420Sscottl if (scb != NULL) { 1095109590Sgibbs if (SCB_IS_SILENT(scb)) 1096109590Sgibbs silent = TRUE; 1097109590Sgibbs else 1098109590Sgibbs ahc_print_path(ahc, scb); 1099107420Sscottl scb->flags |= SCB_TRANSMISSION_ERROR; 1100107420Sscottl } else 110172325Sgibbs printf("%s:%c:%d: ", ahc_name(ahc), intr_channel, 110263457Sgibbs SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID))); 110365942Sgibbs scsirate = ahc_inb(ahc, SCSIRATE); 1104109590Sgibbs if (silent == FALSE) { 1105109590Sgibbs printf("parity error detected %s. " 1106109590Sgibbs "SEQADDR(0x%x) SCSIRATE(0x%x)\n", 1107109590Sgibbs ahc_phase_table[i].phasemsg, 1108109590Sgibbs ahc_inw(ahc, SEQADDR0), 1109109590Sgibbs scsirate); 1110109590Sgibbs if ((ahc->features & AHC_DT) != 0) { 1111109590Sgibbs if ((sstat2 & CRCVALERR) != 0) 1112109590Sgibbs printf("\tCRC Value Mismatch\n"); 1113109590Sgibbs if ((sstat2 & CRCENDERR) != 0) 1114109590Sgibbs printf("\tNo terminal CRC packet " 1115109590Sgibbs "recevied\n"); 1116109590Sgibbs if ((sstat2 & CRCREQERR) != 0) 1117109590Sgibbs printf("\tIllegal CRC packet " 1118109590Sgibbs "request\n"); 1119109590Sgibbs if ((sstat2 & DUAL_EDGE_ERR) != 0) 1120109590Sgibbs printf("\tUnexpected %sDT Data Phase\n", 1121109590Sgibbs (scsirate & SINGLE_EDGE) 1122109590Sgibbs ? "" : "non-"); 1123102670Sgibbs } 112465942Sgibbs } 112565942Sgibbs 1126109590Sgibbs if ((ahc->features & AHC_DT) != 0 1127109590Sgibbs && (sstat2 & DUAL_EDGE_ERR) != 0) { 1128109590Sgibbs /* 1129109590Sgibbs * This error applies regardless of 1130109590Sgibbs * data direction, so ignore the value 1131109590Sgibbs * in the phase table. 1132109590Sgibbs */ 1133109590Sgibbs mesg_out = MSG_INITIATOR_DET_ERR; 1134109590Sgibbs } 1135109590Sgibbs 113657099Sgibbs /* 113757099Sgibbs * We've set the hardware to assert ATN if we 113857099Sgibbs * get a parity error on "in" phases, so all we 113957099Sgibbs * need to do is stuff the message buffer with 114057099Sgibbs * the appropriate message. "In" phases have set 114157099Sgibbs * mesg_out to something other than MSG_NOP. 114257099Sgibbs */ 114357099Sgibbs if (mesg_out != MSG_NOOP) { 114457099Sgibbs if (ahc->msg_type != MSG_TYPE_NONE) 114557099Sgibbs ahc->send_msg_perror = TRUE; 114657099Sgibbs else 114757099Sgibbs ahc_outb(ahc, MSG_OUT, mesg_out); 114857099Sgibbs } 114995378Sgibbs /* 115095378Sgibbs * Force a renegotiation with this target just in 115195378Sgibbs * case we are out of sync for some external reason 115295378Sgibbs * unknown (or unreported) by the target. 115395378Sgibbs */ 1154114621Sgibbs ahc_fetch_devinfo(ahc, &devinfo); 1155114621Sgibbs ahc_force_renegotiation(ahc, &devinfo); 1156114621Sgibbs 115757099Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 115874094Sgibbs ahc_unpause(ahc); 115976634Sgibbs } else if ((status & SELTO) != 0) { 116095378Sgibbs u_int scbptr; 116176634Sgibbs 116276634Sgibbs /* Stop the selection */ 116376634Sgibbs ahc_outb(ahc, SCSISEQ, 0); 116476634Sgibbs 116576634Sgibbs /* No more pending messages */ 116676634Sgibbs ahc_clear_msg_state(ahc); 116776634Sgibbs 116876634Sgibbs /* Clear interrupt state */ 116976634Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE); 117076634Sgibbs ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR); 117176634Sgibbs 117276634Sgibbs /* 117376634Sgibbs * Although the driver does not care about the 117476634Sgibbs * 'Selection in Progress' status bit, the busy 117576634Sgibbs * LED does. SELINGO is only cleared by a sucessfull 117676634Sgibbs * selection, so we must manually clear it to insure 117776634Sgibbs * the LED turns off just incase no future successful 117876634Sgibbs * selections occur (e.g. no devices on the bus). 117976634Sgibbs */ 118076634Sgibbs ahc_outb(ahc, CLRSINT0, CLRSELINGO); 118176634Sgibbs 118276634Sgibbs scbptr = ahc_inb(ahc, WAITING_SCBH); 118376634Sgibbs ahc_outb(ahc, SCBPTR, scbptr); 118476634Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 118576634Sgibbs 118676634Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 118776634Sgibbs if (scb == NULL) { 118876634Sgibbs printf("%s: ahc_intr - referenced scb not " 118976634Sgibbs "valid during SELTO scb(%d, %d)\n", 119076634Sgibbs ahc_name(ahc), scbptr, scb_index); 1191107420Sscottl ahc_dump_card_state(ahc); 119276634Sgibbs } else { 1193114621Sgibbs struct ahc_devinfo devinfo; 1194109590Sgibbs#ifdef AHC_DEBUG 1195109590Sgibbs if ((ahc_debug & AHC_SHOW_SELTO) != 0) { 1196109590Sgibbs ahc_print_path(ahc, scb); 1197109590Sgibbs printf("Saw Selection Timeout for SCB 0x%x\n", 1198109590Sgibbs scb_index); 1199109590Sgibbs } 1200109590Sgibbs#endif 1201114621Sgibbs ahc_scb_devinfo(ahc, &devinfo, scb); 1202123579Sgibbs aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); 120376634Sgibbs ahc_freeze_devq(ahc, scb); 1204129133Sgibbs 1205129133Sgibbs /* 1206129133Sgibbs * Cancel any pending transactions on the device 1207129133Sgibbs * now that it seems to be missing. This will 1208129133Sgibbs * also revert us to async/narrow transfers until 1209129133Sgibbs * we can renegotiate with the device. 1210129133Sgibbs */ 1211129133Sgibbs ahc_handle_devreset(ahc, &devinfo, 1212129133Sgibbs CAM_SEL_TIMEOUT, 1213129133Sgibbs "Selection Timeout", 1214129133Sgibbs /*verbose_level*/1); 121576634Sgibbs } 121676634Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 121776634Sgibbs ahc_restart(ahc); 121857099Sgibbs } else if ((status & BUSFREE) != 0 121957099Sgibbs && (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) { 1220114621Sgibbs struct ahc_devinfo devinfo; 1221114621Sgibbs u_int lastphase; 1222114621Sgibbs u_int saved_scsiid; 1223114621Sgibbs u_int saved_lun; 1224114621Sgibbs u_int target; 1225114621Sgibbs u_int initiator_role_id; 1226114621Sgibbs char channel; 1227114621Sgibbs int printerror; 122872325Sgibbs 122957099Sgibbs /* 123072325Sgibbs * Clear our selection hardware as soon as possible. 123172325Sgibbs * We may have an entry in the waiting Q for this target, 123272325Sgibbs * that is affected by this busfree and we don't want to 123372325Sgibbs * go about selecting the target while we handle the event. 123472325Sgibbs */ 123572325Sgibbs ahc_outb(ahc, SCSISEQ, 123672325Sgibbs ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); 123772325Sgibbs 123872325Sgibbs /* 123972325Sgibbs * Disable busfree interrupts and clear the busfree 124072325Sgibbs * interrupt status. We do this here so that several 124172325Sgibbs * bus transactions occur prior to clearing the SCSIINT 124272325Sgibbs * latch. It can take a bit for the clearing to take effect. 124372325Sgibbs */ 124472325Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE); 124572325Sgibbs ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR); 124672325Sgibbs 124772325Sgibbs /* 124872325Sgibbs * Look at what phase we were last in. 124939220Sgibbs * If its message out, chances are pretty good 125039220Sgibbs * that the busfree was in response to one of 125139220Sgibbs * our abort requests. 125239220Sgibbs */ 125372325Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 125472325Sgibbs saved_scsiid = ahc_inb(ahc, SAVED_SCSIID); 125572325Sgibbs saved_lun = ahc_inb(ahc, SAVED_LUN); 125672325Sgibbs target = SCSIID_TARGET(ahc, saved_scsiid); 125772325Sgibbs initiator_role_id = SCSIID_OUR_ID(saved_scsiid); 125872325Sgibbs channel = SCSIID_CHANNEL(ahc, saved_scsiid); 1259114621Sgibbs ahc_compile_devinfo(&devinfo, initiator_role_id, 1260114621Sgibbs target, saved_lun, channel, ROLE_INITIATOR); 126172325Sgibbs printerror = 1; 126239220Sgibbs 126339220Sgibbs if (lastphase == P_MESGOUT) { 126439220Sgibbs u_int tag; 126539220Sgibbs 126639220Sgibbs tag = SCB_LIST_NULL; 126770204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT_TAG, TRUE) 126870204Sgibbs || ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT, TRUE)) { 126970204Sgibbs if (ahc->msgout_buf[ahc->msgout_index - 1] 127070204Sgibbs == MSG_ABORT_TAG) 127170204Sgibbs tag = scb->hscb->tag; 127265942Sgibbs ahc_print_path(ahc, scb); 127372325Sgibbs printf("SCB %d - Abort%s Completed.\n", 127439323Smjacob scb->hscb->tag, tag == SCB_LIST_NULL ? 127572325Sgibbs "" : " Tag"); 127654211Sgibbs ahc_abort_scbs(ahc, target, channel, 127763457Sgibbs saved_lun, tag, 127854211Sgibbs ROLE_INITIATOR, 127954211Sgibbs CAM_REQ_ABORTED); 128039220Sgibbs printerror = 0; 128170204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_1B, 128270204Sgibbs MSG_BUS_DEV_RESET, TRUE)) { 128365942Sgibbs#ifdef __FreeBSD__ 128454211Sgibbs /* 128554211Sgibbs * Don't mark the user's request for this BDR 128654211Sgibbs * as completing with CAM_BDR_SENT. CAM3 128754211Sgibbs * specifies CAM_REQ_CMP. 128854211Sgibbs */ 128954211Sgibbs if (scb != NULL 129065942Sgibbs && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV 129163457Sgibbs && ahc_match_scb(ahc, scb, target, channel, 129265942Sgibbs CAM_LUN_WILDCARD, 129357099Sgibbs SCB_LIST_NULL, 129457099Sgibbs ROLE_INITIATOR)) { 1295123579Sgibbs aic_set_transaction_status(scb, CAM_REQ_CMP); 129654211Sgibbs } 129765942Sgibbs#endif 129844966Sgibbs ahc_compile_devinfo(&devinfo, 129944966Sgibbs initiator_role_id, 130044966Sgibbs target, 130165942Sgibbs CAM_LUN_WILDCARD, 130244966Sgibbs channel, 130344966Sgibbs ROLE_INITIATOR); 130444507Sgibbs ahc_handle_devreset(ahc, &devinfo, 130565942Sgibbs CAM_BDR_SENT, 130639506Sgibbs "Bus Device Reset", 130754211Sgibbs /*verbose_level*/0); 130839220Sgibbs printerror = 0; 130970204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, 131070204Sgibbs MSG_EXT_PPR, FALSE)) { 131170204Sgibbs struct ahc_initiator_tinfo *tinfo; 131274972Sgibbs struct ahc_tmode_tstate *tstate; 131370204Sgibbs 131470204Sgibbs /* 131570204Sgibbs * PPR Rejected. Try non-ppr negotiation 131670204Sgibbs * and retry command. 131770204Sgibbs */ 131870204Sgibbs tinfo = ahc_fetch_transinfo(ahc, 131970204Sgibbs devinfo.channel, 132070204Sgibbs devinfo.our_scsiid, 132170204Sgibbs devinfo.target, 132270204Sgibbs &tstate); 132376634Sgibbs tinfo->curr.transport_version = 2; 132470204Sgibbs tinfo->goal.transport_version = 2; 132570204Sgibbs tinfo->goal.ppr_options = 0; 132670204Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 132770204Sgibbs printerror = 0; 132870204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, 1329115918Sgibbs MSG_EXT_WDTR, FALSE)) { 133070204Sgibbs /* 1331115918Sgibbs * Negotiation Rejected. Go-narrow and 133270204Sgibbs * retry command. 133370204Sgibbs */ 133470204Sgibbs ahc_set_width(ahc, &devinfo, 133570204Sgibbs MSG_EXT_WDTR_BUS_8_BIT, 133670204Sgibbs AHC_TRANS_CUR|AHC_TRANS_GOAL, 133770204Sgibbs /*paused*/TRUE); 1338115918Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 1339115918Sgibbs printerror = 0; 1340115918Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, 1341115918Sgibbs MSG_EXT_SDTR, FALSE)) { 1342115918Sgibbs /* 1343115918Sgibbs * Negotiation Rejected. Go-async and 1344115918Sgibbs * retry command. 1345115918Sgibbs */ 134670204Sgibbs ahc_set_syncrate(ahc, &devinfo, 134770204Sgibbs /*syncrate*/NULL, 134870204Sgibbs /*period*/0, /*offset*/0, 134970204Sgibbs /*ppr_options*/0, 135070204Sgibbs AHC_TRANS_CUR|AHC_TRANS_GOAL, 135170204Sgibbs /*paused*/TRUE); 135270204Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 135370204Sgibbs printerror = 0; 135444507Sgibbs } 135539220Sgibbs } 135639220Sgibbs if (printerror != 0) { 135763457Sgibbs u_int i; 135855581Sgibbs 135939220Sgibbs if (scb != NULL) { 136039506Sgibbs u_int tag; 136139220Sgibbs 136239220Sgibbs if ((scb->hscb->control & TAG_ENB) != 0) 136339220Sgibbs tag = scb->hscb->tag; 136439220Sgibbs else 136539220Sgibbs tag = SCB_LIST_NULL; 136666800Sgibbs ahc_print_path(ahc, scb); 136739220Sgibbs ahc_abort_scbs(ahc, target, channel, 136863457Sgibbs SCB_GET_LUN(scb), tag, 136949933Sgibbs ROLE_INITIATOR, 137039220Sgibbs CAM_UNEXP_BUSFREE); 137139220Sgibbs } else { 137257099Sgibbs /* 137357099Sgibbs * We had not fully identified this connection, 137457099Sgibbs * so we cannot abort anything. 137557099Sgibbs */ 137639220Sgibbs printf("%s: ", ahc_name(ahc)); 137739220Sgibbs } 137855581Sgibbs for (i = 0; i < num_phases; i++) { 137974094Sgibbs if (lastphase == ahc_phase_table[i].phase) 138055581Sgibbs break; 138155581Sgibbs } 1382114621Sgibbs if (lastphase != P_BUSFREE) { 1383114621Sgibbs /* 1384114621Sgibbs * Renegotiate with this device at the 1385114621Sgibbs * next oportunity just in case this busfree 1386114621Sgibbs * is due to a negotiation mismatch with the 1387114621Sgibbs * device. 1388114621Sgibbs */ 1389114621Sgibbs ahc_force_renegotiation(ahc, &devinfo); 1390114621Sgibbs } 139155581Sgibbs printf("Unexpected busfree %s\n" 139239220Sgibbs "SEQADDR == 0x%x\n", 139374094Sgibbs ahc_phase_table[i].phasemsg, 139474094Sgibbs ahc_inb(ahc, SEQADDR0) 139539220Sgibbs | (ahc_inb(ahc, SEQADDR1) << 8)); 139639220Sgibbs } 139739220Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 139874094Sgibbs ahc_restart(ahc); 139939220Sgibbs } else { 140072325Sgibbs printf("%s: Missing case in ahc_handle_scsiint. status = %x\n", 140172325Sgibbs ahc_name(ahc), status); 140272325Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 140339220Sgibbs } 140439220Sgibbs} 140539220Sgibbs 140695378Sgibbs/* 140795378Sgibbs * Force renegotiation to occur the next time we initiate 140895378Sgibbs * a command to the current device. 140995378Sgibbs */ 141095378Sgibbsstatic void 1411114621Sgibbsahc_force_renegotiation(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 141295378Sgibbs{ 141395378Sgibbs struct ahc_initiator_tinfo *targ_info; 141495378Sgibbs struct ahc_tmode_tstate *tstate; 141595378Sgibbs 141695378Sgibbs targ_info = ahc_fetch_transinfo(ahc, 1417114621Sgibbs devinfo->channel, 1418114621Sgibbs devinfo->our_scsiid, 1419114621Sgibbs devinfo->target, 142095378Sgibbs &tstate); 1421114621Sgibbs ahc_update_neg_request(ahc, devinfo, tstate, 1422107420Sscottl targ_info, AHC_NEG_IF_NON_ASYNC); 142395378Sgibbs} 142495378Sgibbs 142568579Sgibbs#define AHC_MAX_STEPS 2000 142666647Sgibbsvoid 142766647Sgibbsahc_clear_critical_section(struct ahc_softc *ahc) 142866647Sgibbs{ 142966647Sgibbs int stepping; 143068579Sgibbs int steps; 143166845Sgibbs u_int simode0; 143266845Sgibbs u_int simode1; 143365942Sgibbs 143466647Sgibbs if (ahc->num_critical_sections == 0) 143566647Sgibbs return; 143666647Sgibbs 143766647Sgibbs stepping = FALSE; 143868579Sgibbs steps = 0; 143966845Sgibbs simode0 = 0; 144066845Sgibbs simode1 = 0; 144166647Sgibbs for (;;) { 144266647Sgibbs struct cs *cs; 144366647Sgibbs u_int seqaddr; 144466647Sgibbs u_int i; 144566647Sgibbs 144666647Sgibbs seqaddr = ahc_inb(ahc, SEQADDR0) 144766647Sgibbs | (ahc_inb(ahc, SEQADDR1) << 8); 144866647Sgibbs 144981170Sgibbs /* 145081170Sgibbs * Seqaddr represents the next instruction to execute, 145181170Sgibbs * so we are really executing the instruction just 145281170Sgibbs * before it. 145381170Sgibbs */ 145466647Sgibbs cs = ahc->critical_sections; 145566647Sgibbs for (i = 0; i < ahc->num_critical_sections; i++, cs++) { 145666647Sgibbs 145766647Sgibbs if (cs->begin < seqaddr && cs->end >= seqaddr) 145866647Sgibbs break; 145966647Sgibbs } 146066647Sgibbs 146166647Sgibbs if (i == ahc->num_critical_sections) 146266647Sgibbs break; 146366647Sgibbs 146468579Sgibbs if (steps > AHC_MAX_STEPS) { 146568579Sgibbs printf("%s: Infinite loop in critical section\n", 146668579Sgibbs ahc_name(ahc)); 146768579Sgibbs ahc_dump_card_state(ahc); 146868579Sgibbs panic("critical section loop"); 146968579Sgibbs } 147068579Sgibbs 147168579Sgibbs steps++; 147266845Sgibbs if (stepping == FALSE) { 147366845Sgibbs 147466845Sgibbs /* 147566845Sgibbs * Disable all interrupt sources so that the 147666845Sgibbs * sequencer will not be stuck by a pausing 147766845Sgibbs * interrupt condition while we attempt to 147866845Sgibbs * leave a critical section. 147966845Sgibbs */ 148066845Sgibbs simode0 = ahc_inb(ahc, SIMODE0); 148166845Sgibbs ahc_outb(ahc, SIMODE0, 0); 148266845Sgibbs simode1 = ahc_inb(ahc, SIMODE1); 1483107420Sscottl if ((ahc->features & AHC_DT) != 0) 1484107420Sscottl /* 1485107420Sscottl * On DT class controllers, we 1486107420Sscottl * use the enhanced busfree logic. 1487107420Sscottl * Unfortunately we cannot re-enable 1488107420Sscottl * busfree detection within the 1489107420Sscottl * current connection, so we must 1490107420Sscottl * leave it on while single stepping. 1491107420Sscottl */ 1492115920Sgibbs ahc_outb(ahc, SIMODE1, simode1 & ENBUSFREE); 1493107420Sscottl else 1494107420Sscottl ahc_outb(ahc, SIMODE1, 0); 149566845Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 1496115332Sgibbs ahc_outb(ahc, SEQCTL, ahc->seqctl | STEP); 149766647Sgibbs stepping = TRUE; 149866647Sgibbs } 1499107420Sscottl if ((ahc->features & AHC_DT) != 0) { 1500107420Sscottl ahc_outb(ahc, CLRSINT1, CLRBUSFREE); 1501107420Sscottl ahc_outb(ahc, CLRINT, CLRSCSIINT); 1502107420Sscottl } 150366647Sgibbs ahc_outb(ahc, HCNTRL, ahc->unpause); 150495378Sgibbs while (!ahc_is_paused(ahc)) 1505123579Sgibbs aic_delay(200); 150666647Sgibbs } 150766845Sgibbs if (stepping) { 150866845Sgibbs ahc_outb(ahc, SIMODE0, simode0); 150966845Sgibbs ahc_outb(ahc, SIMODE1, simode1); 1510115332Sgibbs ahc_outb(ahc, SEQCTL, ahc->seqctl); 151166845Sgibbs } 151266647Sgibbs} 151366647Sgibbs 151465942Sgibbs/* 151565942Sgibbs * Clear any pending interrupt status. 151665942Sgibbs */ 151765942Sgibbsvoid 151865942Sgibbsahc_clear_intstat(struct ahc_softc *ahc) 151941646Sgibbs{ 152065942Sgibbs /* Clear any interrupt conditions this may have caused */ 152165942Sgibbs ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI 152265942Sgibbs |CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG| 152365942Sgibbs CLRREQINIT); 152495378Sgibbs ahc_flush_device_writes(ahc); 152570204Sgibbs ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO); 152695378Sgibbs ahc_flush_device_writes(ahc); 152765942Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 152895378Sgibbs ahc_flush_device_writes(ahc); 152965942Sgibbs} 153065942Sgibbs 153165942Sgibbs/**************************** Debugging Routines ******************************/ 153295378Sgibbs#ifdef AHC_DEBUG 1533102670Sgibbsuint32_t ahc_debug = AHC_DEBUG_OPTS; 153495378Sgibbs#endif 153595378Sgibbs 153665942Sgibbsvoid 153765942Sgibbsahc_print_scb(struct scb *scb) 153865942Sgibbs{ 153965942Sgibbs int i; 154065942Sgibbs 154165942Sgibbs struct hardware_scb *hscb = scb->hscb; 154265942Sgibbs 154365942Sgibbs printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", 154479874Sgibbs (void *)scb, 154565942Sgibbs hscb->control, 154665942Sgibbs hscb->scsiid, 154765942Sgibbs hscb->lun, 154865942Sgibbs hscb->cdb_len); 154988022Sgibbs printf("Shared Data: "); 155088022Sgibbs for (i = 0; i < sizeof(hscb->shared_data.cdb); i++) 155188022Sgibbs printf("%#02x", hscb->shared_data.cdb[i]); 155265942Sgibbs printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", 1553123579Sgibbs aic_le32toh(hscb->dataptr), 1554123579Sgibbs aic_le32toh(hscb->datacnt), 1555123579Sgibbs aic_le32toh(hscb->sgptr), 155665942Sgibbs hscb->tag); 155765942Sgibbs if (scb->sg_count > 0) { 155865942Sgibbs for (i = 0; i < scb->sg_count; i++) { 155979874Sgibbs printf("sg[%d] - Addr 0x%x%x : Length %d\n", 156065942Sgibbs i, 1561123579Sgibbs (aic_le32toh(scb->sg_list[i].len) >> 24 156279874Sgibbs & SG_HIGH_ADDR_BITS), 1563123579Sgibbs aic_le32toh(scb->sg_list[i].addr), 1564123579Sgibbs aic_le32toh(scb->sg_list[i].len)); 156565942Sgibbs } 156665942Sgibbs } 156765942Sgibbs} 156865942Sgibbs 156965942Sgibbs/************************* Transfer Negotiation *******************************/ 157065942Sgibbs/* 157165942Sgibbs * Allocate per target mode instance (ID we respond to as a target) 157265942Sgibbs * transfer negotiation data structures. 157365942Sgibbs */ 157474972Sgibbsstatic struct ahc_tmode_tstate * 157565942Sgibbsahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel) 157665942Sgibbs{ 157774972Sgibbs struct ahc_tmode_tstate *master_tstate; 157874972Sgibbs struct ahc_tmode_tstate *tstate; 157965942Sgibbs int i; 158065942Sgibbs 158165942Sgibbs master_tstate = ahc->enabled_targets[ahc->our_id]; 158265942Sgibbs if (channel == 'B') { 158365942Sgibbs scsi_id += 8; 158465942Sgibbs master_tstate = ahc->enabled_targets[ahc->our_id_b + 8]; 158565942Sgibbs } 158665942Sgibbs if (ahc->enabled_targets[scsi_id] != NULL 158765942Sgibbs && ahc->enabled_targets[scsi_id] != master_tstate) 158865942Sgibbs panic("%s: ahc_alloc_tstate - Target already allocated", 158965942Sgibbs ahc_name(ahc)); 1590102670Sgibbs tstate = (struct ahc_tmode_tstate*)malloc(sizeof(*tstate), 1591102670Sgibbs M_DEVBUF, M_NOWAIT); 159265942Sgibbs if (tstate == NULL) 159365942Sgibbs return (NULL); 159465942Sgibbs 159541646Sgibbs /* 159665942Sgibbs * If we have allocated a master tstate, copy user settings from 159765942Sgibbs * the master tstate (taken from SRAM or the EEPROM) for this 159865942Sgibbs * channel, but reset our current and goal settings to async/narrow 159965942Sgibbs * until an initiator talks to us. 160041646Sgibbs */ 160165942Sgibbs if (master_tstate != NULL) { 160265942Sgibbs memcpy(tstate, master_tstate, sizeof(*tstate)); 160365942Sgibbs memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns)); 160465942Sgibbs tstate->ultraenb = 0; 160595378Sgibbs for (i = 0; i < AHC_NUM_TARGETS; i++) { 160676634Sgibbs memset(&tstate->transinfo[i].curr, 0, 160776634Sgibbs sizeof(tstate->transinfo[i].curr)); 160865942Sgibbs memset(&tstate->transinfo[i].goal, 0, 160965942Sgibbs sizeof(tstate->transinfo[i].goal)); 161065942Sgibbs } 161165942Sgibbs } else 161265942Sgibbs memset(tstate, 0, sizeof(*tstate)); 161365942Sgibbs ahc->enabled_targets[scsi_id] = tstate; 161465942Sgibbs return (tstate); 161565942Sgibbs} 161665942Sgibbs 161771717Sgibbs#ifdef AHC_TARGET_MODE 161865942Sgibbs/* 161965942Sgibbs * Free per target mode instance (ID we respond to as a target) 162065942Sgibbs * transfer negotiation data structures. 162165942Sgibbs */ 162265942Sgibbsstatic void 162365942Sgibbsahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force) 162465942Sgibbs{ 162574972Sgibbs struct ahc_tmode_tstate *tstate; 162665942Sgibbs 162774972Sgibbs /* 162874972Sgibbs * Don't clean up our "master" tstate. 162974972Sgibbs * It has our default user settings. 163074972Sgibbs */ 163174972Sgibbs if (((channel == 'B' && scsi_id == ahc->our_id_b) 163265942Sgibbs || (channel == 'A' && scsi_id == ahc->our_id)) 163365942Sgibbs && force == FALSE) 163465942Sgibbs return; 163565942Sgibbs 163665942Sgibbs if (channel == 'B') 163765942Sgibbs scsi_id += 8; 163865942Sgibbs tstate = ahc->enabled_targets[scsi_id]; 163965942Sgibbs if (tstate != NULL) 164065942Sgibbs free(tstate, M_DEVBUF); 164165942Sgibbs ahc->enabled_targets[scsi_id] = NULL; 164265942Sgibbs} 164371717Sgibbs#endif 164465942Sgibbs 164565942Sgibbs/* 164665942Sgibbs * Called when we have an active connection to a target on the bus, 164765942Sgibbs * this function finds the nearest syncrate to the input period limited 164868087Sgibbs * by the capabilities of the bus connectivity of and sync settings for 164968087Sgibbs * the target. 165065942Sgibbs */ 1651107420Sscottlstruct ahc_syncrate * 165268087Sgibbsahc_devlimited_syncrate(struct ahc_softc *ahc, 165368087Sgibbs struct ahc_initiator_tinfo *tinfo, 165495378Sgibbs u_int *period, u_int *ppr_options, role_t role) 165595378Sgibbs{ 165668087Sgibbs struct ahc_transinfo *transinfo; 165765942Sgibbs u_int maxsync; 165865942Sgibbs 165965942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 166065942Sgibbs if ((ahc_inb(ahc, SBLKCTL) & ENAB40) != 0 166165942Sgibbs && (ahc_inb(ahc, SSTAT2) & EXP_ACTIVE) == 0) { 166265942Sgibbs maxsync = AHC_SYNCRATE_DT; 166365942Sgibbs } else { 166465942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 166565942Sgibbs /* Can't do DT on an SE bus */ 166665942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 166765942Sgibbs } 166876634Sgibbs } else if ((ahc->features & AHC_ULTRA) != 0) { 166965942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 167065942Sgibbs } else { 167165942Sgibbs maxsync = AHC_SYNCRATE_FAST; 167265942Sgibbs } 167368087Sgibbs /* 167468087Sgibbs * Never allow a value higher than our current goal 167568087Sgibbs * period otherwise we may allow a target initiated 167668087Sgibbs * negotiation to go above the limit as set by the 167768087Sgibbs * user. In the case of an initiator initiated 167868087Sgibbs * sync negotiation, we limit based on the user 167968087Sgibbs * setting. This allows the system to still accept 168068087Sgibbs * incoming negotiations even if target initiated 168168087Sgibbs * negotiation is not performed. 168268087Sgibbs */ 168368087Sgibbs if (role == ROLE_TARGET) 168468087Sgibbs transinfo = &tinfo->user; 168568087Sgibbs else 168668087Sgibbs transinfo = &tinfo->goal; 168768087Sgibbs *ppr_options &= transinfo->ppr_options; 1688109590Sgibbs if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) { 1689109590Sgibbs maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2); 1690109590Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 1691109590Sgibbs } 169268087Sgibbs if (transinfo->period == 0) { 169368087Sgibbs *period = 0; 169468087Sgibbs *ppr_options = 0; 169568087Sgibbs return (NULL); 169668087Sgibbs } 169768087Sgibbs *period = MAX(*period, transinfo->period); 169865942Sgibbs return (ahc_find_syncrate(ahc, period, ppr_options, maxsync)); 169965942Sgibbs} 170065942Sgibbs 170165942Sgibbs/* 170265942Sgibbs * Look up the valid period to SCSIRATE conversion in our table. 170365942Sgibbs * Return the period and offset that should be sent to the target 170465942Sgibbs * if this was the beginning of an SDTR. 170565942Sgibbs */ 170665942Sgibbsstruct ahc_syncrate * 170765942Sgibbsahc_find_syncrate(struct ahc_softc *ahc, u_int *period, 170865942Sgibbs u_int *ppr_options, u_int maxsync) 170965942Sgibbs{ 171065942Sgibbs struct ahc_syncrate *syncrate; 171165942Sgibbs 171265942Sgibbs if ((ahc->features & AHC_DT) == 0) 171365942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 171476634Sgibbs 171576634Sgibbs /* Skip all DT only entries if DT is not available */ 171676634Sgibbs if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0 171776634Sgibbs && maxsync < AHC_SYNCRATE_ULTRA2) 171876634Sgibbs maxsync = AHC_SYNCRATE_ULTRA2; 171965942Sgibbs 172065942Sgibbs for (syncrate = &ahc_syncrates[maxsync]; 172165942Sgibbs syncrate->rate != NULL; 172265942Sgibbs syncrate++) { 172365942Sgibbs 172465942Sgibbs /* 172565942Sgibbs * The Ultra2 table doesn't go as low 172665942Sgibbs * as for the Fast/Ultra cards. 172765942Sgibbs */ 172865942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0 172965942Sgibbs && (syncrate->sxfr_u2 == 0)) 173065942Sgibbs break; 173165942Sgibbs 173265942Sgibbs if (*period <= syncrate->period) { 173365942Sgibbs /* 173465942Sgibbs * When responding to a target that requests 173565942Sgibbs * sync, the requested rate may fall between 173665942Sgibbs * two rates that we can output, but still be 173765942Sgibbs * a rate that we can receive. Because of this, 173865942Sgibbs * we want to respond to the target with 173965942Sgibbs * the same rate that it sent to us even 174065942Sgibbs * if the period we use to send data to it 174165942Sgibbs * is lower. Only lower the response period 174265942Sgibbs * if we must. 174365942Sgibbs */ 174465942Sgibbs if (syncrate == &ahc_syncrates[maxsync]) 174565942Sgibbs *period = syncrate->period; 174665942Sgibbs 174765942Sgibbs /* 174865942Sgibbs * At some speeds, we only support 174965942Sgibbs * ST transfers. 175065942Sgibbs */ 175165942Sgibbs if ((syncrate->sxfr_u2 & ST_SXFR) != 0) 175265942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 175365942Sgibbs break; 175465942Sgibbs } 175565942Sgibbs } 175665942Sgibbs 175765942Sgibbs if ((*period == 0) 175865942Sgibbs || (syncrate->rate == NULL) 175965942Sgibbs || ((ahc->features & AHC_ULTRA2) != 0 176065942Sgibbs && (syncrate->sxfr_u2 == 0))) { 176165942Sgibbs /* Use asynchronous transfers. */ 176265942Sgibbs *period = 0; 176365942Sgibbs syncrate = NULL; 176465942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 176565942Sgibbs } 176665942Sgibbs return (syncrate); 176765942Sgibbs} 176865942Sgibbs 176965942Sgibbs/* 177065942Sgibbs * Convert from an entry in our syncrate table to the SCSI equivalent 177165942Sgibbs * sync "period" factor. 177265942Sgibbs */ 177365942Sgibbsu_int 177465942Sgibbsahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync) 177565942Sgibbs{ 177665942Sgibbs struct ahc_syncrate *syncrate; 177765942Sgibbs 177865942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 177965942Sgibbs scsirate &= SXFR_ULTRA2; 178065942Sgibbs else 178165942Sgibbs scsirate &= SXFR; 178265942Sgibbs 178365942Sgibbs syncrate = &ahc_syncrates[maxsync]; 178465942Sgibbs while (syncrate->rate != NULL) { 178565942Sgibbs 178665942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 178765942Sgibbs if (syncrate->sxfr_u2 == 0) 178865942Sgibbs break; 178965942Sgibbs else if (scsirate == (syncrate->sxfr_u2 & SXFR_ULTRA2)) 179065942Sgibbs return (syncrate->period); 179165942Sgibbs } else if (scsirate == (syncrate->sxfr & SXFR)) { 179265942Sgibbs return (syncrate->period); 179365942Sgibbs } 179465942Sgibbs syncrate++; 179565942Sgibbs } 179665942Sgibbs return (0); /* async */ 179765942Sgibbs} 179865942Sgibbs 179965942Sgibbs/* 180065942Sgibbs * Truncate the given synchronous offset to a value the 180165942Sgibbs * current adapter type and syncrate are capable of. 180265942Sgibbs */ 180365942Sgibbsvoid 180468087Sgibbsahc_validate_offset(struct ahc_softc *ahc, 180568087Sgibbs struct ahc_initiator_tinfo *tinfo, 180668087Sgibbs struct ahc_syncrate *syncrate, 180768087Sgibbs u_int *offset, int wide, role_t role) 180865942Sgibbs{ 180965942Sgibbs u_int maxoffset; 181065942Sgibbs 181165942Sgibbs /* Limit offset to what we can do */ 181265942Sgibbs if (syncrate == NULL) { 181365942Sgibbs maxoffset = 0; 181465942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 181565942Sgibbs maxoffset = MAX_OFFSET_ULTRA2; 181665942Sgibbs } else { 181765942Sgibbs if (wide) 181865942Sgibbs maxoffset = MAX_OFFSET_16BIT; 181965942Sgibbs else 182065942Sgibbs maxoffset = MAX_OFFSET_8BIT; 182165942Sgibbs } 182265942Sgibbs *offset = MIN(*offset, maxoffset); 182368087Sgibbs if (tinfo != NULL) { 182468087Sgibbs if (role == ROLE_TARGET) 182568087Sgibbs *offset = MIN(*offset, tinfo->user.offset); 182668087Sgibbs else 182768087Sgibbs *offset = MIN(*offset, tinfo->goal.offset); 182868087Sgibbs } 182965942Sgibbs} 183065942Sgibbs 183165942Sgibbs/* 183265942Sgibbs * Truncate the given transfer width parameter to a value the 183365942Sgibbs * current adapter type is capable of. 183465942Sgibbs */ 183565942Sgibbsvoid 183668087Sgibbsahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, 183768087Sgibbs u_int *bus_width, role_t role) 183865942Sgibbs{ 183965942Sgibbs switch (*bus_width) { 184065942Sgibbs default: 184165942Sgibbs if (ahc->features & AHC_WIDE) { 184265942Sgibbs /* Respond Wide */ 184365942Sgibbs *bus_width = MSG_EXT_WDTR_BUS_16_BIT; 184465942Sgibbs break; 184565942Sgibbs } 184665942Sgibbs /* FALLTHROUGH */ 184765942Sgibbs case MSG_EXT_WDTR_BUS_8_BIT: 184868087Sgibbs *bus_width = MSG_EXT_WDTR_BUS_8_BIT; 184965942Sgibbs break; 185065942Sgibbs } 185168087Sgibbs if (tinfo != NULL) { 185268087Sgibbs if (role == ROLE_TARGET) 185368087Sgibbs *bus_width = MIN(tinfo->user.width, *bus_width); 185468087Sgibbs else 185568087Sgibbs *bus_width = MIN(tinfo->goal.width, *bus_width); 185668087Sgibbs } 185765942Sgibbs} 185865942Sgibbs 185965942Sgibbs/* 186065942Sgibbs * Update the bitmask of targets for which the controller should 186165942Sgibbs * negotiate with at the next convenient oportunity. This currently 186265942Sgibbs * means the next time we send the initial identify messages for 186365942Sgibbs * a new transaction. 186465942Sgibbs */ 186574972Sgibbsint 186674972Sgibbsahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 186774972Sgibbs struct ahc_tmode_tstate *tstate, 1868107420Sscottl struct ahc_initiator_tinfo *tinfo, ahc_neg_type neg_type) 186965942Sgibbs{ 187074972Sgibbs u_int auto_negotiate_orig; 187165942Sgibbs 187274972Sgibbs auto_negotiate_orig = tstate->auto_negotiate; 1873107420Sscottl if (neg_type == AHC_NEG_ALWAYS) { 1874107420Sscottl /* 1875107420Sscottl * Force our "current" settings to be 1876107420Sscottl * unknown so that unless a bus reset 1877107420Sscottl * occurs the need to renegotiate is 1878107420Sscottl * recorded persistently. 1879107420Sscottl */ 1880109590Sgibbs if ((ahc->features & AHC_WIDE) != 0) 1881109590Sgibbs tinfo->curr.width = AHC_WIDTH_UNKNOWN; 1882107420Sscottl tinfo->curr.period = AHC_PERIOD_UNKNOWN; 1883107420Sscottl tinfo->curr.offset = AHC_OFFSET_UNKNOWN; 1884107420Sscottl } 188576634Sgibbs if (tinfo->curr.period != tinfo->goal.period 188676634Sgibbs || tinfo->curr.width != tinfo->goal.width 188776634Sgibbs || tinfo->curr.offset != tinfo->goal.offset 188876634Sgibbs || tinfo->curr.ppr_options != tinfo->goal.ppr_options 1889107420Sscottl || (neg_type == AHC_NEG_IF_NON_ASYNC 1890102670Sgibbs && (tinfo->goal.offset != 0 189168087Sgibbs || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT 189268087Sgibbs || tinfo->goal.ppr_options != 0))) 189374972Sgibbs tstate->auto_negotiate |= devinfo->target_mask; 189465942Sgibbs else 189574972Sgibbs tstate->auto_negotiate &= ~devinfo->target_mask; 189665942Sgibbs 189774972Sgibbs return (auto_negotiate_orig != tstate->auto_negotiate); 189865942Sgibbs} 189965942Sgibbs 190065942Sgibbs/* 190176634Sgibbs * Update the user/goal/curr tables of synchronous negotiation 190265942Sgibbs * parameters as well as, in the case of a current or active update, 190365942Sgibbs * any data structures on the host controller. In the case of an 190465942Sgibbs * active update, the specified target is currently talking to us on 190565942Sgibbs * the bus, so the transfer parameter update must take effect 190665942Sgibbs * immediately. 190765942Sgibbs */ 190865942Sgibbsvoid 190965942Sgibbsahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 191065942Sgibbs struct ahc_syncrate *syncrate, u_int period, 191165942Sgibbs u_int offset, u_int ppr_options, u_int type, int paused) 191265942Sgibbs{ 191344507Sgibbs struct ahc_initiator_tinfo *tinfo; 191474972Sgibbs struct ahc_tmode_tstate *tstate; 191565942Sgibbs u_int old_period; 191665942Sgibbs u_int old_offset; 191766647Sgibbs u_int old_ppr; 191874972Sgibbs int active; 191974972Sgibbs int update_needed; 192041646Sgibbs 192174972Sgibbs active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; 192274972Sgibbs update_needed = 0; 192374972Sgibbs 192465942Sgibbs if (syncrate == NULL) { 192565942Sgibbs period = 0; 192665942Sgibbs offset = 0; 192765942Sgibbs } 192865942Sgibbs 192944507Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 193044507Sgibbs devinfo->target, &tstate); 193172811Sgibbs 193272811Sgibbs if ((type & AHC_TRANS_USER) != 0) { 193372811Sgibbs tinfo->user.period = period; 193472811Sgibbs tinfo->user.offset = offset; 193572811Sgibbs tinfo->user.ppr_options = ppr_options; 193672811Sgibbs } 193772811Sgibbs 193872811Sgibbs if ((type & AHC_TRANS_GOAL) != 0) { 193972811Sgibbs tinfo->goal.period = period; 194072811Sgibbs tinfo->goal.offset = offset; 194172811Sgibbs tinfo->goal.ppr_options = ppr_options; 194272811Sgibbs } 194372811Sgibbs 194476634Sgibbs old_period = tinfo->curr.period; 194576634Sgibbs old_offset = tinfo->curr.offset; 194676634Sgibbs old_ppr = tinfo->curr.ppr_options; 194741646Sgibbs 194865942Sgibbs if ((type & AHC_TRANS_CUR) != 0 194966647Sgibbs && (old_period != period 195066647Sgibbs || old_offset != offset 195166647Sgibbs || old_ppr != ppr_options)) { 195265942Sgibbs u_int scsirate; 195365942Sgibbs 195474972Sgibbs update_needed++; 195565942Sgibbs scsirate = tinfo->scsirate; 195665942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 195765942Sgibbs 195865942Sgibbs scsirate &= ~(SXFR_ULTRA2|SINGLE_EDGE|ENABLE_CRC); 195965942Sgibbs if (syncrate != NULL) { 196065942Sgibbs scsirate |= syncrate->sxfr_u2; 196165942Sgibbs if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) 196265942Sgibbs scsirate |= ENABLE_CRC; 196365942Sgibbs else 196465942Sgibbs scsirate |= SINGLE_EDGE; 196565942Sgibbs } 196665942Sgibbs } else { 196765942Sgibbs 196865942Sgibbs scsirate &= ~(SXFR|SOFS); 196965942Sgibbs /* 197065942Sgibbs * Ensure Ultra mode is set properly for 197165942Sgibbs * this target. 197265942Sgibbs */ 197365942Sgibbs tstate->ultraenb &= ~devinfo->target_mask; 197465942Sgibbs if (syncrate != NULL) { 197565942Sgibbs if (syncrate->sxfr & ULTRA_SXFR) { 197665942Sgibbs tstate->ultraenb |= 197765942Sgibbs devinfo->target_mask; 197865942Sgibbs } 197965942Sgibbs scsirate |= syncrate->sxfr & SXFR; 198065942Sgibbs scsirate |= offset & SOFS; 198165942Sgibbs } 198265942Sgibbs if (active) { 198365942Sgibbs u_int sxfrctl0; 198465942Sgibbs 198565942Sgibbs sxfrctl0 = ahc_inb(ahc, SXFRCTL0); 198665942Sgibbs sxfrctl0 &= ~FAST20; 198765942Sgibbs if (tstate->ultraenb & devinfo->target_mask) 198865942Sgibbs sxfrctl0 |= FAST20; 198965942Sgibbs ahc_outb(ahc, SXFRCTL0, sxfrctl0); 199065942Sgibbs } 199165942Sgibbs } 199265942Sgibbs if (active) { 199365942Sgibbs ahc_outb(ahc, SCSIRATE, scsirate); 199465942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 199565942Sgibbs ahc_outb(ahc, SCSIOFFSET, offset); 199665942Sgibbs } 199765942Sgibbs 199865942Sgibbs tinfo->scsirate = scsirate; 199976634Sgibbs tinfo->curr.period = period; 200076634Sgibbs tinfo->curr.offset = offset; 200176634Sgibbs tinfo->curr.ppr_options = ppr_options; 200265942Sgibbs 200366269Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 200476634Sgibbs CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); 200565942Sgibbs if (bootverbose) { 200665942Sgibbs if (offset != 0) { 200765942Sgibbs printf("%s: target %d synchronous at %sMHz%s, " 200865942Sgibbs "offset = 0x%x\n", ahc_name(ahc), 200965942Sgibbs devinfo->target, syncrate->rate, 201065942Sgibbs (ppr_options & MSG_EXT_PPR_DT_REQ) 201165942Sgibbs ? " DT" : "", offset); 201265942Sgibbs } else { 201365942Sgibbs printf("%s: target %d using " 201465942Sgibbs "asynchronous transfers\n", 201565942Sgibbs ahc_name(ahc), devinfo->target); 201665942Sgibbs } 201765942Sgibbs } 201841646Sgibbs } 201941646Sgibbs 202074972Sgibbs update_needed += ahc_update_neg_request(ahc, devinfo, tstate, 2021107420Sscottl tinfo, AHC_NEG_TO_GOAL); 202274972Sgibbs 202374972Sgibbs if (update_needed) 202474972Sgibbs ahc_update_pending_scbs(ahc); 202565942Sgibbs} 202665942Sgibbs 202765942Sgibbs/* 202876634Sgibbs * Update the user/goal/curr tables of wide negotiation 202965942Sgibbs * parameters as well as, in the case of a current or active update, 203065942Sgibbs * any data structures on the host controller. In the case of an 203165942Sgibbs * active update, the specified target is currently talking to us on 203265942Sgibbs * the bus, so the transfer parameter update must take effect 203365942Sgibbs * immediately. 203465942Sgibbs */ 203565942Sgibbsvoid 203665942Sgibbsahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 203765942Sgibbs u_int width, u_int type, int paused) 203865942Sgibbs{ 203974972Sgibbs struct ahc_initiator_tinfo *tinfo; 204074972Sgibbs struct ahc_tmode_tstate *tstate; 204174972Sgibbs u_int oldwidth; 204274972Sgibbs int active; 204374972Sgibbs int update_needed; 204465942Sgibbs 204574972Sgibbs active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; 204674972Sgibbs update_needed = 0; 204765942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 204865942Sgibbs devinfo->target, &tstate); 204972811Sgibbs 205072811Sgibbs if ((type & AHC_TRANS_USER) != 0) 205172811Sgibbs tinfo->user.width = width; 205272811Sgibbs 205372811Sgibbs if ((type & AHC_TRANS_GOAL) != 0) 205472811Sgibbs tinfo->goal.width = width; 205572811Sgibbs 205676634Sgibbs oldwidth = tinfo->curr.width; 205765942Sgibbs if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) { 205865942Sgibbs u_int scsirate; 205965942Sgibbs 206074972Sgibbs update_needed++; 206165942Sgibbs scsirate = tinfo->scsirate; 206265942Sgibbs scsirate &= ~WIDEXFER; 206365942Sgibbs if (width == MSG_EXT_WDTR_BUS_16_BIT) 206465942Sgibbs scsirate |= WIDEXFER; 206565942Sgibbs 206665942Sgibbs tinfo->scsirate = scsirate; 206765942Sgibbs 206865942Sgibbs if (active) 206965942Sgibbs ahc_outb(ahc, SCSIRATE, scsirate); 207065942Sgibbs 207176634Sgibbs tinfo->curr.width = width; 207265942Sgibbs 207366269Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 207476634Sgibbs CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); 207565942Sgibbs if (bootverbose) { 207665942Sgibbs printf("%s: target %d using %dbit transfers\n", 207765942Sgibbs ahc_name(ahc), devinfo->target, 207865942Sgibbs 8 * (0x01 << width)); 207965942Sgibbs } 208041646Sgibbs } 208165942Sgibbs 208274972Sgibbs update_needed += ahc_update_neg_request(ahc, devinfo, tstate, 2083107420Sscottl tinfo, AHC_NEG_TO_GOAL); 208474972Sgibbs if (update_needed) 208574972Sgibbs ahc_update_pending_scbs(ahc); 208641646Sgibbs} 208741646Sgibbs 208865942Sgibbs/* 208965942Sgibbs * Update the current state of tagged queuing for a given target. 209065942Sgibbs */ 209165942Sgibbsvoid 209276634Sgibbsahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 209376634Sgibbs ahc_queue_alg alg) 209465942Sgibbs{ 209576634Sgibbs ahc_platform_set_tags(ahc, devinfo, alg); 209676634Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 209776634Sgibbs devinfo->lun, AC_TRANSFER_NEG, &alg); 209865942Sgibbs} 209965942Sgibbs 210065942Sgibbs/* 210165942Sgibbs * When the transfer settings for a connection change, update any 210265942Sgibbs * in-transit SCBs to contain the new data so the hardware will 210365942Sgibbs * be set correctly during future (re)selections. 210465942Sgibbs */ 210541646Sgibbsstatic void 210674972Sgibbsahc_update_pending_scbs(struct ahc_softc *ahc) 210765942Sgibbs{ 210865942Sgibbs struct scb *pending_scb; 210965942Sgibbs int pending_scb_count; 211065942Sgibbs int i; 211175048Sgibbs int paused; 211265942Sgibbs u_int saved_scbptr; 211365942Sgibbs 211465942Sgibbs /* 211565942Sgibbs * Traverse the pending SCB list and ensure that all of the 211665942Sgibbs * SCBs there have the proper settings. 211765942Sgibbs */ 211865942Sgibbs pending_scb_count = 0; 211966800Sgibbs LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) { 212065942Sgibbs struct ahc_devinfo devinfo; 212165942Sgibbs struct hardware_scb *pending_hscb; 212265942Sgibbs struct ahc_initiator_tinfo *tinfo; 212374972Sgibbs struct ahc_tmode_tstate *tstate; 212479874Sgibbs 212565942Sgibbs ahc_scb_devinfo(ahc, &devinfo, pending_scb); 212665942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 212765942Sgibbs devinfo.our_scsiid, 212865942Sgibbs devinfo.target, &tstate); 212965942Sgibbs pending_hscb = pending_scb->hscb; 213065942Sgibbs pending_hscb->control &= ~ULTRAENB; 213165942Sgibbs if ((tstate->ultraenb & devinfo.target_mask) != 0) 213265942Sgibbs pending_hscb->control |= ULTRAENB; 213365942Sgibbs pending_hscb->scsirate = tinfo->scsirate; 213476634Sgibbs pending_hscb->scsioffset = tinfo->curr.offset; 213574972Sgibbs if ((tstate->auto_negotiate & devinfo.target_mask) == 0 213674972Sgibbs && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { 213774972Sgibbs pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; 213874972Sgibbs pending_hscb->control &= ~MK_MESSAGE; 213974972Sgibbs } 214079874Sgibbs ahc_sync_scb(ahc, pending_scb, 214179874Sgibbs BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 214265942Sgibbs pending_scb_count++; 214365942Sgibbs } 214465942Sgibbs 214565942Sgibbs if (pending_scb_count == 0) 214665942Sgibbs return; 214765942Sgibbs 214875048Sgibbs if (ahc_is_paused(ahc)) { 214975048Sgibbs paused = 1; 215075048Sgibbs } else { 215175048Sgibbs paused = 0; 215275048Sgibbs ahc_pause(ahc); 215375048Sgibbs } 215475048Sgibbs 215565942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 215665942Sgibbs /* Ensure that the hscbs down on the card match the new information */ 215765942Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 215866800Sgibbs struct hardware_scb *pending_hscb; 215966800Sgibbs u_int control; 216066800Sgibbs u_int scb_tag; 216165942Sgibbs 216265942Sgibbs ahc_outb(ahc, SCBPTR, i); 216365942Sgibbs scb_tag = ahc_inb(ahc, SCB_TAG); 216466800Sgibbs pending_scb = ahc_lookup_scb(ahc, scb_tag); 216566800Sgibbs if (pending_scb == NULL) 216666800Sgibbs continue; 216765942Sgibbs 216866800Sgibbs pending_hscb = pending_scb->hscb; 216966800Sgibbs control = ahc_inb(ahc, SCB_CONTROL); 217074972Sgibbs control &= ~(ULTRAENB|MK_MESSAGE); 217174972Sgibbs control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE); 217266800Sgibbs ahc_outb(ahc, SCB_CONTROL, control); 217366800Sgibbs ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate); 217466800Sgibbs ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset); 217565942Sgibbs } 217665942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 217775048Sgibbs 217875048Sgibbs if (paused == 0) 217975048Sgibbs ahc_unpause(ahc); 218065942Sgibbs} 218165942Sgibbs 218265942Sgibbs/**************************** Pathing Information *****************************/ 218365942Sgibbsstatic void 218465942Sgibbsahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 218565942Sgibbs{ 218665942Sgibbs u_int saved_scsiid; 218765942Sgibbs role_t role; 218865942Sgibbs int our_id; 218965942Sgibbs 219065942Sgibbs if (ahc_inb(ahc, SSTAT0) & TARGET) 219165942Sgibbs role = ROLE_TARGET; 219265942Sgibbs else 219365942Sgibbs role = ROLE_INITIATOR; 219465942Sgibbs 219565942Sgibbs if (role == ROLE_TARGET 219665942Sgibbs && (ahc->features & AHC_MULTI_TID) != 0 2197102670Sgibbs && (ahc_inb(ahc, SEQ_FLAGS) 2198102670Sgibbs & (CMDPHASE_PENDING|TARG_CMD_PENDING|NO_DISCONNECT)) != 0) { 219965942Sgibbs /* We were selected, so pull our id from TARGIDIN */ 220065942Sgibbs our_id = ahc_inb(ahc, TARGIDIN) & OID; 220165942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) 220265942Sgibbs our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; 220365942Sgibbs else 220465942Sgibbs our_id = ahc_inb(ahc, SCSIID) & OID; 220565942Sgibbs 220665942Sgibbs saved_scsiid = ahc_inb(ahc, SAVED_SCSIID); 220765942Sgibbs ahc_compile_devinfo(devinfo, 220865942Sgibbs our_id, 220965942Sgibbs SCSIID_TARGET(ahc, saved_scsiid), 221065942Sgibbs ahc_inb(ahc, SAVED_LUN), 221165942Sgibbs SCSIID_CHANNEL(ahc, saved_scsiid), 221265942Sgibbs role); 221365942Sgibbs} 221465942Sgibbs 221574094Sgibbsstruct ahc_phase_table_entry* 221674094Sgibbsahc_lookup_phase_entry(int phase) 221774094Sgibbs{ 221874094Sgibbs struct ahc_phase_table_entry *entry; 221974434Sgibbs struct ahc_phase_table_entry *last_entry; 222074094Sgibbs 222174094Sgibbs /* 222274094Sgibbs * num_phases doesn't include the default entry which 222374094Sgibbs * will be returned if the phase doesn't match. 222474094Sgibbs */ 222574434Sgibbs last_entry = &ahc_phase_table[num_phases]; 222674434Sgibbs for (entry = ahc_phase_table; entry < last_entry; entry++) { 222774094Sgibbs if (phase == entry->phase) 222874094Sgibbs break; 222974094Sgibbs } 223074094Sgibbs return (entry); 223174094Sgibbs} 223274094Sgibbs 223365942Sgibbsvoid 223465942Sgibbsahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target, 223565942Sgibbs u_int lun, char channel, role_t role) 223665942Sgibbs{ 223765942Sgibbs devinfo->our_scsiid = our_id; 223865942Sgibbs devinfo->target = target; 223965942Sgibbs devinfo->lun = lun; 224065942Sgibbs devinfo->target_offset = target; 224165942Sgibbs devinfo->channel = channel; 224265942Sgibbs devinfo->role = role; 224365942Sgibbs if (channel == 'B') 224465942Sgibbs devinfo->target_offset += 8; 224565942Sgibbs devinfo->target_mask = (0x01 << devinfo->target_offset); 224665942Sgibbs} 224765942Sgibbs 2248107420Sscottlvoid 2249102670Sgibbsahc_print_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 2250102670Sgibbs{ 2251107420Sscottl printf("%s:%c:%d:%d: ", ahc_name(ahc), devinfo->channel, 2252102670Sgibbs devinfo->target, devinfo->lun); 2253102670Sgibbs} 2254102670Sgibbs 2255102670Sgibbsstatic void 225665942Sgibbsahc_scb_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 225765942Sgibbs struct scb *scb) 225865942Sgibbs{ 225965942Sgibbs role_t role; 226065942Sgibbs int our_id; 226165942Sgibbs 226265942Sgibbs our_id = SCSIID_OUR_ID(scb->hscb->scsiid); 226365942Sgibbs role = ROLE_INITIATOR; 2264107420Sscottl if ((scb->flags & SCB_TARGET_SCB) != 0) 226565942Sgibbs role = ROLE_TARGET; 226665942Sgibbs ahc_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahc, scb), 226765942Sgibbs SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahc, scb), role); 226865942Sgibbs} 226965942Sgibbs 227065942Sgibbs 227165942Sgibbs/************************ Message Phase Processing ****************************/ 227276634Sgibbsstatic void 227376634Sgibbsahc_assert_atn(struct ahc_softc *ahc) 227476634Sgibbs{ 227576634Sgibbs u_int scsisigo; 227676634Sgibbs 227776634Sgibbs scsisigo = ATNO; 227876634Sgibbs if ((ahc->features & AHC_DT) == 0) 227976634Sgibbs scsisigo |= ahc_inb(ahc, SCSISIGI); 228076634Sgibbs ahc_outb(ahc, SCSISIGO, scsisigo); 228176634Sgibbs} 228276634Sgibbs 228365942Sgibbs/* 228465942Sgibbs * When an initiator transaction with the MK_MESSAGE flag either reconnects 228565942Sgibbs * or enters the initial message out phase, we are interrupted. Fill our 228665942Sgibbs * outgoing message buffer with the appropriate message and beging handing 228765942Sgibbs * the message phase(s) manually. 228865942Sgibbs */ 228965942Sgibbsstatic void 229041646Sgibbsahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 229141646Sgibbs struct scb *scb) 229241646Sgibbs{ 229365942Sgibbs /* 229441646Sgibbs * To facilitate adding multiple messages together, 229541646Sgibbs * each routine should increment the index and len 229641646Sgibbs * variables instead of setting them explicitly. 229765942Sgibbs */ 229841646Sgibbs ahc->msgout_index = 0; 229941646Sgibbs ahc->msgout_len = 0; 230041646Sgibbs 230141646Sgibbs if ((scb->flags & SCB_DEVICE_RESET) == 0 230241646Sgibbs && ahc_inb(ahc, MSG_OUT) == MSG_IDENTIFYFLAG) { 230341646Sgibbs u_int identify_msg; 230441646Sgibbs 230563457Sgibbs identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb); 230641646Sgibbs if ((scb->hscb->control & DISCENB) != 0) 230741646Sgibbs identify_msg |= MSG_IDENTIFY_DISCFLAG; 230841646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = identify_msg; 230941646Sgibbs ahc->msgout_len++; 231041646Sgibbs 231141646Sgibbs if ((scb->hscb->control & TAG_ENB) != 0) { 231241646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = 231365942Sgibbs scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE); 231441646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = scb->hscb->tag; 231541646Sgibbs ahc->msgout_len += 2; 231641646Sgibbs } 231741646Sgibbs } 231841646Sgibbs 231941646Sgibbs if (scb->flags & SCB_DEVICE_RESET) { 232041646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_BUS_DEV_RESET; 232141646Sgibbs ahc->msgout_len++; 232265942Sgibbs ahc_print_path(ahc, scb); 232341646Sgibbs printf("Bus Device Reset Message Sent\n"); 232472325Sgibbs /* 232572325Sgibbs * Clear our selection hardware in advance of 232672325Sgibbs * the busfree. We may have an entry in the waiting 232772325Sgibbs * Q for this target, and we don't want to go about 232872325Sgibbs * selecting while we handle the busfree and blow it 232972325Sgibbs * away. 233072325Sgibbs */ 233172325Sgibbs ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); 233263457Sgibbs } else if ((scb->flags & SCB_ABORT) != 0) { 233341646Sgibbs if ((scb->hscb->control & TAG_ENB) != 0) 233441646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT_TAG; 233541646Sgibbs else 233641646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT; 233741646Sgibbs ahc->msgout_len++; 233865942Sgibbs ahc_print_path(ahc, scb); 233972325Sgibbs printf("Abort%s Message Sent\n", 234072325Sgibbs (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : ""); 234172325Sgibbs /* 234272325Sgibbs * Clear our selection hardware in advance of 234372325Sgibbs * the busfree. We may have an entry in the waiting 234472325Sgibbs * Q for this target, and we don't want to go about 234572325Sgibbs * selecting while we handle the busfree and blow it 234672325Sgibbs * away. 234772325Sgibbs */ 234872325Sgibbs ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); 234974972Sgibbs } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) { 235041646Sgibbs ahc_build_transfer_msg(ahc, devinfo); 235141646Sgibbs } else { 235241646Sgibbs printf("ahc_intr: AWAITING_MSG for an SCB that " 235363457Sgibbs "does not have a waiting message\n"); 235463457Sgibbs printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, 235563457Sgibbs devinfo->target_mask); 235641646Sgibbs panic("SCB = %d, SCB Control = %x, MSG_OUT = %x " 235741646Sgibbs "SCB flags = %x", scb->hscb->tag, scb->hscb->control, 235841646Sgibbs ahc_inb(ahc, MSG_OUT), scb->flags); 235941646Sgibbs } 236041646Sgibbs 236141646Sgibbs /* 236241646Sgibbs * Clear the MK_MESSAGE flag from the SCB so we aren't 236341646Sgibbs * asked to send this message again. 236441646Sgibbs */ 236541646Sgibbs ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE); 236674972Sgibbs scb->hscb->control &= ~MK_MESSAGE; 236741646Sgibbs ahc->msgout_index = 0; 236841646Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 236941646Sgibbs} 237070204Sgibbs 237165942Sgibbs/* 237265942Sgibbs * Build an appropriate transfer negotiation message for the 237365942Sgibbs * currently active target. 237465942Sgibbs */ 237541646Sgibbsstatic void 237665942Sgibbsahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 237741646Sgibbs{ 237841646Sgibbs /* 237965942Sgibbs * We need to initiate transfer negotiations. 238065942Sgibbs * If our current and goal settings are identical, 238165942Sgibbs * we want to renegotiate due to a check condition. 238241646Sgibbs */ 238365942Sgibbs struct ahc_initiator_tinfo *tinfo; 238474972Sgibbs struct ahc_tmode_tstate *tstate; 238565942Sgibbs struct ahc_syncrate *rate; 238665942Sgibbs int dowide; 238765942Sgibbs int dosync; 238865942Sgibbs int doppr; 238965942Sgibbs u_int period; 239065942Sgibbs u_int ppr_options; 239165942Sgibbs u_int offset; 239241646Sgibbs 239365942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 239463457Sgibbs devinfo->target, &tstate); 239576634Sgibbs /* 239676634Sgibbs * Filter our period based on the current connection. 239776634Sgibbs * If we can't perform DT transfers on this segment (not in LVD 239876634Sgibbs * mode for instance), then our decision to issue a PPR message 239976634Sgibbs * may change. 240076634Sgibbs */ 240176634Sgibbs period = tinfo->goal.period; 2402115918Sgibbs offset = tinfo->goal.offset; 240376634Sgibbs ppr_options = tinfo->goal.ppr_options; 240479874Sgibbs /* Target initiated PPR is not allowed in the SCSI spec */ 240579874Sgibbs if (devinfo->role == ROLE_TARGET) 240679874Sgibbs ppr_options = 0; 240776634Sgibbs rate = ahc_devlimited_syncrate(ahc, tinfo, &period, 240876634Sgibbs &ppr_options, devinfo->role); 240976634Sgibbs dowide = tinfo->curr.width != tinfo->goal.width; 2410115918Sgibbs dosync = tinfo->curr.offset != offset || tinfo->curr.period != period; 2411107420Sscottl /* 2412107420Sscottl * Only use PPR if we have options that need it, even if the device 2413107420Sscottl * claims to support it. There might be an expander in the way 2414107420Sscottl * that doesn't. 2415107420Sscottl */ 2416107420Sscottl doppr = ppr_options != 0; 241741646Sgibbs 241865942Sgibbs if (!dowide && !dosync && !doppr) { 241965942Sgibbs dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT; 2420102670Sgibbs dosync = tinfo->goal.offset != 0; 242165942Sgibbs } 242241646Sgibbs 242365942Sgibbs if (!dowide && !dosync && !doppr) { 2424107420Sscottl /* 2425107420Sscottl * Force async with a WDTR message if we have a wide bus, 2426107420Sscottl * or just issue an SDTR with a 0 offset. 2427107420Sscottl */ 2428107420Sscottl if ((ahc->features & AHC_WIDE) != 0) 2429107420Sscottl dowide = 1; 2430107420Sscottl else 2431107420Sscottl dosync = 1; 2432107420Sscottl 2433107420Sscottl if (bootverbose) { 2434107420Sscottl ahc_print_devinfo(ahc, devinfo); 2435107420Sscottl printf("Ensuring async\n"); 2436107420Sscottl } 243765942Sgibbs } 243841646Sgibbs 243968087Sgibbs /* Target initiated PPR is not allowed in the SCSI spec */ 244068087Sgibbs if (devinfo->role == ROLE_TARGET) 2441107420Sscottl doppr = 0; 244268087Sgibbs 244366269Sgibbs /* 244466269Sgibbs * Both the PPR message and SDTR message require the 244566269Sgibbs * goal syncrate to be limited to what the target device 244666269Sgibbs * is capable of handling (based on whether an LVD->SE 244766269Sgibbs * expander is on the bus), so combine these two cases. 244866269Sgibbs * Regardless, guarantee that if we are using WDTR and SDTR 244966269Sgibbs * messages that WDTR comes first. 245066269Sgibbs */ 2451107420Sscottl if (doppr || (dosync && !dowide)) { 245241646Sgibbs 245365942Sgibbs offset = tinfo->goal.offset; 245468087Sgibbs ahc_validate_offset(ahc, tinfo, rate, &offset, 2455107420Sscottl doppr ? tinfo->goal.width 2456107420Sscottl : tinfo->curr.width, 245768087Sgibbs devinfo->role); 2458107420Sscottl if (doppr) { 245966647Sgibbs ahc_construct_ppr(ahc, devinfo, period, offset, 246066269Sgibbs tinfo->goal.width, ppr_options); 246166647Sgibbs } else { 246266647Sgibbs ahc_construct_sdtr(ahc, devinfo, period, offset); 246366647Sgibbs } 246466269Sgibbs } else { 246566647Sgibbs ahc_construct_wdtr(ahc, devinfo, tinfo->goal.width); 246665942Sgibbs } 246765942Sgibbs} 246841646Sgibbs 246965942Sgibbs/* 247066269Sgibbs * Build a synchronous negotiation message in our message 247165942Sgibbs * buffer based on the input parameters. 247265942Sgibbs */ 247365942Sgibbsstatic void 247466647Sgibbsahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 247566647Sgibbs u_int period, u_int offset) 247665942Sgibbs{ 2477107420Sscottl if (offset == 0) 2478107420Sscottl period = AHC_ASYNC_XFER_PERIOD; 247965942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; 248065942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN; 248165942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR; 248265942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = period; 248365942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = offset; 248465942Sgibbs ahc->msgout_len += 5; 248566647Sgibbs if (bootverbose) { 248666647Sgibbs printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", 248766647Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 248866647Sgibbs devinfo->lun, period, offset); 248966647Sgibbs } 249065942Sgibbs} 249141646Sgibbs 249265942Sgibbs/* 249395378Sgibbs * Build a wide negotiation message in our message 249465942Sgibbs * buffer based on the input parameters. 249565942Sgibbs */ 249665942Sgibbsstatic void 249766647Sgibbsahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 249866647Sgibbs u_int bus_width) 249965942Sgibbs{ 250065942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; 250165942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN; 250265942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR; 250365942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = bus_width; 250465942Sgibbs ahc->msgout_len += 4; 250566647Sgibbs if (bootverbose) { 250666647Sgibbs printf("(%s:%c:%d:%d): Sending WDTR %x\n", 250766647Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 250866647Sgibbs devinfo->lun, bus_width); 250966647Sgibbs } 251041646Sgibbs} 251141646Sgibbs 251265942Sgibbs/* 251365942Sgibbs * Build a parallel protocol request message in our message 251465942Sgibbs * buffer based on the input parameters. 251565942Sgibbs */ 251641646Sgibbsstatic void 251766647Sgibbsahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 251866647Sgibbs u_int period, u_int offset, u_int bus_width, 251966647Sgibbs u_int ppr_options) 252065942Sgibbs{ 2521107420Sscottl if (offset == 0) 2522107420Sscottl period = AHC_ASYNC_XFER_PERIOD; 252365942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; 252465942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN; 252565942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR; 252665942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = period; 252765942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = 0; 252865942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = offset; 252965942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = bus_width; 253065942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = ppr_options; 253165942Sgibbs ahc->msgout_len += 8; 253266647Sgibbs if (bootverbose) { 253366647Sgibbs printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " 253466647Sgibbs "offset %x, ppr_options %x\n", ahc_name(ahc), 253566647Sgibbs devinfo->channel, devinfo->target, devinfo->lun, 253666647Sgibbs bus_width, period, offset, ppr_options); 253766647Sgibbs } 253865942Sgibbs} 253965942Sgibbs 254065942Sgibbs/* 254165942Sgibbs * Clear any active message state. 254265942Sgibbs */ 254365942Sgibbsstatic void 254441646Sgibbsahc_clear_msg_state(struct ahc_softc *ahc) 254541646Sgibbs{ 254641646Sgibbs ahc->msgout_len = 0; 254741646Sgibbs ahc->msgin_index = 0; 254841646Sgibbs ahc->msg_type = MSG_TYPE_NONE; 254974094Sgibbs if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0) { 255070204Sgibbs /* 255170204Sgibbs * The target didn't care to respond to our 255270204Sgibbs * message request, so clear ATN. 255370204Sgibbs */ 255470204Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 255570204Sgibbs } 255641887Sgibbs ahc_outb(ahc, MSG_OUT, MSG_NOOP); 255795378Sgibbs ahc_outb(ahc, SEQ_FLAGS2, 255895378Sgibbs ahc_inb(ahc, SEQ_FLAGS2) & ~TARGET_MSG_PENDING); 255941646Sgibbs} 256041646Sgibbs 2561107420Sscottlstatic void 2562107420Sscottlahc_handle_proto_violation(struct ahc_softc *ahc) 2563107420Sscottl{ 2564107420Sscottl struct ahc_devinfo devinfo; 2565107420Sscottl struct scb *scb; 2566107420Sscottl u_int scbid; 2567107420Sscottl u_int seq_flags; 2568107420Sscottl u_int curphase; 2569107420Sscottl u_int lastphase; 2570107420Sscottl int found; 2571107420Sscottl 2572107420Sscottl ahc_fetch_devinfo(ahc, &devinfo); 2573107420Sscottl scbid = ahc_inb(ahc, SCB_TAG); 2574107420Sscottl scb = ahc_lookup_scb(ahc, scbid); 2575107420Sscottl seq_flags = ahc_inb(ahc, SEQ_FLAGS); 2576107420Sscottl curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 2577107420Sscottl lastphase = ahc_inb(ahc, LASTPHASE); 2578107420Sscottl if ((seq_flags & NOT_IDENTIFIED) != 0) { 2579107420Sscottl 2580107420Sscottl /* 2581107420Sscottl * The reconnecting target either did not send an 2582107420Sscottl * identify message, or did, but we didn't find an SCB 2583107420Sscottl * to match. 2584107420Sscottl */ 2585107420Sscottl ahc_print_devinfo(ahc, &devinfo); 2586107420Sscottl printf("Target did not send an IDENTIFY message. " 2587107420Sscottl "LASTPHASE = 0x%x.\n", lastphase); 2588107420Sscottl scb = NULL; 2589107420Sscottl } else if (scb == NULL) { 2590107420Sscottl /* 2591107420Sscottl * We don't seem to have an SCB active for this 2592107420Sscottl * transaction. Print an error and reset the bus. 2593107420Sscottl */ 2594107420Sscottl ahc_print_devinfo(ahc, &devinfo); 2595107420Sscottl printf("No SCB found during protocol violation\n"); 2596107420Sscottl goto proto_violation_reset; 2597107420Sscottl } else { 2598123579Sgibbs aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); 2599107420Sscottl if ((seq_flags & NO_CDB_SENT) != 0) { 2600107420Sscottl ahc_print_path(ahc, scb); 2601107420Sscottl printf("No or incomplete CDB sent to device.\n"); 2602107420Sscottl } else if ((ahc_inb(ahc, SCB_CONTROL) & STATUS_RCVD) == 0) { 2603107420Sscottl /* 2604107420Sscottl * The target never bothered to provide status to 2605107420Sscottl * us prior to completing the command. Since we don't 2606107420Sscottl * know the disposition of this command, we must attempt 2607107420Sscottl * to abort it. Assert ATN and prepare to send an abort 2608107420Sscottl * message. 2609107420Sscottl */ 2610107420Sscottl ahc_print_path(ahc, scb); 2611107420Sscottl printf("Completed command without status.\n"); 2612107420Sscottl } else { 2613107420Sscottl ahc_print_path(ahc, scb); 2614107420Sscottl printf("Unknown protocol violation.\n"); 2615107420Sscottl ahc_dump_card_state(ahc); 2616107420Sscottl } 2617107420Sscottl } 2618107420Sscottl if ((lastphase & ~P_DATAIN_DT) == 0 2619107420Sscottl || lastphase == P_COMMAND) { 2620107420Sscottlproto_violation_reset: 2621107420Sscottl /* 2622107420Sscottl * Target either went directly to data/command 2623107420Sscottl * phase or didn't respond to our ATN. 2624107420Sscottl * The only safe thing to do is to blow 2625107420Sscottl * it away with a bus reset. 2626107420Sscottl */ 2627107420Sscottl found = ahc_reset_channel(ahc, 'A', TRUE); 2628107420Sscottl printf("%s: Issued Channel %c Bus Reset. " 2629107420Sscottl "%d SCBs aborted\n", ahc_name(ahc), 'A', found); 2630107420Sscottl } else { 2631107420Sscottl /* 2632107420Sscottl * Leave the selection hardware off in case 2633107420Sscottl * this abort attempt will affect yet to 2634107420Sscottl * be sent commands. 2635107420Sscottl */ 2636107420Sscottl ahc_outb(ahc, SCSISEQ, 2637107420Sscottl ahc_inb(ahc, SCSISEQ) & ~ENSELO); 2638107420Sscottl ahc_assert_atn(ahc); 2639107420Sscottl ahc_outb(ahc, MSG_OUT, HOST_MSG); 2640107420Sscottl if (scb == NULL) { 2641107420Sscottl ahc_print_devinfo(ahc, &devinfo); 2642107420Sscottl ahc->msgout_buf[0] = MSG_ABORT_TASK; 2643107420Sscottl ahc->msgout_len = 1; 2644107420Sscottl ahc->msgout_index = 0; 2645107420Sscottl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 2646107420Sscottl } else { 2647107420Sscottl ahc_print_path(ahc, scb); 2648107420Sscottl scb->flags |= SCB_ABORT; 2649107420Sscottl } 2650107420Sscottl printf("Protocol violation %s. Attempting to abort.\n", 2651107420Sscottl ahc_lookup_phase_entry(curphase)->phasemsg); 2652107420Sscottl } 2653107420Sscottl} 2654107420Sscottl 265565942Sgibbs/* 265665942Sgibbs * Manual message loop handler. 265765942Sgibbs */ 265841646Sgibbsstatic void 265965942Sgibbsahc_handle_message_phase(struct ahc_softc *ahc) 266039220Sgibbs{ 266139506Sgibbs struct ahc_devinfo devinfo; 266241646Sgibbs u_int bus_phase; 266341646Sgibbs int end_session; 266439220Sgibbs 266539220Sgibbs ahc_fetch_devinfo(ahc, &devinfo); 266641646Sgibbs end_session = FALSE; 266741646Sgibbs bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 266841646Sgibbs 266941646Sgibbsreswitch: 267039220Sgibbs switch (ahc->msg_type) { 267139220Sgibbs case MSG_TYPE_INITIATOR_MSGOUT: 267239220Sgibbs { 267341646Sgibbs int lastbyte; 267441646Sgibbs int phasemis; 267541646Sgibbs int msgdone; 267639220Sgibbs 267741646Sgibbs if (ahc->msgout_len == 0) 267866269Sgibbs panic("HOST_MSG_LOOP interrupt with no active message"); 267939220Sgibbs 2680102670Sgibbs#ifdef AHC_DEBUG 2681104071Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2682102670Sgibbs ahc_print_devinfo(ahc, &devinfo); 2683102670Sgibbs printf("INITIATOR_MSG_OUT"); 2684104071Sgibbs } 2685102670Sgibbs#endif 268639220Sgibbs phasemis = bus_phase != P_MESGOUT; 268741646Sgibbs if (phasemis) { 2688102670Sgibbs#ifdef AHC_DEBUG 2689102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2690102670Sgibbs printf(" PHASEMIS %s\n", 2691102670Sgibbs ahc_lookup_phase_entry(bus_phase) 2692102670Sgibbs ->phasemsg); 2693102670Sgibbs } 2694102670Sgibbs#endif 269541646Sgibbs if (bus_phase == P_MESGIN) { 269641646Sgibbs /* 269741646Sgibbs * Change gears and see if 269841646Sgibbs * this messages is of interest to 269941646Sgibbs * us or should be passed back to 270041646Sgibbs * the sequencer. 270141646Sgibbs */ 270241887Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 270341646Sgibbs ahc->send_msg_perror = FALSE; 270441646Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN; 270541646Sgibbs ahc->msgin_index = 0; 270641646Sgibbs goto reswitch; 270739220Sgibbs } 270841646Sgibbs end_session = TRUE; 270941646Sgibbs break; 271041646Sgibbs } 271139220Sgibbs 271241646Sgibbs if (ahc->send_msg_perror) { 271341646Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 271441646Sgibbs ahc_outb(ahc, CLRSINT1, CLRREQINIT); 2715102670Sgibbs#ifdef AHC_DEBUG 2716102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2717102670Sgibbs printf(" byte 0x%x\n", ahc->send_msg_perror); 2718102670Sgibbs#endif 271941646Sgibbs ahc_outb(ahc, SCSIDATL, MSG_PARITY_ERROR); 272041646Sgibbs break; 272141646Sgibbs } 272241646Sgibbs 272341646Sgibbs msgdone = ahc->msgout_index == ahc->msgout_len; 272441646Sgibbs if (msgdone) { 272539220Sgibbs /* 272641646Sgibbs * The target has requested a retry. 272741646Sgibbs * Re-assert ATN, reset our message index to 272841646Sgibbs * 0, and try again. 272939220Sgibbs */ 273041646Sgibbs ahc->msgout_index = 0; 273176634Sgibbs ahc_assert_atn(ahc); 273239220Sgibbs } 273341646Sgibbs 273441646Sgibbs lastbyte = ahc->msgout_index == (ahc->msgout_len - 1); 273541646Sgibbs if (lastbyte) { 273641646Sgibbs /* Last byte is signified by dropping ATN */ 273741646Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 273841646Sgibbs } 273941646Sgibbs 274041646Sgibbs /* 274141646Sgibbs * Clear our interrupt status and present 274241646Sgibbs * the next byte on the bus. 274341646Sgibbs */ 274441646Sgibbs ahc_outb(ahc, CLRSINT1, CLRREQINIT); 2745102670Sgibbs#ifdef AHC_DEBUG 2746102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2747102670Sgibbs printf(" byte 0x%x\n", 2748102670Sgibbs ahc->msgout_buf[ahc->msgout_index]); 2749102670Sgibbs#endif 275041646Sgibbs ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); 275139220Sgibbs break; 275239220Sgibbs } 275339220Sgibbs case MSG_TYPE_INITIATOR_MSGIN: 275439220Sgibbs { 275541646Sgibbs int phasemis; 275641646Sgibbs int message_done; 275739220Sgibbs 2758102670Sgibbs#ifdef AHC_DEBUG 2759102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2760102670Sgibbs ahc_print_devinfo(ahc, &devinfo); 2761102670Sgibbs printf("INITIATOR_MSG_IN"); 2762102670Sgibbs } 2763102670Sgibbs#endif 276441646Sgibbs phasemis = bus_phase != P_MESGIN; 276541646Sgibbs if (phasemis) { 2766102670Sgibbs#ifdef AHC_DEBUG 2767102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2768102670Sgibbs printf(" PHASEMIS %s\n", 2769102670Sgibbs ahc_lookup_phase_entry(bus_phase) 2770102670Sgibbs ->phasemsg); 2771102670Sgibbs } 2772102670Sgibbs#endif 277341646Sgibbs ahc->msgin_index = 0; 277441646Sgibbs if (bus_phase == P_MESGOUT 277541646Sgibbs && (ahc->send_msg_perror == TRUE 277641646Sgibbs || (ahc->msgout_len != 0 277741646Sgibbs && ahc->msgout_index == 0))) { 277841646Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 277941646Sgibbs goto reswitch; 278041646Sgibbs } 278141646Sgibbs end_session = TRUE; 278241646Sgibbs break; 278341646Sgibbs } 278441646Sgibbs 278541646Sgibbs /* Pull the byte in without acking it */ 278641646Sgibbs ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIBUSL); 2787102670Sgibbs#ifdef AHC_DEBUG 2788102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2789102670Sgibbs printf(" byte 0x%x\n", 2790102670Sgibbs ahc->msgin_buf[ahc->msgin_index]); 2791102670Sgibbs#endif 279241646Sgibbs 279365942Sgibbs message_done = ahc_parse_msg(ahc, &devinfo); 279441646Sgibbs 279541646Sgibbs if (message_done) { 279641646Sgibbs /* 279741646Sgibbs * Clear our incoming message buffer in case there 279841646Sgibbs * is another message following this one. 279941646Sgibbs */ 280041646Sgibbs ahc->msgin_index = 0; 280141646Sgibbs 280241646Sgibbs /* 280341646Sgibbs * If this message illicited a response, 280441646Sgibbs * assert ATN so the target takes us to the 280541646Sgibbs * message out phase. 280641646Sgibbs */ 2807109590Sgibbs if (ahc->msgout_len != 0) { 2808109590Sgibbs#ifdef AHC_DEBUG 2809109590Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2810109590Sgibbs ahc_print_devinfo(ahc, &devinfo); 2811109590Sgibbs printf("Asserting ATN for response\n"); 2812109590Sgibbs } 2813109590Sgibbs#endif 281476634Sgibbs ahc_assert_atn(ahc); 2815109590Sgibbs } 281654211Sgibbs } else 281754211Sgibbs ahc->msgin_index++; 281841646Sgibbs 2819102670Sgibbs if (message_done == MSGLOOP_TERMINATED) { 2820102670Sgibbs end_session = TRUE; 2821102670Sgibbs } else { 2822102670Sgibbs /* Ack the byte */ 2823102670Sgibbs ahc_outb(ahc, CLRSINT1, CLRREQINIT); 2824102670Sgibbs ahc_inb(ahc, SCSIDATL); 2825102670Sgibbs } 282641646Sgibbs break; 282741646Sgibbs } 282841646Sgibbs case MSG_TYPE_TARGET_MSGIN: 282941646Sgibbs { 283041646Sgibbs int msgdone; 283141646Sgibbs 283241646Sgibbs if (ahc->msgout_len == 0) 283342652Sgibbs panic("Target MSGIN with no active message"); 283441646Sgibbs 2835136711Sgibbs#ifdef AHC_DEBUG 2836136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2837136711Sgibbs ahc_print_devinfo(ahc, &devinfo); 2838136711Sgibbs printf("TARGET_MSG_IN"); 2839136711Sgibbs } 2840136711Sgibbs#endif 2841136711Sgibbs 284241646Sgibbs /* 284341646Sgibbs * If we interrupted a mesgout session, the initiator 284441646Sgibbs * will not know this until our first REQ. So, we 284541646Sgibbs * only honor mesgout requests after we've sent our 284641646Sgibbs * first byte. 284741646Sgibbs */ 284841646Sgibbs if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0 2849136711Sgibbs && ahc->msgout_index > 0) { 285041646Sgibbs 2851136711Sgibbs /* 2852136711Sgibbs * Change gears and see if this messages is 2853136711Sgibbs * of interest to us or should be passed back 2854136711Sgibbs * to the sequencer. 2855136711Sgibbs */ 2856136711Sgibbs#ifdef AHC_DEBUG 2857136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2858136711Sgibbs printf(" Honoring ATN Request.\n"); 2859136711Sgibbs#endif 2860136711Sgibbs ahc->msg_type = MSG_TYPE_TARGET_MSGOUT; 286141646Sgibbs 286241646Sgibbs /* 2863136711Sgibbs * Disable SCSI Programmed I/O during the 2864136711Sgibbs * phase change so as to avoid phantom REQs. 286541646Sgibbs */ 2866136711Sgibbs ahc_outb(ahc, SXFRCTL0, 2867136711Sgibbs ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); 2868136711Sgibbs 2869136711Sgibbs /* 2870136711Sgibbs * Since SPIORDY asserts when ACK is asserted 2871136711Sgibbs * for P_MSGOUT, and SPIORDY's assertion triggered 2872136711Sgibbs * our entry into this routine, wait for ACK to 2873136711Sgibbs * *de-assert* before changing phases. 2874136711Sgibbs */ 2875136711Sgibbs while ((ahc_inb(ahc, SCSISIGI) & ACKI) != 0) 2876136711Sgibbs ; 2877136711Sgibbs 287841646Sgibbs ahc_outb(ahc, SCSISIGO, P_MESGOUT | BSYO); 2879136711Sgibbs 2880136711Sgibbs /* 2881136711Sgibbs * All phase line changes require a bus 2882136711Sgibbs * settle delay before REQ is asserted. 2883136711Sgibbs * [SCSI SPI4 10.7.1] 2884136711Sgibbs */ 2885136711Sgibbs ahc_flush_device_writes(ahc); 2886136711Sgibbs aic_delay(AHC_BUSSETTLE_DELAY); 2887136711Sgibbs 288841646Sgibbs ahc->msgin_index = 0; 2889136711Sgibbs /* Enable SCSI Programmed I/O to REQ for first byte */ 289041646Sgibbs ahc_outb(ahc, SXFRCTL0, 289141646Sgibbs ahc_inb(ahc, SXFRCTL0) | SPIOEN); 289241646Sgibbs break; 289339220Sgibbs } 289441646Sgibbs 289541646Sgibbs msgdone = ahc->msgout_index == ahc->msgout_len; 289641646Sgibbs if (msgdone) { 289741646Sgibbs ahc_outb(ahc, SXFRCTL0, 289841646Sgibbs ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); 289941646Sgibbs end_session = TRUE; 290041646Sgibbs break; 290139220Sgibbs } 290241646Sgibbs 290341646Sgibbs /* 290441646Sgibbs * Present the next byte on the bus. 290541646Sgibbs */ 2906136711Sgibbs#ifdef AHC_DEBUG 2907136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2908136711Sgibbs printf(" byte 0x%x\n", 2909136711Sgibbs ahc->msgout_buf[ahc->msgout_index]); 2910136711Sgibbs#endif 291141646Sgibbs ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN); 291241646Sgibbs ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); 291339220Sgibbs break; 291439220Sgibbs } 291541646Sgibbs case MSG_TYPE_TARGET_MSGOUT: 291641646Sgibbs { 291741646Sgibbs int lastbyte; 291841646Sgibbs int msgdone; 291941646Sgibbs 2920136711Sgibbs#ifdef AHC_DEBUG 2921136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2922136711Sgibbs ahc_print_devinfo(ahc, &devinfo); 2923136711Sgibbs printf("TARGET_MSG_OUT"); 2924136711Sgibbs } 2925136711Sgibbs#endif 292641646Sgibbs /* 292741646Sgibbs * The initiator signals that this is 292841646Sgibbs * the last byte by dropping ATN. 292941646Sgibbs */ 293041646Sgibbs lastbyte = (ahc_inb(ahc, SCSISIGI) & ATNI) == 0; 293141646Sgibbs 293241646Sgibbs /* 293341646Sgibbs * Read the latched byte, but turn off SPIOEN first 293495378Sgibbs * so that we don't inadvertently cause a REQ for the 293541646Sgibbs * next byte. 293641646Sgibbs */ 293741646Sgibbs ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); 293841646Sgibbs ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIDATL); 2939136711Sgibbs 2940136711Sgibbs#ifdef AHC_DEBUG 2941136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2942136711Sgibbs printf(" byte 0x%x\n", 2943136711Sgibbs ahc->msgin_buf[ahc->msgin_index]); 2944136711Sgibbs#endif 2945136711Sgibbs 294665942Sgibbs msgdone = ahc_parse_msg(ahc, &devinfo); 294749933Sgibbs if (msgdone == MSGLOOP_TERMINATED) { 294849933Sgibbs /* 294949933Sgibbs * The message is *really* done in that it caused 295049933Sgibbs * us to go to bus free. The sequencer has already 295149933Sgibbs * been reset at this point, so pull the ejection 295249933Sgibbs * handle. 295349933Sgibbs */ 295449933Sgibbs return; 295549933Sgibbs } 295649933Sgibbs 295741646Sgibbs ahc->msgin_index++; 295841646Sgibbs 295941646Sgibbs /* 296041646Sgibbs * XXX Read spec about initiator dropping ATN too soon 296141646Sgibbs * and use msgdone to detect it. 296241646Sgibbs */ 296349933Sgibbs if (msgdone == MSGLOOP_MSGCOMPLETE) { 296441646Sgibbs ahc->msgin_index = 0; 296541646Sgibbs 296641646Sgibbs /* 296741646Sgibbs * If this message illicited a response, transition 296841646Sgibbs * to the Message in phase and send it. 296941646Sgibbs */ 297041646Sgibbs if (ahc->msgout_len != 0) { 2971136711Sgibbs#ifdef AHC_DEBUG 2972136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2973136711Sgibbs ahc_print_devinfo(ahc, &devinfo); 2974136711Sgibbs printf(" preparing response.\n"); 2975136711Sgibbs } 2976136711Sgibbs#endif 297741646Sgibbs ahc_outb(ahc, SCSISIGO, P_MESGIN | BSYO); 2978136711Sgibbs 2979136711Sgibbs /* 2980136711Sgibbs * All phase line changes require a bus 2981136711Sgibbs * settle delay before REQ is asserted. 2982136711Sgibbs * [SCSI SPI4 10.7.1] When transitioning 2983136711Sgibbs * from an OUT to an IN phase, we must 2984136711Sgibbs * also wait a data release delay to allow 2985136711Sgibbs * the initiator time to release the data 2986136711Sgibbs * lines. [SCSI SPI4 10.12] 2987136711Sgibbs */ 2988136711Sgibbs ahc_flush_device_writes(ahc); 2989136711Sgibbs aic_delay(AHC_BUSSETTLE_DELAY 2990136711Sgibbs + AHC_DATARELEASE_DELAY); 2991136711Sgibbs 2992136711Sgibbs /* 2993136711Sgibbs * Enable SCSI Programmed I/O. This will 2994136711Sgibbs * immediately cause SPIORDY to assert, 2995136711Sgibbs * and the sequencer will call our message 2996136711Sgibbs * loop again. 2997136711Sgibbs */ 299841646Sgibbs ahc_outb(ahc, SXFRCTL0, 299941646Sgibbs ahc_inb(ahc, SXFRCTL0) | SPIOEN); 300041646Sgibbs ahc->msg_type = MSG_TYPE_TARGET_MSGIN; 300141646Sgibbs ahc->msgin_index = 0; 300241646Sgibbs break; 300341646Sgibbs } 300441646Sgibbs } 300541646Sgibbs 300641646Sgibbs if (lastbyte) 300741646Sgibbs end_session = TRUE; 300841646Sgibbs else { 300941646Sgibbs /* Ask for the next byte. */ 301041646Sgibbs ahc_outb(ahc, SXFRCTL0, 301141646Sgibbs ahc_inb(ahc, SXFRCTL0) | SPIOEN); 301241646Sgibbs } 301341646Sgibbs 301441646Sgibbs break; 301541646Sgibbs } 301639220Sgibbs default: 301739220Sgibbs panic("Unknown REQINIT message type"); 301839220Sgibbs } 301941646Sgibbs 302041646Sgibbs if (end_session) { 302141646Sgibbs ahc_clear_msg_state(ahc); 302241646Sgibbs ahc_outb(ahc, RETURN_1, EXIT_MSG_LOOP); 302341646Sgibbs } else 302441646Sgibbs ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP); 302539220Sgibbs} 302639220Sgibbs 302741646Sgibbs/* 302841646Sgibbs * See if we sent a particular extended message to the target. 302965942Sgibbs * If "full" is true, return true only if the target saw the full 303065942Sgibbs * message. If "full" is false, return true if the target saw at 303165942Sgibbs * least the first byte of the message. 303241646Sgibbs */ 303339220Sgibbsstatic int 303470204Sgibbsahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, u_int msgval, int full) 303541646Sgibbs{ 303641646Sgibbs int found; 303763457Sgibbs u_int index; 303841646Sgibbs 303941646Sgibbs found = FALSE; 304041646Sgibbs index = 0; 304141646Sgibbs 304241646Sgibbs while (index < ahc->msgout_len) { 304357099Sgibbs if (ahc->msgout_buf[index] == MSG_EXTENDED) { 304470204Sgibbs u_int end_index; 304557099Sgibbs 304670204Sgibbs end_index = index + 1 + ahc->msgout_buf[index + 1]; 304770204Sgibbs if (ahc->msgout_buf[index+2] == msgval 304870204Sgibbs && type == AHCMSG_EXT) { 304941646Sgibbs 305041646Sgibbs if (full) { 305141646Sgibbs if (ahc->msgout_index > end_index) 305241646Sgibbs found = TRUE; 305341646Sgibbs } else if (ahc->msgout_index > index) 305441646Sgibbs found = TRUE; 305541646Sgibbs } 305670204Sgibbs index = end_index; 305776634Sgibbs } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_TASK 305857099Sgibbs && ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) { 305957099Sgibbs 306057099Sgibbs /* Skip tag type and tag id or residue param*/ 306157099Sgibbs index += 2; 306241646Sgibbs } else { 306357099Sgibbs /* Single byte message */ 306470204Sgibbs if (type == AHCMSG_1B 306570204Sgibbs && ahc->msgout_buf[index] == msgval 306670204Sgibbs && ahc->msgout_index > index) 306770204Sgibbs found = TRUE; 306857099Sgibbs index++; 306941646Sgibbs } 307070204Sgibbs 307170204Sgibbs if (found) 307270204Sgibbs break; 307341646Sgibbs } 307441646Sgibbs return (found); 307541646Sgibbs} 307641646Sgibbs 307765942Sgibbs/* 307876634Sgibbs * Wait for a complete incoming message, parse it, and respond accordingly. 307965942Sgibbs */ 308041646Sgibbsstatic int 308165942Sgibbsahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 308239220Sgibbs{ 308344507Sgibbs struct ahc_initiator_tinfo *tinfo; 308474972Sgibbs struct ahc_tmode_tstate *tstate; 308544507Sgibbs int reject; 308644507Sgibbs int done; 308744507Sgibbs int response; 308844507Sgibbs u_int targ_scsirate; 308939220Sgibbs 309049933Sgibbs done = MSGLOOP_IN_PROG; 309141646Sgibbs response = FALSE; 309239220Sgibbs reject = FALSE; 309344507Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 309444507Sgibbs devinfo->target, &tstate); 309544507Sgibbs targ_scsirate = tinfo->scsirate; 309644507Sgibbs 309739220Sgibbs /* 3098114621Sgibbs * Parse as much of the message as is available, 309939220Sgibbs * rejecting it if we don't support it. When 3100114621Sgibbs * the entire message is available and has been 310155581Sgibbs * handled, return MSGLOOP_MSGCOMPLETE, indicating 310255581Sgibbs * that we have parsed an entire message. 310341646Sgibbs * 310441646Sgibbs * In the case of extended messages, we accept the length 310541646Sgibbs * byte outright and perform more checking once we know the 310641646Sgibbs * extended message type. 310739220Sgibbs */ 310842652Sgibbs switch (ahc->msgin_buf[0]) { 3109102670Sgibbs case MSG_DISCONNECT: 3110102670Sgibbs case MSG_SAVEDATAPOINTER: 3111102670Sgibbs case MSG_CMDCOMPLETE: 3112102670Sgibbs case MSG_RESTOREPOINTERS: 3113102670Sgibbs case MSG_IGN_WIDE_RESIDUE: 3114102670Sgibbs /* 3115102670Sgibbs * End our message loop as these are messages 3116102670Sgibbs * the sequencer handles on its own. 3117102670Sgibbs */ 3118102670Sgibbs done = MSGLOOP_TERMINATED; 3119102670Sgibbs break; 312042652Sgibbs case MSG_MESSAGE_REJECT: 312141887Sgibbs response = ahc_handle_msg_reject(ahc, devinfo); 312242652Sgibbs /* FALLTHROUGH */ 312342652Sgibbs case MSG_NOOP: 312449933Sgibbs done = MSGLOOP_MSGCOMPLETE; 312542652Sgibbs break; 312642652Sgibbs case MSG_EXTENDED: 312742652Sgibbs { 312842652Sgibbs /* Wait for enough of the message to begin validation */ 312942652Sgibbs if (ahc->msgin_index < 2) 313042652Sgibbs break; 313141646Sgibbs switch (ahc->msgin_buf[2]) { 313239220Sgibbs case MSG_EXT_SDTR: 313339220Sgibbs { 313439220Sgibbs struct ahc_syncrate *syncrate; 313539220Sgibbs u_int period; 313663457Sgibbs u_int ppr_options; 313739220Sgibbs u_int offset; 313839220Sgibbs u_int saved_offset; 313939220Sgibbs 314041646Sgibbs if (ahc->msgin_buf[1] != MSG_EXT_SDTR_LEN) { 314139220Sgibbs reject = TRUE; 314239220Sgibbs break; 314339220Sgibbs } 314439220Sgibbs 314539220Sgibbs /* 314639220Sgibbs * Wait until we have both args before validating 314739220Sgibbs * and acting on this message. 314841646Sgibbs * 314941646Sgibbs * Add one to MSG_EXT_SDTR_LEN to account for 315041646Sgibbs * the extended message preamble. 315139220Sgibbs */ 315241646Sgibbs if (ahc->msgin_index < (MSG_EXT_SDTR_LEN + 1)) 315339220Sgibbs break; 315439220Sgibbs 315541646Sgibbs period = ahc->msgin_buf[3]; 315663457Sgibbs ppr_options = 0; 315741646Sgibbs saved_offset = offset = ahc->msgin_buf[4]; 315868087Sgibbs syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period, 315968087Sgibbs &ppr_options, 316068087Sgibbs devinfo->role); 316168087Sgibbs ahc_validate_offset(ahc, tinfo, syncrate, &offset, 316268087Sgibbs targ_scsirate & WIDEXFER, 316368087Sgibbs devinfo->role); 316466647Sgibbs if (bootverbose) { 316566647Sgibbs printf("(%s:%c:%d:%d): Received " 316666647Sgibbs "SDTR period %x, offset %x\n\t" 316766647Sgibbs "Filtered to period %x, offset %x\n", 316866647Sgibbs ahc_name(ahc), devinfo->channel, 316966647Sgibbs devinfo->target, devinfo->lun, 317066647Sgibbs ahc->msgin_buf[3], saved_offset, 317166647Sgibbs period, offset); 317266647Sgibbs } 317365942Sgibbs ahc_set_syncrate(ahc, devinfo, 317463457Sgibbs syncrate, period, 317563457Sgibbs offset, ppr_options, 317647287Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 317747287Sgibbs /*paused*/TRUE); 317839220Sgibbs 317939220Sgibbs /* 318039220Sgibbs * See if we initiated Sync Negotiation 318139220Sgibbs * and didn't have to fall down to async 318239220Sgibbs * transfers. 318339220Sgibbs */ 318470204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, TRUE)) { 318539220Sgibbs /* We started it */ 318639220Sgibbs if (saved_offset != offset) { 318739220Sgibbs /* Went too low - force async */ 318839220Sgibbs reject = TRUE; 318939220Sgibbs } 319039220Sgibbs } else { 319139220Sgibbs /* 319239220Sgibbs * Send our own SDTR in reply 319339220Sgibbs */ 319474972Sgibbs if (bootverbose 319574972Sgibbs && devinfo->role == ROLE_INITIATOR) { 319666647Sgibbs printf("(%s:%c:%d:%d): Target " 319766647Sgibbs "Initiated SDTR\n", 319866647Sgibbs ahc_name(ahc), devinfo->channel, 319966647Sgibbs devinfo->target, devinfo->lun); 320066647Sgibbs } 320141646Sgibbs ahc->msgout_index = 0; 320241646Sgibbs ahc->msgout_len = 0; 320366647Sgibbs ahc_construct_sdtr(ahc, devinfo, 320466647Sgibbs period, offset); 320541646Sgibbs ahc->msgout_index = 0; 320641646Sgibbs response = TRUE; 320739220Sgibbs } 320849933Sgibbs done = MSGLOOP_MSGCOMPLETE; 320939220Sgibbs break; 321039220Sgibbs } 321139220Sgibbs case MSG_EXT_WDTR: 321239220Sgibbs { 321363457Sgibbs u_int bus_width; 321463457Sgibbs u_int saved_width; 321563457Sgibbs u_int sending_reply; 321639220Sgibbs 321741646Sgibbs sending_reply = FALSE; 321841646Sgibbs if (ahc->msgin_buf[1] != MSG_EXT_WDTR_LEN) { 321939220Sgibbs reject = TRUE; 322039220Sgibbs break; 322139220Sgibbs } 322239220Sgibbs 322339220Sgibbs /* 322439220Sgibbs * Wait until we have our arg before validating 322539220Sgibbs * and acting on this message. 322641646Sgibbs * 322741646Sgibbs * Add one to MSG_EXT_WDTR_LEN to account for 322841646Sgibbs * the extended message preamble. 322939220Sgibbs */ 323041646Sgibbs if (ahc->msgin_index < (MSG_EXT_WDTR_LEN + 1)) 323139220Sgibbs break; 323239220Sgibbs 323341646Sgibbs bus_width = ahc->msgin_buf[3]; 323463457Sgibbs saved_width = bus_width; 323568087Sgibbs ahc_validate_width(ahc, tinfo, &bus_width, 323668087Sgibbs devinfo->role); 323766647Sgibbs if (bootverbose) { 323866647Sgibbs printf("(%s:%c:%d:%d): Received WDTR " 323966647Sgibbs "%x filtered to %x\n", 324066647Sgibbs ahc_name(ahc), devinfo->channel, 324166647Sgibbs devinfo->target, devinfo->lun, 324266647Sgibbs saved_width, bus_width); 324366647Sgibbs } 324463457Sgibbs 324570204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, TRUE)) { 324639220Sgibbs /* 324739220Sgibbs * Don't send a WDTR back to the 324839220Sgibbs * target, since we asked first. 324963457Sgibbs * If the width went higher than our 325063457Sgibbs * request, reject it. 325139220Sgibbs */ 325263457Sgibbs if (saved_width > bus_width) { 325339220Sgibbs reject = TRUE; 325466647Sgibbs printf("(%s:%c:%d:%d): requested %dBit " 325539220Sgibbs "transfers. Rejecting...\n", 325666647Sgibbs ahc_name(ahc), devinfo->channel, 325766647Sgibbs devinfo->target, devinfo->lun, 325839220Sgibbs 8 * (0x01 << bus_width)); 325963457Sgibbs bus_width = 0; 326039220Sgibbs } 326139220Sgibbs } else { 326239220Sgibbs /* 326339220Sgibbs * Send our own WDTR in reply 326439220Sgibbs */ 326574972Sgibbs if (bootverbose 326674972Sgibbs && devinfo->role == ROLE_INITIATOR) { 326766647Sgibbs printf("(%s:%c:%d:%d): Target " 326866647Sgibbs "Initiated WDTR\n", 326966647Sgibbs ahc_name(ahc), devinfo->channel, 327066647Sgibbs devinfo->target, devinfo->lun); 327166647Sgibbs } 327241646Sgibbs ahc->msgout_index = 0; 327341646Sgibbs ahc->msgout_len = 0; 327466647Sgibbs ahc_construct_wdtr(ahc, devinfo, bus_width); 327541646Sgibbs ahc->msgout_index = 0; 327641646Sgibbs response = TRUE; 327741646Sgibbs sending_reply = TRUE; 327839220Sgibbs } 3279115918Sgibbs /* 3280115918Sgibbs * After a wide message, we are async, but 3281115918Sgibbs * some devices don't seem to honor this portion 3282115918Sgibbs * of the spec. Force a renegotiation of the 3283115918Sgibbs * sync component of our transfer agreement even 3284115918Sgibbs * if our goal is async. By updating our width 3285115918Sgibbs * after forcing the negotiation, we avoid 3286115918Sgibbs * renegotiating for width. 3287115918Sgibbs */ 3288115918Sgibbs ahc_update_neg_request(ahc, devinfo, tstate, 3289115918Sgibbs tinfo, AHC_NEG_ALWAYS); 329065942Sgibbs ahc_set_width(ahc, devinfo, bus_width, 329147287Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 329247287Sgibbs /*paused*/TRUE); 329341646Sgibbs if (sending_reply == FALSE && reject == FALSE) { 329439220Sgibbs 3295115918Sgibbs /* 3296115918Sgibbs * We will always have an SDTR to send. 3297115918Sgibbs */ 3298115918Sgibbs ahc->msgout_index = 0; 3299115918Sgibbs ahc->msgout_len = 0; 3300115918Sgibbs ahc_build_transfer_msg(ahc, devinfo); 3301115918Sgibbs ahc->msgout_index = 0; 3302115918Sgibbs response = TRUE; 330339220Sgibbs } 330449933Sgibbs done = MSGLOOP_MSGCOMPLETE; 330539220Sgibbs break; 330639220Sgibbs } 330763457Sgibbs case MSG_EXT_PPR: 330863457Sgibbs { 330963457Sgibbs struct ahc_syncrate *syncrate; 331063457Sgibbs u_int period; 331163457Sgibbs u_int offset; 331263457Sgibbs u_int bus_width; 331363457Sgibbs u_int ppr_options; 331463457Sgibbs u_int saved_width; 331563457Sgibbs u_int saved_offset; 331663457Sgibbs u_int saved_ppr_options; 331763457Sgibbs 331863457Sgibbs if (ahc->msgin_buf[1] != MSG_EXT_PPR_LEN) { 331963457Sgibbs reject = TRUE; 332063457Sgibbs break; 332163457Sgibbs } 332263457Sgibbs 332363457Sgibbs /* 332463457Sgibbs * Wait until we have all args before validating 332563457Sgibbs * and acting on this message. 332663457Sgibbs * 332763457Sgibbs * Add one to MSG_EXT_PPR_LEN to account for 332863457Sgibbs * the extended message preamble. 332963457Sgibbs */ 333063457Sgibbs if (ahc->msgin_index < (MSG_EXT_PPR_LEN + 1)) 333163457Sgibbs break; 333263457Sgibbs 333363457Sgibbs period = ahc->msgin_buf[3]; 333463457Sgibbs offset = ahc->msgin_buf[5]; 333563457Sgibbs bus_width = ahc->msgin_buf[6]; 333663457Sgibbs saved_width = bus_width; 333763457Sgibbs ppr_options = ahc->msgin_buf[7]; 333863457Sgibbs /* 333963457Sgibbs * According to the spec, a DT only 334063457Sgibbs * period factor with no DT option 334163457Sgibbs * set implies async. 334263457Sgibbs */ 334363457Sgibbs if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0 334463457Sgibbs && period == 9) 334563457Sgibbs offset = 0; 334663457Sgibbs saved_ppr_options = ppr_options; 334763457Sgibbs saved_offset = offset; 334863457Sgibbs 334963457Sgibbs /* 335063457Sgibbs * Mask out any options we don't support 335163457Sgibbs * on any controller. Transfer options are 335263457Sgibbs * only available if we are negotiating wide. 335363457Sgibbs */ 335463457Sgibbs ppr_options &= MSG_EXT_PPR_DT_REQ; 335563457Sgibbs if (bus_width == 0) 335663457Sgibbs ppr_options = 0; 335763457Sgibbs 335868087Sgibbs ahc_validate_width(ahc, tinfo, &bus_width, 335968087Sgibbs devinfo->role); 336068087Sgibbs syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period, 336168087Sgibbs &ppr_options, 336268087Sgibbs devinfo->role); 336368087Sgibbs ahc_validate_offset(ahc, tinfo, syncrate, 336468087Sgibbs &offset, bus_width, 336568087Sgibbs devinfo->role); 336663457Sgibbs 336770204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, TRUE)) { 336863457Sgibbs /* 336963457Sgibbs * If we are unable to do any of the 337063457Sgibbs * requested options (we went too low), 337163457Sgibbs * then we'll have to reject the message. 337263457Sgibbs */ 337363457Sgibbs if (saved_width > bus_width 337463457Sgibbs || saved_offset != offset 337566647Sgibbs || saved_ppr_options != ppr_options) { 337663457Sgibbs reject = TRUE; 337766647Sgibbs period = 0; 337866647Sgibbs offset = 0; 337966647Sgibbs bus_width = 0; 338066647Sgibbs ppr_options = 0; 338166647Sgibbs syncrate = NULL; 338266647Sgibbs } 338363457Sgibbs } else { 338468087Sgibbs if (devinfo->role != ROLE_TARGET) 338568087Sgibbs printf("(%s:%c:%d:%d): Target " 338668087Sgibbs "Initiated PPR\n", 338768087Sgibbs ahc_name(ahc), devinfo->channel, 338868087Sgibbs devinfo->target, devinfo->lun); 338968087Sgibbs else 339068087Sgibbs printf("(%s:%c:%d:%d): Initiator " 339168087Sgibbs "Initiated PPR\n", 339268087Sgibbs ahc_name(ahc), devinfo->channel, 339368087Sgibbs devinfo->target, devinfo->lun); 339468087Sgibbs ahc->msgout_index = 0; 339568087Sgibbs ahc->msgout_len = 0; 339668087Sgibbs ahc_construct_ppr(ahc, devinfo, period, offset, 339768087Sgibbs bus_width, ppr_options); 339868087Sgibbs ahc->msgout_index = 0; 339963457Sgibbs response = TRUE; 340063457Sgibbs } 340166647Sgibbs if (bootverbose) { 340266647Sgibbs printf("(%s:%c:%d:%d): Received PPR width %x, " 340366647Sgibbs "period %x, offset %x,options %x\n" 340466647Sgibbs "\tFiltered to width %x, period %x, " 340566647Sgibbs "offset %x, options %x\n", 340666647Sgibbs ahc_name(ahc), devinfo->channel, 340766647Sgibbs devinfo->target, devinfo->lun, 340874094Sgibbs saved_width, ahc->msgin_buf[3], 340966647Sgibbs saved_offset, saved_ppr_options, 341066647Sgibbs bus_width, period, offset, ppr_options); 341166647Sgibbs } 341265942Sgibbs ahc_set_width(ahc, devinfo, bus_width, 341365942Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 341465942Sgibbs /*paused*/TRUE); 341565942Sgibbs ahc_set_syncrate(ahc, devinfo, 341663457Sgibbs syncrate, period, 341763457Sgibbs offset, ppr_options, 341863457Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 341963457Sgibbs /*paused*/TRUE); 342068087Sgibbs done = MSGLOOP_MSGCOMPLETE; 342163457Sgibbs break; 342263457Sgibbs } 342339220Sgibbs default: 342439220Sgibbs /* Unknown extended message. Reject it. */ 342539220Sgibbs reject = TRUE; 342639220Sgibbs break; 342739220Sgibbs } 342842708Sgibbs break; 342939220Sgibbs } 343095378Sgibbs#ifdef AHC_TARGET_MODE 343149933Sgibbs case MSG_BUS_DEV_RESET: 343249933Sgibbs ahc_handle_devreset(ahc, devinfo, 343365942Sgibbs CAM_BDR_SENT, 343449933Sgibbs "Bus Device Reset Received", 343554211Sgibbs /*verbose_level*/0); 343674094Sgibbs ahc_restart(ahc); 343749933Sgibbs done = MSGLOOP_TERMINATED; 343849933Sgibbs break; 343949933Sgibbs case MSG_ABORT_TAG: 344042652Sgibbs case MSG_ABORT: 344142652Sgibbs case MSG_CLEAR_QUEUE: 344295378Sgibbs { 344395378Sgibbs int tag; 344495378Sgibbs 344542652Sgibbs /* Target mode messages */ 344649933Sgibbs if (devinfo->role != ROLE_TARGET) { 344742652Sgibbs reject = TRUE; 344849933Sgibbs break; 344949933Sgibbs } 345095378Sgibbs tag = SCB_LIST_NULL; 345195378Sgibbs if (ahc->msgin_buf[0] == MSG_ABORT_TAG) 345295378Sgibbs tag = ahc_inb(ahc, INITIATOR_TAG); 345349933Sgibbs ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, 345495378Sgibbs devinfo->lun, tag, ROLE_TARGET, 345595378Sgibbs CAM_REQ_ABORTED); 345649933Sgibbs 345749933Sgibbs tstate = ahc->enabled_targets[devinfo->our_scsiid]; 345849933Sgibbs if (tstate != NULL) { 345974972Sgibbs struct ahc_tmode_lstate* lstate; 346049933Sgibbs 346149933Sgibbs lstate = tstate->enabled_luns[devinfo->lun]; 346249933Sgibbs if (lstate != NULL) { 346349933Sgibbs ahc_queue_lstate_event(ahc, lstate, 346449933Sgibbs devinfo->our_scsiid, 346549933Sgibbs ahc->msgin_buf[0], 346695378Sgibbs /*arg*/tag); 346749933Sgibbs ahc_send_lstate_events(ahc, lstate); 346849933Sgibbs } 346949933Sgibbs } 347095378Sgibbs ahc_restart(ahc); 347195378Sgibbs done = MSGLOOP_TERMINATED; 347242652Sgibbs break; 347395378Sgibbs } 347465942Sgibbs#endif 347549933Sgibbs case MSG_TERM_IO_PROC: 347642652Sgibbs default: 347742652Sgibbs reject = TRUE; 347842652Sgibbs break; 347942652Sgibbs } 348039220Sgibbs 348139220Sgibbs if (reject) { 348239220Sgibbs /* 348349933Sgibbs * Setup to reject the message. 348439220Sgibbs */ 348541646Sgibbs ahc->msgout_index = 0; 348641646Sgibbs ahc->msgout_len = 1; 348741646Sgibbs ahc->msgout_buf[0] = MSG_MESSAGE_REJECT; 348849933Sgibbs done = MSGLOOP_MSGCOMPLETE; 348941646Sgibbs response = TRUE; 349039220Sgibbs } 349141646Sgibbs 349249933Sgibbs if (done != MSGLOOP_IN_PROG && !response) 349341646Sgibbs /* Clear the outgoing message buffer */ 349441646Sgibbs ahc->msgout_len = 0; 349541646Sgibbs 349639220Sgibbs return (done); 349739220Sgibbs} 349839220Sgibbs 349965942Sgibbs/* 350065942Sgibbs * Process a message reject message. 350165942Sgibbs */ 350265942Sgibbsstatic int 350365942Sgibbsahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 350465942Sgibbs{ 350565942Sgibbs /* 350665942Sgibbs * What we care about here is if we had an 350765942Sgibbs * outstanding SDTR or WDTR message for this 350865942Sgibbs * target. If we did, this is a signal that 350965942Sgibbs * the target is refusing negotiation. 351065942Sgibbs */ 351165942Sgibbs struct scb *scb; 351265942Sgibbs struct ahc_initiator_tinfo *tinfo; 351374972Sgibbs struct ahc_tmode_tstate *tstate; 351465942Sgibbs u_int scb_index; 351565942Sgibbs u_int last_msg; 351665942Sgibbs int response = 0; 351765942Sgibbs 351865942Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 351966647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 352065942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, 352165942Sgibbs devinfo->our_scsiid, 352265942Sgibbs devinfo->target, &tstate); 352365942Sgibbs /* Might be necessary */ 352465942Sgibbs last_msg = ahc_inb(ahc, LAST_MSG); 352565942Sgibbs 352670204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) { 352766269Sgibbs /* 352866269Sgibbs * Target does not support the PPR message. 352966269Sgibbs * Attempt to negotiate SPI-2 style. 353066269Sgibbs */ 353166647Sgibbs if (bootverbose) { 353266647Sgibbs printf("(%s:%c:%d:%d): PPR Rejected. " 353366647Sgibbs "Trying WDTR/SDTR\n", 353466647Sgibbs ahc_name(ahc), devinfo->channel, 353566647Sgibbs devinfo->target, devinfo->lun); 353666647Sgibbs } 353766269Sgibbs tinfo->goal.ppr_options = 0; 353876634Sgibbs tinfo->curr.transport_version = 2; 353966269Sgibbs tinfo->goal.transport_version = 2; 354066269Sgibbs ahc->msgout_index = 0; 354166269Sgibbs ahc->msgout_len = 0; 354266269Sgibbs ahc_build_transfer_msg(ahc, devinfo); 354366269Sgibbs ahc->msgout_index = 0; 354466269Sgibbs response = 1; 354570204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) { 354665942Sgibbs 354765942Sgibbs /* note 8bit xfers */ 354866647Sgibbs printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " 354965942Sgibbs "8bit transfers\n", ahc_name(ahc), 355066647Sgibbs devinfo->channel, devinfo->target, devinfo->lun); 355165942Sgibbs ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, 355265942Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 355365942Sgibbs /*paused*/TRUE); 355465942Sgibbs /* 355565942Sgibbs * No need to clear the sync rate. If the target 355665942Sgibbs * did not accept the command, our syncrate is 355765942Sgibbs * unaffected. If the target started the negotiation, 355865942Sgibbs * but rejected our response, we already cleared the 355965942Sgibbs * sync rate before sending our WDTR. 356065942Sgibbs */ 3561109590Sgibbs if (tinfo->goal.offset != tinfo->curr.offset) { 356265942Sgibbs 356365942Sgibbs /* Start the sync negotiation */ 356465942Sgibbs ahc->msgout_index = 0; 356565942Sgibbs ahc->msgout_len = 0; 356666269Sgibbs ahc_build_transfer_msg(ahc, devinfo); 356765942Sgibbs ahc->msgout_index = 0; 356865942Sgibbs response = 1; 356965942Sgibbs } 357070204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) { 357165942Sgibbs /* note asynch xfers and clear flag */ 357265942Sgibbs ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, /*period*/0, 357365942Sgibbs /*offset*/0, /*ppr_options*/0, 357465942Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 357565942Sgibbs /*paused*/TRUE); 357666647Sgibbs printf("(%s:%c:%d:%d): refuses synchronous negotiation. " 357765942Sgibbs "Using asynchronous transfers\n", 357866647Sgibbs ahc_name(ahc), devinfo->channel, 357966647Sgibbs devinfo->target, devinfo->lun); 358076634Sgibbs } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) { 358176634Sgibbs int tag_type; 358276634Sgibbs int mask; 358365942Sgibbs 358476634Sgibbs tag_type = (scb->hscb->control & MSG_SIMPLE_TASK); 358565942Sgibbs 358676634Sgibbs if (tag_type == MSG_SIMPLE_TASK) { 358776634Sgibbs printf("(%s:%c:%d:%d): refuses tagged commands. " 358876634Sgibbs "Performing non-tagged I/O\n", ahc_name(ahc), 358976634Sgibbs devinfo->channel, devinfo->target, devinfo->lun); 359076634Sgibbs ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE); 359176634Sgibbs mask = ~0x23; 359276634Sgibbs } else { 359376634Sgibbs printf("(%s:%c:%d:%d): refuses %s tagged commands. " 359476634Sgibbs "Performing simple queue tagged I/O only\n", 359576634Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 359676634Sgibbs devinfo->lun, tag_type == MSG_ORDERED_TASK 359776634Sgibbs ? "ordered" : "head of queue"); 359876634Sgibbs ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC); 359976634Sgibbs mask = ~0x03; 360076634Sgibbs } 360176634Sgibbs 360265942Sgibbs /* 360365942Sgibbs * Resend the identify for this CCB as the target 360465942Sgibbs * may believe that the selection is invalid otherwise. 360565942Sgibbs */ 360665942Sgibbs ahc_outb(ahc, SCB_CONTROL, 360776634Sgibbs ahc_inb(ahc, SCB_CONTROL) & mask); 360876634Sgibbs scb->hscb->control &= mask; 3609123579Sgibbs aic_set_transaction_tag(scb, /*enabled*/FALSE, 361076634Sgibbs /*type*/MSG_SIMPLE_TASK); 361165942Sgibbs ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG); 361276634Sgibbs ahc_assert_atn(ahc); 361365942Sgibbs 361465942Sgibbs /* 361565942Sgibbs * This transaction is now at the head of 361665942Sgibbs * the untagged queue for this target. 361765942Sgibbs */ 361871390Sgibbs if ((ahc->flags & AHC_SCB_BTT) == 0) { 361965942Sgibbs struct scb_tailq *untagged_q; 362065942Sgibbs 362172811Sgibbs untagged_q = 362272811Sgibbs &(ahc->untagged_queues[devinfo->target_offset]); 362365942Sgibbs TAILQ_INSERT_HEAD(untagged_q, scb, links.tqe); 362468087Sgibbs scb->flags |= SCB_UNTAGGEDQ; 362565942Sgibbs } 362665942Sgibbs ahc_busy_tcl(ahc, BUILD_TCL(scb->hscb->scsiid, devinfo->lun), 362765942Sgibbs scb->hscb->tag); 362865942Sgibbs 362965942Sgibbs /* 363065942Sgibbs * Requeue all tagged commands for this target 363165942Sgibbs * currently in our posession so they can be 363265942Sgibbs * converted to untagged commands. 363365942Sgibbs */ 363465942Sgibbs ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), 363565942Sgibbs SCB_GET_CHANNEL(ahc, scb), 363665942Sgibbs SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL, 363765942Sgibbs ROLE_INITIATOR, CAM_REQUEUE_REQ, 363865942Sgibbs SEARCH_COMPLETE); 363965942Sgibbs } else { 364065942Sgibbs /* 364165942Sgibbs * Otherwise, we ignore it. 364265942Sgibbs */ 364365942Sgibbs printf("%s:%c:%d: Message reject for %x -- ignored\n", 364465942Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 364565942Sgibbs last_msg); 364665942Sgibbs } 364765942Sgibbs return (response); 364865942Sgibbs} 364965942Sgibbs 365065942Sgibbs/* 365165942Sgibbs * Process an ingnore wide residue message. 365265942Sgibbs */ 365339220Sgibbsstatic void 365442652Sgibbsahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 365542652Sgibbs{ 365642652Sgibbs u_int scb_index; 365742652Sgibbs struct scb *scb; 365842652Sgibbs 365942652Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 366066647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 366165942Sgibbs /* 366265942Sgibbs * XXX Actually check data direction in the sequencer? 366365942Sgibbs * Perhaps add datadir to some spare bits in the hscb? 366465942Sgibbs */ 366542652Sgibbs if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0 3666123579Sgibbs || aic_get_transfer_dir(scb) != CAM_DIR_IN) { 366742652Sgibbs /* 366842652Sgibbs * Ignore the message if we haven't 366942652Sgibbs * seen an appropriate data phase yet. 367042652Sgibbs */ 367142652Sgibbs } else { 367242652Sgibbs /* 367342652Sgibbs * If the residual occurred on the last 367442652Sgibbs * transfer and the transfer request was 367542652Sgibbs * expected to end on an odd count, do 367642652Sgibbs * nothing. Otherwise, subtract a byte 367742652Sgibbs * and update the residual count accordingly. 367842652Sgibbs */ 367963457Sgibbs uint32_t sgptr; 368042652Sgibbs 368163457Sgibbs sgptr = ahc_inb(ahc, SCB_RESIDUAL_SGPTR); 368263457Sgibbs if ((sgptr & SG_LIST_NULL) != 0 3683115333Sgibbs && (ahc_inb(ahc, SCB_LUN) & SCB_XFERLEN_ODD) != 0) { 368442652Sgibbs /* 368542652Sgibbs * If the residual occurred on the last 368642652Sgibbs * transfer and the transfer request was 368742652Sgibbs * expected to end on an odd count, do 368842652Sgibbs * nothing. 368942652Sgibbs */ 369042652Sgibbs } else { 369163457Sgibbs struct ahc_dma_seg *sg; 369263457Sgibbs uint32_t data_cnt; 369363457Sgibbs uint32_t data_addr; 369479874Sgibbs uint32_t sglen; 369542652Sgibbs 3696115333Sgibbs /* Pull in all of the sgptr */ 3697115333Sgibbs sgptr = ahc_inl(ahc, SCB_RESIDUAL_SGPTR); 3698115333Sgibbs data_cnt = ahc_inl(ahc, SCB_RESIDUAL_DATACNT); 369942652Sgibbs 3700115333Sgibbs if ((sgptr & SG_LIST_NULL) != 0) { 3701115333Sgibbs /* 3702115333Sgibbs * The residual data count is not updated 3703115333Sgibbs * for the command run to completion case. 3704115333Sgibbs * Explicitly zero the count. 3705115333Sgibbs */ 3706115333Sgibbs data_cnt &= ~AHC_SG_LEN_MASK; 3707115333Sgibbs } 370842652Sgibbs 3709115333Sgibbs data_addr = ahc_inl(ahc, SHADDR); 3710115333Sgibbs 371142652Sgibbs data_cnt += 1; 371242652Sgibbs data_addr -= 1; 3713115333Sgibbs sgptr &= SG_PTR_MASK; 371442652Sgibbs 371563457Sgibbs sg = ahc_sg_bus_to_virt(scb, sgptr); 3716115333Sgibbs 371763457Sgibbs /* 371863457Sgibbs * The residual sg ptr points to the next S/G 371963457Sgibbs * to load so we must go back one. 372063457Sgibbs */ 372163457Sgibbs sg--; 3722123579Sgibbs sglen = aic_le32toh(sg->len) & AHC_SG_LEN_MASK; 372363457Sgibbs if (sg != scb->sg_list 372479874Sgibbs && sglen < (data_cnt & AHC_SG_LEN_MASK)) { 372542652Sgibbs 372663457Sgibbs sg--; 3727123579Sgibbs sglen = aic_le32toh(sg->len); 372879874Sgibbs /* 372979874Sgibbs * Preserve High Address and SG_LIST bits 373079874Sgibbs * while setting the count to 1. 373179874Sgibbs */ 373279874Sgibbs data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK)); 3733123579Sgibbs data_addr = aic_le32toh(sg->addr) 373479874Sgibbs + (sglen & AHC_SG_LEN_MASK) - 1; 373542652Sgibbs 373655581Sgibbs /* 373763457Sgibbs * Increment sg so it points to the 373863457Sgibbs * "next" sg. 373955581Sgibbs */ 374063457Sgibbs sg++; 374163457Sgibbs sgptr = ahc_sg_virt_to_bus(scb, sg); 374242652Sgibbs } 3743115333Sgibbs ahc_outl(ahc, SCB_RESIDUAL_SGPTR, sgptr); 3744115333Sgibbs ahc_outl(ahc, SCB_RESIDUAL_DATACNT, data_cnt); 3745115333Sgibbs /* 3746115333Sgibbs * Toggle the "oddness" of the transfer length 3747115333Sgibbs * to handle this mid-transfer ignore wide 3748115333Sgibbs * residue. This ensures that the oddness is 3749115333Sgibbs * correct for subsequent data transfers. 3750115333Sgibbs */ 3751115333Sgibbs ahc_outb(ahc, SCB_LUN, 3752115333Sgibbs ahc_inb(ahc, SCB_LUN) ^ SCB_XFERLEN_ODD); 375342652Sgibbs } 375442652Sgibbs } 375542652Sgibbs} 375642652Sgibbs 375779874Sgibbs 375865942Sgibbs/* 375979874Sgibbs * Reinitialize the data pointers for the active transfer 376079874Sgibbs * based on its current residual. 376179874Sgibbs */ 376279874Sgibbsstatic void 376379874Sgibbsahc_reinitialize_dataptrs(struct ahc_softc *ahc) 376479874Sgibbs{ 376579874Sgibbs struct scb *scb; 376679874Sgibbs struct ahc_dma_seg *sg; 376779874Sgibbs u_int scb_index; 376879874Sgibbs uint32_t sgptr; 376979874Sgibbs uint32_t resid; 377079874Sgibbs uint32_t dataptr; 377179874Sgibbs 377279874Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 377379874Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 377479874Sgibbs sgptr = (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24) 377579874Sgibbs | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16) 377679874Sgibbs | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8) 377779874Sgibbs | ahc_inb(ahc, SCB_RESIDUAL_SGPTR); 377879874Sgibbs 377979874Sgibbs sgptr &= SG_PTR_MASK; 378079874Sgibbs sg = ahc_sg_bus_to_virt(scb, sgptr); 378179874Sgibbs 378279874Sgibbs /* The residual sg_ptr always points to the next sg */ 378379874Sgibbs sg--; 378479874Sgibbs 378579874Sgibbs resid = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 2) << 16) 378679874Sgibbs | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8) 378779874Sgibbs | ahc_inb(ahc, SCB_RESIDUAL_DATACNT); 378879874Sgibbs 3789123579Sgibbs dataptr = aic_le32toh(sg->addr) 3790123579Sgibbs + (aic_le32toh(sg->len) & AHC_SG_LEN_MASK) 379179874Sgibbs - resid; 379279874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 379379874Sgibbs u_int dscommand1; 379479874Sgibbs 379579874Sgibbs dscommand1 = ahc_inb(ahc, DSCOMMAND1); 379679874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); 379779874Sgibbs ahc_outb(ahc, HADDR, 3798123579Sgibbs (aic_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); 379979874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1); 380079874Sgibbs } 380179874Sgibbs ahc_outb(ahc, HADDR + 3, dataptr >> 24); 380279874Sgibbs ahc_outb(ahc, HADDR + 2, dataptr >> 16); 380379874Sgibbs ahc_outb(ahc, HADDR + 1, dataptr >> 8); 380479874Sgibbs ahc_outb(ahc, HADDR, dataptr); 380579874Sgibbs ahc_outb(ahc, HCNT + 2, resid >> 16); 380679874Sgibbs ahc_outb(ahc, HCNT + 1, resid >> 8); 380779874Sgibbs ahc_outb(ahc, HCNT, resid); 380879874Sgibbs if ((ahc->features & AHC_ULTRA2) == 0) { 380979874Sgibbs ahc_outb(ahc, STCNT + 2, resid >> 16); 381079874Sgibbs ahc_outb(ahc, STCNT + 1, resid >> 8); 381179874Sgibbs ahc_outb(ahc, STCNT, resid); 381279874Sgibbs } 381379874Sgibbs} 381479874Sgibbs 381579874Sgibbs/* 381665942Sgibbs * Handle the effects of issuing a bus device reset message. 381765942Sgibbs */ 381842652Sgibbsstatic void 381944507Sgibbsahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 382065942Sgibbs cam_status status, char *message, int verbose_level) 382139220Sgibbs{ 382265942Sgibbs#ifdef AHC_TARGET_MODE 382374972Sgibbs struct ahc_tmode_tstate* tstate; 382449933Sgibbs u_int lun; 382565942Sgibbs#endif 382665942Sgibbs int found; 382739220Sgibbs 382849933Sgibbs found = ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, 382949933Sgibbs CAM_LUN_WILDCARD, SCB_LIST_NULL, devinfo->role, 383049933Sgibbs status); 383150662Sgibbs 383265942Sgibbs#ifdef AHC_TARGET_MODE 383339220Sgibbs /* 383465942Sgibbs * Send an immediate notify ccb to all target mord peripheral 383549933Sgibbs * drivers affected by this action. 383649933Sgibbs */ 383749933Sgibbs tstate = ahc->enabled_targets[devinfo->our_scsiid]; 383849933Sgibbs if (tstate != NULL) { 383970204Sgibbs for (lun = 0; lun < AHC_NUM_LUNS; lun++) { 384074972Sgibbs struct ahc_tmode_lstate* lstate; 384149933Sgibbs 384249933Sgibbs lstate = tstate->enabled_luns[lun]; 384349933Sgibbs if (lstate == NULL) 384449933Sgibbs continue; 384549933Sgibbs 384649933Sgibbs ahc_queue_lstate_event(ahc, lstate, devinfo->our_scsiid, 384749933Sgibbs MSG_BUS_DEV_RESET, /*arg*/0); 384849933Sgibbs ahc_send_lstate_events(ahc, lstate); 384949933Sgibbs } 385049933Sgibbs } 385165942Sgibbs#endif 385249933Sgibbs 385349933Sgibbs /* 385439220Sgibbs * Go back to async/narrow transfers and renegotiate. 385539220Sgibbs */ 385665942Sgibbs ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, 385747287Sgibbs AHC_TRANS_CUR, /*paused*/TRUE); 385865942Sgibbs ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, 385963457Sgibbs /*period*/0, /*offset*/0, /*ppr_options*/0, 386063457Sgibbs AHC_TRANS_CUR, /*paused*/TRUE); 386139220Sgibbs 3862129133Sgibbs if (status != CAM_SEL_TIMEOUT) 3863129133Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 3864129133Sgibbs CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); 386539220Sgibbs 386639220Sgibbs if (message != NULL 386754211Sgibbs && (verbose_level <= bootverbose)) 386839220Sgibbs printf("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc), 386944507Sgibbs message, devinfo->channel, devinfo->target, found); 387039220Sgibbs} 387140028Sgibbs 387265942Sgibbs#ifdef AHC_TARGET_MODE 387374972Sgibbsstatic void 387474972Sgibbsahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 387574972Sgibbs struct scb *scb) 387665942Sgibbs{ 387774972Sgibbs 387865942Sgibbs /* 387965942Sgibbs * To facilitate adding multiple messages together, 388065942Sgibbs * each routine should increment the index and len 388165942Sgibbs * variables instead of setting them explicitly. 388265942Sgibbs */ 388365942Sgibbs ahc->msgout_index = 0; 388465942Sgibbs ahc->msgout_len = 0; 388565942Sgibbs 388674972Sgibbs if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0) 388765942Sgibbs ahc_build_transfer_msg(ahc, devinfo); 388865942Sgibbs else 388965942Sgibbs panic("ahc_intr: AWAITING target message with no message"); 389065942Sgibbs 389165942Sgibbs ahc->msgout_index = 0; 389265942Sgibbs ahc->msg_type = MSG_TYPE_TARGET_MSGIN; 389365942Sgibbs} 389465942Sgibbs#endif 389565942Sgibbs/**************************** Initialization **********************************/ 389639220Sgibbs/* 389765942Sgibbs * Allocate a controller structure for a new device 389865942Sgibbs * and perform initial initializion. 389939220Sgibbs */ 390065942Sgibbsstruct ahc_softc * 390165942Sgibbsahc_alloc(void *platform_arg, char *name) 390239220Sgibbs{ 390365942Sgibbs struct ahc_softc *ahc; 390465942Sgibbs int i; 390539220Sgibbs 390670204Sgibbs#ifndef __FreeBSD__ 390765942Sgibbs ahc = malloc(sizeof(*ahc), M_DEVBUF, M_NOWAIT); 390865942Sgibbs if (!ahc) { 390965942Sgibbs printf("aic7xxx: cannot malloc softc!\n"); 391065942Sgibbs free(name, M_DEVBUF); 391165942Sgibbs return NULL; 391265942Sgibbs } 391370204Sgibbs#else 391470204Sgibbs ahc = device_get_softc((device_t)platform_arg); 391570204Sgibbs#endif 391665942Sgibbs memset(ahc, 0, sizeof(*ahc)); 3917102670Sgibbs ahc->seep_config = malloc(sizeof(*ahc->seep_config), 3918102670Sgibbs M_DEVBUF, M_NOWAIT); 3919102670Sgibbs if (ahc->seep_config == NULL) { 3920102670Sgibbs#ifndef __FreeBSD__ 3921102670Sgibbs free(ahc, M_DEVBUF); 3922102670Sgibbs#endif 3923102670Sgibbs free(name, M_DEVBUF); 3924102670Sgibbs return (NULL); 3925102670Sgibbs } 392665942Sgibbs LIST_INIT(&ahc->pending_scbs); 3927141999Sgibbs LIST_INIT(&ahc->timedout_scbs); 392872325Sgibbs /* We don't know our unit number until the OSM sets it */ 392965942Sgibbs ahc->name = name; 393074972Sgibbs ahc->unit = -1; 393179874Sgibbs ahc->description = NULL; 393279874Sgibbs ahc->channel = 'A'; 393379874Sgibbs ahc->channel_b = 'B'; 393479874Sgibbs ahc->chip = AHC_NONE; 393579874Sgibbs ahc->features = AHC_FENONE; 393679874Sgibbs ahc->bugs = AHC_BUGNONE; 393779874Sgibbs ahc->flags = AHC_FNONE; 3938115332Sgibbs /* 3939115332Sgibbs * Default to all error reporting enabled with the 3940115332Sgibbs * sequencer operating at its fastest speed. 3941115332Sgibbs * The bus attach code may modify this. 3942115332Sgibbs */ 3943115332Sgibbs ahc->seqctl = FASTMODE; 394479874Sgibbs 394595378Sgibbs for (i = 0; i < AHC_NUM_TARGETS; i++) 394665942Sgibbs TAILQ_INIT(&ahc->untagged_queues[i]); 394765942Sgibbs if (ahc_platform_alloc(ahc, platform_arg) != 0) { 394865942Sgibbs ahc_free(ahc); 394965942Sgibbs ahc = NULL; 395065942Sgibbs } 3951168807Sscottl ahc_lockinit(ahc); 395265942Sgibbs return (ahc); 395365942Sgibbs} 395439220Sgibbs 395565942Sgibbsint 395679874Sgibbsahc_softc_init(struct ahc_softc *ahc) 395765942Sgibbs{ 395839220Sgibbs 395965942Sgibbs /* The IRQMS bit is only valid on VL and EISA chips */ 396081809Sgibbs if ((ahc->chip & AHC_PCI) == 0) 396181809Sgibbs ahc->unpause = ahc_inb(ahc, HCNTRL) & IRQMS; 396281809Sgibbs else 396381809Sgibbs ahc->unpause = 0; 396465942Sgibbs ahc->pause = ahc->unpause | PAUSE; 396572085Sasmodai /* XXX The shared scb data stuff should be deprecated */ 396665942Sgibbs if (ahc->scb_data == NULL) { 396765942Sgibbs ahc->scb_data = malloc(sizeof(*ahc->scb_data), 396865942Sgibbs M_DEVBUF, M_NOWAIT); 396965942Sgibbs if (ahc->scb_data == NULL) 397065942Sgibbs return (ENOMEM); 397165942Sgibbs memset(ahc->scb_data, 0, sizeof(*ahc->scb_data)); 397263457Sgibbs } 397363457Sgibbs 397465942Sgibbs return (0); 397565942Sgibbs} 397639220Sgibbs 397765942Sgibbsvoid 397865942Sgibbsahc_softc_insert(struct ahc_softc *ahc) 397965942Sgibbs{ 398065942Sgibbs struct ahc_softc *list_ahc; 398139220Sgibbs 3982123579Sgibbs#if AIC_PCI_CONFIG > 0 398365942Sgibbs /* 398465942Sgibbs * Second Function PCI devices need to inherit some 398574094Sgibbs * settings from function 0. 398665942Sgibbs */ 398765942Sgibbs if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI 398874094Sgibbs && (ahc->features & AHC_MULTI_FUNC) != 0) { 398965942Sgibbs TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { 3990123579Sgibbs aic_dev_softc_t list_pci; 3991123579Sgibbs aic_dev_softc_t pci; 399239220Sgibbs 399365942Sgibbs list_pci = list_ahc->dev_softc; 399465942Sgibbs pci = ahc->dev_softc; 3995123579Sgibbs if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) 3996123579Sgibbs && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { 399774094Sgibbs struct ahc_softc *master; 399874094Sgibbs struct ahc_softc *slave; 399974094Sgibbs 4000123579Sgibbs if (aic_get_pci_function(list_pci) == 0) { 400174094Sgibbs master = list_ahc; 400274094Sgibbs slave = ahc; 400374094Sgibbs } else { 400474094Sgibbs master = ahc; 400574094Sgibbs slave = list_ahc; 400674094Sgibbs } 400774094Sgibbs slave->flags &= ~AHC_BIOS_ENABLED; 400874094Sgibbs slave->flags |= 400974094Sgibbs master->flags & AHC_BIOS_ENABLED; 401074094Sgibbs slave->flags &= ~AHC_PRIMARY_CHANNEL; 401174094Sgibbs slave->flags |= 401274094Sgibbs master->flags & AHC_PRIMARY_CHANNEL; 401365942Sgibbs break; 401465942Sgibbs } 401565942Sgibbs } 401639220Sgibbs } 401765942Sgibbs#endif 401839220Sgibbs 401939220Sgibbs /* 402065942Sgibbs * Insertion sort into our list of softcs. 402139220Sgibbs */ 402265942Sgibbs list_ahc = TAILQ_FIRST(&ahc_tailq); 402365942Sgibbs while (list_ahc != NULL 4024114621Sgibbs && ahc_softc_comp(ahc, list_ahc) <= 0) 402565942Sgibbs list_ahc = TAILQ_NEXT(list_ahc, links); 402665942Sgibbs if (list_ahc != NULL) 402765942Sgibbs TAILQ_INSERT_BEFORE(list_ahc, ahc, links); 402865942Sgibbs else 402965942Sgibbs TAILQ_INSERT_TAIL(&ahc_tailq, ahc, links); 403065942Sgibbs ahc->init_level++; 403165942Sgibbs} 403239220Sgibbs 403365942Sgibbsvoid 403465942Sgibbsahc_set_unit(struct ahc_softc *ahc, int unit) 403565942Sgibbs{ 403665942Sgibbs ahc->unit = unit; 403765942Sgibbs} 403839220Sgibbs 403965942Sgibbsvoid 404065942Sgibbsahc_set_name(struct ahc_softc *ahc, char *name) 404165942Sgibbs{ 404265942Sgibbs if (ahc->name != NULL) 404365942Sgibbs free(ahc->name, M_DEVBUF); 404465942Sgibbs ahc->name = name; 404565942Sgibbs} 404639220Sgibbs 404765942Sgibbsvoid 404865942Sgibbsahc_free(struct ahc_softc *ahc) 404965942Sgibbs{ 405070204Sgibbs int i; 405170204Sgibbs 4052123579Sgibbs ahc_terminate_recovery_thread(ahc); 405365942Sgibbs switch (ahc->init_level) { 405470204Sgibbs default: 405570204Sgibbs case 5: 405665942Sgibbs ahc_shutdown(ahc); 405765942Sgibbs /* FALLTHROUGH */ 405870204Sgibbs case 4: 4059123579Sgibbs aic_dmamap_unload(ahc, ahc->shared_data_dmat, 406065942Sgibbs ahc->shared_data_dmamap); 406165942Sgibbs /* FALLTHROUGH */ 406270204Sgibbs case 3: 4063123579Sgibbs aic_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, 406465942Sgibbs ahc->shared_data_dmamap); 4065123579Sgibbs aic_dmamap_destroy(ahc, ahc->shared_data_dmat, 406665942Sgibbs ahc->shared_data_dmamap); 406765942Sgibbs /* FALLTHROUGH */ 406870204Sgibbs case 2: 4069123579Sgibbs aic_dma_tag_destroy(ahc, ahc->shared_data_dmat); 407065942Sgibbs case 1: 407165942Sgibbs#ifndef __linux__ 4072123579Sgibbs aic_dma_tag_destroy(ahc, ahc->buffer_dmat); 407365942Sgibbs#endif 407465942Sgibbs break; 407572325Sgibbs case 0: 407672325Sgibbs break; 407765942Sgibbs } 407839220Sgibbs 407972325Sgibbs#ifndef __linux__ 4080123579Sgibbs aic_dma_tag_destroy(ahc, ahc->parent_dmat); 408172325Sgibbs#endif 408265942Sgibbs ahc_platform_free(ahc); 4083114621Sgibbs ahc_fini_scbdata(ahc); 408470204Sgibbs for (i = 0; i < AHC_NUM_TARGETS; i++) { 408574972Sgibbs struct ahc_tmode_tstate *tstate; 408670204Sgibbs 408770204Sgibbs tstate = ahc->enabled_targets[i]; 408870204Sgibbs if (tstate != NULL) { 4089115337Sgibbs#ifdef AHC_TARGET_MODE 409070204Sgibbs int j; 409170204Sgibbs 409270204Sgibbs for (j = 0; j < AHC_NUM_LUNS; j++) { 409374972Sgibbs struct ahc_tmode_lstate *lstate; 409470204Sgibbs 409570204Sgibbs lstate = tstate->enabled_luns[j]; 409670204Sgibbs if (lstate != NULL) { 409770204Sgibbs xpt_free_path(lstate->path); 409870204Sgibbs free(lstate, M_DEVBUF); 409970204Sgibbs } 410070204Sgibbs } 410170204Sgibbs#endif 410270204Sgibbs free(tstate, M_DEVBUF); 410370204Sgibbs } 410439220Sgibbs } 4105115337Sgibbs#ifdef AHC_TARGET_MODE 410670204Sgibbs if (ahc->black_hole != NULL) { 410770204Sgibbs xpt_free_path(ahc->black_hole->path); 410870204Sgibbs free(ahc->black_hole, M_DEVBUF); 410970204Sgibbs } 411065942Sgibbs#endif 411165942Sgibbs if (ahc->name != NULL) 411265942Sgibbs free(ahc->name, M_DEVBUF); 4113102670Sgibbs if (ahc->seep_config != NULL) 4114102670Sgibbs free(ahc->seep_config, M_DEVBUF); 411570204Sgibbs#ifndef __FreeBSD__ 411665942Sgibbs free(ahc, M_DEVBUF); 411770204Sgibbs#endif 411865942Sgibbs return; 411965942Sgibbs} 412039220Sgibbs 412165942Sgibbsvoid 412265942Sgibbsahc_shutdown(void *arg) 412365942Sgibbs{ 412465942Sgibbs struct ahc_softc *ahc; 412565942Sgibbs int i; 412665942Sgibbs 412765942Sgibbs ahc = (struct ahc_softc *)arg; 412865942Sgibbs 412965942Sgibbs /* This will reset most registers to 0, but not all */ 4130115917Sgibbs ahc_reset(ahc, /*reinit*/FALSE); 413165942Sgibbs ahc_outb(ahc, SCSISEQ, 0); 413265942Sgibbs ahc_outb(ahc, SXFRCTL0, 0); 413365942Sgibbs ahc_outb(ahc, DSPCISTATUS, 0); 413465942Sgibbs 413595378Sgibbs for (i = TARG_SCSIRATE; i < SCSICONF; i++) 413665942Sgibbs ahc_outb(ahc, i, 0); 413765942Sgibbs} 413865942Sgibbs 413965942Sgibbs/* 414065942Sgibbs * Reset the controller and record some information about it 4141115917Sgibbs * that is only available just after a reset. If "reinit" is 4142115917Sgibbs * non-zero, this reset occured after initial configuration 4143115917Sgibbs * and the caller requests that the chip be fully reinitialized 4144115917Sgibbs * to a runable state. Chip interrupts are *not* enabled after 4145115917Sgibbs * a reinitialization. The caller must enable interrupts via 4146115917Sgibbs * ahc_intr_enable(). 414765942Sgibbs */ 414865942Sgibbsint 4149115917Sgibbsahc_reset(struct ahc_softc *ahc, int reinit) 415065942Sgibbs{ 415165942Sgibbs u_int sblkctl; 415265942Sgibbs u_int sxfrctl1_a, sxfrctl1_b; 4153114621Sgibbs int error; 415465942Sgibbs int wait; 415565942Sgibbs 415665942Sgibbs /* 415765942Sgibbs * Preserve the value of the SXFRCTL1 register for all channels. 415865942Sgibbs * It contains settings that affect termination and we don't want 415965942Sgibbs * to disturb the integrity of the bus. 416065942Sgibbs */ 416174094Sgibbs ahc_pause(ahc); 416265942Sgibbs sxfrctl1_b = 0; 416365942Sgibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { 416465942Sgibbs u_int sblkctl; 416565942Sgibbs 416645965Sgibbs /* 416765942Sgibbs * Save channel B's settings in case this chip 416865942Sgibbs * is setup for TWIN channel operation. 416945965Sgibbs */ 417065942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 417165942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); 417265942Sgibbs sxfrctl1_b = ahc_inb(ahc, SXFRCTL1); 417365942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); 417439220Sgibbs } 417565942Sgibbs sxfrctl1_a = ahc_inb(ahc, SXFRCTL1); 417665942Sgibbs 417765942Sgibbs ahc_outb(ahc, HCNTRL, CHIPRST | ahc->pause); 417865942Sgibbs 417965942Sgibbs /* 418095378Sgibbs * Ensure that the reset has finished. We delay 1000us 418195378Sgibbs * prior to reading the register to make sure the chip 418295378Sgibbs * has sufficiently completed its reset to handle register 418395378Sgibbs * accesses. 418465942Sgibbs */ 418565942Sgibbs wait = 1000; 418665942Sgibbs do { 4187123579Sgibbs aic_delay(1000); 418865942Sgibbs } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK)); 418965942Sgibbs 419065942Sgibbs if (wait == 0) { 419165942Sgibbs printf("%s: WARNING - Failed chip reset! " 419265942Sgibbs "Trying to initialize anyway.\n", ahc_name(ahc)); 419365942Sgibbs } 419470204Sgibbs ahc_outb(ahc, HCNTRL, ahc->pause); 419565942Sgibbs 419665942Sgibbs /* Determine channel configuration */ 419765942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL) & (SELBUSB|SELWIDE); 419865942Sgibbs /* No Twin Channel PCI cards */ 419965942Sgibbs if ((ahc->chip & AHC_PCI) != 0) 420065942Sgibbs sblkctl &= ~SELBUSB; 420165942Sgibbs switch (sblkctl) { 420265942Sgibbs case 0: 420365942Sgibbs /* Single Narrow Channel */ 420465942Sgibbs break; 420565942Sgibbs case 2: 420665942Sgibbs /* Wide Channel */ 420765942Sgibbs ahc->features |= AHC_WIDE; 420865942Sgibbs break; 420965942Sgibbs case 8: 421065942Sgibbs /* Twin Channel */ 421165942Sgibbs ahc->features |= AHC_TWIN; 421265942Sgibbs break; 421365942Sgibbs default: 421465942Sgibbs printf(" Unsupported adapter type. Ignoring\n"); 421565942Sgibbs return(-1); 421665942Sgibbs } 421765942Sgibbs 421865942Sgibbs /* 421965942Sgibbs * Reload sxfrctl1. 422065942Sgibbs * 422165942Sgibbs * We must always initialize STPWEN to 1 before we 422265942Sgibbs * restore the saved values. STPWEN is initialized 422365942Sgibbs * to a tri-state condition which can only be cleared 422465942Sgibbs * by turning it on. 422565942Sgibbs */ 422665942Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 422765942Sgibbs u_int sblkctl; 422865942Sgibbs 422965942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 423065942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); 423165942Sgibbs ahc_outb(ahc, SXFRCTL1, sxfrctl1_b); 423265942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); 423365942Sgibbs } 423465942Sgibbs ahc_outb(ahc, SXFRCTL1, sxfrctl1_a); 423565942Sgibbs 4236114621Sgibbs error = 0; 4237115917Sgibbs if (reinit != 0) 4238114621Sgibbs /* 4239114621Sgibbs * If a recovery action has forced a chip reset, 4240114621Sgibbs * re-initialize the chip to our liking. 4241114621Sgibbs */ 4242114621Sgibbs error = ahc->bus_chip_init(ahc); 424365942Sgibbs#ifdef AHC_DUMP_SEQ 4244114621Sgibbs else 424565942Sgibbs ahc_dumpseq(ahc); 424665942Sgibbs#endif 424765942Sgibbs 4248114621Sgibbs return (error); 424939220Sgibbs} 425039220Sgibbs 425139220Sgibbs/* 425239220Sgibbs * Determine the number of SCBs available on the controller 425339220Sgibbs */ 425439220Sgibbsint 425539220Sgibbsahc_probe_scbs(struct ahc_softc *ahc) { 425639220Sgibbs int i; 425739220Sgibbs 425839220Sgibbs for (i = 0; i < AHC_SCB_MAX; i++) { 425970204Sgibbs 426039220Sgibbs ahc_outb(ahc, SCBPTR, i); 426165942Sgibbs ahc_outb(ahc, SCB_BASE, i); 426265942Sgibbs if (ahc_inb(ahc, SCB_BASE) != i) 426339220Sgibbs break; 426439220Sgibbs ahc_outb(ahc, SCBPTR, 0); 426565942Sgibbs if (ahc_inb(ahc, SCB_BASE) != 0) 426639220Sgibbs break; 426739220Sgibbs } 426839220Sgibbs return (i); 426939220Sgibbs} 427039220Sgibbs 427165942Sgibbsstatic void 427265942Sgibbsahc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 427365942Sgibbs{ 427465942Sgibbs bus_addr_t *baddr; 427565942Sgibbs 427665942Sgibbs baddr = (bus_addr_t *)arg; 427765942Sgibbs *baddr = segs->ds_addr; 427865942Sgibbs} 427965942Sgibbs 428070204Sgibbsstatic void 428170204Sgibbsahc_build_free_scb_list(struct ahc_softc *ahc) 428270204Sgibbs{ 4283102670Sgibbs int scbsize; 428470204Sgibbs int i; 428570204Sgibbs 4286102670Sgibbs scbsize = 32; 4287102670Sgibbs if ((ahc->flags & AHC_LSCBS_ENABLED) != 0) 4288102670Sgibbs scbsize = 64; 4289102670Sgibbs 429070204Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 4291102670Sgibbs int j; 4292102670Sgibbs 429370204Sgibbs ahc_outb(ahc, SCBPTR, i); 429470204Sgibbs 4295102670Sgibbs /* 4296102670Sgibbs * Touch all SCB bytes to avoid parity errors 4297102670Sgibbs * should one of our debugging routines read 4298102670Sgibbs * an otherwise uninitiatlized byte. 4299102670Sgibbs */ 4300102670Sgibbs for (j = 0; j < scbsize; j++) 4301102670Sgibbs ahc_outb(ahc, SCB_BASE+j, 0xFF); 4302102670Sgibbs 430370204Sgibbs /* Clear the control byte. */ 430470204Sgibbs ahc_outb(ahc, SCB_CONTROL, 0); 430570204Sgibbs 430670204Sgibbs /* Set the next pointer */ 430770204Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) 430870204Sgibbs ahc_outb(ahc, SCB_NEXT, i+1); 430970204Sgibbs else 431070204Sgibbs ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL); 431170204Sgibbs 4312102670Sgibbs /* Make the tag number, SCSIID, and lun invalid */ 431370204Sgibbs ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL); 4314102670Sgibbs ahc_outb(ahc, SCB_SCSIID, 0xFF); 4315102670Sgibbs ahc_outb(ahc, SCB_LUN, 0xFF); 431670204Sgibbs } 431770204Sgibbs 4318114621Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 4319114621Sgibbs /* SCB 0 heads the free list. */ 4320114621Sgibbs ahc_outb(ahc, FREE_SCBH, 0); 4321114621Sgibbs } else { 4322114621Sgibbs /* No free list. */ 4323114621Sgibbs ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL); 4324114621Sgibbs } 4325114621Sgibbs 432670204Sgibbs /* Make sure that the last SCB terminates the free list */ 432770204Sgibbs ahc_outb(ahc, SCBPTR, i-1); 432870204Sgibbs ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL); 432970204Sgibbs} 433070204Sgibbs 433165942Sgibbsstatic int 433265942Sgibbsahc_init_scbdata(struct ahc_softc *ahc) 433365942Sgibbs{ 433465942Sgibbs struct scb_data *scb_data; 433565942Sgibbs 433665942Sgibbs scb_data = ahc->scb_data; 433765942Sgibbs SLIST_INIT(&scb_data->free_scbs); 433865942Sgibbs SLIST_INIT(&scb_data->sg_maps); 433965942Sgibbs 434065942Sgibbs /* Allocate SCB resources */ 434165942Sgibbs scb_data->scbarray = 434295378Sgibbs (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, 434365942Sgibbs M_DEVBUF, M_NOWAIT); 434465942Sgibbs if (scb_data->scbarray == NULL) 434565942Sgibbs return (ENOMEM); 434695378Sgibbs memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC); 434765942Sgibbs 434865942Sgibbs /* Determine the number of hardware SCBs and initialize them */ 434965942Sgibbs 435065942Sgibbs scb_data->maxhscbs = ahc_probe_scbs(ahc); 435170204Sgibbs if (ahc->scb_data->maxhscbs == 0) { 435270204Sgibbs printf("%s: No SCB space found\n", ahc_name(ahc)); 435370204Sgibbs return (ENXIO); 435465942Sgibbs } 435565942Sgibbs 435665942Sgibbs /* 435765942Sgibbs * Create our DMA tags. These tags define the kinds of device 435865942Sgibbs * accessible memory allocations and memory mappings we will 435965942Sgibbs * need to perform during normal operation. 436065942Sgibbs * 436165942Sgibbs * Unless we need to further restrict the allocation, we rely 436265942Sgibbs * on the restrictions of the parent dmat, hence the common 436365942Sgibbs * use of MAXADDR and MAXSIZE. 436465942Sgibbs */ 436565942Sgibbs 436665942Sgibbs /* DMA tag for our hardware scb structures */ 4367123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 436879874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 436979874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 437065942Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 437165942Sgibbs /*filter*/NULL, /*filterarg*/NULL, 437295378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), 437365942Sgibbs /*nsegments*/1, 437465942Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 437565942Sgibbs /*flags*/0, &scb_data->hscb_dmat) != 0) { 437665942Sgibbs goto error_exit; 437765942Sgibbs } 437865942Sgibbs 437965942Sgibbs scb_data->init_level++; 438065942Sgibbs 438179874Sgibbs /* Allocation for our hscbs */ 4382123579Sgibbs if (aic_dmamem_alloc(ahc, scb_data->hscb_dmat, 438365942Sgibbs (void **)&scb_data->hscbs, 4384219577Smarius BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 4385219577Smarius &scb_data->hscb_dmamap) != 0) { 438665942Sgibbs goto error_exit; 438765942Sgibbs } 438865942Sgibbs 438965942Sgibbs scb_data->init_level++; 439065942Sgibbs 439165942Sgibbs /* And permanently map them */ 4392123579Sgibbs aic_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, 439365942Sgibbs scb_data->hscbs, 439495378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), 439565942Sgibbs ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0); 439665942Sgibbs 439765942Sgibbs scb_data->init_level++; 439865942Sgibbs 439965942Sgibbs /* DMA tag for our sense buffers */ 4400123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 440179874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 440279874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 440365942Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 440465942Sgibbs /*filter*/NULL, /*filterarg*/NULL, 440595378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), 440665942Sgibbs /*nsegments*/1, 440765942Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 440865942Sgibbs /*flags*/0, &scb_data->sense_dmat) != 0) { 440965942Sgibbs goto error_exit; 441065942Sgibbs } 441165942Sgibbs 441265942Sgibbs scb_data->init_level++; 441365942Sgibbs 441465942Sgibbs /* Allocate them */ 4415123579Sgibbs if (aic_dmamem_alloc(ahc, scb_data->sense_dmat, 441665942Sgibbs (void **)&scb_data->sense, 441765942Sgibbs BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) { 441865942Sgibbs goto error_exit; 441965942Sgibbs } 442065942Sgibbs 442165942Sgibbs scb_data->init_level++; 442265942Sgibbs 442365942Sgibbs /* And permanently map them */ 4424123579Sgibbs aic_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, 442565942Sgibbs scb_data->sense, 442695378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), 442765942Sgibbs ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0); 442865942Sgibbs 442965942Sgibbs scb_data->init_level++; 443065942Sgibbs 443165942Sgibbs /* DMA tag for our S/G structures. We allocate in page sized chunks */ 4432123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, 443379874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 443479874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 443565942Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 443665942Sgibbs /*filter*/NULL, /*filterarg*/NULL, 443765942Sgibbs PAGE_SIZE, /*nsegments*/1, 443865942Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 443965942Sgibbs /*flags*/0, &scb_data->sg_dmat) != 0) { 444065942Sgibbs goto error_exit; 444165942Sgibbs } 444265942Sgibbs 444365942Sgibbs scb_data->init_level++; 444465942Sgibbs 444565942Sgibbs /* Perform initial CCB allocation */ 444695378Sgibbs memset(scb_data->hscbs, 0, 444795378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb)); 4448168873Sscottl while (ahc_alloc_scbs(ahc) != 0) 4449168873Sscottl ; 445065942Sgibbs 445165942Sgibbs if (scb_data->numscbs == 0) { 445265942Sgibbs printf("%s: ahc_init_scbdata - " 445365942Sgibbs "Unable to allocate initial scbs\n", 445465942Sgibbs ahc_name(ahc)); 445565942Sgibbs goto error_exit; 445665942Sgibbs } 445765942Sgibbs 445865942Sgibbs /* 4459114621Sgibbs * Reserve the next queued SCB. 446066647Sgibbs */ 446166647Sgibbs ahc->next_queued_scb = ahc_get_scb(ahc); 446266647Sgibbs 446366647Sgibbs /* 446465942Sgibbs * Note that we were successfull 446565942Sgibbs */ 446665942Sgibbs return (0); 446765942Sgibbs 446865942Sgibbserror_exit: 446965942Sgibbs 447065942Sgibbs return (ENOMEM); 447165942Sgibbs} 447265942Sgibbs 447365942Sgibbsstatic void 447465942Sgibbsahc_fini_scbdata(struct ahc_softc *ahc) 447565942Sgibbs{ 447665942Sgibbs struct scb_data *scb_data; 447765942Sgibbs 447865942Sgibbs scb_data = ahc->scb_data; 447968660Sgibbs if (scb_data == NULL) 448068660Sgibbs return; 448165942Sgibbs 448265942Sgibbs switch (scb_data->init_level) { 448365942Sgibbs default: 448465942Sgibbs case 7: 448565942Sgibbs { 448665942Sgibbs struct sg_map_node *sg_map; 448765942Sgibbs 448865942Sgibbs while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) { 448965942Sgibbs SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); 4490123579Sgibbs aic_dmamap_unload(ahc, scb_data->sg_dmat, 449165942Sgibbs sg_map->sg_dmamap); 4492123579Sgibbs aic_dmamem_free(ahc, scb_data->sg_dmat, 449365942Sgibbs sg_map->sg_vaddr, 449465942Sgibbs sg_map->sg_dmamap); 449565942Sgibbs free(sg_map, M_DEVBUF); 449665942Sgibbs } 4497123579Sgibbs aic_dma_tag_destroy(ahc, scb_data->sg_dmat); 449865942Sgibbs } 449965942Sgibbs case 6: 4500123579Sgibbs aic_dmamap_unload(ahc, scb_data->sense_dmat, 450165942Sgibbs scb_data->sense_dmamap); 450265942Sgibbs case 5: 4503123579Sgibbs aic_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, 450465942Sgibbs scb_data->sense_dmamap); 4505123579Sgibbs aic_dmamap_destroy(ahc, scb_data->sense_dmat, 450665942Sgibbs scb_data->sense_dmamap); 450765942Sgibbs case 4: 4508123579Sgibbs aic_dma_tag_destroy(ahc, scb_data->sense_dmat); 450965942Sgibbs case 3: 4510123579Sgibbs aic_dmamap_unload(ahc, scb_data->hscb_dmat, 451165942Sgibbs scb_data->hscb_dmamap); 451265942Sgibbs case 2: 4513123579Sgibbs aic_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, 451465942Sgibbs scb_data->hscb_dmamap); 4515123579Sgibbs aic_dmamap_destroy(ahc, scb_data->hscb_dmat, 451665942Sgibbs scb_data->hscb_dmamap); 451765942Sgibbs case 1: 4518123579Sgibbs aic_dma_tag_destroy(ahc, scb_data->hscb_dmat); 451965942Sgibbs break; 452070204Sgibbs case 0: 452170204Sgibbs break; 452265942Sgibbs } 452365942Sgibbs if (scb_data->scbarray != NULL) 452465942Sgibbs free(scb_data->scbarray, M_DEVBUF); 452565942Sgibbs} 452665942Sgibbs 4527168873Sscottlint 452865942Sgibbsahc_alloc_scbs(struct ahc_softc *ahc) 452965942Sgibbs{ 453065942Sgibbs struct scb_data *scb_data; 453165942Sgibbs struct scb *next_scb; 453265942Sgibbs struct sg_map_node *sg_map; 453365942Sgibbs bus_addr_t physaddr; 453465942Sgibbs struct ahc_dma_seg *segs; 453565942Sgibbs int newcount; 453665942Sgibbs int i; 453765942Sgibbs 453865942Sgibbs scb_data = ahc->scb_data; 453995378Sgibbs if (scb_data->numscbs >= AHC_SCB_MAX_ALLOC) 454065942Sgibbs /* Can't allocate any more */ 4541168873Sscottl return (0); 454265942Sgibbs 454365942Sgibbs next_scb = &scb_data->scbarray[scb_data->numscbs]; 454465942Sgibbs 454565942Sgibbs sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 454665942Sgibbs 454765942Sgibbs if (sg_map == NULL) 4548168873Sscottl return (0); 454965942Sgibbs 455065942Sgibbs /* Allocate S/G space for the next batch of SCBS */ 4551123579Sgibbs if (aic_dmamem_alloc(ahc, scb_data->sg_dmat, 455265942Sgibbs (void **)&sg_map->sg_vaddr, 4553219577Smarius BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 4554219577Smarius &sg_map->sg_dmamap) != 0) { 455565942Sgibbs free(sg_map, M_DEVBUF); 4556168873Sscottl return (0); 455765942Sgibbs } 455865942Sgibbs 455965942Sgibbs SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); 456065942Sgibbs 4561123579Sgibbs aic_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, 456265942Sgibbs sg_map->sg_vaddr, PAGE_SIZE, ahc_dmamap_cb, 456365942Sgibbs &sg_map->sg_physaddr, /*flags*/0); 456465942Sgibbs 456565942Sgibbs segs = sg_map->sg_vaddr; 456665942Sgibbs physaddr = sg_map->sg_physaddr; 456765942Sgibbs 456865942Sgibbs newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg))); 456995378Sgibbs newcount = MIN(newcount, (AHC_SCB_MAX_ALLOC - scb_data->numscbs)); 457095378Sgibbs for (i = 0; i < newcount; i++) { 457165942Sgibbs struct scb_platform_data *pdata; 457265942Sgibbs#ifndef __linux__ 457365942Sgibbs int error; 457465942Sgibbs#endif 457565942Sgibbs pdata = (struct scb_platform_data *)malloc(sizeof(*pdata), 457665942Sgibbs M_DEVBUF, M_NOWAIT); 457765942Sgibbs if (pdata == NULL) 457865942Sgibbs break; 457965942Sgibbs next_scb->platform_data = pdata; 458079874Sgibbs next_scb->sg_map = sg_map; 458165942Sgibbs next_scb->sg_list = segs; 458265942Sgibbs /* 458365942Sgibbs * The sequencer always starts with the second entry. 458465942Sgibbs * The first entry is embedded in the scb. 458565942Sgibbs */ 458665942Sgibbs next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg); 458766986Sgibbs next_scb->ahc_softc = ahc; 4588123579Sgibbs next_scb->flags = SCB_FLAG_NONE; 458965942Sgibbs#ifndef __linux__ 4590123579Sgibbs error = aic_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, 459165942Sgibbs &next_scb->dmamap); 459265942Sgibbs if (error != 0) 459365942Sgibbs break; 459465942Sgibbs#endif 459565942Sgibbs next_scb->hscb = &scb_data->hscbs[scb_data->numscbs]; 459665942Sgibbs next_scb->hscb->tag = ahc->scb_data->numscbs; 4597168807Sscottl aic_timer_init(&next_scb->io_timer); 459865942Sgibbs SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, 459965942Sgibbs next_scb, links.sle); 460065942Sgibbs segs += AHC_NSEG; 460165942Sgibbs physaddr += (AHC_NSEG * sizeof(struct ahc_dma_seg)); 460265942Sgibbs next_scb++; 460365942Sgibbs ahc->scb_data->numscbs++; 460465942Sgibbs } 4605168873Sscottl return (i); 460665942Sgibbs} 460765942Sgibbs 460865942Sgibbsvoid 460965942Sgibbsahc_controller_info(struct ahc_softc *ahc, char *buf) 461065942Sgibbs{ 461165942Sgibbs int len; 461265942Sgibbs 461365942Sgibbs len = sprintf(buf, "%s: ", ahc_chip_names[ahc->chip & AHC_CHIPID_MASK]); 461465942Sgibbs buf += len; 461565942Sgibbs if ((ahc->features & AHC_TWIN) != 0) 461665942Sgibbs len = sprintf(buf, "Twin Channel, A SCSI Id=%d, " 461765942Sgibbs "B SCSI Id=%d, primary %c, ", 461865942Sgibbs ahc->our_id, ahc->our_id_b, 461974094Sgibbs (ahc->flags & AHC_PRIMARY_CHANNEL) + 'A'); 462065942Sgibbs else { 462176634Sgibbs const char *speed; 462265942Sgibbs const char *type; 462365942Sgibbs 462476634Sgibbs speed = ""; 462576634Sgibbs if ((ahc->features & AHC_ULTRA) != 0) { 462676634Sgibbs speed = "Ultra "; 462776634Sgibbs } else if ((ahc->features & AHC_DT) != 0) { 462876634Sgibbs speed = "Ultra160 "; 462976634Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 463076634Sgibbs speed = "Ultra2 "; 463176634Sgibbs } 463265942Sgibbs if ((ahc->features & AHC_WIDE) != 0) { 463365942Sgibbs type = "Wide"; 463465942Sgibbs } else { 463565942Sgibbs type = "Single"; 463665942Sgibbs } 463776634Sgibbs len = sprintf(buf, "%s%s Channel %c, SCSI Id=%d, ", 463876634Sgibbs speed, type, ahc->channel, ahc->our_id); 463965942Sgibbs } 464065942Sgibbs buf += len; 464165942Sgibbs 464268087Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) 464366269Sgibbs sprintf(buf, "%d/%d SCBs", 464495378Sgibbs ahc->scb_data->maxhscbs, AHC_MAX_QUEUE); 464565942Sgibbs else 464666269Sgibbs sprintf(buf, "%d SCBs", ahc->scb_data->maxhscbs); 464765942Sgibbs} 464865942Sgibbs 4649114621Sgibbsint 4650114621Sgibbsahc_chip_init(struct ahc_softc *ahc) 4651114621Sgibbs{ 4652114621Sgibbs int term; 4653114621Sgibbs int error; 4654114621Sgibbs u_int i; 4655114621Sgibbs u_int scsi_conf; 4656114621Sgibbs u_int scsiseq_template; 4657114621Sgibbs uint32_t physaddr; 4658114621Sgibbs 4659114621Sgibbs ahc_outb(ahc, SEQ_FLAGS, 0); 4660114621Sgibbs ahc_outb(ahc, SEQ_FLAGS2, 0); 4661114621Sgibbs 4662114621Sgibbs /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/ 4663114621Sgibbs if (ahc->features & AHC_TWIN) { 4664114621Sgibbs 4665114621Sgibbs /* 4666114621Sgibbs * Setup Channel B first. 4667114621Sgibbs */ 4668114621Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB); 4669114621Sgibbs term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0; 4670114621Sgibbs ahc_outb(ahc, SCSIID, ahc->our_id_b); 4671114621Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF + 1); 4672114621Sgibbs ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) 4673114621Sgibbs |term|ahc->seltime_b|ENSTIMER|ACTNEGEN); 4674114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 4675114621Sgibbs ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR); 4676114621Sgibbs ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); 4677114621Sgibbs ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN); 4678114621Sgibbs 4679114621Sgibbs /* Select Channel A */ 4680114621Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB); 4681114621Sgibbs } 4682114621Sgibbs term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0; 4683114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 4684114621Sgibbs ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id); 4685114621Sgibbs else 4686114621Sgibbs ahc_outb(ahc, SCSIID, ahc->our_id); 4687114621Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF); 4688114621Sgibbs ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) 4689114621Sgibbs |term|ahc->seltime 4690114621Sgibbs |ENSTIMER|ACTNEGEN); 4691114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 4692114621Sgibbs ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR); 4693114621Sgibbs ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); 4694114621Sgibbs ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN); 4695114621Sgibbs 4696114621Sgibbs /* There are no untagged SCBs active yet. */ 4697114621Sgibbs for (i = 0; i < 16; i++) { 4698114621Sgibbs ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, 0)); 4699114621Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 4700114621Sgibbs int lun; 4701114621Sgibbs 4702114621Sgibbs /* 4703114621Sgibbs * The SCB based BTT allows an entry per 4704114621Sgibbs * target and lun pair. 4705114621Sgibbs */ 4706114621Sgibbs for (lun = 1; lun < AHC_NUM_LUNS; lun++) 4707114621Sgibbs ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, lun)); 4708114621Sgibbs } 4709114621Sgibbs } 4710114621Sgibbs 4711114621Sgibbs /* All of our queues are empty */ 4712114621Sgibbs for (i = 0; i < 256; i++) 4713114621Sgibbs ahc->qoutfifo[i] = SCB_LIST_NULL; 4714114621Sgibbs ahc_sync_qoutfifo(ahc, BUS_DMASYNC_PREREAD); 4715114621Sgibbs 4716114621Sgibbs for (i = 0; i < 256; i++) 4717114621Sgibbs ahc->qinfifo[i] = SCB_LIST_NULL; 4718114621Sgibbs 4719114621Sgibbs if ((ahc->features & AHC_MULTI_TID) != 0) { 4720114621Sgibbs ahc_outb(ahc, TARGID, 0); 4721114621Sgibbs ahc_outb(ahc, TARGID + 1, 0); 4722114621Sgibbs } 4723114621Sgibbs 4724114621Sgibbs /* 4725114621Sgibbs * Tell the sequencer where it can find our arrays in memory. 4726114621Sgibbs */ 4727114621Sgibbs physaddr = ahc->scb_data->hscb_busaddr; 4728114621Sgibbs ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF); 4729114621Sgibbs ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF); 4730114621Sgibbs ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF); 4731114621Sgibbs ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF); 4732114621Sgibbs 4733114621Sgibbs physaddr = ahc->shared_data_busaddr; 4734114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR, physaddr & 0xFF); 4735114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR + 1, (physaddr >> 8) & 0xFF); 4736114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR + 2, (physaddr >> 16) & 0xFF); 4737114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR + 3, (physaddr >> 24) & 0xFF); 4738114621Sgibbs 4739114621Sgibbs /* 4740114621Sgibbs * Initialize the group code to command length table. 4741114621Sgibbs * This overrides the values in TARG_SCSIRATE, so only 4742114621Sgibbs * setup the table after we have processed that information. 4743114621Sgibbs */ 4744114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE, 5); 4745114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 1, 9); 4746114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 2, 9); 4747114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 3, 0); 4748114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 4, 15); 4749114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 5, 11); 4750114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 6, 0); 4751114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 7, 0); 4752114621Sgibbs 4753114621Sgibbs if ((ahc->features & AHC_HS_MAILBOX) != 0) 4754114621Sgibbs ahc_outb(ahc, HS_MAILBOX, 0); 4755114621Sgibbs 4756114621Sgibbs /* Tell the sequencer of our initial queue positions */ 4757114621Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) { 4758114621Sgibbs ahc->tqinfifonext = 1; 4759114621Sgibbs ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1); 4760114621Sgibbs ahc_outb(ahc, TQINPOS, ahc->tqinfifonext); 4761114621Sgibbs } 4762114621Sgibbs ahc->qinfifonext = 0; 4763114621Sgibbs ahc->qoutfifonext = 0; 4764114621Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 4765114621Sgibbs ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256); 4766114621Sgibbs ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); 4767114621Sgibbs ahc_outb(ahc, SNSCB_QOFF, ahc->qinfifonext); 4768114621Sgibbs ahc_outb(ahc, SDSCB_QOFF, 0); 4769114621Sgibbs } else { 4770114621Sgibbs ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); 4771114621Sgibbs ahc_outb(ahc, QINPOS, ahc->qinfifonext); 4772114621Sgibbs ahc_outb(ahc, QOUTPOS, ahc->qoutfifonext); 4773114621Sgibbs } 4774114621Sgibbs 4775114621Sgibbs /* We don't have any waiting selections */ 4776114621Sgibbs ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL); 4777114621Sgibbs 4778114621Sgibbs /* Our disconnection list is empty too */ 4779114621Sgibbs ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL); 4780114621Sgibbs 4781114621Sgibbs /* Message out buffer starts empty */ 4782114621Sgibbs ahc_outb(ahc, MSG_OUT, MSG_NOOP); 4783114621Sgibbs 4784114621Sgibbs /* 4785114621Sgibbs * Setup the allowed SCSI Sequences based on operational mode. 4786114621Sgibbs * If we are a target, we'll enalbe select in operations once 4787114621Sgibbs * we've had a lun enabled. 4788114621Sgibbs */ 4789114621Sgibbs scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP; 4790114621Sgibbs if ((ahc->flags & AHC_INITIATORROLE) != 0) 4791114621Sgibbs scsiseq_template |= ENRSELI; 4792114621Sgibbs ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template); 4793114621Sgibbs 4794114621Sgibbs /* Initialize our list of free SCBs. */ 4795114621Sgibbs ahc_build_free_scb_list(ahc); 4796114621Sgibbs 4797114621Sgibbs /* 4798114621Sgibbs * Tell the sequencer which SCB will be the next one it receives. 4799114621Sgibbs */ 4800114621Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag); 4801114621Sgibbs 4802114621Sgibbs /* 4803114621Sgibbs * Load the Sequencer program and Enable the adapter 4804114621Sgibbs * in "fast" mode. 4805114621Sgibbs */ 4806114621Sgibbs if (bootverbose) 4807114621Sgibbs printf("%s: Downloading Sequencer Program...", 4808114621Sgibbs ahc_name(ahc)); 4809114621Sgibbs 4810114621Sgibbs error = ahc_loadseq(ahc); 4811114621Sgibbs if (error != 0) 4812114621Sgibbs return (error); 4813114621Sgibbs 4814114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 4815114621Sgibbs int wait; 4816114621Sgibbs 4817114621Sgibbs /* 4818114621Sgibbs * Wait for up to 500ms for our transceivers 4819114621Sgibbs * to settle. If the adapter does not have 4820114621Sgibbs * a cable attached, the transceivers may 4821114621Sgibbs * never settle, so don't complain if we 4822114621Sgibbs * fail here. 4823114621Sgibbs */ 4824114621Sgibbs for (wait = 5000; 4825114621Sgibbs (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; 4826114621Sgibbs wait--) 4827123579Sgibbs aic_delay(100); 4828114621Sgibbs } 4829115917Sgibbs ahc_restart(ahc); 4830114621Sgibbs return (0); 4831114621Sgibbs} 4832114621Sgibbs 483339220Sgibbs/* 483439220Sgibbs * Start the board, ready for normal operation 483539220Sgibbs */ 483639220Sgibbsint 483739220Sgibbsahc_init(struct ahc_softc *ahc) 483839220Sgibbs{ 483965942Sgibbs int max_targ; 4840123579Sgibbs int error; 4841114621Sgibbs u_int i; 484265942Sgibbs u_int scsi_conf; 484365942Sgibbs u_int ultraenb; 484465942Sgibbs u_int discenable; 484565942Sgibbs u_int tagenable; 484665942Sgibbs size_t driver_data_size; 484739220Sgibbs 4848109590Sgibbs#ifdef AHC_DEBUG 4849109590Sgibbs if ((ahc_debug & AHC_DEBUG_SEQUENCER) != 0) 4850109590Sgibbs ahc->flags |= AHC_SEQUENCER_DEBUG; 485168087Sgibbs#endif 485268087Sgibbs 485339220Sgibbs#ifdef AHC_PRINT_SRAM 485439220Sgibbs printf("Scratch Ram:"); 485539220Sgibbs for (i = 0x20; i < 0x5f; i++) { 485639220Sgibbs if (((i % 8) == 0) && (i != 0)) { 485739220Sgibbs printf ("\n "); 485839220Sgibbs } 485939220Sgibbs printf (" 0x%x", ahc_inb(ahc, i)); 486039220Sgibbs } 486139220Sgibbs if ((ahc->features & AHC_MORE_SRAM) != 0) { 486239220Sgibbs for (i = 0x70; i < 0x7f; i++) { 486339220Sgibbs if (((i % 8) == 0) && (i != 0)) { 486439220Sgibbs printf ("\n "); 486539220Sgibbs } 486639220Sgibbs printf (" 0x%x", ahc_inb(ahc, i)); 486739220Sgibbs } 486839220Sgibbs } 486939220Sgibbs printf ("\n"); 487095378Sgibbs /* 487195378Sgibbs * Reading uninitialized scratch ram may 487295378Sgibbs * generate parity errors. 487395378Sgibbs */ 487495378Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 487595378Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 487639220Sgibbs#endif 487765942Sgibbs max_targ = 15; 487839220Sgibbs 487939220Sgibbs /* 488039220Sgibbs * Assume we have a board at this stage and it has been reset. 488139220Sgibbs */ 488257099Sgibbs if ((ahc->flags & AHC_USEDEFAULTS) != 0) 488339220Sgibbs ahc->our_id = ahc->our_id_b = 7; 488439220Sgibbs 488539220Sgibbs /* 488641646Sgibbs * Default to allowing initiator operations. 488741646Sgibbs */ 488868087Sgibbs ahc->flags |= AHC_INITIATORROLE; 488941646Sgibbs 489068087Sgibbs /* 489168087Sgibbs * Only allow target mode features if this unit has them enabled. 489268087Sgibbs */ 489368087Sgibbs if ((AHC_TMODE_ENABLE & (0x1 << ahc->unit)) == 0) 489468087Sgibbs ahc->features &= ~AHC_TARGETMODE; 489539220Sgibbs 489665942Sgibbs#ifndef __linux__ 489745965Sgibbs /* DMA tag for mapping buffers into device visible space. */ 4898123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 489979874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 4900114621Sgibbs /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING 4901114621Sgibbs ? (bus_addr_t)0x7FFFFFFFFFULL 4902114621Sgibbs : BUS_SPACE_MAXADDR_32BIT, 490345965Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 490445965Sgibbs /*filter*/NULL, /*filterarg*/NULL, 4905108479Sscottl /*maxsize*/(AHC_NSEG - 1) * PAGE_SIZE, 4906108479Sscottl /*nsegments*/AHC_NSEG, 490745965Sgibbs /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 490845965Sgibbs /*flags*/BUS_DMA_ALLOCNOW, 490945965Sgibbs &ahc->buffer_dmat) != 0) { 491045965Sgibbs return (ENOMEM); 491145965Sgibbs } 491265942Sgibbs#endif 491345965Sgibbs 491445965Sgibbs ahc->init_level++; 491545965Sgibbs 491644507Sgibbs /* 491745965Sgibbs * DMA tag for our command fifos and other data in system memory 491845965Sgibbs * the card's sequencer must be able to access. For initiator 4919102670Sgibbs * roles, we need to allocate space for the qinfifo and qoutfifo. 492063457Sgibbs * The qinfifo and qoutfifo are composed of 256 1 byte elements. 492165942Sgibbs * When providing for the target mode role, we must additionally 492263457Sgibbs * provide space for the incoming target command fifo and an extra 492363457Sgibbs * byte to deal with a dma bug in some chip versions. 492445965Sgibbs */ 492563457Sgibbs driver_data_size = 2 * 256 * sizeof(uint8_t); 492668087Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) 492757099Sgibbs driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd) 492857099Sgibbs + /*DMA WideOdd Bug Buffer*/1; 4929123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 493079874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 493179874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 493245965Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 493345965Sgibbs /*filter*/NULL, /*filterarg*/NULL, 493445965Sgibbs driver_data_size, 493545965Sgibbs /*nsegments*/1, 493645965Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 493745965Sgibbs /*flags*/0, &ahc->shared_data_dmat) != 0) { 493845965Sgibbs return (ENOMEM); 493945965Sgibbs } 494045965Sgibbs 494145965Sgibbs ahc->init_level++; 494245965Sgibbs 494345965Sgibbs /* Allocation of driver data */ 4944123579Sgibbs if (aic_dmamem_alloc(ahc, ahc->shared_data_dmat, 494563457Sgibbs (void **)&ahc->qoutfifo, 4946219577Smarius BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 4947219577Smarius &ahc->shared_data_dmamap) != 0) { 494845965Sgibbs return (ENOMEM); 494945965Sgibbs } 495045965Sgibbs 495145965Sgibbs ahc->init_level++; 495245965Sgibbs 495365942Sgibbs /* And permanently map it in */ 4954123579Sgibbs aic_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, 495565942Sgibbs ahc->qoutfifo, driver_data_size, ahc_dmamap_cb, 495663457Sgibbs &ahc->shared_data_busaddr, /*flags*/0); 495745965Sgibbs 495868087Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) { 495963457Sgibbs ahc->targetcmds = (struct target_cmd *)ahc->qoutfifo; 496071390Sgibbs ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[AHC_TMODE_CMDS]; 496163457Sgibbs ahc->dma_bug_buf = ahc->shared_data_busaddr 496263457Sgibbs + driver_data_size - 1; 496363457Sgibbs /* All target command blocks start out invalid. */ 496463457Sgibbs for (i = 0; i < AHC_TMODE_CMDS; i++) 496563457Sgibbs ahc->targetcmds[i].cmd_valid = 0; 496679874Sgibbs ahc_sync_tqinfifo(ahc, BUS_DMASYNC_PREREAD); 496763457Sgibbs ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[256]; 496863457Sgibbs } 496963457Sgibbs ahc->qinfifo = &ahc->qoutfifo[256]; 497063457Sgibbs 497145965Sgibbs ahc->init_level++; 497245965Sgibbs 497357099Sgibbs /* Allocate SCB data now that buffer_dmat is initialized */ 497445965Sgibbs if (ahc->scb_data->maxhscbs == 0) 497565942Sgibbs if (ahc_init_scbdata(ahc) != 0) 497645965Sgibbs return (ENOMEM); 497745965Sgibbs 497845965Sgibbs /* 497944507Sgibbs * Allocate a tstate to house information for our 498044507Sgibbs * initiator presence on the bus as well as the user 498144507Sgibbs * data for any target mode initiator. 498244507Sgibbs */ 498344507Sgibbs if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) { 498474972Sgibbs printf("%s: unable to allocate ahc_tmode_tstate. " 498544507Sgibbs "Failing attach\n", ahc_name(ahc)); 498674972Sgibbs return (ENOMEM); 498744507Sgibbs } 498841646Sgibbs 498939220Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 499044507Sgibbs if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) { 499174972Sgibbs printf("%s: unable to allocate ahc_tmode_tstate. " 499244507Sgibbs "Failing attach\n", ahc_name(ahc)); 499374972Sgibbs return (ENOMEM); 499444507Sgibbs } 499539220Sgibbs } 499639220Sgibbs 4997123579Sgibbs /* 4998123579Sgibbs * Fire up a recovery thread for this controller. 4999123579Sgibbs */ 5000123579Sgibbs error = ahc_spawn_recovery_thread(ahc); 5001123579Sgibbs if (error != 0) 5002123579Sgibbs return (error); 5003123579Sgibbs 500495378Sgibbs if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) { 500539220Sgibbs ahc->flags |= AHC_PAGESCBS; 500639220Sgibbs } else { 500739220Sgibbs ahc->flags &= ~AHC_PAGESCBS; 500839220Sgibbs } 500939220Sgibbs 501039220Sgibbs#ifdef AHC_DEBUG 5011102670Sgibbs if (ahc_debug & AHC_SHOW_MISC) { 5012114621Sgibbs printf("%s: hardware scb %u bytes; kernel scb %u bytes; " 5013114621Sgibbs "ahc_dma %u bytes\n", 501439220Sgibbs ahc_name(ahc), 5015114621Sgibbs (u_int)sizeof(struct hardware_scb), 5016114621Sgibbs (u_int)sizeof(struct scb), 5017114621Sgibbs (u_int)sizeof(struct ahc_dma_seg)); 501839220Sgibbs } 501939220Sgibbs#endif /* AHC_DEBUG */ 502039220Sgibbs 5021114621Sgibbs /* 5022114621Sgibbs * Look at the information that board initialization or 5023114621Sgibbs * the board bios has left us. 5024114621Sgibbs */ 502539220Sgibbs if (ahc->features & AHC_TWIN) { 502639220Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF + 1); 502741816Sgibbs if ((scsi_conf & RESET_SCSI) != 0 502868087Sgibbs && (ahc->flags & AHC_INITIATORROLE) != 0) 502941816Sgibbs ahc->flags |= AHC_RESET_BUS_B; 5030114621Sgibbs } 503139220Sgibbs 503239220Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF); 503341816Sgibbs if ((scsi_conf & RESET_SCSI) != 0 503468087Sgibbs && (ahc->flags & AHC_INITIATORROLE) != 0) 503541816Sgibbs ahc->flags |= AHC_RESET_BUS_A; 503639220Sgibbs 503744507Sgibbs ultraenb = 0; 503844507Sgibbs tagenable = ALL_TARGETS_MASK; 503939220Sgibbs 504039220Sgibbs /* Grab the disconnection disable table and invert it for our needs */ 504195378Sgibbs if ((ahc->flags & AHC_USEDEFAULTS) != 0) { 504239220Sgibbs printf("%s: Host Adapter Bios disabled. Using default SCSI " 504339220Sgibbs "device parameters\n", ahc_name(ahc)); 504440125Sgibbs ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B| 504540125Sgibbs AHC_TERM_ENB_A|AHC_TERM_ENB_B; 504644507Sgibbs discenable = ALL_TARGETS_MASK; 504739220Sgibbs if ((ahc->features & AHC_ULTRA) != 0) 504844507Sgibbs ultraenb = ALL_TARGETS_MASK; 504939220Sgibbs } else { 505044507Sgibbs discenable = ~((ahc_inb(ahc, DISC_DSB + 1) << 8) 505144507Sgibbs | ahc_inb(ahc, DISC_DSB)); 505239220Sgibbs if ((ahc->features & (AHC_ULTRA|AHC_ULTRA2)) != 0) 505344507Sgibbs ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8) 505439220Sgibbs | ahc_inb(ahc, ULTRA_ENB); 505539220Sgibbs } 505639220Sgibbs 505739220Sgibbs if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) 505839220Sgibbs max_targ = 7; 505939220Sgibbs 506039220Sgibbs for (i = 0; i <= max_targ; i++) { 506144507Sgibbs struct ahc_initiator_tinfo *tinfo; 506274972Sgibbs struct ahc_tmode_tstate *tstate; 506344507Sgibbs u_int our_id; 506444507Sgibbs u_int target_id; 506544507Sgibbs char channel; 506639220Sgibbs 506744507Sgibbs channel = 'A'; 506844507Sgibbs our_id = ahc->our_id; 506944507Sgibbs target_id = i; 507044507Sgibbs if (i > 7 && (ahc->features & AHC_TWIN) != 0) { 507144507Sgibbs channel = 'B'; 507244507Sgibbs our_id = ahc->our_id_b; 507344507Sgibbs target_id = i % 8; 507444507Sgibbs } 507544507Sgibbs tinfo = ahc_fetch_transinfo(ahc, channel, our_id, 507644507Sgibbs target_id, &tstate); 507739220Sgibbs /* Default to async narrow across the board */ 507865942Sgibbs memset(tinfo, 0, sizeof(*tinfo)); 507939220Sgibbs if (ahc->flags & AHC_USEDEFAULTS) { 508039220Sgibbs if ((ahc->features & AHC_WIDE) != 0) 508144507Sgibbs tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; 508239220Sgibbs 508339220Sgibbs /* 508439220Sgibbs * These will be truncated when we determine the 508539220Sgibbs * connection type we have with the target. 508639220Sgibbs */ 508744507Sgibbs tinfo->user.period = ahc_syncrates->period; 5088114621Sgibbs tinfo->user.offset = MAX_OFFSET; 508939220Sgibbs } else { 509039220Sgibbs u_int scsirate; 509163457Sgibbs uint16_t mask; 509239220Sgibbs 509339220Sgibbs /* Take the settings leftover in scratch RAM. */ 509439220Sgibbs scsirate = ahc_inb(ahc, TARG_SCSIRATE + i); 509539220Sgibbs mask = (0x01 << i); 509639220Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 509739220Sgibbs u_int offset; 509855581Sgibbs u_int maxsync; 509939220Sgibbs 510039220Sgibbs if ((scsirate & SOFS) == 0x0F) { 510139220Sgibbs /* 510239220Sgibbs * Haven't negotiated yet, 510339220Sgibbs * so the format is different. 510439220Sgibbs */ 510539220Sgibbs scsirate = (scsirate & SXFR) >> 4 510644507Sgibbs | (ultraenb & mask) 510755581Sgibbs ? 0x08 : 0x0 510839220Sgibbs | (scsirate & WIDEXFER); 510939220Sgibbs offset = MAX_OFFSET_ULTRA2; 511039220Sgibbs } else 511139220Sgibbs offset = ahc_inb(ahc, TARG_OFFSET + i); 511274094Sgibbs if ((scsirate & ~WIDEXFER) == 0 && offset != 0) 511374094Sgibbs /* Set to the lowest sync rate, 5MHz */ 511474094Sgibbs scsirate |= 0x1c; 511555581Sgibbs maxsync = AHC_SYNCRATE_ULTRA2; 511655581Sgibbs if ((ahc->features & AHC_DT) != 0) 511755581Sgibbs maxsync = AHC_SYNCRATE_DT; 511847414Sgibbs tinfo->user.period = 511955581Sgibbs ahc_find_period(ahc, scsirate, maxsync); 512039220Sgibbs if (offset == 0) 512144507Sgibbs tinfo->user.period = 0; 512239220Sgibbs else 5123114621Sgibbs tinfo->user.offset = MAX_OFFSET; 512463457Sgibbs if ((scsirate & SXFR_ULTRA2) <= 8/*10MHz*/ 512563457Sgibbs && (ahc->features & AHC_DT) != 0) 512663457Sgibbs tinfo->user.ppr_options = 512763457Sgibbs MSG_EXT_PPR_DT_REQ; 512839220Sgibbs } else if ((scsirate & SOFS) != 0) { 512968087Sgibbs if ((scsirate & SXFR) == 0x40 513068087Sgibbs && (ultraenb & mask) != 0) { 513168087Sgibbs /* Treat 10MHz as a non-ultra speed */ 513268087Sgibbs scsirate &= ~SXFR; 513368087Sgibbs ultraenb &= ~mask; 513468087Sgibbs } 513544507Sgibbs tinfo->user.period = 513639220Sgibbs ahc_find_period(ahc, scsirate, 513744507Sgibbs (ultraenb & mask) 513839220Sgibbs ? AHC_SYNCRATE_ULTRA 513939220Sgibbs : AHC_SYNCRATE_FAST); 514046099Sken if (tinfo->user.period != 0) 5141114621Sgibbs tinfo->user.offset = MAX_OFFSET; 514239220Sgibbs } 514374094Sgibbs if (tinfo->user.period == 0) 514474094Sgibbs tinfo->user.offset = 0; 514539220Sgibbs if ((scsirate & WIDEXFER) != 0 514644507Sgibbs && (ahc->features & AHC_WIDE) != 0) 514744507Sgibbs tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; 514863457Sgibbs tinfo->user.protocol_version = 4; 514963457Sgibbs if ((ahc->features & AHC_DT) != 0) 515063457Sgibbs tinfo->user.transport_version = 3; 515163457Sgibbs else 515263457Sgibbs tinfo->user.transport_version = 2; 515363457Sgibbs tinfo->goal.protocol_version = 2; 515463457Sgibbs tinfo->goal.transport_version = 2; 515576634Sgibbs tinfo->curr.protocol_version = 2; 515676634Sgibbs tinfo->curr.transport_version = 2; 515739220Sgibbs } 5158109590Sgibbs tstate->ultraenb = 0; 515939220Sgibbs } 516049933Sgibbs ahc->user_discenable = discenable; 516149933Sgibbs ahc->user_tagenable = tagenable; 516239220Sgibbs 5163114621Sgibbs return (ahc->bus_chip_init(ahc)); 516439220Sgibbs} 516539220Sgibbs 516674972Sgibbsvoid 516774972Sgibbsahc_intr_enable(struct ahc_softc *ahc, int enable) 516874972Sgibbs{ 516974972Sgibbs u_int hcntrl; 517074972Sgibbs 517174972Sgibbs hcntrl = ahc_inb(ahc, HCNTRL); 517274972Sgibbs hcntrl &= ~INTEN; 517374972Sgibbs ahc->pause &= ~INTEN; 517474972Sgibbs ahc->unpause &= ~INTEN; 517574972Sgibbs if (enable) { 517674972Sgibbs hcntrl |= INTEN; 517774972Sgibbs ahc->pause |= INTEN; 517874972Sgibbs ahc->unpause |= INTEN; 517974972Sgibbs } 518074972Sgibbs ahc_outb(ahc, HCNTRL, hcntrl); 518174972Sgibbs} 518274972Sgibbs 518370204Sgibbs/* 518470204Sgibbs * Ensure that the card is paused in a location 518570204Sgibbs * outside of all critical sections and that all 518670204Sgibbs * pending work is completed prior to returning. 518770204Sgibbs * This routine should only be called from outside 518870204Sgibbs * an interrupt context. 518970204Sgibbs */ 519070204Sgibbsvoid 519170204Sgibbsahc_pause_and_flushwork(struct ahc_softc *ahc) 519270204Sgibbs{ 519371390Sgibbs int intstat; 519471390Sgibbs int maxloops; 5195102670Sgibbs int paused; 519671390Sgibbs 519771390Sgibbs maxloops = 1000; 519870204Sgibbs ahc->flags |= AHC_ALL_INTERRUPTS; 5199102670Sgibbs paused = FALSE; 520070204Sgibbs do { 5201123579Sgibbs if (paused) { 5202102670Sgibbs ahc_unpause(ahc); 5203123579Sgibbs /* 5204123579Sgibbs * Give the sequencer some time to service 5205123579Sgibbs * any active selections. 5206123579Sgibbs */ 5207129133Sgibbs aic_delay(500); 5208123579Sgibbs } 520970204Sgibbs ahc_intr(ahc); 521074094Sgibbs ahc_pause(ahc); 5211102670Sgibbs paused = TRUE; 5212102670Sgibbs ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO); 5213114621Sgibbs intstat = ahc_inb(ahc, INTSTAT); 5214129133Sgibbs if ((intstat & INT_PEND) == 0) { 5215129133Sgibbs ahc_clear_critical_section(ahc); 5216129133Sgibbs intstat = ahc_inb(ahc, INTSTAT); 5217129133Sgibbs } 5218102670Sgibbs } while (--maxloops 5219114621Sgibbs && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0) 5220114621Sgibbs && ((intstat & INT_PEND) != 0 5221114621Sgibbs || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)) != 0)); 522271390Sgibbs if (maxloops == 0) { 522371390Sgibbs printf("Infinite interrupt loop, INTSTAT = %x", 5224102670Sgibbs ahc_inb(ahc, INTSTAT)); 522571390Sgibbs } 522670204Sgibbs ahc_platform_flushwork(ahc); 522770204Sgibbs ahc->flags &= ~AHC_ALL_INTERRUPTS; 522870204Sgibbs} 522970204Sgibbs 523070204Sgibbsint 523170204Sgibbsahc_suspend(struct ahc_softc *ahc) 523270204Sgibbs{ 523370204Sgibbs 523470204Sgibbs ahc_pause_and_flushwork(ahc); 523570204Sgibbs 5236114621Sgibbs if (LIST_FIRST(&ahc->pending_scbs) != NULL) { 5237114621Sgibbs ahc_unpause(ahc); 523870204Sgibbs return (EBUSY); 5239114621Sgibbs } 524070204Sgibbs 5241115337Sgibbs#ifdef AHC_TARGET_MODE 524270204Sgibbs /* 524370204Sgibbs * XXX What about ATIOs that have not yet been serviced? 524470204Sgibbs * Perhaps we should just refuse to be suspended if we 524570204Sgibbs * are acting in a target role. 524670204Sgibbs */ 5247114621Sgibbs if (ahc->pending_device != NULL) { 5248114621Sgibbs ahc_unpause(ahc); 524970204Sgibbs return (EBUSY); 5250114621Sgibbs } 525170204Sgibbs#endif 525270204Sgibbs ahc_shutdown(ahc); 525370204Sgibbs return (0); 525470204Sgibbs} 525570204Sgibbs 525670204Sgibbsint 525770204Sgibbsahc_resume(struct ahc_softc *ahc) 525870204Sgibbs{ 525970204Sgibbs 5260115917Sgibbs ahc_reset(ahc, /*reinit*/TRUE); 5261115917Sgibbs ahc_intr_enable(ahc, TRUE); 5262115917Sgibbs ahc_restart(ahc); 526370204Sgibbs return (0); 526470204Sgibbs} 526570204Sgibbs 526665942Sgibbs/************************** Busy Target Table *********************************/ 526765942Sgibbs/* 526865942Sgibbs * Return the untagged transaction id for a given target/channel lun. 526965942Sgibbs * Optionally, clear the entry. 527065942Sgibbs */ 527165942Sgibbsu_int 527270204Sgibbsahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl) 527339220Sgibbs{ 527465942Sgibbs u_int scbid; 527565942Sgibbs u_int target_offset; 527639220Sgibbs 527771390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 527865942Sgibbs u_int saved_scbptr; 527965942Sgibbs 528065942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 528165942Sgibbs ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); 528265942Sgibbs scbid = ahc_inb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl)); 528365942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 528442652Sgibbs } else { 528565942Sgibbs target_offset = TCL_TARGET_OFFSET(tcl); 528665942Sgibbs scbid = ahc_inb(ahc, BUSY_TARGETS + target_offset); 528742652Sgibbs } 528842652Sgibbs 528965942Sgibbs return (scbid); 529039220Sgibbs} 529139220Sgibbs 529265942Sgibbsvoid 529370204Sgibbsahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl) 529470204Sgibbs{ 529570204Sgibbs u_int target_offset; 529670204Sgibbs 529771390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 529870204Sgibbs u_int saved_scbptr; 529970204Sgibbs 530070204Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 530170204Sgibbs ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); 530270204Sgibbs ahc_outb(ahc, SCB_64_BTT+TCL_TARGET_OFFSET(tcl), SCB_LIST_NULL); 530370204Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 530470204Sgibbs } else { 530570204Sgibbs target_offset = TCL_TARGET_OFFSET(tcl); 530670204Sgibbs ahc_outb(ahc, BUSY_TARGETS + target_offset, SCB_LIST_NULL); 530770204Sgibbs } 530870204Sgibbs} 530970204Sgibbs 531070204Sgibbsvoid 531165942Sgibbsahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int scbid) 531239220Sgibbs{ 531365942Sgibbs u_int target_offset; 531439220Sgibbs 531571390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 531665942Sgibbs u_int saved_scbptr; 531739220Sgibbs 531865942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 531965942Sgibbs ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); 532065942Sgibbs ahc_outb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl), scbid); 532165942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 532239220Sgibbs } else { 532365942Sgibbs target_offset = TCL_TARGET_OFFSET(tcl); 532465942Sgibbs ahc_outb(ahc, BUSY_TARGETS + target_offset, scbid); 532539220Sgibbs } 532639220Sgibbs} 532739220Sgibbs 532865942Sgibbs/************************** SCB and SCB queue management **********************/ 532965942Sgibbsint 533065942Sgibbsahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target, 533165942Sgibbs char channel, int lun, u_int tag, role_t role) 533239220Sgibbs{ 533365942Sgibbs int targ = SCB_GET_TARGET(ahc, scb); 533465942Sgibbs char chan = SCB_GET_CHANNEL(ahc, scb); 533565942Sgibbs int slun = SCB_GET_LUN(scb); 533665942Sgibbs int match; 533739220Sgibbs 533865942Sgibbs match = ((chan == channel) || (channel == ALL_CHANNELS)); 533965942Sgibbs if (match != 0) 534065942Sgibbs match = ((targ == target) || (target == CAM_TARGET_WILDCARD)); 534165942Sgibbs if (match != 0) 534265942Sgibbs match = ((lun == slun) || (lun == CAM_LUN_WILDCARD)); 534365942Sgibbs if (match != 0) { 5344115337Sgibbs#ifdef AHC_TARGET_MODE 534565942Sgibbs int group; 534663457Sgibbs 534765942Sgibbs group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code); 534865942Sgibbs if (role == ROLE_INITIATOR) { 534972325Sgibbs match = (group != XPT_FC_GROUP_TMODE) 535065942Sgibbs && ((tag == scb->hscb->tag) 535165942Sgibbs || (tag == SCB_LIST_NULL)); 535265942Sgibbs } else if (role == ROLE_TARGET) { 535365942Sgibbs match = (group == XPT_FC_GROUP_TMODE) 535465942Sgibbs && ((tag == scb->io_ctx->csio.tag_id) 535565942Sgibbs || (tag == SCB_LIST_NULL)); 535639220Sgibbs } 535765942Sgibbs#else /* !AHC_TARGET_MODE */ 535865942Sgibbs match = ((tag == scb->hscb->tag) || (tag == SCB_LIST_NULL)); 535965942Sgibbs#endif /* AHC_TARGET_MODE */ 536039220Sgibbs } 536139220Sgibbs 536265942Sgibbs return match; 536339220Sgibbs} 536439220Sgibbs 536565942Sgibbsvoid 536665942Sgibbsahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb) 536739220Sgibbs{ 536839220Sgibbs int target; 536939220Sgibbs char channel; 537039220Sgibbs int lun; 537139220Sgibbs 537265942Sgibbs target = SCB_GET_TARGET(ahc, scb); 537365942Sgibbs lun = SCB_GET_LUN(scb); 537465942Sgibbs channel = SCB_GET_CHANNEL(ahc, scb); 537539220Sgibbs 537639220Sgibbs ahc_search_qinfifo(ahc, target, channel, lun, 537749933Sgibbs /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN, 537849933Sgibbs CAM_REQUEUE_REQ, SEARCH_COMPLETE); 537939220Sgibbs 538065942Sgibbs ahc_platform_freeze_devq(ahc, scb); 538139220Sgibbs} 538239220Sgibbs 538366800Sgibbsvoid 538468087Sgibbsahc_qinfifo_requeue_tail(struct ahc_softc *ahc, struct scb *scb) 538568087Sgibbs{ 538668087Sgibbs struct scb *prev_scb; 538768087Sgibbs 538868087Sgibbs prev_scb = NULL; 538968087Sgibbs if (ahc_qinfifo_count(ahc) != 0) { 539068087Sgibbs u_int prev_tag; 539168402Sgibbs uint8_t prev_pos; 539268087Sgibbs 539368402Sgibbs prev_pos = ahc->qinfifonext - 1; 539468402Sgibbs prev_tag = ahc->qinfifo[prev_pos]; 539568087Sgibbs prev_scb = ahc_lookup_scb(ahc, prev_tag); 539668087Sgibbs } 539768087Sgibbs ahc_qinfifo_requeue(ahc, prev_scb, scb); 539868087Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 539968087Sgibbs ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); 540068087Sgibbs } else { 540168087Sgibbs ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); 540268087Sgibbs } 540368087Sgibbs} 540468087Sgibbs 540568087Sgibbsstatic void 540666647Sgibbsahc_qinfifo_requeue(struct ahc_softc *ahc, struct scb *prev_scb, 540766647Sgibbs struct scb *scb) 540866647Sgibbs{ 540979874Sgibbs if (prev_scb == NULL) { 541066647Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag); 541179874Sgibbs } else { 541266647Sgibbs prev_scb->hscb->next = scb->hscb->tag; 541379874Sgibbs ahc_sync_scb(ahc, prev_scb, 541479874Sgibbs BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 541579874Sgibbs } 541666647Sgibbs ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; 541766647Sgibbs scb->hscb->next = ahc->next_queued_scb->hscb->tag; 541879874Sgibbs ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 541966647Sgibbs} 542066647Sgibbs 542168087Sgibbsstatic int 542266800Sgibbsahc_qinfifo_count(struct ahc_softc *ahc) 542366800Sgibbs{ 5424102670Sgibbs uint8_t qinpos; 5425102670Sgibbs uint8_t diff; 542666800Sgibbs 542766800Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 542866800Sgibbs qinpos = ahc_inb(ahc, SNSCB_QOFF); 542966800Sgibbs ahc_outb(ahc, SNSCB_QOFF, qinpos); 543066800Sgibbs } else 543166800Sgibbs qinpos = ahc_inb(ahc, QINPOS); 543268402Sgibbs diff = ahc->qinfifonext - qinpos; 543368402Sgibbs return (diff); 543466800Sgibbs} 543566800Sgibbs 543666800Sgibbsint 543739220Sgibbsahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, 543863457Sgibbs int lun, u_int tag, role_t role, uint32_t status, 543939220Sgibbs ahc_search_action action) 544039220Sgibbs{ 544165942Sgibbs struct scb *scb; 544266647Sgibbs struct scb *prev_scb; 544366647Sgibbs uint8_t qinstart; 544463457Sgibbs uint8_t qinpos; 544563457Sgibbs uint8_t qintail; 544695378Sgibbs uint8_t next; 544795378Sgibbs uint8_t prev; 544863457Sgibbs uint8_t curscbptr; 544965942Sgibbs int found; 545066800Sgibbs int have_qregs; 545139220Sgibbs 545239220Sgibbs qintail = ahc->qinfifonext; 545366800Sgibbs have_qregs = (ahc->features & AHC_QUEUE_REGS) != 0; 545466800Sgibbs if (have_qregs) { 545566647Sgibbs qinstart = ahc_inb(ahc, SNSCB_QOFF); 545666647Sgibbs ahc_outb(ahc, SNSCB_QOFF, qinstart); 545766647Sgibbs } else 545866647Sgibbs qinstart = ahc_inb(ahc, QINPOS); 545966647Sgibbs qinpos = qinstart; 546039220Sgibbs found = 0; 546166647Sgibbs prev_scb = NULL; 546239220Sgibbs 546363457Sgibbs if (action == SEARCH_COMPLETE) { 546463457Sgibbs /* 546563457Sgibbs * Don't attempt to run any queued untagged transactions 546663457Sgibbs * until we are done with the abort process. 546763457Sgibbs */ 546863457Sgibbs ahc_freeze_untagged_queues(ahc); 546963457Sgibbs } 547063457Sgibbs 547139220Sgibbs /* 547239220Sgibbs * Start with an empty queue. Entries that are not chosen 547339220Sgibbs * for removal will be re-added to the queue as we go. 547439220Sgibbs */ 547539220Sgibbs ahc->qinfifonext = qinpos; 547666647Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag); 547739220Sgibbs 547839220Sgibbs while (qinpos != qintail) { 547966647Sgibbs scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinpos]); 548079874Sgibbs if (scb == NULL) { 548179874Sgibbs printf("qinpos = %d, SCB index = %d\n", 548279874Sgibbs qinpos, ahc->qinfifo[qinpos]); 548379874Sgibbs panic("Loop 1\n"); 548479874Sgibbs } 548579874Sgibbs 548665942Sgibbs if (ahc_match_scb(ahc, scb, target, channel, lun, tag, role)) { 548739220Sgibbs /* 548863457Sgibbs * We found an scb that needs to be acted on. 548939220Sgibbs */ 549063457Sgibbs found++; 549139220Sgibbs switch (action) { 549239220Sgibbs case SEARCH_COMPLETE: 549365942Sgibbs { 549465942Sgibbs cam_status ostat; 549572325Sgibbs cam_status cstat; 549665942Sgibbs 5497123579Sgibbs ostat = aic_get_transaction_status(scb); 549865942Sgibbs if (ostat == CAM_REQ_INPROG) 5499123579Sgibbs aic_set_transaction_status(scb, status); 5500123579Sgibbs cstat = aic_get_transaction_status(scb); 550172325Sgibbs if (cstat != CAM_REQ_CMP) 5502123579Sgibbs aic_freeze_scb(scb); 550365942Sgibbs if ((scb->flags & SCB_ACTIVE) == 0) 550465942Sgibbs printf("Inactive SCB in qinfifo\n"); 550565942Sgibbs ahc_done(ahc, scb); 550666647Sgibbs 550766717Sgibbs /* FALLTHROUGH */ 550895378Sgibbs } 550966717Sgibbs case SEARCH_REMOVE: 551039220Sgibbs break; 551139220Sgibbs case SEARCH_COUNT: 551266647Sgibbs ahc_qinfifo_requeue(ahc, prev_scb, scb); 551366647Sgibbs prev_scb = scb; 551439220Sgibbs break; 551539220Sgibbs } 551639220Sgibbs } else { 551766647Sgibbs ahc_qinfifo_requeue(ahc, prev_scb, scb); 551866647Sgibbs prev_scb = scb; 551939220Sgibbs } 552039220Sgibbs qinpos++; 552139220Sgibbs } 552239220Sgibbs 552339220Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 552439220Sgibbs ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); 552539220Sgibbs } else { 552639220Sgibbs ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); 552739220Sgibbs } 552839220Sgibbs 552971390Sgibbs if (action != SEARCH_COUNT 553071390Sgibbs && (found != 0) 553171390Sgibbs && (qinstart != ahc->qinfifonext)) { 553271390Sgibbs /* 553371390Sgibbs * The sequencer may be in the process of dmaing 553471390Sgibbs * down the SCB at the beginning of the queue. 553571390Sgibbs * This could be problematic if either the first, 553671390Sgibbs * or the second SCB is removed from the queue 553771390Sgibbs * (the first SCB includes a pointer to the "next" 553871390Sgibbs * SCB to dma). If we have removed any entries, swap 553971390Sgibbs * the first element in the queue with the next HSCB 554071390Sgibbs * so the sequencer will notice that NEXT_QUEUED_SCB 554171390Sgibbs * has changed during its dma attempt and will retry 554271390Sgibbs * the DMA. 554371390Sgibbs */ 554471390Sgibbs scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinstart]); 554571390Sgibbs 554679874Sgibbs if (scb == NULL) { 554779874Sgibbs printf("found = %d, qinstart = %d, qinfifionext = %d\n", 554879874Sgibbs found, qinstart, ahc->qinfifonext); 554979874Sgibbs panic("First/Second Qinfifo fixup\n"); 555079874Sgibbs } 555171390Sgibbs /* 555271390Sgibbs * ahc_swap_with_next_hscb forces our next pointer to 555371390Sgibbs * point to the reserved SCB for future commands. Save 555471390Sgibbs * and restore our original next pointer to maintain 555571390Sgibbs * queue integrity. 555671390Sgibbs */ 555771390Sgibbs next = scb->hscb->next; 555871390Sgibbs ahc->scb_data->scbindex[scb->hscb->tag] = NULL; 555971390Sgibbs ahc_swap_with_next_hscb(ahc, scb); 556071390Sgibbs scb->hscb->next = next; 556171390Sgibbs ahc->qinfifo[qinstart] = scb->hscb->tag; 556271390Sgibbs 556371473Sgibbs /* Tell the card about the new head of the qinfifo. */ 556471473Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag); 556571473Sgibbs 556671390Sgibbs /* Fixup the tail "next" pointer. */ 556771390Sgibbs qintail = ahc->qinfifonext - 1; 556871390Sgibbs scb = ahc_lookup_scb(ahc, ahc->qinfifo[qintail]); 556971390Sgibbs scb->hscb->next = ahc->next_queued_scb->hscb->tag; 557071390Sgibbs } 557171390Sgibbs 557263457Sgibbs /* 557363457Sgibbs * Search waiting for selection list. 557463457Sgibbs */ 557563457Sgibbs curscbptr = ahc_inb(ahc, SCBPTR); 557663457Sgibbs next = ahc_inb(ahc, WAITING_SCBH); /* Start at head of list. */ 557763457Sgibbs prev = SCB_LIST_NULL; 557863457Sgibbs 557963457Sgibbs while (next != SCB_LIST_NULL) { 558063457Sgibbs uint8_t scb_index; 558163457Sgibbs 558263457Sgibbs ahc_outb(ahc, SCBPTR, next); 558363457Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 558463457Sgibbs if (scb_index >= ahc->scb_data->numscbs) { 558568087Sgibbs printf("Waiting List inconsistency. " 558668087Sgibbs "SCB index == %d, yet numscbs == %d.", 558768087Sgibbs scb_index, ahc->scb_data->numscbs); 558868087Sgibbs ahc_dump_card_state(ahc); 558968087Sgibbs panic("for safety"); 559063457Sgibbs } 559166647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 559279874Sgibbs if (scb == NULL) { 559379874Sgibbs printf("scb_index = %d, next = %d\n", 559479874Sgibbs scb_index, next); 559579874Sgibbs panic("Waiting List traversal\n"); 559679874Sgibbs } 559765942Sgibbs if (ahc_match_scb(ahc, scb, target, channel, 559863457Sgibbs lun, SCB_LIST_NULL, role)) { 559963457Sgibbs /* 560063457Sgibbs * We found an scb that needs to be acted on. 560163457Sgibbs */ 560263457Sgibbs found++; 560363457Sgibbs switch (action) { 560463457Sgibbs case SEARCH_COMPLETE: 560565942Sgibbs { 560665942Sgibbs cam_status ostat; 560772325Sgibbs cam_status cstat; 560865942Sgibbs 5609123579Sgibbs ostat = aic_get_transaction_status(scb); 561065942Sgibbs if (ostat == CAM_REQ_INPROG) 5611123579Sgibbs aic_set_transaction_status(scb, 561265942Sgibbs status); 5613123579Sgibbs cstat = aic_get_transaction_status(scb); 561472325Sgibbs if (cstat != CAM_REQ_CMP) 5615123579Sgibbs aic_freeze_scb(scb); 561665942Sgibbs if ((scb->flags & SCB_ACTIVE) == 0) 5617125449Sgibbs printf("Inactive SCB in Wait List\n"); 561865942Sgibbs ahc_done(ahc, scb); 561968087Sgibbs /* FALLTHROUGH */ 562068087Sgibbs } 562168087Sgibbs case SEARCH_REMOVE: 562268087Sgibbs next = ahc_rem_wscb(ahc, next, prev); 562363457Sgibbs break; 562463457Sgibbs case SEARCH_COUNT: 562563457Sgibbs prev = next; 562663457Sgibbs next = ahc_inb(ahc, SCB_NEXT); 562763457Sgibbs break; 562863457Sgibbs } 562963457Sgibbs } else { 563063457Sgibbs 563163457Sgibbs prev = next; 563263457Sgibbs next = ahc_inb(ahc, SCB_NEXT); 563363457Sgibbs } 563463457Sgibbs } 563563457Sgibbs ahc_outb(ahc, SCBPTR, curscbptr); 563663457Sgibbs 5637123579Sgibbs found += ahc_search_untagged_queues(ahc, /*aic_io_ctx_t*/NULL, target, 5638102670Sgibbs channel, lun, status, action); 5639102670Sgibbs 5640102670Sgibbs if (action == SEARCH_COMPLETE) 5641102670Sgibbs ahc_release_untagged_queues(ahc); 5642102670Sgibbs return (found); 5643102670Sgibbs} 5644102670Sgibbs 5645102670Sgibbsint 5646123579Sgibbsahc_search_untagged_queues(struct ahc_softc *ahc, aic_io_ctx_t ctx, 5647102670Sgibbs int target, char channel, int lun, uint32_t status, 5648102670Sgibbs ahc_search_action action) 5649102670Sgibbs{ 5650102670Sgibbs struct scb *scb; 5651102670Sgibbs int maxtarget; 5652102670Sgibbs int found; 5653102670Sgibbs int i; 5654102670Sgibbs 5655102670Sgibbs if (action == SEARCH_COMPLETE) { 5656102670Sgibbs /* 5657102670Sgibbs * Don't attempt to run any queued untagged transactions 5658102670Sgibbs * until we are done with the abort process. 5659102670Sgibbs */ 5660102670Sgibbs ahc_freeze_untagged_queues(ahc); 5661102670Sgibbs } 5662102670Sgibbs 5663102670Sgibbs found = 0; 566463457Sgibbs i = 0; 566565942Sgibbs if ((ahc->flags & AHC_SCB_BTT) == 0) { 566639220Sgibbs 566765942Sgibbs maxtarget = 16; 566865942Sgibbs if (target != CAM_TARGET_WILDCARD) { 566939220Sgibbs 567065942Sgibbs i = target; 567165942Sgibbs if (channel == 'B') 567265942Sgibbs i += 8; 567365942Sgibbs maxtarget = i + 1; 567463821Sgibbs } 567565942Sgibbs } else { 567665942Sgibbs maxtarget = 0; 567763457Sgibbs } 567839220Sgibbs 567965942Sgibbs for (; i < maxtarget; i++) { 568065942Sgibbs struct scb_tailq *untagged_q; 568165942Sgibbs struct scb *next_scb; 568239220Sgibbs 568365942Sgibbs untagged_q = &(ahc->untagged_queues[i]); 568465942Sgibbs next_scb = TAILQ_FIRST(untagged_q); 568565942Sgibbs while (next_scb != NULL) { 568639220Sgibbs 568765942Sgibbs scb = next_scb; 568865942Sgibbs next_scb = TAILQ_NEXT(scb, links.tqe); 568957099Sgibbs 569065942Sgibbs /* 569165942Sgibbs * The head of the list may be the currently 569265942Sgibbs * active untagged command for a device. 569365942Sgibbs * We're only searching for commands that 569465942Sgibbs * have not been started. A transaction 569565942Sgibbs * marked active but still in the qinfifo 569665942Sgibbs * is removed by the qinfifo scanning code 569765942Sgibbs * above. 569865942Sgibbs */ 569965942Sgibbs if ((scb->flags & SCB_ACTIVE) != 0) 570065942Sgibbs continue; 570139220Sgibbs 5702102670Sgibbs if (ahc_match_scb(ahc, scb, target, channel, lun, 5703102670Sgibbs SCB_LIST_NULL, ROLE_INITIATOR) == 0 5704102670Sgibbs || (ctx != NULL && ctx != scb->io_ctx)) 5705102670Sgibbs continue; 570665942Sgibbs 5707102670Sgibbs /* 5708102670Sgibbs * We found an scb that needs to be acted on. 5709102670Sgibbs */ 5710102670Sgibbs found++; 5711102670Sgibbs switch (action) { 5712102670Sgibbs case SEARCH_COMPLETE: 5713102670Sgibbs { 5714102670Sgibbs cam_status ostat; 5715102670Sgibbs cam_status cstat; 5716102670Sgibbs 5717123579Sgibbs ostat = aic_get_transaction_status(scb); 5718102670Sgibbs if (ostat == CAM_REQ_INPROG) 5719123579Sgibbs aic_set_transaction_status(scb, status); 5720123579Sgibbs cstat = aic_get_transaction_status(scb); 5721102670Sgibbs if (cstat != CAM_REQ_CMP) 5722123579Sgibbs aic_freeze_scb(scb); 5723102670Sgibbs ahc_done(ahc, scb); 5724102670Sgibbs break; 572539220Sgibbs } 5726102670Sgibbs case SEARCH_REMOVE: 5727102670Sgibbs scb->flags &= ~SCB_UNTAGGEDQ; 5728102670Sgibbs TAILQ_REMOVE(untagged_q, scb, links.tqe); 5729102670Sgibbs break; 5730102670Sgibbs case SEARCH_COUNT: 5731102670Sgibbs break; 5732102670Sgibbs } 573339220Sgibbs } 573439220Sgibbs } 573565942Sgibbs 573665942Sgibbs if (action == SEARCH_COMPLETE) 573765942Sgibbs ahc_release_untagged_queues(ahc); 573865942Sgibbs return (found); 573939220Sgibbs} 574039220Sgibbs 574165942Sgibbsint 574239506Sgibbsahc_search_disc_list(struct ahc_softc *ahc, int target, char channel, 574357099Sgibbs int lun, u_int tag, int stop_on_first, int remove, 574457099Sgibbs int save_state) 574539220Sgibbs{ 574639506Sgibbs struct scb *scbp; 574739506Sgibbs u_int next; 574839506Sgibbs u_int prev; 574939506Sgibbs u_int count; 575039506Sgibbs u_int active_scb; 575139220Sgibbs 575239506Sgibbs count = 0; 575339506Sgibbs next = ahc_inb(ahc, DISCONNECTED_SCBH); 575439506Sgibbs prev = SCB_LIST_NULL; 575539506Sgibbs 575657099Sgibbs if (save_state) { 575757099Sgibbs /* restore this when we're done */ 575857099Sgibbs active_scb = ahc_inb(ahc, SCBPTR); 575957099Sgibbs } else 576057099Sgibbs /* Silence compiler */ 576157099Sgibbs active_scb = SCB_LIST_NULL; 576239506Sgibbs 576339506Sgibbs while (next != SCB_LIST_NULL) { 576439506Sgibbs u_int scb_index; 576539506Sgibbs 576639506Sgibbs ahc_outb(ahc, SCBPTR, next); 576739506Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 576839506Sgibbs if (scb_index >= ahc->scb_data->numscbs) { 576968087Sgibbs printf("Disconnected List inconsistency. " 577068087Sgibbs "SCB index == %d, yet numscbs == %d.", 577168087Sgibbs scb_index, ahc->scb_data->numscbs); 577268087Sgibbs ahc_dump_card_state(ahc); 577368087Sgibbs panic("for safety"); 577439506Sgibbs } 577563457Sgibbs 577663457Sgibbs if (next == prev) { 577763457Sgibbs panic("Disconnected List Loop. " 577863457Sgibbs "cur SCBPTR == %x, prev SCBPTR == %x.", 577963457Sgibbs next, prev); 578063457Sgibbs } 578166647Sgibbs scbp = ahc_lookup_scb(ahc, scb_index); 578263457Sgibbs if (ahc_match_scb(ahc, scbp, target, channel, lun, 578349933Sgibbs tag, ROLE_INITIATOR)) { 578439506Sgibbs count++; 578557099Sgibbs if (remove) { 578657099Sgibbs next = 578757099Sgibbs ahc_rem_scb_from_disc_list(ahc, prev, next); 578857099Sgibbs } else { 578957099Sgibbs prev = next; 579057099Sgibbs next = ahc_inb(ahc, SCB_NEXT); 579157099Sgibbs } 579257099Sgibbs if (stop_on_first) 579357099Sgibbs break; 579439506Sgibbs } else { 579539506Sgibbs prev = next; 579639506Sgibbs next = ahc_inb(ahc, SCB_NEXT); 579739506Sgibbs } 579839506Sgibbs } 579957099Sgibbs if (save_state) 580057099Sgibbs ahc_outb(ahc, SCBPTR, active_scb); 580139506Sgibbs return (count); 580239506Sgibbs} 580339506Sgibbs 580465942Sgibbs/* 580565942Sgibbs * Remove an SCB from the on chip list of disconnected transactions. 580665942Sgibbs * This is empty/unused if we are not performing SCB paging. 580765942Sgibbs */ 580839506Sgibbsstatic u_int 580939506Sgibbsahc_rem_scb_from_disc_list(struct ahc_softc *ahc, u_int prev, u_int scbptr) 581039506Sgibbs{ 581139506Sgibbs u_int next; 581239506Sgibbs 581339220Sgibbs ahc_outb(ahc, SCBPTR, scbptr); 581439220Sgibbs next = ahc_inb(ahc, SCB_NEXT); 581539220Sgibbs 581639220Sgibbs ahc_outb(ahc, SCB_CONTROL, 0); 581739220Sgibbs 581839220Sgibbs ahc_add_curscb_to_free_list(ahc); 581939220Sgibbs 582039220Sgibbs if (prev != SCB_LIST_NULL) { 582139220Sgibbs ahc_outb(ahc, SCBPTR, prev); 582239220Sgibbs ahc_outb(ahc, SCB_NEXT, next); 582339220Sgibbs } else 582439220Sgibbs ahc_outb(ahc, DISCONNECTED_SCBH, next); 582539220Sgibbs 582649933Sgibbs return (next); 582739220Sgibbs} 582839220Sgibbs 582965942Sgibbs/* 583065942Sgibbs * Add the SCB as selected by SCBPTR onto the on chip list of 583165942Sgibbs * free hardware SCBs. This list is empty/unused if we are not 583265942Sgibbs * performing SCB paging. 583365942Sgibbs */ 583439220Sgibbsstatic void 583539220Sgibbsahc_add_curscb_to_free_list(struct ahc_softc *ahc) 583639220Sgibbs{ 583765942Sgibbs /* 583865942Sgibbs * Invalidate the tag so that our abort 583965942Sgibbs * routines don't think it's active. 584065942Sgibbs */ 584139220Sgibbs ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL); 584239220Sgibbs 584368087Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 584468087Sgibbs ahc_outb(ahc, SCB_NEXT, ahc_inb(ahc, FREE_SCBH)); 584568087Sgibbs ahc_outb(ahc, FREE_SCBH, ahc_inb(ahc, SCBPTR)); 584668087Sgibbs } 584739220Sgibbs} 584839220Sgibbs 584939220Sgibbs/* 585039220Sgibbs * Manipulate the waiting for selection list and return the 585139220Sgibbs * scb that follows the one that we remove. 585239220Sgibbs */ 585339506Sgibbsstatic u_int 585463457Sgibbsahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev) 585539220Sgibbs{ 585639506Sgibbs u_int curscb, next; 585739220Sgibbs 585839220Sgibbs /* 585939220Sgibbs * Select the SCB we want to abort and 586039220Sgibbs * pull the next pointer out of it. 586139220Sgibbs */ 586239220Sgibbs curscb = ahc_inb(ahc, SCBPTR); 586339220Sgibbs ahc_outb(ahc, SCBPTR, scbpos); 586439220Sgibbs next = ahc_inb(ahc, SCB_NEXT); 586539220Sgibbs 586639220Sgibbs /* Clear the necessary fields */ 586739220Sgibbs ahc_outb(ahc, SCB_CONTROL, 0); 586839220Sgibbs 586939220Sgibbs ahc_add_curscb_to_free_list(ahc); 587039220Sgibbs 587139220Sgibbs /* update the waiting list */ 587239220Sgibbs if (prev == SCB_LIST_NULL) { 587339220Sgibbs /* First in the list */ 587439220Sgibbs ahc_outb(ahc, WAITING_SCBH, next); 587539220Sgibbs 587639220Sgibbs /* 587739220Sgibbs * Ensure we aren't attempting to perform 587839220Sgibbs * selection for this entry. 587939220Sgibbs */ 588039220Sgibbs ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); 588139220Sgibbs } else { 588239220Sgibbs /* 588339220Sgibbs * Select the scb that pointed to us 588439220Sgibbs * and update its next pointer. 588539220Sgibbs */ 588639220Sgibbs ahc_outb(ahc, SCBPTR, prev); 588739220Sgibbs ahc_outb(ahc, SCB_NEXT, next); 588839220Sgibbs } 588939220Sgibbs 589039220Sgibbs /* 589139220Sgibbs * Point us back at the original scb position. 589239220Sgibbs */ 589339220Sgibbs ahc_outb(ahc, SCBPTR, curscb); 589439220Sgibbs return next; 589539220Sgibbs} 589639220Sgibbs 589765942Sgibbs/******************************** Error Handling ******************************/ 589865942Sgibbs/* 589965942Sgibbs * Abort all SCBs that match the given description (target/channel/lun/tag), 590065942Sgibbs * setting their status to the passed in status if the status has not already 590165942Sgibbs * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer 590265942Sgibbs * is paused before it is called. 590365942Sgibbs */ 590465942Sgibbsint 590565942Sgibbsahc_abort_scbs(struct ahc_softc *ahc, int target, char channel, 590665942Sgibbs int lun, u_int tag, role_t role, uint32_t status) 590739220Sgibbs{ 590865942Sgibbs struct scb *scbp; 590965942Sgibbs struct scb *scbp_next; 591065942Sgibbs u_int active_scb; 591166986Sgibbs int i, j; 591265942Sgibbs int maxtarget; 591366986Sgibbs int minlun; 591466986Sgibbs int maxlun; 591566986Sgibbs 591665942Sgibbs int found; 591765942Sgibbs 591865942Sgibbs /* 591965942Sgibbs * Don't attempt to run any queued untagged transactions 592065942Sgibbs * until we are done with the abort process. 592165942Sgibbs */ 592265942Sgibbs ahc_freeze_untagged_queues(ahc); 592365942Sgibbs 592465942Sgibbs /* restore this when we're done */ 592565942Sgibbs active_scb = ahc_inb(ahc, SCBPTR); 592665942Sgibbs 592765942Sgibbs found = ahc_search_qinfifo(ahc, target, channel, lun, SCB_LIST_NULL, 592865942Sgibbs role, CAM_REQUEUE_REQ, SEARCH_COMPLETE); 592965942Sgibbs 593065942Sgibbs /* 593165942Sgibbs * Clean out the busy target table for any untagged commands. 593265942Sgibbs */ 593365942Sgibbs i = 0; 593465942Sgibbs maxtarget = 16; 593565942Sgibbs if (target != CAM_TARGET_WILDCARD) { 593665942Sgibbs i = target; 593765942Sgibbs if (channel == 'B') 593865942Sgibbs i += 8; 593965942Sgibbs maxtarget = i + 1; 594065942Sgibbs } 594165942Sgibbs 594266986Sgibbs if (lun == CAM_LUN_WILDCARD) { 594365942Sgibbs 594466986Sgibbs /* 594566986Sgibbs * Unless we are using an SCB based 594666986Sgibbs * busy targets table, there is only 594766986Sgibbs * one table entry for all luns of 594866986Sgibbs * a target. 594966986Sgibbs */ 595066986Sgibbs minlun = 0; 595166986Sgibbs maxlun = 1; 595266986Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) 595366986Sgibbs maxlun = AHC_NUM_LUNS; 595466986Sgibbs } else { 595566986Sgibbs minlun = lun; 595666986Sgibbs maxlun = lun + 1; 595766986Sgibbs } 595865942Sgibbs 595995378Sgibbs if (role != ROLE_TARGET) { 596095378Sgibbs for (;i < maxtarget; i++) { 596195378Sgibbs for (j = minlun;j < maxlun; j++) { 596295378Sgibbs u_int scbid; 596395378Sgibbs u_int tcl; 596495378Sgibbs 596595378Sgibbs tcl = BUILD_TCL(i << 4, j); 596695378Sgibbs scbid = ahc_index_busy_tcl(ahc, tcl); 596795378Sgibbs scbp = ahc_lookup_scb(ahc, scbid); 596895378Sgibbs if (scbp == NULL 596995378Sgibbs || ahc_match_scb(ahc, scbp, target, channel, 597095378Sgibbs lun, tag, role) == 0) 597195378Sgibbs continue; 597295378Sgibbs ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, j)); 597395378Sgibbs } 597495378Sgibbs } 597595378Sgibbs 597695378Sgibbs /* 597795378Sgibbs * Go through the disconnected list and remove any entries we 597895378Sgibbs * have queued for completion, 0'ing their control byte too. 597995378Sgibbs * We save the active SCB and restore it ourselves, so there 598095378Sgibbs * is no reason for this search to restore it too. 598195378Sgibbs */ 598295378Sgibbs ahc_search_disc_list(ahc, target, channel, lun, tag, 598395378Sgibbs /*stop_on_first*/FALSE, /*remove*/TRUE, 598495378Sgibbs /*save_state*/FALSE); 598565942Sgibbs } 598665942Sgibbs 598765942Sgibbs /* 598865942Sgibbs * Go through the hardware SCB array looking for commands that 598995378Sgibbs * were active but not on any list. In some cases, these remnants 599095378Sgibbs * might not still have mappings in the scbindex array (e.g. unexpected 599195378Sgibbs * bus free with the same scb queued for an abort). Don't hold this 599295378Sgibbs * against them. 599365942Sgibbs */ 599468087Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 599565942Sgibbs u_int scbid; 599665942Sgibbs 599765942Sgibbs ahc_outb(ahc, SCBPTR, i); 599865942Sgibbs scbid = ahc_inb(ahc, SCB_TAG); 599966647Sgibbs scbp = ahc_lookup_scb(ahc, scbid); 600095378Sgibbs if ((scbp == NULL && scbid != SCB_LIST_NULL) 600195378Sgibbs || (scbp != NULL 600295378Sgibbs && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role))) 600365942Sgibbs ahc_add_curscb_to_free_list(ahc); 600465942Sgibbs } 600565942Sgibbs 600665942Sgibbs /* 600765942Sgibbs * Go through the pending CCB list and look for 600865942Sgibbs * commands for this target that are still active. 600965942Sgibbs * These are other tagged commands that were 601076634Sgibbs * disconnected when the reset occurred. 601165942Sgibbs */ 601265942Sgibbs scbp_next = LIST_FIRST(&ahc->pending_scbs); 601365942Sgibbs while (scbp_next != NULL) { 601465942Sgibbs scbp = scbp_next; 601565942Sgibbs scbp_next = LIST_NEXT(scbp, pending_links); 601665942Sgibbs if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) { 601765942Sgibbs cam_status ostat; 601865942Sgibbs 6019123579Sgibbs ostat = aic_get_transaction_status(scbp); 602065942Sgibbs if (ostat == CAM_REQ_INPROG) 6021123579Sgibbs aic_set_transaction_status(scbp, status); 6022123579Sgibbs if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) 6023123579Sgibbs aic_freeze_scb(scbp); 602465942Sgibbs if ((scbp->flags & SCB_ACTIVE) == 0) 602565942Sgibbs printf("Inactive SCB on pending list\n"); 602665942Sgibbs ahc_done(ahc, scbp); 602765942Sgibbs found++; 602865942Sgibbs } 602965942Sgibbs } 603065942Sgibbs ahc_outb(ahc, SCBPTR, active_scb); 603165942Sgibbs ahc_platform_abort_scbs(ahc, target, channel, lun, tag, role, status); 603265942Sgibbs ahc_release_untagged_queues(ahc); 603365942Sgibbs return found; 603439220Sgibbs} 603539220Sgibbs 603639220Sgibbsstatic void 603739220Sgibbsahc_reset_current_bus(struct ahc_softc *ahc) 603839220Sgibbs{ 603963457Sgibbs uint8_t scsiseq; 604039220Sgibbs 604139220Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST); 604239220Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ); 604339220Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO); 604495378Sgibbs ahc_flush_device_writes(ahc); 6045123579Sgibbs aic_delay(AHC_BUSRESET_DELAY); 604639220Sgibbs /* Turn off the bus reset */ 604739220Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO); 604839220Sgibbs 604939220Sgibbs ahc_clear_intstat(ahc); 605039220Sgibbs 605139220Sgibbs /* Re-enable reset interrupts */ 605239220Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST); 605339220Sgibbs} 605439220Sgibbs 605565942Sgibbsint 605639220Sgibbsahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset) 605739220Sgibbs{ 605865942Sgibbs struct ahc_devinfo devinfo; 605944507Sgibbs u_int initiator, target, max_scsiid; 606044507Sgibbs u_int sblkctl; 606179874Sgibbs u_int scsiseq; 606279874Sgibbs u_int simode1; 606344507Sgibbs int found; 606449933Sgibbs int restart_needed; 606544507Sgibbs char cur_channel; 606639220Sgibbs 606744507Sgibbs ahc->pending_device = NULL; 606844507Sgibbs 606965942Sgibbs ahc_compile_devinfo(&devinfo, 607065942Sgibbs CAM_TARGET_WILDCARD, 607165942Sgibbs CAM_TARGET_WILDCARD, 607265942Sgibbs CAM_LUN_WILDCARD, 607365942Sgibbs channel, ROLE_UNKNOWN); 607474094Sgibbs ahc_pause(ahc); 607549933Sgibbs 607666647Sgibbs /* Make sure the sequencer is in a safe location. */ 607766647Sgibbs ahc_clear_critical_section(ahc); 607866647Sgibbs 607939220Sgibbs /* 608049933Sgibbs * Run our command complete fifos to ensure that we perform 608149933Sgibbs * completion processing on any commands that 'completed' 608249933Sgibbs * before the reset occurred. 608349933Sgibbs */ 608449933Sgibbs ahc_run_qoutfifo(ahc); 6085115337Sgibbs#ifdef AHC_TARGET_MODE 608695378Sgibbs /* 608795378Sgibbs * XXX - In Twin mode, the tqinfifo may have commands 608895378Sgibbs * for an unaffected channel in it. However, if 608995378Sgibbs * we have run out of ATIO resources to drain that 609095378Sgibbs * queue, we may not get them all out here. Further, 609195378Sgibbs * the blocked transactions for the reset channel 609295378Sgibbs * should just be killed off, irrespecitve of whether 609395378Sgibbs * we are blocked on ATIO resources. Write a routine 609495378Sgibbs * to compact the tqinfifo appropriately. 609595378Sgibbs */ 609668087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 609755581Sgibbs ahc_run_tqinfifo(ahc, /*paused*/TRUE); 609849933Sgibbs } 609965942Sgibbs#endif 610049933Sgibbs 610149933Sgibbs /* 610249933Sgibbs * Reset the bus if we are initiating this reset 610349933Sgibbs */ 610449933Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 610549933Sgibbs cur_channel = 'A'; 610649933Sgibbs if ((ahc->features & AHC_TWIN) != 0 610749933Sgibbs && ((sblkctl & SELBUSB) != 0)) 610849933Sgibbs cur_channel = 'B'; 610979874Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); 611049933Sgibbs if (cur_channel != channel) { 611149933Sgibbs /* Case 1: Command for another bus is active 611249933Sgibbs * Stealthily reset the other bus without 611349933Sgibbs * upsetting the current bus. 611449933Sgibbs */ 611549933Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB); 611679874Sgibbs simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); 6117115337Sgibbs#ifdef AHC_TARGET_MODE 611879874Sgibbs /* 611979874Sgibbs * Bus resets clear ENSELI, so we cannot 612079874Sgibbs * defer re-enabling bus reset interrupts 612179874Sgibbs * if we are in target mode. 612279874Sgibbs */ 612379874Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) 612495378Sgibbs simode1 |= ENSCSIRST; 612579874Sgibbs#endif 612695378Sgibbs ahc_outb(ahc, SIMODE1, simode1); 612795378Sgibbs if (initiate_reset) 612895378Sgibbs ahc_reset_current_bus(ahc); 612995378Sgibbs ahc_clear_intstat(ahc); 613079874Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); 613149933Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl); 613249933Sgibbs restart_needed = FALSE; 613349933Sgibbs } else { 613449933Sgibbs /* Case 2: A command from this bus is active or we're idle */ 613579874Sgibbs simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); 6136115337Sgibbs#ifdef AHC_TARGET_MODE 613779874Sgibbs /* 613879874Sgibbs * Bus resets clear ENSELI, so we cannot 613979874Sgibbs * defer re-enabling bus reset interrupts 614079874Sgibbs * if we are in target mode. 614179874Sgibbs */ 614279874Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) 614395378Sgibbs simode1 |= ENSCSIRST; 614479874Sgibbs#endif 614595378Sgibbs ahc_outb(ahc, SIMODE1, simode1); 614695378Sgibbs if (initiate_reset) 614795378Sgibbs ahc_reset_current_bus(ahc); 614895378Sgibbs ahc_clear_intstat(ahc); 614979874Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); 615049933Sgibbs restart_needed = TRUE; 615149933Sgibbs } 615249933Sgibbs 615349933Sgibbs /* 615439220Sgibbs * Clean up all the state information for the 615539220Sgibbs * pending transactions on this bus. 615639220Sgibbs */ 615741646Sgibbs found = ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, channel, 615841646Sgibbs CAM_LUN_WILDCARD, SCB_LIST_NULL, 615949933Sgibbs ROLE_UNKNOWN, CAM_SCSI_BUS_RESET); 616039220Sgibbs 616149933Sgibbs max_scsiid = (ahc->features & AHC_WIDE) ? 15 : 7; 616249933Sgibbs 616365942Sgibbs#ifdef AHC_TARGET_MODE 616449933Sgibbs /* 616549933Sgibbs * Send an immediate notify ccb to all target more peripheral 616649933Sgibbs * drivers affected by this action. 616749933Sgibbs */ 616849933Sgibbs for (target = 0; target <= max_scsiid; target++) { 616974972Sgibbs struct ahc_tmode_tstate* tstate; 617049933Sgibbs u_int lun; 617149933Sgibbs 617249933Sgibbs tstate = ahc->enabled_targets[target]; 617349933Sgibbs if (tstate == NULL) 617449933Sgibbs continue; 617570204Sgibbs for (lun = 0; lun < AHC_NUM_LUNS; lun++) { 617674972Sgibbs struct ahc_tmode_lstate* lstate; 617749933Sgibbs 617849933Sgibbs lstate = tstate->enabled_luns[lun]; 617949933Sgibbs if (lstate == NULL) 618049933Sgibbs continue; 618149933Sgibbs 618249933Sgibbs ahc_queue_lstate_event(ahc, lstate, CAM_TARGET_WILDCARD, 618349933Sgibbs EVENT_TYPE_BUS_RESET, /*arg*/0); 618449933Sgibbs ahc_send_lstate_events(ahc, lstate); 618549933Sgibbs } 618649933Sgibbs } 618765942Sgibbs#endif 618839220Sgibbs /* Notify the XPT that a bus reset occurred */ 618966269Sgibbs ahc_send_async(ahc, devinfo.channel, CAM_TARGET_WILDCARD, 619076634Sgibbs CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); 619139220Sgibbs 619239220Sgibbs /* 619339220Sgibbs * Revert to async/narrow transfers until we renegotiate. 619439220Sgibbs */ 619544507Sgibbs for (target = 0; target <= max_scsiid; target++) { 619639220Sgibbs 619744507Sgibbs if (ahc->enabled_targets[target] == NULL) 619844507Sgibbs continue; 619944507Sgibbs for (initiator = 0; initiator <= max_scsiid; initiator++) { 620044507Sgibbs struct ahc_devinfo devinfo; 620144507Sgibbs 620244507Sgibbs ahc_compile_devinfo(&devinfo, target, initiator, 620344507Sgibbs CAM_LUN_WILDCARD, 620444507Sgibbs channel, ROLE_UNKNOWN); 620565942Sgibbs ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 620647287Sgibbs AHC_TRANS_CUR, /*paused*/TRUE); 620765942Sgibbs ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, 620865942Sgibbs /*period*/0, /*offset*/0, 620965942Sgibbs /*ppr_options*/0, AHC_TRANS_CUR, 621065942Sgibbs /*paused*/TRUE); 621144507Sgibbs } 621239220Sgibbs } 621339220Sgibbs 621449933Sgibbs if (restart_needed) 621574094Sgibbs ahc_restart(ahc); 621649933Sgibbs else 621774094Sgibbs ahc_unpause(ahc); 621839220Sgibbs return found; 621939220Sgibbs} 622039220Sgibbs 622139220Sgibbs 622265942Sgibbs/***************************** Residual Processing ****************************/ 622365942Sgibbs/* 622465942Sgibbs * Calculate the residual for a just completed SCB. 622565942Sgibbs */ 622676634Sgibbsvoid 622795378Sgibbsahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) 622839220Sgibbs{ 622963457Sgibbs struct hardware_scb *hscb; 623063457Sgibbs struct status_pkt *spkt; 623170693Sgibbs uint32_t sgptr; 623270693Sgibbs uint32_t resid_sgptr; 623363457Sgibbs uint32_t resid; 623439220Sgibbs 623563457Sgibbs /* 623663854Sgibbs * 5 cases. 623763457Sgibbs * 1) No residual. 623863457Sgibbs * SG_RESID_VALID clear in sgptr. 623963457Sgibbs * 2) Transferless command 624063457Sgibbs * 3) Never performed any transfers. 624163457Sgibbs * sgptr has SG_FULL_RESID set. 624263854Sgibbs * 4) No residual but target did not 624363854Sgibbs * save data pointers after the 624463854Sgibbs * last transfer, so sgptr was 624563854Sgibbs * never updated. 624663854Sgibbs * 5) We have a partial residual. 624763457Sgibbs * Use residual_sgptr to determine 624863457Sgibbs * where we are. 624963457Sgibbs */ 625063457Sgibbs 625139220Sgibbs hscb = scb->hscb; 6252123579Sgibbs sgptr = aic_le32toh(hscb->sgptr); 625370693Sgibbs if ((sgptr & SG_RESID_VALID) == 0) 625463854Sgibbs /* Case 1 */ 625563457Sgibbs return; 625670693Sgibbs sgptr &= ~SG_RESID_VALID; 625739220Sgibbs 625870693Sgibbs if ((sgptr & SG_LIST_NULL) != 0) 625963854Sgibbs /* Case 2 */ 626063457Sgibbs return; 626163457Sgibbs 626263457Sgibbs spkt = &hscb->shared_data.status; 6263123579Sgibbs resid_sgptr = aic_le32toh(spkt->residual_sg_ptr); 626470693Sgibbs if ((sgptr & SG_FULL_RESID) != 0) { 626563854Sgibbs /* Case 3 */ 6266123579Sgibbs resid = aic_get_transfer_length(scb); 626770693Sgibbs } else if ((resid_sgptr & SG_LIST_NULL) != 0) { 626863854Sgibbs /* Case 4 */ 626963854Sgibbs return; 627070693Sgibbs } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) { 627170693Sgibbs panic("Bogus resid sgptr value 0x%x\n", resid_sgptr); 6272141978Sgibbs /* NOTREACHED */ 6273141978Sgibbs return; 627465942Sgibbs } else { 627563457Sgibbs struct ahc_dma_seg *sg; 627663457Sgibbs 627739220Sgibbs /* 627839220Sgibbs * Remainder of the SG where the transfer 627963457Sgibbs * stopped. 628039220Sgibbs */ 6281123579Sgibbs resid = aic_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; 628270693Sgibbs sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK); 628339220Sgibbs 628463457Sgibbs /* The residual sg_ptr always points to the next sg */ 628563457Sgibbs sg--; 628663457Sgibbs 628739220Sgibbs /* 628839220Sgibbs * Add up the contents of all residual 628939220Sgibbs * SG segments that are after the SG where 629039220Sgibbs * the transfer stopped. 629139220Sgibbs */ 6292123579Sgibbs while ((aic_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { 629339220Sgibbs sg++; 6294123579Sgibbs resid += aic_le32toh(sg->len) & AHC_SG_LEN_MASK; 629539220Sgibbs } 629663457Sgibbs } 629765942Sgibbs if ((scb->flags & SCB_SENSE) == 0) 6298123579Sgibbs aic_set_residual(scb, resid); 629965942Sgibbs else 6300123579Sgibbs aic_set_sense_residual(scb, resid); 630139220Sgibbs 630258258Sgibbs#ifdef AHC_DEBUG 6303102670Sgibbs if ((ahc_debug & AHC_SHOW_MISC) != 0) { 630465942Sgibbs ahc_print_path(ahc, scb); 6305109590Sgibbs printf("Handled %sResidual of %d bytes\n", 6306109590Sgibbs (scb->flags & SCB_SENSE) ? "Sense " : "", resid); 630763457Sgibbs } 630858258Sgibbs#endif 630939220Sgibbs} 631039220Sgibbs 631165942Sgibbs/******************************* Target Mode **********************************/ 631265942Sgibbs#ifdef AHC_TARGET_MODE 631349933Sgibbs/* 631449933Sgibbs * Add a target mode event to this lun's queue 631549933Sgibbs */ 631649933Sgibbsstatic void 631774972Sgibbsahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate, 631849933Sgibbs u_int initiator_id, u_int event_type, u_int event_arg) 631949933Sgibbs{ 632049933Sgibbs struct ahc_tmode_event *event; 632149933Sgibbs int pending; 632249933Sgibbs 632349933Sgibbs xpt_freeze_devq(lstate->path, /*count*/1); 632449933Sgibbs if (lstate->event_w_idx >= lstate->event_r_idx) 632549933Sgibbs pending = lstate->event_w_idx - lstate->event_r_idx; 632649933Sgibbs else 632749933Sgibbs pending = AHC_TMODE_EVENT_BUFFER_SIZE + 1 632849933Sgibbs - (lstate->event_r_idx - lstate->event_w_idx); 632949933Sgibbs 633049933Sgibbs if (event_type == EVENT_TYPE_BUS_RESET 633149933Sgibbs || event_type == MSG_BUS_DEV_RESET) { 633249933Sgibbs /* 633349933Sgibbs * Any earlier events are irrelevant, so reset our buffer. 633449933Sgibbs * This has the effect of allowing us to deal with reset 633549933Sgibbs * floods (an external device holding down the reset line) 633649933Sgibbs * without losing the event that is really interesting. 633749933Sgibbs */ 633849933Sgibbs lstate->event_r_idx = 0; 633949933Sgibbs lstate->event_w_idx = 0; 634049933Sgibbs xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE); 634149933Sgibbs } 634249933Sgibbs 634349933Sgibbs if (pending == AHC_TMODE_EVENT_BUFFER_SIZE) { 634449933Sgibbs xpt_print_path(lstate->path); 634549933Sgibbs printf("immediate event %x:%x lost\n", 634649933Sgibbs lstate->event_buffer[lstate->event_r_idx].event_type, 634749933Sgibbs lstate->event_buffer[lstate->event_r_idx].event_arg); 634849933Sgibbs lstate->event_r_idx++; 634949933Sgibbs if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE) 635049933Sgibbs lstate->event_r_idx = 0; 635149933Sgibbs xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE); 635249933Sgibbs } 635349933Sgibbs 635449933Sgibbs event = &lstate->event_buffer[lstate->event_w_idx]; 635549933Sgibbs event->initiator_id = initiator_id; 635649933Sgibbs event->event_type = event_type; 635749933Sgibbs event->event_arg = event_arg; 635849933Sgibbs lstate->event_w_idx++; 635949933Sgibbs if (lstate->event_w_idx == AHC_TMODE_EVENT_BUFFER_SIZE) 636049933Sgibbs lstate->event_w_idx = 0; 636149933Sgibbs} 636249933Sgibbs 636349933Sgibbs/* 636449933Sgibbs * Send any target mode events queued up waiting 636549933Sgibbs * for immediate notify resources. 636649933Sgibbs */ 636765942Sgibbsvoid 636874972Sgibbsahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate) 636949933Sgibbs{ 637049933Sgibbs struct ccb_hdr *ccbh; 6371237601Sken struct ccb_immediate_notify *inot; 637249933Sgibbs 637349933Sgibbs while (lstate->event_r_idx != lstate->event_w_idx 637449933Sgibbs && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) { 637549933Sgibbs struct ahc_tmode_event *event; 637649933Sgibbs 637749933Sgibbs event = &lstate->event_buffer[lstate->event_r_idx]; 637849933Sgibbs SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle); 6379237601Sken inot = (struct ccb_immediate_notify *)ccbh; 638049933Sgibbs switch (event->event_type) { 638149933Sgibbs case EVENT_TYPE_BUS_RESET: 638249933Sgibbs ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN; 638349933Sgibbs break; 638449933Sgibbs default: 638549933Sgibbs ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; 6386237601Sken inot->arg = event->event_type; 6387237601Sken inot->seq_id = event->event_arg; 638849933Sgibbs break; 638949933Sgibbs } 639049933Sgibbs inot->initiator_id = event->initiator_id; 639149933Sgibbs xpt_done((union ccb *)inot); 639249933Sgibbs lstate->event_r_idx++; 639349933Sgibbs if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE) 639449933Sgibbs lstate->event_r_idx = 0; 639549933Sgibbs } 639649933Sgibbs} 639765942Sgibbs#endif 639865942Sgibbs 639965942Sgibbs/******************** Sequencer Program Patching/Download *********************/ 640065942Sgibbs 640165942Sgibbs#ifdef AHC_DUMP_SEQ 640265942Sgibbsvoid 640365942Sgibbsahc_dumpseq(struct ahc_softc* ahc) 640465942Sgibbs{ 640565942Sgibbs int i; 640665942Sgibbs 640765942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); 640865942Sgibbs ahc_outb(ahc, SEQADDR0, 0); 640965942Sgibbs ahc_outb(ahc, SEQADDR1, 0); 6410114621Sgibbs for (i = 0; i < ahc->instruction_ram_size; i++) { 641165942Sgibbs uint8_t ins_bytes[4]; 641265942Sgibbs 641365942Sgibbs ahc_insb(ahc, SEQRAM, ins_bytes, 4); 641465942Sgibbs printf("0x%08x\n", ins_bytes[0] << 24 641565942Sgibbs | ins_bytes[1] << 16 641665942Sgibbs | ins_bytes[2] << 8 641765942Sgibbs | ins_bytes[3]); 641865942Sgibbs } 641965942Sgibbs} 642065942Sgibbs#endif 642165942Sgibbs 6422114621Sgibbsstatic int 642365942Sgibbsahc_loadseq(struct ahc_softc *ahc) 642465942Sgibbs{ 642566647Sgibbs struct cs cs_table[num_critical_sections]; 642666845Sgibbs u_int begin_set[num_critical_sections]; 642766845Sgibbs u_int end_set[num_critical_sections]; 642866647Sgibbs struct patch *cur_patch; 642966845Sgibbs u_int cs_count; 643066647Sgibbs u_int cur_cs; 643166647Sgibbs u_int i; 643266647Sgibbs u_int skip_addr; 643366647Sgibbs u_int sg_prefetch_cnt; 6434114621Sgibbs int downloaded; 643566647Sgibbs uint8_t download_consts[7]; 643665942Sgibbs 643766647Sgibbs /* 643866647Sgibbs * Start out with 0 critical sections 643966647Sgibbs * that apply to this firmware load. 644066647Sgibbs */ 644166845Sgibbs cs_count = 0; 644266647Sgibbs cur_cs = 0; 644366845Sgibbs memset(begin_set, 0, sizeof(begin_set)); 644466845Sgibbs memset(end_set, 0, sizeof(end_set)); 644566647Sgibbs 644665942Sgibbs /* Setup downloadable constant table */ 644765942Sgibbs download_consts[QOUTFIFO_OFFSET] = 0; 644865942Sgibbs if (ahc->targetcmds != NULL) 644965942Sgibbs download_consts[QOUTFIFO_OFFSET] += 32; 645065942Sgibbs download_consts[QINFIFO_OFFSET] = download_consts[QOUTFIFO_OFFSET] + 1; 645165942Sgibbs download_consts[CACHESIZE_MASK] = ahc->pci_cachesize - 1; 645265942Sgibbs download_consts[INVERTED_CACHESIZE_MASK] = ~(ahc->pci_cachesize - 1); 645366647Sgibbs sg_prefetch_cnt = ahc->pci_cachesize; 645466647Sgibbs if (sg_prefetch_cnt < (2 * sizeof(struct ahc_dma_seg))) 645566647Sgibbs sg_prefetch_cnt = 2 * sizeof(struct ahc_dma_seg); 645666647Sgibbs download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt; 645766647Sgibbs download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_cnt - 1); 645866647Sgibbs download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_cnt - 1); 645965942Sgibbs 646065942Sgibbs cur_patch = patches; 646165942Sgibbs downloaded = 0; 646265942Sgibbs skip_addr = 0; 646365942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); 646465942Sgibbs ahc_outb(ahc, SEQADDR0, 0); 646565942Sgibbs ahc_outb(ahc, SEQADDR1, 0); 646665942Sgibbs 646765942Sgibbs for (i = 0; i < sizeof(seqprog)/4; i++) { 646865942Sgibbs if (ahc_check_patch(ahc, &cur_patch, i, &skip_addr) == 0) { 646965942Sgibbs /* 647065942Sgibbs * Don't download this instruction as it 647165942Sgibbs * is in a patch that was removed. 647265942Sgibbs */ 647365942Sgibbs continue; 647465942Sgibbs } 6475114621Sgibbs 6476114621Sgibbs if (downloaded == ahc->instruction_ram_size) { 6477114621Sgibbs /* 6478114621Sgibbs * We're about to exceed the instruction 6479114621Sgibbs * storage capacity for this chip. Fail 6480114621Sgibbs * the load. 6481114621Sgibbs */ 6482114621Sgibbs printf("\n%s: Program too large for instruction memory " 6483114621Sgibbs "size of %d!\n", ahc_name(ahc), 6484114621Sgibbs ahc->instruction_ram_size); 6485114621Sgibbs return (ENOMEM); 6486114621Sgibbs } 6487114621Sgibbs 648866647Sgibbs /* 648966647Sgibbs * Move through the CS table until we find a CS 649066647Sgibbs * that might apply to this instruction. 649166647Sgibbs */ 649266647Sgibbs for (; cur_cs < num_critical_sections; cur_cs++) { 649366845Sgibbs if (critical_sections[cur_cs].end <= i) { 649466845Sgibbs if (begin_set[cs_count] == TRUE 649566845Sgibbs && end_set[cs_count] == FALSE) { 649666845Sgibbs cs_table[cs_count].end = downloaded; 649766845Sgibbs end_set[cs_count] = TRUE; 649866845Sgibbs cs_count++; 649966647Sgibbs } 650066845Sgibbs continue; 650166647Sgibbs } 650266845Sgibbs if (critical_sections[cur_cs].begin <= i 650366845Sgibbs && begin_set[cs_count] == FALSE) { 650466845Sgibbs cs_table[cs_count].begin = downloaded; 650566845Sgibbs begin_set[cs_count] = TRUE; 650666845Sgibbs } 650766845Sgibbs break; 650866647Sgibbs } 650965942Sgibbs ahc_download_instr(ahc, i, download_consts); 651065942Sgibbs downloaded++; 651165942Sgibbs } 651266647Sgibbs 651366845Sgibbs ahc->num_critical_sections = cs_count; 651466845Sgibbs if (cs_count != 0) { 651566647Sgibbs 651666845Sgibbs cs_count *= sizeof(struct cs); 651766845Sgibbs ahc->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT); 651866647Sgibbs if (ahc->critical_sections == NULL) 651966647Sgibbs panic("ahc_loadseq: Could not malloc"); 652066845Sgibbs memcpy(ahc->critical_sections, cs_table, cs_count); 652166647Sgibbs } 652265942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE); 652365942Sgibbs 6524109590Sgibbs if (bootverbose) { 652565942Sgibbs printf(" %d instructions downloaded\n", downloaded); 6526109590Sgibbs printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", 6527109590Sgibbs ahc_name(ahc), ahc->features, ahc->bugs, ahc->flags); 6528109590Sgibbs } 6529114621Sgibbs return (0); 653065942Sgibbs} 653165942Sgibbs 653265942Sgibbsstatic int 653365942Sgibbsahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch, 653465942Sgibbs u_int start_instr, u_int *skip_addr) 653565942Sgibbs{ 653665942Sgibbs struct patch *cur_patch; 653765942Sgibbs struct patch *last_patch; 653865942Sgibbs u_int num_patches; 653965942Sgibbs 654065942Sgibbs num_patches = sizeof(patches)/sizeof(struct patch); 654165942Sgibbs last_patch = &patches[num_patches]; 654265942Sgibbs cur_patch = *start_patch; 654365942Sgibbs 654465942Sgibbs while (cur_patch < last_patch && start_instr == cur_patch->begin) { 654565942Sgibbs 654665942Sgibbs if (cur_patch->patch_func(ahc) == 0) { 654765942Sgibbs 654865942Sgibbs /* Start rejecting code */ 654965942Sgibbs *skip_addr = start_instr + cur_patch->skip_instr; 655065942Sgibbs cur_patch += cur_patch->skip_patch; 655165942Sgibbs } else { 655265942Sgibbs /* Accepted this patch. Advance to the next 655365942Sgibbs * one and wait for our intruction pointer to 655465942Sgibbs * hit this point. 655565942Sgibbs */ 655665942Sgibbs cur_patch++; 655765942Sgibbs } 655865942Sgibbs } 655965942Sgibbs 656065942Sgibbs *start_patch = cur_patch; 656165942Sgibbs if (start_instr < *skip_addr) 656265942Sgibbs /* Still skipping */ 656365942Sgibbs return (0); 656465942Sgibbs 656565942Sgibbs return (1); 656665942Sgibbs} 656765942Sgibbs 656865942Sgibbsstatic void 656965942Sgibbsahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) 657065942Sgibbs{ 657165942Sgibbs union ins_formats instr; 657265942Sgibbs struct ins_format1 *fmt1_ins; 657365942Sgibbs struct ins_format3 *fmt3_ins; 657465942Sgibbs u_int opcode; 657565942Sgibbs 657670693Sgibbs /* 657770693Sgibbs * The firmware is always compiled into a little endian format. 657870693Sgibbs */ 6579123579Sgibbs instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); 658065942Sgibbs 658165942Sgibbs fmt1_ins = &instr.format1; 658265942Sgibbs fmt3_ins = NULL; 658365942Sgibbs 658465942Sgibbs /* Pull the opcode */ 658565942Sgibbs opcode = instr.format1.opcode; 658665942Sgibbs switch (opcode) { 658765942Sgibbs case AIC_OP_JMP: 658865942Sgibbs case AIC_OP_JC: 658965942Sgibbs case AIC_OP_JNC: 659065942Sgibbs case AIC_OP_CALL: 659165942Sgibbs case AIC_OP_JNE: 659265942Sgibbs case AIC_OP_JNZ: 659365942Sgibbs case AIC_OP_JE: 659465942Sgibbs case AIC_OP_JZ: 659565942Sgibbs { 659665942Sgibbs struct patch *cur_patch; 659765942Sgibbs int address_offset; 659865942Sgibbs u_int address; 659965942Sgibbs u_int skip_addr; 660065942Sgibbs u_int i; 660165942Sgibbs 660265942Sgibbs fmt3_ins = &instr.format3; 660365942Sgibbs address_offset = 0; 660465942Sgibbs address = fmt3_ins->address; 660565942Sgibbs cur_patch = patches; 660665942Sgibbs skip_addr = 0; 660765942Sgibbs 660865942Sgibbs for (i = 0; i < address;) { 660965942Sgibbs 661065942Sgibbs ahc_check_patch(ahc, &cur_patch, i, &skip_addr); 661165942Sgibbs 661265942Sgibbs if (skip_addr > i) { 661365942Sgibbs int end_addr; 661465942Sgibbs 661565942Sgibbs end_addr = MIN(address, skip_addr); 661665942Sgibbs address_offset += end_addr - i; 661765942Sgibbs i = skip_addr; 661865942Sgibbs } else { 661965942Sgibbs i++; 662065942Sgibbs } 662165942Sgibbs } 662265942Sgibbs address -= address_offset; 662365942Sgibbs fmt3_ins->address = address; 662465942Sgibbs /* FALLTHROUGH */ 662565942Sgibbs } 662665942Sgibbs case AIC_OP_OR: 662765942Sgibbs case AIC_OP_AND: 662865942Sgibbs case AIC_OP_XOR: 662965942Sgibbs case AIC_OP_ADD: 663065942Sgibbs case AIC_OP_ADC: 663165942Sgibbs case AIC_OP_BMOV: 663265942Sgibbs if (fmt1_ins->parity != 0) { 663365942Sgibbs fmt1_ins->immediate = dconsts[fmt1_ins->immediate]; 663465942Sgibbs } 663565942Sgibbs fmt1_ins->parity = 0; 663668087Sgibbs if ((ahc->features & AHC_CMD_CHAN) == 0 663768087Sgibbs && opcode == AIC_OP_BMOV) { 663868087Sgibbs /* 663968087Sgibbs * Block move was added at the same time 664068087Sgibbs * as the command channel. Verify that 664168087Sgibbs * this is only a move of a single element 664268087Sgibbs * and convert the BMOV to a MOV 664368087Sgibbs * (AND with an immediate of FF). 664468087Sgibbs */ 664568087Sgibbs if (fmt1_ins->immediate != 1) 664668087Sgibbs panic("%s: BMOV not supported\n", 664768087Sgibbs ahc_name(ahc)); 664868087Sgibbs fmt1_ins->opcode = AIC_OP_AND; 664968087Sgibbs fmt1_ins->immediate = 0xff; 665068087Sgibbs } 665165942Sgibbs /* FALLTHROUGH */ 665265942Sgibbs case AIC_OP_ROL: 665365942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 665465942Sgibbs int i, count; 665565942Sgibbs 665665942Sgibbs /* Calculate odd parity for the instruction */ 665765942Sgibbs for (i = 0, count = 0; i < 31; i++) { 665865942Sgibbs uint32_t mask; 665965942Sgibbs 666065942Sgibbs mask = 0x01 << i; 666165942Sgibbs if ((instr.integer & mask) != 0) 666265942Sgibbs count++; 666365942Sgibbs } 666465942Sgibbs if ((count & 0x01) == 0) 666565942Sgibbs instr.format1.parity = 1; 666665942Sgibbs } else { 666765942Sgibbs /* Compress the instruction for older sequencers */ 666865942Sgibbs if (fmt3_ins != NULL) { 666965942Sgibbs instr.integer = 667065942Sgibbs fmt3_ins->immediate 667165942Sgibbs | (fmt3_ins->source << 8) 667265942Sgibbs | (fmt3_ins->address << 16) 667365942Sgibbs | (fmt3_ins->opcode << 25); 667465942Sgibbs } else { 667565942Sgibbs instr.integer = 667665942Sgibbs fmt1_ins->immediate 667765942Sgibbs | (fmt1_ins->source << 8) 667865942Sgibbs | (fmt1_ins->destination << 16) 667965942Sgibbs | (fmt1_ins->ret << 24) 668065942Sgibbs | (fmt1_ins->opcode << 25); 668165942Sgibbs } 668265942Sgibbs } 668370693Sgibbs /* The sequencer is a little endian cpu */ 6684123579Sgibbs instr.integer = aic_htole32(instr.integer); 668565942Sgibbs ahc_outsb(ahc, SEQRAM, instr.bytes, 4); 668665942Sgibbs break; 668765942Sgibbs default: 668865942Sgibbs panic("Unknown opcode encountered in seq program"); 668965942Sgibbs break; 669065942Sgibbs } 669165942Sgibbs} 669265942Sgibbs 6693102670Sgibbsint 6694102670Sgibbsahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries, 6695102670Sgibbs const char *name, u_int address, u_int value, 6696102670Sgibbs u_int *cur_column, u_int wrap_point) 6697102670Sgibbs{ 6698102670Sgibbs int printed; 6699102670Sgibbs u_int printed_mask; 6700141999Sgibbs u_int dummy_column; 6701102670Sgibbs 6702141999Sgibbs if (cur_column == NULL) { 6703141999Sgibbs dummy_column = 0; 6704141999Sgibbs cur_column = &dummy_column; 6705141999Sgibbs } 6706141999Sgibbs 6707144370Ssam if (*cur_column >= wrap_point) { 6708102670Sgibbs printf("\n"); 6709102670Sgibbs *cur_column = 0; 6710102670Sgibbs } 6711102670Sgibbs printed = printf("%s[0x%x]", name, value); 6712102670Sgibbs if (table == NULL) { 6713102670Sgibbs printed += printf(" "); 6714102670Sgibbs *cur_column += printed; 6715102670Sgibbs return (printed); 6716102670Sgibbs } 6717102670Sgibbs printed_mask = 0; 6718102670Sgibbs while (printed_mask != 0xFF) { 6719102670Sgibbs int entry; 6720102670Sgibbs 6721102670Sgibbs for (entry = 0; entry < num_entries; entry++) { 6722102670Sgibbs if (((value & table[entry].mask) 6723102670Sgibbs != table[entry].value) 6724102670Sgibbs || ((printed_mask & table[entry].mask) 6725102670Sgibbs == table[entry].mask)) 6726102670Sgibbs continue; 6727102670Sgibbs 6728102670Sgibbs printed += printf("%s%s", 6729102670Sgibbs printed_mask == 0 ? ":(" : "|", 6730102670Sgibbs table[entry].name); 6731102670Sgibbs printed_mask |= table[entry].mask; 6732102670Sgibbs 6733102670Sgibbs break; 6734102670Sgibbs } 6735102670Sgibbs if (entry >= num_entries) 6736102670Sgibbs break; 6737102670Sgibbs } 6738102670Sgibbs if (printed_mask != 0) 6739102670Sgibbs printed += printf(") "); 6740102670Sgibbs else 6741102670Sgibbs printed += printf(" "); 6742107420Sscottl if (cur_column != NULL) 6743107420Sscottl *cur_column += printed; 6744102670Sgibbs return (printed); 6745102670Sgibbs} 6746102670Sgibbs 674765942Sgibbsvoid 674865942Sgibbsahc_dump_card_state(struct ahc_softc *ahc) 674965942Sgibbs{ 6750107420Sscottl struct scb *scb; 6751107420Sscottl struct scb_tailq *untagged_q; 6752107420Sscottl u_int cur_col; 6753109590Sgibbs int paused; 6754107420Sscottl int target; 6755107420Sscottl int maxtarget; 6756107420Sscottl int i; 675774972Sgibbs uint8_t last_phase; 675865942Sgibbs uint8_t qinpos; 675965942Sgibbs uint8_t qintail; 676065942Sgibbs uint8_t qoutpos; 676165942Sgibbs uint8_t scb_index; 676265942Sgibbs uint8_t saved_scbptr; 676365942Sgibbs 6764109590Sgibbs if (ahc_is_paused(ahc)) { 6765109590Sgibbs paused = 1; 6766109590Sgibbs } else { 6767109590Sgibbs paused = 0; 6768109590Sgibbs ahc_pause(ahc); 6769109590Sgibbs } 6770109590Sgibbs 677165942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 677274972Sgibbs last_phase = ahc_inb(ahc, LASTPHASE); 6773109590Sgibbs printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" 6774109590Sgibbs "%s: Dumping Card State %s, at SEQADDR 0x%x\n", 677574972Sgibbs ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg, 677668579Sgibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 6777109590Sgibbs if (paused) 6778109590Sgibbs printf("Card was paused\n"); 677981170Sgibbs printf("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n", 678081170Sgibbs ahc_inb(ahc, ACCUM), ahc_inb(ahc, SINDEX), ahc_inb(ahc, DINDEX), 678181170Sgibbs ahc_inb(ahc, ARG_2)); 678295378Sgibbs printf("HCNT = 0x%x SCBPTR = 0x%x\n", ahc_inb(ahc, HCNT), 678395378Sgibbs ahc_inb(ahc, SCBPTR)); 6784107420Sscottl cur_col = 0; 678574972Sgibbs if ((ahc->features & AHC_DT) != 0) 6786109590Sgibbs ahc_scsiphase_print(ahc_inb(ahc, SCSIPHASE), &cur_col, 50); 6787109590Sgibbs ahc_scsisigi_print(ahc_inb(ahc, SCSISIGI), &cur_col, 50); 6788109590Sgibbs ahc_error_print(ahc_inb(ahc, ERROR), &cur_col, 50); 6789107420Sscottl ahc_scsibusl_print(ahc_inb(ahc, SCSIBUSL), &cur_col, 50); 6790107420Sscottl ahc_lastphase_print(ahc_inb(ahc, LASTPHASE), &cur_col, 50); 6791107420Sscottl ahc_scsiseq_print(ahc_inb(ahc, SCSISEQ), &cur_col, 50); 6792107420Sscottl ahc_sblkctl_print(ahc_inb(ahc, SBLKCTL), &cur_col, 50); 6793109590Sgibbs ahc_scsirate_print(ahc_inb(ahc, SCSIRATE), &cur_col, 50); 6794107420Sscottl ahc_seqctl_print(ahc_inb(ahc, SEQCTL), &cur_col, 50); 6795107420Sscottl ahc_seq_flags_print(ahc_inb(ahc, SEQ_FLAGS), &cur_col, 50); 6796107420Sscottl ahc_sstat0_print(ahc_inb(ahc, SSTAT0), &cur_col, 50); 6797107420Sscottl ahc_sstat1_print(ahc_inb(ahc, SSTAT1), &cur_col, 50); 6798107420Sscottl ahc_sstat2_print(ahc_inb(ahc, SSTAT2), &cur_col, 50); 6799107420Sscottl ahc_sstat3_print(ahc_inb(ahc, SSTAT3), &cur_col, 50); 6800107420Sscottl ahc_simode0_print(ahc_inb(ahc, SIMODE0), &cur_col, 50); 6801107420Sscottl ahc_simode1_print(ahc_inb(ahc, SIMODE1), &cur_col, 50); 6802107420Sscottl ahc_sxfrctl0_print(ahc_inb(ahc, SXFRCTL0), &cur_col, 50); 6803107420Sscottl ahc_dfcntrl_print(ahc_inb(ahc, DFCNTRL), &cur_col, 50); 6804107420Sscottl ahc_dfstatus_print(ahc_inb(ahc, DFSTATUS), &cur_col, 50); 6805107420Sscottl if (cur_col != 0) 6806107420Sscottl printf("\n"); 6807107420Sscottl printf("STACK:"); 6808109590Sgibbs for (i = 0; i < STACK_SIZE; i++) 6809109590Sgibbs printf(" 0x%x", ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8)); 6810107420Sscottl printf("\nSCB count = %d\n", ahc->scb_data->numscbs); 681171390Sgibbs printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag); 681271390Sgibbs printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB)); 681365942Sgibbs /* QINFIFO */ 681465942Sgibbs printf("QINFIFO entries: "); 681568087Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 681668087Sgibbs qinpos = ahc_inb(ahc, SNSCB_QOFF); 681768087Sgibbs ahc_outb(ahc, SNSCB_QOFF, qinpos); 681868087Sgibbs } else 681968087Sgibbs qinpos = ahc_inb(ahc, QINPOS); 682065942Sgibbs qintail = ahc->qinfifonext; 682165942Sgibbs while (qinpos != qintail) { 682265942Sgibbs printf("%d ", ahc->qinfifo[qinpos]); 682365942Sgibbs qinpos++; 682465942Sgibbs } 682565942Sgibbs printf("\n"); 682665942Sgibbs 682765942Sgibbs printf("Waiting Queue entries: "); 682865942Sgibbs scb_index = ahc_inb(ahc, WAITING_SCBH); 682965942Sgibbs i = 0; 683065942Sgibbs while (scb_index != SCB_LIST_NULL && i++ < 256) { 683165942Sgibbs ahc_outb(ahc, SCBPTR, scb_index); 683265942Sgibbs printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); 683365942Sgibbs scb_index = ahc_inb(ahc, SCB_NEXT); 683465942Sgibbs } 683565942Sgibbs printf("\n"); 683665942Sgibbs 683765942Sgibbs printf("Disconnected Queue entries: "); 683865942Sgibbs scb_index = ahc_inb(ahc, DISCONNECTED_SCBH); 683965942Sgibbs i = 0; 684065942Sgibbs while (scb_index != SCB_LIST_NULL && i++ < 256) { 684165942Sgibbs ahc_outb(ahc, SCBPTR, scb_index); 684265942Sgibbs printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); 684365942Sgibbs scb_index = ahc_inb(ahc, SCB_NEXT); 684465942Sgibbs } 684565942Sgibbs printf("\n"); 684665942Sgibbs 684779874Sgibbs ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); 684865942Sgibbs printf("QOUTFIFO entries: "); 684965942Sgibbs qoutpos = ahc->qoutfifonext; 685065942Sgibbs i = 0; 685165942Sgibbs while (ahc->qoutfifo[qoutpos] != SCB_LIST_NULL && i++ < 256) { 685265942Sgibbs printf("%d ", ahc->qoutfifo[qoutpos]); 685365942Sgibbs qoutpos++; 685465942Sgibbs } 685565942Sgibbs printf("\n"); 685665942Sgibbs 685765942Sgibbs printf("Sequencer Free SCB List: "); 685865942Sgibbs scb_index = ahc_inb(ahc, FREE_SCBH); 685965942Sgibbs i = 0; 686065942Sgibbs while (scb_index != SCB_LIST_NULL && i++ < 256) { 686165942Sgibbs ahc_outb(ahc, SCBPTR, scb_index); 686265942Sgibbs printf("%d ", scb_index); 686365942Sgibbs scb_index = ahc_inb(ahc, SCB_NEXT); 686465942Sgibbs } 686565942Sgibbs printf("\n"); 686665942Sgibbs 686795378Sgibbs printf("Sequencer SCB Info: "); 686895378Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 686995378Sgibbs ahc_outb(ahc, SCBPTR, i); 6870107420Sscottl cur_col = printf("\n%3d ", i); 6871107420Sscottl 6872107420Sscottl ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL), &cur_col, 60); 6873107420Sscottl ahc_scb_scsiid_print(ahc_inb(ahc, SCB_SCSIID), &cur_col, 60); 6874107420Sscottl ahc_scb_lun_print(ahc_inb(ahc, SCB_LUN), &cur_col, 60); 6875107420Sscottl ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60); 687695378Sgibbs } 687795378Sgibbs printf("\n"); 687895378Sgibbs 687965942Sgibbs printf("Pending list: "); 688065942Sgibbs i = 0; 688165942Sgibbs LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { 688265942Sgibbs if (i++ > 256) 688365942Sgibbs break; 6884107420Sscottl cur_col = printf("\n%3d ", scb->hscb->tag); 6885107420Sscottl ahc_scb_control_print(scb->hscb->control, &cur_col, 60); 6886107420Sscottl ahc_scb_scsiid_print(scb->hscb->scsiid, &cur_col, 60); 6887107420Sscottl ahc_scb_lun_print(scb->hscb->lun, &cur_col, 60); 688881170Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) { 688981170Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 6890107420Sscottl printf("("); 6891107420Sscottl ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL), 6892107420Sscottl &cur_col, 60); 6893107420Sscottl ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60); 6894107420Sscottl printf(")"); 689581170Sgibbs } 689665942Sgibbs } 689765942Sgibbs printf("\n"); 689865942Sgibbs 689965942Sgibbs printf("Kernel Free SCB list: "); 690065942Sgibbs i = 0; 690165942Sgibbs SLIST_FOREACH(scb, &ahc->scb_data->free_scbs, links.sle) { 690265942Sgibbs if (i++ > 256) 690365942Sgibbs break; 690465942Sgibbs printf("%d ", scb->hscb->tag); 690565942Sgibbs } 690665942Sgibbs printf("\n"); 690765942Sgibbs 690865942Sgibbs maxtarget = (ahc->features & (AHC_WIDE|AHC_TWIN)) ? 15 : 7; 690965942Sgibbs for (target = 0; target <= maxtarget; target++) { 691068087Sgibbs untagged_q = &ahc->untagged_queues[target]; 691165942Sgibbs if (TAILQ_FIRST(untagged_q) == NULL) 691265942Sgibbs continue; 691365942Sgibbs printf("Untagged Q(%d): ", target); 691465942Sgibbs i = 0; 691565942Sgibbs TAILQ_FOREACH(scb, untagged_q, links.tqe) { 691665942Sgibbs if (i++ > 256) 691765942Sgibbs break; 691865942Sgibbs printf("%d ", scb->hscb->tag); 691965942Sgibbs } 692065942Sgibbs printf("\n"); 692165942Sgibbs } 692265942Sgibbs 692365942Sgibbs ahc_platform_dump_card_state(ahc); 6924109590Sgibbs printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); 692565942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 6926109590Sgibbs if (paused == 0) 6927109590Sgibbs ahc_unpause(ahc); 692865942Sgibbs} 692965942Sgibbs 6930123579Sgibbs/*************************** Timeout Handling *********************************/ 6931123579Sgibbsvoid 6932123579Sgibbsahc_timeout(struct scb *scb) 6933123579Sgibbs{ 6934123579Sgibbs struct ahc_softc *ahc; 6935123579Sgibbs 6936123579Sgibbs ahc = scb->ahc_softc; 6937123579Sgibbs if ((scb->flags & SCB_ACTIVE) != 0) { 6938123579Sgibbs if ((scb->flags & SCB_TIMEDOUT) == 0) { 6939123579Sgibbs LIST_INSERT_HEAD(&ahc->timedout_scbs, scb, 6940123579Sgibbs timedout_links); 6941123579Sgibbs scb->flags |= SCB_TIMEDOUT; 6942123579Sgibbs } 6943123579Sgibbs ahc_wakeup_recovery_thread(ahc); 6944123579Sgibbs } 6945123579Sgibbs} 6946123579Sgibbs 6947123579Sgibbs/* 6948129133Sgibbs * Re-schedule a timeout for the passed in SCB if we determine that some 6949129133Sgibbs * other SCB is in the process of recovery or an SCB with a longer 6950129133Sgibbs * timeout is still pending. Limit our search to just "other_scb" 6951129133Sgibbs * if it is non-NULL. 6952129133Sgibbs */ 6953129133Sgibbsstatic int 6954129133Sgibbsahc_other_scb_timeout(struct ahc_softc *ahc, struct scb *scb, 6955129133Sgibbs struct scb *other_scb) 6956129133Sgibbs{ 6957129133Sgibbs u_int newtimeout; 6958129133Sgibbs int found; 6959129133Sgibbs 6960129133Sgibbs ahc_print_path(ahc, scb); 6961129133Sgibbs printf("Other SCB Timeout%s", 6962129133Sgibbs (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 6963129133Sgibbs ? " again\n" : "\n"); 6964129133Sgibbs 6965129133Sgibbs newtimeout = aic_get_timeout(scb); 6966129133Sgibbs scb->flags |= SCB_OTHERTCL_TIMEOUT; 6967129133Sgibbs found = 0; 6968129133Sgibbs if (other_scb != NULL) { 6969129133Sgibbs if ((other_scb->flags 6970129133Sgibbs & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0 6971129133Sgibbs || (other_scb->flags & SCB_RECOVERY_SCB) != 0) { 6972129133Sgibbs found++; 6973129133Sgibbs newtimeout = MAX(aic_get_timeout(other_scb), 6974129133Sgibbs newtimeout); 6975129133Sgibbs } 6976129133Sgibbs } else { 6977129133Sgibbs LIST_FOREACH(other_scb, &ahc->pending_scbs, pending_links) { 6978129133Sgibbs if ((other_scb->flags 6979129133Sgibbs & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0 6980129133Sgibbs || (other_scb->flags & SCB_RECOVERY_SCB) != 0) { 6981129133Sgibbs found++; 6982129133Sgibbs newtimeout = 6983129133Sgibbs MAX(aic_get_timeout(other_scb), 6984129133Sgibbs newtimeout); 6985129133Sgibbs } 6986129133Sgibbs } 6987129133Sgibbs } 6988129133Sgibbs 6989129133Sgibbs if (found != 0) 6990129133Sgibbs aic_scb_timer_reset(scb, newtimeout); 6991129133Sgibbs else { 6992129133Sgibbs ahc_print_path(ahc, scb); 6993129133Sgibbs printf("No other SCB worth waiting for...\n"); 6994129133Sgibbs } 6995129133Sgibbs 6996129133Sgibbs return (found != 0); 6997129133Sgibbs} 6998129133Sgibbs 6999129133Sgibbs/* 7000123579Sgibbs * ahc_recover_commands determines if any of the commands that have currently 7001123579Sgibbs * timedout are the root cause for this timeout. Innocent commands are given 7002123579Sgibbs * a new timeout while we wait for the command executing on the bus to timeout. 7003123579Sgibbs * This routine is invoked from a thread context so we are allowed to sleep. 7004123579Sgibbs * Our lock is not held on entry. 7005123579Sgibbs */ 7006123579Sgibbsvoid 7007123579Sgibbsahc_recover_commands(struct ahc_softc *ahc) 7008123579Sgibbs{ 7009123579Sgibbs struct scb *scb; 7010123579Sgibbs int found; 7011123579Sgibbs int restart_needed; 7012123579Sgibbs u_int last_phase; 7013123579Sgibbs 7014123579Sgibbs /* 7015123579Sgibbs * Pause the controller and manually flush any 7016123579Sgibbs * commands that have just completed but that our 7017123579Sgibbs * interrupt handler has yet to see. 7018123579Sgibbs */ 7019123579Sgibbs ahc_pause_and_flushwork(ahc); 7020123579Sgibbs 7021123579Sgibbs if (LIST_EMPTY(&ahc->timedout_scbs) != 0) { 7022123579Sgibbs /* 7023123579Sgibbs * The timedout commands have already 7024123579Sgibbs * completed. This typically means 7025123579Sgibbs * that either the timeout value was on 7026123579Sgibbs * the hairy edge of what the device 7027123579Sgibbs * requires or - more likely - interrupts 7028123579Sgibbs * are not happening. 7029123579Sgibbs */ 7030123579Sgibbs printf("%s: Timedout SCBs already complete. " 7031123579Sgibbs "Interrupts may not be functioning.\n", ahc_name(ahc)); 7032123579Sgibbs ahc_unpause(ahc); 7033123579Sgibbs return; 7034123579Sgibbs } 7035123579Sgibbs 7036123579Sgibbs restart_needed = 0; 7037123579Sgibbs printf("%s: Recovery Initiated\n", ahc_name(ahc)); 7038123579Sgibbs ahc_dump_card_state(ahc); 7039123579Sgibbs 7040123579Sgibbs last_phase = ahc_inb(ahc, LASTPHASE); 7041123579Sgibbs while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { 7042123579Sgibbs u_int active_scb_index; 7043123579Sgibbs u_int saved_scbptr; 7044123579Sgibbs int target; 7045123579Sgibbs int lun; 7046123579Sgibbs int i; 7047123579Sgibbs char channel; 7048123579Sgibbs 7049123579Sgibbs target = SCB_GET_TARGET(ahc, scb); 7050123579Sgibbs channel = SCB_GET_CHANNEL(ahc, scb); 7051123579Sgibbs lun = SCB_GET_LUN(scb); 7052123579Sgibbs 7053123579Sgibbs ahc_print_path(ahc, scb); 7054123579Sgibbs printf("SCB 0x%x - timed out\n", scb->hscb->tag); 7055123579Sgibbs if (scb->sg_count > 0) { 7056123579Sgibbs for (i = 0; i < scb->sg_count; i++) { 7057123579Sgibbs printf("sg[%d] - Addr 0x%x : Length %d\n", 7058123579Sgibbs i, 7059123579Sgibbs scb->sg_list[i].addr, 7060123579Sgibbs scb->sg_list[i].len & AHC_SG_LEN_MASK); 7061123579Sgibbs } 7062123579Sgibbs } 7063123579Sgibbs if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { 7064123579Sgibbs /* 7065123579Sgibbs * Been down this road before. 7066123579Sgibbs * Do a full bus reset. 7067123579Sgibbs */ 7068123579Sgibbs aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); 7069123579Sgibbsbus_reset: 7070123579Sgibbs found = ahc_reset_channel(ahc, channel, 7071123579Sgibbs /*Initiate Reset*/TRUE); 7072123579Sgibbs printf("%s: Issued Channel %c Bus Reset. " 7073123579Sgibbs "%d SCBs aborted\n", ahc_name(ahc), channel, 7074123579Sgibbs found); 7075123579Sgibbs continue; 7076123579Sgibbs } 7077123579Sgibbs 7078123579Sgibbs /* 7079123579Sgibbs * Remove the command from the timedout list in 7080123579Sgibbs * preparation for requeing it. 7081123579Sgibbs */ 7082123579Sgibbs LIST_REMOVE(scb, timedout_links); 7083123579Sgibbs scb->flags &= ~SCB_TIMEDOUT; 7084123579Sgibbs 7085123579Sgibbs /* 7086123579Sgibbs * If we are a target, transition to bus free and report 7087123579Sgibbs * the timeout. 7088123579Sgibbs * 7089123579Sgibbs * The target/initiator that is holding up the bus may not 7090123579Sgibbs * be the same as the one that triggered this timeout 7091123579Sgibbs * (different commands have different timeout lengths). 7092123579Sgibbs * If the bus is idle and we are actiing as the initiator 7093123579Sgibbs * for this request, queue a BDR message to the timed out 7094123579Sgibbs * target. Otherwise, if the timed out transaction is 7095123579Sgibbs * active: 7096123579Sgibbs * Initiator transaction: 7097123579Sgibbs * Stuff the message buffer with a BDR message and assert 7098123579Sgibbs * ATN in the hopes that the target will let go of the bus 7099123579Sgibbs * and go to the mesgout phase. If this fails, we'll 7100123579Sgibbs * get another timeout 2 seconds later which will attempt 7101123579Sgibbs * a bus reset. 7102123579Sgibbs * 7103123579Sgibbs * Target transaction: 7104123579Sgibbs * Transition to BUS FREE and report the error. 7105123579Sgibbs * It's good to be the target! 7106123579Sgibbs */ 7107123579Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 7108123579Sgibbs active_scb_index = ahc_inb(ahc, SCB_TAG); 7109123579Sgibbs 7110123579Sgibbs if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 7111123579Sgibbs && (active_scb_index < ahc->scb_data->numscbs)) { 7112123579Sgibbs struct scb *active_scb; 7113123579Sgibbs 7114123579Sgibbs /* 7115123579Sgibbs * If the active SCB is not us, assume that 7116123579Sgibbs * the active SCB has a longer timeout than 7117123579Sgibbs * the timedout SCB, and wait for the active 7118123579Sgibbs * SCB to timeout. 7119123579Sgibbs */ 7120123579Sgibbs active_scb = ahc_lookup_scb(ahc, active_scb_index); 7121123579Sgibbs if (active_scb != scb) { 7122129133Sgibbs if (ahc_other_scb_timeout(ahc, scb, 7123136711Sgibbs active_scb) == 0) 7124129133Sgibbs goto bus_reset; 7125123579Sgibbs continue; 7126123579Sgibbs } 7127123579Sgibbs 7128123579Sgibbs /* It's us */ 7129123579Sgibbs if ((scb->flags & SCB_TARGET_SCB) != 0) { 7130123579Sgibbs 7131123579Sgibbs /* 7132123579Sgibbs * Send back any queued up transactions 7133123579Sgibbs * and properly record the error condition. 7134123579Sgibbs */ 7135123579Sgibbs ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), 7136123579Sgibbs SCB_GET_CHANNEL(ahc, scb), 7137123579Sgibbs SCB_GET_LUN(scb), 7138123579Sgibbs scb->hscb->tag, 7139123579Sgibbs ROLE_TARGET, 7140123579Sgibbs CAM_CMD_TIMEOUT); 7141123579Sgibbs 7142123579Sgibbs /* Will clear us from the bus */ 7143123579Sgibbs restart_needed = 1; 7144123579Sgibbs break; 7145123579Sgibbs } 7146123579Sgibbs 7147123579Sgibbs ahc_set_recoveryscb(ahc, active_scb); 7148123579Sgibbs ahc_outb(ahc, MSG_OUT, HOST_MSG); 7149123579Sgibbs ahc_outb(ahc, SCSISIGO, last_phase|ATNO); 7150123579Sgibbs ahc_print_path(ahc, active_scb); 7151123579Sgibbs printf("BDR message in message buffer\n"); 7152123579Sgibbs active_scb->flags |= SCB_DEVICE_RESET; 7153137870Sgibbs aic_scb_timer_reset(scb, 2 * 1000); 7154123579Sgibbs } else if (last_phase != P_BUSFREE 7155123579Sgibbs && (ahc_inb(ahc, SSTAT1) & REQINIT) == 0) { 7156123579Sgibbs /* 7157123579Sgibbs * SCB is not identified, there 7158123579Sgibbs * is no pending REQ, and the sequencer 7159123579Sgibbs * has not seen a busfree. Looks like 7160123579Sgibbs * a stuck connection waiting to 7161123579Sgibbs * go busfree. Reset the bus. 7162123579Sgibbs */ 7163123579Sgibbs printf("%s: Connection stuck awaiting busfree or " 7164123579Sgibbs "Identify Msg.\n", ahc_name(ahc)); 7165123579Sgibbs goto bus_reset; 7166123579Sgibbs } else { 7167123579Sgibbs int disconnected; 7168123579Sgibbs 7169123579Sgibbs if (last_phase != P_BUSFREE 7170123579Sgibbs && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { 7171123579Sgibbs /* Hung target selection. Goto busfree */ 7172123579Sgibbs printf("%s: Hung target selection\n", 7173123579Sgibbs ahc_name(ahc)); 7174123579Sgibbs restart_needed = 1; 7175123579Sgibbs break; 7176123579Sgibbs } 7177123579Sgibbs 7178123579Sgibbs /* XXX Shouldn't panic. Just punt instead? */ 7179123579Sgibbs if ((scb->flags & SCB_TARGET_SCB) != 0) 7180123579Sgibbs panic("Timed-out target SCB but bus idle"); 7181123579Sgibbs 7182123579Sgibbs if (ahc_search_qinfifo(ahc, target, channel, lun, 7183123579Sgibbs scb->hscb->tag, ROLE_INITIATOR, 7184123579Sgibbs /*status*/0, SEARCH_COUNT) > 0) { 7185123579Sgibbs disconnected = FALSE; 7186123579Sgibbs } else { 7187123579Sgibbs disconnected = TRUE; 7188123579Sgibbs } 7189123579Sgibbs 7190123579Sgibbs if (disconnected) { 7191123579Sgibbs 7192123579Sgibbs ahc_set_recoveryscb(ahc, scb); 7193123579Sgibbs /* 7194123579Sgibbs * Actually re-queue this SCB in an attempt 7195123579Sgibbs * to select the device before it reconnects. 7196123579Sgibbs * In either case (selection or reselection), 7197123579Sgibbs * we will now issue a target reset to the 7198123579Sgibbs * timed-out device. 7199123579Sgibbs * 7200123579Sgibbs * Set the MK_MESSAGE control bit indicating 7201123579Sgibbs * that we desire to send a message. We 7202123579Sgibbs * also set the disconnected flag since 7203123579Sgibbs * in the paging case there is no guarantee 7204123579Sgibbs * that our SCB control byte matches the 7205123579Sgibbs * version on the card. We don't want the 7206123579Sgibbs * sequencer to abort the command thinking 7207123579Sgibbs * an unsolicited reselection occurred. 7208123579Sgibbs */ 7209123579Sgibbs scb->hscb->control |= MK_MESSAGE|DISCONNECTED; 7210123579Sgibbs scb->flags |= SCB_DEVICE_RESET; 7211123579Sgibbs 7212123579Sgibbs /* 7213123579Sgibbs * Remove any cached copy of this SCB in the 7214123579Sgibbs * disconnected list in preparation for the 7215123579Sgibbs * queuing of our abort SCB. We use the 7216123579Sgibbs * same element in the SCB, SCB_NEXT, for 7217123579Sgibbs * both the qinfifo and the disconnected list. 7218123579Sgibbs */ 7219123579Sgibbs ahc_search_disc_list(ahc, target, channel, 7220123579Sgibbs lun, scb->hscb->tag, 7221123579Sgibbs /*stop_on_first*/TRUE, 7222123579Sgibbs /*remove*/TRUE, 7223123579Sgibbs /*save_state*/FALSE); 7224123579Sgibbs 7225123579Sgibbs /* 7226123579Sgibbs * In the non-paging case, the sequencer will 7227123579Sgibbs * never re-reference the in-core SCB. 7228123579Sgibbs * To make sure we are notified during 7229123579Sgibbs * reslection, set the MK_MESSAGE flag in 7230123579Sgibbs * the card's copy of the SCB. 7231123579Sgibbs */ 7232123579Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) { 7233123579Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 7234123579Sgibbs ahc_outb(ahc, SCB_CONTROL, 7235123579Sgibbs ahc_inb(ahc, SCB_CONTROL) 7236123579Sgibbs | MK_MESSAGE); 7237123579Sgibbs } 7238123579Sgibbs 7239123579Sgibbs /* 7240123579Sgibbs * Clear out any entries in the QINFIFO first 7241123579Sgibbs * so we are the next SCB for this target 7242123579Sgibbs * to run. 7243123579Sgibbs */ 7244123579Sgibbs ahc_search_qinfifo(ahc, 7245123579Sgibbs SCB_GET_TARGET(ahc, scb), 7246123579Sgibbs channel, SCB_GET_LUN(scb), 7247123579Sgibbs SCB_LIST_NULL, 7248123579Sgibbs ROLE_INITIATOR, 7249123579Sgibbs CAM_REQUEUE_REQ, 7250123579Sgibbs SEARCH_COMPLETE); 7251123579Sgibbs ahc_print_path(ahc, scb); 7252123579Sgibbs printf("Queuing a BDR SCB\n"); 7253123579Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 7254123579Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 7255137870Sgibbs aic_scb_timer_reset(scb, 2 * 1000); 7256123579Sgibbs } else { 7257123579Sgibbs /* Go "immediatly" to the bus reset */ 7258123579Sgibbs /* This shouldn't happen */ 7259123579Sgibbs ahc_set_recoveryscb(ahc, scb); 7260123579Sgibbs ahc_print_path(ahc, scb); 7261123579Sgibbs printf("SCB %d: Immediate reset. " 7262123579Sgibbs "Flags = 0x%x\n", scb->hscb->tag, 7263123579Sgibbs scb->flags); 7264123579Sgibbs goto bus_reset; 7265123579Sgibbs } 7266123579Sgibbs } 7267123579Sgibbs break; 7268123579Sgibbs } 7269123579Sgibbs 7270123579Sgibbs /* 7271123579Sgibbs * Any remaining SCBs were not the "culprit", so remove 7272123579Sgibbs * them from the timeout list. The timer for these commands 7273123579Sgibbs * will be reset once the recovery SCB completes. 7274123579Sgibbs */ 7275123579Sgibbs while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { 7276123579Sgibbs 7277123579Sgibbs LIST_REMOVE(scb, timedout_links); 7278123579Sgibbs scb->flags &= ~SCB_TIMEDOUT; 7279123579Sgibbs } 7280123579Sgibbs 7281123579Sgibbs if (restart_needed) 7282123579Sgibbs ahc_restart(ahc); 7283123579Sgibbs else 7284123579Sgibbs ahc_unpause(ahc); 7285123579Sgibbs} 7286123579Sgibbs 728765942Sgibbs/************************* Target Mode ****************************************/ 728865942Sgibbs#ifdef AHC_TARGET_MODE 728965942Sgibbscam_status 729065942Sgibbsahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb, 729174972Sgibbs struct ahc_tmode_tstate **tstate, 729274972Sgibbs struct ahc_tmode_lstate **lstate, 729365942Sgibbs int notfound_failure) 729465942Sgibbs{ 729565942Sgibbs 729668087Sgibbs if ((ahc->features & AHC_TARGETMODE) == 0) 729765942Sgibbs return (CAM_REQ_INVALID); 729865942Sgibbs 729965942Sgibbs /* 730065942Sgibbs * Handle the 'black hole' device that sucks up 730165942Sgibbs * requests to unattached luns on enabled targets. 730265942Sgibbs */ 730365942Sgibbs if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD 730465942Sgibbs && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) { 730565942Sgibbs *tstate = NULL; 730665942Sgibbs *lstate = ahc->black_hole; 730765942Sgibbs } else { 730865942Sgibbs u_int max_id; 730965942Sgibbs 731065942Sgibbs max_id = (ahc->features & AHC_WIDE) ? 15 : 7; 731165942Sgibbs if (ccb->ccb_h.target_id > max_id) 731265942Sgibbs return (CAM_TID_INVALID); 731365942Sgibbs 731470204Sgibbs if (ccb->ccb_h.target_lun >= AHC_NUM_LUNS) 731565942Sgibbs return (CAM_LUN_INVALID); 731665942Sgibbs 731765942Sgibbs *tstate = ahc->enabled_targets[ccb->ccb_h.target_id]; 731865942Sgibbs *lstate = NULL; 731965942Sgibbs if (*tstate != NULL) 732065942Sgibbs *lstate = 732165942Sgibbs (*tstate)->enabled_luns[ccb->ccb_h.target_lun]; 732265942Sgibbs } 732365942Sgibbs 732465942Sgibbs if (notfound_failure != 0 && *lstate == NULL) 732565942Sgibbs return (CAM_PATH_INVALID); 732665942Sgibbs 732765942Sgibbs return (CAM_REQ_CMP); 732865942Sgibbs} 732965942Sgibbs 733065942Sgibbsvoid 733165942Sgibbsahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) 733265942Sgibbs{ 733374972Sgibbs struct ahc_tmode_tstate *tstate; 733474972Sgibbs struct ahc_tmode_lstate *lstate; 733565942Sgibbs struct ccb_en_lun *cel; 733665942Sgibbs cam_status status; 733765942Sgibbs u_int target; 733865942Sgibbs u_int lun; 733965942Sgibbs u_int target_mask; 7340102670Sgibbs u_int our_id; 7341114621Sgibbs int error; 734265942Sgibbs char channel; 734365942Sgibbs 734465942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, &lstate, 734568087Sgibbs /*notfound_failure*/FALSE); 734665942Sgibbs 734765942Sgibbs if (status != CAM_REQ_CMP) { 734865942Sgibbs ccb->ccb_h.status = status; 734965942Sgibbs return; 735065942Sgibbs } 735168087Sgibbs 7352102670Sgibbs if (cam_sim_bus(sim) == 0) 7353102670Sgibbs our_id = ahc->our_id; 7354102670Sgibbs else 7355102670Sgibbs our_id = ahc->our_id_b; 735668087Sgibbs 7357102670Sgibbs if (ccb->ccb_h.target_id != our_id) { 7358102670Sgibbs /* 7359102670Sgibbs * our_id represents our initiator ID, or 7360102670Sgibbs * the ID of the first target to have an 7361102670Sgibbs * enabled lun in target mode. There are 7362102670Sgibbs * two cases that may preclude enabling a 7363102670Sgibbs * target id other than our_id. 7364102670Sgibbs * 7365102670Sgibbs * o our_id is for an active initiator role. 7366102670Sgibbs * Since the hardware does not support 7367102670Sgibbs * reselections to the initiator role at 7368102670Sgibbs * anything other than our_id, and our_id 7369102670Sgibbs * is used by the hardware to indicate the 7370102670Sgibbs * ID to use for both select-out and 7371102670Sgibbs * reselect-out operations, the only target 7372102670Sgibbs * ID we can support in this mode is our_id. 7373102670Sgibbs * 7374102670Sgibbs * o The MULTARGID feature is not available and 7375102670Sgibbs * a previous target mode ID has been enabled. 7376102670Sgibbs */ 7377102670Sgibbs if ((ahc->features & AHC_MULTIROLE) != 0) { 737868087Sgibbs 737968087Sgibbs if ((ahc->features & AHC_MULTI_TID) != 0 738068087Sgibbs && (ahc->flags & AHC_INITIATORROLE) != 0) { 738168087Sgibbs /* 738268087Sgibbs * Only allow additional targets if 738368087Sgibbs * the initiator role is disabled. 738468087Sgibbs * The hardware cannot handle a re-select-in 738568087Sgibbs * on the initiator id during a re-select-out 738668087Sgibbs * on a different target id. 738768087Sgibbs */ 738868087Sgibbs status = CAM_TID_INVALID; 738968087Sgibbs } else if ((ahc->flags & AHC_INITIATORROLE) != 0 739068087Sgibbs || ahc->enabled_luns > 0) { 739168087Sgibbs /* 739268087Sgibbs * Only allow our target id to change 739368087Sgibbs * if the initiator role is not configured 739468087Sgibbs * and there are no enabled luns which 739568087Sgibbs * are attached to the currently registered 739668087Sgibbs * scsi id. 739768087Sgibbs */ 739868087Sgibbs status = CAM_TID_INVALID; 739968087Sgibbs } 7400102670Sgibbs } else if ((ahc->features & AHC_MULTI_TID) == 0 7401102670Sgibbs && ahc->enabled_luns > 0) { 7402102670Sgibbs 7403102670Sgibbs status = CAM_TID_INVALID; 740468087Sgibbs } 740568087Sgibbs } 740668087Sgibbs 740768087Sgibbs if (status != CAM_REQ_CMP) { 740868087Sgibbs ccb->ccb_h.status = status; 740968087Sgibbs return; 741068087Sgibbs } 741168087Sgibbs 741268087Sgibbs /* 741368087Sgibbs * We now have an id that is valid. 741468087Sgibbs * If we aren't in target mode, switch modes. 741568087Sgibbs */ 741668087Sgibbs if ((ahc->flags & AHC_TARGETROLE) == 0 741768087Sgibbs && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 7418114621Sgibbs ahc_flag saved_flags; 741968087Sgibbs 742068087Sgibbs printf("Configuring Target Mode\n"); 742168087Sgibbs if (LIST_FIRST(&ahc->pending_scbs) != NULL) { 742268087Sgibbs ccb->ccb_h.status = CAM_BUSY; 742368087Sgibbs return; 742468087Sgibbs } 7425114621Sgibbs saved_flags = ahc->flags; 742668087Sgibbs ahc->flags |= AHC_TARGETROLE; 742768087Sgibbs if ((ahc->features & AHC_MULTIROLE) == 0) 742868087Sgibbs ahc->flags &= ~AHC_INITIATORROLE; 742974094Sgibbs ahc_pause(ahc); 7430114621Sgibbs error = ahc_loadseq(ahc); 7431114621Sgibbs if (error != 0) { 7432114621Sgibbs /* 7433114621Sgibbs * Restore original configuration and notify 7434114621Sgibbs * the caller that we cannot support target mode. 7435114621Sgibbs * Since the adapter started out in this 7436114621Sgibbs * configuration, the firmware load will succeed, 7437114621Sgibbs * so there is no point in checking ahc_loadseq's 7438114621Sgibbs * return value. 7439114621Sgibbs */ 7440114621Sgibbs ahc->flags = saved_flags; 7441114621Sgibbs (void)ahc_loadseq(ahc); 7442115917Sgibbs ahc_restart(ahc); 7443114621Sgibbs ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 7444114621Sgibbs return; 7445114621Sgibbs } 7446115917Sgibbs ahc_restart(ahc); 744768087Sgibbs } 744865942Sgibbs cel = &ccb->cel; 744965942Sgibbs target = ccb->ccb_h.target_id; 745065942Sgibbs lun = ccb->ccb_h.target_lun; 745165942Sgibbs channel = SIM_CHANNEL(ahc, sim); 745265942Sgibbs target_mask = 0x01 << target; 745365942Sgibbs if (channel == 'B') 745465942Sgibbs target_mask <<= 8; 745565942Sgibbs 745665942Sgibbs if (cel->enable != 0) { 745765942Sgibbs u_int scsiseq; 745865942Sgibbs 745965942Sgibbs /* Are we already enabled?? */ 746065942Sgibbs if (lstate != NULL) { 746165942Sgibbs xpt_print_path(ccb->ccb_h.path); 746265942Sgibbs printf("Lun already enabled\n"); 746365942Sgibbs ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; 746465942Sgibbs return; 746565942Sgibbs } 746665942Sgibbs 746765942Sgibbs if (cel->grp6_len != 0 746865942Sgibbs || cel->grp7_len != 0) { 746965942Sgibbs /* 747065942Sgibbs * Don't (yet?) support vendor 747165942Sgibbs * specific commands. 747265942Sgibbs */ 747365942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 747465942Sgibbs printf("Non-zero Group Codes\n"); 747565942Sgibbs return; 747665942Sgibbs } 747765942Sgibbs 747865942Sgibbs /* 747965942Sgibbs * Seems to be okay. 748065942Sgibbs * Setup our data structures. 748165942Sgibbs */ 748265942Sgibbs if (target != CAM_TARGET_WILDCARD && tstate == NULL) { 748365942Sgibbs tstate = ahc_alloc_tstate(ahc, target, channel); 748465942Sgibbs if (tstate == NULL) { 748565942Sgibbs xpt_print_path(ccb->ccb_h.path); 748665942Sgibbs printf("Couldn't allocate tstate\n"); 748765942Sgibbs ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 748865942Sgibbs return; 748965942Sgibbs } 749065942Sgibbs } 749165942Sgibbs lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT); 749265942Sgibbs if (lstate == NULL) { 749365942Sgibbs xpt_print_path(ccb->ccb_h.path); 749465942Sgibbs printf("Couldn't allocate lstate\n"); 749565942Sgibbs ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 749665942Sgibbs return; 749765942Sgibbs } 749865942Sgibbs memset(lstate, 0, sizeof(*lstate)); 749965942Sgibbs status = xpt_create_path(&lstate->path, /*periph*/NULL, 750065942Sgibbs xpt_path_path_id(ccb->ccb_h.path), 750165942Sgibbs xpt_path_target_id(ccb->ccb_h.path), 750265942Sgibbs xpt_path_lun_id(ccb->ccb_h.path)); 750365942Sgibbs if (status != CAM_REQ_CMP) { 750465942Sgibbs free(lstate, M_DEVBUF); 750565942Sgibbs xpt_print_path(ccb->ccb_h.path); 750665942Sgibbs printf("Couldn't allocate path\n"); 750765942Sgibbs ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 750865942Sgibbs return; 750965942Sgibbs } 751065942Sgibbs SLIST_INIT(&lstate->accept_tios); 751165942Sgibbs SLIST_INIT(&lstate->immed_notifies); 751274094Sgibbs ahc_pause(ahc); 751365942Sgibbs if (target != CAM_TARGET_WILDCARD) { 751465942Sgibbs tstate->enabled_luns[lun] = lstate; 751565942Sgibbs ahc->enabled_luns++; 751665942Sgibbs 751765942Sgibbs if ((ahc->features & AHC_MULTI_TID) != 0) { 751865942Sgibbs u_int targid_mask; 751965942Sgibbs 752065942Sgibbs targid_mask = ahc_inb(ahc, TARGID) 752165942Sgibbs | (ahc_inb(ahc, TARGID + 1) << 8); 752265942Sgibbs 752365942Sgibbs targid_mask |= target_mask; 752465942Sgibbs ahc_outb(ahc, TARGID, targid_mask); 752565942Sgibbs ahc_outb(ahc, TARGID+1, (targid_mask >> 8)); 752665942Sgibbs 752765942Sgibbs ahc_update_scsiid(ahc, targid_mask); 752865942Sgibbs } else { 752965942Sgibbs u_int our_id; 753065942Sgibbs char channel; 753165942Sgibbs 753265942Sgibbs channel = SIM_CHANNEL(ahc, sim); 753365942Sgibbs our_id = SIM_SCSI_ID(ahc, sim); 753465942Sgibbs 753565942Sgibbs /* 753665942Sgibbs * This can only happen if selections 753765942Sgibbs * are not enabled 753865942Sgibbs */ 753965942Sgibbs if (target != our_id) { 754065942Sgibbs u_int sblkctl; 754165942Sgibbs char cur_channel; 754265942Sgibbs int swap; 754365942Sgibbs 754465942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 754565942Sgibbs cur_channel = (sblkctl & SELBUSB) 754665942Sgibbs ? 'B' : 'A'; 754765942Sgibbs if ((ahc->features & AHC_TWIN) == 0) 754865942Sgibbs cur_channel = 'A'; 754965942Sgibbs swap = cur_channel != channel; 755065942Sgibbs if (channel == 'A') 755165942Sgibbs ahc->our_id = target; 755265942Sgibbs else 755365942Sgibbs ahc->our_id_b = target; 755465942Sgibbs 755565942Sgibbs if (swap) 755665942Sgibbs ahc_outb(ahc, SBLKCTL, 755765942Sgibbs sblkctl ^ SELBUSB); 755865942Sgibbs 755965942Sgibbs ahc_outb(ahc, SCSIID, target); 756065942Sgibbs 756165942Sgibbs if (swap) 756265942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl); 756365942Sgibbs } 756465942Sgibbs } 756565942Sgibbs } else 756665942Sgibbs ahc->black_hole = lstate; 756765942Sgibbs /* Allow select-in operations */ 756865942Sgibbs if (ahc->black_hole != NULL && ahc->enabled_luns > 0) { 756965942Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); 757065942Sgibbs scsiseq |= ENSELI; 757165942Sgibbs ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq); 757265942Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ); 757365942Sgibbs scsiseq |= ENSELI; 757465942Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq); 757565942Sgibbs } 757674094Sgibbs ahc_unpause(ahc); 757765942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 757865942Sgibbs xpt_print_path(ccb->ccb_h.path); 757965942Sgibbs printf("Lun now enabled for target mode\n"); 758065942Sgibbs } else { 758165942Sgibbs struct scb *scb; 758265942Sgibbs int i, empty; 758365942Sgibbs 758465942Sgibbs if (lstate == NULL) { 758565942Sgibbs ccb->ccb_h.status = CAM_LUN_INVALID; 758665942Sgibbs return; 758765942Sgibbs } 758865942Sgibbs 758965942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 759065942Sgibbs LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { 759165942Sgibbs struct ccb_hdr *ccbh; 759265942Sgibbs 759365942Sgibbs ccbh = &scb->io_ctx->ccb_h; 759465942Sgibbs if (ccbh->func_code == XPT_CONT_TARGET_IO 759565942Sgibbs && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ 759665942Sgibbs printf("CTIO pending\n"); 759765942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 759865942Sgibbs return; 759965942Sgibbs } 760065942Sgibbs } 760165942Sgibbs 760265942Sgibbs if (SLIST_FIRST(&lstate->accept_tios) != NULL) { 760365942Sgibbs printf("ATIOs pending\n"); 760465942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 760565942Sgibbs } 760665942Sgibbs 760765942Sgibbs if (SLIST_FIRST(&lstate->immed_notifies) != NULL) { 760865942Sgibbs printf("INOTs pending\n"); 760965942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 761065942Sgibbs } 761165942Sgibbs 761265942Sgibbs if (ccb->ccb_h.status != CAM_REQ_CMP) { 761365942Sgibbs return; 761465942Sgibbs } 761565942Sgibbs 761665942Sgibbs xpt_print_path(ccb->ccb_h.path); 761765942Sgibbs printf("Target mode disabled\n"); 761865942Sgibbs xpt_free_path(lstate->path); 761965942Sgibbs free(lstate, M_DEVBUF); 762065942Sgibbs 762174094Sgibbs ahc_pause(ahc); 762265942Sgibbs /* Can we clean up the target too? */ 762365942Sgibbs if (target != CAM_TARGET_WILDCARD) { 762465942Sgibbs tstate->enabled_luns[lun] = NULL; 762565942Sgibbs ahc->enabled_luns--; 762665942Sgibbs for (empty = 1, i = 0; i < 8; i++) 762765942Sgibbs if (tstate->enabled_luns[i] != NULL) { 762865942Sgibbs empty = 0; 762965942Sgibbs break; 763065942Sgibbs } 763165942Sgibbs 763265942Sgibbs if (empty) { 763365942Sgibbs ahc_free_tstate(ahc, target, channel, 763465942Sgibbs /*force*/FALSE); 763565942Sgibbs if (ahc->features & AHC_MULTI_TID) { 763665942Sgibbs u_int targid_mask; 763765942Sgibbs 763865942Sgibbs targid_mask = ahc_inb(ahc, TARGID) 763965942Sgibbs | (ahc_inb(ahc, TARGID + 1) 764065942Sgibbs << 8); 764165942Sgibbs 764265942Sgibbs targid_mask &= ~target_mask; 764365942Sgibbs ahc_outb(ahc, TARGID, targid_mask); 764465942Sgibbs ahc_outb(ahc, TARGID+1, 764565942Sgibbs (targid_mask >> 8)); 764665942Sgibbs ahc_update_scsiid(ahc, targid_mask); 764765942Sgibbs } 764865942Sgibbs } 764965942Sgibbs } else { 765065942Sgibbs 765165942Sgibbs ahc->black_hole = NULL; 765265942Sgibbs 765365942Sgibbs /* 765465942Sgibbs * We can't allow selections without 765565942Sgibbs * our black hole device. 765665942Sgibbs */ 765765942Sgibbs empty = TRUE; 765865942Sgibbs } 765965942Sgibbs if (ahc->enabled_luns == 0) { 766065942Sgibbs /* Disallow select-in */ 766165942Sgibbs u_int scsiseq; 766265942Sgibbs 766365942Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); 766465942Sgibbs scsiseq &= ~ENSELI; 766565942Sgibbs ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq); 766665942Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ); 766765942Sgibbs scsiseq &= ~ENSELI; 766865942Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq); 766968087Sgibbs 767068087Sgibbs if ((ahc->features & AHC_MULTIROLE) == 0) { 767168087Sgibbs printf("Configuring Initiator Mode\n"); 767268087Sgibbs ahc->flags &= ~AHC_TARGETROLE; 767368087Sgibbs ahc->flags |= AHC_INITIATORROLE; 7674114621Sgibbs /* 7675114621Sgibbs * Returning to a configuration that 7676114621Sgibbs * fit previously will always succeed. 7677114621Sgibbs */ 7678114621Sgibbs (void)ahc_loadseq(ahc); 7679115917Sgibbs ahc_restart(ahc); 7680115917Sgibbs /* 7681115917Sgibbs * Unpaused. The extra unpause 7682115917Sgibbs * that follows is harmless. 7683115917Sgibbs */ 768468087Sgibbs } 768565942Sgibbs } 768674094Sgibbs ahc_unpause(ahc); 768765942Sgibbs } 768865942Sgibbs} 768965942Sgibbs 769065942Sgibbsstatic void 769165942Sgibbsahc_update_scsiid(struct ahc_softc *ahc, u_int targid_mask) 769265942Sgibbs{ 769365942Sgibbs u_int scsiid_mask; 769465942Sgibbs u_int scsiid; 769565942Sgibbs 769665942Sgibbs if ((ahc->features & AHC_MULTI_TID) == 0) 769765942Sgibbs panic("ahc_update_scsiid called on non-multitid unit\n"); 769865942Sgibbs 769965942Sgibbs /* 7700102670Sgibbs * Since we will rely on the TARGID mask 770165942Sgibbs * for selection enables, ensure that OID 770265942Sgibbs * in SCSIID is not set to some other ID 770365942Sgibbs * that we don't want to allow selections on. 770465942Sgibbs */ 770565942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 770665942Sgibbs scsiid = ahc_inb(ahc, SCSIID_ULTRA2); 770765942Sgibbs else 770865942Sgibbs scsiid = ahc_inb(ahc, SCSIID); 770965942Sgibbs scsiid_mask = 0x1 << (scsiid & OID); 771065942Sgibbs if ((targid_mask & scsiid_mask) == 0) { 771165942Sgibbs u_int our_id; 771265942Sgibbs 771365942Sgibbs /* ffs counts from 1 */ 771465942Sgibbs our_id = ffs(targid_mask); 771565942Sgibbs if (our_id == 0) 771665942Sgibbs our_id = ahc->our_id; 771765942Sgibbs else 771865942Sgibbs our_id--; 771965942Sgibbs scsiid &= TID; 772065942Sgibbs scsiid |= our_id; 772165942Sgibbs } 772265942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 772365942Sgibbs ahc_outb(ahc, SCSIID_ULTRA2, scsiid); 772465942Sgibbs else 772565942Sgibbs ahc_outb(ahc, SCSIID, scsiid); 772665942Sgibbs} 772765942Sgibbs 772865942Sgibbsvoid 772965942Sgibbsahc_run_tqinfifo(struct ahc_softc *ahc, int paused) 773065942Sgibbs{ 773165942Sgibbs struct target_cmd *cmd; 773265942Sgibbs 773365942Sgibbs /* 773465942Sgibbs * If the card supports auto-access pause, 773565942Sgibbs * we can access the card directly regardless 773665942Sgibbs * of whether it is paused or not. 773765942Sgibbs */ 773865942Sgibbs if ((ahc->features & AHC_AUTOPAUSE) != 0) 773965942Sgibbs paused = TRUE; 774065942Sgibbs 774179874Sgibbs ahc_sync_tqinfifo(ahc, BUS_DMASYNC_POSTREAD); 774265942Sgibbs while ((cmd = &ahc->targetcmds[ahc->tqinfifonext])->cmd_valid != 0) { 774365942Sgibbs 774465942Sgibbs /* 774565942Sgibbs * Only advance through the queue if we 774665942Sgibbs * have the resources to process the command. 774765942Sgibbs */ 774865942Sgibbs if (ahc_handle_target_cmd(ahc, cmd) != 0) 774965942Sgibbs break; 775065942Sgibbs 775179874Sgibbs cmd->cmd_valid = 0; 7752123579Sgibbs aic_dmamap_sync(ahc, ahc->shared_data_dmat, 775379874Sgibbs ahc->shared_data_dmamap, 775479874Sgibbs ahc_targetcmd_offset(ahc, ahc->tqinfifonext), 775579874Sgibbs sizeof(struct target_cmd), 775679874Sgibbs BUS_DMASYNC_PREREAD); 775765942Sgibbs ahc->tqinfifonext++; 775865942Sgibbs 775965942Sgibbs /* 776076634Sgibbs * Lazily update our position in the target mode incoming 776165942Sgibbs * command queue as seen by the sequencer. 776265942Sgibbs */ 776365942Sgibbs if ((ahc->tqinfifonext & (HOST_TQINPOS - 1)) == 1) { 776465942Sgibbs if ((ahc->features & AHC_HS_MAILBOX) != 0) { 776565942Sgibbs u_int hs_mailbox; 776665942Sgibbs 776765942Sgibbs hs_mailbox = ahc_inb(ahc, HS_MAILBOX); 776865942Sgibbs hs_mailbox &= ~HOST_TQINPOS; 776965942Sgibbs hs_mailbox |= ahc->tqinfifonext & HOST_TQINPOS; 777065942Sgibbs ahc_outb(ahc, HS_MAILBOX, hs_mailbox); 777165942Sgibbs } else { 777265942Sgibbs if (!paused) 777374094Sgibbs ahc_pause(ahc); 777465942Sgibbs ahc_outb(ahc, KERNEL_TQINPOS, 777565942Sgibbs ahc->tqinfifonext & HOST_TQINPOS); 777665942Sgibbs if (!paused) 777774094Sgibbs ahc_unpause(ahc); 777865942Sgibbs } 777965942Sgibbs } 778065942Sgibbs } 778165942Sgibbs} 778265942Sgibbs 778365942Sgibbsstatic int 778465942Sgibbsahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd) 778565942Sgibbs{ 778674972Sgibbs struct ahc_tmode_tstate *tstate; 778774972Sgibbs struct ahc_tmode_lstate *lstate; 778865942Sgibbs struct ccb_accept_tio *atio; 778965942Sgibbs uint8_t *byte; 779065942Sgibbs int initiator; 779165942Sgibbs int target; 779265942Sgibbs int lun; 779365942Sgibbs 779465942Sgibbs initiator = SCSIID_TARGET(ahc, cmd->scsiid); 779565942Sgibbs target = SCSIID_OUR_ID(cmd->scsiid); 779665942Sgibbs lun = (cmd->identify & MSG_IDENTIFY_LUNMASK); 779765942Sgibbs 779865942Sgibbs byte = cmd->bytes; 779965942Sgibbs tstate = ahc->enabled_targets[target]; 780065942Sgibbs lstate = NULL; 780165942Sgibbs if (tstate != NULL) 780265942Sgibbs lstate = tstate->enabled_luns[lun]; 780365942Sgibbs 780465942Sgibbs /* 780565942Sgibbs * Commands for disabled luns go to the black hole driver. 780665942Sgibbs */ 780765942Sgibbs if (lstate == NULL) 780865942Sgibbs lstate = ahc->black_hole; 780965942Sgibbs 781065942Sgibbs atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios); 781165942Sgibbs if (atio == NULL) { 781265942Sgibbs ahc->flags |= AHC_TQINFIFO_BLOCKED; 781365942Sgibbs /* 781465942Sgibbs * Wait for more ATIOs from the peripheral driver for this lun. 781565942Sgibbs */ 781695378Sgibbs if (bootverbose) 781795378Sgibbs printf("%s: ATIOs exhausted\n", ahc_name(ahc)); 781865942Sgibbs return (1); 781965942Sgibbs } else 782065942Sgibbs ahc->flags &= ~AHC_TQINFIFO_BLOCKED; 7821137871Sgibbs#ifdef AHC_DEBUG 7822137871Sgibbs if (ahc_debug & AHC_SHOW_TQIN) { 7823137871Sgibbs printf("Incoming command from %d for %d:%d%s\n", 7824137871Sgibbs initiator, target, lun, 7825137871Sgibbs lstate == ahc->black_hole ? "(Black Holed)" : ""); 7826137871Sgibbs } 782765942Sgibbs#endif 782865942Sgibbs SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle); 782965942Sgibbs 783065942Sgibbs if (lstate == ahc->black_hole) { 783165942Sgibbs /* Fill in the wildcards */ 783265942Sgibbs atio->ccb_h.target_id = target; 783365942Sgibbs atio->ccb_h.target_lun = lun; 783465942Sgibbs } 783565942Sgibbs 783665942Sgibbs /* 783765942Sgibbs * Package it up and send it off to 783865942Sgibbs * whomever has this lun enabled. 783965942Sgibbs */ 784065942Sgibbs atio->sense_len = 0; 784165942Sgibbs atio->init_id = initiator; 784265942Sgibbs if (byte[0] != 0xFF) { 784365942Sgibbs /* Tag was included */ 784465942Sgibbs atio->tag_action = *byte++; 784565942Sgibbs atio->tag_id = *byte++; 784665942Sgibbs atio->ccb_h.flags = CAM_TAG_ACTION_VALID; 784765942Sgibbs } else { 784865942Sgibbs atio->ccb_h.flags = 0; 784965942Sgibbs } 785065942Sgibbs byte++; 785165942Sgibbs 785265942Sgibbs /* Okay. Now determine the cdb size based on the command code */ 785365942Sgibbs switch (*byte >> CMD_GROUP_CODE_SHIFT) { 785465942Sgibbs case 0: 785565942Sgibbs atio->cdb_len = 6; 785665942Sgibbs break; 785765942Sgibbs case 1: 785865942Sgibbs case 2: 785965942Sgibbs atio->cdb_len = 10; 786065942Sgibbs break; 786165942Sgibbs case 4: 786265942Sgibbs atio->cdb_len = 16; 786365942Sgibbs break; 786465942Sgibbs case 5: 786565942Sgibbs atio->cdb_len = 12; 786665942Sgibbs break; 786765942Sgibbs case 3: 786865942Sgibbs default: 786965942Sgibbs /* Only copy the opcode. */ 787065942Sgibbs atio->cdb_len = 1; 787165942Sgibbs printf("Reserved or VU command code type encountered\n"); 787265942Sgibbs break; 787365942Sgibbs } 787465942Sgibbs 787565942Sgibbs memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len); 787665942Sgibbs 787765942Sgibbs atio->ccb_h.status |= CAM_CDB_RECVD; 787865942Sgibbs 787965942Sgibbs if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) { 788065942Sgibbs /* 788165942Sgibbs * We weren't allowed to disconnect. 788265942Sgibbs * We're hanging on the bus until a 788365942Sgibbs * continue target I/O comes in response 788465942Sgibbs * to this accept tio. 788565942Sgibbs */ 7886137871Sgibbs#ifdef AHC_DEBUG 7887137871Sgibbs if (ahc_debug & AHC_SHOW_TQIN) { 7888137871Sgibbs printf("Received Immediate Command %d:%d:%d - %p\n", 7889137871Sgibbs initiator, target, lun, ahc->pending_device); 7890137871Sgibbs } 789165942Sgibbs#endif 789265942Sgibbs ahc->pending_device = lstate; 7893123579Sgibbs aic_freeze_ccb((union ccb *)atio); 789465942Sgibbs atio->ccb_h.flags |= CAM_DIS_DISCONNECT; 789565942Sgibbs } 789665942Sgibbs xpt_done((union ccb*)atio); 789765942Sgibbs return (0); 789865942Sgibbs} 789965942Sgibbs 790065942Sgibbs#endif 7901