patch-2.4.5 linux/drivers/scsi/aic7xxx/aic7xxx.c

Next file: linux/drivers/scsi/aic7xxx/aic7xxx.h
Previous file: linux/drivers/scsi/aic7xxx/aic7770_linux.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.c linux/drivers/scsi/aic7xxx/aic7xxx.c
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7xxx.c#32 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.c#39 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.61 2000/11/13 03:35:43 gibbs Exp $
  */
@@ -58,9 +58,17 @@
 	"aic7892",
 	"aic7899"
 };
-const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names);
+static const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names);
 
-struct hard_error_entry hard_error[] = {
+/*
+ * Hardware error codes.
+ */
+struct ahc_hard_error_entry {
+        uint8_t errno;
+	char *errmesg;
+};
+
+static struct ahc_hard_error_entry ahc_hard_errors[] = {
 	{ ILLHADDR,	"Illegal Host Access" },
 	{ ILLSADDR,	"Illegal Sequencer Address referrenced" },
 	{ ILLOPCODE,	"Illegal Opcode in sequencer program" },
@@ -70,9 +78,9 @@
 	{ PCIERRSTAT,	"PCI Error detected" },
 	{ CIOPARERR,	"CIOBUS Parity Error" },
 };
-const u_int num_errors = NUM_ELEMENTS(hard_error);
+static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors);
 
-struct phase_table_entry phase_table[] =
+static struct ahc_phase_table_entry ahc_phase_table[] =
 {
 	{ P_DATAOUT,	MSG_NOOP,		"in Data-out phase"	},
 	{ P_DATAIN,	MSG_INITIATOR_DET_ERR,	"in Data-in phase"	},
@@ -90,14 +98,14 @@
  * In most cases we only wish to itterate over real phases, so
  * exclude the last element from the count.
  */
-const u_int num_phases = NUM_ELEMENTS(phase_table) - 1;
+static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1;
 
 /*
  * Valid SCSIRATE values.  (p. 3-17)
  * Provides a mapping of tranfer periods in ns to the proper value to
  * stick in the scsixfer reg.
  */
-struct ahc_syncrate ahc_syncrates[] =
+static struct ahc_syncrate ahc_syncrates[] =
 {
       /* ultra2    fast/ultra  period     rate */
 	{ 0x42,      0x000,      9,      "80.0" },
@@ -121,7 +129,7 @@
 #include "aic7xxx_seq.h"
 
 /**************************** Function Declarations ***************************/
-static struct tmode_tstate*
+static struct ahc_tmode_tstate*
 			ahc_alloc_tstate(struct ahc_softc *ahc,
 					 u_int scsi_id, char channel);
 #ifdef AHC_TARGET_MODE
@@ -134,12 +142,13 @@
 						u_int *period,
 						u_int *ppr_options,
 						role_t role);
-static void		ahc_update_pending_syncrates(struct ahc_softc *ahc);
+static void		ahc_update_pending_scbs(struct ahc_softc *ahc);
 static void		ahc_fetch_devinfo(struct ahc_softc *ahc,
 					  struct ahc_devinfo *devinfo);
 static void		ahc_scb_devinfo(struct ahc_softc *ahc,
 					struct ahc_devinfo *devinfo,
 					struct scb *scb);
+static void		ahc_assert_atn(struct ahc_softc *ahc);
 static void		ahc_setup_initiator_msgout(struct ahc_softc *ahc,
 						   struct ahc_devinfo *devinfo,
 						   struct scb *scb);
@@ -174,6 +183,11 @@
 					    struct ahc_devinfo *devinfo,
 					    cam_status status, char *message,
 					    int verbose_level);
+#if AHC_TARGET_MODE
+static void		ahc_setup_target_msgin(struct ahc_softc *ahc,
+					       struct ahc_devinfo *devinfo,
+					       struct scb *scb);
+#endif
 
 static bus_dmamap_callback_t	ahc_dmamap_cb; 
 static void			ahc_build_free_scb_list(struct ahc_softc *ahc);
@@ -192,7 +206,6 @@
 				       char channel, int lun, u_int tag,
 				       role_t role, uint32_t status);
 static void		ahc_reset_current_bus(struct ahc_softc *ahc);
-static void		ahc_calc_residual(struct scb *scb);
 #ifdef AHC_DUMP_SEQ
 static void		ahc_dumpseq(struct ahc_softc *ahc);
 #endif
@@ -204,7 +217,7 @@
 					   u_int instrptr, uint8_t *dconsts);
 #ifdef AHC_TARGET_MODE
 static void		ahc_queue_lstate_event(struct ahc_softc *ahc,
-					       struct tmode_lstate *lstate,
+					       struct ahc_tmode_lstate *lstate,
 					       u_int initiator_id,
 					       u_int event_type,
 					       u_int event_arg);
@@ -218,10 +231,10 @@
  * Restart the sequencer program from address zero
  */
 void
-restart_sequencer(struct ahc_softc *ahc)
+ahc_restart(struct ahc_softc *ahc)
 {
 
-	pause_sequencer(ahc);
+	ahc_pause(ahc);
 
 	ahc_outb(ahc, SCSISIGO, 0);		/* De-assert BSY */
 	ahc_outb(ahc, MSG_OUT, MSG_NOOP);	/* No message to send */
@@ -259,7 +272,7 @@
 	ahc_outb(ahc, SEQCTL, FASTMODE);
 	ahc_outb(ahc, SEQADDR0, 0);
 	ahc_outb(ahc, SEQADDR1, 0);
-	unpause_sequencer(ahc);
+	ahc_unpause(ahc);
 }
 
 /************************* Input/Output Queues ********************************/
@@ -300,10 +313,7 @@
 		 * Save off the residual
 		 * if there is one.
 		 */
-		if (ahc_check_residual(scb) != 0)
-			ahc_calc_residual(scb);
-		else
-			ahc_set_residual(scb, 0);
+		ahc_update_residual(scb);
 		ahc_done(ahc, scb);
 	}
 }
