Subject: Fixed bt/aha patches
To: None <port-i386@NetBSD.ORG>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: port-i386
Date: 01/04/1997 10:59:27
Please ignore the previous patches. They won't work.
i forgot that 1.2 (at least the source tree I have) doesn't
have extent-based IOport accounting.  

To avoid configuring bha devices as aha's, the aha driver needs
to be changed to also reject bha devices. (The sense of
the return value from aha_find and bha_find has also changed
since 1.2, so the previous patch was very broken.)

That also makes the relative order of bha and aha probing immaterial,
so I deleted the change to sys/dev/isa/files.isa.

The following works for me on a bha device; basically, I applied
the bt changes to the aha driver and reversed the sense of the test.
If someone could test it on an aha 154x, that would be great.


*** sys/dev/isa/bt.c-1.2	Mon May 13 04:36:16 1996
--- sys/dev/isa/bt.c	Sat Jan  4 10:25:41 1997
***************
*** 200,205 ****
--- 200,206 ----
  	int wait;
  	u_char sts;
  	u_char opcode = ibuf[0];
+ 	int rbytes;	/* count of bytes actually returned in obuf */
  
  	if (sc != NULL)
  		name = sc->sc_dev.dv_xname;
***************
*** 232,238 ****
  		if (!i) {
  			printf("%s: bt_cmd, host not idle(0x%x)\n",
  			    name, sts);
! 			return ENXIO;
  		}
  	}
  	/*
--- 233,239 ----
  		if (!i) {
  			printf("%s: bt_cmd, host not idle(0x%x)\n",
  			    name, sts);
! 			return (-1);
  		}
  	}
  	/*
***************
*** 258,264 ****
  			if (opcode != BT_INQUIRE_REVISION)
  				printf("%s: bt_cmd, cmd/data port full\n", name);
  			outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
! 			return ENXIO;
  		}
  		outb(iobase + BT_CMD_PORT, *ibuf++);
  	}
--- 259,265 ----
  			if (opcode != BT_INQUIRE_REVISION)
  				printf("%s: bt_cmd, cmd/data port full\n", name);
  			outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
! 			return (-1);
  		}
  		outb(iobase + BT_CMD_PORT, *ibuf++);
  	}
***************
*** 266,272 ****
  	 * If we expect input, loop that many times, each time,
  	 * looking for the data register to have valid data
  	 */
