Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Jul 1995 21:49:19 +1000
From:      Stephen Hocking <sysseh@devetir.qld.gov.au>
To:        bugs@freebsd.org
Message-ID:  <199507111149.LAA24598@netfl15a.devetir.qld.gov.au>

next in thread | raw e-mail | index | archive | help
The following patch to v1.8 of seagate.c fixes PR i386/337 (seagate controller 
code hangs on boot.) for me. It basically alters its behaiviour when confronted 
with a Future Domain TMC 885 controller in WRT disconnects, deassertion of 
STAT_REQ and various phase checks.

*** seagate.c.dist	Tue Jul  4 11:32:10 1995
--- seagate.c	Tue Jul 11 20:31:23 1995
***************
*** 7,12 ****
--- 7,13 ----
   * Copyright 1992, 1994 Drew Eckhardt (drew@colorado.edu)
   * Copyright 1994, Julian Elischer (julian@tfs.com)
   * Copyright 1994-1995, Serge Vakulenko (vak@cronyx.ru)
+  * Copyright 1995 Stephen Hocking (sysseh@devetir.qld.gov.au)
   *
   * Others that has contributed by example code is
   * 		Glen Overby (overby@cray.com)
***************
*** 45,50 ****
--- 46,57 ----
   *               new asm fragments for data input/output, target-dependent
   *               delays, device flags, polling mode, generic cleanup
   * vak    950115 Added request-sense ops
+  * seh    950701 Fixed up Future Domain TMC-885 problems with disconnects,
+  *               weird phases and the like. (we could probably investigate
+  *               what the board's idea of the phases are, but that requires
+  *               doco that I don't have). Note that it is slower than the
+  *               2.0R driver with both SEA_BLINDTRANSFER & SEA_ASSEMBLER
+  *               defined by a factor of more than 2. I'll look at that later!
   *
   * $Id: seagate.c,v 1.8 1995/05/30 08:03:04 rgrimes Exp $
   */
***************
*** 128,134 ****
  #define HOST_SCSI_ADDR  7       /* address of the adapter on the SCSI bus */
  
  /*
!  * Defice config flags
   */
  #define FLAG_NOPARITY   0x01    /* disable SCSI bus parity check */
  
--- 135,141 ----
  #define HOST_SCSI_ADDR  7       /* address of the adapter on the SCSI bus */
  
  /*
!  * Define config flags
   */
  #define FLAG_NOPARITY   0x01    /* disable SCSI bus parity check */
  
***************
*** 324,330 ****
  static int sea_poll (adapter_t *z, scb_t *scb);
  static int sea_init (adapter_t *z);
  static int sea_reselect (adapter_t *z);
! static int sea_select (adapter_t *z, scb_t *scb);
  static int sea_abort (adapter_t *z, scb_t *scb);
  static void sea_send_abort (adapter_t *z);
  static u_char sea_msg_input (adapter_t *z);
--- 331,337 ----
  static int sea_poll (adapter_t *z, scb_t *scb);
  static int sea_init (adapter_t *z);
  static int sea_reselect (adapter_t *z);
! static int sea_select (volatile adapter_t *z, scb_t *scb);
  static int sea_abort (adapter_t *z, scb_t *scb);
  static void sea_send_abort (adapter_t *z);
  static u_char sea_msg_input (adapter_t *z);
***************
*** 348,353 ****
--- 355,363 ----
  	DC_CLS_MISC		/* host adapters aren't special */
  } };
  
+ /* FD TMC885's can't handle detach & re-attach */
+ static int sea_select_cmd = CMD_DRVR_ENABLE | CMD_ATTN;
+ 
  /*
   * Check if the device can be found at the port given and if so,
   * detect the type of board. Set it up ready for further work.
***************
*** 421,426 ****
--- 431,441 ----
  	z->CONTROL = z->addr + 0x1c00; /* TMC-885/TMC-950 reg. offsets */
  	z->STATUS  = z->addr + 0x1c00;
  	z->DATA    = z->addr + 0x1e00;
+ 	/* FD TMC885's can't handle detach & re-attach */
+ 	sea_select_cmd = CMD_DRVR_ENABLE;
+ 	/* FD TMC-885 is supposed to be at id 6. How strange. */
+ 	z->scsi_addr = HOST_SCSI_ADDR - 1;
+ 	z->scsi_id = 1 << z->scsi_addr;
  	if (sea_init (z) == 0)
  		return (1);
  