@@ -340,14 +350,14 @@
 	 * We upset the sequencer :-(
 	 * Lookup the error message
 	 */
-	int i, error, num_errors;
+	int i;
+	int error;
 
 	error = ahc_inb(ahc, ERROR);
-	num_errors =  sizeof(hard_error)/sizeof(hard_error[0]);
 	for (i = 0; error != 1 && i < num_errors; i++)
 		error >>= 1;
 	printf("%s: brkadrint, %s at seqaddr = 0x%x\n",
-	       ahc_name(ahc), hard_error[i].errmesg,
+	       ahc_name(ahc), ahc_hard_errors[i].errmesg,
 	       ahc_inb(ahc, SEQADDR0) |
 	       (ahc_inb(ahc, SEQADDR1) << 8));
 
@@ -436,6 +446,12 @@
 			break;
 		case SCSI_STATUS_CMD_TERMINATED:
 		case SCSI_STATUS_CHECK_COND:
+		{
+			struct ahc_dma_seg *sg;
+			struct scsi_sense *sc;
+			struct ahc_initiator_tinfo *targ_info;
+			struct ahc_tmode_tstate *tstate;
+			struct ahc_transinfo *tinfo;
 #ifdef AHC_DEBUG
 			if (ahc_debug & AHC_SHOWSENSE) {
 				ahc_print_path(ahc, scb);
@@ -444,99 +460,94 @@
 			}
 #endif
 
-			if (ahc_perform_autosense(scb)) {
-				struct ahc_dma_seg *sg;
-				struct scsi_sense *sc;
-				struct ahc_initiator_tinfo *targ_info;
-				struct tmode_tstate *tstate;
-				struct ahc_transinfo *tinfo;
+			if (ahc_perform_autosense(scb) == 0)
+				break;
 
-				targ_info =
-				    ahc_fetch_transinfo(ahc,
+			targ_info = ahc_fetch_transinfo(ahc,
 							devinfo.channel,
 							devinfo.our_scsiid,
 							devinfo.target,
 							&tstate);
-				tinfo = &targ_info->current;
-				sg = scb->sg_list;
-				sc = (struct scsi_sense *)
-				     (&hscb->shared_data.cdb); 
-				/*
-				 * Save off the residual if there is one.
-				 */
-				if (ahc_check_residual(scb))
-					ahc_calc_residual(scb);
-				else
-					ahc_set_residual(scb, 0);
+			tinfo = &targ_info->curr;
+			sg = scb->sg_list;
+			sc = (struct scsi_sense *)(&hscb->shared_data.cdb); 
+			/*
+			 * Save off the residual if there is one.
+			 */
+			ahc_update_residual(scb);
 #ifdef AHC_DEBUG
-				if (ahc_debug & AHC_SHOWSENSE) {
-					ahc_print_path(ahc, scb);
-					printf("Sending Sense\n");
-				}
+			if (ahc_debug & AHC_SHOWSENSE) {
+				ahc_print_path(ahc, scb);
+				printf("Sending Sense\n");
+			}
 #endif
-				sg->addr = ahc_get_sense_bufaddr(ahc, scb);
-				sg->len = ahc_get_sense_bufsize(ahc, scb);
-				sg->len |= AHC_DMA_LAST_SEG;
-
-				/* Fixup byte order */
-				sg->addr = ahc_htole32(sg->addr);
-				sg->len = ahc_htole32(sg->len);
-
-				sc->opcode = REQUEST_SENSE;
-				sc->byte2 = 0;
-				if (tinfo->protocol_version <= SCSI_REV_2
-				 && SCB_GET_LUN(scb) < 8)
-					sc->byte2 = SCB_GET_LUN(scb) << 5;
-				sc->unused[0] = 0;
-				sc->unused[1] = 0;
-				sc->length = sg->len;
-				sc->control = 0;
+			sg->addr = ahc_get_sense_bufaddr(ahc, scb);
+			sg->len = ahc_get_sense_bufsize(ahc, scb);
+			sg->len |= AHC_DMA_LAST_SEG;
+
+			/* Fixup byte order */
+			sg->addr = ahc_htole32(sg->addr);
+			sg->len = ahc_htole32(sg->len);
+
+			sc->opcode = REQUEST_SENSE;
+			sc->byte2 = 0;
+			if (tinfo->protocol_version <= SCSI_REV_2
+			 && SCB_GET_LUN(scb) < 8)
+				sc->byte2 = SCB_GET_LUN(scb) << 5;
+			sc->unused[0] = 0;
+			sc->unused[1] = 0;
+			sc->length = sg->len;
+			sc->control = 0;
 
-				/*
-				 * XXX Still true???
-				 * Would be nice to preserve DISCENB here,
-				 * but due to the way we manage busy targets,
-				 * we can't.
-				 */
-				hscb->control = 0;
+			/*
+			 * We can't allow the target to disconnect.
+			 * This will be an untagged transaction and
+			 * having the target disconnect will make this
+			 * transaction indestinguishable from outstanding
+			 * tagged transactions.
+			 */
+			hscb->control = 0;
 
-				/*
-				 * This request sense could be because the
-				 * the device lost power or in some other
-				 * way has lost our transfer negotiations.
-				 * Renegotiate if appropriate.  Unit attention
-				 * errors will be reported before any data
-				 * phases occur.
-				 */
-				if (ahc_get_residual(scb) 
-				 == ahc_get_transfer_length(scb)) {
-					ahc_update_target_msg_request(ahc,
-							      &devinfo,
-							      targ_info,
-							      /*force*/TRUE,
-							      /*paused*/TRUE);
-				}
-				hscb->cdb_len = sizeof(*sc);
-				hscb->dataptr = sg->addr; 
-				hscb->datacnt = sg->len;
-				hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
-				hscb->sgptr = ahc_htole32(hscb->sgptr);
-				scb->sg_count = 1;
-				scb->flags |= SCB_SENSE;
-				ahc_qinfifo_requeue_tail(ahc, scb);
-				ahc_outb(ahc, RETURN_1, SEND_SENSE);
+			/*
+			 * This request sense could be because the
+			 * the device lost power or in some other
+			 * way has lost our transfer negotiations.
+			 * Renegotiate if appropriate.  Unit attention
+			 * errors will be reported before any data
+			 * phases occur.
+			 */
+			if (ahc_get_residual(scb) 
+			 == ahc_get_transfer_length(scb)) {
+				ahc_update_neg_request(ahc, &devinfo,
+						       tstate, targ_info,
+						       /*force*/TRUE);
+			}
+			if (tstate->auto_negotiate & devinfo.target_mask) {
+				hscb->control |= MK_MESSAGE;
+				scb->flags &= ~SCB_NEGOTIATE;
+				scb->flags |= SCB_AUTO_NEGOTIATE;
+			}
+			hscb->cdb_len = sizeof(*sc);
+			hscb->dataptr = sg->addr; 
+			hscb->datacnt = sg->len;
+			hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
+			hscb->sgptr = ahc_htole32(hscb->sgptr);
+			scb->sg_count = 1;
+			scb->flags |= SCB_SENSE;
+			ahc_qinfifo_requeue_tail(ahc, scb);
+			ahc_outb(ahc, RETURN_1, SEND_SENSE);
 #ifdef __FreeBSD__
-				/*
-				 * Ensure we have enough time to actually
-				 * retrieve the sense.
-				 */
-				untimeout(ahc_timeout, (caddr_t)scb,
-					  scb->io_ctx->ccb_h.timeout_ch);
-				scb->io_ctx->ccb_h.timeout_ch =
-				    timeout(ahc_timeout, (caddr_t)scb, 5 * hz);
+			/*
+			 * Ensure we have enough time to actually
+			 * retrieve the sense.
+			 */
+			untimeout(ahc_timeout, (caddr_t)scb,
+				  scb->io_ctx->ccb_h.timeout_ch);
+			scb->io_ctx->ccb_h.timeout_ch =
+			    timeout(ahc_timeout, (caddr_t)scb, 5 * hz);
 #endif
-			}
 			break;
+		}
 		default:
 			break;
 		}
@@ -577,7 +588,7 @@
 		ahc->msgout_index = 0;
 		ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
 		ahc_outb(ahc, MSG_OUT, HOST_MSG);
-		ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, LASTPHASE) | ATNO);
+		ahc_assert_atn(ahc);
 		break;
 	}
 	case SEND_REJECT: 
@@ -633,7 +644,7 @@
 		       "Lastphase = 0x%x, Curphase = 0x%x\n",
 		       ahc_name(ahc), devinfo.channel, devinfo.target,
 		       lastphase, ahc_inb(ahc, SCSISIGI));
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 		return;
 	}
 	case HOST_MSG_LOOP:
@@ -650,6 +661,8 @@
 		 * loop.
 		 */
 		if (ahc->msg_type == MSG_TYPE_NONE) {
+			struct scb *scb;
+			u_int scb_index;
 			u_int bus_phase;
 
 			bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
@@ -663,17 +676,13 @@
 				 * we got here.  Just punt the message.
 				 */
 				ahc_clear_intstat(ahc);
-				restart_sequencer(ahc);
+				ahc_restart(ahc);
 				return;
 			}
 
+			scb_index = ahc_inb(ahc, SCB_TAG);
+			scb = ahc_lookup_scb(ahc, scb_index);
 			if (devinfo.role == ROLE_INITIATOR) {
-				struct scb *scb;
-				u_int scb_index;
-
-				scb_index = ahc_inb(ahc, SCB_TAG);
-				scb = ahc_lookup_scb(ahc, scb_index);
-
 				if (scb == NULL)
 					panic("HOST_MSG_LOOP with "
 					      "invalid SCB %x\n", scb_index);
@@ -695,7 +704,9 @@
 				}
 #if AHC_TARGET_MODE
 				else 
-					ahc_setup_target_msgin(ahc, &devinfo);
+					ahc_setup_target_msgin(ahc,
+							       &devinfo,
+							       scb);
 #endif
 			}
 		}
