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: stable/10/sys/dev/aic7xxx/aic7xxx.c 315140 2017-03-12 06:20:28Z mav $"); 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}; 7655581Sgibbs 7774094Sgibbs/* 7874094Sgibbs * Hardware error codes. 7974094Sgibbs */ 8074094Sgibbsstruct ahc_hard_error_entry { 8174094Sgibbs uint8_t errno; 8274094Sgibbs char *errmesg; 8374094Sgibbs}; 8474094Sgibbs 8574094Sgibbsstatic struct ahc_hard_error_entry ahc_hard_errors[] = { 8665942Sgibbs { ILLHADDR, "Illegal Host Access" }, 8765942Sgibbs { ILLSADDR, "Illegal Sequencer Address referrenced" }, 8865942Sgibbs { ILLOPCODE, "Illegal Opcode in sequencer program" }, 8965942Sgibbs { SQPARERR, "Sequencer Parity Error" }, 9065942Sgibbs { DPARERR, "Data-path Parity Error" }, 9165942Sgibbs { MPARERR, "Scratch or SCB Memory Parity Error" }, 9265942Sgibbs { PCIERRSTAT, "PCI Error detected" }, 9365942Sgibbs { CIOPARERR, "CIOBUS Parity Error" }, 9465942Sgibbs}; 9574094Sgibbsstatic const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors); 9641646Sgibbs 9774094Sgibbsstatic struct ahc_phase_table_entry ahc_phase_table[] = 9865942Sgibbs{ 9965942Sgibbs { P_DATAOUT, MSG_NOOP, "in Data-out phase" }, 10065942Sgibbs { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" }, 10165942Sgibbs { P_DATAOUT_DT, MSG_NOOP, "in DT Data-out phase" }, 10265942Sgibbs { P_DATAIN_DT, MSG_INITIATOR_DET_ERR, "in DT Data-in phase" }, 10365942Sgibbs { P_COMMAND, MSG_NOOP, "in Command phase" }, 10465942Sgibbs { P_MESGOUT, MSG_NOOP, "in Message-out phase" }, 10565942Sgibbs { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" }, 10665942Sgibbs { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" }, 10765942Sgibbs { P_BUSFREE, MSG_NOOP, "while idle" }, 10865942Sgibbs { 0, MSG_NOOP, "in unknown phase" } 10939220Sgibbs}; 11039220Sgibbs 11165942Sgibbs/* 11265942Sgibbs * In most cases we only wish to itterate over real phases, so 11365942Sgibbs * exclude the last element from the count. 11465942Sgibbs */ 11574094Sgibbsstatic const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1; 11639220Sgibbs 11765942Sgibbs/* 11865942Sgibbs * Valid SCSIRATE values. (p. 3-17) 119300060Spfg * Provides a mapping of transfer periods in ns to the proper value to 12065942Sgibbs * stick in the scsixfer reg. 12165942Sgibbs */ 12274094Sgibbsstatic struct ahc_syncrate ahc_syncrates[] = 12365942Sgibbs{ 12465942Sgibbs /* ultra2 fast/ultra period rate */ 12565942Sgibbs { 0x42, 0x000, 9, "80.0" }, 12665942Sgibbs { 0x03, 0x000, 10, "40.0" }, 12765942Sgibbs { 0x04, 0x000, 11, "33.0" }, 12865942Sgibbs { 0x05, 0x100, 12, "20.0" }, 12965942Sgibbs { 0x06, 0x110, 15, "16.0" }, 13065942Sgibbs { 0x07, 0x120, 18, "13.4" }, 13165942Sgibbs { 0x08, 0x000, 25, "10.0" }, 13265942Sgibbs { 0x19, 0x010, 31, "8.0" }, 13365942Sgibbs { 0x1a, 0x020, 37, "6.67" }, 13465942Sgibbs { 0x1b, 0x030, 43, "5.7" }, 13565942Sgibbs { 0x1c, 0x040, 50, "5.0" }, 13665942Sgibbs { 0x00, 0x050, 56, "4.4" }, 13765942Sgibbs { 0x00, 0x060, 62, "4.0" }, 13865942Sgibbs { 0x00, 0x070, 68, "3.6" }, 13965942Sgibbs { 0x00, 0x000, 0, NULL } 14065942Sgibbs}; 14139220Sgibbs 14265942Sgibbs/* Our Sequencer Program */ 14365942Sgibbs#include "aic7xxx_seq.h" 14439220Sgibbs 14565942Sgibbs/**************************** Function Declarations ***************************/ 146114621Sgibbsstatic void ahc_force_renegotiation(struct ahc_softc *ahc, 147114621Sgibbs struct ahc_devinfo *devinfo); 14874972Sgibbsstatic struct ahc_tmode_tstate* 14965942Sgibbs ahc_alloc_tstate(struct ahc_softc *ahc, 15065942Sgibbs u_int scsi_id, char channel); 15170204Sgibbs#ifdef AHC_TARGET_MODE 15265942Sgibbsstatic void ahc_free_tstate(struct ahc_softc *ahc, 15365942Sgibbs u_int scsi_id, char channel, int force); 15470204Sgibbs#endif 15565942Sgibbsstatic struct ahc_syncrate* 15665942Sgibbs ahc_devlimited_syncrate(struct ahc_softc *ahc, 15768087Sgibbs struct ahc_initiator_tinfo *, 15865942Sgibbs u_int *period, 15968087Sgibbs u_int *ppr_options, 16068087Sgibbs role_t role); 16174972Sgibbsstatic void ahc_update_pending_scbs(struct ahc_softc *ahc); 16265942Sgibbsstatic void ahc_fetch_devinfo(struct ahc_softc *ahc, 16365942Sgibbs struct ahc_devinfo *devinfo); 16465942Sgibbsstatic void ahc_scb_devinfo(struct ahc_softc *ahc, 16565942Sgibbs struct ahc_devinfo *devinfo, 16665942Sgibbs struct scb *scb); 16776634Sgibbsstatic void ahc_assert_atn(struct ahc_softc *ahc); 16865942Sgibbsstatic void ahc_setup_initiator_msgout(struct ahc_softc *ahc, 16965942Sgibbs struct ahc_devinfo *devinfo, 17065942Sgibbs struct scb *scb); 17165942Sgibbsstatic void ahc_build_transfer_msg(struct ahc_softc *ahc, 17265942Sgibbs struct ahc_devinfo *devinfo); 17365942Sgibbsstatic void ahc_construct_sdtr(struct ahc_softc *ahc, 17466647Sgibbs struct ahc_devinfo *devinfo, 17565942Sgibbs u_int period, u_int offset); 17665942Sgibbsstatic void ahc_construct_wdtr(struct ahc_softc *ahc, 17766647Sgibbs struct ahc_devinfo *devinfo, 17865942Sgibbs u_int bus_width); 17965942Sgibbsstatic void ahc_construct_ppr(struct ahc_softc *ahc, 18066647Sgibbs struct ahc_devinfo *devinfo, 18165942Sgibbs u_int period, u_int offset, 18265942Sgibbs u_int bus_width, u_int ppr_options); 18365942Sgibbsstatic void ahc_clear_msg_state(struct ahc_softc *ahc); 184107420Sscottlstatic void ahc_handle_proto_violation(struct ahc_softc *ahc); 18565942Sgibbsstatic void ahc_handle_message_phase(struct ahc_softc *ahc); 18670204Sgibbstypedef enum { 18770204Sgibbs AHCMSG_1B, 18870204Sgibbs AHCMSG_2B, 18970204Sgibbs AHCMSG_EXT 19070204Sgibbs} ahc_msgtype; 19170204Sgibbsstatic int ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, 19270204Sgibbs u_int msgval, int full); 19365942Sgibbsstatic int ahc_parse_msg(struct ahc_softc *ahc, 19465942Sgibbs struct ahc_devinfo *devinfo); 19565942Sgibbsstatic int ahc_handle_msg_reject(struct ahc_softc *ahc, 19665942Sgibbs struct ahc_devinfo *devinfo); 19765942Sgibbsstatic void ahc_handle_ign_wide_residue(struct ahc_softc *ahc, 19865942Sgibbs struct ahc_devinfo *devinfo); 19979874Sgibbsstatic void ahc_reinitialize_dataptrs(struct ahc_softc *ahc); 20065942Sgibbsstatic void ahc_handle_devreset(struct ahc_softc *ahc, 20165942Sgibbs struct ahc_devinfo *devinfo, 20265942Sgibbs cam_status status, char *message, 20365942Sgibbs int verbose_level); 204115337Sgibbs#ifdef AHC_TARGET_MODE 20574972Sgibbsstatic void ahc_setup_target_msgin(struct ahc_softc *ahc, 20674972Sgibbs struct ahc_devinfo *devinfo, 20774972Sgibbs struct scb *scb); 20876634Sgibbs#endif 20939220Sgibbs 21065942Sgibbsstatic bus_dmamap_callback_t ahc_dmamap_cb; 21170204Sgibbsstatic void ahc_build_free_scb_list(struct ahc_softc *ahc); 21265942Sgibbsstatic int ahc_init_scbdata(struct ahc_softc *ahc); 21365942Sgibbsstatic void ahc_fini_scbdata(struct ahc_softc *ahc); 21468087Sgibbsstatic void ahc_qinfifo_requeue(struct ahc_softc *ahc, 21568087Sgibbs struct scb *prev_scb, 21668087Sgibbs struct scb *scb); 21768087Sgibbsstatic int ahc_qinfifo_count(struct ahc_softc *ahc); 21865942Sgibbsstatic u_int ahc_rem_scb_from_disc_list(struct ahc_softc *ahc, 21965942Sgibbs u_int prev, u_int scbptr); 22065942Sgibbsstatic void ahc_add_curscb_to_free_list(struct ahc_softc *ahc); 22165942Sgibbsstatic u_int ahc_rem_wscb(struct ahc_softc *ahc, 22265942Sgibbs u_int scbpos, u_int prev); 22365942Sgibbsstatic void ahc_reset_current_bus(struct ahc_softc *ahc); 22465942Sgibbs#ifdef AHC_DUMP_SEQ 22565942Sgibbsstatic void ahc_dumpseq(struct ahc_softc *ahc); 22665942Sgibbs#endif 227114621Sgibbsstatic int ahc_loadseq(struct ahc_softc *ahc); 22865942Sgibbsstatic int ahc_check_patch(struct ahc_softc *ahc, 22965942Sgibbs struct patch **start_patch, 23065942Sgibbs u_int start_instr, u_int *skip_addr); 23165942Sgibbsstatic void ahc_download_instr(struct ahc_softc *ahc, 23265942Sgibbs u_int instrptr, uint8_t *dconsts); 233129133Sgibbsstatic int ahc_other_scb_timeout(struct ahc_softc *ahc, 234129133Sgibbs struct scb *scb, 235129133Sgibbs struct scb *other_scb); 23665942Sgibbs#ifdef AHC_TARGET_MODE 23765942Sgibbsstatic void ahc_queue_lstate_event(struct ahc_softc *ahc, 23874972Sgibbs struct ahc_tmode_lstate *lstate, 23965942Sgibbs u_int initiator_id, 24065942Sgibbs u_int event_type, 24165942Sgibbs u_int event_arg); 24265942Sgibbsstatic void ahc_update_scsiid(struct ahc_softc *ahc, 24365942Sgibbs u_int targid_mask); 24465942Sgibbsstatic int ahc_handle_target_cmd(struct ahc_softc *ahc, 24565942Sgibbs struct target_cmd *cmd); 24665942Sgibbs#endif 24765942Sgibbs/************************* Sequencer Execution Control ************************/ 24839220Sgibbs/* 24939220Sgibbs * Restart the sequencer program from address zero 25039220Sgibbs */ 25165942Sgibbsvoid 25274094Sgibbsahc_restart(struct ahc_softc *ahc) 25339220Sgibbs{ 25468087Sgibbs 25574094Sgibbs ahc_pause(ahc); 25674094Sgibbs 25795378Sgibbs /* No more pending messages. */ 25895378Sgibbs ahc_clear_msg_state(ahc); 25995378Sgibbs 26065942Sgibbs ahc_outb(ahc, SCSISIGO, 0); /* De-assert BSY */ 26165942Sgibbs ahc_outb(ahc, MSG_OUT, MSG_NOOP); /* No message to send */ 26265942Sgibbs ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); 26395378Sgibbs ahc_outb(ahc, LASTPHASE, P_BUSFREE); 26495378Sgibbs ahc_outb(ahc, SAVED_SCSIID, 0xFF); 26595378Sgibbs ahc_outb(ahc, SAVED_LUN, 0xFF); 26668087Sgibbs 26766845Sgibbs /* 26866845Sgibbs * Ensure that the sequencer's idea of TQINPOS 26966845Sgibbs * matches our own. The sequencer increments TQINPOS 27066845Sgibbs * only after it sees a DMA complete and a reset could 27166845Sgibbs * occur before the increment leaving the kernel to believe 27266845Sgibbs * the command arrived but the sequencer to not. 27366845Sgibbs */ 27466845Sgibbs ahc_outb(ahc, TQINPOS, ahc->tqinfifonext); 27566845Sgibbs 27665942Sgibbs /* Always allow reselection */ 27765942Sgibbs ahc_outb(ahc, SCSISEQ, 27865942Sgibbs ahc_inb(ahc, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); 27965942Sgibbs if ((ahc->features & AHC_CMD_CHAN) != 0) { 28065942Sgibbs /* Ensure that no DMA operations are in progress */ 28168402Sgibbs ahc_outb(ahc, CCSCBCNT, 0); 28265942Sgibbs ahc_outb(ahc, CCSGCTL, 0); 28365942Sgibbs ahc_outb(ahc, CCSCBCTL, 0); 28465942Sgibbs } 28574094Sgibbs /* 28674094Sgibbs * If we were in the process of DMA'ing SCB data into 28774094Sgibbs * an SCB, replace that SCB on the free list. This prevents 28874094Sgibbs * an SCB leak. 28974094Sgibbs */ 29074094Sgibbs if ((ahc_inb(ahc, SEQ_FLAGS2) & SCB_DMA) != 0) { 29174094Sgibbs ahc_add_curscb_to_free_list(ahc); 29274094Sgibbs ahc_outb(ahc, SEQ_FLAGS2, 29374094Sgibbs ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA); 29474094Sgibbs } 295129133Sgibbs 296129133Sgibbs /* 297129133Sgibbs * Clear any pending sequencer interrupt. It is no 298129133Sgibbs * longer relevant since we're resetting the Program 299129133Sgibbs * Counter. 300129133Sgibbs */ 301129133Sgibbs ahc_outb(ahc, CLRINT, CLRSEQINT); 302129133Sgibbs 30365942Sgibbs ahc_outb(ahc, MWI_RESIDUAL, 0); 304115332Sgibbs ahc_outb(ahc, SEQCTL, ahc->seqctl); 30568087Sgibbs ahc_outb(ahc, SEQADDR0, 0); 30668087Sgibbs ahc_outb(ahc, SEQADDR1, 0); 307129133Sgibbs 30874094Sgibbs ahc_unpause(ahc); 30939220Sgibbs} 31039220Sgibbs 31165942Sgibbs/************************* Input/Output Queues ********************************/ 31265942Sgibbsvoid 31349933Sgibbsahc_run_qoutfifo(struct ahc_softc *ahc) 31449933Sgibbs{ 31549933Sgibbs struct scb *scb; 31649933Sgibbs u_int scb_index; 31749933Sgibbs 31879874Sgibbs ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); 31949933Sgibbs while (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) { 32065942Sgibbs 32149933Sgibbs scb_index = ahc->qoutfifo[ahc->qoutfifonext]; 32265942Sgibbs if ((ahc->qoutfifonext & 0x03) == 0x03) { 32365942Sgibbs u_int modnext; 32449933Sgibbs 32565942Sgibbs /* 32665942Sgibbs * Clear 32bits of QOUTFIFO at a time 32776634Sgibbs * so that we don't clobber an incoming 32865942Sgibbs * byte DMA to the array on architectures 32965942Sgibbs * that only support 32bit load and store 33065942Sgibbs * operations. 33165942Sgibbs */ 33265942Sgibbs modnext = ahc->qoutfifonext & ~0x3; 33365942Sgibbs *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL; 334123579Sgibbs aic_dmamap_sync(ahc, ahc->shared_data_dmat, 33579874Sgibbs ahc->shared_data_dmamap, 33679874Sgibbs /*offset*/modnext, /*len*/4, 33779874Sgibbs BUS_DMASYNC_PREREAD); 33865942Sgibbs } 33965942Sgibbs ahc->qoutfifonext++; 34065942Sgibbs 34166647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 34266647Sgibbs if (scb == NULL) { 34349933Sgibbs printf("%s: WARNING no command for scb %d " 34449933Sgibbs "(cmdcmplt)\nQOUTPOS = %d\n", 34549933Sgibbs ahc_name(ahc), scb_index, 346102670Sgibbs (ahc->qoutfifonext - 1) & 0xFF); 34749933Sgibbs continue; 34849933Sgibbs } 34949933Sgibbs 35049933Sgibbs /* 35149933Sgibbs * Save off the residual 35249933Sgibbs * if there is one. 35349933Sgibbs */ 35495378Sgibbs ahc_update_residual(ahc, scb); 35549933Sgibbs ahc_done(ahc, scb); 35649933Sgibbs } 35749933Sgibbs} 35849933Sgibbs 35965942Sgibbsvoid 36065942Sgibbsahc_run_untagged_queues(struct ahc_softc *ahc) 36145965Sgibbs{ 36263457Sgibbs int i; 36363457Sgibbs 36465942Sgibbs for (i = 0; i < 16; i++) 36565942Sgibbs ahc_run_untagged_queue(ahc, &ahc->untagged_queues[i]); 36639220Sgibbs} 36739220Sgibbs 36863457Sgibbsvoid 36965942Sgibbsahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue) 37063457Sgibbs{ 37165942Sgibbs struct scb *scb; 37263457Sgibbs 37365942Sgibbs if (ahc->untagged_queue_lock != 0) 37465942Sgibbs return; 37539220Sgibbs 37665942Sgibbs if ((scb = TAILQ_FIRST(queue)) != NULL 37765942Sgibbs && (scb->flags & SCB_ACTIVE) == 0) { 37865942Sgibbs scb->flags |= SCB_ACTIVE; 379133911Sgibbs /* 380133911Sgibbs * Timers are disabled while recovery is in progress. 381133911Sgibbs */ 382129133Sgibbs aic_scb_timer_start(scb); 38365942Sgibbs ahc_queue_scb(ahc, scb); 38439220Sgibbs } 38539220Sgibbs} 38639220Sgibbs 38765942Sgibbs/************************* Interrupt Handling *********************************/ 38839220Sgibbsvoid 38965942Sgibbsahc_handle_brkadrint(struct ahc_softc *ahc) 39039220Sgibbs{ 39145965Sgibbs /* 39265942Sgibbs * We upset the sequencer :-( 39365942Sgibbs * Lookup the error message 39445965Sgibbs */ 39574094Sgibbs int i; 39674094Sgibbs int error; 39745965Sgibbs 39865942Sgibbs error = ahc_inb(ahc, ERROR); 39965942Sgibbs for (i = 0; error != 1 && i < num_errors; i++) 40065942Sgibbs error >>= 1; 40168087Sgibbs printf("%s: brkadrint, %s at seqaddr = 0x%x\n", 40274094Sgibbs ahc_name(ahc), ahc_hard_errors[i].errmesg, 40368087Sgibbs ahc_inb(ahc, SEQADDR0) | 40468087Sgibbs (ahc_inb(ahc, SEQADDR1) << 8)); 40545965Sgibbs 40668087Sgibbs ahc_dump_card_state(ahc); 40768087Sgibbs 408114621Sgibbs /* Tell everyone that this HBA is no longer available */ 40965942Sgibbs ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS, 41065942Sgibbs CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN, 41165942Sgibbs CAM_NO_HBA); 41268623Sgibbs 41368623Sgibbs /* Disable all interrupt sources by resetting the controller */ 41468623Sgibbs ahc_shutdown(ahc); 41545965Sgibbs} 41645965Sgibbs 41739220Sgibbsvoid 41839506Sgibbsahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) 41939220Sgibbs{ 42039220Sgibbs struct scb *scb; 42139220Sgibbs struct ahc_devinfo devinfo; 42239220Sgibbs 42339220Sgibbs ahc_fetch_devinfo(ahc, &devinfo); 42439220Sgibbs 42539220Sgibbs /* 42639220Sgibbs * Clear the upper byte that holds SEQINT status 42739220Sgibbs * codes and clear the SEQINT bit. We will unpause 42839220Sgibbs * the sequencer, if appropriate, after servicing 42939220Sgibbs * the request. 43039220Sgibbs */ 43139220Sgibbs ahc_outb(ahc, CLRINT, CLRSEQINT); 43239220Sgibbs switch (intstat & SEQINT_MASK) { 43339220Sgibbs case BAD_STATUS: 43439220Sgibbs { 43539506Sgibbs u_int scb_index; 43639506Sgibbs struct hardware_scb *hscb; 43766647Sgibbs 43839220Sgibbs /* 43966647Sgibbs * Set the default return value to 0 (don't 44066647Sgibbs * send sense). The sense code will change 44166647Sgibbs * this if needed. 44266647Sgibbs */ 44366647Sgibbs ahc_outb(ahc, RETURN_1, 0); 44466647Sgibbs 44566647Sgibbs /* 44639220Sgibbs * The sequencer will notify us when a command 44739220Sgibbs * has an error that would be of interest to 44839220Sgibbs * the kernel. This allows us to leave the sequencer 44939220Sgibbs * running in the common case of command completes 45039220Sgibbs * without error. The sequencer will already have 45139220Sgibbs * dma'd the SCB back up to us, so we can reference 45239220Sgibbs * the in kernel copy directly. 45339220Sgibbs */ 45439220Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 45566647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 45666647Sgibbs if (scb == NULL) { 457102670Sgibbs ahc_print_devinfo(ahc, &devinfo); 458102670Sgibbs printf("ahc_intr - referenced scb " 45939220Sgibbs "not valid during seqint 0x%x scb(%d)\n", 460102670Sgibbs intstat, scb_index); 46168087Sgibbs ahc_dump_card_state(ahc); 46268087Sgibbs panic("for safety"); 46339220Sgibbs goto unpause; 46439220Sgibbs } 46539220Sgibbs 46647433Sgibbs hscb = scb->hscb; 46747433Sgibbs 46839220Sgibbs /* Don't want to clobber the original sense code */ 46939220Sgibbs if ((scb->flags & SCB_SENSE) != 0) { 47039220Sgibbs /* 47139220Sgibbs * Clear the SCB_SENSE Flag and have 47239220Sgibbs * the sequencer do a normal command 47339220Sgibbs * complete. 47439220Sgibbs */ 47539220Sgibbs scb->flags &= ~SCB_SENSE; 476123579Sgibbs aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); 47739220Sgibbs break; 47839220Sgibbs } 479123579Sgibbs aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); 48063457Sgibbs /* Freeze the queue until the client sees the error. */ 48165942Sgibbs ahc_freeze_devq(ahc, scb); 482123579Sgibbs aic_freeze_scb(scb); 483123579Sgibbs aic_set_scsi_status(scb, hscb->shared_data.status.scsi_status); 48465942Sgibbs switch (hscb->shared_data.status.scsi_status) { 48539220Sgibbs case SCSI_STATUS_OK: 48639220Sgibbs printf("%s: Interrupted for staus of 0???\n", 48739220Sgibbs ahc_name(ahc)); 48839220Sgibbs break; 48939220Sgibbs case SCSI_STATUS_CMD_TERMINATED: 49039220Sgibbs case SCSI_STATUS_CHECK_COND: 49174972Sgibbs { 49274972Sgibbs struct ahc_dma_seg *sg; 49374972Sgibbs struct scsi_sense *sc; 49474972Sgibbs struct ahc_initiator_tinfo *targ_info; 49574972Sgibbs struct ahc_tmode_tstate *tstate; 49674972Sgibbs struct ahc_transinfo *tinfo; 49739220Sgibbs#ifdef AHC_DEBUG 498102670Sgibbs if (ahc_debug & AHC_SHOW_SENSE) { 49965942Sgibbs ahc_print_path(ahc, scb); 50039220Sgibbs printf("SCB %d: requests Check Status\n", 50139220Sgibbs scb->hscb->tag); 50239220Sgibbs } 50339220Sgibbs#endif 50465942Sgibbs 505123579Sgibbs if (aic_perform_autosense(scb) == 0) 50674972Sgibbs break; 50739220Sgibbs 50874972Sgibbs targ_info = ahc_fetch_transinfo(ahc, 50963457Sgibbs devinfo.channel, 51063457Sgibbs devinfo.our_scsiid, 51163457Sgibbs devinfo.target, 51263457Sgibbs &tstate); 51376634Sgibbs tinfo = &targ_info->curr; 51474972Sgibbs sg = scb->sg_list; 51574972Sgibbs sc = (struct scsi_sense *)(&hscb->shared_data.cdb); 51674972Sgibbs /* 51774972Sgibbs * Save off the residual if there is one. 51874972Sgibbs */ 51995378Sgibbs ahc_update_residual(ahc, scb); 52039220Sgibbs#ifdef AHC_DEBUG 521102670Sgibbs if (ahc_debug & AHC_SHOW_SENSE) { 52274972Sgibbs ahc_print_path(ahc, scb); 52374972Sgibbs printf("Sending Sense\n"); 52474972Sgibbs } 52539220Sgibbs#endif 52674972Sgibbs sg->addr = ahc_get_sense_bufaddr(ahc, scb); 527123579Sgibbs sg->len = aic_get_sense_bufsize(ahc, scb); 52874972Sgibbs sg->len |= AHC_DMA_LAST_SEG; 52945965Sgibbs 53074972Sgibbs /* Fixup byte order */ 531123579Sgibbs sg->addr = aic_htole32(sg->addr); 532123579Sgibbs sg->len = aic_htole32(sg->len); 53370693Sgibbs 53474972Sgibbs sc->opcode = REQUEST_SENSE; 53574972Sgibbs sc->byte2 = 0; 53674972Sgibbs if (tinfo->protocol_version <= SCSI_REV_2 53774972Sgibbs && SCB_GET_LUN(scb) < 8) 53874972Sgibbs sc->byte2 = SCB_GET_LUN(scb) << 5; 53974972Sgibbs sc->unused[0] = 0; 54074972Sgibbs sc->unused[1] = 0; 54174972Sgibbs sc->length = sg->len; 54274972Sgibbs sc->control = 0; 54339220Sgibbs 54474972Sgibbs /* 54574972Sgibbs * We can't allow the target to disconnect. 54674972Sgibbs * This will be an untagged transaction and 54774972Sgibbs * having the target disconnect will make this 54874972Sgibbs * transaction indestinguishable from outstanding 54974972Sgibbs * tagged transactions. 55074972Sgibbs */ 55174972Sgibbs hscb->control = 0; 55241646Sgibbs 55374972Sgibbs /* 55474972Sgibbs * This request sense could be because the 55574972Sgibbs * the device lost power or in some other 55674972Sgibbs * way has lost our transfer negotiations. 55774972Sgibbs * Renegotiate if appropriate. Unit attention 55874972Sgibbs * errors will be reported before any data 55974972Sgibbs * phases occur. 56074972Sgibbs */ 561123579Sgibbs if (aic_get_residual(scb) 562123579Sgibbs == aic_get_transfer_length(scb)) { 56374972Sgibbs ahc_update_neg_request(ahc, &devinfo, 56474972Sgibbs tstate, targ_info, 565107420Sscottl AHC_NEG_IF_NON_ASYNC); 56674972Sgibbs } 56774972Sgibbs if (tstate->auto_negotiate & devinfo.target_mask) { 56874972Sgibbs hscb->control |= MK_MESSAGE; 56974972Sgibbs scb->flags &= ~SCB_NEGOTIATE; 57074972Sgibbs scb->flags |= SCB_AUTO_NEGOTIATE; 57174972Sgibbs } 57274972Sgibbs hscb->cdb_len = sizeof(*sc); 57374972Sgibbs hscb->dataptr = sg->addr; 57474972Sgibbs hscb->datacnt = sg->len; 57574972Sgibbs hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; 576123579Sgibbs hscb->sgptr = aic_htole32(hscb->sgptr); 57774972Sgibbs scb->sg_count = 1; 57874972Sgibbs scb->flags |= SCB_SENSE; 57974972Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 58074972Sgibbs ahc_outb(ahc, RETURN_1, SEND_SENSE); 58174972Sgibbs /* 58274972Sgibbs * Ensure we have enough time to actually 583133911Sgibbs * retrieve the sense, but only schedule 584133911Sgibbs * the timer if we are not in recovery or 585133911Sgibbs * this is a recovery SCB that is allowed 586133911Sgibbs * to have an active timer. 58774972Sgibbs */ 588133911Sgibbs if (ahc->scb_data->recovery_scbs == 0 589133911Sgibbs || (scb->flags & SCB_RECOVERY_SCB) != 0) 590137870Sgibbs aic_scb_timer_reset(scb, 5 * 1000); 59139220Sgibbs break; 59274972Sgibbs } 59363457Sgibbs default: 59439220Sgibbs break; 59539220Sgibbs } 59639220Sgibbs break; 59739220Sgibbs } 59863457Sgibbs case NO_MATCH: 59942652Sgibbs { 60063457Sgibbs /* Ensure we don't leave the selection hardware on */ 60163457Sgibbs ahc_outb(ahc, SCSISEQ, 60263457Sgibbs ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); 60363457Sgibbs 60463457Sgibbs printf("%s:%c:%d: no active SCB for reconnecting " 60563457Sgibbs "target - issuing BUS DEVICE RESET\n", 60663457Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target); 60763457Sgibbs printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " 60868087Sgibbs "ARG_1 == 0x%x ACCUM = 0x%x\n", 60963457Sgibbs ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), 61068087Sgibbs ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); 61168087Sgibbs printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " 61268087Sgibbs "SINDEX == 0x%x\n", 61368087Sgibbs ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), 61468087Sgibbs ahc_index_busy_tcl(ahc, 61568087Sgibbs BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID), 61670204Sgibbs ahc_inb(ahc, SAVED_LUN))), 61770204Sgibbs ahc_inb(ahc, SINDEX)); 61868087Sgibbs printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " 61968087Sgibbs "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", 62068087Sgibbs ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), 62168087Sgibbs ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), 62268087Sgibbs ahc_inb(ahc, SCB_CONTROL)); 62371390Sgibbs printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", 62471390Sgibbs ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); 62571390Sgibbs printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); 62671390Sgibbs printf("SEQCTL == 0x%x\n", ahc_inb(ahc, SEQCTL)); 62768087Sgibbs ahc_dump_card_state(ahc); 62863457Sgibbs ahc->msgout_buf[0] = MSG_BUS_DEV_RESET; 62963457Sgibbs ahc->msgout_len = 1; 63063457Sgibbs ahc->msgout_index = 0; 63163457Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 63263457Sgibbs ahc_outb(ahc, MSG_OUT, HOST_MSG); 63376634Sgibbs ahc_assert_atn(ahc); 63442652Sgibbs break; 63542652Sgibbs } 63663457Sgibbs case SEND_REJECT: 63763457Sgibbs { 63863457Sgibbs u_int rejbyte = ahc_inb(ahc, ACCUM); 63963457Sgibbs printf("%s:%c:%d: Warning - unknown message received from " 64063457Sgibbs "target (0x%x). Rejecting\n", 64163457Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, rejbyte); 64263457Sgibbs break; 64363457Sgibbs } 644107420Sscottl case PROTO_VIOLATION: 64563457Sgibbs { 646107420Sscottl ahc_handle_proto_violation(ahc); 647107420Sscottl break; 64863457Sgibbs } 64963457Sgibbs case IGN_WIDE_RES: 65063457Sgibbs ahc_handle_ign_wide_residue(ahc, &devinfo); 65163457Sgibbs break; 65279874Sgibbs case PDATA_REINIT: 65379874Sgibbs ahc_reinitialize_dataptrs(ahc); 65479874Sgibbs break; 65563457Sgibbs case BAD_PHASE: 65663457Sgibbs { 65763457Sgibbs u_int lastphase; 65863457Sgibbs 65963457Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 66068579Sgibbs printf("%s:%c:%d: unknown scsi bus phase %x, " 66168579Sgibbs "lastphase = 0x%x. Attempting to continue\n", 66268579Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, 66368579Sgibbs lastphase, ahc_inb(ahc, SCSISIGI)); 66468579Sgibbs break; 66563457Sgibbs } 66668579Sgibbs case MISSED_BUSFREE: 66768579Sgibbs { 66868579Sgibbs u_int lastphase; 66968579Sgibbs 67068579Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 67168579Sgibbs printf("%s:%c:%d: Missed busfree. " 67268579Sgibbs "Lastphase = 0x%x, Curphase = 0x%x\n", 67368579Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, 67468579Sgibbs lastphase, ahc_inb(ahc, SCSISIGI)); 67574094Sgibbs ahc_restart(ahc); 67668579Sgibbs return; 67768579Sgibbs } 67841646Sgibbs case HOST_MSG_LOOP: 67939220Sgibbs { 68039220Sgibbs /* 68141646Sgibbs * The sequencer has encountered a message phase 68241646Sgibbs * that requires host assistance for completion. 68341646Sgibbs * While handling the message phase(s), we will be 68441646Sgibbs * notified by the sequencer after each byte is 685300060Spfg * transferred so we can track bus phase changes. 68641646Sgibbs * 68763457Sgibbs * If this is the first time we've seen a HOST_MSG_LOOP 68863457Sgibbs * interrupt, initialize the state of the host message 68963457Sgibbs * loop. 69039220Sgibbs */ 69141646Sgibbs if (ahc->msg_type == MSG_TYPE_NONE) { 69274972Sgibbs struct scb *scb; 69374972Sgibbs u_int scb_index; 69441646Sgibbs u_int bus_phase; 69539220Sgibbs 69641646Sgibbs bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 69749933Sgibbs if (bus_phase != P_MESGIN 69849933Sgibbs && bus_phase != P_MESGOUT) { 69949933Sgibbs printf("ahc_intr: HOST_MSG_LOOP bad " 70049933Sgibbs "phase 0x%x\n", 70141646Sgibbs bus_phase); 70249933Sgibbs /* 70349933Sgibbs * Probably transitioned to bus free before 70449933Sgibbs * we got here. Just punt the message. 70549933Sgibbs */ 70649933Sgibbs ahc_clear_intstat(ahc); 70774094Sgibbs ahc_restart(ahc); 70863457Sgibbs return; 70949933Sgibbs } 71039220Sgibbs 71174972Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 71274972Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 71341646Sgibbs if (devinfo.role == ROLE_INITIATOR) { 71466647Sgibbs if (scb == NULL) 71566647Sgibbs panic("HOST_MSG_LOOP with " 71666647Sgibbs "invalid SCB %x\n", scb_index); 71766647Sgibbs 71841646Sgibbs if (bus_phase == P_MESGOUT) 71941646Sgibbs ahc_setup_initiator_msgout(ahc, 72041646Sgibbs &devinfo, 72141646Sgibbs scb); 72241646Sgibbs else { 72341646Sgibbs ahc->msg_type = 72441646Sgibbs MSG_TYPE_INITIATOR_MSGIN; 72541646Sgibbs ahc->msgin_index = 0; 72639220Sgibbs } 72795378Sgibbs } 728115337Sgibbs#ifdef AHC_TARGET_MODE 72995378Sgibbs else { 73041646Sgibbs if (bus_phase == P_MESGOUT) { 73141646Sgibbs ahc->msg_type = 73241646Sgibbs MSG_TYPE_TARGET_MSGOUT; 73341646Sgibbs ahc->msgin_index = 0; 73465942Sgibbs } 73565942Sgibbs else 73674972Sgibbs ahc_setup_target_msgin(ahc, 73774972Sgibbs &devinfo, 73874972Sgibbs scb); 73995378Sgibbs } 74065942Sgibbs#endif 74139220Sgibbs } 74239220Sgibbs 74365942Sgibbs ahc_handle_message_phase(ahc); 74441646Sgibbs break; 74539220Sgibbs } 74657099Sgibbs case PERR_DETECTED: 74757099Sgibbs { 74857099Sgibbs /* 74957099Sgibbs * If we've cleared the parity error interrupt 75057099Sgibbs * but the sequencer still believes that SCSIPERR 75157099Sgibbs * is true, it must be that the parity error is 75257099Sgibbs * for the currently presented byte on the bus, 75357099Sgibbs * and we are not in a phase (data-in) where we will 75457099Sgibbs * eventually ack this byte. Ack the byte and 75557099Sgibbs * throw it away in the hope that the target will 75657099Sgibbs * take us to message out to deliver the appropriate 75757099Sgibbs * error message. 75857099Sgibbs */ 75957099Sgibbs if ((intstat & SCSIINT) == 0 76057099Sgibbs && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) { 76157099Sgibbs 76276634Sgibbs if ((ahc->features & AHC_DT) == 0) { 76376634Sgibbs u_int curphase; 76476634Sgibbs 76576634Sgibbs /* 76676634Sgibbs * The hardware will only let you ack bytes 76776634Sgibbs * if the expected phase in SCSISIGO matches 76876634Sgibbs * the current phase. Make sure this is 76976634Sgibbs * currently the case. 77076634Sgibbs */ 77176634Sgibbs curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 77276634Sgibbs ahc_outb(ahc, LASTPHASE, curphase); 77376634Sgibbs ahc_outb(ahc, SCSISIGO, curphase); 77476634Sgibbs } 775107420Sscottl if ((ahc_inb(ahc, SCSISIGI) & (CDI|MSGI)) == 0) { 776107420Sscottl int wait; 777107420Sscottl 778107420Sscottl /* 779107420Sscottl * In a data phase. Faster to bitbucket 780107420Sscottl * the data than to individually ack each 781107420Sscottl * byte. This is also the only strategy 782107420Sscottl * that will work with AUTOACK enabled. 783107420Sscottl */ 784107420Sscottl ahc_outb(ahc, SXFRCTL1, 785107420Sscottl ahc_inb(ahc, SXFRCTL1) | BITBUCKET); 786107420Sscottl wait = 5000; 787107420Sscottl while (--wait != 0) { 788107420Sscottl if ((ahc_inb(ahc, SCSISIGI) 789107420Sscottl & (CDI|MSGI)) != 0) 790107420Sscottl break; 791123579Sgibbs aic_delay(100); 792107420Sscottl } 793107420Sscottl ahc_outb(ahc, SXFRCTL1, 794107420Sscottl ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); 795107420Sscottl if (wait == 0) { 796107420Sscottl struct scb *scb; 797107420Sscottl u_int scb_index; 798107420Sscottl 799107420Sscottl ahc_print_devinfo(ahc, &devinfo); 800107420Sscottl printf("Unable to clear parity error. " 801107420Sscottl "Resetting bus.\n"); 802107420Sscottl scb_index = ahc_inb(ahc, SCB_TAG); 803107420Sscottl scb = ahc_lookup_scb(ahc, scb_index); 804107420Sscottl if (scb != NULL) 805123579Sgibbs aic_set_transaction_status(scb, 806107420Sscottl CAM_UNCOR_PARITY); 807107420Sscottl ahc_reset_channel(ahc, devinfo.channel, 808107420Sscottl /*init reset*/TRUE); 809107420Sscottl } 810107420Sscottl } else { 811107420Sscottl ahc_inb(ahc, SCSIDATL); 812107420Sscottl } 81357099Sgibbs } 81457099Sgibbs break; 81557099Sgibbs } 81639220Sgibbs case DATA_OVERRUN: 81739220Sgibbs { 81839220Sgibbs /* 81939220Sgibbs * When the sequencer detects an overrun, it 82039220Sgibbs * places the controller in "BITBUCKET" mode 82139220Sgibbs * and allows the target to complete its transfer. 82239220Sgibbs * Unfortunately, none of the counters get updated 82339220Sgibbs * when the controller is in this mode, so we have 82439220Sgibbs * no way of knowing how large the overrun was. 82539220Sgibbs */ 82639506Sgibbs u_int scbindex = ahc_inb(ahc, SCB_TAG); 82739506Sgibbs u_int lastphase = ahc_inb(ahc, LASTPHASE); 82863457Sgibbs u_int i; 82939220Sgibbs 83066647Sgibbs scb = ahc_lookup_scb(ahc, scbindex); 83155581Sgibbs for (i = 0; i < num_phases; i++) { 83274094Sgibbs if (lastphase == ahc_phase_table[i].phase) 83355581Sgibbs break; 83455581Sgibbs } 83565942Sgibbs ahc_print_path(ahc, scb); 83655581Sgibbs printf("data overrun detected %s." 83739220Sgibbs " Tag == 0x%x.\n", 83874094Sgibbs ahc_phase_table[i].phasemsg, 83955581Sgibbs scb->hscb->tag); 84065942Sgibbs ahc_print_path(ahc, scb); 84165942Sgibbs printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", 84239220Sgibbs ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", 843123579Sgibbs aic_get_transfer_length(scb), scb->sg_count); 84444507Sgibbs if (scb->sg_count > 0) { 84555581Sgibbs for (i = 0; i < scb->sg_count; i++) { 84679874Sgibbs 84779874Sgibbs printf("sg[%d] - Addr 0x%x%x : Length %d\n", 84844507Sgibbs i, 849123579Sgibbs (aic_le32toh(scb->sg_list[i].len) >> 24 85079874Sgibbs & SG_HIGH_ADDR_BITS), 851123579Sgibbs aic_le32toh(scb->sg_list[i].addr), 852123579Sgibbs aic_le32toh(scb->sg_list[i].len) 85370693Sgibbs & AHC_SG_LEN_MASK); 85444507Sgibbs } 85539220Sgibbs } 85639220Sgibbs /* 85763457Sgibbs * Set this and it will take effect when the 85839220Sgibbs * target does a command complete. 85939220Sgibbs */ 86065942Sgibbs ahc_freeze_devq(ahc, scb); 86195378Sgibbs if ((scb->flags & SCB_SENSE) == 0) { 862123579Sgibbs aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); 86395378Sgibbs } else { 86495378Sgibbs scb->flags &= ~SCB_SENSE; 865123579Sgibbs aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); 86695378Sgibbs } 867123579Sgibbs aic_freeze_scb(scb); 86879874Sgibbs 86979874Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 87079874Sgibbs /* 87179874Sgibbs * Clear the channel in case we return 87279874Sgibbs * to data phase later. 87379874Sgibbs */ 87479874Sgibbs ahc_outb(ahc, SXFRCTL0, 87579874Sgibbs ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); 87679874Sgibbs ahc_outb(ahc, SXFRCTL0, 87779874Sgibbs ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); 87879874Sgibbs } 87979874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 88079874Sgibbs u_int dscommand1; 88179874Sgibbs 88279874Sgibbs /* Ensure HHADDR is 0 for future DMA operations. */ 88379874Sgibbs dscommand1 = ahc_inb(ahc, DSCOMMAND1); 88479874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); 88579874Sgibbs ahc_outb(ahc, HADDR, 0); 88679874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1); 88779874Sgibbs } 88839220Sgibbs break; 88939220Sgibbs } 89068402Sgibbs case MKMSG_FAILED: 89139220Sgibbs { 89268402Sgibbs u_int scbindex; 89368402Sgibbs 89468402Sgibbs printf("%s:%c:%d:%d: Attempt to issue message failed\n", 89568402Sgibbs ahc_name(ahc), devinfo.channel, devinfo.target, 89668402Sgibbs devinfo.lun); 89768402Sgibbs scbindex = ahc_inb(ahc, SCB_TAG); 89868402Sgibbs scb = ahc_lookup_scb(ahc, scbindex); 89968402Sgibbs if (scb != NULL 90068402Sgibbs && (scb->flags & SCB_RECOVERY_SCB) != 0) 90168402Sgibbs /* 90268402Sgibbs * Ensure that we didn't put a second instance of this 90368402Sgibbs * SCB into the QINFIFO. 90468402Sgibbs */ 90568402Sgibbs ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), 90668402Sgibbs SCB_GET_CHANNEL(ahc, scb), 90768402Sgibbs SCB_GET_LUN(scb), scb->hscb->tag, 90868402Sgibbs ROLE_INITIATOR, /*status*/0, 90968402Sgibbs SEARCH_REMOVE); 91063457Sgibbs break; 91163457Sgibbs } 91268087Sgibbs case NO_FREE_SCB: 91368087Sgibbs { 91468087Sgibbs printf("%s: No free or disconnected SCBs\n", ahc_name(ahc)); 91568087Sgibbs ahc_dump_card_state(ahc); 91668087Sgibbs panic("for safety"); 91768087Sgibbs break; 91868087Sgibbs } 91968087Sgibbs case SCB_MISMATCH: 92068087Sgibbs { 92168087Sgibbs u_int scbptr; 92268087Sgibbs 92368087Sgibbs scbptr = ahc_inb(ahc, SCBPTR); 92468087Sgibbs printf("Bogus TAG after DMA. SCBPTR %d, tag %d, our tag %d\n", 92568087Sgibbs scbptr, ahc_inb(ahc, ARG_1), 92668087Sgibbs ahc->scb_data->hscbs[scbptr].tag); 92768087Sgibbs ahc_dump_card_state(ahc); 928300060Spfg panic("for safety"); 92968087Sgibbs break; 93068087Sgibbs } 93168087Sgibbs case OUT_OF_RANGE: 93268087Sgibbs { 93368087Sgibbs printf("%s: BTT calculation out of range\n", ahc_name(ahc)); 93468087Sgibbs printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " 93568087Sgibbs "ARG_1 == 0x%x ACCUM = 0x%x\n", 93668087Sgibbs ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), 93768087Sgibbs ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); 93868087Sgibbs printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " 93968087Sgibbs "SINDEX == 0x%x\n, A == 0x%x\n", 94068087Sgibbs ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), 94168087Sgibbs ahc_index_busy_tcl(ahc, 94268087Sgibbs BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID), 94370204Sgibbs ahc_inb(ahc, SAVED_LUN))), 94470204Sgibbs ahc_inb(ahc, SINDEX), 94568087Sgibbs ahc_inb(ahc, ACCUM)); 94668087Sgibbs printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " 94768087Sgibbs "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", 94868087Sgibbs ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), 94968087Sgibbs ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), 95068087Sgibbs ahc_inb(ahc, SCB_CONTROL)); 95171390Sgibbs printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", 95271390Sgibbs ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); 95371390Sgibbs ahc_dump_card_state(ahc); 95468087Sgibbs panic("for safety"); 95568087Sgibbs break; 95668087Sgibbs } 95739220Sgibbs default: 95839220Sgibbs printf("ahc_intr: seqint, " 95939220Sgibbs "intstat == 0x%x, scsisigi = 0x%x\n", 96039220Sgibbs intstat, ahc_inb(ahc, SCSISIGI)); 96139220Sgibbs break; 96239220Sgibbs } 96339220Sgibbsunpause: 96439220Sgibbs /* 96539220Sgibbs * The sequencer is paused immediately on 96639220Sgibbs * a SEQINT, so we should restart it when 96739220Sgibbs * we're done. 96839220Sgibbs */ 96974094Sgibbs ahc_unpause(ahc); 97039220Sgibbs} 97139220Sgibbs 97265942Sgibbsvoid 97339506Sgibbsahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) 97439220Sgibbs{ 97539506Sgibbs u_int scb_index; 97668579Sgibbs u_int status0; 97739506Sgibbs u_int status; 97839506Sgibbs struct scb *scb; 97940421Sgibbs char cur_channel; 98040421Sgibbs char intr_channel; 98139220Sgibbs 98240421Sgibbs if ((ahc->features & AHC_TWIN) != 0 98340421Sgibbs && ((ahc_inb(ahc, SBLKCTL) & SELBUSB) != 0)) 98440421Sgibbs cur_channel = 'B'; 98540421Sgibbs else 98640421Sgibbs cur_channel = 'A'; 98740421Sgibbs intr_channel = cur_channel; 98840421Sgibbs 98968579Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 99068579Sgibbs status0 = ahc_inb(ahc, SSTAT0) & IOERR; 99168579Sgibbs else 99268579Sgibbs status0 = 0; 99370204Sgibbs status = ahc_inb(ahc, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR); 99468579Sgibbs if (status == 0 && status0 == 0) { 99540421Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 99640421Sgibbs /* Try the other channel */ 99740421Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); 99872811Sgibbs status = ahc_inb(ahc, SSTAT1) 99972811Sgibbs & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR); 100040421Sgibbs intr_channel = (cur_channel == 'A') ? 'B' : 'A'; 100140421Sgibbs } 100240421Sgibbs if (status == 0) { 100340421Sgibbs printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc)); 100466269Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 100574094Sgibbs ahc_unpause(ahc); 100640421Sgibbs return; 100740421Sgibbs } 100840421Sgibbs } 100939220Sgibbs 1010107420Sscottl /* Make sure the sequencer is in a safe location. */ 1011107420Sscottl ahc_clear_critical_section(ahc); 1012107420Sscottl 101340421Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 101466647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 101566647Sgibbs if (scb != NULL 1016107420Sscottl && (ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) 101739220Sgibbs scb = NULL; 101839220Sgibbs 101968579Sgibbs if ((ahc->features & AHC_ULTRA2) != 0 102072325Sgibbs && (status0 & IOERR) != 0) { 102168579Sgibbs int now_lvd; 102268579Sgibbs 102368579Sgibbs now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40; 102468579Sgibbs printf("%s: Transceiver State Has Changed to %s mode\n", 102568579Sgibbs ahc_name(ahc), now_lvd ? "LVD" : "SE"); 102668579Sgibbs ahc_outb(ahc, CLRSINT0, CLRIOERR); 102768579Sgibbs /* 102868579Sgibbs * When transitioning to SE mode, the reset line 102968579Sgibbs * glitches, triggering an arbitration bug in some 103068579Sgibbs * Ultra2 controllers. This bug is cleared when we 103168579Sgibbs * assert the reset line. Since a reset glitch has 103268579Sgibbs * already occurred with this transition and a 103368579Sgibbs * transceiver state change is handled just like 103468579Sgibbs * a bus reset anyway, asserting the reset line 103568579Sgibbs * ourselves is safe. 103668579Sgibbs */ 103768579Sgibbs ahc_reset_channel(ahc, intr_channel, 103868579Sgibbs /*Initiate Reset*/now_lvd == 0); 103968579Sgibbs } else if ((status & SCSIRSTI) != 0) { 104039220Sgibbs printf("%s: Someone reset channel %c\n", 104140421Sgibbs ahc_name(ahc), intr_channel); 104272811Sgibbs if (intr_channel != cur_channel) 104372811Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); 104468579Sgibbs ahc_reset_channel(ahc, intr_channel, /*Initiate Reset*/FALSE); 104557099Sgibbs } else if ((status & SCSIPERR) != 0) { 104639220Sgibbs /* 104757099Sgibbs * Determine the bus phase and queue an appropriate message. 104857099Sgibbs * SCSIPERR is latched true as soon as a parity error 104957099Sgibbs * occurs. If the sequencer acked the transfer that 105057099Sgibbs * caused the parity error and the currently presented 105157099Sgibbs * transfer on the bus has correct parity, SCSIPERR will 105257099Sgibbs * be cleared by CLRSCSIPERR. Use this to determine if 105357099Sgibbs * we should look at the last phase the sequencer recorded, 105457099Sgibbs * or the current phase presented on the bus. 105557099Sgibbs */ 1056114621Sgibbs struct ahc_devinfo devinfo; 1057114621Sgibbs u_int mesg_out; 1058114621Sgibbs u_int curphase; 1059114621Sgibbs u_int errorphase; 1060114621Sgibbs u_int lastphase; 1061114621Sgibbs u_int scsirate; 1062114621Sgibbs u_int i; 1063114621Sgibbs u_int sstat2; 1064114621Sgibbs int silent; 106557099Sgibbs 106657099Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 106757099Sgibbs curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 106865942Sgibbs sstat2 = ahc_inb(ahc, SSTAT2); 106957099Sgibbs ahc_outb(ahc, CLRSINT1, CLRSCSIPERR); 107057099Sgibbs /* 107157099Sgibbs * For all phases save DATA, the sequencer won't 107257099Sgibbs * automatically ack a byte that has a parity error 107357099Sgibbs * in it. So the only way that the current phase 107457099Sgibbs * could be 'data-in' is if the parity error is for 107557099Sgibbs * an already acked byte in the data phase. During 107657099Sgibbs * synchronous data-in transfers, we may actually 107757099Sgibbs * ack bytes before latching the current phase in 107857099Sgibbs * LASTPHASE, leading to the discrepancy between 107957099Sgibbs * curphase and lastphase. 108057099Sgibbs */ 108157099Sgibbs if ((ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0 108265942Sgibbs || curphase == P_DATAIN || curphase == P_DATAIN_DT) 108357099Sgibbs errorphase = curphase; 108457099Sgibbs else 108557099Sgibbs errorphase = lastphase; 108657099Sgibbs 108757099Sgibbs for (i = 0; i < num_phases; i++) { 108874094Sgibbs if (errorphase == ahc_phase_table[i].phase) 108957099Sgibbs break; 109057099Sgibbs } 109174094Sgibbs mesg_out = ahc_phase_table[i].mesg_out; 1092109590Sgibbs silent = FALSE; 1093107420Sscottl if (scb != NULL) { 1094109590Sgibbs if (SCB_IS_SILENT(scb)) 1095109590Sgibbs silent = TRUE; 1096109590Sgibbs else 1097109590Sgibbs ahc_print_path(ahc, scb); 1098107420Sscottl scb->flags |= SCB_TRANSMISSION_ERROR; 1099107420Sscottl } else 110072325Sgibbs printf("%s:%c:%d: ", ahc_name(ahc), intr_channel, 110163457Sgibbs SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID))); 110265942Sgibbs scsirate = ahc_inb(ahc, SCSIRATE); 1103109590Sgibbs if (silent == FALSE) { 1104109590Sgibbs printf("parity error detected %s. " 1105109590Sgibbs "SEQADDR(0x%x) SCSIRATE(0x%x)\n", 1106109590Sgibbs ahc_phase_table[i].phasemsg, 1107109590Sgibbs ahc_inw(ahc, SEQADDR0), 1108109590Sgibbs scsirate); 1109109590Sgibbs if ((ahc->features & AHC_DT) != 0) { 1110109590Sgibbs if ((sstat2 & CRCVALERR) != 0) 1111109590Sgibbs printf("\tCRC Value Mismatch\n"); 1112109590Sgibbs if ((sstat2 & CRCENDERR) != 0) 1113109590Sgibbs printf("\tNo terminal CRC packet " 1114109590Sgibbs "recevied\n"); 1115109590Sgibbs if ((sstat2 & CRCREQERR) != 0) 1116109590Sgibbs printf("\tIllegal CRC packet " 1117109590Sgibbs "request\n"); 1118109590Sgibbs if ((sstat2 & DUAL_EDGE_ERR) != 0) 1119109590Sgibbs printf("\tUnexpected %sDT Data Phase\n", 1120109590Sgibbs (scsirate & SINGLE_EDGE) 1121109590Sgibbs ? "" : "non-"); 1122102670Sgibbs } 112365942Sgibbs } 112465942Sgibbs 1125109590Sgibbs if ((ahc->features & AHC_DT) != 0 1126109590Sgibbs && (sstat2 & DUAL_EDGE_ERR) != 0) { 1127109590Sgibbs /* 1128109590Sgibbs * This error applies regardless of 1129109590Sgibbs * data direction, so ignore the value 1130109590Sgibbs * in the phase table. 1131109590Sgibbs */ 1132109590Sgibbs mesg_out = MSG_INITIATOR_DET_ERR; 1133109590Sgibbs } 1134109590Sgibbs 113557099Sgibbs /* 113657099Sgibbs * We've set the hardware to assert ATN if we 113757099Sgibbs * get a parity error on "in" phases, so all we 113857099Sgibbs * need to do is stuff the message buffer with 113957099Sgibbs * the appropriate message. "In" phases have set 114057099Sgibbs * mesg_out to something other than MSG_NOP. 114157099Sgibbs */ 114257099Sgibbs if (mesg_out != MSG_NOOP) { 114357099Sgibbs if (ahc->msg_type != MSG_TYPE_NONE) 114457099Sgibbs ahc->send_msg_perror = TRUE; 114557099Sgibbs else 114657099Sgibbs ahc_outb(ahc, MSG_OUT, mesg_out); 114757099Sgibbs } 114895378Sgibbs /* 114995378Sgibbs * Force a renegotiation with this target just in 115095378Sgibbs * case we are out of sync for some external reason 115195378Sgibbs * unknown (or unreported) by the target. 115295378Sgibbs */ 1153114621Sgibbs ahc_fetch_devinfo(ahc, &devinfo); 1154114621Sgibbs ahc_force_renegotiation(ahc, &devinfo); 1155114621Sgibbs 115657099Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 115774094Sgibbs ahc_unpause(ahc); 115876634Sgibbs } else if ((status & SELTO) != 0) { 115995378Sgibbs u_int scbptr; 116076634Sgibbs 116176634Sgibbs /* Stop the selection */ 116276634Sgibbs ahc_outb(ahc, SCSISEQ, 0); 116376634Sgibbs 116476634Sgibbs /* No more pending messages */ 116576634Sgibbs ahc_clear_msg_state(ahc); 116676634Sgibbs 116776634Sgibbs /* Clear interrupt state */ 116876634Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE); 116976634Sgibbs ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR); 117076634Sgibbs 117176634Sgibbs /* 117276634Sgibbs * Although the driver does not care about the 117376634Sgibbs * 'Selection in Progress' status bit, the busy 1174300060Spfg * LED does. SELINGO is only cleared by a successful 117576634Sgibbs * selection, so we must manually clear it to insure 117676634Sgibbs * the LED turns off just incase no future successful 117776634Sgibbs * selections occur (e.g. no devices on the bus). 117876634Sgibbs */ 117976634Sgibbs ahc_outb(ahc, CLRSINT0, CLRSELINGO); 118076634Sgibbs 118176634Sgibbs scbptr = ahc_inb(ahc, WAITING_SCBH); 118276634Sgibbs ahc_outb(ahc, SCBPTR, scbptr); 118376634Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 118476634Sgibbs 118576634Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 118676634Sgibbs if (scb == NULL) { 118776634Sgibbs printf("%s: ahc_intr - referenced scb not " 118876634Sgibbs "valid during SELTO scb(%d, %d)\n", 118976634Sgibbs ahc_name(ahc), scbptr, scb_index); 1190107420Sscottl ahc_dump_card_state(ahc); 119176634Sgibbs } else { 1192114621Sgibbs struct ahc_devinfo devinfo; 1193109590Sgibbs#ifdef AHC_DEBUG 1194109590Sgibbs if ((ahc_debug & AHC_SHOW_SELTO) != 0) { 1195109590Sgibbs ahc_print_path(ahc, scb); 1196109590Sgibbs printf("Saw Selection Timeout for SCB 0x%x\n", 1197109590Sgibbs scb_index); 1198109590Sgibbs } 1199109590Sgibbs#endif 1200114621Sgibbs ahc_scb_devinfo(ahc, &devinfo, scb); 1201123579Sgibbs aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); 120276634Sgibbs ahc_freeze_devq(ahc, scb); 1203129133Sgibbs 1204129133Sgibbs /* 1205129133Sgibbs * Cancel any pending transactions on the device 1206129133Sgibbs * now that it seems to be missing. This will 1207129133Sgibbs * also revert us to async/narrow transfers until 1208129133Sgibbs * we can renegotiate with the device. 1209129133Sgibbs */ 1210129133Sgibbs ahc_handle_devreset(ahc, &devinfo, 1211129133Sgibbs CAM_SEL_TIMEOUT, 1212129133Sgibbs "Selection Timeout", 1213129133Sgibbs /*verbose_level*/1); 121476634Sgibbs } 121576634Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 121676634Sgibbs ahc_restart(ahc); 121757099Sgibbs } else if ((status & BUSFREE) != 0 121857099Sgibbs && (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) { 1219114621Sgibbs struct ahc_devinfo devinfo; 1220114621Sgibbs u_int lastphase; 1221114621Sgibbs u_int saved_scsiid; 1222114621Sgibbs u_int saved_lun; 1223114621Sgibbs u_int target; 1224114621Sgibbs u_int initiator_role_id; 1225114621Sgibbs char channel; 1226114621Sgibbs int printerror; 122772325Sgibbs 122857099Sgibbs /* 122972325Sgibbs * Clear our selection hardware as soon as possible. 123072325Sgibbs * We may have an entry in the waiting Q for this target, 123172325Sgibbs * that is affected by this busfree and we don't want to 123272325Sgibbs * go about selecting the target while we handle the event. 123372325Sgibbs */ 123472325Sgibbs ahc_outb(ahc, SCSISEQ, 123572325Sgibbs ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); 123672325Sgibbs 123772325Sgibbs /* 123872325Sgibbs * Disable busfree interrupts and clear the busfree 123972325Sgibbs * interrupt status. We do this here so that several 124072325Sgibbs * bus transactions occur prior to clearing the SCSIINT 124172325Sgibbs * latch. It can take a bit for the clearing to take effect. 124272325Sgibbs */ 124372325Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE); 124472325Sgibbs ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR); 124572325Sgibbs 124672325Sgibbs /* 124772325Sgibbs * Look at what phase we were last in. 124839220Sgibbs * If its message out, chances are pretty good 124939220Sgibbs * that the busfree was in response to one of 125039220Sgibbs * our abort requests. 125139220Sgibbs */ 125272325Sgibbs lastphase = ahc_inb(ahc, LASTPHASE); 125372325Sgibbs saved_scsiid = ahc_inb(ahc, SAVED_SCSIID); 125472325Sgibbs saved_lun = ahc_inb(ahc, SAVED_LUN); 125572325Sgibbs target = SCSIID_TARGET(ahc, saved_scsiid); 125672325Sgibbs initiator_role_id = SCSIID_OUR_ID(saved_scsiid); 125772325Sgibbs channel = SCSIID_CHANNEL(ahc, saved_scsiid); 1258114621Sgibbs ahc_compile_devinfo(&devinfo, initiator_role_id, 1259114621Sgibbs target, saved_lun, channel, ROLE_INITIATOR); 126072325Sgibbs printerror = 1; 126139220Sgibbs 126239220Sgibbs if (lastphase == P_MESGOUT) { 126339220Sgibbs u_int tag; 126439220Sgibbs 126539220Sgibbs tag = SCB_LIST_NULL; 126670204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT_TAG, TRUE) 126770204Sgibbs || ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT, TRUE)) { 126870204Sgibbs if (ahc->msgout_buf[ahc->msgout_index - 1] 126970204Sgibbs == MSG_ABORT_TAG) 127070204Sgibbs tag = scb->hscb->tag; 127165942Sgibbs ahc_print_path(ahc, scb); 127272325Sgibbs printf("SCB %d - Abort%s Completed.\n", 127339323Smjacob scb->hscb->tag, tag == SCB_LIST_NULL ? 127472325Sgibbs "" : " Tag"); 127554211Sgibbs ahc_abort_scbs(ahc, target, channel, 127663457Sgibbs saved_lun, tag, 127754211Sgibbs ROLE_INITIATOR, 127854211Sgibbs CAM_REQ_ABORTED); 127939220Sgibbs printerror = 0; 128070204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_1B, 128170204Sgibbs MSG_BUS_DEV_RESET, TRUE)) { 128265942Sgibbs#ifdef __FreeBSD__ 128354211Sgibbs /* 128454211Sgibbs * Don't mark the user's request for this BDR 128554211Sgibbs * as completing with CAM_BDR_SENT. CAM3 128654211Sgibbs * specifies CAM_REQ_CMP. 128754211Sgibbs */ 128854211Sgibbs if (scb != NULL 128965942Sgibbs && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV 129063457Sgibbs && ahc_match_scb(ahc, scb, target, channel, 129165942Sgibbs CAM_LUN_WILDCARD, 129257099Sgibbs SCB_LIST_NULL, 129357099Sgibbs ROLE_INITIATOR)) { 1294123579Sgibbs aic_set_transaction_status(scb, CAM_REQ_CMP); 129554211Sgibbs } 129665942Sgibbs#endif 129744966Sgibbs ahc_compile_devinfo(&devinfo, 129844966Sgibbs initiator_role_id, 129944966Sgibbs target, 130065942Sgibbs CAM_LUN_WILDCARD, 130144966Sgibbs channel, 130244966Sgibbs ROLE_INITIATOR); 130344507Sgibbs ahc_handle_devreset(ahc, &devinfo, 130465942Sgibbs CAM_BDR_SENT, 130539506Sgibbs "Bus Device Reset", 130654211Sgibbs /*verbose_level*/0); 130739220Sgibbs printerror = 0; 130870204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, 130970204Sgibbs MSG_EXT_PPR, FALSE)) { 131070204Sgibbs struct ahc_initiator_tinfo *tinfo; 131174972Sgibbs struct ahc_tmode_tstate *tstate; 131270204Sgibbs 131370204Sgibbs /* 131470204Sgibbs * PPR Rejected. Try non-ppr negotiation 131570204Sgibbs * and retry command. 131670204Sgibbs */ 131770204Sgibbs tinfo = ahc_fetch_transinfo(ahc, 131870204Sgibbs devinfo.channel, 131970204Sgibbs devinfo.our_scsiid, 132070204Sgibbs devinfo.target, 132170204Sgibbs &tstate); 132276634Sgibbs tinfo->curr.transport_version = 2; 132370204Sgibbs tinfo->goal.transport_version = 2; 132470204Sgibbs tinfo->goal.ppr_options = 0; 132570204Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 132670204Sgibbs printerror = 0; 132770204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, 1328115918Sgibbs MSG_EXT_WDTR, FALSE)) { 132970204Sgibbs /* 1330115918Sgibbs * Negotiation Rejected. Go-narrow and 133170204Sgibbs * retry command. 133270204Sgibbs */ 133370204Sgibbs ahc_set_width(ahc, &devinfo, 133470204Sgibbs MSG_EXT_WDTR_BUS_8_BIT, 133570204Sgibbs AHC_TRANS_CUR|AHC_TRANS_GOAL, 133670204Sgibbs /*paused*/TRUE); 1337115918Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 1338115918Sgibbs printerror = 0; 1339115918Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, 1340115918Sgibbs MSG_EXT_SDTR, FALSE)) { 1341115918Sgibbs /* 1342115918Sgibbs * Negotiation Rejected. Go-async and 1343115918Sgibbs * retry command. 1344115918Sgibbs */ 134570204Sgibbs ahc_set_syncrate(ahc, &devinfo, 134670204Sgibbs /*syncrate*/NULL, 134770204Sgibbs /*period*/0, /*offset*/0, 134870204Sgibbs /*ppr_options*/0, 134970204Sgibbs AHC_TRANS_CUR|AHC_TRANS_GOAL, 135070204Sgibbs /*paused*/TRUE); 135170204Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 135270204Sgibbs printerror = 0; 135344507Sgibbs } 135439220Sgibbs } 135539220Sgibbs if (printerror != 0) { 135663457Sgibbs u_int i; 135755581Sgibbs 135839220Sgibbs if (scb != NULL) { 135939506Sgibbs u_int tag; 136039220Sgibbs 136139220Sgibbs if ((scb->hscb->control & TAG_ENB) != 0) 136239220Sgibbs tag = scb->hscb->tag; 136339220Sgibbs else 136439220Sgibbs tag = SCB_LIST_NULL; 136566800Sgibbs ahc_print_path(ahc, scb); 136639220Sgibbs ahc_abort_scbs(ahc, target, channel, 136763457Sgibbs SCB_GET_LUN(scb), tag, 136849933Sgibbs ROLE_INITIATOR, 136939220Sgibbs CAM_UNEXP_BUSFREE); 137039220Sgibbs } else { 137157099Sgibbs /* 137257099Sgibbs * We had not fully identified this connection, 137357099Sgibbs * so we cannot abort anything. 137457099Sgibbs */ 137539220Sgibbs printf("%s: ", ahc_name(ahc)); 137639220Sgibbs } 137755581Sgibbs for (i = 0; i < num_phases; i++) { 137874094Sgibbs if (lastphase == ahc_phase_table[i].phase) 137955581Sgibbs break; 138055581Sgibbs } 1381114621Sgibbs if (lastphase != P_BUSFREE) { 1382114621Sgibbs /* 1383114621Sgibbs * Renegotiate with this device at the 1384300060Spfg * next opportunity just in case this busfree 1385114621Sgibbs * is due to a negotiation mismatch with the 1386114621Sgibbs * device. 1387114621Sgibbs */ 1388114621Sgibbs ahc_force_renegotiation(ahc, &devinfo); 1389114621Sgibbs } 139055581Sgibbs printf("Unexpected busfree %s\n" 139139220Sgibbs "SEQADDR == 0x%x\n", 139274094Sgibbs ahc_phase_table[i].phasemsg, 139374094Sgibbs ahc_inb(ahc, SEQADDR0) 139439220Sgibbs | (ahc_inb(ahc, SEQADDR1) << 8)); 139539220Sgibbs } 139639220Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 139774094Sgibbs ahc_restart(ahc); 139839220Sgibbs } else { 139972325Sgibbs printf("%s: Missing case in ahc_handle_scsiint. status = %x\n", 140072325Sgibbs ahc_name(ahc), status); 140172325Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 140239220Sgibbs } 140339220Sgibbs} 140439220Sgibbs 140595378Sgibbs/* 140695378Sgibbs * Force renegotiation to occur the next time we initiate 140795378Sgibbs * a command to the current device. 140895378Sgibbs */ 140995378Sgibbsstatic void 1410114621Sgibbsahc_force_renegotiation(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 141195378Sgibbs{ 141295378Sgibbs struct ahc_initiator_tinfo *targ_info; 141395378Sgibbs struct ahc_tmode_tstate *tstate; 141495378Sgibbs 141595378Sgibbs targ_info = ahc_fetch_transinfo(ahc, 1416114621Sgibbs devinfo->channel, 1417114621Sgibbs devinfo->our_scsiid, 1418114621Sgibbs devinfo->target, 141995378Sgibbs &tstate); 1420114621Sgibbs ahc_update_neg_request(ahc, devinfo, tstate, 1421107420Sscottl targ_info, AHC_NEG_IF_NON_ASYNC); 142295378Sgibbs} 142395378Sgibbs 142468579Sgibbs#define AHC_MAX_STEPS 2000 142566647Sgibbsvoid 142666647Sgibbsahc_clear_critical_section(struct ahc_softc *ahc) 142766647Sgibbs{ 142866647Sgibbs int stepping; 142968579Sgibbs int steps; 143066845Sgibbs u_int simode0; 143166845Sgibbs u_int simode1; 143265942Sgibbs 143366647Sgibbs if (ahc->num_critical_sections == 0) 143466647Sgibbs return; 143566647Sgibbs 143666647Sgibbs stepping = FALSE; 143768579Sgibbs steps = 0; 143866845Sgibbs simode0 = 0; 143966845Sgibbs simode1 = 0; 144066647Sgibbs for (;;) { 144166647Sgibbs struct cs *cs; 144266647Sgibbs u_int seqaddr; 144366647Sgibbs u_int i; 144466647Sgibbs 144566647Sgibbs seqaddr = ahc_inb(ahc, SEQADDR0) 144666647Sgibbs | (ahc_inb(ahc, SEQADDR1) << 8); 144766647Sgibbs 144881170Sgibbs /* 144981170Sgibbs * Seqaddr represents the next instruction to execute, 145081170Sgibbs * so we are really executing the instruction just 145181170Sgibbs * before it. 145281170Sgibbs */ 145366647Sgibbs cs = ahc->critical_sections; 145466647Sgibbs for (i = 0; i < ahc->num_critical_sections; i++, cs++) { 145566647Sgibbs 145666647Sgibbs if (cs->begin < seqaddr && cs->end >= seqaddr) 145766647Sgibbs break; 145866647Sgibbs } 145966647Sgibbs 146066647Sgibbs if (i == ahc->num_critical_sections) 146166647Sgibbs break; 146266647Sgibbs 146368579Sgibbs if (steps > AHC_MAX_STEPS) { 146468579Sgibbs printf("%s: Infinite loop in critical section\n", 146568579Sgibbs ahc_name(ahc)); 146668579Sgibbs ahc_dump_card_state(ahc); 146768579Sgibbs panic("critical section loop"); 146868579Sgibbs } 146968579Sgibbs 147068579Sgibbs steps++; 147166845Sgibbs if (stepping == FALSE) { 147266845Sgibbs 147366845Sgibbs /* 147466845Sgibbs * Disable all interrupt sources so that the 147566845Sgibbs * sequencer will not be stuck by a pausing 147666845Sgibbs * interrupt condition while we attempt to 147766845Sgibbs * leave a critical section. 147866845Sgibbs */ 147966845Sgibbs simode0 = ahc_inb(ahc, SIMODE0); 148066845Sgibbs ahc_outb(ahc, SIMODE0, 0); 148166845Sgibbs simode1 = ahc_inb(ahc, SIMODE1); 1482107420Sscottl if ((ahc->features & AHC_DT) != 0) 1483107420Sscottl /* 1484107420Sscottl * On DT class controllers, we 1485107420Sscottl * use the enhanced busfree logic. 1486107420Sscottl * Unfortunately we cannot re-enable 1487107420Sscottl * busfree detection within the 1488107420Sscottl * current connection, so we must 1489107420Sscottl * leave it on while single stepping. 1490107420Sscottl */ 1491115920Sgibbs ahc_outb(ahc, SIMODE1, simode1 & ENBUSFREE); 1492107420Sscottl else 1493107420Sscottl ahc_outb(ahc, SIMODE1, 0); 149466845Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 1495115332Sgibbs ahc_outb(ahc, SEQCTL, ahc->seqctl | STEP); 149666647Sgibbs stepping = TRUE; 149766647Sgibbs } 1498107420Sscottl if ((ahc->features & AHC_DT) != 0) { 1499107420Sscottl ahc_outb(ahc, CLRSINT1, CLRBUSFREE); 1500107420Sscottl ahc_outb(ahc, CLRINT, CLRSCSIINT); 1501107420Sscottl } 150266647Sgibbs ahc_outb(ahc, HCNTRL, ahc->unpause); 150395378Sgibbs while (!ahc_is_paused(ahc)) 1504123579Sgibbs aic_delay(200); 150566647Sgibbs } 150666845Sgibbs if (stepping) { 150766845Sgibbs ahc_outb(ahc, SIMODE0, simode0); 150866845Sgibbs ahc_outb(ahc, SIMODE1, simode1); 1509115332Sgibbs ahc_outb(ahc, SEQCTL, ahc->seqctl); 151066845Sgibbs } 151166647Sgibbs} 151266647Sgibbs 151365942Sgibbs/* 151465942Sgibbs * Clear any pending interrupt status. 151565942Sgibbs */ 151665942Sgibbsvoid 151765942Sgibbsahc_clear_intstat(struct ahc_softc *ahc) 151841646Sgibbs{ 151965942Sgibbs /* Clear any interrupt conditions this may have caused */ 152065942Sgibbs ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI 152165942Sgibbs |CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG| 152265942Sgibbs CLRREQINIT); 152395378Sgibbs ahc_flush_device_writes(ahc); 152470204Sgibbs ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO); 152595378Sgibbs ahc_flush_device_writes(ahc); 152665942Sgibbs ahc_outb(ahc, CLRINT, CLRSCSIINT); 152795378Sgibbs ahc_flush_device_writes(ahc); 152865942Sgibbs} 152965942Sgibbs 153065942Sgibbs/**************************** Debugging Routines ******************************/ 153195378Sgibbs#ifdef AHC_DEBUG 1532102670Sgibbsuint32_t ahc_debug = AHC_DEBUG_OPTS; 153395378Sgibbs#endif 153495378Sgibbs 153565942Sgibbsvoid 153665942Sgibbsahc_print_scb(struct scb *scb) 153765942Sgibbs{ 153865942Sgibbs int i; 153965942Sgibbs 154065942Sgibbs struct hardware_scb *hscb = scb->hscb; 154165942Sgibbs 154265942Sgibbs printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", 154379874Sgibbs (void *)scb, 154465942Sgibbs hscb->control, 154565942Sgibbs hscb->scsiid, 154665942Sgibbs hscb->lun, 154765942Sgibbs hscb->cdb_len); 154888022Sgibbs printf("Shared Data: "); 154988022Sgibbs for (i = 0; i < sizeof(hscb->shared_data.cdb); i++) 155088022Sgibbs printf("%#02x", hscb->shared_data.cdb[i]); 155165942Sgibbs printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", 1552123579Sgibbs aic_le32toh(hscb->dataptr), 1553123579Sgibbs aic_le32toh(hscb->datacnt), 1554123579Sgibbs aic_le32toh(hscb->sgptr), 155565942Sgibbs hscb->tag); 155665942Sgibbs if (scb->sg_count > 0) { 155765942Sgibbs for (i = 0; i < scb->sg_count; i++) { 155879874Sgibbs printf("sg[%d] - Addr 0x%x%x : Length %d\n", 155965942Sgibbs i, 1560123579Sgibbs (aic_le32toh(scb->sg_list[i].len) >> 24 156179874Sgibbs & SG_HIGH_ADDR_BITS), 1562123579Sgibbs aic_le32toh(scb->sg_list[i].addr), 1563123579Sgibbs aic_le32toh(scb->sg_list[i].len)); 156465942Sgibbs } 156565942Sgibbs } 156665942Sgibbs} 156765942Sgibbs 156865942Sgibbs/************************* Transfer Negotiation *******************************/ 156965942Sgibbs/* 157065942Sgibbs * Allocate per target mode instance (ID we respond to as a target) 157165942Sgibbs * transfer negotiation data structures. 157265942Sgibbs */ 157374972Sgibbsstatic struct ahc_tmode_tstate * 157465942Sgibbsahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel) 157565942Sgibbs{ 157674972Sgibbs struct ahc_tmode_tstate *master_tstate; 157774972Sgibbs struct ahc_tmode_tstate *tstate; 157865942Sgibbs int i; 157965942Sgibbs 158065942Sgibbs master_tstate = ahc->enabled_targets[ahc->our_id]; 158165942Sgibbs if (channel == 'B') { 158265942Sgibbs scsi_id += 8; 158365942Sgibbs master_tstate = ahc->enabled_targets[ahc->our_id_b + 8]; 158465942Sgibbs } 158565942Sgibbs if (ahc->enabled_targets[scsi_id] != NULL 158665942Sgibbs && ahc->enabled_targets[scsi_id] != master_tstate) 158765942Sgibbs panic("%s: ahc_alloc_tstate - Target already allocated", 158865942Sgibbs ahc_name(ahc)); 1589102670Sgibbs tstate = (struct ahc_tmode_tstate*)malloc(sizeof(*tstate), 1590102670Sgibbs M_DEVBUF, M_NOWAIT); 159165942Sgibbs if (tstate == NULL) 159265942Sgibbs return (NULL); 159365942Sgibbs 159441646Sgibbs /* 159565942Sgibbs * If we have allocated a master tstate, copy user settings from 159665942Sgibbs * the master tstate (taken from SRAM or the EEPROM) for this 159765942Sgibbs * channel, but reset our current and goal settings to async/narrow 159865942Sgibbs * until an initiator talks to us. 159941646Sgibbs */ 160065942Sgibbs if (master_tstate != NULL) { 160165942Sgibbs memcpy(tstate, master_tstate, sizeof(*tstate)); 160265942Sgibbs memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns)); 160365942Sgibbs tstate->ultraenb = 0; 160495378Sgibbs for (i = 0; i < AHC_NUM_TARGETS; i++) { 160576634Sgibbs memset(&tstate->transinfo[i].curr, 0, 160676634Sgibbs sizeof(tstate->transinfo[i].curr)); 160765942Sgibbs memset(&tstate->transinfo[i].goal, 0, 160865942Sgibbs sizeof(tstate->transinfo[i].goal)); 160965942Sgibbs } 161065942Sgibbs } else 161165942Sgibbs memset(tstate, 0, sizeof(*tstate)); 161265942Sgibbs ahc->enabled_targets[scsi_id] = tstate; 161365942Sgibbs return (tstate); 161465942Sgibbs} 161565942Sgibbs 161671717Sgibbs#ifdef AHC_TARGET_MODE 161765942Sgibbs/* 161865942Sgibbs * Free per target mode instance (ID we respond to as a target) 161965942Sgibbs * transfer negotiation data structures. 162065942Sgibbs */ 162165942Sgibbsstatic void 162265942Sgibbsahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force) 162365942Sgibbs{ 162474972Sgibbs struct ahc_tmode_tstate *tstate; 162565942Sgibbs 162674972Sgibbs /* 162774972Sgibbs * Don't clean up our "master" tstate. 162874972Sgibbs * It has our default user settings. 162974972Sgibbs */ 163074972Sgibbs if (((channel == 'B' && scsi_id == ahc->our_id_b) 163165942Sgibbs || (channel == 'A' && scsi_id == ahc->our_id)) 163265942Sgibbs && force == FALSE) 163365942Sgibbs return; 163465942Sgibbs 163565942Sgibbs if (channel == 'B') 163665942Sgibbs scsi_id += 8; 163765942Sgibbs tstate = ahc->enabled_targets[scsi_id]; 163865942Sgibbs if (tstate != NULL) 163965942Sgibbs free(tstate, M_DEVBUF); 164065942Sgibbs ahc->enabled_targets[scsi_id] = NULL; 164165942Sgibbs} 164271717Sgibbs#endif 164365942Sgibbs 164465942Sgibbs/* 164565942Sgibbs * Called when we have an active connection to a target on the bus, 164665942Sgibbs * this function finds the nearest syncrate to the input period limited 164768087Sgibbs * by the capabilities of the bus connectivity of and sync settings for 164868087Sgibbs * the target. 164965942Sgibbs */ 1650107420Sscottlstruct ahc_syncrate * 165168087Sgibbsahc_devlimited_syncrate(struct ahc_softc *ahc, 165268087Sgibbs struct ahc_initiator_tinfo *tinfo, 165395378Sgibbs u_int *period, u_int *ppr_options, role_t role) 165495378Sgibbs{ 165568087Sgibbs struct ahc_transinfo *transinfo; 165665942Sgibbs u_int maxsync; 165765942Sgibbs 165865942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 165965942Sgibbs if ((ahc_inb(ahc, SBLKCTL) & ENAB40) != 0 166065942Sgibbs && (ahc_inb(ahc, SSTAT2) & EXP_ACTIVE) == 0) { 166165942Sgibbs maxsync = AHC_SYNCRATE_DT; 166265942Sgibbs } else { 166365942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 166465942Sgibbs /* Can't do DT on an SE bus */ 166565942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 166665942Sgibbs } 166776634Sgibbs } else if ((ahc->features & AHC_ULTRA) != 0) { 166865942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 166965942Sgibbs } else { 167065942Sgibbs maxsync = AHC_SYNCRATE_FAST; 167165942Sgibbs } 167268087Sgibbs /* 167368087Sgibbs * Never allow a value higher than our current goal 167468087Sgibbs * period otherwise we may allow a target initiated 167568087Sgibbs * negotiation to go above the limit as set by the 167668087Sgibbs * user. In the case of an initiator initiated 167768087Sgibbs * sync negotiation, we limit based on the user 167868087Sgibbs * setting. This allows the system to still accept 167968087Sgibbs * incoming negotiations even if target initiated 168068087Sgibbs * negotiation is not performed. 168168087Sgibbs */ 168268087Sgibbs if (role == ROLE_TARGET) 168368087Sgibbs transinfo = &tinfo->user; 168468087Sgibbs else 168568087Sgibbs transinfo = &tinfo->goal; 168668087Sgibbs *ppr_options &= transinfo->ppr_options; 1687109590Sgibbs if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) { 1688109590Sgibbs maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2); 1689109590Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 1690109590Sgibbs } 169168087Sgibbs if (transinfo->period == 0) { 169268087Sgibbs *period = 0; 169368087Sgibbs *ppr_options = 0; 169468087Sgibbs return (NULL); 169568087Sgibbs } 169668087Sgibbs *period = MAX(*period, transinfo->period); 169765942Sgibbs return (ahc_find_syncrate(ahc, period, ppr_options, maxsync)); 169865942Sgibbs} 169965942Sgibbs 170065942Sgibbs/* 170165942Sgibbs * Look up the valid period to SCSIRATE conversion in our table. 170265942Sgibbs * Return the period and offset that should be sent to the target 170365942Sgibbs * if this was the beginning of an SDTR. 170465942Sgibbs */ 170565942Sgibbsstruct ahc_syncrate * 170665942Sgibbsahc_find_syncrate(struct ahc_softc *ahc, u_int *period, 170765942Sgibbs u_int *ppr_options, u_int maxsync) 170865942Sgibbs{ 170965942Sgibbs struct ahc_syncrate *syncrate; 171065942Sgibbs 171165942Sgibbs if ((ahc->features & AHC_DT) == 0) 171265942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 171376634Sgibbs 171476634Sgibbs /* Skip all DT only entries if DT is not available */ 171576634Sgibbs if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0 171676634Sgibbs && maxsync < AHC_SYNCRATE_ULTRA2) 171776634Sgibbs maxsync = AHC_SYNCRATE_ULTRA2; 171865942Sgibbs 171965942Sgibbs for (syncrate = &ahc_syncrates[maxsync]; 172065942Sgibbs syncrate->rate != NULL; 172165942Sgibbs syncrate++) { 172265942Sgibbs 172365942Sgibbs /* 172465942Sgibbs * The Ultra2 table doesn't go as low 172565942Sgibbs * as for the Fast/Ultra cards. 172665942Sgibbs */ 172765942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0 172865942Sgibbs && (syncrate->sxfr_u2 == 0)) 172965942Sgibbs break; 173065942Sgibbs 173165942Sgibbs if (*period <= syncrate->period) { 173265942Sgibbs /* 173365942Sgibbs * When responding to a target that requests 173465942Sgibbs * sync, the requested rate may fall between 173565942Sgibbs * two rates that we can output, but still be 173665942Sgibbs * a rate that we can receive. Because of this, 173765942Sgibbs * we want to respond to the target with 173865942Sgibbs * the same rate that it sent to us even 173965942Sgibbs * if the period we use to send data to it 174065942Sgibbs * is lower. Only lower the response period 174165942Sgibbs * if we must. 174265942Sgibbs */ 174365942Sgibbs if (syncrate == &ahc_syncrates[maxsync]) 174465942Sgibbs *period = syncrate->period; 174565942Sgibbs 174665942Sgibbs /* 174765942Sgibbs * At some speeds, we only support 174865942Sgibbs * ST transfers. 174965942Sgibbs */ 175065942Sgibbs if ((syncrate->sxfr_u2 & ST_SXFR) != 0) 175165942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 175265942Sgibbs break; 175365942Sgibbs } 175465942Sgibbs } 175565942Sgibbs 175665942Sgibbs if ((*period == 0) 175765942Sgibbs || (syncrate->rate == NULL) 175865942Sgibbs || ((ahc->features & AHC_ULTRA2) != 0 175965942Sgibbs && (syncrate->sxfr_u2 == 0))) { 176065942Sgibbs /* Use asynchronous transfers. */ 176165942Sgibbs *period = 0; 176265942Sgibbs syncrate = NULL; 176365942Sgibbs *ppr_options &= ~MSG_EXT_PPR_DT_REQ; 176465942Sgibbs } 176565942Sgibbs return (syncrate); 176665942Sgibbs} 176765942Sgibbs 176865942Sgibbs/* 176965942Sgibbs * Convert from an entry in our syncrate table to the SCSI equivalent 177065942Sgibbs * sync "period" factor. 177165942Sgibbs */ 177265942Sgibbsu_int 177365942Sgibbsahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync) 177465942Sgibbs{ 177565942Sgibbs struct ahc_syncrate *syncrate; 177665942Sgibbs 177765942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 177865942Sgibbs scsirate &= SXFR_ULTRA2; 177965942Sgibbs else 178065942Sgibbs scsirate &= SXFR; 178165942Sgibbs 178265942Sgibbs syncrate = &ahc_syncrates[maxsync]; 178365942Sgibbs while (syncrate->rate != NULL) { 178465942Sgibbs 178565942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 178665942Sgibbs if (syncrate->sxfr_u2 == 0) 178765942Sgibbs break; 178865942Sgibbs else if (scsirate == (syncrate->sxfr_u2 & SXFR_ULTRA2)) 178965942Sgibbs return (syncrate->period); 179065942Sgibbs } else if (scsirate == (syncrate->sxfr & SXFR)) { 179165942Sgibbs return (syncrate->period); 179265942Sgibbs } 179365942Sgibbs syncrate++; 179465942Sgibbs } 179565942Sgibbs return (0); /* async */ 179665942Sgibbs} 179765942Sgibbs 179865942Sgibbs/* 179965942Sgibbs * Truncate the given synchronous offset to a value the 180065942Sgibbs * current adapter type and syncrate are capable of. 180165942Sgibbs */ 180265942Sgibbsvoid 180368087Sgibbsahc_validate_offset(struct ahc_softc *ahc, 180468087Sgibbs struct ahc_initiator_tinfo *tinfo, 180568087Sgibbs struct ahc_syncrate *syncrate, 180668087Sgibbs u_int *offset, int wide, role_t role) 180765942Sgibbs{ 180865942Sgibbs u_int maxoffset; 180965942Sgibbs 181065942Sgibbs /* Limit offset to what we can do */ 181165942Sgibbs if (syncrate == NULL) { 181265942Sgibbs maxoffset = 0; 181365942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 181465942Sgibbs maxoffset = MAX_OFFSET_ULTRA2; 181565942Sgibbs } else { 181665942Sgibbs if (wide) 181765942Sgibbs maxoffset = MAX_OFFSET_16BIT; 181865942Sgibbs else 181965942Sgibbs maxoffset = MAX_OFFSET_8BIT; 182065942Sgibbs } 182165942Sgibbs *offset = MIN(*offset, maxoffset); 182268087Sgibbs if (tinfo != NULL) { 182368087Sgibbs if (role == ROLE_TARGET) 182468087Sgibbs *offset = MIN(*offset, tinfo->user.offset); 182568087Sgibbs else 182668087Sgibbs *offset = MIN(*offset, tinfo->goal.offset); 182768087Sgibbs } 182865942Sgibbs} 182965942Sgibbs 183065942Sgibbs/* 183165942Sgibbs * Truncate the given transfer width parameter to a value the 183265942Sgibbs * current adapter type is capable of. 183365942Sgibbs */ 183465942Sgibbsvoid 183568087Sgibbsahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, 183668087Sgibbs u_int *bus_width, role_t role) 183765942Sgibbs{ 183865942Sgibbs switch (*bus_width) { 183965942Sgibbs default: 184065942Sgibbs if (ahc->features & AHC_WIDE) { 184165942Sgibbs /* Respond Wide */ 184265942Sgibbs *bus_width = MSG_EXT_WDTR_BUS_16_BIT; 184365942Sgibbs break; 184465942Sgibbs } 184565942Sgibbs /* FALLTHROUGH */ 184665942Sgibbs case MSG_EXT_WDTR_BUS_8_BIT: 184768087Sgibbs *bus_width = MSG_EXT_WDTR_BUS_8_BIT; 184865942Sgibbs break; 184965942Sgibbs } 185068087Sgibbs if (tinfo != NULL) { 185168087Sgibbs if (role == ROLE_TARGET) 185268087Sgibbs *bus_width = MIN(tinfo->user.width, *bus_width); 185368087Sgibbs else 185468087Sgibbs *bus_width = MIN(tinfo->goal.width, *bus_width); 185568087Sgibbs } 185665942Sgibbs} 185765942Sgibbs 185865942Sgibbs/* 185965942Sgibbs * Update the bitmask of targets for which the controller should 1860300060Spfg * negotiate with at the next convenient opportunity. This currently 186165942Sgibbs * means the next time we send the initial identify messages for 186265942Sgibbs * a new transaction. 186365942Sgibbs */ 186474972Sgibbsint 186574972Sgibbsahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 186674972Sgibbs struct ahc_tmode_tstate *tstate, 1867107420Sscottl struct ahc_initiator_tinfo *tinfo, ahc_neg_type neg_type) 186865942Sgibbs{ 186974972Sgibbs u_int auto_negotiate_orig; 187065942Sgibbs 187174972Sgibbs auto_negotiate_orig = tstate->auto_negotiate; 1872107420Sscottl if (neg_type == AHC_NEG_ALWAYS) { 1873107420Sscottl /* 1874107420Sscottl * Force our "current" settings to be 1875107420Sscottl * unknown so that unless a bus reset 1876107420Sscottl * occurs the need to renegotiate is 1877107420Sscottl * recorded persistently. 1878107420Sscottl */ 1879109590Sgibbs if ((ahc->features & AHC_WIDE) != 0) 1880109590Sgibbs tinfo->curr.width = AHC_WIDTH_UNKNOWN; 1881107420Sscottl tinfo->curr.period = AHC_PERIOD_UNKNOWN; 1882107420Sscottl tinfo->curr.offset = AHC_OFFSET_UNKNOWN; 1883107420Sscottl } 188476634Sgibbs if (tinfo->curr.period != tinfo->goal.period 188576634Sgibbs || tinfo->curr.width != tinfo->goal.width 188676634Sgibbs || tinfo->curr.offset != tinfo->goal.offset 188776634Sgibbs || tinfo->curr.ppr_options != tinfo->goal.ppr_options 1888107420Sscottl || (neg_type == AHC_NEG_IF_NON_ASYNC 1889102670Sgibbs && (tinfo->goal.offset != 0 189068087Sgibbs || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT 189168087Sgibbs || tinfo->goal.ppr_options != 0))) 189274972Sgibbs tstate->auto_negotiate |= devinfo->target_mask; 189365942Sgibbs else 189474972Sgibbs tstate->auto_negotiate &= ~devinfo->target_mask; 189565942Sgibbs 189674972Sgibbs return (auto_negotiate_orig != tstate->auto_negotiate); 189765942Sgibbs} 189865942Sgibbs 189965942Sgibbs/* 190076634Sgibbs * Update the user/goal/curr tables of synchronous negotiation 190165942Sgibbs * parameters as well as, in the case of a current or active update, 190265942Sgibbs * any data structures on the host controller. In the case of an 190365942Sgibbs * active update, the specified target is currently talking to us on 190465942Sgibbs * the bus, so the transfer parameter update must take effect 190565942Sgibbs * immediately. 190665942Sgibbs */ 190765942Sgibbsvoid 190865942Sgibbsahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 190965942Sgibbs struct ahc_syncrate *syncrate, u_int period, 191065942Sgibbs u_int offset, u_int ppr_options, u_int type, int paused) 191165942Sgibbs{ 191244507Sgibbs struct ahc_initiator_tinfo *tinfo; 191374972Sgibbs struct ahc_tmode_tstate *tstate; 191465942Sgibbs u_int old_period; 191565942Sgibbs u_int old_offset; 191666647Sgibbs u_int old_ppr; 191774972Sgibbs int active; 191874972Sgibbs int update_needed; 191941646Sgibbs 192074972Sgibbs active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; 192174972Sgibbs update_needed = 0; 192274972Sgibbs 192365942Sgibbs if (syncrate == NULL) { 192465942Sgibbs period = 0; 192565942Sgibbs offset = 0; 192665942Sgibbs } 192765942Sgibbs 192844507Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 192944507Sgibbs devinfo->target, &tstate); 193072811Sgibbs 193172811Sgibbs if ((type & AHC_TRANS_USER) != 0) { 193272811Sgibbs tinfo->user.period = period; 193372811Sgibbs tinfo->user.offset = offset; 193472811Sgibbs tinfo->user.ppr_options = ppr_options; 193572811Sgibbs } 193672811Sgibbs 193772811Sgibbs if ((type & AHC_TRANS_GOAL) != 0) { 193872811Sgibbs tinfo->goal.period = period; 193972811Sgibbs tinfo->goal.offset = offset; 194072811Sgibbs tinfo->goal.ppr_options = ppr_options; 194172811Sgibbs } 194272811Sgibbs 194376634Sgibbs old_period = tinfo->curr.period; 194476634Sgibbs old_offset = tinfo->curr.offset; 194576634Sgibbs old_ppr = tinfo->curr.ppr_options; 194641646Sgibbs 194765942Sgibbs if ((type & AHC_TRANS_CUR) != 0 194866647Sgibbs && (old_period != period 194966647Sgibbs || old_offset != offset 195066647Sgibbs || old_ppr != ppr_options)) { 195165942Sgibbs u_int scsirate; 195265942Sgibbs 195374972Sgibbs update_needed++; 195465942Sgibbs scsirate = tinfo->scsirate; 195565942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 195665942Sgibbs 195765942Sgibbs scsirate &= ~(SXFR_ULTRA2|SINGLE_EDGE|ENABLE_CRC); 195865942Sgibbs if (syncrate != NULL) { 195965942Sgibbs scsirate |= syncrate->sxfr_u2; 196065942Sgibbs if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) 196165942Sgibbs scsirate |= ENABLE_CRC; 196265942Sgibbs else 196365942Sgibbs scsirate |= SINGLE_EDGE; 196465942Sgibbs } 196565942Sgibbs } else { 196665942Sgibbs 196765942Sgibbs scsirate &= ~(SXFR|SOFS); 196865942Sgibbs /* 196965942Sgibbs * Ensure Ultra mode is set properly for 197065942Sgibbs * this target. 197165942Sgibbs */ 197265942Sgibbs tstate->ultraenb &= ~devinfo->target_mask; 197365942Sgibbs if (syncrate != NULL) { 197465942Sgibbs if (syncrate->sxfr & ULTRA_SXFR) { 197565942Sgibbs tstate->ultraenb |= 197665942Sgibbs devinfo->target_mask; 197765942Sgibbs } 197865942Sgibbs scsirate |= syncrate->sxfr & SXFR; 197965942Sgibbs scsirate |= offset & SOFS; 198065942Sgibbs } 198165942Sgibbs if (active) { 198265942Sgibbs u_int sxfrctl0; 198365942Sgibbs 198465942Sgibbs sxfrctl0 = ahc_inb(ahc, SXFRCTL0); 198565942Sgibbs sxfrctl0 &= ~FAST20; 198665942Sgibbs if (tstate->ultraenb & devinfo->target_mask) 198765942Sgibbs sxfrctl0 |= FAST20; 198865942Sgibbs ahc_outb(ahc, SXFRCTL0, sxfrctl0); 198965942Sgibbs } 199065942Sgibbs } 199165942Sgibbs if (active) { 199265942Sgibbs ahc_outb(ahc, SCSIRATE, scsirate); 199365942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 199465942Sgibbs ahc_outb(ahc, SCSIOFFSET, offset); 199565942Sgibbs } 199665942Sgibbs 199765942Sgibbs tinfo->scsirate = scsirate; 199876634Sgibbs tinfo->curr.period = period; 199976634Sgibbs tinfo->curr.offset = offset; 200076634Sgibbs tinfo->curr.ppr_options = ppr_options; 200165942Sgibbs 200266269Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 200376634Sgibbs CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); 200465942Sgibbs if (bootverbose) { 200565942Sgibbs if (offset != 0) { 200665942Sgibbs printf("%s: target %d synchronous at %sMHz%s, " 200765942Sgibbs "offset = 0x%x\n", ahc_name(ahc), 200865942Sgibbs devinfo->target, syncrate->rate, 200965942Sgibbs (ppr_options & MSG_EXT_PPR_DT_REQ) 201065942Sgibbs ? " DT" : "", offset); 201165942Sgibbs } else { 201265942Sgibbs printf("%s: target %d using " 201365942Sgibbs "asynchronous transfers\n", 201465942Sgibbs ahc_name(ahc), devinfo->target); 201565942Sgibbs } 201665942Sgibbs } 201741646Sgibbs } 201841646Sgibbs 201974972Sgibbs update_needed += ahc_update_neg_request(ahc, devinfo, tstate, 2020107420Sscottl tinfo, AHC_NEG_TO_GOAL); 202174972Sgibbs 202274972Sgibbs if (update_needed) 202374972Sgibbs ahc_update_pending_scbs(ahc); 202465942Sgibbs} 202565942Sgibbs 202665942Sgibbs/* 202776634Sgibbs * Update the user/goal/curr tables of wide negotiation 202865942Sgibbs * parameters as well as, in the case of a current or active update, 202965942Sgibbs * any data structures on the host controller. In the case of an 203065942Sgibbs * active update, the specified target is currently talking to us on 203165942Sgibbs * the bus, so the transfer parameter update must take effect 203265942Sgibbs * immediately. 203365942Sgibbs */ 203465942Sgibbsvoid 203565942Sgibbsahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 203665942Sgibbs u_int width, u_int type, int paused) 203765942Sgibbs{ 203874972Sgibbs struct ahc_initiator_tinfo *tinfo; 203974972Sgibbs struct ahc_tmode_tstate *tstate; 204074972Sgibbs u_int oldwidth; 204174972Sgibbs int active; 204274972Sgibbs int update_needed; 204365942Sgibbs 204474972Sgibbs active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; 204574972Sgibbs update_needed = 0; 204665942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 204765942Sgibbs devinfo->target, &tstate); 204872811Sgibbs 204972811Sgibbs if ((type & AHC_TRANS_USER) != 0) 205072811Sgibbs tinfo->user.width = width; 205172811Sgibbs 205272811Sgibbs if ((type & AHC_TRANS_GOAL) != 0) 205372811Sgibbs tinfo->goal.width = width; 205472811Sgibbs 205576634Sgibbs oldwidth = tinfo->curr.width; 205665942Sgibbs if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) { 205765942Sgibbs u_int scsirate; 205865942Sgibbs 205974972Sgibbs update_needed++; 206065942Sgibbs scsirate = tinfo->scsirate; 206165942Sgibbs scsirate &= ~WIDEXFER; 206265942Sgibbs if (width == MSG_EXT_WDTR_BUS_16_BIT) 206365942Sgibbs scsirate |= WIDEXFER; 206465942Sgibbs 206565942Sgibbs tinfo->scsirate = scsirate; 206665942Sgibbs 206765942Sgibbs if (active) 206865942Sgibbs ahc_outb(ahc, SCSIRATE, scsirate); 206965942Sgibbs 207076634Sgibbs tinfo->curr.width = width; 207165942Sgibbs 207266269Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 207376634Sgibbs CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); 207465942Sgibbs if (bootverbose) { 207565942Sgibbs printf("%s: target %d using %dbit transfers\n", 207665942Sgibbs ahc_name(ahc), devinfo->target, 207765942Sgibbs 8 * (0x01 << width)); 207865942Sgibbs } 207941646Sgibbs } 208065942Sgibbs 208174972Sgibbs update_needed += ahc_update_neg_request(ahc, devinfo, tstate, 2082107420Sscottl tinfo, AHC_NEG_TO_GOAL); 208374972Sgibbs if (update_needed) 208474972Sgibbs ahc_update_pending_scbs(ahc); 208541646Sgibbs} 208641646Sgibbs 208765942Sgibbs/* 208865942Sgibbs * Update the current state of tagged queuing for a given target. 208965942Sgibbs */ 209065942Sgibbsvoid 209176634Sgibbsahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 209276634Sgibbs ahc_queue_alg alg) 209365942Sgibbs{ 209476634Sgibbs ahc_platform_set_tags(ahc, devinfo, alg); 209576634Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 209676634Sgibbs devinfo->lun, AC_TRANSFER_NEG, &alg); 209765942Sgibbs} 209865942Sgibbs 209965942Sgibbs/* 210065942Sgibbs * When the transfer settings for a connection change, update any 210165942Sgibbs * in-transit SCBs to contain the new data so the hardware will 210265942Sgibbs * be set correctly during future (re)selections. 210365942Sgibbs */ 210441646Sgibbsstatic void 210574972Sgibbsahc_update_pending_scbs(struct ahc_softc *ahc) 210665942Sgibbs{ 210765942Sgibbs struct scb *pending_scb; 210865942Sgibbs int pending_scb_count; 210965942Sgibbs int i; 211075048Sgibbs int paused; 211165942Sgibbs u_int saved_scbptr; 211265942Sgibbs 211365942Sgibbs /* 211465942Sgibbs * Traverse the pending SCB list and ensure that all of the 211565942Sgibbs * SCBs there have the proper settings. 211665942Sgibbs */ 211765942Sgibbs pending_scb_count = 0; 211866800Sgibbs LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) { 211965942Sgibbs struct ahc_devinfo devinfo; 212065942Sgibbs struct hardware_scb *pending_hscb; 212165942Sgibbs struct ahc_initiator_tinfo *tinfo; 212274972Sgibbs struct ahc_tmode_tstate *tstate; 212379874Sgibbs 212465942Sgibbs ahc_scb_devinfo(ahc, &devinfo, pending_scb); 212565942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 212665942Sgibbs devinfo.our_scsiid, 212765942Sgibbs devinfo.target, &tstate); 212865942Sgibbs pending_hscb = pending_scb->hscb; 212965942Sgibbs pending_hscb->control &= ~ULTRAENB; 213065942Sgibbs if ((tstate->ultraenb & devinfo.target_mask) != 0) 213165942Sgibbs pending_hscb->control |= ULTRAENB; 213265942Sgibbs pending_hscb->scsirate = tinfo->scsirate; 213376634Sgibbs pending_hscb->scsioffset = tinfo->curr.offset; 213474972Sgibbs if ((tstate->auto_negotiate & devinfo.target_mask) == 0 213574972Sgibbs && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { 213674972Sgibbs pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; 213774972Sgibbs pending_hscb->control &= ~MK_MESSAGE; 213874972Sgibbs } 213979874Sgibbs ahc_sync_scb(ahc, pending_scb, 214079874Sgibbs BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 214165942Sgibbs pending_scb_count++; 214265942Sgibbs } 214365942Sgibbs 214465942Sgibbs if (pending_scb_count == 0) 214565942Sgibbs return; 214665942Sgibbs 214775048Sgibbs if (ahc_is_paused(ahc)) { 214875048Sgibbs paused = 1; 214975048Sgibbs } else { 215075048Sgibbs paused = 0; 215175048Sgibbs ahc_pause(ahc); 215275048Sgibbs } 215375048Sgibbs 215465942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 215565942Sgibbs /* Ensure that the hscbs down on the card match the new information */ 215665942Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 215766800Sgibbs struct hardware_scb *pending_hscb; 215866800Sgibbs u_int control; 215966800Sgibbs u_int scb_tag; 216065942Sgibbs 216165942Sgibbs ahc_outb(ahc, SCBPTR, i); 216265942Sgibbs scb_tag = ahc_inb(ahc, SCB_TAG); 216366800Sgibbs pending_scb = ahc_lookup_scb(ahc, scb_tag); 216466800Sgibbs if (pending_scb == NULL) 216566800Sgibbs continue; 216665942Sgibbs 216766800Sgibbs pending_hscb = pending_scb->hscb; 216866800Sgibbs control = ahc_inb(ahc, SCB_CONTROL); 216974972Sgibbs control &= ~(ULTRAENB|MK_MESSAGE); 217074972Sgibbs control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE); 217166800Sgibbs ahc_outb(ahc, SCB_CONTROL, control); 217266800Sgibbs ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate); 217366800Sgibbs ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset); 217465942Sgibbs } 217565942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 217675048Sgibbs 217775048Sgibbs if (paused == 0) 217875048Sgibbs ahc_unpause(ahc); 217965942Sgibbs} 218065942Sgibbs 218165942Sgibbs/**************************** Pathing Information *****************************/ 218265942Sgibbsstatic void 218365942Sgibbsahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 218465942Sgibbs{ 218565942Sgibbs u_int saved_scsiid; 218665942Sgibbs role_t role; 218765942Sgibbs int our_id; 218865942Sgibbs 218965942Sgibbs if (ahc_inb(ahc, SSTAT0) & TARGET) 219065942Sgibbs role = ROLE_TARGET; 219165942Sgibbs else 219265942Sgibbs role = ROLE_INITIATOR; 219365942Sgibbs 219465942Sgibbs if (role == ROLE_TARGET 219565942Sgibbs && (ahc->features & AHC_MULTI_TID) != 0 2196102670Sgibbs && (ahc_inb(ahc, SEQ_FLAGS) 2197102670Sgibbs & (CMDPHASE_PENDING|TARG_CMD_PENDING|NO_DISCONNECT)) != 0) { 219865942Sgibbs /* We were selected, so pull our id from TARGIDIN */ 219965942Sgibbs our_id = ahc_inb(ahc, TARGIDIN) & OID; 220065942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) 220165942Sgibbs our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; 220265942Sgibbs else 220365942Sgibbs our_id = ahc_inb(ahc, SCSIID) & OID; 220465942Sgibbs 220565942Sgibbs saved_scsiid = ahc_inb(ahc, SAVED_SCSIID); 220665942Sgibbs ahc_compile_devinfo(devinfo, 220765942Sgibbs our_id, 220865942Sgibbs SCSIID_TARGET(ahc, saved_scsiid), 220965942Sgibbs ahc_inb(ahc, SAVED_LUN), 221065942Sgibbs SCSIID_CHANNEL(ahc, saved_scsiid), 221165942Sgibbs role); 221265942Sgibbs} 221365942Sgibbs 221474094Sgibbsstruct ahc_phase_table_entry* 221574094Sgibbsahc_lookup_phase_entry(int phase) 221674094Sgibbs{ 221774094Sgibbs struct ahc_phase_table_entry *entry; 221874434Sgibbs struct ahc_phase_table_entry *last_entry; 221974094Sgibbs 222074094Sgibbs /* 222174094Sgibbs * num_phases doesn't include the default entry which 222274094Sgibbs * will be returned if the phase doesn't match. 222374094Sgibbs */ 222474434Sgibbs last_entry = &ahc_phase_table[num_phases]; 222574434Sgibbs for (entry = ahc_phase_table; entry < last_entry; entry++) { 222674094Sgibbs if (phase == entry->phase) 222774094Sgibbs break; 222874094Sgibbs } 222974094Sgibbs return (entry); 223074094Sgibbs} 223174094Sgibbs 223265942Sgibbsvoid 223365942Sgibbsahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target, 223465942Sgibbs u_int lun, char channel, role_t role) 223565942Sgibbs{ 223665942Sgibbs devinfo->our_scsiid = our_id; 223765942Sgibbs devinfo->target = target; 223865942Sgibbs devinfo->lun = lun; 223965942Sgibbs devinfo->target_offset = target; 224065942Sgibbs devinfo->channel = channel; 224165942Sgibbs devinfo->role = role; 224265942Sgibbs if (channel == 'B') 224365942Sgibbs devinfo->target_offset += 8; 224465942Sgibbs devinfo->target_mask = (0x01 << devinfo->target_offset); 224565942Sgibbs} 224665942Sgibbs 2247107420Sscottlvoid 2248102670Sgibbsahc_print_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 2249102670Sgibbs{ 2250107420Sscottl printf("%s:%c:%d:%d: ", ahc_name(ahc), devinfo->channel, 2251102670Sgibbs devinfo->target, devinfo->lun); 2252102670Sgibbs} 2253102670Sgibbs 2254102670Sgibbsstatic void 225565942Sgibbsahc_scb_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 225665942Sgibbs struct scb *scb) 225765942Sgibbs{ 225865942Sgibbs role_t role; 225965942Sgibbs int our_id; 226065942Sgibbs 226165942Sgibbs our_id = SCSIID_OUR_ID(scb->hscb->scsiid); 226265942Sgibbs role = ROLE_INITIATOR; 2263107420Sscottl if ((scb->flags & SCB_TARGET_SCB) != 0) 226465942Sgibbs role = ROLE_TARGET; 226565942Sgibbs ahc_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahc, scb), 226665942Sgibbs SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahc, scb), role); 226765942Sgibbs} 226865942Sgibbs 226965942Sgibbs 227065942Sgibbs/************************ Message Phase Processing ****************************/ 227176634Sgibbsstatic void 227276634Sgibbsahc_assert_atn(struct ahc_softc *ahc) 227376634Sgibbs{ 227476634Sgibbs u_int scsisigo; 227576634Sgibbs 227676634Sgibbs scsisigo = ATNO; 227776634Sgibbs if ((ahc->features & AHC_DT) == 0) 227876634Sgibbs scsisigo |= ahc_inb(ahc, SCSISIGI); 227976634Sgibbs ahc_outb(ahc, SCSISIGO, scsisigo); 228076634Sgibbs} 228176634Sgibbs 228265942Sgibbs/* 228365942Sgibbs * When an initiator transaction with the MK_MESSAGE flag either reconnects 228465942Sgibbs * or enters the initial message out phase, we are interrupted. Fill our 228565942Sgibbs * outgoing message buffer with the appropriate message and beging handing 228665942Sgibbs * the message phase(s) manually. 228765942Sgibbs */ 228865942Sgibbsstatic void 228941646Sgibbsahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 229041646Sgibbs struct scb *scb) 229141646Sgibbs{ 229265942Sgibbs /* 229341646Sgibbs * To facilitate adding multiple messages together, 229441646Sgibbs * each routine should increment the index and len 229541646Sgibbs * variables instead of setting them explicitly. 229665942Sgibbs */ 229741646Sgibbs ahc->msgout_index = 0; 229841646Sgibbs ahc->msgout_len = 0; 229941646Sgibbs 230041646Sgibbs if ((scb->flags & SCB_DEVICE_RESET) == 0 230141646Sgibbs && ahc_inb(ahc, MSG_OUT) == MSG_IDENTIFYFLAG) { 230241646Sgibbs u_int identify_msg; 230341646Sgibbs 230463457Sgibbs identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb); 230541646Sgibbs if ((scb->hscb->control & DISCENB) != 0) 230641646Sgibbs identify_msg |= MSG_IDENTIFY_DISCFLAG; 230741646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = identify_msg; 230841646Sgibbs ahc->msgout_len++; 230941646Sgibbs 231041646Sgibbs if ((scb->hscb->control & TAG_ENB) != 0) { 231141646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = 231265942Sgibbs scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE); 231341646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = scb->hscb->tag; 231441646Sgibbs ahc->msgout_len += 2; 231541646Sgibbs } 231641646Sgibbs } 231741646Sgibbs 231841646Sgibbs if (scb->flags & SCB_DEVICE_RESET) { 231941646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_BUS_DEV_RESET; 232041646Sgibbs ahc->msgout_len++; 232165942Sgibbs ahc_print_path(ahc, scb); 232241646Sgibbs printf("Bus Device Reset Message Sent\n"); 232372325Sgibbs /* 232472325Sgibbs * Clear our selection hardware in advance of 232572325Sgibbs * the busfree. We may have an entry in the waiting 232672325Sgibbs * Q for this target, and we don't want to go about 232772325Sgibbs * selecting while we handle the busfree and blow it 232872325Sgibbs * away. 232972325Sgibbs */ 233072325Sgibbs ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); 233163457Sgibbs } else if ((scb->flags & SCB_ABORT) != 0) { 233241646Sgibbs if ((scb->hscb->control & TAG_ENB) != 0) 233341646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT_TAG; 233441646Sgibbs else 233541646Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT; 233641646Sgibbs ahc->msgout_len++; 233765942Sgibbs ahc_print_path(ahc, scb); 233872325Sgibbs printf("Abort%s Message Sent\n", 233972325Sgibbs (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : ""); 234072325Sgibbs /* 234172325Sgibbs * Clear our selection hardware in advance of 234272325Sgibbs * the busfree. We may have an entry in the waiting 234372325Sgibbs * Q for this target, and we don't want to go about 234472325Sgibbs * selecting while we handle the busfree and blow it 234572325Sgibbs * away. 234672325Sgibbs */ 234772325Sgibbs ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); 234874972Sgibbs } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) { 234941646Sgibbs ahc_build_transfer_msg(ahc, devinfo); 235041646Sgibbs } else { 235141646Sgibbs printf("ahc_intr: AWAITING_MSG for an SCB that " 235263457Sgibbs "does not have a waiting message\n"); 235363457Sgibbs printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, 235463457Sgibbs devinfo->target_mask); 235541646Sgibbs panic("SCB = %d, SCB Control = %x, MSG_OUT = %x " 235641646Sgibbs "SCB flags = %x", scb->hscb->tag, scb->hscb->control, 235741646Sgibbs ahc_inb(ahc, MSG_OUT), scb->flags); 235841646Sgibbs } 235941646Sgibbs 236041646Sgibbs /* 236141646Sgibbs * Clear the MK_MESSAGE flag from the SCB so we aren't 236241646Sgibbs * asked to send this message again. 236341646Sgibbs */ 236441646Sgibbs ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE); 236574972Sgibbs scb->hscb->control &= ~MK_MESSAGE; 236641646Sgibbs ahc->msgout_index = 0; 236741646Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 236841646Sgibbs} 236970204Sgibbs 237065942Sgibbs/* 237165942Sgibbs * Build an appropriate transfer negotiation message for the 237265942Sgibbs * currently active target. 237365942Sgibbs */ 237441646Sgibbsstatic void 237565942Sgibbsahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 237641646Sgibbs{ 237741646Sgibbs /* 237865942Sgibbs * We need to initiate transfer negotiations. 237965942Sgibbs * If our current and goal settings are identical, 238065942Sgibbs * we want to renegotiate due to a check condition. 238141646Sgibbs */ 238265942Sgibbs struct ahc_initiator_tinfo *tinfo; 238374972Sgibbs struct ahc_tmode_tstate *tstate; 238465942Sgibbs struct ahc_syncrate *rate; 238565942Sgibbs int dowide; 238665942Sgibbs int dosync; 238765942Sgibbs int doppr; 238865942Sgibbs u_int period; 238965942Sgibbs u_int ppr_options; 239065942Sgibbs u_int offset; 239141646Sgibbs 239265942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 239363457Sgibbs devinfo->target, &tstate); 239476634Sgibbs /* 239576634Sgibbs * Filter our period based on the current connection. 239676634Sgibbs * If we can't perform DT transfers on this segment (not in LVD 239776634Sgibbs * mode for instance), then our decision to issue a PPR message 239876634Sgibbs * may change. 239976634Sgibbs */ 240076634Sgibbs period = tinfo->goal.period; 2401115918Sgibbs offset = tinfo->goal.offset; 240276634Sgibbs ppr_options = tinfo->goal.ppr_options; 240379874Sgibbs /* Target initiated PPR is not allowed in the SCSI spec */ 240479874Sgibbs if (devinfo->role == ROLE_TARGET) 240579874Sgibbs ppr_options = 0; 240676634Sgibbs rate = ahc_devlimited_syncrate(ahc, tinfo, &period, 240776634Sgibbs &ppr_options, devinfo->role); 240876634Sgibbs dowide = tinfo->curr.width != tinfo->goal.width; 2409115918Sgibbs dosync = tinfo->curr.offset != offset || tinfo->curr.period != period; 2410107420Sscottl /* 2411107420Sscottl * Only use PPR if we have options that need it, even if the device 2412107420Sscottl * claims to support it. There might be an expander in the way 2413107420Sscottl * that doesn't. 2414107420Sscottl */ 2415107420Sscottl doppr = ppr_options != 0; 241641646Sgibbs 241765942Sgibbs if (!dowide && !dosync && !doppr) { 241865942Sgibbs dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT; 2419102670Sgibbs dosync = tinfo->goal.offset != 0; 242065942Sgibbs } 242141646Sgibbs 242265942Sgibbs if (!dowide && !dosync && !doppr) { 2423107420Sscottl /* 2424107420Sscottl * Force async with a WDTR message if we have a wide bus, 2425107420Sscottl * or just issue an SDTR with a 0 offset. 2426107420Sscottl */ 2427107420Sscottl if ((ahc->features & AHC_WIDE) != 0) 2428107420Sscottl dowide = 1; 2429107420Sscottl else 2430107420Sscottl dosync = 1; 2431107420Sscottl 2432107420Sscottl if (bootverbose) { 2433107420Sscottl ahc_print_devinfo(ahc, devinfo); 2434107420Sscottl printf("Ensuring async\n"); 2435107420Sscottl } 243665942Sgibbs } 243741646Sgibbs 243868087Sgibbs /* Target initiated PPR is not allowed in the SCSI spec */ 243968087Sgibbs if (devinfo->role == ROLE_TARGET) 2440107420Sscottl doppr = 0; 244168087Sgibbs 244266269Sgibbs /* 244366269Sgibbs * Both the PPR message and SDTR message require the 244466269Sgibbs * goal syncrate to be limited to what the target device 244566269Sgibbs * is capable of handling (based on whether an LVD->SE 244666269Sgibbs * expander is on the bus), so combine these two cases. 244766269Sgibbs * Regardless, guarantee that if we are using WDTR and SDTR 244866269Sgibbs * messages that WDTR comes first. 244966269Sgibbs */ 2450107420Sscottl if (doppr || (dosync && !dowide)) { 245141646Sgibbs 245265942Sgibbs offset = tinfo->goal.offset; 245368087Sgibbs ahc_validate_offset(ahc, tinfo, rate, &offset, 2454107420Sscottl doppr ? tinfo->goal.width 2455107420Sscottl : tinfo->curr.width, 245668087Sgibbs devinfo->role); 2457107420Sscottl if (doppr) { 245866647Sgibbs ahc_construct_ppr(ahc, devinfo, period, offset, 245966269Sgibbs tinfo->goal.width, ppr_options); 246066647Sgibbs } else { 246166647Sgibbs ahc_construct_sdtr(ahc, devinfo, period, offset); 246266647Sgibbs } 246366269Sgibbs } else { 246466647Sgibbs ahc_construct_wdtr(ahc, devinfo, tinfo->goal.width); 246565942Sgibbs } 246665942Sgibbs} 246741646Sgibbs 246865942Sgibbs/* 246966269Sgibbs * Build a synchronous negotiation message in our message 247065942Sgibbs * buffer based on the input parameters. 247165942Sgibbs */ 247265942Sgibbsstatic void 247366647Sgibbsahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 247466647Sgibbs u_int period, u_int offset) 247565942Sgibbs{ 2476107420Sscottl if (offset == 0) 2477107420Sscottl period = AHC_ASYNC_XFER_PERIOD; 247865942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; 247965942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN; 248065942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR; 248165942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = period; 248265942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = offset; 248365942Sgibbs ahc->msgout_len += 5; 248466647Sgibbs if (bootverbose) { 248566647Sgibbs printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", 248666647Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 248766647Sgibbs devinfo->lun, period, offset); 248866647Sgibbs } 248965942Sgibbs} 249041646Sgibbs 249165942Sgibbs/* 249295378Sgibbs * Build a wide negotiation message in our message 249365942Sgibbs * buffer based on the input parameters. 249465942Sgibbs */ 249565942Sgibbsstatic void 249666647Sgibbsahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 249766647Sgibbs u_int bus_width) 249865942Sgibbs{ 249965942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; 250065942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN; 250165942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR; 250265942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = bus_width; 250365942Sgibbs ahc->msgout_len += 4; 250466647Sgibbs if (bootverbose) { 250566647Sgibbs printf("(%s:%c:%d:%d): Sending WDTR %x\n", 250666647Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 250766647Sgibbs devinfo->lun, bus_width); 250866647Sgibbs } 250941646Sgibbs} 251041646Sgibbs 251165942Sgibbs/* 251265942Sgibbs * Build a parallel protocol request message in our message 251365942Sgibbs * buffer based on the input parameters. 251465942Sgibbs */ 251541646Sgibbsstatic void 251666647Sgibbsahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 251766647Sgibbs u_int period, u_int offset, u_int bus_width, 251866647Sgibbs u_int ppr_options) 251965942Sgibbs{ 2520107420Sscottl if (offset == 0) 2521107420Sscottl period = AHC_ASYNC_XFER_PERIOD; 252265942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; 252365942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN; 252465942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR; 252565942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = period; 252665942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = 0; 252765942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = offset; 252865942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = bus_width; 252965942Sgibbs ahc->msgout_buf[ahc->msgout_index++] = ppr_options; 253065942Sgibbs ahc->msgout_len += 8; 253166647Sgibbs if (bootverbose) { 253266647Sgibbs printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " 253366647Sgibbs "offset %x, ppr_options %x\n", ahc_name(ahc), 253466647Sgibbs devinfo->channel, devinfo->target, devinfo->lun, 253566647Sgibbs bus_width, period, offset, ppr_options); 253666647Sgibbs } 253765942Sgibbs} 253865942Sgibbs 253965942Sgibbs/* 254065942Sgibbs * Clear any active message state. 254165942Sgibbs */ 254265942Sgibbsstatic void 254341646Sgibbsahc_clear_msg_state(struct ahc_softc *ahc) 254441646Sgibbs{ 254541646Sgibbs ahc->msgout_len = 0; 254641646Sgibbs ahc->msgin_index = 0; 254741646Sgibbs ahc->msg_type = MSG_TYPE_NONE; 254874094Sgibbs if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0) { 254970204Sgibbs /* 255070204Sgibbs * The target didn't care to respond to our 255170204Sgibbs * message request, so clear ATN. 255270204Sgibbs */ 255370204Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 255470204Sgibbs } 255541887Sgibbs ahc_outb(ahc, MSG_OUT, MSG_NOOP); 255695378Sgibbs ahc_outb(ahc, SEQ_FLAGS2, 255795378Sgibbs ahc_inb(ahc, SEQ_FLAGS2) & ~TARGET_MSG_PENDING); 255841646Sgibbs} 255941646Sgibbs 2560107420Sscottlstatic void 2561107420Sscottlahc_handle_proto_violation(struct ahc_softc *ahc) 2562107420Sscottl{ 2563107420Sscottl struct ahc_devinfo devinfo; 2564107420Sscottl struct scb *scb; 2565107420Sscottl u_int scbid; 2566107420Sscottl u_int seq_flags; 2567107420Sscottl u_int curphase; 2568107420Sscottl u_int lastphase; 2569107420Sscottl int found; 2570107420Sscottl 2571107420Sscottl ahc_fetch_devinfo(ahc, &devinfo); 2572107420Sscottl scbid = ahc_inb(ahc, SCB_TAG); 2573107420Sscottl scb = ahc_lookup_scb(ahc, scbid); 2574107420Sscottl seq_flags = ahc_inb(ahc, SEQ_FLAGS); 2575107420Sscottl curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 2576107420Sscottl lastphase = ahc_inb(ahc, LASTPHASE); 2577107420Sscottl if ((seq_flags & NOT_IDENTIFIED) != 0) { 2578107420Sscottl 2579107420Sscottl /* 2580107420Sscottl * The reconnecting target either did not send an 2581107420Sscottl * identify message, or did, but we didn't find an SCB 2582107420Sscottl * to match. 2583107420Sscottl */ 2584107420Sscottl ahc_print_devinfo(ahc, &devinfo); 2585107420Sscottl printf("Target did not send an IDENTIFY message. " 2586107420Sscottl "LASTPHASE = 0x%x.\n", lastphase); 2587107420Sscottl scb = NULL; 2588107420Sscottl } else if (scb == NULL) { 2589107420Sscottl /* 2590107420Sscottl * We don't seem to have an SCB active for this 2591107420Sscottl * transaction. Print an error and reset the bus. 2592107420Sscottl */ 2593107420Sscottl ahc_print_devinfo(ahc, &devinfo); 2594107420Sscottl printf("No SCB found during protocol violation\n"); 2595107420Sscottl goto proto_violation_reset; 2596107420Sscottl } else { 2597123579Sgibbs aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); 2598107420Sscottl if ((seq_flags & NO_CDB_SENT) != 0) { 2599107420Sscottl ahc_print_path(ahc, scb); 2600107420Sscottl printf("No or incomplete CDB sent to device.\n"); 2601107420Sscottl } else if ((ahc_inb(ahc, SCB_CONTROL) & STATUS_RCVD) == 0) { 2602107420Sscottl /* 2603107420Sscottl * The target never bothered to provide status to 2604107420Sscottl * us prior to completing the command. Since we don't 2605107420Sscottl * know the disposition of this command, we must attempt 2606107420Sscottl * to abort it. Assert ATN and prepare to send an abort 2607107420Sscottl * message. 2608107420Sscottl */ 2609107420Sscottl ahc_print_path(ahc, scb); 2610107420Sscottl printf("Completed command without status.\n"); 2611107420Sscottl } else { 2612107420Sscottl ahc_print_path(ahc, scb); 2613107420Sscottl printf("Unknown protocol violation.\n"); 2614107420Sscottl ahc_dump_card_state(ahc); 2615107420Sscottl } 2616107420Sscottl } 2617107420Sscottl if ((lastphase & ~P_DATAIN_DT) == 0 2618107420Sscottl || lastphase == P_COMMAND) { 2619107420Sscottlproto_violation_reset: 2620107420Sscottl /* 2621107420Sscottl * Target either went directly to data/command 2622107420Sscottl * phase or didn't respond to our ATN. 2623107420Sscottl * The only safe thing to do is to blow 2624107420Sscottl * it away with a bus reset. 2625107420Sscottl */ 2626107420Sscottl found = ahc_reset_channel(ahc, 'A', TRUE); 2627107420Sscottl printf("%s: Issued Channel %c Bus Reset. " 2628107420Sscottl "%d SCBs aborted\n", ahc_name(ahc), 'A', found); 2629107420Sscottl } else { 2630107420Sscottl /* 2631107420Sscottl * Leave the selection hardware off in case 2632107420Sscottl * this abort attempt will affect yet to 2633107420Sscottl * be sent commands. 2634107420Sscottl */ 2635107420Sscottl ahc_outb(ahc, SCSISEQ, 2636107420Sscottl ahc_inb(ahc, SCSISEQ) & ~ENSELO); 2637107420Sscottl ahc_assert_atn(ahc); 2638107420Sscottl ahc_outb(ahc, MSG_OUT, HOST_MSG); 2639107420Sscottl if (scb == NULL) { 2640107420Sscottl ahc_print_devinfo(ahc, &devinfo); 2641107420Sscottl ahc->msgout_buf[0] = MSG_ABORT_TASK; 2642107420Sscottl ahc->msgout_len = 1; 2643107420Sscottl ahc->msgout_index = 0; 2644107420Sscottl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 2645107420Sscottl } else { 2646107420Sscottl ahc_print_path(ahc, scb); 2647107420Sscottl scb->flags |= SCB_ABORT; 2648107420Sscottl } 2649107420Sscottl printf("Protocol violation %s. Attempting to abort.\n", 2650107420Sscottl ahc_lookup_phase_entry(curphase)->phasemsg); 2651107420Sscottl } 2652107420Sscottl} 2653107420Sscottl 265465942Sgibbs/* 265565942Sgibbs * Manual message loop handler. 265665942Sgibbs */ 265741646Sgibbsstatic void 265865942Sgibbsahc_handle_message_phase(struct ahc_softc *ahc) 265939220Sgibbs{ 266039506Sgibbs struct ahc_devinfo devinfo; 266141646Sgibbs u_int bus_phase; 266241646Sgibbs int end_session; 266339220Sgibbs 266439220Sgibbs ahc_fetch_devinfo(ahc, &devinfo); 266541646Sgibbs end_session = FALSE; 266641646Sgibbs bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; 266741646Sgibbs 266841646Sgibbsreswitch: 266939220Sgibbs switch (ahc->msg_type) { 267039220Sgibbs case MSG_TYPE_INITIATOR_MSGOUT: 267139220Sgibbs { 267241646Sgibbs int lastbyte; 267341646Sgibbs int phasemis; 267441646Sgibbs int msgdone; 267539220Sgibbs 267641646Sgibbs if (ahc->msgout_len == 0) 267766269Sgibbs panic("HOST_MSG_LOOP interrupt with no active message"); 267839220Sgibbs 2679102670Sgibbs#ifdef AHC_DEBUG 2680104071Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2681102670Sgibbs ahc_print_devinfo(ahc, &devinfo); 2682102670Sgibbs printf("INITIATOR_MSG_OUT"); 2683104071Sgibbs } 2684102670Sgibbs#endif 268539220Sgibbs phasemis = bus_phase != P_MESGOUT; 268641646Sgibbs if (phasemis) { 2687102670Sgibbs#ifdef AHC_DEBUG 2688102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2689102670Sgibbs printf(" PHASEMIS %s\n", 2690102670Sgibbs ahc_lookup_phase_entry(bus_phase) 2691102670Sgibbs ->phasemsg); 2692102670Sgibbs } 2693102670Sgibbs#endif 269441646Sgibbs if (bus_phase == P_MESGIN) { 269541646Sgibbs /* 269641646Sgibbs * Change gears and see if 269741646Sgibbs * this messages is of interest to 269841646Sgibbs * us or should be passed back to 269941646Sgibbs * the sequencer. 270041646Sgibbs */ 270141887Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 270241646Sgibbs ahc->send_msg_perror = FALSE; 270341646Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN; 270441646Sgibbs ahc->msgin_index = 0; 270541646Sgibbs goto reswitch; 270639220Sgibbs } 270741646Sgibbs end_session = TRUE; 270841646Sgibbs break; 270941646Sgibbs } 271039220Sgibbs 271141646Sgibbs if (ahc->send_msg_perror) { 271241646Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 271341646Sgibbs ahc_outb(ahc, CLRSINT1, CLRREQINIT); 2714102670Sgibbs#ifdef AHC_DEBUG 2715102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2716102670Sgibbs printf(" byte 0x%x\n", ahc->send_msg_perror); 2717102670Sgibbs#endif 271841646Sgibbs ahc_outb(ahc, SCSIDATL, MSG_PARITY_ERROR); 271941646Sgibbs break; 272041646Sgibbs } 272141646Sgibbs 272241646Sgibbs msgdone = ahc->msgout_index == ahc->msgout_len; 272341646Sgibbs if (msgdone) { 272439220Sgibbs /* 272541646Sgibbs * The target has requested a retry. 272641646Sgibbs * Re-assert ATN, reset our message index to 272741646Sgibbs * 0, and try again. 272839220Sgibbs */ 272941646Sgibbs ahc->msgout_index = 0; 273076634Sgibbs ahc_assert_atn(ahc); 273139220Sgibbs } 273241646Sgibbs 273341646Sgibbs lastbyte = ahc->msgout_index == (ahc->msgout_len - 1); 273441646Sgibbs if (lastbyte) { 273541646Sgibbs /* Last byte is signified by dropping ATN */ 273641646Sgibbs ahc_outb(ahc, CLRSINT1, CLRATNO); 273741646Sgibbs } 273841646Sgibbs 273941646Sgibbs /* 274041646Sgibbs * Clear our interrupt status and present 274141646Sgibbs * the next byte on the bus. 274241646Sgibbs */ 274341646Sgibbs ahc_outb(ahc, CLRSINT1, CLRREQINIT); 2744102670Sgibbs#ifdef AHC_DEBUG 2745102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2746102670Sgibbs printf(" byte 0x%x\n", 2747102670Sgibbs ahc->msgout_buf[ahc->msgout_index]); 2748102670Sgibbs#endif 274941646Sgibbs ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); 275039220Sgibbs break; 275139220Sgibbs } 275239220Sgibbs case MSG_TYPE_INITIATOR_MSGIN: 275339220Sgibbs { 275441646Sgibbs int phasemis; 275541646Sgibbs int message_done; 275639220Sgibbs 2757102670Sgibbs#ifdef AHC_DEBUG 2758102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2759102670Sgibbs ahc_print_devinfo(ahc, &devinfo); 2760102670Sgibbs printf("INITIATOR_MSG_IN"); 2761102670Sgibbs } 2762102670Sgibbs#endif 276341646Sgibbs phasemis = bus_phase != P_MESGIN; 276441646Sgibbs if (phasemis) { 2765102670Sgibbs#ifdef AHC_DEBUG 2766102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2767102670Sgibbs printf(" PHASEMIS %s\n", 2768102670Sgibbs ahc_lookup_phase_entry(bus_phase) 2769102670Sgibbs ->phasemsg); 2770102670Sgibbs } 2771102670Sgibbs#endif 277241646Sgibbs ahc->msgin_index = 0; 277341646Sgibbs if (bus_phase == P_MESGOUT 277441646Sgibbs && (ahc->send_msg_perror == TRUE 277541646Sgibbs || (ahc->msgout_len != 0 277641646Sgibbs && ahc->msgout_index == 0))) { 277741646Sgibbs ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; 277841646Sgibbs goto reswitch; 277941646Sgibbs } 278041646Sgibbs end_session = TRUE; 278141646Sgibbs break; 278241646Sgibbs } 278341646Sgibbs 278441646Sgibbs /* Pull the byte in without acking it */ 278541646Sgibbs ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIBUSL); 2786102670Sgibbs#ifdef AHC_DEBUG 2787102670Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2788102670Sgibbs printf(" byte 0x%x\n", 2789102670Sgibbs ahc->msgin_buf[ahc->msgin_index]); 2790102670Sgibbs#endif 279141646Sgibbs 279265942Sgibbs message_done = ahc_parse_msg(ahc, &devinfo); 279341646Sgibbs 279441646Sgibbs if (message_done) { 279541646Sgibbs /* 279641646Sgibbs * Clear our incoming message buffer in case there 279741646Sgibbs * is another message following this one. 279841646Sgibbs */ 279941646Sgibbs ahc->msgin_index = 0; 280041646Sgibbs 280141646Sgibbs /* 280241646Sgibbs * If this message illicited a response, 280341646Sgibbs * assert ATN so the target takes us to the 280441646Sgibbs * message out phase. 280541646Sgibbs */ 2806109590Sgibbs if (ahc->msgout_len != 0) { 2807109590Sgibbs#ifdef AHC_DEBUG 2808109590Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2809109590Sgibbs ahc_print_devinfo(ahc, &devinfo); 2810109590Sgibbs printf("Asserting ATN for response\n"); 2811109590Sgibbs } 2812109590Sgibbs#endif 281376634Sgibbs ahc_assert_atn(ahc); 2814109590Sgibbs } 281554211Sgibbs } else 281654211Sgibbs ahc->msgin_index++; 281741646Sgibbs 2818102670Sgibbs if (message_done == MSGLOOP_TERMINATED) { 2819102670Sgibbs end_session = TRUE; 2820102670Sgibbs } else { 2821102670Sgibbs /* Ack the byte */ 2822102670Sgibbs ahc_outb(ahc, CLRSINT1, CLRREQINIT); 2823102670Sgibbs ahc_inb(ahc, SCSIDATL); 2824102670Sgibbs } 282541646Sgibbs break; 282641646Sgibbs } 282741646Sgibbs case MSG_TYPE_TARGET_MSGIN: 282841646Sgibbs { 282941646Sgibbs int msgdone; 283041646Sgibbs 283141646Sgibbs if (ahc->msgout_len == 0) 283242652Sgibbs panic("Target MSGIN with no active message"); 283341646Sgibbs 2834136711Sgibbs#ifdef AHC_DEBUG 2835136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2836136711Sgibbs ahc_print_devinfo(ahc, &devinfo); 2837136711Sgibbs printf("TARGET_MSG_IN"); 2838136711Sgibbs } 2839136711Sgibbs#endif 2840136711Sgibbs 284141646Sgibbs /* 284241646Sgibbs * If we interrupted a mesgout session, the initiator 284341646Sgibbs * will not know this until our first REQ. So, we 284441646Sgibbs * only honor mesgout requests after we've sent our 284541646Sgibbs * first byte. 284641646Sgibbs */ 284741646Sgibbs if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0 2848136711Sgibbs && ahc->msgout_index > 0) { 284941646Sgibbs 2850136711Sgibbs /* 2851136711Sgibbs * Change gears and see if this messages is 2852136711Sgibbs * of interest to us or should be passed back 2853136711Sgibbs * to the sequencer. 2854136711Sgibbs */ 2855136711Sgibbs#ifdef AHC_DEBUG 2856136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2857136711Sgibbs printf(" Honoring ATN Request.\n"); 2858136711Sgibbs#endif 2859136711Sgibbs ahc->msg_type = MSG_TYPE_TARGET_MSGOUT; 286041646Sgibbs 286141646Sgibbs /* 2862136711Sgibbs * Disable SCSI Programmed I/O during the 2863136711Sgibbs * phase change so as to avoid phantom REQs. 286441646Sgibbs */ 2865136711Sgibbs ahc_outb(ahc, SXFRCTL0, 2866136711Sgibbs ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); 2867136711Sgibbs 2868136711Sgibbs /* 2869136711Sgibbs * Since SPIORDY asserts when ACK is asserted 2870136711Sgibbs * for P_MSGOUT, and SPIORDY's assertion triggered 2871136711Sgibbs * our entry into this routine, wait for ACK to 2872136711Sgibbs * *de-assert* before changing phases. 2873136711Sgibbs */ 2874136711Sgibbs while ((ahc_inb(ahc, SCSISIGI) & ACKI) != 0) 2875136711Sgibbs ; 2876136711Sgibbs 287741646Sgibbs ahc_outb(ahc, SCSISIGO, P_MESGOUT | BSYO); 2878136711Sgibbs 2879136711Sgibbs /* 2880136711Sgibbs * All phase line changes require a bus 2881136711Sgibbs * settle delay before REQ is asserted. 2882136711Sgibbs * [SCSI SPI4 10.7.1] 2883136711Sgibbs */ 2884136711Sgibbs ahc_flush_device_writes(ahc); 2885136711Sgibbs aic_delay(AHC_BUSSETTLE_DELAY); 2886136711Sgibbs 288741646Sgibbs ahc->msgin_index = 0; 2888136711Sgibbs /* Enable SCSI Programmed I/O to REQ for first byte */ 288941646Sgibbs ahc_outb(ahc, SXFRCTL0, 289041646Sgibbs ahc_inb(ahc, SXFRCTL0) | SPIOEN); 289141646Sgibbs break; 289239220Sgibbs } 289341646Sgibbs 289441646Sgibbs msgdone = ahc->msgout_index == ahc->msgout_len; 289541646Sgibbs if (msgdone) { 289641646Sgibbs ahc_outb(ahc, SXFRCTL0, 289741646Sgibbs ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); 289841646Sgibbs end_session = TRUE; 289941646Sgibbs break; 290039220Sgibbs } 290141646Sgibbs 290241646Sgibbs /* 290341646Sgibbs * Present the next byte on the bus. 290441646Sgibbs */ 2905136711Sgibbs#ifdef AHC_DEBUG 2906136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2907136711Sgibbs printf(" byte 0x%x\n", 2908136711Sgibbs ahc->msgout_buf[ahc->msgout_index]); 2909136711Sgibbs#endif 291041646Sgibbs ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN); 291141646Sgibbs ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); 291239220Sgibbs break; 291339220Sgibbs } 291441646Sgibbs case MSG_TYPE_TARGET_MSGOUT: 291541646Sgibbs { 291641646Sgibbs int lastbyte; 291741646Sgibbs int msgdone; 291841646Sgibbs 2919136711Sgibbs#ifdef AHC_DEBUG 2920136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2921136711Sgibbs ahc_print_devinfo(ahc, &devinfo); 2922136711Sgibbs printf("TARGET_MSG_OUT"); 2923136711Sgibbs } 2924136711Sgibbs#endif 292541646Sgibbs /* 292641646Sgibbs * The initiator signals that this is 292741646Sgibbs * the last byte by dropping ATN. 292841646Sgibbs */ 292941646Sgibbs lastbyte = (ahc_inb(ahc, SCSISIGI) & ATNI) == 0; 293041646Sgibbs 293141646Sgibbs /* 293241646Sgibbs * Read the latched byte, but turn off SPIOEN first 293395378Sgibbs * so that we don't inadvertently cause a REQ for the 293441646Sgibbs * next byte. 293541646Sgibbs */ 293641646Sgibbs ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); 293741646Sgibbs ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIDATL); 2938136711Sgibbs 2939136711Sgibbs#ifdef AHC_DEBUG 2940136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) 2941136711Sgibbs printf(" byte 0x%x\n", 2942136711Sgibbs ahc->msgin_buf[ahc->msgin_index]); 2943136711Sgibbs#endif 2944136711Sgibbs 294565942Sgibbs msgdone = ahc_parse_msg(ahc, &devinfo); 294649933Sgibbs if (msgdone == MSGLOOP_TERMINATED) { 294749933Sgibbs /* 294849933Sgibbs * The message is *really* done in that it caused 294949933Sgibbs * us to go to bus free. The sequencer has already 295049933Sgibbs * been reset at this point, so pull the ejection 295149933Sgibbs * handle. 295249933Sgibbs */ 295349933Sgibbs return; 295449933Sgibbs } 295549933Sgibbs 295641646Sgibbs ahc->msgin_index++; 295741646Sgibbs 295841646Sgibbs /* 295941646Sgibbs * XXX Read spec about initiator dropping ATN too soon 296041646Sgibbs * and use msgdone to detect it. 296141646Sgibbs */ 296249933Sgibbs if (msgdone == MSGLOOP_MSGCOMPLETE) { 296341646Sgibbs ahc->msgin_index = 0; 296441646Sgibbs 296541646Sgibbs /* 296641646Sgibbs * If this message illicited a response, transition 296741646Sgibbs * to the Message in phase and send it. 296841646Sgibbs */ 296941646Sgibbs if (ahc->msgout_len != 0) { 2970136711Sgibbs#ifdef AHC_DEBUG 2971136711Sgibbs if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { 2972136711Sgibbs ahc_print_devinfo(ahc, &devinfo); 2973136711Sgibbs printf(" preparing response.\n"); 2974136711Sgibbs } 2975136711Sgibbs#endif 297641646Sgibbs ahc_outb(ahc, SCSISIGO, P_MESGIN | BSYO); 2977136711Sgibbs 2978136711Sgibbs /* 2979136711Sgibbs * All phase line changes require a bus 2980136711Sgibbs * settle delay before REQ is asserted. 2981136711Sgibbs * [SCSI SPI4 10.7.1] When transitioning 2982136711Sgibbs * from an OUT to an IN phase, we must 2983136711Sgibbs * also wait a data release delay to allow 2984136711Sgibbs * the initiator time to release the data 2985136711Sgibbs * lines. [SCSI SPI4 10.12] 2986136711Sgibbs */ 2987136711Sgibbs ahc_flush_device_writes(ahc); 2988136711Sgibbs aic_delay(AHC_BUSSETTLE_DELAY 2989136711Sgibbs + AHC_DATARELEASE_DELAY); 2990136711Sgibbs 2991136711Sgibbs /* 2992136711Sgibbs * Enable SCSI Programmed I/O. This will 2993136711Sgibbs * immediately cause SPIORDY to assert, 2994136711Sgibbs * and the sequencer will call our message 2995136711Sgibbs * loop again. 2996136711Sgibbs */ 299741646Sgibbs ahc_outb(ahc, SXFRCTL0, 299841646Sgibbs ahc_inb(ahc, SXFRCTL0) | SPIOEN); 299941646Sgibbs ahc->msg_type = MSG_TYPE_TARGET_MSGIN; 300041646Sgibbs ahc->msgin_index = 0; 300141646Sgibbs break; 300241646Sgibbs } 300341646Sgibbs } 300441646Sgibbs 300541646Sgibbs if (lastbyte) 300641646Sgibbs end_session = TRUE; 300741646Sgibbs else { 300841646Sgibbs /* Ask for the next byte. */ 300941646Sgibbs ahc_outb(ahc, SXFRCTL0, 301041646Sgibbs ahc_inb(ahc, SXFRCTL0) | SPIOEN); 301141646Sgibbs } 301241646Sgibbs 301341646Sgibbs break; 301441646Sgibbs } 301539220Sgibbs default: 301639220Sgibbs panic("Unknown REQINIT message type"); 301739220Sgibbs } 301841646Sgibbs 301941646Sgibbs if (end_session) { 302041646Sgibbs ahc_clear_msg_state(ahc); 302141646Sgibbs ahc_outb(ahc, RETURN_1, EXIT_MSG_LOOP); 302241646Sgibbs } else 302341646Sgibbs ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP); 302439220Sgibbs} 302539220Sgibbs 302641646Sgibbs/* 302741646Sgibbs * See if we sent a particular extended message to the target. 302865942Sgibbs * If "full" is true, return true only if the target saw the full 302965942Sgibbs * message. If "full" is false, return true if the target saw at 303065942Sgibbs * least the first byte of the message. 303141646Sgibbs */ 303239220Sgibbsstatic int 303370204Sgibbsahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, u_int msgval, int full) 303441646Sgibbs{ 303541646Sgibbs int found; 303663457Sgibbs u_int index; 303741646Sgibbs 303841646Sgibbs found = FALSE; 303941646Sgibbs index = 0; 304041646Sgibbs 304141646Sgibbs while (index < ahc->msgout_len) { 304257099Sgibbs if (ahc->msgout_buf[index] == MSG_EXTENDED) { 304370204Sgibbs u_int end_index; 304457099Sgibbs 304570204Sgibbs end_index = index + 1 + ahc->msgout_buf[index + 1]; 304670204Sgibbs if (ahc->msgout_buf[index+2] == msgval 304770204Sgibbs && type == AHCMSG_EXT) { 304841646Sgibbs 304941646Sgibbs if (full) { 305041646Sgibbs if (ahc->msgout_index > end_index) 305141646Sgibbs found = TRUE; 305241646Sgibbs } else if (ahc->msgout_index > index) 305341646Sgibbs found = TRUE; 305441646Sgibbs } 305570204Sgibbs index = end_index; 305676634Sgibbs } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_TASK 305757099Sgibbs && ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) { 305857099Sgibbs 305957099Sgibbs /* Skip tag type and tag id or residue param*/ 306057099Sgibbs index += 2; 306141646Sgibbs } else { 306257099Sgibbs /* Single byte message */ 306370204Sgibbs if (type == AHCMSG_1B 306470204Sgibbs && ahc->msgout_buf[index] == msgval 306570204Sgibbs && ahc->msgout_index > index) 306670204Sgibbs found = TRUE; 306757099Sgibbs index++; 306841646Sgibbs } 306970204Sgibbs 307070204Sgibbs if (found) 307170204Sgibbs break; 307241646Sgibbs } 307341646Sgibbs return (found); 307441646Sgibbs} 307541646Sgibbs 307665942Sgibbs/* 307776634Sgibbs * Wait for a complete incoming message, parse it, and respond accordingly. 307865942Sgibbs */ 307941646Sgibbsstatic int 308065942Sgibbsahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 308139220Sgibbs{ 308244507Sgibbs struct ahc_initiator_tinfo *tinfo; 308374972Sgibbs struct ahc_tmode_tstate *tstate; 308444507Sgibbs int reject; 308544507Sgibbs int done; 308644507Sgibbs int response; 308744507Sgibbs u_int targ_scsirate; 308839220Sgibbs 308949933Sgibbs done = MSGLOOP_IN_PROG; 309041646Sgibbs response = FALSE; 309139220Sgibbs reject = FALSE; 309244507Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 309344507Sgibbs devinfo->target, &tstate); 309444507Sgibbs targ_scsirate = tinfo->scsirate; 309544507Sgibbs 309639220Sgibbs /* 3097114621Sgibbs * Parse as much of the message as is available, 309839220Sgibbs * rejecting it if we don't support it. When 3099114621Sgibbs * the entire message is available and has been 310055581Sgibbs * handled, return MSGLOOP_MSGCOMPLETE, indicating 310155581Sgibbs * that we have parsed an entire message. 310241646Sgibbs * 310341646Sgibbs * In the case of extended messages, we accept the length 310441646Sgibbs * byte outright and perform more checking once we know the 310541646Sgibbs * extended message type. 310639220Sgibbs */ 310742652Sgibbs switch (ahc->msgin_buf[0]) { 3108102670Sgibbs case MSG_DISCONNECT: 3109102670Sgibbs case MSG_SAVEDATAPOINTER: 3110102670Sgibbs case MSG_CMDCOMPLETE: 3111102670Sgibbs case MSG_RESTOREPOINTERS: 3112102670Sgibbs case MSG_IGN_WIDE_RESIDUE: 3113102670Sgibbs /* 3114102670Sgibbs * End our message loop as these are messages 3115102670Sgibbs * the sequencer handles on its own. 3116102670Sgibbs */ 3117102670Sgibbs done = MSGLOOP_TERMINATED; 3118102670Sgibbs break; 311942652Sgibbs case MSG_MESSAGE_REJECT: 312041887Sgibbs response = ahc_handle_msg_reject(ahc, devinfo); 312142652Sgibbs /* FALLTHROUGH */ 312242652Sgibbs case MSG_NOOP: 312349933Sgibbs done = MSGLOOP_MSGCOMPLETE; 312442652Sgibbs break; 312542652Sgibbs case MSG_EXTENDED: 312642652Sgibbs { 312742652Sgibbs /* Wait for enough of the message to begin validation */ 312842652Sgibbs if (ahc->msgin_index < 2) 312942652Sgibbs break; 313041646Sgibbs switch (ahc->msgin_buf[2]) { 313139220Sgibbs case MSG_EXT_SDTR: 313239220Sgibbs { 313339220Sgibbs struct ahc_syncrate *syncrate; 313439220Sgibbs u_int period; 313563457Sgibbs u_int ppr_options; 313639220Sgibbs u_int offset; 313739220Sgibbs u_int saved_offset; 313839220Sgibbs 313941646Sgibbs if (ahc->msgin_buf[1] != MSG_EXT_SDTR_LEN) { 314039220Sgibbs reject = TRUE; 314139220Sgibbs break; 314239220Sgibbs } 314339220Sgibbs 314439220Sgibbs /* 314539220Sgibbs * Wait until we have both args before validating 314639220Sgibbs * and acting on this message. 314741646Sgibbs * 314841646Sgibbs * Add one to MSG_EXT_SDTR_LEN to account for 314941646Sgibbs * the extended message preamble. 315039220Sgibbs */ 315141646Sgibbs if (ahc->msgin_index < (MSG_EXT_SDTR_LEN + 1)) 315239220Sgibbs break; 315339220Sgibbs 315441646Sgibbs period = ahc->msgin_buf[3]; 315563457Sgibbs ppr_options = 0; 315641646Sgibbs saved_offset = offset = ahc->msgin_buf[4]; 315768087Sgibbs syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period, 315868087Sgibbs &ppr_options, 315968087Sgibbs devinfo->role); 316068087Sgibbs ahc_validate_offset(ahc, tinfo, syncrate, &offset, 316168087Sgibbs targ_scsirate & WIDEXFER, 316268087Sgibbs devinfo->role); 316366647Sgibbs if (bootverbose) { 316466647Sgibbs printf("(%s:%c:%d:%d): Received " 316566647Sgibbs "SDTR period %x, offset %x\n\t" 316666647Sgibbs "Filtered to period %x, offset %x\n", 316766647Sgibbs ahc_name(ahc), devinfo->channel, 316866647Sgibbs devinfo->target, devinfo->lun, 316966647Sgibbs ahc->msgin_buf[3], saved_offset, 317066647Sgibbs period, offset); 317166647Sgibbs } 317265942Sgibbs ahc_set_syncrate(ahc, devinfo, 317363457Sgibbs syncrate, period, 317463457Sgibbs offset, ppr_options, 317547287Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 317647287Sgibbs /*paused*/TRUE); 317739220Sgibbs 317839220Sgibbs /* 317939220Sgibbs * See if we initiated Sync Negotiation 318039220Sgibbs * and didn't have to fall down to async 318139220Sgibbs * transfers. 318239220Sgibbs */ 318370204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, TRUE)) { 318439220Sgibbs /* We started it */ 318539220Sgibbs if (saved_offset != offset) { 318639220Sgibbs /* Went too low - force async */ 318739220Sgibbs reject = TRUE; 318839220Sgibbs } 318939220Sgibbs } else { 319039220Sgibbs /* 319139220Sgibbs * Send our own SDTR in reply 319239220Sgibbs */ 319374972Sgibbs if (bootverbose 319474972Sgibbs && devinfo->role == ROLE_INITIATOR) { 319566647Sgibbs printf("(%s:%c:%d:%d): Target " 319666647Sgibbs "Initiated SDTR\n", 319766647Sgibbs ahc_name(ahc), devinfo->channel, 319866647Sgibbs devinfo->target, devinfo->lun); 319966647Sgibbs } 320041646Sgibbs ahc->msgout_index = 0; 320141646Sgibbs ahc->msgout_len = 0; 320266647Sgibbs ahc_construct_sdtr(ahc, devinfo, 320366647Sgibbs period, offset); 320441646Sgibbs ahc->msgout_index = 0; 320541646Sgibbs response = TRUE; 320639220Sgibbs } 320749933Sgibbs done = MSGLOOP_MSGCOMPLETE; 320839220Sgibbs break; 320939220Sgibbs } 321039220Sgibbs case MSG_EXT_WDTR: 321139220Sgibbs { 321263457Sgibbs u_int bus_width; 321363457Sgibbs u_int saved_width; 321463457Sgibbs u_int sending_reply; 321539220Sgibbs 321641646Sgibbs sending_reply = FALSE; 321741646Sgibbs if (ahc->msgin_buf[1] != MSG_EXT_WDTR_LEN) { 321839220Sgibbs reject = TRUE; 321939220Sgibbs break; 322039220Sgibbs } 322139220Sgibbs 322239220Sgibbs /* 322339220Sgibbs * Wait until we have our arg before validating 322439220Sgibbs * and acting on this message. 322541646Sgibbs * 322641646Sgibbs * Add one to MSG_EXT_WDTR_LEN to account for 322741646Sgibbs * the extended message preamble. 322839220Sgibbs */ 322941646Sgibbs if (ahc->msgin_index < (MSG_EXT_WDTR_LEN + 1)) 323039220Sgibbs break; 323139220Sgibbs 323241646Sgibbs bus_width = ahc->msgin_buf[3]; 323363457Sgibbs saved_width = bus_width; 323468087Sgibbs ahc_validate_width(ahc, tinfo, &bus_width, 323568087Sgibbs devinfo->role); 323666647Sgibbs if (bootverbose) { 323766647Sgibbs printf("(%s:%c:%d:%d): Received WDTR " 323866647Sgibbs "%x filtered to %x\n", 323966647Sgibbs ahc_name(ahc), devinfo->channel, 324066647Sgibbs devinfo->target, devinfo->lun, 324166647Sgibbs saved_width, bus_width); 324266647Sgibbs } 324363457Sgibbs 324470204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, TRUE)) { 324539220Sgibbs /* 324639220Sgibbs * Don't send a WDTR back to the 324739220Sgibbs * target, since we asked first. 324863457Sgibbs * If the width went higher than our 324963457Sgibbs * request, reject it. 325039220Sgibbs */ 325163457Sgibbs if (saved_width > bus_width) { 325239220Sgibbs reject = TRUE; 325366647Sgibbs printf("(%s:%c:%d:%d): requested %dBit " 325439220Sgibbs "transfers. Rejecting...\n", 325566647Sgibbs ahc_name(ahc), devinfo->channel, 325666647Sgibbs devinfo->target, devinfo->lun, 325739220Sgibbs 8 * (0x01 << bus_width)); 325863457Sgibbs bus_width = 0; 325939220Sgibbs } 326039220Sgibbs } else { 326139220Sgibbs /* 326239220Sgibbs * Send our own WDTR in reply 326339220Sgibbs */ 326474972Sgibbs if (bootverbose 326574972Sgibbs && devinfo->role == ROLE_INITIATOR) { 326666647Sgibbs printf("(%s:%c:%d:%d): Target " 326766647Sgibbs "Initiated WDTR\n", 326866647Sgibbs ahc_name(ahc), devinfo->channel, 326966647Sgibbs devinfo->target, devinfo->lun); 327066647Sgibbs } 327141646Sgibbs ahc->msgout_index = 0; 327241646Sgibbs ahc->msgout_len = 0; 327366647Sgibbs ahc_construct_wdtr(ahc, devinfo, bus_width); 327441646Sgibbs ahc->msgout_index = 0; 327541646Sgibbs response = TRUE; 327641646Sgibbs sending_reply = TRUE; 327739220Sgibbs } 3278115918Sgibbs /* 3279115918Sgibbs * After a wide message, we are async, but 3280115918Sgibbs * some devices don't seem to honor this portion 3281115918Sgibbs * of the spec. Force a renegotiation of the 3282115918Sgibbs * sync component of our transfer agreement even 3283115918Sgibbs * if our goal is async. By updating our width 3284115918Sgibbs * after forcing the negotiation, we avoid 3285115918Sgibbs * renegotiating for width. 3286115918Sgibbs */ 3287115918Sgibbs ahc_update_neg_request(ahc, devinfo, tstate, 3288115918Sgibbs tinfo, AHC_NEG_ALWAYS); 328965942Sgibbs ahc_set_width(ahc, devinfo, bus_width, 329047287Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 329147287Sgibbs /*paused*/TRUE); 329241646Sgibbs if (sending_reply == FALSE && reject == FALSE) { 329339220Sgibbs 3294115918Sgibbs /* 3295115918Sgibbs * We will always have an SDTR to send. 3296115918Sgibbs */ 3297115918Sgibbs ahc->msgout_index = 0; 3298115918Sgibbs ahc->msgout_len = 0; 3299115918Sgibbs ahc_build_transfer_msg(ahc, devinfo); 3300115918Sgibbs ahc->msgout_index = 0; 3301115918Sgibbs response = TRUE; 330239220Sgibbs } 330349933Sgibbs done = MSGLOOP_MSGCOMPLETE; 330439220Sgibbs break; 330539220Sgibbs } 330663457Sgibbs case MSG_EXT_PPR: 330763457Sgibbs { 330863457Sgibbs struct ahc_syncrate *syncrate; 330963457Sgibbs u_int period; 331063457Sgibbs u_int offset; 331163457Sgibbs u_int bus_width; 331263457Sgibbs u_int ppr_options; 331363457Sgibbs u_int saved_width; 331463457Sgibbs u_int saved_offset; 331563457Sgibbs u_int saved_ppr_options; 331663457Sgibbs 331763457Sgibbs if (ahc->msgin_buf[1] != MSG_EXT_PPR_LEN) { 331863457Sgibbs reject = TRUE; 331963457Sgibbs break; 332063457Sgibbs } 332163457Sgibbs 332263457Sgibbs /* 332363457Sgibbs * Wait until we have all args before validating 332463457Sgibbs * and acting on this message. 332563457Sgibbs * 332663457Sgibbs * Add one to MSG_EXT_PPR_LEN to account for 332763457Sgibbs * the extended message preamble. 332863457Sgibbs */ 332963457Sgibbs if (ahc->msgin_index < (MSG_EXT_PPR_LEN + 1)) 333063457Sgibbs break; 333163457Sgibbs 333263457Sgibbs period = ahc->msgin_buf[3]; 333363457Sgibbs offset = ahc->msgin_buf[5]; 333463457Sgibbs bus_width = ahc->msgin_buf[6]; 333563457Sgibbs saved_width = bus_width; 333663457Sgibbs ppr_options = ahc->msgin_buf[7]; 333763457Sgibbs /* 333863457Sgibbs * According to the spec, a DT only 333963457Sgibbs * period factor with no DT option 334063457Sgibbs * set implies async. 334163457Sgibbs */ 334263457Sgibbs if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0 334363457Sgibbs && period == 9) 334463457Sgibbs offset = 0; 334563457Sgibbs saved_ppr_options = ppr_options; 334663457Sgibbs saved_offset = offset; 334763457Sgibbs 334863457Sgibbs /* 334963457Sgibbs * Mask out any options we don't support 335063457Sgibbs * on any controller. Transfer options are 335163457Sgibbs * only available if we are negotiating wide. 335263457Sgibbs */ 335363457Sgibbs ppr_options &= MSG_EXT_PPR_DT_REQ; 335463457Sgibbs if (bus_width == 0) 335563457Sgibbs ppr_options = 0; 335663457Sgibbs 335768087Sgibbs ahc_validate_width(ahc, tinfo, &bus_width, 335868087Sgibbs devinfo->role); 335968087Sgibbs syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period, 336068087Sgibbs &ppr_options, 336168087Sgibbs devinfo->role); 336268087Sgibbs ahc_validate_offset(ahc, tinfo, syncrate, 336368087Sgibbs &offset, bus_width, 336468087Sgibbs devinfo->role); 336563457Sgibbs 336670204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, TRUE)) { 336763457Sgibbs /* 336863457Sgibbs * If we are unable to do any of the 336963457Sgibbs * requested options (we went too low), 337063457Sgibbs * then we'll have to reject the message. 337163457Sgibbs */ 337263457Sgibbs if (saved_width > bus_width 337363457Sgibbs || saved_offset != offset 337466647Sgibbs || saved_ppr_options != ppr_options) { 337563457Sgibbs reject = TRUE; 337666647Sgibbs period = 0; 337766647Sgibbs offset = 0; 337866647Sgibbs bus_width = 0; 337966647Sgibbs ppr_options = 0; 338066647Sgibbs syncrate = NULL; 338166647Sgibbs } 338263457Sgibbs } else { 338368087Sgibbs if (devinfo->role != ROLE_TARGET) 338468087Sgibbs printf("(%s:%c:%d:%d): Target " 338568087Sgibbs "Initiated PPR\n", 338668087Sgibbs ahc_name(ahc), devinfo->channel, 338768087Sgibbs devinfo->target, devinfo->lun); 338868087Sgibbs else 338968087Sgibbs printf("(%s:%c:%d:%d): Initiator " 339068087Sgibbs "Initiated PPR\n", 339168087Sgibbs ahc_name(ahc), devinfo->channel, 339268087Sgibbs devinfo->target, devinfo->lun); 339368087Sgibbs ahc->msgout_index = 0; 339468087Sgibbs ahc->msgout_len = 0; 339568087Sgibbs ahc_construct_ppr(ahc, devinfo, period, offset, 339668087Sgibbs bus_width, ppr_options); 339768087Sgibbs ahc->msgout_index = 0; 339863457Sgibbs response = TRUE; 339963457Sgibbs } 340066647Sgibbs if (bootverbose) { 340166647Sgibbs printf("(%s:%c:%d:%d): Received PPR width %x, " 340266647Sgibbs "period %x, offset %x,options %x\n" 340366647Sgibbs "\tFiltered to width %x, period %x, " 340466647Sgibbs "offset %x, options %x\n", 340566647Sgibbs ahc_name(ahc), devinfo->channel, 340666647Sgibbs devinfo->target, devinfo->lun, 340774094Sgibbs saved_width, ahc->msgin_buf[3], 340866647Sgibbs saved_offset, saved_ppr_options, 340966647Sgibbs bus_width, period, offset, ppr_options); 341066647Sgibbs } 341165942Sgibbs ahc_set_width(ahc, devinfo, bus_width, 341265942Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 341365942Sgibbs /*paused*/TRUE); 341465942Sgibbs ahc_set_syncrate(ahc, devinfo, 341563457Sgibbs syncrate, period, 341663457Sgibbs offset, ppr_options, 341763457Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 341863457Sgibbs /*paused*/TRUE); 341968087Sgibbs done = MSGLOOP_MSGCOMPLETE; 342063457Sgibbs break; 342163457Sgibbs } 342239220Sgibbs default: 342339220Sgibbs /* Unknown extended message. Reject it. */ 342439220Sgibbs reject = TRUE; 342539220Sgibbs break; 342639220Sgibbs } 342742708Sgibbs break; 342839220Sgibbs } 342995378Sgibbs#ifdef AHC_TARGET_MODE 343049933Sgibbs case MSG_BUS_DEV_RESET: 343149933Sgibbs ahc_handle_devreset(ahc, devinfo, 343265942Sgibbs CAM_BDR_SENT, 343349933Sgibbs "Bus Device Reset Received", 343454211Sgibbs /*verbose_level*/0); 343574094Sgibbs ahc_restart(ahc); 343649933Sgibbs done = MSGLOOP_TERMINATED; 343749933Sgibbs break; 343849933Sgibbs case MSG_ABORT_TAG: 343942652Sgibbs case MSG_ABORT: 344042652Sgibbs case MSG_CLEAR_QUEUE: 344195378Sgibbs { 344295378Sgibbs int tag; 344395378Sgibbs 344442652Sgibbs /* Target mode messages */ 344549933Sgibbs if (devinfo->role != ROLE_TARGET) { 344642652Sgibbs reject = TRUE; 344749933Sgibbs break; 344849933Sgibbs } 344995378Sgibbs tag = SCB_LIST_NULL; 345095378Sgibbs if (ahc->msgin_buf[0] == MSG_ABORT_TAG) 345195378Sgibbs tag = ahc_inb(ahc, INITIATOR_TAG); 345249933Sgibbs ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, 345395378Sgibbs devinfo->lun, tag, ROLE_TARGET, 345495378Sgibbs CAM_REQ_ABORTED); 345549933Sgibbs 345649933Sgibbs tstate = ahc->enabled_targets[devinfo->our_scsiid]; 345749933Sgibbs if (tstate != NULL) { 345874972Sgibbs struct ahc_tmode_lstate* lstate; 345949933Sgibbs 346049933Sgibbs lstate = tstate->enabled_luns[devinfo->lun]; 346149933Sgibbs if (lstate != NULL) { 346249933Sgibbs ahc_queue_lstate_event(ahc, lstate, 346349933Sgibbs devinfo->our_scsiid, 346449933Sgibbs ahc->msgin_buf[0], 346595378Sgibbs /*arg*/tag); 346649933Sgibbs ahc_send_lstate_events(ahc, lstate); 346749933Sgibbs } 346849933Sgibbs } 346995378Sgibbs ahc_restart(ahc); 347095378Sgibbs done = MSGLOOP_TERMINATED; 347142652Sgibbs break; 347295378Sgibbs } 347365942Sgibbs#endif 347449933Sgibbs case MSG_TERM_IO_PROC: 347542652Sgibbs default: 347642652Sgibbs reject = TRUE; 347742652Sgibbs break; 347842652Sgibbs } 347939220Sgibbs 348039220Sgibbs if (reject) { 348139220Sgibbs /* 348249933Sgibbs * Setup to reject the message. 348339220Sgibbs */ 348441646Sgibbs ahc->msgout_index = 0; 348541646Sgibbs ahc->msgout_len = 1; 348641646Sgibbs ahc->msgout_buf[0] = MSG_MESSAGE_REJECT; 348749933Sgibbs done = MSGLOOP_MSGCOMPLETE; 348841646Sgibbs response = TRUE; 348939220Sgibbs } 349041646Sgibbs 349149933Sgibbs if (done != MSGLOOP_IN_PROG && !response) 349241646Sgibbs /* Clear the outgoing message buffer */ 349341646Sgibbs ahc->msgout_len = 0; 349441646Sgibbs 349539220Sgibbs return (done); 349639220Sgibbs} 349739220Sgibbs 349865942Sgibbs/* 349965942Sgibbs * Process a message reject message. 350065942Sgibbs */ 350165942Sgibbsstatic int 350265942Sgibbsahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 350365942Sgibbs{ 350465942Sgibbs /* 350565942Sgibbs * What we care about here is if we had an 350665942Sgibbs * outstanding SDTR or WDTR message for this 350765942Sgibbs * target. If we did, this is a signal that 350865942Sgibbs * the target is refusing negotiation. 350965942Sgibbs */ 351065942Sgibbs struct scb *scb; 351165942Sgibbs struct ahc_initiator_tinfo *tinfo; 351274972Sgibbs struct ahc_tmode_tstate *tstate; 351365942Sgibbs u_int scb_index; 351465942Sgibbs u_int last_msg; 351565942Sgibbs int response = 0; 351665942Sgibbs 351765942Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 351866647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 351965942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, 352065942Sgibbs devinfo->our_scsiid, 352165942Sgibbs devinfo->target, &tstate); 352265942Sgibbs /* Might be necessary */ 352365942Sgibbs last_msg = ahc_inb(ahc, LAST_MSG); 352465942Sgibbs 352570204Sgibbs if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) { 352666269Sgibbs /* 352766269Sgibbs * Target does not support the PPR message. 352866269Sgibbs * Attempt to negotiate SPI-2 style. 352966269Sgibbs */ 353066647Sgibbs if (bootverbose) { 353166647Sgibbs printf("(%s:%c:%d:%d): PPR Rejected. " 353266647Sgibbs "Trying WDTR/SDTR\n", 353366647Sgibbs ahc_name(ahc), devinfo->channel, 353466647Sgibbs devinfo->target, devinfo->lun); 353566647Sgibbs } 353666269Sgibbs tinfo->goal.ppr_options = 0; 353776634Sgibbs tinfo->curr.transport_version = 2; 353866269Sgibbs tinfo->goal.transport_version = 2; 353966269Sgibbs ahc->msgout_index = 0; 354066269Sgibbs ahc->msgout_len = 0; 354166269Sgibbs ahc_build_transfer_msg(ahc, devinfo); 354266269Sgibbs ahc->msgout_index = 0; 354366269Sgibbs response = 1; 354470204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) { 354565942Sgibbs 354665942Sgibbs /* note 8bit xfers */ 354766647Sgibbs printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " 354865942Sgibbs "8bit transfers\n", ahc_name(ahc), 354966647Sgibbs devinfo->channel, devinfo->target, devinfo->lun); 355065942Sgibbs ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, 355165942Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 355265942Sgibbs /*paused*/TRUE); 355365942Sgibbs /* 355465942Sgibbs * No need to clear the sync rate. If the target 355565942Sgibbs * did not accept the command, our syncrate is 355665942Sgibbs * unaffected. If the target started the negotiation, 355765942Sgibbs * but rejected our response, we already cleared the 355865942Sgibbs * sync rate before sending our WDTR. 355965942Sgibbs */ 3560109590Sgibbs if (tinfo->goal.offset != tinfo->curr.offset) { 356165942Sgibbs 356265942Sgibbs /* Start the sync negotiation */ 356365942Sgibbs ahc->msgout_index = 0; 356465942Sgibbs ahc->msgout_len = 0; 356566269Sgibbs ahc_build_transfer_msg(ahc, devinfo); 356665942Sgibbs ahc->msgout_index = 0; 356765942Sgibbs response = 1; 356865942Sgibbs } 356970204Sgibbs } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) { 357065942Sgibbs /* note asynch xfers and clear flag */ 357165942Sgibbs ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, /*period*/0, 357265942Sgibbs /*offset*/0, /*ppr_options*/0, 357365942Sgibbs AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, 357465942Sgibbs /*paused*/TRUE); 357566647Sgibbs printf("(%s:%c:%d:%d): refuses synchronous negotiation. " 357665942Sgibbs "Using asynchronous transfers\n", 357766647Sgibbs ahc_name(ahc), devinfo->channel, 357866647Sgibbs devinfo->target, devinfo->lun); 357976634Sgibbs } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) { 358076634Sgibbs int tag_type; 358176634Sgibbs int mask; 358265942Sgibbs 358376634Sgibbs tag_type = (scb->hscb->control & MSG_SIMPLE_TASK); 358465942Sgibbs 358576634Sgibbs if (tag_type == MSG_SIMPLE_TASK) { 358676634Sgibbs printf("(%s:%c:%d:%d): refuses tagged commands. " 358776634Sgibbs "Performing non-tagged I/O\n", ahc_name(ahc), 358876634Sgibbs devinfo->channel, devinfo->target, devinfo->lun); 358976634Sgibbs ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE); 359076634Sgibbs mask = ~0x23; 359176634Sgibbs } else { 359276634Sgibbs printf("(%s:%c:%d:%d): refuses %s tagged commands. " 359376634Sgibbs "Performing simple queue tagged I/O only\n", 359476634Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 359576634Sgibbs devinfo->lun, tag_type == MSG_ORDERED_TASK 359676634Sgibbs ? "ordered" : "head of queue"); 359776634Sgibbs ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC); 359876634Sgibbs mask = ~0x03; 359976634Sgibbs } 360076634Sgibbs 360165942Sgibbs /* 360265942Sgibbs * Resend the identify for this CCB as the target 360365942Sgibbs * may believe that the selection is invalid otherwise. 360465942Sgibbs */ 360565942Sgibbs ahc_outb(ahc, SCB_CONTROL, 360676634Sgibbs ahc_inb(ahc, SCB_CONTROL) & mask); 360776634Sgibbs scb->hscb->control &= mask; 3608123579Sgibbs aic_set_transaction_tag(scb, /*enabled*/FALSE, 360976634Sgibbs /*type*/MSG_SIMPLE_TASK); 361065942Sgibbs ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG); 361176634Sgibbs ahc_assert_atn(ahc); 361265942Sgibbs 361365942Sgibbs /* 361465942Sgibbs * This transaction is now at the head of 361565942Sgibbs * the untagged queue for this target. 361665942Sgibbs */ 361771390Sgibbs if ((ahc->flags & AHC_SCB_BTT) == 0) { 361865942Sgibbs struct scb_tailq *untagged_q; 361965942Sgibbs 362072811Sgibbs untagged_q = 362172811Sgibbs &(ahc->untagged_queues[devinfo->target_offset]); 362265942Sgibbs TAILQ_INSERT_HEAD(untagged_q, scb, links.tqe); 362368087Sgibbs scb->flags |= SCB_UNTAGGEDQ; 362465942Sgibbs } 362565942Sgibbs ahc_busy_tcl(ahc, BUILD_TCL(scb->hscb->scsiid, devinfo->lun), 362665942Sgibbs scb->hscb->tag); 362765942Sgibbs 362865942Sgibbs /* 362965942Sgibbs * Requeue all tagged commands for this target 3630300060Spfg * currently in our possession so they can be 363165942Sgibbs * converted to untagged commands. 363265942Sgibbs */ 363365942Sgibbs ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), 363465942Sgibbs SCB_GET_CHANNEL(ahc, scb), 363565942Sgibbs SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL, 363665942Sgibbs ROLE_INITIATOR, CAM_REQUEUE_REQ, 363765942Sgibbs SEARCH_COMPLETE); 363865942Sgibbs } else { 363965942Sgibbs /* 364065942Sgibbs * Otherwise, we ignore it. 364165942Sgibbs */ 364265942Sgibbs printf("%s:%c:%d: Message reject for %x -- ignored\n", 364365942Sgibbs ahc_name(ahc), devinfo->channel, devinfo->target, 364465942Sgibbs last_msg); 364565942Sgibbs } 364665942Sgibbs return (response); 364765942Sgibbs} 364865942Sgibbs 364965942Sgibbs/* 365065942Sgibbs * Process an ingnore wide residue message. 365165942Sgibbs */ 365239220Sgibbsstatic void 365342652Sgibbsahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 365442652Sgibbs{ 365542652Sgibbs u_int scb_index; 365642652Sgibbs struct scb *scb; 365742652Sgibbs 365842652Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 365966647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 366065942Sgibbs /* 366165942Sgibbs * XXX Actually check data direction in the sequencer? 366265942Sgibbs * Perhaps add datadir to some spare bits in the hscb? 366365942Sgibbs */ 366442652Sgibbs if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0 3665123579Sgibbs || aic_get_transfer_dir(scb) != CAM_DIR_IN) { 366642652Sgibbs /* 366742652Sgibbs * Ignore the message if we haven't 366842652Sgibbs * seen an appropriate data phase yet. 366942652Sgibbs */ 367042652Sgibbs } else { 367142652Sgibbs /* 367242652Sgibbs * If the residual occurred on the last 367342652Sgibbs * transfer and the transfer request was 367442652Sgibbs * expected to end on an odd count, do 367542652Sgibbs * nothing. Otherwise, subtract a byte 367642652Sgibbs * and update the residual count accordingly. 367742652Sgibbs */ 367863457Sgibbs uint32_t sgptr; 367942652Sgibbs 368063457Sgibbs sgptr = ahc_inb(ahc, SCB_RESIDUAL_SGPTR); 368163457Sgibbs if ((sgptr & SG_LIST_NULL) != 0 3682115333Sgibbs && (ahc_inb(ahc, SCB_LUN) & SCB_XFERLEN_ODD) != 0) { 368342652Sgibbs /* 368442652Sgibbs * If the residual occurred on the last 368542652Sgibbs * transfer and the transfer request was 368642652Sgibbs * expected to end on an odd count, do 368742652Sgibbs * nothing. 368842652Sgibbs */ 368942652Sgibbs } else { 369063457Sgibbs struct ahc_dma_seg *sg; 369163457Sgibbs uint32_t data_cnt; 369263457Sgibbs uint32_t data_addr; 369379874Sgibbs uint32_t sglen; 369442652Sgibbs 3695115333Sgibbs /* Pull in all of the sgptr */ 3696115333Sgibbs sgptr = ahc_inl(ahc, SCB_RESIDUAL_SGPTR); 3697115333Sgibbs data_cnt = ahc_inl(ahc, SCB_RESIDUAL_DATACNT); 369842652Sgibbs 3699115333Sgibbs if ((sgptr & SG_LIST_NULL) != 0) { 3700115333Sgibbs /* 3701115333Sgibbs * The residual data count is not updated 3702115333Sgibbs * for the command run to completion case. 3703115333Sgibbs * Explicitly zero the count. 3704115333Sgibbs */ 3705115333Sgibbs data_cnt &= ~AHC_SG_LEN_MASK; 3706115333Sgibbs } 370742652Sgibbs 3708115333Sgibbs data_addr = ahc_inl(ahc, SHADDR); 3709115333Sgibbs 371042652Sgibbs data_cnt += 1; 371142652Sgibbs data_addr -= 1; 3712115333Sgibbs sgptr &= SG_PTR_MASK; 371342652Sgibbs 371463457Sgibbs sg = ahc_sg_bus_to_virt(scb, sgptr); 3715115333Sgibbs 371663457Sgibbs /* 371763457Sgibbs * The residual sg ptr points to the next S/G 371863457Sgibbs * to load so we must go back one. 371963457Sgibbs */ 372063457Sgibbs sg--; 3721123579Sgibbs sglen = aic_le32toh(sg->len) & AHC_SG_LEN_MASK; 372263457Sgibbs if (sg != scb->sg_list 372379874Sgibbs && sglen < (data_cnt & AHC_SG_LEN_MASK)) { 372442652Sgibbs 372563457Sgibbs sg--; 3726123579Sgibbs sglen = aic_le32toh(sg->len); 372779874Sgibbs /* 372879874Sgibbs * Preserve High Address and SG_LIST bits 372979874Sgibbs * while setting the count to 1. 373079874Sgibbs */ 373179874Sgibbs data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK)); 3732123579Sgibbs data_addr = aic_le32toh(sg->addr) 373379874Sgibbs + (sglen & AHC_SG_LEN_MASK) - 1; 373442652Sgibbs 373555581Sgibbs /* 373663457Sgibbs * Increment sg so it points to the 373763457Sgibbs * "next" sg. 373855581Sgibbs */ 373963457Sgibbs sg++; 374063457Sgibbs sgptr = ahc_sg_virt_to_bus(scb, sg); 374142652Sgibbs } 3742115333Sgibbs ahc_outl(ahc, SCB_RESIDUAL_SGPTR, sgptr); 3743115333Sgibbs ahc_outl(ahc, SCB_RESIDUAL_DATACNT, data_cnt); 3744115333Sgibbs /* 3745115333Sgibbs * Toggle the "oddness" of the transfer length 3746115333Sgibbs * to handle this mid-transfer ignore wide 3747115333Sgibbs * residue. This ensures that the oddness is 3748115333Sgibbs * correct for subsequent data transfers. 3749115333Sgibbs */ 3750115333Sgibbs ahc_outb(ahc, SCB_LUN, 3751115333Sgibbs ahc_inb(ahc, SCB_LUN) ^ SCB_XFERLEN_ODD); 375242652Sgibbs } 375342652Sgibbs } 375442652Sgibbs} 375542652Sgibbs 375679874Sgibbs 375765942Sgibbs/* 375879874Sgibbs * Reinitialize the data pointers for the active transfer 375979874Sgibbs * based on its current residual. 376079874Sgibbs */ 376179874Sgibbsstatic void 376279874Sgibbsahc_reinitialize_dataptrs(struct ahc_softc *ahc) 376379874Sgibbs{ 376479874Sgibbs struct scb *scb; 376579874Sgibbs struct ahc_dma_seg *sg; 376679874Sgibbs u_int scb_index; 376779874Sgibbs uint32_t sgptr; 376879874Sgibbs uint32_t resid; 376979874Sgibbs uint32_t dataptr; 377079874Sgibbs 377179874Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 377279874Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 377379874Sgibbs sgptr = (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24) 377479874Sgibbs | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16) 377579874Sgibbs | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8) 377679874Sgibbs | ahc_inb(ahc, SCB_RESIDUAL_SGPTR); 377779874Sgibbs 377879874Sgibbs sgptr &= SG_PTR_MASK; 377979874Sgibbs sg = ahc_sg_bus_to_virt(scb, sgptr); 378079874Sgibbs 378179874Sgibbs /* The residual sg_ptr always points to the next sg */ 378279874Sgibbs sg--; 378379874Sgibbs 378479874Sgibbs resid = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 2) << 16) 378579874Sgibbs | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8) 378679874Sgibbs | ahc_inb(ahc, SCB_RESIDUAL_DATACNT); 378779874Sgibbs 3788123579Sgibbs dataptr = aic_le32toh(sg->addr) 3789123579Sgibbs + (aic_le32toh(sg->len) & AHC_SG_LEN_MASK) 379079874Sgibbs - resid; 379179874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 379279874Sgibbs u_int dscommand1; 379379874Sgibbs 379479874Sgibbs dscommand1 = ahc_inb(ahc, DSCOMMAND1); 379579874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); 379679874Sgibbs ahc_outb(ahc, HADDR, 3797123579Sgibbs (aic_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); 379879874Sgibbs ahc_outb(ahc, DSCOMMAND1, dscommand1); 379979874Sgibbs } 380079874Sgibbs ahc_outb(ahc, HADDR + 3, dataptr >> 24); 380179874Sgibbs ahc_outb(ahc, HADDR + 2, dataptr >> 16); 380279874Sgibbs ahc_outb(ahc, HADDR + 1, dataptr >> 8); 380379874Sgibbs ahc_outb(ahc, HADDR, dataptr); 380479874Sgibbs ahc_outb(ahc, HCNT + 2, resid >> 16); 380579874Sgibbs ahc_outb(ahc, HCNT + 1, resid >> 8); 380679874Sgibbs ahc_outb(ahc, HCNT, resid); 380779874Sgibbs if ((ahc->features & AHC_ULTRA2) == 0) { 380879874Sgibbs ahc_outb(ahc, STCNT + 2, resid >> 16); 380979874Sgibbs ahc_outb(ahc, STCNT + 1, resid >> 8); 381079874Sgibbs ahc_outb(ahc, STCNT, resid); 381179874Sgibbs } 381279874Sgibbs} 381379874Sgibbs 381479874Sgibbs/* 381565942Sgibbs * Handle the effects of issuing a bus device reset message. 381665942Sgibbs */ 381742652Sgibbsstatic void 381844507Sgibbsahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 381965942Sgibbs cam_status status, char *message, int verbose_level) 382039220Sgibbs{ 382165942Sgibbs#ifdef AHC_TARGET_MODE 382274972Sgibbs struct ahc_tmode_tstate* tstate; 382349933Sgibbs u_int lun; 382465942Sgibbs#endif 382565942Sgibbs int found; 382639220Sgibbs 382749933Sgibbs found = ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, 382849933Sgibbs CAM_LUN_WILDCARD, SCB_LIST_NULL, devinfo->role, 382949933Sgibbs status); 383050662Sgibbs 383165942Sgibbs#ifdef AHC_TARGET_MODE 383239220Sgibbs /* 383365942Sgibbs * Send an immediate notify ccb to all target mord peripheral 383449933Sgibbs * drivers affected by this action. 383549933Sgibbs */ 383649933Sgibbs tstate = ahc->enabled_targets[devinfo->our_scsiid]; 383749933Sgibbs if (tstate != NULL) { 383870204Sgibbs for (lun = 0; lun < AHC_NUM_LUNS; lun++) { 383974972Sgibbs struct ahc_tmode_lstate* lstate; 384049933Sgibbs 384149933Sgibbs lstate = tstate->enabled_luns[lun]; 384249933Sgibbs if (lstate == NULL) 384349933Sgibbs continue; 384449933Sgibbs 384549933Sgibbs ahc_queue_lstate_event(ahc, lstate, devinfo->our_scsiid, 384649933Sgibbs MSG_BUS_DEV_RESET, /*arg*/0); 384749933Sgibbs ahc_send_lstate_events(ahc, lstate); 384849933Sgibbs } 384949933Sgibbs } 385065942Sgibbs#endif 385149933Sgibbs 385249933Sgibbs /* 385339220Sgibbs * Go back to async/narrow transfers and renegotiate. 385439220Sgibbs */ 385565942Sgibbs ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, 385647287Sgibbs AHC_TRANS_CUR, /*paused*/TRUE); 385765942Sgibbs ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, 385863457Sgibbs /*period*/0, /*offset*/0, /*ppr_options*/0, 385963457Sgibbs AHC_TRANS_CUR, /*paused*/TRUE); 386039220Sgibbs 3861129133Sgibbs if (status != CAM_SEL_TIMEOUT) 3862129133Sgibbs ahc_send_async(ahc, devinfo->channel, devinfo->target, 3863129133Sgibbs CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); 386439220Sgibbs 386539220Sgibbs if (message != NULL 386654211Sgibbs && (verbose_level <= bootverbose)) 386739220Sgibbs printf("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc), 386844507Sgibbs message, devinfo->channel, devinfo->target, found); 386939220Sgibbs} 387040028Sgibbs 387165942Sgibbs#ifdef AHC_TARGET_MODE 387274972Sgibbsstatic void 387374972Sgibbsahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, 387474972Sgibbs struct scb *scb) 387565942Sgibbs{ 387674972Sgibbs 387765942Sgibbs /* 387865942Sgibbs * To facilitate adding multiple messages together, 387965942Sgibbs * each routine should increment the index and len 388065942Sgibbs * variables instead of setting them explicitly. 388165942Sgibbs */ 388265942Sgibbs ahc->msgout_index = 0; 388365942Sgibbs ahc->msgout_len = 0; 388465942Sgibbs 388574972Sgibbs if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0) 388665942Sgibbs ahc_build_transfer_msg(ahc, devinfo); 388765942Sgibbs else 388865942Sgibbs panic("ahc_intr: AWAITING target message with no message"); 388965942Sgibbs 389065942Sgibbs ahc->msgout_index = 0; 389165942Sgibbs ahc->msg_type = MSG_TYPE_TARGET_MSGIN; 389265942Sgibbs} 389365942Sgibbs#endif 389465942Sgibbs/**************************** Initialization **********************************/ 389539220Sgibbs/* 389665942Sgibbs * Allocate a controller structure for a new device 389765942Sgibbs * and perform initial initializion. 389839220Sgibbs */ 389965942Sgibbsstruct ahc_softc * 390065942Sgibbsahc_alloc(void *platform_arg, char *name) 390139220Sgibbs{ 390265942Sgibbs struct ahc_softc *ahc; 390365942Sgibbs int i; 390439220Sgibbs 390570204Sgibbs#ifndef __FreeBSD__ 390665942Sgibbs ahc = malloc(sizeof(*ahc), M_DEVBUF, M_NOWAIT); 390765942Sgibbs if (!ahc) { 390865942Sgibbs printf("aic7xxx: cannot malloc softc!\n"); 390965942Sgibbs free(name, M_DEVBUF); 391065942Sgibbs return NULL; 391165942Sgibbs } 391270204Sgibbs#else 391370204Sgibbs ahc = device_get_softc((device_t)platform_arg); 391470204Sgibbs#endif 391565942Sgibbs memset(ahc, 0, sizeof(*ahc)); 3916102670Sgibbs ahc->seep_config = malloc(sizeof(*ahc->seep_config), 3917102670Sgibbs M_DEVBUF, M_NOWAIT); 3918102670Sgibbs if (ahc->seep_config == NULL) { 3919102670Sgibbs#ifndef __FreeBSD__ 3920102670Sgibbs free(ahc, M_DEVBUF); 3921102670Sgibbs#endif 3922102670Sgibbs free(name, M_DEVBUF); 3923102670Sgibbs return (NULL); 3924102670Sgibbs } 392565942Sgibbs LIST_INIT(&ahc->pending_scbs); 3926141999Sgibbs LIST_INIT(&ahc->timedout_scbs); 392772325Sgibbs /* We don't know our unit number until the OSM sets it */ 392865942Sgibbs ahc->name = name; 392974972Sgibbs ahc->unit = -1; 393079874Sgibbs ahc->description = NULL; 393179874Sgibbs ahc->channel = 'A'; 393279874Sgibbs ahc->channel_b = 'B'; 393379874Sgibbs ahc->chip = AHC_NONE; 393479874Sgibbs ahc->features = AHC_FENONE; 393579874Sgibbs ahc->bugs = AHC_BUGNONE; 393679874Sgibbs ahc->flags = AHC_FNONE; 3937115332Sgibbs /* 3938115332Sgibbs * Default to all error reporting enabled with the 3939115332Sgibbs * sequencer operating at its fastest speed. 3940115332Sgibbs * The bus attach code may modify this. 3941115332Sgibbs */ 3942115332Sgibbs ahc->seqctl = FASTMODE; 394379874Sgibbs 394495378Sgibbs for (i = 0; i < AHC_NUM_TARGETS; i++) 394565942Sgibbs TAILQ_INIT(&ahc->untagged_queues[i]); 394665942Sgibbs if (ahc_platform_alloc(ahc, platform_arg) != 0) { 394765942Sgibbs ahc_free(ahc); 394865942Sgibbs ahc = NULL; 394965942Sgibbs } 3950168807Sscottl ahc_lockinit(ahc); 395165942Sgibbs return (ahc); 395265942Sgibbs} 395339220Sgibbs 395465942Sgibbsint 395579874Sgibbsahc_softc_init(struct ahc_softc *ahc) 395665942Sgibbs{ 395739220Sgibbs 395865942Sgibbs /* The IRQMS bit is only valid on VL and EISA chips */ 395981809Sgibbs if ((ahc->chip & AHC_PCI) == 0) 396081809Sgibbs ahc->unpause = ahc_inb(ahc, HCNTRL) & IRQMS; 396181809Sgibbs else 396281809Sgibbs ahc->unpause = 0; 396365942Sgibbs ahc->pause = ahc->unpause | PAUSE; 396472085Sasmodai /* XXX The shared scb data stuff should be deprecated */ 396565942Sgibbs if (ahc->scb_data == NULL) { 396665942Sgibbs ahc->scb_data = malloc(sizeof(*ahc->scb_data), 396765942Sgibbs M_DEVBUF, M_NOWAIT); 396865942Sgibbs if (ahc->scb_data == NULL) 396965942Sgibbs return (ENOMEM); 397065942Sgibbs memset(ahc->scb_data, 0, sizeof(*ahc->scb_data)); 397163457Sgibbs } 397263457Sgibbs 397365942Sgibbs return (0); 397465942Sgibbs} 397539220Sgibbs 397665942Sgibbsvoid 397765942Sgibbsahc_softc_insert(struct ahc_softc *ahc) 397865942Sgibbs{ 397965942Sgibbs struct ahc_softc *list_ahc; 398039220Sgibbs 3981123579Sgibbs#if AIC_PCI_CONFIG > 0 398265942Sgibbs /* 398365942Sgibbs * Second Function PCI devices need to inherit some 398474094Sgibbs * settings from function 0. 398565942Sgibbs */ 398665942Sgibbs if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI 398774094Sgibbs && (ahc->features & AHC_MULTI_FUNC) != 0) { 398865942Sgibbs TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { 3989123579Sgibbs aic_dev_softc_t list_pci; 3990123579Sgibbs aic_dev_softc_t pci; 399139220Sgibbs 399265942Sgibbs list_pci = list_ahc->dev_softc; 399365942Sgibbs pci = ahc->dev_softc; 3994123579Sgibbs if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) 3995123579Sgibbs && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { 399674094Sgibbs struct ahc_softc *master; 399774094Sgibbs struct ahc_softc *slave; 399874094Sgibbs 3999123579Sgibbs if (aic_get_pci_function(list_pci) == 0) { 400074094Sgibbs master = list_ahc; 400174094Sgibbs slave = ahc; 400274094Sgibbs } else { 400374094Sgibbs master = ahc; 400474094Sgibbs slave = list_ahc; 400574094Sgibbs } 400674094Sgibbs slave->flags &= ~AHC_BIOS_ENABLED; 400774094Sgibbs slave->flags |= 400874094Sgibbs master->flags & AHC_BIOS_ENABLED; 400974094Sgibbs slave->flags &= ~AHC_PRIMARY_CHANNEL; 401074094Sgibbs slave->flags |= 401174094Sgibbs master->flags & AHC_PRIMARY_CHANNEL; 401265942Sgibbs break; 401365942Sgibbs } 401465942Sgibbs } 401539220Sgibbs } 401665942Sgibbs#endif 401739220Sgibbs 401839220Sgibbs /* 401965942Sgibbs * Insertion sort into our list of softcs. 402039220Sgibbs */ 402165942Sgibbs list_ahc = TAILQ_FIRST(&ahc_tailq); 402265942Sgibbs while (list_ahc != NULL 4023114621Sgibbs && ahc_softc_comp(ahc, list_ahc) <= 0) 402465942Sgibbs list_ahc = TAILQ_NEXT(list_ahc, links); 402565942Sgibbs if (list_ahc != NULL) 402665942Sgibbs TAILQ_INSERT_BEFORE(list_ahc, ahc, links); 402765942Sgibbs else 402865942Sgibbs TAILQ_INSERT_TAIL(&ahc_tailq, ahc, links); 402965942Sgibbs ahc->init_level++; 403065942Sgibbs} 403139220Sgibbs 403265942Sgibbsvoid 403365942Sgibbsahc_set_unit(struct ahc_softc *ahc, int unit) 403465942Sgibbs{ 403565942Sgibbs ahc->unit = unit; 403665942Sgibbs} 403739220Sgibbs 403865942Sgibbsvoid 403965942Sgibbsahc_set_name(struct ahc_softc *ahc, char *name) 404065942Sgibbs{ 404165942Sgibbs if (ahc->name != NULL) 404265942Sgibbs free(ahc->name, M_DEVBUF); 404365942Sgibbs ahc->name = name; 404465942Sgibbs} 404539220Sgibbs 404665942Sgibbsvoid 404765942Sgibbsahc_free(struct ahc_softc *ahc) 404865942Sgibbs{ 404970204Sgibbs int i; 405070204Sgibbs 4051123579Sgibbs ahc_terminate_recovery_thread(ahc); 405265942Sgibbs switch (ahc->init_level) { 405370204Sgibbs default: 405470204Sgibbs case 5: 405565942Sgibbs ahc_shutdown(ahc); 405665942Sgibbs /* FALLTHROUGH */ 405770204Sgibbs case 4: 4058123579Sgibbs aic_dmamap_unload(ahc, ahc->shared_data_dmat, 405965942Sgibbs ahc->shared_data_dmamap); 406065942Sgibbs /* FALLTHROUGH */ 406170204Sgibbs case 3: 4062123579Sgibbs aic_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, 406365942Sgibbs ahc->shared_data_dmamap); 4064123579Sgibbs aic_dmamap_destroy(ahc, ahc->shared_data_dmat, 406565942Sgibbs ahc->shared_data_dmamap); 406665942Sgibbs /* FALLTHROUGH */ 406770204Sgibbs case 2: 4068123579Sgibbs aic_dma_tag_destroy(ahc, ahc->shared_data_dmat); 406965942Sgibbs case 1: 407065942Sgibbs#ifndef __linux__ 4071123579Sgibbs aic_dma_tag_destroy(ahc, ahc->buffer_dmat); 407265942Sgibbs#endif 407365942Sgibbs break; 407472325Sgibbs case 0: 407572325Sgibbs break; 407665942Sgibbs } 407739220Sgibbs 407872325Sgibbs#ifndef __linux__ 4079123579Sgibbs aic_dma_tag_destroy(ahc, ahc->parent_dmat); 408072325Sgibbs#endif 408165942Sgibbs ahc_platform_free(ahc); 4082114621Sgibbs ahc_fini_scbdata(ahc); 408370204Sgibbs for (i = 0; i < AHC_NUM_TARGETS; i++) { 408474972Sgibbs struct ahc_tmode_tstate *tstate; 408570204Sgibbs 408670204Sgibbs tstate = ahc->enabled_targets[i]; 408770204Sgibbs if (tstate != NULL) { 4088115337Sgibbs#ifdef AHC_TARGET_MODE 408970204Sgibbs int j; 409070204Sgibbs 409170204Sgibbs for (j = 0; j < AHC_NUM_LUNS; j++) { 409274972Sgibbs struct ahc_tmode_lstate *lstate; 409370204Sgibbs 409470204Sgibbs lstate = tstate->enabled_luns[j]; 409570204Sgibbs if (lstate != NULL) { 409670204Sgibbs xpt_free_path(lstate->path); 409770204Sgibbs free(lstate, M_DEVBUF); 409870204Sgibbs } 409970204Sgibbs } 410070204Sgibbs#endif 410170204Sgibbs free(tstate, M_DEVBUF); 410270204Sgibbs } 410339220Sgibbs } 4104115337Sgibbs#ifdef AHC_TARGET_MODE 410570204Sgibbs if (ahc->black_hole != NULL) { 410670204Sgibbs xpt_free_path(ahc->black_hole->path); 410770204Sgibbs free(ahc->black_hole, M_DEVBUF); 410870204Sgibbs } 410965942Sgibbs#endif 411065942Sgibbs if (ahc->name != NULL) 411165942Sgibbs free(ahc->name, M_DEVBUF); 4112102670Sgibbs if (ahc->seep_config != NULL) 4113102670Sgibbs free(ahc->seep_config, M_DEVBUF); 411470204Sgibbs#ifndef __FreeBSD__ 411565942Sgibbs free(ahc, M_DEVBUF); 411670204Sgibbs#endif 411765942Sgibbs return; 411865942Sgibbs} 411939220Sgibbs 412065942Sgibbsvoid 412165942Sgibbsahc_shutdown(void *arg) 412265942Sgibbs{ 412365942Sgibbs struct ahc_softc *ahc; 412465942Sgibbs int i; 412565942Sgibbs 412665942Sgibbs ahc = (struct ahc_softc *)arg; 412765942Sgibbs 412865942Sgibbs /* This will reset most registers to 0, but not all */ 4129115917Sgibbs ahc_reset(ahc, /*reinit*/FALSE); 413065942Sgibbs ahc_outb(ahc, SCSISEQ, 0); 413165942Sgibbs ahc_outb(ahc, SXFRCTL0, 0); 413265942Sgibbs ahc_outb(ahc, DSPCISTATUS, 0); 413365942Sgibbs 413495378Sgibbs for (i = TARG_SCSIRATE; i < SCSICONF; i++) 413565942Sgibbs ahc_outb(ahc, i, 0); 413665942Sgibbs} 413765942Sgibbs 413865942Sgibbs/* 413965942Sgibbs * Reset the controller and record some information about it 4140115917Sgibbs * that is only available just after a reset. If "reinit" is 4141300060Spfg * non-zero, this reset occurred after initial configuration 4142115917Sgibbs * and the caller requests that the chip be fully reinitialized 4143115917Sgibbs * to a runable state. Chip interrupts are *not* enabled after 4144115917Sgibbs * a reinitialization. The caller must enable interrupts via 4145115917Sgibbs * ahc_intr_enable(). 414665942Sgibbs */ 414765942Sgibbsint 4148115917Sgibbsahc_reset(struct ahc_softc *ahc, int reinit) 414965942Sgibbs{ 415065942Sgibbs u_int sblkctl; 415165942Sgibbs u_int sxfrctl1_a, sxfrctl1_b; 4152114621Sgibbs int error; 415365942Sgibbs int wait; 415465942Sgibbs 415565942Sgibbs /* 415665942Sgibbs * Preserve the value of the SXFRCTL1 register for all channels. 415765942Sgibbs * It contains settings that affect termination and we don't want 415865942Sgibbs * to disturb the integrity of the bus. 415965942Sgibbs */ 416074094Sgibbs ahc_pause(ahc); 416165942Sgibbs sxfrctl1_b = 0; 416265942Sgibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { 416365942Sgibbs u_int sblkctl; 416465942Sgibbs 416545965Sgibbs /* 416665942Sgibbs * Save channel B's settings in case this chip 416765942Sgibbs * is setup for TWIN channel operation. 416845965Sgibbs */ 416965942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 417065942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); 417165942Sgibbs sxfrctl1_b = ahc_inb(ahc, SXFRCTL1); 417265942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); 417339220Sgibbs } 417465942Sgibbs sxfrctl1_a = ahc_inb(ahc, SXFRCTL1); 417565942Sgibbs 417665942Sgibbs ahc_outb(ahc, HCNTRL, CHIPRST | ahc->pause); 417765942Sgibbs 417865942Sgibbs /* 417995378Sgibbs * Ensure that the reset has finished. We delay 1000us 418095378Sgibbs * prior to reading the register to make sure the chip 418195378Sgibbs * has sufficiently completed its reset to handle register 418295378Sgibbs * accesses. 418365942Sgibbs */ 418465942Sgibbs wait = 1000; 418565942Sgibbs do { 4186123579Sgibbs aic_delay(1000); 418765942Sgibbs } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK)); 418865942Sgibbs 418965942Sgibbs if (wait == 0) { 419065942Sgibbs printf("%s: WARNING - Failed chip reset! " 419165942Sgibbs "Trying to initialize anyway.\n", ahc_name(ahc)); 419265942Sgibbs } 419370204Sgibbs ahc_outb(ahc, HCNTRL, ahc->pause); 419465942Sgibbs 419565942Sgibbs /* Determine channel configuration */ 419665942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL) & (SELBUSB|SELWIDE); 419765942Sgibbs /* No Twin Channel PCI cards */ 419865942Sgibbs if ((ahc->chip & AHC_PCI) != 0) 419965942Sgibbs sblkctl &= ~SELBUSB; 420065942Sgibbs switch (sblkctl) { 420165942Sgibbs case 0: 420265942Sgibbs /* Single Narrow Channel */ 420365942Sgibbs break; 420465942Sgibbs case 2: 420565942Sgibbs /* Wide Channel */ 420665942Sgibbs ahc->features |= AHC_WIDE; 420765942Sgibbs break; 420865942Sgibbs case 8: 420965942Sgibbs /* Twin Channel */ 421065942Sgibbs ahc->features |= AHC_TWIN; 421165942Sgibbs break; 421265942Sgibbs default: 421365942Sgibbs printf(" Unsupported adapter type. Ignoring\n"); 421465942Sgibbs return(-1); 421565942Sgibbs } 421665942Sgibbs 421765942Sgibbs /* 421865942Sgibbs * Reload sxfrctl1. 421965942Sgibbs * 422065942Sgibbs * We must always initialize STPWEN to 1 before we 422165942Sgibbs * restore the saved values. STPWEN is initialized 422265942Sgibbs * to a tri-state condition which can only be cleared 422365942Sgibbs * by turning it on. 422465942Sgibbs */ 422565942Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 422665942Sgibbs u_int sblkctl; 422765942Sgibbs 422865942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 422965942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB); 423065942Sgibbs ahc_outb(ahc, SXFRCTL1, sxfrctl1_b); 423165942Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB); 423265942Sgibbs } 423365942Sgibbs ahc_outb(ahc, SXFRCTL1, sxfrctl1_a); 423465942Sgibbs 4235114621Sgibbs error = 0; 4236115917Sgibbs if (reinit != 0) 4237114621Sgibbs /* 4238114621Sgibbs * If a recovery action has forced a chip reset, 4239114621Sgibbs * re-initialize the chip to our liking. 4240114621Sgibbs */ 4241114621Sgibbs error = ahc->bus_chip_init(ahc); 424265942Sgibbs#ifdef AHC_DUMP_SEQ 4243114621Sgibbs else 424465942Sgibbs ahc_dumpseq(ahc); 424565942Sgibbs#endif 424665942Sgibbs 4247114621Sgibbs return (error); 424839220Sgibbs} 424939220Sgibbs 425039220Sgibbs/* 425139220Sgibbs * Determine the number of SCBs available on the controller 425239220Sgibbs */ 425339220Sgibbsint 425439220Sgibbsahc_probe_scbs(struct ahc_softc *ahc) { 425539220Sgibbs int i; 425639220Sgibbs 425739220Sgibbs for (i = 0; i < AHC_SCB_MAX; i++) { 425870204Sgibbs 425939220Sgibbs ahc_outb(ahc, SCBPTR, i); 426065942Sgibbs ahc_outb(ahc, SCB_BASE, i); 426165942Sgibbs if (ahc_inb(ahc, SCB_BASE) != i) 426239220Sgibbs break; 426339220Sgibbs ahc_outb(ahc, SCBPTR, 0); 426465942Sgibbs if (ahc_inb(ahc, SCB_BASE) != 0) 426539220Sgibbs break; 426639220Sgibbs } 426739220Sgibbs return (i); 426839220Sgibbs} 426939220Sgibbs 427065942Sgibbsstatic void 427165942Sgibbsahc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 427265942Sgibbs{ 427365942Sgibbs bus_addr_t *baddr; 427465942Sgibbs 427565942Sgibbs baddr = (bus_addr_t *)arg; 427665942Sgibbs *baddr = segs->ds_addr; 427765942Sgibbs} 427865942Sgibbs 427970204Sgibbsstatic void 428070204Sgibbsahc_build_free_scb_list(struct ahc_softc *ahc) 428170204Sgibbs{ 4282102670Sgibbs int scbsize; 428370204Sgibbs int i; 428470204Sgibbs 4285102670Sgibbs scbsize = 32; 4286102670Sgibbs if ((ahc->flags & AHC_LSCBS_ENABLED) != 0) 4287102670Sgibbs scbsize = 64; 4288102670Sgibbs 428970204Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 4290102670Sgibbs int j; 4291102670Sgibbs 429270204Sgibbs ahc_outb(ahc, SCBPTR, i); 429370204Sgibbs 4294102670Sgibbs /* 4295102670Sgibbs * Touch all SCB bytes to avoid parity errors 4296102670Sgibbs * should one of our debugging routines read 4297102670Sgibbs * an otherwise uninitiatlized byte. 4298102670Sgibbs */ 4299102670Sgibbs for (j = 0; j < scbsize; j++) 4300102670Sgibbs ahc_outb(ahc, SCB_BASE+j, 0xFF); 4301102670Sgibbs 430270204Sgibbs /* Clear the control byte. */ 430370204Sgibbs ahc_outb(ahc, SCB_CONTROL, 0); 430470204Sgibbs 430570204Sgibbs /* Set the next pointer */ 430670204Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) 430770204Sgibbs ahc_outb(ahc, SCB_NEXT, i+1); 430870204Sgibbs else 430970204Sgibbs ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL); 431070204Sgibbs 4311102670Sgibbs /* Make the tag number, SCSIID, and lun invalid */ 431270204Sgibbs ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL); 4313102670Sgibbs ahc_outb(ahc, SCB_SCSIID, 0xFF); 4314102670Sgibbs ahc_outb(ahc, SCB_LUN, 0xFF); 431570204Sgibbs } 431670204Sgibbs 4317114621Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 4318114621Sgibbs /* SCB 0 heads the free list. */ 4319114621Sgibbs ahc_outb(ahc, FREE_SCBH, 0); 4320114621Sgibbs } else { 4321114621Sgibbs /* No free list. */ 4322114621Sgibbs ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL); 4323114621Sgibbs } 4324114621Sgibbs 432570204Sgibbs /* Make sure that the last SCB terminates the free list */ 432670204Sgibbs ahc_outb(ahc, SCBPTR, i-1); 432770204Sgibbs ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL); 432870204Sgibbs} 432970204Sgibbs 433065942Sgibbsstatic int 433165942Sgibbsahc_init_scbdata(struct ahc_softc *ahc) 433265942Sgibbs{ 433365942Sgibbs struct scb_data *scb_data; 433465942Sgibbs 433565942Sgibbs scb_data = ahc->scb_data; 433665942Sgibbs SLIST_INIT(&scb_data->free_scbs); 433765942Sgibbs SLIST_INIT(&scb_data->sg_maps); 433865942Sgibbs 433965942Sgibbs /* Allocate SCB resources */ 434065942Sgibbs scb_data->scbarray = 434195378Sgibbs (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, 434265942Sgibbs M_DEVBUF, M_NOWAIT); 434365942Sgibbs if (scb_data->scbarray == NULL) 434465942Sgibbs return (ENOMEM); 434595378Sgibbs memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC); 434665942Sgibbs 434765942Sgibbs /* Determine the number of hardware SCBs and initialize them */ 434865942Sgibbs 434965942Sgibbs scb_data->maxhscbs = ahc_probe_scbs(ahc); 435070204Sgibbs if (ahc->scb_data->maxhscbs == 0) { 435170204Sgibbs printf("%s: No SCB space found\n", ahc_name(ahc)); 435270204Sgibbs return (ENXIO); 435365942Sgibbs } 435465942Sgibbs 435565942Sgibbs /* 435665942Sgibbs * Create our DMA tags. These tags define the kinds of device 435765942Sgibbs * accessible memory allocations and memory mappings we will 435865942Sgibbs * need to perform during normal operation. 435965942Sgibbs * 436065942Sgibbs * Unless we need to further restrict the allocation, we rely 436165942Sgibbs * on the restrictions of the parent dmat, hence the common 436265942Sgibbs * use of MAXADDR and MAXSIZE. 436365942Sgibbs */ 436465942Sgibbs 436565942Sgibbs /* DMA tag for our hardware scb structures */ 4366123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 436779874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 436879874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 436965942Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 437065942Sgibbs /*filter*/NULL, /*filterarg*/NULL, 437195378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), 437265942Sgibbs /*nsegments*/1, 437365942Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 437465942Sgibbs /*flags*/0, &scb_data->hscb_dmat) != 0) { 437565942Sgibbs goto error_exit; 437665942Sgibbs } 437765942Sgibbs 437865942Sgibbs scb_data->init_level++; 437965942Sgibbs 438079874Sgibbs /* Allocation for our hscbs */ 4381123579Sgibbs if (aic_dmamem_alloc(ahc, scb_data->hscb_dmat, 438265942Sgibbs (void **)&scb_data->hscbs, 4383219577Smarius BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 4384219577Smarius &scb_data->hscb_dmamap) != 0) { 438565942Sgibbs goto error_exit; 438665942Sgibbs } 438765942Sgibbs 438865942Sgibbs scb_data->init_level++; 438965942Sgibbs 439065942Sgibbs /* And permanently map them */ 4391123579Sgibbs aic_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, 439265942Sgibbs scb_data->hscbs, 439395378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), 439465942Sgibbs ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0); 439565942Sgibbs 439665942Sgibbs scb_data->init_level++; 439765942Sgibbs 439865942Sgibbs /* DMA tag for our sense buffers */ 4399123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 440079874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 440179874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 440265942Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 440365942Sgibbs /*filter*/NULL, /*filterarg*/NULL, 440495378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), 440565942Sgibbs /*nsegments*/1, 440665942Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 440765942Sgibbs /*flags*/0, &scb_data->sense_dmat) != 0) { 440865942Sgibbs goto error_exit; 440965942Sgibbs } 441065942Sgibbs 441165942Sgibbs scb_data->init_level++; 441265942Sgibbs 441365942Sgibbs /* Allocate them */ 4414123579Sgibbs if (aic_dmamem_alloc(ahc, scb_data->sense_dmat, 441565942Sgibbs (void **)&scb_data->sense, 441665942Sgibbs BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) { 441765942Sgibbs goto error_exit; 441865942Sgibbs } 441965942Sgibbs 442065942Sgibbs scb_data->init_level++; 442165942Sgibbs 442265942Sgibbs /* And permanently map them */ 4423123579Sgibbs aic_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, 442465942Sgibbs scb_data->sense, 442595378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), 442665942Sgibbs ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0); 442765942Sgibbs 442865942Sgibbs scb_data->init_level++; 442965942Sgibbs 443065942Sgibbs /* DMA tag for our S/G structures. We allocate in page sized chunks */ 4431123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, 443279874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 443379874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 443465942Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 443565942Sgibbs /*filter*/NULL, /*filterarg*/NULL, 443665942Sgibbs PAGE_SIZE, /*nsegments*/1, 443765942Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 443865942Sgibbs /*flags*/0, &scb_data->sg_dmat) != 0) { 443965942Sgibbs goto error_exit; 444065942Sgibbs } 444165942Sgibbs 444265942Sgibbs scb_data->init_level++; 444365942Sgibbs 444465942Sgibbs /* Perform initial CCB allocation */ 444595378Sgibbs memset(scb_data->hscbs, 0, 444695378Sgibbs AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb)); 4447168873Sscottl while (ahc_alloc_scbs(ahc) != 0) 4448168873Sscottl ; 444965942Sgibbs 445065942Sgibbs if (scb_data->numscbs == 0) { 445165942Sgibbs printf("%s: ahc_init_scbdata - " 445265942Sgibbs "Unable to allocate initial scbs\n", 445365942Sgibbs ahc_name(ahc)); 445465942Sgibbs goto error_exit; 445565942Sgibbs } 445665942Sgibbs 445765942Sgibbs /* 4458114621Sgibbs * Reserve the next queued SCB. 445966647Sgibbs */ 446066647Sgibbs ahc->next_queued_scb = ahc_get_scb(ahc); 446166647Sgibbs 446266647Sgibbs /* 4463300060Spfg * Note that we were successful 446465942Sgibbs */ 446565942Sgibbs return (0); 446665942Sgibbs 446765942Sgibbserror_exit: 446865942Sgibbs 446965942Sgibbs return (ENOMEM); 447065942Sgibbs} 447165942Sgibbs 447265942Sgibbsstatic void 447365942Sgibbsahc_fini_scbdata(struct ahc_softc *ahc) 447465942Sgibbs{ 447565942Sgibbs struct scb_data *scb_data; 447665942Sgibbs 447765942Sgibbs scb_data = ahc->scb_data; 447868660Sgibbs if (scb_data == NULL) 447968660Sgibbs return; 448065942Sgibbs 448165942Sgibbs switch (scb_data->init_level) { 448265942Sgibbs default: 448365942Sgibbs case 7: 448465942Sgibbs { 448565942Sgibbs struct sg_map_node *sg_map; 448665942Sgibbs 448765942Sgibbs while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) { 448865942Sgibbs SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); 4489123579Sgibbs aic_dmamap_unload(ahc, scb_data->sg_dmat, 449065942Sgibbs sg_map->sg_dmamap); 4491123579Sgibbs aic_dmamem_free(ahc, scb_data->sg_dmat, 449265942Sgibbs sg_map->sg_vaddr, 449365942Sgibbs sg_map->sg_dmamap); 449465942Sgibbs free(sg_map, M_DEVBUF); 449565942Sgibbs } 4496123579Sgibbs aic_dma_tag_destroy(ahc, scb_data->sg_dmat); 449765942Sgibbs } 449865942Sgibbs case 6: 4499123579Sgibbs aic_dmamap_unload(ahc, scb_data->sense_dmat, 450065942Sgibbs scb_data->sense_dmamap); 450165942Sgibbs case 5: 4502123579Sgibbs aic_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, 450365942Sgibbs scb_data->sense_dmamap); 4504123579Sgibbs aic_dmamap_destroy(ahc, scb_data->sense_dmat, 450565942Sgibbs scb_data->sense_dmamap); 450665942Sgibbs case 4: 4507123579Sgibbs aic_dma_tag_destroy(ahc, scb_data->sense_dmat); 450865942Sgibbs case 3: 4509123579Sgibbs aic_dmamap_unload(ahc, scb_data->hscb_dmat, 451065942Sgibbs scb_data->hscb_dmamap); 451165942Sgibbs case 2: 4512123579Sgibbs aic_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, 451365942Sgibbs scb_data->hscb_dmamap); 4514123579Sgibbs aic_dmamap_destroy(ahc, scb_data->hscb_dmat, 451565942Sgibbs scb_data->hscb_dmamap); 451665942Sgibbs case 1: 4517123579Sgibbs aic_dma_tag_destroy(ahc, scb_data->hscb_dmat); 451865942Sgibbs break; 451970204Sgibbs case 0: 452070204Sgibbs break; 452165942Sgibbs } 452265942Sgibbs if (scb_data->scbarray != NULL) 452365942Sgibbs free(scb_data->scbarray, M_DEVBUF); 452465942Sgibbs} 452565942Sgibbs 4526168873Sscottlint 452765942Sgibbsahc_alloc_scbs(struct ahc_softc *ahc) 452865942Sgibbs{ 452965942Sgibbs struct scb_data *scb_data; 453065942Sgibbs struct scb *next_scb; 453165942Sgibbs struct sg_map_node *sg_map; 453265942Sgibbs bus_addr_t physaddr; 453365942Sgibbs struct ahc_dma_seg *segs; 453465942Sgibbs int newcount; 453565942Sgibbs int i; 453665942Sgibbs 453765942Sgibbs scb_data = ahc->scb_data; 453895378Sgibbs if (scb_data->numscbs >= AHC_SCB_MAX_ALLOC) 453965942Sgibbs /* Can't allocate any more */ 4540168873Sscottl return (0); 454165942Sgibbs 454265942Sgibbs next_scb = &scb_data->scbarray[scb_data->numscbs]; 454365942Sgibbs 454465942Sgibbs sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 454565942Sgibbs 454665942Sgibbs if (sg_map == NULL) 4547168873Sscottl return (0); 454865942Sgibbs 454965942Sgibbs /* Allocate S/G space for the next batch of SCBS */ 4550123579Sgibbs if (aic_dmamem_alloc(ahc, scb_data->sg_dmat, 455165942Sgibbs (void **)&sg_map->sg_vaddr, 4552219577Smarius BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 4553219577Smarius &sg_map->sg_dmamap) != 0) { 455465942Sgibbs free(sg_map, M_DEVBUF); 4555168873Sscottl return (0); 455665942Sgibbs } 455765942Sgibbs 455865942Sgibbs SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); 455965942Sgibbs 4560123579Sgibbs aic_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, 456165942Sgibbs sg_map->sg_vaddr, PAGE_SIZE, ahc_dmamap_cb, 456265942Sgibbs &sg_map->sg_physaddr, /*flags*/0); 456365942Sgibbs 456465942Sgibbs segs = sg_map->sg_vaddr; 456565942Sgibbs physaddr = sg_map->sg_physaddr; 456665942Sgibbs 456765942Sgibbs newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg))); 456895378Sgibbs newcount = MIN(newcount, (AHC_SCB_MAX_ALLOC - scb_data->numscbs)); 456995378Sgibbs for (i = 0; i < newcount; i++) { 457065942Sgibbs struct scb_platform_data *pdata; 457165942Sgibbs#ifndef __linux__ 457265942Sgibbs int error; 457365942Sgibbs#endif 457465942Sgibbs pdata = (struct scb_platform_data *)malloc(sizeof(*pdata), 457565942Sgibbs M_DEVBUF, M_NOWAIT); 457665942Sgibbs if (pdata == NULL) 457765942Sgibbs break; 457865942Sgibbs next_scb->platform_data = pdata; 457979874Sgibbs next_scb->sg_map = sg_map; 458065942Sgibbs next_scb->sg_list = segs; 458165942Sgibbs /* 458265942Sgibbs * The sequencer always starts with the second entry. 458365942Sgibbs * The first entry is embedded in the scb. 458465942Sgibbs */ 458565942Sgibbs next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg); 458666986Sgibbs next_scb->ahc_softc = ahc; 4587123579Sgibbs next_scb->flags = SCB_FLAG_NONE; 458865942Sgibbs#ifndef __linux__ 4589123579Sgibbs error = aic_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, 459065942Sgibbs &next_scb->dmamap); 459165942Sgibbs if (error != 0) 459265942Sgibbs break; 459365942Sgibbs#endif 459465942Sgibbs next_scb->hscb = &scb_data->hscbs[scb_data->numscbs]; 459565942Sgibbs next_scb->hscb->tag = ahc->scb_data->numscbs; 4596168807Sscottl aic_timer_init(&next_scb->io_timer); 459765942Sgibbs SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, 459865942Sgibbs next_scb, links.sle); 459965942Sgibbs segs += AHC_NSEG; 460065942Sgibbs physaddr += (AHC_NSEG * sizeof(struct ahc_dma_seg)); 460165942Sgibbs next_scb++; 460265942Sgibbs ahc->scb_data->numscbs++; 460365942Sgibbs } 4604168873Sscottl return (i); 460565942Sgibbs} 460665942Sgibbs 460765942Sgibbsvoid 460865942Sgibbsahc_controller_info(struct ahc_softc *ahc, char *buf) 460965942Sgibbs{ 461065942Sgibbs int len; 461165942Sgibbs 461265942Sgibbs len = sprintf(buf, "%s: ", ahc_chip_names[ahc->chip & AHC_CHIPID_MASK]); 461365942Sgibbs buf += len; 461465942Sgibbs if ((ahc->features & AHC_TWIN) != 0) 461565942Sgibbs len = sprintf(buf, "Twin Channel, A SCSI Id=%d, " 461665942Sgibbs "B SCSI Id=%d, primary %c, ", 461765942Sgibbs ahc->our_id, ahc->our_id_b, 461874094Sgibbs (ahc->flags & AHC_PRIMARY_CHANNEL) + 'A'); 461965942Sgibbs else { 462076634Sgibbs const char *speed; 462165942Sgibbs const char *type; 462265942Sgibbs 462376634Sgibbs speed = ""; 462476634Sgibbs if ((ahc->features & AHC_ULTRA) != 0) { 462576634Sgibbs speed = "Ultra "; 462676634Sgibbs } else if ((ahc->features & AHC_DT) != 0) { 462776634Sgibbs speed = "Ultra160 "; 462876634Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 462976634Sgibbs speed = "Ultra2 "; 463076634Sgibbs } 463165942Sgibbs if ((ahc->features & AHC_WIDE) != 0) { 463265942Sgibbs type = "Wide"; 463365942Sgibbs } else { 463465942Sgibbs type = "Single"; 463565942Sgibbs } 463676634Sgibbs len = sprintf(buf, "%s%s Channel %c, SCSI Id=%d, ", 463776634Sgibbs speed, type, ahc->channel, ahc->our_id); 463865942Sgibbs } 463965942Sgibbs buf += len; 464065942Sgibbs 464168087Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) 464266269Sgibbs sprintf(buf, "%d/%d SCBs", 464395378Sgibbs ahc->scb_data->maxhscbs, AHC_MAX_QUEUE); 464465942Sgibbs else 464566269Sgibbs sprintf(buf, "%d SCBs", ahc->scb_data->maxhscbs); 464665942Sgibbs} 464765942Sgibbs 4648114621Sgibbsint 4649114621Sgibbsahc_chip_init(struct ahc_softc *ahc) 4650114621Sgibbs{ 4651114621Sgibbs int term; 4652114621Sgibbs int error; 4653114621Sgibbs u_int i; 4654114621Sgibbs u_int scsi_conf; 4655114621Sgibbs u_int scsiseq_template; 4656114621Sgibbs uint32_t physaddr; 4657114621Sgibbs 4658114621Sgibbs ahc_outb(ahc, SEQ_FLAGS, 0); 4659114621Sgibbs ahc_outb(ahc, SEQ_FLAGS2, 0); 4660114621Sgibbs 4661114621Sgibbs /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/ 4662114621Sgibbs if (ahc->features & AHC_TWIN) { 4663114621Sgibbs 4664114621Sgibbs /* 4665114621Sgibbs * Setup Channel B first. 4666114621Sgibbs */ 4667114621Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB); 4668114621Sgibbs term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0; 4669114621Sgibbs ahc_outb(ahc, SCSIID, ahc->our_id_b); 4670114621Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF + 1); 4671114621Sgibbs ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) 4672114621Sgibbs |term|ahc->seltime_b|ENSTIMER|ACTNEGEN); 4673114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 4674114621Sgibbs ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR); 4675114621Sgibbs ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); 4676114621Sgibbs ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN); 4677114621Sgibbs 4678114621Sgibbs /* Select Channel A */ 4679114621Sgibbs ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB); 4680114621Sgibbs } 4681114621Sgibbs term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0; 4682114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 4683114621Sgibbs ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id); 4684114621Sgibbs else 4685114621Sgibbs ahc_outb(ahc, SCSIID, ahc->our_id); 4686114621Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF); 4687114621Sgibbs ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) 4688114621Sgibbs |term|ahc->seltime 4689114621Sgibbs |ENSTIMER|ACTNEGEN); 4690114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 4691114621Sgibbs ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR); 4692114621Sgibbs ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); 4693114621Sgibbs ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN); 4694114621Sgibbs 4695114621Sgibbs /* There are no untagged SCBs active yet. */ 4696114621Sgibbs for (i = 0; i < 16; i++) { 4697114621Sgibbs ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, 0)); 4698114621Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 4699114621Sgibbs int lun; 4700114621Sgibbs 4701114621Sgibbs /* 4702114621Sgibbs * The SCB based BTT allows an entry per 4703114621Sgibbs * target and lun pair. 4704114621Sgibbs */ 4705114621Sgibbs for (lun = 1; lun < AHC_NUM_LUNS; lun++) 4706114621Sgibbs ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, lun)); 4707114621Sgibbs } 4708114621Sgibbs } 4709114621Sgibbs 4710114621Sgibbs /* All of our queues are empty */ 4711114621Sgibbs for (i = 0; i < 256; i++) 4712114621Sgibbs ahc->qoutfifo[i] = SCB_LIST_NULL; 4713114621Sgibbs ahc_sync_qoutfifo(ahc, BUS_DMASYNC_PREREAD); 4714114621Sgibbs 4715114621Sgibbs for (i = 0; i < 256; i++) 4716114621Sgibbs ahc->qinfifo[i] = SCB_LIST_NULL; 4717114621Sgibbs 4718114621Sgibbs if ((ahc->features & AHC_MULTI_TID) != 0) { 4719114621Sgibbs ahc_outb(ahc, TARGID, 0); 4720114621Sgibbs ahc_outb(ahc, TARGID + 1, 0); 4721114621Sgibbs } 4722114621Sgibbs 4723114621Sgibbs /* 4724114621Sgibbs * Tell the sequencer where it can find our arrays in memory. 4725114621Sgibbs */ 4726114621Sgibbs physaddr = ahc->scb_data->hscb_busaddr; 4727114621Sgibbs ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF); 4728114621Sgibbs ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF); 4729114621Sgibbs ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF); 4730114621Sgibbs ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF); 4731114621Sgibbs 4732114621Sgibbs physaddr = ahc->shared_data_busaddr; 4733114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR, physaddr & 0xFF); 4734114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR + 1, (physaddr >> 8) & 0xFF); 4735114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR + 2, (physaddr >> 16) & 0xFF); 4736114621Sgibbs ahc_outb(ahc, SHARED_DATA_ADDR + 3, (physaddr >> 24) & 0xFF); 4737114621Sgibbs 4738114621Sgibbs /* 4739114621Sgibbs * Initialize the group code to command length table. 4740114621Sgibbs * This overrides the values in TARG_SCSIRATE, so only 4741114621Sgibbs * setup the table after we have processed that information. 4742114621Sgibbs */ 4743114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE, 5); 4744114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 1, 9); 4745114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 2, 9); 4746114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 3, 0); 4747114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 4, 15); 4748114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 5, 11); 4749114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 6, 0); 4750114621Sgibbs ahc_outb(ahc, CMDSIZE_TABLE + 7, 0); 4751114621Sgibbs 4752114621Sgibbs if ((ahc->features & AHC_HS_MAILBOX) != 0) 4753114621Sgibbs ahc_outb(ahc, HS_MAILBOX, 0); 4754114621Sgibbs 4755114621Sgibbs /* Tell the sequencer of our initial queue positions */ 4756114621Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) { 4757114621Sgibbs ahc->tqinfifonext = 1; 4758114621Sgibbs ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1); 4759114621Sgibbs ahc_outb(ahc, TQINPOS, ahc->tqinfifonext); 4760114621Sgibbs } 4761114621Sgibbs ahc->qinfifonext = 0; 4762114621Sgibbs ahc->qoutfifonext = 0; 4763114621Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 4764114621Sgibbs ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256); 4765114621Sgibbs ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); 4766114621Sgibbs ahc_outb(ahc, SNSCB_QOFF, ahc->qinfifonext); 4767114621Sgibbs ahc_outb(ahc, SDSCB_QOFF, 0); 4768114621Sgibbs } else { 4769114621Sgibbs ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); 4770114621Sgibbs ahc_outb(ahc, QINPOS, ahc->qinfifonext); 4771114621Sgibbs ahc_outb(ahc, QOUTPOS, ahc->qoutfifonext); 4772114621Sgibbs } 4773114621Sgibbs 4774114621Sgibbs /* We don't have any waiting selections */ 4775114621Sgibbs ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL); 4776114621Sgibbs 4777114621Sgibbs /* Our disconnection list is empty too */ 4778114621Sgibbs ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL); 4779114621Sgibbs 4780114621Sgibbs /* Message out buffer starts empty */ 4781114621Sgibbs ahc_outb(ahc, MSG_OUT, MSG_NOOP); 4782114621Sgibbs 4783114621Sgibbs /* 4784114621Sgibbs * Setup the allowed SCSI Sequences based on operational mode. 4785114621Sgibbs * If we are a target, we'll enalbe select in operations once 4786114621Sgibbs * we've had a lun enabled. 4787114621Sgibbs */ 4788114621Sgibbs scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP; 4789114621Sgibbs if ((ahc->flags & AHC_INITIATORROLE) != 0) 4790114621Sgibbs scsiseq_template |= ENRSELI; 4791114621Sgibbs ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template); 4792114621Sgibbs 4793114621Sgibbs /* Initialize our list of free SCBs. */ 4794114621Sgibbs ahc_build_free_scb_list(ahc); 4795114621Sgibbs 4796114621Sgibbs /* 4797114621Sgibbs * Tell the sequencer which SCB will be the next one it receives. 4798114621Sgibbs */ 4799114621Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag); 4800114621Sgibbs 4801114621Sgibbs /* 4802114621Sgibbs * Load the Sequencer program and Enable the adapter 4803114621Sgibbs * in "fast" mode. 4804114621Sgibbs */ 4805114621Sgibbs if (bootverbose) 4806114621Sgibbs printf("%s: Downloading Sequencer Program...", 4807114621Sgibbs ahc_name(ahc)); 4808114621Sgibbs 4809114621Sgibbs error = ahc_loadseq(ahc); 4810114621Sgibbs if (error != 0) 4811114621Sgibbs return (error); 4812114621Sgibbs 4813114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 4814114621Sgibbs int wait; 4815114621Sgibbs 4816114621Sgibbs /* 4817114621Sgibbs * Wait for up to 500ms for our transceivers 4818114621Sgibbs * to settle. If the adapter does not have 4819114621Sgibbs * a cable attached, the transceivers may 4820114621Sgibbs * never settle, so don't complain if we 4821114621Sgibbs * fail here. 4822114621Sgibbs */ 4823114621Sgibbs for (wait = 5000; 4824114621Sgibbs (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; 4825114621Sgibbs wait--) 4826123579Sgibbs aic_delay(100); 4827114621Sgibbs } 4828115917Sgibbs ahc_restart(ahc); 4829114621Sgibbs return (0); 4830114621Sgibbs} 4831114621Sgibbs 483239220Sgibbs/* 483339220Sgibbs * Start the board, ready for normal operation 483439220Sgibbs */ 483539220Sgibbsint 483639220Sgibbsahc_init(struct ahc_softc *ahc) 483739220Sgibbs{ 483865942Sgibbs int max_targ; 4839123579Sgibbs int error; 4840114621Sgibbs u_int i; 484165942Sgibbs u_int scsi_conf; 484265942Sgibbs u_int ultraenb; 484365942Sgibbs u_int discenable; 484465942Sgibbs u_int tagenable; 484565942Sgibbs size_t driver_data_size; 484639220Sgibbs 4847109590Sgibbs#ifdef AHC_DEBUG 4848109590Sgibbs if ((ahc_debug & AHC_DEBUG_SEQUENCER) != 0) 4849109590Sgibbs ahc->flags |= AHC_SEQUENCER_DEBUG; 485068087Sgibbs#endif 485168087Sgibbs 485239220Sgibbs#ifdef AHC_PRINT_SRAM 485339220Sgibbs printf("Scratch Ram:"); 485439220Sgibbs for (i = 0x20; i < 0x5f; i++) { 485539220Sgibbs if (((i % 8) == 0) && (i != 0)) { 485639220Sgibbs printf ("\n "); 485739220Sgibbs } 485839220Sgibbs printf (" 0x%x", ahc_inb(ahc, i)); 485939220Sgibbs } 486039220Sgibbs if ((ahc->features & AHC_MORE_SRAM) != 0) { 486139220Sgibbs for (i = 0x70; i < 0x7f; i++) { 486239220Sgibbs if (((i % 8) == 0) && (i != 0)) { 486339220Sgibbs printf ("\n "); 486439220Sgibbs } 486539220Sgibbs printf (" 0x%x", ahc_inb(ahc, i)); 486639220Sgibbs } 486739220Sgibbs } 486839220Sgibbs printf ("\n"); 486995378Sgibbs /* 487095378Sgibbs * Reading uninitialized scratch ram may 487195378Sgibbs * generate parity errors. 487295378Sgibbs */ 487395378Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 487495378Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 487539220Sgibbs#endif 487665942Sgibbs max_targ = 15; 487739220Sgibbs 487839220Sgibbs /* 487939220Sgibbs * Assume we have a board at this stage and it has been reset. 488039220Sgibbs */ 488157099Sgibbs if ((ahc->flags & AHC_USEDEFAULTS) != 0) 488239220Sgibbs ahc->our_id = ahc->our_id_b = 7; 488339220Sgibbs 488439220Sgibbs /* 488541646Sgibbs * Default to allowing initiator operations. 488641646Sgibbs */ 488768087Sgibbs ahc->flags |= AHC_INITIATORROLE; 488841646Sgibbs 488968087Sgibbs /* 489068087Sgibbs * Only allow target mode features if this unit has them enabled. 489168087Sgibbs */ 489268087Sgibbs if ((AHC_TMODE_ENABLE & (0x1 << ahc->unit)) == 0) 489368087Sgibbs ahc->features &= ~AHC_TARGETMODE; 489439220Sgibbs 489565942Sgibbs#ifndef __linux__ 489645965Sgibbs /* DMA tag for mapping buffers into device visible space. */ 4897123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 489879874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 4899114621Sgibbs /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING 4900114621Sgibbs ? (bus_addr_t)0x7FFFFFFFFFULL 4901114621Sgibbs : BUS_SPACE_MAXADDR_32BIT, 490245965Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 490345965Sgibbs /*filter*/NULL, /*filterarg*/NULL, 4904108479Sscottl /*maxsize*/(AHC_NSEG - 1) * PAGE_SIZE, 4905108479Sscottl /*nsegments*/AHC_NSEG, 490645965Sgibbs /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 490745965Sgibbs /*flags*/BUS_DMA_ALLOCNOW, 490845965Sgibbs &ahc->buffer_dmat) != 0) { 490945965Sgibbs return (ENOMEM); 491045965Sgibbs } 491165942Sgibbs#endif 491245965Sgibbs 491345965Sgibbs ahc->init_level++; 491445965Sgibbs 491544507Sgibbs /* 491645965Sgibbs * DMA tag for our command fifos and other data in system memory 491745965Sgibbs * the card's sequencer must be able to access. For initiator 4918102670Sgibbs * roles, we need to allocate space for the qinfifo and qoutfifo. 491963457Sgibbs * The qinfifo and qoutfifo are composed of 256 1 byte elements. 492065942Sgibbs * When providing for the target mode role, we must additionally 492163457Sgibbs * provide space for the incoming target command fifo and an extra 492263457Sgibbs * byte to deal with a dma bug in some chip versions. 492345965Sgibbs */ 492463457Sgibbs driver_data_size = 2 * 256 * sizeof(uint8_t); 492568087Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) 492657099Sgibbs driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd) 492757099Sgibbs + /*DMA WideOdd Bug Buffer*/1; 4928123579Sgibbs if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, 492979874Sgibbs /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, 493079874Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 493145965Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 493245965Sgibbs /*filter*/NULL, /*filterarg*/NULL, 493345965Sgibbs driver_data_size, 493445965Sgibbs /*nsegments*/1, 493545965Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 493645965Sgibbs /*flags*/0, &ahc->shared_data_dmat) != 0) { 493745965Sgibbs return (ENOMEM); 493845965Sgibbs } 493945965Sgibbs 494045965Sgibbs ahc->init_level++; 494145965Sgibbs 494245965Sgibbs /* Allocation of driver data */ 4943123579Sgibbs if (aic_dmamem_alloc(ahc, ahc->shared_data_dmat, 494463457Sgibbs (void **)&ahc->qoutfifo, 4945219577Smarius BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 4946219577Smarius &ahc->shared_data_dmamap) != 0) { 494745965Sgibbs return (ENOMEM); 494845965Sgibbs } 494945965Sgibbs 495045965Sgibbs ahc->init_level++; 495145965Sgibbs 495265942Sgibbs /* And permanently map it in */ 4953123579Sgibbs aic_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, 495465942Sgibbs ahc->qoutfifo, driver_data_size, ahc_dmamap_cb, 495563457Sgibbs &ahc->shared_data_busaddr, /*flags*/0); 495645965Sgibbs 495768087Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) { 495863457Sgibbs ahc->targetcmds = (struct target_cmd *)ahc->qoutfifo; 495971390Sgibbs ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[AHC_TMODE_CMDS]; 496063457Sgibbs ahc->dma_bug_buf = ahc->shared_data_busaddr 496163457Sgibbs + driver_data_size - 1; 496263457Sgibbs /* All target command blocks start out invalid. */ 496363457Sgibbs for (i = 0; i < AHC_TMODE_CMDS; i++) 496463457Sgibbs ahc->targetcmds[i].cmd_valid = 0; 496579874Sgibbs ahc_sync_tqinfifo(ahc, BUS_DMASYNC_PREREAD); 496663457Sgibbs ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[256]; 496763457Sgibbs } 496863457Sgibbs ahc->qinfifo = &ahc->qoutfifo[256]; 496963457Sgibbs 497045965Sgibbs ahc->init_level++; 497145965Sgibbs 497257099Sgibbs /* Allocate SCB data now that buffer_dmat is initialized */ 497345965Sgibbs if (ahc->scb_data->maxhscbs == 0) 497465942Sgibbs if (ahc_init_scbdata(ahc) != 0) 497545965Sgibbs return (ENOMEM); 497645965Sgibbs 497745965Sgibbs /* 497844507Sgibbs * Allocate a tstate to house information for our 497944507Sgibbs * initiator presence on the bus as well as the user 498044507Sgibbs * data for any target mode initiator. 498144507Sgibbs */ 498244507Sgibbs if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) { 498374972Sgibbs printf("%s: unable to allocate ahc_tmode_tstate. " 498444507Sgibbs "Failing attach\n", ahc_name(ahc)); 498574972Sgibbs return (ENOMEM); 498644507Sgibbs } 498741646Sgibbs 498839220Sgibbs if ((ahc->features & AHC_TWIN) != 0) { 498944507Sgibbs if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) { 499074972Sgibbs printf("%s: unable to allocate ahc_tmode_tstate. " 499144507Sgibbs "Failing attach\n", ahc_name(ahc)); 499274972Sgibbs return (ENOMEM); 499344507Sgibbs } 499439220Sgibbs } 499539220Sgibbs 4996123579Sgibbs /* 4997123579Sgibbs * Fire up a recovery thread for this controller. 4998123579Sgibbs */ 4999123579Sgibbs error = ahc_spawn_recovery_thread(ahc); 5000123579Sgibbs if (error != 0) 5001123579Sgibbs return (error); 5002123579Sgibbs 500395378Sgibbs if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) { 500439220Sgibbs ahc->flags |= AHC_PAGESCBS; 500539220Sgibbs } else { 500639220Sgibbs ahc->flags &= ~AHC_PAGESCBS; 500739220Sgibbs } 500839220Sgibbs 500939220Sgibbs#ifdef AHC_DEBUG 5010102670Sgibbs if (ahc_debug & AHC_SHOW_MISC) { 5011114621Sgibbs printf("%s: hardware scb %u bytes; kernel scb %u bytes; " 5012114621Sgibbs "ahc_dma %u bytes\n", 501339220Sgibbs ahc_name(ahc), 5014114621Sgibbs (u_int)sizeof(struct hardware_scb), 5015114621Sgibbs (u_int)sizeof(struct scb), 5016114621Sgibbs (u_int)sizeof(struct ahc_dma_seg)); 501739220Sgibbs } 501839220Sgibbs#endif /* AHC_DEBUG */ 501939220Sgibbs 5020114621Sgibbs /* 5021114621Sgibbs * Look at the information that board initialization or 5022114621Sgibbs * the board bios has left us. 5023114621Sgibbs */ 502439220Sgibbs if (ahc->features & AHC_TWIN) { 502539220Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF + 1); 502641816Sgibbs if ((scsi_conf & RESET_SCSI) != 0 502768087Sgibbs && (ahc->flags & AHC_INITIATORROLE) != 0) 502841816Sgibbs ahc->flags |= AHC_RESET_BUS_B; 5029114621Sgibbs } 503039220Sgibbs 503139220Sgibbs scsi_conf = ahc_inb(ahc, SCSICONF); 503241816Sgibbs if ((scsi_conf & RESET_SCSI) != 0 503368087Sgibbs && (ahc->flags & AHC_INITIATORROLE) != 0) 503441816Sgibbs ahc->flags |= AHC_RESET_BUS_A; 503539220Sgibbs 503644507Sgibbs ultraenb = 0; 503744507Sgibbs tagenable = ALL_TARGETS_MASK; 503839220Sgibbs 503939220Sgibbs /* Grab the disconnection disable table and invert it for our needs */ 504095378Sgibbs if ((ahc->flags & AHC_USEDEFAULTS) != 0) { 504139220Sgibbs printf("%s: Host Adapter Bios disabled. Using default SCSI " 504239220Sgibbs "device parameters\n", ahc_name(ahc)); 504340125Sgibbs ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B| 504440125Sgibbs AHC_TERM_ENB_A|AHC_TERM_ENB_B; 504544507Sgibbs discenable = ALL_TARGETS_MASK; 504639220Sgibbs if ((ahc->features & AHC_ULTRA) != 0) 504744507Sgibbs ultraenb = ALL_TARGETS_MASK; 504839220Sgibbs } else { 504944507Sgibbs discenable = ~((ahc_inb(ahc, DISC_DSB + 1) << 8) 505044507Sgibbs | ahc_inb(ahc, DISC_DSB)); 505139220Sgibbs if ((ahc->features & (AHC_ULTRA|AHC_ULTRA2)) != 0) 505244507Sgibbs ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8) 505339220Sgibbs | ahc_inb(ahc, ULTRA_ENB); 505439220Sgibbs } 505539220Sgibbs 505639220Sgibbs if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) 505739220Sgibbs max_targ = 7; 505839220Sgibbs 505939220Sgibbs for (i = 0; i <= max_targ; i++) { 506044507Sgibbs struct ahc_initiator_tinfo *tinfo; 506174972Sgibbs struct ahc_tmode_tstate *tstate; 506244507Sgibbs u_int our_id; 506344507Sgibbs u_int target_id; 506444507Sgibbs char channel; 506539220Sgibbs 506644507Sgibbs channel = 'A'; 506744507Sgibbs our_id = ahc->our_id; 506844507Sgibbs target_id = i; 506944507Sgibbs if (i > 7 && (ahc->features & AHC_TWIN) != 0) { 507044507Sgibbs channel = 'B'; 507144507Sgibbs our_id = ahc->our_id_b; 507244507Sgibbs target_id = i % 8; 507344507Sgibbs } 507444507Sgibbs tinfo = ahc_fetch_transinfo(ahc, channel, our_id, 507544507Sgibbs target_id, &tstate); 507639220Sgibbs /* Default to async narrow across the board */ 507765942Sgibbs memset(tinfo, 0, sizeof(*tinfo)); 507839220Sgibbs if (ahc->flags & AHC_USEDEFAULTS) { 507939220Sgibbs if ((ahc->features & AHC_WIDE) != 0) 508044507Sgibbs tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; 508139220Sgibbs 508239220Sgibbs /* 508339220Sgibbs * These will be truncated when we determine the 508439220Sgibbs * connection type we have with the target. 508539220Sgibbs */ 508644507Sgibbs tinfo->user.period = ahc_syncrates->period; 5087114621Sgibbs tinfo->user.offset = MAX_OFFSET; 508839220Sgibbs } else { 508939220Sgibbs u_int scsirate; 509063457Sgibbs uint16_t mask; 509139220Sgibbs 509239220Sgibbs /* Take the settings leftover in scratch RAM. */ 509339220Sgibbs scsirate = ahc_inb(ahc, TARG_SCSIRATE + i); 509439220Sgibbs mask = (0x01 << i); 509539220Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 509639220Sgibbs u_int offset; 509755581Sgibbs u_int maxsync; 509839220Sgibbs 509939220Sgibbs if ((scsirate & SOFS) == 0x0F) { 510039220Sgibbs /* 510139220Sgibbs * Haven't negotiated yet, 510239220Sgibbs * so the format is different. 510339220Sgibbs */ 510439220Sgibbs scsirate = (scsirate & SXFR) >> 4 510544507Sgibbs | (ultraenb & mask) 510655581Sgibbs ? 0x08 : 0x0 510739220Sgibbs | (scsirate & WIDEXFER); 510839220Sgibbs offset = MAX_OFFSET_ULTRA2; 510939220Sgibbs } else 511039220Sgibbs offset = ahc_inb(ahc, TARG_OFFSET + i); 511174094Sgibbs if ((scsirate & ~WIDEXFER) == 0 && offset != 0) 511274094Sgibbs /* Set to the lowest sync rate, 5MHz */ 511374094Sgibbs scsirate |= 0x1c; 511455581Sgibbs maxsync = AHC_SYNCRATE_ULTRA2; 511555581Sgibbs if ((ahc->features & AHC_DT) != 0) 511655581Sgibbs maxsync = AHC_SYNCRATE_DT; 511747414Sgibbs tinfo->user.period = 511855581Sgibbs ahc_find_period(ahc, scsirate, maxsync); 511939220Sgibbs if (offset == 0) 512044507Sgibbs tinfo->user.period = 0; 512139220Sgibbs else 5122114621Sgibbs tinfo->user.offset = MAX_OFFSET; 512363457Sgibbs if ((scsirate & SXFR_ULTRA2) <= 8/*10MHz*/ 512463457Sgibbs && (ahc->features & AHC_DT) != 0) 512563457Sgibbs tinfo->user.ppr_options = 512663457Sgibbs MSG_EXT_PPR_DT_REQ; 512739220Sgibbs } else if ((scsirate & SOFS) != 0) { 512868087Sgibbs if ((scsirate & SXFR) == 0x40 512968087Sgibbs && (ultraenb & mask) != 0) { 513068087Sgibbs /* Treat 10MHz as a non-ultra speed */ 513168087Sgibbs scsirate &= ~SXFR; 513268087Sgibbs ultraenb &= ~mask; 513368087Sgibbs } 513444507Sgibbs tinfo->user.period = 513539220Sgibbs ahc_find_period(ahc, scsirate, 513644507Sgibbs (ultraenb & mask) 513739220Sgibbs ? AHC_SYNCRATE_ULTRA 513839220Sgibbs : AHC_SYNCRATE_FAST); 513946099Sken if (tinfo->user.period != 0) 5140114621Sgibbs tinfo->user.offset = MAX_OFFSET; 514139220Sgibbs } 514274094Sgibbs if (tinfo->user.period == 0) 514374094Sgibbs tinfo->user.offset = 0; 514439220Sgibbs if ((scsirate & WIDEXFER) != 0 514544507Sgibbs && (ahc->features & AHC_WIDE) != 0) 514644507Sgibbs tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; 514763457Sgibbs tinfo->user.protocol_version = 4; 514863457Sgibbs if ((ahc->features & AHC_DT) != 0) 514963457Sgibbs tinfo->user.transport_version = 3; 515063457Sgibbs else 515163457Sgibbs tinfo->user.transport_version = 2; 515263457Sgibbs tinfo->goal.protocol_version = 2; 515363457Sgibbs tinfo->goal.transport_version = 2; 515476634Sgibbs tinfo->curr.protocol_version = 2; 515576634Sgibbs tinfo->curr.transport_version = 2; 515639220Sgibbs } 5157109590Sgibbs tstate->ultraenb = 0; 515839220Sgibbs } 515949933Sgibbs ahc->user_discenable = discenable; 516049933Sgibbs ahc->user_tagenable = tagenable; 516139220Sgibbs 5162114621Sgibbs return (ahc->bus_chip_init(ahc)); 516339220Sgibbs} 516439220Sgibbs 516574972Sgibbsvoid 516674972Sgibbsahc_intr_enable(struct ahc_softc *ahc, int enable) 516774972Sgibbs{ 516874972Sgibbs u_int hcntrl; 516974972Sgibbs 517074972Sgibbs hcntrl = ahc_inb(ahc, HCNTRL); 517174972Sgibbs hcntrl &= ~INTEN; 517274972Sgibbs ahc->pause &= ~INTEN; 517374972Sgibbs ahc->unpause &= ~INTEN; 517474972Sgibbs if (enable) { 517574972Sgibbs hcntrl |= INTEN; 517674972Sgibbs ahc->pause |= INTEN; 517774972Sgibbs ahc->unpause |= INTEN; 517874972Sgibbs } 517974972Sgibbs ahc_outb(ahc, HCNTRL, hcntrl); 518074972Sgibbs} 518174972Sgibbs 518270204Sgibbs/* 518370204Sgibbs * Ensure that the card is paused in a location 518470204Sgibbs * outside of all critical sections and that all 518570204Sgibbs * pending work is completed prior to returning. 518670204Sgibbs * This routine should only be called from outside 518770204Sgibbs * an interrupt context. 518870204Sgibbs */ 518970204Sgibbsvoid 519070204Sgibbsahc_pause_and_flushwork(struct ahc_softc *ahc) 519170204Sgibbs{ 519271390Sgibbs int intstat; 519371390Sgibbs int maxloops; 5194102670Sgibbs int paused; 519571390Sgibbs 519671390Sgibbs maxloops = 1000; 519770204Sgibbs ahc->flags |= AHC_ALL_INTERRUPTS; 5198102670Sgibbs paused = FALSE; 519970204Sgibbs do { 5200123579Sgibbs if (paused) { 5201102670Sgibbs ahc_unpause(ahc); 5202123579Sgibbs /* 5203123579Sgibbs * Give the sequencer some time to service 5204123579Sgibbs * any active selections. 5205123579Sgibbs */ 5206129133Sgibbs aic_delay(500); 5207123579Sgibbs } 520870204Sgibbs ahc_intr(ahc); 520974094Sgibbs ahc_pause(ahc); 5210102670Sgibbs paused = TRUE; 5211102670Sgibbs ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO); 5212114621Sgibbs intstat = ahc_inb(ahc, INTSTAT); 5213129133Sgibbs if ((intstat & INT_PEND) == 0) { 5214129133Sgibbs ahc_clear_critical_section(ahc); 5215129133Sgibbs intstat = ahc_inb(ahc, INTSTAT); 5216129133Sgibbs } 5217102670Sgibbs } while (--maxloops 5218114621Sgibbs && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0) 5219114621Sgibbs && ((intstat & INT_PEND) != 0 5220114621Sgibbs || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)) != 0)); 522171390Sgibbs if (maxloops == 0) { 522271390Sgibbs printf("Infinite interrupt loop, INTSTAT = %x", 5223102670Sgibbs ahc_inb(ahc, INTSTAT)); 522471390Sgibbs } 522570204Sgibbs ahc_platform_flushwork(ahc); 522670204Sgibbs ahc->flags &= ~AHC_ALL_INTERRUPTS; 522770204Sgibbs} 522870204Sgibbs 522970204Sgibbsint 523070204Sgibbsahc_suspend(struct ahc_softc *ahc) 523170204Sgibbs{ 523270204Sgibbs 523370204Sgibbs ahc_pause_and_flushwork(ahc); 523470204Sgibbs 5235114621Sgibbs if (LIST_FIRST(&ahc->pending_scbs) != NULL) { 5236114621Sgibbs ahc_unpause(ahc); 523770204Sgibbs return (EBUSY); 5238114621Sgibbs } 523970204Sgibbs 5240115337Sgibbs#ifdef AHC_TARGET_MODE 524170204Sgibbs /* 524270204Sgibbs * XXX What about ATIOs that have not yet been serviced? 524370204Sgibbs * Perhaps we should just refuse to be suspended if we 524470204Sgibbs * are acting in a target role. 524570204Sgibbs */ 5246114621Sgibbs if (ahc->pending_device != NULL) { 5247114621Sgibbs ahc_unpause(ahc); 524870204Sgibbs return (EBUSY); 5249114621Sgibbs } 525070204Sgibbs#endif 525170204Sgibbs ahc_shutdown(ahc); 525270204Sgibbs return (0); 525370204Sgibbs} 525470204Sgibbs 525570204Sgibbsint 525670204Sgibbsahc_resume(struct ahc_softc *ahc) 525770204Sgibbs{ 525870204Sgibbs 5259115917Sgibbs ahc_reset(ahc, /*reinit*/TRUE); 5260115917Sgibbs ahc_intr_enable(ahc, TRUE); 5261115917Sgibbs ahc_restart(ahc); 526270204Sgibbs return (0); 526370204Sgibbs} 526470204Sgibbs 526565942Sgibbs/************************** Busy Target Table *********************************/ 526665942Sgibbs/* 526765942Sgibbs * Return the untagged transaction id for a given target/channel lun. 526865942Sgibbs * Optionally, clear the entry. 526965942Sgibbs */ 527065942Sgibbsu_int 527170204Sgibbsahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl) 527239220Sgibbs{ 527365942Sgibbs u_int scbid; 527465942Sgibbs u_int target_offset; 527539220Sgibbs 527671390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 527765942Sgibbs u_int saved_scbptr; 527865942Sgibbs 527965942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 528065942Sgibbs ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); 528165942Sgibbs scbid = ahc_inb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl)); 528265942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 528342652Sgibbs } else { 528465942Sgibbs target_offset = TCL_TARGET_OFFSET(tcl); 528565942Sgibbs scbid = ahc_inb(ahc, BUSY_TARGETS + target_offset); 528642652Sgibbs } 528742652Sgibbs 528865942Sgibbs return (scbid); 528939220Sgibbs} 529039220Sgibbs 529165942Sgibbsvoid 529270204Sgibbsahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl) 529370204Sgibbs{ 529470204Sgibbs u_int target_offset; 529570204Sgibbs 529671390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 529770204Sgibbs u_int saved_scbptr; 529870204Sgibbs 529970204Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 530070204Sgibbs ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); 530170204Sgibbs ahc_outb(ahc, SCB_64_BTT+TCL_TARGET_OFFSET(tcl), SCB_LIST_NULL); 530270204Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 530370204Sgibbs } else { 530470204Sgibbs target_offset = TCL_TARGET_OFFSET(tcl); 530570204Sgibbs ahc_outb(ahc, BUSY_TARGETS + target_offset, SCB_LIST_NULL); 530670204Sgibbs } 530770204Sgibbs} 530870204Sgibbs 530970204Sgibbsvoid 531065942Sgibbsahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int scbid) 531139220Sgibbs{ 531265942Sgibbs u_int target_offset; 531339220Sgibbs 531471390Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) { 531565942Sgibbs u_int saved_scbptr; 531639220Sgibbs 531765942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 531865942Sgibbs ahc_outb(ahc, SCBPTR, TCL_LUN(tcl)); 531965942Sgibbs ahc_outb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl), scbid); 532065942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 532139220Sgibbs } else { 532265942Sgibbs target_offset = TCL_TARGET_OFFSET(tcl); 532365942Sgibbs ahc_outb(ahc, BUSY_TARGETS + target_offset, scbid); 532439220Sgibbs } 532539220Sgibbs} 532639220Sgibbs 532765942Sgibbs/************************** SCB and SCB queue management **********************/ 532865942Sgibbsint 532965942Sgibbsahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target, 533065942Sgibbs char channel, int lun, u_int tag, role_t role) 533139220Sgibbs{ 533265942Sgibbs int targ = SCB_GET_TARGET(ahc, scb); 533365942Sgibbs char chan = SCB_GET_CHANNEL(ahc, scb); 533465942Sgibbs int slun = SCB_GET_LUN(scb); 533565942Sgibbs int match; 533639220Sgibbs 533765942Sgibbs match = ((chan == channel) || (channel == ALL_CHANNELS)); 533865942Sgibbs if (match != 0) 533965942Sgibbs match = ((targ == target) || (target == CAM_TARGET_WILDCARD)); 534065942Sgibbs if (match != 0) 534165942Sgibbs match = ((lun == slun) || (lun == CAM_LUN_WILDCARD)); 534265942Sgibbs if (match != 0) { 5343115337Sgibbs#ifdef AHC_TARGET_MODE 534465942Sgibbs int group; 534563457Sgibbs 534665942Sgibbs group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code); 534765942Sgibbs if (role == ROLE_INITIATOR) { 534872325Sgibbs match = (group != XPT_FC_GROUP_TMODE) 534965942Sgibbs && ((tag == scb->hscb->tag) 535065942Sgibbs || (tag == SCB_LIST_NULL)); 535165942Sgibbs } else if (role == ROLE_TARGET) { 535265942Sgibbs match = (group == XPT_FC_GROUP_TMODE) 535365942Sgibbs && ((tag == scb->io_ctx->csio.tag_id) 535465942Sgibbs || (tag == SCB_LIST_NULL)); 535539220Sgibbs } 535665942Sgibbs#else /* !AHC_TARGET_MODE */ 535765942Sgibbs match = ((tag == scb->hscb->tag) || (tag == SCB_LIST_NULL)); 535865942Sgibbs#endif /* AHC_TARGET_MODE */ 535939220Sgibbs } 536039220Sgibbs 536165942Sgibbs return match; 536239220Sgibbs} 536339220Sgibbs 536465942Sgibbsvoid 536565942Sgibbsahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb) 536639220Sgibbs{ 536739220Sgibbs int target; 536839220Sgibbs char channel; 536939220Sgibbs int lun; 537039220Sgibbs 537165942Sgibbs target = SCB_GET_TARGET(ahc, scb); 537265942Sgibbs lun = SCB_GET_LUN(scb); 537365942Sgibbs channel = SCB_GET_CHANNEL(ahc, scb); 537439220Sgibbs 537539220Sgibbs ahc_search_qinfifo(ahc, target, channel, lun, 537649933Sgibbs /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN, 537749933Sgibbs CAM_REQUEUE_REQ, SEARCH_COMPLETE); 537839220Sgibbs 537965942Sgibbs ahc_platform_freeze_devq(ahc, scb); 538039220Sgibbs} 538139220Sgibbs 538266800Sgibbsvoid 538368087Sgibbsahc_qinfifo_requeue_tail(struct ahc_softc *ahc, struct scb *scb) 538468087Sgibbs{ 538568087Sgibbs struct scb *prev_scb; 538668087Sgibbs 538768087Sgibbs prev_scb = NULL; 538868087Sgibbs if (ahc_qinfifo_count(ahc) != 0) { 538968087Sgibbs u_int prev_tag; 539068402Sgibbs uint8_t prev_pos; 539168087Sgibbs 539268402Sgibbs prev_pos = ahc->qinfifonext - 1; 539368402Sgibbs prev_tag = ahc->qinfifo[prev_pos]; 539468087Sgibbs prev_scb = ahc_lookup_scb(ahc, prev_tag); 539568087Sgibbs } 539668087Sgibbs ahc_qinfifo_requeue(ahc, prev_scb, scb); 539768087Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 539868087Sgibbs ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); 539968087Sgibbs } else { 540068087Sgibbs ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); 540168087Sgibbs } 540268087Sgibbs} 540368087Sgibbs 540468087Sgibbsstatic void 540566647Sgibbsahc_qinfifo_requeue(struct ahc_softc *ahc, struct scb *prev_scb, 540666647Sgibbs struct scb *scb) 540766647Sgibbs{ 540879874Sgibbs if (prev_scb == NULL) { 540966647Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag); 541079874Sgibbs } else { 541166647Sgibbs prev_scb->hscb->next = scb->hscb->tag; 541279874Sgibbs ahc_sync_scb(ahc, prev_scb, 541379874Sgibbs BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 541479874Sgibbs } 541566647Sgibbs ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; 541666647Sgibbs scb->hscb->next = ahc->next_queued_scb->hscb->tag; 541779874Sgibbs ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 541866647Sgibbs} 541966647Sgibbs 542068087Sgibbsstatic int 542166800Sgibbsahc_qinfifo_count(struct ahc_softc *ahc) 542266800Sgibbs{ 5423102670Sgibbs uint8_t qinpos; 5424102670Sgibbs uint8_t diff; 542566800Sgibbs 542666800Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 542766800Sgibbs qinpos = ahc_inb(ahc, SNSCB_QOFF); 542866800Sgibbs ahc_outb(ahc, SNSCB_QOFF, qinpos); 542966800Sgibbs } else 543066800Sgibbs qinpos = ahc_inb(ahc, QINPOS); 543168402Sgibbs diff = ahc->qinfifonext - qinpos; 543268402Sgibbs return (diff); 543366800Sgibbs} 543466800Sgibbs 543566800Sgibbsint 543639220Sgibbsahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, 543763457Sgibbs int lun, u_int tag, role_t role, uint32_t status, 543839220Sgibbs ahc_search_action action) 543939220Sgibbs{ 544065942Sgibbs struct scb *scb; 544166647Sgibbs struct scb *prev_scb; 544266647Sgibbs uint8_t qinstart; 544363457Sgibbs uint8_t qinpos; 544463457Sgibbs uint8_t qintail; 544595378Sgibbs uint8_t next; 544695378Sgibbs uint8_t prev; 544763457Sgibbs uint8_t curscbptr; 544865942Sgibbs int found; 544966800Sgibbs int have_qregs; 545039220Sgibbs 545139220Sgibbs qintail = ahc->qinfifonext; 545266800Sgibbs have_qregs = (ahc->features & AHC_QUEUE_REGS) != 0; 545366800Sgibbs if (have_qregs) { 545466647Sgibbs qinstart = ahc_inb(ahc, SNSCB_QOFF); 545566647Sgibbs ahc_outb(ahc, SNSCB_QOFF, qinstart); 545666647Sgibbs } else 545766647Sgibbs qinstart = ahc_inb(ahc, QINPOS); 545866647Sgibbs qinpos = qinstart; 545939220Sgibbs found = 0; 546066647Sgibbs prev_scb = NULL; 546139220Sgibbs 546263457Sgibbs if (action == SEARCH_COMPLETE) { 546363457Sgibbs /* 546463457Sgibbs * Don't attempt to run any queued untagged transactions 546563457Sgibbs * until we are done with the abort process. 546663457Sgibbs */ 546763457Sgibbs ahc_freeze_untagged_queues(ahc); 546863457Sgibbs } 546963457Sgibbs 547039220Sgibbs /* 547139220Sgibbs * Start with an empty queue. Entries that are not chosen 547239220Sgibbs * for removal will be re-added to the queue as we go. 547339220Sgibbs */ 547439220Sgibbs ahc->qinfifonext = qinpos; 547566647Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag); 547639220Sgibbs 547739220Sgibbs while (qinpos != qintail) { 547866647Sgibbs scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinpos]); 547979874Sgibbs if (scb == NULL) { 548079874Sgibbs printf("qinpos = %d, SCB index = %d\n", 548179874Sgibbs qinpos, ahc->qinfifo[qinpos]); 548279874Sgibbs panic("Loop 1\n"); 548379874Sgibbs } 548479874Sgibbs 548565942Sgibbs if (ahc_match_scb(ahc, scb, target, channel, lun, tag, role)) { 548639220Sgibbs /* 548763457Sgibbs * We found an scb that needs to be acted on. 548839220Sgibbs */ 548963457Sgibbs found++; 549039220Sgibbs switch (action) { 549139220Sgibbs case SEARCH_COMPLETE: 549265942Sgibbs { 549365942Sgibbs cam_status ostat; 549472325Sgibbs cam_status cstat; 549565942Sgibbs 5496123579Sgibbs ostat = aic_get_transaction_status(scb); 549765942Sgibbs if (ostat == CAM_REQ_INPROG) 5498123579Sgibbs aic_set_transaction_status(scb, status); 5499123579Sgibbs cstat = aic_get_transaction_status(scb); 550072325Sgibbs if (cstat != CAM_REQ_CMP) 5501123579Sgibbs aic_freeze_scb(scb); 550265942Sgibbs if ((scb->flags & SCB_ACTIVE) == 0) 550365942Sgibbs printf("Inactive SCB in qinfifo\n"); 550465942Sgibbs ahc_done(ahc, scb); 550566647Sgibbs 550666717Sgibbs /* FALLTHROUGH */ 550795378Sgibbs } 550866717Sgibbs case SEARCH_REMOVE: 550939220Sgibbs break; 551039220Sgibbs case SEARCH_COUNT: 551166647Sgibbs ahc_qinfifo_requeue(ahc, prev_scb, scb); 551266647Sgibbs prev_scb = scb; 551339220Sgibbs break; 551439220Sgibbs } 551539220Sgibbs } else { 551666647Sgibbs ahc_qinfifo_requeue(ahc, prev_scb, scb); 551766647Sgibbs prev_scb = scb; 551839220Sgibbs } 551939220Sgibbs qinpos++; 552039220Sgibbs } 552139220Sgibbs 552239220Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 552339220Sgibbs ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); 552439220Sgibbs } else { 552539220Sgibbs ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); 552639220Sgibbs } 552739220Sgibbs 552871390Sgibbs if (action != SEARCH_COUNT 552971390Sgibbs && (found != 0) 553071390Sgibbs && (qinstart != ahc->qinfifonext)) { 553171390Sgibbs /* 553271390Sgibbs * The sequencer may be in the process of dmaing 553371390Sgibbs * down the SCB at the beginning of the queue. 553471390Sgibbs * This could be problematic if either the first, 553571390Sgibbs * or the second SCB is removed from the queue 553671390Sgibbs * (the first SCB includes a pointer to the "next" 553771390Sgibbs * SCB to dma). If we have removed any entries, swap 553871390Sgibbs * the first element in the queue with the next HSCB 553971390Sgibbs * so the sequencer will notice that NEXT_QUEUED_SCB 554071390Sgibbs * has changed during its dma attempt and will retry 554171390Sgibbs * the DMA. 554271390Sgibbs */ 554371390Sgibbs scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinstart]); 554471390Sgibbs 554579874Sgibbs if (scb == NULL) { 554679874Sgibbs printf("found = %d, qinstart = %d, qinfifionext = %d\n", 554779874Sgibbs found, qinstart, ahc->qinfifonext); 554879874Sgibbs panic("First/Second Qinfifo fixup\n"); 554979874Sgibbs } 555071390Sgibbs /* 555171390Sgibbs * ahc_swap_with_next_hscb forces our next pointer to 555271390Sgibbs * point to the reserved SCB for future commands. Save 555371390Sgibbs * and restore our original next pointer to maintain 555471390Sgibbs * queue integrity. 555571390Sgibbs */ 555671390Sgibbs next = scb->hscb->next; 555771390Sgibbs ahc->scb_data->scbindex[scb->hscb->tag] = NULL; 555871390Sgibbs ahc_swap_with_next_hscb(ahc, scb); 555971390Sgibbs scb->hscb->next = next; 556071390Sgibbs ahc->qinfifo[qinstart] = scb->hscb->tag; 556171390Sgibbs 556271473Sgibbs /* Tell the card about the new head of the qinfifo. */ 556371473Sgibbs ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag); 556471473Sgibbs 556571390Sgibbs /* Fixup the tail "next" pointer. */ 556671390Sgibbs qintail = ahc->qinfifonext - 1; 556771390Sgibbs scb = ahc_lookup_scb(ahc, ahc->qinfifo[qintail]); 556871390Sgibbs scb->hscb->next = ahc->next_queued_scb->hscb->tag; 556971390Sgibbs } 557071390Sgibbs 557163457Sgibbs /* 557263457Sgibbs * Search waiting for selection list. 557363457Sgibbs */ 557463457Sgibbs curscbptr = ahc_inb(ahc, SCBPTR); 557563457Sgibbs next = ahc_inb(ahc, WAITING_SCBH); /* Start at head of list. */ 557663457Sgibbs prev = SCB_LIST_NULL; 557763457Sgibbs 557863457Sgibbs while (next != SCB_LIST_NULL) { 557963457Sgibbs uint8_t scb_index; 558063457Sgibbs 558163457Sgibbs ahc_outb(ahc, SCBPTR, next); 558263457Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 558363457Sgibbs if (scb_index >= ahc->scb_data->numscbs) { 558468087Sgibbs printf("Waiting List inconsistency. " 558568087Sgibbs "SCB index == %d, yet numscbs == %d.", 558668087Sgibbs scb_index, ahc->scb_data->numscbs); 558768087Sgibbs ahc_dump_card_state(ahc); 558868087Sgibbs panic("for safety"); 558963457Sgibbs } 559066647Sgibbs scb = ahc_lookup_scb(ahc, scb_index); 559179874Sgibbs if (scb == NULL) { 559279874Sgibbs printf("scb_index = %d, next = %d\n", 559379874Sgibbs scb_index, next); 559479874Sgibbs panic("Waiting List traversal\n"); 559579874Sgibbs } 559665942Sgibbs if (ahc_match_scb(ahc, scb, target, channel, 559763457Sgibbs lun, SCB_LIST_NULL, role)) { 559863457Sgibbs /* 559963457Sgibbs * We found an scb that needs to be acted on. 560063457Sgibbs */ 560163457Sgibbs found++; 560263457Sgibbs switch (action) { 560363457Sgibbs case SEARCH_COMPLETE: 560465942Sgibbs { 560565942Sgibbs cam_status ostat; 560672325Sgibbs cam_status cstat; 560765942Sgibbs 5608123579Sgibbs ostat = aic_get_transaction_status(scb); 560965942Sgibbs if (ostat == CAM_REQ_INPROG) 5610123579Sgibbs aic_set_transaction_status(scb, 561165942Sgibbs status); 5612123579Sgibbs cstat = aic_get_transaction_status(scb); 561372325Sgibbs if (cstat != CAM_REQ_CMP) 5614123579Sgibbs aic_freeze_scb(scb); 561565942Sgibbs if ((scb->flags & SCB_ACTIVE) == 0) 5616125449Sgibbs printf("Inactive SCB in Wait List\n"); 561765942Sgibbs ahc_done(ahc, scb); 561868087Sgibbs /* FALLTHROUGH */ 561968087Sgibbs } 562068087Sgibbs case SEARCH_REMOVE: 562168087Sgibbs next = ahc_rem_wscb(ahc, next, prev); 562263457Sgibbs break; 562363457Sgibbs case SEARCH_COUNT: 562463457Sgibbs prev = next; 562563457Sgibbs next = ahc_inb(ahc, SCB_NEXT); 562663457Sgibbs break; 562763457Sgibbs } 562863457Sgibbs } else { 562963457Sgibbs 563063457Sgibbs prev = next; 563163457Sgibbs next = ahc_inb(ahc, SCB_NEXT); 563263457Sgibbs } 563363457Sgibbs } 563463457Sgibbs ahc_outb(ahc, SCBPTR, curscbptr); 563563457Sgibbs 5636123579Sgibbs found += ahc_search_untagged_queues(ahc, /*aic_io_ctx_t*/NULL, target, 5637102670Sgibbs channel, lun, status, action); 5638102670Sgibbs 5639102670Sgibbs if (action == SEARCH_COMPLETE) 5640102670Sgibbs ahc_release_untagged_queues(ahc); 5641102670Sgibbs return (found); 5642102670Sgibbs} 5643102670Sgibbs 5644102670Sgibbsint 5645123579Sgibbsahc_search_untagged_queues(struct ahc_softc *ahc, aic_io_ctx_t ctx, 5646102670Sgibbs int target, char channel, int lun, uint32_t status, 5647102670Sgibbs ahc_search_action action) 5648102670Sgibbs{ 5649102670Sgibbs struct scb *scb; 5650102670Sgibbs int maxtarget; 5651102670Sgibbs int found; 5652102670Sgibbs int i; 5653102670Sgibbs 5654102670Sgibbs if (action == SEARCH_COMPLETE) { 5655102670Sgibbs /* 5656102670Sgibbs * Don't attempt to run any queued untagged transactions 5657102670Sgibbs * until we are done with the abort process. 5658102670Sgibbs */ 5659102670Sgibbs ahc_freeze_untagged_queues(ahc); 5660102670Sgibbs } 5661102670Sgibbs 5662102670Sgibbs found = 0; 566363457Sgibbs i = 0; 566465942Sgibbs if ((ahc->flags & AHC_SCB_BTT) == 0) { 566539220Sgibbs 566665942Sgibbs maxtarget = 16; 566765942Sgibbs if (target != CAM_TARGET_WILDCARD) { 566839220Sgibbs 566965942Sgibbs i = target; 567065942Sgibbs if (channel == 'B') 567165942Sgibbs i += 8; 567265942Sgibbs maxtarget = i + 1; 567363821Sgibbs } 567465942Sgibbs } else { 567565942Sgibbs maxtarget = 0; 567663457Sgibbs } 567739220Sgibbs 567865942Sgibbs for (; i < maxtarget; i++) { 567965942Sgibbs struct scb_tailq *untagged_q; 568065942Sgibbs struct scb *next_scb; 568139220Sgibbs 568265942Sgibbs untagged_q = &(ahc->untagged_queues[i]); 568365942Sgibbs next_scb = TAILQ_FIRST(untagged_q); 568465942Sgibbs while (next_scb != NULL) { 568539220Sgibbs 568665942Sgibbs scb = next_scb; 568765942Sgibbs next_scb = TAILQ_NEXT(scb, links.tqe); 568857099Sgibbs 568965942Sgibbs /* 569065942Sgibbs * The head of the list may be the currently 569165942Sgibbs * active untagged command for a device. 569265942Sgibbs * We're only searching for commands that 569365942Sgibbs * have not been started. A transaction 569465942Sgibbs * marked active but still in the qinfifo 569565942Sgibbs * is removed by the qinfifo scanning code 569665942Sgibbs * above. 569765942Sgibbs */ 569865942Sgibbs if ((scb->flags & SCB_ACTIVE) != 0) 569965942Sgibbs continue; 570039220Sgibbs 5701102670Sgibbs if (ahc_match_scb(ahc, scb, target, channel, lun, 5702102670Sgibbs SCB_LIST_NULL, ROLE_INITIATOR) == 0 5703102670Sgibbs || (ctx != NULL && ctx != scb->io_ctx)) 5704102670Sgibbs continue; 570565942Sgibbs 5706102670Sgibbs /* 5707102670Sgibbs * We found an scb that needs to be acted on. 5708102670Sgibbs */ 5709102670Sgibbs found++; 5710102670Sgibbs switch (action) { 5711102670Sgibbs case SEARCH_COMPLETE: 5712102670Sgibbs { 5713102670Sgibbs cam_status ostat; 5714102670Sgibbs cam_status cstat; 5715102670Sgibbs 5716123579Sgibbs ostat = aic_get_transaction_status(scb); 5717102670Sgibbs if (ostat == CAM_REQ_INPROG) 5718123579Sgibbs aic_set_transaction_status(scb, status); 5719123579Sgibbs cstat = aic_get_transaction_status(scb); 5720102670Sgibbs if (cstat != CAM_REQ_CMP) 5721123579Sgibbs aic_freeze_scb(scb); 5722102670Sgibbs ahc_done(ahc, scb); 5723102670Sgibbs break; 572439220Sgibbs } 5725102670Sgibbs case SEARCH_REMOVE: 5726102670Sgibbs scb->flags &= ~SCB_UNTAGGEDQ; 5727102670Sgibbs TAILQ_REMOVE(untagged_q, scb, links.tqe); 5728102670Sgibbs break; 5729102670Sgibbs case SEARCH_COUNT: 5730102670Sgibbs break; 5731102670Sgibbs } 573239220Sgibbs } 573339220Sgibbs } 573465942Sgibbs 573565942Sgibbs if (action == SEARCH_COMPLETE) 573665942Sgibbs ahc_release_untagged_queues(ahc); 573765942Sgibbs return (found); 573839220Sgibbs} 573939220Sgibbs 574065942Sgibbsint 574139506Sgibbsahc_search_disc_list(struct ahc_softc *ahc, int target, char channel, 574257099Sgibbs int lun, u_int tag, int stop_on_first, int remove, 574357099Sgibbs int save_state) 574439220Sgibbs{ 574539506Sgibbs struct scb *scbp; 574639506Sgibbs u_int next; 574739506Sgibbs u_int prev; 574839506Sgibbs u_int count; 574939506Sgibbs u_int active_scb; 575039220Sgibbs 575139506Sgibbs count = 0; 575239506Sgibbs next = ahc_inb(ahc, DISCONNECTED_SCBH); 575339506Sgibbs prev = SCB_LIST_NULL; 575439506Sgibbs 575557099Sgibbs if (save_state) { 575657099Sgibbs /* restore this when we're done */ 575757099Sgibbs active_scb = ahc_inb(ahc, SCBPTR); 575857099Sgibbs } else 575957099Sgibbs /* Silence compiler */ 576057099Sgibbs active_scb = SCB_LIST_NULL; 576139506Sgibbs 576239506Sgibbs while (next != SCB_LIST_NULL) { 576339506Sgibbs u_int scb_index; 576439506Sgibbs 576539506Sgibbs ahc_outb(ahc, SCBPTR, next); 576639506Sgibbs scb_index = ahc_inb(ahc, SCB_TAG); 576739506Sgibbs if (scb_index >= ahc->scb_data->numscbs) { 576868087Sgibbs printf("Disconnected List inconsistency. " 576968087Sgibbs "SCB index == %d, yet numscbs == %d.", 577068087Sgibbs scb_index, ahc->scb_data->numscbs); 577168087Sgibbs ahc_dump_card_state(ahc); 577268087Sgibbs panic("for safety"); 577339506Sgibbs } 577463457Sgibbs 577563457Sgibbs if (next == prev) { 577663457Sgibbs panic("Disconnected List Loop. " 577763457Sgibbs "cur SCBPTR == %x, prev SCBPTR == %x.", 577863457Sgibbs next, prev); 577963457Sgibbs } 578066647Sgibbs scbp = ahc_lookup_scb(ahc, scb_index); 578163457Sgibbs if (ahc_match_scb(ahc, scbp, target, channel, lun, 578249933Sgibbs tag, ROLE_INITIATOR)) { 578339506Sgibbs count++; 578457099Sgibbs if (remove) { 578557099Sgibbs next = 578657099Sgibbs ahc_rem_scb_from_disc_list(ahc, prev, next); 578757099Sgibbs } else { 578857099Sgibbs prev = next; 578957099Sgibbs next = ahc_inb(ahc, SCB_NEXT); 579057099Sgibbs } 579157099Sgibbs if (stop_on_first) 579257099Sgibbs break; 579339506Sgibbs } else { 579439506Sgibbs prev = next; 579539506Sgibbs next = ahc_inb(ahc, SCB_NEXT); 579639506Sgibbs } 579739506Sgibbs } 579857099Sgibbs if (save_state) 579957099Sgibbs ahc_outb(ahc, SCBPTR, active_scb); 580039506Sgibbs return (count); 580139506Sgibbs} 580239506Sgibbs 580365942Sgibbs/* 580465942Sgibbs * Remove an SCB from the on chip list of disconnected transactions. 580565942Sgibbs * This is empty/unused if we are not performing SCB paging. 580665942Sgibbs */ 580739506Sgibbsstatic u_int 580839506Sgibbsahc_rem_scb_from_disc_list(struct ahc_softc *ahc, u_int prev, u_int scbptr) 580939506Sgibbs{ 581039506Sgibbs u_int next; 581139506Sgibbs 581239220Sgibbs ahc_outb(ahc, SCBPTR, scbptr); 581339220Sgibbs next = ahc_inb(ahc, SCB_NEXT); 581439220Sgibbs 581539220Sgibbs ahc_outb(ahc, SCB_CONTROL, 0); 581639220Sgibbs 581739220Sgibbs ahc_add_curscb_to_free_list(ahc); 581839220Sgibbs 581939220Sgibbs if (prev != SCB_LIST_NULL) { 582039220Sgibbs ahc_outb(ahc, SCBPTR, prev); 582139220Sgibbs ahc_outb(ahc, SCB_NEXT, next); 582239220Sgibbs } else 582339220Sgibbs ahc_outb(ahc, DISCONNECTED_SCBH, next); 582439220Sgibbs 582549933Sgibbs return (next); 582639220Sgibbs} 582739220Sgibbs 582865942Sgibbs/* 582965942Sgibbs * Add the SCB as selected by SCBPTR onto the on chip list of 583065942Sgibbs * free hardware SCBs. This list is empty/unused if we are not 583165942Sgibbs * performing SCB paging. 583265942Sgibbs */ 583339220Sgibbsstatic void 583439220Sgibbsahc_add_curscb_to_free_list(struct ahc_softc *ahc) 583539220Sgibbs{ 583665942Sgibbs /* 583765942Sgibbs * Invalidate the tag so that our abort 583865942Sgibbs * routines don't think it's active. 583965942Sgibbs */ 584039220Sgibbs ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL); 584139220Sgibbs 584268087Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 584368087Sgibbs ahc_outb(ahc, SCB_NEXT, ahc_inb(ahc, FREE_SCBH)); 584468087Sgibbs ahc_outb(ahc, FREE_SCBH, ahc_inb(ahc, SCBPTR)); 584568087Sgibbs } 584639220Sgibbs} 584739220Sgibbs 584839220Sgibbs/* 584939220Sgibbs * Manipulate the waiting for selection list and return the 585039220Sgibbs * scb that follows the one that we remove. 585139220Sgibbs */ 585239506Sgibbsstatic u_int 585363457Sgibbsahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev) 585439220Sgibbs{ 585539506Sgibbs u_int curscb, next; 585639220Sgibbs 585739220Sgibbs /* 585839220Sgibbs * Select the SCB we want to abort and 585939220Sgibbs * pull the next pointer out of it. 586039220Sgibbs */ 586139220Sgibbs curscb = ahc_inb(ahc, SCBPTR); 586239220Sgibbs ahc_outb(ahc, SCBPTR, scbpos); 586339220Sgibbs next = ahc_inb(ahc, SCB_NEXT); 586439220Sgibbs 586539220Sgibbs /* Clear the necessary fields */ 586639220Sgibbs ahc_outb(ahc, SCB_CONTROL, 0); 586739220Sgibbs 586839220Sgibbs ahc_add_curscb_to_free_list(ahc); 586939220Sgibbs 587039220Sgibbs /* update the waiting list */ 587139220Sgibbs if (prev == SCB_LIST_NULL) { 587239220Sgibbs /* First in the list */ 587339220Sgibbs ahc_outb(ahc, WAITING_SCBH, next); 587439220Sgibbs 587539220Sgibbs /* 587639220Sgibbs * Ensure we aren't attempting to perform 587739220Sgibbs * selection for this entry. 587839220Sgibbs */ 587939220Sgibbs ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); 588039220Sgibbs } else { 588139220Sgibbs /* 588239220Sgibbs * Select the scb that pointed to us 588339220Sgibbs * and update its next pointer. 588439220Sgibbs */ 588539220Sgibbs ahc_outb(ahc, SCBPTR, prev); 588639220Sgibbs ahc_outb(ahc, SCB_NEXT, next); 588739220Sgibbs } 588839220Sgibbs 588939220Sgibbs /* 589039220Sgibbs * Point us back at the original scb position. 589139220Sgibbs */ 589239220Sgibbs ahc_outb(ahc, SCBPTR, curscb); 589339220Sgibbs return next; 589439220Sgibbs} 589539220Sgibbs 589665942Sgibbs/******************************** Error Handling ******************************/ 589765942Sgibbs/* 589865942Sgibbs * Abort all SCBs that match the given description (target/channel/lun/tag), 589965942Sgibbs * setting their status to the passed in status if the status has not already 590065942Sgibbs * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer 590165942Sgibbs * is paused before it is called. 590265942Sgibbs */ 590365942Sgibbsint 590465942Sgibbsahc_abort_scbs(struct ahc_softc *ahc, int target, char channel, 590565942Sgibbs int lun, u_int tag, role_t role, uint32_t status) 590639220Sgibbs{ 590765942Sgibbs struct scb *scbp; 590865942Sgibbs struct scb *scbp_next; 590965942Sgibbs u_int active_scb; 591066986Sgibbs int i, j; 591165942Sgibbs int maxtarget; 591266986Sgibbs int minlun; 591366986Sgibbs int maxlun; 591466986Sgibbs 591565942Sgibbs int found; 591665942Sgibbs 591765942Sgibbs /* 591865942Sgibbs * Don't attempt to run any queued untagged transactions 591965942Sgibbs * until we are done with the abort process. 592065942Sgibbs */ 592165942Sgibbs ahc_freeze_untagged_queues(ahc); 592265942Sgibbs 592365942Sgibbs /* restore this when we're done */ 592465942Sgibbs active_scb = ahc_inb(ahc, SCBPTR); 592565942Sgibbs 592665942Sgibbs found = ahc_search_qinfifo(ahc, target, channel, lun, SCB_LIST_NULL, 592765942Sgibbs role, CAM_REQUEUE_REQ, SEARCH_COMPLETE); 592865942Sgibbs 592965942Sgibbs /* 593065942Sgibbs * Clean out the busy target table for any untagged commands. 593165942Sgibbs */ 593265942Sgibbs i = 0; 593365942Sgibbs maxtarget = 16; 593465942Sgibbs if (target != CAM_TARGET_WILDCARD) { 593565942Sgibbs i = target; 593665942Sgibbs if (channel == 'B') 593765942Sgibbs i += 8; 593865942Sgibbs maxtarget = i + 1; 593965942Sgibbs } 594065942Sgibbs 594166986Sgibbs if (lun == CAM_LUN_WILDCARD) { 594265942Sgibbs 594366986Sgibbs /* 594466986Sgibbs * Unless we are using an SCB based 594566986Sgibbs * busy targets table, there is only 594666986Sgibbs * one table entry for all luns of 594766986Sgibbs * a target. 594866986Sgibbs */ 594966986Sgibbs minlun = 0; 595066986Sgibbs maxlun = 1; 595166986Sgibbs if ((ahc->flags & AHC_SCB_BTT) != 0) 595266986Sgibbs maxlun = AHC_NUM_LUNS; 595366986Sgibbs } else { 595466986Sgibbs minlun = lun; 595566986Sgibbs maxlun = lun + 1; 595666986Sgibbs } 595765942Sgibbs 595895378Sgibbs if (role != ROLE_TARGET) { 595995378Sgibbs for (;i < maxtarget; i++) { 596095378Sgibbs for (j = minlun;j < maxlun; j++) { 596195378Sgibbs u_int scbid; 596295378Sgibbs u_int tcl; 596395378Sgibbs 596495378Sgibbs tcl = BUILD_TCL(i << 4, j); 596595378Sgibbs scbid = ahc_index_busy_tcl(ahc, tcl); 596695378Sgibbs scbp = ahc_lookup_scb(ahc, scbid); 596795378Sgibbs if (scbp == NULL 596895378Sgibbs || ahc_match_scb(ahc, scbp, target, channel, 596995378Sgibbs lun, tag, role) == 0) 597095378Sgibbs continue; 597195378Sgibbs ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, j)); 597295378Sgibbs } 597395378Sgibbs } 597495378Sgibbs 597595378Sgibbs /* 597695378Sgibbs * Go through the disconnected list and remove any entries we 597795378Sgibbs * have queued for completion, 0'ing their control byte too. 597895378Sgibbs * We save the active SCB and restore it ourselves, so there 597995378Sgibbs * is no reason for this search to restore it too. 598095378Sgibbs */ 598195378Sgibbs ahc_search_disc_list(ahc, target, channel, lun, tag, 598295378Sgibbs /*stop_on_first*/FALSE, /*remove*/TRUE, 598395378Sgibbs /*save_state*/FALSE); 598465942Sgibbs } 598565942Sgibbs 598665942Sgibbs /* 598765942Sgibbs * Go through the hardware SCB array looking for commands that 598895378Sgibbs * were active but not on any list. In some cases, these remnants 598995378Sgibbs * might not still have mappings in the scbindex array (e.g. unexpected 599095378Sgibbs * bus free with the same scb queued for an abort). Don't hold this 599195378Sgibbs * against them. 599265942Sgibbs */ 599368087Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 599465942Sgibbs u_int scbid; 599565942Sgibbs 599665942Sgibbs ahc_outb(ahc, SCBPTR, i); 599765942Sgibbs scbid = ahc_inb(ahc, SCB_TAG); 599866647Sgibbs scbp = ahc_lookup_scb(ahc, scbid); 599995378Sgibbs if ((scbp == NULL && scbid != SCB_LIST_NULL) 600095378Sgibbs || (scbp != NULL 600195378Sgibbs && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role))) 600265942Sgibbs ahc_add_curscb_to_free_list(ahc); 600365942Sgibbs } 600465942Sgibbs 600565942Sgibbs /* 600665942Sgibbs * Go through the pending CCB list and look for 600765942Sgibbs * commands for this target that are still active. 600865942Sgibbs * These are other tagged commands that were 600976634Sgibbs * disconnected when the reset occurred. 601065942Sgibbs */ 601165942Sgibbs scbp_next = LIST_FIRST(&ahc->pending_scbs); 601265942Sgibbs while (scbp_next != NULL) { 601365942Sgibbs scbp = scbp_next; 601465942Sgibbs scbp_next = LIST_NEXT(scbp, pending_links); 601565942Sgibbs if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) { 601665942Sgibbs cam_status ostat; 601765942Sgibbs 6018123579Sgibbs ostat = aic_get_transaction_status(scbp); 601965942Sgibbs if (ostat == CAM_REQ_INPROG) 6020123579Sgibbs aic_set_transaction_status(scbp, status); 6021123579Sgibbs if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) 6022123579Sgibbs aic_freeze_scb(scbp); 602365942Sgibbs if ((scbp->flags & SCB_ACTIVE) == 0) 602465942Sgibbs printf("Inactive SCB on pending list\n"); 602565942Sgibbs ahc_done(ahc, scbp); 602665942Sgibbs found++; 602765942Sgibbs } 602865942Sgibbs } 602965942Sgibbs ahc_outb(ahc, SCBPTR, active_scb); 603065942Sgibbs ahc_platform_abort_scbs(ahc, target, channel, lun, tag, role, status); 603165942Sgibbs ahc_release_untagged_queues(ahc); 603265942Sgibbs return found; 603339220Sgibbs} 603439220Sgibbs 603539220Sgibbsstatic void 603639220Sgibbsahc_reset_current_bus(struct ahc_softc *ahc) 603739220Sgibbs{ 603863457Sgibbs uint8_t scsiseq; 603939220Sgibbs 604039220Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST); 604139220Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ); 604239220Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO); 604395378Sgibbs ahc_flush_device_writes(ahc); 6044123579Sgibbs aic_delay(AHC_BUSRESET_DELAY); 604539220Sgibbs /* Turn off the bus reset */ 604639220Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO); 604739220Sgibbs 604839220Sgibbs ahc_clear_intstat(ahc); 604939220Sgibbs 605039220Sgibbs /* Re-enable reset interrupts */ 605139220Sgibbs ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST); 605239220Sgibbs} 605339220Sgibbs 605465942Sgibbsint 605539220Sgibbsahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset) 605639220Sgibbs{ 605765942Sgibbs struct ahc_devinfo devinfo; 605844507Sgibbs u_int initiator, target, max_scsiid; 605944507Sgibbs u_int sblkctl; 606079874Sgibbs u_int scsiseq; 606179874Sgibbs u_int simode1; 606244507Sgibbs int found; 606349933Sgibbs int restart_needed; 606444507Sgibbs char cur_channel; 606539220Sgibbs 606644507Sgibbs ahc->pending_device = NULL; 606744507Sgibbs 606865942Sgibbs ahc_compile_devinfo(&devinfo, 606965942Sgibbs CAM_TARGET_WILDCARD, 607065942Sgibbs CAM_TARGET_WILDCARD, 607165942Sgibbs CAM_LUN_WILDCARD, 607265942Sgibbs channel, ROLE_UNKNOWN); 607374094Sgibbs ahc_pause(ahc); 607449933Sgibbs 607566647Sgibbs /* Make sure the sequencer is in a safe location. */ 607666647Sgibbs ahc_clear_critical_section(ahc); 607766647Sgibbs 607839220Sgibbs /* 607949933Sgibbs * Run our command complete fifos to ensure that we perform 608049933Sgibbs * completion processing on any commands that 'completed' 608149933Sgibbs * before the reset occurred. 608249933Sgibbs */ 608349933Sgibbs ahc_run_qoutfifo(ahc); 6084115337Sgibbs#ifdef AHC_TARGET_MODE 608595378Sgibbs /* 608695378Sgibbs * XXX - In Twin mode, the tqinfifo may have commands 608795378Sgibbs * for an unaffected channel in it. However, if 608895378Sgibbs * we have run out of ATIO resources to drain that 608995378Sgibbs * queue, we may not get them all out here. Further, 609095378Sgibbs * the blocked transactions for the reset channel 609195378Sgibbs * should just be killed off, irrespecitve of whether 609295378Sgibbs * we are blocked on ATIO resources. Write a routine 609395378Sgibbs * to compact the tqinfifo appropriately. 609495378Sgibbs */ 609568087Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 609655581Sgibbs ahc_run_tqinfifo(ahc, /*paused*/TRUE); 609749933Sgibbs } 609865942Sgibbs#endif 609949933Sgibbs 610049933Sgibbs /* 610149933Sgibbs * Reset the bus if we are initiating this reset 610249933Sgibbs */ 610349933Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 610449933Sgibbs cur_channel = 'A'; 610549933Sgibbs if ((ahc->features & AHC_TWIN) != 0 610649933Sgibbs && ((sblkctl & SELBUSB) != 0)) 610749933Sgibbs cur_channel = 'B'; 610879874Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); 610949933Sgibbs if (cur_channel != channel) { 611049933Sgibbs /* Case 1: Command for another bus is active 611149933Sgibbs * Stealthily reset the other bus without 611249933Sgibbs * upsetting the current bus. 611349933Sgibbs */ 611449933Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB); 611579874Sgibbs simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); 6116115337Sgibbs#ifdef AHC_TARGET_MODE 611779874Sgibbs /* 611879874Sgibbs * Bus resets clear ENSELI, so we cannot 611979874Sgibbs * defer re-enabling bus reset interrupts 612079874Sgibbs * if we are in target mode. 612179874Sgibbs */ 612279874Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) 612395378Sgibbs simode1 |= ENSCSIRST; 612479874Sgibbs#endif 612595378Sgibbs ahc_outb(ahc, SIMODE1, simode1); 612695378Sgibbs if (initiate_reset) 612795378Sgibbs ahc_reset_current_bus(ahc); 612895378Sgibbs ahc_clear_intstat(ahc); 612979874Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); 613049933Sgibbs ahc_outb(ahc, SBLKCTL, sblkctl); 613149933Sgibbs restart_needed = FALSE; 613249933Sgibbs } else { 613349933Sgibbs /* Case 2: A command from this bus is active or we're idle */ 613479874Sgibbs simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); 6135115337Sgibbs#ifdef AHC_TARGET_MODE 613679874Sgibbs /* 613779874Sgibbs * Bus resets clear ENSELI, so we cannot 613879874Sgibbs * defer re-enabling bus reset interrupts 613979874Sgibbs * if we are in target mode. 614079874Sgibbs */ 614179874Sgibbs if ((ahc->flags & AHC_TARGETROLE) != 0) 614295378Sgibbs simode1 |= ENSCSIRST; 614379874Sgibbs#endif 614495378Sgibbs ahc_outb(ahc, SIMODE1, simode1); 614595378Sgibbs if (initiate_reset) 614695378Sgibbs ahc_reset_current_bus(ahc); 614795378Sgibbs ahc_clear_intstat(ahc); 614879874Sgibbs ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); 614949933Sgibbs restart_needed = TRUE; 615049933Sgibbs } 615149933Sgibbs 615249933Sgibbs /* 615339220Sgibbs * Clean up all the state information for the 615439220Sgibbs * pending transactions on this bus. 615539220Sgibbs */ 615641646Sgibbs found = ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, channel, 615741646Sgibbs CAM_LUN_WILDCARD, SCB_LIST_NULL, 615849933Sgibbs ROLE_UNKNOWN, CAM_SCSI_BUS_RESET); 615939220Sgibbs 616049933Sgibbs max_scsiid = (ahc->features & AHC_WIDE) ? 15 : 7; 616149933Sgibbs 616265942Sgibbs#ifdef AHC_TARGET_MODE 616349933Sgibbs /* 616449933Sgibbs * Send an immediate notify ccb to all target more peripheral 616549933Sgibbs * drivers affected by this action. 616649933Sgibbs */ 616749933Sgibbs for (target = 0; target <= max_scsiid; target++) { 616874972Sgibbs struct ahc_tmode_tstate* tstate; 616949933Sgibbs u_int lun; 617049933Sgibbs 617149933Sgibbs tstate = ahc->enabled_targets[target]; 617249933Sgibbs if (tstate == NULL) 617349933Sgibbs continue; 617470204Sgibbs for (lun = 0; lun < AHC_NUM_LUNS; lun++) { 617574972Sgibbs struct ahc_tmode_lstate* lstate; 617649933Sgibbs 617749933Sgibbs lstate = tstate->enabled_luns[lun]; 617849933Sgibbs if (lstate == NULL) 617949933Sgibbs continue; 618049933Sgibbs 618149933Sgibbs ahc_queue_lstate_event(ahc, lstate, CAM_TARGET_WILDCARD, 618249933Sgibbs EVENT_TYPE_BUS_RESET, /*arg*/0); 618349933Sgibbs ahc_send_lstate_events(ahc, lstate); 618449933Sgibbs } 618549933Sgibbs } 618665942Sgibbs#endif 618739220Sgibbs /* Notify the XPT that a bus reset occurred */ 618866269Sgibbs ahc_send_async(ahc, devinfo.channel, CAM_TARGET_WILDCARD, 618976634Sgibbs CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); 619039220Sgibbs 619139220Sgibbs /* 619239220Sgibbs * Revert to async/narrow transfers until we renegotiate. 619339220Sgibbs */ 619444507Sgibbs for (target = 0; target <= max_scsiid; target++) { 619539220Sgibbs 619644507Sgibbs if (ahc->enabled_targets[target] == NULL) 619744507Sgibbs continue; 619844507Sgibbs for (initiator = 0; initiator <= max_scsiid; initiator++) { 619944507Sgibbs struct ahc_devinfo devinfo; 620044507Sgibbs 620144507Sgibbs ahc_compile_devinfo(&devinfo, target, initiator, 620244507Sgibbs CAM_LUN_WILDCARD, 620344507Sgibbs channel, ROLE_UNKNOWN); 620465942Sgibbs ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 620547287Sgibbs AHC_TRANS_CUR, /*paused*/TRUE); 620665942Sgibbs ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, 620765942Sgibbs /*period*/0, /*offset*/0, 620865942Sgibbs /*ppr_options*/0, AHC_TRANS_CUR, 620965942Sgibbs /*paused*/TRUE); 621044507Sgibbs } 621139220Sgibbs } 621239220Sgibbs 621349933Sgibbs if (restart_needed) 621474094Sgibbs ahc_restart(ahc); 621549933Sgibbs else 621674094Sgibbs ahc_unpause(ahc); 621739220Sgibbs return found; 621839220Sgibbs} 621939220Sgibbs 622039220Sgibbs 622165942Sgibbs/***************************** Residual Processing ****************************/ 622265942Sgibbs/* 622365942Sgibbs * Calculate the residual for a just completed SCB. 622465942Sgibbs */ 622576634Sgibbsvoid 622695378Sgibbsahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) 622739220Sgibbs{ 622863457Sgibbs struct hardware_scb *hscb; 622963457Sgibbs struct status_pkt *spkt; 623070693Sgibbs uint32_t sgptr; 623170693Sgibbs uint32_t resid_sgptr; 623263457Sgibbs uint32_t resid; 623339220Sgibbs 623463457Sgibbs /* 623563854Sgibbs * 5 cases. 623663457Sgibbs * 1) No residual. 623763457Sgibbs * SG_RESID_VALID clear in sgptr. 623863457Sgibbs * 2) Transferless command 623963457Sgibbs * 3) Never performed any transfers. 624063457Sgibbs * sgptr has SG_FULL_RESID set. 624163854Sgibbs * 4) No residual but target did not 624263854Sgibbs * save data pointers after the 624363854Sgibbs * last transfer, so sgptr was 624463854Sgibbs * never updated. 624563854Sgibbs * 5) We have a partial residual. 624663457Sgibbs * Use residual_sgptr to determine 624763457Sgibbs * where we are. 624863457Sgibbs */ 624963457Sgibbs 625039220Sgibbs hscb = scb->hscb; 6251123579Sgibbs sgptr = aic_le32toh(hscb->sgptr); 625270693Sgibbs if ((sgptr & SG_RESID_VALID) == 0) 625363854Sgibbs /* Case 1 */ 625463457Sgibbs return; 625570693Sgibbs sgptr &= ~SG_RESID_VALID; 625639220Sgibbs 625770693Sgibbs if ((sgptr & SG_LIST_NULL) != 0) 625863854Sgibbs /* Case 2 */ 625963457Sgibbs return; 626063457Sgibbs 626163457Sgibbs spkt = &hscb->shared_data.status; 6262123579Sgibbs resid_sgptr = aic_le32toh(spkt->residual_sg_ptr); 626370693Sgibbs if ((sgptr & SG_FULL_RESID) != 0) { 626463854Sgibbs /* Case 3 */ 6265123579Sgibbs resid = aic_get_transfer_length(scb); 626670693Sgibbs } else if ((resid_sgptr & SG_LIST_NULL) != 0) { 626763854Sgibbs /* Case 4 */ 626863854Sgibbs return; 626970693Sgibbs } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) { 627070693Sgibbs panic("Bogus resid sgptr value 0x%x\n", resid_sgptr); 6271141978Sgibbs /* NOTREACHED */ 6272141978Sgibbs return; 627365942Sgibbs } else { 627463457Sgibbs struct ahc_dma_seg *sg; 627563457Sgibbs 627639220Sgibbs /* 627739220Sgibbs * Remainder of the SG where the transfer 627863457Sgibbs * stopped. 627939220Sgibbs */ 6280123579Sgibbs resid = aic_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; 628170693Sgibbs sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK); 628239220Sgibbs 628363457Sgibbs /* The residual sg_ptr always points to the next sg */ 628463457Sgibbs sg--; 628563457Sgibbs 628639220Sgibbs /* 628739220Sgibbs * Add up the contents of all residual 628839220Sgibbs * SG segments that are after the SG where 628939220Sgibbs * the transfer stopped. 629039220Sgibbs */ 6291123579Sgibbs while ((aic_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { 629239220Sgibbs sg++; 6293123579Sgibbs resid += aic_le32toh(sg->len) & AHC_SG_LEN_MASK; 629439220Sgibbs } 629563457Sgibbs } 629665942Sgibbs if ((scb->flags & SCB_SENSE) == 0) 6297123579Sgibbs aic_set_residual(scb, resid); 629865942Sgibbs else 6299123579Sgibbs aic_set_sense_residual(scb, resid); 630039220Sgibbs 630158258Sgibbs#ifdef AHC_DEBUG 6302102670Sgibbs if ((ahc_debug & AHC_SHOW_MISC) != 0) { 630365942Sgibbs ahc_print_path(ahc, scb); 6304109590Sgibbs printf("Handled %sResidual of %d bytes\n", 6305109590Sgibbs (scb->flags & SCB_SENSE) ? "Sense " : "", resid); 630663457Sgibbs } 630758258Sgibbs#endif 630839220Sgibbs} 630939220Sgibbs 631065942Sgibbs/******************************* Target Mode **********************************/ 631165942Sgibbs#ifdef AHC_TARGET_MODE 631249933Sgibbs/* 631349933Sgibbs * Add a target mode event to this lun's queue 631449933Sgibbs */ 631549933Sgibbsstatic void 631674972Sgibbsahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate, 631749933Sgibbs u_int initiator_id, u_int event_type, u_int event_arg) 631849933Sgibbs{ 631949933Sgibbs struct ahc_tmode_event *event; 632049933Sgibbs int pending; 632149933Sgibbs 632249933Sgibbs xpt_freeze_devq(lstate->path, /*count*/1); 632349933Sgibbs if (lstate->event_w_idx >= lstate->event_r_idx) 632449933Sgibbs pending = lstate->event_w_idx - lstate->event_r_idx; 632549933Sgibbs else 632649933Sgibbs pending = AHC_TMODE_EVENT_BUFFER_SIZE + 1 632749933Sgibbs - (lstate->event_r_idx - lstate->event_w_idx); 632849933Sgibbs 632949933Sgibbs if (event_type == EVENT_TYPE_BUS_RESET 633049933Sgibbs || event_type == MSG_BUS_DEV_RESET) { 633149933Sgibbs /* 633249933Sgibbs * Any earlier events are irrelevant, so reset our buffer. 633349933Sgibbs * This has the effect of allowing us to deal with reset 633449933Sgibbs * floods (an external device holding down the reset line) 633549933Sgibbs * without losing the event that is really interesting. 633649933Sgibbs */ 633749933Sgibbs lstate->event_r_idx = 0; 633849933Sgibbs lstate->event_w_idx = 0; 633949933Sgibbs xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE); 634049933Sgibbs } 634149933Sgibbs 634249933Sgibbs if (pending == AHC_TMODE_EVENT_BUFFER_SIZE) { 634349933Sgibbs xpt_print_path(lstate->path); 634449933Sgibbs printf("immediate event %x:%x lost\n", 634549933Sgibbs lstate->event_buffer[lstate->event_r_idx].event_type, 634649933Sgibbs lstate->event_buffer[lstate->event_r_idx].event_arg); 634749933Sgibbs lstate->event_r_idx++; 634849933Sgibbs if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE) 634949933Sgibbs lstate->event_r_idx = 0; 635049933Sgibbs xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE); 635149933Sgibbs } 635249933Sgibbs 635349933Sgibbs event = &lstate->event_buffer[lstate->event_w_idx]; 635449933Sgibbs event->initiator_id = initiator_id; 635549933Sgibbs event->event_type = event_type; 635649933Sgibbs event->event_arg = event_arg; 635749933Sgibbs lstate->event_w_idx++; 635849933Sgibbs if (lstate->event_w_idx == AHC_TMODE_EVENT_BUFFER_SIZE) 635949933Sgibbs lstate->event_w_idx = 0; 636049933Sgibbs} 636149933Sgibbs 636249933Sgibbs/* 636349933Sgibbs * Send any target mode events queued up waiting 636449933Sgibbs * for immediate notify resources. 636549933Sgibbs */ 636665942Sgibbsvoid 636774972Sgibbsahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate) 636849933Sgibbs{ 636949933Sgibbs struct ccb_hdr *ccbh; 6370237601Sken struct ccb_immediate_notify *inot; 637149933Sgibbs 637249933Sgibbs while (lstate->event_r_idx != lstate->event_w_idx 637349933Sgibbs && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) { 637449933Sgibbs struct ahc_tmode_event *event; 637549933Sgibbs 637649933Sgibbs event = &lstate->event_buffer[lstate->event_r_idx]; 637749933Sgibbs SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle); 6378237601Sken inot = (struct ccb_immediate_notify *)ccbh; 637949933Sgibbs switch (event->event_type) { 638049933Sgibbs case EVENT_TYPE_BUS_RESET: 638149933Sgibbs ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN; 638249933Sgibbs break; 638349933Sgibbs default: 638449933Sgibbs ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; 6385237601Sken inot->arg = event->event_type; 6386237601Sken inot->seq_id = event->event_arg; 638749933Sgibbs break; 638849933Sgibbs } 638949933Sgibbs inot->initiator_id = event->initiator_id; 639049933Sgibbs xpt_done((union ccb *)inot); 639149933Sgibbs lstate->event_r_idx++; 639249933Sgibbs if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE) 639349933Sgibbs lstate->event_r_idx = 0; 639449933Sgibbs } 639549933Sgibbs} 639665942Sgibbs#endif 639765942Sgibbs 639865942Sgibbs/******************** Sequencer Program Patching/Download *********************/ 639965942Sgibbs 640065942Sgibbs#ifdef AHC_DUMP_SEQ 640165942Sgibbsvoid 640265942Sgibbsahc_dumpseq(struct ahc_softc* ahc) 640365942Sgibbs{ 640465942Sgibbs int i; 640565942Sgibbs 640665942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); 640765942Sgibbs ahc_outb(ahc, SEQADDR0, 0); 640865942Sgibbs ahc_outb(ahc, SEQADDR1, 0); 6409114621Sgibbs for (i = 0; i < ahc->instruction_ram_size; i++) { 641065942Sgibbs uint8_t ins_bytes[4]; 641165942Sgibbs 641265942Sgibbs ahc_insb(ahc, SEQRAM, ins_bytes, 4); 641365942Sgibbs printf("0x%08x\n", ins_bytes[0] << 24 641465942Sgibbs | ins_bytes[1] << 16 641565942Sgibbs | ins_bytes[2] << 8 641665942Sgibbs | ins_bytes[3]); 641765942Sgibbs } 641865942Sgibbs} 641965942Sgibbs#endif 642065942Sgibbs 6421114621Sgibbsstatic int 642265942Sgibbsahc_loadseq(struct ahc_softc *ahc) 642365942Sgibbs{ 642466647Sgibbs struct cs cs_table[num_critical_sections]; 642566845Sgibbs u_int begin_set[num_critical_sections]; 642666845Sgibbs u_int end_set[num_critical_sections]; 642766647Sgibbs struct patch *cur_patch; 642866845Sgibbs u_int cs_count; 642966647Sgibbs u_int cur_cs; 643066647Sgibbs u_int i; 643166647Sgibbs u_int skip_addr; 643266647Sgibbs u_int sg_prefetch_cnt; 6433114621Sgibbs int downloaded; 643466647Sgibbs uint8_t download_consts[7]; 643565942Sgibbs 643666647Sgibbs /* 643766647Sgibbs * Start out with 0 critical sections 643866647Sgibbs * that apply to this firmware load. 643966647Sgibbs */ 644066845Sgibbs cs_count = 0; 644166647Sgibbs cur_cs = 0; 644266845Sgibbs memset(begin_set, 0, sizeof(begin_set)); 644366845Sgibbs memset(end_set, 0, sizeof(end_set)); 644466647Sgibbs 644565942Sgibbs /* Setup downloadable constant table */ 644665942Sgibbs download_consts[QOUTFIFO_OFFSET] = 0; 644765942Sgibbs if (ahc->targetcmds != NULL) 644865942Sgibbs download_consts[QOUTFIFO_OFFSET] += 32; 644965942Sgibbs download_consts[QINFIFO_OFFSET] = download_consts[QOUTFIFO_OFFSET] + 1; 645065942Sgibbs download_consts[CACHESIZE_MASK] = ahc->pci_cachesize - 1; 645165942Sgibbs download_consts[INVERTED_CACHESIZE_MASK] = ~(ahc->pci_cachesize - 1); 645266647Sgibbs sg_prefetch_cnt = ahc->pci_cachesize; 645366647Sgibbs if (sg_prefetch_cnt < (2 * sizeof(struct ahc_dma_seg))) 645466647Sgibbs sg_prefetch_cnt = 2 * sizeof(struct ahc_dma_seg); 645566647Sgibbs download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt; 645666647Sgibbs download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_cnt - 1); 645766647Sgibbs download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_cnt - 1); 645865942Sgibbs 645965942Sgibbs cur_patch = patches; 646065942Sgibbs downloaded = 0; 646165942Sgibbs skip_addr = 0; 646265942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); 646365942Sgibbs ahc_outb(ahc, SEQADDR0, 0); 646465942Sgibbs ahc_outb(ahc, SEQADDR1, 0); 646565942Sgibbs 646665942Sgibbs for (i = 0; i < sizeof(seqprog)/4; i++) { 646765942Sgibbs if (ahc_check_patch(ahc, &cur_patch, i, &skip_addr) == 0) { 646865942Sgibbs /* 646965942Sgibbs * Don't download this instruction as it 647065942Sgibbs * is in a patch that was removed. 647165942Sgibbs */ 647265942Sgibbs continue; 647365942Sgibbs } 6474114621Sgibbs 6475114621Sgibbs if (downloaded == ahc->instruction_ram_size) { 6476114621Sgibbs /* 6477114621Sgibbs * We're about to exceed the instruction 6478114621Sgibbs * storage capacity for this chip. Fail 6479114621Sgibbs * the load. 6480114621Sgibbs */ 6481114621Sgibbs printf("\n%s: Program too large for instruction memory " 6482114621Sgibbs "size of %d!\n", ahc_name(ahc), 6483114621Sgibbs ahc->instruction_ram_size); 6484114621Sgibbs return (ENOMEM); 6485114621Sgibbs } 6486114621Sgibbs 648766647Sgibbs /* 648866647Sgibbs * Move through the CS table until we find a CS 648966647Sgibbs * that might apply to this instruction. 649066647Sgibbs */ 649166647Sgibbs for (; cur_cs < num_critical_sections; cur_cs++) { 649266845Sgibbs if (critical_sections[cur_cs].end <= i) { 649366845Sgibbs if (begin_set[cs_count] == TRUE 649466845Sgibbs && end_set[cs_count] == FALSE) { 649566845Sgibbs cs_table[cs_count].end = downloaded; 649666845Sgibbs end_set[cs_count] = TRUE; 649766845Sgibbs cs_count++; 649866647Sgibbs } 649966845Sgibbs continue; 650066647Sgibbs } 650166845Sgibbs if (critical_sections[cur_cs].begin <= i 650266845Sgibbs && begin_set[cs_count] == FALSE) { 650366845Sgibbs cs_table[cs_count].begin = downloaded; 650466845Sgibbs begin_set[cs_count] = TRUE; 650566845Sgibbs } 650666845Sgibbs break; 650766647Sgibbs } 650865942Sgibbs ahc_download_instr(ahc, i, download_consts); 650965942Sgibbs downloaded++; 651065942Sgibbs } 651166647Sgibbs 651266845Sgibbs ahc->num_critical_sections = cs_count; 651366845Sgibbs if (cs_count != 0) { 651466647Sgibbs 651566845Sgibbs cs_count *= sizeof(struct cs); 651666845Sgibbs ahc->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT); 651766647Sgibbs if (ahc->critical_sections == NULL) 651866647Sgibbs panic("ahc_loadseq: Could not malloc"); 651966845Sgibbs memcpy(ahc->critical_sections, cs_table, cs_count); 652066647Sgibbs } 652165942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE); 652265942Sgibbs 6523109590Sgibbs if (bootverbose) { 652465942Sgibbs printf(" %d instructions downloaded\n", downloaded); 6525109590Sgibbs printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", 6526109590Sgibbs ahc_name(ahc), ahc->features, ahc->bugs, ahc->flags); 6527109590Sgibbs } 6528114621Sgibbs return (0); 652965942Sgibbs} 653065942Sgibbs 653165942Sgibbsstatic int 653265942Sgibbsahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch, 653365942Sgibbs u_int start_instr, u_int *skip_addr) 653465942Sgibbs{ 653565942Sgibbs struct patch *cur_patch; 653665942Sgibbs struct patch *last_patch; 653765942Sgibbs u_int num_patches; 653865942Sgibbs 653965942Sgibbs num_patches = sizeof(patches)/sizeof(struct patch); 654065942Sgibbs last_patch = &patches[num_patches]; 654165942Sgibbs cur_patch = *start_patch; 654265942Sgibbs 654365942Sgibbs while (cur_patch < last_patch && start_instr == cur_patch->begin) { 654465942Sgibbs 654565942Sgibbs if (cur_patch->patch_func(ahc) == 0) { 654665942Sgibbs 654765942Sgibbs /* Start rejecting code */ 654865942Sgibbs *skip_addr = start_instr + cur_patch->skip_instr; 654965942Sgibbs cur_patch += cur_patch->skip_patch; 655065942Sgibbs } else { 655165942Sgibbs /* Accepted this patch. Advance to the next 6552300060Spfg * one and wait for our instruction pointer to 655365942Sgibbs * hit this point. 655465942Sgibbs */ 655565942Sgibbs cur_patch++; 655665942Sgibbs } 655765942Sgibbs } 655865942Sgibbs 655965942Sgibbs *start_patch = cur_patch; 656065942Sgibbs if (start_instr < *skip_addr) 656165942Sgibbs /* Still skipping */ 656265942Sgibbs return (0); 656365942Sgibbs 656465942Sgibbs return (1); 656565942Sgibbs} 656665942Sgibbs 656765942Sgibbsstatic void 656865942Sgibbsahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) 656965942Sgibbs{ 657065942Sgibbs union ins_formats instr; 657165942Sgibbs struct ins_format1 *fmt1_ins; 657265942Sgibbs struct ins_format3 *fmt3_ins; 657365942Sgibbs u_int opcode; 657465942Sgibbs 657570693Sgibbs /* 657670693Sgibbs * The firmware is always compiled into a little endian format. 657770693Sgibbs */ 6578123579Sgibbs instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); 657965942Sgibbs 658065942Sgibbs fmt1_ins = &instr.format1; 658165942Sgibbs fmt3_ins = NULL; 658265942Sgibbs 658365942Sgibbs /* Pull the opcode */ 658465942Sgibbs opcode = instr.format1.opcode; 658565942Sgibbs switch (opcode) { 658665942Sgibbs case AIC_OP_JMP: 658765942Sgibbs case AIC_OP_JC: 658865942Sgibbs case AIC_OP_JNC: 658965942Sgibbs case AIC_OP_CALL: 659065942Sgibbs case AIC_OP_JNE: 659165942Sgibbs case AIC_OP_JNZ: 659265942Sgibbs case AIC_OP_JE: 659365942Sgibbs case AIC_OP_JZ: 659465942Sgibbs { 659565942Sgibbs struct patch *cur_patch; 659665942Sgibbs int address_offset; 659765942Sgibbs u_int address; 659865942Sgibbs u_int skip_addr; 659965942Sgibbs u_int i; 660065942Sgibbs 660165942Sgibbs fmt3_ins = &instr.format3; 660265942Sgibbs address_offset = 0; 660365942Sgibbs address = fmt3_ins->address; 660465942Sgibbs cur_patch = patches; 660565942Sgibbs skip_addr = 0; 660665942Sgibbs 660765942Sgibbs for (i = 0; i < address;) { 660865942Sgibbs 660965942Sgibbs ahc_check_patch(ahc, &cur_patch, i, &skip_addr); 661065942Sgibbs 661165942Sgibbs if (skip_addr > i) { 661265942Sgibbs int end_addr; 661365942Sgibbs 661465942Sgibbs end_addr = MIN(address, skip_addr); 661565942Sgibbs address_offset += end_addr - i; 661665942Sgibbs i = skip_addr; 661765942Sgibbs } else { 661865942Sgibbs i++; 661965942Sgibbs } 662065942Sgibbs } 662165942Sgibbs address -= address_offset; 662265942Sgibbs fmt3_ins->address = address; 662365942Sgibbs /* FALLTHROUGH */ 662465942Sgibbs } 662565942Sgibbs case AIC_OP_OR: 662665942Sgibbs case AIC_OP_AND: 662765942Sgibbs case AIC_OP_XOR: 662865942Sgibbs case AIC_OP_ADD: 662965942Sgibbs case AIC_OP_ADC: 663065942Sgibbs case AIC_OP_BMOV: 663165942Sgibbs if (fmt1_ins->parity != 0) { 663265942Sgibbs fmt1_ins->immediate = dconsts[fmt1_ins->immediate]; 663365942Sgibbs } 663465942Sgibbs fmt1_ins->parity = 0; 663568087Sgibbs if ((ahc->features & AHC_CMD_CHAN) == 0 663668087Sgibbs && opcode == AIC_OP_BMOV) { 663768087Sgibbs /* 663868087Sgibbs * Block move was added at the same time 663968087Sgibbs * as the command channel. Verify that 664068087Sgibbs * this is only a move of a single element 664168087Sgibbs * and convert the BMOV to a MOV 664268087Sgibbs * (AND with an immediate of FF). 664368087Sgibbs */ 664468087Sgibbs if (fmt1_ins->immediate != 1) 664568087Sgibbs panic("%s: BMOV not supported\n", 664668087Sgibbs ahc_name(ahc)); 664768087Sgibbs fmt1_ins->opcode = AIC_OP_AND; 664868087Sgibbs fmt1_ins->immediate = 0xff; 664968087Sgibbs } 665065942Sgibbs /* FALLTHROUGH */ 665165942Sgibbs case AIC_OP_ROL: 665265942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 665365942Sgibbs int i, count; 665465942Sgibbs 665565942Sgibbs /* Calculate odd parity for the instruction */ 665665942Sgibbs for (i = 0, count = 0; i < 31; i++) { 665765942Sgibbs uint32_t mask; 665865942Sgibbs 665965942Sgibbs mask = 0x01 << i; 666065942Sgibbs if ((instr.integer & mask) != 0) 666165942Sgibbs count++; 666265942Sgibbs } 666365942Sgibbs if ((count & 0x01) == 0) 666465942Sgibbs instr.format1.parity = 1; 666565942Sgibbs } else { 666665942Sgibbs /* Compress the instruction for older sequencers */ 666765942Sgibbs if (fmt3_ins != NULL) { 666865942Sgibbs instr.integer = 666965942Sgibbs fmt3_ins->immediate 667065942Sgibbs | (fmt3_ins->source << 8) 667165942Sgibbs | (fmt3_ins->address << 16) 667265942Sgibbs | (fmt3_ins->opcode << 25); 667365942Sgibbs } else { 667465942Sgibbs instr.integer = 667565942Sgibbs fmt1_ins->immediate 667665942Sgibbs | (fmt1_ins->source << 8) 667765942Sgibbs | (fmt1_ins->destination << 16) 667865942Sgibbs | (fmt1_ins->ret << 24) 667965942Sgibbs | (fmt1_ins->opcode << 25); 668065942Sgibbs } 668165942Sgibbs } 668270693Sgibbs /* The sequencer is a little endian cpu */ 6683123579Sgibbs instr.integer = aic_htole32(instr.integer); 668465942Sgibbs ahc_outsb(ahc, SEQRAM, instr.bytes, 4); 668565942Sgibbs break; 668665942Sgibbs default: 668765942Sgibbs panic("Unknown opcode encountered in seq program"); 668865942Sgibbs break; 668965942Sgibbs } 669065942Sgibbs} 669165942Sgibbs 6692102670Sgibbsint 6693102670Sgibbsahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries, 6694102670Sgibbs const char *name, u_int address, u_int value, 6695102670Sgibbs u_int *cur_column, u_int wrap_point) 6696102670Sgibbs{ 6697102670Sgibbs int printed; 6698102670Sgibbs u_int printed_mask; 6699141999Sgibbs u_int dummy_column; 6700102670Sgibbs 6701141999Sgibbs if (cur_column == NULL) { 6702141999Sgibbs dummy_column = 0; 6703141999Sgibbs cur_column = &dummy_column; 6704141999Sgibbs } 6705141999Sgibbs 6706144370Ssam if (*cur_column >= wrap_point) { 6707102670Sgibbs printf("\n"); 6708102670Sgibbs *cur_column = 0; 6709102670Sgibbs } 6710102670Sgibbs printed = printf("%s[0x%x]", name, value); 6711102670Sgibbs if (table == NULL) { 6712102670Sgibbs printed += printf(" "); 6713102670Sgibbs *cur_column += printed; 6714102670Sgibbs return (printed); 6715102670Sgibbs } 6716102670Sgibbs printed_mask = 0; 6717102670Sgibbs while (printed_mask != 0xFF) { 6718102670Sgibbs int entry; 6719102670Sgibbs 6720102670Sgibbs for (entry = 0; entry < num_entries; entry++) { 6721102670Sgibbs if (((value & table[entry].mask) 6722102670Sgibbs != table[entry].value) 6723102670Sgibbs || ((printed_mask & table[entry].mask) 6724102670Sgibbs == table[entry].mask)) 6725102670Sgibbs continue; 6726102670Sgibbs 6727102670Sgibbs printed += printf("%s%s", 6728102670Sgibbs printed_mask == 0 ? ":(" : "|", 6729102670Sgibbs table[entry].name); 6730102670Sgibbs printed_mask |= table[entry].mask; 6731102670Sgibbs 6732102670Sgibbs break; 6733102670Sgibbs } 6734102670Sgibbs if (entry >= num_entries) 6735102670Sgibbs break; 6736102670Sgibbs } 6737102670Sgibbs if (printed_mask != 0) 6738102670Sgibbs printed += printf(") "); 6739102670Sgibbs else 6740102670Sgibbs printed += printf(" "); 6741107420Sscottl if (cur_column != NULL) 6742107420Sscottl *cur_column += printed; 6743102670Sgibbs return (printed); 6744102670Sgibbs} 6745102670Sgibbs 674665942Sgibbsvoid 674765942Sgibbsahc_dump_card_state(struct ahc_softc *ahc) 674865942Sgibbs{ 6749107420Sscottl struct scb *scb; 6750107420Sscottl struct scb_tailq *untagged_q; 6751107420Sscottl u_int cur_col; 6752109590Sgibbs int paused; 6753107420Sscottl int target; 6754107420Sscottl int maxtarget; 6755107420Sscottl int i; 675674972Sgibbs uint8_t last_phase; 675765942Sgibbs uint8_t qinpos; 675865942Sgibbs uint8_t qintail; 675965942Sgibbs uint8_t qoutpos; 676065942Sgibbs uint8_t scb_index; 676165942Sgibbs uint8_t saved_scbptr; 676265942Sgibbs 6763109590Sgibbs if (ahc_is_paused(ahc)) { 6764109590Sgibbs paused = 1; 6765109590Sgibbs } else { 6766109590Sgibbs paused = 0; 6767109590Sgibbs ahc_pause(ahc); 6768109590Sgibbs } 6769109590Sgibbs 677065942Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 677174972Sgibbs last_phase = ahc_inb(ahc, LASTPHASE); 6772109590Sgibbs printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" 6773109590Sgibbs "%s: Dumping Card State %s, at SEQADDR 0x%x\n", 677474972Sgibbs ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg, 677568579Sgibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 6776109590Sgibbs if (paused) 6777109590Sgibbs printf("Card was paused\n"); 677881170Sgibbs printf("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n", 677981170Sgibbs ahc_inb(ahc, ACCUM), ahc_inb(ahc, SINDEX), ahc_inb(ahc, DINDEX), 678081170Sgibbs ahc_inb(ahc, ARG_2)); 678195378Sgibbs printf("HCNT = 0x%x SCBPTR = 0x%x\n", ahc_inb(ahc, HCNT), 678295378Sgibbs ahc_inb(ahc, SCBPTR)); 6783107420Sscottl cur_col = 0; 678474972Sgibbs if ((ahc->features & AHC_DT) != 0) 6785109590Sgibbs ahc_scsiphase_print(ahc_inb(ahc, SCSIPHASE), &cur_col, 50); 6786109590Sgibbs ahc_scsisigi_print(ahc_inb(ahc, SCSISIGI), &cur_col, 50); 6787109590Sgibbs ahc_error_print(ahc_inb(ahc, ERROR), &cur_col, 50); 6788107420Sscottl ahc_scsibusl_print(ahc_inb(ahc, SCSIBUSL), &cur_col, 50); 6789107420Sscottl ahc_lastphase_print(ahc_inb(ahc, LASTPHASE), &cur_col, 50); 6790107420Sscottl ahc_scsiseq_print(ahc_inb(ahc, SCSISEQ), &cur_col, 50); 6791107420Sscottl ahc_sblkctl_print(ahc_inb(ahc, SBLKCTL), &cur_col, 50); 6792109590Sgibbs ahc_scsirate_print(ahc_inb(ahc, SCSIRATE), &cur_col, 50); 6793107420Sscottl ahc_seqctl_print(ahc_inb(ahc, SEQCTL), &cur_col, 50); 6794107420Sscottl ahc_seq_flags_print(ahc_inb(ahc, SEQ_FLAGS), &cur_col, 50); 6795107420Sscottl ahc_sstat0_print(ahc_inb(ahc, SSTAT0), &cur_col, 50); 6796107420Sscottl ahc_sstat1_print(ahc_inb(ahc, SSTAT1), &cur_col, 50); 6797107420Sscottl ahc_sstat2_print(ahc_inb(ahc, SSTAT2), &cur_col, 50); 6798107420Sscottl ahc_sstat3_print(ahc_inb(ahc, SSTAT3), &cur_col, 50); 6799107420Sscottl ahc_simode0_print(ahc_inb(ahc, SIMODE0), &cur_col, 50); 6800107420Sscottl ahc_simode1_print(ahc_inb(ahc, SIMODE1), &cur_col, 50); 6801107420Sscottl ahc_sxfrctl0_print(ahc_inb(ahc, SXFRCTL0), &cur_col, 50); 6802107420Sscottl ahc_dfcntrl_print(ahc_inb(ahc, DFCNTRL), &cur_col, 50); 6803107420Sscottl ahc_dfstatus_print(ahc_inb(ahc, DFSTATUS), &cur_col, 50); 6804107420Sscottl if (cur_col != 0) 6805107420Sscottl printf("\n"); 6806107420Sscottl printf("STACK:"); 6807109590Sgibbs for (i = 0; i < STACK_SIZE; i++) 6808109590Sgibbs printf(" 0x%x", ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8)); 6809107420Sscottl printf("\nSCB count = %d\n", ahc->scb_data->numscbs); 681071390Sgibbs printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag); 681171390Sgibbs printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB)); 681265942Sgibbs /* QINFIFO */ 681365942Sgibbs printf("QINFIFO entries: "); 681468087Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 681568087Sgibbs qinpos = ahc_inb(ahc, SNSCB_QOFF); 681668087Sgibbs ahc_outb(ahc, SNSCB_QOFF, qinpos); 681768087Sgibbs } else 681868087Sgibbs qinpos = ahc_inb(ahc, QINPOS); 681965942Sgibbs qintail = ahc->qinfifonext; 682065942Sgibbs while (qinpos != qintail) { 682165942Sgibbs printf("%d ", ahc->qinfifo[qinpos]); 682265942Sgibbs qinpos++; 682365942Sgibbs } 682465942Sgibbs printf("\n"); 682565942Sgibbs 682665942Sgibbs printf("Waiting Queue entries: "); 682765942Sgibbs scb_index = ahc_inb(ahc, WAITING_SCBH); 682865942Sgibbs i = 0; 682965942Sgibbs while (scb_index != SCB_LIST_NULL && i++ < 256) { 683065942Sgibbs ahc_outb(ahc, SCBPTR, scb_index); 683165942Sgibbs printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); 683265942Sgibbs scb_index = ahc_inb(ahc, SCB_NEXT); 683365942Sgibbs } 683465942Sgibbs printf("\n"); 683565942Sgibbs 683665942Sgibbs printf("Disconnected Queue entries: "); 683765942Sgibbs scb_index = ahc_inb(ahc, DISCONNECTED_SCBH); 683865942Sgibbs i = 0; 683965942Sgibbs while (scb_index != SCB_LIST_NULL && i++ < 256) { 684065942Sgibbs ahc_outb(ahc, SCBPTR, scb_index); 684165942Sgibbs printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); 684265942Sgibbs scb_index = ahc_inb(ahc, SCB_NEXT); 684365942Sgibbs } 684465942Sgibbs printf("\n"); 684565942Sgibbs 684679874Sgibbs ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); 684765942Sgibbs printf("QOUTFIFO entries: "); 684865942Sgibbs qoutpos = ahc->qoutfifonext; 684965942Sgibbs i = 0; 685065942Sgibbs while (ahc->qoutfifo[qoutpos] != SCB_LIST_NULL && i++ < 256) { 685165942Sgibbs printf("%d ", ahc->qoutfifo[qoutpos]); 685265942Sgibbs qoutpos++; 685365942Sgibbs } 685465942Sgibbs printf("\n"); 685565942Sgibbs 685665942Sgibbs printf("Sequencer Free SCB List: "); 685765942Sgibbs scb_index = ahc_inb(ahc, FREE_SCBH); 685865942Sgibbs i = 0; 685965942Sgibbs while (scb_index != SCB_LIST_NULL && i++ < 256) { 686065942Sgibbs ahc_outb(ahc, SCBPTR, scb_index); 686165942Sgibbs printf("%d ", scb_index); 686265942Sgibbs scb_index = ahc_inb(ahc, SCB_NEXT); 686365942Sgibbs } 686465942Sgibbs printf("\n"); 686565942Sgibbs 686695378Sgibbs printf("Sequencer SCB Info: "); 686795378Sgibbs for (i = 0; i < ahc->scb_data->maxhscbs; i++) { 686895378Sgibbs ahc_outb(ahc, SCBPTR, i); 6869107420Sscottl cur_col = printf("\n%3d ", i); 6870107420Sscottl 6871107420Sscottl ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL), &cur_col, 60); 6872107420Sscottl ahc_scb_scsiid_print(ahc_inb(ahc, SCB_SCSIID), &cur_col, 60); 6873107420Sscottl ahc_scb_lun_print(ahc_inb(ahc, SCB_LUN), &cur_col, 60); 6874107420Sscottl ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60); 687595378Sgibbs } 687695378Sgibbs printf("\n"); 687795378Sgibbs 687865942Sgibbs printf("Pending list: "); 687965942Sgibbs i = 0; 688065942Sgibbs LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { 688165942Sgibbs if (i++ > 256) 688265942Sgibbs break; 6883107420Sscottl cur_col = printf("\n%3d ", scb->hscb->tag); 6884107420Sscottl ahc_scb_control_print(scb->hscb->control, &cur_col, 60); 6885107420Sscottl ahc_scb_scsiid_print(scb->hscb->scsiid, &cur_col, 60); 6886107420Sscottl ahc_scb_lun_print(scb->hscb->lun, &cur_col, 60); 688781170Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) { 688881170Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 6889107420Sscottl printf("("); 6890107420Sscottl ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL), 6891107420Sscottl &cur_col, 60); 6892107420Sscottl ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60); 6893107420Sscottl printf(")"); 689481170Sgibbs } 689565942Sgibbs } 689665942Sgibbs printf("\n"); 689765942Sgibbs 689865942Sgibbs printf("Kernel Free SCB list: "); 689965942Sgibbs i = 0; 690065942Sgibbs SLIST_FOREACH(scb, &ahc->scb_data->free_scbs, links.sle) { 690165942Sgibbs if (i++ > 256) 690265942Sgibbs break; 690365942Sgibbs printf("%d ", scb->hscb->tag); 690465942Sgibbs } 690565942Sgibbs printf("\n"); 690665942Sgibbs 690765942Sgibbs maxtarget = (ahc->features & (AHC_WIDE|AHC_TWIN)) ? 15 : 7; 690865942Sgibbs for (target = 0; target <= maxtarget; target++) { 690968087Sgibbs untagged_q = &ahc->untagged_queues[target]; 691065942Sgibbs if (TAILQ_FIRST(untagged_q) == NULL) 691165942Sgibbs continue; 691265942Sgibbs printf("Untagged Q(%d): ", target); 691365942Sgibbs i = 0; 691465942Sgibbs TAILQ_FOREACH(scb, untagged_q, links.tqe) { 691565942Sgibbs if (i++ > 256) 691665942Sgibbs break; 691765942Sgibbs printf("%d ", scb->hscb->tag); 691865942Sgibbs } 691965942Sgibbs printf("\n"); 692065942Sgibbs } 692165942Sgibbs 692265942Sgibbs ahc_platform_dump_card_state(ahc); 6923109590Sgibbs printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); 692465942Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 6925109590Sgibbs if (paused == 0) 6926109590Sgibbs ahc_unpause(ahc); 692765942Sgibbs} 692865942Sgibbs 6929123579Sgibbs/*************************** Timeout Handling *********************************/ 6930123579Sgibbsvoid 6931123579Sgibbsahc_timeout(struct scb *scb) 6932123579Sgibbs{ 6933123579Sgibbs struct ahc_softc *ahc; 6934123579Sgibbs 6935123579Sgibbs ahc = scb->ahc_softc; 6936123579Sgibbs if ((scb->flags & SCB_ACTIVE) != 0) { 6937123579Sgibbs if ((scb->flags & SCB_TIMEDOUT) == 0) { 6938123579Sgibbs LIST_INSERT_HEAD(&ahc->timedout_scbs, scb, 6939123579Sgibbs timedout_links); 6940123579Sgibbs scb->flags |= SCB_TIMEDOUT; 6941123579Sgibbs } 6942123579Sgibbs ahc_wakeup_recovery_thread(ahc); 6943123579Sgibbs } 6944123579Sgibbs} 6945123579Sgibbs 6946123579Sgibbs/* 6947129133Sgibbs * Re-schedule a timeout for the passed in SCB if we determine that some 6948129133Sgibbs * other SCB is in the process of recovery or an SCB with a longer 6949129133Sgibbs * timeout is still pending. Limit our search to just "other_scb" 6950129133Sgibbs * if it is non-NULL. 6951129133Sgibbs */ 6952129133Sgibbsstatic int 6953129133Sgibbsahc_other_scb_timeout(struct ahc_softc *ahc, struct scb *scb, 6954129133Sgibbs struct scb *other_scb) 6955129133Sgibbs{ 6956129133Sgibbs u_int newtimeout; 6957129133Sgibbs int found; 6958129133Sgibbs 6959129133Sgibbs ahc_print_path(ahc, scb); 6960129133Sgibbs printf("Other SCB Timeout%s", 6961129133Sgibbs (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 6962129133Sgibbs ? " again\n" : "\n"); 6963129133Sgibbs 6964129133Sgibbs newtimeout = aic_get_timeout(scb); 6965129133Sgibbs scb->flags |= SCB_OTHERTCL_TIMEOUT; 6966129133Sgibbs found = 0; 6967129133Sgibbs if (other_scb != NULL) { 6968129133Sgibbs if ((other_scb->flags 6969129133Sgibbs & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0 6970129133Sgibbs || (other_scb->flags & SCB_RECOVERY_SCB) != 0) { 6971129133Sgibbs found++; 6972129133Sgibbs newtimeout = MAX(aic_get_timeout(other_scb), 6973129133Sgibbs newtimeout); 6974129133Sgibbs } 6975129133Sgibbs } else { 6976129133Sgibbs LIST_FOREACH(other_scb, &ahc->pending_scbs, pending_links) { 6977129133Sgibbs if ((other_scb->flags 6978129133Sgibbs & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0 6979129133Sgibbs || (other_scb->flags & SCB_RECOVERY_SCB) != 0) { 6980129133Sgibbs found++; 6981129133Sgibbs newtimeout = 6982129133Sgibbs MAX(aic_get_timeout(other_scb), 6983129133Sgibbs newtimeout); 6984129133Sgibbs } 6985129133Sgibbs } 6986129133Sgibbs } 6987129133Sgibbs 6988129133Sgibbs if (found != 0) 6989129133Sgibbs aic_scb_timer_reset(scb, newtimeout); 6990129133Sgibbs else { 6991129133Sgibbs ahc_print_path(ahc, scb); 6992129133Sgibbs printf("No other SCB worth waiting for...\n"); 6993129133Sgibbs } 6994129133Sgibbs 6995129133Sgibbs return (found != 0); 6996129133Sgibbs} 6997129133Sgibbs 6998129133Sgibbs/* 6999123579Sgibbs * ahc_recover_commands determines if any of the commands that have currently 7000123579Sgibbs * timedout are the root cause for this timeout. Innocent commands are given 7001123579Sgibbs * a new timeout while we wait for the command executing on the bus to timeout. 7002123579Sgibbs * This routine is invoked from a thread context so we are allowed to sleep. 7003123579Sgibbs * Our lock is not held on entry. 7004123579Sgibbs */ 7005123579Sgibbsvoid 7006123579Sgibbsahc_recover_commands(struct ahc_softc *ahc) 7007123579Sgibbs{ 7008123579Sgibbs struct scb *scb; 7009123579Sgibbs int found; 7010123579Sgibbs int restart_needed; 7011123579Sgibbs u_int last_phase; 7012123579Sgibbs 7013123579Sgibbs /* 7014123579Sgibbs * Pause the controller and manually flush any 7015123579Sgibbs * commands that have just completed but that our 7016123579Sgibbs * interrupt handler has yet to see. 7017123579Sgibbs */ 7018123579Sgibbs ahc_pause_and_flushwork(ahc); 7019123579Sgibbs 7020123579Sgibbs if (LIST_EMPTY(&ahc->timedout_scbs) != 0) { 7021123579Sgibbs /* 7022123579Sgibbs * The timedout commands have already 7023123579Sgibbs * completed. This typically means 7024123579Sgibbs * that either the timeout value was on 7025123579Sgibbs * the hairy edge of what the device 7026123579Sgibbs * requires or - more likely - interrupts 7027123579Sgibbs * are not happening. 7028123579Sgibbs */ 7029123579Sgibbs printf("%s: Timedout SCBs already complete. " 7030123579Sgibbs "Interrupts may not be functioning.\n", ahc_name(ahc)); 7031123579Sgibbs ahc_unpause(ahc); 7032123579Sgibbs return; 7033123579Sgibbs } 7034123579Sgibbs 7035123579Sgibbs restart_needed = 0; 7036123579Sgibbs printf("%s: Recovery Initiated\n", ahc_name(ahc)); 7037123579Sgibbs ahc_dump_card_state(ahc); 7038123579Sgibbs 7039123579Sgibbs last_phase = ahc_inb(ahc, LASTPHASE); 7040123579Sgibbs while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { 7041123579Sgibbs u_int active_scb_index; 7042123579Sgibbs u_int saved_scbptr; 7043123579Sgibbs int target; 7044123579Sgibbs int lun; 7045123579Sgibbs int i; 7046123579Sgibbs char channel; 7047123579Sgibbs 7048123579Sgibbs target = SCB_GET_TARGET(ahc, scb); 7049123579Sgibbs channel = SCB_GET_CHANNEL(ahc, scb); 7050123579Sgibbs lun = SCB_GET_LUN(scb); 7051123579Sgibbs 7052123579Sgibbs ahc_print_path(ahc, scb); 7053123579Sgibbs printf("SCB 0x%x - timed out\n", scb->hscb->tag); 7054123579Sgibbs if (scb->sg_count > 0) { 7055123579Sgibbs for (i = 0; i < scb->sg_count; i++) { 7056123579Sgibbs printf("sg[%d] - Addr 0x%x : Length %d\n", 7057123579Sgibbs i, 7058123579Sgibbs scb->sg_list[i].addr, 7059123579Sgibbs scb->sg_list[i].len & AHC_SG_LEN_MASK); 7060123579Sgibbs } 7061123579Sgibbs } 7062123579Sgibbs if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { 7063123579Sgibbs /* 7064123579Sgibbs * Been down this road before. 7065123579Sgibbs * Do a full bus reset. 7066123579Sgibbs */ 7067123579Sgibbs aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); 7068123579Sgibbsbus_reset: 7069123579Sgibbs found = ahc_reset_channel(ahc, channel, 7070123579Sgibbs /*Initiate Reset*/TRUE); 7071123579Sgibbs printf("%s: Issued Channel %c Bus Reset. " 7072123579Sgibbs "%d SCBs aborted\n", ahc_name(ahc), channel, 7073123579Sgibbs found); 7074123579Sgibbs continue; 7075123579Sgibbs } 7076123579Sgibbs 7077123579Sgibbs /* 7078123579Sgibbs * Remove the command from the timedout list in 7079123579Sgibbs * preparation for requeing it. 7080123579Sgibbs */ 7081123579Sgibbs LIST_REMOVE(scb, timedout_links); 7082123579Sgibbs scb->flags &= ~SCB_TIMEDOUT; 7083123579Sgibbs 7084123579Sgibbs /* 7085123579Sgibbs * If we are a target, transition to bus free and report 7086123579Sgibbs * the timeout. 7087123579Sgibbs * 7088123579Sgibbs * The target/initiator that is holding up the bus may not 7089123579Sgibbs * be the same as the one that triggered this timeout 7090123579Sgibbs * (different commands have different timeout lengths). 7091123579Sgibbs * If the bus is idle and we are actiing as the initiator 7092123579Sgibbs * for this request, queue a BDR message to the timed out 7093123579Sgibbs * target. Otherwise, if the timed out transaction is 7094123579Sgibbs * active: 7095123579Sgibbs * Initiator transaction: 7096123579Sgibbs * Stuff the message buffer with a BDR message and assert 7097123579Sgibbs * ATN in the hopes that the target will let go of the bus 7098123579Sgibbs * and go to the mesgout phase. If this fails, we'll 7099123579Sgibbs * get another timeout 2 seconds later which will attempt 7100123579Sgibbs * a bus reset. 7101123579Sgibbs * 7102123579Sgibbs * Target transaction: 7103123579Sgibbs * Transition to BUS FREE and report the error. 7104123579Sgibbs * It's good to be the target! 7105123579Sgibbs */ 7106123579Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 7107123579Sgibbs active_scb_index = ahc_inb(ahc, SCB_TAG); 7108123579Sgibbs 7109123579Sgibbs if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 7110123579Sgibbs && (active_scb_index < ahc->scb_data->numscbs)) { 7111123579Sgibbs struct scb *active_scb; 7112123579Sgibbs 7113123579Sgibbs /* 7114123579Sgibbs * If the active SCB is not us, assume that 7115123579Sgibbs * the active SCB has a longer timeout than 7116123579Sgibbs * the timedout SCB, and wait for the active 7117123579Sgibbs * SCB to timeout. 7118123579Sgibbs */ 7119123579Sgibbs active_scb = ahc_lookup_scb(ahc, active_scb_index); 7120123579Sgibbs if (active_scb != scb) { 7121129133Sgibbs if (ahc_other_scb_timeout(ahc, scb, 7122136711Sgibbs active_scb) == 0) 7123129133Sgibbs goto bus_reset; 7124123579Sgibbs continue; 7125123579Sgibbs } 7126123579Sgibbs 7127123579Sgibbs /* It's us */ 7128123579Sgibbs if ((scb->flags & SCB_TARGET_SCB) != 0) { 7129123579Sgibbs 7130123579Sgibbs /* 7131123579Sgibbs * Send back any queued up transactions 7132123579Sgibbs * and properly record the error condition. 7133123579Sgibbs */ 7134123579Sgibbs ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), 7135123579Sgibbs SCB_GET_CHANNEL(ahc, scb), 7136123579Sgibbs SCB_GET_LUN(scb), 7137123579Sgibbs scb->hscb->tag, 7138123579Sgibbs ROLE_TARGET, 7139123579Sgibbs CAM_CMD_TIMEOUT); 7140123579Sgibbs 7141123579Sgibbs /* Will clear us from the bus */ 7142123579Sgibbs restart_needed = 1; 7143123579Sgibbs break; 7144123579Sgibbs } 7145123579Sgibbs 7146123579Sgibbs ahc_set_recoveryscb(ahc, active_scb); 7147123579Sgibbs ahc_outb(ahc, MSG_OUT, HOST_MSG); 7148123579Sgibbs ahc_outb(ahc, SCSISIGO, last_phase|ATNO); 7149123579Sgibbs ahc_print_path(ahc, active_scb); 7150123579Sgibbs printf("BDR message in message buffer\n"); 7151123579Sgibbs active_scb->flags |= SCB_DEVICE_RESET; 7152137870Sgibbs aic_scb_timer_reset(scb, 2 * 1000); 7153123579Sgibbs } else if (last_phase != P_BUSFREE 7154123579Sgibbs && (ahc_inb(ahc, SSTAT1) & REQINIT) == 0) { 7155123579Sgibbs /* 7156123579Sgibbs * SCB is not identified, there 7157123579Sgibbs * is no pending REQ, and the sequencer 7158123579Sgibbs * has not seen a busfree. Looks like 7159123579Sgibbs * a stuck connection waiting to 7160123579Sgibbs * go busfree. Reset the bus. 7161123579Sgibbs */ 7162123579Sgibbs printf("%s: Connection stuck awaiting busfree or " 7163123579Sgibbs "Identify Msg.\n", ahc_name(ahc)); 7164123579Sgibbs goto bus_reset; 7165123579Sgibbs } else { 7166123579Sgibbs int disconnected; 7167123579Sgibbs 7168123579Sgibbs if (last_phase != P_BUSFREE 7169123579Sgibbs && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { 7170123579Sgibbs /* Hung target selection. Goto busfree */ 7171123579Sgibbs printf("%s: Hung target selection\n", 7172123579Sgibbs ahc_name(ahc)); 7173123579Sgibbs restart_needed = 1; 7174123579Sgibbs break; 7175123579Sgibbs } 7176123579Sgibbs 7177123579Sgibbs /* XXX Shouldn't panic. Just punt instead? */ 7178123579Sgibbs if ((scb->flags & SCB_TARGET_SCB) != 0) 7179123579Sgibbs panic("Timed-out target SCB but bus idle"); 7180123579Sgibbs 7181123579Sgibbs if (ahc_search_qinfifo(ahc, target, channel, lun, 7182123579Sgibbs scb->hscb->tag, ROLE_INITIATOR, 7183123579Sgibbs /*status*/0, SEARCH_COUNT) > 0) { 7184123579Sgibbs disconnected = FALSE; 7185123579Sgibbs } else { 7186123579Sgibbs disconnected = TRUE; 7187123579Sgibbs } 7188123579Sgibbs 7189123579Sgibbs if (disconnected) { 7190123579Sgibbs 7191123579Sgibbs ahc_set_recoveryscb(ahc, scb); 7192123579Sgibbs /* 7193123579Sgibbs * Actually re-queue this SCB in an attempt 7194123579Sgibbs * to select the device before it reconnects. 7195123579Sgibbs * In either case (selection or reselection), 7196123579Sgibbs * we will now issue a target reset to the 7197123579Sgibbs * timed-out device. 7198123579Sgibbs * 7199123579Sgibbs * Set the MK_MESSAGE control bit indicating 7200123579Sgibbs * that we desire to send a message. We 7201123579Sgibbs * also set the disconnected flag since 7202123579Sgibbs * in the paging case there is no guarantee 7203123579Sgibbs * that our SCB control byte matches the 7204123579Sgibbs * version on the card. We don't want the 7205123579Sgibbs * sequencer to abort the command thinking 7206123579Sgibbs * an unsolicited reselection occurred. 7207123579Sgibbs */ 7208123579Sgibbs scb->hscb->control |= MK_MESSAGE|DISCONNECTED; 7209123579Sgibbs scb->flags |= SCB_DEVICE_RESET; 7210123579Sgibbs 7211123579Sgibbs /* 7212123579Sgibbs * Remove any cached copy of this SCB in the 7213123579Sgibbs * disconnected list in preparation for the 7214123579Sgibbs * queuing of our abort SCB. We use the 7215123579Sgibbs * same element in the SCB, SCB_NEXT, for 7216123579Sgibbs * both the qinfifo and the disconnected list. 7217123579Sgibbs */ 7218123579Sgibbs ahc_search_disc_list(ahc, target, channel, 7219123579Sgibbs lun, scb->hscb->tag, 7220123579Sgibbs /*stop_on_first*/TRUE, 7221123579Sgibbs /*remove*/TRUE, 7222123579Sgibbs /*save_state*/FALSE); 7223123579Sgibbs 7224123579Sgibbs /* 7225123579Sgibbs * In the non-paging case, the sequencer will 7226123579Sgibbs * never re-reference the in-core SCB. 7227123579Sgibbs * To make sure we are notified during 7228123579Sgibbs * reslection, set the MK_MESSAGE flag in 7229123579Sgibbs * the card's copy of the SCB. 7230123579Sgibbs */ 7231123579Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) { 7232123579Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 7233123579Sgibbs ahc_outb(ahc, SCB_CONTROL, 7234123579Sgibbs ahc_inb(ahc, SCB_CONTROL) 7235123579Sgibbs | MK_MESSAGE); 7236123579Sgibbs } 7237123579Sgibbs 7238123579Sgibbs /* 7239123579Sgibbs * Clear out any entries in the QINFIFO first 7240123579Sgibbs * so we are the next SCB for this target 7241123579Sgibbs * to run. 7242123579Sgibbs */ 7243123579Sgibbs ahc_search_qinfifo(ahc, 7244123579Sgibbs SCB_GET_TARGET(ahc, scb), 7245123579Sgibbs channel, SCB_GET_LUN(scb), 7246123579Sgibbs SCB_LIST_NULL, 7247123579Sgibbs ROLE_INITIATOR, 7248123579Sgibbs CAM_REQUEUE_REQ, 7249123579Sgibbs SEARCH_COMPLETE); 7250123579Sgibbs ahc_print_path(ahc, scb); 7251123579Sgibbs printf("Queuing a BDR SCB\n"); 7252123579Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 7253123579Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 7254137870Sgibbs aic_scb_timer_reset(scb, 2 * 1000); 7255123579Sgibbs } else { 7256300060Spfg /* Go "immediately" to the bus reset */ 7257123579Sgibbs /* This shouldn't happen */ 7258123579Sgibbs ahc_set_recoveryscb(ahc, scb); 7259123579Sgibbs ahc_print_path(ahc, scb); 7260123579Sgibbs printf("SCB %d: Immediate reset. " 7261123579Sgibbs "Flags = 0x%x\n", scb->hscb->tag, 7262123579Sgibbs scb->flags); 7263123579Sgibbs goto bus_reset; 7264123579Sgibbs } 7265123579Sgibbs } 7266123579Sgibbs break; 7267123579Sgibbs } 7268123579Sgibbs 7269123579Sgibbs /* 7270123579Sgibbs * Any remaining SCBs were not the "culprit", so remove 7271123579Sgibbs * them from the timeout list. The timer for these commands 7272123579Sgibbs * will be reset once the recovery SCB completes. 7273123579Sgibbs */ 7274123579Sgibbs while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { 7275123579Sgibbs 7276123579Sgibbs LIST_REMOVE(scb, timedout_links); 7277123579Sgibbs scb->flags &= ~SCB_TIMEDOUT; 7278123579Sgibbs } 7279123579Sgibbs 7280123579Sgibbs if (restart_needed) 7281123579Sgibbs ahc_restart(ahc); 7282123579Sgibbs else 7283123579Sgibbs ahc_unpause(ahc); 7284123579Sgibbs} 7285123579Sgibbs 728665942Sgibbs/************************* Target Mode ****************************************/ 728765942Sgibbs#ifdef AHC_TARGET_MODE 728865942Sgibbscam_status 728965942Sgibbsahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb, 729074972Sgibbs struct ahc_tmode_tstate **tstate, 729174972Sgibbs struct ahc_tmode_lstate **lstate, 729265942Sgibbs int notfound_failure) 729365942Sgibbs{ 729465942Sgibbs 729568087Sgibbs if ((ahc->features & AHC_TARGETMODE) == 0) 729665942Sgibbs return (CAM_REQ_INVALID); 729765942Sgibbs 729865942Sgibbs /* 729965942Sgibbs * Handle the 'black hole' device that sucks up 730065942Sgibbs * requests to unattached luns on enabled targets. 730165942Sgibbs */ 730265942Sgibbs if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD 730365942Sgibbs && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) { 730465942Sgibbs *tstate = NULL; 730565942Sgibbs *lstate = ahc->black_hole; 730665942Sgibbs } else { 730765942Sgibbs u_int max_id; 730865942Sgibbs 730965942Sgibbs max_id = (ahc->features & AHC_WIDE) ? 15 : 7; 731065942Sgibbs if (ccb->ccb_h.target_id > max_id) 731165942Sgibbs return (CAM_TID_INVALID); 731265942Sgibbs 731370204Sgibbs if (ccb->ccb_h.target_lun >= AHC_NUM_LUNS) 731465942Sgibbs return (CAM_LUN_INVALID); 731565942Sgibbs 731665942Sgibbs *tstate = ahc->enabled_targets[ccb->ccb_h.target_id]; 731765942Sgibbs *lstate = NULL; 731865942Sgibbs if (*tstate != NULL) 731965942Sgibbs *lstate = 732065942Sgibbs (*tstate)->enabled_luns[ccb->ccb_h.target_lun]; 732165942Sgibbs } 732265942Sgibbs 732365942Sgibbs if (notfound_failure != 0 && *lstate == NULL) 732465942Sgibbs return (CAM_PATH_INVALID); 732565942Sgibbs 732665942Sgibbs return (CAM_REQ_CMP); 732765942Sgibbs} 732865942Sgibbs 732965942Sgibbsvoid 733065942Sgibbsahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) 733165942Sgibbs{ 733274972Sgibbs struct ahc_tmode_tstate *tstate; 733374972Sgibbs struct ahc_tmode_lstate *lstate; 733465942Sgibbs struct ccb_en_lun *cel; 733565942Sgibbs cam_status status; 733665942Sgibbs u_int target; 733765942Sgibbs u_int lun; 733865942Sgibbs u_int target_mask; 7339102670Sgibbs u_int our_id; 7340114621Sgibbs int error; 734165942Sgibbs char channel; 734265942Sgibbs 734365942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, &lstate, 734468087Sgibbs /*notfound_failure*/FALSE); 734565942Sgibbs 734665942Sgibbs if (status != CAM_REQ_CMP) { 734765942Sgibbs ccb->ccb_h.status = status; 734865942Sgibbs return; 734965942Sgibbs } 735068087Sgibbs 7351102670Sgibbs if (cam_sim_bus(sim) == 0) 7352102670Sgibbs our_id = ahc->our_id; 7353102670Sgibbs else 7354102670Sgibbs our_id = ahc->our_id_b; 735568087Sgibbs 7356315140Smav if (ccb->ccb_h.target_id != our_id 7357315140Smav && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 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++; 7846260342Smav atio->ccb_h.flags |= CAM_TAG_ACTION_VALID; 784765942Sgibbs } else { 7848260342Smav atio->ccb_h.flags &= ~CAM_TAG_ACTION_VALID; 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