si_isa.c revision 127135
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 */
2156505Speter
22119419Sobrien#include <sys/cdefs.h>
23119419Sobrien__FBSDID("$FreeBSD: head/sys/dev/si/si_isa.c 127135 2004-03-17 17:50:55Z njl $");
24119419Sobrien
2556505Speter#include "opt_debug_si.h"
2656505Speter
2756505Speter#include <sys/param.h>
2856505Speter#include <sys/systm.h>
2956505Speter#include <sys/kernel.h>
3056505Speter#include <sys/bus.h>
3156505Speter#include <machine/bus.h>
3256505Speter#include <sys/rman.h>
3356505Speter#include <machine/resource.h>
3456505Speter
3556505Speter#include <dev/si/sireg.h>
3656505Speter#include <dev/si/sivar.h>
3756505Speter
3856505Speter#include <isa/isavar.h>
3956505Speter
4056505Speter/* Look for a valid board at the given mem addr */
4156505Speterstatic int
4256505Spetersi_isa_probe(device_t dev)
4356505Speter{
4456505Speter	struct si_softc *sc;
4556505Speter	int type;
4656505Speter	u_int i, ramsize;
4756505Speter	volatile unsigned char was, *ux;
4856505Speter	volatile unsigned char *maddr;
4956505Speter	unsigned char *paddr;
5056505Speter	int unit;
5156505Speter
52100744Speter	/* No pnp support */
53100744Speter	if (isa_get_vendorid(dev))
54100744Speter		return (ENXIO);
55100744Speter
5656505Speter	sc = device_get_softc(dev);
5756505Speter	unit = device_get_unit(dev);
5856505Speter
5956505Speter	sc->sc_mem_rid = 0;
6056505Speter	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
6156505Speter					    &sc->sc_mem_rid,
6256505Speter					    0, ~0, SIPROBEALLOC, RF_ACTIVE);
63100744Speter	if (!sc->sc_mem_res) {
64100744Speter		device_printf(dev, "cannot allocate memory resource\n");
6556505Speter		return ENXIO;
66100744Speter	}
6756505Speter	paddr = (caddr_t)rman_get_start(sc->sc_mem_res);/* physical */
6856505Speter	maddr = rman_get_virtual(sc->sc_mem_res);	/* in kvm */
6956505Speter
7056505Speter	DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n",
7156505Speter		unit, maddr, paddr));
7256505Speter
7356505Speter	/*
7456505Speter	 * this is a lie, but it's easier than trying to handle caching
7556505Speter	 * and ram conflicts in the >1M and <16M region.
7656505Speter	 */
7756505Speter	if ((caddr_t)paddr < (caddr_t)0xA0000 ||
7856505Speter	    (caddr_t)paddr >= (caddr_t)0x100000) {
79100744Speter		device_printf(dev, "maddr (%p) out of range\n", paddr);
8056505Speter		goto fail;
8156505Speter	}
8256505Speter
83106572Sjhb	if (((uintptr_t)paddr & 0x7fff) != 0) {
84100744Speter		device_printf(dev, "maddr (%p) not on 32k boundary\n", paddr);
8556505Speter		goto fail;
8656505Speter	}
8756505Speter
8856505Speter	/* Is there anything out there? (0x17 is just an arbitrary number) */
8956505Speter	*maddr = 0x17;
9056505Speter	if (*maddr != 0x17) {
91100744Speter		device_printf(dev, "0x17 check fail at phys %p\n", paddr);
9256505Speter		goto fail;
9356505Speter	}
9456505Speter	/*
9556505Speter	 * Let's look first for a JET ISA card, since that's pretty easy
9656505Speter	 *
9756505Speter	 * All jet hosts are supposed to have this string in the IDROM,
9856505Speter	 * but it's not worth checking on self-IDing busses like PCI.
9956505Speter	 */
10056505Speter	{
10156505Speter		unsigned char *jet_chk_str = "JET HOST BY KEV#";
10256505Speter
10356505Speter		for (i = 0; i < strlen(jet_chk_str); i++)
10456505Speter			if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i))
10556505Speter				goto try_mk2;
10656505Speter	}
10756505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET first check - 0x%x\n",
10856505Speter		unit, (*(maddr+SIJETIDBASE))));
10956505Speter	if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff))
11056505Speter		goto try_mk2;
11156505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET second check - 0x%x\n",
11256505Speter		unit, (*(maddr+SIJETIDBASE+2))));
11356505Speter	if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8))
11456505Speter		goto try_mk2;
11556505Speter	/* It must be a Jet ISA or RIO card */
11656505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET id check - 0x%x\n",
11756505Speter		unit, (*(maddr+SIUNIQID))));
11856505Speter	if ((*(maddr+SIUNIQID) & 0xf0) != 0x20)
11956505Speter		goto try_mk2;
12056505Speter	/* It must be a Jet ISA SI/XIO card */
12156505Speter	*(maddr + SIJETCONFIG) = 0;
12256505Speter	type = SIJETISA;
12356505Speter	ramsize = SIJET_RAMSIZE;
12456505Speter	goto got_card;
12556505Speter
12656505Spetertry_mk2:
12756505Speter	/*
12856505Speter	 * OK, now to see if whatever responded is really an SI card.
12956505Speter	 * Try for a MK II next (SIHOST2)
13056505Speter	 */
13156505Speter	for (i = SIPLSIG; i < SIPLSIG + 8; i++)
13256505Speter		if ((*(maddr+i) & 7) != (~(unsigned char)i & 7))
13356505Speter			goto try_mk1;
13456505Speter
13556505Speter	/* It must be an SIHOST2 */
13656505Speter	*(maddr + SIPLRESET) = 0;
13756505Speter	*(maddr + SIPLIRQCLR) = 0;
13856505Speter	*(maddr + SIPLIRQSET) = 0x10;
13956505Speter	type = SIHOST2;
14056505Speter	ramsize = SIHOST2_RAMSIZE;
14156505Speter	goto got_card;
14256505Speter
14356505Spetertry_mk1:
14456505Speter	/*
14556505Speter	 * Its not a MK II, so try for a MK I (SIHOST)
14656505Speter	 */
14756505Speter	*(maddr+SIRESET) = 0x0;		/* reset the card */
14856505Speter	*(maddr+SIINTCL) = 0x0;		/* clear int */
14956505Speter	*(maddr+SIRAM) = 0x17;
15056505Speter	if (*(maddr+SIRAM) != (unsigned char)0x17)
15156505Speter		goto fail;
15256505Speter	*(maddr+0x7ff8) = 0x17;
15356505Speter	if (*(maddr+0x7ff8) != (unsigned char)0x17) {
154100744Speter		device_printf(dev, "0x17 check fail at phys %p = 0x%x\n",
155100744Speter		    paddr+0x77f8, *(maddr+0x77f8));
15656505Speter		goto fail;
15756505Speter	}
15856505Speter
15956505Speter	/* It must be an SIHOST (maybe?) - there must be a better way XXX */
16056505Speter	type = SIHOST;
16156505Speter	ramsize = SIHOST_RAMSIZE;
16256505Speter
16356505Spetergot_card:
16456505Speter	DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n",
16556505Speter		unit, type));
16656505Speter	/* Try the acid test */
16756505Speter	ux = maddr + SIRAM;
16856505Speter	for (i = 0; i < ramsize; i++, ux++)
16956505Speter		*ux = (unsigned char)(i&0xff);
17056505Speter	ux = maddr + SIRAM;
17156505Speter	for (i = 0; i < ramsize; i++, ux++) {
17256505Speter		if ((was = *ux) != (unsigned char)(i&0xff)) {
173100744Speter			device_printf(dev,
174100744Speter			    "memtest fail at phys %p, was %x should be %x\n",
175100744Speter			    paddr + i, was, i & 0xff);
17656505Speter			goto fail;
17756505Speter		}
17856505Speter	}
17956505Speter
18056505Speter	/* clear out the RAM */
18156505Speter	ux = maddr + SIRAM;
18256505Speter	for (i = 0; i < ramsize; i++)
18356505Speter		*ux++ = 0;
18456505Speter	ux = maddr + SIRAM;
18556505Speter	for (i = 0; i < ramsize; i++) {
18656505Speter		if ((was = *ux++) != 0) {
187100744Speter			device_printf(dev, "clear fail at phys %p, was %x\n",
188100744Speter			    paddr + i, was);
18956505Speter			goto fail;
19056505Speter		}
19156505Speter	}
19256505Speter
19356505Speter	/*
19456505Speter	 * Success, we've found a valid board, now fill in
19556505Speter	 * the adapter structure.
19656505Speter	 */
19756505Speter	switch (type) {
19856505Speter	case SIHOST2:
19956505Speter		switch (isa_get_irq(dev)) {
20056505Speter		case 11:
20156505Speter		case 12:
20256505Speter		case 15:
20356505Speter			break;
20456505Speter		default:
205100744Speter			device_printf(dev,
206100744Speter			    "bad IRQ value - %d (11, 12, 15 allowed)\n",
207100744Speter			    isa_get_irq(dev));
20856505Speter			goto fail;
20956505Speter		}
21056505Speter		sc->sc_memsize = SIHOST2_MEMSIZE;
21156505Speter		break;
21256505Speter	case SIHOST:
21356505Speter		switch (isa_get_irq(dev)) {
21456505Speter		case 11:
21556505Speter		case 12:
21656505Speter		case 15:
21756505Speter			break;
21856505Speter		default:
219100744Speter			device_printf(dev,
220100744Speter			    "bad IRQ value - %d (11, 12, 15 allowed)\n",
221100744Speter			    isa_get_irq(dev));
222100744Speter			goto fail;
22356505Speter		}
22456505Speter		sc->sc_memsize = SIHOST_MEMSIZE;
22556505Speter		break;
22656505Speter	case SIJETISA:
22756505Speter		switch (isa_get_irq(dev)) {
22856505Speter		case 9:
22956505Speter		case 10:
23056505Speter		case 11:
23156505Speter		case 12:
23256505Speter		case 15:
23356505Speter			break;
23456505Speter		default:
235100744Speter			device_printf(dev,
236100744Speter			    "bad IRQ value - %d (9, 10, 11, 12, 15 allowed)\n",
237100744Speter			    isa_get_irq(dev));
238100744Speter			goto fail;
23956505Speter		}
24056505Speter		sc->sc_memsize = SIJETISA_MEMSIZE;
24156505Speter		break;
24256505Speter	case SIMCA:		/* MCA */
24356505Speter	default:
244100744Speter		device_printf(dev, "card type %d not supported\n", type);
24556505Speter		goto fail;
24656505Speter	}
24756505Speter	sc->sc_type = type;
24856505Speter	bus_release_resource(dev, SYS_RES_MEMORY,
24956505Speter			     sc->sc_mem_rid, sc->sc_mem_res);
25056505Speter	sc->sc_mem_res = 0;
25156505Speter	return (0);		/* success! */
25256505Speter
25356505Speterfail:
25456505Speter	if (sc->sc_mem_res) {
25556505Speter		bus_release_resource(dev, SYS_RES_MEMORY,
25656505Speter				     sc->sc_mem_rid, sc->sc_mem_res);
25756505Speter		sc->sc_mem_res = 0;
25856505Speter	}
25956505Speter	return(EINVAL);
26056505Speter}
26156505Speter
26256505Speterstatic int
26356505Spetersi_isa_attach(device_t dev)
26456505Speter{
26556505Speter	int error;
26656505Speter	void *ih;
26756505Speter	struct si_softc *sc;
26856505Speter
26956505Speter	error = 0;
27056505Speter	ih = NULL;
27156505Speter	sc = device_get_softc(dev);
27256505Speter
27356505Speter	sc->sc_mem_rid = 0;
274127135Snjl	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
275127135Snjl						&sc->sc_mem_rid,
276127135Snjl						RF_ACTIVE);
27756505Speter	if (!sc->sc_mem_res) {
27856505Speter		device_printf(dev, "couldn't map memory\n");
27956505Speter		goto fail;
28056505Speter	}
28156505Speter	sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_mem_res);
28256505Speter	sc->sc_maddr = rman_get_virtual(sc->sc_mem_res);
28356505Speter
28456505Speter	sc->sc_irq_rid = 0;
285127135Snjl	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
286127135Snjl						&sc->sc_irq_rid,
287127135Snjl						RF_ACTIVE | RF_SHAREABLE);
28856505Speter	if (!sc->sc_irq_res) {
28956505Speter		device_printf(dev, "couldn't allocate interrupt\n");
29056505Speter		goto fail;
29156505Speter	}
29256505Speter	sc->sc_irq = rman_get_start(sc->sc_irq_res);
29356505Speter	error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY,
29456505Speter			       si_intr, sc,&ih);
29556505Speter	if (error) {
29656505Speter		device_printf(dev, "couldn't activate interrupt\n");
29756505Speter		goto fail;
29856505Speter	}
29956505Speter
30056505Speter	error = siattach(dev);
30156505Speter	if (error)
30256505Speter		goto fail;
30356505Speter	return (0);		/* success */
30456505Speter
30556505Speterfail:
30656505Speter	if (error == 0)
30756505Speter		error = ENXIO;
30856505Speter	if (sc->sc_irq_res) {
30956505Speter		if (ih)
31056505Speter			bus_teardown_intr(dev, sc->sc_irq_res, ih);
31156505Speter		bus_release_resource(dev, SYS_RES_IRQ,
31256505Speter				     sc->sc_irq_rid, sc->sc_irq_res);
31356505Speter		sc->sc_irq_res = 0;
31456505Speter	}
31556505Speter	if (sc->sc_mem_res) {
31656505Speter		bus_release_resource(dev, SYS_RES_MEMORY,
31756505Speter				     sc->sc_mem_rid, sc->sc_mem_res);
31856505Speter		sc->sc_mem_res = 0;
31956505Speter	}
32056505Speter	return (error);
32156505Speter}
32256505Speter
32356505Speterstatic device_method_t si_isa_methods[] = {
32456505Speter	/* Device interface */
32556505Speter	DEVMETHOD(device_probe,		si_isa_probe),
32656505Speter	DEVMETHOD(device_attach,	si_isa_attach),
32756505Speter
32856505Speter	{ 0, 0 }
32956505Speter};
33056505Speter
33156505Speterstatic driver_t si_isa_driver = {
33256505Speter	"si",
33356505Speter	si_isa_methods,
33456505Speter	sizeof(struct si_softc),
33556505Speter};
33656505Speter
33756505SpeterDRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0);
338