@@ -718,17 +729,20 @@
 		 */
 		if ((intstat & SCSIINT) == 0
 		 && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) {
-			u_int curphase;
 
-			/*
-			 * The hardware will only let you ack bytes
-			 * if the expected phase in SCSISIGO matches
-			 * the current phase.  Make sure this is
-			 * currently the case.
-			 */
-			curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
-			ahc_outb(ahc, LASTPHASE, curphase);
-			ahc_outb(ahc, SCSISIGO, curphase);
+			if ((ahc->features & AHC_DT) == 0) {
+				u_int curphase;
+
+				/*
+				 * The hardware will only let you ack bytes
+				 * if the expected phase in SCSISIGO matches
+				 * the current phase.  Make sure this is
+				 * currently the case.
+				 */
+				curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
+				ahc_outb(ahc, LASTPHASE, curphase);
+				ahc_outb(ahc, SCSISIGO, curphase);
+			}
 			ahc_inb(ahc, SCSIDATL);
 		}
 		break;
@@ -749,13 +763,13 @@
 
 		scb = ahc_lookup_scb(ahc, scbindex);
 		for (i = 0; i < num_phases; i++) {
-			if (lastphase == phase_table[i].phase)
+			if (lastphase == ahc_phase_table[i].phase)
 				break;
 		}
 		ahc_print_path(ahc, scb);
 		printf("data overrun detected %s."
 		       "  Tag == 0x%x.\n",
-		       phase_table[i].phasemsg,
+		       ahc_phase_table[i].phasemsg,
   		       scb->hscb->tag);
 		ahc_print_path(ahc, scb);
 		printf("%s seen Data Phase.  Length = %ld.  NumSGs = %d.\n",
@@ -858,7 +872,7 @@
 	 *  a SEQINT, so we should restart it when
 	 *  we're done.
 	 */
-	unpause_sequencer(ahc);
+	ahc_unpause(ahc);
 }
 
 void
@@ -897,7 +911,7 @@
 		if (status == 0) {
 			printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc));
 			ahc_outb(ahc, CLRINT, CLRSCSIINT);
-			unpause_sequencer(ahc);
+			ahc_unpause(ahc);
 			return;
 		}
 	}
@@ -975,10 +989,10 @@
 			errorphase = lastphase;
 
 		for (i = 0; i < num_phases; i++) {
-			if (errorphase == phase_table[i].phase)
+			if (errorphase == ahc_phase_table[i].phase)
 				break;
 		}
-		mesg_out = phase_table[i].mesg_out;
+		mesg_out = ahc_phase_table[i].mesg_out;
 		if (scb != NULL)
 			ahc_print_path(ahc, scb);
 		else
@@ -987,7 +1001,7 @@
 		scsirate = ahc_inb(ahc, SCSIRATE);
 		printf("parity error detected %s. "
 		       "SEQADDR(0x%x) SCSIRATE(0x%x)\n",
-		       phase_table[i].phasemsg,
+		       ahc_phase_table[i].phasemsg,
 		       ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8),
 		       scsirate);
 