! 	while (ocnt--) {
  		for (i = wait; i; i--) {
  			sts = inb(iobase + BT_STAT_PORT);
  			if (sts & BT_STAT_DF)
--- 267,274 ----
  	 * If we expect input, loop that many times, each time,
  	 * looking for the data register to have valid data
  	 */
! 	rbytes = 0;
! 	while (rbytes < ocnt) {
  		for (i = wait; i; i--) {
  			sts = inb(iobase + BT_STAT_PORT);
  			if (sts & BT_STAT_DF)
***************
*** 278,286 ****
  				printf("%s: bt_cmd, cmd/data port empty %d\n",
  				    name, ocnt);
  			outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
! 			return ENXIO;
  		}
  		*obuf++ = inb(iobase + BT_DATA_PORT);
  	}
  	/*
  	 * Wait for the board to report a finished instruction.
--- 280,289 ----
  				printf("%s: bt_cmd, cmd/data port empty %d\n",
  				    name, ocnt);
  			outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
! 			return (-1);
  		}
  		*obuf++ = inb(iobase + BT_DATA_PORT);
+ 		rbytes++;
  	}
  	/*
  	 * Wait for the board to report a finished instruction.
***************
*** 298,308 ****
  		if (!i) {
  			printf("%s: bt_cmd, host not finished(0x%x)\n",
  			    name, sts);
! 			return ENXIO;
  		}
  	}
  	outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
! 	return 0;
  }
  
  /*
--- 301,311 ----
  		if (!i) {
  			printf("%s: bt_cmd, host not finished(0x%x)\n",
  			    name, sts);
! 			return (-1);
  		}
  	}
  	outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
! 	return (rbytes);
  }
  
  /*
***************
*** 805,811 ****
  }
  
  /*
!  * Find the board and find it's irq/drq
   */
  int
  bt_find(ia, sc)
--- 808,815 ----
  }
  
  /*
!  * Find the board and find it's irq/drq.
!  * returns 0 if device found, 1 otherwise.
   */
  int
  bt_find(ia, sc)
***************
*** 819,824 ****
--- 823,833 ----
  	struct bt_config config;
  	int irq, drq;
  
+ 	/* Check something is at the ports we need to access */
+ 	sts = inb(iobase + BT_STAT_PORT);
+ 	if (sts == 0xFF)
+ 		return (1);
+ 
  	/*
  	 * reset board, If it doesn't respond, assume
  	 * that it's not there.. good for the probe
***************
*** 842,854 ****
  	}
  
  	/*
  	 * Check that we actually know how to use this board.
  	 */
  	delay(1000);
  	inquire.cmd.opcode = BT_INQUIRE_EXTENDED;
  	inquire.cmd.len = sizeof(inquire.reply);
! 	bt_cmd(iobase, sc, sizeof(inquire.cmd), (u_char *)&inquire.cmd,
  	    sizeof(inquire.reply), (u_char *)&inquire.reply);
  	switch (inquire.reply.bus_type) {
  	case BT_BUS_TYPE_24BIT:
  		/* XXXX How do we avoid conflicting with the aha1542 probe? */
--- 851,898 ----
  	}
  
  	/*
+ 	 * The BusLogic cards implement an Adaptec 1542 (aha)-compatible
+ 	 * interface. The native bha interface is not compatible with 
+ 	 * an aha. 1542. We need to ensure that we never match an
+ 	 * Adaptec 1542. We must also avoid sending Adaptec-compatible
+ 	 * commands to a real bha, lest it go into 1542 emulation mode.
+ 	 * (On an indirect bus like ISA, we should always probe for BusLogic
+ 	 * interfaces  before Adaptec interfaces).
+ 	 */
+ 
+ 	/*
+ 	 * Make sure we don't match an AHA-1542A or AHA-1542B, by checking
+ 	 * for an extended-geometry register.  The 1542[AB] don't have one.
+ 	 */
+ 	sts = inb(iobase +  BT_EXTGEOM_PORT);
+ 	if (sts == 0xFF)
+ 		return (1);
+ 
+ 	/*
  	 * Check that we actually know how to use this board.
  	 */
  	delay(1000);
  	inquire.cmd.opcode = BT_INQUIRE_EXTENDED;
  	inquire.cmd.len = sizeof(inquire.reply);
! 	i = bt_cmd(iobase, sc, sizeof(inquire.cmd), (u_char *)&inquire.cmd,
  	    sizeof(inquire.reply), (u_char *)&inquire.reply);
+ 
+ 	/*
+ 	 * Some 1542Cs (CP, perhaps not CF, may depend on firmware rev)
+ 	 * have the extended-geometry register and also respond to
+ 	 * BT_INQUIRE_EXTENDED.  Make sure we never  match such cards,
+ 	 * by checking the size of the reply is what a BusLogic card returns.
+ 	 */
+ 	if (i != sizeof(inquire.reply)) {
+ #ifdef BHADEBUG
+ 		printf("bt_find: board returned %d instead of %d to %s\n",
+ 		       i, sizeof(inquire.reply), "INQUIRE_EXTENDED");
+ #endif
+ 		return (1);
+ 	}
+ 
+ 	/* OK, we've found a buslogic adapter. */
+ 
  	switch (inquire.reply.bus_type) {
  	case BT_BUS_TYPE_24BIT:
  		/* XXXX How do we avoid conflicting with the aha1542 probe? */
*** sys/dev/isa/btreg.h-1.2	Thu May  2 04:42:25 1996
--- sys/dev/isa/btreg.h	Sat Jan  4 10:46:06 1997
***************
*** 1,8 ****
--- 1,12 ----
+ #ifndef ltophys
+ 
  typedef u_int8_t physaddr[4];
  typedef u_int8_t physlen[4];
  #define	ltophys	_lto4l
  #define	phystol	_4ltol
  
+ #endif
+ 
  /*
   * I/O port offsets
   */
***************
*** 11,16 ****
--- 15,21 ----
  #define	BT_CMD_PORT		1	/* command (wo) */
  #define	BT_DATA_PORT		1	/* data (ro) */
  #define	BT_INTR_PORT		2	/* interrupt status (ro) */
+ #define	BT_EXTGEOM_PORT		3	/* extended geometry(ro) */
  
  /*
   * BT_CTRL bits
***************
*** 188,194 ****
  #define	BT_BUS_TYPE_32BIT	'E'	/* EISA/VLB/PCI bus */
  #define	BT_BUS_TYPE_MCA		'M'	/* MicroChannel bus */
  		u_char	bios_address;	/* Address of adapter BIOS */
! 		u_short	max_segment;	/* ? */
  	} reply;
  };
  
