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};
6797883Sgibbsstatic const u_int num_chip_names = NUM_ELEMENTS(ahd_chip_names);
6897883Sgibbs
6997883Sgibbs/*
7097883Sgibbs * Hardware error codes.
7197883Sgibbs */
7297883Sgibbsstruct ahd_hard_error_entry {
7397883Sgibbs        uint8_t errno;
7497883Sgibbs	char *errmesg;
7597883Sgibbs};
7697883Sgibbs
7797883Sgibbsstatic struct ahd_hard_error_entry ahd_hard_errors[] = {
7897883Sgibbs	{ DSCTMOUT,	"Discard Timer has timed out" },
7997883Sgibbs	{ ILLOPCODE,	"Illegal Opcode in sequencer program" },
8097883Sgibbs	{ SQPARERR,	"Sequencer Parity Error" },
8197883Sgibbs	{ DPARERR,	"Data-path Parity Error" },
8297883Sgibbs	{ MPARERR,	"Scratch or SCB Memory Parity Error" },
8397883Sgibbs	{ CIOPARERR,	"CIOBUS Parity Error" },
8497883Sgibbs};
8597883Sgibbsstatic const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors);
8697883Sgibbs
8797883Sgibbsstatic struct ahd_phase_table_entry ahd_phase_table[] =
8897883Sgibbs{
8997883Sgibbs	{ P_DATAOUT,	MSG_NOOP,		"in Data-out phase"	},
9097883Sgibbs	{ P_DATAIN,	MSG_INITIATOR_DET_ERR,	"in Data-in phase"	},
9197883Sgibbs	{ P_DATAOUT_DT,	MSG_NOOP,		"in DT Data-out phase"	},
9297883Sgibbs	{ P_DATAIN_DT,	MSG_INITIATOR_DET_ERR,	"in DT Data-in phase"	},
9397883Sgibbs	{ P_COMMAND,	MSG_NOOP,		"in Command phase"	},
9497883Sgibbs	{ P_MESGOUT,	MSG_NOOP,		"in Message-out phase"	},
9597883Sgibbs	{ P_STATUS,	MSG_INITIATOR_DET_ERR,	"in Status phase"	},
9697883Sgibbs	{ P_MESGIN,	MSG_PARITY_ERROR,	"in Message-in phase"	},
9797883Sgibbs	{ P_BUSFREE,	MSG_NOOP,		"while idle"		},
9897883Sgibbs	{ 0,		MSG_NOOP,		"in unknown phase"	}
9997883Sgibbs};
10097883Sgibbs
10197883Sgibbs/*
10297883Sgibbs * In most cases we only wish to itterate over real phases, so
10397883Sgibbs * exclude the last element from the count.
10497883Sgibbs */
10597883Sgibbsstatic const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1;
10697883Sgibbs
10797883Sgibbs/* Our Sequencer Program */
10897883Sgibbs#include "aic79xx_seq.h"
10997883Sgibbs
11097883Sgibbs/**************************** Function Declarations ***************************/
11197883Sgibbsstatic void		ahd_handle_transmission_error(struct ahd_softc *ahd);
11297883Sgibbsstatic void		ahd_handle_lqiphase_error(struct ahd_softc *ahd,
11397883Sgibbs						  u_int lqistat1);
11497883Sgibbsstatic int		ahd_handle_pkt_busfree(struct ahd_softc *ahd,
11597883Sgibbs					       u_int busfreetime);
11697883Sgibbsstatic int		ahd_handle_nonpkt_busfree(struct ahd_softc *ahd);
117102679Sgibbsstatic void		ahd_handle_proto_violation(struct ahd_softc *ahd);
11897883Sgibbsstatic void		ahd_force_renegotiation(struct ahd_softc *ahd,
11997883Sgibbs						struct ahd_devinfo *devinfo);
12097883Sgibbs
12197883Sgibbsstatic struct ahd_tmode_tstate*
12297883Sgibbs			ahd_alloc_tstate(struct ahd_softc *ahd,
12397883Sgibbs					 u_int scsi_id, char channel);
12497883Sgibbs#ifdef AHD_TARGET_MODE
12597883Sgibbsstatic void		ahd_free_tstate(struct ahd_softc *ahd,
12697883Sgibbs					u_int scsi_id, char channel, int force);
12797883Sgibbs#endif
12897883Sgibbsstatic void		ahd_devlimited_syncrate(struct ahd_softc *ahd,
12997883Sgibbs					        struct ahd_initiator_tinfo *,
13097883Sgibbs						u_int *period,
13197883Sgibbs						u_int *ppr_options,
13297883Sgibbs						role_t role);
13397883Sgibbsstatic void		ahd_update_neg_table(struct ahd_softc *ahd,
13497883Sgibbs					     struct ahd_devinfo *devinfo,
13597883Sgibbs					     struct ahd_transinfo *tinfo);
13697883Sgibbsstatic void		ahd_update_pending_scbs(struct ahd_softc *ahd);
13797883Sgibbsstatic void		ahd_fetch_devinfo(struct ahd_softc *ahd,
13897883Sgibbs					  struct ahd_devinfo *devinfo);
13997883Sgibbsstatic void		ahd_scb_devinfo(struct ahd_softc *ahd,
14097883Sgibbs					struct ahd_devinfo *devinfo,
14197883Sgibbs					struct scb *scb);
14297883Sgibbsstatic void		ahd_setup_initiator_msgout(struct ahd_softc *ahd,
14397883Sgibbs						   struct ahd_devinfo *devinfo,
14497883Sgibbs						   struct scb *scb);
14597883Sgibbsstatic void		ahd_build_transfer_msg(struct ahd_softc *ahd,
14697883Sgibbs					       struct ahd_devinfo *devinfo);
14797883Sgibbsstatic void		ahd_construct_sdtr(struct ahd_softc *ahd,
14897883Sgibbs					   struct ahd_devinfo *devinfo,
14997883Sgibbs					   u_int period, u_int offset);
15097883Sgibbsstatic void		ahd_construct_wdtr(struct ahd_softc *ahd,
15197883Sgibbs					   struct ahd_devinfo *devinfo,
15297883Sgibbs					   u_int bus_width);
15397883Sgibbsstatic void		ahd_construct_ppr(struct ahd_softc *ahd,
15497883Sgibbs					  struct ahd_devinfo *devinfo,
15597883Sgibbs					  u_int period, u_int offset,
15697883Sgibbs					  u_int bus_width, u_int ppr_options);
15797883Sgibbsstatic void		ahd_clear_msg_state(struct ahd_softc *ahd);
15897883Sgibbsstatic void		ahd_handle_message_phase(struct ahd_softc *ahd);
15997883Sgibbstypedef enum {
16097883Sgibbs	AHDMSG_1B,
16197883Sgibbs	AHDMSG_2B,
16297883Sgibbs	AHDMSG_EXT
16397883Sgibbs} ahd_msgtype;
16497883Sgibbsstatic int		ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type,
16597883Sgibbs				     u_int msgval, int full);
16697883Sgibbsstatic int		ahd_parse_msg(struct ahd_softc *ahd,
16797883Sgibbs				      struct ahd_devinfo *devinfo);
16897883Sgibbsstatic int		ahd_handle_msg_reject(struct ahd_softc *ahd,
16997883Sgibbs					      struct ahd_devinfo *devinfo);
17097883Sgibbsstatic void		ahd_handle_ign_wide_residue(struct ahd_softc *ahd,
17197883Sgibbs						struct ahd_devinfo *devinfo);
17297883Sgibbsstatic void		ahd_reinitialize_dataptrs(struct ahd_softc *ahd);
17397883Sgibbsstatic void		ahd_handle_devreset(struct ahd_softc *ahd,
17497883Sgibbs					    struct ahd_devinfo *devinfo,
175109588Sgibbs					    u_int lun, cam_status status,
176109588Sgibbs					    char *message, int verbose_level);
177153072Sru#ifdef AHD_TARGET_MODE
17897883Sgibbsstatic void		ahd_setup_target_msgin(struct ahd_softc *ahd,
17997883Sgibbs					       struct ahd_devinfo *devinfo,
18097883Sgibbs					       struct scb *scb);
18197883Sgibbs#endif
18297883Sgibbs
183106803Sscottlstatic u_int		ahd_sglist_size(struct ahd_softc *ahd);
184106803Sscottlstatic u_int		ahd_sglist_allocsize(struct ahd_softc *ahd);
18597883Sgibbsstatic bus_dmamap_callback_t
18697883Sgibbs			ahd_dmamap_cb;
18797883Sgibbsstatic void		ahd_initialize_hscbs(struct ahd_softc *ahd);
18897883Sgibbsstatic int		ahd_init_scbdata(struct ahd_softc *ahd);
18997883Sgibbsstatic void		ahd_fini_scbdata(struct ahd_softc *ahd);
19097883Sgibbsstatic void		ahd_setup_iocell_workaround(struct ahd_softc *ahd);
19197883Sgibbsstatic void		ahd_iocell_first_selection(struct ahd_softc *ahd);
192102679Sgibbsstatic void		ahd_add_col_list(struct ahd_softc *ahd,
193102679Sgibbs					 struct scb *scb, u_int col_idx);
194102679Sgibbsstatic void		ahd_rem_col_list(struct ahd_softc *ahd,
195102679Sgibbs					 struct scb *scb);
19697883Sgibbsstatic void		ahd_chip_init(struct ahd_softc *ahd);
19797883Sgibbsstatic void		ahd_qinfifo_requeue(struct ahd_softc *ahd,
19897883Sgibbs					    struct scb *prev_scb,
19997883Sgibbs					    struct scb *scb);
20097883Sgibbsstatic int		ahd_qinfifo_count(struct ahd_softc *ahd);
20197883Sgibbsstatic int		ahd_search_scb_list(struct ahd_softc *ahd, int target,
20297883Sgibbs					    char channel, int lun, u_int tag,
20397883Sgibbs					    role_t role, uint32_t status,
20497883Sgibbs					    ahd_search_action action,
205133122Sgibbs					    u_int *list_head, u_int *list_tail,
206133122Sgibbs					    u_int tid);
20797883Sgibbsstatic void		ahd_stitch_tid_list(struct ahd_softc *ahd,
20897883Sgibbs					    u_int tid_prev, u_int tid_cur,
20997883Sgibbs					    u_int tid_next);
21097883Sgibbsstatic void		ahd_add_scb_to_free_list(struct ahd_softc *ahd,
21197883Sgibbs						 u_int scbid);
21297883Sgibbsstatic u_int		ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
21397883Sgibbs				     u_int prev, u_int next, u_int tid);
21497883Sgibbsstatic void		ahd_reset_current_bus(struct ahd_softc *ahd);
21597883Sgibbsstatic ahd_callback_t	ahd_reset_poll;
216109588Sgibbsstatic ahd_callback_t	ahd_stat_timer;
21797883Sgibbs#ifdef AHD_DUMP_SEQ
21897883Sgibbsstatic void		ahd_dumpseq(struct ahd_softc *ahd);
21997883Sgibbs#endif
22097883Sgibbsstatic void		ahd_loadseq(struct ahd_softc *ahd);
22197883Sgibbsstatic int		ahd_check_patch(struct ahd_softc *ahd,
22297883Sgibbs					struct patch **start_patch,
22397883Sgibbs					u_int start_instr, u_int *skip_addr);
22497883Sgibbsstatic u_int		ahd_resolve_seqaddr(struct ahd_softc *ahd,
22597883Sgibbs					    u_int address);
22697883Sgibbsstatic void		ahd_download_instr(struct ahd_softc *ahd,
22797883Sgibbs					   u_int instrptr, uint8_t *dconsts);
228107441Sscottlstatic int		ahd_probe_stack_size(struct ahd_softc *ahd);
229129134Sgibbsstatic int		ahd_other_scb_timeout(struct ahd_softc *ahd,
230123579Sgibbs					      struct scb *scb,
231123579Sgibbs					      struct scb *other_scb);
232116940Sgibbsstatic int		ahd_scb_active_in_fifo(struct ahd_softc *ahd,
233116940Sgibbs					       struct scb *scb);
234116940Sgibbsstatic void		ahd_run_data_fifo(struct ahd_softc *ahd,
235116940Sgibbs					  struct scb *scb);
236116940Sgibbs
23797883Sgibbs#ifdef AHD_TARGET_MODE
23897883Sgibbsstatic void		ahd_queue_lstate_event(struct ahd_softc *ahd,
23997883Sgibbs					       struct ahd_tmode_lstate *lstate,
24097883Sgibbs					       u_int initiator_id,
24197883Sgibbs					       u_int event_type,
24297883Sgibbs					       u_int event_arg);
24397883Sgibbsstatic void		ahd_update_scsiid(struct ahd_softc *ahd,
24497883Sgibbs					  u_int targid_mask);
24597883Sgibbsstatic int		ahd_handle_target_cmd(struct ahd_softc *ahd,
24697883Sgibbs					      struct target_cmd *cmd);
24797883Sgibbs#endif
24897883Sgibbs
24997883Sgibbs/******************************** Private Inlines *****************************/
25097883Sgibbsstatic __inline void	ahd_assert_atn(struct ahd_softc *ahd);
25197883Sgibbsstatic __inline int	ahd_currently_packetized(struct ahd_softc *ahd);
25297883Sgibbsstatic __inline int	ahd_set_active_fifo(struct ahd_softc *ahd);
25397883Sgibbs
25497883Sgibbsstatic __inline void
25597883Sgibbsahd_assert_atn(struct ahd_softc *ahd)
25697883Sgibbs{
25797883Sgibbs	ahd_outb(ahd, SCSISIGO, ATNO);
25897883Sgibbs}
25997883Sgibbs
26097883Sgibbs/*
26197883Sgibbs * Determine if the current connection has a packetized
26297883Sgibbs * agreement.  This does not necessarily mean that we
26397883Sgibbs * are currently in a packetized transfer.  We could
26497883Sgibbs * just as easily be sending or receiving a message.
26597883Sgibbs */
26697883Sgibbsstatic __inline int
26797883Sgibbsahd_currently_packetized(struct ahd_softc *ahd)
26897883Sgibbs{
26997883Sgibbs	ahd_mode_state	 saved_modes;
27097883Sgibbs	int		 packetized;
27197883Sgibbs
27297883Sgibbs	saved_modes = ahd_save_modes(ahd);
27397883Sgibbs	if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) {
27497883Sgibbs		/*
27597883Sgibbs		 * The packetized bit refers to the last
27697883Sgibbs		 * connection, not the current one.  Check
27797883Sgibbs		 * for non-zero LQISTATE instead.
27897883Sgibbs		 */
27997883Sgibbs		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
28097883Sgibbs		packetized = ahd_inb(ahd, LQISTATE) != 0;
28197883Sgibbs	} else {
28297883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
28397883Sgibbs		packetized = ahd_inb(ahd, LQISTAT2) & PACKETIZED;
28497883Sgibbs	}
28597883Sgibbs	ahd_restore_modes(ahd, saved_modes);
28697883Sgibbs	return (packetized);
28797883Sgibbs}
28897883Sgibbs
28997883Sgibbsstatic __inline int
29097883Sgibbsahd_set_active_fifo(struct ahd_softc *ahd)
29197883Sgibbs{
29297883Sgibbs	u_int active_fifo;
29397883Sgibbs
29497883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
29597883Sgibbs	active_fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
29697883Sgibbs	switch (active_fifo) {
29797883Sgibbs	case 0:
29897883Sgibbs	case 1:
29997883Sgibbs		ahd_set_modes(ahd, active_fifo, active_fifo);
30097883Sgibbs		return (1);
30197883Sgibbs	default:
30297883Sgibbs		return (0);
30397883Sgibbs	}
30497883Sgibbs}
30597883Sgibbs
30697883Sgibbs/************************* Sequencer Execution Control ************************/
30797883Sgibbs/*
30897883Sgibbs * Restart the sequencer program from address zero
30997883Sgibbs */
31097883Sgibbsvoid
31197883Sgibbsahd_restart(struct ahd_softc *ahd)
31297883Sgibbs{
31397883Sgibbs
31497883Sgibbs	ahd_pause(ahd);
31597883Sgibbs
31697883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
31797883Sgibbs
31897883Sgibbs	/* No more pending messages */
31997883Sgibbs	ahd_clear_msg_state(ahd);
32097883Sgibbs	ahd_outb(ahd, SCSISIGO, 0);		/* De-assert BSY */
32197883Sgibbs	ahd_outb(ahd, MSG_OUT, MSG_NOOP);	/* No message to send */
32297883Sgibbs	ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET);
32397883Sgibbs	ahd_outb(ahd, SEQINTCTL, 0);
32497883Sgibbs	ahd_outb(ahd, LASTPHASE, P_BUSFREE);
32597883Sgibbs	ahd_outb(ahd, SEQ_FLAGS, 0);
32697883Sgibbs	ahd_outb(ahd, SAVED_SCSIID, 0xFF);
32797883Sgibbs	ahd_outb(ahd, SAVED_LUN, 0xFF);
32897883Sgibbs
32997883Sgibbs	/*
33097883Sgibbs	 * Ensure that the sequencer's idea of TQINPOS
33197883Sgibbs	 * matches our own.  The sequencer increments TQINPOS
33297883Sgibbs	 * only after it sees a DMA complete and a reset could
33397883Sgibbs	 * occur before the increment leaving the kernel to believe
33497883Sgibbs	 * the command arrived but the sequencer to not.
33597883Sgibbs	 */
33697883Sgibbs	ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
33797883Sgibbs
33897883Sgibbs	/* Always allow reselection */
33997883Sgibbs	ahd_outb(ahd, SCSISEQ1,
34097883Sgibbs		 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
34197883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
342129134Sgibbs
343129134Sgibbs	/*
344129134Sgibbs	 * Clear any pending sequencer interrupt.  It is no
345129134Sgibbs	 * longer relevant since we're resetting the Program
346129134Sgibbs	 * Counter.
347129134Sgibbs	 */
348129134Sgibbs	ahd_outb(ahd, CLRINT, CLRSEQINT);
349129134Sgibbs
35097883Sgibbs	ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
35197883Sgibbs	ahd_unpause(ahd);
35297883Sgibbs}
35397883Sgibbs
35497883Sgibbsvoid
35597883Sgibbsahd_clear_fifo(struct ahd_softc *ahd, u_int fifo)
35697883Sgibbs{
35797883Sgibbs	ahd_mode_state	 saved_modes;
35897883Sgibbs
35997883Sgibbs#ifdef AHD_DEBUG
36097883Sgibbs	if ((ahd_debug & AHD_SHOW_FIFOS) != 0)
36197883Sgibbs		printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo);
36297883Sgibbs#endif
36397883Sgibbs	saved_modes = ahd_save_modes(ahd);
36497883Sgibbs	ahd_set_modes(ahd, fifo, fifo);
36597883Sgibbs	ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
36697883Sgibbs	if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
36797883Sgibbs		ahd_outb(ahd, CCSGCTL, CCSGRESET);
36897883Sgibbs	ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
36997883Sgibbs	ahd_outb(ahd, SG_STATE, 0);
37097883Sgibbs	ahd_restore_modes(ahd, saved_modes);
37197883Sgibbs}
37297883Sgibbs
37397883Sgibbs/************************* Input/Output Queues ********************************/
374109588Sgibbs/*
375109588Sgibbs * Flush and completed commands that are sitting in the command
376109588Sgibbs * complete queues down on the chip but have yet to be dma'ed back up.
377109588Sgibbs */
37897883Sgibbsvoid
379109588Sgibbsahd_flush_qoutfifo(struct ahd_softc *ahd)
380109588Sgibbs{
381109588Sgibbs	struct		scb *scb;
382109588Sgibbs	ahd_mode_state	saved_modes;
383109588Sgibbs	u_int		saved_scbptr;
384109588Sgibbs	u_int		ccscbctl;
385109588Sgibbs	u_int		scbid;
386109588Sgibbs	u_int		next_scbid;
387109588Sgibbs
388109588Sgibbs	saved_modes = ahd_save_modes(ahd);
389116940Sgibbs
390116940Sgibbs	/*
391123579Sgibbs	 * Flush the good status FIFO for completed packetized commands.
392116940Sgibbs	 */
393116940Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
394109588Sgibbs	saved_scbptr = ahd_get_scbptr(ahd);
395116940Sgibbs	while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
396116940Sgibbs		u_int fifo_mode;
397116940Sgibbs		u_int i;
398116940Sgibbs
399123579Sgibbs		scbid = ahd_inw(ahd, GSFIFO);
400116940Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
401116940Sgibbs		if (scb == NULL) {
402116940Sgibbs			printf("%s: Warning - GSFIFO SCB %d invalid\n",
403116940Sgibbs			       ahd_name(ahd), scbid);
404199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
405116940Sgibbs			continue;
406116940Sgibbs		}
407116940Sgibbs		/*
408116940Sgibbs		 * Determine if this transaction is still active in
409116940Sgibbs		 * any FIFO.  If it is, we must flush that FIFO to
410116940Sgibbs		 * the host before completing the  command.
411116940Sgibbs		 */
412116940Sgibbs		fifo_mode = 0;
413123579Sgibbsrescan_fifos:
414116940Sgibbs		for (i = 0; i < 2; i++) {
415116940Sgibbs			/* Toggle to the other mode. */
416116940Sgibbs			fifo_mode ^= 1;
417116940Sgibbs			ahd_set_modes(ahd, fifo_mode, fifo_mode);
418123655Sgibbs
419123655Sgibbs			if (ahd_scb_active_in_fifo(ahd, scb) == 0)
420116940Sgibbs				continue;
421109588Sgibbs
422116940Sgibbs			ahd_run_data_fifo(ahd, scb);
423116940Sgibbs
424116940Sgibbs			/*
425123579Sgibbs			 * Running this FIFO may cause a CFG4DATA for
426123579Sgibbs			 * this same transaction to assert in the other
427123579Sgibbs			 * FIFO or a new snapshot SAVEPTRS interrupt
428123579Sgibbs			 * in this FIFO.  Even running a FIFO may not
429123579Sgibbs			 * clear the transaction if we are still waiting
430123579Sgibbs			 * for data to drain to the host. We must loop
431123579Sgibbs			 * until the transaction is not active in either
432123579Sgibbs			 * FIFO just to be sure.  Reset our loop counter
433123579Sgibbs			 * so we will visit both FIFOs again before
434123655Sgibbs			 * declaring this transaction finished.  We
435123655Sgibbs			 * also delay a bit so that status has a chance
436123655Sgibbs			 * to change before we look at this FIFO again.
437116940Sgibbs			 */
438123655Sgibbs			aic_delay(200);
439123579Sgibbs			goto rescan_fifos;
440116940Sgibbs		}
441116940Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
442116940Sgibbs		ahd_set_scbptr(ahd, scbid);
443116940Sgibbs		if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0
444116940Sgibbs		 && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0
445116940Sgibbs		  || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)
446116940Sgibbs		      & SG_LIST_NULL) != 0)) {
447116940Sgibbs			u_int comp_head;
448116940Sgibbs
449116940Sgibbs			/*
450116940Sgibbs			 * The transfer completed with a residual.
451116940Sgibbs			 * Place this SCB on the complete DMA list
452123579Sgibbs			 * so that we update our in-core copy of the
453116940Sgibbs			 * SCB before completing the command.
454116940Sgibbs			 */
455116940Sgibbs			ahd_outb(ahd, SCB_SCSI_STATUS, 0);
456116940Sgibbs			ahd_outb(ahd, SCB_SGPTR,
457116940Sgibbs				 ahd_inb_scbram(ahd, SCB_SGPTR)
458116940Sgibbs				 | SG_STATUS_VALID);
459125448Sgibbs			ahd_outw(ahd, SCB_TAG, scbid);
460125448Sgibbs			ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
461116940Sgibbs			comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
462125448Sgibbs			if (SCBID_IS_NULL(comp_head)) {
463125448Sgibbs				ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
464125448Sgibbs				ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
465125448Sgibbs			} else {
466125448Sgibbs				u_int tail;
467125448Sgibbs
468125448Sgibbs				tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
469125448Sgibbs				ahd_set_scbptr(ahd, tail);
470125448Sgibbs				ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
471125448Sgibbs				ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
472125448Sgibbs				ahd_set_scbptr(ahd, scbid);
473125448Sgibbs			}
474116940Sgibbs		} else
475116940Sgibbs			ahd_complete_scb(ahd, scb);
476116940Sgibbs	}
477116940Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
478116940Sgibbs
479109588Sgibbs	/*
480116940Sgibbs	 * Setup for command channel portion of flush.
481116940Sgibbs	 */
482116940Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
483116940Sgibbs
484116940Sgibbs	/*
485109588Sgibbs	 * Wait for any inprogress DMA to complete and clear DMA state
486109588Sgibbs	 * if this if for an SCB in the qinfifo.
487109588Sgibbs	 */
488116767Sgibbs	while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) {
489109588Sgibbs
490109588Sgibbs		if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) {
491109588Sgibbs			if ((ccscbctl & ARRDONE) != 0)
492109588Sgibbs				break;
493109588Sgibbs		} else if ((ccscbctl & CCSCBDONE) != 0)
494109588Sgibbs			break;
495123579Sgibbs		aic_delay(200);
496109588Sgibbs	}
497123579Sgibbs	/*
498123579Sgibbs	 * We leave the sequencer to cleanup in the case of DMA's to
499123579Sgibbs	 * update the qoutfifo.  In all other cases (DMA's to the
500123579Sgibbs	 * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
501123579Sgibbs	 * we disable the DMA engine so that the sequencer will not
502123579Sgibbs	 * attempt to handle the DMA completion.
503123579Sgibbs	 */
504123579Sgibbs	if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
505109588Sgibbs		ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
506109588Sgibbs
507123579Sgibbs	/*
508123579Sgibbs	 * Complete any SCBs that just finished
509123579Sgibbs	 * being DMA'ed into the qoutfifo.
510123579Sgibbs	 */
511123579Sgibbs	ahd_run_qoutfifo(ahd);
512123579Sgibbs
513116940Sgibbs	saved_scbptr = ahd_get_scbptr(ahd);
514109588Sgibbs	/*
515109588Sgibbs	 * Manually update/complete any completed SCBs that are waiting to be
516109588Sgibbs	 * DMA'ed back up to the host.
517109588Sgibbs	 */
518109588Sgibbs	scbid = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
519109588Sgibbs	while (!SCBID_IS_NULL(scbid)) {
520109588Sgibbs		uint8_t *hscb_ptr;
521109588Sgibbs		u_int	 i;
522109588Sgibbs
523109588Sgibbs		ahd_set_scbptr(ahd, scbid);
524111954Sgibbs		next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
525109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
526109588Sgibbs		if (scb == NULL) {
527109588Sgibbs			printf("%s: Warning - DMA-up and complete "
528109588Sgibbs			       "SCB %d invalid\n", ahd_name(ahd), scbid);
529199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
530109588Sgibbs			continue;
531109588Sgibbs		}
532109588Sgibbs		hscb_ptr = (uint8_t *)scb->hscb;
533109588Sgibbs		for (i = 0; i < sizeof(struct hardware_scb); i++)
534111954Sgibbs			*hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE + i);
535109588Sgibbs
536109588Sgibbs		ahd_complete_scb(ahd, scb);
537109588Sgibbs		scbid = next_scbid;
538109588Sgibbs	}
539109588Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
540125448Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
541109588Sgibbs
542125448Sgibbs	scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
543125448Sgibbs	while (!SCBID_IS_NULL(scbid)) {
544125448Sgibbs
545125448Sgibbs		ahd_set_scbptr(ahd, scbid);
546125448Sgibbs		next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
547125448Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
548125448Sgibbs		if (scb == NULL) {
549125448Sgibbs			printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
550125448Sgibbs			       ahd_name(ahd), scbid);
551199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
552125448Sgibbs			continue;
553125448Sgibbs		}
554125448Sgibbs
555125448Sgibbs		ahd_complete_scb(ahd, scb);
556125448Sgibbs		scbid = next_scbid;
557125448Sgibbs	}
558125448Sgibbs	ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
559125448Sgibbs
560109588Sgibbs	scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
561109588Sgibbs	while (!SCBID_IS_NULL(scbid)) {
562109588Sgibbs
563109588Sgibbs		ahd_set_scbptr(ahd, scbid);
564111954Sgibbs		next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
565109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
566109588Sgibbs		if (scb == NULL) {
567109588Sgibbs			printf("%s: Warning - Complete SCB %d invalid\n",
568109588Sgibbs			       ahd_name(ahd), scbid);
569199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
570109588Sgibbs			continue;
571109588Sgibbs		}
572109588Sgibbs
573109588Sgibbs		ahd_complete_scb(ahd, scb);
574109588Sgibbs		scbid = next_scbid;
575109588Sgibbs	}
576109588Sgibbs	ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
577116940Sgibbs
578116940Sgibbs	/*
579116940Sgibbs	 * Restore state.
580116940Sgibbs	 */
581109588Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
582116940Sgibbs	ahd_restore_modes(ahd, saved_modes);
583116940Sgibbs	ahd->flags |= AHD_UPDATE_PEND_CMDS;
584116940Sgibbs}
585109588Sgibbs
586116940Sgibbs/*
587116940Sgibbs * Determine if an SCB for a packetized transaction
588116940Sgibbs * is active in a FIFO.
589116940Sgibbs */
590116940Sgibbsstatic int
591116940Sgibbsahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)
592116940Sgibbs{
593116940Sgibbs
594109588Sgibbs	/*
595116940Sgibbs	 * The FIFO is only active for our transaction if
596116940Sgibbs	 * the SCBPTR matches the SCB's ID and the firmware
597116940Sgibbs	 * has installed a handler for the FIFO or we have
598116940Sgibbs	 * a pending SAVEPTRS or CFG4DATA interrupt.
599109588Sgibbs	 */
600116940Sgibbs	if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)
601116940Sgibbs	 || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0
602116940Sgibbs	  && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))
603116940Sgibbs		return (0);
604116940Sgibbs
605116940Sgibbs	return (1);
606116940Sgibbs}
607116940Sgibbs
608116940Sgibbs/*
609116940Sgibbs * Run a data fifo to completion for a transaction we know
610116940Sgibbs * has completed across the SCSI bus (good status has been
611116940Sgibbs * received).  We are already set to the correct FIFO mode
612116940Sgibbs * on entry to this routine.
613116940Sgibbs *
614116940Sgibbs * This function attempts to operate exactly as the firmware
615116940Sgibbs * would when running this FIFO.  Care must be taken to update
616116940Sgibbs * this routine any time the firmware's FIFO algorithm is
617116940Sgibbs * changed.
618116940Sgibbs */
619116940Sgibbsstatic void
620116940Sgibbsahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
621116940Sgibbs{
622116940Sgibbs	u_int seqintsrc;
623116940Sgibbs
624123579Sgibbs	seqintsrc = ahd_inb(ahd, SEQINTSRC);
625123579Sgibbs	if ((seqintsrc & CFG4DATA) != 0) {
626123579Sgibbs		uint32_t datacnt;
627123579Sgibbs		uint32_t sgptr;
628116940Sgibbs
629123579Sgibbs		/*
630123579Sgibbs		 * Clear full residual flag.
631123579Sgibbs		 */
632123579Sgibbs		sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
633123579Sgibbs		ahd_outb(ahd, SCB_SGPTR, sgptr);
634116940Sgibbs
635123579Sgibbs		/*
636123579Sgibbs		 * Load datacnt and address.
637123579Sgibbs		 */
638123579Sgibbs		datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
639123579Sgibbs		if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
640123579Sgibbs			sgptr |= LAST_SEG;
641123579Sgibbs			ahd_outb(ahd, SG_STATE, 0);
642123579Sgibbs		} else
643123579Sgibbs			ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
644123579Sgibbs		ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
645123579Sgibbs		ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
646123579Sgibbs		ahd_outb(ahd, SG_CACHE_PRE, sgptr);
647123579Sgibbs		ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
648116940Sgibbs
649123579Sgibbs		/*
650123579Sgibbs		 * Initialize Residual Fields.
651123579Sgibbs		 */
652123579Sgibbs		ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
653123579Sgibbs		ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
654116940Sgibbs
655123579Sgibbs		/*
656123579Sgibbs		 * Mark the SCB as having a FIFO in use.
657123579Sgibbs		 */
658123579Sgibbs		ahd_outb(ahd, SCB_FIFO_USE_COUNT,
659123579Sgibbs			 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
660116940Sgibbs
661123579Sgibbs		/*
662123579Sgibbs		 * Install a "fake" handler for this FIFO.
663123579Sgibbs		 */
664123579Sgibbs		ahd_outw(ahd, LONGJMP_ADDR, 0);
665116940Sgibbs
666123579Sgibbs		/*
667123579Sgibbs		 * Notify the hardware that we have satisfied
668123579Sgibbs		 * this sequencer interrupt.
669123579Sgibbs		 */
670123579Sgibbs		ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
671123579Sgibbs	} else if ((seqintsrc & SAVEPTRS) != 0) {
672123579Sgibbs		uint32_t sgptr;
673123579Sgibbs		uint32_t resid;
674123579Sgibbs
675123579Sgibbs		if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
676116940Sgibbs			/*
677123579Sgibbs			 * Snapshot Save Pointers.  All that
678123579Sgibbs			 * is necessary to clear the snapshot
679123579Sgibbs			 * is a CLRCHN.
680116940Sgibbs			 */
681123579Sgibbs			goto clrchn;
682123579Sgibbs		}
683116940Sgibbs
684123579Sgibbs		/*
685123579Sgibbs		 * Disable S/G fetch so the DMA engine
686123579Sgibbs		 * is available to future users.
687123579Sgibbs		 */
688123579Sgibbs		if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
689123579Sgibbs			ahd_outb(ahd, CCSGCTL, 0);
690123579Sgibbs		ahd_outb(ahd, SG_STATE, 0);
691116940Sgibbs
692123579Sgibbs		/*
693123579Sgibbs		 * Flush the data FIFO.  Strickly only
694123579Sgibbs		 * necessary for Rev A parts.
695123579Sgibbs		 */
696123579Sgibbs		ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
697116940Sgibbs
698123579Sgibbs		/*
699123579Sgibbs		 * Calculate residual.
700123579Sgibbs		 */
701123579Sgibbs		sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
702123579Sgibbs		resid = ahd_inl(ahd, SHCNT);
703123579Sgibbs		resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
704123579Sgibbs		ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
705123579Sgibbs		if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
706116940Sgibbs			/*
707123579Sgibbs			 * Must back up to the correct S/G element.
708123579Sgibbs			 * Typically this just means resetting our
709123579Sgibbs			 * low byte to the offset in the SG_CACHE,
710123579Sgibbs			 * but if we wrapped, we have to correct
711123579Sgibbs			 * the other bytes of the sgptr too.
712116940Sgibbs			 */
713123579Sgibbs			if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
714123579Sgibbs			 && (sgptr & 0x80) == 0)
715123579Sgibbs				sgptr -= 0x100;
716123579Sgibbs			sgptr &= ~0xFF;
717123579Sgibbs			sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
718123579Sgibbs			       & SG_ADDR_MASK;
719123579Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
720123579Sgibbs			ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
721123579Sgibbs		} else if ((resid & AHD_SG_LEN_MASK) == 0) {
722123579Sgibbs			ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
723123579Sgibbs				 sgptr | SG_LIST_NULL);
724123579Sgibbs		}
725123579Sgibbs		/*
726123579Sgibbs		 * Save Pointers.
727123579Sgibbs		 */
728123579Sgibbs		ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
729123579Sgibbs		ahd_outl(ahd, SCB_DATACNT, resid);
730123579Sgibbs		ahd_outl(ahd, SCB_SGPTR, sgptr);
731123579Sgibbs		ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
732123579Sgibbs		ahd_outb(ahd, SEQIMODE,
733123579Sgibbs			 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
734123579Sgibbs		/*
735123579Sgibbs		 * If the data is to the SCSI bus, we are
736123579Sgibbs		 * done, otherwise wait for FIFOEMP.
737123579Sgibbs		 */
738123579Sgibbs		if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
739123579Sgibbs			goto clrchn;
740123579Sgibbs	} else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
741123579Sgibbs		uint32_t sgptr;
742123579Sgibbs		uint64_t data_addr;
743123579Sgibbs		uint32_t data_len;
744123579Sgibbs		u_int	 dfcntrl;
745116940Sgibbs
746123579Sgibbs		/*
747123579Sgibbs		 * Disable S/G fetch so the DMA engine
748123579Sgibbs		 * is available to future users.  We won't
749123579Sgibbs		 * be using the DMA engine to load segments.
750123579Sgibbs		 */
751123579Sgibbs		if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
752123579Sgibbs			ahd_outb(ahd, CCSGCTL, 0);
753123579Sgibbs			ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
754123579Sgibbs		}
755116940Sgibbs
756123579Sgibbs		/*
757123579Sgibbs		 * Wait for the DMA engine to notice that the
758123579Sgibbs		 * host transfer is enabled and that there is
759123579Sgibbs		 * space in the S/G FIFO for new segments before
760123579Sgibbs		 * loading more segments.
761123579Sgibbs		 */
762123579Sgibbs		if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
763123579Sgibbs		 && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
764116940Sgibbs
765116940Sgibbs			/*
766116940Sgibbs			 * Determine the offset of the next S/G
767116940Sgibbs			 * element to load.
768116940Sgibbs			 */
769116940Sgibbs			sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
770116940Sgibbs			sgptr &= SG_PTR_MASK;
771116940Sgibbs			if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
772116940Sgibbs				struct ahd_dma64_seg *sg;
773116940Sgibbs
774116940Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
775116940Sgibbs				data_addr = sg->addr;
776116940Sgibbs				data_len = sg->len;
777116940Sgibbs				sgptr += sizeof(*sg);
778116940Sgibbs			} else {
779116940Sgibbs				struct	ahd_dma_seg *sg;
780116940Sgibbs
781116940Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
782116940Sgibbs				data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;
783116940Sgibbs				data_addr <<= 8;
784116940Sgibbs				data_addr |= sg->addr;
785116940Sgibbs				data_len = sg->len;
786116940Sgibbs				sgptr += sizeof(*sg);
787116940Sgibbs			}
788116940Sgibbs
789116940Sgibbs			/*
790116940Sgibbs			 * Update residual information.
791116940Sgibbs			 */
792116940Sgibbs			ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);
793116940Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
794116940Sgibbs
795116940Sgibbs			/*
796116940Sgibbs			 * Load the S/G.
797116940Sgibbs			 */
798116940Sgibbs			if (data_len & AHD_DMA_LAST_SEG) {
799116940Sgibbs				sgptr |= LAST_SEG;
800116940Sgibbs				ahd_outb(ahd, SG_STATE, 0);
801116940Sgibbs			}
802116940Sgibbs			ahd_outq(ahd, HADDR, data_addr);
803116940Sgibbs			ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);
804116940Sgibbs			ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);
805116940Sgibbs
806116940Sgibbs			/*
807116940Sgibbs			 * Advertise the segment to the hardware.
808116940Sgibbs			 */
809116940Sgibbs			dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
810123579Sgibbs			if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
811116940Sgibbs				/*
812116940Sgibbs				 * Use SCSIENWRDIS so that SCSIEN
813116940Sgibbs				 * is never modified by this
814116940Sgibbs				 * operation.
815116940Sgibbs				 */
816116940Sgibbs				dfcntrl |= SCSIENWRDIS;
817116940Sgibbs			}
818116940Sgibbs			ahd_outb(ahd, DFCNTRL, dfcntrl);
819123579Sgibbs		}
820123579Sgibbs	} else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
821116940Sgibbs
822123579Sgibbs		/*
823123579Sgibbs		 * Transfer completed to the end of SG list
824123579Sgibbs		 * and has flushed to the host.
825123579Sgibbs		 */
826123579Sgibbs		ahd_outb(ahd, SCB_SGPTR,
827123579Sgibbs			 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
828123579Sgibbs		goto clrchn;
829123579Sgibbs	} else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
830123579Sgibbsclrchn:
831123579Sgibbs		/*
832123579Sgibbs		 * Clear any handler for this FIFO, decrement
833123579Sgibbs		 * the FIFO use count for the SCB, and release
834123579Sgibbs		 * the FIFO.
835123579Sgibbs		 */
836123579Sgibbs		ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
837123579Sgibbs		ahd_outb(ahd, SCB_FIFO_USE_COUNT,
838123579Sgibbs			 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
839123579Sgibbs		ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
840109588Sgibbs	}
841109588Sgibbs}
842109588Sgibbs
843125448Sgibbs/*
844125448Sgibbs * Look for entries in the QoutFIFO that have completed.
845125448Sgibbs * The valid_tag completion field indicates the validity
846125448Sgibbs * of the entry - the valid value toggles each time through
847125448Sgibbs * the queue. We use the sg_status field in the completion
848125448Sgibbs * entry to avoid referencing the hscb if the completion
849125448Sgibbs * occurred with no errors and no residual.  sg_status is
850125448Sgibbs * a copy of the first byte (little endian) of the sgptr
851125448Sgibbs * hscb field.
852125448Sgibbs */
853109588Sgibbsvoid
85497883Sgibbsahd_run_qoutfifo(struct ahd_softc *ahd)
85597883Sgibbs{
856125448Sgibbs	struct ahd_completion *completion;
85797883Sgibbs	struct scb *scb;
85897883Sgibbs	u_int  scb_index;
85997883Sgibbs
860109588Sgibbs	if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0)
861109588Sgibbs		panic("ahd_run_qoutfifo recursion");
862109588Sgibbs	ahd->flags |= AHD_RUNNING_QOUTFIFO;
86397883Sgibbs	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
864125448Sgibbs	for (;;) {
865125448Sgibbs		completion = &ahd->qoutfifo[ahd->qoutfifonext];
86697883Sgibbs
867125448Sgibbs		if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
868125448Sgibbs			break;
869125448Sgibbs
870125448Sgibbs		scb_index = aic_le16toh(completion->tag);
87197883Sgibbs		scb = ahd_lookup_scb(ahd, scb_index);
87297883Sgibbs		if (scb == NULL) {
87397883Sgibbs			printf("%s: WARNING no command for scb %d "
87497883Sgibbs			       "(cmdcmplt)\nQOUTPOS = %d\n",
87597883Sgibbs			       ahd_name(ahd), scb_index,
87697883Sgibbs			       ahd->qoutfifonext);
877199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
87897883Sgibbs			ahd_dump_card_state(ahd);
879125448Sgibbs		} else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
880125448Sgibbs			ahd_handle_scb_status(ahd, scb);
881125448Sgibbs		} else {
882125448Sgibbs			ahd_done(ahd, scb);
883125448Sgibbs		}
88497883Sgibbs
885102679Sgibbs		ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
886102679Sgibbs		if (ahd->qoutfifonext == 0)
887125448Sgibbs			ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
88897883Sgibbs	}
889109588Sgibbs	ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
89097883Sgibbs}
89197883Sgibbs
89297883Sgibbs/************************* Interrupt Handling *********************************/
89397883Sgibbsvoid
89497883Sgibbsahd_handle_hwerrint(struct ahd_softc *ahd)
89597883Sgibbs{
89697883Sgibbs	/*
89797883Sgibbs	 * Some catastrophic hardware error has occurred.
89897883Sgibbs	 * Print it for the user and disable the controller.
89997883Sgibbs	 */
90097883Sgibbs	int i;
90197883Sgibbs	int error;
90297883Sgibbs
90397883Sgibbs	error = ahd_inb(ahd, ERROR);
90497883Sgibbs	for (i = 0; i < num_errors; i++) {
905199260Sattilio		if ((error & ahd_hard_errors[i].errno) != 0) {
90697883Sgibbs			printf("%s: hwerrint, %s\n",
90797883Sgibbs			       ahd_name(ahd), ahd_hard_errors[i].errmesg);
908199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
909199260Sattilio		}
91097883Sgibbs	}
91197883Sgibbs
91297883Sgibbs	ahd_dump_card_state(ahd);
91397883Sgibbs	panic("BRKADRINT");
91497883Sgibbs
915114623Sgibbs	/* Tell everyone that this HBA is no longer available */
91697883Sgibbs	ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
91797883Sgibbs		       CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,
91897883Sgibbs		       CAM_NO_HBA);
91997883Sgibbs
92097883Sgibbs	/* Tell the system that this controller has gone away. */
92197883Sgibbs	ahd_free(ahd);
92297883Sgibbs}
92397883Sgibbs
92497883Sgibbsvoid
92597883Sgibbsahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
92697883Sgibbs{
92797883Sgibbs	u_int seqintcode;
92897883Sgibbs
92997883Sgibbs	/*
93097883Sgibbs	 * Save the sequencer interrupt code and clear the SEQINT
93197883Sgibbs	 * bit. We will unpause the sequencer, if appropriate,
93297883Sgibbs	 * after servicing the request.
93397883Sgibbs	 */
93497883Sgibbs	seqintcode = ahd_inb(ahd, SEQINTCODE);
93597883Sgibbs	ahd_outb(ahd, CLRINT, CLRSEQINT);
936107441Sscottl	if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
937107441Sscottl		/*
938107441Sscottl		 * Unpause the sequencer and let it clear
939107441Sscottl		 * SEQINT by writing NO_SEQINT to it.  This
940107441Sscottl		 * will cause the sequencer to be paused again,
941107441Sscottl		 * which is the expected state of this routine.
942107441Sscottl		 */
943107441Sscottl		ahd_unpause(ahd);
944107441Sscottl		while (!ahd_is_paused(ahd))
945107441Sscottl			;
946107441Sscottl		ahd_outb(ahd, CLRINT, CLRSEQINT);
947107441Sscottl	}
94897883Sgibbs	ahd_update_modes(ahd);
94997883Sgibbs#ifdef AHD_DEBUG
95097883Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0)
95197883Sgibbs		printf("%s: Handle Seqint Called for code %d\n",
95297883Sgibbs		       ahd_name(ahd), seqintcode);
95397883Sgibbs#endif
95497883Sgibbs	switch (seqintcode) {
95597883Sgibbs	case ENTERING_NONPACK:
95697883Sgibbs	{
95797883Sgibbs		struct	scb *scb;
95897883Sgibbs		u_int	scbid;
95997883Sgibbs
96097883Sgibbs		AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
96197883Sgibbs				 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
96297883Sgibbs		scbid = ahd_get_scbptr(ahd);
96397883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
96497883Sgibbs		if (scb == NULL) {
96597883Sgibbs			/*
96697883Sgibbs			 * Somehow need to know if this
96797883Sgibbs			 * is from a selection or reselection.
968116935Sgibbs			 * From that, we can determine target
96997883Sgibbs			 * ID so we at least have an I_T nexus.
97097883Sgibbs			 */
97197883Sgibbs		} else {
97297883Sgibbs			ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
97397883Sgibbs			ahd_outb(ahd, SAVED_LUN, scb->hscb->lun);
97497883Sgibbs			ahd_outb(ahd, SEQ_FLAGS, 0x0);
97597883Sgibbs		}
97697883Sgibbs		if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0
97797883Sgibbs		 && (ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
97897883Sgibbs			/*
97997883Sgibbs			 * Phase change after read stream with
98097883Sgibbs			 * CRC error with P0 asserted on last
98197883Sgibbs			 * packet.
98297883Sgibbs			 */
983107441Sscottl#ifdef AHD_DEBUG
984107441Sscottl			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
985107441Sscottl				printf("%s: Assuming LQIPHASE_NLQ with "
986107441Sscottl				       "P0 assertion\n", ahd_name(ahd));
987107441Sscottl#endif
98897883Sgibbs		}
989107441Sscottl#ifdef AHD_DEBUG
990107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
991107441Sscottl			printf("%s: Entering NONPACK\n", ahd_name(ahd));
992107441Sscottl#endif
99397883Sgibbs		break;
99497883Sgibbs	}
99597883Sgibbs	case INVALID_SEQINT:
99697883Sgibbs		printf("%s: Invalid Sequencer interrupt occurred.\n",
99797883Sgibbs		       ahd_name(ahd));
99897883Sgibbs		ahd_dump_card_state(ahd);
99997883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
1000199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
100197883Sgibbs		break;
100297883Sgibbs	case STATUS_OVERRUN:
100397883Sgibbs	{
1004114623Sgibbs		struct	scb *scb;
1005114623Sgibbs		u_int	scbid;
1006114623Sgibbs
1007114623Sgibbs		scbid = ahd_get_scbptr(ahd);
1008114623Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1009114623Sgibbs		if (scb != NULL)
1010114623Sgibbs			ahd_print_path(ahd, scb);
1011114623Sgibbs		else
1012114623Sgibbs			printf("%s: ", ahd_name(ahd));
1013114623Sgibbs		printf("SCB %d Packetized Status Overrun", scbid);
101497883Sgibbs		ahd_dump_card_state(ahd);
101597883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
1016199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
101797883Sgibbs		break;
101897883Sgibbs	}
101997883Sgibbs	case CFG4ISTAT_INTR:
102097883Sgibbs	{
102197883Sgibbs		struct	scb *scb;
102297883Sgibbs		u_int	scbid;
102397883Sgibbs
102497883Sgibbs		scbid = ahd_get_scbptr(ahd);
102597883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
102697883Sgibbs		if (scb == NULL) {
102797883Sgibbs			ahd_dump_card_state(ahd);
102897883Sgibbs			printf("CFG4ISTAT: Free SCB %d referenced", scbid);
1029199260Sattilio			AHD_FATAL_ERROR(ahd);
103097883Sgibbs			panic("For safety");
103197883Sgibbs		}
103297883Sgibbs		ahd_outq(ahd, HADDR, scb->sense_busaddr);
103397883Sgibbs		ahd_outw(ahd, HCNT, AHD_SENSE_BUFSIZE);
103497883Sgibbs		ahd_outb(ahd, HCNT + 2, 0);
103597883Sgibbs		ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG);
103697883Sgibbs		ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
103797883Sgibbs		break;
103897883Sgibbs	}
103997883Sgibbs	case ILLEGAL_PHASE:
104097883Sgibbs	{
104197883Sgibbs		u_int bus_phase;
104297883Sgibbs
104397883Sgibbs		bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
104497883Sgibbs		printf("%s: ILLEGAL_PHASE 0x%x\n",
104597883Sgibbs		       ahd_name(ahd), bus_phase);
104697883Sgibbs
104797883Sgibbs		switch (bus_phase) {
104897883Sgibbs		case P_DATAOUT:
104997883Sgibbs		case P_DATAIN:
105097883Sgibbs		case P_DATAOUT_DT:
105197883Sgibbs		case P_DATAIN_DT:
105297883Sgibbs		case P_MESGOUT:
105397883Sgibbs		case P_STATUS:
105497883Sgibbs		case P_MESGIN:
105597883Sgibbs			ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
105697883Sgibbs			printf("%s: Issued Bus Reset.\n", ahd_name(ahd));
1057199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
105897883Sgibbs			break;
105997883Sgibbs		case P_COMMAND:
106097883Sgibbs		{
106197883Sgibbs			struct	ahd_devinfo devinfo;
106297883Sgibbs			struct	scb *scb;
106397883Sgibbs			struct	ahd_initiator_tinfo *targ_info;
106497883Sgibbs			struct	ahd_tmode_tstate *tstate;
106597883Sgibbs			struct	ahd_transinfo *tinfo;
106697883Sgibbs			u_int	scbid;
106797883Sgibbs
106897883Sgibbs			/*
106997883Sgibbs			 * If a target takes us into the command phase
107097883Sgibbs			 * assume that it has been externally reset and
107197883Sgibbs			 * has thus lost our previous packetized negotiation
107297883Sgibbs			 * agreement.  Since we have not sent an identify
107397883Sgibbs			 * message and may not have fully qualified the
107497883Sgibbs			 * connection, we change our command to TUR, assert
107597883Sgibbs			 * ATN and ABORT the task when we go to message in
107697883Sgibbs			 * phase.  The OSM will see the REQUEUE_REQUEST
107797883Sgibbs			 * status and retry the command.
107897883Sgibbs			 */
107997883Sgibbs			scbid = ahd_get_scbptr(ahd);
108097883Sgibbs			scb = ahd_lookup_scb(ahd, scbid);
108197883Sgibbs			if (scb == NULL) {
1082199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
108397883Sgibbs				printf("Invalid phase with no valid SCB.  "
108497883Sgibbs				       "Resetting bus.\n");
108597883Sgibbs				ahd_reset_channel(ahd, 'A',
108697883Sgibbs						  /*Initiate Reset*/TRUE);
108797883Sgibbs				break;
108897883Sgibbs			}
108997883Sgibbs			ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
109097883Sgibbs					    SCB_GET_TARGET(ahd, scb),
109197883Sgibbs					    SCB_GET_LUN(scb),
109297883Sgibbs					    SCB_GET_CHANNEL(ahd, scb),
109397883Sgibbs					    ROLE_INITIATOR);
109497883Sgibbs			targ_info = ahd_fetch_transinfo(ahd,
109597883Sgibbs							devinfo.channel,
109697883Sgibbs							devinfo.our_scsiid,
109797883Sgibbs							devinfo.target,
109897883Sgibbs							&tstate);
109997883Sgibbs			tinfo = &targ_info->curr;
110097883Sgibbs			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
1101109588Sgibbs				      AHD_TRANS_ACTIVE, /*paused*/TRUE);
110297883Sgibbs			ahd_set_syncrate(ahd, &devinfo, /*period*/0,
110397883Sgibbs					 /*offset*/0, /*ppr_options*/0,
110497883Sgibbs					 AHD_TRANS_ACTIVE, /*paused*/TRUE);
110597883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE, 0);
110697883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+1, 0);
110797883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+2, 0);
110897883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+3, 0);
110997883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+4, 0);
111097883Sgibbs			ahd_outb(ahd, SCB_CDB_STORE+5, 0);
111197883Sgibbs			ahd_outb(ahd, SCB_CDB_LEN, 6);
111297883Sgibbs			scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);
111397883Sgibbs			scb->hscb->control |= MK_MESSAGE;
111497883Sgibbs			ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);
111597883Sgibbs			ahd_outb(ahd, MSG_OUT, HOST_MSG);
111697883Sgibbs			ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
111797883Sgibbs			/*
111897883Sgibbs			 * The lun is 0, regardless of the SCB's lun
111997883Sgibbs			 * as we have not sent an identify message.
112097883Sgibbs			 */
112197883Sgibbs			ahd_outb(ahd, SAVED_LUN, 0);
112297883Sgibbs			ahd_outb(ahd, SEQ_FLAGS, 0);
112397883Sgibbs			ahd_assert_atn(ahd);
1124123579Sgibbs			scb->flags &= ~SCB_PACKETIZED;
112597883Sgibbs			scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
112697883Sgibbs			ahd_freeze_devq(ahd, scb);
1127123579Sgibbs			aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
1128123579Sgibbs			aic_freeze_scb(scb);
112997883Sgibbs
113097883Sgibbs			/*
113197883Sgibbs			 * Allow the sequencer to continue with
113297883Sgibbs			 * non-pack processing.
113397883Sgibbs			 */
113497883Sgibbs			ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
113597883Sgibbs			ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT);
113697883Sgibbs			if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
113797883Sgibbs				ahd_outb(ahd, CLRLQOINT1, 0);
113897883Sgibbs			}
1139107441Sscottl#ifdef AHD_DEBUG
1140107441Sscottl			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1141107441Sscottl				ahd_print_path(ahd, scb);
1142199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
1143107441Sscottl				printf("Unexpected command phase from "
1144107441Sscottl				       "packetized target\n");
1145107441Sscottl			}
1146107441Sscottl#endif
114797883Sgibbs			break;
114897883Sgibbs		}
114997883Sgibbs		}
115097883Sgibbs		break;
115197883Sgibbs	}
115297883Sgibbs	case CFG4OVERRUN:
1153107441Sscottl	{
1154107441Sscottl		struct	scb *scb;
1155107441Sscottl		u_int	scb_index;
1156107441Sscottl
1157107441Sscottl#ifdef AHD_DEBUG
1158107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1159107441Sscottl			printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd),
1160107441Sscottl			       ahd_inb(ahd, MODE_PTR));
1161107441Sscottl		}
1162107441Sscottl#endif
1163107441Sscottl		scb_index = ahd_get_scbptr(ahd);
1164107441Sscottl		scb = ahd_lookup_scb(ahd, scb_index);
1165107441Sscottl		if (scb == NULL) {
1166107441Sscottl			/*
1167107441Sscottl			 * Attempt to transfer to an SCB that is
1168107441Sscottl			 * not outstanding.
1169107441Sscottl			 */
1170107441Sscottl			ahd_assert_atn(ahd);
1171107441Sscottl			ahd_outb(ahd, MSG_OUT, HOST_MSG);
1172107441Sscottl			ahd->msgout_buf[0] = MSG_ABORT_TASK;
1173107441Sscottl			ahd->msgout_len = 1;
1174107441Sscottl			ahd->msgout_index = 0;
1175107441Sscottl			ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
1176107441Sscottl			/*
1177107441Sscottl			 * Clear status received flag to prevent any
1178107441Sscottl			 * attempt to complete this bogus SCB.
1179107441Sscottl			 */
1180107441Sscottl			ahd_outb(ahd, SCB_CONTROL,
1181116940Sgibbs				 ahd_inb_scbram(ahd, SCB_CONTROL)
1182116940Sgibbs				 & ~STATUS_RCVD);
1183107441Sscottl		}
118497883Sgibbs		break;
1185107441Sscottl	}
118697883Sgibbs	case DUMP_CARD_STATE:
118797883Sgibbs	{
118897883Sgibbs		ahd_dump_card_state(ahd);
118997883Sgibbs		break;
119097883Sgibbs	}
119197883Sgibbs	case PDATA_REINIT:
119297883Sgibbs	{
1193107441Sscottl#ifdef AHD_DEBUG
1194107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1195107441Sscottl			printf("%s: PDATA_REINIT - DFCNTRL = 0x%x "
1196107441Sscottl			       "SG_CACHE_SHADOW = 0x%x\n",
1197107441Sscottl			       ahd_name(ahd), ahd_inb(ahd, DFCNTRL),
1198107441Sscottl			       ahd_inb(ahd, SG_CACHE_SHADOW));
1199107441Sscottl		}
1200107441Sscottl#endif
120197883Sgibbs		ahd_reinitialize_dataptrs(ahd);
120297883Sgibbs		break;
120397883Sgibbs	}
120497883Sgibbs	case HOST_MSG_LOOP:
120597883Sgibbs	{
120697883Sgibbs		struct ahd_devinfo devinfo;
120797883Sgibbs
120897883Sgibbs		/*
120997883Sgibbs		 * The sequencer has encountered a message phase
121097883Sgibbs		 * that requires host assistance for completion.
121197883Sgibbs		 * While handling the message phase(s), we will be
121297883Sgibbs		 * notified by the sequencer after each byte is
121397883Sgibbs		 * transfered so we can track bus phase changes.
121497883Sgibbs		 *
121597883Sgibbs		 * If this is the first time we've seen a HOST_MSG_LOOP
121697883Sgibbs		 * interrupt, initialize the state of the host message
121797883Sgibbs		 * loop.
121897883Sgibbs		 */
121997883Sgibbs		ahd_fetch_devinfo(ahd, &devinfo);
122097883Sgibbs		if (ahd->msg_type == MSG_TYPE_NONE) {
122197883Sgibbs			struct scb *scb;
122297883Sgibbs			u_int scb_index;
122397883Sgibbs			u_int bus_phase;
122497883Sgibbs
122597883Sgibbs			bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
122697883Sgibbs			if (bus_phase != P_MESGIN
122797883Sgibbs			 && bus_phase != P_MESGOUT) {
122897883Sgibbs				printf("ahd_intr: HOST_MSG_LOOP bad "
1229107441Sscottl				       "phase 0x%x\n", bus_phase);
1230199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
123197883Sgibbs				/*
123297883Sgibbs				 * Probably transitioned to bus free before
123397883Sgibbs				 * we got here.  Just punt the message.
123497883Sgibbs				 */
123597883Sgibbs				ahd_dump_card_state(ahd);
123697883Sgibbs				ahd_clear_intstat(ahd);
123797883Sgibbs				ahd_restart(ahd);
123897883Sgibbs				return;
123997883Sgibbs			}
124097883Sgibbs
124197883Sgibbs			scb_index = ahd_get_scbptr(ahd);
124297883Sgibbs			scb = ahd_lookup_scb(ahd, scb_index);
124397883Sgibbs			if (devinfo.role == ROLE_INITIATOR) {
124497883Sgibbs				if (bus_phase == P_MESGOUT)
124597883Sgibbs					ahd_setup_initiator_msgout(ahd,
124697883Sgibbs								   &devinfo,
124797883Sgibbs								   scb);
124897883Sgibbs				else {
124997883Sgibbs					ahd->msg_type =
125097883Sgibbs					    MSG_TYPE_INITIATOR_MSGIN;
125197883Sgibbs					ahd->msgin_index = 0;
125297883Sgibbs				}
125397883Sgibbs			}
1254153072Sru#ifdef AHD_TARGET_MODE
125597883Sgibbs			else {
125697883Sgibbs				if (bus_phase == P_MESGOUT) {
125797883Sgibbs					ahd->msg_type =
125897883Sgibbs					    MSG_TYPE_TARGET_MSGOUT;
125997883Sgibbs					ahd->msgin_index = 0;
126097883Sgibbs				}
126197883Sgibbs				else
126297883Sgibbs					ahd_setup_target_msgin(ahd,
126397883Sgibbs							       &devinfo,
126497883Sgibbs							       scb);
126597883Sgibbs			}
126697883Sgibbs#endif
126797883Sgibbs		}
126897883Sgibbs
126997883Sgibbs		ahd_handle_message_phase(ahd);
127097883Sgibbs		break;
127197883Sgibbs	}
127297883Sgibbs	case NO_MATCH:
127397883Sgibbs	{
127497883Sgibbs		/* Ensure we don't leave the selection hardware on */
127597883Sgibbs		AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
127697883Sgibbs		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
127797883Sgibbs
127897883Sgibbs		printf("%s:%c:%d: no active SCB for reconnecting "
127997883Sgibbs		       "target - issuing BUS DEVICE RESET\n",
1280102679Sgibbs		       ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4);
128197883Sgibbs		printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "
1282102679Sgibbs		       "REG0 == 0x%x ACCUM = 0x%x\n",
128397883Sgibbs		       ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN),
1284102679Sgibbs		       ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM));
128597883Sgibbs		printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "
128697883Sgibbs		       "SINDEX == 0x%x\n",
128797883Sgibbs		       ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd),
128897883Sgibbs		       ahd_find_busy_tcl(ahd,
1289102679Sgibbs					 BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),
1290102679Sgibbs						   ahd_inb(ahd, SAVED_LUN))),
1291102679Sgibbs		       ahd_inw(ahd, SINDEX));
129297883Sgibbs		printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "
129397883Sgibbs		       "SCB_CONTROL == 0x%x\n",
129497883Sgibbs		       ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID),
129597883Sgibbs		       ahd_inb_scbram(ahd, SCB_LUN),
129697883Sgibbs		       ahd_inb_scbram(ahd, SCB_CONTROL));
129797883Sgibbs		printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n",
129897883Sgibbs		       ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI));
129997883Sgibbs		printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0));
130097883Sgibbs		printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0));
130197883Sgibbs		ahd_dump_card_state(ahd);
130297883Sgibbs		ahd->msgout_buf[0] = MSG_BUS_DEV_RESET;
130397883Sgibbs		ahd->msgout_len = 1;
130497883Sgibbs		ahd->msgout_index = 0;
130597883Sgibbs		ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
130697883Sgibbs		ahd_outb(ahd, MSG_OUT, HOST_MSG);
130797883Sgibbs		ahd_assert_atn(ahd);
130897883Sgibbs		break;
130997883Sgibbs	}
131097883Sgibbs	case PROTO_VIOLATION:
131197883Sgibbs	{
1312102679Sgibbs		ahd_handle_proto_violation(ahd);
1313102679Sgibbs		break;
131497883Sgibbs	}
131597883Sgibbs	case IGN_WIDE_RES:
131697883Sgibbs	{
131797883Sgibbs		struct ahd_devinfo devinfo;
131897883Sgibbs
131997883Sgibbs		ahd_fetch_devinfo(ahd, &devinfo);
132097883Sgibbs		ahd_handle_ign_wide_residue(ahd, &devinfo);
132197883Sgibbs		break;
132297883Sgibbs	}
132397883Sgibbs	case BAD_PHASE:
132497883Sgibbs	{
132597883Sgibbs		u_int lastphase;
132697883Sgibbs
132797883Sgibbs		lastphase = ahd_inb(ahd, LASTPHASE);
132897883Sgibbs		printf("%s:%c:%d: unknown scsi bus phase %x, "
132997883Sgibbs		       "lastphase = 0x%x.  Attempting to continue\n",
133097883Sgibbs		       ahd_name(ahd), 'A',
133197883Sgibbs		       SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
133297883Sgibbs		       lastphase, ahd_inb(ahd, SCSISIGI));
1333199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
133497883Sgibbs		break;
133597883Sgibbs	}
133697883Sgibbs	case MISSED_BUSFREE:
133797883Sgibbs	{
133897883Sgibbs		u_int lastphase;
133997883Sgibbs
134097883Sgibbs		lastphase = ahd_inb(ahd, LASTPHASE);
134197883Sgibbs		printf("%s:%c:%d: Missed busfree. "
134297883Sgibbs		       "Lastphase = 0x%x, Curphase = 0x%x\n",
134397883Sgibbs		       ahd_name(ahd), 'A',
134497883Sgibbs		       SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
134597883Sgibbs		       lastphase, ahd_inb(ahd, SCSISIGI));
1346199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
134797883Sgibbs		ahd_restart(ahd);
134897883Sgibbs		return;
134997883Sgibbs	}
135097883Sgibbs	case DATA_OVERRUN:
135197883Sgibbs	{
135297883Sgibbs		/*
135397883Sgibbs		 * When the sequencer detects an overrun, it
135497883Sgibbs		 * places the controller in "BITBUCKET" mode
135597883Sgibbs		 * and allows the target to complete its transfer.
135697883Sgibbs		 * Unfortunately, none of the counters get updated
135797883Sgibbs		 * when the controller is in this mode, so we have
135897883Sgibbs		 * no way of knowing how large the overrun was.
135997883Sgibbs		 */
136097883Sgibbs		struct	scb *scb;
1361107441Sscottl		u_int	scbindex;
1362107441Sscottl#ifdef AHD_DEBUG
1363107441Sscottl		u_int	lastphase;
1364107441Sscottl#endif
136597883Sgibbs
1366107441Sscottl		scbindex = ahd_get_scbptr(ahd);
136797883Sgibbs		scb = ahd_lookup_scb(ahd, scbindex);
1368107441Sscottl#ifdef AHD_DEBUG
1369107441Sscottl		lastphase = ahd_inb(ahd, LASTPHASE);
1370107441Sscottl		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1371107441Sscottl			ahd_print_path(ahd, scb);
1372107441Sscottl			printf("data overrun detected %s.  Tag == 0x%x.\n",
1373107441Sscottl			       ahd_lookup_phase_entry(lastphase)->phasemsg,
1374107441Sscottl			       SCB_GET_TAG(scb));
1375107441Sscottl			ahd_print_path(ahd, scb);
1376107441Sscottl			printf("%s seen Data Phase.  Length = %ld.  "
1377107441Sscottl			       "NumSGs = %d.\n",
1378107441Sscottl			       ahd_inb(ahd, SEQ_FLAGS) & DPHASE
1379107441Sscottl			       ? "Have" : "Haven't",
1380123579Sgibbs			       aic_get_transfer_length(scb), scb->sg_count);
1381107441Sscottl			ahd_dump_sglist(scb);
1382107441Sscottl		}
1383107441Sscottl#endif
138497883Sgibbs
138597883Sgibbs		/*
138697883Sgibbs		 * Set this and it will take effect when the
138797883Sgibbs		 * target does a command complete.
138897883Sgibbs		 */
138997883Sgibbs		ahd_freeze_devq(ahd, scb);
1390123579Sgibbs		aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
1391123579Sgibbs		aic_freeze_scb(scb);
139297883Sgibbs		break;
139397883Sgibbs	}
139497883Sgibbs	case MKMSG_FAILED:
139597883Sgibbs	{
139697883Sgibbs		struct ahd_devinfo devinfo;
139797883Sgibbs		struct scb *scb;
139897883Sgibbs		u_int scbid;
139997883Sgibbs
140097883Sgibbs		ahd_fetch_devinfo(ahd, &devinfo);
140197883Sgibbs		printf("%s:%c:%d:%d: Attempt to issue message failed\n",
140297883Sgibbs		       ahd_name(ahd), devinfo.channel, devinfo.target,
140397883Sgibbs		       devinfo.lun);
140497883Sgibbs		scbid = ahd_get_scbptr(ahd);
140597883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1406199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
140797883Sgibbs		if (scb != NULL
140897883Sgibbs		 && (scb->flags & SCB_RECOVERY_SCB) != 0)
140997883Sgibbs			/*
141097883Sgibbs			 * Ensure that we didn't put a second instance of this
141197883Sgibbs			 * SCB into the QINFIFO.
141297883Sgibbs			 */
141397883Sgibbs			ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
141497883Sgibbs					   SCB_GET_CHANNEL(ahd, scb),
141597883Sgibbs					   SCB_GET_LUN(scb), SCB_GET_TAG(scb),
141697883Sgibbs					   ROLE_INITIATOR, /*status*/0,
141797883Sgibbs					   SEARCH_REMOVE);
141897883Sgibbs		ahd_outb(ahd, SCB_CONTROL,
1419116940Sgibbs			 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
142097883Sgibbs		break;
142197883Sgibbs	}
1422109588Sgibbs	case TASKMGMT_FUNC_COMPLETE:
1423109588Sgibbs	{
1424109588Sgibbs		u_int	scbid;
1425109588Sgibbs		struct	scb *scb;
1426109588Sgibbs
1427109588Sgibbs		scbid = ahd_get_scbptr(ahd);
1428109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1429109588Sgibbs		if (scb != NULL) {
1430109588Sgibbs			u_int	   lun;
1431109588Sgibbs			u_int	   tag;
1432109588Sgibbs			cam_status error;
1433109588Sgibbs
1434109588Sgibbs			ahd_print_path(ahd, scb);
1435109588Sgibbs			printf("Task Management Func 0x%x Complete\n",
1436109588Sgibbs			       scb->hscb->task_management);
1437109588Sgibbs			lun = CAM_LUN_WILDCARD;
1438109588Sgibbs			tag = SCB_LIST_NULL;
1439109588Sgibbs
1440109588Sgibbs			switch (scb->hscb->task_management) {
1441109588Sgibbs			case SIU_TASKMGMT_ABORT_TASK:
1442114623Sgibbs				tag = SCB_GET_TAG(scb);
1443109588Sgibbs			case SIU_TASKMGMT_ABORT_TASK_SET:
1444109588Sgibbs			case SIU_TASKMGMT_CLEAR_TASK_SET:
1445109588Sgibbs				lun = scb->hscb->lun;
1446109588Sgibbs				error = CAM_REQ_ABORTED;
1447109588Sgibbs				ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
1448109588Sgibbs					       'A', lun, tag, ROLE_INITIATOR,
1449109588Sgibbs					       error);
1450109588Sgibbs				break;
1451109588Sgibbs			case SIU_TASKMGMT_LUN_RESET:
1452109588Sgibbs				lun = scb->hscb->lun;
1453109588Sgibbs			case SIU_TASKMGMT_TARGET_RESET:
1454109588Sgibbs			{
1455109588Sgibbs				struct ahd_devinfo devinfo;
1456109588Sgibbs
1457109588Sgibbs				ahd_scb_devinfo(ahd, &devinfo, scb);
1458109588Sgibbs				error = CAM_BDR_SENT;
1459109588Sgibbs				ahd_handle_devreset(ahd, &devinfo, lun,
1460109588Sgibbs						    CAM_BDR_SENT,
1461109588Sgibbs						    lun != CAM_LUN_WILDCARD
1462109588Sgibbs						    ? "Lun Reset"
1463109588Sgibbs						    : "Target Reset",
1464109588Sgibbs						    /*verbose_level*/0);
1465109588Sgibbs				break;
1466109588Sgibbs			}
1467109588Sgibbs			default:
1468109588Sgibbs				panic("Unexpected TaskMgmt Func\n");
1469109588Sgibbs				break;
1470109588Sgibbs			}
1471109588Sgibbs		}
1472109588Sgibbs		break;
1473109588Sgibbs	}
1474109588Sgibbs	case TASKMGMT_CMD_CMPLT_OKAY:
1475109588Sgibbs	{
1476109588Sgibbs		u_int	scbid;
1477109588Sgibbs		struct	scb *scb;
1478109588Sgibbs
1479109588Sgibbs		/*
1480109588Sgibbs		 * An ABORT TASK TMF failed to be delivered before
1481109588Sgibbs		 * the targeted command completed normally.
1482109588Sgibbs		 */
1483109588Sgibbs		scbid = ahd_get_scbptr(ahd);
1484109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1485109588Sgibbs		if (scb != NULL) {
1486109588Sgibbs			/*
1487109588Sgibbs			 * Remove the second instance of this SCB from
1488109588Sgibbs			 * the QINFIFO if it is still there.
1489109588Sgibbs                         */
1490109588Sgibbs			ahd_print_path(ahd, scb);
1491109588Sgibbs			printf("SCB completes before TMF\n");
1492109588Sgibbs			/*
1493109588Sgibbs			 * Handle losing the race.  Wait until any
1494109588Sgibbs			 * current selection completes.  We will then
1495109588Sgibbs			 * set the TMF back to zero in this SCB so that
1496109588Sgibbs			 * the sequencer doesn't bother to issue another
1497109588Sgibbs			 * sequencer interrupt for its completion.
1498109588Sgibbs			 */
1499109588Sgibbs			while ((ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
1500109588Sgibbs			    && (ahd_inb(ahd, SSTAT0) & SELDO) == 0
1501109588Sgibbs			    && (ahd_inb(ahd, SSTAT1) & SELTO) == 0)
1502109588Sgibbs				;
1503109588Sgibbs			ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0);
1504109588Sgibbs			ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
1505109588Sgibbs					   SCB_GET_CHANNEL(ahd, scb),
1506114623Sgibbs					   SCB_GET_LUN(scb), SCB_GET_TAG(scb),
1507109588Sgibbs					   ROLE_INITIATOR, /*status*/0,
1508109588Sgibbs					   SEARCH_REMOVE);
1509109588Sgibbs		}
1510109588Sgibbs		break;
1511109588Sgibbs	}
1512107441Sscottl	case TRACEPOINT0:
1513107441Sscottl	case TRACEPOINT1:
1514107441Sscottl	case TRACEPOINT2:
1515107441Sscottl	case TRACEPOINT3:
1516107441Sscottl		printf("%s: Tracepoint %d\n", ahd_name(ahd),
1517107441Sscottl		       seqintcode - TRACEPOINT0);
1518107441Sscottl		break;
1519107441Sscottl	case NO_SEQINT:
1520107441Sscottl		break;
1521107441Sscottl	case SAW_HWERR:
1522107441Sscottl		ahd_handle_hwerrint(ahd);
1523107441Sscottl		break;
1524102679Sgibbs	default:
1525102679Sgibbs		printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd),
1526102679Sgibbs		       seqintcode);
1527102679Sgibbs		break;
152897883Sgibbs	}
152997883Sgibbs	/*
153097883Sgibbs	 *  The sequencer is paused immediately on
153197883Sgibbs	 *  a SEQINT, so we should restart it when
153297883Sgibbs	 *  we're done.
153397883Sgibbs	 */
153497883Sgibbs	ahd_unpause(ahd);
153597883Sgibbs}
153697883Sgibbs
153797883Sgibbsvoid
153897883Sgibbsahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
153997883Sgibbs{
154097883Sgibbs	struct scb	*scb;
154197883Sgibbs	u_int		 status0;
154297883Sgibbs	u_int		 status3;
154397883Sgibbs	u_int		 status;
154497883Sgibbs	u_int		 lqistat1;
154597883Sgibbs	u_int		 lqostat0;
154697883Sgibbs	u_int		 scbid;
1547107441Sscottl	u_int		 busfreetime;
154897883Sgibbs
154997883Sgibbs	ahd_update_modes(ahd);
155097883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
155197883Sgibbs
155297883Sgibbs	status3 = ahd_inb(ahd, SSTAT3) & (NTRAMPERR|OSRAMPERR);
155397883Sgibbs	status0 = ahd_inb(ahd, SSTAT0) & (IOERR|OVERRUN|SELDI|SELDO);
155497883Sgibbs	status = ahd_inb(ahd, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);
155597883Sgibbs	lqistat1 = ahd_inb(ahd, LQISTAT1);
155697883Sgibbs	lqostat0 = ahd_inb(ahd, LQOSTAT0);
1557107441Sscottl	busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
155897883Sgibbs	if ((status0 & (SELDI|SELDO)) != 0) {
155997883Sgibbs		u_int simode0;
156097883Sgibbs
156197883Sgibbs		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
156297883Sgibbs		simode0 = ahd_inb(ahd, SIMODE0);
1563102679Sgibbs		status0 &= simode0 & (IOERR|OVERRUN|SELDI|SELDO);
156497883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
156597883Sgibbs	}
156697883Sgibbs	scbid = ahd_get_scbptr(ahd);
156797883Sgibbs	scb = ahd_lookup_scb(ahd, scbid);
156897883Sgibbs	if (scb != NULL
156997883Sgibbs	 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
157097883Sgibbs		scb = NULL;
157197883Sgibbs
157297883Sgibbs	if ((status0 & IOERR) != 0) {
1573102679Sgibbs		u_int now_lvd;
157497883Sgibbs
157597883Sgibbs		now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40;
157697883Sgibbs		printf("%s: Transceiver State Has Changed to %s mode\n",
157797883Sgibbs		       ahd_name(ahd), now_lvd ? "LVD" : "SE");
157897883Sgibbs		ahd_outb(ahd, CLRSINT0, CLRIOERR);
157997883Sgibbs		/*
1580102679Sgibbs		 * A change in I/O mode is equivalent to a bus reset.
158197883Sgibbs		 */
1582114623Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
158397883Sgibbs		ahd_pause(ahd);
158497883Sgibbs		ahd_setup_iocell_workaround(ahd);
158597883Sgibbs		ahd_unpause(ahd);
158697883Sgibbs	} else if ((status0 & OVERRUN) != 0) {
1587129134Sgibbs
158897883Sgibbs		printf("%s: SCSI offset overrun detected.  Resetting bus.\n",
158997883Sgibbs		       ahd_name(ahd));
1590199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
159197883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
159297883Sgibbs	} else if ((status & SCSIRSTI) != 0) {
1593129134Sgibbs
159497883Sgibbs		printf("%s: Someone reset channel A\n", ahd_name(ahd));
159597883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
1596199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
159797883Sgibbs	} else if ((status & SCSIPERR) != 0) {
1598129134Sgibbs
1599129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1600129134Sgibbs		ahd_clear_critical_section(ahd);
1601129134Sgibbs
160297883Sgibbs		ahd_handle_transmission_error(ahd);
160397883Sgibbs	} else if (lqostat0 != 0) {
1604129134Sgibbs
160597883Sgibbs		printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
160697883Sgibbs		ahd_outb(ahd, CLRLQOINT0, lqostat0);
1607129134Sgibbs		if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
160897883Sgibbs			ahd_outb(ahd, CLRLQOINT1, 0);
160997883Sgibbs	} else if ((status & SELTO) != 0) {
1610107441Sscottl		u_int  scbid;
161197883Sgibbs
161297883Sgibbs		/* Stop the selection */
161397883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
161497883Sgibbs
1615129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1616129134Sgibbs		ahd_clear_critical_section(ahd);
1617129134Sgibbs
161897883Sgibbs		/* No more pending messages */
161997883Sgibbs		ahd_clear_msg_state(ahd);
162097883Sgibbs
162197883Sgibbs		/* Clear interrupt state */
162297883Sgibbs		ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
162397883Sgibbs
162497883Sgibbs		/*
162597883Sgibbs		 * Although the driver does not care about the
162697883Sgibbs		 * 'Selection in Progress' status bit, the busy
162797883Sgibbs		 * LED does.  SELINGO is only cleared by a sucessfull
162897883Sgibbs		 * selection, so we must manually clear it to insure
162997883Sgibbs		 * the LED turns off just incase no future successful
163097883Sgibbs		 * selections occur (e.g. no devices on the bus).
163197883Sgibbs		 */
163297883Sgibbs		ahd_outb(ahd, CLRSINT0, CLRSELINGO);
163397883Sgibbs
163497883Sgibbs		scbid = ahd_inw(ahd, WAITING_TID_HEAD);
163597883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
163697883Sgibbs		if (scb == NULL) {
163797883Sgibbs			printf("%s: ahd_intr - referenced scb not "
163897883Sgibbs			       "valid during SELTO scb(0x%x)\n",
163997883Sgibbs			       ahd_name(ahd), scbid);
164097883Sgibbs			ahd_dump_card_state(ahd);
1641199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
164297883Sgibbs		} else {
1643107441Sscottl			struct ahd_devinfo devinfo;
1644104023Sgibbs#ifdef AHD_DEBUG
1645104023Sgibbs			if ((ahd_debug & AHD_SHOW_SELTO) != 0) {
1646104023Sgibbs				ahd_print_path(ahd, scb);
1647104023Sgibbs				printf("Saw Selection Timeout for SCB 0x%x\n",
1648104023Sgibbs				       scbid);
1649104023Sgibbs			}
1650104023Sgibbs#endif
1651107441Sscottl			ahd_scb_devinfo(ahd, &devinfo, scb);
1652123579Sgibbs			aic_set_transaction_status(scb, CAM_SEL_TIMEOUT);
165397883Sgibbs			ahd_freeze_devq(ahd, scb);
1654129134Sgibbs
1655129134Sgibbs			/*
1656129134Sgibbs			 * Cancel any pending transactions on the device
1657129134Sgibbs			 * now that it seems to be missing.  This will
1658129134Sgibbs			 * also revert us to async/narrow transfers until
1659129134Sgibbs			 * we can renegotiate with the device.
1660129134Sgibbs			 */
1661129134Sgibbs			ahd_handle_devreset(ahd, &devinfo,
1662129134Sgibbs					    CAM_LUN_WILDCARD,
1663129134Sgibbs					    CAM_SEL_TIMEOUT,
1664129134Sgibbs					    "Selection Timeout",
1665129134Sgibbs					    /*verbose_level*/1);
166697883Sgibbs		}
166797883Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
166897883Sgibbs		ahd_iocell_first_selection(ahd);
1669109588Sgibbs		ahd_unpause(ahd);
167097883Sgibbs	} else if ((status0 & (SELDI|SELDO)) != 0) {
1671129134Sgibbs
167297883Sgibbs		ahd_iocell_first_selection(ahd);
167397883Sgibbs		ahd_unpause(ahd);
167497883Sgibbs	} else if (status3 != 0) {
167597883Sgibbs		printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n",
167697883Sgibbs		       ahd_name(ahd), status3);
1677199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
167897883Sgibbs		ahd_outb(ahd, CLRSINT3, status3);
167997883Sgibbs	} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
1680129134Sgibbs
1681129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1682129134Sgibbs		ahd_clear_critical_section(ahd);
1683129134Sgibbs
168497883Sgibbs		ahd_handle_lqiphase_error(ahd, lqistat1);
1685111653Sgibbs	} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
1686111653Sgibbs		/*
1687111653Sgibbs		 * This status can be delayed during some
1688111653Sgibbs		 * streaming operations.  The SCSIPHASE
1689111653Sgibbs		 * handler has already dealt with this case
1690111653Sgibbs		 * so just clear the error.
1691111653Sgibbs		 */
1692111653Sgibbs		ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);
1693133122Sgibbs	} else if ((status & BUSFREE) != 0
1694133122Sgibbs		|| (lqistat1 & LQOBUSFREE) != 0) {
169597883Sgibbs		u_int lqostat1;
169697883Sgibbs		int   restart;
169797883Sgibbs		int   clear_fifo;
169897883Sgibbs		int   packetized;
169997883Sgibbs		u_int mode;
170097883Sgibbs
170197883Sgibbs		/*
170297883Sgibbs		 * Clear our selection hardware as soon as possible.
170397883Sgibbs		 * We may have an entry in the waiting Q for this target,
170497883Sgibbs		 * that is affected by this busfree and we don't want to
170597883Sgibbs		 * go about selecting the target while we handle the event.
170697883Sgibbs		 */
170797883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
170897883Sgibbs
1709129134Sgibbs		/* Make sure the sequencer is in a safe location. */
1710129134Sgibbs		ahd_clear_critical_section(ahd);
1711129134Sgibbs
171297883Sgibbs		/*
171397883Sgibbs		 * Determine what we were up to at the time of
171497883Sgibbs		 * the busfree.
171597883Sgibbs		 */
171697883Sgibbs		mode = AHD_MODE_SCSI;
171797883Sgibbs		busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
171897883Sgibbs		lqostat1 = ahd_inb(ahd, LQOSTAT1);
171997883Sgibbs		switch (busfreetime) {
172097883Sgibbs		case BUSFREE_DFF0:
172197883Sgibbs		case BUSFREE_DFF1:
172297883Sgibbs		{
172397883Sgibbs			u_int	scbid;
172497883Sgibbs			struct	scb *scb;
172597883Sgibbs
172697883Sgibbs			mode = busfreetime == BUSFREE_DFF0
172797883Sgibbs			     ? AHD_MODE_DFF0 : AHD_MODE_DFF1;
172897883Sgibbs			ahd_set_modes(ahd, mode, mode);
172997883Sgibbs			scbid = ahd_get_scbptr(ahd);
173097883Sgibbs			scb = ahd_lookup_scb(ahd, scbid);
173197883Sgibbs			if (scb == NULL) {
1732114623Sgibbs				printf("%s: Invalid SCB %d in DFF%d "
173397883Sgibbs				       "during unexpected busfree\n",
1734114623Sgibbs				       ahd_name(ahd), scbid, mode);
173597883Sgibbs				packetized = 0;
1736199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
173797883Sgibbs			} else
173897883Sgibbs				packetized = (scb->flags & SCB_PACKETIZED) != 0;
173997883Sgibbs			clear_fifo = 1;
174097883Sgibbs			break;
174197883Sgibbs		}
174297883Sgibbs		case BUSFREE_LQO:
174397883Sgibbs			clear_fifo = 0;
174497883Sgibbs			packetized = 1;
174597883Sgibbs			break;
174697883Sgibbs		default:
174797883Sgibbs			clear_fifo = 0;
174897883Sgibbs			packetized =  (lqostat1 & LQOBUSFREE) != 0;
174997883Sgibbs			if (!packetized
1750125448Sgibbs			 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
1751129134Sgibbs			 && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
1752125448Sgibbs			 && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
1753125448Sgibbs			  || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
1754125448Sgibbs				/*
1755125448Sgibbs				 * Assume packetized if we are not
1756125448Sgibbs				 * on the bus in a non-packetized
1757125448Sgibbs				 * capacity and any pending selection
1758125448Sgibbs				 * was a packetized selection.
1759125448Sgibbs				 */
176097883Sgibbs				packetized = 1;
176197883Sgibbs			break;
176297883Sgibbs		}
176397883Sgibbs
176497883Sgibbs#ifdef AHD_DEBUG
176597883Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
176697883Sgibbs			printf("Saw Busfree.  Busfreetime = 0x%x.\n",
176797883Sgibbs			       busfreetime);
176897883Sgibbs#endif
176997883Sgibbs		/*
177097883Sgibbs		 * Busfrees that occur in non-packetized phases are
177197883Sgibbs		 * handled by the nonpkt_busfree handler.
177297883Sgibbs		 */
177397883Sgibbs		if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) {
177497883Sgibbs			restart = ahd_handle_pkt_busfree(ahd, busfreetime);
177597883Sgibbs		} else {
1776104023Sgibbs			packetized = 0;
177797883Sgibbs			restart = ahd_handle_nonpkt_busfree(ahd);
177897883Sgibbs		}
177997883Sgibbs		/*
178097883Sgibbs		 * Clear the busfree interrupt status.  The setting of
1781104023Sgibbs		 * the interrupt is a pulse, so in a perfect world, we
1782104023Sgibbs		 * would not need to muck with the ENBUSFREE logic.  This
1783104023Sgibbs		 * would ensure that if the bus moves on to another
1784104023Sgibbs		 * connection, busfree protection is still in force.  If
1785104023Sgibbs		 * BUSFREEREV is broken, however, we must manually clear
1786104023Sgibbs		 * the ENBUSFREE if the busfree occurred during a non-pack
1787104023Sgibbs		 * connection so that we don't get false positives during
1788104023Sgibbs		 * future, packetized, connections.
178997883Sgibbs		 */
1790104023Sgibbs		ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
1791104023Sgibbs		if (packetized == 0
1792104023Sgibbs		 && (ahd->bugs & AHD_BUSFREEREV_BUG) != 0)
1793104023Sgibbs			ahd_outb(ahd, SIMODE1,
1794104023Sgibbs				 ahd_inb(ahd, SIMODE1) & ~ENBUSFREE);
179597883Sgibbs
179697883Sgibbs		if (clear_fifo)
179797883Sgibbs			ahd_clear_fifo(ahd, mode);
179897883Sgibbs
179997883Sgibbs		ahd_clear_msg_state(ahd);
1800104023Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
1801102679Sgibbs		if (restart) {
180297883Sgibbs			ahd_restart(ahd);
1803102679Sgibbs		} else {
180497883Sgibbs			ahd_unpause(ahd);
180597883Sgibbs		}
180697883Sgibbs	} else {
180797883Sgibbs		printf("%s: Missing case in ahd_handle_scsiint. status = %x\n",
180897883Sgibbs		       ahd_name(ahd), status);
180997883Sgibbs		ahd_dump_card_state(ahd);
1810102679Sgibbs		ahd_clear_intstat(ahd);
181197883Sgibbs		ahd_unpause(ahd);
181297883Sgibbs	}
181397883Sgibbs}
181497883Sgibbs
181597883Sgibbsstatic void
181697883Sgibbsahd_handle_transmission_error(struct ahd_softc *ahd)
181797883Sgibbs{
1818107441Sscottl	struct	scb *scb;
1819107441Sscottl	u_int	scbid;
1820104023Sgibbs	u_int	lqistat1;
1821104023Sgibbs	u_int	lqistat2;
1822104023Sgibbs	u_int	msg_out;
1823104023Sgibbs	u_int	curphase;
1824104023Sgibbs	u_int	lastphase;
1825104023Sgibbs	u_int	perrdiag;
1826104023Sgibbs	u_int	cur_col;
1827109588Sgibbs	int	silent;
182897883Sgibbs
1829107441Sscottl	scb = NULL;
183097883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
183197883Sgibbs	lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);
183297883Sgibbs	lqistat2 = ahd_inb(ahd, LQISTAT2);
183397883Sgibbs	if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0
183497883Sgibbs	 && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) {
183597883Sgibbs		u_int lqistate;
183697883Sgibbs
183797883Sgibbs		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
183897883Sgibbs		lqistate = ahd_inb(ahd, LQISTATE);
183997883Sgibbs		if ((lqistate >= 0x1E && lqistate <= 0x24)
184097883Sgibbs		 || (lqistate == 0x29)) {
1841107441Sscottl#ifdef AHD_DEBUG
1842107441Sscottl			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
1843107441Sscottl				printf("%s: NLQCRC found via LQISTATE\n",
1844107441Sscottl				       ahd_name(ahd));
1845107441Sscottl			}
1846107441Sscottl#endif
184797883Sgibbs			lqistat1 |= LQICRCI_NLQ;
184897883Sgibbs		}
184997883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
185097883Sgibbs	}
185197883Sgibbs
185297883Sgibbs	ahd_outb(ahd, CLRLQIINT1, lqistat1);
185397883Sgibbs	lastphase = ahd_inb(ahd, LASTPHASE);
185497883Sgibbs	curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
185597883Sgibbs	perrdiag = ahd_inb(ahd, PERRDIAG);
185697883Sgibbs	msg_out = MSG_INITIATOR_DET_ERR;
185797883Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSCSIPERR);
1858109588Sgibbs
1859109588Sgibbs	/*
1860109588Sgibbs	 * Try to find the SCB associated with this error.
1861109588Sgibbs	 */
1862109588Sgibbs	silent = FALSE;
1863109588Sgibbs	if (lqistat1 == 0
1864109588Sgibbs	 || (lqistat1 & LQICRCI_NLQ) != 0) {
1865109588Sgibbs	 	if ((lqistat1 & (LQICRCI_NLQ|LQIOVERI_NLQ)) != 0)
1866109588Sgibbs			ahd_set_active_fifo(ahd);
1867109588Sgibbs		scbid = ahd_get_scbptr(ahd);
1868109588Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
1869109588Sgibbs		if (scb != NULL && SCB_IS_SILENT(scb))
1870109588Sgibbs			silent = TRUE;
1871109588Sgibbs	}
1872109588Sgibbs
1873104023Sgibbs	cur_col = 0;
1874109588Sgibbs	if (silent == FALSE) {
1875109588Sgibbs		printf("%s: Transmission error detected\n", ahd_name(ahd));
1876109588Sgibbs		ahd_lqistat1_print(lqistat1, &cur_col, 50);
1877109588Sgibbs		ahd_lastphase_print(lastphase, &cur_col, 50);
1878109588Sgibbs		ahd_scsisigi_print(curphase, &cur_col, 50);
1879109588Sgibbs		ahd_perrdiag_print(perrdiag, &cur_col, 50);
1880109588Sgibbs		printf("\n");
1881199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
1882109588Sgibbs		ahd_dump_card_state(ahd);
1883109588Sgibbs	}
1884109588Sgibbs
188597883Sgibbs	if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) {
1886109588Sgibbs		if (silent == FALSE) {
1887109588Sgibbs			printf("%s: Gross protocol error during incoming "
1888109588Sgibbs			       "packet.  lqistat1 == 0x%x.  Resetting bus.\n",
1889109588Sgibbs			       ahd_name(ahd), lqistat1);
1890199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
1891109588Sgibbs		}
189297883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
189397883Sgibbs		return;
189497883Sgibbs	} else if ((lqistat1 & LQICRCI_LQ) != 0) {
189597883Sgibbs		/*
189697883Sgibbs		 * A CRC error has been detected on an incoming LQ.
189797883Sgibbs		 * The bus is currently hung on the last ACK.
189897883Sgibbs		 * Hit LQIRETRY to release the last ack, and
189997883Sgibbs		 * wait for the sequencer to determine that ATNO
190097883Sgibbs		 * is asserted while in message out to take us
190197883Sgibbs		 * to our host message loop.  No NONPACKREQ or
190297883Sgibbs		 * LQIPHASE type errors will occur in this
190397883Sgibbs		 * scenario.  After this first LQIRETRY, the LQI
190497883Sgibbs		 * manager will be in ISELO where it will
190597883Sgibbs		 * happily sit until another packet phase begins.
190697883Sgibbs		 * Unexpected bus free detection is enabled
190797883Sgibbs		 * through any phases that occur after we release
190897883Sgibbs		 * this last ack until the LQI manager sees a
190997883Sgibbs		 * packet phase.  This implies we may have to
191097883Sgibbs		 * ignore a perfectly valid "unexected busfree"
191197883Sgibbs		 * after our "initiator detected error" message is
191297883Sgibbs		 * sent.  A busfree is the expected response after
191397883Sgibbs		 * we tell the target that it's L_Q was corrupted.
191497883Sgibbs		 * (SPI4R09 10.7.3.3.3)
191597883Sgibbs		 */
191697883Sgibbs		ahd_outb(ahd, LQCTL2, LQIRETRY);
191797883Sgibbs		printf("LQIRetry for LQICRCI_LQ to release ACK\n");
1918199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
191997883Sgibbs	} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
192097883Sgibbs		/*
192197883Sgibbs		 * We detected a CRC error in a NON-LQ packet.
192297883Sgibbs		 * The hardware has varying behavior in this situation
192397883Sgibbs		 * depending on whether this packet was part of a
192497883Sgibbs		 * stream or not.
192597883Sgibbs		 *
192697883Sgibbs		 * PKT by PKT mode:
192797883Sgibbs		 * The hardware has already acked the complete packet.
192897883Sgibbs		 * If the target honors our outstanding ATN condition,
192997883Sgibbs		 * we should be (or soon will be) in MSGOUT phase.
193097883Sgibbs		 * This will trigger the LQIPHASE_LQ status bit as the
193197883Sgibbs		 * hardware was expecting another LQ.  Unexpected
193297883Sgibbs		 * busfree detection is enabled.  Once LQIPHASE_LQ is
193397883Sgibbs		 * true (first entry into host message loop is much
193497883Sgibbs		 * the same), we must clear LQIPHASE_LQ and hit
193597883Sgibbs		 * LQIRETRY so the hardware is ready to handle
193697883Sgibbs		 * a future LQ.  NONPACKREQ will not be asserted again
193797883Sgibbs		 * once we hit LQIRETRY until another packet is
193897883Sgibbs		 * processed.  The target may either go busfree
193997883Sgibbs		 * or start another packet in response to our message.
194097883Sgibbs		 *
194197883Sgibbs		 * Read Streaming P0 asserted:
194297883Sgibbs		 * If we raise ATN and the target completes the entire
194397883Sgibbs		 * stream (P0 asserted during the last packet), the
194497883Sgibbs		 * hardware will ack all data and return to the ISTART
194597883Sgibbs		 * state.  When the target reponds to our ATN condition,
194697883Sgibbs		 * LQIPHASE_LQ will be asserted.  We should respond to
194797883Sgibbs		 * this with an LQIRETRY to prepare for any future
194897883Sgibbs		 * packets.  NONPACKREQ will not be asserted again
194997883Sgibbs		 * once we hit LQIRETRY until another packet is
195097883Sgibbs		 * processed.  The target may either go busfree or
195197883Sgibbs		 * start another packet in response to our message.
195297883Sgibbs		 * Busfree detection is enabled.
195397883Sgibbs		 *
195497883Sgibbs		 * Read Streaming P0 not asserted:
195597883Sgibbs		 * If we raise ATN and the target transitions to
195697883Sgibbs		 * MSGOUT in or after a packet where P0 is not
195797883Sgibbs		 * asserted, the hardware will assert LQIPHASE_NLQ.
195897883Sgibbs		 * We should respond to the LQIPHASE_NLQ with an
1959107441Sscottl		 * LQIRETRY.  Should the target stay in a non-pkt
196097883Sgibbs		 * phase after we send our message, the hardware
196197883Sgibbs		 * will assert LQIPHASE_LQ.  Recovery is then just as
196297883Sgibbs		 * listed above for the read streaming with P0 asserted.
196397883Sgibbs		 * Busfree detection is enabled.
196497883Sgibbs		 */
1965109588Sgibbs		if (silent == FALSE)
1966109588Sgibbs			printf("LQICRC_NLQ\n");
196797883Sgibbs		if (scb == NULL) {
196897883Sgibbs			printf("%s: No SCB valid for LQICRC_NLQ.  "
196997883Sgibbs			       "Resetting bus\n", ahd_name(ahd));
1970199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
197197883Sgibbs			ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
197297883Sgibbs			return;
197397883Sgibbs		}
197497883Sgibbs	} else if ((lqistat1 & LQIBADLQI) != 0) {
197597883Sgibbs		printf("Need to handle BADLQI!\n");
197697883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
197797883Sgibbs		return;
1978102679Sgibbs	} else if ((perrdiag & (PARITYERR|PREVPHASE)) == PARITYERR) {
197997883Sgibbs		if ((curphase & ~P_DATAIN_DT) != 0) {
198097883Sgibbs			/* Ack the byte.  So we can continue. */
1981109588Sgibbs			if (silent == FALSE)
1982109588Sgibbs				printf("Acking %s to clear perror\n",
1983109588Sgibbs				    ahd_lookup_phase_entry(curphase)->phasemsg);
198497883Sgibbs			ahd_inb(ahd, SCSIDAT);
198597883Sgibbs		}
198697883Sgibbs
198797883Sgibbs		if (curphase == P_MESGIN)
198897883Sgibbs			msg_out = MSG_PARITY_ERROR;
198997883Sgibbs	}
199097883Sgibbs
199197883Sgibbs	/*
199297883Sgibbs	 * We've set the hardware to assert ATN if we
199397883Sgibbs	 * get a parity error on "in" phases, so all we
199497883Sgibbs	 * need to do is stuff the message buffer with
199597883Sgibbs	 * the appropriate message.  "In" phases have set
199697883Sgibbs	 * mesg_out to something other than MSG_NOP.
199797883Sgibbs	 */
199897883Sgibbs	ahd->send_msg_perror = msg_out;
1999107441Sscottl	if (scb != NULL && msg_out == MSG_INITIATOR_DET_ERR)
2000107441Sscottl		scb->flags |= SCB_TRANSMISSION_ERROR;
200197883Sgibbs	ahd_outb(ahd, MSG_OUT, HOST_MSG);
200297883Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
200397883Sgibbs	ahd_unpause(ahd);
200497883Sgibbs}
200597883Sgibbs
200697883Sgibbsstatic void
200797883Sgibbsahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)
200897883Sgibbs{
200997883Sgibbs	/*
201097883Sgibbs	 * Clear the sources of the interrupts.
201197883Sgibbs	 */
201297883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
201397883Sgibbs	ahd_outb(ahd, CLRLQIINT1, lqistat1);
201497883Sgibbs
201597883Sgibbs	/*
201697883Sgibbs	 * If the "illegal" phase changes were in response
201797883Sgibbs	 * to our ATN to flag a CRC error, AND we ended up
201897883Sgibbs	 * on packet boundaries, clear the error, restart the
201997883Sgibbs	 * LQI manager as appropriate, and go on our merry
202097883Sgibbs	 * way toward sending the message.  Otherwise, reset
202197883Sgibbs	 * the bus to clear the error.
202297883Sgibbs	 */
202397883Sgibbs	ahd_set_active_fifo(ahd);
202497883Sgibbs	if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0
202597883Sgibbs	 && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) {
202697883Sgibbs		if ((lqistat1 & LQIPHASE_LQ) != 0) {
202797883Sgibbs			printf("LQIRETRY for LQIPHASE_LQ\n");
2028199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
202997883Sgibbs			ahd_outb(ahd, LQCTL2, LQIRETRY);
203097883Sgibbs		} else if ((lqistat1 & LQIPHASE_NLQ) != 0) {
2031107441Sscottl			printf("LQIRETRY for LQIPHASE_NLQ\n");
2032199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
203397883Sgibbs			ahd_outb(ahd, LQCTL2, LQIRETRY);
203497883Sgibbs		} else
203597883Sgibbs			panic("ahd_handle_lqiphase_error: No phase errors\n");
203697883Sgibbs		ahd_dump_card_state(ahd);
203797883Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
203897883Sgibbs		ahd_unpause(ahd);
203997883Sgibbs	} else {
204097883Sgibbs		printf("Reseting Channel for LQI Phase error\n");
2041199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
204297883Sgibbs		ahd_dump_card_state(ahd);
204397883Sgibbs		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
204497883Sgibbs	}
204597883Sgibbs}
204697883Sgibbs
204797883Sgibbs/*
204897883Sgibbs * Packetized unexpected or expected busfree.
2049104023Sgibbs * Entered in mode based on busfreetime.
205097883Sgibbs */
205197883Sgibbsstatic int
205297883Sgibbsahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
205397883Sgibbs{
205497883Sgibbs	u_int lqostat1;
205597883Sgibbs
205697883Sgibbs	AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
205797883Sgibbs			 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
205897883Sgibbs	lqostat1 = ahd_inb(ahd, LQOSTAT1);
205997883Sgibbs	if ((lqostat1 & LQOBUSFREE) != 0) {
206097883Sgibbs		struct scb *scb;
206197883Sgibbs		u_int scbid;
2062104023Sgibbs		u_int saved_scbptr;
206397883Sgibbs		u_int waiting_h;
206497883Sgibbs		u_int waiting_t;
206597883Sgibbs		u_int next;
206697883Sgibbs
2067104023Sgibbs		/*
2068104023Sgibbs		 * The LQO manager detected an unexpected busfree
2069104023Sgibbs		 * either:
2070104023Sgibbs		 *
2071104023Sgibbs		 * 1) During an outgoing LQ.
2072104023Sgibbs		 * 2) After an outgoing LQ but before the first
2073104023Sgibbs		 *    REQ of the command packet.
2074104023Sgibbs		 * 3) During an outgoing command packet.
2075104023Sgibbs		 *
2076104023Sgibbs		 * In all cases, CURRSCB is pointing to the
2077104023Sgibbs		 * SCB that encountered the failure.  Clean
2078104023Sgibbs		 * up the queue, clear SELDO and LQOBUSFREE,
2079104023Sgibbs		 * and allow the sequencer to restart the select
2080104023Sgibbs		 * out at its lesure.
2081104023Sgibbs		 */
2082104023Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2083104023Sgibbs		scbid = ahd_inw(ahd, CURRSCB);
208497883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
208597883Sgibbs		if (scb == NULL)
208697883Sgibbs		       panic("SCB not valid during LQOBUSFREE");
208797883Sgibbs		/*
208897883Sgibbs		 * Clear the status.
208997883Sgibbs		 */
209097883Sgibbs		ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE);
2091104023Sgibbs		if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
209297883Sgibbs			ahd_outb(ahd, CLRLQOINT1, 0);
2093104023Sgibbs		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
2094111653Sgibbs		ahd_flush_device_writes(ahd);
2095104023Sgibbs		ahd_outb(ahd, CLRSINT0, CLRSELDO);
2096104023Sgibbs
209797883Sgibbs		/*
2098111653Sgibbs		 * Return the LQO manager to its idle loop.  It will
2099111653Sgibbs		 * not do this automatically if the busfree occurs
2100111653Sgibbs		 * after the first REQ of either the LQ or command
2101111653Sgibbs		 * packet or between the LQ and command packet.
2102111653Sgibbs		 */
2103111653Sgibbs		ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE);
2104111653Sgibbs
2105111653Sgibbs		/*
2106104023Sgibbs		 * Update the waiting for selection queue so
2107104023Sgibbs		 * we restart on the correct SCB.
210897883Sgibbs		 */
210997883Sgibbs		waiting_h = ahd_inw(ahd, WAITING_TID_HEAD);
2110104023Sgibbs		saved_scbptr = ahd_get_scbptr(ahd);
211197883Sgibbs		if (waiting_h != scbid) {
211297883Sgibbs
211397883Sgibbs			ahd_outw(ahd, WAITING_TID_HEAD, scbid);
211497883Sgibbs			waiting_t = ahd_inw(ahd, WAITING_TID_TAIL);
211597883Sgibbs			if (waiting_t == waiting_h) {
211697883Sgibbs				ahd_outw(ahd, WAITING_TID_TAIL, scbid);
2117111653Sgibbs				next = SCB_LIST_NULL;
211897883Sgibbs			} else {
211997883Sgibbs				ahd_set_scbptr(ahd, waiting_h);
2120111954Sgibbs				next = ahd_inw_scbram(ahd, SCB_NEXT2);
212197883Sgibbs			}
212297883Sgibbs			ahd_set_scbptr(ahd, scbid);
212397883Sgibbs			ahd_outw(ahd, SCB_NEXT2, next);
212497883Sgibbs		}
2125104023Sgibbs		ahd_set_scbptr(ahd, saved_scbptr);
2126107441Sscottl		if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS) {
2127109588Sgibbs			if (SCB_IS_SILENT(scb) == FALSE) {
2128109588Sgibbs				ahd_print_path(ahd, scb);
2129109588Sgibbs				printf("Probable outgoing LQ CRC error.  "
2130109588Sgibbs				       "Retrying command\n");
2131199260Sattilio				AHD_CORRECTABLE_ERROR(ahd);
2132109588Sgibbs			}
2133107441Sscottl			scb->crc_retry_count++;
2134107441Sscottl		} else {
2135123579Sgibbs			aic_set_transaction_status(scb, CAM_UNCOR_PARITY);
2136123579Sgibbs			aic_freeze_scb(scb);
2137107441Sscottl			ahd_freeze_devq(ahd, scb);
2138107441Sscottl		}
213997883Sgibbs		/* Return unpausing the sequencer. */
214097883Sgibbs		return (0);
2141107441Sscottl	} else if ((ahd_inb(ahd, PERRDIAG) & PARITYERR) != 0) {
2142107441Sscottl		/*
2143107441Sscottl		 * Ignore what are really parity errors that
2144107441Sscottl		 * occur on the last REQ of a free running
2145107441Sscottl		 * clock prior to going busfree.  Some drives
2146107441Sscottl		 * do not properly active negate just before
2147107441Sscottl		 * going busfree resulting in a parity glitch.
2148107441Sscottl		 */
2149107441Sscottl		ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE);
2150107441Sscottl#ifdef AHD_DEBUG
2151107441Sscottl		if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0)
2152107441Sscottl			printf("%s: Parity on last REQ detected "
2153107441Sscottl			       "during busfree phase.\n",
2154107441Sscottl			       ahd_name(ahd));
2155107441Sscottl#endif
2156107441Sscottl		/* Return unpausing the sequencer. */
2157107441Sscottl		return (0);
215897883Sgibbs	}
215997883Sgibbs	if (ahd->src_mode != AHD_MODE_SCSI) {
216097883Sgibbs		u_int	scbid;
216197883Sgibbs		struct	scb *scb;
216297883Sgibbs
216397883Sgibbs		scbid = ahd_get_scbptr(ahd);
216497883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
216597883Sgibbs		ahd_print_path(ahd, scb);
216697883Sgibbs		printf("Unexpected PKT busfree condition\n");
2167199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2168111653Sgibbs		ahd_dump_card_state(ahd);
216997883Sgibbs		ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A',
217097883Sgibbs			       SCB_GET_LUN(scb), SCB_GET_TAG(scb),
217197883Sgibbs			       ROLE_INITIATOR, CAM_UNEXP_BUSFREE);
217297883Sgibbs
217397883Sgibbs		/* Return restarting the sequencer. */
217497883Sgibbs		return (1);
217597883Sgibbs	}
217697883Sgibbs	printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd));
2177199260Sattilio	AHD_UNCORRECTABLE_ERROR(ahd);
217897883Sgibbs	ahd_dump_card_state(ahd);
217997883Sgibbs	/* Restart the sequencer. */
218097883Sgibbs	return (1);
218197883Sgibbs}
218297883Sgibbs
218397883Sgibbs/*
218497883Sgibbs * Non-packetized unexpected or expected busfree.
218597883Sgibbs */
218697883Sgibbsstatic int
218797883Sgibbsahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
218897883Sgibbs{
218997883Sgibbs	struct	ahd_devinfo devinfo;
219097883Sgibbs	struct	scb *scb;
219197883Sgibbs	u_int	lastphase;
219297883Sgibbs	u_int	saved_scsiid;
219397883Sgibbs	u_int	saved_lun;
219497883Sgibbs	u_int	target;
219597883Sgibbs	u_int	initiator_role_id;
219697883Sgibbs	u_int	scbid;
2197107441Sscottl	u_int	ppr_busfree;
219897883Sgibbs	int	printerror;
219997883Sgibbs
220097883Sgibbs	/*
220197883Sgibbs	 * Look at what phase we were last in.  If its message out,
220297883Sgibbs	 * chances are pretty good that the busfree was in response
220397883Sgibbs	 * to one of our abort requests.
220497883Sgibbs	 */
220597883Sgibbs	lastphase = ahd_inb(ahd, LASTPHASE);
220697883Sgibbs	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
220797883Sgibbs	saved_lun = ahd_inb(ahd, SAVED_LUN);
220897883Sgibbs	target = SCSIID_TARGET(ahd, saved_scsiid);
220997883Sgibbs	initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
221097883Sgibbs	ahd_compile_devinfo(&devinfo, initiator_role_id,
221197883Sgibbs			    target, saved_lun, 'A', ROLE_INITIATOR);
221297883Sgibbs	printerror = 1;
221397883Sgibbs
221497883Sgibbs	scbid = ahd_get_scbptr(ahd);
221597883Sgibbs	scb = ahd_lookup_scb(ahd, scbid);
221697883Sgibbs	if (scb != NULL
221797883Sgibbs	 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
221897883Sgibbs		scb = NULL;
221997883Sgibbs
2220107441Sscottl	ppr_busfree = (ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0;
222197883Sgibbs	if (lastphase == P_MESGOUT) {
222297883Sgibbs		u_int tag;
222397883Sgibbs
222497883Sgibbs		tag = SCB_LIST_NULL;
222597883Sgibbs		if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT_TAG, TRUE)
222697883Sgibbs		 || ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT, TRUE)) {
222797883Sgibbs			int found;
222897883Sgibbs			int sent_msg;
222997883Sgibbs
2230102679Sgibbs			if (scb == NULL) {
2231102679Sgibbs				ahd_print_devinfo(ahd, &devinfo);
2232102679Sgibbs				printf("Abort for unidentified "
2233102679Sgibbs				       "connection completed.\n");
2234102679Sgibbs				/* restart the sequencer. */
2235102679Sgibbs				return (1);
2236102679Sgibbs			}
223797883Sgibbs			sent_msg = ahd->msgout_buf[ahd->msgout_index - 1];
223897883Sgibbs			ahd_print_path(ahd, scb);
223997883Sgibbs			printf("SCB %d - Abort%s Completed.\n",
224097883Sgibbs			       SCB_GET_TAG(scb),
224197883Sgibbs			       sent_msg == MSG_ABORT_TAG ? "" : " Tag");
224297883Sgibbs
224397883Sgibbs			if (sent_msg == MSG_ABORT_TAG)
224497883Sgibbs				tag = SCB_GET_TAG(scb);
224597883Sgibbs
224697883Sgibbs			if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) {
224797883Sgibbs				/*
224897883Sgibbs				 * This abort is in response to an
224997883Sgibbs				 * unexpected switch to command phase
225097883Sgibbs				 * for a packetized connection.  Since
225197883Sgibbs				 * the identify message was never sent,
225297883Sgibbs				 * "saved lun" is 0.  We really want to
225397883Sgibbs				 * abort only the SCB that encountered
225497883Sgibbs				 * this error, which could have a different
225597883Sgibbs				 * lun.  The SCB will be retried so the OS
225697883Sgibbs				 * will see the UA after renegotiating to
225797883Sgibbs				 * packetized.
225897883Sgibbs				 */
225997883Sgibbs				tag = SCB_GET_TAG(scb);
226097883Sgibbs				saved_lun = scb->hscb->lun;
226197883Sgibbs			}
226297883Sgibbs			found = ahd_abort_scbs(ahd, target, 'A', saved_lun,
226397883Sgibbs					       tag, ROLE_INITIATOR,
226497883Sgibbs					       CAM_REQ_ABORTED);
226597883Sgibbs			printf("found == 0x%x\n", found);
226697883Sgibbs			printerror = 0;
226797883Sgibbs		} else if (ahd_sent_msg(ahd, AHDMSG_1B,
226897883Sgibbs					MSG_BUS_DEV_RESET, TRUE)) {
226997883Sgibbs#ifdef __FreeBSD__
227097883Sgibbs			/*
227197883Sgibbs			 * Don't mark the user's request for this BDR
227297883Sgibbs			 * as completing with CAM_BDR_SENT.  CAM3
227397883Sgibbs			 * specifies CAM_REQ_CMP.
227497883Sgibbs			 */
227597883Sgibbs			if (scb != NULL
227697883Sgibbs			 && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV
227797883Sgibbs			 && ahd_match_scb(ahd, scb, target, 'A',
227897883Sgibbs					  CAM_LUN_WILDCARD, SCB_LIST_NULL,
227997883Sgibbs					  ROLE_INITIATOR))
2280123579Sgibbs				aic_set_transaction_status(scb, CAM_REQ_CMP);
228197883Sgibbs#endif
2282109588Sgibbs			ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD,
2283109588Sgibbs					    CAM_BDR_SENT, "Bus Device Reset",
228497883Sgibbs					    /*verbose_level*/0);
228597883Sgibbs			printerror = 0;
2286107441Sscottl		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, FALSE)
2287107441Sscottl			&& ppr_busfree == 0) {
228897883Sgibbs			struct ahd_initiator_tinfo *tinfo;
228997883Sgibbs			struct ahd_tmode_tstate *tstate;
229097883Sgibbs
229197883Sgibbs			/*
2292133122Sgibbs			 * PPR Rejected.
2293133122Sgibbs			 *
2294133122Sgibbs			 * If the previous negotiation was packetized,
2295133122Sgibbs			 * this could be because the device has been
2296133122Sgibbs			 * reset without our knowledge.  Force our
2297133122Sgibbs			 * current negotiation to async and retry the
2298133122Sgibbs			 * negotiation.  Otherwise retry the command
2299133122Sgibbs			 * with non-ppr negotiation.
230097883Sgibbs			 */
2301107441Sscottl#ifdef AHD_DEBUG
2302107441Sscottl			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2303107441Sscottl				printf("PPR negotiation rejected busfree.\n");
2304107441Sscottl#endif
230597883Sgibbs			tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
230697883Sgibbs						    devinfo.our_scsiid,
230797883Sgibbs						    devinfo.target, &tstate);
2308133122Sgibbs			if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) {
2309133122Sgibbs				ahd_set_width(ahd, &devinfo,
2310133122Sgibbs					      MSG_EXT_WDTR_BUS_8_BIT,
2311133122Sgibbs					      AHD_TRANS_CUR,
2312133122Sgibbs					      /*paused*/TRUE);
2313133122Sgibbs				ahd_set_syncrate(ahd, &devinfo,
2314133122Sgibbs						/*period*/0, /*offset*/0,
2315133122Sgibbs						/*ppr_options*/0,
2316133122Sgibbs						AHD_TRANS_CUR,
2317133122Sgibbs						/*paused*/TRUE);
2318133122Sgibbs				/*
2319133122Sgibbs				 * The expect PPR busfree handler below
2320133122Sgibbs				 * will effect the retry and necessary
2321133122Sgibbs				 * abort.
2322133122Sgibbs				 */
2323133122Sgibbs			} else {
2324133122Sgibbs				tinfo->curr.transport_version = 2;
2325133122Sgibbs				tinfo->goal.transport_version = 2;
2326133122Sgibbs				tinfo->goal.ppr_options = 0;
2327133122Sgibbs				/*
2328133122Sgibbs				 * Remove any SCBs in the waiting for selection
2329133122Sgibbs				 * queue that may also be for this target so
2330133122Sgibbs				 * that command ordering is preserved.
2331133122Sgibbs				 */
2332133122Sgibbs				ahd_freeze_devq(ahd, scb);
2333133122Sgibbs				ahd_qinfifo_requeue_tail(ahd, scb);
2334133122Sgibbs				printerror = 0;
2335133122Sgibbs			}
2336115918Sgibbs		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
2337107441Sscottl			&& ppr_busfree == 0) {
233897883Sgibbs			/*
2339115918Sgibbs			 * Negotiation Rejected.  Go-narrow and
234097883Sgibbs			 * retry command.
234197883Sgibbs			 */
2342107441Sscottl#ifdef AHD_DEBUG
2343107441Sscottl			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2344115918Sgibbs				printf("WDTR negotiation rejected busfree.\n");
2345107441Sscottl#endif
234697883Sgibbs			ahd_set_width(ahd, &devinfo,
234797883Sgibbs				      MSG_EXT_WDTR_BUS_8_BIT,
234897883Sgibbs				      AHD_TRANS_CUR|AHD_TRANS_GOAL,
234997883Sgibbs				      /*paused*/TRUE);
2350133122Sgibbs			/*
2351133122Sgibbs			 * Remove any SCBs in the waiting for selection
2352133122Sgibbs			 * queue that may also be for this target so that
2353133122Sgibbs			 * command ordering is preserved.
2354133122Sgibbs			 */
2355133122Sgibbs			ahd_freeze_devq(ahd, scb);
2356115918Sgibbs			ahd_qinfifo_requeue_tail(ahd, scb);
2357115918Sgibbs			printerror = 0;
2358115918Sgibbs		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
2359115918Sgibbs			&& ppr_busfree == 0) {
2360115918Sgibbs			/*
2361115918Sgibbs			 * Negotiation Rejected.  Go-async and
2362115918Sgibbs			 * retry command.
2363115918Sgibbs			 */
2364115918Sgibbs#ifdef AHD_DEBUG
2365115918Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2366115918Sgibbs				printf("SDTR negotiation rejected busfree.\n");
2367115918Sgibbs#endif
236897883Sgibbs			ahd_set_syncrate(ahd, &devinfo,
236997883Sgibbs					/*period*/0, /*offset*/0,
237097883Sgibbs					/*ppr_options*/0,
237197883Sgibbs					AHD_TRANS_CUR|AHD_TRANS_GOAL,
237297883Sgibbs					/*paused*/TRUE);
2373133122Sgibbs			/*
2374133122Sgibbs			 * Remove any SCBs in the waiting for selection
2375133122Sgibbs			 * queue that may also be for this target so that
2376133122Sgibbs			 * command ordering is preserved.
2377133122Sgibbs			 */
2378133122Sgibbs			ahd_freeze_devq(ahd, scb);
237997883Sgibbs			ahd_qinfifo_requeue_tail(ahd, scb);
238097883Sgibbs			printerror = 0;
238197883Sgibbs		} else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0
238297883Sgibbs			&& ahd_sent_msg(ahd, AHDMSG_1B,
238397883Sgibbs					 MSG_INITIATOR_DET_ERR, TRUE)) {
238497883Sgibbs
238597883Sgibbs#ifdef AHD_DEBUG
238697883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
238797883Sgibbs				printf("Expected IDE Busfree\n");
238897883Sgibbs#endif
238997883Sgibbs			printerror = 0;
2390107441Sscottl		} else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE)
2391107441Sscottl			&& ahd_sent_msg(ahd, AHDMSG_1B,
2392107441Sscottl					MSG_MESSAGE_REJECT, TRUE)) {
2393107441Sscottl
2394107441Sscottl#ifdef AHD_DEBUG
2395107441Sscottl			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2396107441Sscottl				printf("Expected QAS Reject Busfree\n");
2397107441Sscottl#endif
2398107441Sscottl			printerror = 0;
239997883Sgibbs		}
2400102679Sgibbs	}
240197883Sgibbs
2402102679Sgibbs	/*
2403102679Sgibbs	 * The busfree required flag is honored at the end of
2404102679Sgibbs	 * the message phases.  We check it last in case we
2405102679Sgibbs	 * had to send some other message that caused a busfree.
2406102679Sgibbs	 */
2407102679Sgibbs	if (printerror != 0
2408102679Sgibbs	 && (lastphase == P_MESGIN || lastphase == P_MESGOUT)
2409102679Sgibbs	 && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) {
241097883Sgibbs
2411102679Sgibbs		ahd_freeze_devq(ahd, scb);
2412123579Sgibbs		aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
2413123579Sgibbs		aic_freeze_scb(scb);
2414102679Sgibbs		if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) {
2415102679Sgibbs			ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
2416102679Sgibbs				       SCB_GET_CHANNEL(ahd, scb),
2417102679Sgibbs				       SCB_GET_LUN(scb), SCB_LIST_NULL,
2418102679Sgibbs				       ROLE_INITIATOR, CAM_REQ_ABORTED);
2419102679Sgibbs		} else {
242097883Sgibbs#ifdef AHD_DEBUG
2421102679Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2422102679Sgibbs				printf("PPR Negotiation Busfree.\n");
242397883Sgibbs#endif
2424102679Sgibbs			ahd_done(ahd, scb);
242597883Sgibbs		}
2426102679Sgibbs		printerror = 0;
242797883Sgibbs	}
242897883Sgibbs	if (printerror != 0) {
242997883Sgibbs		int aborted;
243097883Sgibbs
243197883Sgibbs		aborted = 0;
243297883Sgibbs		if (scb != NULL) {
243397883Sgibbs			u_int tag;
243497883Sgibbs
243597883Sgibbs			if ((scb->hscb->control & TAG_ENB) != 0)
243697883Sgibbs				tag = SCB_GET_TAG(scb);
243797883Sgibbs			else
243897883Sgibbs				tag = SCB_LIST_NULL;
243997883Sgibbs			ahd_print_path(ahd, scb);
244097883Sgibbs			aborted = ahd_abort_scbs(ahd, target, 'A',
244197883Sgibbs				       SCB_GET_LUN(scb), tag,
244297883Sgibbs				       ROLE_INITIATOR,
244397883Sgibbs				       CAM_UNEXP_BUSFREE);
244497883Sgibbs		} else {
244597883Sgibbs			/*
244697883Sgibbs			 * We had not fully identified this connection,
244797883Sgibbs			 * so we cannot abort anything.
244897883Sgibbs			 */
244997883Sgibbs			printf("%s: ", ahd_name(ahd));
245097883Sgibbs		}
245197883Sgibbs		printf("Unexpected busfree %s, %d SCBs aborted, "
245297883Sgibbs		       "PRGMCNT == 0x%x\n",
245397883Sgibbs		       ahd_lookup_phase_entry(lastphase)->phasemsg,
245497883Sgibbs		       aborted,
2455123579Sgibbs		       ahd_inw(ahd, PRGMCNT));
2456199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
245797883Sgibbs		ahd_dump_card_state(ahd);
2458133122Sgibbs		if (lastphase != P_BUSFREE)
2459133122Sgibbs			ahd_force_renegotiation(ahd, &devinfo);
246097883Sgibbs	}
246197883Sgibbs	/* Always restart the sequencer. */
246297883Sgibbs	return (1);
246397883Sgibbs}
246497883Sgibbs
2465102679Sgibbsstatic void
2466102679Sgibbsahd_handle_proto_violation(struct ahd_softc *ahd)
2467102679Sgibbs{
2468102679Sgibbs	struct	ahd_devinfo devinfo;
2469102679Sgibbs	struct	scb *scb;
2470102679Sgibbs	u_int	scbid;
2471102679Sgibbs	u_int	seq_flags;
2472102679Sgibbs	u_int	curphase;
2473102679Sgibbs	u_int	lastphase;
2474102679Sgibbs	int	found;
2475102679Sgibbs
2476102679Sgibbs	ahd_fetch_devinfo(ahd, &devinfo);
2477102679Sgibbs	scbid = ahd_get_scbptr(ahd);
2478102679Sgibbs	scb = ahd_lookup_scb(ahd, scbid);
2479102679Sgibbs	seq_flags = ahd_inb(ahd, SEQ_FLAGS);
2480102679Sgibbs	curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
2481102679Sgibbs	lastphase = ahd_inb(ahd, LASTPHASE);
2482102679Sgibbs	if ((seq_flags & NOT_IDENTIFIED) != 0) {
2483102679Sgibbs
2484102679Sgibbs		/*
2485102679Sgibbs		 * The reconnecting target either did not send an
2486102679Sgibbs		 * identify message, or did, but we didn't find an SCB
2487102679Sgibbs		 * to match.
2488102679Sgibbs		 */
2489102679Sgibbs		ahd_print_devinfo(ahd, &devinfo);
2490102679Sgibbs		printf("Target did not send an IDENTIFY message. "
2491102679Sgibbs		       "LASTPHASE = 0x%x.\n", lastphase);
2492199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2493102679Sgibbs		scb = NULL;
2494102679Sgibbs	} else if (scb == NULL) {
2495102679Sgibbs		/*
2496102679Sgibbs		 * We don't seem to have an SCB active for this
2497102679Sgibbs		 * transaction.  Print an error and reset the bus.
2498102679Sgibbs		 */
2499102679Sgibbs		ahd_print_devinfo(ahd, &devinfo);
2500102679Sgibbs		printf("No SCB found during protocol violation\n");
2501199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2502102679Sgibbs		goto proto_violation_reset;
2503102679Sgibbs	} else {
2504123579Sgibbs		aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
2505102679Sgibbs		if ((seq_flags & NO_CDB_SENT) != 0) {
2506102679Sgibbs			ahd_print_path(ahd, scb);
2507102679Sgibbs			printf("No or incomplete CDB sent to device.\n");
2508199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
2509111954Sgibbs		} else if ((ahd_inb_scbram(ahd, SCB_CONTROL)
2510111954Sgibbs			  & STATUS_RCVD) == 0) {
2511102679Sgibbs			/*
2512102679Sgibbs			 * The target never bothered to provide status to
2513102679Sgibbs			 * us prior to completing the command.  Since we don't
2514102679Sgibbs			 * know the disposition of this command, we must attempt
2515102679Sgibbs			 * to abort it.  Assert ATN and prepare to send an abort
2516102679Sgibbs			 * message.
2517102679Sgibbs			 */
2518102679Sgibbs			ahd_print_path(ahd, scb);
2519102679Sgibbs			printf("Completed command without status.\n");
2520102679Sgibbs		} else {
2521102679Sgibbs			ahd_print_path(ahd, scb);
2522102679Sgibbs			printf("Unknown protocol violation.\n");
2523199260Sattilio			AHD_UNCORRECTABLE_ERROR(ahd);
2524102679Sgibbs			ahd_dump_card_state(ahd);
2525102679Sgibbs		}
2526102679Sgibbs	}
2527107441Sscottl	if ((lastphase & ~P_DATAIN_DT) == 0
2528107441Sscottl	 || lastphase == P_COMMAND) {
2529102679Sgibbsproto_violation_reset:
2530102679Sgibbs		/*
2531102679Sgibbs		 * Target either went directly to data
2532102679Sgibbs		 * phase or didn't respond to our ATN.
2533102679Sgibbs		 * The only safe thing to do is to blow
2534102679Sgibbs		 * it away with a bus reset.
2535102679Sgibbs		 */
2536102679Sgibbs		found = ahd_reset_channel(ahd, 'A', TRUE);
2537102679Sgibbs		printf("%s: Issued Channel %c Bus Reset. "
2538102679Sgibbs		       "%d SCBs aborted\n", ahd_name(ahd), 'A', found);
2539199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2540102679Sgibbs	} else {
2541102679Sgibbs		/*
2542102679Sgibbs		 * Leave the selection hardware off in case
2543102679Sgibbs		 * this abort attempt will affect yet to
2544102679Sgibbs		 * be sent commands.
2545102679Sgibbs		 */
2546102679Sgibbs		ahd_outb(ahd, SCSISEQ0,
2547102679Sgibbs			 ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
2548102679Sgibbs		ahd_assert_atn(ahd);
2549102679Sgibbs		ahd_outb(ahd, MSG_OUT, HOST_MSG);
2550102679Sgibbs		if (scb == NULL) {
2551102679Sgibbs			ahd_print_devinfo(ahd, &devinfo);
2552102679Sgibbs			ahd->msgout_buf[0] = MSG_ABORT_TASK;
2553102679Sgibbs			ahd->msgout_len = 1;
2554102679Sgibbs			ahd->msgout_index = 0;
2555102679Sgibbs			ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2556102679Sgibbs		} else {
2557102679Sgibbs			ahd_print_path(ahd, scb);
2558102679Sgibbs			scb->flags |= SCB_ABORT;
2559102679Sgibbs		}
2560102679Sgibbs		printf("Protocol violation %s.  Attempting to abort.\n",
2561102679Sgibbs		       ahd_lookup_phase_entry(curphase)->phasemsg);
2562199260Sattilio		AHD_UNCORRECTABLE_ERROR(ahd);
2563102679Sgibbs	}
2564102679Sgibbs}
2565102679Sgibbs
256697883Sgibbs/*
256797883Sgibbs * Force renegotiation to occur the next time we initiate
256897883Sgibbs * a command to the current device.
256997883Sgibbs */
257097883Sgibbsstatic void
257197883Sgibbsahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
257297883Sgibbs{
257397883Sgibbs	struct	ahd_initiator_tinfo *targ_info;
257497883Sgibbs	struct	ahd_tmode_tstate *tstate;
257597883Sgibbs
2576107441Sscottl#ifdef AHD_DEBUG
2577107441Sscottl	if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
2578107441Sscottl		ahd_print_devinfo(ahd, devinfo);
2579107441Sscottl		printf("Forcing renegotiation\n");
2580107441Sscottl	}
2581107441Sscottl#endif
258297883Sgibbs	targ_info = ahd_fetch_transinfo(ahd,
258397883Sgibbs					devinfo->channel,
258497883Sgibbs					devinfo->our_scsiid,
258597883Sgibbs					devinfo->target,
258697883Sgibbs					&tstate);
258797883Sgibbs	ahd_update_neg_request(ahd, devinfo, tstate,
2588107441Sscottl			       targ_info, AHD_NEG_IF_NON_ASYNC);
258997883Sgibbs}
259097883Sgibbs
259197883Sgibbs#define AHD_MAX_STEPS 2000
259297883Sgibbsvoid
259397883Sgibbsahd_clear_critical_section(struct ahd_softc *ahd)
259497883Sgibbs{
259597883Sgibbs	ahd_mode_state	saved_modes;
259697883Sgibbs	int		stepping;
259797883Sgibbs	int		steps;
2598107441Sscottl	int		first_instr;
2599107441Sscottl	u_int		simode0;
2600107441Sscottl	u_int		simode1;
2601107441Sscottl	u_int		simode3;
2602107441Sscottl	u_int		lqimode0;
2603107441Sscottl	u_int		lqimode1;
2604107441Sscottl	u_int		lqomode0;
2605107441Sscottl	u_int		lqomode1;
260697883Sgibbs
260797883Sgibbs	if (ahd->num_critical_sections == 0)
260897883Sgibbs		return;
260997883Sgibbs
261097883Sgibbs	stepping = FALSE;
261197883Sgibbs	steps = 0;
2612107441Sscottl	first_instr = 0;
2613107441Sscottl	simode0 = 0;
2614107441Sscottl	simode1 = 0;
2615107441Sscottl	simode3 = 0;
2616107441Sscottl	lqimode0 = 0;
2617107441Sscottl	lqimode1 = 0;
2618107441Sscottl	lqomode0 = 0;
2619107441Sscottl	lqomode1 = 0;
262097883Sgibbs	saved_modes = ahd_save_modes(ahd);
262197883Sgibbs	for (;;) {
262297883Sgibbs		struct	cs *cs;
262397883Sgibbs		u_int	seqaddr;
262497883Sgibbs		u_int	i;
262597883Sgibbs
262697883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2627123579Sgibbs		seqaddr = ahd_inw(ahd, CURADDR);
262897883Sgibbs
262997883Sgibbs		cs = ahd->critical_sections;
263097883Sgibbs		for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
263197883Sgibbs
263297883Sgibbs			if (cs->begin < seqaddr && cs->end >= seqaddr)
263397883Sgibbs				break;
263497883Sgibbs		}
263597883Sgibbs
263697883Sgibbs		if (i == ahd->num_critical_sections)
263797883Sgibbs			break;
263897883Sgibbs
263997883Sgibbs		if (steps > AHD_MAX_STEPS) {
2640107441Sscottl			printf("%s: Infinite loop in critical section\n"
2641107441Sscottl			       "%s: First Instruction 0x%x now 0x%x\n",
2642107441Sscottl			       ahd_name(ahd), ahd_name(ahd), first_instr,
2643107441Sscottl			       seqaddr);
2644199260Sattilio			AHD_FATAL_ERROR(ahd);
264597883Sgibbs			ahd_dump_card_state(ahd);
264697883Sgibbs			panic("critical section loop");
264797883Sgibbs		}
264897883Sgibbs
264997883Sgibbs		steps++;
2650107441Sscottl#ifdef AHD_DEBUG
2651107441Sscottl		if ((ahd_debug & AHD_SHOW_MISC) != 0)
2652107441Sscottl			printf("%s: Single stepping at 0x%x\n", ahd_name(ahd),
2653107441Sscottl			       seqaddr);
2654107441Sscottl#endif
265597883Sgibbs		if (stepping == FALSE) {
265697883Sgibbs
2657107441Sscottl			first_instr = seqaddr;
2658107441Sscottl  			ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
2659107441Sscottl  			simode0 = ahd_inb(ahd, SIMODE0);
2660107441Sscottl			simode3 = ahd_inb(ahd, SIMODE3);
2661107441Sscottl			lqimode0 = ahd_inb(ahd, LQIMODE0);
2662107441Sscottl			lqimode1 = ahd_inb(ahd, LQIMODE1);
2663107441Sscottl			lqomode0 = ahd_inb(ahd, LQOMODE0);
2664107441Sscottl			lqomode1 = ahd_inb(ahd, LQOMODE1);
2665107441Sscottl			ahd_outb(ahd, SIMODE0, 0);
2666107441Sscottl			ahd_outb(ahd, SIMODE3, 0);
2667107441Sscottl			ahd_outb(ahd, LQIMODE0, 0);
2668107441Sscottl			ahd_outb(ahd, LQIMODE1, 0);
2669107441Sscottl			ahd_outb(ahd, LQOMODE0, 0);
2670107441Sscottl			ahd_outb(ahd, LQOMODE1, 0);
267197883Sgibbs			ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2672116935Sgibbs			simode1 = ahd_inb(ahd, SIMODE1);
2673116935Sgibbs			/*
2674116935Sgibbs			 * We don't clear ENBUSFREE.  Unfortunately
2675116935Sgibbs			 * we cannot re-enable busfree detection within
2676116935Sgibbs			 * the current connection, so we must leave it
2677116935Sgibbs			 * on while single stepping.
2678116935Sgibbs			 */
2679116935Sgibbs			ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE);
268097883Sgibbs			ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP);
268197883Sgibbs			stepping = TRUE;
268297883Sgibbs		}
2683107441Sscottl		ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
2684107441Sscottl		ahd_outb(ahd, CLRINT, CLRSCSIINT);
268597883Sgibbs		ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
268697883Sgibbs		ahd_outb(ahd, HCNTRL, ahd->unpause);
2687116935Sgibbs		while (!ahd_is_paused(ahd))
2688123579Sgibbs			aic_delay(200);
268997883Sgibbs		ahd_update_modes(ahd);
269097883Sgibbs	}
269197883Sgibbs	if (stepping) {
2692107441Sscottl		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
2693107441Sscottl		ahd_outb(ahd, SIMODE0, simode0);
2694107441Sscottl		ahd_outb(ahd, SIMODE3, simode3);
2695107441Sscottl		ahd_outb(ahd, LQIMODE0, lqimode0);
2696107441Sscottl		ahd_outb(ahd, LQIMODE1, lqimode1);
2697107441Sscottl		ahd_outb(ahd, LQOMODE0, lqomode0);
2698107441Sscottl		ahd_outb(ahd, LQOMODE1, lqomode1);
269997883Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
270097883Sgibbs		ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);
2701107441Sscottl  		ahd_outb(ahd, SIMODE1, simode1);
2702114623Sgibbs		/*
2703114623Sgibbs		 * SCSIINT seems to glitch occassionally when
2704114623Sgibbs		 * the interrupt masks are restored.  Clear SCSIINT
2705114623Sgibbs		 * one more time so that only persistent errors
2706114623Sgibbs		 * are seen as a real interrupt.
2707114623Sgibbs		 */
2708114623Sgibbs		ahd_outb(ahd, CLRINT, CLRSCSIINT);
270997883Sgibbs	}
271097883Sgibbs	ahd_restore_modes(ahd, saved_modes);
271197883Sgibbs}
271297883Sgibbs
271397883Sgibbs/*
271497883Sgibbs * Clear any pending interrupt status.
271597883Sgibbs */
271697883Sgibbsvoid
271797883Sgibbsahd_clear_intstat(struct ahd_softc *ahd)
271897883Sgibbs{
2719102679Sgibbs	AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
2720102679Sgibbs			 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
272197883Sgibbs	/* Clear any interrupt conditions this may have caused */
2722102679Sgibbs	ahd_outb(ahd, CLRLQIINT0, CLRLQIATNQAS|CLRLQICRCT1|CLRLQICRCT2
2723102679Sgibbs				 |CLRLQIBADLQT|CLRLQIATNLQ|CLRLQIATNCMD);
2724102679Sgibbs	ahd_outb(ahd, CLRLQIINT1, CLRLQIPHASE_LQ|CLRLQIPHASE_NLQ|CLRLIQABORT
2725102679Sgibbs				 |CLRLQICRCI_LQ|CLRLQICRCI_NLQ|CLRLQIBADLQI
2726102679Sgibbs				 |CLRLQIOVERI_LQ|CLRLQIOVERI_NLQ|CLRNONPACKREQ);
2727102679Sgibbs	ahd_outb(ahd, CLRLQOINT0, CLRLQOTARGSCBPERR|CLRLQOSTOPT2|CLRLQOATNLQ
2728102679Sgibbs				 |CLRLQOATNPKT|CLRLQOTCRC);
2729102679Sgibbs	ahd_outb(ahd, CLRLQOINT1, CLRLQOINITSCBPERR|CLRLQOSTOPI2|CLRLQOBADQAS
2730102679Sgibbs				 |CLRLQOBUSFREE|CLRLQOPHACHGINPKT);
2731104023Sgibbs	if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
2732104023Sgibbs		ahd_outb(ahd, CLRLQOINT0, 0);
2733104023Sgibbs		ahd_outb(ahd, CLRLQOINT1, 0);
2734104023Sgibbs	}
2735102679Sgibbs	ahd_outb(ahd, CLRSINT3, CLRNTRAMPERR|CLROSRAMPERR);
273697883Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
273797883Sgibbs				|CLRBUSFREE|CLRSCSIPERR|CLRREQINIT);
2738107441Sscottl	ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO
2739107441Sscottl			        |CLRIOERR|CLROVERRUN);
274097883Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
274197883Sgibbs}
274297883Sgibbs
274397883Sgibbs/**************************** Debugging Routines ******************************/
274497883Sgibbs#ifdef AHD_DEBUG
274597883Sgibbsuint32_t ahd_debug = AHD_DEBUG_OPTS;
274697883Sgibbs#endif
274797883Sgibbsvoid
274897883Sgibbsahd_print_scb(struct scb *scb)
274997883Sgibbs{
275097883Sgibbs	struct hardware_scb *hscb;
275197883Sgibbs	int i;
275297883Sgibbs
275397883Sgibbs	hscb = scb->hscb;
275497883Sgibbs	printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n",
275597883Sgibbs	       (void *)scb,
275697883Sgibbs	       hscb->control,
275797883Sgibbs	       hscb->scsiid,
275897883Sgibbs	       hscb->lun,
275997883Sgibbs	       hscb->cdb_len);
276097883Sgibbs	printf("Shared Data: ");
276197883Sgibbs	for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++)
276297883Sgibbs		printf("%#02x", hscb->shared_data.idata.cdb[i]);
276397883Sgibbs	printf("        dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n",
2764123579Sgibbs	       (uint32_t)((aic_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),
2765123579Sgibbs	       (uint32_t)(aic_le64toh(hscb->dataptr) & 0xFFFFFFFF),
2766123579Sgibbs	       aic_le32toh(hscb->datacnt),
2767123579Sgibbs	       aic_le32toh(hscb->sgptr),
276897883Sgibbs	       SCB_GET_TAG(scb));
276997883Sgibbs	ahd_dump_sglist(scb);
277097883Sgibbs}
277197883Sgibbs
277297883Sgibbsvoid
277397883Sgibbsahd_dump_sglist(struct scb *scb)
277497883Sgibbs{
277597883Sgibbs	int i;
277697883Sgibbs
277797883Sgibbs	if (scb->sg_count > 0) {
277897883Sgibbs		if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) {
277997883Sgibbs			struct ahd_dma64_seg *sg_list;
278097883Sgibbs
278197883Sgibbs			sg_list = (struct ahd_dma64_seg*)scb->sg_list;
278297883Sgibbs			for (i = 0; i < scb->sg_count; i++) {
278397883Sgibbs				uint64_t addr;
2784104023Sgibbs				uint32_t len;
278597883Sgibbs
2786123579Sgibbs				addr = aic_le64toh(sg_list[i].addr);
2787123579Sgibbs				len = aic_le32toh(sg_list[i].len);
2788104023Sgibbs				printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
278997883Sgibbs				       i,
279097883Sgibbs				       (uint32_t)((addr >> 32) & 0xFFFFFFFF),
279197883Sgibbs				       (uint32_t)(addr & 0xFFFFFFFF),
2792104023Sgibbs				       sg_list[i].len & AHD_SG_LEN_MASK,
2793104023Sgibbs				       (sg_list[i].len & AHD_DMA_LAST_SEG)
2794104023Sgibbs				     ? " Last" : "");
279597883Sgibbs			}
279697883Sgibbs		} else {
279797883Sgibbs			struct ahd_dma_seg *sg_list;
279897883Sgibbs
279997883Sgibbs			sg_list = (struct ahd_dma_seg*)scb->sg_list;
280097883Sgibbs			for (i = 0; i < scb->sg_count; i++) {
2801104023Sgibbs				uint32_t len;
2802104023Sgibbs
2803123579Sgibbs				len = aic_le32toh(sg_list[i].len);
2804104023Sgibbs				printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
280597883Sgibbs				       i,
2806116938Sgibbs				       (len & AHD_SG_HIGH_ADDR_MASK) >> 24,
2807123579Sgibbs				       aic_le32toh(sg_list[i].addr),
2808104023Sgibbs				       len & AHD_SG_LEN_MASK,
2809104023Sgibbs				       len & AHD_DMA_LAST_SEG ? " Last" : "");
281097883Sgibbs			}
281197883Sgibbs		}
281297883Sgibbs	}
281397883Sgibbs}
281497883Sgibbs
281597883Sgibbs/************************* Transfer Negotiation *******************************/
281697883Sgibbs/*
281797883Sgibbs * Allocate per target mode instance (ID we respond to as a target)
281897883Sgibbs * transfer negotiation data structures.
281997883Sgibbs */
282097883Sgibbsstatic struct ahd_tmode_tstate *
282197883Sgibbsahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel)
282297883Sgibbs{
282397883Sgibbs	struct ahd_tmode_tstate *master_tstate;
282497883Sgibbs	struct ahd_tmode_tstate *tstate;
282597883Sgibbs	int i;
282697883Sgibbs
282797883Sgibbs	master_tstate = ahd->enabled_targets[ahd->our_id];
282897883Sgibbs	if (ahd->enabled_targets[scsi_id] != NULL
282997883Sgibbs	 && ahd->enabled_targets[scsi_id] != master_tstate)
283097883Sgibbs		panic("%s: ahd_alloc_tstate - Target already allocated",
283197883Sgibbs		      ahd_name(ahd));
283297883Sgibbs	tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT);
283397883Sgibbs	if (tstate == NULL)
283497883Sgibbs		return (NULL);
283597883Sgibbs
283697883Sgibbs	/*
283797883Sgibbs	 * If we have allocated a master tstate, copy user settings from
283897883Sgibbs	 * the master tstate (taken from SRAM or the EEPROM) for this
283997883Sgibbs	 * channel, but reset our current and goal settings to async/narrow
284097883Sgibbs	 * until an initiator talks to us.
284197883Sgibbs	 */
284297883Sgibbs	if (master_tstate != NULL) {
284397883Sgibbs		memcpy(tstate, master_tstate, sizeof(*tstate));
284497883Sgibbs		memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
284597883Sgibbs		for (i = 0; i < 16; i++) {
284697883Sgibbs			memset(&tstate->transinfo[i].curr, 0,
284797883Sgibbs			      sizeof(tstate->transinfo[i].curr));
284897883Sgibbs			memset(&tstate->transinfo[i].goal, 0,
284997883Sgibbs			      sizeof(tstate->transinfo[i].goal));
285097883Sgibbs		}
285197883Sgibbs	} else
285297883Sgibbs		memset(tstate, 0, sizeof(*tstate));
285397883Sgibbs	ahd->enabled_targets[scsi_id] = tstate;
285497883Sgibbs	return (tstate);
285597883Sgibbs}
285697883Sgibbs
285797883Sgibbs#ifdef AHD_TARGET_MODE
285897883Sgibbs/*
285997883Sgibbs * Free per target mode instance (ID we respond to as a target)
286097883Sgibbs * transfer negotiation data structures.
286197883Sgibbs */
286297883Sgibbsstatic void
286397883Sgibbsahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force)
286497883Sgibbs{
286597883Sgibbs	struct ahd_tmode_tstate *tstate;
286697883Sgibbs
286797883Sgibbs	/*
286897883Sgibbs	 * Don't clean up our "master" tstate.
286997883Sgibbs	 * It has our default user settings.
287097883Sgibbs	 */
287197883Sgibbs	if (scsi_id == ahd->our_id
287297883Sgibbs	 && force == FALSE)
287397883Sgibbs		return;
287497883Sgibbs
287597883Sgibbs	tstate = ahd->enabled_targets[scsi_id];
287697883Sgibbs	if (tstate != NULL)
287797883Sgibbs		free(tstate, M_DEVBUF);
287897883Sgibbs	ahd->enabled_targets[scsi_id] = NULL;
287997883Sgibbs}
288097883Sgibbs#endif
288197883Sgibbs
288297883Sgibbs/*
288397883Sgibbs * Called when we have an active connection to a target on the bus,
288497883Sgibbs * this function finds the nearest period to the input period limited
288597883Sgibbs * by the capabilities of the bus connectivity of and sync settings for
288697883Sgibbs * the target.
288797883Sgibbs */
288897883Sgibbsvoid
288997883Sgibbsahd_devlimited_syncrate(struct ahd_softc *ahd,
289097883Sgibbs			struct ahd_initiator_tinfo *tinfo,
289197883Sgibbs			u_int *period, u_int *ppr_options, role_t role)
289297883Sgibbs{
289397883Sgibbs	struct	ahd_transinfo *transinfo;
289497883Sgibbs	u_int	maxsync;
289597883Sgibbs
289697883Sgibbs	if ((ahd_inb(ahd, SBLKCTL) & ENAB40) != 0
289797883Sgibbs	 && (ahd_inb(ahd, SSTAT2) & EXP_ACTIVE) == 0) {
289897883Sgibbs		maxsync = AHD_SYNCRATE_PACED;
289997883Sgibbs	} else {
290097883Sgibbs		maxsync = AHD_SYNCRATE_ULTRA;
290197883Sgibbs		/* Can't do DT related options on an SE bus */
290297883Sgibbs		*ppr_options &= MSG_EXT_PPR_QAS_REQ;
290397883Sgibbs	}
290497883Sgibbs	/*
290597883Sgibbs	 * Never allow a value higher than our current goal
290697883Sgibbs	 * period otherwise we may allow a target initiated
290797883Sgibbs	 * negotiation to go above the limit as set by the
290897883Sgibbs	 * user.  In the case of an initiator initiated
290997883Sgibbs	 * sync negotiation, we limit based on the user
291097883Sgibbs	 * setting.  This allows the system to still accept
291197883Sgibbs	 * incoming negotiations even if target initiated
291297883Sgibbs	 * negotiation is not performed.
291397883Sgibbs	 */
291497883Sgibbs	if (role == ROLE_TARGET)
291597883Sgibbs		transinfo = &tinfo->user;
291697883Sgibbs	else
291797883Sgibbs		transinfo = &tinfo->goal;
291897883Sgibbs	*ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN);
2919109588Sgibbs	if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) {
2920107441Sscottl		maxsync = MAX(maxsync, AHD_SYNCRATE_ULTRA2);
2921109588Sgibbs		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
2922109588Sgibbs	}
292397883Sgibbs	if (transinfo->period == 0) {
292497883Sgibbs		*period = 0;
292597883Sgibbs		*ppr_options = 0;
292697883Sgibbs	} else {
292797883Sgibbs		*period = MAX(*period, transinfo->period);
292897883Sgibbs		ahd_find_syncrate(ahd, period, ppr_options, maxsync);
292997883Sgibbs	}
293097883Sgibbs}
293197883Sgibbs
293297883Sgibbs/*
293397883Sgibbs * Look up the valid period to SCSIRATE conversion in our table.
293497883Sgibbs * Return the period and offset that should be sent to the target
293597883Sgibbs * if this was the beginning of an SDTR.
293697883Sgibbs */
293797883Sgibbsvoid
293897883Sgibbsahd_find_syncrate(struct ahd_softc *ahd, u_int *period,
293997883Sgibbs		  u_int *ppr_options, u_int maxsync)
294097883Sgibbs{
294197883Sgibbs	if (*period < maxsync)
294297883Sgibbs		*period = maxsync;
294397883Sgibbs
294497883Sgibbs	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) != 0
294597883Sgibbs	 && *period > AHD_SYNCRATE_MIN_DT)
294697883Sgibbs		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
294797883Sgibbs
294897883Sgibbs	if (*period > AHD_SYNCRATE_MIN)
294997883Sgibbs		*period = 0;
295097883Sgibbs
295197883Sgibbs	/* Honor PPR option conformance rules. */
2952107441Sscottl	if (*period > AHD_SYNCRATE_PACED)
2953107441Sscottl		*ppr_options &= ~MSG_EXT_PPR_RTI;
2954107441Sscottl
295597883Sgibbs	if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
295697883Sgibbs		*ppr_options &= (MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ);
295797883Sgibbs
295897883Sgibbs	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0)
295997883Sgibbs		*ppr_options &= MSG_EXT_PPR_QAS_REQ;
2960109588Sgibbs
2961109588Sgibbs	/* Skip all PACED only entries if IU is not available */
2962109588Sgibbs	if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0
2963109588Sgibbs	 && *period < AHD_SYNCRATE_DT)
2964109588Sgibbs		*period = AHD_SYNCRATE_DT;
2965109588Sgibbs
2966109588Sgibbs	/* Skip all DT only entries if DT is not available */
2967109588Sgibbs	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
2968109588Sgibbs	 && *period < AHD_SYNCRATE_ULTRA2)
2969109588Sgibbs		*period = AHD_SYNCRATE_ULTRA2;
297097883Sgibbs}
297197883Sgibbs
297297883Sgibbs/*
297397883Sgibbs * Truncate the given synchronous offset to a value the
297497883Sgibbs * current adapter type and syncrate are capable of.
297597883Sgibbs */
297697883Sgibbsvoid
297797883Sgibbsahd_validate_offset(struct ahd_softc *ahd,
297897883Sgibbs		    struct ahd_initiator_tinfo *tinfo,
297997883Sgibbs		    u_int period, u_int *offset, int wide,
298097883Sgibbs		    role_t role)
298197883Sgibbs{
298297883Sgibbs	u_int maxoffset;
298397883Sgibbs
298497883Sgibbs	/* Limit offset to what we can do */
298597883Sgibbs	if (period == 0)
298697883Sgibbs		maxoffset = 0;
2987107441Sscottl	else if (period <= AHD_SYNCRATE_PACED) {
2988107441Sscottl		if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
2989107441Sscottl			maxoffset = MAX_OFFSET_PACED_BUG;
2990107441Sscottl		else
2991107441Sscottl			maxoffset = MAX_OFFSET_PACED;
2992107441Sscottl	} else
2993107441Sscottl		maxoffset = MAX_OFFSET_NON_PACED;
299497883Sgibbs	*offset = MIN(*offset, maxoffset);
299597883Sgibbs	if (tinfo != NULL) {
299697883Sgibbs		if (role == ROLE_TARGET)
299797883Sgibbs			*offset = MIN(*offset, tinfo->user.offset);
299897883Sgibbs		else
299997883Sgibbs			*offset = MIN(*offset, tinfo->goal.offset);
300097883Sgibbs	}
300197883Sgibbs}
300297883Sgibbs
300397883Sgibbs/*
300497883Sgibbs * Truncate the given transfer width parameter to a value the
300597883Sgibbs * current adapter type is capable of.
300697883Sgibbs */
300797883Sgibbsvoid
300897883Sgibbsahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo,
300997883Sgibbs		   u_int *bus_width, role_t role)
301097883Sgibbs{
301197883Sgibbs	switch (*bus_width) {
301297883Sgibbs	default:
301397883Sgibbs		if (ahd->features & AHD_WIDE) {
301497883Sgibbs			/* Respond Wide */
301597883Sgibbs			*bus_width = MSG_EXT_WDTR_BUS_16_BIT;
301697883Sgibbs			break;
301797883Sgibbs		}
301897883Sgibbs		/* FALLTHROUGH */
301997883Sgibbs	case MSG_EXT_WDTR_BUS_8_BIT:
302097883Sgibbs		*bus_width = MSG_EXT_WDTR_BUS_8_BIT;
302197883Sgibbs		break;
302297883Sgibbs	}
302397883Sgibbs	if (tinfo != NULL) {
302497883Sgibbs		if (role == ROLE_TARGET)
302597883Sgibbs			*bus_width = MIN(tinfo->user.width, *bus_width);
302697883Sgibbs		else
302797883Sgibbs			*bus_width = MIN(tinfo->goal.width, *bus_width);
302897883Sgibbs	}
302997883Sgibbs}
303097883Sgibbs
303197883Sgibbs/*
303297883Sgibbs * Update the bitmask of targets for which the controller should
303397883Sgibbs * negotiate with at the next convenient oportunity.  This currently
303497883Sgibbs * means the next time we send the initial identify messages for
303597883Sgibbs * a new transaction.
303697883Sgibbs */
303797883Sgibbsint
303897883Sgibbsahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
303997883Sgibbs		       struct ahd_tmode_tstate *tstate,
3040107441Sscottl		       struct ahd_initiator_tinfo *tinfo, ahd_neg_type neg_type)
304197883Sgibbs{
304297883Sgibbs	u_int auto_negotiate_orig;
304397883Sgibbs
304497883Sgibbs	auto_negotiate_orig = tstate->auto_negotiate;
3045107441Sscottl	if (neg_type == AHD_NEG_ALWAYS) {
3046107441Sscottl		/*
3047107441Sscottl		 * Force our "current" settings to be
3048107441Sscottl		 * unknown so that unless a bus reset
3049107441Sscottl		 * occurs the need to renegotiate is
3050107441Sscottl		 * recorded persistently.
3051107441Sscottl		 */
3052109588Sgibbs		if ((ahd->features & AHD_WIDE) != 0)
3053109588Sgibbs			tinfo->curr.width = AHD_WIDTH_UNKNOWN;
3054107441Sscottl		tinfo->curr.period = AHD_PERIOD_UNKNOWN;
3055107441Sscottl		tinfo->curr.offset = AHD_OFFSET_UNKNOWN;
3056107441Sscottl	}
305797883Sgibbs	if (tinfo->curr.period != tinfo->goal.period
305897883Sgibbs	 || tinfo->curr.width != tinfo->goal.width
305997883Sgibbs	 || tinfo->curr.offset != tinfo->goal.offset
306097883Sgibbs	 || tinfo->curr.ppr_options != tinfo->goal.ppr_options
3061107441Sscottl	 || (neg_type == AHD_NEG_IF_NON_ASYNC
3062107441Sscottl	  && (tinfo->goal.offset != 0
306397883Sgibbs	   || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
306497883Sgibbs	   || tinfo->goal.ppr_options != 0)))
306597883Sgibbs		tstate->auto_negotiate |= devinfo->target_mask;
306697883Sgibbs	else
306797883Sgibbs		tstate->auto_negotiate &= ~devinfo->target_mask;
306897883Sgibbs
306997883Sgibbs	return (auto_negotiate_orig != tstate->auto_negotiate);
307097883Sgibbs}
307197883Sgibbs
307297883Sgibbs/*
307397883Sgibbs * Update the user/goal/curr tables of synchronous negotiation
307497883Sgibbs * parameters as well as, in the case of a current or active update,
307597883Sgibbs * any data structures on the host controller.  In the case of an
307697883Sgibbs * active update, the specified target is currently talking to us on
307797883Sgibbs * the bus, so the transfer parameter update must take effect
307897883Sgibbs * immediately.
307997883Sgibbs */
308097883Sgibbsvoid
308197883Sgibbsahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
308297883Sgibbs		 u_int period, u_int offset, u_int ppr_options,
308397883Sgibbs		 u_int type, int paused)
308497883Sgibbs{
308597883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
308697883Sgibbs	struct	ahd_tmode_tstate *tstate;
308797883Sgibbs	u_int	old_period;
308897883Sgibbs	u_int	old_offset;
308997883Sgibbs	u_int	old_ppr;
309097883Sgibbs	int	active;
309197883Sgibbs	int	update_needed;
309297883Sgibbs
309397883Sgibbs	active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
309497883Sgibbs	update_needed = 0;
309597883Sgibbs
309697883Sgibbs	if (period == 0 || offset == 0) {
309797883Sgibbs		period = 0;
309897883Sgibbs		offset = 0;
309997883Sgibbs	}
310097883Sgibbs
310197883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
310297883Sgibbs				    devinfo->target, &tstate);
310397883Sgibbs
310497883Sgibbs	if ((type & AHD_TRANS_USER) != 0) {
310597883Sgibbs		tinfo->user.period = period;
310697883Sgibbs		tinfo->user.offset = offset;
310797883Sgibbs		tinfo->user.ppr_options = ppr_options;
310897883Sgibbs	}
310997883Sgibbs
311097883Sgibbs	if ((type & AHD_TRANS_GOAL) != 0) {
311197883Sgibbs		tinfo->goal.period = period;
311297883Sgibbs		tinfo->goal.offset = offset;
311397883Sgibbs		tinfo->goal.ppr_options = ppr_options;
311497883Sgibbs	}
311597883Sgibbs
311697883Sgibbs	old_period = tinfo->curr.period;
311797883Sgibbs	old_offset = tinfo->curr.offset;
311897883Sgibbs	old_ppr	   = tinfo->curr.ppr_options;
311997883Sgibbs
312097883Sgibbs	if ((type & AHD_TRANS_CUR) != 0
312197883Sgibbs	 && (old_period != period
312297883Sgibbs	  || old_offset != offset
312397883Sgibbs	  || old_ppr != ppr_options)) {
312497883Sgibbs
312597883Sgibbs		update_needed++;
312697883Sgibbs
312797883Sgibbs		tinfo->curr.period = period;
312897883Sgibbs		tinfo->curr.offset = offset;
312997883Sgibbs		tinfo->curr.ppr_options = ppr_options;
313097883Sgibbs
313197883Sgibbs		ahd_send_async(ahd, devinfo->channel, devinfo->target,
313297883Sgibbs			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
313397883Sgibbs		if (bootverbose) {
313497883Sgibbs			if (offset != 0) {
3135109588Sgibbs				int options;
3136109588Sgibbs
313797883Sgibbs				printf("%s: target %d synchronous with "
3138109588Sgibbs				       "period = 0x%x, offset = 0x%x",
313997883Sgibbs				       ahd_name(ahd), devinfo->target,
3140109588Sgibbs				       period, offset);
3141109588Sgibbs				options = 0;
3142111954Sgibbs				if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
3143111954Sgibbs					printf("(RDSTRM");
3144111954Sgibbs					options++;
3145111954Sgibbs				}
3146109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
3147111954Sgibbs					printf("%s", options ? "|DT" : "(DT");
3148109588Sgibbs					options++;
3149109588Sgibbs				}
3150109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3151109588Sgibbs					printf("%s", options ? "|IU" : "(IU");
3152109588Sgibbs					options++;
3153109588Sgibbs				}
3154109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_RTI) != 0) {
3155109588Sgibbs					printf("%s", options ? "|RTI" : "(RTI");
3156109588Sgibbs					options++;
3157109588Sgibbs				}
3158109588Sgibbs				if ((ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
3159109588Sgibbs					printf("%s", options ? "|QAS" : "(QAS");
3160109588Sgibbs					options++;
3161109588Sgibbs				}
3162109588Sgibbs				if (options != 0)
3163109588Sgibbs					printf(")\n");
3164109588Sgibbs				else
3165109588Sgibbs					printf("\n");
316697883Sgibbs			} else {
316797883Sgibbs				printf("%s: target %d using "
3168109588Sgibbs				       "asynchronous transfers%s\n",
3169109588Sgibbs				       ahd_name(ahd), devinfo->target,
3170109588Sgibbs				       (ppr_options & MSG_EXT_PPR_QAS_REQ) != 0
3171109588Sgibbs				     ?  "(QAS)" : "");
317297883Sgibbs			}
317397883Sgibbs		}
317497883Sgibbs	}
317597883Sgibbs	/*
317697883Sgibbs	 * Always refresh the neg-table to handle the case of the
317797883Sgibbs	 * sequencer setting the ENATNO bit for a MK_MESSAGE request.
317897883Sgibbs	 * We will always renegotiate in that case if this is a
3179102679Sgibbs	 * packetized request.  Also manage the busfree expected flag
3180102679Sgibbs	 * from this common routine so that we catch changes due to
3181102679Sgibbs	 * WDTR or SDTR messages.
318297883Sgibbs	 */
3183102679Sgibbs	if ((type & AHD_TRANS_CUR) != 0) {
3184102679Sgibbs		if (!paused)
3185102679Sgibbs			ahd_pause(ahd);
318697883Sgibbs		ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
3187102679Sgibbs		if (!paused)
3188102679Sgibbs			ahd_unpause(ahd);
3189102679Sgibbs		if (ahd->msg_type != MSG_TYPE_NONE) {
3190102679Sgibbs			if ((old_ppr & MSG_EXT_PPR_IU_REQ)
3191102679Sgibbs			 != (ppr_options & MSG_EXT_PPR_IU_REQ)) {
3192102679Sgibbs#ifdef AHD_DEBUG
3193107441Sscottl				if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3194107441Sscottl					ahd_print_devinfo(ahd, devinfo);
3195102679Sgibbs					printf("Expecting IU Change busfree\n");
3196107441Sscottl				}
3197102679Sgibbs#endif
3198102679Sgibbs				ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
3199102679Sgibbs					       |  MSG_FLAG_IU_REQ_CHANGED;
3200102679Sgibbs			}
3201102679Sgibbs			if ((old_ppr & MSG_EXT_PPR_IU_REQ) != 0) {
3202102679Sgibbs#ifdef AHD_DEBUG
3203102679Sgibbs				if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
3204102679Sgibbs					printf("PPR with IU_REQ outstanding\n");
3205102679Sgibbs#endif
3206102679Sgibbs				ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE;
3207102679Sgibbs			}
3208102679Sgibbs		}
3209102679Sgibbs	}
321097883Sgibbs
321197883Sgibbs	update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
3212107441Sscottl						tinfo, AHD_NEG_TO_GOAL);
321397883Sgibbs
3214102679Sgibbs	if (update_needed && active)
321597883Sgibbs		ahd_update_pending_scbs(ahd);
321697883Sgibbs}
321797883Sgibbs
321897883Sgibbs/*
321997883Sgibbs * Update the user/goal/curr tables of wide negotiation
322097883Sgibbs * parameters as well as, in the case of a current or active update,
322197883Sgibbs * any data structures on the host controller.  In the case of an
322297883Sgibbs * active update, the specified target is currently talking to us on
322397883Sgibbs * the bus, so the transfer parameter update must take effect
322497883Sgibbs * immediately.
322597883Sgibbs */
322697883Sgibbsvoid
322797883Sgibbsahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
322897883Sgibbs	      u_int width, u_int type, int paused)
322997883Sgibbs{
323097883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
323197883Sgibbs	struct	ahd_tmode_tstate *tstate;
323297883Sgibbs	u_int	oldwidth;
323397883Sgibbs	int	active;
323497883Sgibbs	int	update_needed;
323597883Sgibbs
323697883Sgibbs	active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
323797883Sgibbs	update_needed = 0;
323897883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
323997883Sgibbs				    devinfo->target, &tstate);
324097883Sgibbs
324197883Sgibbs	if ((type & AHD_TRANS_USER) != 0)
324297883Sgibbs		tinfo->user.width = width;
324397883Sgibbs
324497883Sgibbs	if ((type & AHD_TRANS_GOAL) != 0)
324597883Sgibbs		tinfo->goal.width = width;
324697883Sgibbs
324797883Sgibbs	oldwidth = tinfo->curr.width;
324897883Sgibbs	if ((type & AHD_TRANS_CUR) != 0 && oldwidth != width) {
324997883Sgibbs
325097883Sgibbs		update_needed++;
325197883Sgibbs
325297883Sgibbs		tinfo->curr.width = width;
325397883Sgibbs		ahd_send_async(ahd, devinfo->channel, devinfo->target,
325497883Sgibbs			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
325597883Sgibbs		if (bootverbose) {
325697883Sgibbs			printf("%s: target %d using %dbit transfers\n",
325797883Sgibbs			       ahd_name(ahd), devinfo->target,
325897883Sgibbs			       8 * (0x01 << width));
325997883Sgibbs		}
326097883Sgibbs	}
3261102679Sgibbs
3262102679Sgibbs	if ((type & AHD_TRANS_CUR) != 0) {
3263102679Sgibbs		if (!paused)
3264102679Sgibbs			ahd_pause(ahd);
326597883Sgibbs		ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
3266102679Sgibbs		if (!paused)
3267102679Sgibbs			ahd_unpause(ahd);
3268102679Sgibbs	}
326997883Sgibbs
327097883Sgibbs	update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
3271107441Sscottl						tinfo, AHD_NEG_TO_GOAL);
3272102679Sgibbs	if (update_needed && active)
327397883Sgibbs		ahd_update_pending_scbs(ahd);
3274102679Sgibbs
327597883Sgibbs}
327697883Sgibbs
327797883Sgibbs/*
327897883Sgibbs * Update the current state of tagged queuing for a given target.
327997883Sgibbs */
328097883Sgibbsvoid
328197883Sgibbsahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
328297883Sgibbs	     ahd_queue_alg alg)
328397883Sgibbs{
3284109588Sgibbs	ahd_platform_set_tags(ahd, devinfo, alg);
3285109588Sgibbs	ahd_send_async(ahd, devinfo->channel, devinfo->target,
3286109588Sgibbs		       devinfo->lun, AC_TRANSFER_NEG, &alg);
328797883Sgibbs}
328897883Sgibbs
328997883Sgibbsstatic void
329097883Sgibbsahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
329197883Sgibbs		     struct ahd_transinfo *tinfo)
329297883Sgibbs{
329397883Sgibbs	ahd_mode_state	saved_modes;
329497883Sgibbs	u_int		period;
329597883Sgibbs	u_int		ppr_opts;
329697883Sgibbs	u_int		con_opts;
329797883Sgibbs	u_int		offset;
3298109588Sgibbs	u_int		saved_negoaddr;
3299107441Sscottl	uint8_t		iocell_opts[sizeof(ahd->iocell_opts)];
330097883Sgibbs
330197883Sgibbs	saved_modes = ahd_save_modes(ahd);
330297883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
330397883Sgibbs
3304109588Sgibbs	saved_negoaddr = ahd_inb(ahd, NEGOADDR);
330597883Sgibbs	ahd_outb(ahd, NEGOADDR, devinfo->target);
330697883Sgibbs	period = tinfo->period;
330797883Sgibbs	offset = tinfo->offset;
3308107441Sscottl	memcpy(iocell_opts, ahd->iocell_opts, sizeof(ahd->iocell_opts));
3309107441Sscottl	ppr_opts = tinfo->ppr_options & (MSG_EXT_PPR_QAS_REQ|MSG_EXT_PPR_DT_REQ
3310107441Sscottl					|MSG_EXT_PPR_IU_REQ|MSG_EXT_PPR_RTI);
3311107441Sscottl	con_opts = 0;
331297883Sgibbs	if (period == 0)
331397883Sgibbs		period = AHD_SYNCRATE_ASYNC;
331497883Sgibbs	if (period == AHD_SYNCRATE_160) {
3315107441Sscottl
3316107441Sscottl		if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
3317107441Sscottl			/*
3318107441Sscottl			 * When the SPI4 spec was finalized, PACE transfers
3319107441Sscottl			 * was not made a configurable option in the PPR
3320107441Sscottl			 * message.  Instead it is assumed to be enabled for
3321107441Sscottl			 * any syncrate faster than 80MHz.  Nevertheless,
3322107441Sscottl			 * Harpoon2A4 allows this to be configurable.
3323107441Sscottl			 *
3324107441Sscottl			 * Harpoon2A4 also assumes at most 2 data bytes per
3325107441Sscottl			 * negotiated REQ/ACK offset.  Paced transfers take
3326107441Sscottl			 * 4, so we must adjust our offset.
3327107441Sscottl			 */
3328107441Sscottl			ppr_opts |= PPROPT_PACE;
3329107441Sscottl			offset *= 2;
3330107441Sscottl
3331107441Sscottl			/*
3332107441Sscottl			 * Harpoon2A assumed that there would be a
3333107441Sscottl			 * fallback rate between 160MHz and 80Mhz,
3334107441Sscottl			 * so 7 is used as the period factor rather
3335107441Sscottl			 * than 8 for 160MHz.
3336107441Sscottl			 */
3337107441Sscottl			period = AHD_SYNCRATE_REVA_160;
3338107441Sscottl		}
3339107441Sscottl		if ((tinfo->ppr_options & MSG_EXT_PPR_PCOMP_EN) == 0)
3340107441Sscottl			iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
3341107441Sscottl			    ~AHD_PRECOMP_MASK;
3342107441Sscottl	} else {
3343107441Sscottl		/*
3344107441Sscottl		 * Precomp should be disabled for non-paced transfers.
3345107441Sscottl		 */
3346107441Sscottl		iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
3347107441Sscottl
3348107441Sscottl		if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
3349123579Sgibbs		 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
3350123579Sgibbs		 && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
3351107441Sscottl			/*
3352107441Sscottl			 * Slow down our CRC interval to be
3353123579Sgibbs			 * compatible with non-packetized
3354123579Sgibbs			 * U160 devices that can't handle a
3355123579Sgibbs			 * CRC at full speed.
3356107441Sscottl			 */
3357107441Sscottl			con_opts |= ENSLOWCRC;
3358107441Sscottl		}
3359123579Sgibbs
3360123579Sgibbs		if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
3361123579Sgibbs			/*
3362123579Sgibbs			 * On H2A4, revert to a slower slewrate
3363123579Sgibbs			 * on non-paced transfers.
3364123579Sgibbs			 */
3365123579Sgibbs			iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
3366123579Sgibbs			    ~AHD_SLEWRATE_MASK;
3367123579Sgibbs		}
336897883Sgibbs	}
336997883Sgibbs
3370107441Sscottl	ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
3371107441Sscottl	ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_PRECOMP_SLEW_INDEX]);
3372107441Sscottl	ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_AMPLITUDE);
3373107441Sscottl	ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_AMPLITUDE_INDEX]);
3374107441Sscottl
337597883Sgibbs	ahd_outb(ahd, NEGPERIOD, period);
337697883Sgibbs	ahd_outb(ahd, NEGPPROPTS, ppr_opts);
337797883Sgibbs	ahd_outb(ahd, NEGOFFSET, offset);
337897883Sgibbs
337997883Sgibbs	if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT)
338097883Sgibbs		con_opts |= WIDEXFER;
338197883Sgibbs
338297883Sgibbs	/*
338397883Sgibbs	 * During packetized transfers, the target will
338497883Sgibbs	 * give us the oportunity to send command packets
338597883Sgibbs	 * without us asserting attention.
338697883Sgibbs	 */
338797883Sgibbs	if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
338897883Sgibbs		con_opts |= ENAUTOATNO;
338997883Sgibbs	ahd_outb(ahd, NEGCONOPTS, con_opts);
3390109588Sgibbs	ahd_outb(ahd, NEGOADDR, saved_negoaddr);
339197883Sgibbs	ahd_restore_modes(ahd, saved_modes);
339297883Sgibbs}
339397883Sgibbs
339497883Sgibbs/*
3395102679Sgibbs * When the transfer settings for a connection change, setup for
3396102679Sgibbs * negotiation in pending SCBs to effect the change as quickly as
3397102679Sgibbs * possible.  We also cancel any negotiations that are scheduled
3398102679Sgibbs * for inflight SCBs that have not been started yet.
339997883Sgibbs */
340097883Sgibbsstatic void
340197883Sgibbsahd_update_pending_scbs(struct ahd_softc *ahd)
340297883Sgibbs{
340397883Sgibbs	struct		scb *pending_scb;
340497883Sgibbs	int		pending_scb_count;
340597883Sgibbs	int		paused;
340697883Sgibbs	u_int		saved_scbptr;
340797883Sgibbs	ahd_mode_state	saved_modes;
340897883Sgibbs
340997883Sgibbs	/*
341097883Sgibbs	 * Traverse the pending SCB list and ensure that all of the
3411102679Sgibbs	 * SCBs there have the proper settings.  We can only safely
3412102679Sgibbs	 * clear the negotiation required flag (setting requires the
3413102679Sgibbs	 * execution queue to be modified) and this is only possible
3414102679Sgibbs	 * if we are not already attempting to select out for this
3415102679Sgibbs	 * SCB.  For this reason, all callers only call this routine
3416102679Sgibbs	 * if we are changing the negotiation settings for the currently
3417102679Sgibbs	 * active transaction on the bus.
341897883Sgibbs	 */
341997883Sgibbs	pending_scb_count = 0;
342097883Sgibbs	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
342197883Sgibbs		struct ahd_devinfo devinfo;
342297883Sgibbs		struct ahd_initiator_tinfo *tinfo;
342397883Sgibbs		struct ahd_tmode_tstate *tstate;
342497883Sgibbs
342597883Sgibbs		ahd_scb_devinfo(ahd, &devinfo, pending_scb);
342697883Sgibbs		tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
342797883Sgibbs					    devinfo.our_scsiid,
342897883Sgibbs					    devinfo.target, &tstate);
342997883Sgibbs		if ((tstate->auto_negotiate & devinfo.target_mask) == 0
343097883Sgibbs		 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
343197883Sgibbs			pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
3432133122Sgibbs			pending_scb->hscb->control &= ~MK_MESSAGE;
343397883Sgibbs		}
343497883Sgibbs		ahd_sync_scb(ahd, pending_scb,
343597883Sgibbs			     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
343697883Sgibbs		pending_scb_count++;
343797883Sgibbs	}
343897883Sgibbs
343997883Sgibbs	if (pending_scb_count == 0)
344097883Sgibbs		return;
344197883Sgibbs
344297883Sgibbs	if (ahd_is_paused(ahd)) {
344397883Sgibbs		paused = 1;
344497883Sgibbs	} else {
344597883Sgibbs		paused = 0;
344697883Sgibbs		ahd_pause(ahd);
344797883Sgibbs	}
344897883Sgibbs
3449102679Sgibbs	/*
3450102679Sgibbs	 * Force the sequencer to reinitialize the selection for
3451102679Sgibbs	 * the command at the head of the execution queue if it
3452102679Sgibbs	 * has already been setup.  The negotiation changes may
3453129134Sgibbs	 * effect whether we select-out with ATN.  It is only
3454129134Sgibbs	 * safe to clear ENSELO when the bus is not free and no
3455129134Sgibbs	 * selection is in progres or completed.
3456102679Sgibbs	 */
345797883Sgibbs	saved_modes = ahd_save_modes(ahd);
345897883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3459129134Sgibbs	if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
3460129134Sgibbs	 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
3461129134Sgibbs		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
346297883Sgibbs	saved_scbptr = ahd_get_scbptr(ahd);
346397883Sgibbs	/* Ensure that the hscbs down on the card match the new information */
3464133122Sgibbs	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
3465133122Sgibbs		u_int	scb_tag;
346697883Sgibbs		u_int	control;
346797883Sgibbs
3468133122Sgibbs		scb_tag = SCB_GET_TAG(pending_scb);
3469116938Sgibbs		ahd_set_scbptr(ahd, scb_tag);
347097883Sgibbs		control = ahd_inb_scbram(ahd, SCB_CONTROL);
347197883Sgibbs		control &= ~MK_MESSAGE;
3472133122Sgibbs		control |= pending_scb->hscb->control & MK_MESSAGE;
347397883Sgibbs		ahd_outb(ahd, SCB_CONTROL, control);
347497883Sgibbs	}
3475104023Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
347697883Sgibbs	ahd_restore_modes(ahd, saved_modes);
347797883Sgibbs
347897883Sgibbs	if (paused == 0)
347997883Sgibbs		ahd_unpause(ahd);
348097883Sgibbs}
348197883Sgibbs
348297883Sgibbs/**************************** Pathing Information *****************************/
348397883Sgibbsstatic void
348497883Sgibbsahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
348597883Sgibbs{
348697883Sgibbs	ahd_mode_state	saved_modes;
348797883Sgibbs	u_int		saved_scsiid;
348897883Sgibbs	role_t		role;
348997883Sgibbs	int		our_id;
349097883Sgibbs
349197883Sgibbs	saved_modes = ahd_save_modes(ahd);
349297883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
349397883Sgibbs
349497883Sgibbs	if (ahd_inb(ahd, SSTAT0) & TARGET)
349597883Sgibbs		role = ROLE_TARGET;
349697883Sgibbs	else
349797883Sgibbs		role = ROLE_INITIATOR;
349897883Sgibbs
349997883Sgibbs	if (role == ROLE_TARGET
350097883Sgibbs	 && (ahd_inb(ahd, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) {
350197883Sgibbs		/* We were selected, so pull our id from TARGIDIN */
350297883Sgibbs		our_id = ahd_inb(ahd, TARGIDIN) & OID;
350397883Sgibbs	} else if (role == ROLE_TARGET)
350497883Sgibbs		our_id = ahd_inb(ahd, TOWNID);
350597883Sgibbs	else
350697883Sgibbs		our_id = ahd_inb(ahd, IOWNID);
350797883Sgibbs
350897883Sgibbs	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
350997883Sgibbs	ahd_compile_devinfo(devinfo,
351097883Sgibbs			    our_id,
351197883Sgibbs			    SCSIID_TARGET(ahd, saved_scsiid),
351297883Sgibbs			    ahd_inb(ahd, SAVED_LUN),
351397883Sgibbs			    SCSIID_CHANNEL(ahd, saved_scsiid),
351497883Sgibbs			    role);
351597883Sgibbs	ahd_restore_modes(ahd, saved_modes);
351697883Sgibbs}
351797883Sgibbs
3518107441Sscottlvoid
3519102679Sgibbsahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
3520102679Sgibbs{
3521107441Sscottl	printf("%s:%c:%d:%d: ", ahd_name(ahd), 'A',
3522102679Sgibbs	       devinfo->target, devinfo->lun);
3523102679Sgibbs}
3524102679Sgibbs
352597883Sgibbsstruct ahd_phase_table_entry*
352697883Sgibbsahd_lookup_phase_entry(int phase)
352797883Sgibbs{
352897883Sgibbs	struct ahd_phase_table_entry *entry;
352997883Sgibbs	struct ahd_phase_table_entry *last_entry;
353097883Sgibbs
353197883Sgibbs	/*
353297883Sgibbs	 * num_phases doesn't include the default entry which
353397883Sgibbs	 * will be returned if the phase doesn't match.
353497883Sgibbs	 */
353597883Sgibbs	last_entry = &ahd_phase_table[num_phases];
353697883Sgibbs	for (entry = ahd_phase_table; entry < last_entry; entry++) {
353797883Sgibbs		if (phase == entry->phase)
353897883Sgibbs			break;
353997883Sgibbs	}
354097883Sgibbs	return (entry);
354197883Sgibbs}
354297883Sgibbs
354397883Sgibbsvoid
354497883Sgibbsahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target,
354597883Sgibbs		    u_int lun, char channel, role_t role)
354697883Sgibbs{
354797883Sgibbs	devinfo->our_scsiid = our_id;
354897883Sgibbs	devinfo->target = target;
354997883Sgibbs	devinfo->lun = lun;
355097883Sgibbs	devinfo->target_offset = target;
355197883Sgibbs	devinfo->channel = channel;
355297883Sgibbs	devinfo->role = role;
355397883Sgibbs	if (channel == 'B')
355497883Sgibbs		devinfo->target_offset += 8;
355597883Sgibbs	devinfo->target_mask = (0x01 << devinfo->target_offset);
355697883Sgibbs}
355797883Sgibbs
355897883Sgibbsstatic void
355997883Sgibbsahd_scb_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
356097883Sgibbs		struct scb *scb)
356197883Sgibbs{
356297883Sgibbs	role_t	role;
356397883Sgibbs	int	our_id;
356497883Sgibbs
356597883Sgibbs	our_id = SCSIID_OUR_ID(scb->hscb->scsiid);
356697883Sgibbs	role = ROLE_INITIATOR;
356797883Sgibbs	if ((scb->hscb->control & TARGET_SCB) != 0)
356897883Sgibbs		role = ROLE_TARGET;
356997883Sgibbs	ahd_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahd, scb),
357097883Sgibbs			    SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahd, scb), role);
357197883Sgibbs}
357297883Sgibbs
357397883Sgibbs
357497883Sgibbs/************************ Message Phase Processing ****************************/
357597883Sgibbs/*
357697883Sgibbs * When an initiator transaction with the MK_MESSAGE flag either reconnects
357797883Sgibbs * or enters the initial message out phase, we are interrupted.  Fill our
357897883Sgibbs * outgoing message buffer with the appropriate message and beging handing
357997883Sgibbs * the message phase(s) manually.
358097883Sgibbs */
358197883Sgibbsstatic void
358297883Sgibbsahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
358397883Sgibbs			   struct scb *scb)
358497883Sgibbs{
358597883Sgibbs	/*
358697883Sgibbs	 * To facilitate adding multiple messages together,
358797883Sgibbs	 * each routine should increment the index and len
358897883Sgibbs	 * variables instead of setting them explicitly.
358997883Sgibbs	 */
359097883Sgibbs	ahd->msgout_index = 0;
359197883Sgibbs	ahd->msgout_len = 0;
359297883Sgibbs
359397883Sgibbs	if (ahd_currently_packetized(ahd))
359497883Sgibbs		ahd->msg_flags |= MSG_FLAG_PACKETIZED;
359597883Sgibbs
359697883Sgibbs	if (ahd->send_msg_perror
359797883Sgibbs	 && ahd_inb(ahd, MSG_OUT) == HOST_MSG) {
359897883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = ahd->send_msg_perror;
359997883Sgibbs		ahd->msgout_len++;
360097883Sgibbs		ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
3601107441Sscottl#ifdef AHD_DEBUG
3602107441Sscottl		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
3603107441Sscottl			printf("Setting up for Parity Error delivery\n");
3604107441Sscottl#endif
360597883Sgibbs		return;
360697883Sgibbs	} else if (scb == NULL) {
360797883Sgibbs		printf("%s: WARNING. No pending message for "
360897883Sgibbs		       "I_T msgin.  Issuing NO-OP\n", ahd_name(ahd));
3609199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
361097883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP;
361197883Sgibbs		ahd->msgout_len++;
361297883Sgibbs		ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
361397883Sgibbs		return;
361497883Sgibbs	}
361597883Sgibbs
361697883Sgibbs	if ((scb->flags & SCB_DEVICE_RESET) == 0
361797883Sgibbs	 && (scb->flags & SCB_PACKETIZED) == 0
361897883Sgibbs	 && ahd_inb(ahd, MSG_OUT) == MSG_IDENTIFYFLAG) {
361997883Sgibbs		u_int identify_msg;
362097883Sgibbs
362197883Sgibbs		identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb);
362297883Sgibbs		if ((scb->hscb->control & DISCENB) != 0)
362397883Sgibbs			identify_msg |= MSG_IDENTIFY_DISCFLAG;
362497883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = identify_msg;
362597883Sgibbs		ahd->msgout_len++;
362697883Sgibbs
362797883Sgibbs		if ((scb->hscb->control & TAG_ENB) != 0) {
362897883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] =
362997883Sgibbs			    scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE);
363097883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] = SCB_GET_TAG(scb);
363197883Sgibbs			ahd->msgout_len += 2;
363297883Sgibbs		}
363397883Sgibbs	}
363497883Sgibbs
363597883Sgibbs	if (scb->flags & SCB_DEVICE_RESET) {
363697883Sgibbs		ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET;
363797883Sgibbs		ahd->msgout_len++;
363897883Sgibbs		ahd_print_path(ahd, scb);
363997883Sgibbs		printf("Bus Device Reset Message Sent\n");
3640199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
364197883Sgibbs		/*
364297883Sgibbs		 * Clear our selection hardware in advance of
364397883Sgibbs		 * the busfree.  We may have an entry in the waiting
364497883Sgibbs		 * Q for this target, and we don't want to go about
364597883Sgibbs		 * selecting while we handle the busfree and blow it
364697883Sgibbs		 * away.
364797883Sgibbs		 */
364897883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
364997883Sgibbs	} else if ((scb->flags & SCB_ABORT) != 0) {
365097883Sgibbs
365197883Sgibbs		if ((scb->hscb->control & TAG_ENB) != 0) {
365297883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT_TAG;
365397883Sgibbs		} else {
365497883Sgibbs			ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT;
365597883Sgibbs		}
365697883Sgibbs		ahd->msgout_len++;
365797883Sgibbs		ahd_print_path(ahd, scb);
365897883Sgibbs		printf("Abort%s Message Sent\n",
365997883Sgibbs		       (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");
3660199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
366197883Sgibbs		/*
366297883Sgibbs		 * Clear our selection hardware in advance of
366397883Sgibbs		 * the busfree.  We may have an entry in the waiting
366497883Sgibbs		 * Q for this target, and we don't want to go about
366597883Sgibbs		 * selecting while we handle the busfree and blow it
366697883Sgibbs		 * away.
366797883Sgibbs		 */
366897883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
366997883Sgibbs	} else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
367097883Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
367197883Sgibbs		/*
367297883Sgibbs		 * Clear our selection hardware in advance of potential
367397883Sgibbs		 * PPR IU status change busfree.  We may have an entry in
367497883Sgibbs		 * the waiting Q for this target, and we don't want to go
367597883Sgibbs		 * about selecting while we handle the busfree and blow
367697883Sgibbs		 * it away.
367797883Sgibbs		 */
367897883Sgibbs		ahd_outb(ahd, SCSISEQ0, 0);
367997883Sgibbs	} else {
368097883Sgibbs		printf("ahd_intr: AWAITING_MSG for an SCB that "
368197883Sgibbs		       "does not have a waiting message\n");
368297883Sgibbs		printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid,
368397883Sgibbs		       devinfo->target_mask);
3684199260Sattilio		AHD_FATAL_ERROR(ahd);
3685109588Sgibbs		panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
368697883Sgibbs		      "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
3687116940Sgibbs		      ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
3688109588Sgibbs		      scb->flags);
368997883Sgibbs	}
369097883Sgibbs
369197883Sgibbs	/*
369297883Sgibbs	 * Clear the MK_MESSAGE flag from the SCB so we aren't
369397883Sgibbs	 * asked to send this message again.
369497883Sgibbs	 */
369597883Sgibbs	ahd_outb(ahd, SCB_CONTROL,
369697883Sgibbs		 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
369797883Sgibbs	scb->hscb->control &= ~MK_MESSAGE;
369897883Sgibbs	ahd->msgout_index = 0;
369997883Sgibbs	ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
370097883Sgibbs}
370197883Sgibbs
370297883Sgibbs/*
370397883Sgibbs * Build an appropriate transfer negotiation message for the
370497883Sgibbs * currently active target.
370597883Sgibbs */
370697883Sgibbsstatic void
370797883Sgibbsahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
370897883Sgibbs{
370997883Sgibbs	/*
371097883Sgibbs	 * We need to initiate transfer negotiations.
371197883Sgibbs	 * If our current and goal settings are identical,
371297883Sgibbs	 * we want to renegotiate due to a check condition.
371397883Sgibbs	 */
371497883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
371597883Sgibbs	struct	ahd_tmode_tstate *tstate;
371697883Sgibbs	int	dowide;
371797883Sgibbs	int	dosync;
371897883Sgibbs	int	doppr;
371997883Sgibbs	u_int	period;
372097883Sgibbs	u_int	ppr_options;
372197883Sgibbs	u_int	offset;
372297883Sgibbs
372397883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
372497883Sgibbs				    devinfo->target, &tstate);
372597883Sgibbs	/*
372697883Sgibbs	 * Filter our period based on the current connection.
372797883Sgibbs	 * If we can't perform DT transfers on this segment (not in LVD
372897883Sgibbs	 * mode for instance), then our decision to issue a PPR message
372997883Sgibbs	 * may change.
373097883Sgibbs	 */
373197883Sgibbs	period = tinfo->goal.period;
3732115918Sgibbs	offset = tinfo->goal.offset;
373397883Sgibbs	ppr_options = tinfo->goal.ppr_options;
373497883Sgibbs	/* Target initiated PPR is not allowed in the SCSI spec */
373597883Sgibbs	if (devinfo->role == ROLE_TARGET)
373697883Sgibbs		ppr_options = 0;
373797883Sgibbs	ahd_devlimited_syncrate(ahd, tinfo, &period,
373897883Sgibbs				&ppr_options, devinfo->role);
373997883Sgibbs	dowide = tinfo->curr.width != tinfo->goal.width;
3740115918Sgibbs	dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
3741107441Sscottl	/*
3742107441Sscottl	 * Only use PPR if we have options that need it, even if the device
3743107441Sscottl	 * claims to support it.  There might be an expander in the way
3744107441Sscottl	 * that doesn't.
3745107441Sscottl	 */
3746107441Sscottl	doppr = ppr_options != 0;
374797883Sgibbs
374897883Sgibbs	if (!dowide && !dosync && !doppr) {
374997883Sgibbs		dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
3750115918Sgibbs		dosync = tinfo->goal.offset != 0;
375197883Sgibbs	}
375297883Sgibbs
375397883Sgibbs	if (!dowide && !dosync && !doppr) {
3754107441Sscottl		/*
3755107441Sscottl		 * Force async with a WDTR message if we have a wide bus,
3756107441Sscottl		 * or just issue an SDTR with a 0 offset.
3757107441Sscottl		 */
3758107441Sscottl		if ((ahd->features & AHD_WIDE) != 0)
3759107441Sscottl			dowide = 1;
3760107441Sscottl		else
3761107441Sscottl			dosync = 1;
3762107441Sscottl
3763107441Sscottl		if (bootverbose) {
3764107441Sscottl			ahd_print_devinfo(ahd, devinfo);
3765107441Sscottl			printf("Ensuring async\n");
3766107441Sscottl		}
376797883Sgibbs	}
376897883Sgibbs	/* Target initiated PPR is not allowed in the SCSI spec */
376997883Sgibbs	if (devinfo->role == ROLE_TARGET)
3770107441Sscottl		doppr = 0;
377197883Sgibbs
377297883Sgibbs	/*
377397883Sgibbs	 * Both the PPR message and SDTR message require the
377497883Sgibbs	 * goal syncrate to be limited to what the target device
377597883Sgibbs	 * is capable of handling (based on whether an LVD->SE
377697883Sgibbs	 * expander is on the bus), so combine these two cases.
377797883Sgibbs	 * Regardless, guarantee that if we are using WDTR and SDTR
377897883Sgibbs	 * messages that WDTR comes first.
377997883Sgibbs	 */
3780107441Sscottl	if (doppr || (dosync && !dowide)) {
378197883Sgibbs
378297883Sgibbs		offset = tinfo->goal.offset;
378397883Sgibbs		ahd_validate_offset(ahd, tinfo, period, &offset,
3784107441Sscottl				    doppr ? tinfo->goal.width
3785107441Sscottl					  : tinfo->curr.width,
378697883Sgibbs				    devinfo->role);
3787107441Sscottl		if (doppr) {
378897883Sgibbs			ahd_construct_ppr(ahd, devinfo, period, offset,
378997883Sgibbs					  tinfo->goal.width, ppr_options);
379097883Sgibbs		} else {
379197883Sgibbs			ahd_construct_sdtr(ahd, devinfo, period, offset);
379297883Sgibbs		}
379397883Sgibbs	} else {
379497883Sgibbs		ahd_construct_wdtr(ahd, devinfo, tinfo->goal.width);
379597883Sgibbs	}
379697883Sgibbs}
379797883Sgibbs
379897883Sgibbs/*
379997883Sgibbs * Build a synchronous negotiation message in our message
380097883Sgibbs * buffer based on the input parameters.
380197883Sgibbs */
380297883Sgibbsstatic void
380397883Sgibbsahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
380497883Sgibbs		   u_int period, u_int offset)
380597883Sgibbs{
3806107441Sscottl	if (offset == 0)
3807107441Sscottl		period = AHD_ASYNC_XFER_PERIOD;
380897883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
380997883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN;
381097883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR;
381197883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = period;
381297883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = offset;
381397883Sgibbs	ahd->msgout_len += 5;
381497883Sgibbs	if (bootverbose) {
381597883Sgibbs		printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",
381697883Sgibbs		       ahd_name(ahd), devinfo->channel, devinfo->target,
381797883Sgibbs		       devinfo->lun, period, offset);
381897883Sgibbs	}
381997883Sgibbs}
382097883Sgibbs
382197883Sgibbs/*
382297883Sgibbs * Build a wide negotiateion message in our message
382397883Sgibbs * buffer based on the input parameters.
382497883Sgibbs */
382597883Sgibbsstatic void
382697883Sgibbsahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
382797883Sgibbs		   u_int bus_width)
382897883Sgibbs{
382997883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
383097883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN;
383197883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR;
383297883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = bus_width;
383397883Sgibbs	ahd->msgout_len += 4;
383497883Sgibbs	if (bootverbose) {
383597883Sgibbs		printf("(%s:%c:%d:%d): Sending WDTR %x\n",
383697883Sgibbs		       ahd_name(ahd), devinfo->channel, devinfo->target,
383797883Sgibbs		       devinfo->lun, bus_width);
383897883Sgibbs	}
383997883Sgibbs}
384097883Sgibbs
384197883Sgibbs/*
384297883Sgibbs * Build a parallel protocol request message in our message
384397883Sgibbs * buffer based on the input parameters.
384497883Sgibbs */
384597883Sgibbsstatic void
384697883Sgibbsahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
384797883Sgibbs		  u_int period, u_int offset, u_int bus_width,
384897883Sgibbs		  u_int ppr_options)
384997883Sgibbs{
385097883Sgibbs	/*
385197883Sgibbs	 * Always request precompensation from
385297883Sgibbs	 * the other target if we are running
385397883Sgibbs	 * at paced syncrates.
385497883Sgibbs	 */
385597883Sgibbs	if (period <= AHD_SYNCRATE_PACED)
385697883Sgibbs		ppr_options |= MSG_EXT_PPR_PCOMP_EN;
3857107441Sscottl	if (offset == 0)
3858107441Sscottl		period = AHD_ASYNC_XFER_PERIOD;
385997883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
386097883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN;
386197883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR;
386297883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = period;
386397883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = 0;
386497883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = offset;
386597883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = bus_width;
386697883Sgibbs	ahd->msgout_buf[ahd->msgout_index++] = ppr_options;
386797883Sgibbs	ahd->msgout_len += 8;
386897883Sgibbs	if (bootverbose) {
386997883Sgibbs		printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "
387097883Sgibbs		       "offset %x, ppr_options %x\n", ahd_name(ahd),
387197883Sgibbs		       devinfo->channel, devinfo->target, devinfo->lun,
387297883Sgibbs		       bus_width, period, offset, ppr_options);
387397883Sgibbs	}
387497883Sgibbs}
387597883Sgibbs
387697883Sgibbs/*
387797883Sgibbs * Clear any active message state.
387897883Sgibbs */
387997883Sgibbsstatic void
388097883Sgibbsahd_clear_msg_state(struct ahd_softc *ahd)
388197883Sgibbs{
388297883Sgibbs	ahd_mode_state saved_modes;
388397883Sgibbs
388497883Sgibbs	saved_modes = ahd_save_modes(ahd);
388597883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
388697883Sgibbs	ahd->send_msg_perror = 0;
388797883Sgibbs	ahd->msg_flags = MSG_FLAG_NONE;
388897883Sgibbs	ahd->msgout_len = 0;
388997883Sgibbs	ahd->msgin_index = 0;
389097883Sgibbs	ahd->msg_type = MSG_TYPE_NONE;
389197883Sgibbs	if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
389297883Sgibbs		/*
389397883Sgibbs		 * The target didn't care to respond to our
389497883Sgibbs		 * message request, so clear ATN.
389597883Sgibbs		 */
389697883Sgibbs		ahd_outb(ahd, CLRSINT1, CLRATNO);
389797883Sgibbs	}
389897883Sgibbs	ahd_outb(ahd, MSG_OUT, MSG_NOOP);
389997883Sgibbs	ahd_outb(ahd, SEQ_FLAGS2,
390097883Sgibbs		 ahd_inb(ahd, SEQ_FLAGS2) & ~TARGET_MSG_PENDING);
390197883Sgibbs	ahd_restore_modes(ahd, saved_modes);
390297883Sgibbs}
390397883Sgibbs
390497883Sgibbs/*
390597883Sgibbs * Manual message loop handler.
390697883Sgibbs */
390797883Sgibbsstatic void
390897883Sgibbsahd_handle_message_phase(struct ahd_softc *ahd)
390997883Sgibbs{
391097883Sgibbs	struct	ahd_devinfo devinfo;
391197883Sgibbs	u_int	bus_phase;
391297883Sgibbs	int	end_session;
391397883Sgibbs
391497883Sgibbs	ahd_fetch_devinfo(ahd, &devinfo);
391597883Sgibbs	end_session = FALSE;
391697883Sgibbs	bus_phase = ahd_inb(ahd, LASTPHASE);
391797883Sgibbs
391897883Sgibbs	if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) {
391997883Sgibbs		printf("LQIRETRY for LQIPHASE_OUTPKT\n");
392097883Sgibbs		ahd_outb(ahd, LQCTL2, LQIRETRY);
392197883Sgibbs	}
392297883Sgibbsreswitch:
392397883Sgibbs	switch (ahd->msg_type) {
392497883Sgibbs	case MSG_TYPE_INITIATOR_MSGOUT:
392597883Sgibbs	{
392697883Sgibbs		int lastbyte;
392797883Sgibbs		int phasemis;
392897883Sgibbs		int msgdone;
392997883Sgibbs
393097883Sgibbs		if (ahd->msgout_len == 0 && ahd->send_msg_perror == 0)
393197883Sgibbs			panic("HOST_MSG_LOOP interrupt with no active message");
393297883Sgibbs
393397883Sgibbs#ifdef AHD_DEBUG
3934102679Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3935102679Sgibbs			ahd_print_devinfo(ahd, &devinfo);
3936102679Sgibbs			printf("INITIATOR_MSG_OUT");
3937102679Sgibbs		}
393897883Sgibbs#endif
393997883Sgibbs		phasemis = bus_phase != P_MESGOUT;
394097883Sgibbs		if (phasemis) {
394197883Sgibbs#ifdef AHD_DEBUG
394297883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
3943102679Sgibbs				printf(" PHASEMIS %s\n",
394497883Sgibbs				       ahd_lookup_phase_entry(bus_phase)
394597883Sgibbs							     ->phasemsg);
394697883Sgibbs			}
394797883Sgibbs#endif
394897883Sgibbs			if (bus_phase == P_MESGIN) {
394997883Sgibbs				/*
395097883Sgibbs				 * Change gears and see if
395197883Sgibbs				 * this messages is of interest to
395297883Sgibbs				 * us or should be passed back to
395397883Sgibbs				 * the sequencer.
395497883Sgibbs				 */
395597883Sgibbs				ahd_outb(ahd, CLRSINT1, CLRATNO);
395697883Sgibbs				ahd->send_msg_perror = 0;
395797883Sgibbs				ahd->msg_type = MSG_TYPE_INITIATOR_MSGIN;
395897883Sgibbs				ahd->msgin_index = 0;
395997883Sgibbs				goto reswitch;
396097883Sgibbs			}
396197883Sgibbs			end_session = TRUE;
396297883Sgibbs			break;
396397883Sgibbs		}
396497883Sgibbs
396597883Sgibbs		if (ahd->send_msg_perror) {
396697883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRATNO);
396797883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRREQINIT);
396897883Sgibbs#ifdef AHD_DEBUG
396997883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
397097883Sgibbs				printf(" byte 0x%x\n", ahd->send_msg_perror);
397197883Sgibbs#endif
397297883Sgibbs			/*
397397883Sgibbs			 * If we are notifying the target of a CRC error
397497883Sgibbs			 * during packetized operations, the target is
397597883Sgibbs			 * within its rights to acknowledge our message
397697883Sgibbs			 * with a busfree.
397797883Sgibbs			 */
397897883Sgibbs			if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0
397997883Sgibbs			 && ahd->send_msg_perror == MSG_INITIATOR_DET_ERR)
398097883Sgibbs				ahd->msg_flags |= MSG_FLAG_EXPECT_IDE_BUSFREE;
398197883Sgibbs
398297883Sgibbs			ahd_outb(ahd, RETURN_2, ahd->send_msg_perror);
398397883Sgibbs			ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
398497883Sgibbs			break;
398597883Sgibbs		}
398697883Sgibbs
398797883Sgibbs		msgdone	= ahd->msgout_index == ahd->msgout_len;
398897883Sgibbs		if (msgdone) {
398997883Sgibbs			/*
399097883Sgibbs			 * The target has requested a retry.
399197883Sgibbs			 * Re-assert ATN, reset our message index to
399297883Sgibbs			 * 0, and try again.
399397883Sgibbs			 */
399497883Sgibbs			ahd->msgout_index = 0;
399597883Sgibbs			ahd_assert_atn(ahd);
399697883Sgibbs		}
399797883Sgibbs
399897883Sgibbs		lastbyte = ahd->msgout_index == (ahd->msgout_len - 1);
399997883Sgibbs		if (lastbyte) {
400097883Sgibbs			/* Last byte is signified by dropping ATN */
400197883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRATNO);
400297883Sgibbs		}
400397883Sgibbs
400497883Sgibbs		/*
400597883Sgibbs		 * Clear our interrupt status and present
400697883Sgibbs		 * the next byte on the bus.
400797883Sgibbs		 */
400897883Sgibbs		ahd_outb(ahd, CLRSINT1, CLRREQINIT);
400997883Sgibbs#ifdef AHD_DEBUG
401097883Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
401197883Sgibbs			printf(" byte 0x%x\n",
401297883Sgibbs			       ahd->msgout_buf[ahd->msgout_index]);
401397883Sgibbs#endif
401497883Sgibbs		ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]);
401597883Sgibbs		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
401697883Sgibbs		break;
401797883Sgibbs	}
401897883Sgibbs	case MSG_TYPE_INITIATOR_MSGIN:
401997883Sgibbs	{
402097883Sgibbs		int phasemis;
402197883Sgibbs		int message_done;
402297883Sgibbs
402397883Sgibbs#ifdef AHD_DEBUG
4024102679Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
4025102679Sgibbs			ahd_print_devinfo(ahd, &devinfo);
4026102679Sgibbs			printf("INITIATOR_MSG_IN");
4027102679Sgibbs		}
402897883Sgibbs#endif
402997883Sgibbs		phasemis = bus_phase != P_MESGIN;
403097883Sgibbs		if (phasemis) {
403197883Sgibbs#ifdef AHD_DEBUG
403297883Sgibbs			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
403397883Sgibbs				printf(" PHASEMIS %s\n",
403497883Sgibbs				       ahd_lookup_phase_entry(bus_phase)
403597883Sgibbs							     ->phasemsg);
403697883Sgibbs			}
403797883Sgibbs#endif
403897883Sgibbs			ahd->msgin_index = 0;
403997883Sgibbs			if (bus_phase == P_MESGOUT
404097883Sgibbs			 && (ahd->send_msg_perror != 0
404197883Sgibbs			  || (ahd->msgout_len != 0
404297883Sgibbs			   && ahd->msgout_index == 0))) {
404397883Sgibbs				ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
404497883Sgibbs				goto reswitch;
404597883Sgibbs			}
404697883Sgibbs			end_session = TRUE;
404797883Sgibbs			break;
404897883Sgibbs		}
404997883Sgibbs
405097883Sgibbs		/* Pull the byte in without acking it */
405197883Sgibbs		ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS);
405297883Sgibbs#ifdef AHD_DEBUG
405397883Sgibbs		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
405497883Sgibbs			printf(" byte 0x%x\n",
405597883Sgibbs			       ahd->msgin_buf[ahd->msgin_index]);
405697883Sgibbs#endif
405797883Sgibbs
405897883Sgibbs		message_done = ahd_parse_msg(ahd, &devinfo);
405997883Sgibbs
406097883Sgibbs		if (message_done) {
406197883Sgibbs			/*
406297883Sgibbs			 * Clear our incoming message buffer in case there
406397883Sgibbs			 * is another message following this one.
406497883Sgibbs			 */
406597883Sgibbs			ahd->msgin_index = 0;
406697883Sgibbs
406797883Sgibbs			/*
406897883Sgibbs			 * If this message illicited a response,
406997883Sgibbs			 * assert ATN so the target takes us to the
407097883Sgibbs			 * message out phase.
407197883Sgibbs			 */
4072109588Sgibbs			if (ahd->msgout_len != 0) {
4073109588Sgibbs#ifdef AHD_DEBUG
4074109588Sgibbs				if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
4075109588Sgibbs					ahd_print_devinfo(ahd, &devinfo);
4076109588Sgibbs					printf("Asserting ATN for response\n");
4077109588Sgibbs				}
4078109588Sgibbs#endif
407997883Sgibbs				ahd_assert_atn(ahd);
4080109588Sgibbs			}
408197883Sgibbs		} else
408297883Sgibbs			ahd->msgin_index++;
408397883Sgibbs
408497883Sgibbs		if (message_done == MSGLOOP_TERMINATED) {
408597883Sgibbs			end_session = TRUE;
408697883Sgibbs		} else {
408797883Sgibbs			/* Ack the byte */
408897883Sgibbs			ahd_outb(ahd, CLRSINT1, CLRREQINIT);
408997883Sgibbs			ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_READ);
409097883Sgibbs		}
409197883Sgibbs		break;
409297883Sgibbs	}
409397883Sgibbs	case MSG_TYPE_TARGET_MSGIN:
409497883Sgibbs	{
409597883Sgibbs		int msgdone;
409697883Sgibbs		int msgout_request;
409797883Sgibbs
409897883Sgibbs		/*
409997883Sgibbs		 * By default, the message loop will continue.
410097883Sgibbs		 */
410197883Sgibbs		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
410297883Sgibbs
410397883Sgibbs		if (ahd->msgout_len == 0)
410497883Sgibbs			panic("Target MSGIN with no active message");
410597883Sgibbs
410697883Sgibbs		/*
410797883Sgibbs		 * If we interrupted a mesgout session, the initiator
410897883Sgibbs		 * will not know this until our first REQ.  So, we
410997883Sgibbs		 * only honor mesgout requests after we've sent our
411097883Sgibbs		 * first byte.
411197883Sgibbs		 */
411297883Sgibbs		if ((ahd_inb(ahd, SCSISIGI) & ATNI) != 0
411397883Sgibbs		 && ahd->msgout_index > 0)
411497883Sgibbs			msgout_request = TRUE;
411597883Sgibbs		else
411697883Sgibbs			msgout_request = FALSE;
411797883Sgibbs
411897883Sgibbs		if (msgout_request) {
411997883Sgibbs
412097883Sgibbs			/*
412197883Sgibbs			 * Change gears and see if
412297883Sgibbs			 * this messages is of interest to
412397883Sgibbs			 * us or should be passed back to
412497883Sgibbs			 * the sequencer.
412597883Sgibbs			 */
412697883Sgibbs			ahd->msg_type = MSG_TYPE_TARGET_MSGOUT;
412797883Sgibbs			ahd_outb(ahd, SCSISIGO, P_MESGOUT | BSYO);
412897883Sgibbs			ahd->msgin_index = 0;
412997883Sgibbs			/* Dummy read to REQ for first byte */
413097883Sgibbs			ahd_inb(ahd, SCSIDAT);
413197883Sgibbs			ahd_outb(ahd, SXFRCTL0,
413297883Sgibbs				 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
413397883Sgibbs			break;
413497883Sgibbs		}
413597883Sgibbs
413697883Sgibbs		msgdone = ahd->msgout_index == ahd->msgout_len;
413797883Sgibbs		if (msgdone) {
413897883Sgibbs			ahd_outb(ahd, SXFRCTL0,
413997883Sgibbs				 ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
414097883Sgibbs			end_session = TRUE;
414197883Sgibbs			break;
414297883Sgibbs		}
414397883Sgibbs
414497883Sgibbs		/*
414597883Sgibbs		 * Present the next byte on the bus.
414697883Sgibbs		 */
414797883Sgibbs		ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) | SPIOEN);
414897883Sgibbs		ahd_outb(ahd, SCSIDAT, ahd->msgout_buf[ahd->msgout_index++]);
414997883Sgibbs		break;
415097883Sgibbs	}
415197883Sgibbs	case MSG_TYPE_TARGET_MSGOUT:
415297883Sgibbs	{
415397883Sgibbs		int lastbyte;
415497883Sgibbs		int msgdone;
415597883Sgibbs
415697883Sgibbs		/*
415797883Sgibbs		 * By default, the message loop will continue.
415897883Sgibbs		 */
415997883Sgibbs		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
416097883Sgibbs
416197883Sgibbs		/*
416297883Sgibbs		 * The initiator signals that this is
416397883Sgibbs		 * the last byte by dropping ATN.
416497883Sgibbs		 */
416597883Sgibbs		lastbyte = (ahd_inb(ahd, SCSISIGI) & ATNI) == 0;
416697883Sgibbs
416797883Sgibbs		/*
416897883Sgibbs		 * Read the latched byte, but turn off SPIOEN first
416997883Sgibbs		 * so that we don't inadvertently cause a REQ for the
417097883Sgibbs		 * next byte.
417197883Sgibbs		 */
417297883Sgibbs		ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
417397883Sgibbs		ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIDAT);
417497883Sgibbs		msgdone = ahd_parse_msg(ahd, &devinfo);
417597883Sgibbs		if (msgdone == MSGLOOP_TERMINATED) {
417697883Sgibbs			/*
417797883Sgibbs			 * The message is *really* done in that it caused
417897883Sgibbs			 * us to go to bus free.  The sequencer has already
417997883Sgibbs			 * been reset at this point, so pull the ejection
418097883Sgibbs			 * handle.
418197883Sgibbs			 */
418297883Sgibbs			return;
418397883Sgibbs		}
418497883Sgibbs
418597883Sgibbs		ahd->msgin_index++;
418697883Sgibbs
418797883Sgibbs		/*
418897883Sgibbs		 * XXX Read spec about initiator dropping ATN too soon
418997883Sgibbs		 *     and use msgdone to detect it.
419097883Sgibbs		 */
419197883Sgibbs		if (msgdone == MSGLOOP_MSGCOMPLETE) {
419297883Sgibbs			ahd->msgin_index = 0;
419397883Sgibbs
419497883Sgibbs			/*
419597883Sgibbs			 * If this message illicited a response, transition
419697883Sgibbs			 * to the Message in phase and send it.
419797883Sgibbs			 */
419897883Sgibbs			if (ahd->msgout_len != 0) {
419997883Sgibbs				ahd_outb(ahd, SCSISIGO, P_MESGIN | BSYO);
420097883Sgibbs				ahd_outb(ahd, SXFRCTL0,
420197883Sgibbs					 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
420297883Sgibbs				ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
420397883Sgibbs				ahd->msgin_index = 0;
420497883Sgibbs				break;
420597883Sgibbs			}
420697883Sgibbs		}
420797883Sgibbs
420897883Sgibbs		if (lastbyte)
420997883Sgibbs			end_session = TRUE;
421097883Sgibbs		else {
421197883Sgibbs			/* Ask for the next byte. */
421297883Sgibbs			ahd_outb(ahd, SXFRCTL0,
421397883Sgibbs				 ahd_inb(ahd, SXFRCTL0) | SPIOEN);
421497883Sgibbs		}
421597883Sgibbs
421697883Sgibbs		break;
421797883Sgibbs	}
421897883Sgibbs	default:
421997883Sgibbs		panic("Unknown REQINIT message type");
422097883Sgibbs	}
422197883Sgibbs
422297883Sgibbs	if (end_session) {
422397883Sgibbs		if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) {
422497883Sgibbs			printf("%s: Returning to Idle Loop\n",
422597883Sgibbs			       ahd_name(ahd));
4226116935Sgibbs			ahd_clear_msg_state(ahd);
4227116935Sgibbs
4228116935Sgibbs			/*
4229116935Sgibbs			 * Perform the equivalent of a clear_target_state.
4230116935Sgibbs			 */
423197883Sgibbs			ahd_outb(ahd, LASTPHASE, P_BUSFREE);
4232116935Sgibbs			ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT);
423397883Sgibbs			ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
423497883Sgibbs		} else {
423597883Sgibbs			ahd_clear_msg_state(ahd);
423697883Sgibbs			ahd_outb(ahd, RETURN_1, EXIT_MSG_LOOP);
423797883Sgibbs		}
423897883Sgibbs	}
423997883Sgibbs}
424097883Sgibbs
424197883Sgibbs/*
424297883Sgibbs * See if we sent a particular extended message to the target.
424397883Sgibbs * If "full" is true, return true only if the target saw the full
424497883Sgibbs * message.  If "full" is false, return true if the target saw at
424597883Sgibbs * least the first byte of the message.
424697883Sgibbs */
424797883Sgibbsstatic int
424897883Sgibbsahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, u_int msgval, int full)
424997883Sgibbs{
425097883Sgibbs	int found;
425197883Sgibbs	u_int index;
425297883Sgibbs
425397883Sgibbs	found = FALSE;
425497883Sgibbs	index = 0;
425597883Sgibbs
425697883Sgibbs	while (index < ahd->msgout_len) {
425797883Sgibbs		if (ahd->msgout_buf[index] == MSG_EXTENDED) {
425897883Sgibbs			u_int end_index;
425997883Sgibbs
426097883Sgibbs			end_index = index + 1 + ahd->msgout_buf[index + 1];
426197883Sgibbs			if (ahd->msgout_buf[index+2] == msgval
426297883Sgibbs			 && type == AHDMSG_EXT) {
426397883Sgibbs
426497883Sgibbs				if (full) {
426597883Sgibbs					if (ahd->msgout_index > end_index)
426697883Sgibbs						found = TRUE;
426797883Sgibbs				} else if (ahd->msgout_index > index)
426897883Sgibbs					found = TRUE;
426997883Sgibbs			}
427097883Sgibbs			index = end_index;
427197883Sgibbs		} else if (ahd->msgout_buf[index] >= MSG_SIMPLE_TASK
427297883Sgibbs			&& ahd->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
427397883Sgibbs
427497883Sgibbs			/* Skip tag type and tag id or residue param*/
427597883Sgibbs			index += 2;
427697883Sgibbs		} else {
427797883Sgibbs			/* Single byte message */
427897883Sgibbs			if (type == AHDMSG_1B
4279109588Sgibbs			 && ahd->msgout_index > index
4280109588Sgibbs			 && (ahd->msgout_buf[index] == msgval
4281109588Sgibbs			  || ((ahd->msgout_buf[index] & MSG_IDENTIFYFLAG) != 0
4282109588Sgibbs			   && msgval == MSG_IDENTIFYFLAG)))
428397883Sgibbs				found = TRUE;
428497883Sgibbs			index++;
428597883Sgibbs		}
428697883Sgibbs
428797883Sgibbs		if (found)
428897883Sgibbs			break;
428997883Sgibbs	}
429097883Sgibbs	return (found);
429197883Sgibbs}
429297883Sgibbs
429397883Sgibbs/*
429497883Sgibbs * Wait for a complete incoming message, parse it, and respond accordingly.
429597883Sgibbs */
429697883Sgibbsstatic int
429797883Sgibbsahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
429897883Sgibbs{
429997883Sgibbs	struct	ahd_initiator_tinfo *tinfo;
430097883Sgibbs	struct	ahd_tmode_tstate *tstate;
430197883Sgibbs	int	reject;
430297883Sgibbs	int	done;
430397883Sgibbs	int	response;
430497883Sgibbs
430597883Sgibbs	done = MSGLOOP_IN_PROG;
430697883Sgibbs	response = FALSE;
430797883Sgibbs	reject = FALSE;
430897883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
430997883Sgibbs				    devinfo->target, &tstate);
431097883Sgibbs
431197883Sgibbs	/*
4312114623Sgibbs	 * Parse as much of the message as is available,
431397883Sgibbs	 * rejecting it if we don't support it.  When
4314114623Sgibbs	 * the entire message is available and has been
431597883Sgibbs	 * handled, return MSGLOOP_MSGCOMPLETE, indicating
431697883Sgibbs	 * that we have parsed an entire message.
431797883Sgibbs	 *
431897883Sgibbs	 * In the case of extended messages, we accept the length
431997883Sgibbs	 * byte outright and perform more checking once we know the
432097883Sgibbs	 * extended message type.
432197883Sgibbs	 */
432297883Sgibbs	switch (ahd->msgin_buf[0]) {
432397883Sgibbs	case MSG_DISCONNECT:
432497883Sgibbs	case MSG_SAVEDATAPOINTER:
432597883Sgibbs	case MSG_CMDCOMPLETE:
432697883Sgibbs	case MSG_RESTOREPOINTERS:
432797883Sgibbs	case MSG_IGN_WIDE_RESIDUE:
432897883Sgibbs		/*
432997883Sgibbs		 * End our message loop as these are messages
433097883Sgibbs		 * the sequencer handles on its own.
433197883Sgibbs		 */
433297883Sgibbs		done = MSGLOOP_TERMINATED;
433397883Sgibbs		break;
433497883Sgibbs	case MSG_MESSAGE_REJECT:
433597883Sgibbs		response = ahd_handle_msg_reject(ahd, devinfo);
433697883Sgibbs		/* FALLTHROUGH */
433797883Sgibbs	case MSG_NOOP:
433897883Sgibbs		done = MSGLOOP_MSGCOMPLETE;
433997883Sgibbs		break;
434097883Sgibbs	case MSG_EXTENDED:
434197883Sgibbs	{
434297883Sgibbs		/* Wait for enough of the message to begin validation */
434397883Sgibbs		if (ahd->msgin_index < 2)
434497883Sgibbs			break;
434597883Sgibbs		switch (ahd->msgin_buf[2]) {
434697883Sgibbs		case MSG_EXT_SDTR:
434797883Sgibbs		{
434897883Sgibbs			u_int	 period;
434997883Sgibbs			u_int	 ppr_options;
435097883Sgibbs			u_int	 offset;
435197883Sgibbs			u_int	 saved_offset;
435297883Sgibbs
435397883Sgibbs			if (ahd->msgin_buf[1] != MSG_EXT_SDTR_LEN) {
435497883Sgibbs				reject = TRUE;
435597883Sgibbs				break;
435697883Sgibbs			}
435797883Sgibbs
435897883Sgibbs			/*
435997883Sgibbs			 * Wait until we have both args before validating
436097883Sgibbs			 * and acting on this message.
436197883Sgibbs			 *
436297883Sgibbs			 * Add one to MSG_EXT_SDTR_LEN to account for
436397883Sgibbs			 * the extended message preamble.
436497883Sgibbs			 */
436597883Sgibbs			if (ahd->msgin_index < (MSG_EXT_SDTR_LEN + 1))
436697883Sgibbs				break;
436797883Sgibbs
436897883Sgibbs			period = ahd->msgin_buf[3];
436997883Sgibbs			ppr_options = 0;
437097883Sgibbs			saved_offset = offset = ahd->msgin_buf[4];
437197883Sgibbs			ahd_devlimited_syncrate(ahd, tinfo, &period,
437297883Sgibbs						&ppr_options, devinfo->role);
437397883Sgibbs			ahd_validate_offset(ahd, tinfo, period, &offset,
437497883Sgibbs					    tinfo->curr.width, devinfo->role);
437597883Sgibbs			if (bootverbose) {
437697883Sgibbs				printf("(%s:%c:%d:%d): Received "
437797883Sgibbs				       "SDTR period %x, offset %x\n\t"
437897883Sgibbs				       "Filtered to period %x, offset %x\n",
437997883Sgibbs				       ahd_name(ahd), devinfo->channel,
438097883Sgibbs				       devinfo->target, devinfo->lun,
438197883Sgibbs				       ahd->msgin_buf[3], saved_offset,
438297883Sgibbs				       period, offset);
438397883Sgibbs			}
438497883Sgibbs			ahd_set_syncrate(ahd, devinfo, period,
438597883Sgibbs					 offset, ppr_options,
438697883Sgibbs					 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
438797883Sgibbs					 /*paused*/TRUE);
438897883Sgibbs
438997883Sgibbs			/*
439097883Sgibbs			 * See if we initiated Sync Negotiation
439197883Sgibbs			 * and didn't have to fall down to async
439297883Sgibbs			 * transfers.
439397883Sgibbs			 */
439497883Sgibbs			if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, TRUE)) {
439597883Sgibbs				/* We started it */
439697883Sgibbs				if (saved_offset != offset) {
439797883Sgibbs					/* Went too low - force async */
439897883Sgibbs					reject = TRUE;
439997883Sgibbs				}
440097883Sgibbs			} else {
440197883Sgibbs				/*
440297883Sgibbs				 * Send our own SDTR in reply
440397883Sgibbs				 */
440497883Sgibbs				if (bootverbose
440597883Sgibbs				 && devinfo->role == ROLE_INITIATOR) {
440697883Sgibbs					printf("(%s:%c:%d:%d): Target "
440797883Sgibbs					       "Initiated SDTR\n",
440897883Sgibbs					       ahd_name(ahd), devinfo->channel,
440997883Sgibbs					       devinfo->target, devinfo->lun);
441097883Sgibbs				}
441197883Sgibbs				ahd->msgout_index = 0;
441297883Sgibbs				ahd->msgout_len = 0;
441397883Sgibbs				ahd_construct_sdtr(ahd, devinfo,
441497883Sgibbs						   period, offset);
441597883Sgibbs				ahd->msgout_index = 0;
441697883Sgibbs				response = TRUE;
441797883Sgibbs			}
441897883Sgibbs			done = MSGLOOP_MSGCOMPLETE;
441997883Sgibbs			break;
442097883Sgibbs		}
442197883Sgibbs		case MSG_EXT_WDTR:
442297883Sgibbs		{
442397883Sgibbs			u_int bus_width;
442497883Sgibbs			u_int saved_width;
442597883Sgibbs			u_int sending_reply;
442697883Sgibbs
442797883Sgibbs			sending_reply = FALSE;
442897883Sgibbs			if (ahd->msgin_buf[1] != MSG_EXT_WDTR_LEN) {
442997883Sgibbs				reject = TRUE;
443097883Sgibbs				break;
443197883Sgibbs			}
443297883Sgibbs
443397883Sgibbs			/*
443497883Sgibbs			 * Wait until we have our arg before validating
443597883Sgibbs			 * and acting on this message.
443697883Sgibbs			 *
443797883Sgibbs			 * Add one to MSG_EXT_WDTR_LEN to account for
443897883Sgibbs			 * the extended message preamble.
443997883Sgibbs			 */
444097883Sgibbs			if (ahd->msgin_index < (MSG_EXT_WDTR_LEN + 1))
444197883Sgibbs				break;
444297883Sgibbs
444397883Sgibbs			bus_width = ahd->msgin_buf[3];
444497883Sgibbs			saved_width = bus_width;
444597883Sgibbs			ahd_validate_width(ahd, tinfo, &bus_width,
444697883Sgibbs					   devinfo->role);
444797883Sgibbs			if (bootverbose) {
444897883Sgibbs				printf("(%s:%c:%d:%d): Received WDTR "
444997883Sgibbs				       "%x filtered to %x\n",
445097883Sgibbs				       ahd_name(ahd), devinfo->channel,
445197883Sgibbs				       devinfo->target, devinfo->lun,
445297883Sgibbs				       saved_width, bus_width);
445397883Sgibbs			}
445497883Sgibbs
445597883Sgibbs			if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, TRUE)) {
445697883Sgibbs				/*
445797883Sgibbs				 * Don't send a WDTR back to the
445897883Sgibbs				 * target, since we asked first.
445997883Sgibbs				 * If the width went higher than our
446097883Sgibbs				 * request, reject it.
446197883Sgibbs				 */
446297883Sgibbs				if (saved_width > bus_width) {
446397883Sgibbs					reject = TRUE;
446497883Sgibbs					printf("(%s:%c:%d:%d): requested %dBit "
446597883Sgibbs					       "transfers.  Rejecting...\n",
446697883Sgibbs					       ahd_name(ahd), devinfo->channel,
446797883Sgibbs					       devinfo->target, devinfo->lun,
446897883Sgibbs					       8 * (0x01 << bus_width));
446997883Sgibbs					bus_width = 0;
447097883Sgibbs				}
447197883Sgibbs			} else {
447297883Sgibbs				/*
447397883Sgibbs				 * Send our own WDTR in reply
447497883Sgibbs				 */
447597883Sgibbs				if (bootverbose
447697883Sgibbs				 && devinfo->role == ROLE_INITIATOR) {
447797883Sgibbs					printf("(%s:%c:%d:%d): Target "
447897883Sgibbs					       "Initiated WDTR\n",
447997883Sgibbs					       ahd_name(ahd), devinfo->channel,
448097883Sgibbs					       devinfo->target, devinfo->lun);
448197883Sgibbs				}
448297883Sgibbs				ahd->msgout_index = 0;
448397883Sgibbs				ahd->msgout_len = 0;
448497883Sgibbs				ahd_construct_wdtr(ahd, devinfo, bus_width);
448597883Sgibbs				ahd->msgout_index = 0;
448697883Sgibbs				response = TRUE;
448797883Sgibbs				sending_reply = TRUE;
448897883Sgibbs			}
4489115918Sgibbs			/*
4490115918Sgibbs			 * After a wide message, we are async, but
4491115918Sgibbs			 * some devices don't seem to honor this portion
4492115918Sgibbs			 * of the spec.  Force a renegotiation of the
4493115918Sgibbs			 * sync component of our transfer agreement even
4494115918Sgibbs			 * if our goal is async.  By updating our width
4495115918Sgibbs			 * after forcing the negotiation, we avoid
4496115918Sgibbs			 * renegotiating for width.
4497115918Sgibbs			 */
4498115918Sgibbs			ahd_update_neg_request(ahd, devinfo, tstate,
4499115918Sgibbs					       tinfo, AHD_NEG_ALWAYS);
450097883Sgibbs			ahd_set_width(ahd, devinfo, bus_width,
450197883Sgibbs				      AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
450297883Sgibbs				      /*paused*/TRUE);
450397883Sgibbs			if (sending_reply == FALSE && reject == FALSE) {
450497883Sgibbs
4505115918Sgibbs				/*
4506115918Sgibbs				 * We will always have an SDTR to send.
4507115918Sgibbs				 */
4508115918Sgibbs				ahd->msgout_index = 0;
4509115918Sgibbs				ahd->msgout_len = 0;
4510115918Sgibbs				ahd_build_transfer_msg(ahd, devinfo);
4511115918Sgibbs				ahd->msgout_index = 0;
4512115918Sgibbs				response = TRUE;
451397883Sgibbs			}
451497883Sgibbs			done = MSGLOOP_MSGCOMPLETE;
451597883Sgibbs			break;
451697883Sgibbs		}
451797883Sgibbs		case MSG_EXT_PPR:
451897883Sgibbs		{
451997883Sgibbs			u_int	period;
452097883Sgibbs			u_int	offset;
452197883Sgibbs			u_int	bus_width;
452297883Sgibbs			u_int	ppr_options;
452397883Sgibbs			u_int	saved_width;
452497883Sgibbs			u_int	saved_offset;
452597883Sgibbs			u_int	saved_ppr_options;
452697883Sgibbs
452797883Sgibbs			if (ahd->msgin_buf[1] != MSG_EXT_PPR_LEN) {
452897883Sgibbs				reject = TRUE;
452997883Sgibbs				break;
453097883Sgibbs			}
453197883Sgibbs
453297883Sgibbs			/*
453397883Sgibbs			 * Wait until we have all args before validating
453497883Sgibbs			 * and acting on this message.
453597883Sgibbs			 *
453697883Sgibbs			 * Add one to MSG_EXT_PPR_LEN to account for
453797883Sgibbs			 * the extended message preamble.
453897883Sgibbs			 */
453997883Sgibbs			if (ahd->msgin_index < (MSG_EXT_PPR_LEN + 1))
454097883Sgibbs				break;
454197883Sgibbs
454297883Sgibbs			period = ahd->msgin_buf[3];
454397883Sgibbs			offset = ahd->msgin_buf[5];
454497883Sgibbs			bus_width = ahd->msgin_buf[6];
454597883Sgibbs			saved_width = bus_width;
454697883Sgibbs			ppr_options = ahd->msgin_buf[7];
454797883Sgibbs			/*
454897883Sgibbs			 * According to the spec, a DT only
454997883Sgibbs			 * period factor with no DT option
455097883Sgibbs			 * set implies async.
455197883Sgibbs			 */
455297883Sgibbs			if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0
455397883Sgibbs			 && period <= 9)
455497883Sgibbs				offset = 0;
455597883Sgibbs			saved_ppr_options = ppr_options;
455697883Sgibbs			saved_offset = offset;
455797883Sgibbs
455897883Sgibbs			/*
455997883Sgibbs			 * Transfer options are only available if we
456097883Sgibbs			 * are negotiating wide.
456197883Sgibbs			 */
456297883Sgibbs			if (bus_width == 0)
456397883Sgibbs				ppr_options &= MSG_EXT_PPR_QAS_REQ;
456497883Sgibbs
456597883Sgibbs			ahd_validate_width(ahd, tinfo, &bus_width,
456697883Sgibbs					   devinfo->role);
456797883Sgibbs			ahd_devlimited_syncrate(ahd, tinfo, &period,
456897883Sgibbs						&ppr_options, devinfo->role);
456997883Sgibbs			ahd_validate_offset(ahd, tinfo, period, &offset,
457097883Sgibbs					    bus_width, devinfo->role);
457197883Sgibbs
457297883Sgibbs			if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, TRUE)) {
457397883Sgibbs				/*
457497883Sgibbs				 * If we are unable to do any of the
457597883Sgibbs				 * requested options (we went too low),
457697883Sgibbs				 * then we'll have to reject the message.
457797883Sgibbs				 */
457897883Sgibbs				if (saved_width > bus_width
457997883Sgibbs				 || saved_offset != offset
458097883Sgibbs				 || saved_ppr_options != ppr_options) {
458197883Sgibbs					reject = TRUE;
458297883Sgibbs					period = 0;
458397883Sgibbs					offset = 0;
458497883Sgibbs					bus_width = 0;
458597883Sgibbs					ppr_options = 0;
458697883Sgibbs				}
458797883Sgibbs			} else {
458897883Sgibbs				if (devinfo->role != ROLE_TARGET)
458997883Sgibbs					printf("(%s:%c:%d:%d): Target "
459097883Sgibbs					       "Initiated PPR\n",
459197883Sgibbs					       ahd_name(ahd), devinfo->channel,
459297883Sgibbs					       devinfo->target, devinfo->lun);
459397883Sgibbs				else
459497883Sgibbs					printf("(%s:%c:%d:%d): Initiator "
459597883Sgibbs					       "Initiated PPR\n",
459697883Sgibbs					       ahd_name(ahd), devinfo->channel,
459797883Sgibbs					       devinfo->target, devinfo->lun);
459897883Sgibbs				ahd->msgout_index = 0;
459997883Sgibbs				ahd->msgout_len = 0;
460097883Sgibbs				ahd_construct_ppr(ahd, devinfo, period, offset,
460197883Sgibbs						  bus_width, ppr_options);
460297883Sgibbs				ahd->msgout_index = 0;
460397883Sgibbs				response = TRUE;
460497883Sgibbs			}
460597883Sgibbs			if (bootverbose) {
460697883Sgibbs				printf("(%s:%c:%d:%d): Received PPR width %x, "
460797883Sgibbs				       "period %x, offset %x,options %x\n"
460897883Sgibbs				       "\tFiltered to width %x, period %x, "
460997883Sgibbs				       "offset %x, options %x\n",
461097883Sgibbs				       ahd_name(ahd), devinfo->channel,
461197883Sgibbs				       devinfo->target, devinfo->lun,
461297883Sgibbs				       saved_width, ahd->msgin_buf[3],
461397883Sgibbs				       saved_offset, saved_ppr_options,
461497883Sgibbs				       bus_width, period, offset, ppr_options);
461597883Sgibbs			}
461697883Sgibbs			ahd_set_width(ahd, devinfo, bus_width,
461797883Sgibbs				      AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
461897883Sgibbs				      /*paused*/TRUE);
461997883Sgibbs			ahd_set_syncrate(ahd, devinfo, period,
462097883Sgibbs					 offset, ppr_options,
462197883Sgibbs					 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
462297883Sgibbs					 /*paused*/TRUE);
462397883Sgibbs
462497883Sgibbs			done = MSGLOOP_MSGCOMPLETE;
462597883Sgibbs			break;
462697883Sgibbs		}
462797883Sgibbs		default:
462897883Sgibbs			/* Unknown extended message.  Reject it. */
462997883Sgibbs			reject = TRUE;
463097883Sgibbs			break;
463197883Sgibbs		}
463297883Sgibbs		break;
463397883Sgibbs	}
463497883Sgibbs#ifdef AHD_TARGET_MODE
463597883Sgibbs	case MSG_BUS_DEV_RESET:
4636109588Sgibbs		ahd_handle_devreset(ahd, devinfo, CAM_LUN_WILDCARD,
463797883Sgibbs				    CAM_BDR_SENT,
463897883Sgibbs				    "Bus Device Reset Received",
463997883Sgibbs				    /*verbose_level*/0);
464097883Sgibbs		ahd_restart(ahd);
464197883Sgibbs		done = MSGLOOP_TERMINATED;
464297883Sgibbs		break;
464397883Sgibbs	case MSG_ABORT_TAG:
464497883Sgibbs	case MSG_ABORT:
464597883Sgibbs	case MSG_CLEAR_QUEUE:
464697883Sgibbs	{
464797883Sgibbs		int tag;
464897883Sgibbs
464997883Sgibbs		/* Target mode messages */
465097883Sgibbs		if (devinfo->role != ROLE_TARGET) {
465197883Sgibbs			reject = TRUE;
465297883Sgibbs			break;
465397883Sgibbs		}
465497883Sgibbs		tag = SCB_LIST_NULL;
465597883Sgibbs		if (ahd->msgin_buf[0] == MSG_ABORT_TAG)
465697883Sgibbs			tag = ahd_inb(ahd, INITIATOR_TAG);
465797883Sgibbs		ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
465897883Sgibbs			       devinfo->lun, tag, ROLE_TARGET,
465997883Sgibbs			       CAM_REQ_ABORTED);
466097883Sgibbs
466197883Sgibbs		tstate = ahd->enabled_targets[devinfo->our_scsiid];
466297883Sgibbs		if (tstate != NULL) {
466397883Sgibbs			struct ahd_tmode_lstate* lstate;
466497883Sgibbs
466597883Sgibbs			lstate = tstate->enabled_luns[devinfo->lun];
466697883Sgibbs			if (lstate != NULL) {
466797883Sgibbs				ahd_queue_lstate_event(ahd, lstate,
466897883Sgibbs						       devinfo->our_scsiid,
466997883Sgibbs						       ahd->msgin_buf[0],
467097883Sgibbs						       /*arg*/tag);
467197883Sgibbs				ahd_send_lstate_events(ahd, lstate);
467297883Sgibbs			}
467397883Sgibbs		}
467497883Sgibbs		ahd_restart(ahd);
467597883Sgibbs		done = MSGLOOP_TERMINATED;
467697883Sgibbs		break;
467797883Sgibbs	}
467897883Sgibbs#endif
467997883Sgibbs	case MSG_QAS_REQUEST:
4680107441Sscottl#ifdef AHD_DEBUG
4681107441Sscottl		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
4682107441Sscottl			printf("%s: QAS request.  SCSISIGI == 0x%x\n",
4683107441Sscottl			       ahd_name(ahd), ahd_inb(ahd, SCSISIGI));
4684107441Sscottl#endif
4685107441Sscottl		ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE;
468697883Sgibbs		/* FALLTHROUGH */
468797883Sgibbs	case MSG_TERM_IO_PROC:
468897883Sgibbs	default:
468997883Sgibbs		reject = TRUE;
469097883Sgibbs		break;
469197883Sgibbs	}
469297883Sgibbs
469397883Sgibbs	if (reject) {
469497883Sgibbs		/*
469597883Sgibbs		 * Setup to reject the message.
469697883Sgibbs		 */
469797883Sgibbs		ahd->msgout_index = 0;
469897883Sgibbs		ahd->msgout_len = 1;
469997883Sgibbs		ahd->msgout_buf[0] = MSG_MESSAGE_REJECT;
470097883Sgibbs		done = MSGLOOP_MSGCOMPLETE;
470197883Sgibbs		response = TRUE;
470297883Sgibbs	}
470397883Sgibbs
470497883Sgibbs	if (done != MSGLOOP_IN_PROG && !response)
470597883Sgibbs		/* Clear the outgoing message buffer */
470697883Sgibbs		ahd->msgout_len = 0;
470797883Sgibbs
470897883Sgibbs	return (done);
470997883Sgibbs}
471097883Sgibbs
471197883Sgibbs/*
471297883Sgibbs * Process a message reject message.
471397883Sgibbs */
471497883Sgibbsstatic int
471597883Sgibbsahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
471697883Sgibbs{
471797883Sgibbs	/*
471897883Sgibbs	 * What we care about here is if we had an
471997883Sgibbs	 * outstanding SDTR or WDTR message for this
472097883Sgibbs	 * target.  If we did, this is a signal that
472197883Sgibbs	 * the target is refusing negotiation.
472297883Sgibbs	 */
472397883Sgibbs	struct scb *scb;
472497883Sgibbs	struct ahd_initiator_tinfo *tinfo;
472597883Sgibbs	struct ahd_tmode_tstate *tstate;
472697883Sgibbs	u_int scb_index;
472797883Sgibbs	u_int last_msg;
472897883Sgibbs	int   response = 0;
472997883Sgibbs
473097883Sgibbs	scb_index = ahd_get_scbptr(ahd);
473197883Sgibbs	scb = ahd_lookup_scb(ahd, scb_index);
473297883Sgibbs	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
473397883Sgibbs				    devinfo->our_scsiid,
473497883Sgibbs				    devinfo->target, &tstate);
473597883Sgibbs	/* Might be necessary */
473697883Sgibbs	last_msg = ahd_inb(ahd, LAST_MSG);
473797883Sgibbs
473897883Sgibbs	if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) {
4739107441Sscottl		if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, /*full*/TRUE)
4740107441Sscottl		 && tinfo->goal.period <= AHD_SYNCRATE_PACED) {
4741107441Sscottl			/*
4742107441Sscottl			 * Target may not like our SPI-4 PPR Options.
4743107441Sscottl			 * Attempt to negotiate 80MHz which will turn
4744107441Sscottl			 * off these options.
4745107441Sscottl			 */
4746107441Sscottl			if (bootverbose) {
4747107441Sscottl				printf("(%s:%c:%d:%d): PPR Rejected. "
4748107441Sscottl				       "Trying simple U160 PPR\n",
4749107441Sscottl				       ahd_name(ahd), devinfo->channel,
4750107441Sscottl				       devinfo->target, devinfo->lun);
4751107441Sscottl			}
4752107441Sscottl			tinfo->goal.period = AHD_SYNCRATE_DT;
4753107441Sscottl			tinfo->goal.ppr_options &= MSG_EXT_PPR_IU_REQ
4754107441Sscottl						|  MSG_EXT_PPR_QAS_REQ
4755107441Sscottl						|  MSG_EXT_PPR_DT_REQ;
4756107441Sscottl		} else {
4757107441Sscottl			/*
4758107441Sscottl			 * Target does not support the PPR message.
4759107441Sscottl			 * Attempt to negotiate SPI-2 style.
4760107441Sscottl			 */
4761107441Sscottl			if (bootverbose) {
4762107441Sscottl				printf("(%s:%c:%d:%d): PPR Rejected. "
4763107441Sscottl				       "Trying WDTR/SDTR\n",
4764107441Sscottl				       ahd_name(ahd), devinfo->channel,
4765107441Sscottl				       devinfo->target, devinfo->lun);
4766107441Sscottl			}
4767107441Sscottl			tinfo->goal.ppr_options = 0;
4768107441Sscottl			tinfo->curr.transport_version = 2;
4769107441Sscottl			tinfo->goal.transport_version = 2;
477097883Sgibbs		}
477197883Sgibbs		ahd->msgout_index = 0;
477297883Sgibbs		ahd->msgout_len = 0;
477397883Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
477497883Sgibbs		ahd->msgout_index = 0;
477597883Sgibbs		response = 1;
477697883Sgibbs	} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) {
477797883Sgibbs
477897883Sgibbs		/* note 8bit xfers */
477997883Sgibbs		printf("(%s:%c:%d:%d): refuses WIDE negotiation.  Using "
478097883Sgibbs		       "8bit transfers\n", ahd_name(ahd),
478197883Sgibbs		       devinfo->channel, devinfo->target, devinfo->lun);
478297883Sgibbs		ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
478397883Sgibbs			      AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
478497883Sgibbs			      /*paused*/TRUE);
478597883Sgibbs		/*
478697883Sgibbs		 * No need to clear the sync rate.  If the target
478797883Sgibbs		 * did not accept the command, our syncrate is
478897883Sgibbs		 * unaffected.  If the target started the negotiation,
478997883Sgibbs		 * but rejected our response, we already cleared the
479097883Sgibbs		 * sync rate before sending our WDTR.
479197883Sgibbs		 */
4792109603Sgibbs		if (tinfo->goal.offset != tinfo->curr.offset) {
479397883Sgibbs
479497883Sgibbs			/* Start the sync negotiation */
479597883Sgibbs			ahd->msgout_index = 0;
479697883Sgibbs			ahd->msgout_len = 0;
479797883Sgibbs			ahd_build_transfer_msg(ahd, devinfo);
479897883Sgibbs			ahd->msgout_index = 0;
479997883Sgibbs			response = 1;
480097883Sgibbs		}
480197883Sgibbs	} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) {
480297883Sgibbs		/* note asynch xfers and clear flag */
480397883Sgibbs		ahd_set_syncrate(ahd, devinfo, /*period*/0,
480497883Sgibbs				 /*offset*/0, /*ppr_options*/0,
480597883Sgibbs				 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
480697883Sgibbs				 /*paused*/TRUE);
480797883Sgibbs		printf("(%s:%c:%d:%d): refuses synchronous negotiation. "
480897883Sgibbs		       "Using asynchronous transfers\n",
480997883Sgibbs		       ahd_name(ahd), devinfo->channel,
481097883Sgibbs		       devinfo->target, devinfo->lun);
481197883Sgibbs	} else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
481297883Sgibbs		int tag_type;
481397883Sgibbs		int mask;
481497883Sgibbs
481597883Sgibbs		tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
481697883Sgibbs
481797883Sgibbs		if (tag_type == MSG_SIMPLE_TASK) {
481897883Sgibbs			printf("(%s:%c:%d:%d): refuses tagged commands.  "
481997883Sgibbs			       "Performing non-tagged I/O\n", ahd_name(ahd),
482097883Sgibbs			       devinfo->channel, devinfo->target, devinfo->lun);
482197883Sgibbs			ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE);
482297883Sgibbs			mask = ~0x23;
482397883Sgibbs		} else {
482497883Sgibbs			printf("(%s:%c:%d:%d): refuses %s tagged commands.  "
482597883Sgibbs			       "Performing simple queue tagged I/O only\n",
482697883Sgibbs			       ahd_name(ahd), devinfo->channel, devinfo->target,
482797883Sgibbs			       devinfo->lun, tag_type == MSG_ORDERED_TASK
482897883Sgibbs			       ? "ordered" : "head of queue");
482997883Sgibbs			ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC);
483097883Sgibbs			mask = ~0x03;
483197883Sgibbs		}
483297883Sgibbs
483397883Sgibbs		/*
483497883Sgibbs		 * Resend the identify for this CCB as the target
483597883Sgibbs		 * may believe that the selection is invalid otherwise.
483697883Sgibbs		 */
483797883Sgibbs		ahd_outb(ahd, SCB_CONTROL,
483897883Sgibbs			 ahd_inb_scbram(ahd, SCB_CONTROL) & mask);
483997883Sgibbs	 	scb->hscb->control &= mask;
4840123579Sgibbs		aic_set_transaction_tag(scb, /*enabled*/FALSE,
484197883Sgibbs					/*type*/MSG_SIMPLE_TASK);
484297883Sgibbs		ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG);
484397883Sgibbs		ahd_assert_atn(ahd);
484497883Sgibbs		ahd_busy_tcl(ahd, BUILD_TCL(scb->hscb->scsiid, devinfo->lun),
484597883Sgibbs			     SCB_GET_TAG(scb));
484697883Sgibbs
484797883Sgibbs		/*
484897883Sgibbs		 * Requeue all tagged commands for this target
484997883Sgibbs		 * currently in our posession so they can be
485097883Sgibbs		 * converted to untagged commands.
485197883Sgibbs		 */
485297883Sgibbs		ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
485397883Sgibbs				   SCB_GET_CHANNEL(ahd, scb),
485497883Sgibbs				   SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL,
485597883Sgibbs				   ROLE_INITIATOR, CAM_REQUEUE_REQ,
485697883Sgibbs				   SEARCH_COMPLETE);
4857109588Sgibbs	} else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_IDENTIFYFLAG, TRUE)) {
4858109588Sgibbs		/*
4859109588Sgibbs		 * Most likely the device believes that we had
4860109588Sgibbs		 * previously negotiated packetized.
4861109588Sgibbs		 */
4862109588Sgibbs		ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
4863109588Sgibbs			       |  MSG_FLAG_IU_REQ_CHANGED;
4864109588Sgibbs
4865109588Sgibbs		ahd_force_renegotiation(ahd, devinfo);
4866109588Sgibbs		ahd->msgout_index = 0;
4867109588Sgibbs		ahd->msgout_len = 0;
4868109588Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
4869109588Sgibbs		ahd->msgout_index = 0;
4870109588Sgibbs		response = 1;
487197883Sgibbs	} else {
487297883Sgibbs		/*
487397883Sgibbs		 * Otherwise, we ignore it.
487497883Sgibbs		 */
487597883Sgibbs		printf("%s:%c:%d: Message reject for %x -- ignored\n",
487697883Sgibbs		       ahd_name(ahd), devinfo->channel, devinfo->target,
487797883Sgibbs		       last_msg);
487897883Sgibbs	}
487997883Sgibbs	return (response);
488097883Sgibbs}
488197883Sgibbs
488297883Sgibbs/*
488397883Sgibbs * Process an ingnore wide residue message.
488497883Sgibbs */
488597883Sgibbsstatic void
488697883Sgibbsahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
488797883Sgibbs{
488897883Sgibbs	u_int scb_index;
488997883Sgibbs	struct scb *scb;
489097883Sgibbs
489197883Sgibbs	scb_index = ahd_get_scbptr(ahd);
489297883Sgibbs	scb = ahd_lookup_scb(ahd, scb_index);
489397883Sgibbs	/*
489497883Sgibbs	 * XXX Actually check data direction in the sequencer?
489597883Sgibbs	 * Perhaps add datadir to some spare bits in the hscb?
489697883Sgibbs	 */
489797883Sgibbs	if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0
4898123579Sgibbs	 || aic_get_transfer_dir(scb) != CAM_DIR_IN) {
489997883Sgibbs		/*
490097883Sgibbs		 * Ignore the message if we haven't
490197883Sgibbs		 * seen an appropriate data phase yet.
490297883Sgibbs		 */
490397883Sgibbs	} else {
490497883Sgibbs		/*
490597883Sgibbs		 * If the residual occurred on the last
490697883Sgibbs		 * transfer and the transfer request was
490797883Sgibbs		 * expected to end on an odd count, do
490897883Sgibbs		 * nothing.  Otherwise, subtract a byte
490997883Sgibbs		 * and update the residual count accordingly.
491097883Sgibbs		 */
491197883Sgibbs		uint32_t sgptr;
491297883Sgibbs
491397883Sgibbs		sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
491497883Sgibbs		if ((sgptr & SG_LIST_NULL) != 0
4915116940Sgibbs		 && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
4916116940Sgibbs		     & SCB_XFERLEN_ODD) != 0) {
491797883Sgibbs			/*
491897883Sgibbs			 * If the residual occurred on the last
491997883Sgibbs			 * transfer and the transfer request was
492097883Sgibbs			 * expected to end on an odd count, do
492197883Sgibbs			 * nothing.
492297883Sgibbs			 */
492397883Sgibbs		} else {
492497883Sgibbs			uint32_t data_cnt;
492597883Sgibbs			uint64_t data_addr;
492697883Sgibbs			uint32_t sglen;
492797883Sgibbs
492897883Sgibbs			/* Pull in the rest of the sgptr */
4929115335Sgibbs			sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
4930115335Sgibbs			data_cnt = ahd_inl_scbram(ahd, SCB_RESIDUAL_DATACNT);
4931115335Sgibbs			if ((sgptr & SG_LIST_NULL) != 0) {
4932115335Sgibbs				/*
4933115335Sgibbs				 * The residual data count is not updated
4934115335Sgibbs				 * for the command run to completion case.
4935115335Sgibbs				 * Explicitly zero the count.
4936115335Sgibbs				 */
4937115335Sgibbs				data_cnt &= ~AHD_SG_LEN_MASK;
4938115335Sgibbs			}
4939115335Sgibbs			data_addr = ahd_inq(ahd, SHADDR);
494097883Sgibbs			data_cnt += 1;
494197883Sgibbs			data_addr -= 1;
4942115335Sgibbs			sgptr &= SG_PTR_MASK;
494397883Sgibbs			if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
494497883Sgibbs				struct ahd_dma64_seg *sg;
494597883Sgibbs
494697883Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
494797883Sgibbs
494897883Sgibbs				/*
494997883Sgibbs				 * The residual sg ptr points to the next S/G
495097883Sgibbs				 * to load so we must go back one.
495197883Sgibbs				 */
495297883Sgibbs				sg--;
4953123579Sgibbs				sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
495497883Sgibbs				if (sg != scb->sg_list
495597883Sgibbs				 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
495697883Sgibbs
495797883Sgibbs					sg--;
4958123579Sgibbs					sglen = aic_le32toh(sg->len);
495997883Sgibbs					/*
496097883Sgibbs					 * Preserve High Address and SG_LIST
496197883Sgibbs					 * bits while setting the count to 1.
496297883Sgibbs					 */
496397883Sgibbs					data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
4964123579Sgibbs					data_addr = aic_le64toh(sg->addr)
496597883Sgibbs						  + (sglen & AHD_SG_LEN_MASK)
496697883Sgibbs						  - 1;
496797883Sgibbs
496897883Sgibbs					/*
496997883Sgibbs					 * Increment sg so it points to the
497097883Sgibbs					 * "next" sg.
497197883Sgibbs					 */
497297883Sgibbs					sg++;
497397883Sgibbs					sgptr = ahd_sg_virt_to_bus(ahd, scb,
497497883Sgibbs								   sg);
497597883Sgibbs				}
497697883Sgibbs			} else {
497797883Sgibbs				struct ahd_dma_seg *sg;
497897883Sgibbs
497997883Sgibbs				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
498097883Sgibbs
498197883Sgibbs				/*
498297883Sgibbs				 * The residual sg ptr points to the next S/G
498397883Sgibbs				 * to load so we must go back one.
498497883Sgibbs				 */
498597883Sgibbs				sg--;
4986123579Sgibbs				sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
498797883Sgibbs				if (sg != scb->sg_list
498897883Sgibbs				 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
498997883Sgibbs
499097883Sgibbs					sg--;
4991123579Sgibbs					sglen = aic_le32toh(sg->len);
499297883Sgibbs					/*
499397883Sgibbs					 * Preserve High Address and SG_LIST
499497883Sgibbs					 * bits while setting the count to 1.
499597883Sgibbs					 */
499697883Sgibbs					data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
4997123579Sgibbs					data_addr = aic_le32toh(sg->addr)
499897883Sgibbs						  + (sglen & AHD_SG_LEN_MASK)
499997883Sgibbs						  - 1;
500097883Sgibbs
500197883Sgibbs					/*
500297883Sgibbs					 * Increment sg so it points to the
500397883Sgibbs					 * "next" sg.
500497883Sgibbs					 */
500597883Sgibbs					sg++;
500697883Sgibbs					sgptr = ahd_sg_virt_to_bus(ahd, scb,
500797883Sgibbs								  sg);
500897883Sgibbs				}
500997883Sgibbs			}
5010115335Sgibbs			/*
5011115335Sgibbs			 * Toggle the "oddness" of the transfer length
5012115335Sgibbs			 * to handle this mid-transfer ignore wide
5013115335Sgibbs			 * residue.  This ensures that the oddness is
5014115335Sgibbs			 * correct for subsequent data transfers.
5015115335Sgibbs			 */
5016115335Sgibbs			ahd_outb(ahd, SCB_TASK_ATTRIBUTE,
5017116940Sgibbs			    ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
5018116940Sgibbs			    ^ SCB_XFERLEN_ODD);
501997883Sgibbs
5020115335Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
5021115335Sgibbs			ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);
502297883Sgibbs			/*
502397883Sgibbs			 * The FIFO's pointers will be updated if/when the
502497883Sgibbs			 * sequencer re-enters a data phase.
502597883Sgibbs			 */
502697883Sgibbs		}
502797883Sgibbs	}
502897883Sgibbs}
502997883Sgibbs
503097883Sgibbs
503197883Sgibbs/*
503297883Sgibbs * Reinitialize the data pointers for the active transfer
503397883Sgibbs * based on its current residual.
503497883Sgibbs */
503597883Sgibbsstatic void
503697883Sgibbsahd_reinitialize_dataptrs(struct ahd_softc *ahd)
503797883Sgibbs{
503897883Sgibbs	struct		 scb *scb;
503997883Sgibbs	ahd_mode_state	 saved_modes;
504097883Sgibbs	u_int		 scb_index;
504197883Sgibbs	u_int		 wait;
504297883Sgibbs	uint32_t	 sgptr;
504397883Sgibbs	uint32_t	 resid;
504497883Sgibbs	uint64_t	 dataptr;
504597883Sgibbs
504697883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK,
504797883Sgibbs			 AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK);
504897883Sgibbs
504997883Sgibbs	scb_index = ahd_get_scbptr(ahd);
505097883Sgibbs	scb = ahd_lookup_scb(ahd, scb_index);
505197883Sgibbs
505297883Sgibbs	/*
505397883Sgibbs	 * Release and reacquire the FIFO so we
505497883Sgibbs	 * have a clean slate.
505597883Sgibbs	 */
505697883Sgibbs	ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
505797883Sgibbs	wait = 1000;
5058116935Sgibbs	while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))
5059123579Sgibbs		aic_delay(100);
506097883Sgibbs	if (wait == 0) {
506197883Sgibbs		ahd_print_path(ahd, scb);
506297883Sgibbs		printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");
506397883Sgibbs		ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
506497883Sgibbs	}
506597883Sgibbs	saved_modes = ahd_save_modes(ahd);
506697883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
506797883Sgibbs	ahd_outb(ahd, DFFSTAT,
5068107441Sscottl		 ahd_inb(ahd, DFFSTAT)
5069107441Sscottl		| (saved_modes == 0x11 ? CURRFIFO_1 : CURRFIFO_0));
507097883Sgibbs
507197883Sgibbs	/*
507297883Sgibbs	 * Determine initial values for data_addr and data_cnt
507397883Sgibbs	 * for resuming the data phase.
507497883Sgibbs	 */
5075123579Sgibbs	sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
507697883Sgibbs	sgptr &= SG_PTR_MASK;
507797883Sgibbs
507897883Sgibbs	resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
507997883Sgibbs	      | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 1) << 8)
508097883Sgibbs	      | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT);
508197883Sgibbs
508297883Sgibbs	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
508397883Sgibbs		struct ahd_dma64_seg *sg;
508497883Sgibbs
508597883Sgibbs		sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
508697883Sgibbs
508797883Sgibbs		/* The residual sg_ptr always points to the next sg */
508897883Sgibbs		sg--;
508997883Sgibbs
5090123579Sgibbs		dataptr = aic_le64toh(sg->addr)
5091123579Sgibbs			+ (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
509297883Sgibbs			- resid;
5093123579Sgibbs		ahd_outl(ahd, HADDR + 4, dataptr >> 32);
509497883Sgibbs	} else {
509597883Sgibbs		struct	 ahd_dma_seg *sg;
509697883Sgibbs
509797883Sgibbs		sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
509897883Sgibbs
509997883Sgibbs		/* The residual sg_ptr always points to the next sg */
510097883Sgibbs		sg--;
510197883Sgibbs
5102123579Sgibbs		dataptr = aic_le32toh(sg->addr)
5103123579Sgibbs			+ (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
510497883Sgibbs			- resid;
510597883Sgibbs		ahd_outb(ahd, HADDR + 4,
5106123579Sgibbs			 (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
510797883Sgibbs	}
5108123579Sgibbs	ahd_outl(ahd, HADDR, dataptr);
510997883Sgibbs	ahd_outb(ahd, HCNT + 2, resid >> 16);
511097883Sgibbs	ahd_outb(ahd, HCNT + 1, resid >> 8);
511197883Sgibbs	ahd_outb(ahd, HCNT, resid);
511297883Sgibbs}
511397883Sgibbs
511497883Sgibbs/*
511597883Sgibbs * Handle the effects of issuing a bus device reset message.
511697883Sgibbs */
511797883Sgibbsstatic void
511897883Sgibbsahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
5119109588Sgibbs		    u_int lun, cam_status status, char *message,
5120109588Sgibbs		    int verbose_level)
512197883Sgibbs{
512297883Sgibbs#ifdef AHD_TARGET_MODE
512397883Sgibbs	struct ahd_tmode_tstate* tstate;
512497883Sgibbs#endif
512597883Sgibbs	int found;
512697883Sgibbs
512797883Sgibbs	found = ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
5128109588Sgibbs			       lun, SCB_LIST_NULL, devinfo->role,
512997883Sgibbs			       status);
513097883Sgibbs
513197883Sgibbs#ifdef AHD_TARGET_MODE
513297883Sgibbs	/*
513397883Sgibbs	 * Send an immediate notify ccb to all target mord peripheral
513497883Sgibbs	 * drivers affected by this action.
513597883Sgibbs	 */
513697883Sgibbs	tstate = ahd->enabled_targets[devinfo->our_scsiid];
513797883Sgibbs	if (tstate != NULL) {
5138109588Sgibbs		u_int cur_lun;
5139109588Sgibbs		u_int max_lun;
5140109588Sgibbs
5141109588Sgibbs		if (lun != CAM_LUN_WILDCARD) {
5142109588Sgibbs			cur_lun = 0;
5143109588Sgibbs			max_lun = AHD_NUM_LUNS - 1;
5144109588Sgibbs		} else {
5145109588Sgibbs			cur_lun = lun;
5146109588Sgibbs			max_lun = lun;
5147109588Sgibbs		}
5148109588Sgibbs		for (cur_lun <= max_lun; cur_lun++) {
514997883Sgibbs			struct ahd_tmode_lstate* lstate;
515097883Sgibbs
5151109588Sgibbs			lstate = tstate->enabled_luns[cur_lun];
515297883Sgibbs			if (lstate == NULL)
515397883Sgibbs				continue;
515497883Sgibbs
515597883Sgibbs			ahd_queue_lstate_event(ahd, lstate, devinfo->our_scsiid,
515697883Sgibbs					       MSG_BUS_DEV_RESET, /*arg*/0);
515797883Sgibbs			ahd_send_lstate_events(ahd, lstate);
515897883Sgibbs		}
515997883Sgibbs	}
516097883Sgibbs#endif
516197883Sgibbs
516297883Sgibbs	/*
516397883Sgibbs	 * Go back to async/narrow transfers and renegotiate.
516497883Sgibbs	 */
516597883Sgibbs	ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
516697883Sgibbs		      AHD_TRANS_CUR, /*paused*/TRUE);
516797883Sgibbs	ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
5168129134Sgibbs			 /*ppr_options*/0, AHD_TRANS_CUR,
5169129134Sgibbs			 /*paused*/TRUE);
517097883Sgibbs
5171129134Sgibbs	if (status != CAM_SEL_TIMEOUT)
5172129134Sgibbs		ahd_send_async(ahd, devinfo->channel, devinfo->target,
5173129134Sgibbs			       lun, AC_SENT_BDR, NULL);
517497883Sgibbs
517597883Sgibbs	if (message != NULL
5176199260Sattilio	 && (verbose_level <= bootverbose)) {
5177199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
517897883Sgibbs		printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
517997883Sgibbs		       message, devinfo->channel, devinfo->target, found);
5180199260Sattilio	}
518197883Sgibbs}
518297883Sgibbs
518397883Sgibbs#ifdef AHD_TARGET_MODE
518497883Sgibbsstatic void
518597883Sgibbsahd_setup_target_msgin(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
518697883Sgibbs		       struct scb *scb)
518797883Sgibbs{
518897883Sgibbs
518997883Sgibbs	/*
519097883Sgibbs	 * To facilitate adding multiple messages together,
519197883Sgibbs	 * each routine should increment the index and len
519297883Sgibbs	 * variables instead of setting them explicitly.
519397883Sgibbs	 */
519497883Sgibbs	ahd->msgout_index = 0;
519597883Sgibbs	ahd->msgout_len = 0;
519697883Sgibbs
519797883Sgibbs	if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
519897883Sgibbs		ahd_build_transfer_msg(ahd, devinfo);
519997883Sgibbs	else
520097883Sgibbs		panic("ahd_intr: AWAITING target message with no message");
520197883Sgibbs
520297883Sgibbs	ahd->msgout_index = 0;
520397883Sgibbs	ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
520497883Sgibbs}
520597883Sgibbs#endif
520697883Sgibbs/**************************** Initialization **********************************/
5207106803Sscottlstatic u_int
520897883Sgibbsahd_sglist_size(struct ahd_softc *ahd)
520997883Sgibbs{
521097883Sgibbs	bus_size_t list_size;
521197883Sgibbs
521297883Sgibbs	list_size = sizeof(struct ahd_dma_seg) * AHD_NSEG;
521397883Sgibbs	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
521497883Sgibbs		list_size = sizeof(struct ahd_dma64_seg) * AHD_NSEG;
521597883Sgibbs	return (list_size);
521697883Sgibbs}
521797883Sgibbs
521897883Sgibbs/*
521997883Sgibbs * Calculate the optimum S/G List allocation size.  S/G elements used
522097883Sgibbs * for a given transaction must be physically contiguous.  Assume the
522197883Sgibbs * OS will allocate full pages to us, so it doesn't make sense to request
522297883Sgibbs * less than a page.
522397883Sgibbs */
5224106803Sscottlstatic u_int
522597883Sgibbsahd_sglist_allocsize(struct ahd_softc *ahd)
522697883Sgibbs{
522797883Sgibbs	bus_size_t sg_list_increment;
522897883Sgibbs	bus_size_t sg_list_size;
522997883Sgibbs	bus_size_t max_list_size;
523097883Sgibbs	bus_size_t best_list_size;
523197883Sgibbs
523297883Sgibbs	/* Start out with the minimum required for AHD_NSEG. */
523397883Sgibbs	sg_list_increment = ahd_sglist_size(ahd);
523497883Sgibbs	sg_list_size = sg_list_increment;
523597883Sgibbs
523697883Sgibbs	/* Get us as close as possible to a page in size. */
523797883Sgibbs	while ((sg_list_size + sg_list_increment) <= PAGE_SIZE)
523897883Sgibbs		sg_list_size += sg_list_increment;
523997883Sgibbs
524097883Sgibbs	/*
524197883Sgibbs	 * Try to reduce the amount of wastage by allocating
524297883Sgibbs	 * multiple pages.
524397883Sgibbs	 */
524497883Sgibbs	best_list_size = sg_list_size;
524597883Sgibbs	max_list_size = roundup(sg_list_increment, PAGE_SIZE);
524697883Sgibbs	if (max_list_size < 4 * PAGE_SIZE)
524797883Sgibbs		max_list_size = 4 * PAGE_SIZE;
524897883Sgibbs	if (max_list_size > (AHD_SCB_MAX_ALLOC * sg_list_increment))
524997883Sgibbs		max_list_size = (AHD_SCB_MAX_ALLOC * sg_list_increment);
525097883Sgibbs	while ((sg_list_size + sg_list_increment) <= max_list_size
525197883Sgibbs	   &&  (sg_list_size % PAGE_SIZE) != 0) {
525297883Sgibbs		bus_size_t new_mod;
525397883Sgibbs		bus_size_t best_mod;
525497883Sgibbs
525597883Sgibbs		sg_list_size += sg_list_increment;
525697883Sgibbs		new_mod = sg_list_size % PAGE_SIZE;
525797883Sgibbs		best_mod = best_list_size % PAGE_SIZE;
525897883Sgibbs		if (new_mod > best_mod || new_mod == 0) {
525997883Sgibbs			best_list_size = sg_list_size;
526097883Sgibbs		}
526197883Sgibbs	}
526297883Sgibbs	return (best_list_size);
526397883Sgibbs}
526497883Sgibbs
526597883Sgibbs/*
526697883Sgibbs * Allocate a controller structure for a new device
526797883Sgibbs * and perform initial initializion.
526897883Sgibbs */
526997883Sgibbsstruct ahd_softc *
527097883Sgibbsahd_alloc(void *platform_arg, char *name)
527197883Sgibbs{
527297883Sgibbs	struct  ahd_softc *ahd;
527397883Sgibbs
527497883Sgibbs#ifndef	__FreeBSD__
527597883Sgibbs	ahd = malloc(sizeof(*ahd), M_DEVBUF, M_NOWAIT);
527697883Sgibbs	if (!ahd) {
527797883Sgibbs		printf("aic7xxx: cannot malloc softc!\n");
527897883Sgibbs		free(name, M_DEVBUF);
527997883Sgibbs		return NULL;
528097883Sgibbs	}
528197883Sgibbs#else
528297883Sgibbs	ahd = device_get_softc((device_t)platform_arg);
528397883Sgibbs#endif
528497883Sgibbs	memset(ahd, 0, sizeof(*ahd));
528597883Sgibbs	ahd->seep_config = malloc(sizeof(*ahd->seep_config),
528697883Sgibbs				  M_DEVBUF, M_NOWAIT);
528797883Sgibbs	if (ahd->seep_config == NULL) {
528897883Sgibbs#ifndef	__FreeBSD__
528997883Sgibbs		free(ahd, M_DEVBUF);
529097883Sgibbs#endif
529197883Sgibbs		free(name, M_DEVBUF);
529297883Sgibbs		return (NULL);
529397883Sgibbs	}
529497883Sgibbs	LIST_INIT(&ahd->pending_scbs);
5295141978Sgibbs	LIST_INIT(&ahd->timedout_scbs);
529697883Sgibbs	/* We don't know our unit number until the OSM sets it */
529797883Sgibbs	ahd->name = name;
529897883Sgibbs	ahd->unit = -1;
529997883Sgibbs	ahd->description = NULL;
530097883Sgibbs	ahd->bus_description = NULL;
530197883Sgibbs	ahd->channel = 'A';
530297883Sgibbs	ahd->chip = AHD_NONE;
530397883Sgibbs	ahd->features = AHD_FENONE;
530497883Sgibbs	ahd->bugs = AHD_BUGNONE;
530597883Sgibbs	ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A
530697883Sgibbs		   | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A;
5307123579Sgibbs	aic_timer_init(&ahd->reset_timer);
5308123579Sgibbs	aic_timer_init(&ahd->stat_timer);
5309115329Sgibbs	ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT;
5310115329Sgibbs	ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT;
5311115329Sgibbs	ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT;
5312115329Sgibbs	ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT;
5313115329Sgibbs	ahd->int_coalescing_stop_threshold =
5314115329Sgibbs	    AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT;
531597883Sgibbs
531697883Sgibbs	if (ahd_platform_alloc(ahd, platform_arg) != 0) {
531797883Sgibbs		ahd_free(ahd);
531897883Sgibbs		ahd = NULL;
531997883Sgibbs	}
5320168807Sscottl	ahd_lockinit(ahd);
5321102679Sgibbs#ifdef AHD_DEBUG
5322102679Sgibbs	if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {
5323106803Sscottl		printf("%s: scb size = 0x%x, hscb size = 0x%x\n",
5324106803Sscottl		       ahd_name(ahd), (u_int)sizeof(struct scb),
5325106803Sscottl		       (u_int)sizeof(struct hardware_scb));
5326102679Sgibbs	}
5327102679Sgibbs#endif
532897883Sgibbs	return (ahd);
532997883Sgibbs}
533097883Sgibbs
533197883Sgibbsint
533297883Sgibbsahd_softc_init(struct ahd_softc *ahd)
533397883Sgibbs{
533497883Sgibbs
533597883Sgibbs	ahd->unpause = 0;
533697883Sgibbs	ahd->pause = PAUSE;
533797883Sgibbs	return (0);
533897883Sgibbs}
533997883Sgibbs
534097883Sgibbsvoid
534197883Sgibbsahd_softc_insert(struct ahd_softc *ahd)
534297883Sgibbs{
534397883Sgibbs	struct ahd_softc *list_ahd;
534497883Sgibbs
5345123579Sgibbs#if AIC_PCI_CONFIG > 0
534697883Sgibbs	/*
534797883Sgibbs	 * Second Function PCI devices need to inherit some
534897883Sgibbs	 * settings from function 0.
534997883Sgibbs	 */
535097883Sgibbs	if ((ahd->features & AHD_MULTI_FUNC) != 0) {
535197883Sgibbs		TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
5352123579Sgibbs			aic_dev_softc_t list_pci;
5353123579Sgibbs			aic_dev_softc_t pci;
535497883Sgibbs
535597883Sgibbs			list_pci = list_ahd->dev_softc;
535697883Sgibbs			pci = ahd->dev_softc;
5357123579Sgibbs			if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci)
5358123579Sgibbs			 && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) {
535997883Sgibbs				struct ahd_softc *master;
536097883Sgibbs				struct ahd_softc *slave;
536197883Sgibbs
5362123579Sgibbs				if (aic_get_pci_function(list_pci) == 0) {
536397883Sgibbs					master = list_ahd;
536497883Sgibbs					slave = ahd;
536597883Sgibbs				} else {
536697883Sgibbs					master = ahd;
536797883Sgibbs					slave = list_ahd;
536897883Sgibbs				}
536997883Sgibbs				slave->flags &= ~AHD_BIOS_ENABLED;
537097883Sgibbs				slave->flags |=
537197883Sgibbs				    master->flags & AHD_BIOS_ENABLED;
537297883Sgibbs				break;
537397883Sgibbs			}
537497883Sgibbs		}
537597883Sgibbs	}
537697883Sgibbs#endif
537797883Sgibbs
537897883Sgibbs	/*
537997883Sgibbs	 * Insertion sort into our list of softcs.
538097883Sgibbs	 */
538197883Sgibbs	list_ahd = TAILQ_FIRST(&ahd_tailq);
538297883Sgibbs	while (list_ahd != NULL
5383114623Sgibbs	    && ahd_softc_comp(ahd, list_ahd) <= 0)
538497883Sgibbs		list_ahd = TAILQ_NEXT(list_ahd, links);
538597883Sgibbs	if (list_ahd != NULL)
538697883Sgibbs		TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
538797883Sgibbs	else
538897883Sgibbs		TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
538997883Sgibbs	ahd->init_level++;
539097883Sgibbs}
539197883Sgibbs
539297883Sgibbsvoid
539397883Sgibbsahd_set_unit(struct ahd_softc *ahd, int unit)
539497883Sgibbs{
539597883Sgibbs	ahd->unit = unit;
539697883Sgibbs}
539797883Sgibbs
539897883Sgibbsvoid
539997883Sgibbsahd_set_name(struct ahd_softc *ahd, char *name)
540097883Sgibbs{
540197883Sgibbs	if (ahd->name != NULL)
540297883Sgibbs		free(ahd->name, M_DEVBUF);
540397883Sgibbs	ahd->name = name;
540497883Sgibbs}
540597883Sgibbs
540697883Sgibbsvoid
540797883Sgibbsahd_free(struct ahd_softc *ahd)
540897883Sgibbs{
540997883Sgibbs	int i;
541097883Sgibbs
5411123579Sgibbs	ahd_terminate_recovery_thread(ahd);
541297883Sgibbs	switch (ahd->init_level) {
541397883Sgibbs	default:
541497883Sgibbs	case 5:
541597883Sgibbs		ahd_shutdown(ahd);
541697883Sgibbs		/* FALLTHROUGH */
541797883Sgibbs	case 4:
5418123579Sgibbs		aic_dmamap_unload(ahd, ahd->shared_data_dmat,
5419123579Sgibbs				  ahd->shared_data_map.dmamap);
542097883Sgibbs		/* FALLTHROUGH */
542197883Sgibbs	case 3:
5422123579Sgibbs		aic_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
5423123579Sgibbs				ahd->shared_data_map.dmamap);
5424123579Sgibbs		aic_dmamap_destroy(ahd, ahd->shared_data_dmat,
5425123579Sgibbs				   ahd->shared_data_map.dmamap);
542697883Sgibbs		/* FALLTHROUGH */
542797883Sgibbs	case 2:
5428123579Sgibbs		aic_dma_tag_destroy(ahd, ahd->shared_data_dmat);
542997883Sgibbs	case 1:
543097883Sgibbs#ifndef __linux__
5431123579Sgibbs		aic_dma_tag_destroy(ahd, ahd->buffer_dmat);
543297883Sgibbs#endif
543397883Sgibbs		break;
543497883Sgibbs	case 0:
543597883Sgibbs		break;
543697883Sgibbs	}
543797883Sgibbs
543897883Sgibbs#ifndef __linux__
5439123579Sgibbs	aic_dma_tag_destroy(ahd, ahd->parent_dmat);
544097883Sgibbs#endif
544197883Sgibbs	ahd_platform_free(ahd);
5442114623Sgibbs	ahd_fini_scbdata(ahd);
544397883Sgibbs	for (i = 0; i < AHD_NUM_TARGETS; i++) {
544497883Sgibbs		struct ahd_tmode_tstate *tstate;
544597883Sgibbs
544697883Sgibbs		tstate = ahd->enabled_targets[i];
544797883Sgibbs		if (tstate != NULL) {
5448153072Sru#ifdef AHD_TARGET_MODE
544997883Sgibbs			int j;
545097883Sgibbs
545197883Sgibbs			for (j = 0; j < AHD_NUM_LUNS; j++) {
545297883Sgibbs				struct ahd_tmode_lstate *lstate;
545397883Sgibbs
545497883Sgibbs				lstate = tstate->enabled_luns[j];
545597883Sgibbs				if (lstate != NULL) {
545697883Sgibbs					xpt_free_path(lstate->path);
545797883Sgibbs					free(lstate, M_DEVBUF);
545897883Sgibbs				}
545997883Sgibbs			}
546097883Sgibbs#endif
546197883Sgibbs			free(tstate, M_DEVBUF);
546297883Sgibbs		}
546397883Sgibbs	}
5464153072Sru#ifdef AHD_TARGET_MODE
546597883Sgibbs	if (ahd->black_hole != NULL) {
546697883Sgibbs		xpt_free_path(ahd->black_hole->path);
546797883Sgibbs		free(ahd->black_hole, M_DEVBUF);
546897883Sgibbs	}
546997883Sgibbs#endif
547097883Sgibbs	if (ahd->name != NULL)
547197883Sgibbs		free(ahd->name, M_DEVBUF);
547297883Sgibbs	if (ahd->seep_config != NULL)
547397883Sgibbs		free(ahd->seep_config, M_DEVBUF);
5474107441Sscottl	if (ahd->saved_stack != NULL)
5475107441Sscottl		free(ahd->saved_stack, M_DEVBUF);
547697883Sgibbs#ifndef __FreeBSD__
547797883Sgibbs	free(ahd, M_DEVBUF);
547897883Sgibbs#endif
547997883Sgibbs	return;
548097883Sgibbs}
548197883Sgibbs
548297883Sgibbsvoid
548397883Sgibbsahd_shutdown(void *arg)
548497883Sgibbs{
548597883Sgibbs	struct	ahd_softc *ahd;
548697883Sgibbs
548797883Sgibbs	ahd = (struct ahd_softc *)arg;
548897883Sgibbs
5489109588Sgibbs	/*
5490109588Sgibbs	 * Stop periodic timer callbacks.
5491109588Sgibbs	 */
5492123579Sgibbs	aic_timer_stop(&ahd->reset_timer);
5493123579Sgibbs	aic_timer_stop(&ahd->stat_timer);
5494109588Sgibbs
549597883Sgibbs	/* This will reset most registers to 0, but not all */
5496115917Sgibbs	ahd_reset(ahd, /*reinit*/FALSE);
549797883Sgibbs}
549897883Sgibbs
549997883Sgibbs/*
550097883Sgibbs * Reset the controller and record some information about it
5501115917Sgibbs * that is only available just after a reset.  If "reinit" is
5502115917Sgibbs * non-zero, this reset occured after initial configuration
5503115917Sgibbs * and the caller requests that the chip be fully reinitialized
5504115917Sgibbs * to a runable state.  Chip interrupts are *not* enabled after
5505115917Sgibbs * a reinitialization.  The caller must enable interrupts via
5506115917Sgibbs * ahd_intr_enable().
550797883Sgibbs */
550897883Sgibbsint
5509115917Sgibbsahd_reset(struct ahd_softc *ahd, int reinit)
551097883Sgibbs{
551197883Sgibbs	u_int	 sxfrctl1;
551297883Sgibbs	int	 wait;
551397883Sgibbs	uint32_t cmd;
551497883Sgibbs
551597883Sgibbs	/*
551697883Sgibbs	 * Preserve the value of the SXFRCTL1 register for all channels.
551797883Sgibbs	 * It contains settings that affect termination and we don't want
551897883Sgibbs	 * to disturb the integrity of the bus.
551997883Sgibbs	 */
552097883Sgibbs	ahd_pause(ahd);
5521111954Sgibbs	ahd_update_modes(ahd);
5522111653Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
552397883Sgibbs	sxfrctl1 = ahd_inb(ahd, SXFRCTL1);
552497883Sgibbs
5525123579Sgibbs	cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
552697883Sgibbs	if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
552797883Sgibbs		uint32_t mod_cmd;
552897883Sgibbs
552997883Sgibbs		/*
553097883Sgibbs		 * A4 Razor #632
553197883Sgibbs		 * During the assertion of CHIPRST, the chip
553297883Sgibbs		 * does not disable its parity logic prior to
553397883Sgibbs		 * the start of the reset.  This may cause a
553497883Sgibbs		 * parity error to be detected and thus a
553597883Sgibbs		 * spurious SERR or PERR assertion.  Disble
553697883Sgibbs		 * PERR and SERR responses during the CHIPRST.
553797883Sgibbs		 */
553897883Sgibbs		mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN);
5539123579Sgibbs		aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
554097883Sgibbs				     mod_cmd, /*bytes*/2);
554197883Sgibbs	}
554297883Sgibbs	ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause);
554397883Sgibbs
554497883Sgibbs	/*
554597883Sgibbs	 * Ensure that the reset has finished.  We delay 1000us
554697883Sgibbs	 * prior to reading the register to make sure the chip
554797883Sgibbs	 * has sufficiently completed its reset to handle register
554897883Sgibbs	 * accesses.
554997883Sgibbs	 */
555097883Sgibbs	wait = 1000;
555197883Sgibbs	do {
5552123579Sgibbs		aic_delay(1000);
555397883Sgibbs	} while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK));
555497883Sgibbs
555597883Sgibbs	if (wait == 0) {
555697883Sgibbs		printf("%s: WARNING - Failed chip reset!  "
555797883Sgibbs		       "Trying to initialize anyway.\n", ahd_name(ahd));
5558199260Sattilio		AHD_FATAL_ERROR(ahd);
555997883Sgibbs	}
556097883Sgibbs	ahd_outb(ahd, HCNTRL, ahd->pause);
556197883Sgibbs
556297883Sgibbs	if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
556397883Sgibbs		/*
556497883Sgibbs		 * Clear any latched PCI error status and restore
556597883Sgibbs		 * previous SERR and PERR response enables.
556697883Sgibbs		 */
5567123579Sgibbs		aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
556897883Sgibbs				     0xFF, /*bytes*/1);
5569123579Sgibbs		aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
557097883Sgibbs				     cmd, /*bytes*/2);
557197883Sgibbs	}
5572111653Sgibbs
5573111653Sgibbs	/*
5574111653Sgibbs	 * Mode should be SCSI after a chip reset, but lets
5575111954Sgibbs	 * set it just to be safe.  We touch the MODE_PTR
5576111954Sgibbs	 * register directly so as to bypass the lazy update
5577111954Sgibbs	 * code in ahd_set_modes().
5578111653Sgibbs	 */
557997883Sgibbs	ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
5580111954Sgibbs	ahd_outb(ahd, MODE_PTR,
5581111954Sgibbs		 ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI));
558297883Sgibbs
558397883Sgibbs	/*
558497883Sgibbs	 * Restore SXFRCTL1.
558597883Sgibbs	 *
558697883Sgibbs	 * We must always initialize STPWEN to 1 before we
558797883Sgibbs	 * restore the saved values.  STPWEN is initialized
558897883Sgibbs	 * to a tri-state condition which can only be cleared
558997883Sgibbs	 * by turning it on.
559097883Sgibbs	 */
559197883Sgibbs	ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
559297883Sgibbs	ahd_outb(ahd, SXFRCTL1, sxfrctl1);
559397883Sgibbs
5594111653Sgibbs	/* Determine chip configuration */
5595111653Sgibbs	ahd->features &= ~AHD_WIDE;
5596111653Sgibbs	if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0)
5597111653Sgibbs		ahd->features |= AHD_WIDE;
5598111653Sgibbs
559997883Sgibbs	/*
560097883Sgibbs	 * If a recovery action has forced a chip reset,
5601111653Sgibbs	 * re-initialize the chip to our liking.
560297883Sgibbs	 */
5603115917Sgibbs	if (reinit != 0)
560497883Sgibbs		ahd_chip_init(ahd);
560597883Sgibbs
560697883Sgibbs	return (0);
560797883Sgibbs}
560897883Sgibbs
560997883Sgibbs/*
561097883Sgibbs * Determine the number of SCBs available on the controller
561197883Sgibbs */
561297883Sgibbsint
561397883Sgibbsahd_probe_scbs(struct ahd_softc *ahd) {
561497883Sgibbs	int i;
561597883Sgibbs
561697883Sgibbs	AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
561797883Sgibbs			 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
561897883Sgibbs	for (i = 0; i < AHD_SCB_MAX; i++) {
561997883Sgibbs		int j;
562097883Sgibbs
562197883Sgibbs		ahd_set_scbptr(ahd, i);
562297883Sgibbs		ahd_outw(ahd, SCB_BASE, i);
562397883Sgibbs		for (j = 2; j < 64; j++)
562497883Sgibbs			ahd_outb(ahd, SCB_BASE+j, 0);
562597883Sgibbs		/* Start out life as unallocated (needing an abort) */
562697883Sgibbs		ahd_outb(ahd, SCB_CONTROL, MK_MESSAGE);
562797883Sgibbs		if (ahd_inw_scbram(ahd, SCB_BASE) != i)
562897883Sgibbs			break;
562997883Sgibbs		ahd_set_scbptr(ahd, 0);
563097883Sgibbs		if (ahd_inw_scbram(ahd, SCB_BASE) != 0)
563197883Sgibbs			break;
563297883Sgibbs	}
563397883Sgibbs	return (i);
563497883Sgibbs}
563597883Sgibbs
563697883Sgibbsstatic void
563797883Sgibbsahd_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
563897883Sgibbs{
563997883Sgibbs	bus_addr_t *baddr;
564097883Sgibbs
564197883Sgibbs	baddr = (bus_addr_t *)arg;
564297883Sgibbs	*baddr = segs->ds_addr;
564397883Sgibbs}
564497883Sgibbs
564597883Sgibbsstatic void
564697883Sgibbsahd_initialize_hscbs(struct ahd_softc *ahd)
564797883Sgibbs{
564897883Sgibbs	int i;
564997883Sgibbs
565097883Sgibbs	for (i = 0; i < ahd->scb_data.maxhscbs; i++) {
565197883Sgibbs		ahd_set_scbptr(ahd, i);
565297883Sgibbs
565397883Sgibbs		/* Clear the control byte. */
565497883Sgibbs		ahd_outb(ahd, SCB_CONTROL, 0);
565597883Sgibbs
565697883Sgibbs		/* Set the next pointer */
565797883Sgibbs		ahd_outw(ahd, SCB_NEXT, SCB_LIST_NULL);
565897883Sgibbs	}
565997883Sgibbs}
566097883Sgibbs
566197883Sgibbsstatic int
566297883Sgibbsahd_init_scbdata(struct ahd_softc *ahd)
566397883Sgibbs{
5664102679Sgibbs	struct	scb_data *scb_data;
5665102679Sgibbs	int	i;
566697883Sgibbs
566797883Sgibbs	scb_data = &ahd->scb_data;
5668102679Sgibbs	TAILQ_INIT(&scb_data->free_scbs);
5669102679Sgibbs	for (i = 0; i < AHD_NUM_TARGETS * AHD_NUM_LUNS_NONPKT; i++)
5670102679Sgibbs		LIST_INIT(&scb_data->free_scb_lists[i]);
5671102679Sgibbs	LIST_INIT(&scb_data->any_dev_free_scb_list);
567297883Sgibbs	SLIST_INIT(&scb_data->hscb_maps);
567397883Sgibbs	SLIST_INIT(&scb_data->sg_maps);
567497883Sgibbs	SLIST_INIT(&scb_data->sense_maps);
567597883Sgibbs
567697883Sgibbs	/* Determine the number of hardware SCBs and initialize them */
567797883Sgibbs	scb_data->maxhscbs = ahd_probe_scbs(ahd);
567897883Sgibbs	if (scb_data->maxhscbs == 0) {
567997883Sgibbs		printf("%s: No SCB space found\n", ahd_name(ahd));
5680199260Sattilio		AHD_FATAL_ERROR(ahd);
568197883Sgibbs		return (ENXIO);
568297883Sgibbs	}
568397883Sgibbs
568497883Sgibbs	ahd_initialize_hscbs(ahd);
568597883Sgibbs
568697883Sgibbs	/*
568797883Sgibbs	 * Create our DMA tags.  These tags define the kinds of device
568897883Sgibbs	 * accessible memory allocations and memory mappings we will
568997883Sgibbs	 * need to perform during normal operation.
569097883Sgibbs	 *
569197883Sgibbs	 * Unless we need to further restrict the allocation, we rely
569297883Sgibbs	 * on the restrictions of the parent dmat, hence the common
569397883Sgibbs	 * use of MAXADDR and MAXSIZE.
569497883Sgibbs	 */
569597883Sgibbs
569697883Sgibbs	/* DMA tag for our hardware scb structures */
5697123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
569897883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
569997883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
570097883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
570197883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
570297883Sgibbs			       PAGE_SIZE, /*nsegments*/1,
570397883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
570497883Sgibbs			       /*flags*/0, &scb_data->hscb_dmat) != 0) {
570597883Sgibbs		goto error_exit;
570697883Sgibbs	}
570797883Sgibbs
570897883Sgibbs	scb_data->init_level++;
570997883Sgibbs
571097883Sgibbs	/* DMA tag for our S/G structures. */
5711123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8,
571297883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
571397883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
571497883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
571597883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
571697883Sgibbs			       ahd_sglist_allocsize(ahd), /*nsegments*/1,
571797883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
571897883Sgibbs			       /*flags*/0, &scb_data->sg_dmat) != 0) {
571997883Sgibbs		goto error_exit;
572097883Sgibbs	}
572197883Sgibbs#ifdef AHD_DEBUG
572297883Sgibbs	if ((ahd_debug & AHD_SHOW_MEMORY) != 0)
572397883Sgibbs		printf("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd),
572497883Sgibbs		       ahd_sglist_allocsize(ahd));
572597883Sgibbs#endif
572697883Sgibbs
572797883Sgibbs	scb_data->init_level++;
572897883Sgibbs
572997883Sgibbs	/* DMA tag for our sense buffers.  We allocate in page sized chunks */
5730123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
573197883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
573297883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
573397883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
573497883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
573597883Sgibbs			       PAGE_SIZE, /*nsegments*/1,
573697883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
573797883Sgibbs			       /*flags*/0, &scb_data->sense_dmat) != 0) {
573897883Sgibbs		goto error_exit;
573997883Sgibbs	}
574097883Sgibbs
574197883Sgibbs	scb_data->init_level++;
574297883Sgibbs
574397883Sgibbs	/* Perform initial CCB allocation */
5744168873Sscottl	while (ahd_alloc_scbs(ahd) != 0)
5745168873Sscottl		;
574697883Sgibbs
574797883Sgibbs	if (scb_data->numscbs == 0) {
574897883Sgibbs		printf("%s: ahd_init_scbdata - "
574997883Sgibbs		       "Unable to allocate initial scbs\n",
575097883Sgibbs		       ahd_name(ahd));
575197883Sgibbs		goto error_exit;
575297883Sgibbs	}
575397883Sgibbs
575497883Sgibbs	/*
575597883Sgibbs	 * Note that we were successfull
575697883Sgibbs	 */
575797883Sgibbs	return (0);
575897883Sgibbs
575997883Sgibbserror_exit:
576097883Sgibbs
576197883Sgibbs	return (ENOMEM);
576297883Sgibbs}
576397883Sgibbs
5764102679Sgibbsstatic struct scb *
5765102679Sgibbsahd_find_scb_by_tag(struct ahd_softc *ahd, u_int tag)
5766102679Sgibbs{
5767102679Sgibbs	struct scb *scb;
5768102679Sgibbs
5769102679Sgibbs	/*
5770102679Sgibbs	 * Look on the pending list.
5771102679Sgibbs	 */
5772102679Sgibbs	LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
5773102679Sgibbs		if (SCB_GET_TAG(scb) == tag)
5774102679Sgibbs			return (scb);
5775102679Sgibbs	}
5776102679Sgibbs
5777102679Sgibbs	/*
5778102679Sgibbs	 * Then on all of the collision free lists.
5779102679Sgibbs	 */
5780102679Sgibbs	TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
5781102679Sgibbs		struct scb *list_scb;
5782102679Sgibbs
5783102679Sgibbs		list_scb = scb;
5784102679Sgibbs		do {
5785102679Sgibbs			if (SCB_GET_TAG(list_scb) == tag)
5786102679Sgibbs				return (list_scb);
5787102679Sgibbs			list_scb = LIST_NEXT(list_scb, collision_links);
5788102679Sgibbs		} while (list_scb);
5789102679Sgibbs	}
5790102679Sgibbs
5791102679Sgibbs	/*
5792102679Sgibbs	 * And finally on the generic free list.
5793102679Sgibbs	 */
5794102679Sgibbs	LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
5795102679Sgibbs		if (SCB_GET_TAG(scb) == tag)
5796102679Sgibbs			return (scb);
5797102679Sgibbs	}
5798102679Sgibbs
5799102679Sgibbs	return (NULL);
5800102679Sgibbs}
5801102679Sgibbs
580297883Sgibbsstatic void
580397883Sgibbsahd_fini_scbdata(struct ahd_softc *ahd)
580497883Sgibbs{
580597883Sgibbs	struct scb_data *scb_data;
580697883Sgibbs
580797883Sgibbs	scb_data = &ahd->scb_data;
580897883Sgibbs	if (scb_data == NULL)
580997883Sgibbs		return;
581097883Sgibbs
581197883Sgibbs	switch (scb_data->init_level) {
581297883Sgibbs	default:
581397883Sgibbs	case 7:
581497883Sgibbs	{
581597883Sgibbs		struct map_node *sns_map;
581697883Sgibbs
581797883Sgibbs		while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) {
581897883Sgibbs			SLIST_REMOVE_HEAD(&scb_data->sense_maps, links);
5819123579Sgibbs			aic_dmamap_unload(ahd, scb_data->sense_dmat,
582097883Sgibbs					  sns_map->dmamap);
5821123579Sgibbs			aic_dmamem_free(ahd, scb_data->sense_dmat,
582297883Sgibbs					sns_map->vaddr, sns_map->dmamap);
582397883Sgibbs			free(sns_map, M_DEVBUF);
582497883Sgibbs		}
5825123579Sgibbs		aic_dma_tag_destroy(ahd, scb_data->sense_dmat);
582697883Sgibbs		/* FALLTHROUGH */
582797883Sgibbs	}
582897883Sgibbs	case 6:
582997883Sgibbs	{
583097883Sgibbs		struct map_node *sg_map;
583197883Sgibbs
583297883Sgibbs		while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) {
583397883Sgibbs			SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
5834123579Sgibbs			aic_dmamap_unload(ahd, scb_data->sg_dmat,
583597883Sgibbs					  sg_map->dmamap);
5836123579Sgibbs			aic_dmamem_free(ahd, scb_data->sg_dmat,
583797883Sgibbs					sg_map->vaddr, sg_map->dmamap);
583897883Sgibbs			free(sg_map, M_DEVBUF);
583997883Sgibbs		}
5840123579Sgibbs		aic_dma_tag_destroy(ahd, scb_data->sg_dmat);
584197883Sgibbs		/* FALLTHROUGH */
584297883Sgibbs	}
584397883Sgibbs	case 5:
584497883Sgibbs	{
584597883Sgibbs		struct map_node *hscb_map;
584697883Sgibbs
584797883Sgibbs		while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) {
584897883Sgibbs			SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links);
5849123579Sgibbs			aic_dmamap_unload(ahd, scb_data->hscb_dmat,
585097883Sgibbs					  hscb_map->dmamap);
5851123579Sgibbs			aic_dmamem_free(ahd, scb_data->hscb_dmat,
585297883Sgibbs					hscb_map->vaddr, hscb_map->dmamap);
585397883Sgibbs			free(hscb_map, M_DEVBUF);
585497883Sgibbs		}
5855123579Sgibbs		aic_dma_tag_destroy(ahd, scb_data->hscb_dmat);
585697883Sgibbs		/* FALLTHROUGH */
585797883Sgibbs	}
585897883Sgibbs	case 4:
585997883Sgibbs	case 3:
586097883Sgibbs	case 2:
586197883Sgibbs	case 1:
586297883Sgibbs	case 0:
586397883Sgibbs		break;
586497883Sgibbs	}
586597883Sgibbs}
586697883Sgibbs
586797883Sgibbs/*
586897883Sgibbs * DSP filter Bypass must be enabled until the first selection
586997883Sgibbs * after a change in bus mode (Razor #491 and #493).
587097883Sgibbs */
587197883Sgibbsstatic void
587297883Sgibbsahd_setup_iocell_workaround(struct ahd_softc *ahd)
587397883Sgibbs{
587497883Sgibbs	ahd_mode_state saved_modes;
587597883Sgibbs
587697883Sgibbs	saved_modes = ahd_save_modes(ahd);
587797883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
587897883Sgibbs	ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL)
587997883Sgibbs	       | BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS);
588097883Sgibbs	ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI));
5881104023Sgibbs#ifdef AHD_DEBUG
5882104023Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0)
5883104023Sgibbs		printf("%s: Setting up iocell workaround\n", ahd_name(ahd));
5884104023Sgibbs#endif
588597883Sgibbs	ahd_restore_modes(ahd, saved_modes);
5886116938Sgibbs	ahd->flags &= ~AHD_HAD_FIRST_SEL;
588797883Sgibbs}
588897883Sgibbs
588997883Sgibbsstatic void
589097883Sgibbsahd_iocell_first_selection(struct ahd_softc *ahd)
589197883Sgibbs{
589297883Sgibbs	ahd_mode_state	saved_modes;
589397883Sgibbs	u_int		sblkctl;
589497883Sgibbs
5895116938Sgibbs	if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0)
5896116938Sgibbs		return;
589797883Sgibbs	saved_modes = ahd_save_modes(ahd);
589897883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
589997883Sgibbs	sblkctl = ahd_inb(ahd, SBLKCTL);
590097883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
5901104023Sgibbs#ifdef AHD_DEBUG
5902104023Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0)
5903104023Sgibbs		printf("%s: iocell first selection\n", ahd_name(ahd));
5904104023Sgibbs#endif
590597883Sgibbs	if ((sblkctl & ENAB40) != 0) {
590697883Sgibbs		ahd_outb(ahd, DSPDATACTL,
590797883Sgibbs			 ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB);
5908104023Sgibbs#ifdef AHD_DEBUG
5909104023Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
5910104023Sgibbs			printf("%s: BYPASS now disabled\n", ahd_name(ahd));
5911104023Sgibbs#endif
591297883Sgibbs	}
591397883Sgibbs	ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI));
591497883Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
591597883Sgibbs	ahd_restore_modes(ahd, saved_modes);
5916116938Sgibbs	ahd->flags |= AHD_HAD_FIRST_SEL;
591797883Sgibbs}
591897883Sgibbs
5919102679Sgibbs/*************************** SCB Management ***********************************/
5920102679Sgibbsstatic void
5921102679Sgibbsahd_add_col_list(struct ahd_softc *ahd, struct scb *scb, u_int col_idx)
5922102679Sgibbs{
5923102679Sgibbs	struct	scb_list *free_list;
5924102679Sgibbs	struct	scb_tailq *free_tailq;
5925102679Sgibbs	struct	scb *first_scb;
5926102679Sgibbs
5927102679Sgibbs	scb->flags |= SCB_ON_COL_LIST;
5928102679Sgibbs	AHD_SET_SCB_COL_IDX(scb, col_idx);
5929102679Sgibbs	free_list = &ahd->scb_data.free_scb_lists[col_idx];
5930102679Sgibbs	free_tailq = &ahd->scb_data.free_scbs;
5931102679Sgibbs	first_scb = LIST_FIRST(free_list);
5932102679Sgibbs	if (first_scb != NULL) {
5933102679Sgibbs		LIST_INSERT_AFTER(first_scb, scb, collision_links);
5934102679Sgibbs	} else {
5935102679Sgibbs		LIST_INSERT_HEAD(free_list, scb, collision_links);
5936102679Sgibbs		TAILQ_INSERT_TAIL(free_tailq, scb, links.tqe);
5937102679Sgibbs	}
5938102679Sgibbs}
5939102679Sgibbs
5940102679Sgibbsstatic void
5941102679Sgibbsahd_rem_col_list(struct ahd_softc *ahd, struct scb *scb)
5942102679Sgibbs{
5943102679Sgibbs	struct	scb_list *free_list;
5944102679Sgibbs	struct	scb_tailq *free_tailq;
5945102679Sgibbs	struct	scb *first_scb;
5946102679Sgibbs	u_int	col_idx;
5947102679Sgibbs
5948102679Sgibbs	scb->flags &= ~SCB_ON_COL_LIST;
5949102679Sgibbs	col_idx = AHD_GET_SCB_COL_IDX(ahd, scb);
5950102679Sgibbs	free_list = &ahd->scb_data.free_scb_lists[col_idx];
5951102679Sgibbs	free_tailq = &ahd->scb_data.free_scbs;
5952102679Sgibbs	first_scb = LIST_FIRST(free_list);
5953102679Sgibbs	if (first_scb == scb) {
5954102679Sgibbs		struct scb *next_scb;
5955102679Sgibbs
5956102679Sgibbs		/*
5957102679Sgibbs		 * Maintain order in the collision free
5958102679Sgibbs		 * lists for fairness if this device has
5959102679Sgibbs		 * other colliding tags active.
5960102679Sgibbs		 */
5961102679Sgibbs		next_scb = LIST_NEXT(scb, collision_links);
5962102679Sgibbs		if (next_scb != NULL) {
5963102679Sgibbs			TAILQ_INSERT_AFTER(free_tailq, scb,
5964102679Sgibbs					   next_scb, links.tqe);
5965102679Sgibbs		}
5966102679Sgibbs		TAILQ_REMOVE(free_tailq, scb, links.tqe);
5967102679Sgibbs	}
5968102679Sgibbs	LIST_REMOVE(scb, collision_links);
5969102679Sgibbs}
5970102679Sgibbs
5971102679Sgibbs/*
5972102679Sgibbs * Get a free scb. If there are none, see if we can allocate a new SCB.
5973102679Sgibbs */
5974102679Sgibbsstruct scb *
5975102679Sgibbsahd_get_scb(struct ahd_softc *ahd, u_int col_idx)
5976102679Sgibbs{
5977102679Sgibbs	struct scb *scb;
5978102679Sgibbs	int tries;
5979102679Sgibbs
5980102679Sgibbs	tries = 0;
5981102679Sgibbslook_again:
5982102679Sgibbs	TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
5983102679Sgibbs		if (AHD_GET_SCB_COL_IDX(ahd, scb) != col_idx) {
5984102679Sgibbs			ahd_rem_col_list(ahd, scb);
5985102679Sgibbs			goto found;
5986102679Sgibbs		}
5987102679Sgibbs	}
5988102679Sgibbs	if ((scb = LIST_FIRST(&ahd->scb_data.any_dev_free_scb_list)) == NULL) {
5989102679Sgibbs
5990102679Sgibbs		if (tries++ != 0)
5991102679Sgibbs			return (NULL);
5992168873Sscottl		if (ahd_alloc_scbs(ahd) == 0)
5993168873Sscottl			return (NULL);
5994102679Sgibbs		goto look_again;
5995102679Sgibbs	}
5996102679Sgibbs	LIST_REMOVE(scb, links.le);
5997102679Sgibbs	if (col_idx != AHD_NEVER_COL_IDX
5998102679Sgibbs	 && (scb->col_scb != NULL)
5999102679Sgibbs	 && (scb->col_scb->flags & SCB_ACTIVE) == 0) {
6000102679Sgibbs		LIST_REMOVE(scb->col_scb, links.le);
6001102679Sgibbs		ahd_add_col_list(ahd, scb->col_scb, col_idx);
6002102679Sgibbs	}
6003102679Sgibbsfound:
6004102679Sgibbs	scb->flags |= SCB_ACTIVE;
6005102679Sgibbs	return (scb);
6006102679Sgibbs}
6007102679Sgibbs
6008102679Sgibbs/*
6009102679Sgibbs * Return an SCB resource to the free list.
6010102679Sgibbs */
601197883Sgibbsvoid
6012102679Sgibbsahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
6013102679Sgibbs{
6014102679Sgibbs
6015102679Sgibbs	/* Clean up for the next user */
6016102679Sgibbs	scb->flags = SCB_FLAG_NONE;
6017102679Sgibbs	scb->hscb->control = 0;
6018114623Sgibbs	ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
6019102679Sgibbs
6020102679Sgibbs	if (scb->col_scb == NULL) {
6021102679Sgibbs
6022102679Sgibbs		/*
6023102679Sgibbs		 * No collision possible.  Just free normally.
6024102679Sgibbs		 */
6025102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6026102679Sgibbs				 scb, links.le);
6027102679Sgibbs	} else if ((scb->col_scb->flags & SCB_ON_COL_LIST) != 0) {
6028102679Sgibbs
6029102679Sgibbs		/*
6030102679Sgibbs		 * The SCB we might have collided with is on
6031102679Sgibbs		 * a free collision list.  Put both SCBs on
6032102679Sgibbs		 * the generic list.
6033102679Sgibbs		 */
6034102679Sgibbs		ahd_rem_col_list(ahd, scb->col_scb);
6035102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6036102679Sgibbs				 scb, links.le);
6037102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6038102679Sgibbs				 scb->col_scb, links.le);
6039102679Sgibbs	} else if ((scb->col_scb->flags
6040102679Sgibbs		  & (SCB_PACKETIZED|SCB_ACTIVE)) == SCB_ACTIVE
6041102679Sgibbs		&& (scb->col_scb->hscb->control & TAG_ENB) != 0) {
6042102679Sgibbs
6043102679Sgibbs		/*
6044102679Sgibbs		 * The SCB we might collide with on the next allocation
6045102679Sgibbs		 * is still active in a non-packetized, tagged, context.
6046102679Sgibbs		 * Put us on the SCB collision list.
6047102679Sgibbs		 */
6048102679Sgibbs		ahd_add_col_list(ahd, scb,
6049102679Sgibbs				 AHD_GET_SCB_COL_IDX(ahd, scb->col_scb));
6050102679Sgibbs	} else {
6051102679Sgibbs		/*
6052102679Sgibbs		 * The SCB we might collide with on the next allocation
6053102679Sgibbs		 * is either active in a packetized context, or free.
6054102679Sgibbs		 * Since we can't collide, put this SCB on the generic
6055102679Sgibbs		 * free list.
6056102679Sgibbs		 */
6057102679Sgibbs		LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
6058102679Sgibbs				 scb, links.le);
6059102679Sgibbs	}
6060102679Sgibbs
6061123579Sgibbs	aic_platform_scb_free(ahd, scb);
6062102679Sgibbs}
6063102679Sgibbs
6064168873Sscottlint
606597883Sgibbsahd_alloc_scbs(struct ahd_softc *ahd)
606697883Sgibbs{
606797883Sgibbs	struct scb_data *scb_data;
606897883Sgibbs	struct scb	*next_scb;
606997883Sgibbs	struct hardware_scb *hscb;
607097883Sgibbs	struct map_node *hscb_map;
607197883Sgibbs	struct map_node *sg_map;
607297883Sgibbs	struct map_node *sense_map;
607397883Sgibbs	uint8_t		*segs;
607497883Sgibbs	uint8_t		*sense_data;
607597883Sgibbs	bus_addr_t	 hscb_busaddr;
607697883Sgibbs	bus_addr_t	 sg_busaddr;
607797883Sgibbs	bus_addr_t	 sense_busaddr;
607897883Sgibbs	int		 newcount;
607997883Sgibbs	int		 i;
608097883Sgibbs
608197883Sgibbs	scb_data = &ahd->scb_data;
608297883Sgibbs	if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC)
608397883Sgibbs		/* Can't allocate any more */
6084168873Sscottl		return (0);
608597883Sgibbs
608697883Sgibbs	if (scb_data->scbs_left != 0) {
608797883Sgibbs		int offset;
608897883Sgibbs
608997883Sgibbs		offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left;
609097883Sgibbs		hscb_map = SLIST_FIRST(&scb_data->hscb_maps);
609197883Sgibbs		hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset];
6092123579Sgibbs		hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb));
609397883Sgibbs	} else {
609497883Sgibbs		hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT);
609597883Sgibbs
609697883Sgibbs		if (hscb_map == NULL)
6097168873Sscottl			return (0);
609897883Sgibbs
609997883Sgibbs		/* Allocate the next batch of hardware SCBs */
6100123579Sgibbs		if (aic_dmamem_alloc(ahd, scb_data->hscb_dmat,
610197883Sgibbs				     (void **)&hscb_map->vaddr,
6102219577Smarius				     BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
6103219577Smarius				     &hscb_map->dmamap) != 0) {
610497883Sgibbs			free(hscb_map, M_DEVBUF);
6105168873Sscottl			return (0);
610697883Sgibbs		}
610797883Sgibbs
610897883Sgibbs		SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links);
610997883Sgibbs
6110123579Sgibbs		aic_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap,
611197883Sgibbs				hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
6112123579Sgibbs				&hscb_map->busaddr, /*flags*/0);
611397883Sgibbs
611497883Sgibbs		hscb = (struct hardware_scb *)hscb_map->vaddr;
6115123579Sgibbs		hscb_busaddr = hscb_map->busaddr;
611697883Sgibbs		scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb);
611797883Sgibbs	}
611897883Sgibbs
611997883Sgibbs	if (scb_data->sgs_left != 0) {
612097883Sgibbs		int offset;
612197883Sgibbs
6122114623Sgibbs		offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd))
6123114623Sgibbs		       - scb_data->sgs_left) * ahd_sglist_size(ahd);
612497883Sgibbs		sg_map = SLIST_FIRST(&scb_data->sg_maps);
612597883Sgibbs		segs = sg_map->vaddr + offset;
6126123579Sgibbs		sg_busaddr = sg_map->busaddr + offset;
612797883Sgibbs	} else {
612897883Sgibbs		sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
612997883Sgibbs
613097883Sgibbs		if (sg_map == NULL)
6131168873Sscottl			return (0);
613297883Sgibbs
613397883Sgibbs		/* Allocate the next batch of S/G lists */
6134123579Sgibbs		if (aic_dmamem_alloc(ahd, scb_data->sg_dmat,
613597883Sgibbs				     (void **)&sg_map->vaddr,
6136219577Smarius				     BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
6137219577Smarius				     &sg_map->dmamap) != 0) {
613897883Sgibbs			free(sg_map, M_DEVBUF);
6139168873Sscottl			return (0);
614097883Sgibbs		}
614197883Sgibbs
614297883Sgibbs		SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
614397883Sgibbs
6144123579Sgibbs		aic_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap,
614597883Sgibbs				sg_map->vaddr, ahd_sglist_allocsize(ahd),
6146123579Sgibbs				ahd_dmamap_cb, &sg_map->busaddr, /*flags*/0);
614797883Sgibbs
614897883Sgibbs		segs = sg_map->vaddr;
6149123579Sgibbs		sg_busaddr = sg_map->busaddr;
615097883Sgibbs		scb_data->sgs_left =
615197883Sgibbs		    ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd);
615297883Sgibbs#ifdef AHD_DEBUG
615397883Sgibbs		if (ahd_debug & AHD_SHOW_MEMORY)
615497883Sgibbs			printf("Mapped SG data\n");
615597883Sgibbs#endif
615697883Sgibbs	}
615797883Sgibbs
615897883Sgibbs	if (scb_data->sense_left != 0) {
615997883Sgibbs		int offset;
616097883Sgibbs
616197883Sgibbs		offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left);
616297883Sgibbs		sense_map = SLIST_FIRST(&scb_data->sense_maps);
616397883Sgibbs		sense_data = sense_map->vaddr + offset;
6164123579Sgibbs		sense_busaddr = sense_map->busaddr + offset;
616597883Sgibbs	} else {
616697883Sgibbs		sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT);
616797883Sgibbs
616897883Sgibbs		if (sense_map == NULL)
6169168873Sscottl			return (0);
617097883Sgibbs
617197883Sgibbs		/* Allocate the next batch of sense buffers */
6172123579Sgibbs		if (aic_dmamem_alloc(ahd, scb_data->sense_dmat,
617397883Sgibbs				     (void **)&sense_map->vaddr,
617497883Sgibbs				     BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) {
617597883Sgibbs			free(sense_map, M_DEVBUF);
6176168873Sscottl			return (0);
617797883Sgibbs		}
617897883Sgibbs
617997883Sgibbs		SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links);
618097883Sgibbs
6181123579Sgibbs		aic_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap,
618297883Sgibbs				sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
6183123579Sgibbs				&sense_map->busaddr, /*flags*/0);
618497883Sgibbs
618597883Sgibbs		sense_data = sense_map->vaddr;
6186123579Sgibbs		sense_busaddr = sense_map->busaddr;
618797883Sgibbs		scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE;
618897883Sgibbs#ifdef AHD_DEBUG
618997883Sgibbs		if (ahd_debug & AHD_SHOW_MEMORY)
619097883Sgibbs			printf("Mapped sense data\n");
619197883Sgibbs#endif
619297883Sgibbs	}
619397883Sgibbs
619497883Sgibbs	newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
619597883Sgibbs	newcount = MIN(newcount, scb_data->sgs_left);
619697883Sgibbs	newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
619797883Sgibbs	scb_data->sense_left -= newcount;
619897883Sgibbs	scb_data->scbs_left -= newcount;
619997883Sgibbs	scb_data->sgs_left -= newcount;
620097883Sgibbs	for (i = 0; i < newcount; i++) {
6201125448Sgibbs		struct scb_platform_data *pdata;
6202102679Sgibbs		u_int col_tag;
620397883Sgibbs#ifndef __linux__
620497883Sgibbs		int error;
620597883Sgibbs#endif
6206125448Sgibbs
620797883Sgibbs		next_scb = (struct scb *)malloc(sizeof(*next_scb),
620897883Sgibbs						M_DEVBUF, M_NOWAIT);
620997883Sgibbs		if (next_scb == NULL)
621097883Sgibbs			break;
621197883Sgibbs
621297883Sgibbs		pdata = (struct scb_platform_data *)malloc(sizeof(*pdata),
621397883Sgibbs							   M_DEVBUF, M_NOWAIT);
621497883Sgibbs		if (pdata == NULL) {
621597883Sgibbs			free(next_scb, M_DEVBUF);
621697883Sgibbs			break;
621797883Sgibbs		}
621897883Sgibbs		next_scb->platform_data = pdata;
621997883Sgibbs		next_scb->hscb_map = hscb_map;
622097883Sgibbs		next_scb->sg_map = sg_map;
622197883Sgibbs		next_scb->sense_map = sense_map;
622297883Sgibbs		next_scb->sg_list = segs;
622397883Sgibbs		next_scb->sense_data = sense_data;
622497883Sgibbs		next_scb->sense_busaddr = sense_busaddr;
6225115331Sgibbs		memset(hscb, 0, sizeof(*hscb));
622697883Sgibbs		next_scb->hscb = hscb;
6227123579Sgibbs		hscb->hscb_busaddr = aic_htole32(hscb_busaddr);
622897883Sgibbs
622997883Sgibbs		/*
623097883Sgibbs		 * The sequencer always starts with the second entry.
623197883Sgibbs		 * The first entry is embedded in the scb.
623297883Sgibbs		 */
623397883Sgibbs		next_scb->sg_list_busaddr = sg_busaddr;
623497883Sgibbs		if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
623597883Sgibbs			next_scb->sg_list_busaddr
623697883Sgibbs			    += sizeof(struct ahd_dma64_seg);
623797883Sgibbs		else
623897883Sgibbs			next_scb->sg_list_busaddr += sizeof(struct ahd_dma_seg);
623997883Sgibbs		next_scb->ahd_softc = ahd;
6240102679Sgibbs		next_scb->flags = SCB_FLAG_NONE;
624197883Sgibbs#ifndef __linux__
6242123579Sgibbs		error = aic_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0,
624397883Sgibbs					  &next_scb->dmamap);
624497883Sgibbs		if (error != 0) {
624597883Sgibbs			free(next_scb, M_DEVBUF);
624697883Sgibbs			free(pdata, M_DEVBUF);
624797883Sgibbs			break;
624897883Sgibbs		}
624997883Sgibbs#endif
6250123579Sgibbs		next_scb->hscb->tag = aic_htole16(scb_data->numscbs);
6251102679Sgibbs		col_tag = scb_data->numscbs ^ 0x100;
6252102679Sgibbs		next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);
6253102679Sgibbs		if (next_scb->col_scb != NULL)
6254102679Sgibbs			next_scb->col_scb->col_scb = next_scb;
6255168807Sscottl		aic_timer_init(&next_scb->io_timer);
6256102679Sgibbs		ahd_free_scb(ahd, next_scb);
625797883Sgibbs		hscb++;
625897883Sgibbs		hscb_busaddr += sizeof(*hscb);
625997883Sgibbs		segs += ahd_sglist_size(ahd);
626097883Sgibbs		sg_busaddr += ahd_sglist_size(ahd);
626197883Sgibbs		sense_data += AHD_SENSE_BUFSIZE;
626297883Sgibbs		sense_busaddr += AHD_SENSE_BUFSIZE;
626397883Sgibbs		scb_data->numscbs++;
626497883Sgibbs	}
6265168873Sscottl	return (i);
626697883Sgibbs}
626797883Sgibbs
626897883Sgibbsvoid
626997883Sgibbsahd_controller_info(struct ahd_softc *ahd, char *buf)
627097883Sgibbs{
627197883Sgibbs	const char *speed;
627297883Sgibbs	const char *type;
627397883Sgibbs	int len;
627497883Sgibbs
627597883Sgibbs	len = sprintf(buf, "%s: ", ahd_chip_names[ahd->chip & AHD_CHIPID_MASK]);
627697883Sgibbs	buf += len;
627797883Sgibbs
627897883Sgibbs	speed = "Ultra320 ";
627997883Sgibbs	if ((ahd->features & AHD_WIDE) != 0) {
6280102679Sgibbs		type = "Wide ";
628197883Sgibbs	} else {
6282102679Sgibbs		type = "Single ";
628397883Sgibbs	}
628497883Sgibbs	len = sprintf(buf, "%s%sChannel %c, SCSI Id=%d, ",
628597883Sgibbs		      speed, type, ahd->channel, ahd->our_id);
628697883Sgibbs	buf += len;
628797883Sgibbs
628897883Sgibbs	sprintf(buf, "%s, %d SCBs", ahd->bus_description,
628997883Sgibbs		ahd->scb_data.maxhscbs);
629097883Sgibbs}
629197883Sgibbs
629297883Sgibbsstatic const char *channel_strings[] = {
629397883Sgibbs	"Primary Low",
629497883Sgibbs	"Primary High",
629597883Sgibbs	"Secondary Low",
629697883Sgibbs	"Secondary High"
629797883Sgibbs};
629897883Sgibbs
629997883Sgibbsstatic const char *termstat_strings[] = {
630097883Sgibbs	"Terminated Correctly",
630197883Sgibbs	"Over Terminated",
630297883Sgibbs	"Under Terminated",
630397883Sgibbs	"Not Configured"
630497883Sgibbs};
630597883Sgibbs
630697883Sgibbs/*
630797883Sgibbs * Start the board, ready for normal operation
630897883Sgibbs */
630997883Sgibbsint
631097883Sgibbsahd_init(struct ahd_softc *ahd)
631197883Sgibbs{
6312102679Sgibbs	uint8_t		*next_vaddr;
6313102679Sgibbs	bus_addr_t	 next_baddr;
6314102679Sgibbs	size_t		 driver_data_size;
6315102679Sgibbs	int		 i;
6316102679Sgibbs	int		 error;
6317102679Sgibbs	u_int		 warn_user;
6318102679Sgibbs	uint8_t		 current_sensing;
6319102679Sgibbs	uint8_t		 fstat;
632097883Sgibbs
632197883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
632297883Sgibbs
6323107441Sscottl	ahd->stack_size = ahd_probe_stack_size(ahd);
6324107441Sscottl	ahd->saved_stack = malloc(ahd->stack_size * sizeof(uint16_t),
6325107441Sscottl				  M_DEVBUF, M_NOWAIT);
6326107441Sscottl	if (ahd->saved_stack == NULL)
6327107441Sscottl		return (ENOMEM);
6328107441Sscottl
632997883Sgibbs	/*
633097883Sgibbs	 * Verify that the compiler hasn't over-agressively
633197883Sgibbs	 * padded important structures.
633297883Sgibbs	 */
633397883Sgibbs	if (sizeof(struct hardware_scb) != 64)
633497883Sgibbs		panic("Hardware SCB size is incorrect");
633597883Sgibbs
633697883Sgibbs#ifdef AHD_DEBUG
633797883Sgibbs	if ((ahd_debug & AHD_DEBUG_SEQUENCER) != 0)
633897883Sgibbs		ahd->flags |= AHD_SEQUENCER_DEBUG;
633997883Sgibbs#endif
634097883Sgibbs
634197883Sgibbs	/*
634297883Sgibbs	 * Default to allowing initiator operations.
634397883Sgibbs	 */
634497883Sgibbs	ahd->flags |= AHD_INITIATORROLE;
634597883Sgibbs
634697883Sgibbs	/*
634797883Sgibbs	 * Only allow target mode features if this unit has them enabled.
634897883Sgibbs	 */
634997883Sgibbs	if ((AHD_TMODE_ENABLE & (0x1 << ahd->unit)) == 0)
635097883Sgibbs		ahd->features &= ~AHD_TARGETMODE;
635197883Sgibbs
635297883Sgibbs#ifndef __linux__
635397883Sgibbs	/* DMA tag for mapping buffers into device visible space. */
6354123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
635597883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
6356114623Sgibbs			       /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING
6357114623Sgibbs					? (bus_addr_t)0x7FFFFFFFFFULL
6358114623Sgibbs					: BUS_SPACE_MAXADDR_32BIT,
635997883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
636097883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
6361108479Sscottl			       /*maxsize*/(AHD_NSEG - 1) * PAGE_SIZE,
6362108479Sscottl			       /*nsegments*/AHD_NSEG,
636397883Sgibbs			       /*maxsegsz*/AHD_MAXTRANSFER_SIZE,
636497883Sgibbs			       /*flags*/BUS_DMA_ALLOCNOW,
636597883Sgibbs			       &ahd->buffer_dmat) != 0) {
636697883Sgibbs		return (ENOMEM);
636797883Sgibbs	}
636897883Sgibbs#endif
636997883Sgibbs
637097883Sgibbs	ahd->init_level++;
637197883Sgibbs
637297883Sgibbs	/*
637397883Sgibbs	 * DMA tag for our command fifos and other data in system memory
637497883Sgibbs	 * the card's sequencer must be able to access.  For initiator
637597883Sgibbs	 * roles, we need to allocate space for the qoutfifo.  When providing
637697883Sgibbs	 * for the target mode role, we must additionally provide space for
637797883Sgibbs	 * the incoming target command fifo.
637897883Sgibbs	 */
6379129134Sgibbs	driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
6380129134Sgibbs			 + sizeof(struct hardware_scb);
638197883Sgibbs	if ((ahd->features & AHD_TARGETMODE) != 0)
638297883Sgibbs		driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
638397883Sgibbs	if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0)
638497883Sgibbs		driver_data_size += PKT_OVERRUN_BUFSIZE;
6385123579Sgibbs	if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
638697883Sgibbs			       /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
638797883Sgibbs			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
638897883Sgibbs			       /*highaddr*/BUS_SPACE_MAXADDR,
638997883Sgibbs			       /*filter*/NULL, /*filterarg*/NULL,
639097883Sgibbs			       driver_data_size,
639197883Sgibbs			       /*nsegments*/1,
639297883Sgibbs			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
639397883Sgibbs			       /*flags*/0, &ahd->shared_data_dmat) != 0) {
639497883Sgibbs		return (ENOMEM);
639597883Sgibbs	}
639697883Sgibbs
639797883Sgibbs	ahd->init_level++;
639897883Sgibbs
639997883Sgibbs	/* Allocation of driver data */
6400123579Sgibbs	if (aic_dmamem_alloc(ahd, ahd->shared_data_dmat,
6401123579Sgibbs			     (void **)&ahd->shared_data_map.vaddr,
6402219577Smarius			     BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
6403123579Sgibbs			     &ahd->shared_data_map.dmamap) != 0) {
640497883Sgibbs		return (ENOMEM);
640597883Sgibbs	}
640697883Sgibbs
640797883Sgibbs	ahd->init_level++;
640897883Sgibbs
640997883Sgibbs	/* And permanently map it in */
6410123579Sgibbs	aic_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
6411123579Sgibbs			ahd->shared_data_map.vaddr, driver_data_size,
6412123579Sgibbs			ahd_dmamap_cb, &ahd->shared_data_map.busaddr,
6413123579Sgibbs			/*flags*/0);
6414125448Sgibbs	ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
6415102679Sgibbs	next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
6416123579Sgibbs	next_baddr = ahd->shared_data_map.busaddr
6417125448Sgibbs		   + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
641897883Sgibbs	if ((ahd->features & AHD_TARGETMODE) != 0) {
6419102679Sgibbs		ahd->targetcmds = (struct target_cmd *)next_vaddr;
6420102679Sgibbs		next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
6421102679Sgibbs		next_baddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
642297883Sgibbs	}
642397883Sgibbs
6424102679Sgibbs	if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
6425102679Sgibbs		ahd->overrun_buf = next_vaddr;
6426102679Sgibbs		next_vaddr += PKT_OVERRUN_BUFSIZE;
6427102679Sgibbs		next_baddr += PKT_OVERRUN_BUFSIZE;
6428102679Sgibbs	}
642997883Sgibbs
6430129134Sgibbs	/*
6431129134Sgibbs	 * We need one SCB to serve as the "next SCB".  Since the
6432129134Sgibbs	 * tag identifier in this SCB will never be used, there is
6433129134Sgibbs	 * no point in using a valid HSCB tag from an SCB pulled from
6434129134Sgibbs	 * the standard free pool.  So, we allocate this "sentinel"
6435129134Sgibbs	 * specially from the DMA safe memory chunk used for the QOUTFIFO.
6436129134Sgibbs	 */
6437129134Sgibbs	ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
6438129134Sgibbs	ahd->next_queued_hscb_map = &ahd->shared_data_map;
6439129134Sgibbs	ahd->next_queued_hscb->hscb_busaddr = aic_htole32(next_baddr);
6440129134Sgibbs
644197883Sgibbs	ahd->init_level++;
644297883Sgibbs
644397883Sgibbs	/* Allocate SCB data now that buffer_dmat is initialized */
644497883Sgibbs	if (ahd_init_scbdata(ahd) != 0)
644597883Sgibbs		return (ENOMEM);
644697883Sgibbs
644797883Sgibbs	if ((ahd->flags & AHD_INITIATORROLE) == 0)
644897883Sgibbs		ahd->flags &= ~AHD_RESET_BUS_A;
644997883Sgibbs
6450107441Sscottl	/*
6451107441Sscottl	 * Before committing these settings to the chip, give
6452107441Sscottl	 * the OSM one last chance to modify our configuration.
6453107441Sscottl	 */
6454107441Sscottl	ahd_platform_init(ahd);
6455107441Sscottl
6456107441Sscottl	/* Bring up the chip. */
645797883Sgibbs	ahd_chip_init(ahd);
645897883Sgibbs
645997883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
646097883Sgibbs
646197883Sgibbs	if ((ahd->flags & AHD_CURRENT_SENSING) == 0)
646297883Sgibbs		goto init_done;
646397883Sgibbs
646497883Sgibbs	/*
646597883Sgibbs	 * Verify termination based on current draw and
646697883Sgibbs	 * warn user if the bus is over/under terminated.
646797883Sgibbs	 */
646897883Sgibbs	error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL,
646997883Sgibbs				   CURSENSE_ENB);
647097883Sgibbs	if (error != 0) {
647197883Sgibbs		printf("%s: current sensing timeout 1\n", ahd_name(ahd));
647297883Sgibbs		goto init_done;
647397883Sgibbs	}
647497883Sgibbs	for (i = 20, fstat = FLX_FSTAT_BUSY;
647597883Sgibbs	     (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) {
647697883Sgibbs		error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat);
647797883Sgibbs		if (error != 0) {
647897883Sgibbs			printf("%s: current sensing timeout 2\n",
647997883Sgibbs			       ahd_name(ahd));
648097883Sgibbs			goto init_done;
648197883Sgibbs		}
648297883Sgibbs	}
648397883Sgibbs	if (i == 0) {
648497883Sgibbs		printf("%s: Timedout during current-sensing test\n",
648597883Sgibbs		       ahd_name(ahd));
648697883Sgibbs		goto init_done;
648797883Sgibbs	}
648897883Sgibbs
648997883Sgibbs	/* Latch Current Sensing status. */
649097883Sgibbs	error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, &current_sensing);
649197883Sgibbs	if (error != 0) {
649297883Sgibbs		printf("%s: current sensing timeout 3\n", ahd_name(ahd));
649397883Sgibbs		goto init_done;
649497883Sgibbs	}
649597883Sgibbs
649697883Sgibbs	/* Diable current sensing. */
649797883Sgibbs	ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
649897883Sgibbs
649997883Sgibbs#ifdef AHD_DEBUG
650097883Sgibbs	if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) {
650197883Sgibbs		printf("%s: current_sensing == 0x%x\n",
650297883Sgibbs		       ahd_name(ahd), current_sensing);
650397883Sgibbs	}
650497883Sgibbs#endif
650597883Sgibbs	warn_user = 0;
650697883Sgibbs	for (i = 0; i < 4; i++, current_sensing >>= FLX_CSTAT_SHIFT) {
650797883Sgibbs		u_int term_stat;
650897883Sgibbs
650997883Sgibbs		term_stat = (current_sensing & FLX_CSTAT_MASK);
651097883Sgibbs		switch (term_stat) {
651197883Sgibbs		case FLX_CSTAT_OVER:
651297883Sgibbs		case FLX_CSTAT_UNDER:
651397883Sgibbs			warn_user++;
651497883Sgibbs		case FLX_CSTAT_INVALID:
651597883Sgibbs		case FLX_CSTAT_OKAY:
651697883Sgibbs			if (warn_user == 0 && bootverbose == 0)
651797883Sgibbs				break;
651897883Sgibbs			printf("%s: %s Channel %s\n", ahd_name(ahd),
651997883Sgibbs			       channel_strings[i], termstat_strings[term_stat]);
652097883Sgibbs			break;
652197883Sgibbs		}
652297883Sgibbs	}
652397883Sgibbs	if (warn_user) {
652497883Sgibbs		printf("%s: WARNING. Termination is not configured correctly.\n"
652597883Sgibbs		       "%s: WARNING. SCSI bus operations may FAIL.\n",
652697883Sgibbs		       ahd_name(ahd), ahd_name(ahd));
6527199260Sattilio		AHD_CORRECTABLE_ERROR(ahd);
652897883Sgibbs	}
652997883Sgibbsinit_done:
653097883Sgibbs	ahd_restart(ahd);
6531137870Sgibbs	aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
6532109588Sgibbs			ahd_stat_timer, ahd);
653397883Sgibbs	return (0);
653497883Sgibbs}
653597883Sgibbs
653697883Sgibbs/*
653797883Sgibbs * (Re)initialize chip state after a chip reset.
653897883Sgibbs */
653997883Sgibbsstatic void
654097883Sgibbsahd_chip_init(struct ahd_softc *ahd)
654197883Sgibbs{
654297883Sgibbs	uint32_t busaddr;
654397883Sgibbs	u_int	 sxfrctl1;
654497883Sgibbs	u_int	 scsiseq_template;
6545102679Sgibbs	u_int	 wait;
654697883Sgibbs	u_int	 i;
654797883Sgibbs	u_int	 target;
654897883Sgibbs
654997883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
655097883Sgibbs	/*
655197883Sgibbs	 * Take the LED out of diagnostic mode
655297883Sgibbs	 */
655397883Sgibbs	ahd_outb(ahd, SBLKCTL, ahd_inb(ahd, SBLKCTL) & ~(DIAGLEDEN|DIAGLEDON));
655497883Sgibbs
6555109588Sgibbs	/*
6556109588Sgibbs	 * Return HS_MAILBOX to its default value.
6557109588Sgibbs	 */
6558109588Sgibbs	ahd->hs_mailbox = 0;
6559109588Sgibbs	ahd_outb(ahd, HS_MAILBOX, 0);
6560109588Sgibbs
656197883Sgibbs	/* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1. */
656297883Sgibbs	ahd_outb(ahd, IOWNID, ahd->our_id);
656397883Sgibbs	ahd_outb(ahd, TOWNID, ahd->our_id);
656497883Sgibbs	sxfrctl1 = (ahd->flags & AHD_TERM_ENB_A) != 0 ? STPWEN : 0;
656597883Sgibbs	sxfrctl1 |= (ahd->flags & AHD_SPCHK_ENB_A) != 0 ? ENSPCHK : 0;
656697883Sgibbs	if ((ahd->bugs & AHD_LONG_SETIMO_BUG)
656797883Sgibbs	 && (ahd->seltime != STIMESEL_MIN)) {
656897883Sgibbs		/*
656997883Sgibbs		 * The selection timer duration is twice as long
657097883Sgibbs		 * as it should be.  Halve it by adding "1" to
657197883Sgibbs		 * the user specified setting.
657297883Sgibbs		 */
657397883Sgibbs		sxfrctl1 |= ahd->seltime + STIMESEL_BUG_ADJ;
657497883Sgibbs	} else {
657597883Sgibbs		sxfrctl1 |= ahd->seltime;
657697883Sgibbs	}
657797883Sgibbs
657897883Sgibbs	ahd_outb(ahd, SXFRCTL0, DFON);
657997883Sgibbs	ahd_outb(ahd, SXFRCTL1, sxfrctl1|ahd->seltime|ENSTIMER|ACTNEGEN);
658097883Sgibbs	ahd_outb(ahd, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
658197883Sgibbs
6582102679Sgibbs	/*
6583102679Sgibbs	 * Now that termination is set, wait for up
6584102679Sgibbs	 * to 500ms for our transceivers to settle.  If
6585102679Sgibbs	 * the adapter does not have a cable attached,
6586114623Sgibbs	 * the transceivers may never settle, so don't
6587102679Sgibbs	 * complain if we fail here.
6588102679Sgibbs	 */
6589102679Sgibbs	for (wait = 10000;
6590102679Sgibbs	     (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
6591102679Sgibbs	     wait--)
6592123579Sgibbs		aic_delay(100);
6593102679Sgibbs
6594102679Sgibbs	/* Clear any false bus resets due to the transceivers settling */
6595102679Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
6596102679Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
6597102679Sgibbs
659897883Sgibbs	/* Initialize mode specific S/G state. */
659997883Sgibbs	for (i = 0; i < 2; i++) {
660097883Sgibbs		ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
660197883Sgibbs		ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
660297883Sgibbs		ahd_outb(ahd, SG_STATE, 0);
660397883Sgibbs		ahd_outb(ahd, CLRSEQINTSRC, 0xFF);
660497883Sgibbs		ahd_outb(ahd, SEQIMODE,
660597883Sgibbs			 ENSAVEPTRS|ENCFG4DATA|ENCFG4ISTAT
660697883Sgibbs			|ENCFG4TSTAT|ENCFG4ICMD|ENCFG4TCMD);
660797883Sgibbs	}
660897883Sgibbs
660997883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
661097883Sgibbs	ahd_outb(ahd, DSCOMMAND0, ahd_inb(ahd, DSCOMMAND0)|MPARCKEN|CACHETHEN);
661197883Sgibbs	ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75);
661297883Sgibbs	ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN);
661397883Sgibbs	ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR);
6614104023Sgibbs	if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
6615104023Sgibbs		ahd_outb(ahd, OPTIONMODE, AUTOACKEN|AUTO_MSGOUT_DE);
6616104023Sgibbs	} else {
6617104023Sgibbs		ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);
6618104023Sgibbs	}
6619111653Sgibbs	ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN|SHVALIDSTDIS);
662097883Sgibbs	if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX)
662197883Sgibbs		/*
662297883Sgibbs		 * Do not issue a target abort when a split completion
662397883Sgibbs		 * error occurs.  Let our PCIX interrupt handler deal
662497883Sgibbs		 * with it instead. H2A4 Razor #625
662597883Sgibbs		 */
662697883Sgibbs		ahd_outb(ahd, PCIXCTL, ahd_inb(ahd, PCIXCTL) | SPLTSTADIS);
662797883Sgibbs
6628107441Sscottl	if ((ahd->bugs & AHD_LQOOVERRUN_BUG) != 0)
6629107441Sscottl		ahd_outb(ahd, LQOSCSCTL, LQONOCHKOVER);
6630107441Sscottl
663197883Sgibbs	/*
663297883Sgibbs	 * Tweak IOCELL settings.
663397883Sgibbs	 */
6634107441Sscottl	if ((ahd->flags & AHD_HP_BOARD) != 0) {
663597883Sgibbs		for (i = 0; i < NUMDSPS; i++) {
663697883Sgibbs			ahd_outb(ahd, DSPSELECT, i);
6637107441Sscottl			ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_HP_DEFAULT);
663897883Sgibbs		}
6639104023Sgibbs#ifdef AHD_DEBUG
6640104023Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
6641104023Sgibbs			printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd),
6642107441Sscottl			       WRTBIASCTL_HP_DEFAULT);
6643104023Sgibbs#endif
664497883Sgibbs	}
664597883Sgibbs	ahd_setup_iocell_workaround(ahd);
664697883Sgibbs
664797883Sgibbs	/*
664897883Sgibbs	 * Enable LQI Manager interrupts.
664997883Sgibbs	 */
665097883Sgibbs	ahd_outb(ahd, LQIMODE1, ENLQIPHASE_LQ|ENLQIPHASE_NLQ|ENLIQABORT
665197883Sgibbs			      | ENLQICRCI_LQ|ENLQICRCI_NLQ|ENLQIBADLQI
665297883Sgibbs			      | ENLQIOVERI_LQ|ENLQIOVERI_NLQ);
665397883Sgibbs	ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC);
665497883Sgibbs	/*
6655133122Sgibbs	 * We choose to have the sequencer catch LQOPHCHGINPKT errors
6656133122Sgibbs	 * manually for the command phase at the start of a packetized
6657133122Sgibbs	 * selection case.  ENLQOBUSFREE should be made redundant by
6658133122Sgibbs	 * the BUSFREE interrupt, but it seems that some LQOBUSFREE
6659133122Sgibbs	 * events fail to assert the BUSFREE interrupt so we must
6660133122Sgibbs	 * also enable LQOBUSFREE interrupts.
666197883Sgibbs	 */
6662133122Sgibbs	ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE);
666397883Sgibbs
666497883Sgibbs	/*
6665109588Sgibbs	 * Setup sequencer interrupt handlers.
666697883Sgibbs	 */
666797883Sgibbs	ahd_outw(ahd, INTVEC1_ADDR, ahd_resolve_seqaddr(ahd, LABEL_seq_isr));
6668109588Sgibbs	ahd_outw(ahd, INTVEC2_ADDR, ahd_resolve_seqaddr(ahd, LABEL_timer_isr));
666997883Sgibbs
667097883Sgibbs	/*
667197883Sgibbs	 * Setup SCB Offset registers.
667297883Sgibbs	 */
6673102679Sgibbs	if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
6674102679Sgibbs		ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb,
6675102679Sgibbs			 pkt_long_lun));
6676102679Sgibbs	} else {
6677102679Sgibbs		ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun));
6678102679Sgibbs	}
667997883Sgibbs	ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len));
6680104023Sgibbs	ahd_outb(ahd, ATTRPTR, offsetof(struct hardware_scb, task_attribute));
668197883Sgibbs	ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management));
668297883Sgibbs	ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb,
668397883Sgibbs				       shared_data.idata.cdb));
668497883Sgibbs	ahd_outb(ahd, QNEXTPTR,
668597883Sgibbs		 offsetof(struct hardware_scb, next_hscb_busaddr));
668697883Sgibbs	ahd_outb(ahd, ABRTBITPTR, MK_MESSAGE_BIT_OFFSET);
668797883Sgibbs	ahd_outb(ahd, ABRTBYTEPTR, offsetof(struct hardware_scb, control));
6688102679Sgibbs	if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
6689102679Sgibbs		ahd_outb(ahd, LUNLEN,
6690102679Sgibbs			 sizeof(ahd->next_queued_hscb->pkt_long_lun) - 1);
6691102679Sgibbs	} else {
6692115408Sscottl		ahd_outb(ahd, LUNLEN, LUNLEN_SINGLE_LEVEL_LUN);
6693102679Sgibbs	}
669497883Sgibbs	ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1);
669597883Sgibbs	ahd_outb(ahd, MAXCMD, 0xFF);
669697883Sgibbs	ahd_outb(ahd, SCBAUTOPTR,
669797883Sgibbs		 AUSCBPTR_EN | offsetof(struct hardware_scb, tag));
669897883Sgibbs
669997883Sgibbs	/* We haven't been enabled for target mode yet. */
670097883Sgibbs	ahd_outb(ahd, MULTARGID, 0);
670197883Sgibbs	ahd_outb(ahd, MULTARGID + 1, 0);
670297883Sgibbs
670397883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
6704107441Sscottl	/* Initialize the negotiation table. */
6705107441Sscottl	if ((ahd->features & AHD_NEW_IOCELL_OPTS) == 0) {
6706107441Sscottl		/*
6707107441Sscottl		 * Clear the spare bytes in the neg table to avoid
6708107441Sscottl		 * spurious parity errors.
6709107441Sscottl		 */
6710107441Sscottl		for (target = 0; target < AHD_NUM_TARGETS; target++) {
6711107441Sscottl			ahd_outb(ahd, NEGOADDR, target);
6712107441Sscottl			ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PER_DEV0);
6713107441Sscottl			for (i = 0; i < AHD_NUM_PER_DEV_ANNEXCOLS; i++)
6714107441Sscottl				ahd_outb(ahd, ANNEXDAT, 0);
6715107441Sscottl		}
6716107441Sscottl	}
671797883Sgibbs	for (target = 0; target < AHD_NUM_TARGETS; target++) {
6718107441Sscottl		struct	 ahd_devinfo devinfo;
6719107441Sscottl		struct	 ahd_initiator_tinfo *tinfo;
6720107441Sscottl		struct	 ahd_tmode_tstate *tstate;
672197883Sgibbs
6722107441Sscottl		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
6723107441Sscottl					    target, &tstate);
6724107441Sscottl		ahd_compile_devinfo(&devinfo, ahd->our_id,
6725107441Sscottl				    target, CAM_LUN_WILDCARD,
6726107441Sscottl				    'A', ROLE_INITIATOR);
6727107441Sscottl		ahd_update_neg_table(ahd, &devinfo, &tinfo->curr);
672897883Sgibbs	}
6729107441Sscottl
673097883Sgibbs	ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR);
6731102679Sgibbs	ahd_outb(ahd, CLRINT, CLRSCSIINT);
673297883Sgibbs
6733153072Sru#ifdef NEEDS_MORE_TESTING
673497883Sgibbs	/*
673597883Sgibbs	 * Always enable abort on incoming L_Qs if this feature is
673697883Sgibbs	 * supported.  We use this to catch invalid SCB references.
673797883Sgibbs	 */
673897883Sgibbs	if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0)
673997883Sgibbs		ahd_outb(ahd, LQCTL1, ABORTPENDING);
674097883Sgibbs	else
6741116935Sgibbs#endif
674297883Sgibbs		ahd_outb(ahd, LQCTL1, 0);
674397883Sgibbs
674497883Sgibbs	/* All of our queues are empty */
674597883Sgibbs	ahd->qoutfifonext = 0;
6746125448Sgibbs	ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
6747125448Sgibbs	ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
674897883Sgibbs	for (i = 0; i < AHD_QOUT_SIZE; i++)
6749125448Sgibbs		ahd->qoutfifo[i].valid_tag = 0;
675097883Sgibbs	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
675197883Sgibbs
675297883Sgibbs	ahd->qinfifonext = 0;
675397883Sgibbs	for (i = 0; i < AHD_QIN_SIZE; i++)
675497883Sgibbs		ahd->qinfifo[i] = SCB_LIST_NULL;
675597883Sgibbs
675697883Sgibbs	if ((ahd->features & AHD_TARGETMODE) != 0) {
675797883Sgibbs		/* All target command blocks start out invalid. */
675897883Sgibbs		for (i = 0; i < AHD_TMODE_CMDS; i++)
675997883Sgibbs			ahd->targetcmds[i].cmd_valid = 0;
676097883Sgibbs		ahd_sync_tqinfifo(ahd, BUS_DMASYNC_PREREAD);
676197883Sgibbs		ahd->tqinfifonext = 1;
676297883Sgibbs		ahd_outb(ahd, KERNEL_TQINPOS, ahd->tqinfifonext - 1);
676397883Sgibbs		ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
676497883Sgibbs	}
676597883Sgibbs
676697883Sgibbs	/* Initialize Scratch Ram. */
676797883Sgibbs	ahd_outb(ahd, SEQ_FLAGS, 0);
676897883Sgibbs	ahd_outb(ahd, SEQ_FLAGS2, 0);
676997883Sgibbs
677097883Sgibbs	/* We don't have any waiting selections */
677197883Sgibbs	ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL);
677297883Sgibbs	ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL);
6773133122Sgibbs	ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL);
6774133122Sgibbs	ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF);
677597883Sgibbs	for (i = 0; i < AHD_NUM_TARGETS; i++)
677697883Sgibbs		ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL);
677797883Sgibbs
677897883Sgibbs	/*
677997883Sgibbs	 * Nobody is waiting to be DMAed into the QOUTFIFO.
678097883Sgibbs	 */
678197883Sgibbs	ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
678297883Sgibbs	ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
678397883Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
6784125448Sgibbs	ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
6785125448Sgibbs	ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
678697883Sgibbs
678797883Sgibbs	/*
678897883Sgibbs	 * The Freeze Count is 0.
678997883Sgibbs	 */
6790125448Sgibbs	ahd->qfreeze_cnt = 0;
679197883Sgibbs	ahd_outw(ahd, QFREEZE_COUNT, 0);
6792125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
679397883Sgibbs
679497883Sgibbs	/*
679597883Sgibbs	 * Tell the sequencer where it can find our arrays in memory.
679697883Sgibbs	 */
6797123579Sgibbs	busaddr = ahd->shared_data_map.busaddr;
6798123579Sgibbs	ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
6799123579Sgibbs	ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
680097883Sgibbs
680197883Sgibbs	/*
680297883Sgibbs	 * Setup the allowed SCSI Sequences based on operational mode.
680397883Sgibbs	 * If we are a target, we'll enable select in operations once
680497883Sgibbs	 * we've had a lun enabled.
680597883Sgibbs	 */
680697883Sgibbs	scsiseq_template = ENAUTOATNP;
680797883Sgibbs	if ((ahd->flags & AHD_INITIATORROLE) != 0)
680897883Sgibbs		scsiseq_template |= ENRSELI;
680997883Sgibbs	ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq_template);
681097883Sgibbs
681197883Sgibbs	/* There are no busy SCBs yet. */
681297883Sgibbs	for (target = 0; target < AHD_NUM_TARGETS; target++) {
681397883Sgibbs		int lun;
681497883Sgibbs
681597883Sgibbs		for (lun = 0; lun < AHD_NUM_LUNS_NONPKT; lun++)
681697883Sgibbs			ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(target, 'A', lun));
681797883Sgibbs	}
681897883Sgibbs
681997883Sgibbs	/*
682097883Sgibbs	 * Initialize the group code to command length table.
682197883Sgibbs	 * Vendor Unique codes are set to 0 so we only capture
682297883Sgibbs	 * the first byte of the cdb.  These can be overridden
682397883Sgibbs	 * when target mode is enabled.
682497883Sgibbs	 */
682597883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE, 5);
682697883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 1, 9);
682797883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 2, 9);
682897883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 3, 0);
682997883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 4, 15);
683097883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 5, 11);
683197883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 6, 0);
683297883Sgibbs	ahd_outb(ahd, CMDSIZE_TABLE + 7, 0);
683397883Sgibbs
683497883Sgibbs	/* Tell the sequencer of our initial queue positions */
683597883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
683697883Sgibbs	ahd_outb(ahd, QOFF_CTLSTA, SCB_QSIZE_512);
683797883Sgibbs	ahd->qinfifonext = 0;
683897883Sgibbs	ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
683997883Sgibbs	ahd_set_hescb_qoff(ahd, 0);
684097883Sgibbs	ahd_set_snscb_qoff(ahd, 0);
684197883Sgibbs	ahd_set_sescb_qoff(ahd, 0);
684297883Sgibbs	ahd_set_sdscb_qoff(ahd, 0);
684397883Sgibbs
684497883Sgibbs	/*
684597883Sgibbs	 * Tell the sequencer which SCB will be the next one it receives.
684697883Sgibbs	 */
6847123579Sgibbs	busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
6848123579Sgibbs	ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
6849109588Sgibbs
6850109588Sgibbs	/*
6851115329Sgibbs	 * Default to coalescing disabled.
6852109588Sgibbs	 */
6853115329Sgibbs	ahd_outw(ahd, INT_COALESCING_CMDCOUNT, 0);
6854109588Sgibbs	ahd_outw(ahd, CMDS_PENDING, 0);
6855115329Sgibbs	ahd_update_coalescing_values(ahd, ahd->int_coalescing_timer,
6856115329Sgibbs				     ahd->int_coalescing_maxcmds,
6857115329Sgibbs				     ahd->int_coalescing_mincmds);
6858115329Sgibbs	ahd_enable_coalescing(ahd, FALSE);
6859109588Sgibbs
686097883Sgibbs	ahd_loadseq(ahd);
686197883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
686297883Sgibbs}
686397883Sgibbs
686497883Sgibbs/*
686597883Sgibbs * Setup default device and controller settings.
686697883Sgibbs * This should only be called if our probe has
686797883Sgibbs * determined that no configuration data is available.
686897883Sgibbs */
686997883Sgibbsint
687097883Sgibbsahd_default_config(struct ahd_softc *ahd)
687197883Sgibbs{
687297883Sgibbs	int	targ;
687397883Sgibbs
687497883Sgibbs	ahd->our_id = 7;
687597883Sgibbs
687697883Sgibbs	/*
687797883Sgibbs	 * Allocate a tstate to house information for our
687897883Sgibbs	 * initiator presence on the bus as well as the user
687997883Sgibbs	 * data for any target mode initiator.
688097883Sgibbs	 */
688197883Sgibbs	if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
688297883Sgibbs		printf("%s: unable to allocate ahd_tmode_tstate.  "
688397883Sgibbs		       "Failing attach\n", ahd_name(ahd));
6884199260Sattilio		AHD_FATAL_ERROR(ahd);
688597883Sgibbs		return (ENOMEM);
688697883Sgibbs	}
688797883Sgibbs
688897883Sgibbs	for (targ = 0; targ < AHD_NUM_TARGETS; targ++) {
688997883Sgibbs		struct	 ahd_devinfo devinfo;
689097883Sgibbs		struct	 ahd_initiator_tinfo *tinfo;
689197883Sgibbs		struct	 ahd_tmode_tstate *tstate;
689297883Sgibbs		uint16_t target_mask;
689397883Sgibbs
689497883Sgibbs		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
689597883Sgibbs					    targ, &tstate);
689697883Sgibbs		/*
689797883Sgibbs		 * We support SPC2 and SPI4.
689897883Sgibbs		 */
689997883Sgibbs		tinfo->user.protocol_version = 4;
690097883Sgibbs		tinfo->user.transport_version = 4;
690197883Sgibbs
690297883Sgibbs		target_mask = 0x01 << targ;
690397883Sgibbs		ahd->user_discenable |= target_mask;
690497883Sgibbs		tstate->discenable |= target_mask;
690597883Sgibbs		ahd->user_tagenable |= target_mask;
690697883Sgibbs#ifdef AHD_FORCE_160
690797883Sgibbs		tinfo->user.period = AHD_SYNCRATE_DT;
690897883Sgibbs#else
690997883Sgibbs		tinfo->user.period = AHD_SYNCRATE_160;
691097883Sgibbs#endif
6911111653Sgibbs		tinfo->user.offset = MAX_OFFSET;
691297883Sgibbs		tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM
691397883Sgibbs					| MSG_EXT_PPR_WR_FLOW
6914104023Sgibbs					| MSG_EXT_PPR_HOLD_MCS
691597883Sgibbs					| MSG_EXT_PPR_IU_REQ
691697883Sgibbs					| MSG_EXT_PPR_QAS_REQ
691797883Sgibbs					| MSG_EXT_PPR_DT_REQ;
6918107441Sscottl		if ((ahd->features & AHD_RTI) != 0)
6919107441Sscottl			tinfo->user.ppr_options |= MSG_EXT_PPR_RTI;
692097883Sgibbs
692197883Sgibbs		tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
692297883Sgibbs
692397883Sgibbs		/*
692497883Sgibbs		 * Start out Async/Narrow/Untagged and with
692597883Sgibbs		 * conservative protocol support.
692697883Sgibbs		 */
692797883Sgibbs		tinfo->goal.protocol_version = 2;
692897883Sgibbs		tinfo->goal.transport_version = 2;
692997883Sgibbs		tinfo->curr.protocol_version = 2;
693097883Sgibbs		tinfo->curr.transport_version = 2;
693197883Sgibbs		ahd_compile_devinfo(&devinfo, ahd->our_id,
693297883Sgibbs				    targ, CAM_LUN_WILDCARD,
693397883Sgibbs				    'A', ROLE_INITIATOR);
693497883Sgibbs		tstate->tagenable &= ~target_mask;
693597883Sgibbs		ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
693697883Sgibbs			      AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);
693797883Sgibbs		ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
693897883Sgibbs				 /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
693997883Sgibbs				 /*paused*/TRUE);
694097883Sgibbs	}
694197883Sgibbs	return (0);
694297883Sgibbs}
694397883Sgibbs
694497883Sgibbs/*
694597883Sgibbs * Parse device configuration information.
694697883Sgibbs */
694797883Sgibbsint
694897883Sgibbsahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc)
694997883Sgibbs{
695097883Sgibbs	int targ;
695197883Sgibbs	int max_targ;
695297883Sgibbs
695397883Sgibbs	max_targ = sc->max_targets & CFMAXTARG;
695497883Sgibbs	ahd->our_id = sc->brtime_id & CFSCSIID;
695597883Sgibbs
695697883Sgibbs	/*
695797883Sgibbs	 * Allocate a tstate to house information for our
695897883Sgibbs	 * initiator presence on the bus as well as the user
695997883Sgibbs	 * data for any target mode initiator.
696097883Sgibbs	 */
696197883Sgibbs	if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
696297883Sgibbs		printf("%s: unable to allocate ahd_tmode_tstate.  "
696397883Sgibbs		       "Failing attach\n", ahd_name(ahd));
6964199260Sattilio		AHD_FATAL_ERROR(ahd);
696597883Sgibbs		return (ENOMEM);
696697883Sgibbs	}
696797883Sgibbs
696897883Sgibbs	for (targ = 0; targ < max_targ; targ++) {
696997883Sgibbs		struct	 ahd_devinfo devinfo;
697097883Sgibbs		struct	 ahd_initiator_tinfo *tinfo;
697197883Sgibbs		struct	 ahd_transinfo *user_tinfo;
697297883Sgibbs		struct	 ahd_tmode_tstate *tstate;
697397883Sgibbs		uint16_t target_mask;
697497883Sgibbs
697597883Sgibbs		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
697697883Sgibbs					    targ, &tstate);
697797883Sgibbs		user_tinfo = &tinfo->user;
697897883Sgibbs
697997883Sgibbs		/*
698097883Sgibbs		 * We support SPC2 and SPI4.
698197883Sgibbs		 */
698297883Sgibbs		tinfo->user.protocol_version = 4;
698397883Sgibbs		tinfo->user.transport_version = 4;
698497883Sgibbs
698597883Sgibbs		target_mask = 0x01 << targ;
698697883Sgibbs		ahd->user_discenable &= ~target_mask;
698797883Sgibbs		tstate->discenable &= ~target_mask;
698897883Sgibbs		ahd->user_tagenable &= ~target_mask;
698997883Sgibbs		if (sc->device_flags[targ] & CFDISC) {
699097883Sgibbs			tstate->discenable |= target_mask;
699197883Sgibbs			ahd->user_discenable |= target_mask;
699297883Sgibbs			ahd->user_tagenable |= target_mask;
699397883Sgibbs		} else {
699497883Sgibbs			/*
699597883Sgibbs			 * Cannot be packetized without disconnection.
699697883Sgibbs			 */
699797883Sgibbs			sc->device_flags[targ] &= ~CFPACKETIZED;
699897883Sgibbs		}
699997883Sgibbs
700097883Sgibbs		user_tinfo->ppr_options = 0;
700197883Sgibbs		user_tinfo->period = (sc->device_flags[targ] & CFXFER);
700297883Sgibbs		if (user_tinfo->period < CFXFER_ASYNC) {
700397883Sgibbs			if (user_tinfo->period <= AHD_PERIOD_10MHz)
700497883Sgibbs				user_tinfo->ppr_options |= MSG_EXT_PPR_DT_REQ;
700597883Sgibbs			user_tinfo->offset = MAX_OFFSET;
700697883Sgibbs		} else  {
700797883Sgibbs			user_tinfo->offset = 0;
7008109588Sgibbs			user_tinfo->period = AHD_ASYNC_XFER_PERIOD;
700997883Sgibbs		}
701097883Sgibbs#ifdef AHD_FORCE_160
701197883Sgibbs		if (user_tinfo->period <= AHD_SYNCRATE_160)
701297883Sgibbs			user_tinfo->period = AHD_SYNCRATE_DT;
701397883Sgibbs#endif
701497883Sgibbs
7015107441Sscottl		if ((sc->device_flags[targ] & CFPACKETIZED) != 0) {
701697883Sgibbs			user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM
701797883Sgibbs						|  MSG_EXT_PPR_WR_FLOW
7018104023Sgibbs						|  MSG_EXT_PPR_HOLD_MCS
701997883Sgibbs						|  MSG_EXT_PPR_IU_REQ;
7020107441Sscottl			if ((ahd->features & AHD_RTI) != 0)
7021107441Sscottl				user_tinfo->ppr_options |= MSG_EXT_PPR_RTI;
7022107441Sscottl		}
702397883Sgibbs
702497883Sgibbs		if ((sc->device_flags[targ] & CFQAS) != 0)
702597883Sgibbs			user_tinfo->ppr_options |= MSG_EXT_PPR_QAS_REQ;
702697883Sgibbs
702797883Sgibbs		if ((sc->device_flags[targ] & CFWIDEB) != 0)
702897883Sgibbs			user_tinfo->width = MSG_EXT_WDTR_BUS_16_BIT;
702997883Sgibbs		else
703097883Sgibbs			user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT;
703197883Sgibbs#ifdef AHD_DEBUG
703297883Sgibbs		if ((ahd_debug & AHD_SHOW_MISC) != 0)
703397883Sgibbs			printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width,
703497883Sgibbs			       user_tinfo->period, user_tinfo->offset,
703597883Sgibbs			       user_tinfo->ppr_options);
703697883Sgibbs#endif
703797883Sgibbs		/*
703897883Sgibbs		 * Start out Async/Narrow/Untagged and with
703997883Sgibbs		 * conservative protocol support.
704097883Sgibbs		 */
704197883Sgibbs		tstate->tagenable &= ~target_mask;
704297883Sgibbs		tinfo->goal.protocol_version = 2;
704397883Sgibbs		tinfo->goal.transport_version = 2;
704497883Sgibbs		tinfo->curr.protocol_version = 2;
704597883Sgibbs		tinfo->curr.transport_version = 2;
704697883Sgibbs		ahd_compile_devinfo(&devinfo, ahd->our_id,
704797883Sgibbs				    targ, CAM_LUN_WILDCARD,
704897883Sgibbs				    'A', ROLE_INITIATOR);
704997883Sgibbs		ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
705097883Sgibbs			      AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);
705197883Sgibbs		ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
705297883Sgibbs				 /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
705397883Sgibbs				 /*paused*/TRUE);
705497883Sgibbs	}
705597883Sgibbs
705697883Sgibbs	ahd->flags &= ~AHD_SPCHK_ENB_A;
705797883Sgibbs	if (sc->bios_control & CFSPARITY)
705897883Sgibbs		ahd->flags |= AHD_SPCHK_ENB_A;
705997883Sgibbs
706097883Sgibbs	ahd->flags &= ~AHD_RESET_BUS_A;
706197883Sgibbs	if (sc->bios_control & CFRESETB)
706297883Sgibbs		ahd->flags |= AHD_RESET_BUS_A;
706397883Sgibbs
706497883Sgibbs	ahd->flags &= ~AHD_EXTENDED_TRANS_A;
706597883Sgibbs	if (sc->bios_control & CFEXTEND)
706697883Sgibbs		ahd->flags |= AHD_EXTENDED_TRANS_A;
706797883Sgibbs
706897883Sgibbs	ahd->flags &= ~AHD_BIOS_ENABLED;
706997883Sgibbs	if ((sc->bios_control & CFBIOSSTATE) == CFBS_ENABLED)
707097883Sgibbs		ahd->flags |= AHD_BIOS_ENABLED;
707197883Sgibbs
707297883Sgibbs	ahd->flags &= ~AHD_STPWLEVEL_A;
707397883Sgibbs	if ((sc->adapter_control & CFSTPWLEVEL) != 0)
707497883Sgibbs		ahd->flags |= AHD_STPWLEVEL_A;
707597883Sgibbs
707697883Sgibbs	return (0);
707797883Sgibbs}
707897883Sgibbs
7079114623Sgibbs/*
7080114623Sgibbs * Parse device configuration information.
7081114623Sgibbs */
7082114623Sgibbsint
7083114623Sgibbsahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd)
7084114623Sgibbs{
7085114623Sgibbs	int error;
7086114623Sgibbs
7087114623Sgibbs	error = ahd_verify_vpd_cksum(vpd);
7088114623Sgibbs	if (error == 0)
7089114623Sgibbs		return (EINVAL);
7090114623Sgibbs	if ((vpd->bios_flags & VPDBOOTHOST) != 0)
7091114623Sgibbs		ahd->flags |= AHD_BOOT_CHANNEL;
7092114623Sgibbs	return (0);
7093114623Sgibbs}
7094114623Sgibbs
709597883Sgibbsvoid
709697883Sgibbsahd_intr_enable(struct ahd_softc *ahd, int enable)
709797883Sgibbs{
709897883Sgibbs	u_int hcntrl;
709997883Sgibbs
710097883Sgibbs	hcntrl = ahd_inb(ahd, HCNTRL);
710197883Sgibbs	hcntrl &= ~INTEN;
710297883Sgibbs	ahd->pause &= ~INTEN;
710397883Sgibbs	ahd->unpause &= ~INTEN;
710497883Sgibbs	if (enable) {
710597883Sgibbs		hcntrl |= INTEN;
710697883Sgibbs		ahd->pause |= INTEN;
710797883Sgibbs		ahd->unpause |= INTEN;
710897883Sgibbs	}
710997883Sgibbs	ahd_outb(ahd, HCNTRL, hcntrl);
711097883Sgibbs}
711197883Sgibbs
7112109588Sgibbsvoid
7113115329Sgibbsahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds,
7114109588Sgibbs			     u_int mincmds)
7115109588Sgibbs{
7116109588Sgibbs	if (timer > AHD_TIMER_MAX_US)
7117109588Sgibbs		timer = AHD_TIMER_MAX_US;
7118115329Sgibbs	ahd->int_coalescing_timer = timer;
7119109588Sgibbs
7120115329Sgibbs	if (maxcmds > AHD_INT_COALESCING_MAXCMDS_MAX)
7121115329Sgibbs		maxcmds = AHD_INT_COALESCING_MAXCMDS_MAX;
7122115329Sgibbs	if (mincmds > AHD_INT_COALESCING_MINCMDS_MAX)
7123115329Sgibbs		mincmds = AHD_INT_COALESCING_MINCMDS_MAX;
7124115329Sgibbs	ahd->int_coalescing_maxcmds = maxcmds;
7125115329Sgibbs	ahd_outw(ahd, INT_COALESCING_TIMER, timer / AHD_TIMER_US_PER_TICK);
7126115329Sgibbs	ahd_outb(ahd, INT_COALESCING_MAXCMDS, -maxcmds);
7127115329Sgibbs	ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds);
7128109588Sgibbs}
7129109588Sgibbs
7130109588Sgibbsvoid
7131115329Sgibbsahd_enable_coalescing(struct ahd_softc *ahd, int enable)
7132109588Sgibbs{
7133109588Sgibbs
7134115329Sgibbs	ahd->hs_mailbox &= ~ENINT_COALESCE;
7135109588Sgibbs	if (enable)
7136115329Sgibbs		ahd->hs_mailbox |= ENINT_COALESCE;
7137109588Sgibbs	ahd_outb(ahd, HS_MAILBOX, ahd->hs_mailbox);
7138109588Sgibbs	ahd_flush_device_writes(ahd);
7139109588Sgibbs	ahd_run_qoutfifo(ahd);
7140109588Sgibbs}
7141109588Sgibbs
714297883Sgibbs/*
714397883Sgibbs * Ensure that the card is paused in a location
714497883Sgibbs * outside of all critical sections and that all
714597883Sgibbs * pending work is completed prior to returning.
714697883Sgibbs * This routine should only be called from outside
714797883Sgibbs * an interrupt context.
714897883Sgibbs */
714997883Sgibbsvoid
715097883Sgibbsahd_pause_and_flushwork(struct ahd_softc *ahd)
715197883Sgibbs{
7152114623Sgibbs	u_int intstat;
7153114623Sgibbs	u_int maxloops;
715497883Sgibbs
715597883Sgibbs	maxloops = 1000;
715697883Sgibbs	ahd->flags |= AHD_ALL_INTERRUPTS;
7157114623Sgibbs	ahd_pause(ahd);
7158114623Sgibbs	/*
7159125448Sgibbs	 * Freeze the outgoing selections.  We do this only
7160114623Sgibbs	 * until we are safely paused without further selections
7161114623Sgibbs	 * pending.
7162114623Sgibbs	 */
7163125448Sgibbs	ahd->qfreeze_cnt--;
7164125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
7165114623Sgibbs	ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
716697883Sgibbs	do {
7167109588Sgibbs
7168114623Sgibbs		ahd_unpause(ahd);
7169123579Sgibbs		/*
7170123579Sgibbs		 * Give the sequencer some time to service
7171123579Sgibbs		 * any active selections.
7172123579Sgibbs		 */
7173129134Sgibbs		aic_delay(500);
7174123579Sgibbs
717597883Sgibbs		ahd_intr(ahd);
717697883Sgibbs		ahd_pause(ahd);
7177114623Sgibbs		intstat = ahd_inb(ahd, INTSTAT);
7178129134Sgibbs		if ((intstat & INT_PEND) == 0) {
7179129134Sgibbs			ahd_clear_critical_section(ahd);
7180129134Sgibbs			intstat = ahd_inb(ahd, INTSTAT);
7181129134Sgibbs		}
7182109588Sgibbs	} while (--maxloops
7183111653Sgibbs	      && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
7184111653Sgibbs	      && ((intstat & INT_PEND) != 0
7185114623Sgibbs	       || (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
7186114623Sgibbs	       || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0));
7187114623Sgibbs
718897883Sgibbs	if (maxloops == 0) {
718997883Sgibbs		printf("Infinite interrupt loop, INTSTAT = %x",
719097883Sgibbs		      ahd_inb(ahd, INTSTAT));
7191199260Sattilio		AHD_FATAL_ERROR(ahd);
719297883Sgibbs	}
7193125448Sgibbs	ahd->qfreeze_cnt++;
7194125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
7195109588Sgibbs
7196109588Sgibbs	ahd_flush_qoutfifo(ahd);
7197109588Sgibbs
719897883Sgibbs	ahd_platform_flushwork(ahd);
719997883Sgibbs	ahd->flags &= ~AHD_ALL_INTERRUPTS;
720097883Sgibbs}
720197883Sgibbs
720297883Sgibbsint
720397883Sgibbsahd_suspend(struct ahd_softc *ahd)
720497883Sgibbs{
720597883Sgibbs
720697883Sgibbs	ahd_pause_and_flushwork(ahd);
720797883Sgibbs
7208115917Sgibbs	if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
7209115917Sgibbs		ahd_unpause(ahd);
721097883Sgibbs		return (EBUSY);
721197883Sgibbs	}
721297883Sgibbs	ahd_shutdown(ahd);
721397883Sgibbs	return (0);
721497883Sgibbs}
721597883Sgibbs
721697883Sgibbsint
721797883Sgibbsahd_resume(struct ahd_softc *ahd)
721897883Sgibbs{
721997883Sgibbs
7220115917Sgibbs	ahd_reset(ahd, /*reinit*/TRUE);
7221115917Sgibbs	ahd_intr_enable(ahd, TRUE);
7222115917Sgibbs	ahd_restart(ahd);
722397883Sgibbs	return (0);
722497883Sgibbs}
722597883Sgibbs
722697883Sgibbs/************************** Busy Target Table *********************************/
722797883Sgibbs/*
722897883Sgibbs * Set SCBPTR to the SCB that contains the busy
722997883Sgibbs * table entry for TCL.  Return the offset into
723097883Sgibbs * the SCB that contains the entry for TCL.
723197883Sgibbs * saved_scbid is dereferenced and set to the
723297883Sgibbs * scbid that should be restored once manipualtion
723397883Sgibbs * of the TCL entry is complete.
723497883Sgibbs */
723597883Sgibbsstatic __inline u_int
723697883Sgibbsahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)
723797883Sgibbs{
723897883Sgibbs	/*
723997883Sgibbs	 * Index to the SCB that contains the busy entry.
724097883Sgibbs	 */
7241104023Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
7242104023Sgibbs	*saved_scbid = ahd_get_scbptr(ahd);
724397883Sgibbs	ahd_set_scbptr(ahd, TCL_LUN(tcl)
7244102679Sgibbs		     | ((TCL_TARGET_OFFSET(tcl) & 0xC) << 4));
724597883Sgibbs
724697883Sgibbs	/*
724797883Sgibbs	 * And now calculate the SCB offset to the entry.
724897883Sgibbs	 * Each entry is 2 bytes wide, hence the
724997883Sgibbs	 * multiplication by 2.
725097883Sgibbs	 */
7251102679Sgibbs	return (((TCL_TARGET_OFFSET(tcl) & 0x3) << 1) + SCB_DISCONNECTED_LISTS);
725297883Sgibbs}
725397883Sgibbs
725497883Sgibbs/*
725597883Sgibbs * Return the untagged transaction id for a given target/channel lun.
725697883Sgibbs */
725797883Sgibbsu_int
725897883Sgibbsahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl)
725997883Sgibbs{
726097883Sgibbs	u_int scbid;
726197883Sgibbs	u_int scb_offset;
726297883Sgibbs	u_int saved_scbptr;
726397883Sgibbs
726497883Sgibbs	scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
726597883Sgibbs	scbid = ahd_inw_scbram(ahd, scb_offset);
726697883Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
726797883Sgibbs	return (scbid);
726897883Sgibbs}
726997883Sgibbs
727097883Sgibbsvoid
727197883Sgibbsahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid)
727297883Sgibbs{
727397883Sgibbs	u_int scb_offset;
727497883Sgibbs	u_int saved_scbptr;
727597883Sgibbs
727697883Sgibbs	scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
727797883Sgibbs	ahd_outw(ahd, scb_offset, scbid);
727897883Sgibbs	ahd_set_scbptr(ahd, saved_scbptr);
727997883Sgibbs}
728097883Sgibbs
728197883Sgibbs/************************** SCB and SCB queue management **********************/
728297883Sgibbsint
728397883Sgibbsahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target,
728497883Sgibbs	      char channel, int lun, u_int tag, role_t role)
728597883Sgibbs{
728697883Sgibbs	int targ = SCB_GET_TARGET(ahd, scb);
728797883Sgibbs	char chan = SCB_GET_CHANNEL(ahd, scb);
728897883Sgibbs	int slun = SCB_GET_LUN(scb);
728997883Sgibbs	int match;
729097883Sgibbs
729197883Sgibbs	match = ((chan == channel) || (channel == ALL_CHANNELS));
729297883Sgibbs	if (match != 0)
729397883Sgibbs		match = ((targ == target) || (target == CAM_TARGET_WILDCARD));
729497883Sgibbs	if (match != 0)
729597883Sgibbs		match = ((lun == slun) || (lun == CAM_LUN_WILDCARD));
729697883Sgibbs	if (match != 0) {
7297153072Sru#ifdef AHD_TARGET_MODE
729897883Sgibbs		int group;
729997883Sgibbs
730097883Sgibbs		group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code);
730197883Sgibbs		if (role == ROLE_INITIATOR) {
730297883Sgibbs			match = (group != XPT_FC_GROUP_TMODE)
730397883Sgibbs			      && ((tag == SCB_GET_TAG(scb))
730497883Sgibbs			       || (tag == SCB_LIST_NULL));
730597883Sgibbs		} else if (role == ROLE_TARGET) {
730697883Sgibbs			match = (group == XPT_FC_GROUP_TMODE)
730797883Sgibbs			      && ((tag == scb->io_ctx->csio.tag_id)
730897883Sgibbs			       || (tag == SCB_LIST_NULL));
730997883Sgibbs		}
731097883Sgibbs#else /* !AHD_TARGET_MODE */
731197883Sgibbs		match = ((tag == SCB_GET_TAG(scb)) || (tag == SCB_LIST_NULL));
731297883Sgibbs#endif /* AHD_TARGET_MODE */
731397883Sgibbs	}
731497883Sgibbs
731597883Sgibbs	return match;
731697883Sgibbs}
731797883Sgibbs
731897883Sgibbsvoid
731997883Sgibbsahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
732097883Sgibbs{
732197883Sgibbs	int	target;
732297883Sgibbs	char	channel;
732397883Sgibbs	int	lun;
732497883Sgibbs
732597883Sgibbs	target = SCB_GET_TARGET(ahd, scb);
732697883Sgibbs	lun = SCB_GET_LUN(scb);
732797883Sgibbs	channel = SCB_GET_CHANNEL(ahd, scb);
732897883Sgibbs
732997883Sgibbs	ahd_search_qinfifo(ahd, target, channel, lun,
733097883Sgibbs			   /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN,
733197883Sgibbs			   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
733297883Sgibbs
733397883Sgibbs	ahd_platform_freeze_devq(ahd, scb);
733497883Sgibbs}
733597883Sgibbs
733697883Sgibbsvoid
733797883Sgibbsahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb)
733897883Sgibbs{
7339107441Sscottl	struct scb	*prev_scb;
7340107441Sscottl	ahd_mode_state	 saved_modes;
734197883Sgibbs
7342107441Sscottl	saved_modes = ahd_save_modes(ahd);
7343107441Sscottl	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
734497883Sgibbs	prev_scb = NULL;
734597883Sgibbs	if (ahd_qinfifo_count(ahd) != 0) {
734697883Sgibbs		u_int prev_tag;
734797883Sgibbs		u_int prev_pos;
734897883Sgibbs
734997883Sgibbs		prev_pos = AHD_QIN_WRAP(ahd->qinfifonext - 1);
735097883Sgibbs		prev_tag = ahd->qinfifo[prev_pos];
735197883Sgibbs		prev_scb = ahd_lookup_scb(ahd, prev_tag);
735297883Sgibbs	}
735397883Sgibbs	ahd_qinfifo_requeue(ahd, prev_scb, scb);
735497883Sgibbs	ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
7355107441Sscottl	ahd_restore_modes(ahd, saved_modes);
735697883Sgibbs}
735797883Sgibbs
735897883Sgibbsstatic void
735997883Sgibbsahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
736097883Sgibbs		    struct scb *scb)
736197883Sgibbs{
736297883Sgibbs	if (prev_scb == NULL) {
736397883Sgibbs		uint32_t busaddr;
736497883Sgibbs
7365123579Sgibbs		busaddr = aic_le32toh(scb->hscb->hscb_busaddr);
7366123579Sgibbs		ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
736797883Sgibbs	} else {
736897883Sgibbs		prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
736997883Sgibbs		ahd_sync_scb(ahd, prev_scb,
737097883Sgibbs			     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
737197883Sgibbs	}
737297883Sgibbs	ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
737397883Sgibbs	ahd->qinfifonext++;
7374102679Sgibbs	scb->hscb->next_hscb_busaddr = ahd->next_queued_hscb->hscb_busaddr;
737597883Sgibbs	ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
737697883Sgibbs}
737797883Sgibbs
737897883Sgibbsstatic int
737997883Sgibbsahd_qinfifo_count(struct ahd_softc *ahd)
738097883Sgibbs{
738197883Sgibbs	u_int qinpos;
738297883Sgibbs	u_int wrap_qinpos;
738397883Sgibbs	u_int wrap_qinfifonext;
738497883Sgibbs
738597883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
738697883Sgibbs	qinpos = ahd_get_snscb_qoff(ahd);
738797883Sgibbs	wrap_qinpos = AHD_QIN_WRAP(qinpos);
738897883Sgibbs	wrap_qinfifonext = AHD_QIN_WRAP(ahd->qinfifonext);
7389109588Sgibbs	if (wrap_qinfifonext >= wrap_qinpos)
739097883Sgibbs		return (wrap_qinfifonext - wrap_qinpos);
739197883Sgibbs	else
739297883Sgibbs		return (wrap_qinfifonext
739397883Sgibbs		      + NUM_ELEMENTS(ahd->qinfifo) - wrap_qinpos);
739497883Sgibbs}
739597883Sgibbs
7396109588Sgibbsvoid
7397109588Sgibbsahd_reset_cmds_pending(struct ahd_softc *ahd)
7398109588Sgibbs{
7399109588Sgibbs	struct		scb *scb;
7400109588Sgibbs	ahd_mode_state	saved_modes;
7401109588Sgibbs	u_int		pending_cmds;
7402109588Sgibbs
7403109588Sgibbs	saved_modes = ahd_save_modes(ahd);
7404109588Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
7405109588Sgibbs
7406109588Sgibbs	/*
7407109588Sgibbs	 * Don't count any commands as outstanding that the
7408109588Sgibbs	 * sequencer has already marked for completion.
7409109588Sgibbs	 */
7410109588Sgibbs	ahd_flush_qoutfifo(ahd);
7411109588Sgibbs
7412109588Sgibbs	pending_cmds = 0;
7413109588Sgibbs	LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
7414109588Sgibbs		pending_cmds++;
7415109588Sgibbs	}
7416109588Sgibbs	ahd_outw(ahd, CMDS_PENDING, pending_cmds - ahd_qinfifo_count(ahd));
7417109588Sgibbs	ahd_restore_modes(ahd, saved_modes);
7418109588Sgibbs	ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
7419109588Sgibbs}
7420109588Sgibbs
7421133122Sgibbsvoid
7422133122Sgibbsahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
7423133122Sgibbs{
7424133122Sgibbs	cam_status ostat;
7425133122Sgibbs	cam_status cstat;
7426133122Sgibbs
7427133122Sgibbs	ostat = aic_get_transaction_status(scb);
7428133122Sgibbs	if (ostat == CAM_REQ_INPROG)
7429133122Sgibbs		aic_set_transaction_status(scb, status);
7430133122Sgibbs	cstat = aic_get_transaction_status(scb);
7431133122Sgibbs	if (cstat != CAM_REQ_CMP)
7432133122Sgibbs		aic_freeze_scb(scb);
7433133122Sgibbs	ahd_done(ahd, scb);
7434133122Sgibbs}
7435133122Sgibbs
743697883Sgibbsint
743797883Sgibbsahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
743897883Sgibbs		   int lun, u_int tag, role_t role, uint32_t status,
743997883Sgibbs		   ahd_search_action action)
744097883Sgibbs{
744197883Sgibbs	struct scb	*scb;
7442133122Sgibbs	struct scb	*mk_msg_scb;
744397883Sgibbs	struct scb	*prev_scb;
744497883Sgibbs	ahd_mode_state	 saved_modes;
744597883Sgibbs	u_int		 qinstart;
744697883Sgibbs	u_int		 qinpos;
744797883Sgibbs	u_int		 qintail;
744897883Sgibbs	u_int		 tid_next;
744997883Sgibbs	u_int		 tid_prev;
745097883Sgibbs	u_int		 scbid;
7451133122Sgibbs	u_int		 seq_flags2;
745297883Sgibbs	u_int		 savedscbptr;
745397883Sgibbs	uint32_t	 busaddr;
745497883Sgibbs	int		 found;
745597883Sgibbs	int		 targets;
745697883Sgibbs
745797883Sgibbs	/* Must be in CCHAN mode */
745897883Sgibbs	saved_modes = ahd_save_modes(ahd);
745997883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
746097883Sgibbs
746197883Sgibbs	/*
746297883Sgibbs	 * Halt any pending SCB DMA.  The sequencer will reinitiate
746397883Sgibbs	 * this dma if the qinfifo is not empty once we unpause.
746497883Sgibbs	 */
746597883Sgibbs	if ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN|CCSCBDIR))
746697883Sgibbs	 == (CCARREN|CCSCBEN|CCSCBDIR)) {
746797883Sgibbs		ahd_outb(ahd, CCSCBCTL,
746897883Sgibbs			 ahd_inb(ahd, CCSCBCTL) & ~(CCARREN|CCSCBEN));
746997883Sgibbs		while ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0)
747097883Sgibbs			;
747197883Sgibbs	}
747297883Sgibbs	/* Determine sequencer's position in the qinfifo. */
747397883Sgibbs	qintail = AHD_QIN_WRAP(ahd->qinfifonext);
747497883Sgibbs	qinstart = ahd_get_snscb_qoff(ahd);
747597883Sgibbs	qinpos = AHD_QIN_WRAP(qinstart);
747697883Sgibbs	found = 0;
747797883Sgibbs	prev_scb = NULL;
747897883Sgibbs
747997883Sgibbs	if (action == SEARCH_PRINT) {
748097883Sgibbs		printf("qinstart = %d qinfifonext = %d\nQINFIFO:",
748197883Sgibbs		       qinstart, ahd->qinfifonext);
748297883Sgibbs	}
748397883Sgibbs
748497883Sgibbs	/*
748597883Sgibbs	 * Start with an empty queue.  Entries that are not chosen
748697883Sgibbs	 * for removal will be re-added to the queue as we go.
748797883Sgibbs	 */
748897883Sgibbs	ahd->qinfifonext = qinstart;
7489123579Sgibbs	busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
7490123579Sgibbs	ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
749197883Sgibbs
749297883Sgibbs	while (qinpos != qintail) {
749397883Sgibbs		scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
749497883Sgibbs		if (scb == NULL) {
749597883Sgibbs			printf("qinpos = %d, SCB index = %d\n",
749697883Sgibbs				qinpos, ahd->qinfifo[qinpos]);
7497199260Sattilio			AHD_FATAL_ERROR(ahd);
749897883Sgibbs			panic("Loop 1\n");
749997883Sgibbs		}
750097883Sgibbs
750197883Sgibbs		if (ahd_match_scb(ahd, scb, target, channel, lun, tag, role)) {
750297883Sgibbs			/*
750397883Sgibbs			 * We found an scb that needs to be acted on.
750497883Sgibbs			 */
750597883Sgibbs			found++;
750697883Sgibbs			switch (action) {
750797883Sgibbs			case SEARCH_COMPLETE:
750897883Sgibbs				if ((scb->flags & SCB_ACTIVE) == 0)
750997883Sgibbs					printf("Inactive SCB in qinfifo\n");
7510133122Sgibbs				ahd_done_with_status(ahd, scb, status);
751197883Sgibbs				/* FALLTHROUGH */
751297883Sgibbs			case SEARCH_REMOVE:
751397883Sgibbs				break;
751497883Sgibbs			case SEARCH_PRINT:
751597883Sgibbs				printf(" 0x%x", ahd->qinfifo[qinpos]);
751697883Sgibbs				/* FALLTHROUGH */
751797883Sgibbs			case SEARCH_COUNT:
751897883Sgibbs				ahd_qinfifo_requeue(ahd, prev_scb, scb);
751997883Sgibbs				prev_scb = scb;
752097883Sgibbs				break;
752197883Sgibbs			}
752297883Sgibbs		} else {
752397883Sgibbs			ahd_qinfifo_requeue(ahd, prev_scb, scb);
752497883Sgibbs			prev_scb = scb;
752597883Sgibbs		}
752697883Sgibbs		qinpos = AHD_QIN_WRAP(qinpos+1);
752797883Sgibbs	}
752897883Sgibbs
752997883Sgibbs	ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
753097883Sgibbs
753197883Sgibbs	if (action == SEARCH_PRINT)
753297883Sgibbs		printf("\nWAITING_TID_QUEUES:\n");
753397883Sgibbs
753497883Sgibbs	/*
753597883Sgibbs	 * Search waiting for selection lists.  We traverse the
753697883Sgibbs	 * list of "their ids" waiting for selection and, if
753797883Sgibbs	 * appropriate, traverse the SCBs of each "their id"
753897883Sgibbs	 * looking for matches.
753997883Sgibbs	 */
7540125448Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
7541133122Sgibbs	seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2);
7542133122Sgibbs	if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) {
7543133122Sgibbs		scbid = ahd_inw(ahd, MK_MESSAGE_SCB);
7544133122Sgibbs		mk_msg_scb = ahd_lookup_scb(ahd, scbid);
7545133122Sgibbs	} else
7546133122Sgibbs		mk_msg_scb = NULL;
754797883Sgibbs	savedscbptr = ahd_get_scbptr(ahd);
754897883Sgibbs	tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
754997883Sgibbs	tid_prev = SCB_LIST_NULL;
755097883Sgibbs	targets = 0;
755197883Sgibbs	for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) {
755297883Sgibbs		u_int tid_head;
7553133122Sgibbs		u_int tid_tail;
755497883Sgibbs
755597883Sgibbs		targets++;
7556133122Sgibbs		if (targets > AHD_NUM_TARGETS)
755797883Sgibbs			panic("TID LIST LOOP");
7558133122Sgibbs
755997883Sgibbs		if (scbid >= ahd->scb_data.numscbs) {
756097883Sgibbs			printf("%s: Waiting TID List inconsistency. "
756197883Sgibbs			       "SCB index == 0x%x, yet numscbs == 0x%x.",
756297883Sgibbs			       ahd_name(ahd), scbid, ahd->scb_data.numscbs);
756397883Sgibbs			ahd_dump_card_state(ahd);
756497883Sgibbs			panic("for safety");
756597883Sgibbs		}
756697883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
756797883Sgibbs		if (scb == NULL) {
756897883Sgibbs			printf("%s: SCB = 0x%x Not Active!\n",
756997883Sgibbs			       ahd_name(ahd), scbid);
757097883Sgibbs			panic("Waiting TID List traversal\n");
757197883Sgibbs		}
757297883Sgibbs		ahd_set_scbptr(ahd, scbid);
757397883Sgibbs		tid_next = ahd_inw_scbram(ahd, SCB_NEXT2);
757497883Sgibbs		if (ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
757597883Sgibbs				  SCB_LIST_NULL, ROLE_UNKNOWN) == 0) {
757697883Sgibbs			tid_prev = scbid;
757797883Sgibbs			continue;
757897883Sgibbs		}
757997883Sgibbs
758097883Sgibbs		/*
758197883Sgibbs		 * We found a list of scbs that needs to be searched.
758297883Sgibbs		 */
758397883Sgibbs		if (action == SEARCH_PRINT)
758497883Sgibbs			printf("       %d ( ", SCB_GET_TARGET(ahd, scb));
758597883Sgibbs		tid_head = scbid;
758697883Sgibbs		found += ahd_search_scb_list(ahd, target, channel,
758797883Sgibbs					     lun, tag, role, status,
7588133122Sgibbs					     action, &tid_head, &tid_tail,
758997883Sgibbs					     SCB_GET_TARGET(ahd, scb));
7590133122Sgibbs		/*
7591133122Sgibbs		 * Check any MK_MESSAGE SCB that is still waiting to
7592133122Sgibbs		 * enter this target's waiting for selection queue.
7593133122Sgibbs		 */
7594133122Sgibbs		if (mk_msg_scb != NULL
7595133122Sgibbs		 && ahd_match_scb(ahd, mk_msg_scb, target, channel,
7596133122Sgibbs				  lun, tag, role)) {
7597133122Sgibbs
7598133122Sgibbs			/*
7599133122Sgibbs			 * We found an scb that needs to be acted on.
7600133122Sgibbs			 */
7601133122Sgibbs			found++;
7602133122Sgibbs			switch (action) {
7603133122Sgibbs			case SEARCH_COMPLETE:
7604133122Sgibbs				if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)
7605133122Sgibbs					printf("Inactive SCB pending MK_MSG\n");
7606133122Sgibbs				ahd_done_with_status(ahd, mk_msg_scb, status);
7607133122Sgibbs				/* FALLTHROUGH */
7608133122Sgibbs			case SEARCH_REMOVE:
7609133122Sgibbs			{
7610133122Sgibbs				u_int tail_offset;
7611133122Sgibbs
7612133122Sgibbs				printf("Removing MK_MSG scb\n");
7613133122Sgibbs
7614133122Sgibbs				/*
7615133122Sgibbs				 * Reset our tail to the tail of the
7616133122Sgibbs				 * main per-target list.
7617133122Sgibbs				 */
7618133122Sgibbs				tail_offset = WAITING_SCB_TAILS
7619133122Sgibbs				    + (2 * SCB_GET_TARGET(ahd, mk_msg_scb));
7620133122Sgibbs				ahd_outw(ahd, tail_offset, tid_tail);
7621133122Sgibbs
7622133122Sgibbs				seq_flags2 &= ~PENDING_MK_MESSAGE;
7623133122Sgibbs				ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
7624133122Sgibbs				ahd_outw(ahd, CMDS_PENDING,
7625133122Sgibbs					 ahd_inw(ahd, CMDS_PENDING)-1);
7626133122Sgibbs				mk_msg_scb = NULL;
7627133122Sgibbs				break;
7628133122Sgibbs			}
7629133122Sgibbs			case SEARCH_PRINT:
7630133122Sgibbs				printf(" 0x%x", SCB_GET_TAG(scb));
7631133122Sgibbs				/* FALLTHROUGH */
7632133122Sgibbs			case SEARCH_COUNT:
7633133122Sgibbs				break;
7634133122Sgibbs			}
7635133122Sgibbs		}
7636133122Sgibbs
7637133122Sgibbs		if (mk_msg_scb != NULL
7638133122Sgibbs		 && SCBID_IS_NULL(tid_head)
7639133122Sgibbs		 && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
7640133122Sgibbs				  SCB_LIST_NULL, ROLE_UNKNOWN)) {
7641133122Sgibbs
7642133122Sgibbs			/*
7643133122Sgibbs			 * When removing the last SCB for a target
7644133122Sgibbs			 * queue with a pending MK_MESSAGE scb, we
7645133122Sgibbs			 * must queue the MK_MESSAGE scb.
7646133122Sgibbs			 */
7647133122Sgibbs			printf("Queueing mk_msg_scb\n");
7648133122Sgibbs			tid_head = ahd_inw(ahd, MK_MESSAGE_SCB);
7649133122Sgibbs			seq_flags2 &= ~PENDING_MK_MESSAGE;
7650133122Sgibbs			ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
7651133122Sgibbs			mk_msg_scb = NULL;
7652133122Sgibbs		}
765397883Sgibbs		if (tid_head != scbid)
765497883Sgibbs			ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next);
765597883Sgibbs		if (!SCBID_IS_NULL(tid_head))
765697883Sgibbs			tid_prev = tid_head;
765797883Sgibbs		if (action == SEARCH_PRINT)
765897883Sgibbs			printf(")\n");
765997883Sgibbs	}
7660133122Sgibbs
7661133122Sgibbs	/* Restore saved state. */
766297883Sgibbs	ahd_set_scbptr(ahd, savedscbptr);
766397883Sgibbs	ahd_restore_modes(ahd, saved_modes);
766497883Sgibbs	return (found);
766597883Sgibbs}
766697883Sgibbs
766797883Sgibbsstatic int
766897883Sgibbsahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
766997883Sgibbs		    int lun, u_int tag, role_t role, uint32_t status,
7670133122Sgibbs		    ahd_search_action action, u_int *list_head,
7671133122Sgibbs		    u_int *list_tail, u_int tid)
767297883Sgibbs{
767397883Sgibbs	struct	scb *scb;
767497883Sgibbs	u_int	scbid;
767597883Sgibbs	u_int	next;
767697883Sgibbs	u_int	prev;
767797883Sgibbs	int	found;
767897883Sgibbs
7679125448Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
768097883Sgibbs	found = 0;
768197883Sgibbs	prev = SCB_LIST_NULL;
768297883Sgibbs	next = *list_head;
7683133122Sgibbs	*list_tail = SCB_LIST_NULL;
768497883Sgibbs	for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) {
768597883Sgibbs		if (scbid >= ahd->scb_data.numscbs) {
768697883Sgibbs			printf("%s:SCB List inconsistency. "
768797883Sgibbs			       "SCB == 0x%x, yet numscbs == 0x%x.",
768897883Sgibbs			       ahd_name(ahd), scbid, ahd->scb_data.numscbs);
768997883Sgibbs			ahd_dump_card_state(ahd);
769097883Sgibbs			panic("for safety");
769197883Sgibbs		}
769297883Sgibbs		scb = ahd_lookup_scb(ahd, scbid);
769397883Sgibbs		if (scb == NULL) {
769497883Sgibbs			printf("%s: SCB = %d Not Active!\n",
769597883Sgibbs			       ahd_name(ahd), scbid);
769697883Sgibbs			panic("Waiting List traversal\n");
769797883Sgibbs		}
769897883Sgibbs		ahd_set_scbptr(ahd, scbid);
7699133122Sgibbs		*list_tail = scbid;
770097883Sgibbs		next = ahd_inw_scbram(ahd, SCB_NEXT);
770197883Sgibbs		if (ahd_match_scb(ahd, scb, target, channel,
770297883Sgibbs				  lun, SCB_LIST_NULL, role) == 0) {
770397883Sgibbs			prev = scbid;
770497883Sgibbs			continue;
770597883Sgibbs		}
770697883Sgibbs		found++;
770797883Sgibbs		switch (action) {
770897883Sgibbs		case SEARCH_COMPLETE:
770997883Sgibbs			if ((scb->flags & SCB_ACTIVE) == 0)
771097883Sgibbs				printf("Inactive SCB in Waiting List\n");
7711133122Sgibbs			ahd_done_with_status(ahd, scb, status);
771297883Sgibbs			/* FALLTHROUGH */
771397883Sgibbs		case SEARCH_REMOVE:
771497883Sgibbs			ahd_rem_wscb(ahd, scbid, prev, next, tid);
7715133122Sgibbs			*list_tail = prev;
7716133122Sgibbs			if (SCBID_IS_NULL(prev))
771797883Sgibbs				*list_head = next;
771897883Sgibbs			break;
771997883Sgibbs		case SEARCH_PRINT:
772097883Sgibbs			printf("0x%x ", scbid);
772197883Sgibbs		case SEARCH_COUNT:
772297883Sgibbs			prev = scbid;
772397883Sgibbs			break;
772497883Sgibbs		}
772597883Sgibbs		if (found > AHD_SCB_MAX)
772697883Sgibbs			panic("SCB LIST LOOP");
772797883Sgibbs	}
7728109588Sgibbs	if (action == SEARCH_COMPLETE
7729109588Sgibbs	 || action == SEARCH_REMOVE)
7730109588Sgibbs		ahd_outw(ahd, CMDS_PENDING, ahd_inw(ahd, CMDS_PENDING) - found);
773197883Sgibbs	return (found);
773297883Sgibbs}
773397883Sgibbs
773497883Sgibbsstatic void
773597883Sgibbsahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
773697883Sgibbs		    u_int tid_cur, u_int tid_next)
773797883Sgibbs{
7738125448Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
773997883Sgibbs
774097883Sgibbs	if (SCBID_IS_NULL(tid_cur)) {
774197883Sgibbs
774297883Sgibbs		/* Bypass current TID list */
774397883Sgibbs		if (SCBID_IS_NULL(tid_prev)) {
774497883Sgibbs			ahd_outw(ahd, WAITING_TID_HEAD, tid_next);
774597883Sgibbs		} else {
774697883Sgibbs			ahd_set_scbptr(ahd, tid_prev);
774797883Sgibbs			ahd_outw(ahd, SCB_NEXT2, tid_next);
774897883Sgibbs		}
774997883Sgibbs		if (SCBID_IS_NULL(tid_next))
775097883Sgibbs			ahd_outw(ahd, WAITING_TID_TAIL, tid_prev);
775197883Sgibbs	} else {
775297883Sgibbs
775397883Sgibbs		/* Stitch through tid_cur */
775497883Sgibbs		if (SCBID_IS_NULL(tid_prev)) {
775597883Sgibbs			ahd_outw(ahd, WAITING_TID_HEAD, tid_cur);
775697883Sgibbs		} else {
775797883Sgibbs			ahd_set_scbptr(ahd, tid_prev);
775897883Sgibbs			ahd_outw(ahd, SCB_NEXT2, tid_cur);
775997883Sgibbs		}
776097883Sgibbs		ahd_set_scbptr(ahd, tid_cur);
776197883Sgibbs		ahd_outw(ahd, SCB_NEXT2, tid_next);
776297883Sgibbs
776397883Sgibbs		if (SCBID_IS_NULL(tid_next))
776497883Sgibbs			ahd_outw(ahd, WAITING_TID_TAIL, tid_cur);
776597883Sgibbs	}
776697883Sgibbs}
776797883Sgibbs
776897883Sgibbs/*
776997883Sgibbs * Manipulate the waiting for selection list and return the
777097883Sgibbs * scb that follows the one that we remove.
777197883Sgibbs */
777297883Sgibbsstatic u_int
777397883Sgibbsahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
777497883Sgibbs	     u_int prev, u_int next, u_int tid)
777597883Sgibbs{
777697883Sgibbs	u_int tail_offset;
777797883Sgibbs
7778125448Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
777997883Sgibbs	if (!SCBID_IS_NULL(prev)) {
778097883Sgibbs		ahd_set_scbptr(ahd, prev);
778197883Sgibbs		ahd_outw(ahd, SCB_NEXT, next);
778297883Sgibbs	}
778397883Sgibbs
778497883Sgibbs	/*
7785133122Sgibbs	 * SCBs that have MK_MESSAGE set in them may
7786133122Sgibbs	 * cause the tail pointer to be updated without
7787133122Sgibbs	 * setting the next pointer of the previous tail.
7788133122Sgibbs	 * Only clear the tail if the removed SCB was
7789133122Sgibbs	 * the tail.
779097883Sgibbs	 */
779197883Sgibbs	tail_offset = WAITING_SCB_TAILS + (2 * tid);
779297883Sgibbs	if (SCBID_IS_NULL(next)
779397883Sgibbs	 && ahd_inw(ahd, tail_offset) == scbid)
779497883Sgibbs		ahd_outw(ahd, tail_offset, prev);
7795133122Sgibbs
779697883Sgibbs	ahd_add_scb_to_free_list(ahd, scbid);
779797883Sgibbs	return (next);
779897883Sgibbs}
779997883Sgibbs
780097883Sgibbs/*
780197883Sgibbs * Add the SCB as selected by SCBPTR onto the on chip list of
780297883Sgibbs * free hardware SCBs.  This list is empty/unused if we are not
780397883Sgibbs * performing SCB paging.
780497883Sgibbs */
780597883Sgibbsstatic void
780697883Sgibbsahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid)
780797883Sgibbs{
780897883Sgibbs/* XXX Need some other mechanism to designate "free". */
780997883Sgibbs	/*
781097883Sgibbs	 * Invalidate the tag so that our abort
781197883Sgibbs	 * routines don't think it's active.
781297883Sgibbs	ahd_outb(ahd, SCB_TAG, SCB_LIST_NULL);
781397883Sgibbs	 */
781497883Sgibbs}
781597883Sgibbs
781697883Sgibbs/******************************** Error Handling ******************************/
781797883Sgibbs/*
781897883Sgibbs * Abort all SCBs that match the given description (target/channel/lun/tag),
781997883Sgibbs * setting their status to the passed in status if the status has not already
782097883Sgibbs * been modified from CAM_REQ_INPROG.  This routine assumes that the sequencer
782197883Sgibbs * is paused before it is called.
782297883Sgibbs */
782397883Sgibbsint
782497883Sgibbsahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
782597883Sgibbs	       int lun, u_int tag, role_t role, uint32_t status)
782697883Sgibbs{
7827104023Sgibbs	struct		scb *scbp;
7828104023Sgibbs	struct		scb *scbp_next;
7829104023Sgibbs	u_int		i, j;
7830104023Sgibbs	u_int		maxtarget;
7831104023Sgibbs	u_int		minlun;
7832104023Sgibbs	u_int		maxlun;
7833104023Sgibbs	int		found;
7834104023Sgibbs	ahd_mode_state	saved_modes;
783597883Sgibbs
7836114623Sgibbs	/* restore this when we're done */
7837104023Sgibbs	saved_modes = ahd_save_modes(ahd);
7838114623Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
783997883Sgibbs
784097883Sgibbs	found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL,
784197883Sgibbs				   role, CAM_REQUEUE_REQ, SEARCH_COMPLETE);
784297883Sgibbs
784397883Sgibbs	/*
784497883Sgibbs	 * Clean out the busy target table for any untagged commands.
784597883Sgibbs	 */
784697883Sgibbs	i = 0;
784797883Sgibbs	maxtarget = 16;
784897883Sgibbs	if (target != CAM_TARGET_WILDCARD) {
784997883Sgibbs		i = target;
785097883Sgibbs		if (channel == 'B')
785197883Sgibbs			i += 8;
785297883Sgibbs		maxtarget = i + 1;
785397883Sgibbs	}
785497883Sgibbs
785597883Sgibbs	if (lun == CAM_LUN_WILDCARD) {
785697883Sgibbs		minlun = 0;
785797883Sgibbs		maxlun = AHD_NUM_LUNS_NONPKT;
785897883Sgibbs	} else if (lun >= AHD_NUM_LUNS_NONPKT) {
785997883Sgibbs		minlun = maxlun = 0;
786097883Sgibbs	} else {
786197883Sgibbs		minlun = lun;
786297883Sgibbs		maxlun = lun + 1;
786397883Sgibbs	}
786497883Sgibbs
786597883Sgibbs	if (role != ROLE_TARGET) {
786697883Sgibbs		for (;i < maxtarget; i++) {
786797883Sgibbs			for (j = minlun;j < maxlun; j++) {
786897883Sgibbs				u_int scbid;
786997883Sgibbs				u_int tcl;
787097883Sgibbs
7871102679Sgibbs				tcl = BUILD_TCL_RAW(i, 'A', j);
787297883Sgibbs				scbid = ahd_find_busy_tcl(ahd, tcl);
787397883Sgibbs				scbp = ahd_lookup_scb(ahd, scbid);
787497883Sgibbs				if (scbp == NULL
787597883Sgibbs				 || ahd_match_scb(ahd, scbp, target, channel,
787697883Sgibbs						  lun, tag, role) == 0)
787797883Sgibbs					continue;
787897883Sgibbs				ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(i, 'A', j));
787997883Sgibbs			}
788097883Sgibbs		}
788197883Sgibbs	}
788297883Sgibbs
788397883Sgibbs	/*
7884109588Sgibbs	 * Don't abort commands that have already completed,
7885109588Sgibbs	 * but haven't quite made it up to the host yet.
7886109588Sgibbs	 */
7887109588Sgibbs	ahd_flush_qoutfifo(ahd);
7888109588Sgibbs
7889109588Sgibbs	/*
789097883Sgibbs	 * Go through the pending CCB list and look for
789197883Sgibbs	 * commands for this target that are still active.
789297883Sgibbs	 * These are other tagged commands that were
789397883Sgibbs	 * disconnected when the reset occurred.
789497883Sgibbs	 */
789597883Sgibbs	scbp_next = LIST_FIRST(&ahd->pending_scbs);
789697883Sgibbs	while (scbp_next != NULL) {
789797883Sgibbs		scbp = scbp_next;
789897883Sgibbs		scbp_next = LIST_NEXT(scbp, pending_links);
789997883Sgibbs		if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) {
790097883Sgibbs			cam_status ostat;
790197883Sgibbs
7902123579Sgibbs			ostat = aic_get_transaction_status(scbp);
790397883Sgibbs			if (ostat == CAM_REQ_INPROG)
7904123579Sgibbs				aic_set_transaction_status(scbp, status);
7905123579Sgibbs			if (aic_get_transaction_status(scbp) != CAM_REQ_CMP)
7906123579Sgibbs				aic_freeze_scb(scbp);
790797883Sgibbs			if ((scbp->flags & SCB_ACTIVE) == 0)
790897883Sgibbs				printf("Inactive SCB on pending list\n");
790997883Sgibbs			ahd_done(ahd, scbp);
791097883Sgibbs			found++;
791197883Sgibbs		}
791297883Sgibbs	}
7913104023Sgibbs	ahd_restore_modes(ahd, saved_modes);
791497883Sgibbs	ahd_platform_abort_scbs(ahd, target, channel, lun, tag, role, status);
7915109588Sgibbs	ahd->flags |= AHD_UPDATE_PEND_CMDS;
791697883Sgibbs	return found;
791797883Sgibbs}
791897883Sgibbs
791997883Sgibbsstatic void
792097883Sgibbsahd_reset_current_bus(struct ahd_softc *ahd)
792197883Sgibbs{
792297883Sgibbs	uint8_t scsiseq;
792397883Sgibbs
792497883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
792597883Sgibbs	ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST);
7926102679Sgibbs	scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);
792797883Sgibbs	ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);
7928116935Sgibbs	ahd_flush_device_writes(ahd);
7929123579Sgibbs	aic_delay(AHD_BUSRESET_DELAY);
793097883Sgibbs	/* Turn off the bus reset */
7931102679Sgibbs	ahd_outb(ahd, SCSISEQ0, scsiseq);
7932116935Sgibbs	ahd_flush_device_writes(ahd);
7933123579Sgibbs	aic_delay(AHD_BUSRESET_DELAY);
793497883Sgibbs	if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {
793597883Sgibbs		/*
793697883Sgibbs		 * 2A Razor #474
793797883Sgibbs		 * Certain chip state is not cleared for
793897883Sgibbs		 * SCSI bus resets that we initiate, so
793997883Sgibbs		 * we must reset the chip.
794097883Sgibbs		 */
7941115917Sgibbs		ahd_reset(ahd, /*reinit*/TRUE);
794297883Sgibbs		ahd_intr_enable(ahd, /*enable*/TRUE);
794397883Sgibbs		AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
794497883Sgibbs	}
794597883Sgibbs
794697883Sgibbs	ahd_clear_intstat(ahd);
794797883Sgibbs}
794897883Sgibbs
794997883Sgibbsint
795097883Sgibbsahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
795197883Sgibbs{
795297883Sgibbs	struct	ahd_devinfo devinfo;
7953102679Sgibbs	u_int	initiator;
795497883Sgibbs	u_int	target;
795597883Sgibbs	u_int	max_scsiid;
795697883Sgibbs	int	found;
7957102679Sgibbs	u_int	fifo;
7958102679Sgibbs	u_int	next_fifo;
795997883Sgibbs
796097883Sgibbs	ahd->pending_device = NULL;
796197883Sgibbs
796297883Sgibbs	ahd_compile_devinfo(&devinfo,
796397883Sgibbs			    CAM_TARGET_WILDCARD,
796497883Sgibbs			    CAM_TARGET_WILDCARD,
796597883Sgibbs			    CAM_LUN_WILDCARD,
796697883Sgibbs			    channel, ROLE_UNKNOWN);
796797883Sgibbs	ahd_pause(ahd);
796897883Sgibbs
796997883Sgibbs	/* Make sure the sequencer is in a safe location. */
797097883Sgibbs	ahd_clear_critical_section(ahd);
797197883Sgibbs
7972153072Sru#ifdef AHD_TARGET_MODE
797397883Sgibbs	if ((ahd->flags & AHD_TARGETROLE) != 0) {
797497883Sgibbs		ahd_run_tqinfifo(ahd, /*paused*/TRUE);
797597883Sgibbs	}
797697883Sgibbs#endif
797797883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
797897883Sgibbs
797997883Sgibbs	/*
7980102679Sgibbs	 * Disable selections so no automatic hardware
7981102679Sgibbs	 * functions will modify chip state.
7982102679Sgibbs	 */
7983102679Sgibbs	ahd_outb(ahd, SCSISEQ0, 0);
7984102679Sgibbs	ahd_outb(ahd, SCSISEQ1, 0);
7985102679Sgibbs
7986102679Sgibbs	/*
7987102679Sgibbs	 * Safely shut down our DMA engines.  Always start with
7988102679Sgibbs	 * the FIFO that is not currently active (if any are
7989102679Sgibbs	 * actively connected).
7990102679Sgibbs	 */
7991102679Sgibbs	next_fifo = fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
7992107441Sscottl	if (next_fifo > CURRFIFO_1)
7993107441Sscottl		/* If disconneced, arbitrarily start with FIFO1. */
7994107441Sscottl		next_fifo = fifo = 0;
7995102679Sgibbs	do {
7996107441Sscottl		next_fifo ^= CURRFIFO_1;
7997102679Sgibbs		ahd_set_modes(ahd, next_fifo, next_fifo);
7998104023Sgibbs		ahd_outb(ahd, DFCNTRL,
7999104023Sgibbs			 ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN));
8000102679Sgibbs		while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0)
8001123579Sgibbs			aic_delay(10);
8002102679Sgibbs		/*
8003102679Sgibbs		 * Set CURRFIFO to the now inactive channel.
8004102679Sgibbs		 */
8005102679Sgibbs		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
8006102679Sgibbs		ahd_outb(ahd, DFFSTAT, next_fifo);
8007102679Sgibbs	} while (next_fifo != fifo);
8008114623Sgibbs
8009102679Sgibbs	/*
801097883Sgibbs	 * Reset the bus if we are initiating this reset
801197883Sgibbs	 */
801297883Sgibbs	ahd_clear_msg_state(ahd);
8013104023Sgibbs	ahd_outb(ahd, SIMODE1,
8014123579Sgibbs		 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
8015114623Sgibbs
801697883Sgibbs	if (initiate_reset)
801797883Sgibbs		ahd_reset_current_bus(ahd);
8018114623Sgibbs
801997883Sgibbs	ahd_clear_intstat(ahd);
802097883Sgibbs
802197883Sgibbs	/*
802297883Sgibbs	 * Clean up all the state information for the
802397883Sgibbs	 * pending transactions on this bus.
802497883Sgibbs	 */
802597883Sgibbs	found = ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, channel,
802697883Sgibbs			       CAM_LUN_WILDCARD, SCB_LIST_NULL,
802797883Sgibbs			       ROLE_UNKNOWN, CAM_SCSI_BUS_RESET);
802897883Sgibbs
8029102679Sgibbs	/*
8030102679Sgibbs	 * Cleanup anything left in the FIFOs.
8031102679Sgibbs	 */
8032102679Sgibbs	ahd_clear_fifo(ahd, 0);
8033102679Sgibbs	ahd_clear_fifo(ahd, 1);
8034102679Sgibbs
8035102679Sgibbs	/*
8036102679Sgibbs	 * Revert to async/narrow transfers until we renegotiate.
8037102679Sgibbs	 */
8038102679Sgibbs	max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
8039102679Sgibbs	for (target = 0; target <= max_scsiid; target++) {
8040102679Sgibbs
8041102679Sgibbs		if (ahd->enabled_targets[target] == NULL)
8042102679Sgibbs			continue;
8043102679Sgibbs		for (initiator = 0; initiator <= max_scsiid; initiator++) {
8044102679Sgibbs			struct ahd_devinfo devinfo;
8045102679Sgibbs
8046102679Sgibbs			ahd_compile_devinfo(&devinfo, target, initiator,
8047102679Sgibbs					    CAM_LUN_WILDCARD,
8048102679Sgibbs					    'A', ROLE_UNKNOWN);
8049102679Sgibbs			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
8050102679Sgibbs				      AHD_TRANS_CUR, /*paused*/TRUE);
8051102679Sgibbs			ahd_set_syncrate(ahd, &devinfo, /*period*/0,
8052102679Sgibbs					 /*offset*/0, /*ppr_options*/0,
8053102679Sgibbs					 AHD_TRANS_CUR, /*paused*/TRUE);
8054102679Sgibbs		}
8055102679Sgibbs	}
8056102679Sgibbs
805797883Sgibbs#ifdef AHD_TARGET_MODE
805897883Sgibbs	max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
805997883Sgibbs
806097883Sgibbs	/*
806197883Sgibbs	 * Send an immediate notify ccb to all target more peripheral
806297883Sgibbs	 * drivers affected by this action.
806397883Sgibbs	 */
806497883Sgibbs	for (target = 0; target <= max_scsiid; target++) {
806597883Sgibbs		struct ahd_tmode_tstate* tstate;
806697883Sgibbs		u_int lun;
806797883Sgibbs
806897883Sgibbs		tstate = ahd->enabled_targets[target];
806997883Sgibbs		if (tstate == NULL)
807097883Sgibbs			continue;
807197883Sgibbs		for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
807297883Sgibbs			struct ahd_tmode_lstate* lstate;
807397883Sgibbs
807497883Sgibbs			lstate = tstate->enabled_luns[lun];
807597883Sgibbs			if (lstate == NULL)
807697883Sgibbs				continue;
807797883Sgibbs
807897883Sgibbs			ahd_queue_lstate_event(ahd, lstate, CAM_TARGET_WILDCARD,
807997883Sgibbs					       EVENT_TYPE_BUS_RESET, /*arg*/0);
808097883Sgibbs			ahd_send_lstate_events(ahd, lstate);
808197883Sgibbs		}
808297883Sgibbs	}
808397883Sgibbs#endif
808497883Sgibbs	/* Notify the XPT that a bus reset occurred */
808597883Sgibbs	ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
808697883Sgibbs		       CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
8087104023Sgibbs	ahd_restart(ahd);
808897883Sgibbs	/*
808997883Sgibbs	 * Freeze the SIMQ until our poller can determine that
809097883Sgibbs	 * the bus reset has really gone away.  We set the initial
809197883Sgibbs	 * timer to 0 to have the check performed as soon as possible
809297883Sgibbs	 * from the timer context.
809397883Sgibbs	 */
8094102679Sgibbs	if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) {
8095102679Sgibbs		ahd->flags |= AHD_RESET_POLL_ACTIVE;
8096123579Sgibbs		aic_freeze_simq(ahd);
8097123579Sgibbs		aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
8098102679Sgibbs	}
809997883Sgibbs	return (found);
810097883Sgibbs}
810197883Sgibbs
810297883Sgibbs
8103137870Sgibbs#define AHD_RESET_POLL_MS 1
810497883Sgibbsstatic void
810597883Sgibbsahd_reset_poll(void *arg)
810697883Sgibbs{
8107168807Sscottl	struct	ahd_softc *ahd = (struct ahd_softc *)arg;
810897883Sgibbs	u_int	scsiseq1;
810997883Sgibbs
8110168807Sscottl	ahd_lock(ahd);
8111102679Sgibbs	ahd_pause(ahd);
8112104023Sgibbs	ahd_update_modes(ahd);
8113104023Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
8114102679Sgibbs	ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
8115102679Sgibbs	if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
8116137870Sgibbs		aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS,
811797883Sgibbs				ahd_reset_poll, ahd);
8118102679Sgibbs		ahd_unpause(ahd);
8119168807Sscottl		ahd_unlock(ahd);
8120102679Sgibbs		return;
812197883Sgibbs	}
812297883Sgibbs
812397883Sgibbs	/* Reset is now low.  Complete chip reinitialization. */
812497883Sgibbs	ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
812597883Sgibbs	scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
812697883Sgibbs	ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
8127102679Sgibbs	ahd_unpause(ahd);
8128102679Sgibbs	ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
8129123579Sgibbs	aic_release_simq(ahd);
8130168807Sscottl	ahd_unlock(ahd);
813197883Sgibbs}
813297883Sgibbs
8133109588Sgibbs/**************************** Statistics Processing ***************************/
8134109588Sgibbsstatic void
8135109588Sgibbsahd_stat_timer(void *arg)
8136109588Sgibbs{
8137168807Sscottl	struct	ahd_softc *ahd = (struct ahd_softc *)arg;
8138109588Sgibbs	int	enint_coal;
8139109588Sgibbs
8140168807Sscottl	ahd_lock(ahd);
8141115329Sgibbs	enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
8142115329Sgibbs	if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold)
8143115329Sgibbs		enint_coal |= ENINT_COALESCE;
8144115329Sgibbs	else if (ahd->cmdcmplt_total < ahd->int_coalescing_stop_threshold)
8145115329Sgibbs		enint_coal &= ~ENINT_COALESCE;
8146109588Sgibbs
8147115329Sgibbs	if (enint_coal != (ahd->hs_mailbox & ENINT_COALESCE)) {
8148115329Sgibbs		ahd_enable_coalescing(ahd, enint_coal);
8149109588Sgibbs#ifdef AHD_DEBUG
8150115329Sgibbs		if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0)
8151115329Sgibbs			printf("%s: Interrupt coalescing "
8152109588Sgibbs			       "now %sabled. Cmds %d\n",
8153109588Sgibbs			       ahd_name(ahd),
8154115329Sgibbs			       (enint_coal & ENINT_COALESCE) ? "en" : "dis",
8155109588Sgibbs			       ahd->cmdcmplt_total);
8156109588Sgibbs#endif
8157109588Sgibbs	}
8158109588Sgibbs
8159109588Sgibbs	ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1);
8160109588Sgibbs	ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket];
8161109588Sgibbs	ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;
8162137870Sgibbs	aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
8163109588Sgibbs			ahd_stat_timer, ahd);
8164168807Sscottl	ahd_unlock(ahd);
8165109588Sgibbs}
8166109588Sgibbs
816797883Sgibbs/****************************** Status Processing *****************************/
816897883Sgibbsvoid
816997883Sgibbsahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
817097883Sgibbs{
817197883Sgibbs	if (scb->hscb->shared_data.istatus.scsi_status != 0) {
817297883Sgibbs		ahd_handle_scsi_status(ahd, scb);
817397883Sgibbs	} else {
817497883Sgibbs		ahd_calc_residual(ahd, scb);
817597883Sgibbs		ahd_done(ahd, scb);
817697883Sgibbs	}
817797883Sgibbs}
817897883Sgibbs
817997883Sgibbsvoid
818097883Sgibbsahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
818197883Sgibbs{
8182123579Sgibbs	struct	hardware_scb *hscb;
8183123579Sgibbs	int	paused;
818497883Sgibbs
818597883Sgibbs	/*
818697883Sgibbs	 * The sequencer freezes its select-out queue
818797883Sgibbs	 * anytime a SCSI status error occurs.  We must
8188125448Sgibbs	 * handle the error and increment our qfreeze count
8189125448Sgibbs	 * to allow the sequencer to continue.  We don't
8190125448Sgibbs	 * bother clearing critical sections here since all
8191125448Sgibbs	 * operations are on data structures that the sequencer
8192125448Sgibbs	 * is not touching once the queue is frozen.
819397883Sgibbs	 */
819497883Sgibbs	hscb = scb->hscb;
819597883Sgibbs
8196123579Sgibbs	if (ahd_is_paused(ahd)) {
8197123579Sgibbs		paused = 1;
8198123579Sgibbs	} else {
8199123579Sgibbs		paused = 0;
8200123579Sgibbs		ahd_pause(ahd);
8201123579Sgibbs	}
8202123579Sgibbs
820397883Sgibbs	/* Freeze the queue until the client sees the error. */
820497883Sgibbs	ahd_freeze_devq(ahd, scb);
8205123579Sgibbs	aic_freeze_scb(scb);
8206125448Sgibbs	ahd->qfreeze_cnt++;
8207125448Sgibbs	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
8208114623Sgibbs
8209123579Sgibbs	if (paused == 0)
8210123579Sgibbs		ahd_unpause(ahd);
8211123579Sgibbs
8212102679Sgibbs	/* Don't want to clobber the original sense code */
8213102679Sgibbs	if ((scb->flags & SCB_SENSE) != 0) {
8214102679Sgibbs		/*
8215102679Sgibbs		 * Clear the SCB_SENSE Flag and perform
8216102679Sgibbs		 * a normal command completion.
8217102679Sgibbs		 */
8218102679Sgibbs		scb->flags &= ~SCB_SENSE;
8219123579Sgibbs		aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
8220102679Sgibbs		ahd_done(ahd, scb);
8221102679Sgibbs		return;
8222102679Sgibbs	}
8223123579Sgibbs	aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
8224123579Sgibbs	aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status);
822597883Sgibbs	switch (hscb->shared_data.istatus.scsi_status) {
822697883Sgibbs	case STATUS_PKT_SENSE:
822797883Sgibbs	{
822897883Sgibbs		struct scsi_status_iu_header *siu;
822997883Sgibbs
823097883Sgibbs		ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD);
823197883Sgibbs		siu = (struct scsi_status_iu_header *)scb->sense_data;
8232123579Sgibbs		aic_set_scsi_status(scb, siu->status);
823397883Sgibbs#ifdef AHD_DEBUG
8234107441Sscottl		if ((ahd_debug & AHD_SHOW_SENSE) != 0) {
823597883Sgibbs			ahd_print_path(ahd, scb);
823697883Sgibbs			printf("SCB 0x%x Received PKT Status of 0x%x\n",
823797883Sgibbs			       SCB_GET_TAG(scb), siu->status);
823897883Sgibbs			printf("\tflags = 0x%x, sense len = 0x%x, "
823997883Sgibbs			       "pktfail = 0x%x\n",
824097883Sgibbs			       siu->flags, scsi_4btoul(siu->sense_length),
824197883Sgibbs			       scsi_4btoul(siu->pkt_failures_length));
8242107441Sscottl		}
824397883Sgibbs#endif
824497883Sgibbs		if ((siu->flags & SIU_RSPVALID) != 0) {
824597883Sgibbs			ahd_print_path(ahd, scb);
824697883Sgibbs			if (scsi_4btoul(siu->pkt_failures_length) < 4) {
824797883Sgibbs				printf("Unable to parse pkt_failures\n");
824897883Sgibbs			} else {
824997883Sgibbs
825097883Sgibbs				switch (SIU_PKTFAIL_CODE(siu)) {
825197883Sgibbs				case SIU_PFC_NONE:
825297883Sgibbs					printf("No packet failure found\n");
8253199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
825497883Sgibbs					break;
825597883Sgibbs				case SIU_PFC_CIU_FIELDS_INVALID:
825697883Sgibbs					printf("Invalid Command IU Field\n");
8257199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
825897883Sgibbs					break;
825997883Sgibbs				case SIU_PFC_TMF_NOT_SUPPORTED:
826097883Sgibbs					printf("TMF not supportd\n");
8261199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
826297883Sgibbs					break;
826397883Sgibbs				case SIU_PFC_TMF_FAILED:
826497883Sgibbs					printf("TMF failed\n");
8265199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
826697883Sgibbs					break;
826797883Sgibbs				case SIU_PFC_INVALID_TYPE_CODE:
826897883Sgibbs					printf("Invalid L_Q Type code\n");
8269199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
827097883Sgibbs					break;
827197883Sgibbs				case SIU_PFC_ILLEGAL_REQUEST:
8272199260Sattilio					AHD_UNCORRECTABLE_ERROR(ahd);
827397883Sgibbs					printf("Illegal request\n");
827497883Sgibbs				default:
827597883Sgibbs					break;
827697883Sgibbs				}
827797883Sgibbs			}
827897883Sgibbs			if (siu->status == SCSI_STATUS_OK)
8279123579Sgibbs				aic_set_transaction_status(scb,
828097883Sgibbs							   CAM_REQ_CMP_ERR);
828197883Sgibbs		}
828297883Sgibbs		if ((siu->flags & SIU_SNSVALID) != 0) {
828397883Sgibbs			scb->flags |= SCB_PKT_SENSE;
828497883Sgibbs#ifdef AHD_DEBUG
828597883Sgibbs			if ((ahd_debug & AHD_SHOW_SENSE) != 0)
828697883Sgibbs				printf("Sense data available\n");
828797883Sgibbs#endif
828897883Sgibbs		}
828997883Sgibbs		ahd_done(ahd, scb);
829097883Sgibbs		break;
829197883Sgibbs	}
829297883Sgibbs	case SCSI_STATUS_CMD_TERMINATED:
829397883Sgibbs	case SCSI_STATUS_CHECK_COND:
829497883Sgibbs	{
829597883Sgibbs		struct ahd_devinfo devinfo;
829697883Sgibbs		struct ahd_dma_seg *sg;
829797883Sgibbs		struct scsi_sense *sc;
829897883Sgibbs		struct ahd_initiator_tinfo *targ_info;
829997883Sgibbs		struct ahd_tmode_tstate *tstate;
830097883Sgibbs		struct ahd_transinfo *tinfo;
830197883Sgibbs#ifdef AHD_DEBUG
830297883Sgibbs		if (ahd_debug & AHD_SHOW_SENSE) {
830397883Sgibbs			ahd_print_path(ahd, scb);
830497883Sgibbs			printf("SCB %d: requests Check Status\n",
830597883Sgibbs			       SCB_GET_TAG(scb));
830697883Sgibbs		}
830797883Sgibbs#endif
830897883Sgibbs
8309123579Sgibbs		if (aic_perform_autosense(scb) == 0)
831097883Sgibbs			break;
831197883Sgibbs
831297883Sgibbs		ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
831397883Sgibbs				    SCB_GET_TARGET(ahd, scb),
831497883Sgibbs				    SCB_GET_LUN(scb),
831597883Sgibbs				    SCB_GET_CHANNEL(ahd, scb),
831697883Sgibbs				    ROLE_INITIATOR);
831797883Sgibbs		targ_info = ahd_fetch_transinfo(ahd,
831897883Sgibbs						devinfo.channel,
831997883Sgibbs						devinfo.our_scsiid,
832097883Sgibbs						devinfo.target,
832197883Sgibbs						&tstate);
832297883Sgibbs		tinfo = &targ_info->curr;
832397883Sgibbs		sg = scb->sg_list;
832497883Sgibbs		sc = (struct scsi_sense *)hscb->shared_data.idata.cdb;
832597883Sgibbs		/*
832697883Sgibbs		 * Save off the residual if there is one.
832797883Sgibbs		 */
832897883Sgibbs		ahd_update_residual(ahd, scb);
832997883Sgibbs#ifdef AHD_DEBUG
833097883Sgibbs		if (ahd_debug & AHD_SHOW_SENSE) {
833197883Sgibbs			ahd_print_path(ahd, scb);
833297883Sgibbs			printf("Sending Sense\n");
833397883Sgibbs		}
833497883Sgibbs#endif
833597883Sgibbs		scb->sg_count = 0;
833697883Sgibbs		sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb),
8337123579Sgibbs				  aic_get_sense_bufsize(ahd, scb),
833897883Sgibbs				  /*last*/TRUE);
833997883Sgibbs		sc->opcode = REQUEST_SENSE;
834097883Sgibbs		sc->byte2 = 0;
834197883Sgibbs		if (tinfo->protocol_version <= SCSI_REV_2
834297883Sgibbs		 && SCB_GET_LUN(scb) < 8)
834397883Sgibbs			sc->byte2 = SCB_GET_LUN(scb) << 5;
834497883Sgibbs		sc->unused[0] = 0;
834597883Sgibbs		sc->unused[1] = 0;
8346123579Sgibbs		sc->length = aic_get_sense_bufsize(ahd, scb);
834797883Sgibbs		sc->control = 0;
834897883Sgibbs
834997883Sgibbs		/*
835097883Sgibbs		 * We can't allow the target to disconnect.
835197883Sgibbs		 * This will be an untagged transaction and
835297883Sgibbs		 * having the target disconnect will make this
835397883Sgibbs		 * transaction indestinguishable from outstanding
835497883Sgibbs		 * tagged transactions.
835597883Sgibbs		 */
835697883Sgibbs		hscb->control = 0;
835797883Sgibbs
835897883Sgibbs		/*
835997883Sgibbs		 * This request sense could be because the
836097883Sgibbs		 * the device lost power or in some other
836197883Sgibbs		 * way has lost our transfer negotiations.
836297883Sgibbs		 * Renegotiate if appropriate.  Unit attention
836397883Sgibbs		 * errors will be reported before any data
836497883Sgibbs		 * phases occur.
836597883Sgibbs		 */
8366123579Sgibbs		if (aic_get_residual(scb) == aic_get_transfer_length(scb)) {
836797883Sgibbs			ahd_update_neg_request(ahd, &devinfo,
836897883Sgibbs					       tstate, targ_info,
8369107441Sscottl					       AHD_NEG_IF_NON_ASYNC);
837097883Sgibbs		}
837197883Sgibbs		if (tstate->auto_negotiate & devinfo.target_mask) {
837297883Sgibbs			hscb->control |= MK_MESSAGE;
837397883Sgibbs			scb->flags &=
837497883Sgibbs			    ~(SCB_NEGOTIATE|SCB_ABORT|SCB_DEVICE_RESET);
837597883Sgibbs			scb->flags |= SCB_AUTO_NEGOTIATE;
837697883Sgibbs		}
837797883Sgibbs		hscb->cdb_len = sizeof(*sc);
837897883Sgibbs		ahd_setup_data_scb(ahd, scb);
837997883Sgibbs		scb->flags |= SCB_SENSE;
838097883Sgibbs		ahd_queue_scb(ahd, scb);
838197883Sgibbs		/*
838297883Sgibbs		 * Ensure we have enough time to actually
8383133911Sgibbs		 * retrieve the sense, but only schedule
8384133911Sgibbs		 * the timer if we are not in recovery or
8385133911Sgibbs		 * this is a recovery SCB that is allowed
8386133911Sgibbs		 * to have an active timer.
838797883Sgibbs		 */
8388133911Sgibbs		if (ahd->scb_data.recovery_scbs == 0
8389133911Sgibbs		 || (scb->flags & SCB_RECOVERY_SCB) != 0)
8390137870Sgibbs			aic_scb_timer_reset(scb, 5 * 1000);
839197883Sgibbs		break;
839297883Sgibbs	}
839397883Sgibbs	case SCSI_STATUS_OK:
839497883Sgibbs		printf("%s: Interrupted for staus of 0???\n",
839597883Sgibbs		       ahd_name(ahd));
839697883Sgibbs		/* FALLTHROUGH */
839797883Sgibbs	default:
839897883Sgibbs		ahd_done(ahd, scb);
839997883Sgibbs		break;
840097883Sgibbs	}
840197883Sgibbs}
840297883Sgibbs
840397883Sgibbs/*
840497883Sgibbs * Calculate the residual for a just completed SCB.
840597883Sgibbs */
840697883Sgibbsvoid
840797883Sgibbsahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
840897883Sgibbs{
840997883Sgibbs	struct hardware_scb *hscb;
841097883Sgibbs	struct initiator_status *spkt;
841197883Sgibbs	uint32_t sgptr;
841297883Sgibbs	uint32_t resid_sgptr;
841397883Sgibbs	uint32_t resid;
841497883Sgibbs
841597883Sgibbs	/*
841697883Sgibbs	 * 5 cases.
841797883Sgibbs	 * 1) No residual.
841897883Sgibbs	 *    SG_STATUS_VALID clear in sgptr.
841997883Sgibbs	 * 2) Transferless command
842097883Sgibbs	 * 3) Never performed any transfers.
842197883Sgibbs	 *    sgptr has SG_FULL_RESID set.
842297883Sgibbs	 * 4) No residual but target did not
842397883Sgibbs	 *    save data pointers after the
842497883Sgibbs	 *    last transfer, so sgptr was
842597883Sgibbs	 *    never updated.
842697883Sgibbs	 * 5) We have a partial residual.
842797883Sgibbs	 *    Use residual_sgptr to determine
842897883Sgibbs	 *    where we are.
842997883Sgibbs	 */
843097883Sgibbs
843197883Sgibbs	hscb = scb->hscb;
8432123579Sgibbs	sgptr = aic_le32toh(hscb->sgptr);
843397883Sgibbs	if ((sgptr & SG_STATUS_VALID) == 0)
843497883Sgibbs		/* Case 1 */
843597883Sgibbs		return;
843697883Sgibbs	sgptr &= ~SG_STATUS_VALID;
843797883Sgibbs
843897883Sgibbs	if ((sgptr & SG_LIST_NULL) != 0)
843997883Sgibbs		/* Case 2 */
844097883Sgibbs		return;
844197883Sgibbs
844297883Sgibbs	/*
844397883Sgibbs	 * Residual fields are the same in both
844497883Sgibbs	 * target and initiator status packets,
844597883Sgibbs	 * so we can always use the initiator fields
844697883Sgibbs	 * regardless of the role for this SCB.
844797883Sgibbs	 */
844897883Sgibbs	spkt = &hscb->shared_data.istatus;
8449123579Sgibbs	resid_sgptr = aic_le32toh(spkt->residual_sgptr);
845097883Sgibbs	if ((sgptr & SG_FULL_RESID) != 0) {
845197883Sgibbs		/* Case 3 */
8452123579Sgibbs		resid = aic_get_transfer_length(scb);
845397883Sgibbs	} else if ((resid_sgptr & SG_LIST_NULL) != 0) {
845497883Sgibbs		/* Case 4 */
845597883Sgibbs		return;
845697883Sgibbs	} else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) {
845797883Sgibbs		ahd_print_path(ahd, scb);
845897883Sgibbs		printf("data overrun detected Tag == 0x%x.\n",
845997883Sgibbs		       SCB_GET_TAG(scb));
846097883Sgibbs		ahd_freeze_devq(ahd, scb);
8461123579Sgibbs		aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
8462123579Sgibbs		aic_freeze_scb(scb);
846397883Sgibbs		return;
846497883Sgibbs	} else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {
846597883Sgibbs		panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);
846697883Sgibbs		/* NOTREACHED */
846797883Sgibbs	} else {
846897883Sgibbs		struct ahd_dma_seg *sg;
846997883Sgibbs
847097883Sgibbs		/*
847197883Sgibbs		 * Remainder of the SG where the transfer
847297883Sgibbs		 * stopped.
847397883Sgibbs		 */
8474123579Sgibbs		resid = aic_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK;
847597883Sgibbs		sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK);
847697883Sgibbs
847797883Sgibbs		/* The residual sg_ptr always points to the next sg */
847897883Sgibbs		sg--;
847997883Sgibbs
848097883Sgibbs		/*
848197883Sgibbs		 * Add up the contents of all residual
848297883Sgibbs		 * SG segments that are after the SG where
848397883Sgibbs		 * the transfer stopped.
848497883Sgibbs		 */
8485123579Sgibbs		while ((aic_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) {
848697883Sgibbs			sg++;
8487123579Sgibbs			resid += aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
848897883Sgibbs		}
848997883Sgibbs	}
849097883Sgibbs	if ((scb->flags & SCB_SENSE) == 0)
8491123579Sgibbs		aic_set_residual(scb, resid);
849297883Sgibbs	else
8493123579Sgibbs		aic_set_sense_residual(scb, resid);
849497883Sgibbs
849597883Sgibbs#ifdef AHD_DEBUG
849697883Sgibbs	if ((ahd_debug & AHD_SHOW_MISC) != 0) {
849797883Sgibbs		ahd_print_path(ahd, scb);
8498109588Sgibbs		printf("Handled %sResidual of %d bytes\n",
8499109588Sgibbs		       (scb->flags & SCB_SENSE) ? "Sense " : "", resid);
850097883Sgibbs	}
850197883Sgibbs#endif
850297883Sgibbs}
850397883Sgibbs
850497883Sgibbs/******************************* Target Mode **********************************/
850597883Sgibbs#ifdef AHD_TARGET_MODE
850697883Sgibbs/*
850797883Sgibbs * Add a target mode event to this lun's queue
850897883Sgibbs */
850997883Sgibbsstatic void
851097883Sgibbsahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate,
851197883Sgibbs		       u_int initiator_id, u_int event_type, u_int event_arg)
851297883Sgibbs{
851397883Sgibbs	struct ahd_tmode_event *event;
851497883Sgibbs	int pending;
851597883Sgibbs
851697883Sgibbs	xpt_freeze_devq(lstate->path, /*count*/1);
851797883Sgibbs	if (lstate->event_w_idx >= lstate->event_r_idx)
851897883Sgibbs		pending = lstate->event_w_idx - lstate->event_r_idx;
851997883Sgibbs	else
852097883Sgibbs		pending = AHD_TMODE_EVENT_BUFFER_SIZE + 1
852197883Sgibbs			- (lstate->event_r_idx - lstate->event_w_idx);
852297883Sgibbs
852397883Sgibbs	if (event_type == EVENT_TYPE_BUS_RESET
852497883Sgibbs	 || event_type == MSG_BUS_DEV_RESET) {
852597883Sgibbs		/*
852697883Sgibbs		 * Any earlier events are irrelevant, so reset our buffer.
852797883Sgibbs		 * This has the effect of allowing us to deal with reset
852897883Sgibbs		 * floods (an external device holding down the reset line)
852997883Sgibbs		 * without losing the event that is really interesting.
853097883Sgibbs		 */
853197883Sgibbs		lstate->event_r_idx = 0;
853297883Sgibbs		lstate->event_w_idx = 0;
853397883Sgibbs		xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE);
853497883Sgibbs	}
853597883Sgibbs
853697883Sgibbs	if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) {
853797883Sgibbs		xpt_print_path(lstate->path);
853897883Sgibbs		printf("immediate event %x:%x lost\n",
853997883Sgibbs		       lstate->event_buffer[lstate->event_r_idx].event_type,
854097883Sgibbs		       lstate->event_buffer[lstate->event_r_idx].event_arg);
854197883Sgibbs		lstate->event_r_idx++;
854297883Sgibbs		if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
854397883Sgibbs			lstate->event_r_idx = 0;
854497883Sgibbs		xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE);
854597883Sgibbs	}
854697883Sgibbs
854797883Sgibbs	event = &lstate->event_buffer[lstate->event_w_idx];
854897883Sgibbs	event->initiator_id = initiator_id;
854997883Sgibbs	event->event_type = event_type;
855097883Sgibbs	event->event_arg = event_arg;
855197883Sgibbs	lstate->event_w_idx++;
855297883Sgibbs	if (lstate->event_w_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
855397883Sgibbs		lstate->event_w_idx = 0;
855497883Sgibbs}
855597883Sgibbs
855697883Sgibbs/*
855797883Sgibbs * Send any target mode events queued up waiting
855897883Sgibbs * for immediate notify resources.
855997883Sgibbs */
856097883Sgibbsvoid
856197883Sgibbsahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate)
856297883Sgibbs{
856397883Sgibbs	struct ccb_hdr *ccbh;
8564237601Sken	struct ccb_immediate_notify *inot;
856597883Sgibbs
856697883Sgibbs	while (lstate->event_r_idx != lstate->event_w_idx
856797883Sgibbs	    && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) {
856897883Sgibbs		struct ahd_tmode_event *event;
856997883Sgibbs
857097883Sgibbs		event = &lstate->event_buffer[lstate->event_r_idx];
857197883Sgibbs		SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle);
8572237601Sken		inot = (struct ccb_immediate_notify *)ccbh;
857397883Sgibbs		switch (event->event_type) {
857497883Sgibbs		case EVENT_TYPE_BUS_RESET:
857597883Sgibbs			ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN;
857697883Sgibbs			break;
857797883Sgibbs		default:
857897883Sgibbs			ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
8579237601Sken			inot->arg = event->event_type;
8580237601Sken			inot->seq_id = event->event_arg;
858197883Sgibbs			break;
858297883Sgibbs		}
858397883Sgibbs		inot->initiator_id = event->initiator_id;
858497883Sgibbs		xpt_done((union ccb *)inot);
858597883Sgibbs		lstate->event_r_idx++;
858697883Sgibbs		if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
858797883Sgibbs			lstate->event_r_idx = 0;
858897883Sgibbs	}
858997883Sgibbs}
859097883Sgibbs#endif
859197883Sgibbs
859297883Sgibbs/******************** Sequencer Program Patching/Download *********************/
859397883Sgibbs
859497883Sgibbs#ifdef AHD_DUMP_SEQ
859597883Sgibbsvoid
859697883Sgibbsahd_dumpseq(struct ahd_softc* ahd)
859797883Sgibbs{
859897883Sgibbs	int i;
859997883Sgibbs	int max_prog;
860097883Sgibbs
860197883Sgibbs	max_prog = 2048;
860297883Sgibbs
860397883Sgibbs	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8604123579Sgibbs	ahd_outw(ahd, PRGMCNT, 0);
860597883Sgibbs	for (i = 0; i < max_prog; i++) {
860697883Sgibbs		uint8_t ins_bytes[4];
860797883Sgibbs
860897883Sgibbs		ahd_insb(ahd, SEQRAM, ins_bytes, 4);
860997883Sgibbs		printf("0x%08x\n", ins_bytes[0] << 24
861097883Sgibbs				 | ins_bytes[1] << 16
861197883Sgibbs				 | ins_bytes[2] << 8
861297883Sgibbs				 | ins_bytes[3]);
861397883Sgibbs	}
861497883Sgibbs}
861597883Sgibbs#endif
861697883Sgibbs
861797883Sgibbsstatic void
861897883Sgibbsahd_loadseq(struct ahd_softc *ahd)
861997883Sgibbs{
862097883Sgibbs	struct	cs cs_table[num_critical_sections];
862197883Sgibbs	u_int	begin_set[num_critical_sections];
862297883Sgibbs	u_int	end_set[num_critical_sections];
862397883Sgibbs	struct	patch *cur_patch;
862497883Sgibbs	u_int	cs_count;
862597883Sgibbs	u_int	cur_cs;
862697883Sgibbs	u_int	i;
862797883Sgibbs	int	downloaded;
862897883Sgibbs	u_int	skip_addr;
862997883Sgibbs	u_int	sg_prefetch_cnt;
863097883Sgibbs	u_int	sg_prefetch_cnt_limit;
863197883Sgibbs	u_int	sg_prefetch_align;
863297883Sgibbs	u_int	sg_size;
8633129134Sgibbs	u_int	cacheline_mask;
863497883Sgibbs	uint8_t	download_consts[DOWNLOAD_CONST_COUNT];
863597883Sgibbs
863697883Sgibbs	if (bootverbose)
863797883Sgibbs		printf("%s: Downloading Sequencer Program...",
863897883Sgibbs		       ahd_name(ahd));
863997883Sgibbs
8640129134Sgibbs#if DOWNLOAD_CONST_COUNT != 8
864197883Sgibbs#error "Download Const Mismatch"
864297883Sgibbs#endif
864397883Sgibbs	/*
864497883Sgibbs	 * Start out with 0 critical sections
864597883Sgibbs	 * that apply to this firmware load.
864697883Sgibbs	 */
864797883Sgibbs	cs_count = 0;
864897883Sgibbs	cur_cs = 0;
864997883Sgibbs	memset(begin_set, 0, sizeof(begin_set));
865097883Sgibbs	memset(end_set, 0, sizeof(end_set));
865197883Sgibbs
865297883Sgibbs	/*
865397883Sgibbs	 * Setup downloadable constant table.
865497883Sgibbs	 *
865597883Sgibbs	 * The computation for the S/G prefetch variables is
865697883Sgibbs	 * a bit complicated.  We would like to always fetch
865797883Sgibbs	 * in terms of cachelined sized increments.  However,
865897883Sgibbs	 * if the cacheline is not an even multiple of the
865997883Sgibbs	 * SG element size or is larger than our SG RAM, using
866097883Sgibbs	 * just the cache size might leave us with only a portion
866197883Sgibbs	 * of an SG element at the tail of a prefetch.  If the
866297883Sgibbs	 * cacheline is larger than our S/G prefetch buffer less
866397883Sgibbs	 * the size of an SG element, we may round down to a cacheline
866497883Sgibbs	 * that doesn't contain any or all of the S/G of interest
866597883Sgibbs	 * within the bounds of our S/G ram.  Provide variables to
866697883Sgibbs	 * the sequencer that will allow it to handle these edge
866797883Sgibbs	 * cases.
866897883Sgibbs	 */
866997883Sgibbs	/* Start by aligning to the nearest cacheline. */
867097883Sgibbs	sg_prefetch_align = ahd->pci_cachesize;
867197883Sgibbs	if (sg_prefetch_align == 0)
8672111653Sgibbs		sg_prefetch_align = 8;
867397883Sgibbs	/* Round down to the nearest power of 2. */
867497883Sgibbs	while (powerof2(sg_prefetch_align) == 0)
867597883Sgibbs		sg_prefetch_align--;
8676129134Sgibbs
8677129134Sgibbs	cacheline_mask = sg_prefetch_align - 1;
8678129134Sgibbs
867997883Sgibbs	/*
868097883Sgibbs	 * If the cacheline boundary is greater than half our prefetch RAM
868197883Sgibbs	 * we risk not being able to fetch even a single complete S/G
868297883Sgibbs	 * segment if we align to that boundary.
868397883Sgibbs	 */
868497883Sgibbs	if (sg_prefetch_align > CCSGADDR_MAX/2)
868597883Sgibbs		sg_prefetch_align = CCSGADDR_MAX/2;
868697883Sgibbs	/* Start by fetching a single cacheline. */
868797883Sgibbs	sg_prefetch_cnt = sg_prefetch_align;
868897883Sgibbs	/*
868997883Sgibbs	 * Increment the prefetch count by cachelines until
869097883Sgibbs	 * at least one S/G element will fit.
869197883Sgibbs	 */
869297883Sgibbs	sg_size = sizeof(struct ahd_dma_seg);
869397883Sgibbs	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
869497883Sgibbs		sg_size = sizeof(struct ahd_dma64_seg);
869597883Sgibbs	while (sg_prefetch_cnt < sg_size)
869697883Sgibbs		sg_prefetch_cnt += sg_prefetch_align;
869797883Sgibbs	/*
869897883Sgibbs	 * If the cacheline is not an even multiple of
869997883Sgibbs	 * the S/G size, we may only get a partial S/G when
870097883Sgibbs	 * we align. Add a cacheline if this is the case.
870197883Sgibbs	 */
870297883Sgibbs	if ((sg_prefetch_align % sg_size) != 0
870397883Sgibbs	 && (sg_prefetch_cnt < CCSGADDR_MAX))
870497883Sgibbs		sg_prefetch_cnt += sg_prefetch_align;
870597883Sgibbs	/*
870697883Sgibbs	 * Lastly, compute a value that the sequencer can use
870797883Sgibbs	 * to determine if the remainder of the CCSGRAM buffer
870897883Sgibbs	 * has a full S/G element in it.
870997883Sgibbs	 */
871097883Sgibbs	sg_prefetch_cnt_limit = -(sg_prefetch_cnt - sg_size + 1);
871197883Sgibbs	download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt;
871297883Sgibbs	download_consts[SG_PREFETCH_CNT_LIMIT] = sg_prefetch_cnt_limit;
871397883Sgibbs	download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_align - 1);
871497883Sgibbs	download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_align - 1);
871597883Sgibbs	download_consts[SG_SIZEOF] = sg_size;
871697883Sgibbs	download_consts[PKT_OVERRUN_BUFOFFSET] =
8717102679Sgibbs		(ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
8718102679Sgibbs	download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
8719129134Sgibbs	download_consts[CACHELINE_MASK] = cacheline_mask;
872097883Sgibbs	cur_patch = patches;
872197883Sgibbs	downloaded = 0;
872297883Sgibbs	skip_addr = 0;
872397883Sgibbs	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
8724123579Sgibbs	ahd_outw(ahd, PRGMCNT, 0);
872597883Sgibbs
872697883Sgibbs	for (i = 0; i < sizeof(seqprog)/4; i++) {
872797883Sgibbs		if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
872897883Sgibbs			/*
872997883Sgibbs			 * Don't download this instruction as it
873097883Sgibbs			 * is in a patch that was removed.
873197883Sgibbs			 */
873297883Sgibbs			continue;
873397883Sgibbs		}
873497883Sgibbs		/*
873597883Sgibbs		 * Move through the CS table until we find a CS
873697883Sgibbs		 * that might apply to this instruction.
873797883Sgibbs		 */
873897883Sgibbs		for (; cur_cs < num_critical_sections; cur_cs++) {
873997883Sgibbs			if (critical_sections[cur_cs].end <= i) {
874097883Sgibbs				if (begin_set[cs_count] == TRUE
874197883Sgibbs				 && end_set[cs_count] == FALSE) {
874297883Sgibbs					cs_table[cs_count].end = downloaded;
874397883Sgibbs				 	end_set[cs_count] = TRUE;
874497883Sgibbs					cs_count++;
874597883Sgibbs				}
874697883Sgibbs				continue;
874797883Sgibbs			}
874897883Sgibbs			if (critical_sections[cur_cs].begin <= i
874997883Sgibbs			 && begin_set[cs_count] == FALSE) {
875097883Sgibbs				cs_table[cs_count].begin = downloaded;
875197883Sgibbs				begin_set[cs_count] = TRUE;
875297883Sgibbs			}
875397883Sgibbs			break;
875497883Sgibbs		}
875597883Sgibbs		ahd_download_instr(ahd, i, download_consts);
875697883Sgibbs		downloaded++;
875797883Sgibbs	}
875897883Sgibbs
875997883Sgibbs	ahd->num_critical_sections = cs_count;
876097883Sgibbs	if (cs_count != 0) {
876197883Sgibbs
876297883Sgibbs		cs_count *= sizeof(struct cs);
876397883Sgibbs		ahd->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT);
876497883Sgibbs		if (ahd->critical_sections == NULL)
876597883Sgibbs			panic("ahd_loadseq: Could not malloc");
876697883Sgibbs		memcpy(ahd->critical_sections, cs_table, cs_count);
876797883Sgibbs	}
876897883Sgibbs	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE);
876997883Sgibbs
8770109588Sgibbs	if (bootverbose) {
877197883Sgibbs		printf(" %d instructions downloaded\n", downloaded);
8772109588Sgibbs		printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n",
8773109588Sgibbs		       ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags);
8774109588Sgibbs	}
877597883Sgibbs}
877697883Sgibbs
877797883Sgibbsstatic int
877897883Sgibbsahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
877997883Sgibbs		u_int start_instr, u_int *skip_addr)
878097883Sgibbs{
878197883Sgibbs	struct	patch *cur_patch;
878297883Sgibbs	struct	patch *last_patch;
878397883Sgibbs	u_int	num_patches;
878497883Sgibbs
878597883Sgibbs	num_patches = sizeof(patches)/sizeof(struct patch);
878697883Sgibbs	last_patch = &patches[num_patches];
878797883Sgibbs	cur_patch = *start_patch;
878897883Sgibbs
878997883Sgibbs	while (cur_patch < last_patch && start_instr == cur_patch->begin) {
879097883Sgibbs
879197883Sgibbs		if (cur_patch->patch_func(ahd) == 0) {
879297883Sgibbs
879397883Sgibbs			/* Start rejecting code */
879497883Sgibbs			*skip_addr = start_instr + cur_patch->skip_instr;
879597883Sgibbs			cur_patch += cur_patch->skip_patch;
879697883Sgibbs		} else {
879797883Sgibbs			/* Accepted this patch.  Advance to the next
879897883Sgibbs			 * one and wait for our intruction pointer to
879997883Sgibbs			 * hit this point.
880097883Sgibbs			 */
880197883Sgibbs			cur_patch++;
880297883Sgibbs		}
880397883Sgibbs	}
880497883Sgibbs
880597883Sgibbs	*start_patch = cur_patch;
880697883Sgibbs	if (start_instr < *skip_addr)
880797883Sgibbs		/* Still skipping */
880897883Sgibbs		return (0);
880997883Sgibbs
881097883Sgibbs	return (1);
881197883Sgibbs}
881297883Sgibbs
881397883Sgibbsstatic u_int
881497883Sgibbsahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)
881597883Sgibbs{
881697883Sgibbs	struct patch *cur_patch;
881797883Sgibbs	int address_offset;
881897883Sgibbs	u_int skip_addr;
881997883Sgibbs	u_int i;
882097883Sgibbs
882197883Sgibbs	address_offset = 0;
882297883Sgibbs	cur_patch = patches;
882397883Sgibbs	skip_addr = 0;
882497883Sgibbs
882597883Sgibbs	for (i = 0; i < address;) {
882697883Sgibbs
882797883Sgibbs		ahd_check_patch(ahd, &cur_patch, i, &skip_addr);
882897883Sgibbs
882997883Sgibbs		if (skip_addr > i) {
883097883Sgibbs			int end_addr;
883197883Sgibbs
883297883Sgibbs			end_addr = MIN(address, skip_addr);
883397883Sgibbs			address_offset += end_addr - i;
883497883Sgibbs			i = skip_addr;
883597883Sgibbs		} else {
883697883Sgibbs			i++;
883797883Sgibbs		}
883897883Sgibbs	}
883997883Sgibbs	return (address - address_offset);
884097883Sgibbs}
884197883Sgibbs
884297883Sgibbsstatic void
884397883Sgibbsahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts)
884497883Sgibbs{
884597883Sgibbs	union	ins_formats instr;
884697883Sgibbs	struct	ins_format1 *fmt1_ins;
884797883Sgibbs	struct	ins_format3 *fmt3_ins;
884897883Sgibbs	u_int	opcode;
884997883Sgibbs
885097883Sgibbs	/*
885197883Sgibbs	 * The firmware is always compiled into a little endian format.
885297883Sgibbs	 */
8853123579Sgibbs	instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
885497883Sgibbs
885597883Sgibbs	fmt1_ins = &instr.format1;
885697883Sgibbs	fmt3_ins = NULL;
885797883Sgibbs
885897883Sgibbs	/* Pull the opcode */
885997883Sgibbs	opcode = instr.format1.opcode;
886097883Sgibbs	switch (opcode) {
886197883Sgibbs	case AIC_OP_JMP:
886297883Sgibbs	case AIC_OP_JC:
886397883Sgibbs	case AIC_OP_JNC:
886497883Sgibbs	case AIC_OP_CALL:
886597883Sgibbs	case AIC_OP_JNE:
886697883Sgibbs	case AIC_OP_JNZ:
886797883Sgibbs	case AIC_OP_JE:
886897883Sgibbs	case AIC_OP_JZ:
886997883Sgibbs	{
887097883Sgibbs		fmt3_ins = &instr.format3;
887197883Sgibbs		fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address);
887297883Sgibbs		/* FALLTHROUGH */
887397883Sgibbs	}
887497883Sgibbs	case AIC_OP_OR:
887597883Sgibbs	case AIC_OP_AND:
887697883Sgibbs	case AIC_OP_XOR:
887797883Sgibbs	case AIC_OP_ADD:
887897883Sgibbs	case AIC_OP_ADC:
887997883Sgibbs	case AIC_OP_BMOV:
888097883Sgibbs		if (fmt1_ins->parity != 0) {
888197883Sgibbs			fmt1_ins->immediate = dconsts[fmt1_ins->immediate];
888297883Sgibbs		}
888397883Sgibbs		fmt1_ins->parity = 0;
888497883Sgibbs		/* FALLTHROUGH */
888597883Sgibbs	case AIC_OP_ROL:
888697883Sgibbs	{
888797883Sgibbs		int i, count;
888897883Sgibbs
888997883Sgibbs		/* Calculate odd parity for the instruction */
889097883Sgibbs		for (i = 0, count = 0; i < 31; i++) {
889197883Sgibbs			uint32_t mask;
889297883Sgibbs
889397883Sgibbs			mask = 0x01 << i;
889497883Sgibbs			if ((instr.integer & mask) != 0)
889597883Sgibbs				count++;
889697883Sgibbs		}
889797883Sgibbs		if ((count & 0x01) == 0)
889897883Sgibbs			instr.format1.parity = 1;
889997883Sgibbs
890097883Sgibbs		/* The sequencer is a little endian cpu */
8901123579Sgibbs		instr.integer = aic_htole32(instr.integer);
890297883Sgibbs		ahd_outsb(ahd, SEQRAM, instr.bytes, 4);
890397883Sgibbs		break;
890497883Sgibbs	}
890597883Sgibbs	default:
890697883Sgibbs		panic("Unknown opcode encountered in seq program");
890797883Sgibbs		break;
890897883Sgibbs	}
890997883Sgibbs}
891097883Sgibbs
8911107441Sscottlstatic int
8912107441Sscottlahd_probe_stack_size(struct ahd_softc *ahd)
8913107441Sscottl{
8914107441Sscottl	int last_probe;
8915107441Sscottl
8916107441Sscottl	last_probe = 0;
8917107441Sscottl	while (1) {
8918107441Sscottl		int i;
8919107441Sscottl
8920107441Sscottl		/*
8921107441Sscottl		 * We avoid using 0 as a pattern to avoid
8922107441Sscottl		 * confusion if the stack implementation
8923107441Sscottl		 * "back-fills" with zeros when "poping'
8924107441Sscottl		 * entries.
8925107441Sscottl		 */
8926107441Sscottl		for (i = 1; i <= last_probe+1; i++) {
8927107441Sscottl		       ahd_outb(ahd, STACK, i & 0xFF);
8928107441Sscottl		       ahd_outb(ahd, STACK, (i >> 8) & 0xFF);
8929107441Sscottl		}
8930107441Sscottl
8931107441Sscottl		/* Verify */
8932107441Sscottl		for (i = last_probe+1; i > 0; i--) {
8933107441Sscottl			u_int stack_entry;
8934107441Sscottl
8935107441Sscottl			stack_entry = ahd_inb(ahd, STACK)
8936107441Sscottl				    |(ahd_inb(ahd, STACK) << 8);
8937107441Sscottl			if (stack_entry != i)
8938107441Sscottl				goto sized;
8939107441Sscottl		}
8940107441Sscottl		last_probe++;
8941107441Sscottl	}
8942107441Sscottlsized:
8943107441Sscottl	return (last_probe);
8944107441Sscottl}
8945107441Sscottl
894697883Sgibbsvoid
8947115336Sgibbsahd_dump_all_cards_state(void)
894897883Sgibbs{
894997883Sgibbs	struct ahd_softc *list_ahd;
895097883Sgibbs
895197883Sgibbs	TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
895297883Sgibbs		ahd_dump_card_state(list_ahd);
895397883Sgibbs	}
895497883Sgibbs}
895597883Sgibbs
8956102679Sgibbsint
8957102679Sgibbsahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
8958102679Sgibbs		   const char *name, u_int address, u_int value,
8959102679Sgibbs		   u_int *cur_column, u_int wrap_point)
8960102679Sgibbs{
8961102679Sgibbs	int	printed;
8962102679Sgibbs	u_int	printed_mask;
8963141999Sgibbs	u_int	dummy_column;
8964102679Sgibbs
8965141999Sgibbs	if (cur_column == NULL) {
8966141999Sgibbs		dummy_column = 0;
8967141999Sgibbs		cur_column = &dummy_column;
8968141999Sgibbs	}
8969141999Sgibbs
8970107441Sscottl	if (cur_column != NULL && *cur_column >= wrap_point) {
8971102679Sgibbs		printf("\n");
8972102679Sgibbs		*cur_column = 0;
8973102679Sgibbs	}
8974102679Sgibbs	printed = printf("%s[0x%x]", name, value);
8975102679Sgibbs	if (table == NULL) {
8976102679Sgibbs		printed += printf(" ");
8977102679Sgibbs		*cur_column += printed;
8978102679Sgibbs		return (printed);
8979102679Sgibbs	}
8980102679Sgibbs	printed_mask = 0;
8981102679Sgibbs	while (printed_mask != 0xFF) {
8982102679Sgibbs		int entry;
8983102679Sgibbs
8984102679Sgibbs		for (entry = 0; entry < num_entries; entry++) {
8985102679Sgibbs			if (((value & table[entry].mask)
8986102679Sgibbs			  != table[entry].value)
8987102679Sgibbs			 || ((printed_mask & table[entry].mask)
8988102679Sgibbs			  == table[entry].mask))
8989102679Sgibbs				continue;
8990102679Sgibbs
8991102679Sgibbs			printed += printf("%s%s",
8992102679Sgibbs					  printed_mask == 0 ? ":(" : "|",
8993102679Sgibbs					  table[entry].name);
8994102679Sgibbs			printed_mask |= table[entry].mask;
8995102679Sgibbs
8996102679Sgibbs			break;
8997102679Sgibbs		}
8998102679Sgibbs		if (entry >= num_entries)
8999102679Sgibbs			break;
9000102679Sgibbs	}
9001102679Sgibbs	if (printed_mask != 0)
9002102679Sgibbs		printed += printf(") ");
9003102679Sgibbs	else
9004102679Sgibbs		printed += printf(" ");
9005141999Sgibbs	*cur_column += printed;
9006102679Sgibbs	return (printed);
9007102679Sgibbs}
9008102679Sgibbs
900997883Sgibbsvoid
901097883Sgibbsahd_dump_card_state(struct ahd_softc *ahd)
901197883Sgibbs{
901297883Sgibbs	struct scb	*scb;
901397883Sgibbs	ahd_mode_state	 saved_modes;
901497883Sgibbs	u_int		 dffstat;
901597883Sgibbs	int		 paused;
901697883Sgibbs	u_int		 scb_index;
9017104023Sgibbs	u_int		 saved_scb_index;
9018102679Sgibbs	u_int		 cur_col;
9019107441Sscottl	int		 i;
902097883Sgibbs
902197883Sgibbs	if (ahd_is_paused(ahd)) {
902297883Sgibbs		paused = 1;
902397883Sgibbs	} else {
902497883Sgibbs		paused = 0;
902597883Sgibbs		ahd_pause(ahd);
902697883Sgibbs	}
902797883Sgibbs	saved_modes = ahd_save_modes(ahd);
902897883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
9029102679Sgibbs	printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
9030102679Sgibbs	       "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
903197883Sgibbs	       ahd_name(ahd),
9032123579Sgibbs	       ahd_inw(ahd, CURADDR),
903397883Sgibbs	       ahd_build_mode_state(ahd, ahd->saved_src_mode,
903497883Sgibbs				    ahd->saved_dst_mode));
903597883Sgibbs	if (paused)
903697883Sgibbs		printf("Card was paused\n");
9037116938Sgibbs
9038116938Sgibbs	if (ahd_check_cmdcmpltqueues(ahd))
9039116938Sgibbs		printf("Completions are pending\n");
9040116938Sgibbs
9041102679Sgibbs	/*
9042102679Sgibbs	 * Mode independent registers.
9043102679Sgibbs	 */
9044102679Sgibbs	cur_col = 0;
9045133122Sgibbs	ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50);
9046133122Sgibbs	ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50);
9047133122Sgibbs	ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50);
9048109588Sgibbs	ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50);
9049109588Sgibbs	ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50);
9050109588Sgibbs	ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50);
9051107441Sscottl	ahd_saved_mode_print(ahd_inb(ahd, SAVED_MODE), &cur_col, 50);
9052107441Sscottl	ahd_dffstat_print(ahd_inb(ahd, DFFSTAT), &cur_col, 50);
9053102679Sgibbs	ahd_scsisigi_print(ahd_inb(ahd, SCSISIGI), &cur_col, 50);
9054102679Sgibbs	ahd_scsiphase_print(ahd_inb(ahd, SCSIPHASE), &cur_col, 50);
9055104023Sgibbs	ahd_scsibus_print(ahd_inb(ahd, SCSIBUS), &cur_col, 50);
9056102679Sgibbs	ahd_lastphase_print(ahd_inb(ahd, LASTPHASE), &cur_col, 50);
9057107441Sscottl	ahd_scsiseq0_print(ahd_inb(ahd, SCSISEQ0), &cur_col, 50);
9058107441Sscottl	ahd_scsiseq1_print(ahd_inb(ahd, SCSISEQ1), &cur_col, 50);
9059107441Sscottl	ahd_seqctl0_print(ahd_inb(ahd, SEQCTL0), &cur_col, 50);
9060107441Sscottl	ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);
9061102679Sgibbs	ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);
9062102679Sgibbs	ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);
9063133122Sgibbs	ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50);
9064133122Sgibbs	ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),
9065133122Sgibbs				       &cur_col, 50);
9066133122Sgibbs	ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50);
9067133122Sgibbs	ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),
9068133122Sgibbs				    &cur_col, 50);
9069102679Sgibbs	ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50);
9070102679Sgibbs	ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50);
9071102679Sgibbs	ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);
9072102679Sgibbs	ahd_sstat3_print(ahd_inb(ahd, SSTAT3), &cur_col, 50);
9073102679Sgibbs	ahd_perrdiag_print(ahd_inb(ahd, PERRDIAG), &cur_col, 50);
9074104023Sgibbs	ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50);
9075104023Sgibbs	ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50);
9076104023Sgibbs	ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50);
9077104023Sgibbs	ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50);
9078104023Sgibbs	ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50);
9079104023Sgibbs	ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50);
9080104023Sgibbs	ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50);
9081104023Sgibbs	printf("\n");
9082109588Sgibbs	printf("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x "
9083109588Sgibbs	       "CURRSCB 0x%x NEXTSCB 0x%x\n",
9084109588Sgibbs	       ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING),
9085109588Sgibbs	       ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB),
9086109588Sgibbs	       ahd_inw(ahd, NEXTSCB));
9087102679Sgibbs	cur_col = 0;
908897883Sgibbs	/* QINFIFO */
908997883Sgibbs	ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
909097883Sgibbs			   CAM_LUN_WILDCARD, SCB_LIST_NULL,
909197883Sgibbs			   ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT);
9092104023Sgibbs	saved_scb_index = ahd_get_scbptr(ahd);
9093102679Sgibbs	printf("Pending list:");
909497883Sgibbs	i = 0;
909597883Sgibbs	LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
909697883Sgibbs		if (i++ > AHD_SCB_MAX)
909797883Sgibbs			break;
9098114623Sgibbs		cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
9099116940Sgibbs				 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT));
910097883Sgibbs		ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
9101116940Sgibbs		ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),
9102116940Sgibbs				      &cur_col, 60);
9103116940Sgibbs		ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),
9104116940Sgibbs				     &cur_col, 60);
910597883Sgibbs	}
9106109588Sgibbs	printf("\nTotal %d\n", i);
910797883Sgibbs
9108150451Sgibbs	printf("Kernel Free SCB lists: ");
910997883Sgibbs	i = 0;
9110102679Sgibbs	TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
9111102679Sgibbs		struct scb *list_scb;
9112102679Sgibbs
9113150451Sgibbs		printf("\n  COLIDX[%d]: ", AHD_GET_SCB_COL_IDX(ahd, scb));
9114102679Sgibbs		list_scb = scb;
9115102679Sgibbs		do {
9116102679Sgibbs			printf("%d ", SCB_GET_TAG(list_scb));
9117102679Sgibbs			list_scb = LIST_NEXT(list_scb, collision_links);
9118102679Sgibbs		} while (list_scb && i++ < AHD_SCB_MAX);
9119102679Sgibbs	}
9120102679Sgibbs
9121150451Sgibbs	printf("\n  Any Device: ");
9122102679Sgibbs	LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
912397883Sgibbs		if (i++ > AHD_SCB_MAX)
912497883Sgibbs			break;
912597883Sgibbs		printf("%d ", SCB_GET_TAG(scb));
912697883Sgibbs	}
912797883Sgibbs	printf("\n");
912897883Sgibbs
912997883Sgibbs	printf("Sequencer Complete DMA-inprog list: ");
913097883Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD);
913197883Sgibbs	i = 0;
913297883Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
913397883Sgibbs		ahd_set_scbptr(ahd, scb_index);
913497883Sgibbs		printf("%d ", scb_index);
9135116940Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
913697883Sgibbs	}
913797883Sgibbs	printf("\n");
913897883Sgibbs
913997883Sgibbs	printf("Sequencer Complete list: ");
914097883Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD);
914197883Sgibbs	i = 0;
914297883Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
914397883Sgibbs		ahd_set_scbptr(ahd, scb_index);
914497883Sgibbs		printf("%d ", scb_index);
9145116940Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
914697883Sgibbs	}
914797883Sgibbs	printf("\n");
914897883Sgibbs
914997883Sgibbs
915097883Sgibbs	printf("Sequencer DMA-Up and Complete list: ");
915197883Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
915297883Sgibbs	i = 0;
915397883Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
915497883Sgibbs		ahd_set_scbptr(ahd, scb_index);
915597883Sgibbs		printf("%d ", scb_index);
9156116940Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
915797883Sgibbs	}
915897883Sgibbs	printf("\n");
9159125448Sgibbs	printf("Sequencer On QFreeze and Complete list: ");
9160125448Sgibbs	scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
9161125448Sgibbs	i = 0;
9162125448Sgibbs	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
9163125448Sgibbs		ahd_set_scbptr(ahd, scb_index);
9164125448Sgibbs		printf("%d ", scb_index);
9165125448Sgibbs		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
9166125448Sgibbs	}
9167125448Sgibbs	printf("\n");
9168104023Sgibbs	ahd_set_scbptr(ahd, saved_scb_index);
916997883Sgibbs	dffstat = ahd_inb(ahd, DFFSTAT);
917097883Sgibbs	for (i = 0; i < 2; i++) {
9171102679Sgibbs#ifdef AHD_DEBUG
917297883Sgibbs		struct scb *fifo_scb;
9173102679Sgibbs#endif
917497883Sgibbs		u_int	    fifo_scbptr;
917597883Sgibbs
917697883Sgibbs		ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
9177104023Sgibbs		fifo_scbptr = ahd_get_scbptr(ahd);
9178133122Sgibbs		printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
917997883Sgibbs		       ahd_name(ahd), i,
918097883Sgibbs		       (dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
9181114623Sgibbs		       ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
9182102679Sgibbs		cur_col = 0;
9183102679Sgibbs		ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50);
9184102679Sgibbs		ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50);
9185102679Sgibbs		ahd_dfcntrl_print(ahd_inb(ahd, DFCNTRL), &cur_col, 50);
9186102679Sgibbs		ahd_dfstatus_print(ahd_inb(ahd, DFSTATUS), &cur_col, 50);
9187102679Sgibbs		ahd_sg_cache_shadow_print(ahd_inb(ahd, SG_CACHE_SHADOW),
9188102679Sgibbs					  &cur_col, 50);
9189102679Sgibbs		ahd_sg_state_print(ahd_inb(ahd, SG_STATE), &cur_col, 50);
9190102679Sgibbs		ahd_dffsxfrctl_print(ahd_inb(ahd, DFFSXFRCTL), &cur_col, 50);
9191102679Sgibbs		ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50);
9192102679Sgibbs		ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50);
9193102679Sgibbs		if (cur_col > 50) {
9194102679Sgibbs			printf("\n");
9195102679Sgibbs			cur_col = 0;
9196102679Sgibbs		}
9197109588Sgibbs		cur_col += printf("SHADDR = 0x%x%x, SHCNT = 0x%x ",
9198102679Sgibbs				  ahd_inl(ahd, SHADDR+4),
9199102679Sgibbs				  ahd_inl(ahd, SHADDR),
9200102679Sgibbs				  (ahd_inb(ahd, SHCNT)
9201102679Sgibbs				| (ahd_inb(ahd, SHCNT + 1) << 8)
9202102679Sgibbs				| (ahd_inb(ahd, SHCNT + 2) << 16)));
9203102679Sgibbs		if (cur_col > 50) {
9204102679Sgibbs			printf("\n");
9205102679Sgibbs			cur_col = 0;
9206102679Sgibbs		}
9207107441Sscottl		cur_col += printf("HADDR = 0x%x%x, HCNT = 0x%x ",
9208102679Sgibbs				  ahd_inl(ahd, HADDR+4),
9209102679Sgibbs				  ahd_inl(ahd, HADDR),
9210102679Sgibbs				  (ahd_inb(ahd, HCNT)
9211102679Sgibbs				| (ahd_inb(ahd, HCNT + 1) << 8)
9212102679Sgibbs				| (ahd_inb(ahd, HCNT + 2) << 16)));
9213102679Sgibbs		ahd_ccsgctl_print(ahd_inb(ahd, CCSGCTL), &cur_col, 50);
9214102679Sgibbs#ifdef AHD_DEBUG
9215102679Sgibbs		if ((ahd_debug & AHD_SHOW_SG) != 0) {
9216102679Sgibbs			fifo_scb = ahd_lookup_scb(ahd, fifo_scbptr);
9217102679Sgibbs			if (fifo_scb != NULL)
9218102679Sgibbs				ahd_dump_sglist(fifo_scb);
9219102679Sgibbs		}
9220102679Sgibbs#endif
922197883Sgibbs	}
9222104023Sgibbs	printf("\nLQIN: ");
922397883Sgibbs	for (i = 0; i < 20; i++)
922497883Sgibbs		printf("0x%x ", ahd_inb(ahd, LQIN + i));
922597883Sgibbs	printf("\n");
922697883Sgibbs	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
922797883Sgibbs	printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n",
922897883Sgibbs	       ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE),
922997883Sgibbs	       ahd_inb(ahd, OPTIONMODE));
923097883Sgibbs	printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n",
923197883Sgibbs	       ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT),
923297883Sgibbs	       ahd_inb(ahd, MAXCMDCNT));
9233133122Sgibbs	printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n",
9234133122Sgibbs	       ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID),
9235133122Sgibbs	       ahd_inb(ahd, SAVED_LUN));
9236107441Sscottl	ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50);
9237107441Sscottl	printf("\n");
9238109588Sgibbs	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
9239109588Sgibbs	cur_col = 0;
9240109588Sgibbs	ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50);
9241109588Sgibbs	printf("\n");
924297883Sgibbs	ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
924397883Sgibbs	printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n",
924497883Sgibbs	       ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX),
924597883Sgibbs	       ahd_inw(ahd, DINDEX));
924697883Sgibbs	printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n",
9247116940Sgibbs	       ahd_name(ahd), ahd_get_scbptr(ahd),
9248116940Sgibbs	       ahd_inw_scbram(ahd, SCB_NEXT),
9249116940Sgibbs	       ahd_inw_scbram(ahd, SCB_NEXT2));
925097883Sgibbs	printf("CDB %x %x %x %x %x %x\n",
9251116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE),
9252116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+1),
9253116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+2),
9254116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+3),
9255116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+4),
9256116940Sgibbs	       ahd_inb_scbram(ahd, SCB_CDB_STORE+5));
925797883Sgibbs	printf("STACK:");
9258107441Sscottl	for (i = 0; i < ahd->stack_size; i++) {
9259107441Sscottl		ahd->saved_stack[i] =
9260107441Sscottl		    ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8);
9261107441Sscottl		printf(" 0x%x", ahd->saved_stack[i]);
9262107441Sscottl	}
9263107441Sscottl	for (i = ahd->stack_size-1; i >= 0; i--) {
9264107441Sscottl		ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF);
9265107441Sscottl		ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
9266107441Sscottl	}
9267102679Sgibbs	printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
926897883Sgibbs	ahd_platform_dump_card_state(ahd);
926997883Sgibbs	ahd_restore_modes(ahd, saved_modes);
927097883Sgibbs	if (paused == 0)
927197883Sgibbs		ahd_unpause(ahd);
927297883Sgibbs}
927397883Sgibbs
927497883Sgibbsvoid
927597883Sgibbsahd_dump_scbs(struct ahd_softc *ahd)
927697883Sgibbs{
927797883Sgibbs	ahd_mode_state saved_modes;
9278104023Sgibbs	u_int	       saved_scb_index;
927997883Sgibbs	int	       i;
928097883Sgibbs
928197883Sgibbs	saved_modes = ahd_save_modes(ahd);
928297883Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
9283104023Sgibbs	saved_scb_index = ahd_get_scbptr(ahd);
928497883Sgibbs	for (i = 0; i < AHD_SCB_MAX; i++) {
928597883Sgibbs		ahd_set_scbptr(ahd, i);
928697883Sgibbs		printf("%3d", i);
928797883Sgibbs		printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",
9288116940Sgibbs		       ahd_inb_scbram(ahd, SCB_CONTROL),
9289116940Sgibbs		       ahd_inb_scbram(ahd, SCB_SCSIID),
9290116940Sgibbs		       ahd_inw_scbram(ahd, SCB_NEXT),
9291116940Sgibbs		       ahd_inw_scbram(ahd, SCB_NEXT2),
9292116940Sgibbs		       ahd_inl_scbram(ahd, SCB_SGPTR),
9293116940Sgibbs		       ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));
929497883Sgibbs	}
929597883Sgibbs	printf("\n");
9296104023Sgibbs	ahd_set_scbptr(ahd, saved_scb_index);
929797883Sgibbs	ahd_restore_modes(ahd, saved_modes);
929897883Sgibbs}
929997883Sgibbs
9300123579Sgibbs
9301123579Sgibbs/*************************** Timeout Handling *********************************/
9302123579Sgibbsvoid
9303123579Sgibbsahd_timeout(struct scb *scb)
9304123579Sgibbs{
9305123579Sgibbs	struct ahd_softc *ahd;
9306123579Sgibbs
9307123579Sgibbs	ahd = scb->ahd_softc;
9308123579Sgibbs	if ((scb->flags & SCB_ACTIVE) != 0) {
9309123579Sgibbs		if ((scb->flags & SCB_TIMEDOUT) == 0) {
9310123579Sgibbs			LIST_INSERT_HEAD(&ahd->timedout_scbs, scb,
9311123579Sgibbs					 timedout_links);
9312123579Sgibbs			scb->flags |= SCB_TIMEDOUT;
9313123579Sgibbs		}
9314123579Sgibbs		ahd_wakeup_recovery_thread(ahd);
9315123579Sgibbs	}
9316123579Sgibbs}
9317123579Sgibbs
9318123579Sgibbs/*
9319123579Sgibbs * ahd_recover_commands determines if any of the commands that have currently
9320123579Sgibbs * timedout are the root cause for this timeout.  Innocent commands are given
9321123579Sgibbs * a new timeout while we wait for the command executing on the bus to timeout.
9322123579Sgibbs * This routine is invoked from a thread context so we are allowed to sleep.
9323123579Sgibbs * Our lock is not held on entry.
9324123579Sgibbs */
9325123579Sgibbsvoid
9326123579Sgibbsahd_recover_commands(struct ahd_softc *ahd)
9327123579Sgibbs{
9328123579Sgibbs	struct	scb *scb;
9329123579Sgibbs	struct	scb *active_scb;
9330123579Sgibbs	int	found;
9331123579Sgibbs	int	was_paused;
9332123579Sgibbs	u_int	active_scbptr;
9333123579Sgibbs	u_int	last_phase;
9334123579Sgibbs
9335123579Sgibbs	/*
9336123579Sgibbs	 * Pause the controller and manually flush any
9337123579Sgibbs	 * commands that have just completed but that our
9338123579Sgibbs	 * interrupt handler has yet to see.
9339123579Sgibbs	 */
9340123579Sgibbs	was_paused = ahd_is_paused(ahd);
9341133122Sgibbs
9342133122Sgibbs	printf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd),
9343133122Sgibbs	       was_paused ? "" : "not ");
9344199260Sattilio	AHD_CORRECTABLE_ERROR(ahd);
9345133122Sgibbs	ahd_dump_card_state(ahd);
9346133122Sgibbs
9347123579Sgibbs	ahd_pause_and_flushwork(ahd);
9348123579Sgibbs
9349123579Sgibbs	if (LIST_EMPTY(&ahd->timedout_scbs) != 0) {
9350123579Sgibbs		/*
9351123579Sgibbs		 * The timedout commands have already
9352123579Sgibbs		 * completed.  This typically means
9353123579Sgibbs		 * that either the timeout value was on
9354123579Sgibbs		 * the hairy edge of what the device
9355123579Sgibbs		 * requires or - more likely - interrupts
9356123579Sgibbs		 * are not happening.
9357123579Sgibbs		 */
9358123579Sgibbs		printf("%s: Timedout SCBs already complete. "
9359123579Sgibbs		       "Interrupts may not be functioning.\n", ahd_name(ahd));
9360123579Sgibbs		ahd_unpause(ahd);
9361123579Sgibbs		return;
9362123579Sgibbs	}
9363123579Sgibbs
9364123579Sgibbs	/*
9365123579Sgibbs	 * Determine identity of SCB acting on the bus.
9366123579Sgibbs	 * This test only catches non-packetized transactions.
9367123579Sgibbs	 * Due to the fleeting nature of packetized operations,
9368123579Sgibbs	 * we can't easily determine that a packetized operation
9369123579Sgibbs	 * is on the bus.
9370123579Sgibbs	 */
9371123579Sgibbs	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
9372123579Sgibbs	last_phase = ahd_inb(ahd, LASTPHASE);
9373123579Sgibbs	active_scbptr = ahd_get_scbptr(ahd);
9374123579Sgibbs	active_scb = NULL;
9375123579Sgibbs	if (last_phase != P_BUSFREE
9376123579Sgibbs	 || (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)
9377123579Sgibbs		active_scb = ahd_lookup_scb(ahd, active_scbptr);
9378123579Sgibbs
9379123579Sgibbs	while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
9380123579Sgibbs		int	target;
9381123579Sgibbs		int	lun;
9382123579Sgibbs		char	channel;
9383123579Sgibbs
9384123579Sgibbs		target = SCB_GET_TARGET(ahd, scb);
9385123579Sgibbs		channel = SCB_GET_CHANNEL(ahd, scb);
9386123579Sgibbs		lun = SCB_GET_LUN(scb);
9387123579Sgibbs
9388123579Sgibbs		ahd_print_path(ahd, scb);
9389141999Sgibbs		printf("SCB %d - timed out\n", SCB_GET_TAG(scb));
9390123579Sgibbs
9391123579Sgibbs		if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
9392123579Sgibbs			/*
9393123579Sgibbs			 * Been down this road before.
9394123579Sgibbs			 * Do a full bus reset.
9395123579Sgibbs			 */
9396123579Sgibbs			aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
9397123579Sgibbsbus_reset:
9398123579Sgibbs			found = ahd_reset_channel(ahd, channel,
9399123579Sgibbs						  /*Initiate Reset*/TRUE);
9400123579Sgibbs			printf("%s: Issued Channel %c Bus Reset. "
9401123579Sgibbs			       "%d SCBs aborted\n", ahd_name(ahd), channel,
9402123579Sgibbs			       found);
9403123579Sgibbs			continue;
9404123579Sgibbs		}
9405123579Sgibbs
9406123579Sgibbs		/*
9407123579Sgibbs		 * Remove the command from the timedout list in
9408123579Sgibbs		 * preparation for requeing it.
9409123579Sgibbs		 */
9410123579Sgibbs		LIST_REMOVE(scb, timedout_links);
9411123579Sgibbs		scb->flags &= ~SCB_TIMEDOUT;
9412123579Sgibbs
9413123579Sgibbs		if (active_scb != NULL) {
9414123579Sgibbs
9415123579Sgibbs			if (active_scb != scb) {
9416129134Sgibbs
9417123579Sgibbs				/*
9418123579Sgibbs				 * If the active SCB is not us, assume that
9419123579Sgibbs				 * the active SCB has a longer timeout than
9420123579Sgibbs				 * the timedout SCB, and wait for the active
9421129134Sgibbs				 * SCB to timeout.  As a safeguard, only
9422129134Sgibbs				 * allow this deferral to continue if some
9423129134Sgibbs				 * untimed-out command is outstanding.
9424123579Sgibbs				 */
9425129134Sgibbs				if (ahd_other_scb_timeout(ahd, scb,
9426133966Sgibbs							  active_scb) == 0)
9427129134Sgibbs					goto bus_reset;
9428123579Sgibbs				continue;
9429123579Sgibbs			}
9430123579Sgibbs
9431123579Sgibbs			/*
9432123579Sgibbs			 * We're active on the bus, so assert ATN
9433123579Sgibbs			 * and hope that the target responds.
9434123579Sgibbs			 */
9435123579Sgibbs			ahd_set_recoveryscb(ahd, active_scb);
9436123579Sgibbs                	active_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
9437123579Sgibbs			ahd_outb(ahd, MSG_OUT, HOST_MSG);
9438123579Sgibbs			ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
9439123579Sgibbs			ahd_print_path(ahd, active_scb);
9440123579Sgibbs			printf("BDR message in message buffer\n");
9441137870Sgibbs			aic_scb_timer_reset(scb, 2 * 1000);
9442123579Sgibbs			break;
9443123579Sgibbs		} else if (last_phase != P_BUSFREE
9444123579Sgibbs			&& ahd_inb(ahd, SCSIPHASE) == 0) {
9445123579Sgibbs			/*
9446123579Sgibbs			 * SCB is not identified, there
9447123579Sgibbs			 * is no pending REQ, and the sequencer
9448123579Sgibbs			 * has not seen a busfree.  Looks like
9449123579Sgibbs			 * a stuck connection waiting to
9450123579Sgibbs			 * go busfree.  Reset the bus.
9451123579Sgibbs			 */
9452123579Sgibbs			printf("%s: Connection stuck awaiting busfree or "
9453123579Sgibbs			       "Identify Msg.\n", ahd_name(ahd));
9454123579Sgibbs			goto bus_reset;
9455123579Sgibbs		} else if (ahd_search_qinfifo(ahd, target, channel, lun,
9456141999Sgibbs					      SCB_GET_TAG(scb),
9457141978Sgibbs					      ROLE_INITIATOR, /*status*/0,
9458141978Sgibbs					      SEARCH_COUNT) > 0) {
9459123579Sgibbs
9460123579Sgibbs			/*
9461123579Sgibbs			 * We haven't even gone out on the bus
9462123579Sgibbs			 * yet, so the timeout must be due to
9463123579Sgibbs			 * some other command.  Reset the timer
9464123579Sgibbs			 * and go on.
9465123579Sgibbs			 */
9466133966Sgibbs			if (ahd_other_scb_timeout(ahd, scb, NULL) == 0)
9467129134Sgibbs				goto bus_reset;
9468123579Sgibbs		} else {
9469123579Sgibbs			/*
9470123579Sgibbs			 * This SCB is for a disconnected transaction
9471123579Sgibbs			 * and we haven't found a better candidate on
9472123579Sgibbs			 * the bus to explain this timeout.
9473123579Sgibbs			 */
9474123579Sgibbs			ahd_set_recoveryscb(ahd, scb);
9475123579Sgibbs
9476123579Sgibbs			/*
9477123579Sgibbs			 * Actually re-queue this SCB in an attempt
9478123579Sgibbs			 * to select the device before it reconnects.
9479123579Sgibbs			 * In either case (selection or reselection),
9480123579Sgibbs			 * we will now issue a target reset to the
9481123579Sgibbs			 * timed-out device.
9482123579Sgibbs			 */
9483123579Sgibbs			scb->flags |= SCB_DEVICE_RESET;
9484123579Sgibbs			scb->hscb->cdb_len = 0;
9485123579Sgibbs			scb->hscb->task_attribute = 0;
9486123579Sgibbs			scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
9487123579Sgibbs
9488123579Sgibbs			ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
9489123579Sgibbs			if ((scb->flags & SCB_PACKETIZED) != 0) {
9490123579Sgibbs				/*
9491123579Sgibbs				 * Mark the SCB has having an outstanding
9492123579Sgibbs				 * task management function.  Should the command
9493123579Sgibbs				 * complete normally before the task management
9494123579Sgibbs				 * function can be sent, the host will be
9495123579Sgibbs				 * notified to abort our requeued SCB.
9496123579Sgibbs				 */
9497123579Sgibbs				ahd_outb(ahd, SCB_TASK_MANAGEMENT,
9498123579Sgibbs					 scb->hscb->task_management);
9499123579Sgibbs			} else {
9500123579Sgibbs				/*
9501123579Sgibbs				 * If non-packetized, set the MK_MESSAGE control
9502123579Sgibbs				 * bit indicating that we desire to send a
9503123579Sgibbs				 * message.  We also set the disconnected flag
9504123579Sgibbs				 * since there is no guarantee that our SCB
9505123579Sgibbs				 * control byte matches the version on the
9506123579Sgibbs				 * card.  We don't want the sequencer to abort
9507123579Sgibbs				 * the command thinking an unsolicited
9508123579Sgibbs				 * reselection occurred.
9509123579Sgibbs				 */
9510123579Sgibbs				scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
9511123579Sgibbs
9512123579Sgibbs				/*
9513123579Sgibbs				 * The sequencer will never re-reference the
9514123579Sgibbs				 * in-core SCB.  To make sure we are notified
9515123579Sgibbs				 * during reslection, set the MK_MESSAGE flag in
9516123579Sgibbs				 * the card's copy of the SCB.
9517123579Sgibbs				 */
9518123579Sgibbs				ahd_outb(ahd, SCB_CONTROL,
9519123579Sgibbs					 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
9520123579Sgibbs			}
9521123579Sgibbs
9522123579Sgibbs			/*
9523123579Sgibbs			 * Clear out any entries in the QINFIFO first
9524123579Sgibbs			 * so we are the next SCB for this target
9525123579Sgibbs			 * to run.
9526123579Sgibbs			 */
9527123579Sgibbs			ahd_search_qinfifo(ahd, target, channel, lun,
9528123579Sgibbs					   SCB_LIST_NULL, ROLE_INITIATOR,
9529123579Sgibbs					   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
9530123579Sgibbs			ahd_qinfifo_requeue_tail(ahd, scb);
9531123579Sgibbs			ahd_set_scbptr(ahd, active_scbptr);
9532123579Sgibbs			ahd_print_path(ahd, scb);
9533123579Sgibbs			printf("Queuing a BDR SCB\n");
9534137870Sgibbs			aic_scb_timer_reset(scb, 2 * 1000);
9535123579Sgibbs			break;
9536123579Sgibbs		}
9537123579Sgibbs	}
9538123579Sgibbs
9539123579Sgibbs	/*
9540123579Sgibbs	 * Any remaining SCBs were not the "culprit", so remove
9541123579Sgibbs	 * them from the timeout list.  The timer for these commands
9542123579Sgibbs	 * will be reset once the recovery SCB completes.
9543123579Sgibbs	 */
9544123579Sgibbs	while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
9545123579Sgibbs
9546123579Sgibbs		LIST_REMOVE(scb, timedout_links);
9547123579Sgibbs		scb->flags &= ~SCB_TIMEDOUT;
9548123579Sgibbs	}
9549123579Sgibbs
9550123579Sgibbs	ahd_unpause(ahd);
9551123579Sgibbs}
9552123579Sgibbs
9553129134Sgibbs/*
9554129134Sgibbs * Re-schedule a timeout for the passed in SCB if we determine that some
9555129134Sgibbs * other SCB is in the process of recovery or an SCB with a longer
9556129134Sgibbs * timeout is still pending.  Limit our search to just "other_scb"
9557129134Sgibbs * if it is non-NULL.
9558129134Sgibbs */
9559129134Sgibbsstatic int
9560123579Sgibbsahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb,
9561123579Sgibbs		      struct scb *other_scb)
9562123579Sgibbs{
9563123579Sgibbs	u_int	newtimeout;
9564129134Sgibbs	int	found;
9565123579Sgibbs
9566123579Sgibbs	ahd_print_path(ahd, scb);
9567123579Sgibbs	printf("Other SCB Timeout%s",
9568123579Sgibbs 	       (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
9569123579Sgibbs	       ? " again\n" : "\n");
9570129134Sgibbs
9571199260Sattilio	AHD_UNCORRECTABLE_ERROR(ahd);
9572129134Sgibbs	newtimeout = aic_get_timeout(scb);
9573123579Sgibbs	scb->flags |= SCB_OTHERTCL_TIMEOUT;
9574129134Sgibbs	found = 0;
9575129134Sgibbs	if (other_scb != NULL) {
9576129134Sgibbs		if ((other_scb->flags
9577129134Sgibbs		   & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0
9578129134Sgibbs		 || (other_scb->flags & SCB_RECOVERY_SCB) != 0) {
9579129134Sgibbs			found++;
9580129134Sgibbs			newtimeout = MAX(aic_get_timeout(other_scb),
9581129134Sgibbs					 newtimeout);
9582129134Sgibbs		}
9583129134Sgibbs	} else {
9584129134Sgibbs		LIST_FOREACH(other_scb, &ahd->pending_scbs, pending_links) {
9585129134Sgibbs			if ((other_scb->flags
9586129134Sgibbs			   & (SCB_OTHERTCL_TIMEOUT|SCB_TIMEDOUT)) == 0
9587129134Sgibbs			 || (other_scb->flags & SCB_RECOVERY_SCB) != 0) {
9588129134Sgibbs				found++;
9589129134Sgibbs				newtimeout = MAX(aic_get_timeout(other_scb),
9590129134Sgibbs						 newtimeout);
9591129134Sgibbs			}
9592129134Sgibbs		}
9593129134Sgibbs	}
9594129134Sgibbs
9595129134Sgibbs	if (found != 0)
9596129134Sgibbs		aic_scb_timer_reset(scb, newtimeout);
9597129134Sgibbs	else {
9598129134Sgibbs		ahd_print_path(ahd, scb);
9599129134Sgibbs		printf("No other SCB worth waiting for...\n");
9600129134Sgibbs	}
9601129134Sgibbs
9602129134Sgibbs	return (found != 0);
9603123579Sgibbs}
9604123579Sgibbs
960597883Sgibbs/**************************** Flexport Logic **********************************/
960697883Sgibbs/*
960797883Sgibbs * Read count 16bit words from 16bit word address start_addr from the
960897883Sgibbs * SEEPROM attached to the controller, into buf, using the controller's
9609114623Sgibbs * SEEPROM reading state machine.  Optionally treat the data as a byte
9610114623Sgibbs * stream in terms of byte order.
961197883Sgibbs */
961297883Sgibbsint
961397883Sgibbsahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf,
9614114623Sgibbs		 u_int start_addr, u_int count, int bytestream)
961597883Sgibbs{
961697883Sgibbs	u_int cur_addr;
961797883Sgibbs	u_int end_addr;
961897883Sgibbs	int   error;
961997883Sgibbs
962097883Sgibbs	/*
962197883Sgibbs	 * If we never make it through the loop even once,
962297883Sgibbs	 * we were passed invalid arguments.
962397883Sgibbs	 */
962497883Sgibbs	error = EINVAL;
962597883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
962697883Sgibbs	end_addr = start_addr + count;
962797883Sgibbs	for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
9628114623Sgibbs
962997883Sgibbs		ahd_outb(ahd, SEEADR, cur_addr);
963097883Sgibbs		ahd_outb(ahd, SEECTL, SEEOP_READ | SEESTART);
963197883Sgibbs
963297883Sgibbs		error = ahd_wait_seeprom(ahd);
963397883Sgibbs		if (error)
963497883Sgibbs			break;
9635114623Sgibbs		if (bytestream != 0) {
9636114623Sgibbs			uint8_t *bytestream_ptr;
9637114623Sgibbs
9638114623Sgibbs			bytestream_ptr = (uint8_t *)buf;
9639114623Sgibbs			*bytestream_ptr++ = ahd_inb(ahd, SEEDAT);
9640114623Sgibbs			*bytestream_ptr = ahd_inb(ahd, SEEDAT+1);
9641114623Sgibbs		} else {
9642114623Sgibbs			/*
9643114623Sgibbs			 * ahd_inw() already handles machine byte order.
9644114623Sgibbs			 */
9645114623Sgibbs			*buf = ahd_inw(ahd, SEEDAT);
9646114623Sgibbs		}
9647114623Sgibbs		buf++;
964897883Sgibbs	}
964997883Sgibbs	return (error);
965097883Sgibbs}
965197883Sgibbs
965297883Sgibbs/*
965397883Sgibbs * Write count 16bit words from buf, into SEEPROM attache to the
965497883Sgibbs * controller starting at 16bit word address start_addr, using the
965597883Sgibbs * controller's SEEPROM writing state machine.
965697883Sgibbs */
965797883Sgibbsint
965897883Sgibbsahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf,
965997883Sgibbs		  u_int start_addr, u_int count)
966097883Sgibbs{
966197883Sgibbs	u_int cur_addr;
966297883Sgibbs	u_int end_addr;
966397883Sgibbs	int   error;
966497883Sgibbs	int   retval;
966597883Sgibbs
966697883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
966797883Sgibbs	error = ENOENT;
966897883Sgibbs
966997883Sgibbs	/* Place the chip into write-enable mode */
967097883Sgibbs	ahd_outb(ahd, SEEADR, SEEOP_EWEN_ADDR);
967197883Sgibbs	ahd_outb(ahd, SEECTL, SEEOP_EWEN | SEESTART);
967297883Sgibbs	error = ahd_wait_seeprom(ahd);
967397883Sgibbs	if (error)
967497883Sgibbs		return (error);
967597883Sgibbs
967697883Sgibbs	/*
967797883Sgibbs	 * Write the data.  If we don't get throught the loop at
967897883Sgibbs	 * least once, the arguments were invalid.
967997883Sgibbs	 */
968097883Sgibbs	retval = EINVAL;
968197883Sgibbs	end_addr = start_addr + count;
968297883Sgibbs	for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
968397883Sgibbs		ahd_outw(ahd, SEEDAT, *buf++);
968497883Sgibbs		ahd_outb(ahd, SEEADR, cur_addr);
968597883Sgibbs		ahd_outb(ahd, SEECTL, SEEOP_WRITE | SEESTART);
968697883Sgibbs
968797883Sgibbs		retval = ahd_wait_seeprom(ahd);
968897883Sgibbs		if (retval)
968997883Sgibbs			break;
969097883Sgibbs	}
969197883Sgibbs
969297883Sgibbs	/*
969397883Sgibbs	 * Disable writes.
969497883Sgibbs	 */
969597883Sgibbs	ahd_outb(ahd, SEEADR, SEEOP_EWDS_ADDR);
969697883Sgibbs	ahd_outb(ahd, SEECTL, SEEOP_EWDS | SEESTART);
969797883Sgibbs	error = ahd_wait_seeprom(ahd);
969897883Sgibbs	if (error)
969997883Sgibbs		return (error);
970097883Sgibbs	return (retval);
970197883Sgibbs}
970297883Sgibbs
970397883Sgibbs/*
970497883Sgibbs * Wait ~100us for the serial eeprom to satisfy our request.
970597883Sgibbs */
970697883Sgibbsint
970797883Sgibbsahd_wait_seeprom(struct ahd_softc *ahd)
970897883Sgibbs{
970997883Sgibbs	int cnt;
971097883Sgibbs
9711123579Sgibbs	cnt = 5000;
971297883Sgibbs	while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
9713123579Sgibbs		aic_delay(5);
971497883Sgibbs
971597883Sgibbs	if (cnt == 0)
971697883Sgibbs		return (ETIMEDOUT);
971797883Sgibbs	return (0);
971897883Sgibbs}
971997883Sgibbs
9720114623Sgibbs/*
9721114623Sgibbs * Validate the two checksums in the per_channel
9722114623Sgibbs * vital product data struct.
9723114623Sgibbs */
972497883Sgibbsint
9725114623Sgibbsahd_verify_vpd_cksum(struct vpd_config *vpd)
9726114623Sgibbs{
9727114623Sgibbs	int i;
9728114623Sgibbs	int maxaddr;
9729114623Sgibbs	uint32_t checksum;
9730114623Sgibbs	uint8_t *vpdarray;
9731114623Sgibbs
9732114623Sgibbs	vpdarray = (uint8_t *)vpd;
9733114623Sgibbs	maxaddr = offsetof(struct vpd_config, vpd_checksum);
9734114623Sgibbs	checksum = 0;
9735114623Sgibbs	for (i = offsetof(struct vpd_config, resource_type); i < maxaddr; i++)
9736114623Sgibbs		checksum = checksum + vpdarray[i];
9737114623Sgibbs	if (checksum == 0
9738114623Sgibbs	 || (-checksum & 0xFF) != vpd->vpd_checksum)
9739114623Sgibbs		return (0);
9740114623Sgibbs
9741114623Sgibbs	checksum = 0;
9742114623Sgibbs	maxaddr = offsetof(struct vpd_config, checksum);
9743114623Sgibbs	for (i = offsetof(struct vpd_config, default_target_flags);
9744114623Sgibbs	     i < maxaddr; i++)
9745114623Sgibbs		checksum = checksum + vpdarray[i];
9746114623Sgibbs	if (checksum == 0
9747114623Sgibbs	 || (-checksum & 0xFF) != vpd->checksum)
9748114623Sgibbs		return (0);
9749114623Sgibbs	return (1);
9750114623Sgibbs}
9751114623Sgibbs
9752114623Sgibbsint
975397883Sgibbsahd_verify_cksum(struct seeprom_config *sc)
975497883Sgibbs{
975597883Sgibbs	int i;
975697883Sgibbs	int maxaddr;
975797883Sgibbs	uint32_t checksum;
975897883Sgibbs	uint16_t *scarray;
975997883Sgibbs
976097883Sgibbs	maxaddr = (sizeof(*sc)/2) - 1;
976197883Sgibbs	checksum = 0;
976297883Sgibbs	scarray = (uint16_t *)sc;
976397883Sgibbs
976497883Sgibbs	for (i = 0; i < maxaddr; i++)
976597883Sgibbs		checksum = checksum + scarray[i];
976697883Sgibbs	if (checksum == 0
976797883Sgibbs	 || (checksum & 0xFFFF) != sc->checksum) {
976897883Sgibbs		return (0);
976997883Sgibbs	} else {
977097883Sgibbs		return (1);
977197883Sgibbs	}
977297883Sgibbs}
977397883Sgibbs
977497883Sgibbsint
977597883Sgibbsahd_acquire_seeprom(struct ahd_softc *ahd)
977697883Sgibbs{
9777102679Sgibbs	/*
9778102679Sgibbs	 * We should be able to determine the SEEPROM type
9779102679Sgibbs	 * from the flexport logic, but unfortunately not
9780102679Sgibbs	 * all implementations have this logic and there is
9781102679Sgibbs	 * no programatic method for determining if the logic
9782102679Sgibbs	 * is present.
9783102679Sgibbs	 */
9784102679Sgibbs	return (1);
9785102679Sgibbs#if 0
978697883Sgibbs	uint8_t	seetype;
978797883Sgibbs	int	error;
978897883Sgibbs
978997883Sgibbs	error = ahd_read_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, &seetype);
979097883Sgibbs	if (error != 0
979197883Sgibbs         || ((seetype & FLX_ROMSTAT_SEECFG) == FLX_ROMSTAT_SEE_NONE))
979297883Sgibbs		return (0);
979397883Sgibbs	return (1);
9794102679Sgibbs#endif
979597883Sgibbs}
979697883Sgibbs
979797883Sgibbsvoid
979897883Sgibbsahd_release_seeprom(struct ahd_softc *ahd)
979997883Sgibbs{
980097883Sgibbs	/* Currently a no-op */
980197883Sgibbs}
980297883Sgibbs
980397883Sgibbsint
980497883Sgibbsahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value)
980597883Sgibbs{
980697883Sgibbs	int error;
980797883Sgibbs
980897883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
980997883Sgibbs	if (addr > 7)
981097883Sgibbs		panic("ahd_write_flexport: address out of range");
981197883Sgibbs	ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
981297883Sgibbs	error = ahd_wait_flexport(ahd);
981397883Sgibbs	if (error != 0)
981497883Sgibbs		return (error);
981597883Sgibbs	ahd_outb(ahd, BRDDAT, value);
981697883Sgibbs	ahd_flush_device_writes(ahd);
981797883Sgibbs	ahd_outb(ahd, BRDCTL, BRDSTB|BRDEN|(addr << 3));
981897883Sgibbs	ahd_flush_device_writes(ahd);
981997883Sgibbs	ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
982097883Sgibbs	ahd_flush_device_writes(ahd);
982197883Sgibbs	ahd_outb(ahd, BRDCTL, 0);
982297883Sgibbs	ahd_flush_device_writes(ahd);
982397883Sgibbs	return (0);
982497883Sgibbs}
982597883Sgibbs
982697883Sgibbsint
982797883Sgibbsahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value)
982897883Sgibbs{
982997883Sgibbs	int	error;
983097883Sgibbs
983197883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
983297883Sgibbs	if (addr > 7)
983397883Sgibbs		panic("ahd_read_flexport: address out of range");
983497883Sgibbs	ahd_outb(ahd, BRDCTL, BRDRW|BRDEN|(addr << 3));
983597883Sgibbs	error = ahd_wait_flexport(ahd);
983697883Sgibbs	if (error != 0)
983797883Sgibbs		return (error);
983897883Sgibbs	*value = ahd_inb(ahd, BRDDAT);
983997883Sgibbs	ahd_outb(ahd, BRDCTL, 0);
984097883Sgibbs	ahd_flush_device_writes(ahd);
984197883Sgibbs	return (0);
984297883Sgibbs}
984397883Sgibbs
984497883Sgibbs/*
984597883Sgibbs * Wait at most 2 seconds for flexport arbitration to succeed.
984697883Sgibbs */
984797883Sgibbsint
984897883Sgibbsahd_wait_flexport(struct ahd_softc *ahd)
984997883Sgibbs{
985097883Sgibbs	int cnt;
985197883Sgibbs
985297883Sgibbs	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
985397883Sgibbs	cnt = 1000000 * 2 / 5;
985497883Sgibbs	while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt)
9855123579Sgibbs		aic_delay(5);
985697883Sgibbs
985797883Sgibbs	if (cnt == 0)
985897883Sgibbs		return (ETIMEDOUT);
985997883Sgibbs	return (0);
986097883Sgibbs}
986197883Sgibbs
986297883Sgibbs/************************* Target Mode ****************************************/
986397883Sgibbs#ifdef AHD_TARGET_MODE
986497883Sgibbscam_status
986597883Sgibbsahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb,
986697883Sgibbs		    struct ahd_tmode_tstate **tstate,
986797883Sgibbs		    struct ahd_tmode_lstate **lstate,
986897883Sgibbs		    int notfound_failure)
986997883Sgibbs{
987097883Sgibbs
987197883Sgibbs	if ((ahd->features & AHD_TARGETMODE) == 0)
987297883Sgibbs		return (CAM_REQ_INVALID);
987397883Sgibbs
987497883Sgibbs	/*
987597883Sgibbs	 * Handle the 'black hole' device that sucks up
987697883Sgibbs	 * requests to unattached luns on enabled targets.
987797883Sgibbs	 */
987897883Sgibbs	if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD
987997883Sgibbs	 && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
988097883Sgibbs		*tstate = NULL;
988197883Sgibbs		*lstate = ahd->black_hole;
988297883Sgibbs	} else {
988397883Sgibbs		u_int max_id;
988497883Sgibbs
988597883Sgibbs		max_id = (ahd->features & AHD_WIDE) ? 15 : 7;
988697883Sgibbs		if (ccb->ccb_h.target_id > max_id)
988797883Sgibbs			return (CAM_TID_INVALID);
988897883Sgibbs
988997883Sgibbs		if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS)
989097883Sgibbs			return (CAM_LUN_INVALID);
989197883Sgibbs
989297883Sgibbs		*tstate = ahd->enabled_targets[ccb->ccb_h.target_id];
989397883Sgibbs		*lstate = NULL;
989497883Sgibbs		if (*tstate != NULL)
989597883Sgibbs			*lstate =
989697883Sgibbs			    (*tstate)->enabled_luns[ccb->ccb_h.target_lun];
989797883Sgibbs	}
989897883Sgibbs
989997883Sgibbs	if (notfound_failure != 0 && *lstate == NULL)
990097883Sgibbs		return (CAM_PATH_INVALID);
990197883Sgibbs
990297883Sgibbs	return (CAM_REQ_CMP);
990397883Sgibbs}
990497883Sgibbs
990597883Sgibbsvoid
990697883Sgibbsahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
990797883Sgibbs{
990897883Sgibbs#if NOT_YET
990997883Sgibbs	struct	   ahd_tmode_tstate *tstate;
991097883Sgibbs	struct	   ahd_tmode_lstate *lstate;
991197883Sgibbs	struct	   ccb_en_lun *cel;
991297883Sgibbs	cam_status status;
991397883Sgibbs	u_int	   target;
991497883Sgibbs	u_int	   lun;
991597883Sgibbs	u_int	   target_mask;
991697883Sgibbs	u_long	   s;
991797883Sgibbs	char	   channel;
991897883Sgibbs
991997883Sgibbs	status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, &lstate,
992097883Sgibbs				     /*notfound_failure*/FALSE);
992197883Sgibbs
992297883Sgibbs	if (status != CAM_REQ_CMP) {
992397883Sgibbs		ccb->ccb_h.status = status;
992497883Sgibbs		return;
992597883Sgibbs	}
992697883Sgibbs
992797883Sgibbs	if ((ahd->features & AHD_MULTIROLE) != 0) {
992897883Sgibbs		u_int	   our_id;
992997883Sgibbs
993097883Sgibbs		our_id = ahd->our_id;
993197883Sgibbs		if (ccb->ccb_h.target_id != our_id) {
993297883Sgibbs			if ((ahd->features & AHD_MULTI_TID) != 0
993397883Sgibbs		   	 && (ahd->flags & AHD_INITIATORROLE) != 0) {
993497883Sgibbs				/*
993597883Sgibbs				 * Only allow additional targets if
993697883Sgibbs				 * the initiator role is disabled.
993797883Sgibbs				 * The hardware cannot handle a re-select-in
993897883Sgibbs				 * on the initiator id during a re-select-out
993997883Sgibbs				 * on a different target id.
994097883Sgibbs				 */
994197883Sgibbs				status = CAM_TID_INVALID;
994297883Sgibbs			} else if ((ahd->flags & AHD_INITIATORROLE) != 0
994397883Sgibbs				|| ahd->enabled_luns > 0) {
994497883Sgibbs				/*
994597883Sgibbs				 * Only allow our target id to change
994697883Sgibbs				 * if the initiator role is not configured
994797883Sgibbs				 * and there are no enabled luns which
994897883Sgibbs				 * are attached to the currently registered
994997883Sgibbs				 * scsi id.
995097883Sgibbs				 */
995197883Sgibbs				status = CAM_TID_INVALID;
995297883Sgibbs			}
995397883Sgibbs		}
995497883Sgibbs	}
995597883Sgibbs
995697883Sgibbs	if (status != CAM_REQ_CMP) {
995797883Sgibbs		ccb->ccb_h.status = status;
995897883Sgibbs		return;
995997883Sgibbs	}
996097883Sgibbs
996197883Sgibbs	/*
996297883Sgibbs	 * We now have an id that is valid.
996397883Sgibbs	 * If we aren't in target mode, switch modes.
996497883Sgibbs	 */
996597883Sgibbs	if ((ahd->flags & AHD_TARGETROLE) == 0
996697883Sgibbs	 && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
996797883Sgibbs		printf("Configuring Target Mode\n");
996897883Sgibbs		if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
996997883Sgibbs			ccb->ccb_h.status = CAM_BUSY;
997097883Sgibbs			return;
997197883Sgibbs		}
997297883Sgibbs		ahd->flags |= AHD_TARGETROLE;
997397883Sgibbs		if ((ahd->features & AHD_MULTIROLE) == 0)
997497883Sgibbs			ahd->flags &= ~AHD_INITIATORROLE;
997597883Sgibbs		ahd_pause(ahd);
997697883Sgibbs		ahd_loadseq(ahd);
9977115917Sgibbs		ahd_restart(ahd);
997897883Sgibbs	}
997997883Sgibbs	cel = &ccb->cel;
998097883Sgibbs	target = ccb->ccb_h.target_id;
998197883Sgibbs	lun = ccb->ccb_h.target_lun;
998297883Sgibbs	channel = SIM_CHANNEL(ahd, sim);
998397883Sgibbs	target_mask = 0x01 << target;
998497883Sgibbs	if (channel == 'B')
998597883Sgibbs		target_mask <<= 8;
998697883Sgibbs
998797883Sgibbs	if (cel->enable != 0) {
998897883Sgibbs		u_int scsiseq1;
998997883Sgibbs
999097883Sgibbs		/* Are we already enabled?? */
999197883Sgibbs		if (lstate != NULL) {
999297883Sgibbs			xpt_print_path(ccb->ccb_h.path);
999397883Sgibbs			printf("Lun already enabled\n");
9994199260Sattilio			AHD_CORRECTABLE_ERROR(ahd);
999597883Sgibbs			ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
999697883Sgibbs			return;
999797883Sgibbs		}
999897883Sgibbs
999997883Sgibbs		if (cel->grp6_len != 0
1000097883Sgibbs		 || cel->grp7_len != 0) {
1000197883Sgibbs			/*
1000297883Sgibbs			 * Don't (yet?) support vendor
1000397883Sgibbs			 * specific commands.
1000497883Sgibbs			 */
1000597883Sgibbs			ccb->ccb_h.status = CAM_REQ_INVALID;
1000697883Sgibbs			printf("Non-zero Group Codes\n");
1000797883Sgibbs			return;
1000897883Sgibbs		}
1000997883Sgibbs
1001097883Sgibbs		/*
1001197883Sgibbs		 * Seems to be okay.
1001297883Sgibbs		 * Setup our data structures.
1001397883Sgibbs		 */
1001497883Sgibbs		if (target != CAM_TARGET_WILDCARD && tstate == NULL) {
1001597883Sgibbs			tstate = ahd_alloc_tstate(ahd, target, channel);
1001697883Sgibbs			if (tstate == NULL) {
1001797883Sgibbs				xpt_print_path(ccb->ccb_h.path);
1001897883Sgibbs				printf("Couldn't allocate tstate\n");
1001997883Sgibbs				ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1002097883Sgibbs				return;
1002197883Sgibbs			}
1002297883Sgibbs		}
1002397883Sgibbs		lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT);
1002497883Sgibbs		if (lstate == NULL) {
1002597883Sgibbs			xpt_print_path(ccb->ccb_h.path);
1002697883Sgibbs			printf("Couldn't allocate lstate\n");
1002797883Sgibbs			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1002897883Sgibbs			return;
1002997883Sgibbs		}
1003097883Sgibbs		memset(lstate, 0, sizeof(*lstate));
1003197883Sgibbs		status = xpt_create_path(&lstate->path, /*periph*/NULL,
1003297883Sgibbs					 xpt_path_path_id(ccb->ccb_h.path),
1003397883Sgibbs					 xpt_path_target_id(ccb->ccb_h.path),
1003497883Sgibbs					 xpt_path_lun_id(ccb->ccb_h.path));
1003597883Sgibbs		if (status != CAM_REQ_CMP) {
1003697883Sgibbs			free(lstate, M_DEVBUF);
1003797883Sgibbs			xpt_print_path(ccb->ccb_h.path);
1003897883Sgibbs			printf("Couldn't allocate path\n");
1003997883Sgibbs			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1004097883Sgibbs			return;
1004197883Sgibbs		}
1004297883Sgibbs		SLIST_INIT(&lstate->accept_tios);
1004397883Sgibbs		SLIST_INIT(&lstate->immed_notifies);
1004497883Sgibbs		ahd_pause(ahd);
1004597883Sgibbs		if (target != CAM_TARGET_WILDCARD) {
1004697883Sgibbs			tstate->enabled_luns[lun] = lstate;
1004797883Sgibbs			ahd->enabled_luns++;
1004897883Sgibbs
1004997883Sgibbs			if ((ahd->features & AHD_MULTI_TID) != 0) {
1005097883Sgibbs				u_int targid_mask;
1005197883Sgibbs
10052123579Sgibbs				targid_mask = ahd_inw(ahd, TARGID);
1005397883Sgibbs				targid_mask |= target_mask;
10054123579Sgibbs				ahd_outw(ahd, TARGID, targid_mask);
1005597883Sgibbs				ahd_update_scsiid(ahd, targid_mask);
1005697883Sgibbs			} else {
1005797883Sgibbs				u_int our_id;
1005897883Sgibbs				char  channel;
1005997883Sgibbs
1006097883Sgibbs				channel = SIM_CHANNEL(ahd, sim);
1006197883Sgibbs				our_id = SIM_SCSI_ID(ahd, sim);
1006297883Sgibbs
1006397883Sgibbs				/*
1006497883Sgibbs				 * This can only happen if selections
1006597883Sgibbs				 * are not enabled
1006697883Sgibbs				 */
1006797883Sgibbs				if (target != our_id) {
1006897883Sgibbs					u_int sblkctl;
1006997883Sgibbs					char  cur_channel;
1007097883Sgibbs					int   swap;
1007197883Sgibbs
1007297883Sgibbs					sblkctl = ahd_inb(ahd, SBLKCTL);
1007397883Sgibbs					cur_channel = (sblkctl & SELBUSB)
1007497883Sgibbs						    ? 'B' : 'A';
1007597883Sgibbs					if ((ahd->features & AHD_TWIN) == 0)
1007697883Sgibbs						cur_channel = 'A';
1007797883Sgibbs					swap = cur_channel != channel;
1007897883Sgibbs					ahd->our_id = target;
1007997883Sgibbs
1008097883Sgibbs					if (swap)
1008197883Sgibbs						ahd_outb(ahd, SBLKCTL,
1008297883Sgibbs							 sblkctl ^ SELBUSB);
1008397883Sgibbs
1008497883Sgibbs					ahd_outb(ahd, SCSIID, target);
1008597883Sgibbs
1008697883Sgibbs					if (swap)
1008797883Sgibbs						ahd_outb(ahd, SBLKCTL, sblkctl);
1008897883Sgibbs				}
1008997883Sgibbs			}
1009097883Sgibbs		} else
1009197883Sgibbs			ahd->black_hole = lstate;
1009297883Sgibbs		/* Allow select-in operations */
1009397883Sgibbs		if (ahd->black_hole != NULL && ahd->enabled_luns > 0) {
1009497883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
1009597883Sgibbs			scsiseq1 |= ENSELI;
1009697883Sgibbs			ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
1009797883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ1);
1009897883Sgibbs			scsiseq1 |= ENSELI;
1009997883Sgibbs			ahd_outb(ahd, SCSISEQ1, scsiseq1);
1010097883Sgibbs		}
1010197883Sgibbs		ahd_unpause(ahd);
1010297883Sgibbs		ccb->ccb_h.status = CAM_REQ_CMP;
1010397883Sgibbs		xpt_print_path(ccb->ccb_h.path);
1010497883Sgibbs		printf("Lun now enabled for target mode\n");
1010597883Sgibbs	} else {
1010697883Sgibbs		struct scb *scb;
1010797883Sgibbs		int i, empty;
1010897883Sgibbs
1010997883Sgibbs		if (lstate == NULL) {
1011097883Sgibbs			ccb->ccb_h.status = CAM_LUN_INVALID;
1011197883Sgibbs			return;
1011297883Sgibbs		}
1011397883Sgibbs
1011497883Sgibbs		ccb->ccb_h.status = CAM_REQ_CMP;
1011597883Sgibbs		LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
1011697883Sgibbs			struct ccb_hdr *ccbh;
1011797883Sgibbs
1011897883Sgibbs			ccbh = &scb->io_ctx->ccb_h;
1011997883Sgibbs			if (ccbh->func_code == XPT_CONT_TARGET_IO
1012097883Sgibbs			 && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
1012197883Sgibbs				printf("CTIO pending\n");
1012297883Sgibbs				ccb->ccb_h.status = CAM_REQ_INVALID;
1012397883Sgibbs				return;
1012497883Sgibbs			}
1012597883Sgibbs		}
1012697883Sgibbs
1012797883Sgibbs		if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
1012897883Sgibbs			printf("ATIOs pending\n");
1012997883Sgibbs			ccb->ccb_h.status = CAM_REQ_INVALID;
1013097883Sgibbs		}
1013197883Sgibbs
1013297883Sgibbs		if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
1013397883Sgibbs			printf("INOTs pending\n");
1013497883Sgibbs			ccb->ccb_h.status = CAM_REQ_INVALID;
1013597883Sgibbs		}
1013697883Sgibbs
1013797883Sgibbs		if (ccb->ccb_h.status != CAM_REQ_CMP) {
1013897883Sgibbs			return;
1013997883Sgibbs		}
1014097883Sgibbs
1014197883Sgibbs		xpt_print_path(ccb->ccb_h.path);
1014297883Sgibbs		printf("Target mode disabled\n");
1014397883Sgibbs		xpt_free_path(lstate->path);
1014497883Sgibbs		free(lstate, M_DEVBUF);
1014597883Sgibbs
1014697883Sgibbs		ahd_pause(ahd);
1014797883Sgibbs		/* Can we clean up the target too? */
1014897883Sgibbs		if (target != CAM_TARGET_WILDCARD) {
1014997883Sgibbs			tstate->enabled_luns[lun] = NULL;
1015097883Sgibbs			ahd->enabled_luns--;
1015197883Sgibbs			for (empty = 1, i = 0; i < 8; i++)
1015297883Sgibbs				if (tstate->enabled_luns[i] != NULL) {
1015397883Sgibbs					empty = 0;
1015497883Sgibbs					break;
1015597883Sgibbs				}
1015697883Sgibbs
1015797883Sgibbs			if (empty) {
1015897883Sgibbs				ahd_free_tstate(ahd, target, channel,
1015997883Sgibbs						/*force*/FALSE);
1016097883Sgibbs				if (ahd->features & AHD_MULTI_TID) {
1016197883Sgibbs					u_int targid_mask;
1016297883Sgibbs
10163123579Sgibbs					targid_mask = ahd_inw(ahd, TARGID);
1016497883Sgibbs					targid_mask &= ~target_mask;
10165123579Sgibbs					ahd_outw(ahd, TARGID, targid_mask);
1016697883Sgibbs					ahd_update_scsiid(ahd, targid_mask);
1016797883Sgibbs				}
1016897883Sgibbs			}
1016997883Sgibbs		} else {
1017097883Sgibbs
1017197883Sgibbs			ahd->black_hole = NULL;
1017297883Sgibbs
1017397883Sgibbs			/*
1017497883Sgibbs			 * We can't allow selections without
1017597883Sgibbs			 * our black hole device.
1017697883Sgibbs			 */
1017797883Sgibbs			empty = TRUE;
1017897883Sgibbs		}
1017997883Sgibbs		if (ahd->enabled_luns == 0) {
1018097883Sgibbs			/* Disallow select-in */
1018197883Sgibbs			u_int scsiseq1;
1018297883Sgibbs
1018397883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
1018497883Sgibbs			scsiseq1 &= ~ENSELI;
1018597883Sgibbs			ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
1018697883Sgibbs			scsiseq1 = ahd_inb(ahd, SCSISEQ1);
1018797883Sgibbs			scsiseq1 &= ~ENSELI;
1018897883Sgibbs			ahd_outb(ahd, SCSISEQ1, scsiseq1);
1018997883Sgibbs
1019097883Sgibbs			if ((ahd->features & AHD_MULTIROLE) == 0) {
1019197883Sgibbs				printf("Configuring Initiator Mode\n");
1019297883Sgibbs				ahd->flags &= ~AHD_TARGETROLE;
1019397883Sgibbs				ahd->flags |= AHD_INITIATORROLE;
1019497883Sgibbs				ahd_pause(ahd);
1019597883Sgibbs				ahd_loadseq(ahd);
10196115917Sgibbs				ahd_restart(ahd);
10197115917Sgibbs				/*
10198115917Sgibbs				 * Unpaused.  The extra unpause
10199115917Sgibbs				 * that follows is harmless.
10200115917Sgibbs				 */
1020197883Sgibbs			}
1020297883Sgibbs		}
1020397883Sgibbs		ahd_unpause(ahd);
1020497883Sgibbs	}
1020597883Sgibbs#endif
1020697883Sgibbs}
1020797883Sgibbs
1020897883Sgibbsstatic void
1020997883Sgibbsahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)
1021097883Sgibbs{
1021197883Sgibbs#if NOT_YET
1021297883Sgibbs	u_int scsiid_mask;
1021397883Sgibbs	u_int scsiid;
1021497883Sgibbs
1021597883Sgibbs	if ((ahd->features & AHD_MULTI_TID) == 0)
1021697883Sgibbs		panic("ahd_update_scsiid called on non-multitid unit\n");
1021797883Sgibbs
1021897883Sgibbs	/*
10219102679Sgibbs	 * Since we will rely on the TARGID mask
1022097883Sgibbs	 * for selection enables, ensure that OID
1022197883Sgibbs	 * in SCSIID is not set to some other ID
1022297883Sgibbs	 * that we don't want to allow selections on.
1022397883Sgibbs	 */
1022497883Sgibbs	if ((ahd->features & AHD_ULTRA2) != 0)
1022597883Sgibbs		scsiid = ahd_inb(ahd, SCSIID_ULTRA2);
1022697883Sgibbs	else
1022797883Sgibbs		scsiid = ahd_inb(ahd, SCSIID);
1022897883Sgibbs	scsiid_mask = 0x1 << (scsiid & OID);
1022997883Sgibbs	if ((targid_mask & scsiid_mask) == 0) {
1023097883Sgibbs		u_int our_id;
1023197883Sgibbs
1023297883Sgibbs		/* ffs counts from 1 */
1023397883Sgibbs		our_id = ffs(targid_mask);
1023497883Sgibbs		if (our_id == 0)
1023597883Sgibbs			our_id = ahd->our_id;
1023697883Sgibbs		else
1023797883Sgibbs			our_id--;
1023897883Sgibbs		scsiid &= TID;
1023997883Sgibbs		scsiid |= our_id;
1024097883Sgibbs	}
1024197883Sgibbs	if ((ahd->features & AHD_ULTRA2) != 0)
1024297883Sgibbs		ahd_outb(ahd, SCSIID_ULTRA2, scsiid);
1024397883Sgibbs	else
1024497883Sgibbs		ahd_outb(ahd, SCSIID, scsiid);
1024597883Sgibbs#endif
1024697883Sgibbs}
1024797883Sgibbs
1024897883Sgibbsvoid
1024997883Sgibbsahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
1025097883Sgibbs{
1025197883Sgibbs	struct target_cmd *cmd;
1025297883Sgibbs
1025397883Sgibbs	ahd_sync_tqinfifo(ahd, BUS_DMASYNC_POSTREAD);
1025497883Sgibbs	while ((cmd = &ahd->targetcmds[ahd->tqinfifonext])->cmd_valid != 0) {
1025597883Sgibbs
1025697883Sgibbs		/*
1025797883Sgibbs		 * Only advance through the queue if we
1025897883Sgibbs		 * have the resources to process the command.
1025997883Sgibbs		 */
1026097883Sgibbs		if (ahd_handle_target_cmd(ahd, cmd) != 0)
1026197883Sgibbs			break;
1026297883Sgibbs
1026397883Sgibbs		cmd->cmd_valid = 0;
1026497883Sgibbs		ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
1026597883Sgibbs				ahd->shared_data_dmamap,
1026697883Sgibbs				ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
1026797883Sgibbs				sizeof(struct target_cmd),
1026897883Sgibbs				BUS_DMASYNC_PREREAD);
1026997883Sgibbs		ahd->tqinfifonext++;
1027097883Sgibbs
1027197883Sgibbs		/*
1027297883Sgibbs		 * Lazily update our position in the target mode incoming
1027397883Sgibbs		 * command queue as seen by the sequencer.
1027497883Sgibbs		 */
1027597883Sgibbs		if ((ahd->tqinfifonext & (HOST_TQINPOS - 1)) == 1) {
1027697883Sgibbs			u_int hs_mailbox;
1027797883Sgibbs
1027897883Sgibbs			hs_mailbox = ahd_inb(ahd, HS_MAILBOX);
1027997883Sgibbs			hs_mailbox &= ~HOST_TQINPOS;
1028097883Sgibbs			hs_mailbox |= ahd->tqinfifonext & HOST_TQINPOS;
1028197883Sgibbs			ahd_outb(ahd, HS_MAILBOX, hs_mailbox);
1028297883Sgibbs		}
1028397883Sgibbs	}
1028497883Sgibbs}
1028597883Sgibbs
1028697883Sgibbsstatic int
1028797883Sgibbsahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd)
1028897883Sgibbs{
1028997883Sgibbs	struct	  ahd_tmode_tstate *tstate;
1029097883Sgibbs	struct	  ahd_tmode_lstate *lstate;
1029197883Sgibbs	struct	  ccb_accept_tio *atio;
1029297883Sgibbs	uint8_t *byte;
1029397883Sgibbs	int	  initiator;
1029497883Sgibbs	int	  target;
1029597883Sgibbs	int	  lun;
1029697883Sgibbs
1029797883Sgibbs	initiator = SCSIID_TARGET(ahd, cmd->scsiid);
1029897883Sgibbs	target = SCSIID_OUR_ID(cmd->scsiid);
1029997883Sgibbs	lun    = (cmd->identify & MSG_IDENTIFY_LUNMASK);
1030097883Sgibbs
1030197883Sgibbs	byte = cmd->bytes;
1030297883Sgibbs	tstate = ahd->enabled_targets[target];
1030397883Sgibbs	lstate = NULL;
1030497883Sgibbs	if (tstate != NULL)
1030597883Sgibbs		lstate = tstate->enabled_luns[lun];
1030697883Sgibbs
1030797883Sgibbs	/*
1030897883Sgibbs	 * Commands for disabled luns go to the black hole driver.
1030997883Sgibbs	 */
1031097883Sgibbs	if (lstate == NULL)
1031197883Sgibbs		lstate = ahd->black_hole;
1031297883Sgibbs
1031397883Sgibbs	atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios);
1031497883Sgibbs	if (atio == NULL) {
1031597883Sgibbs		ahd->flags |= AHD_TQINFIFO_BLOCKED;
1031697883Sgibbs		/*
1031797883Sgibbs		 * Wait for more ATIOs from the peripheral driver for this lun.
1031897883Sgibbs		 */
1031997883Sgibbs		return (1);
1032097883Sgibbs	} else
1032197883Sgibbs		ahd->flags &= ~AHD_TQINFIFO_BLOCKED;
1032297883Sgibbs#ifdef AHD_DEBUG
1032397883Sgibbs	if ((ahd_debug & AHD_SHOW_TQIN) != 0)
1032497883Sgibbs		printf("Incoming command from %d for %d:%d%s\n",
1032597883Sgibbs		       initiator, target, lun,
1032697883Sgibbs		       lstate == ahd->black_hole ? "(Black Holed)" : "");
1032797883Sgibbs#endif
1032897883Sgibbs	SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);
1032997883Sgibbs
1033097883Sgibbs	if (lstate == ahd->black_hole) {
1033197883Sgibbs		/* Fill in the wildcards */
1033297883Sgibbs		atio->ccb_h.target_id = target;
1033397883Sgibbs		atio->ccb_h.target_lun = lun;
1033497883Sgibbs	}
1033597883Sgibbs
1033697883Sgibbs	/*
1033797883Sgibbs	 * Package it up and send it off to
1033897883Sgibbs	 * whomever has this lun enabled.
1033997883Sgibbs	 */
1034097883Sgibbs	atio->sense_len = 0;
1034197883Sgibbs	atio->init_id = initiator;
1034297883Sgibbs	if (byte[0] != 0xFF) {
1034397883Sgibbs		/* Tag was included */
1034497883Sgibbs		atio->tag_action = *byte++;
1034597883Sgibbs		atio->tag_id = *byte++;
1034697883Sgibbs		atio->ccb_h.flags = CAM_TAG_ACTION_VALID;
1034797883Sgibbs	} else {
1034897883Sgibbs		atio->ccb_h.flags = 0;
1034997883Sgibbs	}
1035097883Sgibbs	byte++;
1035197883Sgibbs
1035297883Sgibbs	/* Okay.  Now determine the cdb size based on the command code */
1035397883Sgibbs	switch (*byte >> CMD_GROUP_CODE_SHIFT) {
1035497883Sgibbs	case 0:
1035597883Sgibbs		atio->cdb_len = 6;
1035697883Sgibbs		break;
1035797883Sgibbs	case 1:
1035897883Sgibbs	case 2:
1035997883Sgibbs		atio->cdb_len = 10;
1036097883Sgibbs		break;
1036197883Sgibbs	case 4:
1036297883Sgibbs		atio->cdb_len = 16;
1036397883Sgibbs		break;
1036497883Sgibbs	case 5:
1036597883Sgibbs		atio->cdb_len = 12;
1036697883Sgibbs		break;
1036797883Sgibbs	case 3:
1036897883Sgibbs	default:
1036997883Sgibbs		/* Only copy the opcode. */
1037097883Sgibbs		atio->cdb_len = 1;
1037197883Sgibbs		printf("Reserved or VU command code type encountered\n");
1037297883Sgibbs		break;
1037397883Sgibbs	}
1037497883Sgibbs
1037597883Sgibbs	memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len);
1037697883Sgibbs
1037797883Sgibbs	atio->ccb_h.status |= CAM_CDB_RECVD;
1037897883Sgibbs
1037997883Sgibbs	if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) {
1038097883Sgibbs		/*
1038197883Sgibbs		 * We weren't allowed to disconnect.
1038297883Sgibbs		 * We're hanging on the bus until a
1038397883Sgibbs		 * continue target I/O comes in response
1038497883Sgibbs		 * to this accept tio.
1038597883Sgibbs		 */
1038697883Sgibbs#ifdef AHD_DEBUG
1038797883Sgibbs		if ((ahd_debug & AHD_SHOW_TQIN) != 0)
1038897883Sgibbs			printf("Received Immediate Command %d:%d:%d - %p\n",
1038997883Sgibbs			       initiator, target, lun, ahd->pending_device);
1039097883Sgibbs#endif
1039197883Sgibbs		ahd->pending_device = lstate;
1039297883Sgibbs		ahd_freeze_ccb((union ccb *)atio);
1039397883Sgibbs		atio->ccb_h.flags |= CAM_DIS_DISCONNECT;
1039497883Sgibbs	}
1039597883Sgibbs	xpt_done((union ccb*)atio);
1039697883Sgibbs	return (0);
1039797883Sgibbs}
1039897883Sgibbs
1039997883Sgibbs#endif
10400