@@ -1018,7 +1032,45 @@
 				ahc_outb(ahc, MSG_OUT, mesg_out);
 		}
 		ahc_outb(ahc, CLRINT, CLRSCSIINT);
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
+	} else if ((status & SELTO) != 0) {
+		u_int scbptr;
+
+		/* Stop the selection */
+		ahc_outb(ahc, SCSISEQ, 0);
+
+		/* No more pending messages */
+		ahc_clear_msg_state(ahc);
+
+		/* Clear interrupt state */
+		ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
+		ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
+
+		/*
+		 * Although the driver does not care about the
+		 * 'Selection in Progress' status bit, the busy
+		 * LED does.  SELINGO is only cleared by a sucessful
+		 * selection, so we must manually clear it to insure
+		 * the LED turns off just incase no future successful
+		 * selections occur (e.g. no devices on the bus).
+		 */
+		ahc_outb(ahc, CLRSINT0, CLRSELINGO);
+
+		scbptr = ahc_inb(ahc, WAITING_SCBH);
+		ahc_outb(ahc, SCBPTR, scbptr);
+		scb_index = ahc_inb(ahc, SCB_TAG);
+
+		scb = ahc_lookup_scb(ahc, scb_index);
+		if (scb == NULL) {
+			printf("%s: ahc_intr - referenced scb not "
+			       "valid during SELTO scb(%d, %d)\n",
+			       ahc_name(ahc), scbptr, scb_index);
+		} else {
+			ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
+			ahc_freeze_devq(ahc, scb);
+		}
+		ahc_outb(ahc, CLRINT, CLRSCSIINT);
+		ahc_restart(ahc);
 	} else if ((status & BUSFREE) != 0
 		&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
 		u_int lastphase;
@@ -1113,7 +1165,7 @@
 			} else if (ahc_sent_msg(ahc, AHCMSG_EXT,
 						MSG_EXT_PPR, FALSE)) {
 				struct ahc_initiator_tinfo *tinfo;
-				struct tmode_tstate *tstate;
+				struct ahc_tmode_tstate *tstate;
 
 				/*
 				 * PPR Rejected.  Try non-ppr negotiation
@@ -1124,7 +1176,7 @@
 							    devinfo.our_scsiid,
 							    devinfo.target,
 							    &tstate);
-				tinfo->current.transport_version = 2;
+				tinfo->curr.transport_version = 2;
 				tinfo->goal.transport_version = 2;
 				tinfo->goal.ppr_options = 0;
 				ahc_qinfifo_requeue_tail(ahc, scb);
@@ -1174,54 +1226,18 @@
 				printf("%s: ", ahc_name(ahc));
 			}
 			for (i = 0; i < num_phases; i++) {
-				if (lastphase == phase_table[i].phase)
+				if (lastphase == ahc_phase_table[i].phase)
 					break;
 			}
 			printf("Unexpected busfree %s\n"
 			       "SEQADDR == 0x%x\n",
-			       phase_table[i].phasemsg, ahc_inb(ahc, SEQADDR0)
+			       ahc_phase_table[i].phasemsg,
+			       ahc_inb(ahc, SEQADDR0)
 				| (ahc_inb(ahc, SEQADDR1) << 8));
 		}
 		ahc_clear_msg_state(ahc);
 		ahc_outb(ahc, CLRINT, CLRSCSIINT);
-		restart_sequencer(ahc);
-	} else if ((status & SELTO) != 0) {
-		u_int scbptr;
-
-		/* Stop the selection */
-		ahc_outb(ahc, SCSISEQ, 0);
-
-		/* No more pending messages */
-		ahc_clear_msg_state(ahc);
-
-		/* Clear interrupt state */
-		ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
-
-		/*
-		 * Although the driver does not care about the
-		 * 'Selection in Progress' status bit, the busy
-		 * LED does.  SELINGO is only cleared by a sucessful
-		 * selection, so we must manually clear it to insure
-		 * the LED turns off just incase no future successful
-		 * selections occur (e.g. no devices on the bus).
-		 */
-		ahc_outb(ahc, CLRSINT0, CLRSELINGO);
-
-		scbptr = ahc_inb(ahc, WAITING_SCBH);
-		ahc_outb(ahc, SCBPTR, scbptr);
-		scb_index = ahc_inb(ahc, SCB_TAG);
-
-		scb = ahc_lookup_scb(ahc, scb_index);
-		if (scb == NULL) {
-			printf("%s: ahc_intr - referenced scb not "
-			       "valid during SELTO scb(%d, %d)\n",
-			       ahc_name(ahc), scbptr, scb_index);
-		} else {
-			ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
-			ahc_freeze_devq(ahc, scb);
-		}
-		ahc_outb(ahc, CLRINT, CLRSCSIINT);
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 	} else {
 		printf("%s: Missing case in ahc_handle_scsiint. status = %x\n",
 		       ahc_name(ahc), status);
@@ -1290,7 +1306,7 @@
 		ahc_outb(ahc, HCNTRL, ahc->unpause);
 		do {
 			ahc_delay(200);
-		} while (!sequencer_paused(ahc));
+		} while (!ahc_is_paused(ahc));
 	}
 	if (stepping) {
 		ahc_outb(ahc, SIMODE0, simode0);
@@ -1363,11 +1379,11 @@
  * Allocate per target mode instance (ID we respond to as a target)
  * transfer negotiation data structures.
  */
-static struct tmode_tstate *
+static struct ahc_tmode_tstate *
 ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
 {
-	struct tmode_tstate *master_tstate;
-	struct tmode_tstate *tstate;
+	struct ahc_tmode_tstate *master_tstate;
+	struct ahc_tmode_tstate *tstate;
 	int i;
 
 	master_tstate = ahc->enabled_targets[ahc->our_id];
@@ -1394,8 +1410,8 @@
 		memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
 		tstate->ultraenb = 0;
 		for (i = 0; i < 16; i++) {
-			memset(&tstate->transinfo[i].current, 0,
-			      sizeof(tstate->transinfo[i].current));
+			memset(&tstate->transinfo[i].curr, 0,
+			      sizeof(tstate->transinfo[i].curr));
 			memset(&tstate->transinfo[i].goal, 0,
 			      sizeof(tstate->transinfo[i].goal));
 		}
@@ -1413,11 +1429,13 @@
 static void
 ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
 {
-	struct tmode_tstate *tstate;
+	struct ahc_tmode_tstate *tstate;
 
-	/* Don't clean up the entry for our initiator role */
-	if ((ahc->flags & AHC_INITIATORROLE) != 0
-	 && ((channel == 'B' && scsi_id == ahc->our_id_b)
+	/*
+	 * Don't clean up our "master" tstate.
+	 * It has our default user settings.
+	 */
+	if (((channel == 'B' && scsi_id == ahc->our_id_b)
 	  || (channel == 'A' && scsi_id == ahc->our_id))
 	 && force == FALSE)
 		return;
@@ -1496,6 +1514,11 @@
 
 	if ((ahc->features & AHC_DT) == 0)
 		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
+
+	/* Skip all DT only entries if DT is not available */
+	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
+	 && maxsync < AHC_SYNCRATE_ULTRA2)
+		maxsync = AHC_SYNCRATE_ULTRA2;
 	
 	for (syncrate = &ahc_syncrates[maxsync];
 	     syncrate->rate != NULL;
@@ -1509,11 +1532,6 @@
 		 && (syncrate->sxfr_u2 == 0))
 			break;
 
-		/* Skip any DT entries if DT is not available */
-		if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
-		 && (syncrate->sxfr_u2 & DT_SXFR) != 0)
-			continue;
-
 		if (*period <= syncrate->period) {
 			/*
 			 * When responding to a target that requests
@@ -1647,44 +1665,31 @@
  * means the next time we send the initial identify messages for
  * a new transaction.
  */
-void
-ahc_update_target_msg_request(struct ahc_softc *ahc,
-			      struct ahc_devinfo *devinfo,
-			      struct ahc_initiator_tinfo *tinfo,
-			      int force, int paused)
-{
-	u_int targ_msg_req_orig;
-
-	targ_msg_req_orig = ahc->targ_msg_req;
-	if (tinfo->current.period != tinfo->goal.period
-	 || tinfo->current.width != tinfo->goal.width
-	 || tinfo->current.offset != tinfo->goal.offset
-	 || tinfo->current.ppr_options != tinfo->goal.ppr_options
+int
+ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+		       struct ahc_tmode_tstate *tstate,
+		       struct ahc_initiator_tinfo *tinfo, int force)
+{
+	u_int auto_negotiate_orig;
+
+	auto_negotiate_orig = tstate->auto_negotiate;
+	if (tinfo->curr.period != tinfo->goal.period
+	 || tinfo->curr.width != tinfo->goal.width
+	 || tinfo->curr.offset != tinfo->goal.offset
+	 || tinfo->curr.ppr_options != tinfo->goal.ppr_options
 	 || (force
 	  && (tinfo->goal.period != 0
 	   || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
 	   || tinfo->goal.ppr_options != 0)))
-		ahc->targ_msg_req |= devinfo->target_mask;
+		tstate->auto_negotiate |= devinfo->target_mask;
 	else
-		ahc->targ_msg_req &= ~devinfo->target_mask;
+		tstate->auto_negotiate &= ~devinfo->target_mask;
 
-	if (ahc->targ_msg_req != targ_msg_req_orig) {
-		/* Update the message request bit for this target */
-		if (!paused)
-			pause_sequencer(ahc);
-
-		ahc_outb(ahc, TARGET_MSG_REQUEST,
-			 ahc->targ_msg_req & 0xFF);
-		ahc_outb(ahc, TARGET_MSG_REQUEST + 1,
-			 (ahc->targ_msg_req >> 8) & 0xFF);
-
-		if (!paused)
-			unpause_sequencer(ahc);
-	}
+	return (auto_negotiate_orig != tstate->auto_negotiate);
 }
 
 /*
- * Update the user/goal/current tables of synchronous negotiation
+ * Update the user/goal/curr tables of synchronous negotiation
  * parameters as well as, in the case of a current or active update,
  * any data structures on the host controller.  In the case of an
  * active update, the specified target is currently talking to us on
@@ -1697,11 +1702,15 @@
 		 u_int offset, u_int ppr_options, u_int type, int paused)
 {
 	struct	ahc_initiator_tinfo *tinfo;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	u_int	old_period;
 	u_int	old_offset;
 	u_int	old_ppr;
-	int	active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	int	active;
+	int	update_needed;
+
+	active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	update_needed = 0;
 
 	if (syncrate == NULL) {
 		period = 0;
@@ -1723,9 +1732,9 @@
 		tinfo->goal.ppr_options = ppr_options;
 	}
 
-	old_period = tinfo->current.period;
-	old_offset = tinfo->current.offset;
-	old_ppr	   = tinfo->current.ppr_options;
+	old_period = tinfo->curr.period;
+	old_offset = tinfo->curr.offset;
+	old_ppr	   = tinfo->curr.ppr_options;
 
 	if ((type & AHC_TRANS_CUR) != 0
 	 && (old_period != period
@@ -1733,6 +1742,7 @@
 	  || old_ppr != ppr_options)) {
 		u_int	scsirate;
 
+		update_needed++;
 		scsirate = tinfo->scsirate;
 		if ((ahc->features & AHC_ULTRA2) != 0) {
 
@@ -1777,15 +1787,12 @@
 		}
 
 		tinfo->scsirate = scsirate;
-		tinfo->current.period = period;
-		tinfo->current.offset = offset;
-		tinfo->current.ppr_options = ppr_options;
-
-		/* Update the syncrates in any pending scbs */
-		ahc_update_pending_syncrates(ahc);
+		tinfo->curr.period = period;
+		tinfo->curr.offset = offset;
+		tinfo->curr.ppr_options = ppr_options;
 
 		ahc_send_async(ahc, devinfo->channel, devinfo->target,
-			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
+			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
 		if (bootverbose) {
 			if (offset != 0) {
 				printf("%s: target %d synchronous at %sMHz%s, "
@@ -1801,13 +1808,15 @@
 		}
 	}
 
-	ahc_update_target_msg_request(ahc, devinfo, tinfo,
-				      /*force*/FALSE,
-				      paused);
+	update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
+						tinfo, /*force*/FALSE);
+
+	if (update_needed)
+		ahc_update_pending_scbs(ahc);
 }
 
 /*
- * Update the user/goal/current tables of wide negotiation
+ * Update the user/goal/curr tables of wide negotiation
  * parameters as well as, in the case of a current or active update,
  * any data structures on the host controller.  In the case of an
  * active update, the specified target is currently talking to us on
@@ -1818,11 +1827,14 @@
 ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
 	      u_int width, u_int type, int paused)
 {
-	struct ahc_initiator_tinfo *tinfo;
-	struct tmode_tstate *tstate;
-	u_int  oldwidth;
-	int    active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	struct	ahc_initiator_tinfo *tinfo;
+	struct	ahc_tmode_tstate *tstate;
+	u_int	oldwidth;
+	int	active;
+	int	update_needed;
 
+	active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	update_needed = 0;
 	tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
 				    devinfo->target, &tstate);
 
@@ -1832,10 +1844,11 @@
 	if ((type & AHC_TRANS_GOAL) != 0)
 		tinfo->goal.width = width;
 
-	oldwidth = tinfo->current.width;
+	oldwidth = tinfo->curr.width;
 	if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) {
 		u_int	scsirate;
 
+		update_needed++;
 		scsirate =  tinfo->scsirate;
 		scsirate &= ~WIDEXFER;
 		if (width == MSG_EXT_WDTR_BUS_16_BIT)
@@ -1846,10 +1859,10 @@
 		if (active)
 			ahc_outb(ahc, SCSIRATE, scsirate);
 
-		tinfo->current.width = width;
+		tinfo->curr.width = width;
 
 		ahc_send_async(ahc, devinfo->channel, devinfo->target,
-			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
+			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
 		if (bootverbose) {
 			printf("%s: target %d using %dbit transfers\n",
 			       ahc_name(ahc), devinfo->target,
@@ -1857,35 +1870,22 @@
 		}
 	}
 
-	ahc_update_target_msg_request(ahc, devinfo, tinfo,
-				      /*force*/FALSE, paused);
+	update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
+						tinfo, /*force*/FALSE);
+	if (update_needed)
+		ahc_update_pending_scbs(ahc);
 }
 
 /*
  * Update the current state of tagged queuing for a given target.
  */
 void
-ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable)
+ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+	     ahc_queue_alg alg)
 {
-	struct ahc_initiator_tinfo *tinfo;
-	struct tmode_tstate *tstate;
-	uint16_t orig_tagenable;
-
-	tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
-				    devinfo->target, &tstate);
-
-	orig_tagenable = tstate->tagenable;
-	if (enable)
-		tstate->tagenable |= devinfo->target_mask;
-	else
-		tstate->tagenable &= ~devinfo->target_mask;
-
-	if (orig_tagenable != tstate->tagenable) {
-		ahc_platform_set_tags(ahc, devinfo, enable);
-		ahc_send_async(ahc, devinfo->channel, devinfo->target,
-			       devinfo->lun, AC_TRANSFER_NEG);
-	}
-
+ 	ahc_platform_set_tags(ahc, devinfo, alg);
+ 	ahc_send_async(ahc, devinfo->channel, devinfo->target,
+ 		       devinfo->lun, AC_TRANSFER_NEG, &alg);
 }
 
 /*
@@ -1894,11 +1894,12 @@
  * be set correctly during future (re)selections.
  */
 static void
