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