--- 193,210 ----
  #define	BT_BUS_TYPE_32BIT	'E'	/* EISA/VLB/PCI bus */
  #define	BT_BUS_TYPE_MCA		'M'	/* MicroChannel bus */
  		u_char	bios_address;	/* Address of adapter BIOS */
! 		u_short sg_limit;
! 		u_char	mbox_count;
! 		u_char	mbox_baseaddr[4]; /* packed/unaligned uint_32_t */
! 		u_char	intrflags;
! #define BHA_INTR_LEVEL	0x40		/* bit 6: level-sensitive interrupt */
! 		u_char	firmware_level[3]; /* last 3 digits of firmware rev */
! 		u_char	scsi_flags;	/* supported SCSI  features */
! #define BHA_SCSI_WIDE		0x01
! #define BHA_SCSI_DIFFERENTIAL	0x02
! #define BHA_SCSI_AUTOCONF	0x04
! #define BHA_SCSI_ULTRA		0x08
! #define BHA_SCSI_TERMINATION	0x10
  	} reply;
  };
  
*** sys/dev/isa/aha.c-1.2	Mon May 13 04:36:13 1996
--- sys/dev/isa/aha.c	Sat Jan  4 10:47:17 1997
***************
*** 68,73 ****
--- 68,74 ----
  #include <dev/isa/isavar.h>
  #include <dev/isa/isadmavar.h>
  #include <dev/isa/ahareg.h>
+ #include <dev/isa/btreg.h>		/* Avoid aha154x-compat mode of buslogic cards */
  
  #ifndef DDB
  #define Debugger() panic("should call debugger here (aha1542.c)")
***************
*** 200,205 ****
--- 201,207 ----
  	int wait;
  	u_char sts;
  	u_char opcode = ibuf[0];
+ 	int rbytes;	/* count of bytes actually returned in obuf */
  
  	if (sc != NULL)
  		name = sc->sc_dev.dv_xname;
***************
*** 232,238 ****
  		if (!i) {
  			printf("%s: aha_cmd, host not idle(0x%x)\n",
  			    name, sts);
! 			return ENXIO;
  		}
  	}
  	/*
--- 234,240 ----
  		if (!i) {
  			printf("%s: aha_cmd, host not idle(0x%x)\n",
  			    name, sts);
! 			return (-1);
  		}
  	}
  	/*
***************
*** 258,264 ****
  			if (opcode != AHA_INQUIRE_REVISION)
  				printf("%s: aha_cmd, cmd/data port full\n", name);
  			outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
! 			return ENXIO;
  		}
  		outb(iobase + AHA_CMD_PORT, *ibuf++);
  	}
--- 260,266 ----
  			if (opcode != AHA_INQUIRE_REVISION)
  				printf("%s: aha_cmd, cmd/data port full\n", name);
  			outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
! 			return (-1);
  		}
  		outb(iobase + AHA_CMD_PORT, *ibuf++);
  	}
***************
*** 266,272 ****
  	 * If we expect input, loop that many times, each time,
  	 * looking for the data register to have valid data
  	 */