-ahc_update_pending_syncrates(struct ahc_softc *ahc)
+ahc_update_pending_scbs(struct ahc_softc *ahc)
 {
 	struct	scb *pending_scb;
 	int	pending_scb_count;
 	int	i;
+	int	paused;
 	u_int	saved_scbptr;
 
 	/*
@@ -1910,7 +1911,7 @@
 		struct ahc_devinfo devinfo;
 		struct hardware_scb *pending_hscb;
 		struct ahc_initiator_tinfo *tinfo;
-		struct tmode_tstate *tstate;
+		struct ahc_tmode_tstate *tstate;
 		
 		ahc_scb_devinfo(ahc, &devinfo, pending_scb);
 		tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
@@ -1921,13 +1922,25 @@
 		if ((tstate->ultraenb & devinfo.target_mask) != 0)
 			pending_hscb->control |= ULTRAENB;
 		pending_hscb->scsirate = tinfo->scsirate;
-		pending_hscb->scsioffset = tinfo->current.offset;
+		pending_hscb->scsioffset = tinfo->curr.offset;
+		if ((tstate->auto_negotiate & devinfo.target_mask) == 0
+		 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
+			pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
+			pending_hscb->control &= ~MK_MESSAGE;
+		}
 		pending_scb_count++;
 	}
 
 	if (pending_scb_count == 0)
 		return;
 
+	if (ahc_is_paused(ahc)) {
+		paused = 1;
+	} else {
+		paused = 0;
+		ahc_pause(ahc);
+	}
+
 	saved_scbptr = ahc_inb(ahc, SCBPTR);
 	/* Ensure that the hscbs down on the card match the new information */
 	for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
@@ -1943,14 +1956,16 @@
 
 		pending_hscb = pending_scb->hscb;
 		control = ahc_inb(ahc, SCB_CONTROL);
-		control &= ~ULTRAENB;
-		if ((pending_hscb->control & ULTRAENB) != 0)
-			control |= ULTRAENB;
+		control &= ~(ULTRAENB|MK_MESSAGE);
+		control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE);
 		ahc_outb(ahc, SCB_CONTROL, control);
 		ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate);
 		ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset);
 	}
 	ahc_outb(ahc, SCBPTR, saved_scbptr);
+
+	if (paused == 0)
+		ahc_unpause(ahc);
 }
 
 /**************************** Pathing Information *****************************/
@@ -1985,6 +2000,24 @@
 			    role);
 }
 
+struct ahc_phase_table_entry*
+ahc_lookup_phase_entry(int phase)
+{
+	struct ahc_phase_table_entry *entry;
+	struct ahc_phase_table_entry *last_entry;
+
+	/*
+	 * num_phases doesn't include the default entry which
+	 * will be returned if the phase doesn't match.
+	 */
+	last_entry = &ahc_phase_table[num_phases];
+	for (entry = ahc_phase_table; entry < last_entry; entry++) {
+		if (phase == entry->phase)
+			break;
+	}
+	return (entry);
+}
+
 void
 ahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target,
 		    u_int lun, char channel, role_t role)
@@ -2017,6 +2050,17 @@
 
 
 /************************ Message Phase Processing ****************************/
+static void
+ahc_assert_atn(struct ahc_softc *ahc)
+{
+	u_int scsisigo;
+
+	scsisigo = ATNO;
+	if ((ahc->features & AHC_DT) == 0)
+		scsisigo |= ahc_inb(ahc, SCSISIGI);
+	ahc_outb(ahc, SCSISIGO, scsisigo);
+}
+
 /*
  * When an initiator transaction with the MK_MESSAGE flag either reconnects
  * or enters the initial message out phase, we are interrupted.  Fill our
@@ -2083,8 +2127,7 @@
 		 * away.
 		 */
 		ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
-	} else if ((ahc->targ_msg_req & devinfo->target_mask) != 0
-		|| (scb->flags & SCB_NEGOTIATE) != 0) {
+	} else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
 		ahc_build_transfer_msg(ahc, devinfo);
 	} else {
 		printf("ahc_intr: AWAITING_MSG for an SCB that "
@@ -2101,6 +2144,7 @@
 	 * asked to send this message again.
 	 */
 	ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE);
+	scb->hscb->control &= ~MK_MESSAGE;
 	ahc->msgout_index = 0;
 	ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
 }
@@ -2118,7 +2162,7 @@
 	 * we want to renegotiate due to a check condition.
 	 */
 	struct	ahc_initiator_tinfo *tinfo;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	struct	ahc_syncrate *rate;
 	int	dowide;
 	int	dosync;
@@ -2130,9 +2174,19 @@
 
 	tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
 				    devinfo->target, &tstate);
-	dowide = tinfo->current.width != tinfo->goal.width;
-	dosync = tinfo->current.period != tinfo->goal.period;
-	doppr = tinfo->current.ppr_options != tinfo->goal.ppr_options;
+	/*
+	 * Filter our period based on the current connection.
+	 * If we can't perform DT transfers on this segment (not in LVD
+	 * mode for instance), then our decision to issue a PPR message
+	 * may change.
+	 */
+	period = tinfo->goal.period;
+	ppr_options = tinfo->goal.ppr_options;
+	rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
+				       &ppr_options, devinfo->role);
+	dowide = tinfo->curr.width != tinfo->goal.width;
+	dosync = tinfo->curr.period != period;
+	doppr = tinfo->curr.ppr_options != ppr_options;
 
 	if (!dowide && !dosync && !doppr) {
 		dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
@@ -2145,7 +2199,7 @@
 		      "but no negotiation needed\n");	
 	}
 
-	use_ppr = (tinfo->current.transport_version >= 3) || doppr;
+	use_ppr = (tinfo->curr.transport_version >= 3) || doppr;
 	/* Target initiated PPR is not allowed in the SCSI spec */
 	if (devinfo->role == ROLE_TARGET)
 		use_ppr = 0;
