si_isa.c revision 106572
156505Speter/*
256505Speter * Device driver for Specialix range (SI/XIO) of serial line multiplexors.
356505Speter *
456505Speter * Copyright (C) 2000, Peter Wemm <peter@netplex.com.au>
556505Speter *
656505Speter * Redistribution and use in source and binary forms, with or without
756505Speter * modification, are permitted provided that the following conditions
856505Speter * are met:
956505Speter * 1. Redistributions of source code must retain the above copyright
1056505Speter *    notices, this list of conditions and the following disclaimer.
1156505Speter * 2. Redistributions in binary form must reproduce the above copyright
1256505Speter *    notices, this list of conditions and the following disclaimer in the
1356505Speter *    documentation and/or other materials provided with the distribution.
1456505Speter *
1556505Speter * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
1656505Speter * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1756505Speter * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
1856505Speter * NO EVENT SHALL THE AUTHORS BE LIABLE.
1956505Speter *
2056505Speter * $FreeBSD: head/sys/dev/si/si_isa.c 106572 2002-11-07 19:56:21Z jhb $
2156505Speter */
2256505Speter
2356505Speter#include "opt_debug_si.h"
2456505Speter
2556505Speter#include <sys/param.h>
2656505Speter#include <sys/systm.h>
2756505Speter#include <sys/kernel.h>
2856505Speter#include <sys/bus.h>
2956505Speter#include <machine/bus.h>
3056505Speter#include <sys/rman.h>
3156505Speter#include <machine/resource.h>
3256505Speter
3356505Speter#include <dev/si/sireg.h>
3456505Speter#include <dev/si/sivar.h>
3556505Speter
3656505Speter#include <isa/isavar.h>
3756505Speter
3856505Speter/* Look for a valid board at the given mem addr */
3956505Speterstatic int
4056505Spetersi_isa_probe(device_t dev)
4156505Speter{
4256505Speter	struct si_softc *sc;
4356505Speter	int type;
4456505Speter	u_int i, ramsize;
4556505Speter	volatile unsigned char was, *ux;
4656505Speter	volatile unsigned char *maddr;
4756505Speter	unsigned char *paddr;
4856505Speter	int unit;
4956505Speter
50100744Speter	/* No pnp support */
51100744Speter	if (isa_get_vendorid(dev))
52100744Speter		return (ENXIO);
53100744Speter
5456505Speter	sc = device_get_softc(dev);
5556505Speter	unit = device_get_unit(dev);
5656505Speter
5756505Speter	sc->sc_mem_rid = 0;
5856505Speter	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
5956505Speter					    &sc->sc_mem_rid,
6056505Speter					    0, ~0, SIPROBEALLOC, RF_ACTIVE);
61100744Speter	if (!sc->sc_mem_res) {
62100744Speter		device_printf(dev, "cannot allocate memory resource\n");
6356505Speter		return ENXIO;
64100744Speter	}
6556505Speter	paddr = (caddr_t)rman_get_start(sc->sc_mem_res);/* physical */
6656505Speter	maddr = rman_get_virtual(sc->sc_mem_res);	/* in kvm */
6756505Speter
6856505Speter	DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n",
6956505Speter		unit, maddr, paddr));
7056505Speter
7156505Speter	/*
7256505Speter	 * this is a lie, but it's easier than trying to handle caching
7356505Speter	 * and ram conflicts in the >1M and <16M region.
7456505Speter	 */
7556505Speter	if ((caddr_t)paddr < (caddr_t)0xA0000 ||
7656505Speter	    (caddr_t)paddr >= (caddr_t)0x100000) {
77100744Speter		device_printf(dev, "maddr (%p) out of range\n", paddr);
7856505Speter		goto fail;
7956505Speter	}
8056505Speter
81106572Sjhb	if (((uintptr_t)paddr & 0x7fff) != 0) {
82100744Speter		device_printf(dev, "maddr (%p) not on 32k boundary\n", paddr);
8356505Speter		goto fail;
8456505Speter	}
8556505Speter
8656505Speter	/* Is there anything out there? (0x17 is just an arbitrary number) */
8756505Speter	*maddr = 0x17;
8856505Speter	if (*maddr != 0x17) {
89100744Speter		device_printf(dev, "0x17 check fail at phys %p\n", paddr);
9056505Speter		goto fail;
9156505Speter	}
9256505Speter	/*
9356505Speter	 * Let's look first for a JET ISA card, since that's pretty easy
9456505Speter	 *
9556505Speter	 * All jet hosts are supposed to have this string in the IDROM,
9656505Speter	 * but it's not worth checking on self-IDing busses like PCI.
9756505Speter	 */
9856505Speter	{
9956505Speter		unsigned char *jet_chk_str = "JET HOST BY KEV#";
10056505Speter
10156505Speter		for (i = 0; i < strlen(jet_chk_str); i++)
10256505Speter			if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i))
10356505Speter				goto try_mk2;
10456505Speter	}
10556505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET first check - 0x%x\n",
10656505Speter		unit, (*(maddr+SIJETIDBASE))));
10756505Speter	if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff))
10856505Speter		goto try_mk2;
10956505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET second check - 0x%x\n",
11056505Speter		unit, (*(maddr+SIJETIDBASE+2))));
11156505Speter	if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8))
11256505Speter		goto try_mk2;
11356505Speter	/* It must be a Jet ISA or RIO card */
11456505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET id check - 0x%x\n",
11556505Speter		unit, (*(maddr+SIUNIQID))));
11656505Speter	if ((*(maddr+SIUNIQID) & 0xf0) != 0x20)
11756505Speter		goto try_mk2;
11856505Speter	/* It must be a Jet ISA SI/XIO card */
11956505Speter	*(maddr + SIJETCONFIG) = 0;
12056505Speter	type = SIJETISA;
12156505Speter	ramsize = SIJET_RAMSIZE;
12256505Speter	goto got_card;
12356505Speter
12456505Spetertry_mk2:
12556505Speter	/*
12656505Speter	 * OK, now to see if whatever responded is really an SI card.
12756505Speter	 * Try for a MK II next (SIHOST2)
12856505Speter	 */
12956505Speter	for (i = SIPLSIG; i < SIPLSIG + 8; i++)
13056505Speter		if ((*(maddr+i) & 7) != (~(unsigned char)i & 7))
13156505Speter			goto try_mk1;
13256505Speter
13356505Speter	/* It must be an SIHOST2 */
13456505Speter	*(maddr + SIPLRESET) = 0;
13556505Speter	*(maddr + SIPLIRQCLR) = 0;
13656505Speter	*(maddr + SIPLIRQSET) = 0x10;
13756505Speter	type = SIHOST2;
13856505Speter	ramsize = SIHOST2_RAMSIZE;
13956505Speter	goto got_card;
14056505Speter
14156505Spetertry_mk1:
14256505Speter	/*
14356505Speter	 * Its not a MK II, so try for a MK I (SIHOST)
14456505Speter	 */
14556505Speter	*(maddr+SIRESET) = 0x0;		/* reset the card */
14656505Speter	*(maddr+SIINTCL) = 0x0;		/* clear int */
14756505Speter	*(maddr+SIRAM) = 0x17;
14856505Speter	if (*(maddr+SIRAM) != (unsigned char)0x17)
14956505Speter		goto fail;
15056505Speter	*(maddr+0x7ff8) = 0x17;
15156505Speter	if (*(maddr+0x7ff8) != (unsigned char)0x17) {
152100744Speter		device_printf(dev, "0x17 check fail at phys %p = 0x%x\n",
153100744Speter		    paddr+0x77f8, *(maddr+0x77f8));
15456505Speter		goto fail;
15556505Speter	}
15656505Speter
15756505Speter	/* It must be an SIHOST (maybe?) - there must be a better way XXX */
15856505Speter	type = SIHOST;
15956505Speter	ramsize = SIHOST_RAMSIZE;
16056505Speter
16156505Spetergot_card:
16256505Speter	DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n",
16356505Speter		unit, type));
16456505Speter	/* Try the acid test */
16556505Speter	ux = maddr + SIRAM;
16656505Speter	for (i = 0; i < ramsize; i++, ux++)
16756505Speter		*ux = (unsigned char)(i&0xff);
16856505Speter	ux = maddr + SIRAM;
16956505Speter	for (i = 0; i < ramsize; i++, ux++) {
17056505Speter		if ((was = *ux) != (unsigned char)(i&0xff)) {
171100744Speter			device_printf(dev,
172100744Speter			    "memtest fail at phys %p, was %x should be %x\n",
173100744Speter			    paddr + i, was, i & 0xff);
17456505Speter			goto fail;
17556505Speter		}
17656505Speter	}
17756505Speter
17856505Speter	/* clear out the RAM */
17956505Speter	ux = maddr + SIRAM;
18056505Speter	for (i = 0; i < ramsize; i++)
18156505Speter		*ux++ = 0;
18256505Speter	ux = maddr + SIRAM;
18356505Speter	for (i = 0; i < ramsize; i++) {
18456505Speter		if ((was = *ux++) != 0) {
185100744Speter			device_printf(dev, "clear fail at phys %p, was %x\n",
186100744Speter			    paddr + i, was);
18756505Speter			goto fail;
18856505Speter		}
18956505Speter	}
19056505Speter
19156505Speter	/*
19256505Speter	 * Success, we've found a valid board, now fill in
19356505Speter	 * the adapter structure.
19456505Speter	 */
19556505Speter	switch (type) {
19656505Speter	case SIHOST2:
19756505Speter		switch (isa_get_irq(dev)) {
19856505Speter		case 11:
19956505Speter		case 12:
20056505Speter		case 15:
20156505Speter			break;
20256505Speter		default:
203100744Speter			device_printf(dev,
204100744Speter			    "bad IRQ value - %d (11, 12, 15 allowed)\n",
205100744Speter			    isa_get_irq(dev));
20656505Speter			goto fail;
20756505Speter		}
20856505Speter		sc->sc_memsize = SIHOST2_MEMSIZE;
20956505Speter		break;
21056505Speter	case SIHOST:
21156505Speter		switch (isa_get_irq(dev)) {
21256505Speter		case 11:
21356505Speter		case 12:
21456505Speter		case 15:
21556505Speter			break;
21656505Speter		default:
217100744Speter			device_printf(dev,
218100744Speter			    "bad IRQ value - %d (11, 12, 15 allowed)\n",
219100744Speter			    isa_get_irq(dev));
220100744Speter			goto fail;
22156505Speter		}
22256505Speter		sc->sc_memsize = SIHOST_MEMSIZE;
22356505Speter		break;
22456505Speter	case SIJETISA:
22556505Speter		switch (isa_get_irq(dev)) {
22656505Speter		case 9:
22756505Speter		case 10:
22856505Speter		case 11:
22956505Speter		case 12:
23056505Speter		case 15:
23156505Speter			break;
23256505Speter		default:
233100744Speter			device_printf(dev,
234100744Speter			    "bad IRQ value - %d (9, 10, 11, 12, 15 allowed)\n",
235100744Speter			    isa_get_irq(dev));
236100744Speter			goto fail;
23756505Speter		}
23856505Speter		sc->sc_memsize = SIJETISA_MEMSIZE;
23956505Speter		break;
24056505Speter	case SIMCA:		/* MCA */
24156505Speter	default:
242100744Speter		device_printf(dev, "card type %d not supported\n", type);
24356505Speter		goto fail;
24456505Speter	}
24556505Speter	sc->sc_type = type;
24656505Speter	bus_release_resource(dev, SYS_RES_MEMORY,
24756505Speter			     sc->sc_mem_rid, sc->sc_mem_res);
24856505Speter	sc->sc_mem_res = 0;
24956505Speter	return (0);		/* success! */
25056505Speter
25156505Speterfail:
25256505Speter	if (sc->sc_mem_res) {
25356505Speter		bus_release_resource(dev, SYS_RES_MEMORY,
25456505Speter				     sc->sc_mem_rid, sc->sc_mem_res);
25556505Speter		sc->sc_mem_res = 0;
25656505Speter	}
25756505Speter	return(EINVAL);
25856505Speter}
25956505Speter
26056505Speterstatic int
26156505Spetersi_isa_attach(device_t dev)
26256505Speter{
26356505Speter	int error;
26456505Speter	void *ih;
26556505Speter	struct si_softc *sc;
26656505Speter
26756505Speter	error = 0;
26856505Speter	ih = NULL;
26956505Speter	sc = device_get_softc(dev);
27056505Speter
27156505Speter	sc->sc_mem_rid = 0;
27256505Speter	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
27356505Speter					    &sc->sc_mem_rid,
27456505Speter					    0, ~0, 1, RF_ACTIVE);
27556505Speter	if (!sc->sc_mem_res) {
27656505Speter		device_printf(dev, "couldn't map memory\n");
27756505Speter		goto fail;
27856505Speter	}
27956505Speter	sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_mem_res);
28056505Speter	sc->sc_maddr = rman_get_virtual(sc->sc_mem_res);
28156505Speter
28256505Speter	sc->sc_irq_rid = 0;
28356505Speter	sc->sc_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irq_rid,
28456505Speter					    0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
28556505Speter	if (!sc->sc_irq_res) {
28656505Speter		device_printf(dev, "couldn't allocate interrupt\n");
28756505Speter		goto fail;
28856505Speter	}
28956505Speter	sc->sc_irq = rman_get_start(sc->sc_irq_res);
29056505Speter	error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY,
29156505Speter			       si_intr, sc,&ih);
29256505Speter	if (error) {
29356505Speter		device_printf(dev, "couldn't activate interrupt\n");
29456505Speter		goto fail;
29556505Speter	}
29656505Speter
29756505Speter	error = siattach(dev);
29856505Speter	if (error)
29956505Speter		goto fail;
30056505Speter	return (0);		/* success */
30156505Speter
30256505Speterfail:
30356505Speter	if (error == 0)
30456505Speter		error = ENXIO;
30556505Speter	if (sc->sc_irq_res) {
30656505Speter		if (ih)
30756505Speter			bus_teardown_intr(dev, sc->sc_irq_res, ih);
30856505Speter		bus_release_resource(dev, SYS_RES_IRQ,
30956505Speter				     sc->sc_irq_rid, sc->sc_irq_res);
31056505Speter		sc->sc_irq_res = 0;
31156505Speter	}
31256505Speter	if (sc->sc_mem_res) {
31356505Speter		bus_release_resource(dev, SYS_RES_MEMORY,
31456505Speter				     sc->sc_mem_rid, sc->sc_mem_res);
31556505Speter		sc->sc_mem_res = 0;
31656505Speter	}
31756505Speter	return (error);
31856505Speter}
31956505Speter
32056505Speterstatic device_method_t si_isa_methods[] = {
32156505Speter	/* Device interface */
32256505Speter	DEVMETHOD(device_probe,		si_isa_probe),
32356505Speter	DEVMETHOD(device_attach,	si_isa_attach),
32456505Speter
32556505Speter	{ 0, 0 }
32656505Speter};
32756505Speter
32856505Speterstatic driver_t si_isa_driver = {
32956505Speter	"si",
33056505Speter	si_isa_methods,
33156505Speter	sizeof(struct si_softc),
33256505Speter};
33356505Speter
33456505SpeterDRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0);
335