***************
*** 476,482 ****
  	}
  
  	/* Reset the scsi bus (I don't know if this is needed). */
! 	*z->CONTROL = CMD_RST | CMD_DRVR_ENABLE;
  	/* Hold reset for at least 25 microseconds. */
  	DELAY (25);
  	/* Check that status cleared. */
--- 491,497 ----
  	}
  
  	/* Reset the scsi bus (I don't know if this is needed). */
! 	*z->CONTROL = CMD_RST | CMD_DRVR_ENABLE | z->parity | CMD_INTR;
  	/* Hold reset for at least 25 microseconds. */
  	DELAY (25);
  	/* Check that status cleared. */
***************
*** 497,503 ****
  	/* Enable the adapter. */
  	*z->CONTROL = CMD_INTR | z->parity;
  	/* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */
! 	DELAY (10);
  
  	/* Check that DATA register is NOT writable. */
  	c = *z->DATA;
--- 512,518 ----
  	/* Enable the adapter. */
  	*z->CONTROL = CMD_INTR | z->parity;
  	/* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */
! 	DELAY (15);
  
  	/* Check that DATA register is NOT writable. */
  	c = *z->DATA;
***************
*** 591,598 ****
  	adapter_t *z = &seadata[unit];
  	scb_t *scb;
  
! 	/* PRINT (("sea%d/%d/%d command 0x%x\n", unit, xs->sc_link->target,
! 		xs->sc_link->lun, xs->cmd->opcode)); */
  	if (xs->bp)
  		flags |= SCSI_NOSLEEP;
  	if (flags & ITSDONE) {
--- 606,613 ----
  	adapter_t *z = &seadata[unit];
  	scb_t *scb;
  
! 	PRINT (("sea%d/%d/%d command 0x%x\n", unit, xs->sc_link->target,
! 		xs->sc_link->lun, xs->cmd->opcode)); 
  	if (xs->bp)
  		flags |= SCSI_NOSLEEP;
  	if (flags & ITSDONE) {
***************
*** 680,688 ****
  			 * this time there is no clock queue entry to remove. */
  			sea_timeout ((void*) scb);
  	}
! 	/* PRINT (("sea%d/%d/%d command %s\n", unit,
  		xs->sc_link->target, xs->sc_link->lun,
! 		xs->error ? "failed" : "done")); */
  	return (xs->error ? HAD_ERROR : COMPLETE);
  }
  
--- 695,703 ----
  			 * this time there is no clock queue entry to remove. */
  			sea_timeout ((void*) scb);
  	}
! 	PRINT (("sea%d/%d/%d command %s\n", unit,
  		xs->sc_link->target, xs->sc_link->lun,
! 		xs->error ? "failed" : "done")); 
  	return (xs->error ? HAD_ERROR : COMPLETE);
  }
  
***************
*** 781,790 ****
   * for IDENTIFY and queue messages.
   * Return 1 if selection succeded.
   */