@@ -2160,16 +2214,10 @@
 	 */
 	if (use_ppr || (dosync && !dowide)) {
 
-		period = tinfo->goal.period;
-		ppr_options = tinfo->goal.ppr_options;
-		if (use_ppr == 0)
-			ppr_options = 0;
-		rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
-					       &ppr_options, devinfo->role);
 		offset = tinfo->goal.offset;
 		ahc_validate_offset(ahc, tinfo, rate, &offset,
 				    use_ppr ? tinfo->goal.width
-					    : tinfo->current.width,
+					    : tinfo->curr.width,
 				    devinfo->role);
 		if (use_ppr) {
 			ahc_construct_ppr(ahc, devinfo, period, offset,
@@ -2258,7 +2306,7 @@
 	ahc->msgout_len = 0;
 	ahc->msgin_index = 0;
 	ahc->msg_type = MSG_TYPE_NONE;
-	if ((ahc_inb(ahc, SCSISIGI) & ATNI) == 0) {
+	if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0) {
 		/*
 		 * The target didn't care to respond to our
 		 * message request, so clear ATN.
@@ -2327,7 +2375,7 @@
 			 * 0, and try again.
 			 */
 			ahc->msgout_index = 0;
-			ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
+			ahc_assert_atn(ahc);
 		}
 
 		lastbyte = ahc->msgout_index == (ahc->msgout_len - 1);
@@ -2382,8 +2430,7 @@
 			 * message out phase.
 			 */
 			if (ahc->msgout_len != 0)
-				ahc_outb(ahc, SCSISIGO,
-					 ahc_inb(ahc, SCSISIGO) | ATNO);
+				ahc_assert_atn(ahc);
 		} else 
 			ahc->msgin_index++;
 
@@ -2548,7 +2595,7 @@
 					found = TRUE;
 			}
 			index = end_index;
-		} else if (ahc->msgout_buf[index] >= MSG_SIMPLE_Q_TAG
+		} else if (ahc->msgout_buf[index] >= MSG_SIMPLE_TASK
 			&& ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
 
 			/* Skip tag type and tag id or residue param*/
@@ -2575,7 +2622,7 @@
 ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
 {
 	struct	ahc_initiator_tinfo *tinfo;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	int	reject;
 	int	done;
 	int	response;
@@ -2674,7 +2721,8 @@
 				/*
 				 * Send our own SDTR in reply
 				 */
-				if (bootverbose) {
+				if (bootverbose
+				 && devinfo->role == ROLE_INITIATOR) {
 					printf("(%s:%c:%d:%d): Target "
 					       "Initiated SDTR\n",
 					       ahc_name(ahc), devinfo->channel,
@@ -2744,7 +2792,8 @@
 				/*
 				 * Send our own WDTR in reply
 				 */
-				if (bootverbose) {
+				if (bootverbose
+				 && devinfo->role == ROLE_INITIATOR) {
 					printf("(%s:%c:%d:%d): Target "
 					       "Initiated WDTR\n",
 					       ahc_name(ahc), devinfo->channel,
@@ -2879,7 +2928,7 @@
 				       "offset %x, options %x\n",
 				       ahc_name(ahc), devinfo->channel,
 				       devinfo->target, devinfo->lun,
-				       ahc->msgin_buf[3], saved_width,
+				       saved_width, ahc->msgin_buf[3],
 				       saved_offset, saved_ppr_options,
 				       bus_width, period, offset, ppr_options);
 			}
@@ -2906,7 +2955,7 @@
 				    CAM_BDR_SENT,
 				    "Bus Device Reset Received",
 				    /*verbose_level*/0);
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 		done = MSGLOOP_TERMINATED;
 		break;
 	case MSG_ABORT_TAG:
@@ -2927,7 +2976,7 @@
 
 		tstate = ahc->enabled_targets[devinfo->our_scsiid];
 		if (tstate != NULL) {
-			struct tmode_lstate* lstate;
+			struct ahc_tmode_lstate* lstate;
 
 			lstate = tstate->enabled_luns[devinfo->lun];
 			if (lstate != NULL) {
@@ -2979,7 +3028,7 @@
 	 */
 	struct scb *scb;
 	struct ahc_initiator_tinfo *tinfo;
-	struct tmode_tstate *tstate;
+	struct ahc_tmode_tstate *tstate;
 	u_int scb_index;
 	u_int last_msg;
 	int   response = 0;
@@ -3004,7 +3053,7 @@
 			       devinfo->target, devinfo->lun);
 		}
 		tinfo->goal.ppr_options = 0;
-		tinfo->current.transport_version = 2;
+		tinfo->curr.transport_version = 2;
 		tinfo->goal.transport_version = 2;
 		ahc->msgout_index = 0;
 		ahc->msgout_len = 0;
@@ -3046,24 +3095,39 @@
 		       "Using asynchronous transfers\n",
 		       ahc_name(ahc), devinfo->channel,
 		       devinfo->target, devinfo->lun);
-	} else if ((scb->hscb->control & MSG_SIMPLE_Q_TAG) != 0) {
-
-		printf("(%s:%c:%d:%d): refuses tagged commands.  Performing "
-		       "non-tagged I/O\n", ahc_name(ahc),
-		       devinfo->channel, devinfo->target, devinfo->lun);
-		ahc_set_tags(ahc, devinfo, FALSE);
+	} else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
+		int tag_type;
+		int mask;
+
+		tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
+
+		if (tag_type == MSG_SIMPLE_TASK) {
+			printf("(%s:%c:%d:%d): refuses tagged commands.  "
+			       "Performing non-tagged I/O\n", ahc_name(ahc),
+			       devinfo->channel, devinfo->target, devinfo->lun);
+			ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE);
+			mask = ~0x23;
+		} else {
+			printf("(%s:%c:%d:%d): refuses %s tagged commands.  "
+			       "Performing simple queue tagged I/O only\n",
+			       ahc_name(ahc), devinfo->channel, devinfo->target,
+			       devinfo->lun, tag_type == MSG_ORDERED_TASK
+			       ? "ordered" : "head of queue");
+			ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC);
+			mask = ~0x03;
+		}
 
 		/*
 		 * Resend the identify for this CCB as the target
 		 * may believe that the selection is invalid otherwise.
 		 */
 		ahc_outb(ahc, SCB_CONTROL,
-			 ahc_inb(ahc, SCB_CONTROL) & ~MSG_SIMPLE_Q_TAG);
-	 	scb->hscb->control &= ~MSG_SIMPLE_Q_TAG;
+			 ahc_inb(ahc, SCB_CONTROL) & mask);
+	 	scb->hscb->control &= mask;
 		ahc_set_transaction_tag(scb, /*enabled*/FALSE,
-					/*type*/MSG_SIMPLE_Q_TAG);
+					/*type*/MSG_SIMPLE_TASK);
 		ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG);
-		ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
+		ahc_assert_atn(ahc);
 
 		/*
 		 * This transaction is now at the head of
@@ -3225,7 +3289,7 @@
 		    cam_status status, char *message, int verbose_level)
 {
 #ifdef AHC_TARGET_MODE
-	struct tmode_tstate* tstate;
+	struct ahc_tmode_tstate* tstate;
 	u_int lun;
 #endif
 	int found;
@@ -3242,7 +3306,7 @@
 	tstate = ahc->enabled_targets[devinfo->our_scsiid];
 	if (tstate != NULL) {
 		for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-			struct tmode_lstate* lstate;
+			struct ahc_tmode_lstate* lstate;
 
 			lstate = tstate->enabled_luns[lun];
 			if (lstate == NULL)
@@ -3265,7 +3329,7 @@
 			 AHC_TRANS_CUR, /*paused*/TRUE);
 	
 	ahc_send_async(ahc, devinfo->channel, devinfo->target,
-		       CAM_LUN_WILDCARD, AC_SENT_BDR);
+		       CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
 
 	if (message != NULL
 	 && (verbose_level <= bootverbose))
@@ -3274,9 +3338,11 @@
 }
 
 #ifdef AHC_TARGET_MODE
