1139749Simp/*-
297883Sgibbs * Core routines and tables shareable across OS platforms.
397883Sgibbs *
4133122Sgibbs * Copyright (c) 1994-2002, 2004 Justin T. Gibbs.
5109588Sgibbs * Copyright (c) 2000-2003 Adaptec Inc.
697883Sgibbs * All rights reserved.
797883Sgibbs *
897883Sgibbs * Redistribution and use in source and binary forms, with or without
997883Sgibbs * modification, are permitted provided that the following conditions
1097883Sgibbs * are met:
1197883Sgibbs * 1. Redistributions of source code must retain the above copyright
1297883Sgibbs *    notice, this list of conditions, and the following disclaimer,
1397883Sgibbs *    without modification.
1497883Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1597883Sgibbs *    substantially similar to the "NO WARRANTY" disclaimer below
1697883Sgibbs *    ("Disclaimer") and any redistribution must be conditioned upon
1797883Sgibbs *    including a substantially similar Disclaimer requirement for further
1897883Sgibbs *    binary redistribution.
1997883Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names
2097883Sgibbs *    of any contributors may be used to endorse or promote products derived
2197883Sgibbs *    from this software without specific prior written permission.
2297883Sgibbs *
2397883Sgibbs * Alternatively, this software may be distributed under the terms of the
2497883Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free
2597883Sgibbs * Software Foundation.
2697883Sgibbs *
2797883Sgibbs * NO WARRANTY
2897883Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2997883Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3097883Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3197883Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3297883Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3397883Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3497883Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3597883Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3697883Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3797883Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3897883Sgibbs * POSSIBILITY OF SUCH DAMAGES.
3997883Sgibbs *
40129134Sgibbs * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#246 $
4197883Sgibbs */
4297883Sgibbs
4397883Sgibbs#ifdef __linux__
4497883Sgibbs#include "aic79xx_osm.h"
4597883Sgibbs#include "aic79xx_inline.h"
4697883Sgibbs#include "aicasm/aicasm_insformat.h"
4797883Sgibbs#else
48123579Sgibbs#include <sys/cdefs.h>
49123579Sgibbs__FBSDID("$FreeBSD$");
5097883Sgibbs#include <dev/aic7xxx/aic79xx_osm.h>
5197883Sgibbs#include <dev/aic7xxx/aic79xx_inline.h>
5297883Sgibbs#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
5397883Sgibbs#endif
5497883Sgibbs
55102679Sgibbs/******************************** Globals *************************************/
5697883Sgibbsstruct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
57125448Sgibbsuint32_t ahd_attach_to_HostRAID_controllers = 1;
5897883Sgibbs
5997883Sgibbs/***************************** Lookup Tables **********************************/
6097883Sgibbschar *ahd_chip_names[] =
6197883Sgibbs{
6297883Sgibbs	"NONE",
6397883Sgibbs	"aic7901",
64102679Sgibbs	"aic7902",
65102679Sgibbs	"aic7901A"
6697883Sgibbs};
6797883Sgibbs
6897883Sgibbs/*
6997883Sgibbs * Hardware error codes.
7097883Sgibbs */
7197883Sgibbsstruct ahd_hard_error_entry {
7297883Sgibbs        uint8_t errno;
7397883Sgibbs	char *errmesg;
7497883Sgibbs};
7597883Sgibbs
7697883Sgibbsstatic struct ahd_hard_error_entry ahd_hard_errors[] = {
7797883Sgibbs	{ DSCTMOUT,	"Discard Timer has timed out" },
7897883Sgibbs	{ ILLOPCODE,	"Illegal Opcode in sequencer program" },
7997883Sgibbs	{ SQPARERR,	"Sequencer Parity Error" },
8097883Sgibbs	{ DPARERR,	"Data-path Parity Error" },
8197883Sgibbs	{ MPARERR,	"Scratch or SCB Memory Parity Error" },
8297883Sgibbs	{ CIOPARERR,	"CIOBUS Parity Error" },
8397883Sgibbs};
8497883Sgibbsstatic const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors);
8597883Sgibbs
8697883Sgibbsstatic struct ahd_phase_table_entry ahd_phase_table[] =
8797883Sgibbs{
8897883Sgibbs	{ P_DATAOUT,	MSG_NOOP,		"in Data-out phase"	},
8997883Sgibbs	{ P_DATAIN,	MSG_INITIATOR_DET_ERR,	"in Data-in phase"	},
9097883Sgibbs	{ P_DATAOUT_DT,	MSG_NOOP,		"in DT Data-out phase"	},
9197883Sgibbs	{ P_DATAIN_DT,	MSG_INITIATOR_DET_ERR,	"in DT Data-in phase"	},
9297883Sgibbs	{ P_COMMAND,	MSG_NOOP,		"in Command phase"	},
9397883Sgibbs	{ P_MESGOUT,	MSG_NOOP,		"in Message-out phase"	},
9497883Sgibbs	{ P_STATUS,	MSG_INITIATOR_DET_ERR,	"in Status phase"	},
9597883Sgibbs	{ P_MESGIN,	MSG_PARITY_ERROR,	"in Message-in phase"	},
9697883Sgibbs	{ P_BUSFREE,	MSG_NOOP,		"while idle"		},
9797883Sgibbs	{ 0,		MSG_NOOP,		"in unknown phase"	}
9897883Sgibbs};
9997883Sgibbs
10097883Sgibbs/*
10197883Sgibbs * In most cases we only wish to itterate over real phases, so
10297883Sgibbs * exclude the last element from the count.
10397883Sgibbs */
10497883Sgibbsstatic const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1;
10597883Sgibbs
10697883Sgibbs/* Our Sequencer Program */
10797883Sgibbs#include "aic79xx_seq.h"
10897883Sgibbs
10997883Sgibbs/**************************** Function Declarations ***************************/
11097883Sgibbsstatic void		ahd_handle_transmission_error(struct ahd_softc *ahd);
11197883Sgibbsstatic void		ahd_handle_lqiphase_error(struct ahd_softc *ahd,
11297883Sgibbs						  u_int lqistat1);
11397883Sgibbsstatic int		ahd_handle_pkt_busfree(struct ahd_softc *ahd,
11497883Sgibbs					       u_int busfreetime);
11597883Sgibbsstatic int		ahd_handle_nonpkt_busfree(struct ahd_softc *ahd);
116102679Sgibbsstatic void		ahd_handle_proto_violation(struct ahd_softc *ahd);
11797883Sgibbsstatic void		ahd_force_renegotiation(struct ahd_softc *ahd,
11897883Sgibbs						struct ahd_devinfo *devinfo);
11997883Sgibbs
12097883Sgibbsstatic struct ahd_tmode_tstate*
12197883Sgibbs			ahd_alloc_tstate(struct ahd_softc *ahd,
12297883Sgibbs					 u_int scsi_id, char channel);
12397883Sgibbs#ifdef AHD_TARGET_MODE
12497883Sgibbsstatic void		ahd_free_tstate(struct ahd_softc *ahd,
12597883Sgibbs					u_int scsi_id, char channel, int force);
12697883Sgibbs#endif
12797883Sgibbsstatic void		ahd_devlimited_syncrate(struct ahd_softc *ahd,
12897883Sgibbs					        struct ahd_initiator_tinfo *,
12997883Sgibbs						u_int *period,
13097883Sgibbs						u_int *ppr_options,
13197883Sgibbs						role_t role);
13297883Sgibbsstatic void		ahd_update_neg_table(struct ahd_softc *ahd,
13397883Sgibbs					     struct ahd_devinfo *devinfo,
13497883Sgibbs					     struct ahd_transinfo *tinfo);
13597883Sgibbsstatic void		ahd_update_pending_scbs(struct ahd_softc *ahd);
13697883Sgibbsstatic void		ahd_fetch_devinfo(struct ahd_softc *ahd,
13797883Sgibbs					  struct ahd_devinfo *devinfo);
13897883Sgibbsstatic void		ahd_scb_devinfo(struct ahd_softc *ahd,
13997883Sgibbs					struct ahd_devinfo *devinfo,
14097883Sgibbs					struct scb *scb);
14197883Sgibbsstatic void		ahd_setup_initiator_msgout(struct ahd_softc *ahd,
14297883Sgibbs						   struct ahd_devinfo *devinfo,
14397883Sgibbs						   struct scb *scb);
14497883Sgibbsstatic void		ahd_build_transfer_msg(struct ahd_softc *ahd,
14597883Sgibbs					       struct ahd_devinfo *devinfo);
14697883Sgibbsstatic void		ahd_construct_sdtr(struct ahd_softc *ahd,
14797883Sgibbs					   struct ahd_devinfo *devinfo,
14897883Sgibbs					   u_int period, u_int offset);
14997883Sgibbsstatic void		ahd_construct_wdtr(struct ahd_softc *ahd,
15097883Sgibbs					   struct ahd_devinfo *devinfo,
15197883Sgibbs					   u_int bus_width);
15297883Sgibbsstatic void		ahd_construct_ppr(struct ahd_softc *ahd,
15397883Sgibbs					  struct ahd_devinfo *devinfo,
15497883Sgibbs					  u_int period, u_int offset,
15597883Sgibbs					  u_int bus_width, u_int ppr_options);
15697883Sgibbsstatic void		ahd_clear_msg_state(struct ahd_softc *ahd);
15797883Sgibbsstatic void		ahd_handle_message_phase(struct ahd_softc *ahd);
15897883Sgibbstypedef enum {
15997883Sgibbs	AHDMSG_1B,
16097883Sgibbs	AHDMSG_2B,
16197883Sgibbs	AHDMSG_EXT
16297883Sgibbs} ahd_msgtype;
16397883Sgibbsstatic int		ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type,
16497883Sgibbs				     u_int msgval, int full);
16597883Sgibbsstatic int		ahd_parse_msg(struct ahd_softc *ahd,
16697883Sgibbs				      struct ahd_devinfo *devinfo);
16797883Sgibbsstatic int		ahd_handle_msg_reject(struct ahd_softc *ahd,
16897883Sgibbs					      struct ahd_devinfo *devinfo);
16997883Sgibbsstatic void		ahd_handle_ign_wide_residue(struct ahd_softc *ahd,
17097883Sgibbs						struct ahd_devinfo *devinfo);
17197883Sgibbsstatic void		ahd_reinitialize_dataptrs(struct ahd_softc *ahd);
17297883Sgibbsstatic void		ahd_handle_devreset(struct ahd_softc *ahd,
17397883Sgibbs					    struct ahd_devinfo *devinfo,
174109588Sgibbs					    u_int lun, cam_status status,
175109588Sgibbs					    char *message, int verbose_level);
176153072Sru#ifdef AHD_TARGET_MODE
17797883Sgibbsstatic void		ahd_setup_target_msgin(struct ahd_softc *ahd,
17897883Sgibbs					       struct ahd_devinfo *devinfo,
17997883Sgibbs					       struct scb *scb);
18097883Sgibbs#endif
18197883Sgibbs
182106803Sscottlstatic u_int		ahd_sglist_size(struct ahd_softc *ahd);
183106803Sscottlstatic u_int		ahd_sglist_allocsize(struct ahd_softc *ahd);
18497883Sgibbsstatic bus_dmamap_callback_t
18597883Sgibbs			ahd_dmamap_cb;
18697883Sgibbsstatic void		ahd_initialize_hscbs(struct ahd_softc *ahd);
18797883Sgibbsstatic int		ahd_init_scbdata(struct ahd_softc *ahd);
18897883Sgibbsstatic void		ahd_fini_scbdata(struct ahd_softc *ahd);
18997883Sgibbsstatic void		ahd_setup_iocell_workaround(struct ahd_softc *ahd);
19097883Sgibbsstatic void		ahd_iocell_first_selection(struct ahd_softc *ahd);
191102679Sgibbsstatic void		ahd_add_col_list(struct ahd_softc *ahd,
192102679Sgibbs					 struct scb *scb, u_int col_idx);
193102679Sgibbsstatic void		ahd_rem_col_list(struct ahd_softc *ahd,
194102679Sgibbs					 struct scb *scb);
19597883Sgibbsstatic void		ahd_chip_init(struct ahd_softc *ahd);
19697883Sgibbsstatic void		ahd_qinfifo_requeue(struct ahd_softc *ahd,
19797883Sgibbs					    struct scb *prev_scb,
19897883Sgibbs					    struct scb *scb);
19997883Sgibbsstatic int		ahd_qinfifo_count(struct ahd_softc *ahd);
20097883Sgibbsstatic int		ahd_search_scb_list(struct ahd_softc *ahd, int target,
20197883Sgibbs					    char channel, int lun, u_int tag,
20297883Sgibbs					    role_t role, uint32_t status,
20397883Sgibbs					    ahd_search_action action,
204133122Sgibbs					    u_int *list_head, u_int *list_tail,
205133122Sgibbs					    u_int tid);
20697883Sgibbsstatic void		ahd_stitch_tid_list(struct ahd_softc *ahd,
20797883Sgibbs					    u_int tid_prev, u_int tid_cur,
20897883Sgibbs					    u_int tid_next);
20997883Sgibbsstatic void		ahd_add_scb_to_free_list(struct ahd_softc *ahd,
21097883Sgibbs						 u_int scbid);
21197883Sgibbsstatic u_int		ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
21297883Sgibbs				     u_int prev, u_int next, u_int tid);
21397883Sgibbsstatic void		ahd_reset_current_bus(struct ahd_softc *ahd);
21497883Sgibbsstatic ahd_callback_t	ahd_reset_poll;
215109588Sgibbsstatic ahd_callback_t	ahd_stat_timer;
21697883Sgibbs#ifdef AHD_DUMP_SEQ
21797883Sgibbsstatic void		ahd_dumpseq(struct ahd_softc *ahd);
21897883Sgibbs#endif
21997883Sgibbsstatic void		ahd_loadseq(struct ahd_softc *ahd);
22097883Sgibbsstatic int		ahd_check_patch(struct ahd_softc *ahd,
22197883Sgibbs					struct patch **start_patch,
22297883Sgibbs					u_int start_instr, u_int *skip_addr);
22397883Sgibbsstatic u_int		ahd_resolve_seqaddr(struct ahd_softc *ahd,
22497883Sgibbs					    u_int address);
22597883Sgibbsstatic void		ahd_download_instr(struct ahd_softc *ahd,
22697883Sgibbs					   u_int instrptr, uint8_t *dconsts);
227107441Sscottlstatic int		ahd_probe_stack_size(struct ahd_softc *ahd);
228129134Sgibbsstatic int		ahd_other_scb_timeout(struct ahd_softc *ahd,
229123579Sgibbs					      struct scb *scb,
230123579Sgibbs					      struct scb *other_scb);
231116940Sgibbsstatic int		ahd_scb_active_in_fifo(struct ahd_softc *ahd,
232116940Sgibbs					       struct scb *scb);
233116940Sgibbsstatic void		ahd_run_data_fifo(struct ahd_softc *ahd,
234116940Sgibbs					  struct scb *scb);
235116940Sgibbs
23697883Sgibbs#ifdef AHD_TARGET_MODE
23797883Sgibbsstatic void		ahd_queue_lstate_event(struct ahd_softc *ahd,
23897883Sgibbs					       struct ahd_tmode_lstate *lstate,
23997883Sgibbs					       u_int initiator_id,
24097883Sgibbs					       u_int event_type,
24197883Sgibbs					       u_int event_arg);
24297883Sgibbsstatic void		ahd_update_scsiid(struct ahd_softc *ahd,
24397883Sgibbs					  u_int targid_mask);
24497883Sgibbsstatic int		ahd_handle_target_cmd(struct ahd_softc *ahd,
24597883Sgibbs					      struct target_cmd *cmd);
24697883Sgibbs#endif
24797883Sgibbs
24897883Sgibbs/******************************** Private Inlines *****************************/
24997883Sgibbsstatic __inline void	ahd_assert_atn(struct ahd_softc *ahd);
25097883Sgibbsstatic __inline int	ahd_currently_packetized(struct ahd_softc *ahd);
25197883Sgibbsstatic __inline int	ahd_set_active_fifo(struct ahd_softc *ahd);
25297883Sgibbs
25397883Sgibbsstatic __inline void
25497883Sgibbsahd_assert_atn(struct ahd_softc *ahd)
25597883Sgibbs{
25697883Sgibbs	ahd_outb(ahd, SCSISIGO, ATNO);
25797883Sgibbs}
25897883Sgibbs
25997883Sgibbs/*
26097883Sgibbs * Determine if the current connection has a packetized
26197883Sgibbs * agreement.  This does not necessarily mean that we
26297883Sgibbs * are currently in a packetized transfer.  We could
26397883Sgibbs * just as easily be sending or receiving a message.
26497883Sgibbs */
26597883Sgibbsstatic __inline int
26697883Sgibbsahd_currently_packetized(struct ahd_softc *ahd)
26797883Sgibbs{
26897883Sgibbs	ahd_mode_state	 saved_modes;
26997883Sgibbs	int		 packetized;
27097883Sgibbs
27197883Sgibbs	saved_modes = ahd_save_modes(ahd);
27297883Sgibbs	if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) {
27397883Sgibbs		/*
27497883Sgibbs		 * The packetized bit refers to the last
27597883Sgibbs		 * connection, not the current one.  Check
27697883Sgibbs		 * for non-zero LQISTATE instead.
27797883Sgibbs		 */
27897883Sgibbs		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
27997883Sgibbs		packetized = ahd_inb(ahd, LQISTATE) != 0;
28097883Sgibbs	} else {
28197883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
28297883Sgibbs		packetized = ahd_inb(ahd, LQISTAT2) & PACKETIZED;
28397883Sgibbs	}
28497883Sgibbs	ahd_restore_modes(ahd, saved_modes);
28597883Sgibbs	return (packetized);
28697883Sgibbs}
28797883Sgibbs
28897883Sgibbsstatic __inline int
28997883Sgibbsahd_set_active_fifo(struct ahd_softc *ahd)
29097883Sgibbs{
29197883Sgibbs	u_int active_fifo;
29297883Sgibbs
29397883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
29497883Sgibbs	active_fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
29597883Sgibbs	switch (active_fifo) {
29697883Sgibbs	case 0:
29797883Sgibbs	case 1:
29897883Sgibbs		ahd_set_modes(ahd, active_fifo, active_fifo);
29997883Sgibbs		return (1);
30097883Sgibbs	default:
30197883Sgibbs		return (0);
30297883Sgibbs	}
30397883Sgibbs}
30497883Sgibbs
30597883Sgibbs/************************* Sequencer Execution Control ************************/
30697883Sgibbs/*
30797883Sgibbs * Restart the sequencer program from address zero
30897883Sgibbs */
30997883Sgibbsvoid
31097883Sgibbsahd_restart(struct ahd_softc *ahd)
31197883Sgibbs{
31297883Sgibbs
31397883Sgibbs	ahd_pause(ahd);
31497883Sgibbs
31597883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
31697883Sgibbs
31797883Sgibbs	/* No more pending messages */
31897883Sgibbs	ahd_clear_msg_state(ahd);
31997883Sgibbs	ahd_outb(ahd, SCSISIGO, 0);		/* De-assert BSY */
32097883Sgibbs	ahd_outb(ahd, MSG_OUT, MSG_NOOP);	/* No message to send */
32197883Sgibbs	ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET);
32297883Sgibbs	ahd_outb(ahd, SEQINTCTL, 0);
32397883Sgibbs	ahd_outb(ahd, LASTPHASE, P_BUSFREE);
32497883Sgibbs	ahd_outb(ahd, SEQ_FLAGS, 0);
32597883Sgibbs	ahd_outb(ahd, SAVED_SCSIID, 0xFF);
32697883Sgibbs	ahd_outb(ahd, SAVED_LUN, 0xFF);
32797883Sgibbs
32897883Sgibbs	/*
32997883Sgibbs	 * Ensure that the sequencer's idea of TQINPOS
33097883Sgibbs	 * matches our own.  The sequencer increments TQINPOS
33197883Sgibbs	 * only after it sees a DMA complete and a reset could
33297883Sgibbs	 * occur before the increment leaving the kernel to believe
33397883Sgibbs	 * the command arrived but the sequencer to not.
33497883Sgibbs	 */
33597883Sgibbs	ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
33697883Sgibbs
33797883Sgibbs	/* Always allow reselection */
33897883Sgibbs	ahd_outb(ahd, SCSISEQ1,
33997883Sgibbs		 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
34097883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
341129134Sgibbs
342129134Sgibbs	/*
343129134Sgibbs	 * Clear any pending sequencer interrupt.  It is no
344129134Sgibbs	 * longer relevant since we're resetting the Program
345129134Sgibbs	 * Counter.
346129134Sgibbs	 */
347129134Sgibbs	ahd_outb(ahd, CLRINT, CLRSEQINT);
348129134Sgibbs
34997883Sgibbs	ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
35097883Sgibbs	ahd_unpause(ahd);
35197883Sgibbs}
35297883Sgibbs
35397883Sgibbsvoid
35497883Sgibbsahd_clear_fifo(struct ahd_softc *ahd, u_int fifo)
35597883Sgibbs{
35697883Sgibbs	ahd_mode_state	 saved_modes;
35797883Sgibbs
35897883Sgibbs#ifdef AHD_DEBUG
35997883Sgibbs	if ((ahd_debug & AHD_SHOW_FIFOS) != 0)
36097883Sgibbs		printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo);
36197883Sgibbs#endif
36297883Sgibbs	saved_modes = ahd_save_modes(ahd);
36397883Sgibbs	ahd_set_modes(ahd, fifo, fifo);
36497883Sgibbs	ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
36597883Sgibbs	if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
36697883Sgibbs		ahd_outb(ahd, CCSGCTL, CCSGRESET);
36797883Sgibbs	ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
36897883Sgibbs	ahd_outb(ahd, SG_STATE, 0);
36997883Sgibbs	ahd_restore_modes(ahd, saved_modes);
37097883Sgibbs}
37197883Sgibbs
37297883Sgibbs/************************* Input/Output Queues ********************************/
373109588Sgibbs/*
374109588Sgibbs * Flush and completed commands that are sitting in the command
375109588Sgibbs * complete queues down on the chip but have yet to be dma'ed back up.
376109588Sgibbs */
37797883Sgibbsvoid
378109588Sgibbsahd_flush_qoutfifo(struct ahd_softc *ahd)
379109588Sgibbs{
380109588Sgibbs	struct		scb *scb;
381109588Sgibbs	ahd_mode_state	saved_modes;
382109588Sgibbs	u_int		saved_scbptr;
383109588Sgibbs	u_int		ccscbctl;
384109588Sgibbs	u_int		scbid;
385109588Sgibbs	u_int		next_scbid;
386109588Sgibbs
387109588Sgibbs	saved_modes = ahd_save_modes(ahd);
388116940Sgibbs
389116940Sgibbs	/*
390123579Sgibbs	 * Flush the good status FIFO for completed packetized commands.
391116940Sgibbs	 */
392116940Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
393109588Sgibbs	saved_scbptr = ahd_get_scbptr(ahd);
394116940Sgibbs	while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
395116940Sgibbs		u_int fifo_mode;
396116940Sgibbs		u_int i;
397116940Sgibbs
398123579Sgibbs		scbid = ahd_inw(ahd, GSFIFO);
399116940Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
400116940Sgibbs		if (scb == NULL) {
401116940Sgibbs			printf("%s: Warning - GSFIFO SCB %d invalid\n",
402116940Sgibbs			       ahd_name(ahd), scbid);
403199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
404116940Sgibbs			continue;
405116940Sgibbs		}
406116940Sgibbs		/*
407116940Sgibbs		 * Determine if this transaction is still active in
408116940Sgibbs		 * any FIFO.  If it is, we must flush that FIFO to
409116940Sgibbs		 * the host before completing the  command.
410116940Sgibbs		 */
411116940Sgibbs		fifo_mode = 0;
412123579Sgibbsrescan_fifos:
413116940Sgibbs		for (i = 0; i < 2; i++) {
414116940Sgibbs			/* Toggle to the other mode. */
415116940Sgibbs			fifo_mode ^= 1;
416116940Sgibbs			ahd_set_modes(ahd, fifo_mode, fifo_mode);
417123655Sgibbs
418123655Sgibbs			if (ahd_scb_active_in_fifo(ahd, scb) == 0)
419116940Sgibbs				continue;
420109588Sgibbs
421116940Sgibbs			ahd_run_data_fifo(ahd, scb);
422116940Sgibbs
423116940Sgibbs			/*
424123579Sgibbs			 * Running this FIFO may cause a CFG4DATA for
425123579Sgibbs			 * this same transaction to assert in the other
426123579Sgibbs			 * FIFO or a new snapshot SAVEPTRS interrupt
427123579Sgibbs			 * in this FIFO.  Even running a FIFO may not
428123579Sgibbs			 * clear the transaction if we are still waiting
429123579Sgibbs			 * for data to drain to the host. We must loop
430123579Sgibbs			 * until the transaction is not active in either
431123579Sgibbs			 * FIFO just to be sure.  Reset our loop counter
432123579Sgibbs			 * so we will visit both FIFOs again before
433123655Sgibbs			 * declaring this transaction finished.  We
434123655Sgibbs			 * also delay a bit so that status has a chance
435123655Sgibbs			 * to change before we look at this FIFO again.
436116940Sgibbs			 */
437123655Sgibbs			aic_delay(200);
438123579Sgibbs			goto rescan_fifos;
439116940Sgibbs		}
440116940Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
441116940Sgibbs		ahd_set_scbptr(ahd, scbid);
442116940Sgibbs		if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0
443116940Sgibbs		 && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0
444116940Sgibbs		  || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)
445116940Sgibbs		      & SG_LIST_NULL) != 0)) {
446116940Sgibbs			u_int comp_head;
447116940Sgibbs
448116940Sgibbs			/*
449116940Sgibbs			 * The transfer completed with a residual.
450116940Sgibbs			 * Place this SCB on the complete DMA list
451123579Sgibbs			 * so that we update our in-core copy of the
452116940Sgibbs			 * SCB before completing the command.
453116940Sgibbs			 */
454116940Sgibbs			ahd_outb(ahd, SCB_SCSI_STATUS, 0);
455116940Sgibbs			ahd_outb(ahd, SCB_SGPTR,
456116940Sgibbs				 ahd_inb_scbram(ahd, SCB_SGPTR)
457116940Sgibbs				 | SG_STATUS_VALID);
458125448Sgibbs			ahd_outw(ahd, SCB_TAG, scbid);
459125448Sgibbs			ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
460116940Sgibbs			comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
461125448Sgibbs			if (SCBID_IS_NULL(comp_head)) {
462125448Sgibbs				ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
463125448Sgibbs				ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
464125448Sgibbs			} else {
465125448Sgibbs				u_int tail;
466125448Sgibbs
467125448Sgibbs				tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
468125448Sgibbs				ahd_set_scbptr(ahd, tail);
469125448Sgibbs				ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
470125448Sgibbs				ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
471125448Sgibbs				ahd_set_scbptr(ahd, scbid);
472125448Sgibbs			}
473116940Sgibbs		} else
474116940Sgibbs			ahd_complete_scb(ahd, scb);
475116940Sgibbs	}
476116940Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
477116940Sgibbs
478109588Sgibbs	/*
479116940Sgibbs	 * Setup for command channel portion of flush.
480116940Sgibbs	 */
481116940Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
482116940Sgibbs
483116940Sgibbs	/*
484109588Sgibbs	 * Wait for any inprogress DMA to complete and clear DMA state
485109588Sgibbs	 * if this if for an SCB in the qinfifo.
486109588Sgibbs	 */
487116767Sgibbs	while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) {
488109588Sgibbs
489109588Sgibbs		if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) {
490109588Sgibbs			if ((ccscbctl & ARRDONE) != 0)
491109588Sgibbs				break;
492109588Sgibbs		} else if ((ccscbctl & CCSCBDONE) != 0)
493109588Sgibbs			break;
494123579Sgibbs		aic_delay(200);
495109588Sgibbs	}
496123579Sgibbs	/*
497123579Sgibbs	 * We leave the sequencer to cleanup in the case of DMA's to
498123579Sgibbs	 * update the qoutfifo.  In all other cases (DMA's to the
499123579Sgibbs	 * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
500123579Sgibbs	 * we disable the DMA engine so that the sequencer will not
501123579Sgibbs	 * attempt to handle the DMA completion.
502123579Sgibbs	 */
503123579Sgibbs	if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
504109588Sgibbs		ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
505109588Sgibbs
506123579Sgibbs	/*
507123579Sgibbs	 * Complete any SCBs that just finished
508123579Sgibbs	 * being DMA'ed into the qoutfifo.
509123579Sgibbs	 */
510123579Sgibbs	ahd_run_qoutfifo(ahd);
511123579Sgibbs
512116940Sgibbs	saved_scbptr = ahd_get_scbptr(ahd);
513109588Sgibbs	/*
514109588Sgibbs	 * Manually update/complete any completed SCBs that are waiting to be
515109588Sgibbs	 * DMA'ed back up to the host.
516109588Sgibbs	 */
517109588Sgibbs	scbid = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
518109588Sgibbs	while (!SCBID_IS_NULL(scbid)) {
519109588Sgibbs		uint8_t *hscb_ptr;
520109588Sgibbs		u_int	 i;
521109588Sgibbs
522109588Sgibbs		ahd_set_scbptr(ahd, scbid);
523111954Sgibbs		next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
524109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
525109588Sgibbs		if (scb == NULL) {
526109588Sgibbs			printf("%s: Warning - DMA-up and complete "
527109588Sgibbs			       "SCB %d invalid\n", ahd_name(ahd), scbid);
528199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
529109588Sgibbs			continue;
530109588Sgibbs		}
531109588Sgibbs		hscb_ptr = (uint8_t *)scb->hscb;
532109588Sgibbs		for (i = 0; i < sizeof(struct hardware_scb); i++)
533111954Sgibbs			*hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE + i);
534109588Sgibbs
535109588Sgibbs		ahd_complete_scb(ahd, scb);
536109588Sgibbs		scbid = next_scbid;
537109588Sgibbs	}
538109588Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
539125448Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
540109588Sgibbs
541125448Sgibbs	scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
542125448Sgibbs	while (!SCBID_IS_NULL(scbid)) {
543125448Sgibbs
544125448Sgibbs		ahd_set_scbptr(ahd, scbid);
545125448Sgibbs		next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
546125448Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
547125448Sgibbs		if (scb == NULL) {
548125448Sgibbs			printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
549125448Sgibbs			       ahd_name(ahd), scbid);
550199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
551125448Sgibbs			continue;
552125448Sgibbs		}
553125448Sgibbs
554125448Sgibbs		ahd_complete_scb(ahd, scb);
555125448Sgibbs		scbid = next_scbid;
556125448Sgibbs	}
557125448Sgibbs	ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
558125448Sgibbs
559109588Sgibbs	scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
560109588Sgibbs	while (!SCBID_IS_NULL(scbid)) {
561109588Sgibbs
562109588Sgibbs		ahd_set_scbptr(ahd, scbid);
563111954Sgibbs		next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
564109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
565109588Sgibbs		if (scb == NULL) {
566109588Sgibbs			printf("%s: Warning - Complete SCB %d invalid\n",
567109588Sgibbs			       ahd_name(ahd), scbid);
568199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
569109588Sgibbs			continue;
570109588Sgibbs		}
571109588Sgibbs
572109588Sgibbs		ahd_complete_scb(ahd, scb);
573109588Sgibbs		scbid = next_scbid;
574109588Sgibbs	}
575109588Sgibbs	ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
576116940Sgibbs
577116940Sgibbs	/*
578116940Sgibbs	 * Restore state.
579116940Sgibbs	 */
580109588Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
581116940Sgibbs	ahd_restore_modes(ahd, saved_modes);
582116940Sgibbs	ahd->flags |= AHD_UPDATE_PEND_CMDS;
583116940Sgibbs}
584109588Sgibbs
585116940Sgibbs/*
586116940Sgibbs * Determine if an SCB for a packetized transaction
587116940Sgibbs * is active in a FIFO.
588116940Sgibbs */
589116940Sgibbsstatic int
590116940Sgibbsahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)
591116940Sgibbs{
592116940Sgibbs
593109588Sgibbs	/*
594116940Sgibbs	 * The FIFO is only active for our transaction if
595116940Sgibbs	 * the SCBPTR matches the SCB's ID and the firmware
596116940Sgibbs	 * has installed a handler for the FIFO or we have
597116940Sgibbs	 * a pending SAVEPTRS or CFG4DATA interrupt.
598109588Sgibbs	 */
599116940Sgibbs	if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)
600116940Sgibbs	 || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0
601116940Sgibbs	  && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))
602116940Sgibbs		return (0);
603116940Sgibbs
604116940Sgibbs	return (1);
605116940Sgibbs}
606116940Sgibbs
607116940Sgibbs/*
608116940Sgibbs * Run a data fifo to completion for a transaction we know
609116940Sgibbs * has completed across the SCSI bus (good status has been
610116940Sgibbs * received).  We are already set to the correct FIFO mode
611116940Sgibbs * on entry to this routine.
612116940Sgibbs *
613116940Sgibbs * This function attempts to operate exactly as the firmware
614116940Sgibbs * would when running this FIFO.  Care must be taken to update
615116940Sgibbs * this routine any time the firmware's FIFO algorithm is
616116940Sgibbs * changed.
617116940Sgibbs */
618116940Sgibbsstatic void
619116940Sgibbsahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
620116940Sgibbs{
621116940Sgibbs	u_int seqintsrc;
622116940Sgibbs
623123579Sgibbs	seqintsrc = ahd_inb(ahd, SEQINTSRC);
624123579Sgibbs	if ((seqintsrc & CFG4DATA) != 0) {
625123579Sgibbs		uint32_t datacnt;
626123579Sgibbs		uint32_t sgptr;
627116940Sgibbs
628123579Sgibbs		/*
629123579Sgibbs		 * Clear full residual flag.
630123579Sgibbs		 */
631123579Sgibbs		sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
632123579Sgibbs		ahd_outb(ahd, SCB_SGPTR, sgptr);
633116940Sgibbs
634123579Sgibbs		/*
635123579Sgibbs		 * Load datacnt and address.
636123579Sgibbs		 */
637123579Sgibbs		datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
638123579Sgibbs		if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
639123579Sgibbs			sgptr |= LAST_SEG;
640123579Sgibbs			ahd_outb(ahd, SG_STATE, 0);
641123579Sgibbs		} else
642123579Sgibbs			ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
643123579Sgibbs		ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
644123579Sgibbs		ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
645123579Sgibbs		ahd_outb(ahd, SG_CACHE_PRE, sgptr);
646123579Sgibbs		ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
647116940Sgibbs
648123579Sgibbs		/*
649123579Sgibbs		 * Initialize Residual Fields.
650123579Sgibbs		 */
651123579Sgibbs		ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
652123579Sgibbs		ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
653116940Sgibbs
654123579Sgibbs		/*
655123579Sgibbs		 * Mark the SCB as having a FIFO in use.
656123579Sgibbs		 */
657123579Sgibbs		ahd_outb(ahd, SCB_FIFO_USE_COUNT,
658123579Sgibbs			 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
659116940Sgibbs
660123579Sgibbs		/*
661123579Sgibbs		 * Install a "fake" handler for this FIFO.
662123579Sgibbs		 */
663123579Sgibbs		ahd_outw(ahd, LONGJMP_ADDR, 0);
664116940Sgibbs
665123579Sgibbs		/*
666123579Sgibbs		 * Notify the hardware that we have satisfied
667123579Sgibbs		 * this sequencer interrupt.
668123579Sgibbs		 */
669123579Sgibbs		ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
670123579Sgibbs	} else if ((seqintsrc & SAVEPTRS) != 0) {
671123579Sgibbs		uint32_t sgptr;
672123579Sgibbs		uint32_t resid;
673123579Sgibbs
674123579Sgibbs		if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
675116940Sgibbs			/*
676123579Sgibbs			 * Snapshot Save Pointers.  All that
677123579Sgibbs			 * is necessary to clear the snapshot
678123579Sgibbs			 * is a CLRCHN.
679116940Sgibbs			 */
680123579Sgibbs			goto clrchn;
681123579Sgibbs		}
682116940Sgibbs
683123579Sgibbs		/*
684123579Sgibbs		 * Disable S/G fetch so the DMA engine
685123579Sgibbs		 * is available to future users.
686123579Sgibbs		 */
687123579Sgibbs		if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
688123579Sgibbs			ahd_outb(ahd, CCSGCTL, 0);
689123579Sgibbs		ahd_outb(ahd, SG_STATE, 0);
690116940Sgibbs
691123579Sgibbs		/*
692123579Sgibbs		 * Flush the data FIFO.  Strickly only
693123579Sgibbs		 * necessary for Rev A parts.
694123579Sgibbs		 */
695123579Sgibbs		ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
696116940Sgibbs
697123579Sgibbs		/*
698123579Sgibbs		 * Calculate residual.
699123579Sgibbs		 */
700123579Sgibbs		sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
701123579Sgibbs		resid = ahd_inl(ahd, SHCNT);
702123579Sgibbs		resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
703123579Sgibbs		ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
704123579Sgibbs		if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
705116940Sgibbs			/*
706123579Sgibbs			 * Must back up to the correct S/G element.
707123579Sgibbs			 * Typically this just means resetting our
708123579Sgibbs			 * low byte to the offset in the SG_CACHE,
709123579Sgibbs			 * but if we wrapped, we have to correct
710123579Sgibbs			 * the other bytes of the sgptr too.
711116940Sgibbs			 */
712123579Sgibbs			if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
713123579Sgibbs			 && (sgptr & 0x80) == 0)
714123579Sgibbs				sgptr -= 0x100;
715123579Sgibbs			sgptr &= ~0xFF;
716123579Sgibbs			sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
717123579Sgibbs			       & SG_ADDR_MASK;
718123579Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
719123579Sgibbs			ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
720123579Sgibbs		} else if ((resid & AHD_SG_LEN_MASK) == 0) {
721123579Sgibbs			ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
722123579Sgibbs				 sgptr | SG_LIST_NULL);
723123579Sgibbs		}
724123579Sgibbs		/*
725123579Sgibbs		 * Save Pointers.
726123579Sgibbs		 */
727123579Sgibbs		ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
728123579Sgibbs		ahd_outl(ahd, SCB_DATACNT, resid);
729123579Sgibbs		ahd_outl(ahd, SCB_SGPTR, sgptr);
730123579Sgibbs		ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
731123579Sgibbs		ahd_outb(ahd, SEQIMODE,
732123579Sgibbs			 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
733123579Sgibbs		/*
734123579Sgibbs		 * If the data is to the SCSI bus, we are
735123579Sgibbs		 * done, otherwise wait for FIFOEMP.
736123579Sgibbs		 */
737123579Sgibbs		if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
738123579Sgibbs			goto clrchn;
739123579Sgibbs	} else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
740123579Sgibbs		uint32_t sgptr;
741123579Sgibbs		uint64_t data_addr;
742123579Sgibbs		uint32_t data_len;
743123579Sgibbs		u_int	 dfcntrl;
744116940Sgibbs
745123579Sgibbs		/*
746123579Sgibbs		 * Disable S/G fetch so the DMA engine
747123579Sgibbs		 * is available to future users.  We won't
748123579Sgibbs		 * be using the DMA engine to load segments.
749123579Sgibbs		 */
750123579Sgibbs		if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
751123579Sgibbs			ahd_outb(ahd, CCSGCTL, 0);
752123579Sgibbs			ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
753123579Sgibbs		}
754116940Sgibbs
755123579Sgibbs		/*
756123579Sgibbs		 * Wait for the DMA engine to notice that the
757123579Sgibbs		 * host transfer is enabled and that there is
758123579Sgibbs		 * space in the S/G FIFO for new segments before
759123579Sgibbs		 * loading more segments.
760123579Sgibbs		 */
761123579Sgibbs		if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
762123579Sgibbs		 && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
763116940Sgibbs
764116940Sgibbs			/*
765116940Sgibbs			 * Determine the offset of the next S/G
766116940Sgibbs			 * element to load.
767116940Sgibbs			 */
768116940Sgibbs			sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
769116940Sgibbs			sgptr &= SG_PTR_MASK;
770116940Sgibbs			if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
771116940Sgibbs				struct ahd_dma64_seg *sg;
772116940Sgibbs
773116940Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
774116940Sgibbs				data_addr = sg->addr;
775116940Sgibbs				data_len = sg->len;
776116940Sgibbs				sgptr += sizeof(*sg);
777116940Sgibbs			} else {
778116940Sgibbs				struct	ahd_dma_seg *sg;
779116940Sgibbs
780116940Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
781116940Sgibbs				data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;
782116940Sgibbs				data_addr <<= 8;
783116940Sgibbs				data_addr |= sg->addr;
784116940Sgibbs				data_len = sg->len;
785116940Sgibbs				sgptr += sizeof(*sg);
786116940Sgibbs			}
787116940Sgibbs
788116940Sgibbs			/*
789116940Sgibbs			 * Update residual information.
790116940Sgibbs			 */
791116940Sgibbs			ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);
792116940Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
793116940Sgibbs
794116940Sgibbs			/*
795116940Sgibbs			 * Load the S/G.
796116940Sgibbs			 */
797116940Sgibbs			if (data_len & AHD_DMA_LAST_SEG) {
798116940Sgibbs				sgptr |= LAST_SEG;
799116940Sgibbs				ahd_outb(ahd, SG_STATE, 0);
800116940Sgibbs			}
801116940Sgibbs			ahd_outq(ahd, HADDR, data_addr);
802116940Sgibbs			ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);
803116940Sgibbs			ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);
804116940Sgibbs
805116940Sgibbs			/*
806116940Sgibbs			 * Advertise the segment to the hardware.
807116940Sgibbs			 */
808116940Sgibbs			dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
809123579Sgibbs			if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
810116940Sgibbs				/*
811116940Sgibbs				 * Use SCSIENWRDIS so that SCSIEN
812116940Sgibbs				 * is never modified by this
813116940Sgibbs				 * operation.
814116940Sgibbs				 */
815116940Sgibbs				dfcntrl |= SCSIENWRDIS;
816116940Sgibbs			}
817116940Sgibbs			ahd_outb(ahd, DFCNTRL, dfcntrl);
818123579Sgibbs		}
819123579Sgibbs	} else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
820116940Sgibbs
821123579Sgibbs		/*
822123579Sgibbs		 * Transfer completed to the end of SG list
823123579Sgibbs		 * and has flushed to the host.
824123579Sgibbs		 */
825123579Sgibbs		ahd_outb(ahd, SCB_SGPTR,
826123579Sgibbs			 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
827123579Sgibbs		goto clrchn;
828123579Sgibbs	} else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
829123579Sgibbsclrchn:
830123579Sgibbs		/*
831123579Sgibbs		 * Clear any handler for this FIFO, decrement
832123579Sgibbs		 * the FIFO use count for the SCB, and release
833123579Sgibbs		 * the FIFO.
834123579Sgibbs		 */
835123579Sgibbs		ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
836123579Sgibbs		ahd_outb(ahd, SCB_FIFO_USE_COUNT,
837123579Sgibbs			 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
838123579Sgibbs		ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
839109588Sgibbs	}
840109588Sgibbs}
841109588Sgibbs
842125448Sgibbs/*
843125448Sgibbs * Look for entries in the QoutFIFO that have completed.
844125448Sgibbs * The valid_tag completion field indicates the validity
845125448Sgibbs * of the entry - the valid value toggles each time through
846125448Sgibbs * the queue. We use the sg_status field in the completion
847125448Sgibbs * entry to avoid referencing the hscb if the completion
848125448Sgibbs * occurred with no errors and no residual.  sg_status is
849125448Sgibbs * a copy of the first byte (little endian) of the sgptr
850125448Sgibbs * hscb field.
851125448Sgibbs */
852109588Sgibbsvoid
85397883Sgibbsahd_run_qoutfifo(struct ahd_softc *ahd)
85497883Sgibbs{
855125448Sgibbs	struct ahd_completion *completion;
85697883Sgibbs	struct scb *scb;
85797883Sgibbs	u_int  scb_index;
85897883Sgibbs
859109588Sgibbs	if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0)
860109588Sgibbs		panic("ahd_run_qoutfifo recursion");
861109588Sgibbs	ahd->flags |= AHD_RUNNING_QOUTFIFO;
86297883Sgibbs	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
863125448Sgibbs	for (;;) {
864125448Sgibbs		completion = &ahd->qoutfifo[ahd->qoutfifonext];
86597883Sgibbs
866125448Sgibbs		if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
867125448Sgibbs			break;
868125448Sgibbs
869125448Sgibbs		scb_index = aic_le16toh(completion->tag);
87097883Sgibbs		scb = ahd_lookup_scb(ahd, scb_index);
87197883Sgibbs		if (scb == NULL) {
87297883Sgibbs			printf("%s: WARNING no command for scb %d "
87397883Sgibbs			       "(cmdcmplt)\nQOUTPOS = %d\n",
87497883Sgibbs			       ahd_name(ahd), scb_index,
87597883Sgibbs			       ahd->qoutfifonext);
876199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
87797883Sgibbs			ahd_dump_card_state(ahd);
878125448Sgibbs		} else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
879125448Sgibbs			ahd_handle_scb_status(ahd, scb);
880125448Sgibbs		} else {
881125448Sgibbs			ahd_done(ahd, scb);
882125448Sgibbs		}
88397883Sgibbs
884102679Sgibbs		ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
885102679Sgibbs		if (ahd->qoutfifonext == 0)
886125448Sgibbs			ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
88797883Sgibbs	}
888109588Sgibbs	ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
88997883Sgibbs}
89097883Sgibbs
89197883Sgibbs/************************* Interrupt Handling *********************************/
89297883Sgibbsvoid
89397883Sgibbsahd_handle_hwerrint(struct ahd_softc *ahd)
89497883Sgibbs{
89597883Sgibbs	/*
89697883Sgibbs	 * Some catastrophic hardware error has occurred.
89797883Sgibbs	 * Print it for the user and disable the controller.
89897883Sgibbs	 */
89997883Sgibbs	int i;
90097883Sgibbs	int error;
90197883Sgibbs
90297883Sgibbs	error = ahd_inb(ahd, ERROR);
90397883Sgibbs	for (i = 0; i < num_errors; i++) {
904199260Sattilio		if ((error & ahd_hard_errors[i].errno) != 0) {
90597883Sgibbs			printf("%s: hwerrint, %s\n",
90697883Sgibbs			       ahd_name(ahd), ahd_hard_errors[i].errmesg);
907199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
908199260Sattilio		}
90997883Sgibbs	}
91097883Sgibbs
91197883Sgibbs	ahd_dump_card_state(ahd);
91297883Sgibbs	panic("BRKADRINT");
91397883Sgibbs
914114623Sgibbs	/* Tell everyone that this HBA is no longer available */
91597883Sgibbs	ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
91697883Sgibbs		       CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,
91797883Sgibbs		       CAM_NO_HBA);
91897883Sgibbs
91997883Sgibbs	/* Tell the system that this controller has gone away. */
92097883Sgibbs	ahd_free(ahd);
92197883Sgibbs}
92297883Sgibbs
92397883Sgibbsvoid
92497883Sgibbsahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
92597883Sgibbs{
92697883Sgibbs	u_int seqintcode;
92797883Sgibbs
92897883Sgibbs	/*
92997883Sgibbs	 * Save the sequencer interrupt code and clear the SEQINT
93097883Sgibbs	 * bit. We will unpause the sequencer, if appropriate,
93197883Sgibbs	 * after servicing the request.
93297883Sgibbs	 */
93397883Sgibbs	seqintcode = ahd_inb(ahd, SEQINTCODE);
93497883Sgibbs	ahd_outb(ahd, CLRINT, CLRSEQINT);
935107441Sscottl	if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
936107441Sscottl		/*
937107441Sscottl		 * Unpause the sequencer and let it clear
938107441Sscottl		 * SEQINT by writing NO_SEQINT to it.  This
939107441Sscottl		 * will cause the sequencer to be paused again,
940107441Sscottl		 * which is the expected state of this routine.
941107441Sscottl		 */
942107441Sscottl		ahd_unpause(ahd);
943107441Sscottl		while (!ahd_is_paused(ahd))
944107441Sscottl			;
945107441Sscottl		ahd_outb(ahd, CLRINT, CLRSEQINT);
946107441Sscottl	}
94797883Sgibbs	ahd_update_modes(ahd);
94897883Sgibbs#ifdef AHD_DEBUG
94997883Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0)
95097883Sgibbs		printf("%s: Handle Seqint Called for code %d\n",
95197883Sgibbs		       ahd_name(ahd), seqintcode);
95297883Sgibbs#endif
95397883Sgibbs	switch (seqintcode) {
95497883Sgibbs	case ENTERING_NONPACK:
95597883Sgibbs	{
95697883Sgibbs		struct	scb *scb;
95797883Sgibbs		u_int	scbid;
95897883Sgibbs
95997883Sgibbs		AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
96097883Sgibbs				 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
96197883Sgibbs		scbid = ahd_get_scbptr(ahd);
96297883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
96397883Sgibbs		if (scb == NULL) {
96497883Sgibbs			/*
96597883Sgibbs			 * Somehow need to know if this
96697883Sgibbs			 * is from a selection or reselection.
967116935Sgibbs			 * From that, we can determine target
96897883Sgibbs			 * ID so we at least have an I_T nexus.
96997883Sgibbs			 */
97097883Sgibbs		} else {
97197883Sgibbs			ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
97297883Sgibbs			ahd_outb(ahd, SAVED_LUN, scb->hscb->lun);
97397883Sgibbs			ahd_outb(ahd, SEQ_FLAGS, 0x0);
97497883Sgibbs		}
97597883Sgibbs		if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0
97697883Sgibbs		 && (ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
97797883Sgibbs			/*
97897883Sgibbs			 * Phase change after read stream with
97997883Sgibbs			 * CRC error with P0 asserted on last
98097883Sgibbs			 * packet.
98197883Sgibbs			 */
982107441Sscottl#ifdef AHD_DEBUG
983107441Sscottl			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
984107441Sscottl				printf("%s: Assuming LQIPHASE_NLQ with "
985107441Sscottl				       "P0 assertion\n", ahd_name(ahd));
986107441Sscottl#endif
98797883Sgibbs		}
988107441Sscottl#ifdef AHD_DEBUG
989107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
990107441Sscottl			printf("%s: Entering NONPACK\n", ahd_name(ahd));
991107441Sscottl#endif
99297883Sgibbs		break;
99397883Sgibbs	}
99497883Sgibbs	case INVALID_SEQINT:
99597883Sgibbs		printf("%s: Invalid Sequencer interrupt occurred.\n",
99697883Sgibbs		       ahd_name(ahd));
99797883Sgibbs		ahd_dump_card_state(ahd);
99897883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
999199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
100097883Sgibbs		break;
100197883Sgibbs	case STATUS_OVERRUN:
100297883Sgibbs	{
1003114623Sgibbs		struct	scb *scb;
1004114623Sgibbs		u_int	scbid;
1005114623Sgibbs
1006114623Sgibbs		scbid = ahd_get_scbptr(ahd);
1007114623Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1008114623Sgibbs		if (scb != NULL)
1009114623Sgibbs			ahd_print_path(ahd, scb);
1010114623Sgibbs		else
1011114623Sgibbs			printf("%s: ", ahd_name(ahd));
1012114623Sgibbs		printf("SCB %d Packetized Status Overrun", scbid);
101397883Sgibbs		ahd_dump_card_state(ahd);
101497883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
1015199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
101697883Sgibbs		break;
101797883Sgibbs	}
101897883Sgibbs	case CFG4ISTAT_INTR:
101997883Sgibbs	{
102097883Sgibbs		struct	scb *scb;
102197883Sgibbs		u_int	scbid;
102297883Sgibbs
102397883Sgibbs		scbid = ahd_get_scbptr(ahd);
102497883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
102597883Sgibbs		if (scb == NULL) {
102697883Sgibbs			ahd_dump_card_state(ahd);
102797883Sgibbs			printf("CFG4ISTAT: Free SCB %d referenced", scbid);
1028199260Sattilio			AHD_FATAL_ERROR(ahd);
102997883Sgibbs			panic("For safety");
103097883Sgibbs		}
103197883Sgibbs		ahd_outq(ahd, HADDR, scb->sense_busaddr);
103297883Sgibbs		ahd_outw(ahd, HCNT, AHD_SENSE_BUFSIZE);
103397883Sgibbs		ahd_outb(ahd, HCNT + 2, 0);
103497883Sgibbs		ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG);
103597883Sgibbs		ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
103697883Sgibbs		break;
103797883Sgibbs	}
103897883Sgibbs	case ILLEGAL_PHASE:
103997883Sgibbs	{
104097883Sgibbs		u_int bus_phase;
104197883Sgibbs
104297883Sgibbs		bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
104397883Sgibbs		printf("%s: ILLEGAL_PHASE 0x%x\n",
104497883Sgibbs		       ahd_name(ahd), bus_phase);
104597883Sgibbs
104697883Sgibbs		switch (bus_phase) {
104797883Sgibbs		case P_DATAOUT:
104897883Sgibbs		case P_DATAIN:
104997883Sgibbs		case P_DATAOUT_DT:
105097883Sgibbs		case P_DATAIN_DT:
105197883Sgibbs		case P_MESGOUT:
105297883Sgibbs		case P_STATUS:
105397883Sgibbs		case P_MESGIN:
105497883Sgibbs			ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
105597883Sgibbs			printf("%s: Issued Bus Reset.\n", ahd_name(ahd));
1056199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
105797883Sgibbs			break;
105897883Sgibbs		case P_COMMAND:
105997883Sgibbs		{
106097883Sgibbs			struct	ahd_devinfo devinfo;
106197883Sgibbs			struct	scb *scb;
106297883Sgibbs			struct	ahd_initiator_tinfo *targ_info;
106397883Sgibbs			struct	ahd_tmode_tstate *tstate;
106497883Sgibbs			struct	ahd_transinfo *tinfo;
106597883Sgibbs			u_int	scbid;
106697883Sgibbs
106797883Sgibbs			/*
106897883Sgibbs			 * If a target takes us into the command phase
106997883Sgibbs			 * assume that it has been externally reset and
107097883Sgibbs			 * has thus lost our previous packetized negotiation
107197883Sgibbs			 * agreement.  Since we have not sent an identify
107297883Sgibbs			 * message and may not have fully qualified the
107397883Sgibbs			 * connection, we change our command to TUR, assert
107497883Sgibbs			 * ATN and ABORT the task when we go to message in
107597883Sgibbs			 * phase.  The OSM will see the REQUEUE_REQUEST
107697883Sgibbs			 * status and retry the command.
107797883Sgibbs			 */
107897883Sgibbs			scbid = ahd_get_scbptr(ahd);
107997883Sgibbs			scb = ahd_lookup_scb(ahd, scbid);
108097883Sgibbs			if (scb == NULL) {
1081199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
108297883Sgibbs				printf("Invalid phase with no valid SCB.  "
108397883Sgibbs				       "Resetting bus.\n");
108497883Sgibbs				ahd_reset_channel(ahd, 'A',
108597883Sgibbs						  /*Initiate Reset*/TRUE);
108697883Sgibbs				break;
108797883Sgibbs			}
108897883Sgibbs			ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
108997883Sgibbs					    SCB_GET_TARGET(ahd, scb),
109097883Sgibbs					    SCB_GET_LUN(scb),
109197883Sgibbs					    SCB_GET_CHANNEL(ahd, scb),
109297883Sgibbs					    ROLE_INITIATOR);
109397883Sgibbs			targ_info = ahd_fetch_transinfo(ahd,
109497883Sgibbs							devinfo.channel,
109597883Sgibbs							devinfo.our_scsiid,
109697883Sgibbs							devinfo.target,
109797883Sgibbs							&tstate);
109897883Sgibbs			tinfo = &targ_info->curr;
109997883Sgibbs			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
1100109588Sgibbs				      AHD_TRANS_ACTIVE, /*paused*/TRUE);
110197883Sgibbs			ahd_set_syncrate(ahd, &devinfo, /*period*/0,
110297883Sgibbs					 /*offset*/0, /*ppr_options*/0,
110397883Sgibbs					 AHD_TRANS_ACTIVE, /*paused*/TRUE);
110497883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE, 0);
110597883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+1, 0);
110697883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+2, 0);
110797883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+3, 0);
110897883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+4, 0);
110997883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+5, 0);
111097883Sgibbs			ahd_outb(ahd, SCB_CDB_LEN, 6);
111197883Sgibbs			scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);
111297883Sgibbs			scb->hscb->control |= MK_MESSAGE;
111397883Sgibbs			ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);
111497883Sgibbs			ahd_outb(ahd, MSG_OUT, HOST_MSG);
111597883Sgibbs			ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
111697883Sgibbs			/*
111797883Sgibbs			 * The lun is 0, regardless of the SCB's lun
111897883Sgibbs			 * as we have not sent an identify message.
111997883Sgibbs			 */
112097883Sgibbs			ahd_outb(ahd, SAVED_LUN, 0);
112197883Sgibbs			ahd_outb(ahd, SEQ_FLAGS, 0);
112297883Sgibbs			ahd_assert_atn(ahd);
1123123579Sgibbs			scb->flags &= ~SCB_PACKETIZED;
112497883Sgibbs			scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
112597883Sgibbs			ahd_freeze_devq(ahd, scb);
1126123579Sgibbs			aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
1127123579Sgibbs			aic_freeze_scb(scb);
112897883Sgibbs
112997883Sgibbs			/*
113097883Sgibbs			 * Allow the sequencer to continue with
113197883Sgibbs			 * non-pack processing.
113297883Sgibbs			 */
113397883Sgibbs			ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
113497883Sgibbs			ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT);
113597883Sgibbs			if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
113697883Sgibbs				ahd_outb(ahd, CLRLQOINT1, 0);
113797883Sgibbs			}
1138107441Sscottl#ifdef AHD_DEBUG
1139107441Sscottl			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1140107441Sscottl				ahd_print_path(ahd, scb);
1141199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
1142107441Sscottl				printf("Unexpected command phase from "
1143107441Sscottl				       "packetized target\n");
1144107441Sscottl			}
1145107441Sscottl#endif
114697883Sgibbs			break;
114797883Sgibbs		}
114897883Sgibbs		}
114997883Sgibbs		break;
115097883Sgibbs	}
115197883Sgibbs	case CFG4OVERRUN:
1152107441Sscottl	{
1153107441Sscottl		struct	scb *scb;
1154107441Sscottl		u_int	scb_index;
1155107441Sscottl
1156107441Sscottl#ifdef AHD_DEBUG
1157107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1158107441Sscottl			printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd),
1159107441Sscottl			       ahd_inb(ahd, MODE_PTR));
1160107441Sscottl		}
1161107441Sscottl#endif
1162107441Sscottl		scb_index = ahd_get_scbptr(ahd);
1163107441Sscottl		scb = ahd_lookup_scb(ahd, scb_index);
1164107441Sscottl		if (scb == NULL) {
1165107441Sscottl			/*
1166107441Sscottl			 * Attempt to transfer to an SCB that is
1167107441Sscottl			 * not outstanding.
1168107441Sscottl			 */
1169107441Sscottl			ahd_assert_atn(ahd);
1170107441Sscottl			ahd_outb(ahd, MSG_OUT, HOST_MSG);
1171107441Sscottl			ahd->msgout_buf[0] = MSG_ABORT_TASK;
1172107441Sscottl			ahd->msgout_len = 1;
1173107441Sscottl			ahd->msgout_index = 0;
1174107441Sscottl			ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
1175107441Sscottl			/*
1176107441Sscottl			 * Clear status received flag to prevent any
1177107441Sscottl			 * attempt to complete this bogus SCB.
1178107441Sscottl			 */
1179107441Sscottl			ahd_outb(ahd, SCB_CONTROL,
1180116940Sgibbs				 ahd_inb_scbram(ahd, SCB_CONTROL)
1181116940Sgibbs				 & ~STATUS_RCVD);
1182107441Sscottl		}
118397883Sgibbs		break;
1184107441Sscottl	}
118597883Sgibbs	case DUMP_CARD_STATE:
118697883Sgibbs	{
118797883Sgibbs		ahd_dump_card_state(ahd);
118897883Sgibbs		break;
118997883Sgibbs	}
119097883Sgibbs	case PDATA_REINIT:
119197883Sgibbs	{
1192107441Sscottl#ifdef AHD_DEBUG
1193107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1194107441Sscottl			printf("%s: PDATA_REINIT - DFCNTRL = 0x%x "
1195107441Sscottl			       "SG_CACHE_SHADOW = 0x%x\n",
1196107441Sscottl			       ahd_name(ahd), ahd_inb(ahd, DFCNTRL),
1197107441Sscottl			       ahd_inb(ahd, SG_CACHE_SHADOW));
1198107441Sscottl		}
1199107441Sscottl#endif
120097883Sgibbs		ahd_reinitialize_dataptrs(ahd);
120197883Sgibbs		break;
120297883Sgibbs	}
120397883Sgibbs	case HOST_MSG_LOOP:
120497883Sgibbs	{
120597883Sgibbs		struct ahd_devinfo devinfo;
120697883Sgibbs
120797883Sgibbs		/*
120897883Sgibbs		 * The sequencer has encountered a message phase
120997883Sgibbs		 * that requires host assistance for completion.
121097883Sgibbs		 * While handling the message phase(s), we will be
121197883Sgibbs		 * notified by the sequencer after each byte is
121297883Sgibbs		 * transfered so we can track bus phase changes.
121397883Sgibbs		 *
121497883Sgibbs		 * If this is the first time we've seen a HOST_MSG_LOOP
121597883Sgibbs		 * interrupt, initialize the state of the host message
121697883Sgibbs		 * loop.
121797883Sgibbs		 */
121897883Sgibbs		ahd_fetch_devinfo(ahd, &devinfo);
121997883Sgibbs		if (ahd->msg_type == MSG_TYPE_NONE) {
122097883Sgibbs			struct scb *scb;
122197883Sgibbs			u_int scb_index;
122297883Sgibbs			u_int bus_phase;
122397883Sgibbs
122497883Sgibbs			bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
122597883Sgibbs			if (bus_phase != P_MESGIN
122697883Sgibbs			 && bus_phase != P_MESGOUT) {
122797883Sgibbs				printf("ahd_intr: HOST_MSG_LOOP bad "
1228107441Sscottl				       "phase 0x%x\n", bus_phase);
1229199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
123097883Sgibbs				/*
123197883Sgibbs				 * Probably transitioned to bus free before
123297883Sgibbs				 * we got here.  Just punt the message.
123397883Sgibbs				 */
123497883Sgibbs				ahd_dump_card_state(ahd);
123597883Sgibbs				ahd_clear_intstat(ahd);
123697883Sgibbs				ahd_restart(ahd);
123797883Sgibbs				return;
123897883Sgibbs			}
123997883Sgibbs
124097883Sgibbs			scb_index = ahd_get_scbptr(ahd);
124197883Sgibbs			scb = ahd_lookup_scb(ahd, scb_index);
124297883Sgibbs			if (devinfo.role == ROLE_INITIATOR) {
124397883Sgibbs				if (bus_phase == P_MESGOUT)
124497883Sgibbs					ahd_setup_initiator_msgout(ahd,
124597883Sgibbs								   &devinfo,
124697883Sgibbs								   scb);
124797883Sgibbs				else {
124897883Sgibbs					ahd->msg_type =
124997883Sgibbs					    MSG_TYPE_INITIATOR_MSGIN;
125097883Sgibbs					ahd->msgin_index = 0;
125197883Sgibbs				}
125297883Sgibbs			}
1253153072Sru#ifdef AHD_TARGET_MODE
125497883Sgibbs			else {
125597883Sgibbs				if (bus_phase == P_MESGOUT) {
125697883Sgibbs					ahd->msg_type =
125797883Sgibbs					    MSG_TYPE_TARGET_MSGOUT;
125897883Sgibbs					ahd->msgin_index = 0;
125997883Sgibbs				}
126097883Sgibbs				else
126197883Sgibbs					ahd_setup_target_msgin(ahd,
126297883Sgibbs							       &devinfo,
126397883Sgibbs							       scb);
126497883Sgibbs			}
126597883Sgibbs#endif
126697883Sgibbs		}
126797883Sgibbs
126897883Sgibbs		ahd_handle_message_phase(ahd);
126997883Sgibbs		break;
127097883Sgibbs	}
127197883Sgibbs	case NO_MATCH:
127297883Sgibbs	{
127397883Sgibbs		/* Ensure we don't leave the selection hardware on */
127497883Sgibbs		AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
127597883Sgibbs		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
127697883Sgibbs
127797883Sgibbs		printf("%s:%c:%d: no active SCB for reconnecting "
127897883Sgibbs		       "target - issuing BUS DEVICE RESET\n",
1279102679Sgibbs		       ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4);
128097883Sgibbs		printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "
1281102679Sgibbs		       "REG0 == 0x%x ACCUM = 0x%x\n",
128297883Sgibbs		       ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN),
1283102679Sgibbs		       ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM));
128497883Sgibbs		printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "
128597883Sgibbs		       "SINDEX == 0x%x\n",
128697883Sgibbs		       ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd),
128797883Sgibbs		       ahd_find_busy_tcl(ahd,
1288102679Sgibbs					 BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),
1289102679Sgibbs						   ahd_inb(ahd, SAVED_LUN))),
1290102679Sgibbs		       ahd_inw(ahd, SINDEX));
129197883Sgibbs		printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "
129297883Sgibbs		       "SCB_CONTROL == 0x%x\n",
129397883Sgibbs		       ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID),
129497883Sgibbs		       ahd_inb_scbram(ahd, SCB_LUN),
129597883Sgibbs		       ahd_inb_scbram(ahd, SCB_CONTROL));
129697883Sgibbs		printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n",
129797883Sgibbs		       ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI));
129897883Sgibbs		printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0));
129997883Sgibbs		printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0));
130097883Sgibbs		ahd_dump_card_state(ahd);
130197883Sgibbs		ahd->msgout_buf[0] = MSG_BUS_DEV_RESET;
130297883Sgibbs		ahd->msgout_len = 1;
130397883Sgibbs		ahd->msgout_index = 0;
130497883Sgibbs		ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
130597883Sgibbs		ahd_outb(ahd, MSG_OUT, HOST_MSG);
130697883Sgibbs		ahd_assert_atn(ahd);
130797883Sgibbs		break;
130897883Sgibbs	}
130997883Sgibbs	case PROTO_VIOLATION:
131097883Sgibbs	{
1311102679Sgibbs		ahd_handle_proto_violation(ahd);
1312102679Sgibbs		break;
131397883Sgibbs	}
131497883Sgibbs	case IGN_WIDE_RES:
131597883Sgibbs	{
131697883Sgibbs		struct ahd_devinfo devinfo;
131797883Sgibbs
131897883Sgibbs		ahd_fetch_devinfo(ahd, &devinfo);
131997883Sgibbs		ahd_handle_ign_wide_residue(ahd, &devinfo);
132097883Sgibbs		break;
132197883Sgibbs	}
132297883Sgibbs	case BAD_PHASE:
132397883Sgibbs	{
132497883Sgibbs		u_int lastphase;
132597883Sgibbs
132697883Sgibbs		lastphase = ahd_inb(ahd, LASTPHASE);
132797883Sgibbs		printf("%s:%c:%d: unknown scsi bus phase %x, "
132897883Sgibbs		       "lastphase = 0x%x.  Attempting to continue\n",
132997883Sgibbs		       ahd_name(ahd), 'A',
133097883Sgibbs		       SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
133197883Sgibbs		       lastphase, ahd_inb(ahd, SCSISIGI));
1332199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
133397883Sgibbs		break;
133497883Sgibbs	}
133597883Sgibbs	case MISSED_BUSFREE:
133697883Sgibbs	{
133797883Sgibbs		u_int lastphase;
133897883Sgibbs
133997883Sgibbs		lastphase = ahd_inb(ahd, LASTPHASE);
134097883Sgibbs		printf("%s:%c:%d: Missed busfree. "
134197883Sgibbs		       "Lastphase = 0x%x, Curphase = 0x%x\n",
134297883Sgibbs		       ahd_name(ahd), 'A',
134397883Sgibbs		       SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
134497883Sgibbs		       lastphase, ahd_inb(ahd, SCSISIGI));
1345199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
134697883Sgibbs		ahd_restart(ahd);
134797883Sgibbs		return;
134897883Sgibbs	}
134997883Sgibbs	case DATA_OVERRUN:
135097883Sgibbs	{
135197883Sgibbs		/*
135297883Sgibbs		 * When the sequencer detects an overrun, it
135397883Sgibbs		 * places the controller in "BITBUCKET" mode
135497883Sgibbs		 * and allows the target to complete its transfer.
135597883Sgibbs		 * Unfortunately, none of the counters get updated
135697883Sgibbs		 * when the controller is in this mode, so we have
135797883Sgibbs		 * no way of knowing how large the overrun was.
135897883Sgibbs		 */
135997883Sgibbs		struct	scb *scb;
1360107441Sscottl		u_int	scbindex;
1361107441Sscottl#ifdef AHD_DEBUG
1362107441Sscottl		u_int	lastphase;
1363107441Sscottl#endif
136497883Sgibbs
1365107441Sscottl		scbindex = ahd_get_scbptr(ahd);
136697883Sgibbs		scb = ahd_lookup_scb(ahd, scbindex);
1367107441Sscottl#ifdef AHD_DEBUG
1368107441Sscottl		lastphase = ahd_inb(ahd, LASTPHASE);
1369107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1370107441Sscottl			ahd_print_path(ahd, scb);
1371107441Sscottl			printf("data overrun detected %s.  Tag == 0x%x.\n",
1372107441Sscottl			       ahd_lookup_phase_entry(lastphase)->phasemsg,
1373107441Sscottl			       SCB_GET_TAG(scb));
1374107441Sscottl			ahd_print_path(ahd, scb);
1375107441Sscottl			printf("%s seen Data Phase.  Length = %ld.  "
1376107441Sscottl			       "NumSGs = %d.\n",
1377107441Sscottl			       ahd_inb(ahd, SEQ_FLAGS) & DPHASE
1378107441Sscottl			       ? "Have" : "Haven't",
1379123579Sgibbs			       aic_get_transfer_length(scb), scb->sg_count);
1380107441Sscottl			ahd_dump_sglist(scb);
1381107441Sscottl		}
1382107441Sscottl#endif
138397883Sgibbs
138497883Sgibbs		/*
138597883Sgibbs		 * Set this and it will take effect when the
138697883Sgibbs		 * target does a command complete.
138797883Sgibbs		 */
138897883Sgibbs		ahd_freeze_devq(ahd, scb);
1389123579Sgibbs		aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
1390123579Sgibbs		aic_freeze_scb(scb);
139197883Sgibbs		break;
139297883Sgibbs	}
139397883Sgibbs	case MKMSG_FAILED:
139497883Sgibbs	{
139597883Sgibbs		struct ahd_devinfo devinfo;
139697883Sgibbs		struct scb *scb;
139797883Sgibbs		u_int scbid;
139897883Sgibbs
139997883Sgibbs		ahd_fetch_devinfo(ahd, &devinfo);
140097883Sgibbs		printf("%s:%c:%d:%d: Attempt to issue message failed\n",
140197883Sgibbs		       ahd_name(ahd), devinfo.channel, devinfo.target,
140297883Sgibbs		       devinfo.lun);
140397883Sgibbs		scbid = ahd_get_scbptr(ahd);
140497883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1405199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
140697883Sgibbs		if (scb != NULL
140797883Sgibbs		 && (scb->flags & SCB_RECOVERY_SCB) != 0)
140897883Sgibbs			/*
140997883Sgibbs			 * Ensure that we didn't put a second instance of this
141097883Sgibbs			 * SCB into the QINFIFO.
141197883Sgibbs			 */
141297883Sgibbs			ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
141397883Sgibbs					   SCB_GET_CHANNEL(ahd, scb),
141497883Sgibbs					   SCB_GET_LUN(scb), SCB_GET_TAG(scb),
141597883Sgibbs					   ROLE_INITIATOR, /*status*/0,
141697883Sgibbs					   SEARCH_REMOVE);
141797883Sgibbs		ahd_outb(ahd, SCB_CONTROL,
1418116940Sgibbs			 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
141997883Sgibbs		break;
142097883Sgibbs	}
1421109588Sgibbs	case TASKMGMT_FUNC_COMPLETE:
1422109588Sgibbs	{
1423109588Sgibbs		u_int	scbid;
1424109588Sgibbs		struct	scb *scb;
1425109588Sgibbs
1426109588Sgibbs		scbid = ahd_get_scbptr(ahd);
1427109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1428109588Sgibbs		if (scb != NULL) {
1429109588Sgibbs			u_int	   lun;
1430109588Sgibbs			u_int	   tag;
1431109588Sgibbs			cam_status error;
1432109588Sgibbs
1433109588Sgibbs			ahd_print_path(ahd, scb);
1434109588Sgibbs			printf("Task Management Func 0x%x Complete\n",
1435109588Sgibbs			       scb->hscb->task_management);
1436109588Sgibbs			lun = CAM_LUN_WILDCARD;
1437109588Sgibbs			tag = SCB_LIST_NULL;
1438109588Sgibbs
1439109588Sgibbs			switch (scb->hscb->task_management) {
1440109588Sgibbs			case SIU_TASKMGMT_ABORT_TASK:
1441114623Sgibbs				tag = SCB_GET_TAG(scb);
1442109588Sgibbs			case SIU_TASKMGMT_ABORT_TASK_SET:
1443109588Sgibbs			case SIU_TASKMGMT_CLEAR_TASK_SET:
1444109588Sgibbs				lun = scb->hscb->lun;
1445109588Sgibbs				error = CAM_REQ_ABORTED;
1446109588Sgibbs				ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
1447109588Sgibbs					       'A', lun, tag, ROLE_INITIATOR,
1448109588Sgibbs					       error);
1449109588Sgibbs				break;
1450109588Sgibbs			case SIU_TASKMGMT_LUN_RESET:
1451109588Sgibbs				lun = scb->hscb->lun;
1452109588Sgibbs			case SIU_TASKMGMT_TARGET_RESET:
1453109588Sgibbs			{
1454109588Sgibbs				struct ahd_devinfo devinfo;
1455109588Sgibbs
1456109588Sgibbs				ahd_scb_devinfo(ahd, &devinfo, scb);
1457109588Sgibbs				error = CAM_BDR_SENT;
1458109588Sgibbs				ahd_handle_devreset(ahd, &devinfo, lun,
1459109588Sgibbs						    CAM_BDR_SENT,
1460109588Sgibbs						    lun != CAM_LUN_WILDCARD
1461109588Sgibbs						    ? "Lun Reset"
1462109588Sgibbs						    : "Target Reset",
1463109588Sgibbs						    /*verbose_level*/0);
1464109588Sgibbs				break;
1465109588Sgibbs			}
1466109588Sgibbs			default:
1467109588Sgibbs				panic("Unexpected TaskMgmt Func\n");
1468109588Sgibbs				break;
1469109588Sgibbs			}
1470109588Sgibbs		}
1471109588Sgibbs		break;
1472109588Sgibbs	}
1473109588Sgibbs	case TASKMGMT_CMD_CMPLT_OKAY:
1474109588Sgibbs	{
1475109588Sgibbs		u_int	scbid;
1476109588Sgibbs		struct	scb *scb;
1477109588Sgibbs
1478109588Sgibbs		/*
1479109588Sgibbs		 * An ABORT TASK TMF failed to be delivered before
1480109588Sgibbs		 * the targeted command completed normally.
1481109588Sgibbs		 */
1482109588Sgibbs		scbid = ahd_get_scbptr(ahd);
1483109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1484109588Sgibbs		if (scb != NULL) {
1485109588Sgibbs			/*
1486109588Sgibbs			 * Remove the second instance of this SCB from
1487109588Sgibbs			 * the QINFIFO if it is still there.
1488109588Sgibbs                         */
1489109588Sgibbs			ahd_print_path(ahd, scb);
1490109588Sgibbs			printf("SCB completes before TMF\n");
1491109588Sgibbs			/*
1492109588Sgibbs			 * Handle losing the race.  Wait until any
1493109588Sgibbs			 * current selection completes.  We will then
1494109588Sgibbs			 * set the TMF back to zero in this SCB so that
1495109588Sgibbs			 * the sequencer doesn't bother to issue another
1496109588Sgibbs			 * sequencer interrupt for its completion.
1497109588Sgibbs			 */
1498109588Sgibbs			while ((ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
1499109588Sgibbs			    && (ahd_inb(ahd, SSTAT0) & SELDO) == 0
1500109588Sgibbs			    && (ahd_inb(ahd, SSTAT1) & SELTO) == 0)
1501109588Sgibbs				;
1502109588Sgibbs			ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0);
1503109588Sgibbs			ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
1504109588Sgibbs					   SCB_GET_CHANNEL(ahd, scb),
1505114623Sgibbs					   SCB_GET_LUN(scb), SCB_GET_TAG(scb),
1506109588Sgibbs					   ROLE_INITIATOR, /*status*/0,
1507109588Sgibbs					   SEARCH_REMOVE);
1508109588Sgibbs		}
1509109588Sgibbs		break;
1510109588Sgibbs	}
1511107441Sscottl	case TRACEPOINT0:
1512107441Sscottl	case TRACEPOINT1:
1513107441Sscottl	case TRACEPOINT2:
1514107441Sscottl	case TRACEPOINT3:
1515107441Sscottl		printf("%s: Tracepoint %d\n", ahd_name(ahd),
1516107441Sscottl		       seqintcode - TRACEPOINT0);
1517107441Sscottl		break;
1518107441Sscottl	case NO_SEQINT:
1519107441Sscottl		break;
1520107441Sscottl	case SAW_HWERR:
1521107441Sscottl		ahd_handle_hwerrint(ahd);
1522107441Sscottl		break;
1523102679Sgibbs	default:
1524102679Sgibbs		printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd),
1525102679Sgibbs		       seqintcode);
1526102679Sgibbs		break;
152797883Sgibbs	}
152897883Sgibbs	/*
152997883Sgibbs	 *  The sequencer is paused immediately on
153097883Sgibbs	 *  a SEQINT, so we should restart it when
153197883Sgibbs	 *  we're done.
153297883Sgibbs	 */
153397883Sgibbs	ahd_unpause(ahd);
153497883Sgibbs}
153597883Sgibbs
153697883Sgibbsvoid
153797883Sgibbsahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
153897883Sgibbs{
153997883Sgibbs	struct scb	*scb;
154097883Sgibbs	u_int		 status0;
154197883Sgibbs	u_int		 status3;
154297883Sgibbs	u_int		 status;
154397883Sgibbs	u_int		 lqistat1;
154497883Sgibbs	u_int		 lqostat0;
154597883Sgibbs	u_int		 scbid;
1546107441Sscottl	u_int		 busfreetime;
154797883Sgibbs
154897883Sgibbs	ahd_update_modes(ahd);
154997883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
155097883Sgibbs
155197883Sgibbs	status3 = ahd_inb(ahd, SSTAT3) & (NTRAMPERR|OSRAMPERR);
155297883Sgibbs	status0 = ahd_inb(ahd, SSTAT0) & (IOERR|OVERRUN|SELDI|SELDO);
155397883Sgibbs	status = ahd_inb(ahd, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);
155497883Sgibbs	lqistat1 = ahd_inb(ahd, LQISTAT1);
155597883Sgibbs	lqostat0 = ahd_inb(ahd, LQOSTAT0);
1556107441Sscottl	busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
155797883Sgibbs	if ((status0 & (SELDI|SELDO)) != 0) {
155897883Sgibbs		u_int simode0;
155997883Sgibbs
156097883Sgibbs		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
156197883Sgibbs		simode0 = ahd_inb(ahd, SIMODE0);
1562102679Sgibbs		status0 &= simode0 & (IOERR|OVERRUN|SELDI|SELDO);
156397883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
156497883Sgibbs	}
156597883Sgibbs	scbid = ahd_get_scbptr(ahd);
156697883Sgibbs	scb = ahd_lookup_scb(ahd, scbid);
156797883Sgibbs	if (scb != NULL
156897883Sgibbs	 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
156997883Sgibbs		scb = NULL;
157097883Sgibbs
157197883Sgibbs	if ((status0 & IOERR) != 0) {
1572102679Sgibbs		u_int now_lvd;
157397883Sgibbs
157497883Sgibbs		now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40;
157597883Sgibbs		printf("%s: Transceiver State Has Changed to %s mode\n",
157697883Sgibbs		       ahd_name(ahd), now_lvd ? "LVD" : "SE");
157797883Sgibbs		ahd_outb(ahd, CLRSINT0, CLRIOERR);
157897883Sgibbs		/*
1579102679Sgibbs		 * A change in I/O mode is equivalent to a bus reset.
158097883Sgibbs		 */
1581114623Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
158297883Sgibbs		ahd_pause(ahd);
158397883Sgibbs		ahd_setup_iocell_workaround(ahd);
158497883Sgibbs		ahd_unpause(ahd);
158597883Sgibbs	} else if ((status0 & OVERRUN) != 0) {
1586129134Sgibbs
158797883Sgibbs		printf("%s: SCSI offset overrun detected.  Resetting bus.\n",
158897883Sgibbs		       ahd_name(ahd));
1589199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
159097883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
159197883Sgibbs	} else if ((status & SCSIRSTI) != 0) {
1592129134Sgibbs
159397883Sgibbs		printf("%s: Someone reset channel A\n", ahd_name(ahd));
159497883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
1595199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
159697883Sgibbs	} else if ((status & SCSIPERR) != 0) {
1597129134Sgibbs
1598129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1599129134Sgibbs		ahd_clear_critical_section(ahd);
1600129134Sgibbs
160197883Sgibbs		ahd_handle_transmission_error(ahd);
160297883Sgibbs	} else if (lqostat0 != 0) {
1603129134Sgibbs
160497883Sgibbs		printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
160597883Sgibbs		ahd_outb(ahd, CLRLQOINT0, lqostat0);
1606129134Sgibbs		if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
160797883Sgibbs			ahd_outb(ahd, CLRLQOINT1, 0);
160897883Sgibbs	} else if ((status & SELTO) != 0) {
1609107441Sscottl		u_int  scbid;
161097883Sgibbs
161197883Sgibbs		/* Stop the selection */
161297883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
161397883Sgibbs
1614129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1615129134Sgibbs		ahd_clear_critical_section(ahd);
1616129134Sgibbs
161797883Sgibbs		/* No more pending messages */
161897883Sgibbs		ahd_clear_msg_state(ahd);
161997883Sgibbs
162097883Sgibbs		/* Clear interrupt state */
162197883Sgibbs		ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
162297883Sgibbs
162397883Sgibbs		/*
162497883Sgibbs		 * Although the driver does not care about the
162597883Sgibbs		 * 'Selection in Progress' status bit, the busy
162697883Sgibbs		 * LED does.  SELINGO is only cleared by a sucessfull
162797883Sgibbs		 * selection, so we must manually clear it to insure
162897883Sgibbs		 * the LED turns off just incase no future successful
162997883Sgibbs		 * selections occur (e.g. no devices on the bus).
163097883Sgibbs		 */
163197883Sgibbs		ahd_outb(ahd, CLRSINT0, CLRSELINGO);
163297883Sgibbs
163397883Sgibbs		scbid = ahd_inw(ahd, WAITING_TID_HEAD);
163497883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
163597883Sgibbs		if (scb == NULL) {
163697883Sgibbs			printf("%s: ahd_intr - referenced scb not "
163797883Sgibbs			       "valid during SELTO scb(0x%x)\n",
163897883Sgibbs			       ahd_name(ahd), scbid);
163997883Sgibbs			ahd_dump_card_state(ahd);
1640199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
164197883Sgibbs		} else {
1642107441Sscottl			struct ahd_devinfo devinfo;
1643104023Sgibbs#ifdef AHD_DEBUG
1644104023Sgibbs			if ((ahd_debug & AHD_SHOW_SELTO) != 0) {
1645104023Sgibbs				ahd_print_path(ahd, scb);
1646104023Sgibbs				printf("Saw Selection Timeout for SCB 0x%x\n",
1647104023Sgibbs				       scbid);
1648104023Sgibbs			}
1649104023Sgibbs#endif
1650107441Sscottl			ahd_scb_devinfo(ahd, &devinfo, scb);
1651123579Sgibbs			aic_set_transaction_status(scb, CAM_SEL_TIMEOUT);
165297883Sgibbs			ahd_freeze_devq(ahd, scb);
1653129134Sgibbs
1654129134Sgibbs			/*
1655129134Sgibbs			 * Cancel any pending transactions on the device
1656129134Sgibbs			 * now that it seems to be missing.  This will
1657129134Sgibbs			 * also revert us to async/narrow transfers until
1658129134Sgibbs			 * we can renegotiate with the device.
1659129134Sgibbs			 */
1660129134Sgibbs			ahd_handle_devreset(ahd, &devinfo,
1661129134Sgibbs					    CAM_LUN_WILDCARD,
1662129134Sgibbs					    CAM_SEL_TIMEOUT,
1663129134Sgibbs					    "Selection Timeout",
1664129134Sgibbs					    /*verbose_level*/1);
166597883Sgibbs		}
166697883Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
166797883Sgibbs		ahd_iocell_first_selection(ahd);
1668109588Sgibbs		ahd_unpause(ahd);
166997883Sgibbs	} else if ((status0 & (SELDI|SELDO)) != 0) {
1670129134Sgibbs
167197883Sgibbs		ahd_iocell_first_selection(ahd);
167297883Sgibbs		ahd_unpause(ahd);
167397883Sgibbs	} else if (status3 != 0) {
167497883Sgibbs		printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n",
167597883Sgibbs		       ahd_name(ahd), status3);
1676199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
167797883Sgibbs		ahd_outb(ahd, CLRSINT3, status3);
167897883Sgibbs	} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
1679129134Sgibbs
1680129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1681129134Sgibbs		ahd_clear_critical_section(ahd);
1682129134Sgibbs
168397883Sgibbs		ahd_handle_lqiphase_error(ahd, lqistat1);
1684111653Sgibbs	} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
1685111653Sgibbs		/*
1686111653Sgibbs		 * This status can be delayed during some
1687111653Sgibbs		 * streaming operations.  The SCSIPHASE
1688111653Sgibbs		 * handler has already dealt with this case
1689111653Sgibbs		 * so just clear the error.
1690111653Sgibbs		 */
1691111653Sgibbs		ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);
1692133122Sgibbs	} else if ((status & BUSFREE) != 0
1693133122Sgibbs		|| (lqistat1 & LQOBUSFREE) != 0) {
169497883Sgibbs		u_int lqostat1;
169597883Sgibbs		int   restart;
169697883Sgibbs		int   clear_fifo;
169797883Sgibbs		int   packetized;
169897883Sgibbs		u_int mode;
169997883Sgibbs
170097883Sgibbs		/*
170197883Sgibbs		 * Clear our selection hardware as soon as possible.
170297883Sgibbs		 * We may have an entry in the waiting Q for this target,
170397883Sgibbs		 * that is affected by this busfree and we don't want to
170497883Sgibbs		 * go about selecting the target while we handle the event.
170597883Sgibbs		 */
170697883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
170797883Sgibbs
1708129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1709129134Sgibbs		ahd_clear_critical_section(ahd);
1710129134Sgibbs
171197883Sgibbs		/*
171297883Sgibbs		 * Determine what we were up to at the time of
171397883Sgibbs		 * the busfree.
171497883Sgibbs		 */
171597883Sgibbs		mode = AHD_MODE_SCSI;
171697883Sgibbs		busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
171797883Sgibbs		lqostat1 = ahd_inb(ahd, LQOSTAT1);
171897883Sgibbs		switch (busfreetime) {
171997883Sgibbs		case BUSFREE_DFF0:
172097883Sgibbs		case BUSFREE_DFF1:
172197883Sgibbs		{
172297883Sgibbs			u_int	scbid;
172397883Sgibbs			struct	scb *scb;
172497883Sgibbs
172597883Sgibbs			mode = busfreetime == BUSFREE_DFF0
172697883Sgibbs			     ? AHD_MODE_DFF0 : AHD_MODE_DFF1;
172797883Sgibbs			ahd_set_modes(ahd, mode, mode);
172897883Sgibbs			scbid = ahd_get_scbptr(ahd);
172997883Sgibbs			scb = ahd_lookup_scb(ahd, scbid);
173097883Sgibbs			if (scb == NULL) {
1731114623Sgibbs				printf("%s: Invalid SCB %d in DFF%d "
173297883Sgibbs				       "during unexpected busfree\n",
1733114623Sgibbs				       ahd_name(ahd), scbid, mode);
173497883Sgibbs				packetized = 0;
1735199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
173697883Sgibbs			} else
173797883Sgibbs				packetized = (scb->flags & SCB_PACKETIZED) != 0;
173897883Sgibbs			clear_fifo = 1;
173997883Sgibbs			break;
174097883Sgibbs		}
174197883Sgibbs		case BUSFREE_LQO:
174297883Sgibbs			clear_fifo = 0;
174397883Sgibbs			packetized = 1;
174497883Sgibbs			break;
174597883Sgibbs		default:
174697883Sgibbs			clear_fifo = 0;
174797883Sgibbs			packetized =  (lqostat1 & LQOBUSFREE) != 0;
174897883Sgibbs			if (!packetized
1749125448Sgibbs			 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
1750129134Sgibbs			 && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
1751125448Sgibbs			 && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
1752125448Sgibbs			  || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
1753125448Sgibbs				/*
1754125448Sgibbs				 * Assume packetized if we are not
1755125448Sgibbs				 * on the bus in a non-packetized
1756125448Sgibbs				 * capacity and any pending selection
1757125448Sgibbs				 * was a packetized selection.
1758125448Sgibbs				 */
175997883Sgibbs				packetized = 1;
176097883Sgibbs			break;
176197883Sgibbs		}
176297883Sgibbs
176397883Sgibbs#ifdef AHD_DEBUG
176497883Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
176597883Sgibbs			printf("Saw Busfree.  Busfreetime = 0x%x.\n",
176697883Sgibbs			       busfreetime);
176797883Sgibbs#endif
176897883Sgibbs		/*
176997883Sgibbs		 * Busfrees that occur in non-packetized phases are
177097883Sgibbs		 * handled by the nonpkt_busfree handler.
177197883Sgibbs		 */
177297883Sgibbs		if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) {
177397883Sgibbs			restart = ahd_handle_pkt_busfree(ahd, busfreetime);
177497883Sgibbs		} else {
1775104023Sgibbs			packetized = 0;
177697883Sgibbs			restart = ahd_handle_nonpkt_busfree(ahd);
177797883Sgibbs		}
177897883Sgibbs		/*
177997883Sgibbs		 * Clear the busfree interrupt status.  The setting of
1780104023Sgibbs		 * the interrupt is a pulse, so in a perfect world, we
1781104023Sgibbs		 * would not need to muck with the ENBUSFREE logic.  This
1782104023Sgibbs		 * would ensure that if the bus moves on to another
1783104023Sgibbs		 * connection, busfree protection is still in force.  If
1784104023Sgibbs		 * BUSFREEREV is broken, however, we must manually clear
1785104023Sgibbs		 * the ENBUSFREE if the busfree occurred during a non-pack
1786104023Sgibbs		 * connection so that we don't get false positives during
1787104023Sgibbs		 * future, packetized, connections.
178897883Sgibbs		 */
1789104023Sgibbs		ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
1790104023Sgibbs		if (packetized == 0
1791104023Sgibbs		 && (ahd->bugs & AHD_BUSFREEREV_BUG) != 0)
1792104023Sgibbs			ahd_outb(ahd, SIMODE1,
1793104023Sgibbs				 ahd_inb(ahd, SIMODE1) & ~ENBUSFREE);
179497883Sgibbs
179597883Sgibbs		if (clear_fifo)
179697883Sgibbs			ahd_clear_fifo(ahd, mode);
179797883Sgibbs
179897883Sgibbs		ahd_clear_msg_state(ahd);
1799104023Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
1800102679Sgibbs		if (restart) {
180197883Sgibbs			ahd_restart(ahd);
1802102679Sgibbs		} else {
180397883Sgibbs			ahd_unpause(ahd);
180497883Sgibbs		}
180597883Sgibbs	} else {
180697883Sgibbs		printf("%s: Missing case in ahd_handle_scsiint. status = %x\n",
180797883Sgibbs		       ahd_name(ahd), status);
180897883Sgibbs		ahd_dump_card_state(ahd);
1809102679Sgibbs		ahd_clear_intstat(ahd);
181097883Sgibbs		ahd_unpause(ahd);
181197883Sgibbs	}
181297883Sgibbs}
181397883Sgibbs
181497883Sgibbsstatic void
181597883Sgibbsahd_handle_transmission_error(struct ahd_softc *ahd)
181697883Sgibbs{
1817107441Sscottl	struct	scb *scb;
1818107441Sscottl	u_int	scbid;
1819104023Sgibbs	u_int	lqistat1;
1820104023Sgibbs	u_int	lqistat2;
1821104023Sgibbs	u_int	msg_out;
1822104023Sgibbs	u_int	curphase;
1823104023Sgibbs	u_int	lastphase;
1824104023Sgibbs	u_int	perrdiag;
1825104023Sgibbs	u_int	cur_col;
1826109588Sgibbs	int	silent;
182797883Sgibbs
1828107441Sscottl	scb = NULL;
182997883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
183097883Sgibbs	lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);
183197883Sgibbs	lqistat2 = ahd_inb(ahd, LQISTAT2);
183297883Sgibbs	if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0
183397883Sgibbs	 && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) {
183497883Sgibbs		u_int lqistate;
183597883Sgibbs
183697883Sgibbs		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
183797883Sgibbs		lqistate = ahd_inb(ahd, LQISTATE);
183897883Sgibbs		if ((lqistate >= 0x1E && lqistate <= 0x24)
183997883Sgibbs		 || (lqistate == 0x29)) {
1840107441Sscottl#ifdef AHD_DEBUG
1841107441Sscottl			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1842107441Sscottl				printf("%s: NLQCRC found via LQISTATE\n",
1843107441Sscottl				       ahd_name(ahd));
1844107441Sscottl			}
1845107441Sscottl#endif
184697883Sgibbs			lqistat1 |= LQICRCI_NLQ;
184797883Sgibbs		}
184897883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
184997883Sgibbs	}
185097883Sgibbs
185197883Sgibbs	ahd_outb(ahd, CLRLQIINT1, lqistat1);
185297883Sgibbs	lastphase = ahd_inb(ahd, LASTPHASE);
185397883Sgibbs	curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
185497883Sgibbs	perrdiag = ahd_inb(ahd, PERRDIAG);
185597883Sgibbs	msg_out = MSG_INITIATOR_DET_ERR;
185697883Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSCSIPERR);
1857109588Sgibbs
1858109588Sgibbs	/*
1859109588Sgibbs	 * Try to find the SCB associated with this error.
1860109588Sgibbs	 */
1861109588Sgibbs	silent = FALSE;
1862109588Sgibbs	if (lqistat1 == 0
1863109588Sgibbs	 || (lqistat1 & LQICRCI_NLQ) != 0) {
1864109588Sgibbs	 	if ((lqistat1 & (LQICRCI_NLQ|LQIOVERI_NLQ)) != 0)
1865109588Sgibbs			ahd_set_active_fifo(ahd);
1866109588Sgibbs		scbid = ahd_get_scbptr(ahd);
1867109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1868109588Sgibbs		if (scb != NULL && SCB_IS_SILENT(scb))
1869109588Sgibbs			silent = TRUE;
1870109588Sgibbs	}
1871109588Sgibbs
1872104023Sgibbs	cur_col = 0;
1873109588Sgibbs	if (silent == FALSE) {
1874109588Sgibbs		printf("%s: Transmission error detected\n", ahd_name(ahd));
1875109588Sgibbs		ahd_lqistat1_print(lqistat1, &cur_col, 50);
1876109588Sgibbs		ahd_lastphase_print(lastphase, &cur_col, 50);
1877109588Sgibbs		ahd_scsisigi_print(curphase, &cur_col, 50);
1878109588Sgibbs		ahd_perrdiag_print(perrdiag, &cur_col, 50);
1879109588Sgibbs		printf("\n");
1880199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
1881109588Sgibbs		ahd_dump_card_state(ahd);
1882109588Sgibbs	}
1883109588Sgibbs
188497883Sgibbs	if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) {
1885109588Sgibbs		if (silent == FALSE) {
1886109588Sgibbs			printf("%s: Gross protocol error during incoming "
1887109588Sgibbs			       "packet.  lqistat1 == 0x%x.  Resetting bus.\n",
1888109588Sgibbs			       ahd_name(ahd), lqistat1);
1889199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
1890109588Sgibbs		}
189197883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
189297883Sgibbs		return;
189397883Sgibbs	} else if ((lqistat1 & LQICRCI_LQ) != 0) {
189497883Sgibbs		/*
189597883Sgibbs		 * A CRC error has been detected on an incoming LQ.
189697883Sgibbs		 * The bus is currently hung on the last ACK.
189797883Sgibbs		 * Hit LQIRETRY to release the last ack, and
189897883Sgibbs		 * wait for the sequencer to determine that ATNO
189997883Sgibbs		 * is asserted while in message out to take us
190097883Sgibbs		 * to our host message loop.  No NONPACKREQ or
190197883Sgibbs		 * LQIPHASE type errors will occur in this
190297883Sgibbs		 * scenario.  After this first LQIRETRY, the LQI
190397883Sgibbs		 * manager will be in ISELO where it will
190497883Sgibbs		 * happily sit until another packet phase begins.
190597883Sgibbs		 * Unexpected bus free detection is enabled
190697883Sgibbs		 * through any phases that occur after we release
190797883Sgibbs		 * this last ack until the LQI manager sees a
190897883Sgibbs		 * packet phase.  This implies we may have to
190997883Sgibbs		 * ignore a perfectly valid "unexected busfree"
191097883Sgibbs		 * after our "initiator detected error" message is
191197883Sgibbs		 * sent.  A busfree is the expected response after
191297883Sgibbs		 * we tell the target that it's L_Q was corrupted.
191397883Sgibbs		 * (SPI4R09 10.7.3.3.3)
191497883Sgibbs		 */
191597883Sgibbs		ahd_outb(ahd, LQCTL2, LQIRETRY);
191697883Sgibbs		printf("LQIRetry for LQICRCI_LQ to release ACK\n");
1917199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
191897883Sgibbs	} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
191997883Sgibbs		/*
192097883Sgibbs		 * We detected a CRC error in a NON-LQ packet.
192197883Sgibbs		 * The hardware has varying behavior in this situation
192297883Sgibbs		 * depending on whether this packet was part of a
192397883Sgibbs		 * stream or not.
192497883Sgibbs		 *
192597883Sgibbs		 * PKT by PKT mode:
192697883Sgibbs		 * The hardware has already acked the complete packet.
192797883Sgibbs		 * If the target honors our outstanding ATN condition,
192897883Sgibbs		 * we should be (or soon will be) in MSGOUT phase.
192997883Sgibbs		 * This will trigger the LQIPHASE_LQ status bit as the
193097883Sgibbs		 * hardware was expecting another LQ.  Unexpected
193197883Sgibbs		 * busfree detection is enabled.  Once LQIPHASE_LQ is
193297883Sgibbs		 * true (first entry into host message loop is much
193397883Sgibbs		 * the same), we must clear LQIPHASE_LQ and hit
193497883Sgibbs		 * LQIRETRY so the hardware is ready to handle
193597883Sgibbs		 * a future LQ.  NONPACKREQ will not be asserted again
193697883Sgibbs		 * once we hit LQIRETRY until another packet is
193797883Sgibbs		 * processed.  The target may either go busfree
193897883Sgibbs		 * or start another packet in response to our message.
193997883Sgibbs		 *
194097883Sgibbs		 * Read Streaming P0 asserted:
194197883Sgibbs		 * If we raise ATN and the target completes the entire
194297883Sgibbs		 * stream (P0 asserted during the last packet), the
194397883Sgibbs		 * hardware will ack all data and return to the ISTART
194497883Sgibbs		 * state.  When the target reponds to our ATN condition,
194597883Sgibbs		 * LQIPHASE_LQ will be asserted.  We should respond to
194697883Sgibbs		 * this with an LQIRETRY to prepare for any future
194797883Sgibbs		 * packets.  NONPACKREQ will not be asserted again
194897883Sgibbs		 * once we hit LQIRETRY until another packet is
194997883Sgibbs		 * processed.  The target may either go busfree or
195097883Sgibbs		 * start another packet in response to our message.
195197883Sgibbs		 * Busfree detection is enabled.
195297883Sgibbs		 *
195397883Sgibbs		 * Read Streaming P0 not asserted:
195497883Sgibbs		 * If we raise ATN and the target transitions to
195597883Sgibbs		 * MSGOUT in or after a packet where P0 is not
195697883Sgibbs		 * asserted, the hardware will assert LQIPHASE_NLQ.
195797883Sgibbs		 * We should respond to the LQIPHASE_NLQ with an
1958107441Sscottl		 * LQIRETRY.  Should the target stay in a non-pkt
195997883Sgibbs		 * phase after we send our message, the hardware
196097883Sgibbs		 * will assert LQIPHASE_LQ.  Recovery is then just as
196197883Sgibbs		 * listed above for the read streaming with P0 asserted.
196297883Sgibbs		 * Busfree detection is enabled.
196397883Sgibbs		 */
1964109588Sgibbs		if (silent == FALSE)
1965109588Sgibbs			printf("LQICRC_NLQ\n");
196697883Sgibbs		if (scb == NULL) {
196797883Sgibbs			printf("%s: No SCB valid for LQICRC_NLQ.  "
196897883Sgibbs			       "Resetting bus\n", ahd_name(ahd));
1969199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
197097883Sgibbs			ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
197197883Sgibbs			return;
197297883Sgibbs		}
197397883Sgibbs	} else if ((lqistat1 & LQIBADLQI) != 0) {
197497883Sgibbs		printf("Need to handle BADLQI!\n");
197597883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
197697883Sgibbs		return;
1977102679Sgibbs	} else if ((perrdiag & (PARITYERR|PREVPHASE)) == PARITYERR) {
197897883Sgibbs		if ((curphase & ~P_DATAIN_DT) != 0) {
197997883Sgibbs			/* Ack the byte.  So we can continue. */
1980109588Sgibbs			if (silent == FALSE)
1981109588Sgibbs				printf("Acking %s to clear perror\n",
1982109588Sgibbs				    ahd_lookup_phase_entry(curphase)->phasemsg);
198397883Sgibbs			ahd_inb(ahd, SCSIDAT);
198497883Sgibbs		}
198597883Sgibbs
198697883Sgibbs		if (curphase == P_MESGIN)
198797883Sgibbs			msg_out = MSG_PARITY_ERROR;
198897883Sgibbs	}
198997883Sgibbs
199097883Sgibbs	/*
199197883Sgibbs	 * We've set the hardware to assert ATN if we
199297883Sgibbs	 * get a parity error on "in" phases, so all we
199397883Sgibbs	 * need to do is stuff the message buffer with
199497883Sgibbs	 * the appropriate message.  "In" phases have set
199597883Sgibbs	 * mesg_out to something other than MSG_NOP.
199697883Sgibbs	 */
199797883Sgibbs	ahd->send_msg_perror = msg_out;
1998107441Sscottl	if (scb != NULL && msg_out == MSG_INITIATOR_DET_ERR)
1999107441Sscottl		scb->flags |= SCB_TRANSMISSION_ERROR;
200097883Sgibbs	ahd_outb(ahd, MSG_OUT, HOST_MSG);
200197883Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
200297883Sgibbs	ahd_unpause(ahd);
200397883Sgibbs}
200497883Sgibbs
200597883Sgibbsstatic void
200697883Sgibbsahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)
200797883Sgibbs{
200897883Sgibbs	/*
200997883Sgibbs	 * Clear the sources of the interrupts.
201097883Sgibbs	 */
201197883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
201297883Sgibbs	ahd_outb(ahd, CLRLQIINT1, lqistat1);
201397883Sgibbs
201497883Sgibbs	/*
201597883Sgibbs	 * If the "illegal" phase changes were in response
201697883Sgibbs	 * to our ATN to flag a CRC error, AND we ended up
201797883Sgibbs	 * on packet boundaries, clear the error, restart the
201897883Sgibbs	 * LQI manager as appropriate, and go on our merry
201997883Sgibbs	 * way toward sending the message.  Otherwise, reset
202097883Sgibbs	 * the bus to clear the error.
202197883Sgibbs	 */
202297883Sgibbs	ahd_set_active_fifo(ahd);
202397883Sgibbs	if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0
202497883Sgibbs	 && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) {
202597883Sgibbs		if ((lqistat1 & LQIPHASE_LQ) != 0) {
202697883Sgibbs			printf("LQIRETRY for LQIPHASE_LQ\n");
2027199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
202897883Sgibbs			ahd_outb(ahd, LQCTL2, LQIRETRY);
202997883Sgibbs		} else if ((lqistat1 & LQIPHASE_NLQ) != 0) {
2030107441Sscottl			printf("LQIRETRY for LQIPHASE_NLQ\n");
2031199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
203297883Sgibbs			ahd_outb(ahd, LQCTL2, LQIRETRY);
203397883Sgibbs		} else
203497883Sgibbs			panic("ahd_handle_lqiphase_error: No phase errors\n");
203597883Sgibbs		ahd_dump_card_state(ahd);
203697883Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
203797883Sgibbs		ahd_unpause(ahd);
203897883Sgibbs	} else {
203997883Sgibbs		printf("Reseting Channel for LQI Phase error\n");
2040199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
204197883Sgibbs		ahd_dump_card_state(ahd);
204297883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
204397883Sgibbs	}
204497883Sgibbs}
204597883Sgibbs
204697883Sgibbs/*
204797883Sgibbs * Packetized unexpected or expected busfree.
2048104023Sgibbs * Entered in mode based on busfreetime.
204997883Sgibbs */
205097883Sgibbsstatic int
205197883Sgibbsahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
205297883Sgibbs{
205397883Sgibbs	u_int lqostat1;
205497883Sgibbs
205597883Sgibbs	AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
205697883Sgibbs			 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
205797883Sgibbs	lqostat1 = ahd_inb(ahd, LQOSTAT1);
205897883Sgibbs	if ((lqostat1 & LQOBUSFREE) != 0) {
205997883Sgibbs		struct scb *scb;
206097883Sgibbs		u_int scbid;
2061104023Sgibbs		u_int saved_scbptr;
206297883Sgibbs		u_int waiting_h;
206397883Sgibbs		u_int waiting_t;
206497883Sgibbs		u_int next;
206597883Sgibbs
2066104023Sgibbs		/*
2067104023Sgibbs		 * The LQO manager detected an unexpected busfree
2068104023Sgibbs		 * either:
2069104023Sgibbs		 *
2070104023Sgibbs		 * 1) During an outgoing LQ.
2071104023Sgibbs		 * 2) After an outgoing LQ but before the first
2072104023Sgibbs		 *    REQ of the command packet.
2073104023Sgibbs		 * 3) During an outgoing command packet.
2074104023Sgibbs		 *
2075104023Sgibbs		 * In all cases, CURRSCB is pointing to the
2076104023Sgibbs		 * SCB that encountered the failure.  Clean
2077104023Sgibbs		 * up the queue, clear SELDO and LQOBUSFREE,
2078104023Sgibbs		 * and allow the sequencer to restart the select
2079104023Sgibbs		 * out at its lesure.
2080104023Sgibbs		 */
2081104023Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2082104023Sgibbs		scbid = ahd_inw(ahd, CURRSCB);
208397883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
208497883Sgibbs		if (scb == NULL)
208597883Sgibbs		       panic("SCB not valid during LQOBUSFREE");
208697883Sgibbs		/*
208797883Sgibbs		 * Clear the status.
208897883Sgibbs		 */
208997883Sgibbs		ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE);
2090104023Sgibbs		if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
209197883Sgibbs			ahd_outb(ahd, CLRLQOINT1, 0);
2092104023Sgibbs		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
2093111653Sgibbs		ahd_flush_device_writes(ahd);
2094104023Sgibbs		ahd_outb(ahd, CLRSINT0, CLRSELDO);
2095104023Sgibbs
209697883Sgibbs		/*
2097111653Sgibbs		 * Return the LQO manager to its idle loop.  It will
2098111653Sgibbs		 * not do this automatically if the busfree occurs
2099111653Sgibbs		 * after the first REQ of either the LQ or command
2100111653Sgibbs		 * packet or between the LQ and command packet.
2101111653Sgibbs		 */
2102111653Sgibbs		ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE);
2103111653Sgibbs
2104111653Sgibbs		/*
2105104023Sgibbs		 * Update the waiting for selection queue so
2106104023Sgibbs		 * we restart on the correct SCB.
210797883Sgibbs		 */
210897883Sgibbs		waiting_h = ahd_inw(ahd, WAITING_TID_HEAD);
2109104023Sgibbs		saved_scbptr = ahd_get_scbptr(ahd);
211097883Sgibbs		if (waiting_h != scbid) {
211197883Sgibbs
211297883Sgibbs			ahd_outw(ahd, WAITING_TID_HEAD, scbid);
211397883Sgibbs			waiting_t = ahd_inw(ahd, WAITING_TID_TAIL);
211497883Sgibbs			if (waiting_t == waiting_h) {
211597883Sgibbs				ahd_outw(ahd, WAITING_TID_TAIL, scbid);
2116111653Sgibbs				next = SCB_LIST_NULL;
211797883Sgibbs			} else {
211897883Sgibbs				ahd_set_scbptr(ahd, waiting_h);
2119111954Sgibbs				next = ahd_inw_scbram(ahd, SCB_NEXT2);
212097883Sgibbs			}
212197883Sgibbs			ahd_set_scbptr(ahd, scbid);
212297883Sgibbs			ahd_outw(ahd, SCB_NEXT2, next);
212397883Sgibbs		}
2124104023Sgibbs		ahd_set_scbptr(ahd, saved_scbptr);
2125107441Sscottl		if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS) {
2126109588Sgibbs			if (SCB_IS_SILENT(scb) == FALSE) {
2127109588Sgibbs				ahd_print_path(ahd, scb);
2128109588Sgibbs				printf("Probable outgoing LQ CRC error.  "
2129109588Sgibbs				       "Retrying command\n");
2130199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
2131109588Sgibbs			}
2132107441Sscottl			scb->crc_retry_count++;
2133107441Sscottl		} else {
2134123579Sgibbs			aic_set_transaction_status(scb, CAM_UNCOR_PARITY);
2135123579Sgibbs			aic_freeze_scb(scb);
2136107441Sscottl			ahd_freeze_devq(ahd, scb);
2137107441Sscottl		}
213897883Sgibbs		/* Return unpausing the sequencer. */
213997883Sgibbs		return (0);
2140107441Sscottl	} else if ((ahd_inb(ahd, PERRDIAG) & PARITYERR) != 0) {
2141107441Sscottl		/*
2142107441Sscottl		 * Ignore what are really parity errors that
2143107441Sscottl		 * occur on the last REQ of a free running
2144107441Sscottl		 * clock prior to going busfree.  Some drives
2145107441Sscottl		 * do not properly active negate just before
2146107441Sscottl		 * going busfree resulting in a parity glitch.
2147107441Sscottl		 */
2148107441Sscottl		ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE);
2149107441Sscottl#ifdef AHD_DEBUG
2150107441Sscottl		if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0)
2151107441Sscottl			printf("%s: Parity on last REQ detected "
2152107441Sscottl			       "during busfree phase.\n",
2153107441Sscottl			       ahd_name(ahd));
2154107441Sscottl#endif
2155107441Sscottl		/* Return unpausing the sequencer. */
2156107441Sscottl		return (0);
215797883Sgibbs	}
215897883Sgibbs	if (ahd->src_mode != AHD_MODE_SCSI) {
215997883Sgibbs		u_int	scbid;
216097883Sgibbs		struct	scb *scb;
216197883Sgibbs
216297883Sgibbs		scbid = ahd_get_scbptr(ahd);
216397883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
216497883Sgibbs		ahd_print_path(ahd, scb);
216597883Sgibbs		printf("Unexpected PKT busfree condition\n");
2166199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2167111653Sgibbs		ahd_dump_card_state(ahd);
216897883Sgibbs		ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A',
216997883Sgibbs			       SCB_GET_LUN(scb), SCB_GET_TAG(scb),
217097883Sgibbs			       ROLE_INITIATOR, CAM_UNEXP_BUSFREE);
217197883Sgibbs
217297883Sgibbs		/* Return restarting the sequencer. */
217397883Sgibbs		return (1);
217497883Sgibbs	}
217597883Sgibbs	printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd));
2176199260Sattilio	AHD_UNCORRECTABLE_ERROR(ahd);
217797883Sgibbs	ahd_dump_card_state(ahd);
217897883Sgibbs	/* Restart the sequencer. */
217997883Sgibbs	return (1);
218097883Sgibbs}
218197883Sgibbs
218297883Sgibbs/*
218397883Sgibbs * Non-packetized unexpected or expected busfree.
218497883Sgibbs */
218597883Sgibbsstatic int
218697883Sgibbsahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
218797883Sgibbs{
218897883Sgibbs	struct	ahd_devinfo devinfo;
218997883Sgibbs	struct	scb *scb;
219097883Sgibbs	u_int	lastphase;
219197883Sgibbs	u_int	saved_scsiid;
219297883Sgibbs	u_int	saved_lun;
219397883Sgibbs	u_int	target;
219497883Sgibbs	u_int	initiator_role_id;
219597883Sgibbs	u_int	scbid;
2196107441Sscottl	u_int	ppr_busfree;
219797883Sgibbs	int	printerror;
219897883Sgibbs
219997883Sgibbs	/*
220097883Sgibbs	 * Look at what phase we were last in.  If its message out,
220197883Sgibbs	 * chances are pretty good that the busfree was in response
220297883Sgibbs	 * to one of our abort requests.
220397883Sgibbs	 */
220497883Sgibbs	lastphase = ahd_inb(ahd, LASTPHASE);
220597883Sgibbs	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
220697883Sgibbs	saved_lun = ahd_inb(ahd, SAVED_LUN);
220797883Sgibbs	target = SCSIID_TARGET(ahd, saved_scsiid);
220897883Sgibbs	initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
220997883Sgibbs	ahd_compile_devinfo(&devinfo, initiator_role_id,
221097883Sgibbs			    target, saved_lun, 'A', ROLE_INITIATOR);
221197883Sgibbs	printerror = 1;
221297883Sgibbs
221397883Sgibbs	scbid = ahd_get_scbptr(ahd);
221497883Sgibbs	scb = ahd_lookup_scb(ahd, scbid);
221597883Sgibbs	if (scb != NULL
221697883Sgibbs	 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
221797883Sgibbs		scb = NULL;
221897883Sgibbs
2219107441Sscottl	ppr_busfree = (ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0;
222097883Sgibbs	if (lastphase == P_MESGOUT) {
222197883Sgibbs		u_int tag;
222297883Sgibbs
222397883Sgibbs		tag = SCB_LIST_NULL;
222497883Sgibbs		if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT_TAG, TRUE)
222597883Sgibbs		 || ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT, TRUE)) {
222697883Sgibbs			int found;
222797883Sgibbs			int sent_msg;
222897883Sgibbs
2229102679Sgibbs			if (scb == NULL) {
2230102679Sgibbs				ahd_print_devinfo(ahd, &devinfo);
2231102679Sgibbs				printf("Abort for unidentified "
2232102679Sgibbs				       "connection completed.\n");
2233102679Sgibbs				/* restart the sequencer. */
2234102679Sgibbs				return (1);
2235102679Sgibbs			}
223697883Sgibbs			sent_msg = ahd->msgout_buf[ahd->msgout_index - 1];
223797883Sgibbs			ahd_print_path(ahd, scb);
223897883Sgibbs			printf("SCB %d - Abort%s Completed.\n",
223997883Sgibbs			       SCB_GET_TAG(scb),
224097883Sgibbs			       sent_msg == MSG_ABORT_TAG ? "" : " Tag");
224197883Sgibbs
224297883Sgibbs			if (sent_msg == MSG_ABORT_TAG)
224397883Sgibbs				tag = SCB_GET_TAG(scb);
224497883Sgibbs
224597883Sgibbs			if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) {
224697883Sgibbs				/*
224797883Sgibbs				 * This abort is in response to an
224897883Sgibbs				 * unexpected switch to command phase
224997883Sgibbs				 * for a packetized connection.  Since
225097883Sgibbs				 * the identify message was never sent,
225197883Sgibbs				 * "saved lun" is 0.  We really want to
225297883Sgibbs				 * abort only the SCB that encountered
225397883Sgibbs				 * this error, which could have a different
225497883Sgibbs				 * lun.  The SCB will be retried so the OS
225597883Sgibbs				 * will see the UA after renegotiating to
225697883Sgibbs				 * packetized.
225797883Sgibbs				 */
225897883Sgibbs				tag = SCB_GET_TAG(scb);
225997883Sgibbs				saved_lun = scb->hscb->lun;
226097883Sgibbs			}
226197883Sgibbs			found = ahd_abort_scbs(ahd, target, 'A', saved_lun,
226297883Sgibbs					       tag, ROLE_INITIATOR,
226397883Sgibbs					       CAM_REQ_ABORTED);
226497883Sgibbs			printf("found == 0x%x\n", found);
226597883Sgibbs			printerror = 0;
226697883Sgibbs		} else if (ahd_sent_msg(ahd, AHDMSG_1B,
226797883Sgibbs					MSG_BUS_DEV_RESET, TRUE)) {
226897883Sgibbs#ifdef __FreeBSD__
226997883Sgibbs			/*
227097883Sgibbs			 * Don't mark the user's request for this BDR
227197883Sgibbs			 * as completing with CAM_BDR_SENT.  CAM3
227297883Sgibbs			 * specifies CAM_REQ_CMP.
227397883Sgibbs			 */
227497883Sgibbs			if (scb != NULL
227597883Sgibbs			 && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV
227697883Sgibbs			 && ahd_match_scb(ahd, scb, target, 'A',
227797883Sgibbs					  CAM_LUN_WILDCARD, SCB_LIST_NULL,
227897883Sgibbs					  ROLE_INITIATOR))
2279123579Sgibbs				aic_set_transaction_status(scb, CAM_REQ_CMP);
228097883Sgibbs#endif
2281109588Sgibbs			ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD,
2282109588Sgibbs					    CAM_BDR_SENT, "Bus Device Reset",
228397883Sgibbs					    /*verbose_level*/0);
228497883Sgibbs			printerror = 0;
2285107441Sscottl		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, FALSE)
2286107441Sscottl			&& ppr_busfree == 0) {
228797883Sgibbs			struct ahd_initiator_tinfo *tinfo;
228897883Sgibbs			struct ahd_tmode_tstate *tstate;
228997883Sgibbs
229097883Sgibbs			/*
2291133122Sgibbs			 * PPR Rejected.
2292133122Sgibbs			 *
2293133122Sgibbs			 * If the previous negotiation was packetized,
2294133122Sgibbs			 * this could be because the device has been
2295133122Sgibbs			 * reset without our knowledge.  Force our
2296133122Sgibbs			 * current negotiation to async and retry the
2297133122Sgibbs			 * negotiation.  Otherwise retry the command
2298133122Sgibbs			 * with non-ppr negotiation.
229997883Sgibbs			 */
2300107441Sscottl#ifdef AHD_DEBUG
2301107441Sscottl			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2302107441Sscottl				printf("PPR negotiation rejected busfree.\n");
2303107441Sscottl#endif
230497883Sgibbs			tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
230597883Sgibbs						    devinfo.our_scsiid,
230697883Sgibbs						    devinfo.target, &tstate);
2307133122Sgibbs			if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) {
2308133122Sgibbs				ahd_set_width(ahd, &devinfo,
2309133122Sgibbs					      MSG_EXT_WDTR_BUS_8_BIT,
2310133122Sgibbs					      AHD_TRANS_CUR,
2311133122Sgibbs					      /*paused*/TRUE);
2312133122Sgibbs				ahd_set_syncrate(ahd, &devinfo,
2313133122Sgibbs						/*period*/0, /*offset*/0,
2314133122Sgibbs						/*ppr_options*/0,
2315133122Sgibbs						AHD_TRANS_CUR,
2316133122Sgibbs						/*paused*/TRUE);
2317133122Sgibbs				/*
2318133122Sgibbs				 * The expect PPR busfree handler below
2319133122Sgibbs				 * will effect the retry and necessary
2320133122Sgibbs				 * abort.
2321133122Sgibbs				 */
2322133122Sgibbs			} else {
2323133122Sgibbs				tinfo->curr.transport_version = 2;
2324133122Sgibbs				tinfo->goal.transport_version = 2;
2325133122Sgibbs				tinfo->goal.ppr_options = 0;
2326133122Sgibbs				/*
2327133122Sgibbs				 * Remove any SCBs in the waiting for selection
2328133122Sgibbs				 * queue that may also be for this target so
2329133122Sgibbs				 * that command ordering is preserved.
2330133122Sgibbs				 */
2331133122Sgibbs				ahd_freeze_devq(ahd, scb);
2332133122Sgibbs				ahd_qinfifo_requeue_tail(ahd, scb);
2333133122Sgibbs				printerror = 0;
2334133122Sgibbs			}
2335115918Sgibbs		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
2336107441Sscottl			&& ppr_busfree == 0) {
233797883Sgibbs			/*
2338115918Sgibbs			 * Negotiation Rejected.  Go-narrow and
233997883Sgibbs			 * retry command.
234097883Sgibbs			 */
2341107441Sscottl#ifdef AHD_DEBUG
2342107441Sscottl			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2343115918Sgibbs				printf("WDTR negotiation rejected busfree.\n");
2344107441Sscottl#endif
234597883Sgibbs			ahd_set_width(ahd, &devinfo,
234697883Sgibbs				      MSG_EXT_WDTR_BUS_8_BIT,
234797883Sgibbs				      AHD_TRANS_CUR|AHD_TRANS_GOAL,
234897883Sgibbs				      /*paused*/TRUE);
2349133122Sgibbs			/*
2350133122Sgibbs			 * Remove any SCBs in the waiting for selection
2351133122Sgibbs			 * queue that may also be for this target so that
2352133122Sgibbs			 * command ordering is preserved.
2353133122Sgibbs			 */
2354133122Sgibbs			ahd_freeze_devq(ahd, scb);
2355115918Sgibbs			ahd_qinfifo_requeue_tail(ahd, scb);
2356115918Sgibbs			printerror = 0;
2357115918Sgibbs		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
2358115918Sgibbs			&& ppr_busfree == 0) {
2359115918Sgibbs			/*
2360115918Sgibbs			 * Negotiation Rejected.  Go-async and
2361115918Sgibbs			 * retry command.
2362115918Sgibbs			 */
2363115918Sgibbs#ifdef AHD_DEBUG
2364115918Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2365115918Sgibbs				printf("SDTR negotiation rejected busfree.\n");
2366115918Sgibbs#endif
236797883Sgibbs			ahd_set_syncrate(ahd, &devinfo,
236897883Sgibbs					/*period*/0, /*offset*/0,
236997883Sgibbs					/*ppr_options*/0,
237097883Sgibbs					AHD_TRANS_CUR|AHD_TRANS_GOAL,
237197883Sgibbs					/*paused*/TRUE);
2372133122Sgibbs			/*
2373133122Sgibbs			 * Remove any SCBs in the waiting for selection
2374133122Sgibbs			 * queue that may also be for this target so that
2375133122Sgibbs			 * command ordering is preserved.
2376133122Sgibbs			 */
2377133122Sgibbs			ahd_freeze_devq(ahd, scb);
237897883Sgibbs			ahd_qinfifo_requeue_tail(ahd, scb);
237997883Sgibbs			printerror = 0;
238097883Sgibbs		} else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0
238197883Sgibbs			&& ahd_sent_msg(ahd, AHDMSG_1B,
238297883Sgibbs					 MSG_INITIATOR_DET_ERR, TRUE)) {
238397883Sgibbs
238497883Sgibbs#ifdef AHD_DEBUG
238597883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
238697883Sgibbs				printf("Expected IDE Busfree\n");
238797883Sgibbs#endif
238897883Sgibbs			printerror = 0;
2389107441Sscottl		} else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE)
2390107441Sscottl			&& ahd_sent_msg(ahd, AHDMSG_1B,
2391107441Sscottl					MSG_MESSAGE_REJECT, TRUE)) {
2392107441Sscottl
2393107441Sscottl#ifdef AHD_DEBUG
2394107441Sscottl			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2395107441Sscottl				printf("Expected QAS Reject Busfree\n");
2396107441Sscottl#endif
2397107441Sscottl			printerror = 0;
239897883Sgibbs		}
2399102679Sgibbs	}
240097883Sgibbs
2401102679Sgibbs	/*
2402102679Sgibbs	 * The busfree required flag is honored at the end of
2403102679Sgibbs	 * the message phases.  We check it last in case we
2404102679Sgibbs	 * had to send some other message that caused a busfree.
2405102679Sgibbs	 */
2406102679Sgibbs	if (printerror != 0
2407102679Sgibbs	 && (lastphase == P_MESGIN || lastphase == P_MESGOUT)
2408102679Sgibbs	 && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) {
240997883Sgibbs
2410102679Sgibbs		ahd_freeze_devq(ahd, scb);
2411123579Sgibbs		aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
2412123579Sgibbs		aic_freeze_scb(scb);
2413102679Sgibbs		if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) {
2414102679Sgibbs			ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
2415102679Sgibbs				       SCB_GET_CHANNEL(ahd, scb),
2416102679Sgibbs				       SCB_GET_LUN(scb), SCB_LIST_NULL,
2417102679Sgibbs				       ROLE_INITIATOR, CAM_REQ_ABORTED);
2418102679Sgibbs		} else {
241997883Sgibbs#ifdef AHD_DEBUG
2420102679Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2421102679Sgibbs				printf("PPR Negotiation Busfree.\n");
242297883Sgibbs#endif
2423102679Sgibbs			ahd_done(ahd, scb);
242497883Sgibbs		}
2425102679Sgibbs		printerror = 0;
242697883Sgibbs	}
242797883Sgibbs	if (printerror != 0) {
242897883Sgibbs		int aborted;
242997883Sgibbs
243097883Sgibbs		aborted = 0;
243197883Sgibbs		if (scb != NULL) {
243297883Sgibbs			u_int tag;
243397883Sgibbs
243497883Sgibbs			if ((scb->hscb->control & TAG_ENB) != 0)
243597883Sgibbs				tag = SCB_GET_TAG(scb);
243697883Sgibbs			else
243797883Sgibbs				tag = SCB_LIST_NULL;
243897883Sgibbs			ahd_print_path(ahd, scb);
243997883Sgibbs			aborted = ahd_abort_scbs(ahd, target, 'A',
244097883Sgibbs				       SCB_GET_LUN(scb), tag,
244197883Sgibbs				       ROLE_INITIATOR,
244297883Sgibbs				       CAM_UNEXP_BUSFREE);
244397883Sgibbs		} else {
244497883Sgibbs			/*
244597883Sgibbs			 * We had not fully identified this connection,
244697883Sgibbs			 * so we cannot abort anything.
244797883Sgibbs			 */
244897883Sgibbs			printf("%s: ", ahd_name(ahd));
244997883Sgibbs		}
245097883Sgibbs		printf("Unexpected busfree %s, %d SCBs aborted, "
245197883Sgibbs		       "PRGMCNT == 0x%x\n",
245297883Sgibbs		       ahd_lookup_phase_entry(lastphase)->phasemsg,
245397883Sgibbs		       aborted,
2454123579Sgibbs		       ahd_inw(ahd, PRGMCNT));
2455199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
245697883Sgibbs		ahd_dump_card_state(ahd);
2457133122Sgibbs		if (lastphase != P_BUSFREE)
2458133122Sgibbs			ahd_force_renegotiation(ahd, &devinfo);
245997883Sgibbs	}
246097883Sgibbs	/* Always restart the sequencer. */
246197883Sgibbs	return (1);
246297883Sgibbs}
246397883Sgibbs
2464102679Sgibbsstatic void
2465102679Sgibbsahd_handle_proto_violation(struct ahd_softc *ahd)
2466102679Sgibbs{
2467102679Sgibbs	struct	ahd_devinfo devinfo;
2468102679Sgibbs	struct	scb *scb;
2469102679Sgibbs	u_int	scbid;
2470102679Sgibbs	u_int	seq_flags;
2471102679Sgibbs	u_int	curphase;
2472102679Sgibbs	u_int	lastphase;
2473102679Sgibbs	int	found;
2474102679Sgibbs
2475102679Sgibbs	ahd_fetch_devinfo(ahd, &devinfo);
2476102679Sgibbs	scbid = ahd_get_scbptr(ahd);
2477102679Sgibbs	scb = ahd_lookup_scb(ahd, scbid);
2478102679Sgibbs	seq_flags = ahd_inb(ahd, SEQ_FLAGS);
2479102679Sgibbs	curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
2480102679Sgibbs	lastphase = ahd_inb(ahd, LASTPHASE);
2481102679Sgibbs	if ((seq_flags & NOT_IDENTIFIED) != 0) {
2482102679Sgibbs
2483102679Sgibbs		/*
2484102679Sgibbs		 * The reconnecting target either did not send an
2485102679Sgibbs		 * identify message, or did, but we didn't find an SCB
2486102679Sgibbs		 * to match.
2487102679Sgibbs		 */
2488102679Sgibbs		ahd_print_devinfo(ahd, &devinfo);
2489102679Sgibbs		printf("Target did not send an IDENTIFY message. "
2490102679Sgibbs		       "LASTPHASE = 0x%x.\n", lastphase);
2491199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2492102679Sgibbs		scb = NULL;
2493102679Sgibbs	} else if (scb == NULL) {
2494102679Sgibbs		/*
2495102679Sgibbs		 * We don't seem to have an SCB active for this
2496102679Sgibbs		 * transaction.  Print an error and reset the bus.
2497102679Sgibbs		 */
2498102679Sgibbs		ahd_print_devinfo(ahd, &devinfo);
2499102679Sgibbs		printf("No SCB found during protocol violation\n");
2500199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2501102679Sgibbs		goto proto_violation_reset;
2502102679Sgibbs	} else {
2503123579Sgibbs		aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
2504102679Sgibbs		if ((seq_flags & NO_CDB_SENT) != 0) {
2505102679Sgibbs			ahd_print_path(ahd, scb);
2506102679Sgibbs			printf("No or incomplete CDB sent to device.\n");
2507199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
2508111954Sgibbs		} else if ((ahd_inb_scbram(ahd, SCB_CONTROL)
2509111954Sgibbs			  & STATUS_RCVD) == 0) {
2510102679Sgibbs			/*
2511102679Sgibbs			 * The target never bothered to provide status to
2512102679Sgibbs			 * us prior to completing the command.  Since we don't
2513102679Sgibbs			 * know the disposition of this command, we must attempt
2514102679Sgibbs			 * to abort it.  Assert ATN and prepare to send an abort
2515102679Sgibbs			 * message.
2516102679Sgibbs			 */
2517102679Sgibbs			ahd_print_path(ahd, scb);
2518102679Sgibbs			printf("Completed command without status.\n");
2519102679Sgibbs		} else {
2520102679Sgibbs			ahd_print_path(ahd, scb);
2521102679Sgibbs			printf("Unknown protocol violation.\n");
2522199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
2523102679Sgibbs			ahd_dump_card_state(ahd);
2524102679Sgibbs		}
2525102679Sgibbs	}
2526107441Sscottl	if ((lastphase & ~P_DATAIN_DT) == 0
2527107441Sscottl	 || lastphase == P_COMMAND) {
2528102679Sgibbsproto_violation_reset:
2529102679Sgibbs		/*
2530102679Sgibbs		 * Target either went directly to data
2531102679Sgibbs		 * phase or didn't respond to our ATN.
2532102679Sgibbs		 * The only safe thing to do is to blow
2533102679Sgibbs		 * it away with a bus reset.
2534102679Sgibbs		 */
2535102679Sgibbs		found = ahd_reset_channel(ahd, 'A', TRUE);
2536102679Sgibbs		printf("%s: Issued Channel %c Bus Reset. "
2537102679Sgibbs		       "%d SCBs aborted\n", ahd_name(ahd), 'A', found);
2538199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2539102679Sgibbs	} else {
2540102679Sgibbs		/*
2541102679Sgibbs		 * Leave the selection hardware off in case
2542102679Sgibbs		 * this abort attempt will affect yet to
2543102679Sgibbs		 * be sent commands.
2544102679Sgibbs		 */
2545102679Sgibbs		ahd_outb(ahd, SCSISEQ0,
2546102679Sgibbs			 ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
2547102679Sgibbs		ahd_assert_atn(ahd);
2548102679Sgibbs		ahd_outb(ahd, MSG_OUT, HOST_MSG);
2549102679Sgibbs		if (scb == NULL) {
2550102679Sgibbs			ahd_print_devinfo(ahd, &devinfo);
2551102679Sgibbs			ahd->msgout_buf[0] = MSG_ABORT_TASK;
2552102679Sgibbs			ahd->msgout_len = 1;
2553102679Sgibbs			ahd->msgout_index = 0;
2554102679Sgibbs			ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2555102679Sgibbs		} else {
2556102679Sgibbs			ahd_print_path(ahd, scb);
2557102679Sgibbs			scb->flags |= SCB_ABORT;
2558102679Sgibbs		}
2559102679Sgibbs		printf("Protocol violation %s.  Attempting to abort.\n",
2560102679Sgibbs		       ahd_lookup_phase_entry(curphase)->phasemsg);
2561199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2562102679Sgibbs	}
2563102679Sgibbs}
2564102679Sgibbs
256597883Sgibbs/*
256697883Sgibbs * Force renegotiation to occur the next time we initiate
256797883Sgibbs * a command to the current device.
256897883Sgibbs */
256997883Sgibbsstatic void
257097883Sgibbsahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
257197883Sgibbs{
257297883Sgibbs	struct	ahd_initiator_tinfo *targ_info;
257397883Sgibbs	struct	ahd_tmode_tstate *tstate;
257497883Sgibbs
2575107441Sscottl#ifdef AHD_DEBUG
2576107441Sscottl	if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
2577107441Sscottl		ahd_print_devinfo(ahd, devinfo);
2578107441Sscottl		printf("Forcing renegotiation\n");
2579107441Sscottl	}
2580107441Sscottl#endif
258197883Sgibbs	targ_info = ahd_fetch_transinfo(ahd,
258297883Sgibbs					devinfo->channel,
258397883Sgibbs					devinfo->our_scsiid,
258497883Sgibbs					devinfo->target,
258597883Sgibbs					&tstate);
258697883Sgibbs	ahd_update_neg_request(ahd, devinfo, tstate,
2587107441Sscottl			       targ_info, AHD_NEG_IF_NON_ASYNC);
258897883Sgibbs}
258997883Sgibbs
259097883Sgibbs#define AHD_MAX_STEPS 2000
259197883Sgibbsvoid
259297883Sgibbsahd_clear_critical_section(struct ahd_softc *ahd)
259397883Sgibbs{
259497883Sgibbs	ahd_mode_state	saved_modes;
259597883Sgibbs	int		stepping;
259697883Sgibbs	int		steps;
2597107441Sscottl	int		first_instr;
2598107441Sscottl	u_int		simode0;
2599107441Sscottl	u_int		simode1;
2600107441Sscottl	u_int		simode3;
2601107441Sscottl	u_int		lqimode0;
2602107441Sscottl	u_int		lqimode1;
2603107441Sscottl	u_int		lqomode0;
2604107441Sscottl	u_int		lqomode1;
260597883Sgibbs
260697883Sgibbs	if (ahd->num_critical_sections == 0)
260797883Sgibbs		return;
260897883Sgibbs
260997883Sgibbs	stepping = FALSE;
261097883Sgibbs	steps = 0;
2611107441Sscottl	first_instr = 0;
2612107441Sscottl	simode0 = 0;
2613107441Sscottl	simode1 = 0;
2614107441Sscottl	simode3 = 0;
2615107441Sscottl	lqimode0 = 0;
2616107441Sscottl	lqimode1 = 0;
2617107441Sscottl	lqomode0 = 0;
2618107441Sscottl	lqomode1 = 0;
261997883Sgibbs	saved_modes = ahd_save_modes(ahd);
262097883Sgibbs	for (;;) {
262197883Sgibbs		struct	cs *cs;
262297883Sgibbs		u_int	seqaddr;
262397883Sgibbs		u_int	i;
262497883Sgibbs
262597883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2626123579Sgibbs		seqaddr = ahd_inw(ahd, CURADDR);
262797883Sgibbs
262897883Sgibbs		cs = ahd->critical_sections;
262997883Sgibbs		for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
263097883Sgibbs
263197883Sgibbs			if (cs->begin < seqaddr && cs->end >= seqaddr)
263297883Sgibbs				break;
263397883Sgibbs		}
263497883Sgibbs
263597883Sgibbs		if (i == ahd->num_critical_sections)
263697883Sgibbs			break;
263797883Sgibbs
263897883Sgibbs		if (steps > AHD_MAX_STEPS) {
2639107441Sscottl			printf("%s: Infinite loop in critical section\n"
2640107441Sscottl			       "%s: First Instruction 0x%x now 0x%x\n",
2641107441Sscottl			       ahd_name(ahd), ahd_name(ahd), first_instr,
2642107441Sscottl			       seqaddr);
2643199260Sattilio			AHD_FATAL_ERROR(ahd);
264497883Sgibbs			ahd_dump_card_state(ahd);
264597883Sgibbs			panic("critical section loop");
264697883Sgibbs		}
264797883Sgibbs
264897883Sgibbs		steps++;
2649107441Sscottl#ifdef AHD_DEBUG
2650107441Sscottl		if ((ahd_debug & AHD_SHOW_MISC) != 0)
2651107441Sscottl			printf("%s: Single stepping at 0x%x\n", ahd_name(ahd),
2652107441Sscottl			       seqaddr);
2653107441Sscottl#endif
265497883Sgibbs		if (stepping == FALSE) {
265597883Sgibbs
2656107441Sscottl			first_instr = seqaddr;
2657107441Sscottl  			ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
2658107441Sscottl  			simode0 = ahd_inb(ahd, SIMODE0);
2659107441Sscottl			simode3 = ahd_inb(ahd, SIMODE3);
2660107441Sscottl			lqimode0 = ahd_inb(ahd, LQIMODE0);
2661107441Sscottl			lqimode1 = ahd_inb(ahd, LQIMODE1);
2662107441Sscottl			lqomode0 = ahd_inb(ahd, LQOMODE0);
2663107441Sscottl			lqomode1 = ahd_inb(ahd, LQOMODE1);
2664107441Sscottl			ahd_outb(ahd, SIMODE0, 0);
2665107441Sscottl			ahd_outb(ahd, SIMODE3, 0);
2666107441Sscottl			ahd_outb(ahd, LQIMODE0, 0);
2667107441Sscottl			ahd_outb(ahd, LQIMODE1, 0);
2668107441Sscottl			ahd_outb(ahd, LQOMODE0, 0);
2669107441Sscottl			ahd_outb(ahd, LQOMODE1, 0);
267097883Sgibbs			ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2671116935Sgibbs			simode1 = ahd_inb(ahd, SIMODE1);
2672116935Sgibbs			/*
2673116935Sgibbs			 * We don't clear ENBUSFREE.  Unfortunately
2674116935Sgibbs			 * we cannot re-enable busfree detection within
2675116935Sgibbs			 * the current connection, so we must leave it
2676116935Sgibbs			 * on while single stepping.
2677116935Sgibbs			 */
2678116935Sgibbs			ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE);
267997883Sgibbs			ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP);
268097883Sgibbs			stepping = TRUE;
268197883Sgibbs		}
2682107441Sscottl		ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
2683107441Sscottl		ahd_outb(ahd, CLRINT, CLRSCSIINT);
268497883Sgibbs		ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
268597883Sgibbs		ahd_outb(ahd, HCNTRL, ahd->unpause);
2686116935Sgibbs		while (!ahd_is_paused(ahd))
2687123579Sgibbs			aic_delay(200);
268897883Sgibbs		ahd_update_modes(ahd);
268997883Sgibbs	}
269097883Sgibbs	if (stepping) {
2691107441Sscottl		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
2692107441Sscottl		ahd_outb(ahd, SIMODE0, simode0);
2693107441Sscottl		ahd_outb(ahd, SIMODE3, simode3);
2694107441Sscottl		ahd_outb(ahd, LQIMODE0, lqimode0);
2695107441Sscottl		ahd_outb(ahd, LQIMODE1, lqimode1);
2696107441Sscottl		ahd_outb(ahd, LQOMODE0, lqomode0);
2697107441Sscottl		ahd_outb(ahd, LQOMODE1, lqomode1);
269897883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
269997883Sgibbs		ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);
2700107441Sscottl  		ahd_outb(ahd, SIMODE1, simode1);
2701114623Sgibbs		/*
2702114623Sgibbs		 * SCSIINT seems to glitch occassionally when
2703114623Sgibbs		 * the interrupt masks are restored.  Clear SCSIINT
2704114623Sgibbs		 * one more time so that only persistent errors
2705114623Sgibbs		 * are seen as a real interrupt.
2706114623Sgibbs		 */
2707114623Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
270897883Sgibbs	}
270997883Sgibbs	ahd_restore_modes(ahd, saved_modes);
271097883Sgibbs}
271197883Sgibbs
271297883Sgibbs/*
271397883Sgibbs * Clear any pending interrupt status.
271497883Sgibbs */
271597883Sgibbsvoid
271697883Sgibbsahd_clear_intstat(struct ahd_softc *ahd)
271797883Sgibbs{
2718102679Sgibbs	AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
2719102679Sgibbs			 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
272097883Sgibbs	/* Clear any interrupt conditions this may have caused */
2721102679Sgibbs	ahd_outb(ahd, CLRLQIINT0, CLRLQIATNQAS|CLRLQICRCT1|CLRLQICRCT2
2722102679Sgibbs				 |CLRLQIBADLQT|CLRLQIATNLQ|CLRLQIATNCMD);
2723102679Sgibbs	ahd_outb(ahd, CLRLQIINT1, CLRLQIPHASE_LQ|CLRLQIPHASE_NLQ|CLRLIQABORT
2724102679Sgibbs				 |CLRLQICRCI_LQ|CLRLQICRCI_NLQ|CLRLQIBADLQI
2725102679Sgibbs				 |CLRLQIOVERI_LQ|CLRLQIOVERI_NLQ|CLRNONPACKREQ);
2726102679Sgibbs	ahd_outb(ahd, CLRLQOINT0, CLRLQOTARGSCBPERR|CLRLQOSTOPT2|CLRLQOATNLQ
2727102679Sgibbs				 |CLRLQOATNPKT|CLRLQOTCRC);
2728102679Sgibbs	ahd_outb(ahd, CLRLQOINT1, CLRLQOINITSCBPERR|CLRLQOSTOPI2|CLRLQOBADQAS
2729102679Sgibbs				 |CLRLQOBUSFREE|CLRLQOPHACHGINPKT);
2730104023Sgibbs	if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
2731104023Sgibbs		ahd_outb(ahd, CLRLQOINT0, 0);
2732104023Sgibbs		ahd_outb(ahd, CLRLQOINT1, 0);
2733104023Sgibbs	}
2734102679Sgibbs	ahd_outb(ahd, CLRSINT3, CLRNTRAMPERR|CLROSRAMPERR);
273597883Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
273697883Sgibbs				|CLRBUSFREE|CLRSCSIPERR|CLRREQINIT);
2737107441Sscottl	ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO
2738107441Sscottl			        |CLRIOERR|CLROVERRUN);
273997883Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
274097883Sgibbs}
274197883Sgibbs
274297883Sgibbs/**************************** Debugging Routines ******************************/
274397883Sgibbs#ifdef AHD_DEBUG
274497883Sgibbsuint32_t ahd_debug = AHD_DEBUG_OPTS;
274597883Sgibbs#endif
274697883Sgibbsvoid
274797883Sgibbsahd_print_scb(struct scb *scb)
274897883Sgibbs{
274997883Sgibbs	struct hardware_scb *hscb;
275097883Sgibbs	int i;
275197883Sgibbs
275297883Sgibbs	hscb = scb->hscb;
275397883Sgibbs	printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n",
275497883Sgibbs	       (void *)scb,
275597883Sgibbs	       hscb->control,
275697883Sgibbs	       hscb->scsiid,
275797883Sgibbs	       hscb->lun,
275897883Sgibbs	       hscb->cdb_len);
275997883Sgibbs	printf("Shared Data: ");
276097883Sgibbs	for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++)
276197883Sgibbs		printf("%#02x", hscb->shared_data.idata.cdb[i]);
276297883Sgibbs	printf("        dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n",
2763123579Sgibbs	       (uint32_t)((aic_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),
2764123579Sgibbs	       (uint32_t)(aic_le64toh(hscb->dataptr) & 0xFFFFFFFF),
2765123579Sgibbs	       aic_le32toh(hscb->datacnt),
2766123579Sgibbs	       aic_le32toh(hscb->sgptr),
276797883Sgibbs	       SCB_GET_TAG(scb));
276897883Sgibbs	ahd_dump_sglist(scb);
276997883Sgibbs}
277097883Sgibbs
277197883Sgibbsvoid
277297883Sgibbsahd_dump_sglist(struct scb *scb)
277397883Sgibbs{
277497883Sgibbs	int i;
277597883Sgibbs
277697883Sgibbs	if (scb->sg_count > 0) {
277797883Sgibbs		if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) {
277897883Sgibbs			struct ahd_dma64_seg *sg_list;
277997883Sgibbs
278097883Sgibbs			sg_list = (struct ahd_dma64_seg*)scb->sg_list;
278197883Sgibbs			for (i = 0; i < scb->sg_count; i++) {
278297883Sgibbs				uint64_t addr;
2783104023Sgibbs				uint32_t len;
278497883Sgibbs
2785123579Sgibbs				addr = aic_le64toh(sg_list[i].addr);
2786123579Sgibbs				len = aic_le32toh(sg_list[i].len);
2787104023Sgibbs				printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
278897883Sgibbs				       i,
278997883Sgibbs				       (uint32_t)((addr >> 32) & 0xFFFFFFFF),
279097883Sgibbs				       (uint32_t)(addr & 0xFFFFFFFF),
2791104023Sgibbs				       sg_list[i].len & AHD_SG_LEN_MASK,
2792104023Sgibbs				       (sg_list[i].len & AHD_DMA_LAST_SEG)
2793104023Sgibbs				     ? " Last" : "");
279497883Sgibbs			}
279597883Sgibbs		} else {
279697883Sgibbs			struct ahd_dma_seg *sg_list;
279797883Sgibbs
279897883Sgibbs			sg_list = (struct ahd_dma_seg*)scb->sg_list;
279997883Sgibbs			for (i = 0; i < scb->sg_count; i++) {
2800104023Sgibbs				uint32_t len;
2801104023Sgibbs
2802123579Sgibbs				len = aic_le32toh(sg_list[i].len);
2803104023Sgibbs				printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
280497883Sgibbs				       i,
2805116938Sgibbs				       (len & AHD_SG_HIGH_ADDR_MASK) >> 24,
2806123579Sgibbs				       aic_le32toh(sg_list[i].addr),
2807104023Sgibbs				       len & AHD_SG_LEN_MASK,
2808104023Sgibbs				       len & AHD_DMA_LAST_SEG ? " Last" : "");
280997883Sgibbs			}
281097883Sgibbs		}
281197883Sgibbs	}
281297883Sgibbs}
281397883Sgibbs
281497883Sgibbs/************************* Transfer Negotiation *******************************/
281597883Sgibbs/*
281697883Sgibbs * Allocate per target mode instance (ID we respond to as a target)
281797883Sgibbs * transfer negotiation data structures.
281897883Sgibbs */
281997883Sgibbsstatic struct ahd_tmode_tstate *
282097883Sgibbsahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel)
282197883Sgibbs{
282297883Sgibbs	struct ahd_tmode_tstate *master_tstate;
282397883Sgibbs	struct ahd_tmode_tstate *tstate;
282497883Sgibbs	int i;
282597883Sgibbs
282697883Sgibbs	master_tstate = ahd->enabled_targets[ahd->our_id];
282797883Sgibbs	if (ahd->enabled_targets[scsi_id] != NULL
282897883Sgibbs	 && ahd->enabled_targets[scsi_id] != master_tstate)
282997883Sgibbs		panic("%s: ahd_alloc_tstate - Target already allocated",
283097883Sgibbs		      ahd_name(ahd));
283197883Sgibbs	tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT);
283297883Sgibbs	if (tstate == NULL)
283397883Sgibbs		return (NULL);
283497883Sgibbs
283597883Sgibbs	/*
283697883Sgibbs	 * If we have allocated a master tstate, copy user settings from
283797883Sgibbs	 * the master tstate (taken from SRAM or the EEPROM) for this
283897883Sgibbs	 * channel, but reset our current and goal settings to async/narrow
283997883Sgibbs	 * until an initiator talks to us.
284097883Sgibbs	 */
284197883Sgibbs	if (master_tstate != NULL) {
284297883Sgibbs		memcpy(tstate, master_tstate, sizeof(*tstate));
284397883Sgibbs		memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
284497883Sgibbs		for (i = 0; i < 16; i++) {
284597883Sgibbs			memset(&tstate->transinfo[i].curr, 0,
284697883Sgibbs			      sizeof(tstate->transinfo[i].curr));
284797883Sgibbs			memset(&tstate->transinfo[i].goal, 0,
284897883Sgibbs			      sizeof(tstate->transinfo[i].goal));
284997883Sgibbs		}
285097883Sgibbs	} else
285197883Sgibbs		memset(tstate, 0, sizeof(*tstate));
285297883Sgibbs	ahd->enabled_targets[scsi_id] = tstate;
285397883Sgibbs	return (tstate);
285497883Sgibbs}
285597883Sgibbs
285697883Sgibbs#ifdef AHD_TARGET_MODE
285797883Sgibbs/*
285897883Sgibbs * Free per target mode instance (ID we respond to as a target)
285997883Sgibbs * transfer negotiation data structures.
286097883Sgibbs */
286197883Sgibbsstatic void
286297883Sgibbsahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force)
286397883Sgibbs{
286497883Sgibbs	struct ahd_tmode_tstate *tstate;
286597883Sgibbs
286697883Sgibbs	/*
286797883Sgibbs	 * Don't clean up our "master" tstate.
286897883Sgibbs	 * It has our default user settings.
286997883Sgibbs	 */
287097883Sgibbs	if (scsi_id == ahd->our_id
287197883Sgibbs	 && force == FALSE)
287297883Sgibbs		return;
287397883Sgibbs
287497883Sgibbs	tstate = ahd->enabled_targets[scsi_id];
287597883Sgibbs	if (tstate != NULL)
287697883Sgibbs		free(tstate, M_DEVBUF);
287797883Sgibbs	ahd->enabled_targets[scsi_id] = NULL;
287897883Sgibbs}
287997883Sgibbs#endif
288097883Sgibbs
288197883Sgibbs/*
288297883Sgibbs * Called when we have an active connection to a target on the bus,
288397883Sgibbs * this function finds the nearest period to the input period limited
288497883Sgibbs * by the capabilities of the bus connectivity of and sync settings for
288597883Sgibbs * the target.
288697883Sgibbs */
288797883Sgibbsvoid
288897883Sgibbsahd_devlimited_syncrate(struct ahd_softc *ahd,
288997883Sgibbs			struct ahd_initiator_tinfo *tinfo,
289097883Sgibbs			u_int *period, u_int *ppr_options, role_t role)
289197883Sgibbs{
289297883Sgibbs	struct	ahd_transinfo *transinfo;
289397883Sgibbs	u_int	maxsync;
289497883Sgibbs
289597883Sgibbs	if ((ahd_inb(ahd, SBLKCTL) & ENAB40) != 0
289697883Sgibbs	 && (ahd_inb(ahd, SSTAT2) & EXP_ACTIVE) == 0) {
289797883Sgibbs		maxsync = AHD_SYNCRATE_PACED;
289897883Sgibbs	} else {
289997883Sgibbs		maxsync = AHD_SYNCRATE_ULTRA;
290097883Sgibbs		/* Can't do DT related options on an SE bus */
290197883Sgibbs		*ppr_options &= MSG_EXT_PPR_QAS_REQ;
290297883Sgibbs	}
290397883Sgibbs	/*
290497883Sgibbs	 * Never allow a value higher than our current goal
290597883Sgibbs	 * period otherwise we may allow a target initiated
290697883Sgibbs	 * negotiation to go above the limit as set by the
290797883Sgibbs	 * user.  In the case of an initiator initiated
290897883Sgibbs	 * sync negotiation, we limit based on the user
290997883Sgibbs	 * setting.  This allows the system to still accept
291097883Sgibbs	 * incoming negotiations even if target initiated
291197883Sgibbs	 * negotiation is not performed.
291297883Sgibbs	 */
291397883Sgibbs	if (role == ROLE_TARGET)
291497883Sgibbs		transinfo = &tinfo->user;
291597883Sgibbs	else
291697883Sgibbs		transinfo = &tinfo->goal;
291797883Sgibbs	*ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN);
2918109588Sgibbs	if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) {
2919107441Sscottl		maxsync = MAX(maxsync, AHD_SYNCRATE_ULTRA2);
2920109588Sgibbs		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
2921109588Sgibbs	}
292297883Sgibbs	if (transinfo->period == 0) {
292397883Sgibbs		*period = 0;
292497883Sgibbs		*ppr_options = 0;
292597883Sgibbs	} else {
292697883Sgibbs		*period = MAX(*period, transinfo->period);
292797883Sgibbs		ahd_find_syncrate(ahd, period, ppr_options, maxsync);
292897883Sgibbs	}
292997883Sgibbs}
293097883Sgibbs
293197883Sgibbs/*
293297883Sgibbs * Look up the valid period to SCSIRATE conversion in our table.
293397883Sgibbs * Return the period and offset that should be sent to the target
293497883Sgibbs * if this was the beginning of an SDTR.
293597883Sgibbs */
293697883Sgibbsvoid
293797883Sgibbsahd_find_syncrate(struct ahd_softc *ahd, u_int *period,
293897883Sgibbs		  u_int *ppr_options, u_int maxsync)
293997883Sgibbs{
294097883Sgibbs	if (*period < maxsync)
294197883Sgibbs		*period = maxsync;
294297883Sgibbs
294397883Sgibbs	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) != 0
294497883Sgibbs	 && *period > AHD_SYNCRATE_MIN_DT)
294597883Sgibbs		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
294697883Sgibbs
294797883Sgibbs	if (*period > AHD_SYNCRATE_MIN)
294897883Sgibbs		*period = 0;
294997883Sgibbs
295097883Sgibbs	/* Honor PPR option conformance rules. */
2951107441Sscottl	if (*period > AHD_SYNCRATE_PACED)
2952107441Sscottl		*ppr_options &= ~MSG_EXT_PPR_RTI;
2953107441Sscottl
295497883Sgibbs	if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
295597883Sgibbs		*ppr_options &= (MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ);
295697883Sgibbs
295797883Sgibbs	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0)
295897883Sgibbs		*ppr_options &= MSG_EXT_PPR_QAS_REQ;
2959109588Sgibbs
2960109588Sgibbs	/* Skip all PACED only entries if IU is not available */
2961109588Sgibbs	if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0
2962109588Sgibbs	 && *period < AHD_SYNCRATE_DT)
2963109588Sgibbs		*period = AHD_SYNCRATE_DT;
2964109588Sgibbs
2965109588Sgibbs	/* Skip all DT only entries if DT is not available */
2966109588Sgibbs	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
2967109588Sgibbs	 && *period < AHD_SYNCRATE_ULTRA2)
2968109588Sgibbs		*period = AHD_SYNCRATE_ULTRA2;
296997883Sgibbs}
297097883Sgibbs
297197883Sgibbs/*
297297883Sgibbs * Truncate the given synchronous offset to a value the
297397883Sgibbs * current adapter type and syncrate are capable of.
297497883Sgibbs */
297597883Sgibbsvoid
297697883Sgibbsahd_validate_offset(struct ahd_softc *ahd,
297797883Sgibbs		    struct ahd_initiator_tinfo *tinfo,
297897883Sgibbs		    u_int period, u_int *offset, int wide,
297997883Sgibbs		    role_t role)
298097883Sgibbs{
298197883Sgibbs	u_int maxoffset;
298297883Sgibbs
298397883Sgibbs	/* Limit offset to what we can do */
298497883Sgibbs	if (period == 0)
298597883Sgibbs		maxoffset = 0;
2986107441Sscottl	else if (period <= AHD_SYNCRATE_PACED) {
2987107441Sscottl		if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
2988107441Sscottl			maxoffset = MAX_OFFSET_PACED_BUG;
2989107441Sscottl		else
2990107441Sscottl			maxoffset = MAX_OFFSET_PACED;
2991107441Sscottl	} else
2992107441Sscottl		maxoffset = MAX_OFFSET_NON_PACED;
299397883Sgibbs	*offset = MIN(*offset, maxoffset);
299497883Sgibbs	if (tinfo != NULL) {
299597883Sgibbs		if (role == ROLE_TARGET)
299697883Sgibbs			*offset = MIN(*offset, tinfo->user.offset);
299797883Sgibbs		else
299897883Sgibbs			*offset = MIN(*offset, tinfo->goal.offset);
299997883Sgibbs	}
300097883Sgibbs}
300197883Sgibbs
300297883Sgibbs/*
300397883Sgibbs * Truncate the given transfer width parameter to a value the
300497883Sgibbs * current adapter type is capable of.
300597883Sgibbs */
300697883Sgibbsvoid
300797883Sgibbsahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo,
300897883Sgibbs		   u_int *bus_width, role_t role)
300997883Sgibbs{
301097883Sgibbs	switch (*bus_width) {
301197883Sgibbs	default:
301297883Sgibbs		if (ahd->features & AHD_WIDE) {
301397883Sgibbs			/* Respond Wide */
301497883Sgibbs			*bus_width = MSG_EXT_WDTR_BUS_16_BIT;
301597883Sgibbs			break;
301697883Sgibbs		}
301797883Sgibbs		/* FALLTHROUGH */
301897883Sgibbs	case MSG_EXT_WDTR_BUS_8_BIT:
301997883Sgibbs		*bus_width = MSG_EXT_WDTR_BUS_8_BIT;
302097883Sgibbs		break;
302197883Sgibbs	}
302297883Sgibbs	if (tinfo != NULL) {
302397883Sgibbs		if (role == ROLE_TARGET)
302497883Sgibbs			*bus_width = MIN(tinfo->user.width, *bus_width);
302597883Sgibbs		else
302697883Sgibbs			*bus_width = MIN(tinfo->goal.width, *bus_width);
302797883Sgibbs	}
302897883Sgibbs}
302997883Sgibbs
303097883Sgibbs/*
303197883Sgibbs * Update the bitmask of targets for which the controller should
303297883Sgibbs * negotiate with at the next convenient oportunity.  This currently
303397883Sgibbs * means the next time we send the initial identify messages for
303497883Sgibbs * a new transaction.
303597883Sgibbs */
303697883Sgibbsint
303797883Sgibbsahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
303897883Sgibbs		       struct ahd_tmode_tstate *tstate,
3039107441Sscottl		       struct ahd_initiator_tinfo *tinfo, ahd_neg_type neg_type)
304097883Sgibbs{
304197883Sgibbs	u_int auto_negotiate_orig;
304297883Sgibbs
304397883Sgibbs	auto_negotiate_orig = tstate->auto_negotiate;
3044107441Sscottl	if (neg_type == AHD_NEG_ALWAYS) {
3045107441Sscottl		/*
3046107441Sscottl		 * Force our "current" settings to be
3047107441Sscottl		 * unknown so that unless a bus reset
3048107441Sscottl		 * occurs the need to renegotiate is
3049107441Sscottl		 * recorded persistently.
3050107441Sscottl		 */
3051109588Sgibbs		if ((ahd->features & AHD_WIDE) != 0)
3052109588Sgibbs			tinfo->curr.width = AHD_WIDTH_UNKNOWN;
3053107441Sscottl		tinfo->curr.period = AHD_PERIOD_UNKNOWN;
3054107441Sscottl		tinfo->curr.offset = AHD_OFFSET_UNKNOWN;
3055107441Sscottl	}
305697883Sgibbs	if (tinfo->curr.period != tinfo->goal.period
305797883Sgibbs	 || tinfo->curr.width != tinfo->goal.width
305897883Sgibbs	 || tinfo->curr.offset != tinfo->goal.offset
305997883Sgibbs	 || tinfo->curr.ppr_options != tinfo->goal.ppr_options
3060107441Sscottl	 || (neg_type == AHD_NEG_IF_NON_ASYNC
3061107441Sscottl	  && (tinfo->goal.offset != 0
306297883Sgibbs	   || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
306397883Sgibbs	   || tinfo->goal.ppr_options != 0)))
306497883Sgibbs		tstate->auto_negotiate |= devinfo->target_mask;
306597883Sgibbs	else
306697883Sgibbs		tstate->auto_negotiate &= ~devinfo->target_mask;
306797883Sgibbs
306897883Sgibbs	return (auto_negotiate_orig != tstate->auto_negotiate);
306997883Sgibbs}
307097883Sgibbs
307197883Sgibbs/*
307297883Sgibbs * Update the user/goal/curr tables of synchronous negotiation
307397883Sgibbs * parameters as well as, in the case of a current or active update,
307497883Sgibbs * any data structures on the host controller.  In the case of an
307597883Sgibbs * active update, the specified target is currently talking to us on
307697883Sgibbs * the bus, so the transfer parameter update must take effect
307797883Sgibbs * immediately.
307897883Sgibbs */
307997883Sgibbsvoid
308097883Sgibbsahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
308197883Sgibbs		 u_int period, u_int offset, u_int ppr_options,
308297883Sgibbs		 u_int type, int paused)
308397883Sgibbs{
308497883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
308597883Sgibbs	struct	ahd_tmode_tstate *tstate;
308697883Sgibbs	u_int	old_period;
308797883Sgibbs	u_int	old_offset;
308897883Sgibbs	u_int	old_ppr;
308997883Sgibbs	int	active;
309097883Sgibbs	int	update_needed;
309197883Sgibbs
309297883Sgibbs	active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
309397883Sgibbs	update_needed = 0;
309497883Sgibbs
309597883Sgibbs	if (period == 0 || offset == 0) {
309697883Sgibbs		period = 0;
309797883Sgibbs		offset = 0;
309897883Sgibbs	}
309997883Sgibbs
310097883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
310197883Sgibbs				    devinfo->target, &tstate);
310297883Sgibbs
310397883Sgibbs	if ((type & AHD_TRANS_USER) != 0) {
310497883Sgibbs		tinfo->user.period = period;
310597883Sgibbs		tinfo->user.offset = offset;
310697883Sgibbs		tinfo->user.ppr_options = ppr_options;
310797883Sgibbs	}
310897883Sgibbs
310997883Sgibbs	if ((type & AHD_TRANS_GOAL) != 0) {
311097883Sgibbs		tinfo->goal.period = period;
311197883Sgibbs		tinfo->goal.offset = offset;
311297883Sgibbs		tinfo->goal.ppr_options = ppr_options;
311397883Sgibbs	}
311497883Sgibbs
311597883Sgibbs	old_period = tinfo->curr.period;
311697883Sgibbs	old_offset = tinfo->curr.offset;
311797883Sgibbs	old_ppr	   = tinfo->curr.ppr_options;
311897883Sgibbs
311997883Sgibbs	if ((type & AHD_TRANS_CUR) != 0
312097883Sgibbs	 && (old_period != period
312197883Sgibbs	  || old_offset != offset
312297883Sgibbs	  || old_ppr != ppr_options)) {
312397883Sgibbs
312497883Sgibbs		update_needed++;
312597883Sgibbs
312697883Sgibbs		tinfo->curr.period = period;
312797883Sgibbs		tinfo->curr.offset = offset;
312897883Sgibbs		tinfo->curr.ppr_options = ppr_options;
312997883Sgibbs
313097883Sgibbs		ahd_send_async(ahd, devinfo->channel, devinfo->target,
313197883Sgibbs			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
313297883Sgibbs		if (bootverbose) {
313397883Sgibbs			if (offset != 0) {
3134109588Sgibbs				int options;
3135109588Sgibbs
313697883Sgibbs				printf("%s: target %d synchronous with "
3137109588Sgibbs				       "period = 0x%x, offset = 0x%x",
313897883Sgibbs				       ahd_name(ahd), devinfo->target,
3139109588Sgibbs				       period, offset);
3140109588Sgibbs				options = 0;
3141111954Sgibbs				if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
3142111954Sgibbs					printf("(RDSTRM");
3143111954Sgibbs					options++;
3144111954Sgibbs				}
3145109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
3146111954Sgibbs					printf("%s", options ? "|DT" : "(DT");
3147109588Sgibbs					options++;
3148109588Sgibbs				}
3149109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3150109588Sgibbs					printf("%s", options ? "|IU" : "(IU");
3151109588Sgibbs					options++;
3152109588Sgibbs				}
3153109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_RTI) != 0) {
3154109588Sgibbs					printf("%s", options ? "|RTI" : "(RTI");
3155109588Sgibbs					options++;
3156109588Sgibbs				}
3157109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
3158109588Sgibbs					printf("%s", options ? "|QAS" : "(QAS");
3159109588Sgibbs					options++;
3160109588Sgibbs				}
3161109588Sgibbs				if (options != 0)
3162109588Sgibbs					printf(")\n");
3163109588Sgibbs				else
3164109588Sgibbs					printf("\n");
316597883Sgibbs			} else {
316697883Sgibbs				printf("%s: target %d using "
3167109588Sgibbs				       "asynchronous transfers%s\n",
3168109588Sgibbs				       ahd_name(ahd), devinfo->target,
3169109588Sgibbs				       (ppr_options & MSG_EXT_PPR_QAS_REQ) != 0
3170109588Sgibbs				     ?  "(QAS)" : "");
317197883Sgibbs			}
317297883Sgibbs		}
317397883Sgibbs	}
317497883Sgibbs	/*
317597883Sgibbs	 * Always refresh the neg-table to handle the case of the
317697883Sgibbs	 * sequencer setting the ENATNO bit for a MK_MESSAGE request.
317797883Sgibbs	 * We will always renegotiate in that case if this is a
3178102679Sgibbs	 * packetized request.  Also manage the busfree expected flag
3179102679Sgibbs	 * from this common routine so that we catch changes due to
3180102679Sgibbs	 * WDTR or SDTR messages.
318197883Sgibbs	 */
3182102679Sgibbs	if ((type & AHD_TRANS_CUR) != 0) {
3183102679Sgibbs		if (!paused)
3184102679Sgibbs			ahd_pause(ahd);
318597883Sgibbs		ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
3186102679Sgibbs		if (!paused)
3187102679Sgibbs			ahd_unpause(ahd);
3188102679Sgibbs		if (ahd->msg_type != MSG_TYPE_NONE) {
3189102679Sgibbs			if ((old_ppr & MSG_EXT_PPR_IU_REQ)
3190102679Sgibbs			 != (ppr_options & MSG_EXT_PPR_IU_REQ)) {
3191102679Sgibbs#ifdef AHD_DEBUG
3192107441Sscottl				if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3193107441Sscottl					ahd_print_devinfo(ahd, devinfo);
3194102679Sgibbs					printf("Expecting IU Change busfree\n");
3195107441Sscottl				}
3196102679Sgibbs#endif
3197102679Sgibbs				ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
3198102679Sgibbs					       |  MSG_FLAG_IU_REQ_CHANGED;
3199102679Sgibbs			}
3200102679Sgibbs			if ((old_ppr & MSG_EXT_PPR_IU_REQ) != 0) {
3201102679Sgibbs#ifdef AHD_DEBUG
3202102679Sgibbs				if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
3203102679Sgibbs					printf("PPR with IU_REQ outstanding\n");
3204102679Sgibbs#endif
3205102679Sgibbs				ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE;
3206102679Sgibbs			}
3207102679Sgibbs		}
3208102679Sgibbs	}
320997883Sgibbs
321097883Sgibbs	update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
3211107441Sscottl						tinfo, AHD_NEG_TO_GOAL);
321297883Sgibbs
3213102679Sgibbs	if (update_needed && active)
321497883Sgibbs		ahd_update_pending_scbs(ahd);
321597883Sgibbs}
321697883Sgibbs
321797883Sgibbs/*
321897883Sgibbs * Update the user/goal/curr tables of wide negotiation
321997883Sgibbs * parameters as well as, in the case of a current or active update,
322097883Sgibbs * any data structures on the host controller.  In the case of an
322197883Sgibbs * active update, the specified target is currently talking to us on
322297883Sgibbs * the bus, so the transfer parameter update must take effect
322397883Sgibbs * immediately.
322497883Sgibbs */
322597883Sgibbsvoid
322697883Sgibbsahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
322797883Sgibbs	      u_int width, u_int type, int paused)
322897883Sgibbs{
322997883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
323097883Sgibbs	struct	ahd_tmode_tstate *tstate;
323197883Sgibbs	u_int	oldwidth;
323297883Sgibbs	int	active;
323397883Sgibbs	int	update_needed;
323497883Sgibbs
323597883Sgibbs	active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
323697883Sgibbs	update_needed = 0;
323797883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
323897883Sgibbs				    devinfo->target, &tstate);
323997883Sgibbs
324097883Sgibbs	if ((type & AHD_TRANS_USER) != 0)
324197883Sgibbs		tinfo->user.width = width;
324297883Sgibbs
324397883Sgibbs	if ((type & AHD_TRANS_GOAL) != 0)
324497883Sgibbs		tinfo->goal.width = width;
324597883Sgibbs
324697883Sgibbs	oldwidth = tinfo->curr.width;
324797883Sgibbs	if ((type & AHD_TRANS_CUR) != 0 && oldwidth != width) {
324897883Sgibbs
324997883Sgibbs		update_needed++;
325097883Sgibbs
325197883Sgibbs		tinfo->curr.width = width;
325297883Sgibbs		ahd_send_async(ahd, devinfo->channel, devinfo->target,
325397883Sgibbs			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
325497883Sgibbs		if (bootverbose) {
325597883Sgibbs			printf("%s: target %d using %dbit transfers\n",
325697883Sgibbs			       ahd_name(ahd), devinfo->target,
325797883Sgibbs			       8 * (0x01 << width));
325897883Sgibbs		}
325997883Sgibbs	}
3260102679Sgibbs
3261102679Sgibbs	if ((type & AHD_TRANS_CUR) != 0) {
3262102679Sgibbs		if (!paused)
3263102679Sgibbs			ahd_pause(ahd);
326497883Sgibbs		ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
3265102679Sgibbs		if (!paused)
3266102679Sgibbs			ahd_unpause(ahd);
3267102679Sgibbs	}
326897883Sgibbs
326997883Sgibbs	update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
3270107441Sscottl						tinfo, AHD_NEG_TO_GOAL);
3271102679Sgibbs	if (update_needed && active)
327297883Sgibbs		ahd_update_pending_scbs(ahd);
3273102679Sgibbs
327497883Sgibbs}
327597883Sgibbs
327697883Sgibbs/*
327797883Sgibbs * Update the current state of tagged queuing for a given target.
327897883Sgibbs */
327997883Sgibbsvoid
328097883Sgibbsahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
328197883Sgibbs	     ahd_queue_alg alg)
328297883Sgibbs{
3283109588Sgibbs	ahd_platform_set_tags(ahd, devinfo, alg);
3284109588Sgibbs	ahd_send_async(ahd, devinfo->channel, devinfo->target,
3285109588Sgibbs		       devinfo->lun, AC_TRANSFER_NEG, &alg);
328697883Sgibbs}
328797883Sgibbs
328897883Sgibbsstatic void
328997883Sgibbsahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
329097883Sgibbs		     struct ahd_transinfo *tinfo)
329197883Sgibbs{
329297883Sgibbs	ahd_mode_state	saved_modes;
329397883Sgibbs	u_int		period;
329497883Sgibbs	u_int		ppr_opts;
329597883Sgibbs	u_int		con_opts;
329697883Sgibbs	u_int		offset;
3297109588Sgibbs	u_int		saved_negoaddr;
3298107441Sscottl	uint8_t		iocell_opts[sizeof(ahd->iocell_opts)];
329997883Sgibbs
330097883Sgibbs	saved_modes = ahd_save_modes(ahd);
330197883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
330297883Sgibbs
3303109588Sgibbs	saved_negoaddr = ahd_inb(ahd, NEGOADDR);
330497883Sgibbs	ahd_outb(ahd, NEGOADDR, devinfo->target);
330597883Sgibbs	period = tinfo->period;
330697883Sgibbs	offset = tinfo->offset;
3307107441Sscottl	memcpy(iocell_opts, ahd->iocell_opts, sizeof(ahd->iocell_opts));
3308107441Sscottl	ppr_opts = tinfo->ppr_options & (MSG_EXT_PPR_QAS_REQ|MSG_EXT_PPR_DT_REQ
3309107441Sscottl					|MSG_EXT_PPR_IU_REQ|MSG_EXT_PPR_RTI);
3310107441Sscottl	con_opts = 0;
331197883Sgibbs	if (period == 0)
331297883Sgibbs		period = AHD_SYNCRATE_ASYNC;
331397883Sgibbs	if (period == AHD_SYNCRATE_160) {
3314107441Sscottl
3315107441Sscottl		if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
3316107441Sscottl			/*
3317107441Sscottl			 * When the SPI4 spec was finalized, PACE transfers
3318107441Sscottl			 * was not made a configurable option in the PPR
3319107441Sscottl			 * message.  Instead it is assumed to be enabled for
3320107441Sscottl			 * any syncrate faster than 80MHz.  Nevertheless,
3321107441Sscottl			 * Harpoon2A4 allows this to be configurable.
3322107441Sscottl			 *
3323107441Sscottl			 * Harpoon2A4 also assumes at most 2 data bytes per
3324107441Sscottl			 * negotiated REQ/ACK offset.  Paced transfers take
3325107441Sscottl			 * 4, so we must adjust our offset.
3326107441Sscottl			 */
3327107441Sscottl			ppr_opts |= PPROPT_PACE;
3328107441Sscottl			offset *= 2;
3329107441Sscottl
3330107441Sscottl			/*
3331107441Sscottl			 * Harpoon2A assumed that there would be a
3332107441Sscottl			 * fallback rate between 160MHz and 80Mhz,
3333107441Sscottl			 * so 7 is used as the period factor rather
3334107441Sscottl			 * than 8 for 160MHz.
3335107441Sscottl			 */
3336107441Sscottl			period = AHD_SYNCRATE_REVA_160;
3337107441Sscottl		}
3338107441Sscottl		if ((tinfo->ppr_options & MSG_EXT_PPR_PCOMP_EN) == 0)
3339107441Sscottl			iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
3340107441Sscottl			    ~AHD_PRECOMP_MASK;
3341107441Sscottl	} else {
3342107441Sscottl		/*
3343107441Sscottl		 * Precomp should be disabled for non-paced transfers.
3344107441Sscottl		 */
3345107441Sscottl		iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
3346107441Sscottl
3347107441Sscottl		if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
3348123579Sgibbs		 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
3349123579Sgibbs		 && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
3350107441Sscottl			/*
3351107441Sscottl			 * Slow down our CRC interval to be
3352123579Sgibbs			 * compatible with non-packetized
3353123579Sgibbs			 * U160 devices that can't handle a
3354123579Sgibbs			 * CRC at full speed.
3355107441Sscottl			 */
3356107441Sscottl			con_opts |= ENSLOWCRC;
3357107441Sscottl		}
3358123579Sgibbs
3359123579Sgibbs		if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
3360123579Sgibbs			/*
3361123579Sgibbs			 * On H2A4, revert to a slower slewrate
3362123579Sgibbs			 * on non-paced transfers.
3363123579Sgibbs			 */
3364123579Sgibbs			iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
3365123579Sgibbs			    ~AHD_SLEWRATE_MASK;
3366123579Sgibbs		}
336797883Sgibbs	}
336897883Sgibbs
3369107441Sscottl	ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
3370107441Sscottl	ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_PRECOMP_SLEW_INDEX]);
3371107441Sscottl	ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_AMPLITUDE);
3372107441Sscottl	ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_AMPLITUDE_INDEX]);
3373107441Sscottl
337497883Sgibbs	ahd_outb(ahd, NEGPERIOD, period);
337597883Sgibbs	ahd_outb(ahd, NEGPPROPTS, ppr_opts);
337697883Sgibbs	ahd_outb(ahd, NEGOFFSET, offset);
337797883Sgibbs
337897883Sgibbs	if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT)
337997883Sgibbs		con_opts |= WIDEXFER;
338097883Sgibbs
338197883Sgibbs	/*
338297883Sgibbs	 * During packetized transfers, the target will
338397883Sgibbs	 * give us the oportunity to send command packets
338497883Sgibbs	 * without us asserting attention.
338597883Sgibbs	 */
338697883Sgibbs	if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
338797883Sgibbs		con_opts |= ENAUTOATNO;
338897883Sgibbs	ahd_outb(ahd, NEGCONOPTS, con_opts);
3389109588Sgibbs	ahd_outb(ahd, NEGOADDR, saved_negoaddr);
339097883Sgibbs	ahd_restore_modes(ahd, saved_modes);
339197883Sgibbs}
339297883Sgibbs
339397883Sgibbs/*
3394102679Sgibbs * When the transfer settings for a connection change, setup for
3395102679Sgibbs * negotiation in pending SCBs to effect the change as quickly as
3396102679Sgibbs * possible.  We also cancel any negotiations that are scheduled
3397102679Sgibbs * for inflight SCBs that have not been started yet.
339897883Sgibbs */
339997883Sgibbsstatic void
340097883Sgibbsahd_update_pending_scbs(struct ahd_softc *ahd)
340197883Sgibbs{
340297883Sgibbs	struct		scb *pending_scb;
340397883Sgibbs	int		pending_scb_count;
340497883Sgibbs	int		paused;
340597883Sgibbs	u_int		saved_scbptr;
340697883Sgibbs	ahd_mode_state	saved_modes;
340797883Sgibbs
340897883Sgibbs	/*
340997883Sgibbs	 * Traverse the pending SCB list and ensure that all of the
3410102679Sgibbs	 * SCBs there have the proper settings.  We can only safely
3411102679Sgibbs	 * clear the negotiation required flag (setting requires the
3412102679Sgibbs	 * execution queue to be modified) and this is only possible
3413102679Sgibbs	 * if we are not already attempting to select out for this
3414102679Sgibbs	 * SCB.  For this reason, all callers only call this routine
3415102679Sgibbs	 * if we are changing the negotiation settings for the currently
3416102679Sgibbs	 * active transaction on the bus.
341797883Sgibbs	 */
341897883Sgibbs	pending_scb_count = 0;
341997883Sgibbs	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
342097883Sgibbs		struct ahd_devinfo devinfo;
342197883Sgibbs		struct ahd_initiator_tinfo *tinfo;
342297883Sgibbs		struct ahd_tmode_tstate *tstate;
342397883Sgibbs
342497883Sgibbs		ahd_scb_devinfo(ahd, &devinfo, pending_scb);
342597883Sgibbs		tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
342697883Sgibbs					    devinfo.our_scsiid,
342797883Sgibbs					    devinfo.target, &tstate);
342897883Sgibbs		if ((tstate->auto_negotiate & devinfo.target_mask) == 0
342997883Sgibbs		 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
343097883Sgibbs			pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
3431133122Sgibbs			pending_scb->hscb->control &= ~MK_MESSAGE;
343297883Sgibbs		}
343397883Sgibbs		ahd_sync_scb(ahd, pending_scb,
343497883Sgibbs			     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
343597883Sgibbs		pending_scb_count++;
343697883Sgibbs	}
343797883Sgibbs
343897883Sgibbs	if (pending_scb_count == 0)
343997883Sgibbs		return;
344097883Sgibbs
344197883Sgibbs	if (ahd_is_paused(ahd)) {
344297883Sgibbs		paused = 1;
344397883Sgibbs	} else {
344497883Sgibbs		paused = 0;
344597883Sgibbs		ahd_pause(ahd);
344697883Sgibbs	}
344797883Sgibbs
3448102679Sgibbs	/*
3449102679Sgibbs	 * Force the sequencer to reinitialize the selection for
3450102679Sgibbs	 * the command at the head of the execution queue if it
3451102679Sgibbs	 * has already been setup.  The negotiation changes may
3452129134Sgibbs	 * effect whether we select-out with ATN.  It is only
3453129134Sgibbs	 * safe to clear ENSELO when the bus is not free and no
3454129134Sgibbs	 * selection is in progres or completed.
3455102679Sgibbs	 */
345697883Sgibbs	saved_modes = ahd_save_modes(ahd);
345797883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3458129134Sgibbs	if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
3459129134Sgibbs	 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
3460129134Sgibbs		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
346197883Sgibbs	saved_scbptr = ahd_get_scbptr(ahd);
346297883Sgibbs	/* Ensure that the hscbs down on the card match the new information */
3463133122Sgibbs	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
3464133122Sgibbs		u_int	scb_tag;
346597883Sgibbs		u_int	control;
346697883Sgibbs
3467133122Sgibbs		scb_tag = SCB_GET_TAG(pending_scb);
3468116938Sgibbs		ahd_set_scbptr(ahd, scb_tag);
346997883Sgibbs		control = ahd_inb_scbram(ahd, SCB_CONTROL);
347097883Sgibbs		control &= ~MK_MESSAGE;
3471133122Sgibbs		control |= pending_scb->hscb->control & MK_MESSAGE;
347297883Sgibbs		ahd_outb(ahd, SCB_CONTROL, control);
347397883Sgibbs	}
3474104023Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
347597883Sgibbs	ahd_restore_modes(ahd, saved_modes);
347697883Sgibbs
347797883Sgibbs	if (paused == 0)
347897883Sgibbs		ahd_unpause(ahd);
347997883Sgibbs}
348097883Sgibbs
348197883Sgibbs/**************************** Pathing Information *****************************/
348297883Sgibbsstatic void
348397883Sgibbsahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
348497883Sgibbs{
348597883Sgibbs	ahd_mode_state	saved_modes;
348697883Sgibbs	u_int		saved_scsiid;
348797883Sgibbs	role_t		role;
348897883Sgibbs	int		our_id;
348997883Sgibbs
349097883Sgibbs	saved_modes = ahd_save_modes(ahd);
349197883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
349297883Sgibbs
349397883Sgibbs	if (ahd_inb(ahd, SSTAT0) & TARGET)
349497883Sgibbs		role = ROLE_TARGET;
349597883Sgibbs	else
349697883Sgibbs		role = ROLE_INITIATOR;
349797883Sgibbs
349897883Sgibbs	if (role == ROLE_TARGET
349997883Sgibbs	 && (ahd_inb(ahd, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) {
350097883Sgibbs		/* We were selected, so pull our id from TARGIDIN */
350197883Sgibbs		our_id = ahd_inb(ahd, TARGIDIN) & OID;
350297883Sgibbs	} else if (role == ROLE_TARGET)
350397883Sgibbs		our_id = ahd_inb(ahd, TOWNID);
350497883Sgibbs	else
350597883Sgibbs		our_id = ahd_inb(ahd, IOWNID);
350697883Sgibbs
350797883Sgibbs	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
350897883Sgibbs	ahd_compile_devinfo(devinfo,
350997883Sgibbs			    our_id,
351097883Sgibbs			    SCSIID_TARGET(ahd, saved_scsiid),
351197883Sgibbs			    ahd_inb(ahd, SAVED_LUN),
351297883Sgibbs			    SCSIID_CHANNEL(ahd, saved_scsiid),
351397883Sgibbs			    role);
351497883Sgibbs	ahd_restore_modes(ahd, saved_modes);
351597883Sgibbs}
351697883Sgibbs
3517107441Sscottlvoid
3518102679Sgibbsahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
3519102679Sgibbs{
3520107441Sscottl	printf("%s:%c:%d:%d: ", ahd_name(ahd), 'A',
3521102679Sgibbs	       devinfo->target, devinfo->lun);
3522102679Sgibbs}
3523102679Sgibbs
352497883Sgibbsstruct ahd_phase_table_entry*
352597883Sgibbsahd_lookup_phase_entry(int phase)
352697883Sgibbs{
352797883Sgibbs	struct ahd_phase_table_entry *entry;
352897883Sgibbs	struct ahd_phase_table_entry *last_entry;
352997883Sgibbs
353097883Sgibbs	/*
353197883Sgibbs	 * num_phases doesn't include the default entry which
353297883Sgibbs	 * will be returned if the phase doesn't match.
353397883Sgibbs	 */
353497883Sgibbs	last_entry = &ahd_phase_table[num_phases];
353597883Sgibbs	for (entry = ahd_phase_table; entry < last_entry; entry++) {
353697883Sgibbs		if (phase == entry->phase)
353797883Sgibbs			break;
353897883Sgibbs	}
353997883Sgibbs	return (entry);
354097883Sgibbs}
354197883Sgibbs
354297883Sgibbsvoid
354397883Sgibbsahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target,
354497883Sgibbs		    u_int lun, char channel, role_t role)
354597883Sgibbs{
354697883Sgibbs	devinfo->our_scsiid = our_id;
354797883Sgibbs	devinfo->target = target;
354897883Sgibbs	devinfo->lun = lun;
354997883Sgibbs	devinfo->target_offset = target;
355097883Sgibbs	devinfo->channel = channel;
355197883Sgibbs	devinfo->role = role;
355297883Sgibbs	if (channel == 'B')
355397883Sgibbs		devinfo->target_offset += 8;
355497883Sgibbs	devinfo->target_mask = (0x01 << devinfo->target_offset);
355597883Sgibbs}
355697883Sgibbs
355797883Sgibbsstatic void
355897883Sgibbsahd_scb_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
355997883Sgibbs		struct scb *scb)
356097883Sgibbs{
356197883Sgibbs	role_t	role;
356297883Sgibbs	int	our_id;
356397883Sgibbs
356497883Sgibbs	our_id = SCSIID_OUR_ID(scb->hscb->scsiid);
356597883Sgibbs	role = ROLE_INITIATOR;
356697883Sgibbs	if ((scb->hscb->control & TARGET_SCB) != 0)
356797883Sgibbs		role = ROLE_TARGET;
356897883Sgibbs	ahd_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahd, scb),
356997883Sgibbs			    SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahd, scb), role);
357097883Sgibbs}
357197883Sgibbs
357297883Sgibbs
357397883Sgibbs/************************ Message Phase Processing ****************************/
357497883Sgibbs/*
357597883Sgibbs * When an initiator transaction with the MK_MESSAGE flag either reconnects
357697883Sgibbs * or enters the initial message out phase, we are interrupted.  Fill our
357797883Sgibbs * outgoing message buffer with the appropriate message and beging handing
357897883Sgibbs * the message phase(s) manually.
357997883Sgibbs */
358097883Sgibbsstatic void
358197883Sgibbsahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
358297883Sgibbs			   struct scb *scb)
358397883Sgibbs{
358497883Sgibbs	/*
358597883Sgibbs	 * To facilitate adding multiple messages together,
358697883Sgibbs	 * each routine should increment the index and len
358797883Sgibbs	 * variables instead of setting them explicitly.
358897883Sgibbs	 */
358997883Sgibbs	ahd->msgout_index = 0;
359097883Sgibbs	ahd->msgout_len = 0;
359197883Sgibbs
359297883Sgibbs	if (ahd_currently_packetized(ahd))
359397883Sgibbs		ahd->msg_flags |= MSG_FLAG_PACKETIZED;
359497883Sgibbs
359597883Sgibbs	if (ahd->send_msg_perror
359697883Sgibbs	 && ahd_inb(ahd, MSG_OUT) == HOST_MSG) {
359797883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = ahd->send_msg_perror;
359897883Sgibbs		ahd->msgout_len++;
359997883Sgibbs		ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
3600107441Sscottl#ifdef AHD_DEBUG
3601107441Sscottl		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
3602107441Sscottl			printf("Setting up for Parity Error delivery\n");
3603107441Sscottl#endif
360497883Sgibbs		return;
360597883Sgibbs	} else if (scb == NULL) {
360697883Sgibbs		printf("%s: WARNING. No pending message for "
360797883Sgibbs		       "I_T msgin.  Issuing NO-OP\n", ahd_name(ahd));
3608199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
360997883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP;
361097883Sgibbs		ahd->msgout_len++;
361197883Sgibbs		ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
361297883Sgibbs		return;
361397883Sgibbs	}
361497883Sgibbs
361597883Sgibbs	if ((scb->flags & SCB_DEVICE_RESET) == 0
361697883Sgibbs	 && (scb->flags & SCB_PACKETIZED) == 0
361797883Sgibbs	 && ahd_inb(ahd, MSG_OUT) == MSG_IDENTIFYFLAG) {
361897883Sgibbs		u_int identify_msg;
361997883Sgibbs
362097883Sgibbs		identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb);
362197883Sgibbs		if ((scb->hscb->control & DISCENB) != 0)
362297883Sgibbs			identify_msg |= MSG_IDENTIFY_DISCFLAG;
362397883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = identify_msg;
362497883Sgibbs		ahd->msgout_len++;
362597883Sgibbs
362697883Sgibbs		if ((scb->hscb->control & TAG_ENB) != 0) {
362797883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] =
362897883Sgibbs			    scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE);
362997883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] = SCB_GET_TAG(scb);
363097883Sgibbs			ahd->msgout_len += 2;
363197883Sgibbs		}
363297883Sgibbs	}
363397883Sgibbs
363497883Sgibbs	if (scb->flags & SCB_DEVICE_RESET) {
363597883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET;
363697883Sgibbs		ahd->msgout_len++;
363797883Sgibbs		ahd_print_path(ahd, scb);
363897883Sgibbs		printf("Bus Device Reset Message Sent\n");
3639199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
364097883Sgibbs		/*
364197883Sgibbs		 * Clear our selection hardware in advance of
364297883Sgibbs		 * the busfree.  We may have an entry in the waiting
364397883Sgibbs		 * Q for this target, and we don't want to go about
364497883Sgibbs		 * selecting while we handle the busfree and blow it
364597883Sgibbs		 * away.
364697883Sgibbs		 */
364797883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
364897883Sgibbs	} else if ((scb->flags & SCB_ABORT) != 0) {
364997883Sgibbs
365097883Sgibbs		if ((scb->hscb->control & TAG_ENB) != 0) {
365197883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT_TAG;
365297883Sgibbs		} else {
365397883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT;
365497883Sgibbs		}
365597883Sgibbs		ahd->msgout_len++;
365697883Sgibbs		ahd_print_path(ahd, scb);
365797883Sgibbs		printf("Abort%s Message Sent\n",
365897883Sgibbs		       (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");
3659199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
366097883Sgibbs		/*
366197883Sgibbs		 * Clear our selection hardware in advance of
366297883Sgibbs		 * the busfree.  We may have an entry in the waiting
366397883Sgibbs		 * Q for this target, and we don't want to go about
366497883Sgibbs		 * selecting while we handle the busfree and blow it
366597883Sgibbs		 * away.
366697883Sgibbs		 */
366797883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
366897883Sgibbs	} else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
366997883Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
367097883Sgibbs		/*
367197883Sgibbs		 * Clear our selection hardware in advance of potential
367297883Sgibbs		 * PPR IU status change busfree.  We may have an entry in
367397883Sgibbs		 * the waiting Q for this target, and we don't want to go
367497883Sgibbs		 * about selecting while we handle the busfree and blow
367597883Sgibbs		 * it away.
367697883Sgibbs		 */
367797883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
367897883Sgibbs	} else {
367997883Sgibbs		printf("ahd_intr: AWAITING_MSG for an SCB that "
368097883Sgibbs		       "does not have a waiting message\n");
368197883Sgibbs		printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid,
368297883Sgibbs		       devinfo->target_mask);
3683199260Sattilio		AHD_FATAL_ERROR(ahd);
3684109588Sgibbs		panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
368597883Sgibbs		      "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
3686116940Sgibbs		      ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
3687109588Sgibbs		      scb->flags);
368897883Sgibbs	}
368997883Sgibbs
369097883Sgibbs	/*
369197883Sgibbs	 * Clear the MK_MESSAGE flag from the SCB so we aren't
369297883Sgibbs	 * asked to send this message again.
369397883Sgibbs	 */
369497883Sgibbs	ahd_outb(ahd, SCB_CONTROL,
369597883Sgibbs		 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
369697883Sgibbs	scb->hscb->control &= ~MK_MESSAGE;
369797883Sgibbs	ahd->msgout_index = 0;
369897883Sgibbs	ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
369997883Sgibbs}
370097883Sgibbs
370197883Sgibbs/*
370297883Sgibbs * Build an appropriate transfer negotiation message for the
370397883Sgibbs * currently active target.
370497883Sgibbs */
370597883Sgibbsstatic void
370697883Sgibbsahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
370797883Sgibbs{
370897883Sgibbs	/*
370997883Sgibbs	 * We need to initiate transfer negotiations.
371097883Sgibbs	 * If our current and goal settings are identical,
371197883Sgibbs	 * we want to renegotiate due to a check condition.
371297883Sgibbs	 */
371397883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
371497883Sgibbs	struct	ahd_tmode_tstate *tstate;
371597883Sgibbs	int	dowide;
371697883Sgibbs	int	dosync;
371797883Sgibbs	int	doppr;
371897883Sgibbs	u_int	period;
371997883Sgibbs	u_int	ppr_options;
372097883Sgibbs	u_int	offset;
372197883Sgibbs
372297883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
372397883Sgibbs				    devinfo->target, &tstate);
372497883Sgibbs	/*
372597883Sgibbs	 * Filter our period based on the current connection.
372697883Sgibbs	 * If we can't perform DT transfers on this segment (not in LVD
372797883Sgibbs	 * mode for instance), then our decision to issue a PPR message
372897883Sgibbs	 * may change.
372997883Sgibbs	 */
373097883Sgibbs	period = tinfo->goal.period;
3731115918Sgibbs	offset = tinfo->goal.offset;
373297883Sgibbs	ppr_options = tinfo->goal.ppr_options;
373397883Sgibbs	/* Target initiated PPR is not allowed in the SCSI spec */
373497883Sgibbs	if (devinfo->role == ROLE_TARGET)
373597883Sgibbs		ppr_options = 0;
373697883Sgibbs	ahd_devlimited_syncrate(ahd, tinfo, &period,
373797883Sgibbs				&ppr_options, devinfo->role);
373897883Sgibbs	dowide = tinfo->curr.width != tinfo->goal.width;
3739115918Sgibbs	dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
3740107441Sscottl	/*
3741107441Sscottl	 * Only use PPR if we have options that need it, even if the device
3742107441Sscottl	 * claims to support it.  There might be an expander in the way
3743107441Sscottl	 * that doesn't.
3744107441Sscottl	 */
3745107441Sscottl	doppr = ppr_options != 0;
374697883Sgibbs
374797883Sgibbs	if (!dowide && !dosync && !doppr) {
374897883Sgibbs		dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
3749115918Sgibbs		dosync = tinfo->goal.offset != 0;
375097883Sgibbs	}
375197883Sgibbs
375297883Sgibbs	if (!dowide && !dosync && !doppr) {
3753107441Sscottl		/*
3754107441Sscottl		 * Force async with a WDTR message if we have a wide bus,
3755107441Sscottl		 * or just issue an SDTR with a 0 offset.
3756107441Sscottl		 */
3757107441Sscottl		if ((ahd->features & AHD_WIDE) != 0)
3758107441Sscottl			dowide = 1;
3759107441Sscottl		else
3760107441Sscottl			dosync = 1;
3761107441Sscottl
3762107441Sscottl		if (bootverbose) {
3763107441Sscottl			ahd_print_devinfo(ahd, devinfo);
3764107441Sscottl			printf("Ensuring async\n");
3765107441Sscottl		}
376697883Sgibbs	}
376797883Sgibbs	/* Target initiated PPR is not allowed in the SCSI spec */
376897883Sgibbs	if (devinfo->role == ROLE_TARGET)
3769107441Sscottl		doppr = 0;
377097883Sgibbs
377197883Sgibbs	/*
377297883Sgibbs	 * Both the PPR message and SDTR message require the
377397883Sgibbs	 * goal syncrate to be limited to what the target device
377497883Sgibbs	 * is capable of handling (based on whether an LVD->SE
377597883Sgibbs	 * expander is on the bus), so combine these two cases.
377697883Sgibbs	 * Regardless, guarantee that if we are using WDTR and SDTR
377797883Sgibbs	 * messages that WDTR comes first.
377897883Sgibbs	 */
3779107441Sscottl	if (doppr || (dosync && !dowide)) {
378097883Sgibbs
378197883Sgibbs		offset = tinfo->goal.offset;
378297883Sgibbs		ahd_validate_offset(ahd, tinfo, period, &offset,
3783107441Sscottl				    doppr ? tinfo->goal.width
3784107441Sscottl					  : tinfo->curr.width,
378597883Sgibbs				    devinfo->role);
3786107441Sscottl		if (doppr) {
378797883Sgibbs			ahd_construct_ppr(ahd, devinfo, period, offset,
378897883Sgibbs					  tinfo->goal.width, ppr_options);
378997883Sgibbs		} else {
379097883Sgibbs			ahd_construct_sdtr(ahd, devinfo, period, offset);
379197883Sgibbs		}
379297883Sgibbs	} else {
379397883Sgibbs		ahd_construct_wdtr(ahd, devinfo, tinfo->goal.width);
379497883Sgibbs	}
379597883Sgibbs}
379697883Sgibbs
379797883Sgibbs/*
379897883Sgibbs * Build a synchronous negotiation message in our message
379997883Sgibbs * buffer based on the input parameters.
380097883Sgibbs */
380197883Sgibbsstatic void
380297883Sgibbsahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
380397883Sgibbs		   u_int period, u_int offset)
380497883Sgibbs{
3805107441Sscottl	if (offset == 0)
3806107441Sscottl		period = AHD_ASYNC_XFER_PERIOD;
380797883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
380897883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN;
380997883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR;
381097883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = period;
381197883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = offset;
381297883Sgibbs	ahd->msgout_len += 5;
381397883Sgibbs	if (bootverbose) {
381497883Sgibbs		printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",
381597883Sgibbs		       ahd_name(ahd), devinfo->channel, devinfo->target,
381697883Sgibbs		       devinfo->lun, period, offset);
381797883Sgibbs	}
381897883Sgibbs}
381997883Sgibbs
382097883Sgibbs/*
382197883Sgibbs * Build a wide negotiateion message in our message
382297883Sgibbs * buffer based on the input parameters.
382397883Sgibbs */
382497883Sgibbsstatic void
382597883Sgibbsahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
382697883Sgibbs		   u_int bus_width)
382797883Sgibbs{
382897883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
382997883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN;
383097883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR;
383197883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = bus_width;
383297883Sgibbs	ahd->msgout_len += 4;
383397883Sgibbs	if (bootverbose) {
383497883Sgibbs		printf("(%s:%c:%d:%d): Sending WDTR %x\n",
383597883Sgibbs		       ahd_name(ahd), devinfo->channel, devinfo->target,
383697883Sgibbs		       devinfo->lun, bus_width);
383797883Sgibbs	}
383897883Sgibbs}
383997883Sgibbs
384097883Sgibbs/*
384197883Sgibbs * Build a parallel protocol request message in our message
384297883Sgibbs * buffer based on the input parameters.
384397883Sgibbs */
384497883Sgibbsstatic void
384597883Sgibbsahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
384697883Sgibbs		  u_int period, u_int offset, u_int bus_width,
384797883Sgibbs		  u_int ppr_options)
384897883Sgibbs{
384997883Sgibbs	/*
385097883Sgibbs	 * Always request precompensation from
385197883Sgibbs	 * the other target if we are running
385297883Sgibbs	 * at paced syncrates.
385397883Sgibbs	 */
385497883Sgibbs	if (period <= AHD_SYNCRATE_PACED)
385597883Sgibbs		ppr_options |= MSG_EXT_PPR_PCOMP_EN;
3856107441Sscottl	if (offset == 0)
3857107441Sscottl		period = AHD_ASYNC_XFER_PERIOD;
385897883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
385997883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN;
386097883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR;
386197883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = period;
386297883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = 0;
386397883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = offset;
386497883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = bus_width;
386597883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = ppr_options;
386697883Sgibbs	ahd->msgout_len += 8;
386797883Sgibbs	if (bootverbose) {
386897883Sgibbs		printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "
386997883Sgibbs		       "offset %x, ppr_options %x\n", ahd_name(ahd),
387097883Sgibbs		       devinfo->channel, devinfo->target, devinfo->lun,
387197883Sgibbs		       bus_width, period, offset, ppr_options);
387297883Sgibbs	}
387397883Sgibbs}
387497883Sgibbs
387597883Sgibbs/*
387697883Sgibbs * Clear any active message state.
387797883Sgibbs */
387897883Sgibbsstatic void
387997883Sgibbsahd_clear_msg_state(struct ahd_softc *ahd)
388097883Sgibbs{
388197883Sgibbs	ahd_mode_state saved_modes;
388297883Sgibbs
388397883Sgibbs	saved_modes = ahd_save_modes(ahd);
388497883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
388597883Sgibbs	ahd->send_msg_perror = 0;
388697883Sgibbs	ahd->msg_flags = MSG_FLAG_NONE;
388797883Sgibbs	ahd->msgout_len = 0;
388897883Sgibbs	ahd->msgin_index = 0;
388997883Sgibbs	ahd->msg_type = MSG_TYPE_NONE;
389097883Sgibbs	if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
389197883Sgibbs		/*
389297883Sgibbs		 * The target didn't care to respond to our
389397883Sgibbs		 * message request, so clear ATN.
389497883Sgibbs		 */
389597883Sgibbs		ahd_outb(ahd, CLRSINT1, CLRATNO);
389697883Sgibbs	}
389797883Sgibbs	ahd_outb(ahd, MSG_OUT, MSG_NOOP);
389897883Sgibbs	ahd_outb(ahd, SEQ_FLAGS2,
389997883Sgibbs		 ahd_inb(ahd, SEQ_FLAGS2) & ~TARGET_MSG_PENDING);
390097883Sgibbs	ahd_restore_modes(ahd, saved_modes);
390197883Sgibbs}
390297883Sgibbs
390397883Sgibbs/*
390497883Sgibbs * Manual message loop handler.
390597883Sgibbs */
390697883Sgibbsstatic void
390797883Sgibbsahd_handle_message_phase(struct ahd_softc *ahd)
390897883Sgibbs{
390997883Sgibbs	struct	ahd_devinfo devinfo;
391097883Sgibbs	u_int	bus_phase;
391197883Sgibbs	int	end_session;
391297883Sgibbs
391397883Sgibbs	ahd_fetch_devinfo(ahd, &devinfo);
391497883Sgibbs	end_session = FALSE;
391597883Sgibbs	bus_phase = ahd_inb(ahd, LASTPHASE);
391697883Sgibbs
391797883Sgibbs	if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) {
391897883Sgibbs		printf("LQIRETRY for LQIPHASE_OUTPKT\n");
391997883Sgibbs		ahd_outb(ahd, LQCTL2, LQIRETRY);
392097883Sgibbs	}
392197883Sgibbsreswitch:
392297883Sgibbs	switch (ahd->msg_type) {
392397883Sgibbs	case MSG_TYPE_INITIATOR_MSGOUT:
392497883Sgibbs	{
392597883Sgibbs		int lastbyte;
392697883Sgibbs		int phasemis;
392797883Sgibbs		int msgdone;
392897883Sgibbs
392997883Sgibbs		if (ahd->msgout_len == 0 && ahd->send_msg_perror == 0)
393097883Sgibbs			panic("HOST_MSG_LOOP interrupt with no active message");
393197883Sgibbs
393297883Sgibbs#ifdef AHD_DEBUG
3933102679Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3934102679Sgibbs			ahd_print_devinfo(ahd, &devinfo);
3935102679Sgibbs			printf("INITIATOR_MSG_OUT");
3936102679Sgibbs		}
393797883Sgibbs#endif
393897883Sgibbs		phasemis = bus_phase != P_MESGOUT;
393997883Sgibbs		if (phasemis) {
394097883Sgibbs#ifdef AHD_DEBUG
394197883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3942102679Sgibbs				printf(" PHASEMIS %s\n",
394397883Sgibbs				       ahd_lookup_phase_entry(bus_phase)
394497883Sgibbs							     ->phasemsg);
394597883Sgibbs			}
394697883Sgibbs#endif
394797883Sgibbs			if (bus_phase == P_MESGIN) {
394897883Sgibbs				/*
394997883Sgibbs				 * Change gears and see if
395097883Sgibbs				 * this messages is of interest to
395197883Sgibbs				 * us or should be passed back to
395297883Sgibbs				 * the sequencer.
395397883Sgibbs				 */
395497883Sgibbs				ahd_outb(ahd, CLRSINT1, CLRATNO);
395597883Sgibbs				ahd->send_msg_perror = 0;
395697883Sgibbs				ahd->msg_type = MSG_TYPE_INITIATOR_MSGIN;
395797883Sgibbs				ahd->msgin_index = 0;
395897883Sgibbs				goto reswitch;
395997883Sgibbs			}
396097883Sgibbs			end_session = TRUE;
396197883Sgibbs			break;
396297883Sgibbs		}
396397883Sgibbs
396497883Sgibbs		if (ahd->send_msg_perror) {
396597883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRATNO);
396697883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRREQINIT);
396797883Sgibbs#ifdef AHD_DEBUG
396897883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
396997883Sgibbs				printf(" byte 0x%x\n", ahd->send_msg_perror);
397097883Sgibbs#endif
397197883Sgibbs			/*
397297883Sgibbs			 * If we are notifying the target of a CRC error
397397883Sgibbs			 * during packetized operations, the target is
397497883Sgibbs			 * within its rights to acknowledge our message
397597883Sgibbs			 * with a busfree.
397697883Sgibbs			 */
397797883Sgibbs			if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0
397897883Sgibbs			 && ahd->send_msg_perror == MSG_INITIATOR_DET_ERR)
397997883Sgibbs				ahd->msg_flags |= MSG_FLAG_EXPECT_IDE_BUSFREE;
398097883Sgibbs
398197883Sgibbs			ahd_outb(ahd, RETURN_2, ahd->send_msg_perror);
398297883Sgibbs			ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
398397883Sgibbs			break;
398497883Sgibbs		}
398597883Sgibbs
398697883Sgibbs		msgdone	= ahd->msgout_index == ahd->msgout_len;
398797883Sgibbs		if (msgdone) {
398897883Sgibbs			/*
398997883Sgibbs			 * The target has requested a retry.
399097883Sgibbs			 * Re-assert ATN, reset our message index to
399197883Sgibbs			 * 0, and try again.
399297883Sgibbs			 */
399397883Sgibbs			ahd->msgout_index = 0;
399497883Sgibbs			ahd_assert_atn(ahd);
399597883Sgibbs		}
399697883Sgibbs
399797883Sgibbs		lastbyte = ahd->msgout_index == (ahd->msgout_len - 1);
399897883Sgibbs		if (lastbyte) {
399997883Sgibbs			/* Last byte is signified by dropping ATN */
400097883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRATNO);
400197883Sgibbs		}
400297883Sgibbs
400397883Sgibbs		/*
400497883Sgibbs		 * Clear our interrupt status and present
400597883Sgibbs		 * the next byte on the bus.
400697883Sgibbs		 */
400797883Sgibbs		ahd_outb(ahd, CLRSINT1, CLRREQINIT);
400897883Sgibbs#ifdef AHD_DEBUG
400997883Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
401097883Sgibbs			printf(" byte 0x%x\n",
401197883Sgibbs			       ahd->msgout_buf[ahd->msgout_index]);
401297883Sgibbs#endif
401397883Sgibbs		ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]);
401497883Sgibbs		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
401597883Sgibbs		break;
401697883Sgibbs	}
401797883Sgibbs	case MSG_TYPE_INITIATOR_MSGIN:
401897883Sgibbs	{
401997883Sgibbs		int phasemis;
402097883Sgibbs		int message_done;
402197883Sgibbs
402297883Sgibbs#ifdef AHD_DEBUG
4023102679Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
4024102679Sgibbs			ahd_print_devinfo(ahd, &devinfo);
4025102679Sgibbs			printf("INITIATOR_MSG_IN");
4026102679Sgibbs		}
402797883Sgibbs#endif
402897883Sgibbs		phasemis = bus_phase != P_MESGIN;
402997883Sgibbs		if (phasemis) {
403097883Sgibbs#ifdef AHD_DEBUG
403197883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
403297883Sgibbs				printf(" PHASEMIS %s\n",
403397883Sgibbs				       ahd_lookup_phase_entry(bus_phase)
403497883Sgibbs							     ->phasemsg);
403597883Sgibbs			}
403697883Sgibbs#endif
403797883Sgibbs			ahd->msgin_index = 0;
403897883Sgibbs			if (bus_phase == P_MESGOUT
403997883Sgibbs			 && (ahd->send_msg_perror != 0
404097883Sgibbs			  || (ahd->msgout_len != 0
404197883Sgibbs			   && ahd->msgout_index == 0))) {
404297883Sgibbs				ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
404397883Sgibbs				goto reswitch;
404497883Sgibbs			}
404597883Sgibbs			end_session = TRUE;
404697883Sgibbs			break;
404797883Sgibbs		}
404897883Sgibbs
404997883Sgibbs		/* Pull the byte in without acking it */
405097883Sgibbs		ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS);
405197883Sgibbs#ifdef AHD_DEBUG
405297883Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
405397883Sgibbs			printf(" byte 0x%x\n",
405497883Sgibbs			       ahd->msgin_buf[ahd->msgin_index]);
405597883Sgibbs#endif
405697883Sgibbs
405797883Sgibbs		message_done = ahd_parse_msg(ahd, &devinfo);
405897883Sgibbs
405997883Sgibbs		if (message_done) {
406097883Sgibbs			/*
406197883Sgibbs			 * Clear our incoming message buffer in case there
406297883Sgibbs			 * is another message following this one.
406397883Sgibbs			 */
406497883Sgibbs			ahd->msgin_index = 0;
406597883Sgibbs
406697883Sgibbs			/*
406797883Sgibbs			 * If this message illicited a response,
406897883Sgibbs			 * assert ATN so the target takes us to the
406997883Sgibbs			 * message out phase.
407097883Sgibbs			 */
4071109588Sgibbs			if (ahd->msgout_len != 0) {
4072109588Sgibbs#ifdef AHD_DEBUG
4073109588Sgibbs				if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
4074109588Sgibbs					ahd_print_devinfo(ahd, &devinfo);
4075109588Sgibbs					printf("Asserting ATN for response\n");
4076109588Sgibbs				}
4077109588Sgibbs#endif
407897883Sgibbs				ahd_assert_atn(ahd);
4079109588Sgibbs			}
408097883Sgibbs		} else
408197883Sgibbs			ahd->msgin_index++;
408297883Sgibbs
408397883Sgibbs		if (message_done == MSGLOOP_TERMINATED) {
408497883Sgibbs			end_session = TRUE;
408597883Sgibbs		} else {
408697883Sgibbs			/* Ack the byte */
408797883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRREQINIT);
408897883Sgibbs			ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_READ);
408997883Sgibbs		}
409097883Sgibbs		break;
409197883Sgibbs	}
409297883Sgibbs	case MSG_TYPE_TARGET_MSGIN:
409397883Sgibbs	{
409497883Sgibbs		int msgdone;
409597883Sgibbs		int msgout_request;
409697883Sgibbs
409797883Sgibbs		/*
409897883Sgibbs		 * By default, the message loop will continue.
409997883Sgibbs		 */
410097883Sgibbs		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
410197883Sgibbs
410297883Sgibbs		if (ahd->msgout_len == 0)
410397883Sgibbs			panic("Target MSGIN with no active message");
410497883Sgibbs
410597883Sgibbs		/*
410697883Sgibbs		 * If we interrupted a mesgout session, the initiator
410797883Sgibbs		 * will not know this until our first REQ.  So, we
410897883Sgibbs		 * only honor mesgout requests after we've sent our
410997883Sgibbs		 * first byte.
411097883Sgibbs		 */
411197883Sgibbs		if ((ahd_inb(ahd, SCSISIGI) & ATNI) != 0
411297883Sgibbs		 && ahd->msgout_index > 0)
411397883Sgibbs			msgout_request = TRUE;
411497883Sgibbs		else
411597883Sgibbs			msgout_request = FALSE;
411697883Sgibbs
411797883Sgibbs		if (msgout_request) {
411897883Sgibbs
411997883Sgibbs			/*
412097883Sgibbs			 * Change gears and see if
412197883Sgibbs			 * this messages is of interest to
412297883Sgibbs			 * us or should be passed back to
412397883Sgibbs			 * the sequencer.
412497883Sgibbs			 */
412597883Sgibbs			ahd->msg_type = MSG_TYPE_TARGET_MSGOUT;
412697883Sgibbs			ahd_outb(ahd, SCSISIGO, P_MESGOUT | BSYO);
412797883Sgibbs			ahd->msgin_index = 0;
412897883Sgibbs			/* Dummy read to REQ for first byte */
412997883Sgibbs			ahd_inb(ahd, SCSIDAT);
413097883Sgibbs			ahd_outb(ahd, SXFRCTL0,
413197883Sgibbs				 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
413297883Sgibbs			break;
413397883Sgibbs		}
413497883Sgibbs
413597883Sgibbs		msgdone = ahd->msgout_index == ahd->msgout_len;
413697883Sgibbs		if (msgdone) {
413797883Sgibbs			ahd_outb(ahd, SXFRCTL0,
413897883Sgibbs				 ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
413997883Sgibbs			end_session = TRUE;
414097883Sgibbs			break;
414197883Sgibbs		}
414297883Sgibbs
414397883Sgibbs		/*
414497883Sgibbs		 * Present the next byte on the bus.
414597883Sgibbs		 */
414697883Sgibbs		ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) | SPIOEN);
414797883Sgibbs		ahd_outb(ahd, SCSIDAT, ahd->msgout_buf[ahd->msgout_index++]);
414897883Sgibbs		break;
414997883Sgibbs	}
415097883Sgibbs	case MSG_TYPE_TARGET_MSGOUT:
415197883Sgibbs	{
415297883Sgibbs		int lastbyte;
415397883Sgibbs		int msgdone;
415497883Sgibbs
415597883Sgibbs		/*
415697883Sgibbs		 * By default, the message loop will continue.
415797883Sgibbs		 */
415897883Sgibbs		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
415997883Sgibbs
416097883Sgibbs		/*
416197883Sgibbs		 * The initiator signals that this is
416297883Sgibbs		 * the last byte by dropping ATN.
416397883Sgibbs		 */
416497883Sgibbs		lastbyte = (ahd_inb(ahd, SCSISIGI) & ATNI) == 0;
416597883Sgibbs
416697883Sgibbs		/*
416797883Sgibbs		 * Read the latched byte, but turn off SPIOEN first
416897883Sgibbs		 * so that we don't inadvertently cause a REQ for the
416997883Sgibbs		 * next byte.
417097883Sgibbs		 */
417197883Sgibbs		ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
417297883Sgibbs		ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIDAT);
417397883Sgibbs		msgdone = ahd_parse_msg(ahd, &devinfo);
417497883Sgibbs		if (msgdone == MSGLOOP_TERMINATED) {
417597883Sgibbs			/*
417697883Sgibbs			 * The message is *really* done in that it caused
417797883Sgibbs			 * us to go to bus free.  The sequencer has already
417897883Sgibbs			 * been reset at this point, so pull the ejection
417997883Sgibbs			 * handle.
418097883Sgibbs			 */
418197883Sgibbs			return;
418297883Sgibbs		}
418397883Sgibbs
418497883Sgibbs		ahd->msgin_index++;
418597883Sgibbs
418697883Sgibbs		/*
418797883Sgibbs		 * XXX Read spec about initiator dropping ATN too soon
418897883Sgibbs		 *     and use msgdone to detect it.
418997883Sgibbs		 */
419097883Sgibbs		if (msgdone == MSGLOOP_MSGCOMPLETE) {
419197883Sgibbs			ahd->msgin_index = 0;
419297883Sgibbs
419397883Sgibbs			/*
419497883Sgibbs			 * If this message illicited a response, transition
419597883Sgibbs			 * to the Message in phase and send it.
419697883Sgibbs			 */
419797883Sgibbs			if (ahd->msgout_len != 0) {
419897883Sgibbs				ahd_outb(ahd, SCSISIGO, P_MESGIN | BSYO);
419997883Sgibbs				ahd_outb(ahd, SXFRCTL0,
420097883Sgibbs					 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
420197883Sgibbs				ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
420297883Sgibbs				ahd->msgin_index = 0;
420397883Sgibbs				break;
420497883Sgibbs			}
420597883Sgibbs		}
420697883Sgibbs
420797883Sgibbs		if (lastbyte)
420897883Sgibbs			end_session = TRUE;
420997883Sgibbs		else {
421097883Sgibbs			/* Ask for the next byte. */
421197883Sgibbs			ahd_outb(ahd, SXFRCTL0,
421297883Sgibbs				 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
421397883Sgibbs		}
421497883Sgibbs
421597883Sgibbs		break;
421697883Sgibbs	}
421797883Sgibbs	default:
421897883Sgibbs		panic("Unknown REQINIT message type");
421997883Sgibbs	}
422097883Sgibbs
422197883Sgibbs	if (end_session) {
422297883Sgibbs		if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) {
422397883Sgibbs			printf("%s: Returning to Idle Loop\n",
422497883Sgibbs			       ahd_name(ahd));
4225116935Sgibbs			ahd_clear_msg_state(ahd);
4226116935Sgibbs
4227116935Sgibbs			/*
4228116935Sgibbs			 * Perform the equivalent of a clear_target_state.
4229116935Sgibbs			 */
423097883Sgibbs			ahd_outb(ahd, LASTPHASE, P_BUSFREE);
4231116935Sgibbs			ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT);
423297883Sgibbs			ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
423397883Sgibbs		} else {
423497883Sgibbs			ahd_clear_msg_state(ahd);
423597883Sgibbs			ahd_outb(ahd, RETURN_1, EXIT_MSG_LOOP);
423697883Sgibbs		}
423797883Sgibbs	}
423897883Sgibbs}
423997883Sgibbs
424097883Sgibbs/*
424197883Sgibbs * See if we sent a particular extended message to the target.
424297883Sgibbs * If "full" is true, return true only if the target saw the full
424397883Sgibbs * message.  If "full" is false, return true if the target saw at
424497883Sgibbs * least the first byte of the message.
424597883Sgibbs */
424697883Sgibbsstatic int
424797883Sgibbsahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, u_int msgval, int full)
424897883Sgibbs{
424997883Sgibbs	int found;
425097883Sgibbs	u_int index;
425197883Sgibbs
425297883Sgibbs	found = FALSE;
425397883Sgibbs	index = 0;
425497883Sgibbs
425597883Sgibbs	while (index < ahd->msgout_len) {
425697883Sgibbs		if (ahd->msgout_buf[index] == MSG_EXTENDED) {
425797883Sgibbs			u_int end_index;
425897883Sgibbs
425997883Sgibbs			end_index = index + 1 + ahd->msgout_buf[index + 1];
426097883Sgibbs			if (ahd->msgout_buf[index+2] == msgval
426197883Sgibbs			 && type == AHDMSG_EXT) {
426297883Sgibbs
426397883Sgibbs				if (full) {
426497883Sgibbs					if (ahd->msgout_index > end_index)
426597883Sgibbs						found = TRUE;
426697883Sgibbs				} else if (ahd->msgout_index > index)
426797883Sgibbs					found = TRUE;
426897883Sgibbs			}
426997883Sgibbs			index = end_index;
427097883Sgibbs		} else if (ahd->msgout_buf[index] >= MSG_SIMPLE_TASK
427197883Sgibbs			&& ahd->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
427297883Sgibbs
427397883Sgibbs			/* Skip tag type and tag id or residue param*/
427497883Sgibbs			index += 2;
427597883Sgibbs		} else {
427697883Sgibbs			/* Single byte message */
427797883Sgibbs			if (type == AHDMSG_1B
4278109588Sgibbs			 && ahd->msgout_index > index
4279109588Sgibbs			 && (ahd->msgout_buf[index] == msgval
4280109588Sgibbs			  || ((ahd->msgout_buf[index] & MSG_IDENTIFYFLAG) != 0
4281109588Sgibbs			   && msgval == MSG_IDENTIFYFLAG)))
428297883Sgibbs				found = TRUE;
428397883Sgibbs			index++;
428497883Sgibbs		}
428597883Sgibbs
428697883Sgibbs		if (found)
428797883Sgibbs			break;
428897883Sgibbs	}
428997883Sgibbs	return (found);
429097883Sgibbs}
429197883Sgibbs
429297883Sgibbs/*
429397883Sgibbs * Wait for a complete incoming message, parse it, and respond accordingly.
429497883Sgibbs */
429597883Sgibbsstatic int
429697883Sgibbsahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
429797883Sgibbs{
429897883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
429997883Sgibbs	struct	ahd_tmode_tstate *tstate;
430097883Sgibbs	int	reject;
430197883Sgibbs	int	done;
430297883Sgibbs	int	response;
430397883Sgibbs
430497883Sgibbs	done = MSGLOOP_IN_PROG;
430597883Sgibbs	response = FALSE;
430697883Sgibbs	reject = FALSE;
430797883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
430897883Sgibbs				    devinfo->target, &tstate);
430997883Sgibbs
431097883Sgibbs	/*
4311114623Sgibbs	 * Parse as much of the message as is available,
431297883Sgibbs	 * rejecting it if we don't support it.  When
4313114623Sgibbs	 * the entire message is available and has been
431497883Sgibbs	 * handled, return MSGLOOP_MSGCOMPLETE, indicating
431597883Sgibbs	 * that we have parsed an entire message.
431697883Sgibbs	 *
431797883Sgibbs	 * In the case of extended messages, we accept the length
431897883Sgibbs	 * byte outright and perform more checking once we know the
431997883Sgibbs	 * extended message type.
432097883Sgibbs	 */
432197883Sgibbs	switch (ahd->msgin_buf[0]) {
432297883Sgibbs	case MSG_DISCONNECT:
432397883Sgibbs	case MSG_SAVEDATAPOINTER:
432497883Sgibbs	case MSG_CMDCOMPLETE:
432597883Sgibbs	case MSG_RESTOREPOINTERS:
432697883Sgibbs	case MSG_IGN_WIDE_RESIDUE:
432797883Sgibbs		/*
432897883Sgibbs		 * End our message loop as these are messages
432997883Sgibbs		 * the sequencer handles on its own.
433097883Sgibbs		 */
433197883Sgibbs		done = MSGLOOP_TERMINATED;
433297883Sgibbs		break;
433397883Sgibbs	case MSG_MESSAGE_REJECT:
433497883Sgibbs		response = ahd_handle_msg_reject(ahd, devinfo);
433597883Sgibbs		/* FALLTHROUGH */
433697883Sgibbs	case MSG_NOOP:
433797883Sgibbs		done = MSGLOOP_MSGCOMPLETE;
433897883Sgibbs		break;
433997883Sgibbs	case MSG_EXTENDED:
434097883Sgibbs	{
434197883Sgibbs		/* Wait for enough of the message to begin validation */
434297883Sgibbs		if (ahd->msgin_index < 2)
434397883Sgibbs			break;
434497883Sgibbs		switch (ahd->msgin_buf[2]) {
434597883Sgibbs		case MSG_EXT_SDTR:
434697883Sgibbs		{
434797883Sgibbs			u_int	 period;
434897883Sgibbs			u_int	 ppr_options;
434997883Sgibbs			u_int	 offset;
435097883Sgibbs			u_int	 saved_offset;
435197883Sgibbs
435297883Sgibbs			if (ahd->msgin_buf[1] != MSG_EXT_SDTR_LEN) {
435397883Sgibbs				reject = TRUE;
435497883Sgibbs				break;
435597883Sgibbs			}
435697883Sgibbs
435797883Sgibbs			/*
435897883Sgibbs			 * Wait until we have both args before validating
435997883Sgibbs			 * and acting on this message.
436097883Sgibbs			 *
436197883Sgibbs			 * Add one to MSG_EXT_SDTR_LEN to account for
436297883Sgibbs			 * the extended message preamble.
436397883Sgibbs			 */
436497883Sgibbs			if (ahd->msgin_index < (MSG_EXT_SDTR_LEN + 1))
436597883Sgibbs				break;
436697883Sgibbs
436797883Sgibbs			period = ahd->msgin_buf[3];
436897883Sgibbs			ppr_options = 0;
436997883Sgibbs			saved_offset = offset = ahd->msgin_buf[4];
437097883Sgibbs			ahd_devlimited_syncrate(ahd, tinfo, &period,
437197883Sgibbs						&ppr_options, devinfo->role);
437297883Sgibbs			ahd_validate_offset(ahd, tinfo, period, &offset,
437397883Sgibbs					    tinfo->curr.width, devinfo->role);
437497883Sgibbs			if (bootverbose) {
437597883Sgibbs				printf("(%s:%c:%d:%d): Received "
437697883Sgibbs				       "SDTR period %x, offset %x\n\t"
437797883Sgibbs				       "Filtered to period %x, offset %x\n",
437897883Sgibbs				       ahd_name(ahd), devinfo->channel,
437997883Sgibbs				       devinfo->target, devinfo->lun,
438097883Sgibbs				       ahd->msgin_buf[3], saved_offset,
438197883Sgibbs				       period, offset);
438297883Sgibbs			}
438397883Sgibbs			ahd_set_syncrate(ahd, devinfo, period,
438497883Sgibbs					 offset, ppr_options,
438597883Sgibbs					 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
438697883Sgibbs					 /*paused*/TRUE);
438797883Sgibbs
438897883Sgibbs			/*
438997883Sgibbs			 * See if we initiated Sync Negotiation
439097883Sgibbs			 * and didn't have to fall down to async
439197883Sgibbs			 * transfers.
439297883Sgibbs			 */
439397883Sgibbs			if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, TRUE)) {
439497883Sgibbs				/* We started it */
439597883Sgibbs				if (saved_offset != offset) {
439697883Sgibbs					/* Went too low - force async */
439797883Sgibbs					reject = TRUE;
439897883Sgibbs				}
439997883Sgibbs			} else {
440097883Sgibbs				/*
440197883Sgibbs				 * Send our own SDTR in reply
440297883Sgibbs				 */
440397883Sgibbs				if (bootverbose
440497883Sgibbs				 && devinfo->role == ROLE_INITIATOR) {
440597883Sgibbs					printf("(%s:%c:%d:%d): Target "
440697883Sgibbs					       "Initiated SDTR\n",
440797883Sgibbs					       ahd_name(ahd), devinfo->channel,
440897883Sgibbs					       devinfo->target, devinfo->lun);
440997883Sgibbs				}
441097883Sgibbs				ahd->msgout_index = 0;
441197883Sgibbs				ahd->msgout_len = 0;
441297883Sgibbs				ahd_construct_sdtr(ahd, devinfo,
441397883Sgibbs						   period, offset);
441497883Sgibbs				ahd->msgout_index = 0;
441597883Sgibbs				response = TRUE;
441697883Sgibbs			}
441797883Sgibbs			done = MSGLOOP_MSGCOMPLETE;
441897883Sgibbs			break;
441997883Sgibbs		}
442097883Sgibbs		case MSG_EXT_WDTR:
442197883Sgibbs		{
442297883Sgibbs			u_int bus_width;
442397883Sgibbs			u_int saved_width;
442497883Sgibbs			u_int sending_reply;
442597883Sgibbs
442697883Sgibbs			sending_reply = FALSE;
442797883Sgibbs			if (ahd->msgin_buf[1] != MSG_EXT_WDTR_LEN) {
442897883Sgibbs				reject = TRUE;
442997883Sgibbs				break;
443097883Sgibbs			}
443197883Sgibbs
443297883Sgibbs			/*
443397883Sgibbs			 * Wait until we have our arg before validating
443497883Sgibbs			 * and acting on this message.
443597883Sgibbs			 *
443697883Sgibbs			 * Add one to MSG_EXT_WDTR_LEN to account for
443797883Sgibbs			 * the extended message preamble.
443897883Sgibbs			 */
443997883Sgibbs			if (ahd->msgin_index < (MSG_EXT_WDTR_LEN + 1))
444097883Sgibbs				break;
444197883Sgibbs
444297883Sgibbs			bus_width = ahd->msgin_buf[3];
444397883Sgibbs			saved_width = bus_width;
444497883Sgibbs			ahd_validate_width(ahd, tinfo, &bus_width,
444597883Sgibbs					   devinfo->role);
444697883Sgibbs			if (bootverbose) {
444797883Sgibbs				printf("(%s:%c:%d:%d): Received WDTR "
444897883Sgibbs				       "%x filtered to %x\n",
444997883Sgibbs				       ahd_name(ahd), devinfo->channel,
445097883Sgibbs				       devinfo->target, devinfo->lun,
445197883Sgibbs				       saved_width, bus_width);
445297883Sgibbs			}
445397883Sgibbs
445497883Sgibbs			if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, TRUE)) {
445597883Sgibbs				/*
445697883Sgibbs				 * Don't send a WDTR back to the
445797883Sgibbs				 * target, since we asked first.
445897883Sgibbs				 * If the width went higher than our
445997883Sgibbs				 * request, reject it.
446097883Sgibbs				 */
446197883Sgibbs				if (saved_width > bus_width) {
446297883Sgibbs					reject = TRUE;
446397883Sgibbs					printf("(%s:%c:%d:%d): requested %dBit "
446497883Sgibbs					       "transfers.  Rejecting...\n",
446597883Sgibbs					       ahd_name(ahd), devinfo->channel,
446697883Sgibbs					       devinfo->target, devinfo->lun,
446797883Sgibbs					       8 * (0x01 << bus_width));
446897883Sgibbs					bus_width = 0;
446997883Sgibbs				}
447097883Sgibbs			} else {
447197883Sgibbs				/*
447297883Sgibbs				 * Send our own WDTR in reply
447397883Sgibbs				 */
447497883Sgibbs				if (bootverbose
447597883Sgibbs				 && devinfo->role == ROLE_INITIATOR) {
447697883Sgibbs					printf("(%s:%c:%d:%d): Target "
447797883Sgibbs					       "Initiated WDTR\n",
447897883Sgibbs					       ahd_name(ahd), devinfo->channel,
447997883Sgibbs					       devinfo->target, devinfo->lun);
448097883Sgibbs				}
448197883Sgibbs				ahd->msgout_index = 0;
448297883Sgibbs				ahd->msgout_len = 0;
448397883Sgibbs				ahd_construct_wdtr(ahd, devinfo, bus_width);
448497883Sgibbs				ahd->msgout_index = 0;
448597883Sgibbs				response = TRUE;
448697883Sgibbs				sending_reply = TRUE;
448797883Sgibbs			}
4488115918Sgibbs			/*
4489115918Sgibbs			 * After a wide message, we are async, but
4490115918Sgibbs			 * some devices don't seem to honor this portion
4491115918Sgibbs			 * of the spec.  Force a renegotiation of the
4492115918Sgibbs			 * sync component of our transfer agreement even
4493115918Sgibbs			 * if our goal is async.  By updating our width
4494115918Sgibbs			 * after forcing the negotiation, we avoid
4495115918Sgibbs			 * renegotiating for width.
4496115918Sgibbs			 */
4497115918Sgibbs			ahd_update_neg_request(ahd, devinfo, tstate,
4498115918Sgibbs					       tinfo, AHD_NEG_ALWAYS);
449997883Sgibbs			ahd_set_width(ahd, devinfo, bus_width,
450097883Sgibbs				      AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
450197883Sgibbs				      /*paused*/TRUE);
450297883Sgibbs			if (sending_reply == FALSE && reject == FALSE) {
450397883Sgibbs
4504115918Sgibbs				/*
4505115918Sgibbs				 * We will always have an SDTR to send.
4506115918Sgibbs				 */
4507115918Sgibbs				ahd->msgout_index = 0;
4508115918Sgibbs				ahd->msgout_len = 0;
4509115918Sgibbs				ahd_build_transfer_msg(ahd, devinfo);
4510115918Sgibbs				ahd->msgout_index = 0;
4511115918Sgibbs				response = TRUE;
451297883Sgibbs			}
451397883Sgibbs			done = MSGLOOP_MSGCOMPLETE;
451497883Sgibbs			break;
451597883Sgibbs		}
451697883Sgibbs		case MSG_EXT_PPR:
451797883Sgibbs		{
451897883Sgibbs			u_int	period;
451997883Sgibbs			u_int	offset;
452097883Sgibbs			u_int	bus_width;
452197883Sgibbs			u_int	ppr_options;
452297883Sgibbs			u_int	saved_width;
452397883Sgibbs			u_int	saved_offset;
452497883Sgibbs			u_int	saved_ppr_options;
452597883Sgibbs
452697883Sgibbs			if (ahd->msgin_buf[1] != MSG_EXT_PPR_LEN) {
452797883Sgibbs				reject = TRUE;
452897883Sgibbs				break;
452997883Sgibbs			}
453097883Sgibbs
453197883Sgibbs			/*
453297883Sgibbs			 * Wait until we have all args before validating
453397883Sgibbs			 * and acting on this message.
453497883Sgibbs			 *
453597883Sgibbs			 * Add one to MSG_EXT_PPR_LEN to account for
453697883Sgibbs			 * the extended message preamble.
453797883Sgibbs			 */
453897883Sgibbs			if (ahd->msgin_index < (MSG_EXT_PPR_LEN + 1))
453997883Sgibbs				break;
454097883Sgibbs
454197883Sgibbs			period = ahd->msgin_buf[3];
454297883Sgibbs			offset = ahd->msgin_buf[5];
454397883Sgibbs			bus_width = ahd->msgin_buf[6];
454497883Sgibbs			saved_width = bus_width;
454597883Sgibbs			ppr_options = ahd->msgin_buf[7];
454697883Sgibbs			/*
454797883Sgibbs			 * According to the spec, a DT only
454897883Sgibbs			 * period factor with no DT option
454997883Sgibbs			 * set implies async.
455097883Sgibbs			 */
455197883Sgibbs			if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0
455297883Sgibbs			 && period <= 9)
455397883Sgibbs				offset = 0;
455497883Sgibbs			saved_ppr_options = ppr_options;
455597883Sgibbs			saved_offset = offset;
455697883Sgibbs
455797883Sgibbs			/*
455897883Sgibbs			 * Transfer options are only available if we
455997883Sgibbs			 * are negotiating wide.
456097883Sgibbs			 */
456197883Sgibbs			if (bus_width == 0)
456297883Sgibbs				ppr_options &= MSG_EXT_PPR_QAS_REQ;
456397883Sgibbs
456497883Sgibbs			ahd_validate_width(ahd, tinfo, &bus_width,
456597883Sgibbs					   devinfo->role);
456697883Sgibbs			ahd_devlimited_syncrate(ahd, tinfo, &period,
456797883Sgibbs						&ppr_options, devinfo->role);
456897883Sgibbs			ahd_validate_offset(ahd, tinfo, period, &offset,
456997883Sgibbs					    bus_width, devinfo->role);
457097883Sgibbs
457197883Sgibbs			if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, TRUE)) {
457297883Sgibbs				/*
457397883Sgibbs				 * If we are unable to do any of the
457497883Sgibbs				 * requested options (we went too low),
457597883Sgibbs				 * then we'll have to reject the message.
457697883Sgibbs				 */
457797883Sgibbs				if (saved_width > bus_width
457897883Sgibbs				 || saved_offset != offset
457997883Sgibbs				 || saved_ppr_options != ppr_options) {
458097883Sgibbs					reject = TRUE;
458197883Sgibbs					period = 0;
458297883Sgibbs					offset = 0;
458397883Sgibbs					bus_width = 0;
458497883Sgibbs					ppr_options = 0;
458597883Sgibbs				}
458697883Sgibbs			} else {
458797883Sgibbs				if (devinfo->role != ROLE_TARGET)
458897883Sgibbs					printf("(%s:%c:%d:%d): Target "
458997883Sgibbs					       "Initiated PPR\n",
459097883Sgibbs					       ahd_name(ahd), devinfo->channel,
459197883Sgibbs					       devinfo->target, devinfo->lun);
459297883Sgibbs				else
459397883Sgibbs					printf("(%s:%c:%d:%d): Initiator "
459497883Sgibbs					       "Initiated PPR\n",
459597883Sgibbs					       ahd_name(ahd), devinfo->channel,
459697883Sgibbs					       devinfo->target, devinfo->lun);
459797883Sgibbs				ahd->msgout_index = 0;
459897883Sgibbs				ahd->msgout_len = 0;
459997883Sgibbs				ahd_construct_ppr(ahd, devinfo, period, offset,
460097883Sgibbs						  bus_width, ppr_options);
460197883Sgibbs				ahd->msgout_index = 0;
460297883Sgibbs				response = TRUE;
460397883Sgibbs			}
460497883Sgibbs			if (bootverbose) {
460597883Sgibbs				printf("(%s:%c:%d:%d): Received PPR width %x, "
460697883Sgibbs				       "period %x, offset %x,options %x\n"
460797883Sgibbs				       "\tFiltered to width %x, period %x, "
460897883Sgibbs				       "offset %x, options %x\n",
460997883Sgibbs				       ahd_name(ahd), devinfo->channel,
461097883Sgibbs				       devinfo->target, devinfo->lun,
461197883Sgibbs				       saved_width, ahd->msgin_buf[3],
461297883Sgibbs				       saved_offset, saved_ppr_options,
461397883Sgibbs				       bus_width, period, offset, ppr_options);
461497883Sgibbs			}
461597883Sgibbs			ahd_set_width(ahd, devinfo, bus_width,
461697883Sgibbs				      AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
461797883Sgibbs				      /*paused*/TRUE);
461897883Sgibbs			ahd_set_syncrate(ahd, devinfo, period,
461997883Sgibbs					 offset, ppr_options,
462097883Sgibbs					 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
462197883Sgibbs					 /*paused*/TRUE);
462297883Sgibbs
462397883Sgibbs			done = MSGLOOP_MSGCOMPLETE;
462497883Sgibbs			break;
462597883Sgibbs		}
462697883Sgibbs		default:
462797883Sgibbs			/* Unknown extended message.  Reject it. */
462897883Sgibbs			reject = TRUE;
462997883Sgibbs			break;
463097883Sgibbs		}
463197883Sgibbs		break;
463297883Sgibbs	}
463397883Sgibbs#ifdef AHD_TARGET_MODE
463497883Sgibbs	case MSG_BUS_DEV_RESET:
4635109588Sgibbs		ahd_handle_devreset(ahd, devinfo, CAM_LUN_WILDCARD,
463697883Sgibbs				    CAM_BDR_SENT,
463797883Sgibbs				    "Bus Device Reset Received",
463897883Sgibbs				    /*verbose_level*/0);
463997883Sgibbs		ahd_restart(ahd);
464097883Sgibbs		done = MSGLOOP_TERMINATED;
464197883Sgibbs		break;
464297883Sgibbs	case MSG_ABORT_TAG:
464397883Sgibbs	case MSG_ABORT:
464497883Sgibbs	case MSG_CLEAR_QUEUE:
464597883Sgibbs	{
464697883Sgibbs		int tag;
464797883Sgibbs
464897883Sgibbs		/* Target mode messages */
464997883Sgibbs		if (devinfo->role != ROLE_TARGET) {
465097883Sgibbs			reject = TRUE;
465197883Sgibbs			break;
465297883Sgibbs		}
465397883Sgibbs		tag = SCB_LIST_NULL;
465497883Sgibbs		if (ahd->msgin_buf[0] == MSG_ABORT_TAG)
465597883Sgibbs			tag = ahd_inb(ahd, INITIATOR_TAG);
465697883Sgibbs		ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
465797883Sgibbs			       devinfo->lun, tag, ROLE_TARGET,
465897883Sgibbs			       CAM_REQ_ABORTED);
465997883Sgibbs
466097883Sgibbs		tstate = ahd->enabled_targets[devinfo->our_scsiid];
466197883Sgibbs		if (tstate != NULL) {
466297883Sgibbs			struct ahd_tmode_lstate* lstate;
466397883Sgibbs
466497883Sgibbs			lstate = tstate->enabled_luns[devinfo->lun];
466597883Sgibbs			if (lstate != NULL) {
466697883Sgibbs				ahd_queue_lstate_event(ahd, lstate,
466797883Sgibbs						       devinfo->our_scsiid,
466897883Sgibbs						       ahd->msgin_buf[0],
466997883Sgibbs						       /*arg*/tag);
467097883Sgibbs				ahd_send_lstate_events(ahd, lstate);
467197883Sgibbs			}
467297883Sgibbs		}
467397883Sgibbs		ahd_restart(ahd);
467497883Sgibbs		done = MSGLOOP_TERMINATED;
467597883Sgibbs		break;
467697883Sgibbs	}
467797883Sgibbs#endif
467897883Sgibbs	case MSG_QAS_REQUEST:
4679107441Sscottl#ifdef AHD_DEBUG
4680107441Sscottl		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
4681107441Sscottl			printf("%s: QAS request.  SCSISIGI == 0x%x\n",
4682107441Sscottl			       ahd_name(ahd), ahd_inb(ahd, SCSISIGI));
4683107441Sscottl#endif
4684107441Sscottl		ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE;
468597883Sgibbs		/* FALLTHROUGH */
468697883Sgibbs	case MSG_TERM_IO_PROC:
468797883Sgibbs	default:
468897883Sgibbs		reject = TRUE;
468997883Sgibbs		break;
469097883Sgibbs	}
469197883Sgibbs
469297883Sgibbs	if (reject) {
469397883Sgibbs		/*
469497883Sgibbs		 * Setup to reject the message.
469597883Sgibbs		 */
469697883Sgibbs		ahd->msgout_index = 0;
469797883Sgibbs		ahd->msgout_len = 1;
469897883Sgibbs		ahd->msgout_buf[0] = MSG_MESSAGE_REJECT;
469997883Sgibbs		done = MSGLOOP_MSGCOMPLETE;
470097883Sgibbs		response = TRUE;
470197883Sgibbs	}
470297883Sgibbs
470397883Sgibbs	if (done != MSGLOOP_IN_PROG && !response)
470497883Sgibbs		/* Clear the outgoing message buffer */
470597883Sgibbs		ahd->msgout_len = 0;
470697883Sgibbs
470797883Sgibbs	return (done);
470897883Sgibbs}
470997883Sgibbs
471097883Sgibbs/*
471197883Sgibbs * Process a message reject message.
471297883Sgibbs */
471397883Sgibbsstatic int
471497883Sgibbsahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
471597883Sgibbs{
471697883Sgibbs	/*
471797883Sgibbs	 * What we care about here is if we had an
471897883Sgibbs	 * outstanding SDTR or WDTR message for this
471997883Sgibbs	 * target.  If we did, this is a signal that
472097883Sgibbs	 * the target is refusing negotiation.
472197883Sgibbs	 */
472297883Sgibbs	struct scb *scb;
472397883Sgibbs	struct ahd_initiator_tinfo *tinfo;
472497883Sgibbs	struct ahd_tmode_tstate *tstate;
472597883Sgibbs	u_int scb_index;
472697883Sgibbs	u_int last_msg;
472797883Sgibbs	int   response = 0;
472897883Sgibbs
472997883Sgibbs	scb_index = ahd_get_scbptr(ahd);
473097883Sgibbs	scb = ahd_lookup_scb(ahd, scb_index);
473197883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
473297883Sgibbs				    devinfo->our_scsiid,
473397883Sgibbs				    devinfo->target, &tstate);
473497883Sgibbs	/* Might be necessary */
473597883Sgibbs	last_msg = ahd_inb(ahd, LAST_MSG);
473697883Sgibbs
473797883Sgibbs	if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) {
4738107441Sscottl		if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, /*full*/TRUE)
4739107441Sscottl		 && tinfo->goal.period <= AHD_SYNCRATE_PACED) {
4740107441Sscottl			/*
4741107441Sscottl			 * Target may not like our SPI-4 PPR Options.
4742107441Sscottl			 * Attempt to negotiate 80MHz which will turn
4743107441Sscottl			 * off these options.
4744107441Sscottl			 */
4745107441Sscottl			if (bootverbose) {
4746107441Sscottl				printf("(%s:%c:%d:%d): PPR Rejected. "
4747107441Sscottl				       "Trying simple U160 PPR\n",
4748107441Sscottl				       ahd_name(ahd), devinfo->channel,
4749107441Sscottl				       devinfo->target, devinfo->lun);
4750107441Sscottl			}
4751107441Sscottl			tinfo->goal.period = AHD_SYNCRATE_DT;
4752107441Sscottl			tinfo->goal.ppr_options &= MSG_EXT_PPR_IU_REQ
4753107441Sscottl						|  MSG_EXT_PPR_QAS_REQ
4754107441Sscottl						|  MSG_EXT_PPR_DT_REQ;
4755107441Sscottl		} else {
4756107441Sscottl			/*
4757107441Sscottl			 * Target does not support the PPR message.
4758107441Sscottl			 * Attempt to negotiate SPI-2 style.
4759107441Sscottl			 */
4760107441Sscottl			if (bootverbose) {
4761107441Sscottl				printf("(%s:%c:%d:%d): PPR Rejected. "
4762107441Sscottl				       "Trying WDTR/SDTR\n",
4763107441Sscottl				       ahd_name(ahd), devinfo->channel,
4764107441Sscottl				       devinfo->target, devinfo->lun);
4765107441Sscottl			}
4766107441Sscottl			tinfo->goal.ppr_options = 0;
4767107441Sscottl			tinfo->curr.transport_version = 2;
4768107441Sscottl			tinfo->goal.transport_version = 2;
476997883Sgibbs		}
477097883Sgibbs		ahd->msgout_index = 0;
477197883Sgibbs		ahd->msgout_len = 0;
477297883Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
477397883Sgibbs		ahd->msgout_index = 0;
477497883Sgibbs		response = 1;
477597883Sgibbs	} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) {
477697883Sgibbs
477797883Sgibbs		/* note 8bit xfers */
477897883Sgibbs		printf("(%s:%c:%d:%d): refuses WIDE negotiation.  Using "
477997883Sgibbs		       "8bit transfers\n", ahd_name(ahd),
478097883Sgibbs		       devinfo->channel, devinfo->target, devinfo->lun);
478197883Sgibbs		ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
478297883Sgibbs			      AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
478397883Sgibbs			      /*paused*/TRUE);
478497883Sgibbs		/*
478597883Sgibbs		 * No need to clear the sync rate.  If the target
478697883Sgibbs		 * did not accept the command, our syncrate is
478797883Sgibbs		 * unaffected.  If the target started the negotiation,
478897883Sgibbs		 * but rejected our response, we already cleared the
478997883Sgibbs		 * sync rate before sending our WDTR.
479097883Sgibbs		 */
4791109603Sgibbs		if (tinfo->goal.offset != tinfo->curr.offset) {
479297883Sgibbs
479397883Sgibbs			/* Start the sync negotiation */
479497883Sgibbs			ahd->msgout_index = 0;
479597883Sgibbs			ahd->msgout_len = 0;
479697883Sgibbs			ahd_build_transfer_msg(ahd, devinfo);
479797883Sgibbs			ahd->msgout_index = 0;
479897883Sgibbs			response = 1;
479997883Sgibbs		}
480097883Sgibbs	} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) {
480197883Sgibbs		/* note asynch xfers and clear flag */
480297883Sgibbs		ahd_set_syncrate(ahd, devinfo, /*period*/0,
480397883Sgibbs				 /*offset*/0, /*ppr_options*/0,
480497883Sgibbs				 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
480597883Sgibbs				 /*paused*/TRUE);
480697883Sgibbs		printf("(%s:%c:%d:%d): refuses synchronous negotiation. "
480797883Sgibbs		       "Using asynchronous transfers\n",
480897883Sgibbs		       ahd_name(ahd), devinfo->channel,
480997883Sgibbs		       devinfo->target, devinfo->lun);
481097883Sgibbs	} else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
481197883Sgibbs		int tag_type;
481297883Sgibbs		int mask;
481397883Sgibbs
481497883Sgibbs		tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
481597883Sgibbs
481697883Sgibbs		if (tag_type == MSG_SIMPLE_TASK) {
481797883Sgibbs			printf("(%s:%c:%d:%d): refuses tagged commands.  "
481897883Sgibbs			       "Performing non-tagged I/O\n", ahd_name(ahd),
481997883Sgibbs			       devinfo->channel, devinfo->target, devinfo->lun);
482097883Sgibbs			ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE);
482197883Sgibbs			mask = ~0x23;
482297883Sgibbs		} else {
482397883Sgibbs			printf("(%s:%c:%d:%d): refuses %s tagged commands.  "
482497883Sgibbs			       "Performing simple queue tagged I/O only\n",
482597883Sgibbs			       ahd_name(ahd), devinfo->channel, devinfo->target,
482697883Sgibbs			       devinfo->lun, tag_type == MSG_ORDERED_TASK
482797883Sgibbs			       ? "ordered" : "head of queue");
482897883Sgibbs			ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC);
482997883Sgibbs			mask = ~0x03;
483097883Sgibbs		}
483197883Sgibbs
483297883Sgibbs		/*
483397883Sgibbs		 * Resend the identify for this CCB as the target
483497883Sgibbs		 * may believe that the selection is invalid otherwise.
483597883Sgibbs		 */
483697883Sgibbs		ahd_outb(ahd, SCB_CONTROL,
483797883Sgibbs			 ahd_inb_scbram(ahd, SCB_CONTROL) & mask);
483897883Sgibbs	 	scb->hscb->control &= mask;
4839123579Sgibbs		aic_set_transaction_tag(scb, /*enabled*/FALSE,
484097883Sgibbs					/*type*/MSG_SIMPLE_TASK);
484197883Sgibbs		ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG);
484297883Sgibbs		ahd_assert_atn(ahd);
484397883Sgibbs		ahd_busy_tcl(ahd, BUILD_TCL(scb->hscb->scsiid, devinfo->lun),
484497883Sgibbs			     SCB_GET_TAG(scb));
484597883Sgibbs
484697883Sgibbs		/*
484797883Sgibbs		 * Requeue all tagged commands for this target
484897883Sgibbs		 * currently in our posession so they can be
484997883Sgibbs		 * converted to untagged commands.
485097883Sgibbs		 */
485197883Sgibbs		ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
485297883Sgibbs				   SCB_GET_CHANNEL(ahd, scb),
485397883Sgibbs				   SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL,
485497883Sgibbs				   ROLE_INITIATOR, CAM_REQUEUE_REQ,
485597883Sgibbs				   SEARCH_COMPLETE);
4856109588Sgibbs	} else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_IDENTIFYFLAG, TRUE)) {
4857109588Sgibbs		/*
4858109588Sgibbs		 * Most likely the device believes that we had
4859109588Sgibbs		 * previously negotiated packetized.
4860109588Sgibbs		 */
4861109588Sgibbs		ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
4862109588Sgibbs			       |  MSG_FLAG_IU_REQ_CHANGED;
4863109588Sgibbs
4864109588Sgibbs		ahd_force_renegotiation(ahd, devinfo);
4865109588Sgibbs		ahd->msgout_index = 0;
4866109588Sgibbs		ahd->msgout_len = 0;
4867109588Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
4868109588Sgibbs		ahd->msgout_index = 0;
4869109588Sgibbs		response = 1;
487097883Sgibbs	} else {
487197883Sgibbs		/*
487297883Sgibbs		 * Otherwise, we ignore it.
487397883Sgibbs		 */
487497883Sgibbs		printf("%s:%c:%d: Message reject for %x -- ignored\n",
487597883Sgibbs		       ahd_name(ahd), devinfo->channel, devinfo->target,
487697883Sgibbs		       last_msg);
487797883Sgibbs	}
487897883Sgibbs	return (response);
487997883Sgibbs}
488097883Sgibbs
488197883Sgibbs/*
488297883Sgibbs * Process an ingnore wide residue message.
488397883Sgibbs */
488497883Sgibbsstatic void
488597883Sgibbsahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
488697883Sgibbs{
488797883Sgibbs	u_int scb_index;
488897883Sgibbs	struct scb *scb;
488997883Sgibbs
489097883Sgibbs	scb_index = ahd_get_scbptr(ahd);
489197883Sgibbs	scb = ahd_lookup_scb(ahd, scb_index);
489297883Sgibbs	/*
489397883Sgibbs	 * XXX Actually check data direction in the sequencer?
489497883Sgibbs	 * Perhaps add datadir to some spare bits in the hscb?
489597883Sgibbs	 */
489697883Sgibbs	if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0
4897123579Sgibbs	 || aic_get_transfer_dir(scb) != CAM_DIR_IN) {
489897883Sgibbs		/*
489997883Sgibbs		 * Ignore the message if we haven't
490097883Sgibbs		 * seen an appropriate data phase yet.
490197883Sgibbs		 */
490297883Sgibbs	} else {
490397883Sgibbs		/*
490497883Sgibbs		 * If the residual occurred on the last
490597883Sgibbs		 * transfer and the transfer request was
490697883Sgibbs		 * expected to end on an odd count, do
490797883Sgibbs		 * nothing.  Otherwise, subtract a byte
490897883Sgibbs		 * and update the residual count accordingly.
490997883Sgibbs		 */
491097883Sgibbs		uint32_t sgptr;
491197883Sgibbs
491297883Sgibbs		sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
491397883Sgibbs		if ((sgptr & SG_LIST_NULL) != 0
4914116940Sgibbs		 && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
4915116940Sgibbs		     & SCB_XFERLEN_ODD) != 0) {
491697883Sgibbs			/*
491797883Sgibbs			 * If the residual occurred on the last
491897883Sgibbs			 * transfer and the transfer request was
491997883Sgibbs			 * expected to end on an odd count, do
492097883Sgibbs			 * nothing.
492197883Sgibbs			 */
492297883Sgibbs		} else {
492397883Sgibbs			uint32_t data_cnt;
492497883Sgibbs			uint64_t data_addr;
492597883Sgibbs			uint32_t sglen;
492697883Sgibbs
492797883Sgibbs			/* Pull in the rest of the sgptr */
4928115335Sgibbs			sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
4929115335Sgibbs			data_cnt = ahd_inl_scbram(ahd, SCB_RESIDUAL_DATACNT);
4930115335Sgibbs			if ((sgptr & SG_LIST_NULL) != 0) {
4931115335Sgibbs				/*
4932115335Sgibbs				 * The residual data count is not updated
4933115335Sgibbs				 * for the command run to completion case.
4934115335Sgibbs				 * Explicitly zero the count.
4935115335Sgibbs				 */
4936115335Sgibbs				data_cnt &= ~AHD_SG_LEN_MASK;
4937115335Sgibbs			}
4938115335Sgibbs			data_addr = ahd_inq(ahd, SHADDR);
493997883Sgibbs			data_cnt += 1;
494097883Sgibbs			data_addr -= 1;
4941115335Sgibbs			sgptr &= SG_PTR_MASK;
494297883Sgibbs			if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
494397883Sgibbs				struct ahd_dma64_seg *sg;
494497883Sgibbs
494597883Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
494697883Sgibbs
494797883Sgibbs				/*
494897883Sgibbs				 * The residual sg ptr points to the next S/G
494997883Sgibbs				 * to load so we must go back one.
495097883Sgibbs				 */
495197883Sgibbs				sg--;
4952123579Sgibbs				sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
495397883Sgibbs				if (sg != scb->sg_list
495497883Sgibbs				 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
495597883Sgibbs
495697883Sgibbs					sg--;
4957123579Sgibbs					sglen = aic_le32toh(sg->len);
495897883Sgibbs					/*
495997883Sgibbs					 * Preserve High Address and SG_LIST
496097883Sgibbs					 * bits while setting the count to 1.
496197883Sgibbs					 */
496297883Sgibbs					data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
4963123579Sgibbs					data_addr = aic_le64toh(sg->addr)
496497883Sgibbs						  + (sglen & AHD_SG_LEN_MASK)
496597883Sgibbs						  - 1;
496697883Sgibbs
496797883Sgibbs					/*
496897883Sgibbs					 * Increment sg so it points to the
496997883Sgibbs					 * "next" sg.
497097883Sgibbs					 */
497197883Sgibbs					sg++;
497297883Sgibbs					sgptr = ahd_sg_virt_to_bus(ahd, scb,
497397883Sgibbs								   sg);
497497883Sgibbs				}
497597883Sgibbs			} else {
497697883Sgibbs				struct ahd_dma_seg *sg;
497797883Sgibbs
497897883Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
497997883Sgibbs
498097883Sgibbs				/*
498197883Sgibbs				 * The residual sg ptr points to the next S/G
498297883Sgibbs				 * to load so we must go back one.
498397883Sgibbs				 */
498497883Sgibbs				sg--;
4985123579Sgibbs				sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
498697883Sgibbs				if (sg != scb->sg_list
498797883Sgibbs				 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
498897883Sgibbs
498997883Sgibbs					sg--;
4990123579Sgibbs					sglen = aic_le32toh(sg->len);
499197883Sgibbs					/*
499297883Sgibbs					 * Preserve High Address and SG_LIST
499397883Sgibbs					 * bits while setting the count to 1.
499497883Sgibbs					 */
499597883Sgibbs					data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
4996123579Sgibbs					data_addr = aic_le32toh(sg->addr)
499797883Sgibbs						  + (sglen & AHD_SG_LEN_MASK)
499897883Sgibbs						  - 1;
499997883Sgibbs
500097883Sgibbs					/*
500197883Sgibbs					 * Increment sg so it points to the
500297883Sgibbs					 * "next" sg.
500397883Sgibbs					 */
500497883Sgibbs					sg++;
500597883Sgibbs					sgptr = ahd_sg_virt_to_bus(ahd, scb,
500697883Sgibbs								  sg);
500797883Sgibbs				}
500897883Sgibbs			}
5009115335Sgibbs			/*
5010115335Sgibbs			 * Toggle the "oddness" of the transfer length
5011115335Sgibbs			 * to handle this mid-transfer ignore wide
5012115335Sgibbs			 * residue.  This ensures that the oddness is
5013115335Sgibbs			 * correct for subsequent data transfers.
5014115335Sgibbs			 */
5015115335Sgibbs			ahd_outb(ahd, SCB_TASK_ATTRIBUTE,
5016116940Sgibbs			    ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
5017116940Sgibbs			    ^ SCB_XFERLEN_ODD);
501897883Sgibbs
5019115335Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
5020115335Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);
502197883Sgibbs			/*
502297883Sgibbs			 * The FIFO's pointers will be updated if/when the
502397883Sgibbs			 * sequencer re-enters a data phase.
502497883Sgibbs			 */
502597883Sgibbs		}
502697883Sgibbs	}
502797883Sgibbs}
502897883Sgibbs
502997883Sgibbs
503097883Sgibbs/*
503197883Sgibbs * Reinitialize the data pointers for the active transfer
503297883Sgibbs * based on its current residual.
503397883Sgibbs */
503497883Sgibbsstatic void
503597883Sgibbsahd_reinitialize_dataptrs(struct ahd_softc *ahd)
503697883Sgibbs{
503797883Sgibbs	struct		 scb *scb;
503897883Sgibbs	ahd_mode_state	 saved_modes;
503997883Sgibbs	u_int		 scb_index;
504097883Sgibbs	u_int		 wait;
504197883Sgibbs	uint32_t	 sgptr;
504297883Sgibbs	uint32_t	 resid;
504397883Sgibbs	uint64_t	 dataptr;
504497883Sgibbs
504597883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK,
504697883Sgibbs			 AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK);
504797883Sgibbs
504897883Sgibbs	scb_index = ahd_get_scbptr(ahd);
504997883Sgibbs	scb = ahd_lookup_scb(ahd, scb_index);
505097883Sgibbs
505197883Sgibbs	/*
505297883Sgibbs	 * Release and reacquire the FIFO so we
505397883Sgibbs	 * have a clean slate.
505497883Sgibbs	 */
505597883Sgibbs	ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
505697883Sgibbs	wait = 1000;
5057116935Sgibbs	while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))
5058123579Sgibbs		aic_delay(100);
505997883Sgibbs	if (wait == 0) {
506097883Sgibbs		ahd_print_path(ahd, scb);
506197883Sgibbs		printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");
506297883Sgibbs		ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
506397883Sgibbs	}
506497883Sgibbs	saved_modes = ahd_save_modes(ahd);
506597883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
506697883Sgibbs	ahd_outb(ahd, DFFSTAT,
5067107441Sscottl		 ahd_inb(ahd, DFFSTAT)
5068107441Sscottl		| (saved_modes == 0x11 ? CURRFIFO_1 : CURRFIFO_0));
506997883Sgibbs
507097883Sgibbs	/*
507197883Sgibbs	 * Determine initial values for data_addr and data_cnt
507297883Sgibbs	 * for resuming the data phase.
507397883Sgibbs	 */
5074123579Sgibbs	sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
507597883Sgibbs	sgptr &= SG_PTR_MASK;
507697883Sgibbs
507797883Sgibbs	resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
507897883Sgibbs	      | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 1) << 8)
507997883Sgibbs	      | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT);
508097883Sgibbs
508197883Sgibbs	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
508297883Sgibbs		struct ahd_dma64_seg *sg;
508397883Sgibbs
508497883Sgibbs		sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
508597883Sgibbs
508697883Sgibbs		/* The residual sg_ptr always points to the next sg */
508797883Sgibbs		sg--;
508897883Sgibbs
5089123579Sgibbs		dataptr = aic_le64toh(sg->addr)
5090123579Sgibbs			+ (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
509197883Sgibbs			- resid;
5092123579Sgibbs		ahd_outl(ahd, HADDR + 4, dataptr >> 32);
509397883Sgibbs	} else {
509497883Sgibbs		struct	 ahd_dma_seg *sg;
509597883Sgibbs
509697883Sgibbs		sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
509797883Sgibbs
509897883Sgibbs		/* The residual sg_ptr always points to the next sg */
509997883Sgibbs		sg--;
510097883Sgibbs
5101123579Sgibbs		dataptr = aic_le32toh(sg->addr)
5102123579Sgibbs			+ (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
510397883Sgibbs			- resid;
510497883Sgibbs		ahd_outb(ahd, HADDR + 4,
5105123579Sgibbs			 (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
510697883Sgibbs	}
5107123579Sgibbs	ahd_outl(ahd, HADDR, dataptr);
510897883Sgibbs	ahd_outb(ahd, HCNT + 2, resid >> 16);
510997883Sgibbs	ahd_outb(ahd, HCNT + 1, resid >> 8);
511097883Sgibbs	ahd_outb(ahd, HCNT, resid);
511197883Sgibbs}
511297883Sgibbs
511397883Sgibbs/*
511497883Sgibbs * Handle the effects of issuing a bus device reset message.
511597883Sgibbs */
511697883Sgibbsstatic void
511797883Sgibbsahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
5118109588Sgibbs		    u_int lun, cam_status status, char *message,
5119109588Sgibbs		    int verbose_level)
512097883Sgibbs{
512197883Sgibbs#ifdef AHD_TARGET_MODE
512297883Sgibbs	struct ahd_tmode_tstate* tstate;
512397883Sgibbs#endif
512497883Sgibbs	int found;
512597883Sgibbs
512697883Sgibbs	found = ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
5127109588Sgibbs			       lun, SCB_LIST_NULL, devinfo->role,
512897883Sgibbs			       status);
512997883Sgibbs
513097883Sgibbs#ifdef AHD_TARGET_MODE
513197883Sgibbs	/*
513297883Sgibbs	 * Send an immediate notify ccb to all target mord peripheral
513397883Sgibbs	 * drivers affected by this action.
513497883Sgibbs	 */
513597883Sgibbs	tstate = ahd->enabled_targets[devinfo->our_scsiid];
513697883Sgibbs	if (tstate != NULL) {
5137109588Sgibbs		u_int cur_lun;
5138109588Sgibbs		u_int max_lun;
5139109588Sgibbs
5140109588Sgibbs		if (lun != CAM_LUN_WILDCARD) {
5141109588Sgibbs			cur_lun = 0;
5142109588Sgibbs			max_lun = AHD_NUM_LUNS - 1;
5143109588Sgibbs		} else {
5144109588Sgibbs			cur_lun = lun;
5145109588Sgibbs			max_lun = lun;
5146109588Sgibbs		}
5147109588Sgibbs		for (cur_lun <= max_lun; cur_lun++) {
514897883Sgibbs			struct ahd_tmode_lstate* lstate;
514997883Sgibbs
5150109588Sgibbs			lstate = tstate->enabled_luns[cur_lun];
515197883Sgibbs			if (lstate == NULL)
515297883Sgibbs				continue;
515397883Sgibbs
515497883Sgibbs			ahd_queue_lstate_event(ahd, lstate, devinfo->our_scsiid,
515597883Sgibbs					       MSG_BUS_DEV_RESET, /*arg*/0);
515697883Sgibbs			ahd_send_lstate_events(ahd, lstate);
515797883Sgibbs		}
515897883Sgibbs	}
515997883Sgibbs#endif
516097883Sgibbs
516197883Sgibbs	/*
516297883Sgibbs	 * Go back to async/narrow transfers and renegotiate.
516397883Sgibbs	 */
516497883Sgibbs	ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
516597883Sgibbs		      AHD_TRANS_CUR, /*paused*/TRUE);
516697883Sgibbs	ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
5167129134Sgibbs			 /*ppr_options*/0, AHD_TRANS_CUR,
5168129134Sgibbs			 /*paused*/TRUE);
516997883Sgibbs
5170129134Sgibbs	if (status != CAM_SEL_TIMEOUT)
5171129134Sgibbs		ahd_send_async(ahd, devinfo->channel, devinfo->target,
5172129134Sgibbs			       lun, AC_SENT_BDR, NULL);
517397883Sgibbs
517497883Sgibbs	if (message != NULL
5175199260Sattilio	 && (verbose_level <= bootverbose)) {
5176199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
517797883Sgibbs		printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
517897883Sgibbs		       message, devinfo->channel, devinfo->target, found);
5179199260Sattilio	}
518097883Sgibbs}
518197883Sgibbs
518297883Sgibbs#ifdef AHD_TARGET_MODE
518397883Sgibbsstatic void
518497883Sgibbsahd_setup_target_msgin(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
518597883Sgibbs		       struct scb *scb)
518697883Sgibbs{
518797883Sgibbs
518897883Sgibbs	/*
518997883Sgibbs	 * To facilitate adding multiple messages together,
519097883Sgibbs	 * each routine should increment the index and len
519197883Sgibbs	 * variables instead of setting them explicitly.
519297883Sgibbs	 */
519397883Sgibbs	ahd->msgout_index = 0;
519497883Sgibbs	ahd->msgout_len = 0;
519597883Sgibbs
519697883Sgibbs	if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
519797883Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
519897883Sgibbs	else
519997883Sgibbs		panic("ahd_intr: AWAITING target message with no message");
520097883Sgibbs
520197883Sgibbs	ahd->msgout_index = 0;
520297883Sgibbs	ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
520397883Sgibbs}
520497883Sgibbs#endif
520597883Sgibbs/**************************** Initialization **********************************/
5206106803Sscottlstatic u_int
520797883Sgibbsahd_sglist_size(struct ahd_softc *ahd)
520897883Sgibbs{
520997883Sgibbs	bus_size_t list_size;
521097883Sgibbs
521197883Sgibbs	list_size = sizeof(struct ahd_dma_seg) * AHD_NSEG;
521297883Sgibbs	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
521397883Sgibbs		list_size = sizeof(struct ahd_dma64_seg) * AHD_NSEG;
521497883Sgibbs	return (list_size);
521597883Sgibbs}
521697883Sgibbs
521797883Sgibbs/*
521897883Sgibbs * Calculate the optimum S/G List allocation size.  S/G elements used
521997883Sgibbs * for a given transaction must be physically contiguous.  Assume the
522097883Sgibbs * OS will allocate full pages to us, so it doesn't make sense to request
522197883Sgibbs * less than a page.
522297883Sgibbs */
5223106803Sscottlstatic u_int
522497883Sgibbsahd_sglist_allocsize(struct ahd_softc *ahd)
522597883Sgibbs{
522697883Sgibbs	bus_size_t sg_list_increment;
522797883Sgibbs	bus_size_t sg_list_size;
522897883Sgibbs	bus_size_t max_list_size;
522997883Sgibbs	bus_size_t best_list_size;
523097883Sgibbs
523197883Sgibbs	/* Start out with the minimum required for AHD_NSEG. */
523297883Sgibbs	sg_list_increment = ahd_sglist_size(ahd);
523397883Sgibbs	sg_list_size = sg_list_increment;
523497883Sgibbs
523597883Sgibbs	/* Get us as close as possible to a page in size. */
523697883Sgibbs	while ((sg_list_size + sg_list_increment) <= PAGE_SIZE)
523797883Sgibbs		sg_list_size += sg_list_increment;
523897883Sgibbs
523997883Sgibbs	/*
524097883Sgibbs	 * Try to reduce the amount of wastage by allocating
524197883Sgibbs	 * multiple pages.
524297883Sgibbs	 */
524397883Sgibbs	best_list_size = sg_list_size;
524497883Sgibbs	max_list_size = roundup(sg_list_increment, PAGE_SIZE);
524597883Sgibbs	if (max_list_size < 4 * PAGE_SIZE)
524697883Sgibbs		max_list_size = 4 * PAGE_SIZE;
524797883Sgibbs	if (max_list_size > (AHD_SCB_MAX_ALLOC * sg_list_increment))
524897883Sgibbs		max_list_size = (AHD_SCB_MAX_ALLOC * sg_list_increment);
524997883Sgibbs	while ((sg_list_size + sg_list_increment) <= max_list_size
525097883Sgibbs	   &&  (sg_list_size % PAGE_SIZE) != 0) {
525197883Sgibbs		bus_size_t new_mod;
525297883Sgibbs		bus_size_t best_mod;
525397883Sgibbs
525497883Sgibbs		sg_list_size += sg_list_increment;
525597883Sgibbs		new_mod = sg_list_size % PAGE_SIZE;
525697883Sgibbs		best_mod = best_list_size % PAGE_SIZE;
525797883Sgibbs		if (new_mod > best_mod || new_mod == 0) {
525897883Sgibbs			best_list_size = sg_list_size;
525997883Sgibbs		}
526097883Sgibbs	}
526197883Sgibbs	return (best_list_size);
526297883Sgibbs}
526397883Sgibbs
526497883Sgibbs/*
526597883Sgibbs * Allocate a controller structure for a new device
526697883Sgibbs * and perform initial initializion.
526797883Sgibbs */
526897883Sgibbsstruct ahd_softc *
526997883Sgibbsahd_alloc(void *platform_arg, char *name)
527097883Sgibbs{
527197883Sgibbs	struct  ahd_softc *ahd;
527297883Sgibbs
527397883Sgibbs#ifndef	__FreeBSD__
527497883Sgibbs	ahd = malloc(sizeof(*ahd), M_DEVBUF, M_NOWAIT);
527597883Sgibbs	if (!ahd) {
527697883Sgibbs		printf("aic7xxx: cannot malloc softc!\n");
527797883Sgibbs		free(name, M_DEVBUF);
527897883Sgibbs		return NULL;
527997883Sgibbs	}
528097883Sgibbs#else
528197883Sgibbs	ahd = device_get_softc((device_t)platform_arg);
528297883Sgibbs#endif
528397883Sgibbs	memset(ahd, 0, sizeof(*ahd));
528497883Sgibbs	ahd->seep_config = malloc(sizeof(*ahd->seep_config),
528597883Sgibbs				  M_DEVBUF, M_NOWAIT);
528697883Sgibbs	if (ahd->seep_config == NULL) {
528797883Sgibbs#ifndef	__FreeBSD__
528897883Sgibbs		free(ahd, M_DEVBUF);
528997883Sgibbs#endif
529097883Sgibbs		free(name, M_DEVBUF);
529197883Sgibbs		return (NULL);
529297883Sgibbs	}
529397883Sgibbs	LIST_INIT(&ahd->pending_scbs);
5294141978Sgibbs	LIST_INIT(&ahd->timedout_scbs);
529597883Sgibbs	/* We don't know our unit number until the OSM sets it */
529697883Sgibbs	ahd->name = name;
529797883Sgibbs	ahd->unit = -1;
529897883Sgibbs	ahd->description = NULL;
529997883Sgibbs	ahd->bus_description = NULL;
530097883Sgibbs	ahd->channel = 'A';
530197883Sgibbs	ahd->chip = AHD_NONE;
530297883Sgibbs	ahd->features = AHD_FENONE;
530397883Sgibbs	ahd->bugs = AHD_BUGNONE;
530497883Sgibbs	ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A
530597883Sgibbs		   | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A;
5306123579Sgibbs	aic_timer_init(&ahd->reset_timer);
5307123579Sgibbs	aic_timer_init(&ahd->stat_timer);
5308115329Sgibbs	ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT;
5309115329Sgibbs	ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT;
5310115329Sgibbs	ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT;
5311115329Sgibbs	ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT;
5312115329Sgibbs	ahd->int_coalescing_stop_threshold =
5313115329Sgibbs	    AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT;
531497883Sgibbs
531597883Sgibbs	if (ahd_platform_alloc(ahd, platform_arg) != 0) {
531697883Sgibbs		ahd_free(ahd);
531797883Sgibbs		ahd = NULL;
531897883Sgibbs	}
5319168807Sscottl	ahd_lockinit(ahd);
5320102679Sgibbs#ifdef AHD_DEBUG
5321102679Sgibbs	if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {
5322106803Sscottl		printf("%s: scb size = 0x%x, hscb size = 0x%x\n",
5323106803Sscottl		       ahd_name(ahd), (u_int)sizeof(struct scb),
5324106803Sscottl		       (u_int)sizeof(struct hardware_scb));
5325102679Sgibbs	}
5326102679Sgibbs#endif
532797883Sgibbs	return (ahd);
532897883Sgibbs}
532997883Sgibbs
533097883Sgibbsint
533197883Sgibbsahd_softc_init(struct ahd_softc *ahd)
533297883Sgibbs{
533397883Sgibbs
533497883Sgibbs	ahd->unpause = 0;
533597883Sgibbs	ahd->pause = PAUSE;
533697883Sgibbs	return (0);
533797883Sgibbs}
533897883Sgibbs
533997883Sgibbsvoid
534097883Sgibbsahd_softc_insert(struct ahd_softc *ahd)
534197883Sgibbs{
534297883Sgibbs	struct ahd_softc *list_ahd;
534397883Sgibbs
5344123579Sgibbs#if AIC_PCI_CONFIG > 0
534597883Sgibbs	/*
534697883Sgibbs	 * Second Function PCI devices need to inherit some
534797883Sgibbs	 * settings from function 0.
534897883Sgibbs	 */
534997883Sgibbs	if ((ahd->features & AHD_MULTI_FUNC) != 0) {
535097883Sgibbs		TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
5351123579Sgibbs			aic_dev_softc_t list_pci;
5352123579Sgibbs			aic_dev_softc_t pci;
535397883Sgibbs
535497883Sgibbs			list_pci = list_ahd->dev_softc;
535597883Sgibbs			pci = ahd->dev_softc;
5356123579Sgibbs			if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci)
5357123579Sgibbs			 && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) {
535897883Sgibbs				struct ahd_softc *master;
535997883Sgibbs				struct ahd_softc *slave;
536097883Sgibbs
5361123579Sgibbs				if (aic_get_pci_function(list_pci) == 0) {
536297883Sgibbs					master = list_ahd;
536397883Sgibbs					slave = ahd;
536497883Sgibbs				} else {
536597883Sgibbs					master = ahd;
536697883Sgibbs					slave = list_ahd;
536797883Sgibbs				}
536897883Sgibbs				slave->flags &= ~AHD_BIOS_ENABLED;
536997883Sgibbs				slave->flags |=
537097883Sgibbs				    master->flags & AHD_BIOS_ENABLED;
537197883Sgibbs				break;
537297883Sgibbs			}
537397883Sgibbs		}
537497883Sgibbs	}
537597883Sgibbs#endif
537697883Sgibbs
537797883Sgibbs	/*
537897883Sgibbs	 * Insertion sort into our list of softcs.
537997883Sgibbs	 */
538097883Sgibbs	list_ahd = TAILQ_FIRST(&ahd_tailq);
538197883Sgibbs	while (list_ahd != NULL
5382114623Sgibbs	    && ahd_softc_comp(ahd, list_ahd) <= 0)
538397883Sgibbs		list_ahd = TAILQ_NEXT(list_ahd, links);
538497883Sgibbs	if (list_ahd != NULL)
538597883Sgibbs		TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
538697883Sgibbs	else
538797883Sgibbs		TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
538897883Sgibbs	ahd->init_level++;
538997883Sgibbs}
539097883Sgibbs
539197883Sgibbsvoid
539297883Sgibbsahd_set_unit(struct ahd_softc *ahd, int unit)
539397883Sgibbs{
539497883Sgibbs	ahd->unit = unit;
539597883Sgibbs}
539697883Sgibbs
539797883Sgibbsvoid
539897883Sgibbsahd_set_name(struct ahd_softc *ahd, char *name)
539997883Sgibbs{
540097883Sgibbs	if (ahd->name != NULL)
540197883Sgibbs		free(ahd->name, M_DEVBUF);
540297883Sgibbs	ahd->name = name;
540397883Sgibbs}
540497883Sgibbs
540597883Sgibbsvoid
540697883Sgibbsahd_free(struct ahd_softc *ahd)
540797883Sgibbs{
540897883Sgibbs	int i;
540997883Sgibbs
5410123579Sgibbs	ahd_terminate_recovery_thread(ahd);
541197883Sgibbs	switch (ahd->init_level) {
541297883Sgibbs	default:
541397883Sgibbs	case 5:
541497883Sgibbs		ahd_shutdown(ahd);
541597883Sgibbs		/* FALLTHROUGH */
541697883Sgibbs	case 4:
5417123579Sgibbs		aic_dmamap_unload(ahd, ahd->shared_data_dmat,
5418123579Sgibbs				  ahd->shared_data_map.dmamap);
541997883Sgibbs		/* FALLTHROUGH */
542097883Sgibbs	case 3:
5421123579Sgibbs		aic_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
5422123579Sgibbs				ahd->shared_data_map.dmamap);
5423123579Sgibbs		aic_dmamap_destroy(ahd, ahd->shared_data_dmat,
5424123579Sgibbs				   ahd->shared_data_map.dmamap);
542597883Sgibbs		/* FALLTHROUGH */
542697883Sgibbs	case 2:
5427123579Sgibbs		aic_dma_tag_destroy(ahd, ahd->shared_data_dmat);
542897883Sgibbs	case 1:
542997883Sgibbs#ifndef __linux__
5430123579Sgibbs		aic_dma_tag_destroy(ahd, ahd->buffer_dmat);
543197883Sgibbs#endif
543297883Sgibbs		break;
543397883Sgibbs	case 0:
543497883Sgibbs		break;
543597883Sgibbs	}
543697883Sgibbs
543797883Sgibbs#ifndef __linux__
5438123579Sgibbs	aic_dma_tag_destroy(ahd, ahd->parent_dmat);
543997883Sgibbs#endif
544097883Sgibbs	ahd_platform_free(ahd);
5441114623Sgibbs	ahd_fini_scbdata(ahd);
544297883Sgibbs	for (i = 0; i < AHD_NUM_TARGETS; i++) {
544397883Sgibbs		struct ahd_tmode_tstate *tstate;
544497883Sgibbs
544597883Sgibbs		tstate = ahd->enabled_targets[i];
544697883Sgibbs		if (tstate != NULL) {
5447153072Sru#ifdef AHD_TARGET_MODE
544897883Sgibbs			int j;
544997883Sgibbs
545097883Sgibbs			for (j = 0; j < AHD_NUM_LUNS; j++) {
545197883Sgibbs				struct ahd_tmode_lstate *lstate;
545297883Sgibbs
545397883Sgibbs				lstate = tstate->enabled_luns[j];
545497883Sgibbs				if (lstate != NULL) {
545597883Sgibbs					xpt_free_path(lstate->path);
545697883Sgibbs					free(lstate, M_DEVBUF);
545797883Sgibbs				}
545897883Sgibbs			}
545997883Sgibbs#endif
546097883Sgibbs			free(tstate, M_DEVBUF);
546197883Sgibbs		}
546297883Sgibbs	}
5463153072Sru#ifdef AHD_TARGET_MODE
546497883Sgibbs	if (ahd->black_hole != NULL) {
546597883Sgibbs		xpt_free_path(ahd->black_hole->path);
546697883Sgibbs		free(ahd->black_hole, M_DEVBUF);
546797883Sgibbs	}
546897883Sgibbs#endif
546997883Sgibbs	if (ahd->name != NULL)
547097883Sgibbs		free(ahd->name, M_DEVBUF);
547197883Sgibbs	if (ahd->seep_config != NULL)
547297883Sgibbs		free(ahd->seep_config, M_DEVBUF);
5473107441Sscottl	if (ahd->saved_stack != NULL)
5474107441Sscottl		free(ahd->saved_stack, M_DEVBUF);
547597883Sgibbs#ifndef __FreeBSD__
547697883Sgibbs	free(ahd, M_DEVBUF);
547797883Sgibbs#endif
547897883Sgibbs	return;
547997883Sgibbs}
548097883Sgibbs
548197883Sgibbsvoid
548297883Sgibbsahd_shutdown(void *arg)
548397883Sgibbs{
548497883Sgibbs	struct	ahd_softc *ahd;
548597883Sgibbs
548697883Sgibbs	ahd = (struct ahd_softc *)arg;
548797883Sgibbs
5488109588Sgibbs	/*
5489109588Sgibbs	 * Stop periodic timer callbacks.
5490109588Sgibbs	 */
5491123579Sgibbs	aic_timer_stop(&ahd->reset_timer);
5492123579Sgibbs	aic_timer_stop(&ahd->stat_timer);
5493109588Sgibbs
549497883Sgibbs	/* This will reset most registers to 0, but not all */
5495115917Sgibbs	ahd_reset(ahd, /*reinit*/FALSE);
549697883Sgibbs}
549797883Sgibbs
549897883Sgibbs/*
549997883Sgibbs * Reset the controller and record some information about it
5500115917Sgibbs * that is only available just after a reset.  If "reinit" is
5501115917Sgibbs * non-zero, this reset occured after initial configuration
5502115917Sgibbs * and the caller requests that the chip be fully reinitialized
5503115917Sgibbs * to a runable state.  Chip interrupts are *not* enabled after
5504115917Sgibbs * a reinitialization.  The caller must enable interrupts via
5505115917Sgibbs * ahd_intr_enable().
550697883Sgibbs */
550797883Sgibbsint
5508115917Sgibbsahd_reset(struct ahd_softc *ahd, int reinit)
550997883Sgibbs{
551097883Sgibbs	u_int	 sxfrctl1;
551197883Sgibbs	int	 wait;
551297883Sgibbs	uint32_t cmd;
551397883Sgibbs
551497883Sgibbs	/*
551597883Sgibbs	 * Preserve the value of the SXFRCTL1 register for all channels.
551697883Sgibbs	 * It contains settings that affect termination and we don't want
551797883Sgibbs	 * to disturb the integrity of the bus.
551897883Sgibbs	 */
551997883Sgibbs	ahd_pause(ahd);
5520111954Sgibbs	ahd_update_modes(ahd);
5521111653Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
552297883Sgibbs	sxfrctl1 = ahd_inb(ahd, SXFRCTL1);
552397883Sgibbs
5524123579Sgibbs	cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
552597883Sgibbs	if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
552697883Sgibbs		uint32_t mod_cmd;
552797883Sgibbs
552897883Sgibbs		/*
552997883Sgibbs		 * A4 Razor #632
553097883Sgibbs		 * During the assertion of CHIPRST, the chip
553197883Sgibbs		 * does not disable its parity logic prior to
553297883Sgibbs		 * the start of the reset.  This may cause a
553397883Sgibbs		 * parity error to be detected and thus a
553497883Sgibbs		 * spurious SERR or PERR assertion.  Disble
553597883Sgibbs		 * PERR and SERR responses during the CHIPRST.
553697883Sgibbs		 */
553797883Sgibbs		mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN);
5538123579Sgibbs		aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
553997883Sgibbs				     mod_cmd, /*bytes*/2);
554097883Sgibbs	}
554197883Sgibbs	ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause);
554297883Sgibbs
554397883Sgibbs	/*
554497883Sgibbs	 * Ensure that the reset has finished.  We delay 1000us
554597883Sgibbs	 * prior to reading the register to make sure the chip
554697883Sgibbs	 * has sufficiently completed its reset to handle register
554797883Sgibbs	 * accesses.
554897883Sgibbs	 */
554997883Sgibbs	wait = 1000;
555097883Sgibbs	do {
5551123579Sgibbs		aic_delay(1000);
555297883Sgibbs	} while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK));
555397883Sgibbs
555497883Sgibbs	if (wait == 0) {
555597883Sgibbs		printf("%s: WARNING - Failed chip reset!  "
555697883Sgibbs		       "Trying to initialize anyway.\n", ahd_name(ahd));
5557199260Sattilio		AHD_FATAL_ERROR(ahd);
555897883Sgibbs	}
555997883Sgibbs	ahd_outb(ahd, HCNTRL, ahd->pause);
556097883Sgibbs
556197883Sgibbs	if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
556297883Sgibbs		/*
556397883Sgibbs		 * Clear any latched PCI error status and restore
556497883Sgibbs		 * previous SERR and PERR response enables.
556597883Sgibbs		 */
5566123579Sgibbs		aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
556797883Sgibbs				     0xFF, /*bytes*/1);
5568123579Sgibbs		aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
556997883Sgibbs				     cmd, /*bytes*/2);
557097883Sgibbs	}
5571111653Sgibbs
5572111653Sgibbs	/*
5573111653Sgibbs	 * Mode should be SCSI after a chip reset, but lets
5574111954Sgibbs	 * set it just to be safe.  We touch the MODE_PTR
5575111954Sgibbs	 * register directly so as to bypass the lazy update
5576111954Sgibbs	 * code in ahd_set_modes().
5577111653Sgibbs	 */
557897883Sgibbs	ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
5579111954Sgibbs	ahd_outb(ahd, MODE_PTR,
5580111954Sgibbs		 ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI));
558197883Sgibbs
558297883Sgibbs	/*
558397883Sgibbs	 * Restore SXFRCTL1.
558497883Sgibbs	 *
558597883Sgibbs	 * We must always initialize STPWEN to 1 before we
558697883Sgibbs	 * restore the saved values.  STPWEN is initialized
558797883Sgibbs	 * to a tri-state condition which can only be cleared
558897883Sgibbs	 * by turning it on.
558997883Sgibbs	 */
559097883Sgibbs	ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
559197883Sgibbs	ahd_outb(ahd, SXFRCTL1, sxfrctl1);
559297883Sgibbs
5593111653Sgibbs	/* Determine chip configuration */
5594111653Sgibbs	ahd->features &= ~AHD_WIDE;
5595111653Sgibbs	if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0)
5596111653Sgibbs		ahd->features |= AHD_WIDE;
5597111653Sgibbs
559897883Sgibbs	/*
559997883Sgibbs	 * If a recovery action has forced a chip reset,
5600111653Sgibbs	 * re-initialize the chip to our liking.
560197883Sgibbs	 */
5602115917Sgibbs	if (reinit != 0)
560397883Sgibbs		ahd_chip_init(ahd);
560497883Sgibbs
560597883Sgibbs	return (0);
560697883Sgibbs}
560797883Sgibbs
560897883Sgibbs/*
560997883Sgibbs * Determine the number of SCBs available on the controller
561097883Sgibbs */
561197883Sgibbsint
561297883Sgibbsahd_probe_scbs(struct ahd_softc *ahd) {
561397883Sgibbs	int i;
561497883Sgibbs
561597883Sgibbs	AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
561697883Sgibbs			 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
561797883Sgibbs	for (i = 0; i < AHD_SCB_MAX; i++) {
561897883Sgibbs		int j;
561997883Sgibbs
562097883Sgibbs		ahd_set_scbptr(ahd, i);
562197883Sgibbs		ahd_outw(ahd, SCB_BASE, i);
562297883Sgibbs		for (j = 2; j < 64; j++)
562397883Sgibbs			ahd_outb(ahd, SCB_BASE+j, 0);
562497883Sgibbs		/* Start out life as unallocated (needing an abort) */
562597883Sgibbs		ahd_outb(ahd, SCB_CONTROL, MK_MESSAGE);
562697883Sgibbs		if (ahd_inw_scbram(ahd, SCB_BASE) != i)
562797883Sgibbs			break;
562897883Sgibbs		ahd_set_scbptr(ahd, 0);
562997883Sgibbs		if (ahd_inw_scbram(ahd, SCB_BASE) != 0)
563097883Sgibbs			break;
563197883Sgibbs	}
563297883Sgibbs	return (i);
563397883Sgibbs}
563497883Sgibbs
563597883Sgibbsstatic void
563697883Sgibbsahd_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
563797883Sgibbs{
563897883Sgibbs	bus_addr_t *baddr;
563997883Sgibbs
564097883Sgibbs	baddr = (bus_addr_t *)arg;
564197883Sgibbs	*baddr = segs->ds_addr;
564297883Sgibbs}
564397883Sgibbs
564497883Sgibbsstatic void
564597883Sgibbsahd_initialize_hscbs(struct ahd_softc *ahd)
564697883Sgibbs{
564797883Sgibbs	int i;
564897883Sgibbs
564997883Sgibbs	for (i = 0; i < ahd->scb_data.maxhscbs; i++) {
565097883Sgibbs		ahd_set_scbptr(ahd, i);
565197883Sgibbs
565297883Sgibbs		/* Clear the control byte. */
565397883Sgibbs		ahd_outb(ahd, SCB_CONTROL, 0);
565497883Sgibbs
565597883Sgibbs		/* Set the next pointer */
565697883Sgibbs		ahd_outw(ahd, SCB_NEXT, SCB_LIST_NULL);
565797883Sgibbs	}
565897883Sgibbs}
565997883Sgibbs
566097883Sgibbsstatic int
566197883Sgibbsahd_init_scbdata(struct ahd_softc *ahd)
566297883Sgibbs{
5663102679Sgibbs	struct	scb_data *scb_data;
5664102679Sgibbs	int	i;
566597883Sgibbs
566697883Sgibbs	scb_data = &ahd->scb_data;
5667102679Sgibbs	TAILQ_INIT(&scb_data->free_scbs);
5668102679Sgibbs	for (i = 0; i < AHD_NUM_TARGETS * AHD_NUM_LUNS_NONPKT; i++)
5669102679Sgibbs		LIST_INIT(&scb_data->free_scb_lists[i]);
5670102679Sgibbs	LIST_INIT(&scb_data->any_dev_free_scb_list);
567197883Sgibbs	SLIST_INIT(&scb_data->hscb_maps);
567297883Sgibbs	SLIST_INIT(&scb_data->sg_maps);
567397883Sgibbs	SLIST_INIT(&scb_data->sense_maps);
567497883Sgibbs
567597883Sgibbs	/* Determine the number of hardware SCBs and initialize them */
567697883Sgibbs	scb_data->maxhscbs = ahd_probe_scbs(ahd);
567797883Sgibbs	if (scb_data->maxhscbs == 0) {
567897883Sgibbs		printf("%s: No SCB space found\n", ahd_name(ahd));
5679199260Sattilio		AHD_FATAL_ERROR(ahd);
568097883Sgibbs		return (ENXIO);
568197883Sgibbs	}
568297883Sgibbs
568397883Sgibbs	ahd_initialize_hscbs(ahd);
568497883Sgibbs
568597883Sgibbs	/*
568697883Sgibbs	 * Create our DMA tags.  These tags define the kinds of device
568797883Sgibbs	 * accessible memory allocations and memory mappings we will
568897883Sgibbs	 * need to perform during normal operation.
568997883Sgibbs	 *
569097883Sgibbs	 * Unless we need to further restrict the allocation, we rely
569197883Sgibbs	 * on the restrictions of the parent dmat, hence the common
569297883Sgibbs	 * use of MAXADDR and MAXSIZE.
569397883Sgibbs	 */
569497883Sgibbs
569597883Sgibbs	/* DMA tag for our hardware scb structures */
5696123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
569797883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
569897883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
569997883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
570097883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
570197883Sgibbs			       PAGE_SIZE, /*nsegments*/1,
570297883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
570397883Sgibbs			       /*flags*/0, &scb_data->hscb_dmat) != 0) {
570497883Sgibbs		goto error_exit;
570597883Sgibbs	}
570697883Sgibbs
570797883Sgibbs	scb_data->init_level++;
570897883Sgibbs
570997883Sgibbs	/* DMA tag for our S/G structures. */
5710123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8,
571197883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
571297883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
571397883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
571497883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
571597883Sgibbs			       ahd_sglist_allocsize(ahd), /*nsegments*/1,
571697883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
571797883Sgibbs			       /*flags*/0, &scb_data->sg_dmat) != 0) {
571897883Sgibbs		goto error_exit;
571997883Sgibbs	}
572097883Sgibbs#ifdef AHD_DEBUG
572197883Sgibbs	if ((ahd_debug & AHD_SHOW_MEMORY) != 0)
572297883Sgibbs		printf("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd),
572397883Sgibbs		       ahd_sglist_allocsize(ahd));
572497883Sgibbs#endif
572597883Sgibbs
572697883Sgibbs	scb_data->init_level++;
572797883Sgibbs
572897883Sgibbs	/* DMA tag for our sense buffers.  We allocate in page sized chunks */
5729123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
573097883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
573197883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
573297883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
573397883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
573497883Sgibbs			       PAGE_SIZE, /*nsegments*/1,
573597883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
573697883Sgibbs			       /*flags*/0, &scb_data->sense_dmat) != 0) {
573797883Sgibbs		goto error_exit;
573897883Sgibbs	}
573997883Sgibbs
574097883Sgibbs	scb_data->init_level++;
574197883Sgibbs
574297883Sgibbs	/* Perform initial CCB allocation */
5743168873Sscottl	while (ahd_alloc_scbs(ahd) != 0)
5744168873Sscottl		;
574597883Sgibbs
574697883Sgibbs	if (scb_data->numscbs == 0) {
574797883Sgibbs		printf("%s: ahd_init_scbdata - "
574897883Sgibbs		       "Unable to allocate initial scbs\n",
574997883Sgibbs		       ahd_name(ahd));
575097883Sgibbs		goto error_exit;
575197883Sgibbs	}
575297883Sgibbs
575397883Sgibbs	/*
575497883Sgibbs	 * Note that we were successfull
575597883Sgibbs	 */
575697883Sgibbs	return (0);
575797883Sgibbs
575897883Sgibbserror_exit:
575997883Sgibbs
576097883Sgibbs	return (ENOMEM);
576197883Sgibbs}
576297883Sgibbs
5763102679Sgibbsstatic struct scb *
5764102679Sgibbsahd_find_scb_by_tag(struct ahd_softc *ahd, u_int tag)
5765102679Sgibbs{
5766102679Sgibbs	struct scb *scb;
5767102679Sgibbs
5768102679Sgibbs	/*
5769102679Sgibbs	 * Look on the pending list.
5770102679Sgibbs	 */
5771102679Sgibbs	LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
5772102679Sgibbs		if (SCB_GET_TAG(scb) == tag)
5773102679Sgibbs			return (scb);
5774102679Sgibbs	}
5775102679Sgibbs
5776102679Sgibbs	/*
5777102679Sgibbs	 * Then on all of the collision free lists.
5778102679Sgibbs	 */
5779102679Sgibbs	TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
5780102679Sgibbs		struct scb *list_scb;
5781102679Sgibbs
5782102679Sgibbs		list_scb = scb;
5783102679Sgibbs		do {
5784102679Sgibbs			if (SCB_GET_TAG(list_scb) == tag)
5785102679Sgibbs				return (list_scb);
5786102679Sgibbs			list_scb = LIST_NEXT(list_scb, collision_links);
5787102679Sgibbs		} while (list_scb);
5788102679Sgibbs	}
5789102679Sgibbs
5790102679Sgibbs	/*
5791102679Sgibbs	 * And finally on the generic free list.
5792102679Sgibbs	 */
5793102679Sgibbs	LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
5794102679Sgibbs		if (SCB_GET_TAG(scb) == tag)
5795102679Sgibbs			return (scb);
5796102679Sgibbs	}
5797102679Sgibbs
5798102679Sgibbs	return (NULL);
5799102679Sgibbs}
5800102679Sgibbs
580197883Sgibbsstatic void
580297883Sgibbsahd_fini_scbdata(struct ahd_softc *ahd)
580397883Sgibbs{
580497883Sgibbs	struct scb_data *scb_data;
580597883Sgibbs
580697883Sgibbs	scb_data = &ahd->scb_data;
580797883Sgibbs	if (scb_data == NULL)
580897883Sgibbs		return;
580997883Sgibbs
581097883Sgibbs	switch (scb_data->init_level) {
581197883Sgibbs	default:
581297883Sgibbs	case 7:
581397883Sgibbs	{
581497883Sgibbs		struct map_node *sns_map;
581597883Sgibbs
581697883Sgibbs		while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) {
581797883Sgibbs			SLIST_REMOVE_HEAD(&scb_data->sense_maps, links);
5818123579Sgibbs			aic_dmamap_unload(ahd, scb_data->sense_dmat,
581997883Sgibbs					  sns_map->dmamap);
5820123579Sgibbs			aic_dmamem_free(ahd, scb_data->sense_dmat,
582197883Sgibbs					sns_map->vaddr, sns_map->dmamap);
582297883Sgibbs			free(sns_map, M_DEVBUF);
582397883Sgibbs		}
5824123579Sgibbs		aic_dma_tag_destroy(ahd, scb_data->sense_dmat);
582597883Sgibbs		/* FALLTHROUGH */
582697883Sgibbs	}
582797883Sgibbs	case 6:
582897883Sgibbs	{
582997883Sgibbs		struct map_node *sg_map;
583097883Sgibbs
583197883Sgibbs		while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) {
583297883Sgibbs			SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
5833123579Sgibbs			aic_dmamap_unload(ahd, scb_data->sg_dmat,
583497883Sgibbs					  sg_map->dmamap);
5835123579Sgibbs			aic_dmamem_free(ahd, scb_data->sg_dmat,
583697883Sgibbs					sg_map->vaddr, sg_map->dmamap);
583797883Sgibbs			free(sg_map, M_DEVBUF);
583897883Sgibbs		}
5839123579Sgibbs		aic_dma_tag_destroy(ahd, scb_data->sg_dmat);
584097883Sgibbs		/* FALLTHROUGH */
584197883Sgibbs	}
584297883Sgibbs	case 5:
584397883Sgibbs	{
584497883Sgibbs		struct map_node *hscb_map;
584597883Sgibbs
584697883Sgibbs		while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) {
584797883Sgibbs			SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links);
5848123579Sgibbs			aic_dmamap_unload(ahd, scb_data->hscb_dmat,
584997883Sgibbs					  hscb_map->dmamap);
5850123579Sgibbs			aic_dmamem_free(ahd, scb_data->hscb_dmat,
585197883Sgibbs					hscb_map->vaddr, hscb_map->dmamap);
585297883Sgibbs			free(hscb_map, M_DEVBUF);
585397883Sgibbs		}
5854123579Sgibbs		aic_dma_tag_destroy(ahd, scb_data->hscb_dmat);
585597883Sgibbs		/* FALLTHROUGH */
585697883Sgibbs	}
585797883Sgibbs	case 4:
585897883Sgibbs	case 3:
585997883Sgibbs	case 2:
586097883Sgibbs	case 1:
586197883Sgibbs	case 0:
586297883Sgibbs		break;
586397883Sgibbs	}
586497883Sgibbs}
586597883Sgibbs
586697883Sgibbs/*
586797883Sgibbs * DSP filter Bypass must be enabled until the first selection
586897883Sgibbs * after a change in bus mode (Razor #491 and #493).
586997883Sgibbs */
587097883Sgibbsstatic void
587197883Sgibbsahd_setup_iocell_workaround(struct ahd_softc *ahd)
587297883Sgibbs{
587397883Sgibbs	ahd_mode_state saved_modes;
587497883Sgibbs
587597883Sgibbs	saved_modes = ahd_save_modes(ahd);
587697883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
587797883Sgibbs	ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL)
587897883Sgibbs	       | BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS);
587997883Sgibbs	ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI));
5880104023Sgibbs#ifdef AHD_DEBUG
5881104023Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0)
5882104023Sgibbs		printf("%s: Setting up iocell workaround\n", ahd_name(ahd));
5883104023Sgibbs#endif
588497883Sgibbs	ahd_restore_modes(ahd, saved_modes);
5885116938Sgibbs	ahd->flags &= ~AHD_HAD_FIRST_SEL;
588697883Sgibbs}
588797883Sgibbs
588897883Sgibbsstatic void
588997883Sgibbsahd_iocell_first_selection(struct ahd_softc *ahd)
589097883Sgibbs{
589197883Sgibbs	ahd_mode_state	saved_modes;
589297883Sgibbs	u_int		sblkctl;
589397883Sgibbs
5894116938Sgibbs	if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0)
5895116938Sgibbs		return;
589697883Sgibbs	saved_modes = ahd_save_modes(ahd);
589797883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
589897883Sgibbs	sblkctl = ahd_inb(ahd, SBLKCTL);
589997883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
5900104023Sgibbs#ifdef AHD_DEBUG
5901104023Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0)
5902104023Sgibbs		printf("%s: iocell first selection\n", ahd_name(ahd));
5903104023Sgibbs#endif
590497883Sgibbs	if ((sblkctl & ENAB40) != 0) {
590597883Sgibbs		ahd_outb(ahd, DSPDATACTL,
590697883Sgibbs			 ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB);
5907104023Sgibbs#ifdef AHD_DEBUG
5908104023Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
5909104023Sgibbs			printf("%s: BYPASS now disabled\n", ahd_name(ahd));
5910104023Sgibbs#endif
591197883Sgibbs	}
591297883Sgibbs	ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI));
591397883Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
591497883Sgibbs	ahd_restore_modes(ahd, saved_modes);
5915116938Sgibbs	ahd->flags |= AHD_HAD_FIRST_SEL;
591697883Sgibbs}
591797883Sgibbs
5918102679Sgibbs/*************************** SCB Management ***********************************/
5919102679Sgibbsstatic void
5920102679Sgibbsahd_add_col_list(struct ahd_softc *ahd, struct scb *scb, u_int col_idx)
5921102679Sgibbs{
5922102679Sgibbs	struct	scb_list *free_list;
5923102679Sgibbs	struct	scb_tailq *free_tailq;
5924102679Sgibbs	struct	scb *first_scb;
5925102679Sgibbs
5926102679Sgibbs	scb->flags |= SCB_ON_COL_LIST;
5927102679Sgibbs	AHD_SET_SCB_COL_IDX(scb, col_idx);
5928102679Sgibbs	free_list = &ahd->scb_data.free_scb_lists[col_idx];
5929102679Sgibbs	free_tailq = &ahd->scb_data.free_scbs;
5930102679Sgibbs	first_scb = LIST_FIRST(free_list);
5931102679Sgibbs	if (first_scb != NULL) {
5932102679Sgibbs		LIST_INSERT_AFTER(first_scb, scb, collision_links);
5933102679Sgibbs	} else {
5934102679Sgibbs		LIST_INSERT_HEAD(free_list, scb, collision_links);
5935102679Sgibbs		TAILQ_INSERT_TAIL(free_tailq, scb, links.tqe);
5936102679Sgibbs	}
5937102679Sgibbs}
5938102679Sgibbs
5939102679Sgibbsstatic void
5940102679Sgibbsahd_rem_col_list(struct ahd_softc *ahd, struct scb *scb)
5941102679Sgibbs{
5942102679Sgibbs	struct	scb_list *free_list;
5943102679Sgibbs	struct	scb_tailq *free_tailq;
5944102679Sgibbs	struct	scb *first_scb;
5945102679Sgibbs	u_int	col_idx;
5946102679Sgibbs
5947102679Sgibbs	scb->flags &= ~SCB_ON_COL_LIST;
5948102679Sgibbs	col_idx = AHD_GET_SCB_COL_IDX(ahd, scb);
5949102679Sgibbs	free_list = &ahd->scb_data.free_scb_lists[col_idx];
5950102679Sgibbs	free_tailq = &ahd->scb_data.free_scbs;
5951102679Sgibbs	first_scb = LIST_FIRST(free_list);
5952102679Sgibbs	if (first_scb == scb) {
5953102679Sgibbs		struct scb *next_scb;
5954102679Sgibbs
5955102679Sgibbs		/*
5956102679Sgibbs		 * Maintain order in the collision free
5957102679Sgibbs		 * lists for fairness if this device has
5958102679Sgibbs		 * other colliding tags active.
5959102679Sgibbs		 */
5960102679Sgibbs		next_scb = LIST_NEXT(scb, collision_links);
5961102679Sgibbs		if (next_scb != NULL) {
5962102679Sgibbs			TAILQ_INSERT_AFTER(free_tailq, scb,
5963102679Sgibbs					   next_scb, links.tqe);
5964102679Sgibbs		}
5965102679Sgibbs		TAILQ_REMOVE(free_tailq, scb, links.tqe);
5966102679Sgibbs	}
5967102679Sgibbs	LIST_REMOVE(scb, collision_links);
5968102679Sgibbs}
5969102679Sgibbs
5970102679Sgibbs/*
5971102679Sgibbs * Get a free scb. If there are none, see if we can allocate a new SCB.
5972102679Sgibbs */
5973102679Sgibbsstruct scb *
5974102679Sgibbsahd_get_scb(struct ahd_softc *ahd, u_int col_idx)
5975102679Sgibbs{
5976102679Sgibbs	struct scb *scb;
5977102679Sgibbs	int tries;
5978102679Sgibbs
5979102679Sgibbs	tries = 0;
5980102679Sgibbslook_again:
5981102679Sgibbs	TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
5982102679Sgibbs		if (AHD_GET_SCB_COL_IDX(ahd, scb) != col_idx) {
5983102679Sgibbs			ahd_rem_col_list(ahd, scb);
5984102679Sgibbs			goto found;
5985102679Sgibbs		}
5986102679Sgibbs	}
5987102679Sgibbs	if ((scb = LIST_FIRST(&ahd->scb_data.any_dev_free_scb_list)) == NULL) {
5988102679Sgibbs
5989102679Sgibbs		if (tries++ != 0)
5990102679Sgibbs			return (NULL);
5991168873Sscottl		if (ahd_alloc_scbs(ahd) == 0)
5992168873Sscottl			return (NULL);
5993102679Sgibbs		goto look_again;
5994102679Sgibbs	}
5995102679Sgibbs	LIST_REMOVE(scb, links.le);
5996102679Sgibbs	if (col_idx != AHD_NEVER_COL_IDX
5997102679Sgibbs	 && (scb->col_scb != NULL)
5998102679Sgibbs	 && (scb->col_scb->flags & SCB_ACTIVE) == 0) {
5999102679Sgibbs		LIST_REMOVE(scb->col_scb, links.le);
6000102679Sgibbs		ahd_add_col_list(ahd, scb->col_scb, col_idx);
6001102679Sgibbs	}
6002102679Sgibbsfound:
6003102679Sgibbs	scb->flags |= SCB_ACTIVE;
6004102679Sgibbs	return (scb);
6005102679Sgibbs}
6006102679Sgibbs
6007102679Sgibbs/*
6008102679Sgibbs * Return an SCB resource to the free list.
6009102679Sgibbs */
601097883Sgibbsvoid
6011102679Sgibbsahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
6012102679Sgibbs{
6013102679Sgibbs
6014102679Sgibbs	/* Clean up for the next user */
6015102679Sgibbs	scb->flags = SCB_FLAG_NONE;
6016102679Sgibbs	scb->hscb->control = 0;
6017114623Sgibbs	ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
6018102679Sgibbs
6019102679Sgibbs	if (scb->col_scb == NULL) {
6020102679Sgibbs
6021102679Sgibbs		/*
6022102679Sgibbs		 * No collision possible.  Just free normally.
6023102679Sgibbs		 */
6024102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6025102679Sgibbs				 scb, links.le);
6026102679Sgibbs	} else if ((scb->col_scb->flags & SCB_ON_COL_LIST) != 0) {
6027102679Sgibbs
6028102679Sgibbs		/*
6029102679Sgibbs		 * The SCB we might have collided with is on
6030102679Sgibbs		 * a free collision list.  Put both SCBs on
6031102679Sgibbs		 * the generic list.
6032102679Sgibbs		 */
6033102679Sgibbs		ahd_rem_col_list(ahd, scb->col_scb);
6034102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6035102679Sgibbs				 scb, links.le);
6036102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6037102679Sgibbs				 scb->col_scb, links.le);
6038102679Sgibbs	} else if ((scb->col_scb->flags
6039102679Sgibbs		  & (SCB_PACKETIZED|SCB_ACTIVE)) == SCB_ACTIVE
6040102679Sgibbs		&& (scb->col_scb->hscb->control & TAG_ENB) != 0) {
6041102679Sgibbs
6042102679Sgibbs		/*
6043102679Sgibbs		 * The SCB we might collide with on the next allocation
6044102679Sgibbs		 * is still active in a non-packetized, tagged, context.
6045102679Sgibbs		 * Put us on the SCB collision list.
6046102679Sgibbs		 */
6047102679Sgibbs		ahd_add_col_list(ahd, scb,
6048102679Sgibbs				 AHD_GET_SCB_COL_IDX(ahd, scb->col_scb));
6049102679Sgibbs	} else {
6050102679Sgibbs		/*
6051102679Sgibbs		 * The SCB we might collide with on the next allocation
6052102679Sgibbs		 * is either active in a packetized context, or free.
6053102679Sgibbs		 * Since we can't collide, put this SCB on the generic
6054102679Sgibbs		 * free list.
6055102679Sgibbs		 */
6056102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6057102679Sgibbs				 scb, links.le);
6058102679Sgibbs	}
6059102679Sgibbs
6060123579Sgibbs	aic_platform_scb_free(ahd, scb);
6061102679Sgibbs}
6062102679Sgibbs
6063168873Sscottlint
606497883Sgibbsahd_alloc_scbs(struct ahd_softc *ahd)
606597883Sgibbs{
606697883Sgibbs	struct scb_data *scb_data;
606797883Sgibbs	struct scb	*next_scb;
606897883Sgibbs	struct hardware_scb *hscb;
606997883Sgibbs	struct map_node *hscb_map;
607097883Sgibbs	struct map_node *sg_map;
607197883Sgibbs	struct map_node *sense_map;
607297883Sgibbs	uint8_t		*segs;
607397883Sgibbs	uint8_t		*sense_data;
607497883Sgibbs	bus_addr_t	 hscb_busaddr;
607597883Sgibbs	bus_addr_t	 sg_busaddr;
607697883Sgibbs	bus_addr_t	 sense_busaddr;
607797883Sgibbs	int		 newcount;
607897883Sgibbs	int		 i;
607997883Sgibbs
608097883Sgibbs	scb_data = &ahd->scb_data;
608197883Sgibbs	if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC)
608297883Sgibbs		/* Can't allocate any more */
6083168873Sscottl		return (0);
608497883Sgibbs
608597883Sgibbs	if (scb_data->scbs_left != 0) {
608697883Sgibbs		int offset;
608797883Sgibbs
608897883Sgibbs		offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left;
608997883Sgibbs		hscb_map = SLIST_FIRST(&scb_data->hscb_maps);
609097883Sgibbs		hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset];
6091123579Sgibbs		hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb));
609297883Sgibbs	} else {
609397883Sgibbs		hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT);
609497883Sgibbs
609597883Sgibbs		if (hscb_map == NULL)
6096168873Sscottl			return (0);
609797883Sgibbs
609897883Sgibbs		/* Allocate the next batch of hardware SCBs */
6099123579Sgibbs		if (aic_dmamem_alloc(ahd, scb_data->hscb_dmat,
610097883Sgibbs				     (void **)&hscb_map->vaddr,
6101219577Smarius				     BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
6102219577Smarius				     &hscb_map->dmamap) != 0) {
610397883Sgibbs			free(hscb_map, M_DEVBUF);
6104168873Sscottl			return (0);
610597883Sgibbs		}
610697883Sgibbs
610797883Sgibbs		SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links);
610897883Sgibbs
6109123579Sgibbs		aic_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap,
611097883Sgibbs				hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
6111123579Sgibbs				&hscb_map->busaddr, /*flags*/0);
611297883Sgibbs
611397883Sgibbs		hscb = (struct hardware_scb *)hscb_map->vaddr;
6114123579Sgibbs		hscb_busaddr = hscb_map->busaddr;
611597883Sgibbs		scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb);
611697883Sgibbs	}
611797883Sgibbs
611897883Sgibbs	if (scb_data->sgs_left != 0) {
611997883Sgibbs		int offset;
612097883Sgibbs
6121114623Sgibbs		offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd))
6122114623Sgibbs		       - scb_data->sgs_left) * ahd_sglist_size(ahd);
612397883Sgibbs		sg_map = SLIST_FIRST(&scb_data->sg_maps);
612497883Sgibbs		segs = sg_map->vaddr + offset;
6125123579Sgibbs		sg_busaddr = sg_map->busaddr + offset;
612697883Sgibbs	} else {
612797883Sgibbs		sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
612897883Sgibbs
612997883Sgibbs		if (sg_map == NULL)
6130168873Sscottl			return (0);
613197883Sgibbs
613297883Sgibbs		/* Allocate the next batch of S/G lists */
6133123579Sgibbs		if (aic_dmamem_alloc(ahd, scb_data->sg_dmat,
613497883Sgibbs				     (void **)&sg_map->vaddr,
6135219577Smarius				     BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
6136219577Smarius				     &sg_map->dmamap) != 0) {
613797883Sgibbs			free(sg_map, M_DEVBUF);
6138168873Sscottl			return (0);
613997883Sgibbs		}
614097883Sgibbs
614197883Sgibbs		SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
614297883Sgibbs
6143123579Sgibbs		aic_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap,
614497883Sgibbs				sg_map->vaddr, ahd_sglist_allocsize(ahd),
6145123579Sgibbs				ahd_dmamap_cb, &sg_map->busaddr, /*flags*/0);
614697883Sgibbs
614797883Sgibbs		segs = sg_map->vaddr;
6148123579Sgibbs		sg_busaddr = sg_map->busaddr;
614997883Sgibbs		scb_data->sgs_left =
615097883Sgibbs		    ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd);
615197883Sgibbs#ifdef AHD_DEBUG
615297883Sgibbs		if (ahd_debug & AHD_SHOW_MEMORY)
615397883Sgibbs			printf("Mapped SG data\n");
615497883Sgibbs#endif
615597883Sgibbs	}
615697883Sgibbs
615797883Sgibbs	if (scb_data->sense_left != 0) {
615897883Sgibbs		int offset;
615997883Sgibbs
616097883Sgibbs		offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left);
616197883Sgibbs		sense_map = SLIST_FIRST(&scb_data->sense_maps);
616297883Sgibbs		sense_data = sense_map->vaddr + offset;
6163123579Sgibbs		sense_busaddr = sense_map->busaddr + offset;
616497883Sgibbs	} else {
616597883Sgibbs		sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT);
616697883Sgibbs
616797883Sgibbs		if (sense_map == NULL)
6168168873Sscottl			return (0);
616997883Sgibbs
617097883Sgibbs		/* Allocate the next batch of sense buffers */
6171123579Sgibbs		if (aic_dmamem_alloc(ahd, scb_data->sense_dmat,
617297883Sgibbs				     (void **)&sense_map->vaddr,
617397883Sgibbs				     BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) {
617497883Sgibbs			free(sense_map, M_DEVBUF);
6175168873Sscottl			return (0);
617697883Sgibbs		}
617797883Sgibbs
617897883Sgibbs		SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links);
617997883Sgibbs
6180123579Sgibbs		aic_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap,
618197883Sgibbs				sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
6182123579Sgibbs				&sense_map->busaddr, /*flags*/0);
618397883Sgibbs
618497883Sgibbs		sense_data = sense_map->vaddr;
6185123579Sgibbs		sense_busaddr = sense_map->busaddr;
618697883Sgibbs		scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE;
618797883Sgibbs#ifdef AHD_DEBUG
618897883Sgibbs		if (ahd_debug & AHD_SHOW_MEMORY)
618997883Sgibbs			printf("Mapped sense data\n");
619097883Sgibbs#endif
619197883Sgibbs	}
619297883Sgibbs
619397883Sgibbs	newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
619497883Sgibbs	newcount = MIN(newcount, scb_data->sgs_left);
619597883Sgibbs	newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
619697883Sgibbs	scb_data->sense_left -= newcount;
619797883Sgibbs	scb_data->scbs_left -= newcount;
619897883Sgibbs	scb_data->sgs_left -= newcount;
619997883Sgibbs	for (i = 0; i < newcount; i++) {
6200125448Sgibbs		struct scb_platform_data *pdata;
6201102679Sgibbs		u_int col_tag;
620297883Sgibbs#ifndef __linux__
620397883Sgibbs		int error;
620497883Sgibbs#endif
6205125448Sgibbs
620697883Sgibbs		next_scb = (struct scb *)malloc(sizeof(*next_scb),
620797883Sgibbs						M_DEVBUF, M_NOWAIT);
620897883Sgibbs		if (next_scb == NULL)
620997883Sgibbs			break;
621097883Sgibbs
621197883Sgibbs		pdata = (struct scb_platform_data *)malloc(sizeof(*pdata),
621297883Sgibbs							   M_DEVBUF, M_NOWAIT);
621397883Sgibbs		if (pdata == NULL) {
621497883Sgibbs			free(next_scb, M_DEVBUF);
621597883Sgibbs			break;
621697883Sgibbs		}
621797883Sgibbs		next_scb->platform_data = pdata;
621897883Sgibbs		next_scb->hscb_map = hscb_map;
621997883Sgibbs		next_scb->sg_map = sg_map;
622097883Sgibbs		next_scb->sense_map = sense_map;
622197883Sgibbs		next_scb->sg_list = segs;
622297883Sgibbs		next_scb->sense_data = sense_data;
622397883Sgibbs		next_scb->sense_busaddr = sense_busaddr;
6224115331Sgibbs		memset(hscb, 0, sizeof(*hscb));
622597883Sgibbs		next_scb->hscb = hscb;
6226123579Sgibbs		hscb->hscb_busaddr = aic_htole32(hscb_busaddr);
622797883Sgibbs
622897883Sgibbs		/*
622997883Sgibbs		 * The sequencer always starts with the second entry.
623097883Sgibbs		 * The first entry is embedded in the scb.
623197883Sgibbs		 */
623297883Sgibbs		next_scb->sg_list_busaddr = sg_busaddr;
623397883Sgibbs		if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
623497883Sgibbs			next_scb->sg_list_busaddr
623597883Sgibbs			    += sizeof(struct ahd_dma64_seg);
623697883Sgibbs		else
623797883Sgibbs			next_scb->sg_list_busaddr += sizeof(struct ahd_dma_seg);
623897883Sgibbs		next_scb->ahd_softc = ahd;
6239102679Sgibbs		next_scb->flags = SCB_FLAG_NONE;
624097883Sgibbs#ifndef __linux__
6241123579Sgibbs		error = aic_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0,
624297883Sgibbs					  &next_scb->dmamap);
624397883Sgibbs		if (error != 0) {
624497883Sgibbs			free(next_scb, M_DEVBUF);
624597883Sgibbs			free(pdata, M_DEVBUF);
624697883Sgibbs			break;
624797883Sgibbs		}
624897883Sgibbs#endif
6249123579Sgibbs		next_scb->hscb->tag = aic_htole16(scb_data->numscbs);
6250102679Sgibbs		col_tag = scb_data->numscbs ^ 0x100;
6251102679Sgibbs		next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);
6252102679Sgibbs		if (next_scb->col_scb != NULL)
6253102679Sgibbs			next_scb->col_scb->col_scb = next_scb;
6254168807Sscottl		aic_timer_init(&next_scb->io_timer);
6255102679Sgibbs		ahd_free_scb(ahd, next_scb);
625697883Sgibbs		hscb++;
625797883Sgibbs		hscb_busaddr += sizeof(*hscb);
625897883Sgibbs		segs += ahd_sglist_size(ahd);
625997883Sgibbs		sg_busaddr += ahd_sglist_size(ahd);
626097883Sgibbs		sense_data += AHD_SENSE_BUFSIZE;
626197883Sgibbs		sense_busaddr += AHD_SENSE_BUFSIZE;
626297883Sgibbs		scb_data->numscbs++;
626397883Sgibbs	}
6264168873Sscottl	return (i);
626597883Sgibbs}
626697883Sgibbs
626797883Sgibbsvoid
626897883Sgibbsahd_controller_info(struct ahd_softc *ahd, char *buf)
626997883Sgibbs{
627097883Sgibbs	const char *speed;
627197883Sgibbs	const char *type;
627297883Sgibbs	int len;
627397883Sgibbs
627497883Sgibbs	len = sprintf(buf, "%s: ", ahd_chip_names[ahd->chip & AHD_CHIPID_MASK]);
627597883Sgibbs	buf += len;
627697883Sgibbs
627797883Sgibbs	speed = "Ultra320 ";
627897883Sgibbs	if ((ahd->features & AHD_WIDE) != 0) {
6279102679Sgibbs		type = "Wide ";
628097883Sgibbs	} else {
6281102679Sgibbs		type = "Single ";
628297883Sgibbs	}
628397883Sgibbs	len = sprintf(buf, "%s%sChannel %c, SCSI Id=%d, ",
628497883Sgibbs		      speed, type, ahd->channel, ahd->our_id);
628597883Sgibbs	buf += len;
628697883Sgibbs
628797883Sgibbs	sprintf(buf, "%s, %d SCBs", ahd->bus_description,
628897883Sgibbs		ahd->scb_data.maxhscbs);
628997883Sgibbs}
629097883Sgibbs
629197883Sgibbsstatic const char *channel_strings[] = {
629297883Sgibbs	"Primary Low",
629397883Sgibbs	"Primary High",
629497883Sgibbs	"Secondary Low",
629597883Sgibbs	"Secondary High"
629697883Sgibbs};
629797883Sgibbs
629897883Sgibbsstatic const char *termstat_strings[] = {
629997883Sgibbs	"Terminated Correctly",
630097883Sgibbs	"Over Terminated",
630197883Sgibbs	"Under Terminated",
630297883Sgibbs	"Not Configured"
630397883Sgibbs};
630497883Sgibbs
630597883Sgibbs/*
630697883Sgibbs * Start the board, ready for normal operation
630797883Sgibbs */
630897883Sgibbsint
630997883Sgibbsahd_init(struct ahd_softc *ahd)
631097883Sgibbs{
6311102679Sgibbs	uint8_t		*next_vaddr;
6312102679Sgibbs	bus_addr_t	 next_baddr;
6313102679Sgibbs	size_t		 driver_data_size;
6314102679Sgibbs	int		 i;
6315102679Sgibbs	int		 error;
6316102679Sgibbs	u_int		 warn_user;
6317102679Sgibbs	uint8_t		 current_sensing;
6318102679Sgibbs	uint8_t		 fstat;
631997883Sgibbs
632097883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
632197883Sgibbs
6322107441Sscottl	ahd->stack_size = ahd_probe_stack_size(ahd);
6323107441Sscottl	ahd->saved_stack = malloc(ahd->stack_size * sizeof(uint16_t),
6324107441Sscottl				  M_DEVBUF, M_NOWAIT);
6325107441Sscottl	if (ahd->saved_stack == NULL)
6326107441Sscottl		return (ENOMEM);
6327107441Sscottl
632897883Sgibbs	/*
632997883Sgibbs	 * Verify that the compiler hasn't over-agressively
633097883Sgibbs	 * padded important structures.
633197883Sgibbs	 */
633297883Sgibbs	if (sizeof(struct hardware_scb) != 64)
633397883Sgibbs		panic("Hardware SCB size is incorrect");
633497883Sgibbs
633597883Sgibbs#ifdef AHD_DEBUG
633697883Sgibbs	if ((ahd_debug & AHD_DEBUG_SEQUENCER) != 0)
633797883Sgibbs		ahd->flags |= AHD_SEQUENCER_DEBUG;
633897883Sgibbs#endif
633997883Sgibbs
634097883Sgibbs	/*
634197883Sgibbs	 * Default to allowing initiator operations.
634297883Sgibbs	 */
634397883Sgibbs	ahd->flags |= AHD_INITIATORROLE;
634497883Sgibbs
634597883Sgibbs	/*
634697883Sgibbs	 * Only allow target mode features if this unit has them enabled.
634797883Sgibbs	 */
634897883Sgibbs	if ((AHD_TMODE_ENABLE & (0x1 << ahd->unit)) == 0)
634997883Sgibbs		ahd->features &= ~AHD_TARGETMODE;
635097883Sgibbs
635197883Sgibbs#ifndef __linux__
635297883Sgibbs	/* DMA tag for mapping buffers into device visible space. */
6353123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
635497883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
6355114623Sgibbs			       /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING
6356114623Sgibbs					? (bus_addr_t)0x7FFFFFFFFFULL
6357114623Sgibbs					: BUS_SPACE_MAXADDR_32BIT,
635897883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
635997883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
6360108479Sscottl			       /*maxsize*/(AHD_NSEG - 1) * PAGE_SIZE,
6361108479Sscottl			       /*nsegments*/AHD_NSEG,
636297883Sgibbs			       /*maxsegsz*/AHD_MAXTRANSFER_SIZE,
636397883Sgibbs			       /*flags*/BUS_DMA_ALLOCNOW,
636497883Sgibbs			       &ahd->buffer_dmat) != 0) {
636597883Sgibbs		return (ENOMEM);
636697883Sgibbs	}
636797883Sgibbs#endif
636897883Sgibbs
636997883Sgibbs	ahd->init_level++;
637097883Sgibbs
637197883Sgibbs	/*
637297883Sgibbs	 * DMA tag for our command fifos and other data in system memory
637397883Sgibbs	 * the card's sequencer must be able to access.  For initiator
637497883Sgibbs	 * roles, we need to allocate space for the qoutfifo.  When providing
637597883Sgibbs	 * for the target mode role, we must additionally provide space for
637697883Sgibbs	 * the incoming target command fifo.
637797883Sgibbs	 */
6378129134Sgibbs	driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
6379129134Sgibbs			 + sizeof(struct hardware_scb);
638097883Sgibbs	if ((ahd->features & AHD_TARGETMODE) != 0)
638197883Sgibbs		driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
638297883Sgibbs	if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0)
638397883Sgibbs		driver_data_size += PKT_OVERRUN_BUFSIZE;
6384123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
638597883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
638697883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
638797883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
638897883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
638997883Sgibbs			       driver_data_size,
639097883Sgibbs			       /*nsegments*/1,
639197883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
639297883Sgibbs			       /*flags*/0, &ahd->shared_data_dmat) != 0) {
639397883Sgibbs		return (ENOMEM);
639497883Sgibbs	}
639597883Sgibbs
639697883Sgibbs	ahd->init_level++;
639797883Sgibbs
639897883Sgibbs	/* Allocation of driver data */
6399123579Sgibbs	if (aic_dmamem_alloc(ahd, ahd->shared_data_dmat,
6400123579Sgibbs			     (void **)&ahd->shared_data_map.vaddr,
6401219577Smarius			     BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
6402123579Sgibbs			     &ahd->shared_data_map.dmamap) != 0) {
640397883Sgibbs		return (ENOMEM);
640497883Sgibbs	}
640597883Sgibbs
640697883Sgibbs	ahd->init_level++;
640797883Sgibbs
640897883Sgibbs	/* And permanently map it in */
6409123579Sgibbs	aic_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
6410123579Sgibbs			ahd->shared_data_map.vaddr, driver_data_size,
6411123579Sgibbs			ahd_dmamap_cb, &ahd->shared_data_map.busaddr,
6412123579Sgibbs			/*flags*/0);
6413125448Sgibbs	ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
6414102679Sgibbs	next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
6415123579Sgibbs	next_baddr = ahd->shared_data_map.busaddr
6416125448Sgibbs		   + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
641797883Sgibbs	if ((ahd->features & AHD_TARGETMODE) != 0) {
6418102679Sgibbs		ahd->targetcmds = (struct target_cmd *)next_vaddr;
6419102679Sgibbs		next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
6420102679Sgibbs		next_baddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
642197883Sgibbs	}
642297883Sgibbs
6423102679Sgibbs	if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
6424102679Sgibbs		ahd->overrun_buf = next_vaddr;
6425102679Sgibbs		next_vaddr += PKT_OVERRUN_BUFSIZE;
6426102679Sgibbs		next_baddr += PKT_OVERRUN_BUFSIZE;
6427102679Sgibbs	}
642897883Sgibbs
6429129134Sgibbs	/*
6430129134Sgibbs	 * We need one SCB to serve as the "next SCB".  Since the
6431129134Sgibbs	 * tag identifier in this SCB will never be used, there is
6432129134Sgibbs	 * no point in using a valid HSCB tag from an SCB pulled from
6433129134Sgibbs	 * the standard free pool.  So, we allocate this "sentinel"
6434129134Sgibbs	 * specially from the DMA safe memory chunk used for the QOUTFIFO.
6435129134Sgibbs	 */
6436129134Sgibbs	ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
6437129134Sgibbs	ahd->next_queued_hscb_map = &ahd->shared_data_map;
6438129134Sgibbs	ahd->next_queued_hscb->hscb_busaddr = aic_htole32(next_baddr);
6439129134Sgibbs
644097883Sgibbs	ahd->init_level++;
644197883Sgibbs
644297883Sgibbs	/* Allocate SCB data now that buffer_dmat is initialized */
644397883Sgibbs	if (ahd_init_scbdata(ahd) != 0)
644497883Sgibbs		return (ENOMEM);
644597883Sgibbs
644697883Sgibbs	if ((ahd->flags & AHD_INITIATORROLE) == 0)
644797883Sgibbs		ahd->flags &= ~AHD_RESET_BUS_A;
644897883Sgibbs
6449107441Sscottl	/*
6450107441Sscottl	 * Before committing these settings to the chip, give
6451107441Sscottl	 * the OSM one last chance to modify our configuration.
6452107441Sscottl	 */
6453107441Sscottl	ahd_platform_init(ahd);
6454107441Sscottl
6455107441Sscottl	/* Bring up the chip. */
645697883Sgibbs	ahd_chip_init(ahd);
645797883Sgibbs
645897883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
645997883Sgibbs
646097883Sgibbs	if ((ahd->flags & AHD_CURRENT_SENSING) == 0)
646197883Sgibbs		goto init_done;
646297883Sgibbs
646397883Sgibbs	/*
646497883Sgibbs	 * Verify termination based on current draw and
646597883Sgibbs	 * warn user if the bus is over/under terminated.
646697883Sgibbs	 */
646797883Sgibbs	error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL,
646897883Sgibbs				   CURSENSE_ENB);
646997883Sgibbs	if (error != 0) {
647097883Sgibbs		printf("%s: current sensing timeout 1\n", ahd_name(ahd));
647197883Sgibbs		goto init_done;
647297883Sgibbs	}
647397883Sgibbs	for (i = 20, fstat = FLX_FSTAT_BUSY;
647497883Sgibbs	     (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) {
647597883Sgibbs		error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat);
647697883Sgibbs		if (error != 0) {
647797883Sgibbs			printf("%s: current sensing timeout 2\n",
647897883Sgibbs			       ahd_name(ahd));
647997883Sgibbs			goto init_done;
648097883Sgibbs		}
648197883Sgibbs	}
648297883Sgibbs	if (i == 0) {
648397883Sgibbs		printf("%s: Timedout during current-sensing test\n",
648497883Sgibbs		       ahd_name(ahd));
648597883Sgibbs		goto init_done;
648697883Sgibbs	}
648797883Sgibbs
648897883Sgibbs	/* Latch Current Sensing status. */
648997883Sgibbs	error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, &current_sensing);
649097883Sgibbs	if (error != 0) {
649197883Sgibbs		printf("%s: current sensing timeout 3\n", ahd_name(ahd));
649297883Sgibbs		goto init_done;
649397883Sgibbs	}
649497883Sgibbs
649597883Sgibbs	/* Diable current sensing. */
649697883Sgibbs	ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
649797883Sgibbs
649897883Sgibbs#ifdef AHD_DEBUG
649997883Sgibbs	if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) {
650097883Sgibbs		printf("%s: current_sensing == 0x%x\n",
650197883Sgibbs		       ahd_name(ahd), current_sensing);
650297883Sgibbs	}
650397883Sgibbs#endif
650497883Sgibbs	warn_user = 0;
650597883Sgibbs	for (i = 0; i < 4; i++, current_sensing >>= FLX_CSTAT_SHIFT) {
650697883Sgibbs		u_int term_stat;
650797883Sgibbs
650897883Sgibbs		term_stat = (current_sensing & FLX_CSTAT_MASK);
650997883Sgibbs		switch (term_stat) {
651097883Sgibbs		case FLX_CSTAT_OVER:
651197883Sgibbs		case FLX_CSTAT_UNDER:
651297883Sgibbs			warn_user++;
651397883Sgibbs		case FLX_CSTAT_INVALID:
651497883Sgibbs		case FLX_CSTAT_OKAY:
651597883Sgibbs			if (warn_user == 0 && bootverbose == 0)
651697883Sgibbs				break;
651797883Sgibbs			printf("%s: %s Channel %s\n", ahd_name(ahd),
651897883Sgibbs			       channel_strings[i], termstat_strings[term_stat]);
651997883Sgibbs			break;
652097883Sgibbs		}
652197883Sgibbs	}
652297883Sgibbs	if (warn_user) {
652397883Sgibbs		printf("%s: WARNING. Termination is not configured correctly.\n"
652497883Sgibbs		       "%s: WARNING. SCSI bus operations may FAIL.\n",
652597883Sgibbs		       ahd_name(ahd), ahd_name(ahd));
6526199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
652797883Sgibbs	}
652897883Sgibbsinit_done:
652997883Sgibbs	ahd_restart(ahd);
6530137870Sgibbs	aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
6531109588Sgibbs			ahd_stat_timer, ahd);
653297883Sgibbs	return (0);
653397883Sgibbs}
653497883Sgibbs
653597883Sgibbs/*
653697883Sgibbs * (Re)initialize chip state after a chip reset.
653797883Sgibbs */
653897883Sgibbsstatic void
653997883Sgibbsahd_chip_init(struct ahd_softc *ahd)
654097883Sgibbs{
654197883Sgibbs	uint32_t busaddr;
654297883Sgibbs	u_int	 sxfrctl1;
654397883Sgibbs	u_int	 scsiseq_template;
6544102679Sgibbs	u_int	 wait;
654597883Sgibbs	u_int	 i;
654697883Sgibbs	u_int	 target;
654797883Sgibbs
654897883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
654997883Sgibbs	/*
655097883Sgibbs	 * Take the LED out of diagnostic mode
655197883Sgibbs	 */
655297883Sgibbs	ahd_outb(ahd, SBLKCTL, ahd_inb(ahd, SBLKCTL) & ~(DIAGLEDEN|DIAGLEDON));
655397883Sgibbs
6554109588Sgibbs	/*
6555109588Sgibbs	 * Return HS_MAILBOX to its default value.
6556109588Sgibbs	 */
6557109588Sgibbs	ahd->hs_mailbox = 0;
6558109588Sgibbs	ahd_outb(ahd, HS_MAILBOX, 0);
6559109588Sgibbs
656097883Sgibbs	/* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1. */
656197883Sgibbs	ahd_outb(ahd, IOWNID, ahd->our_id);
656297883Sgibbs	ahd_outb(ahd, TOWNID, ahd->our_id);
656397883Sgibbs	sxfrctl1 = (ahd->flags & AHD_TERM_ENB_A) != 0 ? STPWEN : 0;
656497883Sgibbs	sxfrctl1 |= (ahd->flags & AHD_SPCHK_ENB_A) != 0 ? ENSPCHK : 0;
656597883Sgibbs	if ((ahd->bugs & AHD_LONG_SETIMO_BUG)
656697883Sgibbs	 && (ahd->seltime != STIMESEL_MIN)) {
656797883Sgibbs		/*
656897883Sgibbs		 * The selection timer duration is twice as long
656997883Sgibbs		 * as it should be.  Halve it by adding "1" to
657097883Sgibbs		 * the user specified setting.
657197883Sgibbs		 */
657297883Sgibbs		sxfrctl1 |= ahd->seltime + STIMESEL_BUG_ADJ;
657397883Sgibbs	} else {
657497883Sgibbs		sxfrctl1 |= ahd->seltime;
657597883Sgibbs	}
657697883Sgibbs
657797883Sgibbs	ahd_outb(ahd, SXFRCTL0, DFON);
657897883Sgibbs	ahd_outb(ahd, SXFRCTL1, sxfrctl1|ahd->seltime|ENSTIMER|ACTNEGEN);
657997883Sgibbs	ahd_outb(ahd, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
658097883Sgibbs
6581102679Sgibbs	/*
6582102679Sgibbs	 * Now that termination is set, wait for up
6583102679Sgibbs	 * to 500ms for our transceivers to settle.  If
6584102679Sgibbs	 * the adapter does not have a cable attached,
6585114623Sgibbs	 * the transceivers may never settle, so don't
6586102679Sgibbs	 * complain if we fail here.
6587102679Sgibbs	 */
6588102679Sgibbs	for (wait = 10000;
6589102679Sgibbs	     (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
6590102679Sgibbs	     wait--)
6591123579Sgibbs		aic_delay(100);
6592102679Sgibbs
6593102679Sgibbs	/* Clear any false bus resets due to the transceivers settling */
6594102679Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
6595102679Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
6596102679Sgibbs
659797883Sgibbs	/* Initialize mode specific S/G state. */
659897883Sgibbs	for (i = 0; i < 2; i++) {
659997883Sgibbs		ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
660097883Sgibbs		ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
660197883Sgibbs		ahd_outb(ahd, SG_STATE, 0);
660297883Sgibbs		ahd_outb(ahd, CLRSEQINTSRC, 0xFF);
660397883Sgibbs		ahd_outb(ahd, SEQIMODE,
660497883Sgibbs			 ENSAVEPTRS|ENCFG4DATA|ENCFG4ISTAT
660597883Sgibbs			|ENCFG4TSTAT|ENCFG4ICMD|ENCFG4TCMD);
660697883Sgibbs	}
660797883Sgibbs
660897883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
660997883Sgibbs	ahd_outb(ahd, DSCOMMAND0, ahd_inb(ahd, DSCOMMAND0)|MPARCKEN|CACHETHEN);
661097883Sgibbs	ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75);
661197883Sgibbs	ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN);
661297883Sgibbs	ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR);
6613104023Sgibbs	if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
6614104023Sgibbs		ahd_outb(ahd, OPTIONMODE, AUTOACKEN|AUTO_MSGOUT_DE);
6615104023Sgibbs	} else {
6616104023Sgibbs		ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);
6617104023Sgibbs	}
6618111653Sgibbs	ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN|SHVALIDSTDIS);
661997883Sgibbs	if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX)
662097883Sgibbs		/*
662197883Sgibbs		 * Do not issue a target abort when a split completion
662297883Sgibbs		 * error occurs.  Let our PCIX interrupt handler deal
662397883Sgibbs		 * with it instead. H2A4 Razor #625
662497883Sgibbs		 */
662597883Sgibbs		ahd_outb(ahd, PCIXCTL, ahd_inb(ahd, PCIXCTL) | SPLTSTADIS);
662697883Sgibbs
6627107441Sscottl	if ((ahd->bugs & AHD_LQOOVERRUN_BUG) != 0)
6628107441Sscottl		ahd_outb(ahd, LQOSCSCTL, LQONOCHKOVER);
6629107441Sscottl
663097883Sgibbs	/*
663197883Sgibbs	 * Tweak IOCELL settings.
663297883Sgibbs	 */
6633107441Sscottl	if ((ahd->flags & AHD_HP_BOARD) != 0) {
663497883Sgibbs		for (i = 0; i < NUMDSPS; i++) {
663597883Sgibbs			ahd_outb(ahd, DSPSELECT, i);
6636107441Sscottl			ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_HP_DEFAULT);
663797883Sgibbs		}
6638104023Sgibbs#ifdef AHD_DEBUG
6639104023Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
6640104023Sgibbs			printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd),
6641107441Sscottl			       WRTBIASCTL_HP_DEFAULT);
6642104023Sgibbs#endif
664397883Sgibbs	}
664497883Sgibbs	ahd_setup_iocell_workaround(ahd);
664597883Sgibbs
664697883Sgibbs	/*
664797883Sgibbs	 * Enable LQI Manager interrupts.
664897883Sgibbs	 */
664997883Sgibbs	ahd_outb(ahd, LQIMODE1, ENLQIPHASE_LQ|ENLQIPHASE_NLQ|ENLIQABORT
665097883Sgibbs			      | ENLQICRCI_LQ|ENLQICRCI_NLQ|ENLQIBADLQI
665197883Sgibbs			      | ENLQIOVERI_LQ|ENLQIOVERI_NLQ);
665297883Sgibbs	ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC);
665397883Sgibbs	/*
6654133122Sgibbs	 * We choose to have the sequencer catch LQOPHCHGINPKT errors
6655133122Sgibbs	 * manually for the command phase at the start of a packetized
6656133122Sgibbs	 * selection case.  ENLQOBUSFREE should be made redundant by
6657133122Sgibbs	 * the BUSFREE interrupt, but it seems that some LQOBUSFREE
6658133122Sgibbs	 * events fail to assert the BUSFREE interrupt so we must
6659133122Sgibbs	 * also enable LQOBUSFREE interrupts.
666097883Sgibbs	 */
6661133122Sgibbs	ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE);
666297883Sgibbs
666397883Sgibbs	/*
6664109588Sgibbs	 * Setup sequencer interrupt handlers.
666597883Sgibbs	 */
666697883Sgibbs	ahd_outw(ahd, INTVEC1_ADDR, ahd_resolve_seqaddr(ahd, LABEL_seq_isr));
6667109588Sgibbs	ahd_outw(ahd, INTVEC2_ADDR, ahd_resolve_seqaddr(ahd, LABEL_timer_isr));
666897883Sgibbs
666997883Sgibbs	/*
667097883Sgibbs	 * Setup SCB Offset registers.
667197883Sgibbs	 */
6672102679Sgibbs	if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
6673102679Sgibbs		ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb,
6674102679Sgibbs			 pkt_long_lun));
6675102679Sgibbs	} else {
6676102679Sgibbs		ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun));
6677102679Sgibbs	}
667897883Sgibbs	ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len));
6679104023Sgibbs	ahd_outb(ahd, ATTRPTR, offsetof(struct hardware_scb, task_attribute));
668097883Sgibbs	ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management));
668197883Sgibbs	ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb,
668297883Sgibbs				       shared_data.idata.cdb));
668397883Sgibbs	ahd_outb(ahd, QNEXTPTR,
668497883Sgibbs		 offsetof(struct hardware_scb, next_hscb_busaddr));
668597883Sgibbs	ahd_outb(ahd, ABRTBITPTR, MK_MESSAGE_BIT_OFFSET);
668697883Sgibbs	ahd_outb(ahd, ABRTBYTEPTR, offsetof(struct hardware_scb, control));
6687102679Sgibbs	if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
6688102679Sgibbs		ahd_outb(ahd, LUNLEN,
6689102679Sgibbs			 sizeof(ahd->next_queued_hscb->pkt_long_lun) - 1);
6690102679Sgibbs	} else {
6691115408Sscottl		ahd_outb(ahd, LUNLEN, LUNLEN_SINGLE_LEVEL_LUN);
6692102679Sgibbs	}
669397883Sgibbs	ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1);
669497883Sgibbs	ahd_outb(ahd, MAXCMD, 0xFF);
669597883Sgibbs	ahd_outb(ahd, SCBAUTOPTR,
669697883Sgibbs		 AUSCBPTR_EN | offsetof(struct hardware_scb, tag));
669797883Sgibbs
669897883Sgibbs	/* We haven't been enabled for target mode yet. */
669997883Sgibbs	ahd_outb(ahd, MULTARGID, 0);
670097883Sgibbs	ahd_outb(ahd, MULTARGID + 1, 0);
670197883Sgibbs
670297883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
6703107441Sscottl	/* Initialize the negotiation table. */
6704107441Sscottl	if ((ahd->features & AHD_NEW_IOCELL_OPTS) == 0) {
6705107441Sscottl		/*
6706107441Sscottl		 * Clear the spare bytes in the neg table to avoid
6707107441Sscottl		 * spurious parity errors.
6708107441Sscottl		 */
6709107441Sscottl		for (target = 0; target < AHD_NUM_TARGETS; target++) {
6710107441Sscottl			ahd_outb(ahd, NEGOADDR, target);
6711107441Sscottl			ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PER_DEV0);
6712107441Sscottl			for (i = 0; i < AHD_NUM_PER_DEV_ANNEXCOLS; i++)
6713107441Sscottl				ahd_outb(ahd, ANNEXDAT, 0);
6714107441Sscottl		}
6715107441Sscottl	}
671697883Sgibbs	for (target = 0; target < AHD_NUM_TARGETS; target++) {
6717107441Sscottl		struct	 ahd_devinfo devinfo;
6718107441Sscottl		struct	 ahd_initiator_tinfo *tinfo;
6719107441Sscottl		struct	 ahd_tmode_tstate *tstate;
672097883Sgibbs
6721107441Sscottl		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
6722107441Sscottl					    target, &tstate);
6723107441Sscottl		ahd_compile_devinfo(&devinfo, ahd->our_id,
6724107441Sscottl				    target, CAM_LUN_WILDCARD,
6725107441Sscottl				    'A', ROLE_INITIATOR);
6726107441Sscottl		ahd_update_neg_table(ahd, &devinfo, &tinfo->curr);
672797883Sgibbs	}
6728107441Sscottl
672997883Sgibbs	ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR);
6730102679Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
673197883Sgibbs
6732153072Sru#ifdef NEEDS_MORE_TESTING
673397883Sgibbs	/*
673497883Sgibbs	 * Always enable abort on incoming L_Qs if this feature is
673597883Sgibbs	 * supported.  We use this to catch invalid SCB references.
673697883Sgibbs	 */
673797883Sgibbs	if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0)
673897883Sgibbs		ahd_outb(ahd, LQCTL1, ABORTPENDING);
673997883Sgibbs	else
6740116935Sgibbs#endif
674197883Sgibbs		ahd_outb(ahd, LQCTL1, 0);
674297883Sgibbs
674397883Sgibbs	/* All of our queues are empty */
674497883Sgibbs	ahd->qoutfifonext = 0;
6745125448Sgibbs	ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
6746125448Sgibbs	ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
674797883Sgibbs	for (i = 0; i < AHD_QOUT_SIZE; i++)
6748125448Sgibbs		ahd->qoutfifo[i].valid_tag = 0;
674997883Sgibbs	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
675097883Sgibbs
675197883Sgibbs	ahd->qinfifonext = 0;
675297883Sgibbs	for (i = 0; i < AHD_QIN_SIZE; i++)
675397883Sgibbs		ahd->qinfifo[i] = SCB_LIST_NULL;
675497883Sgibbs
675597883Sgibbs	if ((ahd->features & AHD_TARGETMODE) != 0) {
675697883Sgibbs		/* All target command blocks start out invalid. */
675797883Sgibbs		for (i = 0; i < AHD_TMODE_CMDS; i++)
675897883Sgibbs			ahd->targetcmds[i].cmd_valid = 0;
675997883Sgibbs		ahd_sync_tqinfifo(ahd, BUS_DMASYNC_PREREAD);
676097883Sgibbs		ahd->tqinfifonext = 1;
676197883Sgibbs		ahd_outb(ahd, KERNEL_TQINPOS, ahd->tqinfifonext - 1);
676297883Sgibbs		ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
676397883Sgibbs	}
676497883Sgibbs
676597883Sgibbs	/* Initialize Scratch Ram. */
676697883Sgibbs	ahd_outb(ahd, SEQ_FLAGS, 0);
676797883Sgibbs	ahd_outb(ahd, SEQ_FLAGS2, 0);
676897883Sgibbs
676997883Sgibbs	/* We don't have any waiting selections */
677097883Sgibbs	ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL);
677197883Sgibbs	ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL);
6772133122Sgibbs	ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL);
6773133122Sgibbs	ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF);
677497883Sgibbs	for (i = 0; i < AHD_NUM_TARGETS; i++)
677597883Sgibbs		ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL);
677697883Sgibbs
677797883Sgibbs	/*
677897883Sgibbs	 * Nobody is waiting to be DMAed into the QOUTFIFO.
677997883Sgibbs	 */
678097883Sgibbs	ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
678197883Sgibbs	ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
678297883Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
6783125448Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
6784125448Sgibbs	ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
678597883Sgibbs
678697883Sgibbs	/*
678797883Sgibbs	 * The Freeze Count is 0.
678897883Sgibbs	 */
6789125448Sgibbs	ahd->qfreeze_cnt = 0;
679097883Sgibbs	ahd_outw(ahd, QFREEZE_COUNT, 0);
6791125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
679297883Sgibbs
679397883Sgibbs	/*
679497883Sgibbs	 * Tell the sequencer where it can find our arrays in memory.
679597883Sgibbs	 */
6796123579Sgibbs	busaddr = ahd->shared_data_map.busaddr;
6797123579Sgibbs	ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
6798123579Sgibbs	ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
679997883Sgibbs
680097883Sgibbs	/*
680197883Sgibbs	 * Setup the allowed SCSI Sequences based on operational mode.
680297883Sgibbs	 * If we are a target, we'll enable select in operations once
680397883Sgibbs	 * we've had a lun enabled.
680497883Sgibbs	 */
680597883Sgibbs	scsiseq_template = ENAUTOATNP;
680697883Sgibbs	if ((ahd->flags & AHD_INITIATORROLE) != 0)
680797883Sgibbs		scsiseq_template |= ENRSELI;
680897883Sgibbs	ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq_template);
680997883Sgibbs
681097883Sgibbs	/* There are no busy SCBs yet. */
681197883Sgibbs	for (target = 0; target < AHD_NUM_TARGETS; target++) {
681297883Sgibbs		int lun;
681397883Sgibbs
681497883Sgibbs		for (lun = 0; lun < AHD_NUM_LUNS_NONPKT; lun++)
681597883Sgibbs			ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(target, 'A', lun));
681697883Sgibbs	}
681797883Sgibbs
681897883Sgibbs	/*
681997883Sgibbs	 * Initialize the group code to command length table.
682097883Sgibbs	 * Vendor Unique codes are set to 0 so we only capture
682197883Sgibbs	 * the first byte of the cdb.  These can be overridden
682297883Sgibbs	 * when target mode is enabled.
682397883Sgibbs	 */
682497883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE, 5);
682597883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 1, 9);
682697883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 2, 9);
682797883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 3, 0);
682897883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 4, 15);
682997883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 5, 11);
683097883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 6, 0);
683197883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 7, 0);
683297883Sgibbs
683397883Sgibbs	/* Tell the sequencer of our initial queue positions */
683497883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
683597883Sgibbs	ahd_outb(ahd, QOFF_CTLSTA, SCB_QSIZE_512);
683697883Sgibbs	ahd->qinfifonext = 0;
683797883Sgibbs	ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
683897883Sgibbs	ahd_set_hescb_qoff(ahd, 0);
683997883Sgibbs	ahd_set_snscb_qoff(ahd, 0);
684097883Sgibbs	ahd_set_sescb_qoff(ahd, 0);
684197883Sgibbs	ahd_set_sdscb_qoff(ahd, 0);
684297883Sgibbs
684397883Sgibbs	/*
684497883Sgibbs	 * Tell the sequencer which SCB will be the next one it receives.
684597883Sgibbs	 */
6846123579Sgibbs	busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
6847123579Sgibbs	ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
6848109588Sgibbs
6849109588Sgibbs	/*
6850115329Sgibbs	 * Default to coalescing disabled.
6851109588Sgibbs	 */
6852115329Sgibbs	ahd_outw(ahd, INT_COALESCING_CMDCOUNT, 0);
6853109588Sgibbs	ahd_outw(ahd, CMDS_PENDING, 0);
6854115329Sgibbs	ahd_update_coalescing_values(ahd, ahd->int_coalescing_timer,
6855115329Sgibbs				     ahd->int_coalescing_maxcmds,
6856115329Sgibbs				     ahd->int_coalescing_mincmds);
6857115329Sgibbs	ahd_enable_coalescing(ahd, FALSE);
6858109588Sgibbs
685997883Sgibbs	ahd_loadseq(ahd);
686097883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
686197883Sgibbs}
686297883Sgibbs
686397883Sgibbs/*
686497883Sgibbs * Setup default device and controller settings.
686597883Sgibbs * This should only be called if our probe has
686697883Sgibbs * determined that no configuration data is available.
686797883Sgibbs */
686897883Sgibbsint
686997883Sgibbsahd_default_config(struct ahd_softc *ahd)
687097883Sgibbs{
687197883Sgibbs	int	targ;
687297883Sgibbs
687397883Sgibbs	ahd->our_id = 7;
687497883Sgibbs
687597883Sgibbs	/*
687697883Sgibbs	 * Allocate a tstate to house information for our
687797883Sgibbs	 * initiator presence on the bus as well as the user
687897883Sgibbs	 * data for any target mode initiator.
687997883Sgibbs	 */
688097883Sgibbs	if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
688197883Sgibbs		printf("%s: unable to allocate ahd_tmode_tstate.  "
688297883Sgibbs		       "Failing attach\n", ahd_name(ahd));
6883199260Sattilio		AHD_FATAL_ERROR(ahd);
688497883Sgibbs		return (ENOMEM);
688597883Sgibbs	}
688697883Sgibbs
688797883Sgibbs	for (targ = 0; targ < AHD_NUM_TARGETS; targ++) {
688897883Sgibbs		struct	 ahd_devinfo devinfo;
688997883Sgibbs		struct	 ahd_initiator_tinfo *tinfo;
689097883Sgibbs		struct	 ahd_tmode_tstate *tstate;
689197883Sgibbs		uint16_t target_mask;
689297883Sgibbs
689397883Sgibbs		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
689497883Sgibbs					    targ, &tstate);
689597883Sgibbs		/*
689697883Sgibbs		 * We support SPC2 and SPI4.
689797883Sgibbs		 */
689897883Sgibbs		tinfo->user.protocol_version = 4;
689997883Sgibbs		tinfo->user.transport_version = 4;
690097883Sgibbs
690197883Sgibbs		target_mask = 0x01 << targ;
690297883Sgibbs		ahd->user_discenable |= target_mask;
690397883Sgibbs		tstate->discenable |= target_mask;
690497883Sgibbs		ahd->user_tagenable |= target_mask;
690597883Sgibbs#ifdef AHD_FORCE_160
690697883Sgibbs		tinfo->user.period = AHD_SYNCRATE_DT;
690797883Sgibbs#else
690897883Sgibbs		tinfo->user.period = AHD_SYNCRATE_160;
690997883Sgibbs#endif
6910111653Sgibbs		tinfo->user.offset = MAX_OFFSET;
691197883Sgibbs		tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM
691297883Sgibbs					| MSG_EXT_PPR_WR_FLOW
6913104023Sgibbs					| MSG_EXT_PPR_HOLD_MCS
691497883Sgibbs					| MSG_EXT_PPR_IU_REQ
691597883Sgibbs					| MSG_EXT_PPR_QAS_REQ
691697883Sgibbs					| MSG_EXT_PPR_DT_REQ;
6917107441Sscottl		if ((ahd->features & AHD_RTI) != 0)
6918107441Sscottl			tinfo->user.ppr_options |= MSG_EXT_PPR_RTI;
691997883Sgibbs
692097883Sgibbs		tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
692197883Sgibbs
692297883Sgibbs		/*
692397883Sgibbs		 * Start out Async/Narrow/Untagged and with
692497883Sgibbs		 * conservative protocol support.
692597883Sgibbs		 */
692697883Sgibbs		tinfo->goal.protocol_version = 2;
692797883Sgibbs		tinfo->goal.transport_version = 2;
692897883Sgibbs		tinfo->curr.protocol_version = 2;
692997883Sgibbs		tinfo->curr.transport_version = 2;
693097883Sgibbs		ahd_compile_devinfo(&devinfo, ahd->our_id,
693197883Sgibbs				    targ, CAM_LUN_WILDCARD,
693297883Sgibbs				    'A', ROLE_INITIATOR);
693397883Sgibbs		tstate->tagenable &= ~target_mask;
693497883Sgibbs		ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
693597883Sgibbs			      AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);
693697883Sgibbs		ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
693797883Sgibbs				 /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
693897883Sgibbs				 /*paused*/TRUE);
693997883Sgibbs	}
694097883Sgibbs	return (0);
694197883Sgibbs}
694297883Sgibbs
694397883Sgibbs/*
694497883Sgibbs * Parse device configuration information.
694597883Sgibbs */
694697883Sgibbsint
694797883Sgibbsahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc)
694897883Sgibbs{
694997883Sgibbs	int targ;
695097883Sgibbs	int max_targ;
695197883Sgibbs
695297883Sgibbs	max_targ = sc->max_targets & CFMAXTARG;
695397883Sgibbs	ahd->our_id = sc->brtime_id & CFSCSIID;
695497883Sgibbs
695597883Sgibbs	/*
695697883Sgibbs	 * Allocate a tstate to house information for our
695797883Sgibbs	 * initiator presence on the bus as well as the user
695897883Sgibbs	 * data for any target mode initiator.
695997883Sgibbs	 */
696097883Sgibbs	if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
696197883Sgibbs		printf("%s: unable to allocate ahd_tmode_tstate.  "
696297883Sgibbs		       "Failing attach\n", ahd_name(ahd));
6963199260Sattilio		AHD_FATAL_ERROR(ahd);
696497883Sgibbs		return (ENOMEM);
696597883Sgibbs	}
696697883Sgibbs
696797883Sgibbs	for (targ = 0; targ < max_targ; targ++) {
696897883Sgibbs		struct	 ahd_devinfo devinfo;
696997883Sgibbs		struct	 ahd_initiator_tinfo *tinfo;
697097883Sgibbs		struct	 ahd_transinfo *user_tinfo;
697197883Sgibbs		struct	 ahd_tmode_tstate *tstate;
697297883Sgibbs		uint16_t target_mask;
697397883Sgibbs
697497883Sgibbs		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
697597883Sgibbs					    targ, &tstate);
697697883Sgibbs		user_tinfo = &tinfo->user;
697797883Sgibbs
697897883Sgibbs		/*
697997883Sgibbs		 * We support SPC2 and SPI4.
698097883Sgibbs		 */
698197883Sgibbs		tinfo->user.protocol_version = 4;
698297883Sgibbs		tinfo->user.transport_version = 4;
698397883Sgibbs
698497883Sgibbs		target_mask = 0x01 << targ;
698597883Sgibbs		ahd->user_discenable &= ~target_mask;
698697883Sgibbs		tstate->discenable &= ~target_mask;
698797883Sgibbs		ahd->user_tagenable &= ~target_mask;
698897883Sgibbs		if (sc->device_flags[targ] & CFDISC) {
698997883Sgibbs			tstate->discenable |= target_mask;
699097883Sgibbs			ahd->user_discenable |= target_mask;
699197883Sgibbs			ahd->user_tagenable |= target_mask;
699297883Sgibbs		} else {
699397883Sgibbs			/*
699497883Sgibbs			 * Cannot be packetized without disconnection.
699597883Sgibbs			 */
699697883Sgibbs			sc->device_flags[targ] &= ~CFPACKETIZED;
699797883Sgibbs		}
699897883Sgibbs
699997883Sgibbs		user_tinfo->ppr_options = 0;
700097883Sgibbs		user_tinfo->period = (sc->device_flags[targ] & CFXFER);
700197883Sgibbs		if (user_tinfo->period < CFXFER_ASYNC) {
700297883Sgibbs			if (user_tinfo->period <= AHD_PERIOD_10MHz)
700397883Sgibbs				user_tinfo->ppr_options |= MSG_EXT_PPR_DT_REQ;
700497883Sgibbs			user_tinfo->offset = MAX_OFFSET;
700597883Sgibbs		} else  {
700697883Sgibbs			user_tinfo->offset = 0;
7007109588Sgibbs			user_tinfo->period = AHD_ASYNC_XFER_PERIOD;
700897883Sgibbs		}
700997883Sgibbs#ifdef AHD_FORCE_160
701097883Sgibbs		if (user_tinfo->period <= AHD_SYNCRATE_160)
701197883Sgibbs			user_tinfo->period = AHD_SYNCRATE_DT;
701297883Sgibbs#endif
701397883Sgibbs
7014107441Sscottl		if ((sc->device_flags[targ] & CFPACKETIZED) != 0) {
701597883Sgibbs			user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM
701697883Sgibbs						|  MSG_EXT_PPR_WR_FLOW
7017104023Sgibbs						|  MSG_EXT_PPR_HOLD_MCS
701897883Sgibbs						|  MSG_EXT_PPR_IU_REQ;
7019107441Sscottl			if ((ahd->features & AHD_RTI) != 0)
7020107441Sscottl				user_tinfo->ppr_options |= MSG_EXT_PPR_RTI;
7021107441Sscottl		}
702297883Sgibbs
702397883Sgibbs		if ((sc->device_flags[targ] & CFQAS) != 0)
702497883Sgibbs			user_tinfo->ppr_options |= MSG_EXT_PPR_QAS_REQ;
702597883Sgibbs
702697883Sgibbs		if ((sc->device_flags[targ] & CFWIDEB) != 0)
702797883Sgibbs			user_tinfo->width = MSG_EXT_WDTR_BUS_16_BIT;
702897883Sgibbs		else
702997883Sgibbs			user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT;
703097883Sgibbs#ifdef AHD_DEBUG
703197883Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
703297883Sgibbs			printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width,
703397883Sgibbs			       user_tinfo->period, user_tinfo->offset,
703497883Sgibbs			       user_tinfo->ppr_options);
703597883Sgibbs#endif
703697883Sgibbs		/*
703797883Sgibbs		 * Start out Async/Narrow/Untagged and with
703897883Sgibbs		 * conservative protocol support.
703997883Sgibbs		 */
704097883Sgibbs		tstate->tagenable &= ~target_mask;
704197883Sgibbs		tinfo->goal.protocol_version = 2;
704297883Sgibbs		tinfo->goal.transport_version = 2;
704397883Sgibbs		tinfo->curr.protocol_version = 2;
704497883Sgibbs		tinfo->curr.transport_version = 2;
704597883Sgibbs		ahd_compile_devinfo(&devinfo, ahd->our_id,
704697883Sgibbs				    targ, CAM_LUN_WILDCARD,
704797883Sgibbs				    'A', ROLE_INITIATOR);
704897883Sgibbs		ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
704997883Sgibbs			      AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);
705097883Sgibbs		ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
705197883Sgibbs				 /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
705297883Sgibbs				 /*paused*/TRUE);
705397883Sgibbs	}
705497883Sgibbs
705597883Sgibbs	ahd->flags &= ~AHD_SPCHK_ENB_A;
705697883Sgibbs	if (sc->bios_control & CFSPARITY)
705797883Sgibbs		ahd->flags |= AHD_SPCHK_ENB_A;
705897883Sgibbs
705997883Sgibbs	ahd->flags &= ~AHD_RESET_BUS_A;
706097883Sgibbs	if (sc->bios_control & CFRESETB)
706197883Sgibbs		ahd->flags |= AHD_RESET_BUS_A;
706297883Sgibbs
706397883Sgibbs	ahd->flags &= ~AHD_EXTENDED_TRANS_A;
706497883Sgibbs	if (sc->bios_control & CFEXTEND)
706597883Sgibbs		ahd->flags |= AHD_EXTENDED_TRANS_A;
706697883Sgibbs
706797883Sgibbs	ahd->flags &= ~AHD_BIOS_ENABLED;
706897883Sgibbs	if ((sc->bios_control & CFBIOSSTATE) == CFBS_ENABLED)
706997883Sgibbs		ahd->flags |= AHD_BIOS_ENABLED;
707097883Sgibbs
707197883Sgibbs	ahd->flags &= ~AHD_STPWLEVEL_A;
707297883Sgibbs	if ((sc->adapter_control & CFSTPWLEVEL) != 0)
707397883Sgibbs		ahd->flags |= AHD_STPWLEVEL_A;
707497883Sgibbs
707597883Sgibbs	return (0);
707697883Sgibbs}
707797883Sgibbs
7078114623Sgibbs/*
7079114623Sgibbs * Parse device configuration information.
7080114623Sgibbs */
7081114623Sgibbsint
7082114623Sgibbsahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd)
7083114623Sgibbs{
7084114623Sgibbs	int error;
7085114623Sgibbs
7086114623Sgibbs	error = ahd_verify_vpd_cksum(vpd);
7087114623Sgibbs	if (error == 0)
7088114623Sgibbs		return (EINVAL);
7089114623Sgibbs	if ((vpd->bios_flags & VPDBOOTHOST) != 0)
7090114623Sgibbs		ahd->flags |= AHD_BOOT_CHANNEL;
7091114623Sgibbs	return (0);
7092114623Sgibbs}
7093114623Sgibbs
709497883Sgibbsvoid
709597883Sgibbsahd_intr_enable(struct ahd_softc *ahd, int enable)
709697883Sgibbs{
709797883Sgibbs	u_int hcntrl;
709897883Sgibbs
709997883Sgibbs	hcntrl = ahd_inb(ahd, HCNTRL);
710097883Sgibbs	hcntrl &= ~INTEN;
710197883Sgibbs	ahd->pause &= ~INTEN;
710297883Sgibbs	ahd->unpause &= ~INTEN;
710397883Sgibbs	if (enable) {
710497883Sgibbs		hcntrl |= INTEN;
710597883Sgibbs		ahd->pause |= INTEN;
710697883Sgibbs		ahd->unpause |= INTEN;
710797883Sgibbs	}
710897883Sgibbs	ahd_outb(ahd, HCNTRL, hcntrl);
710997883Sgibbs}
711097883Sgibbs
7111109588Sgibbsvoid
7112115329Sgibbsahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds,
7113109588Sgibbs			     u_int mincmds)
7114109588Sgibbs{
7115109588Sgibbs	if (timer > AHD_TIMER_MAX_US)
7116109588Sgibbs		timer = AHD_TIMER_MAX_US;
7117115329Sgibbs	ahd->int_coalescing_timer = timer;
7118109588Sgibbs
7119115329Sgibbs	if (maxcmds > AHD_INT_COALESCING_MAXCMDS_MAX)
7120115329Sgibbs		maxcmds = AHD_INT_COALESCING_MAXCMDS_MAX;
7121115329Sgibbs	if (mincmds > AHD_INT_COALESCING_MINCMDS_MAX)
7122115329Sgibbs		mincmds = AHD_INT_COALESCING_MINCMDS_MAX;
7123115329Sgibbs	ahd->int_coalescing_maxcmds = maxcmds;
7124115329Sgibbs	ahd_outw(ahd, INT_COALESCING_TIMER, timer / AHD_TIMER_US_PER_TICK);
7125115329Sgibbs	ahd_outb(ahd, INT_COALESCING_MAXCMDS, -maxcmds);
7126115329Sgibbs	ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds);
7127109588Sgibbs}
7128109588Sgibbs
7129109588Sgibbsvoid
7130115329Sgibbsahd_enable_coalescing(struct ahd_softc *ahd, int enable)
7131109588Sgibbs{
7132109588Sgibbs
7133115329Sgibbs	ahd->hs_mailbox &= ~ENINT_COALESCE;
7134109588Sgibbs	if (enable)
7135115329Sgibbs		ahd->hs_mailbox |= ENINT_COALESCE;
7136109588Sgibbs	ahd_outb(ahd, HS_MAILBOX, ahd->hs_mailbox);
7137109588Sgibbs	ahd_flush_device_writes(ahd);
7138109588Sgibbs	ahd_run_qoutfifo(ahd);
7139109588Sgibbs}
7140109588Sgibbs
714197883Sgibbs/*
714297883Sgibbs * Ensure that the card is paused in a location
714397883Sgibbs * outside of all critical sections and that all
714497883Sgibbs * pending work is completed prior to returning.
714597883Sgibbs * This routine should only be called from outside
714697883Sgibbs * an interrupt context.
714797883Sgibbs */
714897883Sgibbsvoid
714997883Sgibbsahd_pause_and_flushwork(struct ahd_softc *ahd)
715097883Sgibbs{
7151114623Sgibbs	u_int intstat;
7152114623Sgibbs	u_int maxloops;
715397883Sgibbs
715497883Sgibbs	maxloops = 1000;
715597883Sgibbs	ahd->flags |= AHD_ALL_INTERRUPTS;
7156114623Sgibbs	ahd_pause(ahd);
7157114623Sgibbs	/*
7158125448Sgibbs	 * Freeze the outgoing selections.  We do this only
7159114623Sgibbs	 * until we are safely paused without further selections
7160114623Sgibbs	 * pending.
7161114623Sgibbs	 */
7162125448Sgibbs	ahd->qfreeze_cnt--;
7163125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
7164114623Sgibbs	ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
716597883Sgibbs	do {
7166109588Sgibbs
7167114623Sgibbs		ahd_unpause(ahd);
7168123579Sgibbs		/*
7169123579Sgibbs		 * Give the sequencer some time to service
7170123579Sgibbs		 * any active selections.
7171123579Sgibbs		 */
7172129134Sgibbs		aic_delay(500);
7173123579Sgibbs
717497883Sgibbs		ahd_intr(ahd);
717597883Sgibbs		ahd_pause(ahd);
7176114623Sgibbs		intstat = ahd_inb(ahd, INTSTAT);
7177129134Sgibbs		if ((intstat & INT_PEND) == 0) {
7178129134Sgibbs			ahd_clear_critical_section(ahd);
7179129134Sgibbs			intstat = ahd_inb(ahd, INTSTAT);
7180129134Sgibbs		}
7181109588Sgibbs	} while (--maxloops
7182111653Sgibbs	      && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
7183111653Sgibbs	      && ((intstat & INT_PEND) != 0
7184114623Sgibbs	       || (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
7185114623Sgibbs	       || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0));
7186114623Sgibbs
718797883Sgibbs	if (maxloops == 0) {
718897883Sgibbs		printf("Infinite interrupt loop, INTSTAT = %x",
718997883Sgibbs		      ahd_inb(ahd, INTSTAT));
7190199260Sattilio		AHD_FATAL_ERROR(ahd);
719197883Sgibbs	}
7192125448Sgibbs	ahd->qfreeze_cnt++;
7193125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
7194109588Sgibbs
7195109588Sgibbs	ahd_flush_qoutfifo(ahd);
7196109588Sgibbs
719797883Sgibbs	ahd_platform_flushwork(ahd);
719897883Sgibbs	ahd->flags &= ~AHD_ALL_INTERRUPTS;
719997883Sgibbs}
720097883Sgibbs
720197883Sgibbsint
720297883Sgibbsahd_suspend(struct ahd_softc *ahd)
720397883Sgibbs{
720497883Sgibbs
720597883Sgibbs	ahd_pause_and_flushwork(ahd);
720697883Sgibbs
7207115917Sgibbs	if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
7208115917Sgibbs		ahd_unpause(ahd);
720997883Sgibbs		return (EBUSY);
721097883Sgibbs	}
721197883Sgibbs	ahd_shutdown(ahd);
721297883Sgibbs	return (0);
721397883Sgibbs}
721497883Sgibbs
721597883Sgibbsint
721697883Sgibbsahd_resume(struct ahd_softc *ahd)
721797883Sgibbs{
721897883Sgibbs
7219115917Sgibbs	ahd_reset(ahd, /*reinit*/TRUE);
7220115917Sgibbs	ahd_intr_enable(ahd, TRUE);
7221115917Sgibbs	ahd_restart(ahd);
722297883Sgibbs	return (0);
722397883Sgibbs}
722497883Sgibbs
722597883Sgibbs/************************** Busy Target Table *********************************/
722697883Sgibbs/*
722797883Sgibbs * Set SCBPTR to the SCB that contains the busy
722897883Sgibbs * table entry for TCL.  Return the offset into
722997883Sgibbs * the SCB that contains the entry for TCL.
723097883Sgibbs * saved_scbid is dereferenced and set to the
723197883Sgibbs * scbid that should be restored once manipualtion
723297883Sgibbs * of the TCL entry is complete.
723397883Sgibbs */
723497883Sgibbsstatic __inline u_int
723597883Sgibbsahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)
723697883Sgibbs{
723797883Sgibbs	/*
723897883Sgibbs	 * Index to the SCB that contains the busy entry.
723997883Sgibbs	 */
7240104023Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7241104023Sgibbs	*saved_scbid = ahd_get_scbptr(ahd);
724297883Sgibbs	ahd_set_scbptr(ahd, TCL_LUN(tcl)
7243102679Sgibbs		     | ((TCL_TARGET_OFFSET(tcl) & 0xC) << 4));
724497883Sgibbs
724597883Sgibbs	/*
724697883Sgibbs	 * And now calculate the SCB offset to the entry.
724797883Sgibbs	 * Each entry is 2 bytes wide, hence the
724897883Sgibbs	 * multiplication by 2.
724997883Sgibbs	 */
7250102679Sgibbs	return (((TCL_TARGET_OFFSET(tcl) & 0x3) << 1) + SCB_DISCONNECTED_LISTS);
725197883Sgibbs}
725297883Sgibbs
725397883Sgibbs/*
725497883Sgibbs * Return the untagged transaction id for a given target/channel lun.
725597883Sgibbs */
725697883Sgibbsu_int
725797883Sgibbsahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl)
725897883Sgibbs{
725997883Sgibbs	u_int scbid;
726097883Sgibbs	u_int scb_offset;
726197883Sgibbs	u_int saved_scbptr;
726297883Sgibbs
726397883Sgibbs	scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
726497883Sgibbs	scbid = ahd_inw_scbram(ahd, scb_offset);
726597883Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
726697883Sgibbs	return (scbid);
726797883Sgibbs}
726897883Sgibbs
726997883Sgibbsvoid
727097883Sgibbsahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid)
727197883Sgibbs{
727297883Sgibbs	u_int scb_offset;
727397883Sgibbs	u_int saved_scbptr;
727497883Sgibbs
727597883Sgibbs	scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
727697883Sgibbs	ahd_outw(ahd, scb_offset, scbid);
727797883Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
727897883Sgibbs}
727997883Sgibbs
728097883Sgibbs/************************** SCB and SCB queue management **********************/
728197883Sgibbsint
728297883Sgibbsahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target,
728397883Sgibbs	      char channel, int lun, u_int tag, role_t role)
728497883Sgibbs{
728597883Sgibbs	int targ = SCB_GET_TARGET(ahd, scb);
728697883Sgibbs	char chan = SCB_GET_CHANNEL(ahd, scb);
728797883Sgibbs	int slun = SCB_GET_LUN(scb);
728897883Sgibbs	int match;
728997883Sgibbs
729097883Sgibbs	match = ((chan == channel) || (channel == ALL_CHANNELS));
729197883Sgibbs	if (match != 0)
729297883Sgibbs		match = ((targ == target) || (target == CAM_TARGET_WILDCARD));
729397883Sgibbs	if (match != 0)
729497883Sgibbs		match = ((lun == slun) || (lun == CAM_LUN_WILDCARD));
729597883Sgibbs	if (match != 0) {
7296153072Sru#ifdef AHD_TARGET_MODE
729797883Sgibbs		int group;
729897883Sgibbs
729997883Sgibbs		group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code);
730097883Sgibbs		if (role == ROLE_INITIATOR) {
730197883Sgibbs			match = (group != XPT_FC_GROUP_TMODE)
730297883Sgibbs			      && ((tag == SCB_GET_TAG(scb))
730397883Sgibbs			       || (tag == SCB_LIST_NULL));
730497883Sgibbs		} else if (role == ROLE_TARGET) {
730597883Sgibbs			match = (group == XPT_FC_GROUP_TMODE)
730697883Sgibbs			      && ((tag == scb->io_ctx->csio.tag_id)
730797883Sgibbs			       || (tag == SCB_LIST_NULL));
730897883Sgibbs		}
730997883Sgibbs#else /* !AHD_TARGET_MODE */
731097883Sgibbs		match = ((tag == SCB_GET_TAG(scb)) || (tag == SCB_LIST_NULL));
731197883Sgibbs#endif /* AHD_TARGET_MODE */
731297883Sgibbs	}
731397883Sgibbs
731497883Sgibbs	return match;
731597883Sgibbs}
731697883Sgibbs
731797883Sgibbsvoid
731897883Sgibbsahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
731997883Sgibbs{
732097883Sgibbs	int	target;
732197883Sgibbs	char	channel;
732297883Sgibbs	int	lun;
732397883Sgibbs
732497883Sgibbs	target = SCB_GET_TARGET(ahd, scb);
732597883Sgibbs	lun = SCB_GET_LUN(scb);
732697883Sgibbs	channel = SCB_GET_CHANNEL(ahd, scb);
732797883Sgibbs
732897883Sgibbs	ahd_search_qinfifo(ahd, target, channel, lun,
732997883Sgibbs			   /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN,
733097883Sgibbs			   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
733197883Sgibbs
733297883Sgibbs	ahd_platform_freeze_devq(ahd, scb);
733397883Sgibbs}
733497883Sgibbs
733597883Sgibbsvoid
733697883Sgibbsahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb)
733797883Sgibbs{
7338107441Sscottl	struct scb	*prev_scb;
7339107441Sscottl	ahd_mode_state	 saved_modes;
734097883Sgibbs
7341107441Sscottl	saved_modes = ahd_save_modes(ahd);
7342107441Sscottl	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
734397883Sgibbs	prev_scb = NULL;
734497883Sgibbs	if (ahd_qinfifo_count(ahd) != 0) {
734597883Sgibbs		u_int prev_tag;
734697883Sgibbs		u_int prev_pos;
734797883Sgibbs
734897883Sgibbs		prev_pos = AHD_QIN_WRAP(ahd->qinfifonext - 1);
734997883Sgibbs		prev_tag = ahd->qinfifo[prev_pos];
735097883Sgibbs		prev_scb = ahd_lookup_scb(ahd, prev_tag);
735197883Sgibbs	}
735297883Sgibbs	ahd_qinfifo_requeue(ahd, prev_scb, scb);
735397883Sgibbs	ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
7354107441Sscottl	ahd_restore_modes(ahd, saved_modes);
735597883Sgibbs}
735697883Sgibbs
735797883Sgibbsstatic void
735897883Sgibbsahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
735997883Sgibbs		    struct scb *scb)
736097883Sgibbs{
736197883Sgibbs	if (prev_scb == NULL) {
736297883Sgibbs		uint32_t busaddr;
736397883Sgibbs
7364123579Sgibbs		busaddr = aic_le32toh(scb->hscb->hscb_busaddr);
7365123579Sgibbs		ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
736697883Sgibbs	} else {
736797883Sgibbs		prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
736897883Sgibbs		ahd_sync_scb(ahd, prev_scb,
736997883Sgibbs			     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
737097883Sgibbs	}
737197883Sgibbs	ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
737297883Sgibbs	ahd->qinfifonext++;
7373102679Sgibbs	scb->hscb->next_hscb_busaddr = ahd->next_queued_hscb->hscb_busaddr;
737497883Sgibbs	ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
737597883Sgibbs}
737697883Sgibbs
737797883Sgibbsstatic int
737897883Sgibbsahd_qinfifo_count(struct ahd_softc *ahd)
737997883Sgibbs{
738097883Sgibbs	u_int qinpos;
738197883Sgibbs	u_int wrap_qinpos;
738297883Sgibbs	u_int wrap_qinfifonext;
738397883Sgibbs
738497883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
738597883Sgibbs	qinpos = ahd_get_snscb_qoff(ahd);
738697883Sgibbs	wrap_qinpos = AHD_QIN_WRAP(qinpos);
738797883Sgibbs	wrap_qinfifonext = AHD_QIN_WRAP(ahd->qinfifonext);
7388109588Sgibbs	if (wrap_qinfifonext >= wrap_qinpos)
738997883Sgibbs		return (wrap_qinfifonext - wrap_qinpos);
739097883Sgibbs	else
739197883Sgibbs		return (wrap_qinfifonext
739297883Sgibbs		      + NUM_ELEMENTS(ahd->qinfifo) - wrap_qinpos);
739397883Sgibbs}
739497883Sgibbs
7395109588Sgibbsvoid
7396109588Sgibbsahd_reset_cmds_pending(struct ahd_softc *ahd)
7397109588Sgibbs{
7398109588Sgibbs	struct		scb *scb;
7399109588Sgibbs	ahd_mode_state	saved_modes;
7400109588Sgibbs	u_int		pending_cmds;
7401109588Sgibbs
7402109588Sgibbs	saved_modes = ahd_save_modes(ahd);
7403109588Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
7404109588Sgibbs
7405109588Sgibbs	/*
7406109588Sgibbs	 * Don't count any commands as outstanding that the
7407109588Sgibbs	 * sequencer has already marked for completion.
7408109588Sgibbs	 */
7409109588Sgibbs	ahd_flush_qoutfifo(ahd);
7410109588Sgibbs
7411109588Sgibbs	pending_cmds = 0;
7412109588Sgibbs	LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
7413109588Sgibbs		pending_cmds++;
7414109588Sgibbs	}
7415109588Sgibbs	ahd_outw(ahd, CMDS_PENDING, pending_cmds - ahd_qinfifo_count(ahd));
7416109588Sgibbs	ahd_restore_modes(ahd, saved_modes);
7417109588Sgibbs	ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
7418109588Sgibbs}
7419109588Sgibbs
7420133122Sgibbsvoid
7421133122Sgibbsahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
7422133122Sgibbs{
7423133122Sgibbs	cam_status ostat;
7424133122Sgibbs	cam_status cstat;
7425133122Sgibbs
7426133122Sgibbs	ostat = aic_get_transaction_status(scb);
7427133122Sgibbs	if (ostat == CAM_REQ_INPROG)
7428133122Sgibbs		aic_set_transaction_status(scb, status);
7429133122Sgibbs	cstat = aic_get_transaction_status(scb);
7430133122Sgibbs	if (cstat != CAM_REQ_CMP)
7431133122Sgibbs		aic_freeze_scb(scb);
7432133122Sgibbs	ahd_done(ahd, scb);
7433133122Sgibbs}
7434133122Sgibbs
743597883Sgibbsint
743697883Sgibbsahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
743797883Sgibbs		   int lun, u_int tag, role_t role, uint32_t status,
743897883Sgibbs		   ahd_search_action action)
743997883Sgibbs{
744097883Sgibbs	struct scb	*scb;
7441133122Sgibbs	struct scb	*mk_msg_scb;
744297883Sgibbs	struct scb	*prev_scb;
744397883Sgibbs	ahd_mode_state	 saved_modes;
744497883Sgibbs	u_int		 qinstart;
744597883Sgibbs	u_int		 qinpos;
744697883Sgibbs	u_int		 qintail;
744797883Sgibbs	u_int		 tid_next;
744897883Sgibbs	u_int		 tid_prev;
744997883Sgibbs	u_int		 scbid;
7450133122Sgibbs	u_int		 seq_flags2;
745197883Sgibbs	u_int		 savedscbptr;
745297883Sgibbs	uint32_t	 busaddr;
745397883Sgibbs	int		 found;
745497883Sgibbs	int		 targets;
745597883Sgibbs
745697883Sgibbs	/* Must be in CCHAN mode */
745797883Sgibbs	saved_modes = ahd_save_modes(ahd);
745897883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
745997883Sgibbs
746097883Sgibbs	/*
746197883Sgibbs	 * Halt any pending SCB DMA.  The sequencer will reinitiate
746297883Sgibbs	 * this dma if the qinfifo is not empty once we unpause.
746397883Sgibbs	 */
746497883Sgibbs	if ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN|CCSCBDIR))
746597883Sgibbs	 == (CCARREN|CCSCBEN|CCSCBDIR)) {
746697883Sgibbs		ahd_outb(ahd, CCSCBCTL,
746797883Sgibbs			 ahd_inb(ahd, CCSCBCTL) & ~(CCARREN|CCSCBEN));
746897883Sgibbs		while ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0)
746997883Sgibbs			;
747097883Sgibbs	}
747197883Sgibbs	/* Determine sequencer's position in the qinfifo. */
747297883Sgibbs	qintail = AHD_QIN_WRAP(ahd->qinfifonext);
747397883Sgibbs	qinstart = ahd_get_snscb_qoff(ahd);
747497883Sgibbs	qinpos = AHD_QIN_WRAP(qinstart);
747597883Sgibbs	found = 0;
747697883Sgibbs	prev_scb = NULL;
747797883Sgibbs
747897883Sgibbs	if (action == SEARCH_PRINT) {
747997883Sgibbs		printf("qinstart = %d qinfifonext = %d\nQINFIFO:",
748097883Sgibbs		       qinstart, ahd->qinfifonext);
748197883Sgibbs	}
748297883Sgibbs
748397883Sgibbs	/*
748497883Sgibbs	 * Start with an empty queue.  Entries that are not chosen
748597883Sgibbs	 * for removal will be re-added to the queue as we go.
748697883Sgibbs	 */
748797883Sgibbs	ahd->qinfifonext = qinstart;
7488123579Sgibbs	busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
7489123579Sgibbs	ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
749097883Sgibbs
749197883Sgibbs	while (qinpos != qintail) {
749297883Sgibbs		scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
749397883Sgibbs		if (scb == NULL) {
749497883Sgibbs			printf("qinpos = %d, SCB index = %d\n",
749597883Sgibbs				qinpos, ahd->qinfifo[qinpos]);
7496199260Sattilio			AHD_FATAL_ERROR(ahd);
749797883Sgibbs			panic("Loop 1\n");
749897883Sgibbs		}
749997883Sgibbs
750097883Sgibbs		if (ahd_match_scb(ahd, scb, target, channel, lun, tag, role)) {
750197883Sgibbs			/*
750297883Sgibbs			 * We found an scb that needs to be acted on.
750397883Sgibbs			 */
750497883Sgibbs			found++;
750597883Sgibbs			switch (action) {
750697883Sgibbs			case SEARCH_COMPLETE:
750797883Sgibbs				if ((scb->flags & SCB_ACTIVE) == 0)
750897883Sgibbs					printf("Inactive SCB in qinfifo\n");
7509133122Sgibbs				ahd_done_with_status(ahd, scb, status);
751097883Sgibbs				/* FALLTHROUGH */
751197883Sgibbs			case SEARCH_REMOVE:
751297883Sgibbs				break;
751397883Sgibbs			case SEARCH_PRINT:
751497883Sgibbs				printf(" 0x%x", ahd->qinfifo[qinpos]);
751597883Sgibbs				/* FALLTHROUGH */
751697883Sgibbs			case SEARCH_COUNT:
751797883Sgibbs				ahd_qinfifo_requeue(ahd, prev_scb, scb);
751897883Sgibbs				prev_scb = scb;
751997883Sgibbs				break;
752097883Sgibbs			}
752197883Sgibbs		} else {
752297883Sgibbs			ahd_qinfifo_requeue(ahd, prev_scb, scb);
752397883Sgibbs			prev_scb = scb;
752497883Sgibbs		}
752597883Sgibbs		qinpos = AHD_QIN_WRAP(qinpos+1);
752697883Sgibbs	}
752797883Sgibbs
752897883Sgibbs	ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
752997883Sgibbs
753097883Sgibbs	if (action == SEARCH_PRINT)
753197883Sgibbs		printf("\nWAITING_TID_QUEUES:\n");
753297883Sgibbs
753397883Sgibbs	/*
753497883Sgibbs	 * Search waiting for selection lists.  We traverse the
753597883Sgibbs	 * list of "their ids" waiting for selection and, if
753697883Sgibbs	 * appropriate, traverse the SCBs of each "their id"
753797883Sgibbs	 * looking for matches.
753897883Sgibbs	 */
7539125448Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
7540133122Sgibbs	seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2);
7541133122Sgibbs	if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) {
7542133122Sgibbs		scbid = ahd_inw(ahd, MK_MESSAGE_SCB);
7543133122Sgibbs		mk_msg_scb = ahd_lookup_scb(ahd, scbid);
7544133122Sgibbs	} else
7545133122Sgibbs		mk_msg_scb = NULL;
754697883Sgibbs	savedscbptr = ahd_get_scbptr(ahd);
754797883Sgibbs	tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
754897883Sgibbs	tid_prev = SCB_LIST_NULL;
754997883Sgibbs	targets = 0;
755097883Sgibbs	for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) {
755197883Sgibbs		u_int tid_head;
7552133122Sgibbs		u_int tid_tail;
755397883Sgibbs
755497883Sgibbs		targets++;
7555133122Sgibbs		if (targets > AHD_NUM_TARGETS)
755697883Sgibbs			panic("TID LIST LOOP");
7557133122Sgibbs
755897883Sgibbs		if (scbid >= ahd->scb_data.numscbs) {
755997883Sgibbs			printf("%s: Waiting TID List inconsistency. "
756097883Sgibbs			       "SCB index == 0x%x, yet numscbs == 0x%x.",
756197883Sgibbs			       ahd_name(ahd), scbid, ahd->scb_data.numscbs);
756297883Sgibbs			ahd_dump_card_state(ahd);
756397883Sgibbs			panic("for safety");
756497883Sgibbs		}
756597883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
756697883Sgibbs		if (scb == NULL) {
756797883Sgibbs			printf("%s: SCB = 0x%x Not Active!\n",
756897883Sgibbs			       ahd_name(ahd), scbid);
756997883Sgibbs			panic("Waiting TID List traversal\n");
757097883Sgibbs		}
757197883Sgibbs		ahd_set_scbptr(ahd, scbid);
757297883Sgibbs		tid_next = ahd_inw_scbram(ahd, SCB_NEXT2);
757397883Sgibbs		if (ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
757497883Sgibbs				  SCB_LIST_NULL, ROLE_UNKNOWN) == 0) {
757597883Sgibbs			tid_prev = scbid;
757697883Sgibbs			continue;
757797883Sgibbs		}
757897883Sgibbs
757997883Sgibbs		/*
758097883Sgibbs		 * We found a list of scbs that needs to be searched.
758197883Sgibbs		 */
758297883Sgibbs		if (action == SEARCH_PRINT)
758397883Sgibbs			printf("       %d ( ", SCB_GET_TARGET(ahd, scb));
758497883Sgibbs		tid_head = scbid;
758597883Sgibbs		found += ahd_search_scb_list(ahd, target, channel,
758697883Sgibbs					     lun, tag, role, status,
7587133122Sgibbs					     action, &tid_head, &tid_tail,
758897883Sgibbs					     SCB_GET_TARGET(ahd, scb));
7589133122Sgibbs		/*
7590133122Sgibbs		 * Check any MK_MESSAGE SCB that is still waiting to
7591133122Sgibbs		 * enter this target's waiting for selection queue.
7592133122Sgibbs		 */
7593133122Sgibbs		if (mk_msg_scb != NULL
7594133122Sgibbs		 && ahd_match_scb(ahd, mk_msg_scb, target, channel,
7595133122Sgibbs				  lun, tag, role)) {
7596133122Sgibbs
7597133122Sgibbs			/*
7598133122Sgibbs			 * We found an scb that needs to be acted on.
7599133122Sgibbs			 */
7600133122Sgibbs			found++;
7601133122Sgibbs			switch (action) {
7602133122Sgibbs			case SEARCH_COMPLETE:
7603133122Sgibbs				if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)
7604133122Sgibbs					printf("Inactive SCB pending MK_MSG\n");
7605133122Sgibbs				ahd_done_with_status(ahd, mk_msg_scb, status);
7606133122Sgibbs				/* FALLTHROUGH */
7607133122Sgibbs			case SEARCH_REMOVE:
7608133122Sgibbs			{
7609133122Sgibbs				u_int tail_offset;
7610133122Sgibbs
7611133122Sgibbs				printf("Removing MK_MSG scb\n");
7612133122Sgibbs
7613133122Sgibbs				/*
7614133122Sgibbs				 * Reset our tail to the tail of the
7615133122Sgibbs				 * main per-target list.
7616133122Sgibbs				 */
7617133122Sgibbs				tail_offset = WAITING_SCB_TAILS
7618133122Sgibbs				    + (2 * SCB_GET_TARGET(ahd, mk_msg_scb));
7619133122Sgibbs				ahd_outw(ahd, tail_offset, tid_tail);
7620133122Sgibbs
7621133122Sgibbs				seq_flags2 &= ~PENDING_MK_MESSAGE;
7622133122Sgibbs				ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
7623133122Sgibbs				ahd_outw(ahd, CMDS_PENDING,
7624133122Sgibbs					 ahd_inw(ahd, CMDS_PENDING)-1);
7625133122Sgibbs				mk_msg_scb = NULL;
7626133122Sgibbs				break;
7627133122Sgibbs			}
7628133122Sgibbs			case SEARCH_PRINT:
7629133122Sgibbs				printf(" 0x%x", SCB_GET_TAG(scb));
7630133122Sgibbs				/* FALLTHROUGH */
7631133122Sgibbs			case SEARCH_COUNT:
7632133122Sgibbs				break;
7633133122Sgibbs			}
7634133122Sgibbs		}
7635133122Sgibbs
7636133122Sgibbs		if (mk_msg_scb != NULL
7637133122Sgibbs		 && SCBID_IS_NULL(tid_head)
7638133122Sgibbs		 && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
7639133122Sgibbs				  SCB_LIST_NULL, ROLE_UNKNOWN)) {
7640133122Sgibbs
7641133122Sgibbs			/*
7642133122Sgibbs			 * When removing the last SCB for a target
7643133122Sgibbs			 * queue with a pending MK_MESSAGE scb, we
7644133122Sgibbs			 * must queue the MK_MESSAGE scb.
7645133122Sgibbs			 */
7646133122Sgibbs			printf("Queueing mk_msg_scb\n");
7647133122Sgibbs			tid_head = ahd_inw(ahd, MK_MESSAGE_SCB);
7648133122Sgibbs			seq_flags2 &= ~PENDING_MK_MESSAGE;
7649133122Sgibbs			ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
7650133122Sgibbs			mk_msg_scb = NULL;
7651133122Sgibbs		}
765297883Sgibbs		if (tid_head != scbid)
765397883Sgibbs			ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next);
765497883Sgibbs		if (!SCBID_IS_NULL(tid_head))
765597883Sgibbs			tid_prev = tid_head;
765697883Sgibbs		if (action == SEARCH_PRINT)
765797883Sgibbs			printf(")\n");
765897883Sgibbs	}
7659133122Sgibbs
7660133122Sgibbs	/* Restore saved state. */
766197883Sgibbs	ahd_set_scbptr(ahd, savedscbptr);
766297883Sgibbs	ahd_restore_modes(ahd, saved_modes);
766397883Sgibbs	return (found);
766497883Sgibbs}
766597883Sgibbs
766697883Sgibbsstatic int
766797883Sgibbsahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
766897883Sgibbs		    int lun, u_int tag, role_t role, uint32_t status,
7669133122Sgibbs		    ahd_search_action action, u_int *list_head,
7670133122Sgibbs		    u_int *list_tail, u_int tid)
767197883Sgibbs{
767297883Sgibbs	struct	scb *scb;
767397883Sgibbs	u_int	scbid;
767497883Sgibbs	u_int	next;
767597883Sgibbs	u_int	prev;
767697883Sgibbs	int	found;
767797883Sgibbs
7678125448Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
767997883Sgibbs	found = 0;
768097883Sgibbs	prev = SCB_LIST_NULL;
768197883Sgibbs	next = *list_head;
7682133122Sgibbs	*list_tail = SCB_LIST_NULL;
768397883Sgibbs	for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) {
768497883Sgibbs		if (scbid >= ahd->scb_data.numscbs) {
768597883Sgibbs			printf("%s:SCB List inconsistency. "
768697883Sgibbs			       "SCB == 0x%x, yet numscbs == 0x%x.",
768797883Sgibbs			       ahd_name(ahd), scbid, ahd->scb_data.numscbs);
768897883Sgibbs			ahd_dump_card_state(ahd);
768997883Sgibbs			panic("for safety");
769097883Sgibbs		}
769197883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
769297883Sgibbs		if (scb == NULL) {
769397883Sgibbs			printf("%s: SCB = %d Not Active!\n",
769497883Sgibbs			       ahd_name(ahd), scbid);
769597883Sgibbs			panic("Waiting List traversal\n");
769697883Sgibbs		}
769797883Sgibbs		ahd_set_scbptr(ahd, scbid);
7698133122Sgibbs		*list_tail = scbid;
769997883Sgibbs		next = ahd_inw_scbram(ahd, SCB_NEXT);
770097883Sgibbs		if (ahd_match_scb(ahd, scb, target, channel,
770197883Sgibbs				  lun, SCB_LIST_NULL, role) == 0) {
770297883Sgibbs			prev = scbid;
770397883Sgibbs			continue;
770497883Sgibbs		}
770597883Sgibbs		found++;
770697883Sgibbs		switch (action) {
770797883Sgibbs		case SEARCH_COMPLETE:
770897883Sgibbs			if ((scb->flags & SCB_ACTIVE) == 0)
770997883Sgibbs				printf("Inactive SCB in Waiting List\n");
7710133122Sgibbs			ahd_done_with_status(ahd, scb, status);
771197883Sgibbs			/* FALLTHROUGH */
771297883Sgibbs		case SEARCH_REMOVE:
771397883Sgibbs			ahd_rem_wscb(ahd, scbid, prev, next, tid);
7714133122Sgibbs			*list_tail = prev;
7715133122Sgibbs			if (SCBID_IS_NULL(prev))
771697883Sgibbs				*list_head = next;
771797883Sgibbs			break;
771897883Sgibbs		case SEARCH_PRINT:
771997883Sgibbs			printf("0x%x ", scbid);
772097883Sgibbs		case SEARCH_COUNT:
772197883Sgibbs			prev = scbid;
772297883Sgibbs			break;
772397883Sgibbs		}
772497883Sgibbs		if (found > AHD_SCB_MAX)
772597883Sgibbs			panic("SCB LIST LOOP");
772697883Sgibbs	}
7727109588Sgibbs	if (action == SEARCH_COMPLETE
7728109588Sgibbs	 || action == SEARCH_REMOVE)
7729109588Sgibbs		ahd_outw(ahd, CMDS_PENDING, ahd_inw(ahd, CMDS_PENDING) - found);
773097883Sgibbs	return (found);
773197883Sgibbs}
773297883Sgibbs
773397883Sgibbsstatic void
773497883Sgibbsahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
773597883Sgibbs		    u_int tid_cur, u_int tid_next)
773697883Sgibbs{
7737125448Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
773897883Sgibbs
773997883Sgibbs	if (SCBID_IS_NULL(tid_cur)) {
774097883Sgibbs
774197883Sgibbs		/* Bypass current TID list */
774297883Sgibbs		if (SCBID_IS_NULL(tid_prev)) {
774397883Sgibbs			ahd_outw(ahd, WAITING_TID_HEAD, tid_next);
774497883Sgibbs		} else {
774597883Sgibbs			ahd_set_scbptr(ahd, tid_prev);
774697883Sgibbs			ahd_outw(ahd, SCB_NEXT2, tid_next);
774797883Sgibbs		}
774897883Sgibbs		if (SCBID_IS_NULL(tid_next))
774997883Sgibbs			ahd_outw(ahd, WAITING_TID_TAIL, tid_prev);
775097883Sgibbs	} else {
775197883Sgibbs
775297883Sgibbs		/* Stitch through tid_cur */
775397883Sgibbs		if (SCBID_IS_NULL(tid_prev)) {
775497883Sgibbs			ahd_outw(ahd, WAITING_TID_HEAD, tid_cur);
775597883Sgibbs		} else {
775697883Sgibbs			ahd_set_scbptr(ahd, tid_prev);
775797883Sgibbs			ahd_outw(ahd, SCB_NEXT2, tid_cur);
775897883Sgibbs		}
775997883Sgibbs		ahd_set_scbptr(ahd, tid_cur);
776097883Sgibbs		ahd_outw(ahd, SCB_NEXT2, tid_next);
776197883Sgibbs
776297883Sgibbs		if (SCBID_IS_NULL(tid_next))
776397883Sgibbs			ahd_outw(ahd, WAITING_TID_TAIL, tid_cur);
776497883Sgibbs	}
776597883Sgibbs}
776697883Sgibbs
776797883Sgibbs/*
776897883Sgibbs * Manipulate the waiting for selection list and return the
776997883Sgibbs * scb that follows the one that we remove.
777097883Sgibbs */
777197883Sgibbsstatic u_int
777297883Sgibbsahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
777397883Sgibbs	     u_int prev, u_int next, u_int tid)
777497883Sgibbs{
777597883Sgibbs	u_int tail_offset;
777697883Sgibbs
7777125448Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
777897883Sgibbs	if (!SCBID_IS_NULL(prev)) {
777997883Sgibbs		ahd_set_scbptr(ahd, prev);
778097883Sgibbs		ahd_outw(ahd, SCB_NEXT, next);
778197883Sgibbs	}
778297883Sgibbs
778397883Sgibbs	/*
7784133122Sgibbs	 * SCBs that have MK_MESSAGE set in them may
7785133122Sgibbs	 * cause the tail pointer to be updated without
7786133122Sgibbs	 * setting the next pointer of the previous tail.
7787133122Sgibbs	 * Only clear the tail if the removed SCB was
7788133122Sgibbs	 * the tail.
778997883Sgibbs	 */
779097883Sgibbs	tail_offset = WAITING_SCB_TAILS + (2 * tid);
779197883Sgibbs	if (SCBID_IS_NULL(next)
779297883Sgibbs	 && ahd_inw(ahd, tail_offset) == scbid)
779397883Sgibbs		ahd_outw(ahd, tail_offset, prev);
7794133122Sgibbs
779597883Sgibbs	ahd_add_scb_to_free_list(ahd, scbid);
779697883Sgibbs	return (next);
779797883Sgibbs}
779897883Sgibbs
779997883Sgibbs/*
780097883Sgibbs * Add the SCB as selected by SCBPTR onto the on chip list of
780197883Sgibbs * free hardware SCBs.  This list is empty/unused if we are not
780297883Sgibbs * performing SCB paging.
780397883Sgibbs */
780497883Sgibbsstatic void
780597883Sgibbsahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid)
780697883Sgibbs{
780797883Sgibbs/* XXX Need some other mechanism to designate "free". */
780897883Sgibbs	/*
780997883Sgibbs	 * Invalidate the tag so that our abort
781097883Sgibbs	 * routines don't think it's active.
781197883Sgibbs	ahd_outb(ahd, SCB_TAG, SCB_LIST_NULL);
781297883Sgibbs	 */
781397883Sgibbs}
781497883Sgibbs
781597883Sgibbs/******************************** Error Handling ******************************/
781697883Sgibbs/*
781797883Sgibbs * Abort all SCBs that match the given description (target/channel/lun/tag),
781897883Sgibbs * setting their status to the passed in status if the status has not already
781997883Sgibbs * been modified from CAM_REQ_INPROG.  This routine assumes that the sequencer
782097883Sgibbs * is paused before it is called.
782197883Sgibbs */
782297883Sgibbsint
782397883Sgibbsahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
782497883Sgibbs	       int lun, u_int tag, role_t role, uint32_t status)
782597883Sgibbs{
7826104023Sgibbs	struct		scb *scbp;
7827104023Sgibbs	struct		scb *scbp_next;
7828104023Sgibbs	u_int		i, j;
7829104023Sgibbs	u_int		maxtarget;
7830104023Sgibbs	u_int		minlun;
7831104023Sgibbs	u_int		maxlun;
7832104023Sgibbs	int		found;
7833104023Sgibbs	ahd_mode_state	saved_modes;
783497883Sgibbs
7835114623Sgibbs	/* restore this when we're done */
7836104023Sgibbs	saved_modes = ahd_save_modes(ahd);
7837114623Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
783897883Sgibbs
783997883Sgibbs	found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL,
784097883Sgibbs				   role, CAM_REQUEUE_REQ, SEARCH_COMPLETE);
784197883Sgibbs
784297883Sgibbs	/*
784397883Sgibbs	 * Clean out the busy target table for any untagged commands.
784497883Sgibbs	 */
784597883Sgibbs	i = 0;
784697883Sgibbs	maxtarget = 16;
784797883Sgibbs	if (target != CAM_TARGET_WILDCARD) {
784897883Sgibbs		i = target;
784997883Sgibbs		if (channel == 'B')
785097883Sgibbs			i += 8;
785197883Sgibbs		maxtarget = i + 1;
785297883Sgibbs	}
785397883Sgibbs
785497883Sgibbs	if (lun == CAM_LUN_WILDCARD) {
785597883Sgibbs		minlun = 0;
785697883Sgibbs		maxlun = AHD_NUM_LUNS_NONPKT;
785797883Sgibbs	} else if (lun >= AHD_NUM_LUNS_NONPKT) {
785897883Sgibbs		minlun = maxlun = 0;
785997883Sgibbs	} else {
786097883Sgibbs		minlun = lun;
786197883Sgibbs		maxlun = lun + 1;
786297883Sgibbs	}
786397883Sgibbs
786497883Sgibbs	if (role != ROLE_TARGET) {
786597883Sgibbs		for (;i < maxtarget; i++) {
786697883Sgibbs			for (j = minlun;j < maxlun; j++) {
786797883Sgibbs				u_int scbid;
786897883Sgibbs				u_int tcl;
786997883Sgibbs
7870102679Sgibbs				tcl = BUILD_TCL_RAW(i, 'A', j);
787197883Sgibbs				scbid = ahd_find_busy_tcl(ahd, tcl);
787297883Sgibbs				scbp = ahd_lookup_scb(ahd, scbid);
787397883Sgibbs				if (scbp == NULL
787497883Sgibbs				 || ahd_match_scb(ahd, scbp, target, channel,
787597883Sgibbs						  lun, tag, role) == 0)
787697883Sgibbs					continue;
787797883Sgibbs				ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(i, 'A', j));
787897883Sgibbs			}
787997883Sgibbs		}
788097883Sgibbs	}
788197883Sgibbs
788297883Sgibbs	/*
7883109588Sgibbs	 * Don't abort commands that have already completed,
7884109588Sgibbs	 * but haven't quite made it up to the host yet.
7885109588Sgibbs	 */
7886109588Sgibbs	ahd_flush_qoutfifo(ahd);
7887109588Sgibbs
7888109588Sgibbs	/*
788997883Sgibbs	 * Go through the pending CCB list and look for
789097883Sgibbs	 * commands for this target that are still active.
789197883Sgibbs	 * These are other tagged commands that were
789297883Sgibbs	 * disconnected when the reset occurred.
789397883Sgibbs	 */
789497883Sgibbs	scbp_next = LIST_FIRST(&ahd->pending_scbs);
789597883Sgibbs	while (scbp_next != NULL) {
789697883Sgibbs		scbp = scbp_next;
789797883Sgibbs		scbp_next = LIST_NEXT(scbp, pending_links);
789897883Sgibbs		if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) {
789997883Sgibbs			cam_status ostat;
790097883Sgibbs
7901123579Sgibbs			ostat = aic_get_transaction_status(scbp);
790297883Sgibbs			if (ostat == CAM_REQ_INPROG)
7903123579Sgibbs				aic_set_transaction_status(scbp, status);
7904123579Sgibbs			if (aic_get_transaction_status(scbp) != CAM_REQ_CMP)
7905123579Sgibbs				aic_freeze_scb(scbp);
790697883Sgibbs			if ((scbp->flags & SCB_ACTIVE) == 0)
790797883Sgibbs				printf("Inactive SCB on pending list\n");
790897883Sgibbs			ahd_done(ahd, scbp);
790997883Sgibbs			found++;
791097883Sgibbs		}
791197883Sgibbs	}
7912104023Sgibbs	ahd_restore_modes(ahd, saved_modes);
791397883Sgibbs	ahd_platform_abort_scbs(ahd, target, channel, lun, tag, role, status);
7914109588Sgibbs	ahd->flags |= AHD_UPDATE_PEND_CMDS;
791597883Sgibbs	return found;
791697883Sgibbs}
791797883Sgibbs
791897883Sgibbsstatic void
791997883Sgibbsahd_reset_current_bus(struct ahd_softc *ahd)
792097883Sgibbs{
792197883Sgibbs	uint8_t scsiseq;
792297883Sgibbs
792397883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
792497883Sgibbs	ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST);
7925102679Sgibbs	scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);
792697883Sgibbs	ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);
7927116935Sgibbs	ahd_flush_device_writes(ahd);
7928123579Sgibbs	aic_delay(AHD_BUSRESET_DELAY);
792997883Sgibbs	/* Turn off the bus reset */
7930102679Sgibbs	ahd_outb(ahd, SCSISEQ0, scsiseq);
7931116935Sgibbs	ahd_flush_device_writes(ahd);
7932123579Sgibbs	aic_delay(AHD_BUSRESET_DELAY);
793397883Sgibbs	if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {
793497883Sgibbs		/*
793597883Sgibbs		 * 2A Razor #474
793697883Sgibbs		 * Certain chip state is not cleared for
793797883Sgibbs		 * SCSI bus resets that we initiate, so
793897883Sgibbs		 * we must reset the chip.
793997883Sgibbs		 */
7940115917Sgibbs		ahd_reset(ahd, /*reinit*/TRUE);
794197883Sgibbs		ahd_intr_enable(ahd, /*enable*/TRUE);
794297883Sgibbs		AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
794397883Sgibbs	}
794497883Sgibbs
794597883Sgibbs	ahd_clear_intstat(ahd);
794697883Sgibbs}
794797883Sgibbs
794897883Sgibbsint
794997883Sgibbsahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
795097883Sgibbs{
795197883Sgibbs	struct	ahd_devinfo devinfo;
7952102679Sgibbs	u_int	initiator;
795397883Sgibbs	u_int	target;
795497883Sgibbs	u_int	max_scsiid;
795597883Sgibbs	int	found;
7956102679Sgibbs	u_int	fifo;
7957102679Sgibbs	u_int	next_fifo;
795897883Sgibbs
795997883Sgibbs	ahd->pending_device = NULL;
796097883Sgibbs
796197883Sgibbs	ahd_compile_devinfo(&devinfo,
796297883Sgibbs			    CAM_TARGET_WILDCARD,
796397883Sgibbs			    CAM_TARGET_WILDCARD,
796497883Sgibbs			    CAM_LUN_WILDCARD,
796597883Sgibbs			    channel, ROLE_UNKNOWN);
796697883Sgibbs	ahd_pause(ahd);
796797883Sgibbs
796897883Sgibbs	/* Make sure the sequencer is in a safe location. */
796997883Sgibbs	ahd_clear_critical_section(ahd);
797097883Sgibbs
7971153072Sru#ifdef AHD_TARGET_MODE
797297883Sgibbs	if ((ahd->flags & AHD_TARGETROLE) != 0) {
797397883Sgibbs		ahd_run_tqinfifo(ahd, /*paused*/TRUE);
797497883Sgibbs	}
797597883Sgibbs#endif
797697883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
797797883Sgibbs
797897883Sgibbs	/*
7979102679Sgibbs	 * Disable selections so no automatic hardware
7980102679Sgibbs	 * functions will modify chip state.
7981102679Sgibbs	 */
7982102679Sgibbs	ahd_outb(ahd, SCSISEQ0, 0);
7983102679Sgibbs	ahd_outb(ahd, SCSISEQ1, 0);
7984102679Sgibbs
7985102679Sgibbs	/*
7986102679Sgibbs	 * Safely shut down our DMA engines.  Always start with
7987102679Sgibbs	 * the FIFO that is not currently active (if any are
7988102679Sgibbs	 * actively connected).
7989102679Sgibbs	 */
7990102679Sgibbs	next_fifo = fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
7991107441Sscottl	if (next_fifo > CURRFIFO_1)
7992107441Sscottl		/* If disconneced, arbitrarily start with FIFO1. */
7993107441Sscottl		next_fifo = fifo = 0;
7994102679Sgibbs	do {
7995107441Sscottl		next_fifo ^= CURRFIFO_1;
7996102679Sgibbs		ahd_set_modes(ahd, next_fifo, next_fifo);
7997104023Sgibbs		ahd_outb(ahd, DFCNTRL,
7998104023Sgibbs			 ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN));
7999102679Sgibbs		while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0)
8000123579Sgibbs			aic_delay(10);
8001102679Sgibbs		/*
8002102679Sgibbs		 * Set CURRFIFO to the now inactive channel.
8003102679Sgibbs		 */
8004102679Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
8005102679Sgibbs		ahd_outb(ahd, DFFSTAT, next_fifo);
8006102679Sgibbs	} while (next_fifo != fifo);
8007114623Sgibbs
8008102679Sgibbs	/*
800997883Sgibbs	 * Reset the bus if we are initiating this reset
801097883Sgibbs	 */
801197883Sgibbs	ahd_clear_msg_state(ahd);
8012104023Sgibbs	ahd_outb(ahd, SIMODE1,
8013123579Sgibbs		 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
8014114623Sgibbs
801597883Sgibbs	if (initiate_reset)
801697883Sgibbs		ahd_reset_current_bus(ahd);
8017114623Sgibbs
801897883Sgibbs	ahd_clear_intstat(ahd);
801997883Sgibbs
802097883Sgibbs	/*
802197883Sgibbs	 * Clean up all the state information for the
802297883Sgibbs	 * pending transactions on this bus.
802397883Sgibbs	 */
802497883Sgibbs	found = ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, channel,
802597883Sgibbs			       CAM_LUN_WILDCARD, SCB_LIST_NULL,
802697883Sgibbs			       ROLE_UNKNOWN, CAM_SCSI_BUS_RESET);
802797883Sgibbs
8028102679Sgibbs	/*
8029102679Sgibbs	 * Cleanup anything left in the FIFOs.
8030102679Sgibbs	 */
8031102679Sgibbs	ahd_clear_fifo(ahd, 0);
8032102679Sgibbs	ahd_clear_fifo(ahd, 1);
8033102679Sgibbs
8034102679Sgibbs	/*
8035102679Sgibbs	 * Revert to async/narrow transfers until we renegotiate.
8036102679Sgibbs	 */
8037102679Sgibbs	max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
8038102679Sgibbs	for (target = 0; target <= max_scsiid; target++) {
8039102679Sgibbs
8040102679Sgibbs		if (ahd->enabled_targets[target] == NULL)
8041102679Sgibbs			continue;
8042102679Sgibbs		for (initiator = 0; initiator <= max_scsiid; initiator++) {
8043102679Sgibbs			struct ahd_devinfo devinfo;
8044102679Sgibbs
8045102679Sgibbs			ahd_compile_devinfo(&devinfo, target, initiator,
8046102679Sgibbs					    CAM_LUN_WILDCARD,
8047102679Sgibbs					    'A', ROLE_UNKNOWN);
8048102679Sgibbs			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
8049102679Sgibbs				      AHD_TRANS_CUR, /*paused*/TRUE);
8050102679Sgibbs			ahd_set_syncrate(ahd, &devinfo, /*period*/0,
8051102679Sgibbs					 /*offset*/0, /*ppr_options*/0,
8052102679Sgibbs					 AHD_TRANS_CUR, /*paused*/TRUE);
8053102679Sgibbs		}
8054102679Sgibbs	}
8055102679Sgibbs
805697883Sgibbs#ifdef AHD_TARGET_MODE
805797883Sgibbs	max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
805897883Sgibbs
805997883Sgibbs	/*
806097883Sgibbs	 * Send an immediate notify ccb to all target more peripheral
806197883Sgibbs	 * drivers affected by this action.
806297883Sgibbs	 */
806397883Sgibbs	for (target = 0; target <= max_scsiid; target++) {
806497883Sgibbs		struct ahd_tmode_tstate* tstate;
806597883Sgibbs		u_int lun;
806697883Sgibbs
806797883Sgibbs		tstate = ahd->enabled_targets[target];
806897883Sgibbs		if (tstate == NULL)
806997883Sgibbs			continue;
807097883Sgibbs		for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
807197883Sgibbs			struct ahd_tmode_lstate* lstate;
807297883Sgibbs
807397883Sgibbs			lstate = tstate->enabled_luns[lun];
807497883Sgibbs			if (lstate == NULL)
807597883Sgibbs				continue;
807697883Sgibbs
807797883Sgibbs			ahd_queue_lstate_event(ahd, lstate, CAM_TARGET_WILDCARD,
807897883Sgibbs					       EVENT_TYPE_BUS_RESET, /*arg*/0);
807997883Sgibbs			ahd_send_lstate_events(ahd, lstate);
808097883Sgibbs		}
808197883Sgibbs	}
808297883Sgibbs#endif
808397883Sgibbs	/* Notify the XPT that a bus reset occurred */
808497883Sgibbs	ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
808597883Sgibbs		       CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
8086104023Sgibbs	ahd_restart(ahd);
808797883Sgibbs	/*
808897883Sgibbs	 * Freeze the SIMQ until our poller can determine that
808997883Sgibbs	 * the bus reset has really gone away.  We set the initial
809097883Sgibbs	 * timer to 0 to have the check performed as soon as possible
809197883Sgibbs	 * from the timer context.
809297883Sgibbs	 */
8093102679Sgibbs	if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) {
8094102679Sgibbs		ahd->flags |= AHD_RESET_POLL_ACTIVE;
8095123579Sgibbs		aic_freeze_simq(ahd);
8096123579Sgibbs		aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
8097102679Sgibbs	}
809897883Sgibbs	return (found);
809997883Sgibbs}
810097883Sgibbs
810197883Sgibbs
8102137870Sgibbs#define AHD_RESET_POLL_MS 1
810397883Sgibbsstatic void
810497883Sgibbsahd_reset_poll(void *arg)
810597883Sgibbs{
8106168807Sscottl	struct	ahd_softc *ahd = (struct ahd_softc *)arg;
810797883Sgibbs	u_int	scsiseq1;
810897883Sgibbs
8109168807Sscottl	ahd_lock(ahd);
8110102679Sgibbs	ahd_pause(ahd);
8111104023Sgibbs	ahd_update_modes(ahd);
8112104023Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
8113102679Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
8114102679Sgibbs	if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
8115137870Sgibbs		aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS,
811697883Sgibbs				ahd_reset_poll, ahd);
8117102679Sgibbs		ahd_unpause(ahd);
8118168807Sscottl		ahd_unlock(ahd);
8119102679Sgibbs		return;
812097883Sgibbs	}
812197883Sgibbs
812297883Sgibbs	/* Reset is now low.  Complete chip reinitialization. */
812397883Sgibbs	ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
812497883Sgibbs	scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
812597883Sgibbs	ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
8126102679Sgibbs	ahd_unpause(ahd);
8127102679Sgibbs	ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
8128123579Sgibbs	aic_release_simq(ahd);
8129168807Sscottl	ahd_unlock(ahd);
813097883Sgibbs}
813197883Sgibbs
8132109588Sgibbs/**************************** Statistics Processing ***************************/
8133109588Sgibbsstatic void
8134109588Sgibbsahd_stat_timer(void *arg)
8135109588Sgibbs{
8136168807Sscottl	struct	ahd_softc *ahd = (struct ahd_softc *)arg;
8137109588Sgibbs	int	enint_coal;
8138109588Sgibbs
8139168807Sscottl	ahd_lock(ahd);
8140115329Sgibbs	enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
8141115329Sgibbs	if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold)
8142115329Sgibbs		enint_coal |= ENINT_COALESCE;
8143115329Sgibbs	else if (ahd->cmdcmplt_total < ahd->int_coalescing_stop_threshold)
8144115329Sgibbs		enint_coal &= ~ENINT_COALESCE;
8145109588Sgibbs
8146115329Sgibbs	if (enint_coal != (ahd->hs_mailbox & ENINT_COALESCE)) {
8147115329Sgibbs		ahd_enable_coalescing(ahd, enint_coal);
8148109588Sgibbs#ifdef AHD_DEBUG
8149115329Sgibbs		if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0)
8150115329Sgibbs			printf("%s: Interrupt coalescing "
8151109588Sgibbs			       "now %sabled. Cmds %d\n",
8152109588Sgibbs			       ahd_name(ahd),
8153115329Sgibbs			       (enint_coal & ENINT_COALESCE) ? "en" : "dis",
8154109588Sgibbs			       ahd->cmdcmplt_total);
8155109588Sgibbs#endif
8156109588Sgibbs	}
8157109588Sgibbs
8158109588Sgibbs	ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1);
8159109588Sgibbs	ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket];
8160109588Sgibbs	ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;
8161137870Sgibbs	aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
8162109588Sgibbs			ahd_stat_timer, ahd);
8163168807Sscottl	ahd_unlock(ahd);
8164109588Sgibbs}
8165109588Sgibbs
816697883Sgibbs/****************************** Status Processing *****************************/
816797883Sgibbsvoid
816897883Sgibbsahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
816997883Sgibbs{
817097883Sgibbs	if (scb->hscb->shared_data.istatus.scsi_status != 0) {
817197883Sgibbs		ahd_handle_scsi_status(ahd, scb);
817297883Sgibbs	} else {
817397883Sgibbs		ahd_calc_residual(ahd, scb);
817497883Sgibbs		ahd_done(ahd, scb);
817597883Sgibbs	}
817697883Sgibbs}
817797883Sgibbs
817897883Sgibbsvoid
817997883Sgibbsahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
818097883Sgibbs{
8181123579Sgibbs	struct	hardware_scb *hscb;
8182123579Sgibbs	int	paused;
818397883Sgibbs
818497883Sgibbs	/*
818597883Sgibbs	 * The sequencer freezes its select-out queue
818697883Sgibbs	 * anytime a SCSI status error occurs.  We must
8187125448Sgibbs	 * handle the error and increment our qfreeze count
8188125448Sgibbs	 * to allow the sequencer to continue.  We don't
8189125448Sgibbs	 * bother clearing critical sections here since all
8190125448Sgibbs	 * operations are on data structures that the sequencer
8191125448Sgibbs	 * is not touching once the queue is frozen.
819297883Sgibbs	 */
819397883Sgibbs	hscb = scb->hscb;
819497883Sgibbs
8195123579Sgibbs	if (ahd_is_paused(ahd)) {
8196123579Sgibbs		paused = 1;
8197123579Sgibbs	} else {
8198123579Sgibbs		paused = 0;
8199123579Sgibbs		ahd_pause(ahd);
8200123579Sgibbs	}
8201123579Sgibbs
820297883Sgibbs	/* Freeze the queue until the client sees the error. */
820397883Sgibbs	ahd_freeze_devq(ahd, scb);
8204123579Sgibbs	aic_freeze_scb(scb);
8205125448Sgibbs	ahd->qfreeze_cnt++;
8206125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
8207114623Sgibbs
8208123579Sgibbs	if (paused == 0)
8209123579Sgibbs		ahd_unpause(ahd);
8210123579Sgibbs
8211102679Sgibbs	/* Don't want to clobber the original sense code */
8212102679Sgibbs	if ((scb->flags & SCB_SENSE) != 0) {
8213102679Sgibbs		/*
8214102679Sgibbs		 * Clear the SCB_SENSE Flag and perform
8215102679Sgibbs		 * a normal command completion.
8216102679Sgibbs		 */
8217102679Sgibbs		scb->flags &= ~SCB_SENSE;
8218123579Sgibbs		aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
8219102679Sgibbs		ahd_done(ahd, scb);
8220102679Sgibbs		return;
8221102679Sgibbs	}
8222123579Sgibbs	aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
8223123579Sgibbs	aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status);
822497883Sgibbs	switch (hscb->shared_data.istatus.scsi_status) {
822597883Sgibbs	case STATUS_PKT_SENSE:
822697883Sgibbs	{
822797883Sgibbs		struct scsi_status_iu_header *siu;
822897883Sgibbs
822997883Sgibbs		ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD);
823097883Sgibbs		siu = (struct scsi_status_iu_header *)scb->sense_data;
8231123579Sgibbs		aic_set_scsi_status(scb, siu->status);
823297883Sgibbs#ifdef AHD_DEBUG
8233107441Sscottl		if ((ahd_debug & AHD_SHOW_SENSE) != 0) {
823497883Sgibbs			ahd_print_path(ahd, scb);
823597883Sgibbs			printf("SCB 0x%x Received PKT Status of 0x%x\n",
823697883Sgibbs			       SCB_GET_TAG(scb), siu->status);
823797883Sgibbs			printf("\tflags = 0x%x, sense len = 0x%x, "
823897883Sgibbs			       "pktfail = 0x%x\n",
823997883Sgibbs			       siu->flags, scsi_4btoul(siu->sense_length),
824097883Sgibbs			       scsi_4btoul(siu->pkt_failures_length));
8241107441Sscottl		}
824297883Sgibbs#endif
824397883Sgibbs		if ((siu->flags & SIU_RSPVALID) != 0) {
824497883Sgibbs			ahd_print_path(ahd, scb);
824597883Sgibbs			if (scsi_4btoul(siu->pkt_failures_length) < 4) {
824697883Sgibbs				printf("Unable to parse pkt_failures\n");
824797883Sgibbs			} else {
824897883Sgibbs
824997883Sgibbs				switch (SIU_PKTFAIL_CODE(siu)) {
825097883Sgibbs				case SIU_PFC_NONE:
825197883Sgibbs					printf("No packet failure found\n");
8252199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
825397883Sgibbs					break;
825497883Sgibbs				case SIU_PFC_CIU_FIELDS_INVALID:
825597883Sgibbs					printf("Invalid Command IU Field\n");
8256199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
825797883Sgibbs					break;
825897883Sgibbs				case SIU_PFC_TMF_NOT_SUPPORTED:
825997883Sgibbs					printf("TMF not supportd\n");
8260199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
826197883Sgibbs					break;
826297883Sgibbs				case SIU_PFC_TMF_FAILED:
826397883Sgibbs					printf("TMF failed\n");
8264199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
826597883Sgibbs					break;
826697883Sgibbs				case SIU_PFC_INVALID_TYPE_CODE:
826797883Sgibbs					printf("Invalid L_Q Type code\n");
8268199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
826997883Sgibbs					break;
827097883Sgibbs				case SIU_PFC_ILLEGAL_REQUEST:
8271199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
827297883Sgibbs					printf("Illegal request\n");
827397883Sgibbs				default:
827497883Sgibbs					break;
827597883Sgibbs				}
827697883Sgibbs			}
827797883Sgibbs			if (siu->status == SCSI_STATUS_OK)
8278123579Sgibbs				aic_set_transaction_status(scb,
827997883Sgibbs							   CAM_REQ_CMP_ERR);
828097883Sgibbs		}
828197883Sgibbs		if ((siu->flags & SIU_SNSVALID) != 0) {
828297883Sgibbs			scb->flags |= SCB_PKT_SENSE;
828397883Sgibbs#ifdef AHD_DEBUG
828497883Sgibbs			if ((ahd_debug & AHD_SHOW_SENSE) != 0)
828597883Sgibbs				printf("Sense data available\n");
828697883Sgibbs#endif
828797883Sgibbs		}
828897883Sgibbs		ahd_done(ahd, scb);
828997883Sgibbs		break;
829097883Sgibbs	}
829197883Sgibbs	case SCSI_STATUS_CMD_TERMINATED:
829297883Sgibbs	case SCSI_STATUS_CHECK_COND:
829397883Sgibbs	{
829497883Sgibbs		struct ahd_devinfo devinfo;
829597883Sgibbs		struct ahd_dma_seg *sg;
829697883Sgibbs		struct scsi_sense *sc;
829797883Sgibbs		struct ahd_initiator_tinfo *targ_info;
829897883Sgibbs		struct ahd_tmode_tstate *tstate;
829997883Sgibbs		struct ahd_transinfo *tinfo;
830097883Sgibbs#ifdef AHD_DEBUG
830197883Sgibbs		if (ahd_debug & AHD_SHOW_SENSE) {
830297883Sgibbs			ahd_print_path(ahd, scb);
830397883Sgibbs			printf("SCB %d: requests Check Status\n",
830497883Sgibbs			       SCB_GET_TAG(scb));
830597883Sgibbs		}
830697883Sgibbs#endif
830797883Sgibbs
8308123579Sgibbs		if (aic_perform_autosense(scb) == 0)
830997883Sgibbs			break;
831097883Sgibbs
831197883Sgibbs		ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
831297883Sgibbs				    SCB_GET_TARGET(ahd, scb),
831397883Sgibbs				    SCB_GET_LUN(scb),
831497883Sgibbs				    SCB_GET_CHANNEL(ahd, scb),
831597883Sgibbs				    ROLE_INITIATOR);
831697883Sgibbs		targ_info = ahd_fetch_transinfo(ahd,
831797883Sgibbs						devinfo.channel,
831897883Sgibbs						devinfo.our_scsiid,
831997883Sgibbs						devinfo.target,
832097883Sgibbs						&tstate);
832197883Sgibbs		tinfo = &targ_info->curr;
832297883Sgibbs		sg = scb->sg_list;
832397883Sgibbs		sc = (struct scsi_sense *)hscb->shared_data.idata.cdb;
832497883Sgibbs		/*
832597883Sgibbs		 * Save off the residual if there is one.
832697883Sgibbs		 */
832797883Sgibbs		ahd_update_residual(ahd, scb);
832897883Sgibbs#ifdef AHD_DEBUG
832997883Sgibbs		if (ahd_debug & AHD_SHOW_SENSE) {
833097883Sgibbs			ahd_print_path(ahd, scb);
833197883Sgibbs			printf("Sending Sense\n");
833297883Sgibbs		}
833397883Sgibbs#endif
833497883Sgibbs		scb->sg_count = 0;
833597883Sgibbs		sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb),
8336123579Sgibbs				  aic_get_sense_bufsize(ahd, scb),
833797883Sgibbs				  /*last*/TRUE);
833897883Sgibbs		sc->opcode = REQUEST_SENSE;
833997883Sgibbs		sc->byte2 = 0;
834097883Sgibbs		if (tinfo->protocol_version <= SCSI_REV_2
834197883Sgibbs		 && SCB_GET_LUN(scb) < 8)
834297883Sgibbs			sc->byte2 = SCB_GET_LUN(scb) << 5;
834397883Sgibbs		sc->unused[0] = 0;
834497883Sgibbs		sc->unused[1] = 0;
8345123579Sgibbs		sc->length = aic_get_sense_bufsize(ahd, scb);
834697883Sgibbs		sc->control = 0;
834797883Sgibbs
834897883Sgibbs		/*
834997883Sgibbs		 * We can't allow the target to disconnect.
835097883Sgibbs		 * This will be an untagged transaction and
835197883Sgibbs		 * having the target disconnect will make this
835297883Sgibbs		 * transaction indestinguishable from outstanding
835397883Sgibbs		 * tagged transactions.
835497883Sgibbs		 */
835597883Sgibbs		hscb->control = 0;
835697883Sgibbs
835797883Sgibbs		/*
835897883Sgibbs		 * This request sense could be because the
835997883Sgibbs		 * the device lost power or in some other
836097883Sgibbs		 * way has lost our transfer negotiations.
836197883Sgibbs		 * Renegotiate if appropriate.  Unit attention
836297883Sgibbs		 * errors will be reported before any data
836397883Sgibbs		 * phases occur.
836497883Sgibbs		 */
8365123579Sgibbs		if (aic_get_residual(scb) == aic_get_transfer_length(scb)) {
836697883Sgibbs			ahd_update_neg_request(ahd, &devinfo,
836797883Sgibbs					       tstate, targ_info,
8368107441Sscottl					       AHD_NEG_IF_NON_ASYNC);
836997883Sgibbs		}
837097883Sgibbs		if (tstate->auto_negotiate & devinfo.target_mask) {
837197883Sgibbs			hscb->control |= MK_MESSAGE;
837297883Sgibbs			scb->flags &=
837397883Sgibbs			    ~(SCB_NEGOTIATE|SCB_ABORT|SCB_DEVICE_RESET);
837497883Sgibbs			scb->flags |= SCB_AUTO_NEGOTIATE;
837597883Sgibbs		}
837697883Sgibbs		hscb->cdb_len = sizeof(*sc);
837797883Sgibbs		ahd_setup_data_scb(ahd, scb);
837897883Sgibbs		scb->flags |= SCB_SENSE;
837997883Sgibbs		ahd_queue_scb(ahd, scb);
838097883Sgibbs		/*
838197883Sgibbs		 * Ensure we have enough time to actually
8382133911Sgibbs		 * retrieve the sense, but only schedule
8383133911Sgibbs		 * the timer if we are not in recovery or
8384133911Sgibbs		 * this is a recovery SCB that is allowed
8385133911Sgibbs		 * to have an active timer.
838697883Sgibbs		 */
8387133911Sgibbs		if (ahd->scb_data.recovery_scbs == 0
8388133911Sgibbs		 || (scb->flags & SCB_RECOVERY_SCB) != 0)
8389137870Sgibbs			aic_scb_timer_reset(scb, 5 * 1000);
839097883Sgibbs		break;
839197883Sgibbs	}
839297883Sgibbs	case SCSI_STATUS_OK:
839397883Sgibbs		printf("%s: Interrupted for staus of 0???\n",
839497883Sgibbs		       ahd_name(ahd));
839597883Sgibbs		/* FALLTHROUGH */
839697883Sgibbs	default:
839797883Sgibbs		ahd_done(ahd, scb);
839897883Sgibbs		break;
839997883Sgibbs	}
840097883Sgibbs}
840197883Sgibbs
840297883Sgibbs/*
840397883Sgibbs * Calculate the residual for a just completed SCB.
840497883Sgibbs */
840597883Sgibbsvoid
840697883Sgibbsahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
840797883Sgibbs{
840897883Sgibbs	struct hardware_scb *hscb;
840997883Sgibbs	struct initiator_status *spkt;
841097883Sgibbs	uint32_t sgptr;
841197883Sgibbs	uint32_t resid_sgptr;
841297883Sgibbs	uint32_t resid;
841397883Sgibbs
841497883Sgibbs	/*
841597883Sgibbs	 * 5 cases.
841697883Sgibbs	 * 1) No residual.
841797883Sgibbs	 *    SG_STATUS_VALID clear in sgptr.
841897883Sgibbs	 * 2) Transferless command
841997883Sgibbs	 * 3) Never performed any transfers.
842097883Sgibbs	 *    sgptr has SG_FULL_RESID set.
842197883Sgibbs	 * 4) No residual but target did not
842297883Sgibbs	 *    save data pointers after the
842397883Sgibbs	 *    last transfer, so sgptr was
842497883Sgibbs	 *    never updated.
842597883Sgibbs	 * 5) We have a partial residual.
842697883Sgibbs	 *    Use residual_sgptr to determine
842797883Sgibbs	 *    where we are.
842897883Sgibbs	 */
842997883Sgibbs
843097883Sgibbs	hscb = scb->hscb;
8431123579Sgibbs	sgptr = aic_le32toh(hscb->sgptr);
843297883Sgibbs	if ((sgptr & SG_STATUS_VALID) == 0)
843397883Sgibbs		/* Case 1 */
843497883Sgibbs		return;
843597883Sgibbs	sgptr &= ~SG_STATUS_VALID;
843697883Sgibbs
843797883Sgibbs	if ((sgptr & SG_LIST_NULL) != 0)
843897883Sgibbs		/* Case 2 */
843997883Sgibbs		return;
844097883Sgibbs
844197883Sgibbs	/*
844297883Sgibbs	 * Residual fields are the same in both
844397883Sgibbs	 * target and initiator status packets,
844497883Sgibbs	 * so we can always use the initiator fields
844597883Sgibbs	 * regardless of the role for this SCB.
844697883Sgibbs	 */
844797883Sgibbs	spkt = &hscb->shared_data.istatus;
8448123579Sgibbs	resid_sgptr = aic_le32toh(spkt->residual_sgptr);
844997883Sgibbs	if ((sgptr & SG_FULL_RESID) != 0) {
845097883Sgibbs		/* Case 3 */
8451123579Sgibbs		resid = aic_get_transfer_length(scb);
845297883Sgibbs	} else if ((resid_sgptr & SG_LIST_NULL) != 0) {
845397883Sgibbs		/* Case 4 */
845497883Sgibbs		return;
845597883Sgibbs	} else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) {
845697883Sgibbs		ahd_print_path(ahd, scb);
845797883Sgibbs		printf("data overrun detected Tag == 0x%x.\n",
845897883Sgibbs		       SCB_GET_TAG(scb));
845997883Sgibbs		ahd_freeze_devq(ahd, scb);
8460123579Sgibbs		aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
8461123579Sgibbs		aic_freeze_scb(scb);
846297883Sgibbs		return;
846397883Sgibbs	} else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {
846497883Sgibbs		panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);
846597883Sgibbs		/* NOTREACHED */
846697883Sgibbs	} else {
846797883Sgibbs		struct ahd_dma_seg *sg;
846897883Sgibbs
846997883Sgibbs		/*
847097883Sgibbs		 * Remainder of the SG where the transfer
847197883Sgibbs		 * stopped.
847297883Sgibbs		 */
8473123579Sgibbs		resid = aic_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK;
847497883Sgibbs		sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK);
847597883Sgibbs
847697883Sgibbs		/* The residual sg_ptr always points to the next sg */
847797883Sgibbs		sg--;
847897883Sgibbs
847997883Sgibbs		/*
848097883Sgibbs		 * Add up the contents of all residual
848197883Sgibbs		 * SG segments that are after the SG where
848297883Sgibbs		 * the transfer stopped.
848397883Sgibbs		 */
8484123579Sgibbs		while ((aic_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) {
848597883Sgibbs			sg++;
8486123579Sgibbs			resid += aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
848797883Sgibbs		}
848897883Sgibbs	}
848997883Sgibbs	if ((scb->flags & SCB_SENSE) == 0)
8490123579Sgibbs		aic_set_residual(scb, resid);
849197883Sgibbs	else
8492123579Sgibbs		aic_set_sense_residual(scb, resid);
849397883Sgibbs
849497883Sgibbs#ifdef AHD_DEBUG
849597883Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0) {
849697883Sgibbs		ahd_print_path(ahd, scb);
8497109588Sgibbs		printf("Handled %sResidual of %d bytes\n",
8498109588Sgibbs		       (scb->flags & SCB_SENSE) ? "Sense " : "", resid);
849997883Sgibbs	}
850097883Sgibbs#endif
850197883Sgibbs}
850297883Sgibbs
850397883Sgibbs/******************************* Target Mode **********************************/
850497883Sgibbs#ifdef AHD_TARGET_MODE
850597883Sgibbs/*
850697883Sgibbs * Add a target mode event to this lun's queue
850797883Sgibbs */
850897883Sgibbsstatic void
850997883Sgibbsahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate,
851097883Sgibbs		       u_int initiator_id, u_int event_type, u_int event_arg)
851197883Sgibbs{
851297883Sgibbs	struct ahd_tmode_event *event;
851397883Sgibbs	int pending;
851497883Sgibbs
851597883Sgibbs	xpt_freeze_devq(lstate->path, /*count*/1);
851697883Sgibbs	if (lstate->event_w_idx >= lstate->event_r_idx)
851797883Sgibbs		pending = lstate->event_w_idx - lstate->event_r_idx;
851897883Sgibbs	else
851997883Sgibbs		pending = AHD_TMODE_EVENT_BUFFER_SIZE + 1
852097883Sgibbs			- (lstate->event_r_idx - lstate->event_w_idx);
852197883Sgibbs
852297883Sgibbs	if (event_type == EVENT_TYPE_BUS_RESET
852397883Sgibbs	 || event_type == MSG_BUS_DEV_RESET) {
852497883Sgibbs		/*
852597883Sgibbs		 * Any earlier events are irrelevant, so reset our buffer.
852697883Sgibbs		 * This has the effect of allowing us to deal with reset
852797883Sgibbs		 * floods (an external device holding down the reset line)
852897883Sgibbs		 * without losing the event that is really interesting.
852997883Sgibbs		 */
853097883Sgibbs		lstate->event_r_idx = 0;
853197883Sgibbs		lstate->event_w_idx = 0;
853297883Sgibbs		xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE);
853397883Sgibbs	}
853497883Sgibbs
853597883Sgibbs	if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) {
853697883Sgibbs		xpt_print_path(lstate->path);
853797883Sgibbs		printf("immediate event %x:%x lost\n",
853897883Sgibbs		       lstate->event_buffer[lstate->event_r_idx].event_type,
853997883Sgibbs		       lstate->event_buffer[lstate->event_r_idx].event_arg);
854097883Sgibbs		lstate->event_r_idx++;
854197883Sgibbs		if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
854297883Sgibbs			lstate->event_r_idx = 0;
854397883Sgibbs		xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE);
854497883Sgibbs	}
854597883Sgibbs
854697883Sgibbs	event = &lstate->event_buffer[lstate->event_w_idx];
854797883Sgibbs	event->initiator_id = initiator_id;
854897883Sgibbs	event->event_type = event_type;
854997883Sgibbs	event->event_arg = event_arg;
855097883Sgibbs	lstate->event_w_idx++;
855197883Sgibbs	if (lstate->event_w_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
855297883Sgibbs		lstate->event_w_idx = 0;
855397883Sgibbs}
855497883Sgibbs
855597883Sgibbs/*
855697883Sgibbs * Send any target mode events queued up waiting
855797883Sgibbs * for immediate notify resources.
855897883Sgibbs */
855997883Sgibbsvoid
856097883Sgibbsahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate)
856197883Sgibbs{
856297883Sgibbs	struct ccb_hdr *ccbh;
8563237825Sken	struct ccb_immediate_notify *inot;
856497883Sgibbs
856597883Sgibbs	while (lstate->event_r_idx != lstate->event_w_idx
856697883Sgibbs	    && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) {
856797883Sgibbs		struct ahd_tmode_event *event;
856897883Sgibbs
856997883Sgibbs		event = &lstate->event_buffer[lstate->event_r_idx];
857097883Sgibbs		SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle);
8571237825Sken		inot = (struct ccb_immediate_notify *)ccbh;
857297883Sgibbs		switch (event->event_type) {
857397883Sgibbs		case EVENT_TYPE_BUS_RESET:
857497883Sgibbs			ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN;
857597883Sgibbs			break;
857697883Sgibbs		default:
857797883Sgibbs			ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
8578237825Sken			inot->arg = event->event_type;
8579237825Sken			inot->seq_id = event->event_arg;
858097883Sgibbs			break;
858197883Sgibbs		}
858297883Sgibbs		inot->initiator_id = event->initiator_id;
858397883Sgibbs		xpt_done((union ccb *)inot);
858497883Sgibbs		lstate->event_r_idx++;
858597883Sgibbs		if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
858697883Sgibbs			lstate->event_r_idx = 0;
858797883Sgibbs	}
858897883Sgibbs}
858997883Sgibbs#endif
859097883Sgibbs
859197883Sgibbs/******************** Sequencer Program Patching/Download *********************/
859297883Sgibbs
859397883Sgibbs#ifdef AHD_DUMP_SEQ
859497883Sgibbsvoid
859597883Sgibbsahd_dumpseq(struct ahd_softc* ahd)
859697883Sgibbs{
859797883Sgibbs	int i;
859897883Sgibbs	int max_prog;
859997883Sgibbs
860097883Sgibbs	max_prog = 2048;
860197883Sgibbs
860297883Sgibbs	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8603123579Sgibbs	ahd_outw(ahd, PRGMCNT, 0);
860497883Sgibbs	for (i = 0; i < max_prog; i++) {
860597883Sgibbs		uint8_t ins_bytes[4];
860697883Sgibbs
860797883Sgibbs		ahd_insb(ahd, SEQRAM, ins_bytes, 4);
860897883Sgibbs		printf("0x%08x\n", ins_bytes[0] << 24
860997883Sgibbs				 | ins_bytes[1] << 16
861097883Sgibbs				 | ins_bytes[2] << 8
861197883Sgibbs				 | ins_bytes[3]);
861297883Sgibbs	}
861397883Sgibbs}
861497883Sgibbs#endif
861597883Sgibbs
861697883Sgibbsstatic void
861797883Sgibbsahd_loadseq(struct ahd_softc *ahd)
861897883Sgibbs{
861997883Sgibbs	struct	cs cs_table[num_critical_sections];
862097883Sgibbs	u_int	begin_set[num_critical_sections];
862197883Sgibbs	u_int	end_set[num_critical_sections];
862297883Sgibbs	struct	patch *cur_patch;
862397883Sgibbs	u_int	cs_count;
862497883Sgibbs	u_int	cur_cs;
862597883Sgibbs	u_int	i;
862697883Sgibbs	int	downloaded;
862797883Sgibbs	u_int	skip_addr;
862897883Sgibbs	u_int	sg_prefetch_cnt;
862997883Sgibbs	u_int	sg_prefetch_cnt_limit;
863097883Sgibbs	u_int	sg_prefetch_align;
863197883Sgibbs	u_int	sg_size;
8632129134Sgibbs	u_int	cacheline_mask;
863397883Sgibbs	uint8_t	download_consts[DOWNLOAD_CONST_COUNT];
863497883Sgibbs
863597883Sgibbs	if (bootverbose)
863697883Sgibbs		printf("%s: Downloading Sequencer Program...",
863797883Sgibbs		       ahd_name(ahd));
863897883Sgibbs
8639129134Sgibbs#if DOWNLOAD_CONST_COUNT != 8
864097883Sgibbs#error "Download Const Mismatch"
864197883Sgibbs#endif
864297883Sgibbs	/*
864397883Sgibbs	 * Start out with 0 critical sections
864497883Sgibbs	 * that apply to this firmware load.
864597883Sgibbs	 */
864697883Sgibbs	cs_count = 0;
864797883Sgibbs	cur_cs = 0;
864897883Sgibbs	memset(begin_set, 0, sizeof(begin_set));
864997883Sgibbs	memset(end_set, 0, sizeof(end_set));
865097883Sgibbs
865197883Sgibbs	/*
865297883Sgibbs	 * Setup downloadable constant table.
865397883Sgibbs	 *
865497883Sgibbs	 * The computation for the S/G prefetch variables is
865597883Sgibbs	 * a bit complicated.  We would like to always fetch
865697883Sgibbs	 * in terms of cachelined sized increments.  However,
865797883Sgibbs	 * if the cacheline is not an even multiple of the
865897883Sgibbs	 * SG element size or is larger than our SG RAM, using
865997883Sgibbs	 * just the cache size might leave us with only a portion
866097883Sgibbs	 * of an SG element at the tail of a prefetch.  If the
866197883Sgibbs	 * cacheline is larger than our S/G prefetch buffer less
866297883Sgibbs	 * the size of an SG element, we may round down to a cacheline
866397883Sgibbs	 * that doesn't contain any or all of the S/G of interest
866497883Sgibbs	 * within the bounds of our S/G ram.  Provide variables to
866597883Sgibbs	 * the sequencer that will allow it to handle these edge
866697883Sgibbs	 * cases.
866797883Sgibbs	 */
866897883Sgibbs	/* Start by aligning to the nearest cacheline. */
866997883Sgibbs	sg_prefetch_align = ahd->pci_cachesize;
867097883Sgibbs	if (sg_prefetch_align == 0)
8671111653Sgibbs		sg_prefetch_align = 8;
867297883Sgibbs	/* Round down to the nearest power of 2. */
867397883Sgibbs	while (powerof2(sg_prefetch_align) == 0)
867497883Sgibbs		sg_prefetch_align--;
8675129134Sgibbs
8676129134Sgibbs	cacheline_mask = sg_prefetch_align - 1;
8677129134Sgibbs
867897883Sgibbs	/*
867997883Sgibbs	 * If the cacheline boundary is greater than half our prefetch RAM
868097883Sgibbs	 * we risk not being able to fetch even a single complete S/G
868197883Sgibbs	 * segment if we align to that boundary.
868297883Sgibbs	 */
868397883Sgibbs	if (sg_prefetch_align > CCSGADDR_MAX/2)
868497883Sgibbs		sg_prefetch_align = CCSGADDR_MAX/2;
868597883Sgibbs	/* Start by fetching a single cacheline. */
868697883Sgibbs	sg_prefetch_cnt = sg_prefetch_align;
868797883Sgibbs	/*
868897883Sgibbs	 * Increment the prefetch count by cachelines until
868997883Sgibbs	 * at least one S/G element will fit.
869097883Sgibbs	 */
869197883Sgibbs	sg_size = sizeof(struct ahd_dma_seg);
869297883Sgibbs	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
869397883Sgibbs		sg_size = sizeof(struct ahd_dma64_seg);
869497883Sgibbs	while (sg_prefetch_cnt < sg_size)
869597883Sgibbs		sg_prefetch_cnt += sg_prefetch_align;
869697883Sgibbs	/*
869797883Sgibbs	 * If the cacheline is not an even multiple of
869897883Sgibbs	 * the S/G size, we may only get a partial S/G when
869997883Sgibbs	 * we align. Add a cacheline if this is the case.
870097883Sgibbs	 */
870197883Sgibbs	if ((sg_prefetch_align % sg_size) != 0
870297883Sgibbs	 && (sg_prefetch_cnt < CCSGADDR_MAX))
870397883Sgibbs		sg_prefetch_cnt += sg_prefetch_align;
870497883Sgibbs	/*
870597883Sgibbs	 * Lastly, compute a value that the sequencer can use
870697883Sgibbs	 * to determine if the remainder of the CCSGRAM buffer
870797883Sgibbs	 * has a full S/G element in it.
870897883Sgibbs	 */
870997883Sgibbs	sg_prefetch_cnt_limit = -(sg_prefetch_cnt - sg_size + 1);
871097883Sgibbs	download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt;
871197883Sgibbs	download_consts[SG_PREFETCH_CNT_LIMIT] = sg_prefetch_cnt_limit;
871297883Sgibbs	download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_align - 1);
871397883Sgibbs	download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_align - 1);
871497883Sgibbs	download_consts[SG_SIZEOF] = sg_size;
871597883Sgibbs	download_consts[PKT_OVERRUN_BUFOFFSET] =
8716102679Sgibbs		(ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
8717102679Sgibbs	download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
8718129134Sgibbs	download_consts[CACHELINE_MASK] = cacheline_mask;
871997883Sgibbs	cur_patch = patches;
872097883Sgibbs	downloaded = 0;
872197883Sgibbs	skip_addr = 0;
872297883Sgibbs	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8723123579Sgibbs	ahd_outw(ahd, PRGMCNT, 0);
872497883Sgibbs
872597883Sgibbs	for (i = 0; i < sizeof(seqprog)/4; i++) {
872697883Sgibbs		if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
872797883Sgibbs			/*
872897883Sgibbs			 * Don't download this instruction as it
872997883Sgibbs			 * is in a patch that was removed.
873097883Sgibbs			 */
873197883Sgibbs			continue;
873297883Sgibbs		}
873397883Sgibbs		/*
873497883Sgibbs		 * Move through the CS table until we find a CS
873597883Sgibbs		 * that might apply to this instruction.
873697883Sgibbs		 */
873797883Sgibbs		for (; cur_cs < num_critical_sections; cur_cs++) {
873897883Sgibbs			if (critical_sections[cur_cs].end <= i) {
873997883Sgibbs				if (begin_set[cs_count] == TRUE
874097883Sgibbs				 && end_set[cs_count] == FALSE) {
874197883Sgibbs					cs_table[cs_count].end = downloaded;
874297883Sgibbs				 	end_set[cs_count] = TRUE;
874397883Sgibbs					cs_count++;
874497883Sgibbs				}
874597883Sgibbs				continue;
874697883Sgibbs			}
874797883Sgibbs			if (critical_sections[cur_cs].begin <= i
874897883Sgibbs			 && begin_set[cs_count] == FALSE) {
874997883Sgibbs				cs_table[cs_count].begin = downloaded;
875097883Sgibbs				begin_set[cs_count] = TRUE;
875197883Sgibbs			}
875297883Sgibbs			break;
875397883Sgibbs		}
875497883Sgibbs		ahd_download_instr(ahd, i, download_consts);
875597883Sgibbs		downloaded++;
875697883Sgibbs	}
875797883Sgibbs
875897883Sgibbs	ahd->num_critical_sections = cs_count;
875997883Sgibbs	if (cs_count != 0) {
876097883Sgibbs
876197883Sgibbs		cs_count *= sizeof(struct cs);
876297883Sgibbs		ahd->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT);
876397883Sgibbs		if (ahd->critical_sections == NULL)
876497883Sgibbs			panic("ahd_loadseq: Could not malloc");
876597883Sgibbs		memcpy(ahd->critical_sections, cs_table, cs_count);
876697883Sgibbs	}
876797883Sgibbs	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE);
876897883Sgibbs
8769109588Sgibbs	if (bootverbose) {
877097883Sgibbs		printf(" %d instructions downloaded\n", downloaded);
8771109588Sgibbs		printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n",
8772109588Sgibbs		       ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags);
8773109588Sgibbs	}
877497883Sgibbs}
877597883Sgibbs
877697883Sgibbsstatic int
877797883Sgibbsahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
877897883Sgibbs		u_int start_instr, u_int *skip_addr)
877997883Sgibbs{
878097883Sgibbs	struct	patch *cur_patch;
878197883Sgibbs	struct	patch *last_patch;
878297883Sgibbs	u_int	num_patches;
878397883Sgibbs
878497883Sgibbs	num_patches = sizeof(patches)/sizeof(struct patch);
878597883Sgibbs	last_patch = &patches[num_patches];
878697883Sgibbs	cur_patch = *start_patch;
878797883Sgibbs
878897883Sgibbs	while (cur_patch < last_patch && start_instr == cur_patch->begin) {
878997883Sgibbs
879097883Sgibbs		if (cur_patch->patch_func(ahd) == 0) {
879197883Sgibbs
879297883Sgibbs			/* Start rejecting code */
879397883Sgibbs			*skip_addr = start_instr + cur_patch->skip_instr;
879497883Sgibbs			cur_patch += cur_patch->skip_patch;
879597883Sgibbs		} else {
879697883Sgibbs			/* Accepted this patch.  Advance to the next
879797883Sgibbs			 * one and wait for our intruction pointer to
879897883Sgibbs			 * hit this point.
879997883Sgibbs			 */
880097883Sgibbs			cur_patch++;
880197883Sgibbs		}
880297883Sgibbs	}
880397883Sgibbs
880497883Sgibbs	*start_patch = cur_patch;
880597883Sgibbs	if (start_instr < *skip_addr)
880697883Sgibbs		/* Still skipping */
880797883Sgibbs		return (0);
880897883Sgibbs
880997883Sgibbs	return (1);
881097883Sgibbs}
881197883Sgibbs
881297883Sgibbsstatic u_int
881397883Sgibbsahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)
881497883Sgibbs{
881597883Sgibbs	struct patch *cur_patch;
881697883Sgibbs	int address_offset;
881797883Sgibbs	u_int skip_addr;
881897883Sgibbs	u_int i;
881997883Sgibbs
882097883Sgibbs	address_offset = 0;
882197883Sgibbs	cur_patch = patches;
882297883Sgibbs	skip_addr = 0;
882397883Sgibbs
882497883Sgibbs	for (i = 0; i < address;) {
882597883Sgibbs
882697883Sgibbs		ahd_check_patch(ahd, &cur_patch, i, &skip_addr);
882797883Sgibbs
882897883Sgibbs		if (skip_addr > i) {
882997883Sgibbs			int end_addr;
883097883Sgibbs
883197883Sgibbs			end_addr = MIN(address, skip_addr);
883297883Sgibbs			address_offset += end_addr - i;
883397883Sgibbs			i = skip_addr;
883497883Sgibbs		} else {
883597883Sgibbs			i++;
883697883Sgibbs		}
883797883Sgibbs	}
883897883Sgibbs	return (address - address_offset);
883997883Sgibbs}
884097883Sgibbs
884197883Sgibbsstatic void
884297883Sgibbsahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts)
884397883Sgibbs{
884497883Sgibbs	union	ins_formats instr;
884597883Sgibbs	struct	ins_format1 *fmt1_ins;
884697883Sgibbs	struct	ins_format3 *fmt3_ins;
884797883Sgibbs	u_int	opcode;
884897883Sgibbs
884997883Sgibbs	/*
885097883Sgibbs	 * The firmware is always compiled into a little endian format.
885197883Sgibbs	 */
8852123579Sgibbs	instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
885397883Sgibbs
885497883Sgibbs	fmt1_ins = &instr.format1;
885597883Sgibbs	fmt3_ins = NULL;
885697883Sgibbs
885797883Sgibbs	/* Pull the opcode */
885897883Sgibbs	opcode = instr.format1.opcode;
885997883Sgibbs	switch (opcode) {
886097883Sgibbs	case AIC_OP_JMP:
886197883Sgibbs	case AIC_OP_JC:
886297883Sgibbs	case AIC_OP_JNC:
886397883Sgibbs	case AIC_OP_CALL:
886497883Sgibbs	case AIC_OP_JNE:
886597883Sgibbs	case AIC_OP_JNZ:
886697883Sgibbs	case AIC_OP_JE:
886797883Sgibbs	case AIC_OP_JZ:
886897883Sgibbs	{
886997883Sgibbs		fmt3_ins = &instr.format3;
887097883Sgibbs		fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address);
887197883Sgibbs		/* FALLTHROUGH */
887297883Sgibbs	}
887397883Sgibbs	case AIC_OP_OR:
887497883Sgibbs	case AIC_OP_AND:
887597883Sgibbs	case AIC_OP_XOR:
887697883Sgibbs	case AIC_OP_ADD:
887797883Sgibbs	case AIC_OP_ADC:
887897883Sgibbs	case AIC_OP_BMOV:
887997883Sgibbs		if (fmt1_ins->parity != 0) {
888097883Sgibbs			fmt1_ins->immediate = dconsts[fmt1_ins->immediate];
888197883Sgibbs		}
888297883Sgibbs		fmt1_ins->parity = 0;
888397883Sgibbs		/* FALLTHROUGH */
888497883Sgibbs	case AIC_OP_ROL:
888597883Sgibbs	{
888697883Sgibbs		int i, count;
888797883Sgibbs
888897883Sgibbs		/* Calculate odd parity for the instruction */
888997883Sgibbs		for (i = 0, count = 0; i < 31; i++) {
889097883Sgibbs			uint32_t mask;
889197883Sgibbs
889297883Sgibbs			mask = 0x01 << i;
889397883Sgibbs			if ((instr.integer & mask) != 0)
889497883Sgibbs				count++;
889597883Sgibbs		}
889697883Sgibbs		if ((count & 0x01) == 0)
889797883Sgibbs			instr.format1.parity = 1;
889897883Sgibbs
889997883Sgibbs		/* The sequencer is a little endian cpu */
8900123579Sgibbs		instr.integer = aic_htole32(instr.integer);
890197883Sgibbs		ahd_outsb(ahd, SEQRAM, instr.bytes, 4);
890297883Sgibbs		break;
890397883Sgibbs	}
890497883Sgibbs	default:
890597883Sgibbs		panic("Unknown opcode encountered in seq program");
890697883Sgibbs		break;
890797883Sgibbs	}
890897883Sgibbs}
890997883Sgibbs
8910107441Sscottlstatic int
8911107441Sscottlahd_probe_stack_size(struct ahd_softc *ahd)
8912107441Sscottl{
8913107441Sscottl	int last_probe;
8914107441Sscottl
8915107441Sscottl	last_probe = 0;
8916107441Sscottl	while (1) {
8917107441Sscottl		int i;
8918107441Sscottl
8919107441Sscottl		/*
8920107441Sscottl		 * We avoid using 0 as a pattern to avoid
8921107441Sscottl		 * confusion if the stack implementation
8922107441Sscottl		 * "back-fills" with zeros when "poping'
8923107441Sscottl		 * entries.
8924107441Sscottl		 */
8925107441Sscottl		for (i = 1; i <= last_probe+1; i++) {
8926107441Sscottl		       ahd_outb(ahd, STACK, i & 0xFF);
8927107441Sscottl		       ahd_outb(ahd, STACK, (i >> 8) & 0xFF);
8928107441Sscottl		}
8929107441Sscottl
8930107441Sscottl		/* Verify */
8931107441Sscottl		for (i = last_probe+1; i > 0; i--) {
8932107441Sscottl			u_int stack_entry;
8933107441Sscottl
8934107441Sscottl			stack_entry = ahd_inb(ahd, STACK)
8935107441Sscottl				    |(ahd_inb(ahd, STACK) << 8);
8936107441Sscottl			if (stack_entry != i)
8937107441Sscottl				goto sized;
8938107441Sscottl		}
8939107441Sscottl		last_probe++;
8940107441Sscottl	}
8941107441Sscottlsized:
8942107441Sscottl	return (last_probe);
8943107441Sscottl}
8944107441Sscottl
894597883Sgibbsvoid
8946115336Sgibbsahd_dump_all_cards_state(void)
894797883Sgibbs{
894897883Sgibbs	struct ahd_softc *list_ahd;
894997883Sgibbs
895097883Sgibbs	TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
895197883Sgibbs		ahd_dump_card_state(list_ahd);
895297883Sgibbs	}
895397883Sgibbs}
895497883Sgibbs
8955102679Sgibbsint
8956102679Sgibbsahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
8957102679Sgibbs		   const char *name, u_int address, u_int value,
8958102679Sgibbs		   u_int *cur_column, u_int wrap_point)
8959102679Sgibbs{
8960102679Sgibbs	int	printed;
8961102679Sgibbs	u_int	printed_mask;
8962141999Sgibbs	u_int	dummy_column;
8963102679Sgibbs
8964141999Sgibbs	if (cur_column == NULL) {
8965141999Sgibbs		dummy_column = 0;
8966141999Sgibbs		cur_column = &dummy_column;
8967141999Sgibbs	}
8968141999Sgibbs
8969107441Sscottl	if (cur_column != NULL && *cur_column >= wrap_point) {
8970102679Sgibbs		printf("\n");
8971102679Sgibbs		*cur_column = 0;
8972102679Sgibbs	}
8973102679Sgibbs	printed = printf("%s[0x%x]", name, value);
8974102679Sgibbs	if (table == NULL) {
8975102679Sgibbs		printed += printf(" ");
8976102679Sgibbs		*cur_column += printed;
8977102679Sgibbs		return (printed);
8978102679Sgibbs	}
8979102679Sgibbs	printed_mask = 0;
8980102679Sgibbs	while (printed_mask != 0xFF) {
8981102679Sgibbs		int entry;
8982102679Sgibbs
8983102679Sgibbs		for (entry = 0; entry < num_entries; entry++) {
8984102679Sgibbs			if (((value & table[entry].mask)
8985102679Sgibbs			  != table[entry].value)
8986102679Sgibbs			 || ((printed_mask & table[entry].mask)
8987102679Sgibbs			  == table[entry].mask))
8988102679Sgibbs				continue;
8989102679Sgibbs
8990102679Sgibbs			printed += printf("%s%s",
8991102679Sgibbs					  printed_mask == 0 ? ":(" : "|",
8992102679Sgibbs					  table[entry].name);
8993102679Sgibbs			printed_mask |= table[entry].mask;
8994102679Sgibbs
8995102679Sgibbs			break;
8996102679Sgibbs		}
8997102679Sgibbs		if (entry >= num_entries)
8998102679Sgibbs			break;
8999102679Sgibbs	}
9000102679Sgibbs	if (printed_mask != 0)
9001102679Sgibbs		printed += printf(") ");
9002102679Sgibbs	else
9003102679Sgibbs		printed += printf(" ");
9004141999Sgibbs	*cur_column += printed;
9005102679Sgibbs	return (printed);
9006102679Sgibbs}
9007102679Sgibbs
900897883Sgibbsvoid
900997883Sgibbsahd_dump_card_state(struct ahd_softc *ahd)
901097883Sgibbs{
901197883Sgibbs	struct scb	*scb;
901297883Sgibbs	ahd_mode_state	 saved_modes;
901397883Sgibbs	u_int		 dffstat;
901497883Sgibbs	int		 paused;
901597883Sgibbs	u_int		 scb_index;
9016104023Sgibbs	u_int		 saved_scb_index;
9017102679Sgibbs	u_int		 cur_col;
9018107441Sscottl	int		 i;
901997883Sgibbs
902097883Sgibbs	if (ahd_is_paused(ahd)) {
902197883Sgibbs		paused = 1;
902297883Sgibbs	} else {
902397883Sgibbs		paused = 0;
902497883Sgibbs		ahd_pause(ahd);
902597883Sgibbs	}
902697883Sgibbs	saved_modes = ahd_save_modes(ahd);
902797883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
9028102679Sgibbs	printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
9029102679Sgibbs	       "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
903097883Sgibbs	       ahd_name(ahd),
9031123579Sgibbs	       ahd_inw(ahd, CURADDR),
903297883Sgibbs	       ahd_build_mode_state(ahd, ahd->saved_src_mode,
903397883Sgibbs				    ahd->saved_dst_mode));
903497883Sgibbs	if (paused)
903597883Sgibbs		printf("Card was paused\n");
9036116938Sgibbs
9037116938Sgibbs	if (ahd_check_cmdcmpltqueues(ahd))
9038116938Sgibbs		printf("Completions are pending\n");
9039116938Sgibbs
9040102679Sgibbs	/*
9041102679Sgibbs	 * Mode independent registers.
9042102679Sgibbs	 */
9043102679Sgibbs	cur_col = 0;
9044133122Sgibbs	ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50);
9045133122Sgibbs	ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50);
9046133122Sgibbs	ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50);
9047109588Sgibbs	ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50);
9048109588Sgibbs	ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50);
9049109588Sgibbs	ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50);
9050107441Sscottl	ahd_saved_mode_print(ahd_inb(ahd, SAVED_MODE), &cur_col, 50);
9051107441Sscottl	ahd_dffstat_print(ahd_inb(ahd, DFFSTAT), &cur_col, 50);
9052102679Sgibbs	ahd_scsisigi_print(ahd_inb(ahd, SCSISIGI), &cur_col, 50);
9053102679Sgibbs	ahd_scsiphase_print(ahd_inb(ahd, SCSIPHASE), &cur_col, 50);
9054104023Sgibbs	ahd_scsibus_print(ahd_inb(ahd, SCSIBUS), &cur_col, 50);
9055102679Sgibbs	ahd_lastphase_print(ahd_inb(ahd, LASTPHASE), &cur_col, 50);
9056107441Sscottl	ahd_scsiseq0_print(ahd_inb(ahd, SCSISEQ0), &cur_col, 50);
9057107441Sscottl	ahd_scsiseq1_print(ahd_inb(ahd, SCSISEQ1), &cur_col, 50);
9058107441Sscottl	ahd_seqctl0_print(ahd_inb(ahd, SEQCTL0), &cur_col, 50);
9059107441Sscottl	ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);
9060102679Sgibbs	ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);
9061102679Sgibbs	ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);
9062133122Sgibbs	ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50);
9063133122Sgibbs	ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),
9064133122Sgibbs				       &cur_col, 50);
9065133122Sgibbs	ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50);
9066133122Sgibbs	ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),
9067133122Sgibbs				    &cur_col, 50);
9068102679Sgibbs	ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50);
9069102679Sgibbs	ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50);
9070102679Sgibbs	ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);
9071102679Sgibbs	ahd_sstat3_print(ahd_inb(ahd, SSTAT3), &cur_col, 50);
9072102679Sgibbs	ahd_perrdiag_print(ahd_inb(ahd, PERRDIAG), &cur_col, 50);
9073104023Sgibbs	ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50);
9074104023Sgibbs	ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50);
9075104023Sgibbs	ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50);
9076104023Sgibbs	ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50);
9077104023Sgibbs	ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50);
9078104023Sgibbs	ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50);
9079104023Sgibbs	ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50);
9080104023Sgibbs	printf("\n");
9081109588Sgibbs	printf("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x "
9082109588Sgibbs	       "CURRSCB 0x%x NEXTSCB 0x%x\n",
9083109588Sgibbs	       ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING),
9084109588Sgibbs	       ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB),
9085109588Sgibbs	       ahd_inw(ahd, NEXTSCB));
9086102679Sgibbs	cur_col = 0;
908797883Sgibbs	/* QINFIFO */
908897883Sgibbs	ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
908997883Sgibbs			   CAM_LUN_WILDCARD, SCB_LIST_NULL,
909097883Sgibbs			   ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT);
9091104023Sgibbs	saved_scb_index = ahd_get_scbptr(ahd);
9092102679Sgibbs	printf("Pending list:");
909397883Sgibbs	i = 0;
909497883Sgibbs	LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
909597883Sgibbs		if (i++ > AHD_SCB_MAX)
909697883Sgibbs			break;
9097114623Sgibbs		cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
9098116940Sgibbs				 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT));
909997883Sgibbs		ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
9100116940Sgibbs		ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),
9101116940Sgibbs				      &cur_col, 60);
9102116940Sgibbs		ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),
9103116940Sgibbs				     &cur_col, 60);
910497883Sgibbs	}
9105109588Sgibbs	printf("\nTotal %d\n", i);
910697883Sgibbs
9107150451Sgibbs	printf("Kernel Free SCB lists: ");
910897883Sgibbs	i = 0;
9109102679Sgibbs	TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
9110102679Sgibbs		struct scb *list_scb;
9111102679Sgibbs
9112150451Sgibbs		printf("\n  COLIDX[%d]: ", AHD_GET_SCB_COL_IDX(ahd, scb));
9113102679Sgibbs		list_scb = scb;
9114102679Sgibbs		do {
9115102679Sgibbs			printf("%d ", SCB_GET_TAG(list_scb));
9116102679Sgibbs			list_scb = LIST_NEXT(list_scb, collision_links);
9117102679Sgibbs		} while (list_scb && i++ < AHD_SCB_MAX);
9118102679Sgibbs	}
9119102679Sgibbs
9120150451Sgibbs	printf("\n  Any Device: ");
9121102679Sgibbs	LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
912297883Sgibbs		if (i++ > AHD_SCB_MAX)
912397883Sgibbs			break;
912497883Sgibbs		printf("%d ", SCB_GET_TAG(scb));
912597883Sgibbs	}
912697883Sgibbs	printf("\n");
912797883Sgibbs
912897883Sgibbs	printf("Sequencer Complete DMA-inprog list: ");
912997883Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD);
913097883Sgibbs	i = 0;
913197883Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
913297883Sgibbs		ahd_set_scbptr(ahd, scb_index);
913397883Sgibbs		printf("%d ", scb_index);
9134116940Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
913597883Sgibbs	}
913697883Sgibbs	printf("\n");
913797883Sgibbs
913897883Sgibbs	printf("Sequencer Complete list: ");
913997883Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD);
914097883Sgibbs	i = 0;
914197883Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
914297883Sgibbs		ahd_set_scbptr(ahd, scb_index);
914397883Sgibbs		printf("%d ", scb_index);
9144116940Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
914597883Sgibbs	}
914697883Sgibbs	printf("\n");
914797883Sgibbs
914897883Sgibbs
914997883Sgibbs	printf("Sequencer DMA-Up and Complete list: ");
915097883Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
915197883Sgibbs	i = 0;
915297883Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
915397883Sgibbs		ahd_set_scbptr(ahd, scb_index);
915497883Sgibbs		printf("%d ", scb_index);
9155116940Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
915697883Sgibbs	}
915797883Sgibbs	printf("\n");
9158125448Sgibbs	printf("Sequencer On QFreeze and Complete list: ");
9159125448Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
9160125448Sgibbs	i = 0;
9161125448Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
9162125448Sgibbs		ahd_set_scbptr(ahd, scb_index);
9163125448Sgibbs		printf("%d ", scb_index);
9164125448Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
9165125448Sgibbs	}
9166125448Sgibbs	printf("\n");
9167104023Sgibbs	ahd_set_scbptr(ahd, saved_scb_index);
916897883Sgibbs	dffstat = ahd_inb(ahd, DFFSTAT);
916997883Sgibbs	for (i = 0; i < 2; i++) {
9170102679Sgibbs#ifdef AHD_DEBUG
917197883Sgibbs		struct scb *fifo_scb;
9172102679Sgibbs#endif
917397883Sgibbs		u_int	    fifo_scbptr;
917497883Sgibbs
917597883Sgibbs		ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
9176104023Sgibbs		fifo_scbptr = ahd_get_scbptr(ahd);
9177133122Sgibbs		printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
917897883Sgibbs		       ahd_name(ahd), i,
917997883Sgibbs		       (dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
9180114623Sgibbs		       ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
9181102679Sgibbs		cur_col = 0;
9182102679Sgibbs		ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50);
9183102679Sgibbs		ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50);
9184102679Sgibbs		ahd_dfcntrl_print(ahd_inb(ahd, DFCNTRL), &cur_col, 50);
9185102679Sgibbs		ahd_dfstatus_print(ahd_inb(ahd, DFSTATUS), &cur_col, 50);
9186102679Sgibbs		ahd_sg_cache_shadow_print(ahd_inb(ahd, SG_CACHE_SHADOW),
9187102679Sgibbs					  &cur_col, 50);
9188102679Sgibbs		ahd_sg_state_print(ahd_inb(ahd, SG_STATE), &cur_col, 50);
9189102679Sgibbs		ahd_dffsxfrctl_print(ahd_inb(ahd, DFFSXFRCTL), &cur_col, 50);
9190102679Sgibbs		ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50);
9191102679Sgibbs		ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50);
9192102679Sgibbs		if (cur_col > 50) {
9193102679Sgibbs			printf("\n");
9194102679Sgibbs			cur_col = 0;
9195102679Sgibbs		}
9196109588Sgibbs		cur_col += printf("SHADDR = 0x%x%x, SHCNT = 0x%x ",
9197102679Sgibbs				  ahd_inl(ahd, SHADDR+4),
9198102679Sgibbs				  ahd_inl(ahd, SHADDR),
9199102679Sgibbs				  (ahd_inb(ahd, SHCNT)
9200102679Sgibbs				| (ahd_inb(ahd, SHCNT + 1) << 8)
9201102679Sgibbs				| (ahd_inb(ahd, SHCNT + 2) << 16)));
9202102679Sgibbs		if (cur_col > 50) {
9203102679Sgibbs			printf("\n");
9204102679Sgibbs			cur_col = 0;
9205102679Sgibbs		}
9206107441Sscottl		cur_col += printf("HADDR = 0x%x%x, HCNT = 0x%x ",
9207102679Sgibbs				  ahd_inl(ahd, HADDR+4),
9208102679Sgibbs				  ahd_inl(ahd, HADDR),
9209102679Sgibbs				  (ahd_inb(ahd, HCNT)
9210102679Sgibbs				| (ahd_inb(ahd, HCNT + 1) << 8)
9211102679Sgibbs				| (ahd_inb(ahd, HCNT + 2) << 16)));
9212102679Sgibbs		ahd_ccsgctl_print(ahd_inb(ahd, CCSGCTL), &cur_col, 50);
9213102679Sgibbs#ifdef AHD_DEBUG
9214102679Sgibbs		if ((ahd_debug & AHD_SHOW_SG) != 0) {
9215102679Sgibbs			fifo_scb = ahd_lookup_scb(ahd, fifo_scbptr);
9216102679Sgibbs			if (fifo_scb != NULL)
9217102679Sgibbs				ahd_dump_sglist(fifo_scb);
9218102679Sgibbs		}
9219102679Sgibbs#endif
922097883Sgibbs	}
9221104023Sgibbs	printf("\nLQIN: ");
922297883Sgibbs	for (i = 0; i < 20; i++)
922397883Sgibbs		printf("0x%x ", ahd_inb(ahd, LQIN + i));
922497883Sgibbs	printf("\n");
922597883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
922697883Sgibbs	printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n",
922797883Sgibbs	       ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE),
922897883Sgibbs	       ahd_inb(ahd, OPTIONMODE));
922997883Sgibbs	printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n",
923097883Sgibbs	       ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT),
923197883Sgibbs	       ahd_inb(ahd, MAXCMDCNT));
9232133122Sgibbs	printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n",
9233133122Sgibbs	       ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID),
9234133122Sgibbs	       ahd_inb(ahd, SAVED_LUN));
9235107441Sscottl	ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50);
9236107441Sscottl	printf("\n");
9237109588Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
9238109588Sgibbs	cur_col = 0;
9239109588Sgibbs	ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50);
9240109588Sgibbs	printf("\n");
924197883Sgibbs	ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
924297883Sgibbs	printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n",
924397883Sgibbs	       ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX),
924497883Sgibbs	       ahd_inw(ahd, DINDEX));
924597883Sgibbs	printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n",
9246116940Sgibbs	       ahd_name(ahd), ahd_get_scbptr(ahd),
9247116940Sgibbs	       ahd_inw_scbram(ahd, SCB_NEXT),
9248116940Sgibbs	       ahd_inw_scbram(ahd, SCB_NEXT2));
924997883Sgibbs	printf("CDB %x %x %x %x %x %x\n",
9250116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE),
9251116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+1),
9252116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+2),
9253116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+3),
9254116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+4),
9255116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+5));
925697883Sgibbs	printf("STACK:");
9257107441Sscottl	for (i = 0; i < ahd->stack_size; i++) {
9258107441Sscottl		ahd->saved_stack[i] =
9259107441Sscottl		    ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8);
9260107441Sscottl		printf(" 0x%x", ahd->saved_stack[i]);
9261107441Sscottl	}
9262107441Sscottl	for (i = ahd->stack_size-1; i >= 0; i--) {
9263107441Sscottl		ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF);
9264107441Sscottl		ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
9265107441Sscottl	}
9266102679Sgibbs	printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
926797883Sgibbs	ahd_platform_dump_card_state(ahd);
926897883Sgibbs	ahd_restore_modes(ahd, saved_modes);
926997883Sgibbs	if (paused == 0)
927097883Sgibbs		ahd_unpause(ahd);
927197883Sgibbs}
927297883Sgibbs
927397883Sgibbsvoid
927497883Sgibbsahd_dump_scbs(struct ahd_softc *ahd)
927597883Sgibbs{
927697883Sgibbs	ahd_mode_state saved_modes;
9277104023Sgibbs	u_int	       saved_scb_index;
927897883Sgibbs	int	       i;
927997883Sgibbs
928097883Sgibbs	saved_modes = ahd_save_modes(ahd);
928197883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
9282104023Sgibbs	saved_scb_index = ahd_get_scbptr(ahd);
928397883Sgibbs	for (i = 0; i < AHD_SCB_MAX; i++) {
928497883Sgibbs		ahd_set_scbptr(ahd, i);
928597883Sgibbs		printf("%3d", i);
928697883Sgibbs		printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",
9287116940Sgibbs		       ahd_inb_scbram(ahd, SCB_CONTROL),
9288116940Sgibbs		       ahd_inb_scbram(ahd, SCB_SCSIID),
9289116940Sgibbs		       ahd_inw_scbram(ahd, SCB_NEXT),
9290116940Sgibbs		       ahd_inw_scbram(ahd, SCB_NEXT2),
9291116940Sgibbs		       ahd_inl_scbram(ahd, SCB_SGPTR),
9292116940Sgibbs		       ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));
929397883Sgibbs	}
929497883Sgibbs	printf("\n");
9295104023Sgibbs	ahd_set_scbptr(ahd, saved_scb_index);
929697883Sgibbs	ahd_restore_modes(ahd, saved_modes);
929797883Sgibbs}
929897883Sgibbs
9299123579Sgibbs
9300123579Sgibbs/*************************** Timeout Handling *********************************/
9301123579Sgibbsvoid
9302123579Sgibbsahd_timeout(struct scb *scb)
9303123579Sgibbs{
9304123579Sgibbs	struct ahd_softc *ahd;
9305123579Sgibbs
9306123579Sgibbs	ahd = scb->ahd_softc;
9307123579Sgibbs	if ((scb->flags & SCB_ACTIVE) != 0) {
9308123579Sgibbs		if ((scb->flags & SCB_TIMEDOUT) == 0) {
9309123579Sgibbs			LIST_INSERT_HEAD(&ahd->timedout_scbs, scb,
9310123579Sgibbs					 timedout_links);
9311123579Sgibbs			scb->flags |= SCB_TIMEDOUT;
9312123579Sgibbs		}
9313123579Sgibbs		ahd_wakeup_recovery_thread(ahd);
9314123579Sgibbs	}
9315123579Sgibbs}
9316123579Sgibbs
9317123579Sgibbs/*
9318123579Sgibbs * ahd_recover_commands determines if any of the commands that have currently
9319123579Sgibbs * timedout are the root cause for this timeout.  Innocent commands are given
9320123579Sgibbs * a new timeout while we wait for the command executing on the bus to timeout.
9321123579Sgibbs * This routine is invoked from a thread context so we are allowed to sleep.
9322123579Sgibbs * Our lock is not held on entry.
9323123579Sgibbs */
9324123579Sgibbsvoid
9325123579Sgibbsahd_recover_commands(struct ahd_softc *ahd)
9326123579Sgibbs{
9327123579Sgibbs	struct	scb *scb;
9328123579Sgibbs	struct	scb *active_scb;
9329123579Sgibbs	int	found;
9330123579Sgibbs	int	was_paused;
9331123579Sgibbs	u_int	active_scbptr;
9332123579Sgibbs	u_int	last_phase;
9333123579Sgibbs
9334123579Sgibbs	/*
9335123579Sgibbs	 * Pause the controller and manually flush any
9336123579Sgibbs	 * commands that have just completed but that our
9337123579Sgibbs	 * interrupt handler has yet to see.
9338123579Sgibbs	 */
9339123579Sgibbs	was_paused = ahd_is_paused(ahd);
9340133122Sgibbs
9341133122Sgibbs	printf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd),
9342133122Sgibbs	       was_paused ? "" : "not ");
9343199260Sattilio	AHD_CORRECTABLE_ERROR(ahd);
9344133122Sgibbs	ahd_dump_card_state(ahd);
9345133122Sgibbs
9346123579Sgibbs	ahd_pause_and_flushwork(ahd);
9347123579Sgibbs
9348123579Sgibbs	if (LIST_EMPTY(&ahd->timedout_scbs) != 0) {
9349123579Sgibbs		/*
9350123579Sgibbs		 * The timedout commands have already
9351123579Sgibbs		 * completed.  This typically means
9352123579Sgibbs		 * that either the timeout value was on
9353123579Sgibbs		 * the hairy edge of what the device
9354123579Sgibbs		 * requires or - more likely - interrupts
9355123579Sgibbs		 * are not happening.
9356123579Sgibbs		 */
9357123579Sgibbs		printf("%s: Timedout SCBs already complete. "
9358123579Sgibbs		       "Interrupts may not be functioning.\n", ahd_name(ahd));
9359123579Sgibbs		ahd_unpause(ahd);
9360123579Sgibbs		return;
9361123579Sgibbs	}
9362123579Sgibbs
9363123579Sgibbs	/*
9364123579Sgibbs	 * Determine identity of SCB acting on the bus.
9365123579Sgibbs	 * This test only catches non-packetized transactions.
9366123579Sgibbs	 * Due to the fleeting nature of packetized operations,
9367123579Sgibbs	 * we can't easily determine that a packetized operation
9368123579Sgibbs	 * is on the bus.
9369123579Sgibbs	 */
9370123579Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
9371123579Sgibbs	last_phase = ahd_inb(ahd, LASTPHASE);
9372123579Sgibbs	active_scbptr = ahd_get_scbptr(ahd);
9373123579Sgibbs	active_scb = NULL;
9374123579Sgibbs	if (last_phase != P_BUSFREE
9375123579Sgibbs	 || (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)
9376123579Sgibbs		active_scb = ahd_lookup_scb(ahd, active_scbptr);
9377123579Sgibbs
9378123579Sgibbs	while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
9379123579Sgibbs		int	target;
9380123579Sgibbs		int	lun;
9381123579Sgibbs		char	channel;
9382123579Sgibbs
9383123579Sgibbs		target = SCB_GET_TARGET(ahd, scb);
9384123579Sgibbs		channel = SCB_GET_CHANNEL(ahd, scb);
9385123579Sgibbs		lun = SCB_GET_LUN(scb);
9386123579Sgibbs
9387123579Sgibbs		ahd_print_path(ahd, scb);
9388141999Sgibbs		printf("SCB %d - timed out\n", SCB_GET_TAG(scb));
9389123579Sgibbs
9390123579Sgibbs		if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
9391123579Sgibbs			/*
9392123579Sgibbs			 * Been down this road before.
9393123579Sgibbs			 * Do a full bus reset.
9394123579Sgibbs			 */
9395123579Sgibbs			aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
9396123579Sgibbsbus_reset:
9397123579Sgibbs			found = ahd_reset_channel(ahd, channel,
9398123579Sgibbs						  /*Initiate Reset*/TRUE);
9399123579Sgibbs			printf("%s: Issued Channel %c Bus Reset. "
9400123579Sgibbs			       "%d SCBs aborted\n", ahd_name(ahd), channel,
9401123579Sgibbs			       found);
9402123579Sgibbs			continue;
9403123579Sgibbs		}
9404123579Sgibbs
9405123579Sgibbs		/*
9406123579Sgibbs		 * Remove the command from the timedout list in
9407123579Sgibbs		 * preparation for requeing it.
9408123579Sgibbs		 */
9409123579Sgibbs		LIST_REMOVE(scb, timedout_links);
9410123579Sgibbs		scb->flags &= ~SCB_TIMEDOUT;
9411123579Sgibbs
9412123579Sgibbs		if (active_scb != NULL) {
9413123579Sgibbs
9414123579Sgibbs			if (active_scb != scb) {
9415129134Sgibbs
9416123579Sgibbs				/*
9417123579Sgibbs				 * If the active SCB is not us, assume that
9418123579Sgibbs				 * the active SCB has a longer timeout than
9419123579Sgibbs				 * the timedout SCB, and wait for the active
9420129134Sgibbs				 * SCB to timeout.  As a safeguard, only
9421129134Sgibbs				 * allow this deferral to continue if some
9422129134Sgibbs				 * untimed-out command is outstanding.
9423123579Sgibbs				 */
9424129134Sgibbs				if (ahd_other_scb_timeout(ahd, scb,
9425133966Sgibbs							  active_scb) == 0)
9426129134Sgibbs					goto bus_reset;
9427123579Sgibbs				continue;
9428123579Sgibbs			}
9429123579Sgibbs
9430123579Sgibbs			/*
9431123579Sgibbs			 * We're active on the bus, so assert ATN
9432123579Sgibbs			 * and hope that the target responds.
9433123579Sgibbs			 */
9434123579Sgibbs			ahd_set_recoveryscb(ahd, active_scb);
9435123579Sgibbs                	active_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
9436123579Sgibbs			ahd_outb(ahd, MSG_OUT, HOST_MSG);
9437123579Sgibbs			ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
9438123579Sgibbs			ahd_print_path(ahd, active_scb);
9439123579Sgibbs			printf("BDR message in message buffer\n");
9440137870Sgibbs			aic_scb_timer_reset(scb, 2 * 1000);
9441123579Sgibbs			break;
9442123579Sgibbs		} else if (last_phase != P_BUSFREE
9443123579Sgibbs			&& ahd_inb(ahd, SCSIPHASE) == 0) {
9444123579Sgibbs			/*
9445123579Sgibbs			 * SCB is not identified, there
9446123579Sgibbs			 * is no pending REQ, and the sequencer
9447123579Sgibbs			 * has not seen a busfree.  Looks like
9448123579Sgibbs			 * a stuck connection waiting to
9449123579Sgibbs			 * go busfree.  Reset the bus.
9450123579Sgibbs			 */
9451123579Sgibbs			printf("%s: Connection stuck awaiting busfree or "
9452123579Sgibbs			       "Identify Msg.\n", ahd_name(ahd));
9453123579Sgibbs			goto bus_reset;
9454123579Sgibbs		} else if (ahd_search_qinfifo(ahd, target, channel, lun,
9455141999Sgibbs					      SCB_GET_TAG(scb),
9456141978Sgibbs					      ROLE_INITIATOR, /*status*/0,
9457141978Sgibbs					      SEARCH_COUNT) > 0) {
9458123579Sgibbs
9459123579Sgibbs			/*
9460123579Sgibbs			 * We haven't even gone out on the bus
9461123579Sgibbs			 * yet, so the timeout must be due to
9462123579Sgibbs			 * some other command.  Reset the timer
9463123579Sgibbs			 * and go on.
9464123579Sgibbs			 */
9465133966Sgibbs			if (ahd_other_scb_timeout(ahd, scb, NULL) == 0)
9466129134Sgibbs				goto bus_reset;
9467123579Sgibbs		} else {
9468123579Sgibbs			/*
9469123579Sgibbs			 * This SCB is for a disconnected transaction
9470123579Sgibbs			 * and we haven't found a better candidate on
9471123579Sgibbs			 * the bus to explain this timeout.
9472123579Sgibbs			 */
9473123579Sgibbs			ahd_set_recoveryscb(ahd, scb);
9474123579Sgibbs
9475123579Sgibbs			/*
9476123579Sgibbs			 * Actually re-queue this SCB in an attempt
9477123579Sgibbs			 * to select the device before it reconnects.
9478123579Sgibbs			 * In either case (selection or reselection),
9479123579Sgibbs			 * we will now issue a target reset to the
9480123579Sgibbs			 * timed-out device.
9481123579Sgibbs			 */
9482123579Sgibbs			scb->flags |= SCB_DEVICE_RESET;
9483123579Sgibbs			scb->hscb->cdb_len = 0;
9484123579Sgibbs			scb->hscb->task_attribute = 0;
9485123579Sgibbs			scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
9486123579Sgibbs
9487123579Sgibbs			ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
9488123579Sgibbs			if ((scb->flags & SCB_PACKETIZED) != 0) {
9489123579Sgibbs				/*
9490123579Sgibbs				 * Mark the SCB has having an outstanding
9491123579Sgibbs				 * task management function.  Should the command
9492123579Sgibbs				 * complete normally before the task management
9493123579Sgibbs				 * function can be sent, the host will be
9494123579Sgibbs				 * notified to abort our requeued SCB.
9495123579Sgibbs				 */
9496123579Sgibbs				ahd_outb(ahd, SCB_TASK_MANAGEMENT,
9497123579Sgibbs					 scb->hscb->task_management);
9498123579Sgibbs			} else {
9499123579Sgibbs				/*
9500123579Sgibbs				 * If non-packetized, set the MK_MESSAGE control
9501123579Sgibbs				 * bit indicating that we desire to send a
9502123579Sgibbs				 * message.  We also set the disconnected flag
9503123579Sgibbs				 * since there is no guarantee that our SCB
9504123579Sgibbs				 * control byte matches the version on the
9505123579Sgibbs				 * card.  We don't want the sequencer to abort
9506123579Sgibbs				 * the command thinking an unsolicited
9507123579Sgibbs				 * reselection occurred.
9508123579Sgibbs				 */
9509123579Sgibbs				scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
9510123579Sgibbs
9511123579Sgibbs				/*
9512123579Sgibbs				 * The sequencer will never re-reference the
9513123579Sgibbs				 * in-core SCB.  To make sure we are notified
9514123579Sgibbs				 * during reslection, set the MK_MESSAGE flag in
9515123579Sgibbs				 * the card's copy of the SCB.
9516123579Sgibbs				 */
9517123579Sgibbs				ahd_outb(ahd, SCB_CONTROL,
9518123579Sgibbs					 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
9519123579Sgibbs			}
9520123579Sgibbs
9521123579Sgibbs			/*
9522123579Sgibbs			 * Clear out any entries in the QINFIFO first
9523123579Sgibbs			 * so we are the next SCB for this target
9524123579Sgibbs			 * to run.
9525123579Sgibbs			 */
9526123579Sgibbs			ahd_search_qinfifo(ahd, target, channel, lun,
9527123579Sgibbs					   SCB_LIST_NULL, ROLE_INITIATOR,
9528123579Sgibbs					   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
9529123579Sgibbs			ahd_qinfifo_requeue_tail(ahd, scb);
9530123579Sgibbs			ahd_set_scbptr(ahd, active_scbptr);
9531123579Sgibbs			ahd_print_path(ahd, scb);
9532123579Sgibbs			printf("Queuing a BDR SCB\n");
9533137870Sgibbs			aic_scb_timer_reset(scb, 2 * 1000);
9534123579Sgibbs			break;
9535123579Sgibbs		}
9536123579Sgibbs	}
9537123579Sgibbs
9538123579Sgibbs	/*
9539123579Sgibbs	 * Any remaining SCBs were not the "culprit", so remove
9540123579Sgibbs	 * them from the timeout list.  The timer for these commands
9541123579Sgibbs	 * will be reset once the recovery SCB completes.
9542123579Sgibbs	 */
9543123579Sgibbs	while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
9544123579Sgibbs
9545123579Sgibbs		LIST_REMOVE(scb, timedout_links);
9546123579Sgibbs		scb->flags &= ~SCB_TIMEDOUT;
9547123579Sgibbs	}
9548123579Sgibbs
9549123579Sgibbs	ahd_unpause(ahd);
9550123579Sgibbs}
9551123579Sgibbs
9552129134Sgibbs/*
9553129134Sgibbs * Re-schedule a timeout for the passed in SCB if we determine that some
9554129134Sgibbs * other SCB is in the process of recovery or an SCB with a longer
9555129134Sgibbs * timeout is still pending.  Limit our search to just "other_scb"
9556129134Sgibbs * if it is non-NULL.
9557129134Sgibbs */
9558129134Sgibbsstatic int
9559123579Sgibbsahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb,
9560123579Sgibbs		      struct scb *other_scb)
9561123579Sgibbs{
9562123579Sgibbs	u_int	newtimeout;
9563129134Sgibbs	int	found;
9564123579Sgibbs
9565123579Sgibbs	ahd_print_path(ahd, scb);
9566123579Sgibbs	printf("Other SCB Timeout%s",
9567123579Sgibbs 	       (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
9568123579Sgibbs	       ? " again\n" : "\n");
9569129134Sgibbs
9570199260Sattilio	AHD_UNCORRECTABLE_ERROR(ahd);
9571129134Sgibbs	newtimeout = aic_get_timeout(scb);
9572123579Sgibbs	scb->flags |= SCB_OTHERTCL_TIMEOUT;
9573129134Sgibbs	found = 0;
9574129134Sgibbs	if (other_scb != NULL) {
9575129134Sgibbs		if ((other_scb->flags
9576129134Sgibbs		   & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0
9577129134Sgibbs		 || (other_scb->flags & SCB_RECOVERY_SCB) != 0) {
9578129134Sgibbs			found++;
9579129134Sgibbs			newtimeout = MAX(aic_get_timeout(other_scb),
9580129134Sgibbs					 newtimeout);
9581129134Sgibbs		}
9582129134Sgibbs	} else {
9583129134Sgibbs		LIST_FOREACH(other_scb, &ahd->pending_scbs, pending_links) {
9584129134Sgibbs			if ((other_scb->flags
9585129134Sgibbs			   & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0
9586129134Sgibbs			 || (other_scb->flags & SCB_RECOVERY_SCB) != 0) {
9587129134Sgibbs				found++;
9588129134Sgibbs				newtimeout = MAX(aic_get_timeout(other_scb),
9589129134Sgibbs						 newtimeout);
9590129134Sgibbs			}
9591129134Sgibbs		}
9592129134Sgibbs	}
9593129134Sgibbs
9594129134Sgibbs	if (found != 0)
9595129134Sgibbs		aic_scb_timer_reset(scb, newtimeout);
9596129134Sgibbs	else {
9597129134Sgibbs		ahd_print_path(ahd, scb);
9598129134Sgibbs		printf("No other SCB worth waiting for...\n");
9599129134Sgibbs	}
9600129134Sgibbs
9601129134Sgibbs	return (found != 0);
9602123579Sgibbs}
9603123579Sgibbs
960497883Sgibbs/**************************** Flexport Logic **********************************/
960597883Sgibbs/*
960697883Sgibbs * Read count 16bit words from 16bit word address start_addr from the
960797883Sgibbs * SEEPROM attached to the controller, into buf, using the controller's
9608114623Sgibbs * SEEPROM reading state machine.  Optionally treat the data as a byte
9609114623Sgibbs * stream in terms of byte order.
961097883Sgibbs */
961197883Sgibbsint
961297883Sgibbsahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf,
9613114623Sgibbs		 u_int start_addr, u_int count, int bytestream)
961497883Sgibbs{
961597883Sgibbs	u_int cur_addr;
961697883Sgibbs	u_int end_addr;
961797883Sgibbs	int   error;
961897883Sgibbs
961997883Sgibbs	/*
962097883Sgibbs	 * If we never make it through the loop even once,
962197883Sgibbs	 * we were passed invalid arguments.
962297883Sgibbs	 */
962397883Sgibbs	error = EINVAL;
962497883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
962597883Sgibbs	end_addr = start_addr + count;
962697883Sgibbs	for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
9627114623Sgibbs
962897883Sgibbs		ahd_outb(ahd, SEEADR, cur_addr);
962997883Sgibbs		ahd_outb(ahd, SEECTL, SEEOP_READ | SEESTART);
963097883Sgibbs
963197883Sgibbs		error = ahd_wait_seeprom(ahd);
963297883Sgibbs		if (error)
963397883Sgibbs			break;
9634114623Sgibbs		if (bytestream != 0) {
9635114623Sgibbs			uint8_t *bytestream_ptr;
9636114623Sgibbs
9637114623Sgibbs			bytestream_ptr = (uint8_t *)buf;
9638114623Sgibbs			*bytestream_ptr++ = ahd_inb(ahd, SEEDAT);
9639114623Sgibbs			*bytestream_ptr = ahd_inb(ahd, SEEDAT+1);
9640114623Sgibbs		} else {
9641114623Sgibbs			/*
9642114623Sgibbs			 * ahd_inw() already handles machine byte order.
9643114623Sgibbs			 */
9644114623Sgibbs			*buf = ahd_inw(ahd, SEEDAT);
9645114623Sgibbs		}
9646114623Sgibbs		buf++;
964797883Sgibbs	}
964897883Sgibbs	return (error);
964997883Sgibbs}
965097883Sgibbs
965197883Sgibbs/*
965297883Sgibbs * Write count 16bit words from buf, into SEEPROM attache to the
965397883Sgibbs * controller starting at 16bit word address start_addr, using the
965497883Sgibbs * controller's SEEPROM writing state machine.
965597883Sgibbs */
965697883Sgibbsint
965797883Sgibbsahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf,
965897883Sgibbs		  u_int start_addr, u_int count)
965997883Sgibbs{
966097883Sgibbs	u_int cur_addr;
966197883Sgibbs	u_int end_addr;
966297883Sgibbs	int   error;
966397883Sgibbs	int   retval;
966497883Sgibbs
966597883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
966697883Sgibbs	error = ENOENT;
966797883Sgibbs
966897883Sgibbs	/* Place the chip into write-enable mode */
966997883Sgibbs	ahd_outb(ahd, SEEADR, SEEOP_EWEN_ADDR);
967097883Sgibbs	ahd_outb(ahd, SEECTL, SEEOP_EWEN | SEESTART);
967197883Sgibbs	error = ahd_wait_seeprom(ahd);
967297883Sgibbs	if (error)
967397883Sgibbs		return (error);
967497883Sgibbs
967597883Sgibbs	/*
967697883Sgibbs	 * Write the data.  If we don't get throught the loop at
967797883Sgibbs	 * least once, the arguments were invalid.
967897883Sgibbs	 */
967997883Sgibbs	retval = EINVAL;
968097883Sgibbs	end_addr = start_addr + count;
968197883Sgibbs	for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
968297883Sgibbs		ahd_outw(ahd, SEEDAT, *buf++);
968397883Sgibbs		ahd_outb(ahd, SEEADR, cur_addr);
968497883Sgibbs		ahd_outb(ahd, SEECTL, SEEOP_WRITE | SEESTART);
968597883Sgibbs
968697883Sgibbs		retval = ahd_wait_seeprom(ahd);
968797883Sgibbs		if (retval)
968897883Sgibbs			break;
968997883Sgibbs	}
969097883Sgibbs
969197883Sgibbs	/*
969297883Sgibbs	 * Disable writes.
969397883Sgibbs	 */
969497883Sgibbs	ahd_outb(ahd, SEEADR, SEEOP_EWDS_ADDR);
969597883Sgibbs	ahd_outb(ahd, SEECTL, SEEOP_EWDS | SEESTART);
969697883Sgibbs	error = ahd_wait_seeprom(ahd);
969797883Sgibbs	if (error)
969897883Sgibbs		return (error);
969997883Sgibbs	return (retval);
970097883Sgibbs}
970197883Sgibbs
970297883Sgibbs/*
970397883Sgibbs * Wait ~100us for the serial eeprom to satisfy our request.
970497883Sgibbs */
970597883Sgibbsint
970697883Sgibbsahd_wait_seeprom(struct ahd_softc *ahd)
970797883Sgibbs{
970897883Sgibbs	int cnt;
970997883Sgibbs
9710123579Sgibbs	cnt = 5000;
971197883Sgibbs	while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
9712123579Sgibbs		aic_delay(5);
971397883Sgibbs
971497883Sgibbs	if (cnt == 0)
971597883Sgibbs		return (ETIMEDOUT);
971697883Sgibbs	return (0);
971797883Sgibbs}
971897883Sgibbs
9719114623Sgibbs/*
9720114623Sgibbs * Validate the two checksums in the per_channel
9721114623Sgibbs * vital product data struct.
9722114623Sgibbs */
972397883Sgibbsint
9724114623Sgibbsahd_verify_vpd_cksum(struct vpd_config *vpd)
9725114623Sgibbs{
9726114623Sgibbs	int i;
9727114623Sgibbs	int maxaddr;
9728114623Sgibbs	uint32_t checksum;
9729114623Sgibbs	uint8_t *vpdarray;
9730114623Sgibbs
9731114623Sgibbs	vpdarray = (uint8_t *)vpd;
9732114623Sgibbs	maxaddr = offsetof(struct vpd_config, vpd_checksum);
9733114623Sgibbs	checksum = 0;
9734114623Sgibbs	for (i = offsetof(struct vpd_config, resource_type); i < maxaddr; i++)
9735114623Sgibbs		checksum = checksum + vpdarray[i];
9736114623Sgibbs	if (checksum == 0
9737114623Sgibbs	 || (-checksum & 0xFF) != vpd->vpd_checksum)
9738114623Sgibbs		return (0);
9739114623Sgibbs
9740114623Sgibbs	checksum = 0;
9741114623Sgibbs	maxaddr = offsetof(struct vpd_config, checksum);
9742114623Sgibbs	for (i = offsetof(struct vpd_config, default_target_flags);
9743114623Sgibbs	     i < maxaddr; i++)
9744114623Sgibbs		checksum = checksum + vpdarray[i];
9745114623Sgibbs	if (checksum == 0
9746114623Sgibbs	 || (-checksum & 0xFF) != vpd->checksum)
9747114623Sgibbs		return (0);
9748114623Sgibbs	return (1);
9749114623Sgibbs}
9750114623Sgibbs
9751114623Sgibbsint
975297883Sgibbsahd_verify_cksum(struct seeprom_config *sc)
975397883Sgibbs{
975497883Sgibbs	int i;
975597883Sgibbs	int maxaddr;
975697883Sgibbs	uint32_t checksum;
975797883Sgibbs	uint16_t *scarray;
975897883Sgibbs
975997883Sgibbs	maxaddr = (sizeof(*sc)/2) - 1;
976097883Sgibbs	checksum = 0;
976197883Sgibbs	scarray = (uint16_t *)sc;
976297883Sgibbs
976397883Sgibbs	for (i = 0; i < maxaddr; i++)
976497883Sgibbs		checksum = checksum + scarray[i];
976597883Sgibbs	if (checksum == 0
976697883Sgibbs	 || (checksum & 0xFFFF) != sc->checksum) {
976797883Sgibbs		return (0);
976897883Sgibbs	} else {
976997883Sgibbs		return (1);
977097883Sgibbs	}
977197883Sgibbs}
977297883Sgibbs
977397883Sgibbsint
977497883Sgibbsahd_acquire_seeprom(struct ahd_softc *ahd)
977597883Sgibbs{
9776102679Sgibbs	/*
9777102679Sgibbs	 * We should be able to determine the SEEPROM type
9778102679Sgibbs	 * from the flexport logic, but unfortunately not
9779102679Sgibbs	 * all implementations have this logic and there is
9780102679Sgibbs	 * no programatic method for determining if the logic
9781102679Sgibbs	 * is present.
9782102679Sgibbs	 */
9783102679Sgibbs	return (1);
9784102679Sgibbs#if 0
978597883Sgibbs	uint8_t	seetype;
978697883Sgibbs	int	error;
978797883Sgibbs
978897883Sgibbs	error = ahd_read_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, &seetype);
978997883Sgibbs	if (error != 0
979097883Sgibbs         || ((seetype & FLX_ROMSTAT_SEECFG) == FLX_ROMSTAT_SEE_NONE))
979197883Sgibbs		return (0);
979297883Sgibbs	return (1);
9793102679Sgibbs#endif
979497883Sgibbs}
979597883Sgibbs
979697883Sgibbsvoid
979797883Sgibbsahd_release_seeprom(struct ahd_softc *ahd)
979897883Sgibbs{
979997883Sgibbs	/* Currently a no-op */
980097883Sgibbs}
980197883Sgibbs
980297883Sgibbsint
980397883Sgibbsahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value)
980497883Sgibbs{
980597883Sgibbs	int error;
980697883Sgibbs
980797883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
980897883Sgibbs	if (addr > 7)
980997883Sgibbs		panic("ahd_write_flexport: address out of range");
981097883Sgibbs	ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
981197883Sgibbs	error = ahd_wait_flexport(ahd);
981297883Sgibbs	if (error != 0)
981397883Sgibbs		return (error);
981497883Sgibbs	ahd_outb(ahd, BRDDAT, value);
981597883Sgibbs	ahd_flush_device_writes(ahd);
981697883Sgibbs	ahd_outb(ahd, BRDCTL, BRDSTB|BRDEN|(addr << 3));
981797883Sgibbs	ahd_flush_device_writes(ahd);
981897883Sgibbs	ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
981997883Sgibbs	ahd_flush_device_writes(ahd);
982097883Sgibbs	ahd_outb(ahd, BRDCTL, 0);
982197883Sgibbs	ahd_flush_device_writes(ahd);
982297883Sgibbs	return (0);
982397883Sgibbs}
982497883Sgibbs
982597883Sgibbsint
982697883Sgibbsahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value)
982797883Sgibbs{
982897883Sgibbs	int	error;
982997883Sgibbs
983097883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
983197883Sgibbs	if (addr > 7)
983297883Sgibbs		panic("ahd_read_flexport: address out of range");
983397883Sgibbs	ahd_outb(ahd, BRDCTL, BRDRW|BRDEN|(addr << 3));
983497883Sgibbs	error = ahd_wait_flexport(ahd);
983597883Sgibbs	if (error != 0)
983697883Sgibbs		return (error);
983797883Sgibbs	*value = ahd_inb(ahd, BRDDAT);
983897883Sgibbs	ahd_outb(ahd, BRDCTL, 0);
983997883Sgibbs	ahd_flush_device_writes(ahd);
984097883Sgibbs	return (0);
984197883Sgibbs}
984297883Sgibbs
984397883Sgibbs/*
984497883Sgibbs * Wait at most 2 seconds for flexport arbitration to succeed.
984597883Sgibbs */
984697883Sgibbsint
984797883Sgibbsahd_wait_flexport(struct ahd_softc *ahd)
984897883Sgibbs{
984997883Sgibbs	int cnt;
985097883Sgibbs
985197883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
985297883Sgibbs	cnt = 1000000 * 2 / 5;
985397883Sgibbs	while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt)
9854123579Sgibbs		aic_delay(5);
985597883Sgibbs
985697883Sgibbs	if (cnt == 0)
985797883Sgibbs		return (ETIMEDOUT);
985897883Sgibbs	return (0);
985997883Sgibbs}
986097883Sgibbs
986197883Sgibbs/************************* Target Mode ****************************************/
986297883Sgibbs#ifdef AHD_TARGET_MODE
986397883Sgibbscam_status
986497883Sgibbsahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb,
986597883Sgibbs		    struct ahd_tmode_tstate **tstate,
986697883Sgibbs		    struct ahd_tmode_lstate **lstate,
986797883Sgibbs		    int notfound_failure)
986897883Sgibbs{
986997883Sgibbs
987097883Sgibbs	if ((ahd->features & AHD_TARGETMODE) == 0)
987197883Sgibbs		return (CAM_REQ_INVALID);
987297883Sgibbs
987397883Sgibbs	/*
987497883Sgibbs	 * Handle the 'black hole' device that sucks up
987597883Sgibbs	 * requests to unattached luns on enabled targets.
987697883Sgibbs	 */
987797883Sgibbs	if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD
987897883Sgibbs	 && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
987997883Sgibbs		*tstate = NULL;
988097883Sgibbs		*lstate = ahd->black_hole;
988197883Sgibbs	} else {
988297883Sgibbs		u_int max_id;
988397883Sgibbs
988497883Sgibbs		max_id = (ahd->features & AHD_WIDE) ? 15 : 7;
988597883Sgibbs		if (ccb->ccb_h.target_id > max_id)
988697883Sgibbs			return (CAM_TID_INVALID);
988797883Sgibbs
988897883Sgibbs		if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS)
988997883Sgibbs			return (CAM_LUN_INVALID);
989097883Sgibbs
989197883Sgibbs		*tstate = ahd->enabled_targets[ccb->ccb_h.target_id];
989297883Sgibbs		*lstate = NULL;
989397883Sgibbs		if (*tstate != NULL)
989497883Sgibbs			*lstate =
989597883Sgibbs			    (*tstate)->enabled_luns[ccb->ccb_h.target_lun];
989697883Sgibbs	}
989797883Sgibbs
989897883Sgibbs	if (notfound_failure != 0 && *lstate == NULL)
989997883Sgibbs		return (CAM_PATH_INVALID);
990097883Sgibbs
990197883Sgibbs	return (CAM_REQ_CMP);
990297883Sgibbs}
990397883Sgibbs
990497883Sgibbsvoid
990597883Sgibbsahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
990697883Sgibbs{
990797883Sgibbs#if NOT_YET
990897883Sgibbs	struct	   ahd_tmode_tstate *tstate;
990997883Sgibbs	struct	   ahd_tmode_lstate *lstate;
991097883Sgibbs	struct	   ccb_en_lun *cel;
991197883Sgibbs	cam_status status;
991297883Sgibbs	u_int	   target;
991397883Sgibbs	u_int	   lun;
991497883Sgibbs	u_int	   target_mask;
991597883Sgibbs	u_long	   s;
991697883Sgibbs	char	   channel;
991797883Sgibbs
991897883Sgibbs	status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, &lstate,
991997883Sgibbs				     /*notfound_failure*/FALSE);
992097883Sgibbs
992197883Sgibbs	if (status != CAM_REQ_CMP) {
992297883Sgibbs		ccb->ccb_h.status = status;
992397883Sgibbs		return;
992497883Sgibbs	}
992597883Sgibbs
992697883Sgibbs	if ((ahd->features & AHD_MULTIROLE) != 0) {
992797883Sgibbs		u_int	   our_id;
992897883Sgibbs
992997883Sgibbs		our_id = ahd->our_id;
993097883Sgibbs		if (ccb->ccb_h.target_id != our_id) {
993197883Sgibbs			if ((ahd->features & AHD_MULTI_TID) != 0
993297883Sgibbs		   	 && (ahd->flags & AHD_INITIATORROLE) != 0) {
993397883Sgibbs				/*
993497883Sgibbs				 * Only allow additional targets if
993597883Sgibbs				 * the initiator role is disabled.
993697883Sgibbs				 * The hardware cannot handle a re-select-in
993797883Sgibbs				 * on the initiator id during a re-select-out
993897883Sgibbs				 * on a different target id.
993997883Sgibbs				 */
994097883Sgibbs				status = CAM_TID_INVALID;
994197883Sgibbs			} else if ((ahd->flags & AHD_INITIATORROLE) != 0
994297883Sgibbs				|| ahd->enabled_luns > 0) {
994397883Sgibbs				/*
994497883Sgibbs				 * Only allow our target id to change
994597883Sgibbs				 * if the initiator role is not configured
994697883Sgibbs				 * and there are no enabled luns which
994797883Sgibbs				 * are attached to the currently registered
994897883Sgibbs				 * scsi id.
994997883Sgibbs				 */
995097883Sgibbs				status = CAM_TID_INVALID;
995197883Sgibbs			}
995297883Sgibbs		}
995397883Sgibbs	}
995497883Sgibbs
995597883Sgibbs	if (status != CAM_REQ_CMP) {
995697883Sgibbs		ccb->ccb_h.status = status;
995797883Sgibbs		return;
995897883Sgibbs	}
995997883Sgibbs
996097883Sgibbs	/*
996197883Sgibbs	 * We now have an id that is valid.
996297883Sgibbs	 * If we aren't in target mode, switch modes.
996397883Sgibbs	 */
996497883Sgibbs	if ((ahd->flags & AHD_TARGETROLE) == 0
996597883Sgibbs	 && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
996697883Sgibbs		printf("Configuring Target Mode\n");
996797883Sgibbs		if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
996897883Sgibbs			ccb->ccb_h.status = CAM_BUSY;
996997883Sgibbs			return;
997097883Sgibbs		}
997197883Sgibbs		ahd->flags |= AHD_TARGETROLE;
997297883Sgibbs		if ((ahd->features & AHD_MULTIROLE) == 0)
997397883Sgibbs			ahd->flags &= ~AHD_INITIATORROLE;
997497883Sgibbs		ahd_pause(ahd);
997597883Sgibbs		ahd_loadseq(ahd);
9976115917Sgibbs		ahd_restart(ahd);
997797883Sgibbs	}
997897883Sgibbs	cel = &ccb->cel;
997997883Sgibbs	target = ccb->ccb_h.target_id;
998097883Sgibbs	lun = ccb->ccb_h.target_lun;
998197883Sgibbs	channel = SIM_CHANNEL(ahd, sim);
998297883Sgibbs	target_mask = 0x01 << target;
998397883Sgibbs	if (channel == 'B')
998497883Sgibbs		target_mask <<= 8;
998597883Sgibbs
998697883Sgibbs	if (cel->enable != 0) {
998797883Sgibbs		u_int scsiseq1;
998897883Sgibbs
998997883Sgibbs		/* Are we already enabled?? */
999097883Sgibbs		if (lstate != NULL) {
999197883Sgibbs			xpt_print_path(ccb->ccb_h.path);
999297883Sgibbs			printf("Lun already enabled\n");
9993199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
999497883Sgibbs			ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
999597883Sgibbs			return;
999697883Sgibbs		}
999797883Sgibbs
999897883Sgibbs		if (cel->grp6_len != 0
999997883Sgibbs		 || cel->grp7_len != 0) {
1000097883Sgibbs			/*
1000197883Sgibbs			 * Don't (yet?) support vendor
1000297883Sgibbs			 * specific commands.
1000397883Sgibbs			 */
1000497883Sgibbs			ccb->ccb_h.status = CAM_REQ_INVALID;
1000597883Sgibbs			printf("Non-zero Group Codes\n");
1000697883Sgibbs			return;
1000797883Sgibbs		}
1000897883Sgibbs
1000997883Sgibbs		/*
1001097883Sgibbs		 * Seems to be okay.
1001197883Sgibbs		 * Setup our data structures.
1001297883Sgibbs		 */
1001397883Sgibbs		if (target != CAM_TARGET_WILDCARD && tstate == NULL) {
1001497883Sgibbs			tstate = ahd_alloc_tstate(ahd, target, channel);
1001597883Sgibbs			if (tstate == NULL) {
1001697883Sgibbs				xpt_print_path(ccb->ccb_h.path);
1001797883Sgibbs				printf("Couldn't allocate tstate\n");
1001897883Sgibbs				ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1001997883Sgibbs				return;
1002097883Sgibbs			}
1002197883Sgibbs		}
1002297883Sgibbs		lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT);
1002397883Sgibbs		if (lstate == NULL) {
1002497883Sgibbs			xpt_print_path(ccb->ccb_h.path);
1002597883Sgibbs			printf("Couldn't allocate lstate\n");
1002697883Sgibbs			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1002797883Sgibbs			return;
1002897883Sgibbs		}
1002997883Sgibbs		memset(lstate, 0, sizeof(*lstate));
1003097883Sgibbs		status = xpt_create_path(&lstate->path, /*periph*/NULL,
1003197883Sgibbs					 xpt_path_path_id(ccb->ccb_h.path),
1003297883Sgibbs					 xpt_path_target_id(ccb->ccb_h.path),
1003397883Sgibbs					 xpt_path_lun_id(ccb->ccb_h.path));
1003497883Sgibbs		if (status != CAM_REQ_CMP) {
1003597883Sgibbs			free(lstate, M_DEVBUF);
1003697883Sgibbs			xpt_print_path(ccb->ccb_h.path);
1003797883Sgibbs			printf("Couldn't allocate path\n");
1003897883Sgibbs			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1003997883Sgibbs			return;
1004097883Sgibbs		}
1004197883Sgibbs		SLIST_INIT(&lstate->accept_tios);
1004297883Sgibbs		SLIST_INIT(&lstate->immed_notifies);
1004397883Sgibbs		ahd_pause(ahd);
1004497883Sgibbs		if (target != CAM_TARGET_WILDCARD) {
1004597883Sgibbs			tstate->enabled_luns[lun] = lstate;
1004697883Sgibbs			ahd->enabled_luns++;
1004797883Sgibbs
1004897883Sgibbs			if ((ahd->features & AHD_MULTI_TID) != 0) {
1004997883Sgibbs				u_int targid_mask;
1005097883Sgibbs
10051123579Sgibbs				targid_mask = ahd_inw(ahd, TARGID);
1005297883Sgibbs				targid_mask |= target_mask;
10053123579Sgibbs				ahd_outw(ahd, TARGID, targid_mask);
1005497883Sgibbs				ahd_update_scsiid(ahd, targid_mask);
1005597883Sgibbs			} else {
1005697883Sgibbs				u_int our_id;
1005797883Sgibbs				char  channel;
1005897883Sgibbs
1005997883Sgibbs				channel = SIM_CHANNEL(ahd, sim);
1006097883Sgibbs				our_id = SIM_SCSI_ID(ahd, sim);
1006197883Sgibbs
1006297883Sgibbs				/*
1006397883Sgibbs				 * This can only happen if selections
1006497883Sgibbs				 * are not enabled
1006597883Sgibbs				 */
1006697883Sgibbs				if (target != our_id) {
1006797883Sgibbs					u_int sblkctl;
1006897883Sgibbs					char  cur_channel;
1006997883Sgibbs					int   swap;
1007097883Sgibbs
1007197883Sgibbs					sblkctl = ahd_inb(ahd, SBLKCTL);
1007297883Sgibbs					cur_channel = (sblkctl & SELBUSB)
1007397883Sgibbs						    ? 'B' : 'A';
1007497883Sgibbs					if ((ahd->features & AHD_TWIN) == 0)
1007597883Sgibbs						cur_channel = 'A';
1007697883Sgibbs					swap = cur_channel != channel;
1007797883Sgibbs					ahd->our_id = target;
1007897883Sgibbs
1007997883Sgibbs					if (swap)
1008097883Sgibbs						ahd_outb(ahd, SBLKCTL,
1008197883Sgibbs							 sblkctl ^ SELBUSB);
1008297883Sgibbs
1008397883Sgibbs					ahd_outb(ahd, SCSIID, target);
1008497883Sgibbs
1008597883Sgibbs					if (swap)
1008697883Sgibbs						ahd_outb(ahd, SBLKCTL, sblkctl);
1008797883Sgibbs				}
1008897883Sgibbs			}
1008997883Sgibbs		} else
1009097883Sgibbs			ahd->black_hole = lstate;
1009197883Sgibbs		/* Allow select-in operations */
1009297883Sgibbs		if (ahd->black_hole != NULL && ahd->enabled_luns > 0) {
1009397883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
1009497883Sgibbs			scsiseq1 |= ENSELI;
1009597883Sgibbs			ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
1009697883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ1);
1009797883Sgibbs			scsiseq1 |= ENSELI;
1009897883Sgibbs			ahd_outb(ahd, SCSISEQ1, scsiseq1);
1009997883Sgibbs		}
1010097883Sgibbs		ahd_unpause(ahd);
1010197883Sgibbs		ccb->ccb_h.status = CAM_REQ_CMP;
1010297883Sgibbs		xpt_print_path(ccb->ccb_h.path);
1010397883Sgibbs		printf("Lun now enabled for target mode\n");
1010497883Sgibbs	} else {
1010597883Sgibbs		struct scb *scb;
1010697883Sgibbs		int i, empty;
1010797883Sgibbs
1010897883Sgibbs		if (lstate == NULL) {
1010997883Sgibbs			ccb->ccb_h.status = CAM_LUN_INVALID;
1011097883Sgibbs			return;
1011197883Sgibbs		}
1011297883Sgibbs
1011397883Sgibbs		ccb->ccb_h.status = CAM_REQ_CMP;
1011497883Sgibbs		LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
1011597883Sgibbs			struct ccb_hdr *ccbh;
1011697883Sgibbs
1011797883Sgibbs			ccbh = &scb->io_ctx->ccb_h;
1011897883Sgibbs			if (ccbh->func_code == XPT_CONT_TARGET_IO
1011997883Sgibbs			 && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
1012097883Sgibbs				printf("CTIO pending\n");
1012197883Sgibbs				ccb->ccb_h.status = CAM_REQ_INVALID;
1012297883Sgibbs				return;
1012397883Sgibbs			}
1012497883Sgibbs		}
1012597883Sgibbs
1012697883Sgibbs		if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
1012797883Sgibbs			printf("ATIOs pending\n");
1012897883Sgibbs			ccb->ccb_h.status = CAM_REQ_INVALID;
1012997883Sgibbs		}
1013097883Sgibbs
1013197883Sgibbs		if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
1013297883Sgibbs			printf("INOTs pending\n");
1013397883Sgibbs			ccb->ccb_h.status = CAM_REQ_INVALID;
1013497883Sgibbs		}
1013597883Sgibbs
1013697883Sgibbs		if (ccb->ccb_h.status != CAM_REQ_CMP) {
1013797883Sgibbs			return;
1013897883Sgibbs		}
1013997883Sgibbs
1014097883Sgibbs		xpt_print_path(ccb->ccb_h.path);
1014197883Sgibbs		printf("Target mode disabled\n");
1014297883Sgibbs		xpt_free_path(lstate->path);
1014397883Sgibbs		free(lstate, M_DEVBUF);
1014497883Sgibbs
1014597883Sgibbs		ahd_pause(ahd);
1014697883Sgibbs		/* Can we clean up the target too? */
1014797883Sgibbs		if (target != CAM_TARGET_WILDCARD) {
1014897883Sgibbs			tstate->enabled_luns[lun] = NULL;
1014997883Sgibbs			ahd->enabled_luns--;
1015097883Sgibbs			for (empty = 1, i = 0; i < 8; i++)
1015197883Sgibbs				if (tstate->enabled_luns[i] != NULL) {
1015297883Sgibbs					empty = 0;
1015397883Sgibbs					break;
1015497883Sgibbs				}
1015597883Sgibbs
1015697883Sgibbs			if (empty) {
1015797883Sgibbs				ahd_free_tstate(ahd, target, channel,
1015897883Sgibbs						/*force*/FALSE);
1015997883Sgibbs				if (ahd->features & AHD_MULTI_TID) {
1016097883Sgibbs					u_int targid_mask;
1016197883Sgibbs
10162123579Sgibbs					targid_mask = ahd_inw(ahd, TARGID);
1016397883Sgibbs					targid_mask &= ~target_mask;
10164123579Sgibbs					ahd_outw(ahd, TARGID, targid_mask);
1016597883Sgibbs					ahd_update_scsiid(ahd, targid_mask);
1016697883Sgibbs				}
1016797883Sgibbs			}
1016897883Sgibbs		} else {
1016997883Sgibbs
1017097883Sgibbs			ahd->black_hole = NULL;
1017197883Sgibbs
1017297883Sgibbs			/*
1017397883Sgibbs			 * We can't allow selections without
1017497883Sgibbs			 * our black hole device.
1017597883Sgibbs			 */
1017697883Sgibbs			empty = TRUE;
1017797883Sgibbs		}
1017897883Sgibbs		if (ahd->enabled_luns == 0) {
1017997883Sgibbs			/* Disallow select-in */
1018097883Sgibbs			u_int scsiseq1;
1018197883Sgibbs
1018297883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
1018397883Sgibbs			scsiseq1 &= ~ENSELI;
1018497883Sgibbs			ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
1018597883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ1);
1018697883Sgibbs			scsiseq1 &= ~ENSELI;
1018797883Sgibbs			ahd_outb(ahd, SCSISEQ1, scsiseq1);
1018897883Sgibbs
1018997883Sgibbs			if ((ahd->features & AHD_MULTIROLE) == 0) {
1019097883Sgibbs				printf("Configuring Initiator Mode\n");
1019197883Sgibbs				ahd->flags &= ~AHD_TARGETROLE;
1019297883Sgibbs				ahd->flags |= AHD_INITIATORROLE;
1019397883Sgibbs				ahd_pause(ahd);
1019497883Sgibbs				ahd_loadseq(ahd);
10195115917Sgibbs				ahd_restart(ahd);
10196115917Sgibbs				/*
10197115917Sgibbs				 * Unpaused.  The extra unpause
10198115917Sgibbs				 * that follows is harmless.
10199115917Sgibbs				 */
1020097883Sgibbs			}
1020197883Sgibbs		}
1020297883Sgibbs		ahd_unpause(ahd);
1020397883Sgibbs	}
1020497883Sgibbs#endif
1020597883Sgibbs}
1020697883Sgibbs
1020797883Sgibbsstatic void
1020897883Sgibbsahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)
1020997883Sgibbs{
1021097883Sgibbs#if NOT_YET
1021197883Sgibbs	u_int scsiid_mask;
1021297883Sgibbs	u_int scsiid;
1021397883Sgibbs
1021497883Sgibbs	if ((ahd->features & AHD_MULTI_TID) == 0)
1021597883Sgibbs		panic("ahd_update_scsiid called on non-multitid unit\n");
1021697883Sgibbs
1021797883Sgibbs	/*
10218102679Sgibbs	 * Since we will rely on the TARGID mask
1021997883Sgibbs	 * for selection enables, ensure that OID
1022097883Sgibbs	 * in SCSIID is not set to some other ID
1022197883Sgibbs	 * that we don't want to allow selections on.
1022297883Sgibbs	 */
1022397883Sgibbs	if ((ahd->features & AHD_ULTRA2) != 0)
1022497883Sgibbs		scsiid = ahd_inb(ahd, SCSIID_ULTRA2);
1022597883Sgibbs	else
1022697883Sgibbs		scsiid = ahd_inb(ahd, SCSIID);
1022797883Sgibbs	scsiid_mask = 0x1 << (scsiid & OID);
1022897883Sgibbs	if ((targid_mask & scsiid_mask) == 0) {
1022997883Sgibbs		u_int our_id;
1023097883Sgibbs
1023197883Sgibbs		/* ffs counts from 1 */
1023297883Sgibbs		our_id = ffs(targid_mask);
1023397883Sgibbs		if (our_id == 0)
1023497883Sgibbs			our_id = ahd->our_id;
1023597883Sgibbs		else
1023697883Sgibbs			our_id--;
1023797883Sgibbs		scsiid &= TID;
1023897883Sgibbs		scsiid |= our_id;
1023997883Sgibbs	}
1024097883Sgibbs	if ((ahd->features & AHD_ULTRA2) != 0)
1024197883Sgibbs		ahd_outb(ahd, SCSIID_ULTRA2, scsiid);
1024297883Sgibbs	else
1024397883Sgibbs		ahd_outb(ahd, SCSIID, scsiid);
1024497883Sgibbs#endif
1024597883Sgibbs}
1024697883Sgibbs
1024797883Sgibbsvoid
1024897883Sgibbsahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
1024997883Sgibbs{
1025097883Sgibbs	struct target_cmd *cmd;
1025197883Sgibbs
1025297883Sgibbs	ahd_sync_tqinfifo(ahd, BUS_DMASYNC_POSTREAD);
1025397883Sgibbs	while ((cmd = &ahd->targetcmds[ahd->tqinfifonext])->cmd_valid != 0) {
1025497883Sgibbs
1025597883Sgibbs		/*
1025697883Sgibbs		 * Only advance through the queue if we
1025797883Sgibbs		 * have the resources to process the command.
1025897883Sgibbs		 */
1025997883Sgibbs		if (ahd_handle_target_cmd(ahd, cmd) != 0)
1026097883Sgibbs			break;
1026197883Sgibbs
1026297883Sgibbs		cmd->cmd_valid = 0;
1026397883Sgibbs		ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
1026497883Sgibbs				ahd->shared_data_dmamap,
1026597883Sgibbs				ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
1026697883Sgibbs				sizeof(struct target_cmd),
1026797883Sgibbs				BUS_DMASYNC_PREREAD);
1026897883Sgibbs		ahd->tqinfifonext++;
1026997883Sgibbs
1027097883Sgibbs		/*
1027197883Sgibbs		 * Lazily update our position in the target mode incoming
1027297883Sgibbs		 * command queue as seen by the sequencer.
1027397883Sgibbs		 */
1027497883Sgibbs		if ((ahd->tqinfifonext & (HOST_TQINPOS - 1)) == 1) {
1027597883Sgibbs			u_int hs_mailbox;
1027697883Sgibbs
1027797883Sgibbs			hs_mailbox = ahd_inb(ahd, HS_MAILBOX);
1027897883Sgibbs			hs_mailbox &= ~HOST_TQINPOS;
1027997883Sgibbs			hs_mailbox |= ahd->tqinfifonext & HOST_TQINPOS;
1028097883Sgibbs			ahd_outb(ahd, HS_MAILBOX, hs_mailbox);
1028197883Sgibbs		}
1028297883Sgibbs	}
1028397883Sgibbs}
1028497883Sgibbs
1028597883Sgibbsstatic int
1028697883Sgibbsahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd)
1028797883Sgibbs{
1028897883Sgibbs	struct	  ahd_tmode_tstate *tstate;
1028997883Sgibbs	struct	  ahd_tmode_lstate *lstate;
1029097883Sgibbs	struct	  ccb_accept_tio *atio;
1029197883Sgibbs	uint8_t *byte;
1029297883Sgibbs	int	  initiator;
1029397883Sgibbs	int	  target;
1029497883Sgibbs	int	  lun;
1029597883Sgibbs
1029697883Sgibbs	initiator = SCSIID_TARGET(ahd, cmd->scsiid);
1029797883Sgibbs	target = SCSIID_OUR_ID(cmd->scsiid);
1029897883Sgibbs	lun    = (cmd->identify & MSG_IDENTIFY_LUNMASK);
1029997883Sgibbs
1030097883Sgibbs	byte = cmd->bytes;
1030197883Sgibbs	tstate = ahd->enabled_targets[target];
1030297883Sgibbs	lstate = NULL;
1030397883Sgibbs	if (tstate != NULL)
1030497883Sgibbs		lstate = tstate->enabled_luns[lun];
1030597883Sgibbs
1030697883Sgibbs	/*
1030797883Sgibbs	 * Commands for disabled luns go to the black hole driver.
1030897883Sgibbs	 */
1030997883Sgibbs	if (lstate == NULL)
1031097883Sgibbs		lstate = ahd->black_hole;
1031197883Sgibbs
1031297883Sgibbs	atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios);
1031397883Sgibbs	if (atio == NULL) {
1031497883Sgibbs		ahd->flags |= AHD_TQINFIFO_BLOCKED;
1031597883Sgibbs		/*
1031697883Sgibbs		 * Wait for more ATIOs from the peripheral driver for this lun.
1031797883Sgibbs		 */
1031897883Sgibbs		return (1);
1031997883Sgibbs	} else
1032097883Sgibbs		ahd->flags &= ~AHD_TQINFIFO_BLOCKED;
1032197883Sgibbs#ifdef AHD_DEBUG
1032297883Sgibbs	if ((ahd_debug & AHD_SHOW_TQIN) != 0)
1032397883Sgibbs		printf("Incoming command from %d for %d:%d%s\n",
1032497883Sgibbs		       initiator, target, lun,
1032597883Sgibbs		       lstate == ahd->black_hole ? "(Black Holed)" : "");
1032697883Sgibbs#endif
1032797883Sgibbs	SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);
1032897883Sgibbs
1032997883Sgibbs	if (lstate == ahd->black_hole) {
1033097883Sgibbs		/* Fill in the wildcards */
1033197883Sgibbs		atio->ccb_h.target_id = target;
1033297883Sgibbs		atio->ccb_h.target_lun = lun;
1033397883Sgibbs	}
1033497883Sgibbs
1033597883Sgibbs	/*
1033697883Sgibbs	 * Package it up and send it off to
1033797883Sgibbs	 * whomever has this lun enabled.
1033897883Sgibbs	 */
1033997883Sgibbs	atio->sense_len = 0;
1034097883Sgibbs	atio->init_id = initiator;
1034197883Sgibbs	if (byte[0] != 0xFF) {
1034297883Sgibbs		/* Tag was included */
1034397883Sgibbs		atio->tag_action = *byte++;
1034497883Sgibbs		atio->tag_id = *byte++;
1034597883Sgibbs		atio->ccb_h.flags = CAM_TAG_ACTION_VALID;
1034697883Sgibbs	} else {
1034797883Sgibbs		atio->ccb_h.flags = 0;
1034897883Sgibbs	}
1034997883Sgibbs	byte++;
1035097883Sgibbs
1035197883Sgibbs	/* Okay.  Now determine the cdb size based on the command code */
1035297883Sgibbs	switch (*byte >> CMD_GROUP_CODE_SHIFT) {
1035397883Sgibbs	case 0:
1035497883Sgibbs		atio->cdb_len = 6;
1035597883Sgibbs		break;
1035697883Sgibbs	case 1:
1035797883Sgibbs	case 2:
1035897883Sgibbs		atio->cdb_len = 10;
1035997883Sgibbs		break;
1036097883Sgibbs	case 4:
1036197883Sgibbs		atio->cdb_len = 16;
1036297883Sgibbs		break;
1036397883Sgibbs	case 5:
1036497883Sgibbs		atio->cdb_len = 12;
1036597883Sgibbs		break;
1036697883Sgibbs	case 3:
1036797883Sgibbs	default:
1036897883Sgibbs		/* Only copy the opcode. */
1036997883Sgibbs		atio->cdb_len = 1;
1037097883Sgibbs		printf("Reserved or VU command code type encountered\n");
1037197883Sgibbs		break;
1037297883Sgibbs	}
1037397883Sgibbs
1037497883Sgibbs	memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len);
1037597883Sgibbs
1037697883Sgibbs	atio->ccb_h.status |= CAM_CDB_RECVD;
1037797883Sgibbs
1037897883Sgibbs	if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) {
1037997883Sgibbs		/*
1038097883Sgibbs		 * We weren't allowed to disconnect.
1038197883Sgibbs		 * We're hanging on the bus until a
1038297883Sgibbs		 * continue target I/O comes in response
1038397883Sgibbs		 * to this accept tio.
1038497883Sgibbs		 */
1038597883Sgibbs#ifdef AHD_DEBUG
1038697883Sgibbs		if ((ahd_debug & AHD_SHOW_TQIN) != 0)
1038797883Sgibbs			printf("Received Immediate Command %d:%d:%d - %p\n",
1038897883Sgibbs			       initiator, target, lun, ahd->pending_device);
1038997883Sgibbs#endif
1039097883Sgibbs		ahd->pending_device = lstate;
1039197883Sgibbs		ahd_freeze_ccb((union ccb *)atio);
1039297883Sgibbs		atio->ccb_h.flags |= CAM_DIS_DISCONNECT;
1039397883Sgibbs	}
1039497883Sgibbs	xpt_done((union ccb*)atio);
1039597883Sgibbs	return (0);
1039697883Sgibbs}
1039797883Sgibbs
1039897883Sgibbs#endif
10399