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