-void
-ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+static void
+ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+		       struct scb *scb)
 {
+
 	/*              
 	 * To facilitate adding multiple messages together,
 	 * each routine should increment the index and len
@@ -3285,7 +3351,7 @@
 	ahc->msgout_index = 0;
 	ahc->msgout_len = 0;
 
-	if ((ahc->targ_msg_req & devinfo->target_mask) != 0)
+	if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
 		ahc_build_transfer_msg(ahc, devinfo);
 	else
 		panic("ahc_intr: AWAITING target message with no message");
@@ -3319,6 +3385,7 @@
 	LIST_INIT(&ahc->pending_scbs);
 	/* We don't know our unit number until the OSM sets it */
 	ahc->name = name;
+	ahc->unit = -1;
 	for (i = 0; i < 16; i++)
 		TAILQ_INIT(&ahc->untagged_queues[i]);
 	if (ahc_platform_alloc(ahc, platform_arg) != 0) {
@@ -3337,7 +3404,7 @@
 	ahc->bugs = config->bugs;
 	ahc->flags = config->flags;
 	ahc->channel = config->channel; 
-	ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
+	ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS);
 	ahc->description = config->description;
 	/* The IRQMS bit is only valid on VL and EISA chips */
 	if ((ahc->chip & AHC_PCI) != 0)
@@ -3360,29 +3427,37 @@
 {
 	struct ahc_softc *list_ahc;
 
-#ifdef AHC_SUPPORT_PCI
+#if AHC_PCI_CONFIG > 0
 	/*
 	 * Second Function PCI devices need to inherit some
-	 * settings from function 0.  We assume that function 0
-	 * will always be found prior to function 1.
+	 * settings from function 0.
 	 */
 	if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI
-	 && ahc_get_pci_function(ahc->dev_softc) == 1) {
+	 && (ahc->features & AHC_MULTI_FUNC) != 0) {
 		TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
 			ahc_dev_softc_t list_pci;
 			ahc_dev_softc_t pci;
 
 			list_pci = list_ahc->dev_softc;
 			pci = ahc->dev_softc;
-			if (ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)
-			 && ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
-			 && ahc_get_pci_function(list_pci) == 0) {
-				ahc->flags &= ~AHC_BIOS_ENABLED; 
-				ahc->flags |=
-				    list_ahc->flags & AHC_BIOS_ENABLED;
-				ahc->flags &= ~AHC_CHANNEL_B_PRIMARY; 
-				ahc->flags |=
-				    list_ahc->flags & AHC_CHANNEL_B_PRIMARY;
+			if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
+			 && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) {
+				struct ahc_softc *master;
+				struct ahc_softc *slave;
+
+				if (ahc_get_pci_function(list_pci) == 0) {
+					master = list_ahc;
+					slave = ahc;
+				} else {
+					master = ahc;
+					slave = list_ahc;
+				}
+				slave->flags &= ~AHC_BIOS_ENABLED; 
+				slave->flags |=
+				    master->flags & AHC_BIOS_ENABLED;
+				slave->flags &= ~AHC_PRIMARY_CHANNEL; 
+				slave->flags |=
+				    master->flags & AHC_PRIMARY_CHANNEL;
 				break;
 			}
 		}
@@ -3455,7 +3530,7 @@
 #endif
 	ahc_platform_free(ahc);
 	for (i = 0; i < AHC_NUM_TARGETS; i++) {
-		struct tmode_tstate *tstate;
+		struct ahc_tmode_tstate *tstate;
 
 		tstate = ahc->enabled_targets[i];
 		if (tstate != NULL) {
@@ -3463,7 +3538,7 @@
 			int j;
 
 			for (j = 0; j < AHC_NUM_LUNS; j++) {
-				struct tmode_lstate *lstate;
+				struct ahc_tmode_lstate *lstate;
 
 				lstate = tstate->enabled_luns[j];
 				if (lstate != NULL) {
@@ -3523,7 +3598,7 @@
 	 * It contains settings that affect termination and we don't want
 	 * to disturb the integrity of the bus.
 	 */
-	pause_sequencer(ahc);
+	ahc_pause(ahc);
 	sxfrctl1_b = 0;
 	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
 		u_int sblkctl;
@@ -3961,17 +4036,26 @@
  		len = sprintf(buf, "Twin Channel, A SCSI Id=%d, "
 			      "B SCSI Id=%d, primary %c, ",
 			      ahc->our_id, ahc->our_id_b,
-			      ahc->flags & AHC_CHANNEL_B_PRIMARY ? 'B': 'A');
+			      (ahc->flags & AHC_PRIMARY_CHANNEL) + 'A');
 	else {
+		const char *speed;
 		const char *type;
 
+		speed = "";
+		if ((ahc->features & AHC_ULTRA) != 0) {
+			speed = "Ultra ";
+		} else if ((ahc->features & AHC_DT) != 0) {
+			speed = "Ultra160 ";
+		} else if ((ahc->features & AHC_ULTRA2) != 0) {
+			speed = "Ultra2 ";
+		}
 		if ((ahc->features & AHC_WIDE) != 0) {
 			type = "Wide";
 		} else {
 			type = "Single";
 		}
-		len = sprintf(buf, "%s Channel %c, SCSI Id=%d, ",
-			      type, ahc->channel, ahc->our_id);
+		len = sprintf(buf, "%s%s Channel %c, SCSI Id=%d, ",
+			      speed, type, ahc->channel, ahc->our_id);
 	}
 	buf += len;
 
@@ -4124,16 +4208,16 @@
 	 * data for any target mode initiator.
 	 */
 	if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) {
-		printf("%s: unable to allocate tmode_tstate.  "
+		printf("%s: unable to allocate ahc_tmode_tstate.  "
 		       "Failing attach\n", ahc_name(ahc));
-		return (-1);
+		return (ENOMEM);
 	}
 
 	if ((ahc->features & AHC_TWIN) != 0) {
 		if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) {
-			printf("%s: unable to allocate tmode_tstate.  "
+			printf("%s: unable to allocate ahc_tmode_tstate.  "
 			       "Failing attach\n", ahc_name(ahc));
-			return (-1);
+			return (ENOMEM);
 		}
 	}
 
@@ -4231,7 +4315,7 @@
 
 	for (i = 0; i <= max_targ; i++) {
 		struct ahc_initiator_tinfo *tinfo;
-		struct tmode_tstate *tstate;
+		struct ahc_tmode_tstate *tstate;
 		u_int our_id;
 		u_int target_id;
 		char channel;
@@ -4324,12 +4408,10 @@
 				tinfo->user.transport_version = 2;
 			tinfo->goal.protocol_version = 2;
 			tinfo->goal.transport_version = 2;
-			tinfo->current.protocol_version = 2;
-			tinfo->current.transport_version = 2;
+			tinfo->curr.protocol_version = 2;
+			tinfo->curr.transport_version = 2;
 		}
 		tstate->ultraenb = ultraenb;
-		tstate->discenable = discenable;
-		tstate->tagenable = 0; /* Wait until the XPT says its okay */
 	}
 	ahc->user_discenable = discenable;
 	ahc->user_tagenable = tagenable;
@@ -4395,10 +4477,6 @@
 	ahc_outb(ahc, QINPOS, 0);
 	ahc_outb(ahc, QOUTPOS, 0);
 
-	/* Don't have any special messages to send to targets */
-	ahc_outb(ahc, TARGET_MSG_REQUEST, 0);
-	ahc_outb(ahc, TARGET_MSG_REQUEST + 1, 0);
-
 	/*
 	 * Use the built in queue management registers
 	 * if they are available.
@@ -4450,16 +4528,33 @@
 		 * never settle, so don't complain if we
 		 * fail here.
 		 */
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		for (wait = 5000;
 		     (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
 		     wait--)
 			ahc_delay(100);
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 	}
 	return (0);
 }
 
+void
+ahc_intr_enable(struct ahc_softc *ahc, int enable)
+{
+	u_int hcntrl;
+
+	hcntrl = ahc_inb(ahc, HCNTRL);
+	hcntrl &= ~INTEN;
+	ahc->pause &= ~INTEN;
+	ahc->unpause &= ~INTEN;
+	if (enable) {
+		hcntrl |= INTEN;
+		ahc->pause |= INTEN;
+		ahc->unpause |= INTEN;
+	}
+	ahc_outb(ahc, HCNTRL, hcntrl);
+}
+
 /*
  * Ensure that the card is paused in a location
  * outside of all critical sections and that all
@@ -4478,7 +4573,7 @@
 	intstat = 0;
 	do {
 		ahc_intr(ahc);
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		ahc_clear_critical_section(ahc);
 		if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
 			break;
@@ -5409,7 +5504,7 @@
 			    CAM_TARGET_WILDCARD,
 			    CAM_LUN_WILDCARD,
 			    channel, ROLE_UNKNOWN);
-	pause_sequencer(ahc);
+	ahc_pause(ahc);
 
 	/* Make sure the sequencer is in a safe location. */
 	ahc_clear_critical_section(ahc);
@@ -5478,14 +5573,14 @@
 	 * drivers affected by this action.
 	 */
 	for (target = 0; target <= max_scsiid; target++) {
-		struct tmode_tstate* tstate;
+		struct ahc_tmode_tstate* tstate;
 		u_int lun;
 
 		tstate = ahc->enabled_targets[target];
 		if (tstate == NULL)
 			continue;
 		for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-			struct tmode_lstate* lstate;
+			struct ahc_tmode_lstate* lstate;
 
 			lstate = tstate->enabled_luns[lun];
 			if (lstate == NULL)
@@ -5499,7 +5594,7 @@
 #endif
 	/* Notify the XPT that a bus reset occurred */
 	ahc_send_async(ahc, devinfo.channel, CAM_TARGET_WILDCARD,
-		       CAM_LUN_WILDCARD, AC_BUS_RESET);
+		       CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
 
 	/*
 	 * Revert to async/narrow transfers until we renegotiate.
@@ -5524,9 +5619,9 @@
 	}
 
 	if (restart_needed)
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 	else
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 	return found;
 }
 
@@ -5535,7 +5630,7 @@
 /*
  * Calculate the residual for a just completed SCB.
  */
-static void
+void
 ahc_calc_residual(struct scb *scb)
 {
 	struct hardware_scb *hscb;
@@ -5623,7 +5718,7 @@
  * Add a target mode event to this lun's queue
  */
 static void
-ahc_queue_lstate_event(struct ahc_softc *ahc, struct tmode_lstate *lstate,
+ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate,
 		       u_int initiator_id, u_int event_type, u_int event_arg)
 {
 	struct ahc_tmode_event *event;
@@ -5674,7 +5769,7 @@
  * for immediate notify resources.
  */
 void
-ahc_send_lstate_events(struct ahc_softc *ahc, struct tmode_lstate *lstate)
+ahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate)
 {
 	struct ccb_hdr *ccbh;
 	struct ccb_immed_notify *inot;
@@ -5825,7 +5920,7 @@
 		memcpy(ahc->critical_sections, cs_table, cs_count);
 	}
 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE);
-	restart_sequencer(ahc);
+	ahc_restart(ahc);
 
 	if (bootverbose)
 		printf(" %d instructions downloaded\n", downloaded);
@@ -6000,6 +6095,7 @@
 	int target;
 	int maxtarget;
 	int i;
+	uint8_t last_phase;
 	uint8_t qinpos;
 	uint8_t qintail;
 	uint8_t qoutpos;
@@ -6008,13 +6104,25 @@
 
 	saved_scbptr = ahc_inb(ahc, SCBPTR);
 
-	printf("%s: Dumping Card State at SEQADDR 0x%x\n",
-	       ahc_name(ahc),
+	last_phase = ahc_inb(ahc, LASTPHASE);
+	printf("%s: Dumping Card State %s, at SEQADDR 0x%x\n",
+	       ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg,
 	       ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
-
-	printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x, SSTAT0 0x%x\n",
-	       ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL),
-	       ahc_inb(ahc, SSTAT0));
+	printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x\n",
+	       ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL));
+	printf(" DFCNTRL = 0x%x, DFSTATUS = 0x%x\n",
+	       ahc_inb(ahc, DFCNTRL), ahc_inb(ahc, DFSTATUS));
+	printf("LASTPHASE = 0x%x, SCSISIGI = 0x%x, SXFRCTL0 = 0x%x\n",
+	       last_phase, ahc_inb(ahc, SCSISIGI), ahc_inb(ahc, SXFRCTL0));
+	printf("SSTAT0 = 0x%x, SSTAT1 = 0x%x\n",
+	       ahc_inb(ahc, SSTAT0), ahc_inb(ahc, SSTAT1));
+	if ((ahc->features & AHC_DT) != 0)
+		printf("SCSIPHASE = 0x%x\n", ahc_inb(ahc, SCSIPHASE));
+	printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n",
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8));
 	printf("SCB count = %d\n", ahc->scb_data->numscbs);
 	printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag);
 	printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB));
