si_isa.c revision 56505
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 56505 2000-01-24 07:24:02Z peter $
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
5056505Speter	sc = device_get_softc(dev);
5156505Speter	unit = device_get_unit(dev);
5256505Speter
5356505Speter	sc->sc_mem_rid = 0;
5456505Speter	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
5556505Speter					    &sc->sc_mem_rid,
5656505Speter					    0, ~0, SIPROBEALLOC, RF_ACTIVE);
5756505Speter	if (!sc->sc_mem_res)
5856505Speter		return ENXIO;
5956505Speter	paddr = (caddr_t)rman_get_start(sc->sc_mem_res);/* physical */
6056505Speter	maddr = rman_get_virtual(sc->sc_mem_res);	/* in kvm */
6156505Speter
6256505Speter	DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n",
6356505Speter		unit, maddr, paddr));
6456505Speter
6556505Speter	/*
6656505Speter	 * this is a lie, but it's easier than trying to handle caching
6756505Speter	 * and ram conflicts in the >1M and <16M region.
6856505Speter	 */
6956505Speter	if ((caddr_t)paddr < (caddr_t)0xA0000 ||
7056505Speter	    (caddr_t)paddr >= (caddr_t)0x100000) {
7156505Speter		printf("si%d: iomem (%p) out of range\n",
7256505Speter			unit, (void *)paddr);
7356505Speter		goto fail;
7456505Speter	}
7556505Speter
7656505Speter	if (((u_int)paddr & 0x7fff) != 0) {
7756505Speter		DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
7856505Speter			"si%d: iomem (%x) not on 32k boundary\n", unit, paddr));
7956505Speter		goto fail;
8056505Speter	}
8156505Speter
8256505Speter	/* Is there anything out there? (0x17 is just an arbitrary number) */
8356505Speter	*maddr = 0x17;
8456505Speter	if (*maddr != 0x17) {
8556505Speter		DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
8656505Speter			"si%d: 0x17 check fail at phys 0x%x\n", unit, paddr));
8756505Speter		goto fail;
8856505Speter	}
8956505Speter	/*
9056505Speter	 * Let's look first for a JET ISA card, since that's pretty easy
9156505Speter	 *
9256505Speter	 * All jet hosts are supposed to have this string in the IDROM,
9356505Speter	 * but it's not worth checking on self-IDing busses like PCI.
9456505Speter	 */
9556505Speter	{
9656505Speter		unsigned char *jet_chk_str = "JET HOST BY KEV#";
9756505Speter
9856505Speter		for (i = 0; i < strlen(jet_chk_str); i++)
9956505Speter			if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i))
10056505Speter				goto try_mk2;
10156505Speter	}
10256505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET first check - 0x%x\n",
10356505Speter		unit, (*(maddr+SIJETIDBASE))));
10456505Speter	if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff))
10556505Speter		goto try_mk2;
10656505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET second check - 0x%x\n",
10756505Speter		unit, (*(maddr+SIJETIDBASE+2))));
10856505Speter	if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8))
10956505Speter		goto try_mk2;
11056505Speter	/* It must be a Jet ISA or RIO card */
11156505Speter	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET id check - 0x%x\n",
11256505Speter		unit, (*(maddr+SIUNIQID))));
11356505Speter	if ((*(maddr+SIUNIQID) & 0xf0) != 0x20)
11456505Speter		goto try_mk2;
11556505Speter	/* It must be a Jet ISA SI/XIO card */
11656505Speter	*(maddr + SIJETCONFIG) = 0;
11756505Speter	type = SIJETISA;
11856505Speter	ramsize = SIJET_RAMSIZE;
11956505Speter	goto got_card;
12056505Speter
12156505Spetertry_mk2:
12256505Speter	/*
12356505Speter	 * OK, now to see if whatever responded is really an SI card.
12456505Speter	 * Try for a MK II next (SIHOST2)
12556505Speter	 */
12656505Speter	for (i = SIPLSIG; i < SIPLSIG + 8; i++)
12756505Speter		if ((*(maddr+i) & 7) != (~(unsigned char)i & 7))
12856505Speter			goto try_mk1;
12956505Speter
13056505Speter	/* It must be an SIHOST2 */
13156505Speter	*(maddr + SIPLRESET) = 0;
13256505Speter	*(maddr + SIPLIRQCLR) = 0;
13356505Speter	*(maddr + SIPLIRQSET) = 0x10;
13456505Speter	type = SIHOST2;
13556505Speter	ramsize = SIHOST2_RAMSIZE;
13656505Speter	goto got_card;
13756505Speter
13856505Spetertry_mk1:
13956505Speter	/*
14056505Speter	 * Its not a MK II, so try for a MK I (SIHOST)
14156505Speter	 */
14256505Speter	*(maddr+SIRESET) = 0x0;		/* reset the card */
14356505Speter	*(maddr+SIINTCL) = 0x0;		/* clear int */
14456505Speter	*(maddr+SIRAM) = 0x17;
14556505Speter	if (*(maddr+SIRAM) != (unsigned char)0x17)
14656505Speter		goto fail;
14756505Speter	*(maddr+0x7ff8) = 0x17;
14856505Speter	if (*(maddr+0x7ff8) != (unsigned char)0x17) {
14956505Speter		DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
15056505Speter			"si%d: 0x17 check fail at phys 0x%x = 0x%x\n",
15156505Speter			unit, paddr+0x77f8, *(maddr+0x77f8)));
15256505Speter		goto fail;
15356505Speter	}
15456505Speter
15556505Speter	/* It must be an SIHOST (maybe?) - there must be a better way XXX */
15656505Speter	type = SIHOST;
15756505Speter	ramsize = SIHOST_RAMSIZE;
15856505Speter
15956505Spetergot_card:
16056505Speter	DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n",
16156505Speter		unit, type));
16256505Speter	/* Try the acid test */
16356505Speter	ux = maddr + SIRAM;
16456505Speter	for (i = 0; i < ramsize; i++, ux++)
16556505Speter		*ux = (unsigned char)(i&0xff);
16656505Speter	ux = maddr + SIRAM;
16756505Speter	for (i = 0; i < ramsize; i++, ux++) {
16856505Speter		if ((was = *ux) != (unsigned char)(i&0xff)) {
16956505Speter			DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
17056505Speter				"si%d: match fail at phys 0x%x, was %x should be %x\n",
17156505Speter				unit, paddr + i, was, i&0xff));
17256505Speter			goto fail;
17356505Speter		}
17456505Speter	}
17556505Speter
17656505Speter	/* clear out the RAM */
17756505Speter	ux = maddr + SIRAM;
17856505Speter	for (i = 0; i < ramsize; i++)
17956505Speter		*ux++ = 0;
18056505Speter	ux = maddr + SIRAM;
18156505Speter	for (i = 0; i < ramsize; i++) {
18256505Speter		if ((was = *ux++) != 0) {
18356505Speter			DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
18456505Speter				"si%d: clear fail at phys 0x%x, was %x\n",
18556505Speter				unit, paddr + i, was));
18656505Speter			goto fail;
18756505Speter		}
18856505Speter	}
18956505Speter
19056505Speter	/*
19156505Speter	 * Success, we've found a valid board, now fill in
19256505Speter	 * the adapter structure.
19356505Speter	 */
19456505Speter	switch (type) {
19556505Speter	case SIHOST2:
19656505Speter		switch (isa_get_irq(dev)) {
19756505Speter		case 11:
19856505Speter		case 12:
19956505Speter		case 15:
20056505Speter			break;
20156505Speter		default:
20256505Speterbad_irq:
20356505Speter			DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
20456505Speter				"si%d: bad IRQ value - %d\n",
20556505Speter				unit, 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:
21756505Speter			goto bad_irq;
21856505Speter		}
21956505Speter		sc->sc_memsize = SIHOST_MEMSIZE;
22056505Speter		break;
22156505Speter	case SIJETISA:
22256505Speter		switch (isa_get_irq(dev)) {
22356505Speter		case 9:
22456505Speter		case 10:
22556505Speter		case 11:
22656505Speter		case 12:
22756505Speter		case 15:
22856505Speter			break;
22956505Speter		default:
23056505Speter			goto bad_irq;
23156505Speter		}
23256505Speter		sc->sc_memsize = SIJETISA_MEMSIZE;
23356505Speter		break;
23456505Speter	case SIMCA:		/* MCA */
23556505Speter	default:
23656505Speter		printf("si%d: card type %d not supported\n", unit, type);
23756505Speter		goto fail;
23856505Speter	}
23956505Speter	sc->sc_type = type;
24056505Speter	bus_release_resource(dev, SYS_RES_MEMORY,
24156505Speter			     sc->sc_mem_rid, sc->sc_mem_res);
24256505Speter	sc->sc_mem_res = 0;
24356505Speter	return (0);		/* success! */
24456505Speter
24556505Speterfail:
24656505Speter	if (sc->sc_mem_res) {
24756505Speter		bus_release_resource(dev, SYS_RES_MEMORY,
24856505Speter				     sc->sc_mem_rid, sc->sc_mem_res);
24956505Speter		sc->sc_mem_res = 0;
25056505Speter	}
25156505Speter	return(EINVAL);
25256505Speter}
25356505Speter
25456505Speterstatic int
25556505Spetersi_isa_attach(device_t dev)
25656505Speter{
25756505Speter	int error;
25856505Speter	void *ih;
25956505Speter	struct si_softc *sc;
26056505Speter
26156505Speter	error = 0;
26256505Speter	ih = NULL;
26356505Speter	sc = device_get_softc(dev);
26456505Speter
26556505Speter	sc->sc_mem_rid = 0;
26656505Speter	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
26756505Speter					    &sc->sc_mem_rid,
26856505Speter					    0, ~0, 1, RF_ACTIVE);
26956505Speter	if (!sc->sc_mem_res) {
27056505Speter		device_printf(dev, "couldn't map memory\n");
27156505Speter		goto fail;
27256505Speter	}
27356505Speter	sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_mem_res);
27456505Speter	sc->sc_maddr = rman_get_virtual(sc->sc_mem_res);
27556505Speter
27656505Speter	sc->sc_irq_rid = 0;
27756505Speter	sc->sc_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irq_rid,
27856505Speter					    0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
27956505Speter	if (!sc->sc_irq_res) {
28056505Speter		device_printf(dev, "couldn't allocate interrupt\n");
28156505Speter		goto fail;
28256505Speter	}
28356505Speter	sc->sc_irq = rman_get_start(sc->sc_irq_res);
28456505Speter	error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY,
28556505Speter			       si_intr, sc,&ih);
28656505Speter	if (error) {
28756505Speter		device_printf(dev, "couldn't activate interrupt\n");
28856505Speter		goto fail;
28956505Speter	}
29056505Speter
29156505Speter	error = siattach(dev);
29256505Speter	if (error)
29356505Speter		goto fail;
29456505Speter	return (0);		/* success */
29556505Speter
29656505Speterfail:
29756505Speter	if (error == 0)
29856505Speter		error = ENXIO;
29956505Speter	if (sc->sc_irq_res) {
30056505Speter		if (ih)
30156505Speter			bus_teardown_intr(dev, sc->sc_irq_res, ih);
30256505Speter		bus_release_resource(dev, SYS_RES_IRQ,
30356505Speter				     sc->sc_irq_rid, sc->sc_irq_res);
30456505Speter		sc->sc_irq_res = 0;
30556505Speter	}
30656505Speter	if (sc->sc_mem_res) {
30756505Speter		bus_release_resource(dev, SYS_RES_MEMORY,
30856505Speter				     sc->sc_mem_rid, sc->sc_mem_res);
30956505Speter		sc->sc_mem_res = 0;
31056505Speter	}
31156505Speter	return (error);
31256505Speter}
31356505Speter
31456505Speterstatic device_method_t si_isa_methods[] = {
31556505Speter	/* Device interface */
31656505Speter	DEVMETHOD(device_probe,		si_isa_probe),
31756505Speter	DEVMETHOD(device_attach,	si_isa_attach),
31856505Speter
31956505Speter	{ 0, 0 }
32056505Speter};
32156505Speter
32256505Speterstatic driver_t si_isa_driver = {
32356505Speter	"si",
32456505Speter	si_isa_methods,
32556505Speter	sizeof(struct si_softc),
32656505Speter};
32756505Speter
32856505SpeterDRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0);
329