Home | History | Annotate | Line # | Download | only in isa
ahc_isa.c revision 1.1
      1 /*	$NetBSD: ahc_isa.c,v 1.1 1996/08/05 21:14:29 soda Exp $	*/
      2 
      3 /*
      4  * Product specific probe and attach routines for:
      5  * 	284X VLbus SCSI controllers
      6  *
      7  * Copyright (c) 1996 Jason R. Thorpe.
      8  * All rights reserved.
      9  *
     10  * Copyright (c) 1995, 1996 Christopher G. Demetriou.
     11  * All rights reserved.
     12  *
     13  * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs.
     14  * All rights reserved.
     15  *
     16  * Redistribution and use in source and binary forms, with or without
     17  * modification, are permitted provided that the following conditions
     18  * are met:
     19  * 1. Redistributions of source code must retain the above copyright
     20  *    notice immediately at the beginning of the file, without modification,
     21  *    this list of conditions, and the following disclaimer.
     22  * 2. Redistributions in binary form must reproduce the above copyright
     23  *    notice, this list of conditions and the following disclaimer in the
     24  *    documentation and/or other materials provided with the distribution.
     25  * 3. All advertising materials mentioning features or use of this software
     26  *    must display the following acknowledgement:
     27  *	This product includes software developed by Christopher G. Demetriou
     28  *	for the NetBSD Project.
     29  * 4. The name of the author may not be used to endorse or promote products
     30  *    derived from this software without specific prior written permission.
     31  *
     32  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     35  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
     36  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     42  * SUCH DAMAGE.
     43  */
     44 
     45 /*
     46  * This front-end driver is really sort of a hack.  The AHA-284X likes
     47  * to masquerade as an EISA device.  However, on VLbus machines with
     48  * no EISA signature in the BIOS, the EISA bus will never be scanned.
     49  * This is intended to catch the 284X controllers on those systems
     50  * by looking in "EISA i/o space" for 284X controllers.
     51  *
     52  * This relies heavily on i/o port accounting.  We also just use the
     53  * EISA macros for everything ... it's a real waste to redefine them.
     54  *
     55  * Note: there isn't any #ifdef for FreeBSD in this file, since the
     56  * FreeBSD EISA driver handles all cases of the 284X.
     57  *
     58  *	-- Jason R. Thorpe <thorpej (at) NetBSD.ORG>
     59  *	   July 12, 1996
     60  *
     61  * TODO: some code could be shared with ahc_eisa.c, but it would probably
     62  * be a logistical mightmare to even try.
     63  */
     64 
     65 #include <sys/param.h>
     66 #include <sys/systm.h>
     67 #include <sys/kernel.h>
     68 #include <sys/device.h>
     69 #include <sys/queue.h>
     70 #include <sys/malloc.h>
     71 
     72 #include <machine/bus.h>
     73 #include <machine/intr.h>
     74 
     75 #include <scsi/scsi_all.h>
     76 #include <scsi/scsiconf.h>
     77 
     78 #include <dev/isa/isavar.h>
     79 
     80 #include <dev/eisa/eisareg.h>
     81 #include <dev/eisa/eisavar.h>
     82 #include <dev/eisa/eisadevs.h>
     83 
     84 #include <dev/ic/aic7xxxreg.h>
     85 #include <dev/ic/aic7xxxvar.h>
     86 
     87 /* IO port address setting range as EISA slot number */
     88 #define AHC_ISA_MIN_SLOT	0x1	/* from iobase = 0x1c00 */
     89 #define AHC_ISA_MAX_SLOT	0xe	/* to   iobase = 0xec00 */
     90 
     91 #define AHC_ISA_SLOT_OFFSET	0xc00	/* offset from EISA IO space */
     92 #define AHC_ISA_IOSIZE		0x100
     93 
     94 /*
     95  * I/O port offsets
     96  */
     97 #define INTDEF			0x5cul	/* Interrupt Definition Register */
     98 #define	AHC_ISA_VID		(EISA_SLOTOFF_VID - AHC_ISA_SLOT_OFFSET)
     99 #define	AHC_ISA_PID		(EISA_SLOTOFF_PID - AHC_ISA_SLOT_OFFSET)
    100 #define	AHC_ISA_PRIMING		AHC_ISA_VID	/* enable vendor/product ID */
    101 
    102 /*
    103  * AHC_ISA_PRIMING register values (write)
    104  */
    105 #define	AHC_ISA_PRIMING_VID(index)	(AHC_ISA_VID + (index))
    106 #define	AHC_ISA_PRIMING_PID(index)	(AHC_ISA_PID + (index))
    107 
    108 int	ahc_isa_irq __P((bus_chipset_tag_t, bus_io_handle_t));
    109 int	ahc_isa_idstring __P((bus_chipset_tag_t, bus_io_handle_t, char *));
    110 int	ahc_isa_match __P((struct isa_attach_args *, bus_io_addr_t));
    111 
    112 int	ahc_isa_probe __P((struct device *, void *, void *));
    113 void	ahc_isa_attach __P((struct device *, struct device *, void *));
    114 
    115 struct cfattach ahc_isa_ca = {
    116 	sizeof(struct ahc_data), ahc_isa_probe, ahc_isa_attach
    117 };
    118 
    119 /*
    120  * This keeps track of which slots are to be checked next if the
    121  * iobase locator is a wildcard.  A simple static variable isn't enough,
    122  * since it's conceivable that a system might have more than one ISA
    123  * bus.
    124  *
    125  * The "bus" member is the unit number of the parent ISA bus, e.g. "0"
    126  * for "isa0".
    127  */
    128 struct ahc_isa_slot {
    129 	LIST_ENTRY(ahc_isa_slot)	link;
    130 	int				bus;
    131 	int				slot;
    132 };
    133 static LIST_HEAD(, ahc_isa_slot) ahc_isa_all_slots;
    134 static int ahc_isa_slot_initialized;
    135 
    136 /*
    137  * Return irq setting of the board, otherwise -1.
    138  */
    139 int
    140 ahc_isa_irq(bc, ioh)
    141 	bus_chipset_tag_t bc;
    142 	bus_io_handle_t ioh;
    143 {
    144 	int irq;
    145 	u_char intdef;
    146 
    147 	ahc_reset("ahc_isa", bc, ioh);
    148 	intdef = bus_io_read_1(bc, ioh, INTDEF);
    149 	switch (irq = (intdef & 0xf)) {
    150 	case 9:
    151 	case 10:
    152 	case 11:
    153 	case 12:
    154 	case 14:
    155 	case 15:
    156 		break;
    157 	default:
    158 		printf("ahc_isa_irq: illegal irq setting %d\n", intdef);
    159 		return -1;
    160 	}
    161 
    162 	/* Note that we are going and return (to probe) */
    163 	return irq;
    164 }
    165 
    166 int
    167 ahc_isa_idstring(bc, ioh, idstring)
    168 	bus_chipset_tag_t bc;
    169 	bus_io_handle_t ioh;
    170 	char *idstring;
    171 {
    172 	u_int8_t vid[EISA_NVIDREGS], pid[EISA_NPIDREGS];
    173 	int i;
    174 
    175 	/* Get the vendor ID bytes */
    176 	for (i = 0; i < EISA_NVIDREGS; i++) {
    177 		bus_io_write_1(bc, ioh, AHC_ISA_PRIMING,
    178 		    AHC_ISA_PRIMING_VID(i));
    179 		vid[i] = bus_io_read_1(bc, ioh, AHC_ISA_VID + i);
    180 	}
    181 
    182 	/* Check for device existence */
    183 	if (EISA_VENDID_NODEV(vid)) {
    184 #if 0
    185 		printf("ahc_isa_idstring: no device at 0x%lx\n",
    186 		    ioh); /* XXX knows about ioh guts */
    187 		printf("\t(0x%x, 0x%x)\n", vid[0], vid[1]);
    188 #endif
    189 		return (0);
    190 	}
    191 
    192 	/* And check that the firmware didn't biff something badly */
    193 	if (EISA_VENDID_IDDELAY(vid)) {
    194 		printf("ahc_isa_idstring: BIOS biffed it at 0x%lx\n",
    195 		    ioh);	/* XXX knows about ioh guts */
    196 		return (0);
    197 	}
    198 
    199 	/* Get the product ID bytes */
    200 	for (i = 0; i < EISA_NPIDREGS; i++) {
    201 		bus_io_write_1(bc, ioh, AHC_ISA_PRIMING,
    202 		    AHC_ISA_PRIMING_PID(i));
    203 		pid[i] = bus_io_read_1(bc, ioh, AHC_ISA_PID + i);
    204 	}
    205 
    206 	/* Create the ID string from the vendor and product IDs */
    207 	idstring[0] = EISA_VENDID_0(vid);
    208 	idstring[1] = EISA_VENDID_1(vid);
    209 	idstring[2] = EISA_VENDID_2(vid);
    210 	idstring[3] = EISA_PRODID_0(pid);
    211 	idstring[4] = EISA_PRODID_1(pid);
    212 	idstring[5] = EISA_PRODID_2(pid);
    213 	idstring[6] = EISA_PRODID_3(pid);
    214 	idstring[7] = '\0';		/* sanity */
    215 
    216 	return (1);
    217 }
    218 
    219 int
    220 ahc_isa_match(ia, iobase)
    221 	struct isa_attach_args *ia;
    222 	bus_io_addr_t iobase;
    223 {
    224 	bus_chipset_tag_t bc = ia->ia_bc;
    225 	bus_io_handle_t ioh;
    226 	int irq;
    227 	char idstring[EISA_IDSTRINGLEN];
    228 
    229 	/*
    230 	 * Get a mapping for the while slot-specific address
    231 	 * space.  If we can't, assume nothing's there, but
    232 	 * warn about it.
    233 	 */
    234 	if (bus_io_map(bc, iobase, AHC_ISA_IOSIZE, &ioh)) {
    235 #if 0
    236 		/*
    237 		 * Don't print anything out here, since this could
    238 		 * be common on machines configured to look for
    239 		 * ahc_eisa and ahc_isa.
    240 		 */
    241 		printf("ahc_isa_match: can't map I/O space for 0x%x\n",
    242 		    iobase);
    243 #endif
    244 		return (0);
    245 	}
    246 
    247 	if (!ahc_isa_idstring(bc, ioh, idstring))
    248 		irq = -1;	/* cannot get the ID string */
    249 	else if (strcmp(idstring, "ADP7756") &&
    250 	    strcmp(idstring, "ADP7757"))
    251 		irq = -1;	/* unknown ID strings */
    252 	else
    253 		irq = ahc_isa_irq(bc, ioh);
    254 
    255 	bus_io_unmap(bc, ioh, AHC_ISA_IOSIZE);
    256 
    257 	if (irq < 0)
    258 		return (0);
    259 
    260 	if (ia->ia_irq != IRQUNK &&
    261 	    ia->ia_irq != irq) {
    262 		printf("ahc_isa_match: irq mismatch (kernel %d, card %d)\n",
    263 		    ia->ia_irq, irq);
    264 		return (0);
    265 	}
    266 
    267 	/* We have a match */
    268 	ia->ia_iobase = iobase;
    269 	ia->ia_irq = irq;
    270 	ia->ia_iosize = AHC_ISA_IOSIZE;
    271 	ia->ia_msize = 0;
    272 	return (1);
    273 }
    274 
    275 /*
    276  * Check the slots looking for a board we recognise
    277  * If we find one, note it's address (slot) and call
    278  * the actual probe routine to check it out.
    279  */
    280 int
    281 ahc_isa_probe(parent, match, aux)
    282         struct device *parent;
    283         void *match, *aux;
    284 {
    285 	struct isa_attach_args *ia = aux;
    286 	struct ahc_isa_slot *as;
    287 
    288 	if (ahc_isa_slot_initialized == 0) {
    289 		LIST_INIT(&ahc_isa_all_slots);
    290 		ahc_isa_slot_initialized = 1;
    291 	}
    292 
    293 	if (ia->ia_iobase != IOBASEUNK)
    294 		return (ahc_isa_match(ia, ia->ia_iobase));
    295 
    296 	/*
    297 	 * Find this bus's state.  If we don't yet have a slot
    298 	 * marker, allocate and initialize one.
    299 	 */
    300 	for (as = ahc_isa_all_slots.lh_first; as != NULL;
    301 	    as = as->link.le_next)
    302 		if (as->bus == parent->dv_unit)
    303 			goto found_slot_marker;
    304 
    305 	/*
    306 	 * Don't have one, so make one.
    307 	 */
    308 	as = (struct ahc_isa_slot *)
    309 	    malloc(sizeof(struct ahc_isa_slot), M_DEVBUF, M_NOWAIT);
    310 	if (as == NULL)
    311 		panic("ahc_isa_probe: can't allocate slot marker");
    312 
    313 	as->bus = parent->dv_unit;
    314 	as->slot = AHC_ISA_MIN_SLOT;
    315 	LIST_INSERT_HEAD(&ahc_isa_all_slots, as, link);
    316 
    317  found_slot_marker:
    318 
    319 	for (; as->slot <= AHC_ISA_MAX_SLOT; as->slot++) {
    320 		if (ahc_isa_match(ia, EISA_SLOT_ADDR(as->slot) +
    321 		    AHC_ISA_SLOT_OFFSET)) {
    322 			as->slot++; /* next slot to search */
    323 			return (1);
    324 		}
    325 	}
    326 
    327 	/* No matching cards were found. */
    328 	return (0);
    329 }
    330 
    331 void
    332 ahc_isa_attach(parent, self, aux)
    333 	struct device *parent, *self;
    334 	void *aux;
    335 {
    336 	ahc_type type;
    337 	struct ahc_data *ahc = (void *)self;
    338 	struct isa_attach_args *ia = aux;
    339 	bus_chipset_tag_t bc = ia->ia_bc;
    340 	bus_io_handle_t ioh;
    341 	int irq;
    342 	char idstring[EISA_IDSTRINGLEN];
    343 	const char *model;
    344 
    345 	if (bus_io_map(bc, ia->ia_iobase, ia->ia_iosize, &ioh))
    346 		panic("ahc_isa_attach: could not map slot I/O addresses");
    347 	if (!ahc_isa_idstring(bc, ioh, idstring))
    348 		panic("ahc_isa_attach: could not read ID string");
    349 	if ((irq = ahc_isa_irq(bc, ioh)) < 0)
    350 		panic("ahc_isa_attach: ahc_isa_irq failed!");
    351 
    352 	if (strcmp(idstring, "ADP7756") == 0) {
    353 		model = EISA_PRODUCT_ADP7756;
    354 		type = AHC_284;
    355 	} else if (strcmp(idstring, "ADP7757") == 0) {
    356 		model = EISA_PRODUCT_ADP7757;
    357 		type = AHC_284;
    358 	} else {
    359 		panic("ahc_isa_attach: Unknown device type %s\n", idstring);
    360 	}
    361 	printf(": %s\n", model);
    362 
    363 	ahc_construct(ahc, bc, ioh, type, AHC_FNONE);
    364 
    365 	/*
    366 	 * Tell the user what type of interrupts we're using.
    367 	 * usefull for debugging irq problems
    368 	 */
    369 	printf( "%s: Using %s Interrupts\n", ahc_name(ahc),
    370 	    ahc->pause & IRQMS ?  "Level Sensitive" : "Edge Triggered");
    371 
    372 	/*
    373 	 * Now that we know we own the resources we need, do the
    374 	 * card initialization.
    375 	 *
    376 	 * First, the aic7770 card specific setup.
    377 	 */
    378 
    379 	/* XXX
    380 	 * On AHA-284x,
    381 	 * all values are automagically intialized at
    382 	 * POST for these cards, so we can always rely
    383 	 * on the Scratch Ram values.  However, we should
    384 	 * read the SEEPROM here (Dan has the code to do
    385 	 * it) so we can say what kind of translation the
    386 	 * BIOS is using.  Printing out the geometry could
    387 	 * save a lot of users the grief of failed installs.
    388 	 */
    389 
    390 	/*
    391 	 * See if we have a Rev E or higher aic7770. Anything below a
    392 	 * Rev E will have a R/O autoflush disable configuration bit.
    393 	 * It's still not clear exactly what is differenent about the Rev E.
    394 	 * We think it allows 8 bit entries in the QOUTFIFO to support
    395 	 * "paging" SCBs so you can have more than 4 commands active at
    396 	 * once.
    397 	 */
    398 	{
    399 		char *id_string;
    400 		u_char sblkctl;
    401 		u_char sblkctl_orig;
    402 
    403 		sblkctl_orig = AHC_INB(ahc, SBLKCTL);
    404 		sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
    405 		AHC_OUTB(ahc, SBLKCTL, sblkctl);
    406 		sblkctl = AHC_INB(ahc, SBLKCTL);
    407 		if(sblkctl != sblkctl_orig)
    408 		{
    409 			id_string = "aic7770 >= Rev E, ";
    410 			/*
    411 			 * Ensure autoflush is enabled
    412 			 */
    413 			sblkctl &= ~AUTOFLUSHDIS;
    414 			AHC_OUTB(ahc, SBLKCTL, sblkctl);
    415 
    416 			/* Allow paging on this adapter */
    417 			ahc->flags |= AHC_PAGESCBS;
    418 		}
    419 		else
    420 			id_string = "aic7770 <= Rev C, ";
    421 
    422 		printf("%s: %s", ahc_name(ahc), id_string);
    423 	}
    424 
    425 	/* Setup the FIFO threshold and the bus off time */
    426 	{
    427 		u_char hostconf = AHC_INB(ahc, HOSTCONF);
    428 		AHC_OUTB(ahc, BUSSPD, hostconf & DFTHRSH);
    429 		AHC_OUTB(ahc, BUSTIME, (hostconf << 2) & BOFF);
    430 	}
    431 
    432 	/*
    433 	 * Generic aic7xxx initialization.
    434 	 */
    435 	if(ahc_init(ahc)){
    436 		ahc_free(ahc);
    437 		return;
    438 	}
    439 
    440 	/*
    441 	 * Enable the board's BUS drivers
    442 	 */
    443 	AHC_OUTB(ahc, BCTL, ENABLE);
    444 
    445 	/*
    446 	 * The IRQMS bit enables level sensitive interrupts only allow
    447 	 * IRQ sharing if its set.
    448 	 */
    449 	ahc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
    450 	    ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_intr, ahc);
    451 	if (ahc->sc_ih == NULL) {
    452 		printf("%s: couldn't establish interrupt\n",
    453 		       ahc->sc_dev.dv_xname);
    454 		ahc_free(ahc);
    455 		return;
    456 	}
    457 
    458 	/* Attach sub-devices - always succeeds */
    459 	ahc_attach(ahc);
    460 }
    461