@@ -6112,7 +6220,8 @@
 #ifdef AHC_TARGET_MODE
 cam_status
 ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb,
-		    struct tmode_tstate **tstate, struct tmode_lstate **lstate,
+		    struct ahc_tmode_tstate **tstate,
+		    struct ahc_tmode_lstate **lstate,
 		    int notfound_failure)
 {
 
@@ -6153,8 +6262,8 @@
 void
 ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 {
-	struct	   tmode_tstate *tstate;
-	struct	   tmode_lstate *lstate;
+	struct	   ahc_tmode_tstate *tstate;
+	struct	   ahc_tmode_lstate *lstate;
 	struct	   ccb_en_lun *cel;
 	cam_status status;
 	u_int	   target;
@@ -6227,7 +6336,7 @@
 		ahc->flags |= AHC_TARGETROLE;
 		if ((ahc->features & AHC_MULTIROLE) == 0)
 			ahc->flags &= ~AHC_INITIATORROLE;
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		ahc_loadseq(ahc);
 		ahc_unlock(ahc, &s);
 	}
@@ -6296,7 +6405,7 @@
 		SLIST_INIT(&lstate->accept_tios);
 		SLIST_INIT(&lstate->immed_notifies);
 		ahc_lock(ahc, &s);
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		if (target != CAM_TARGET_WILDCARD) {
 			tstate->enabled_luns[lun] = lstate;
 			ahc->enabled_luns++;
@@ -6360,7 +6469,7 @@
 			scsiseq |= ENSELI;
 			ahc_outb(ahc, SCSISEQ, scsiseq);
 		}
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 		ahc_unlock(ahc, &s);
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_print_path(ccb->ccb_h.path);
@@ -6410,7 +6519,7 @@
 		xpt_free_path(lstate->path);
 		free(lstate, M_DEVBUF);
 
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		/* Can we clean up the target too? */
 		if (target != CAM_TARGET_WILDCARD) {
 			tstate->enabled_luns[lun] = NULL;
@@ -6463,11 +6572,11 @@
 				printf("Configuring Initiator Mode\n");
 				ahc->flags &= ~AHC_TARGETROLE;
 				ahc->flags |= AHC_INITIATORROLE;
-				pause_sequencer(ahc);
+				ahc_pause(ahc);
 				ahc_loadseq(ahc);
 			}
 		}
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 		ahc_unlock(ahc, &s);
 	}
 }
@@ -6549,11 +6658,11 @@
 				ahc_outb(ahc, HS_MAILBOX, hs_mailbox);
 			} else {
 				if (!paused)
-					pause_sequencer(ahc);	
+					ahc_pause(ahc);	
 				ahc_outb(ahc, KERNEL_TQINPOS,
 					 ahc->tqinfifonext & HOST_TQINPOS);
 				if (!paused)
-					unpause_sequencer(ahc);
+					ahc_unpause(ahc);
 			}
 		}
 	}
@@ -6562,8 +6671,8 @@
 static int
 ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
 {
-	struct	  tmode_tstate *tstate;
-	struct	  tmode_lstate *lstate;
+	struct	  ahc_tmode_tstate *tstate;
+	struct	  ahc_tmode_lstate *lstate;
 	struct	  ccb_accept_tio *atio;
 	uint8_t *byte;
 	int	  initiator;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)