! 	while (ocnt--) {
  		for (i = wait; i; i--) {
  			sts = inb(iobase + AHA_STAT_PORT);
  			if (sts & AHA_STAT_DF)
--- 268,275 ----
  	 * If we expect input, loop that many times, each time,
  	 * looking for the data register to have valid data
  	 */
! 	rbytes = 0;
! 	while (rbytes < ocnt) {
  		for (i = wait; i; i--) {
  			sts = inb(iobase + AHA_STAT_PORT);
  			if (sts & AHA_STAT_DF)
***************
*** 278,287 ****
  				printf("%s: aha_cmd, cmd/data port empty %d\n",
  				    name, ocnt);
  			outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
! 			return ENXIO;
  		}
  		*obuf++ = inb(iobase + AHA_DATA_PORT);
  	}
  	/*
  	 * Wait for the board to report a finished instruction.
  	 * We may get an extra interrupt for the HACC signal, but this is
--- 281,292 ----
  				printf("%s: aha_cmd, cmd/data port empty %d\n",
  				    name, ocnt);
  			outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
! 			return (-1);
  		}
  		*obuf++ = inb(iobase + AHA_DATA_PORT);
+  		rbytes++;
  	}
+ 
  	/*
  	 * Wait for the board to report a finished instruction.
  	 * We may get an extra interrupt for the HACC signal, but this is
***************
*** 298,308 ****
  		if (!i) {
  			printf("%s: aha_cmd, host not finished(0x%x)\n",
  			    name, sts);
! 			return ENXIO;
  		}
  	}
  	outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
! 	return 0;
  }
  
  /*
--- 303,313 ----
  		if (!i) {
  			printf("%s: aha_cmd, host not finished(0x%x)\n",
  			    name, sts);
! 			return (-1);
  		}
  	}
  	outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
! 	return rbytes;
  }
  
  /*
***************
*** 806,812 ****
  }
  
  /*
!  * Find the board and find its irq/drq
   */
  int
  aha_find(ia, sc)
--- 811,818 ----
  }
  
  /*
!  * Find the board and find its irq/drq.
!  * return 0 if a board is found, 1 otherwise.
   */
  int
  aha_find(ia, sc)
***************
*** 818,823 ****
--- 824,830 ----
  	u_char sts;
  	struct aha_config config;
  	int irq, drq;
+ 	struct bt_extended_inquire inquire;	/* to detect bha devices */
  
  	/*
  	 * reset board, If it doesn't respond, assume
***************
*** 838,843 ****
--- 845,872 ----
  		if (aha_debug)
  			printf("aha_find: No answer from adaptec board\n");
  #endif /* AHADEBUG */
+ 		return 1;
+ 	}
+ 
+ 	/*
+ 	/*
+ 	 * Make sure this isn't a BusLogic card.
+ 	 * Some 1542Cs (CP, perhaps not CF, may depend on firmware rev)
+ 	 * have the extended-geometry register and also respond to
+ 	 * BT_INQUIRE_EXTENDED.  Make sure we never  match such cards,
+ 	 * by checking the size of the reply is what a BusLogic card returns.
+ 	 */
+ 	delay(1000);
+ 	inquire.cmd.opcode = BT_INQUIRE_EXTENDED;
+ 	inquire.cmd.len = sizeof(inquire.reply);
+ 	i = bt_cmd(iobase, sc, sizeof(inquire.cmd), (u_char *)&inquire.cmd,
+ 	    sizeof(inquire.reply), (u_char *)&inquire.reply);
+ 
+ 	if (i == sizeof(inquire.reply)) {
+ #ifdef AHADEBUG
+ 		printf("aha_find: board returned %d instead of %d to %s\n",
+ 		       i, sizeof(inquire.reply), "INQUIRE_EXTENDED");
+ #endif
  		return 1;
  	}