! int sea_select (adapter_t *z, scb_t *scb)
  {
  	/* Start arbitration. */
! 	*z->CONTROL = z->parity;
  	*z->DATA = z->scsi_id;
  	*z->CONTROL = CMD_START_ARB | z->parity;
  
--- 796,807 ----
   * for IDENTIFY and queue messages.
   * Return 1 if selection succeded.
   */
! int sea_select (volatile adapter_t *z, scb_t *scb)
  {
+ 	register unsigned char	tmp;
+ 
  	/* Start arbitration. */
! 	*z->CONTROL = z->parity | CMD_INTR;
  	*z->DATA = z->scsi_id;
  	*z->CONTROL = CMD_START_ARB | z->parity;
  
***************
*** 801,811 ****
  		*z->CONTROL = CMD_INTR | z->parity;
  		return (0);
  	}
! 	DELAY (2);
  
  	*z->DATA = (1 << scb->xfer->sc_link->target) | z->scsi_id;
! 	*z->CONTROL = CMD_DRVR_ENABLE | CMD_SEL | CMD_ATTN | z->parity;
! 	DELAY (1);
  
  	/* Wait for a bsy from target.
  	 * If the target is not present on the bus, we get
--- 818,828 ----
  		*z->CONTROL = CMD_INTR | z->parity;
  		return (0);
  	}
! 	DELAY (1);
  
  	*z->DATA = (1 << scb->xfer->sc_link->target) | z->scsi_id;
! 	*z->CONTROL = sea_select_cmd | CMD_SEL | z->parity;
! 	DELAY (2);
  
  	/* Wait for a bsy from target.
  	 * If the target is not present on the bus, we get
***************
*** 823,830 ****
  
  	/* Try to make the target to take a message from us.
  	 * Should start a MSGOUT phase. */
! 	*z->CONTROL = CMD_DRVR_ENABLE | CMD_ATTN | z->parity;
! 	DELAY (1);
  	WAITFOR (*z->STATUS & STAT_REQ, 0);
  	if (! (*z->STATUS & STAT_REQ)) {
  		PRINT (("sea%d/%d/%d timeout waiting for REQ\n",
--- 840,852 ----
  
  	/* Try to make the target to take a message from us.
  	 * Should start a MSGOUT phase. */
! 	*z->CONTROL = sea_select_cmd | z->parity;
! 	DELAY (15);
! 	WAITFOR (*z->STATUS & STAT_REQ, 0);
! 
! 	if (z->type == CTLR_FUTURE_DOMAIN)
! 		*z->CONTROL = CMD_INTR | z->parity | CMD_DRVR_ENABLE;
! 
  	WAITFOR (*z->STATUS & STAT_REQ, 0);
  	if (! (*z->STATUS & STAT_REQ)) {
  		PRINT (("sea%d/%d/%d timeout waiting for REQ\n",
***************
*** 835,842 ****
  		return (0);
  	}
  
! 	/* Check for phase mismatch. */
! 	if ((*z->STATUS & PHASE_MASK) != PHASE_MSGOUT) {
  		PRINT (("sea%d/%d/%d waiting for MSGOUT: invalid phase %s\n",
  			z->sc_link.adapter_unit, scb->xfer->sc_link->target,
  			scb->xfer->sc_link->lun,
--- 857,864 ----
  		return (0);
  	}
  
! 	/* Check for phase mismatch. FD 885 always seems to get this wrong! */
! 	if ((*z->STATUS & PHASE_MASK) != PHASE_MSGOUT && z->type != CTLR_FUTURE_DOMAIN) {
  		PRINT (("sea%d/%d/%d waiting for MSGOUT: invalid phase %s\n",
  			z->sc_link.adapter_unit, scb->xfer->sc_link->target,
  			scb->xfer->sc_link->lun,
***************
*** 846,855 ****
  		return (0);
  	}
  
! 	/* Allow disconnects. */
! 	*z->CONTROL = CMD_DRVR_ENABLE | z->parity;
! 	*z->DATA = MSG_IDENTIFY (scb->xfer->sc_link->lun);
! 	WAITREQ (&z->target[scb->xfer->sc_link->target], msgout, 1000);
  	*z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity;
  
  	SET_BUSY (z, scb);
--- 868,879 ----
  		return (0);
  	}
  
! 	/* Allow disconnects. (except for FD controllers) */
! 	if (z->type == CTLR_SEAGATE) {
! 		*z->CONTROL = CMD_DRVR_ENABLE | z->parity;
! 		*z->DATA = MSG_IDENTIFY (scb->xfer->sc_link->lun);
! 		WAITREQ (&z->target[scb->xfer->sc_link->target], msgout, 1000);
! 	}
  	*z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity;
  
  	SET_BUSY (z, scb);
***************
*** 881,887 ****
  	/* Host responds by asserting the BSY signal. */
  	/* Target should respond by deasserting the SEL signal. */
  	target_mask &= ~z->scsi_id;
! 	*z->CONTROL = CMD_DRVR_ENABLE | CMD_BSY | z->parity;
  	WAITFOR (! (*z->STATUS & STAT_SEL), "reselection acknowledge");
  
  	/* Remove the busy status. */
--- 905,911 ----
  	/* Host responds by asserting the BSY signal. */
  	/* Target should respond by deasserting the SEL signal. */
  	target_mask &= ~z->scsi_id;
! 	*z->CONTROL = CMD_DRVR_ENABLE | CMD_BSY | z->parity | CMD_INTR;
  	WAITFOR (! (*z->STATUS & STAT_SEL), "reselection acknowledge");
  
  	/* Remove the busy status. */
***************
*** 1037,1044 ****
   */
  void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen)
  {
! 	u_char *data = *pdata;
! 	u_long len = *plen;
  
  	asm ("cld
  	1:      movb (%%ebx), %%al
--- 1061,1068 ----
   */
  void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen)
  {
! 	volatile u_char *data = *pdata;
! 	volatile u_long len = *plen;
  
  	asm ("cld
  	1:      movb (%%ebx), %%al
***************
*** 1065,1072 ****
   */
  void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen)
  {
! 	u_char *data = *pdata;
! 	u_long len = *plen;
  
  	if (len >= 512) {
  		asm ("  cld
--- 1089,1096 ----
   */
  void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen)
  {
! 	volatile u_char *data = *pdata;
! 	volatile u_long len = *plen;
  
  	if (len >= 512) {
  		asm ("  cld
***************
*** 1123,1129 ****
  
  	PRINT (("%x", *cmd));
  	*z->DATA = *cmd++;
! 	WAITREQ (t, cmdout1, 10000);
  	--cmdlen;
  
  	while (cmdlen) {
--- 1147,1154 ----
  
  	PRINT (("%x", *cmd));
  	*z->DATA = *cmd++;
! 	if (z->type == CTLR_SEAGATE)
! 		WAITREQ (t, cmdout1, 10000);
  	--cmdlen;
  
  	while (cmdlen) {
***************
*** 1132,1140 ****
  		if (! (sts & STAT_BSY))
  			break;
  
! 		/* Check for phase mismatch. */
! 		if ((sts & PHASE_MASK) != PHASE_CMDOUT) {
! 			printf ("sea: sending command: invalid phase %s\n",
  				PHASE_NAME (sts & PHASE_MASK));
  			return;
  		}
--- 1157,1165 ----
  		if (! (sts & STAT_BSY))
  			break;
  
! 		/* Check for phase mismatch. FD 885 seems to get this wrong! */
! 		if ((sts & PHASE_MASK) != PHASE_CMDOUT && z->type != CTLR_FUTURE_DOMAIN) {
! 			printf ("sea: sea_cmd_output: invalid phase %s\n",
  				PHASE_NAME (sts & PHASE_MASK));
  			return;
  		}
***************
*** 1145,1151 ****
  
  		PRINT (("-%x", *cmd));
  		*z->DATA = *cmd++;
! 		WAITREQ (t, cmdout, 1000);
  		--cmdlen;
  	}
  	PRINT (("\n"));
--- 1170,1177 ----
  
  		PRINT (("-%x", *cmd));
  		*z->DATA = *cmd++;
! 		if (z->type == CTLR_SEAGATE)
! 			WAITREQ (t, cmdout, 1000);
  		--cmdlen;
  	}
  	PRINT (("\n"));
***************
*** 1197,1203 ****
  	/* Check for phase mismatch.
  	 * Reached if the target decides that it has finished the transfer. */
  	if ((sts & PHASE_MASK) != PHASE_MSGIN) {
! 		printf ("sea: sending message: invalid phase %s\n",
  			PHASE_NAME (sts & PHASE_MASK));
  		return (MSG_ABORT);
  	}
--- 1223,1229 ----
  	/* Check for phase mismatch.
  	 * Reached if the target decides that it has finished the transfer. */
  	if ((sts & PHASE_MASK) != PHASE_MSGIN) {
! 		printf ("sea: sea_msg_input: invalid phase %s\n",
  			PHASE_NAME (sts & PHASE_MASK));
  		return (MSG_ABORT);
  	}
***************
*** 1343,1349 ****
  			break;
  		case PHASE_STATIN:
  			scb->xfer->status = *z->DATA;
! 			WAITREQ (t, statin, 2000);
  			PRINT (("sea%d/%d/%d (STATIN) got 0x%x\n",
  				z->sc_link.adapter_unit,
  				scb->xfer->sc_link->target,
--- 1369,1376 ----
  			break;
  		case PHASE_STATIN:
  			scb->xfer->status = *z->DATA;
! 			if (z->type == CTLR_SEAGATE)
! 				WAITREQ (t, statin, 2000);
  			PRINT (("sea%d/%d/%d (STATIN) got 0x%x\n",
  				z->sc_link.adapter_unit,
  				scb->xfer->sc_link->target,


        I do not speak for the Worker's Compensation Board of Queensland -
                     They don't pay me enough for that!




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507111149.LAA24598>