si_isa.c revision 56505
11590Srgrimes/*
21590Srgrimes * Device driver for Specialix range (SI/XIO) of serial line multiplexors.
31590Srgrimes *
41590Srgrimes * Copyright (C) 2000, Peter Wemm <peter@netplex.com.au>
51590Srgrimes *
61590Srgrimes * Redistribution and use in source and binary forms, with or without
71590Srgrimes * modification, are permitted provided that the following conditions
81590Srgrimes * are met:
91590Srgrimes * 1. Redistributions of source code must retain the above copyright
101590Srgrimes *    notices, this list of conditions and the following disclaimer.
111590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121590Srgrimes *    notices, this list of conditions and the following disclaimer in the
131590Srgrimes *    documentation and/or other materials provided with the distribution.
141590Srgrimes *
151590Srgrimes * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
161590Srgrimes * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
171590Srgrimes * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
181590Srgrimes * NO EVENT SHALL THE AUTHORS BE LIABLE.
191590Srgrimes *
201590Srgrimes * $FreeBSD: head/sys/dev/si/si_isa.c 56505 2000-01-24 07:24:02Z peter $
211590Srgrimes */
221590Srgrimes
231590Srgrimes#include "opt_debug_si.h"
241590Srgrimes
251590Srgrimes#include <sys/param.h>
261590Srgrimes#include <sys/systm.h>
271590Srgrimes#include <sys/kernel.h>
281590Srgrimes#include <sys/bus.h>
291590Srgrimes#include <machine/bus.h>
30114594Sobrien#include <sys/rman.h>
311590Srgrimes#include <machine/resource.h>
3228564Scharnier
331590Srgrimes#include <dev/si/sireg.h>
341590Srgrimes#include <dev/si/sivar.h>
351590Srgrimes
361590Srgrimes#include <isa/isavar.h>
371590Srgrimes
381590Srgrimes/* Look for a valid board at the given mem addr */
3996438Smikestatic int
4028564Scharniersi_isa_probe(device_t dev)
4196438Smike{
4296438Smike	struct si_softc *sc;
4396438Smike	int type;
441590Srgrimes	u_int i, ramsize;
451590Srgrimes	volatile unsigned char was, *ux;
461590Srgrimes	volatile unsigned char *maddr;
471590Srgrimes	unsigned char *paddr;
481590Srgrimes	int unit;
4991661Sjmallett
5091661Sjmallett	sc = device_get_softc(dev);
511590Srgrimes	unit = device_get_unit(dev);
521590Srgrimes
5391661Sjmallett	sc->sc_mem_rid = 0;
5491661Sjmallett	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
5528564Scharnier					    &sc->sc_mem_rid,
56105519Sfanf					    0, ~0, SIPROBEALLOC, RF_ACTIVE);
5791661Sjmallett	if (!sc->sc_mem_res)
581590Srgrimes		return ENXIO;
5978718Sdd	paddr = (caddr_t)rman_get_start(sc->sc_mem_res);/* physical */
6091661Sjmallett	maddr = rman_get_virtual(sc->sc_mem_res);	/* in kvm */
6128564Scharnier
621590Srgrimes	DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n",
63227197Sed		unit, maddr, paddr));
64227197Sed
6592922Simp	/*
6628564Scharnier	 * this is a lie, but it's easier than trying to handle caching
67227197Sed	 * and ram conflicts in the >1M and <16M region.
68227197Sed	 */
69227197Sed	if ((caddr_t)paddr < (caddr_t)0xA0000 ||
7091661Sjmallett	    (caddr_t)paddr >= (caddr_t)0x100000) {
711590Srgrimes		printf("si%d: iomem (%p) out of range\n",
7296386Salfred			unit, (void *)paddr);
731590Srgrimes		goto fail;
741590Srgrimes	}
7591661Sjmallett
76124830Sgrehan	if (((u_int)paddr & 0x7fff) != 0) {
7791661Sjmallett		DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
781590Srgrimes			"si%d: iomem (%x) not on 32k boundary\n", unit, paddr));
7991661Sjmallett		goto fail;
8091661Sjmallett	}
8191661Sjmallett
82105519Sfanf	/* Is there anything out there? (0x17 is just an arbitrary number) */
8396942Sjmallett	*maddr = 0x17;
8496942Sjmallett	if (*maddr != 0x17) {
8591661Sjmallett		DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
8691661Sjmallett			"si%d: 0x17 check fail at phys 0x%x\n", unit, paddr));
8791661Sjmallett		goto fail;
8891661Sjmallett	}
8991661Sjmallett	/*
9091661Sjmallett	 * Let's look first for a JET ISA card, since that's pretty easy
9191661Sjmallett	 *
9291661Sjmallett	 * All jet hosts are supposed to have this string in the IDROM,
9391661Sjmallett	 * but it's not worth checking on self-IDing busses like PCI.
9491661Sjmallett	 */
9591661Sjmallett	{
9691661Sjmallett		unsigned char *jet_chk_str = "JET HOST BY KEV#";
9791661Sjmallett
981590Srgrimes		for (i = 0; i < strlen(jet_chk_str); i++)
991590Srgrimes			if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i))
1001590Srgrimes				goto try_mk2;
1011590Srgrimes	}
1021590Srgrimes	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET first check - 0x%x\n",
10328564Scharnier		unit, (*(maddr+SIJETIDBASE))));
10428564Scharnier	if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff))
1051590Srgrimes		goto try_mk2;
1061590Srgrimes	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET second check - 0x%x\n",
1071590Srgrimes		unit, (*(maddr+SIJETIDBASE+2))));
1081590Srgrimes	if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8))
1091590Srgrimes		goto try_mk2;
1101590Srgrimes	/* It must be a Jet ISA or RIO card */
1111590Srgrimes	DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET id check - 0x%x\n",
1121590Srgrimes		unit, (*(maddr+SIUNIQID))));
1131590Srgrimes	if ((*(maddr+SIUNIQID) & 0xf0) != 0x20)
1141590Srgrimes		goto try_mk2;
1151590Srgrimes	/* It must be a Jet ISA SI/XIO card */
1161590Srgrimes	*(maddr + SIJETCONFIG) = 0;
1171590Srgrimes	type = SIJETISA;
11891661Sjmallett	ramsize = SIJET_RAMSIZE;
11991661Sjmallett	goto got_card;
12091661Sjmallett
12191661Sjmalletttry_mk2:
12291661Sjmallett	/*
12391661Sjmallett	 * OK, now to see if whatever responded is really an SI card.
12491676Smike	 * Try for a MK II next (SIHOST2)
12591676Smike	 */
12691661Sjmallett	for (i = SIPLSIG; i < SIPLSIG + 8; i++)
12791661Sjmallett		if ((*(maddr+i) & 7) != (~(unsigned char)i & 7))
12891661Sjmallett			goto try_mk1;
12991661Sjmallett
13091661Sjmallett	/* It must be an SIHOST2 */
13128564Scharnier	*(maddr + SIPLRESET) = 0;
1321590Srgrimes	*(maddr + SIPLIRQCLR) = 0;
1331590Srgrimes	*(maddr + SIPLIRQSET) = 0x10;
1341590Srgrimes	type = SIHOST2;
1351590Srgrimes	ramsize = SIHOST2_RAMSIZE;
1361590Srgrimes	goto got_card;
1371590Srgrimes
1381590Srgrimestry_mk1:
13991661Sjmallett	/*
1401590Srgrimes	 * Its not a MK II, so try for a MK I (SIHOST)
141227197Sed	 */
14296438Smike	*(maddr+SIRESET) = 0x0;		/* reset the card */
14391661Sjmallett	*(maddr+SIINTCL) = 0x0;		/* clear int */
14496810Sjmallett	*(maddr+SIRAM) = 0x17;
14596810Sjmallett	if (*(maddr+SIRAM) != (unsigned char)0x17)
14696810Sjmallett		goto fail;
14796810Sjmallett	*(maddr+0x7ff8) = 0x17;
14896810Sjmallett	if (*(maddr+0x7ff8) != (unsigned char)0x17) {
14996810Sjmallett		DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
15091661Sjmallett			"si%d: 0x17 check fail at phys 0x%x = 0x%x\n",
15191661Sjmallett			unit, paddr+0x77f8, *(maddr+0x77f8)));
15291661Sjmallett		goto fail;
15391661Sjmallett	}
15491661Sjmallett
15591661Sjmallett	/* It must be an SIHOST (maybe?) - there must be a better way XXX */
15691661Sjmallett	type = SIHOST;
15791661Sjmallett	ramsize = SIHOST_RAMSIZE;
15891661Sjmallett
15991661Sjmallettgot_card:
16091661Sjmallett	DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n",
16191661Sjmallett		unit, type));
16291661Sjmallett	/* Try the acid test */
16391661Sjmallett	ux = maddr + SIRAM;
16491661Sjmallett	for (i = 0; i < ramsize; i++, ux++)
16591661Sjmallett		*ux = (unsigned char)(i&0xff);
16691661Sjmallett	ux = maddr + SIRAM;
16791661Sjmallett	for (i = 0; i < ramsize; i++, ux++) {
16891661Sjmallett		if ((was = *ux) != (unsigned char)(i&0xff)) {
16991661Sjmallett			DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
17091661Sjmallett				"si%d: match fail at phys 0x%x, was %x should be %x\n",
171227197Sed				unit, paddr + i, was, i&0xff));
17296438Smike			goto fail;
1731590Srgrimes		}
1741590Srgrimes	}
1751590Srgrimes
1761590Srgrimes	/* clear out the RAM */
1771590Srgrimes	ux = maddr + SIRAM;
17891661Sjmallett	for (i = 0; i < ramsize; i++)
17928564Scharnier		*ux++ = 0;
1801590Srgrimes	ux = maddr + SIRAM;
18191661Sjmallett	for (i = 0; i < ramsize; i++) {
1821590Srgrimes		if ((was = *ux++) != 0) {
1831590Srgrimes			DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
18484715Sru				"si%d: clear fail at phys 0x%x, was %x\n",
18584715Sru				unit, paddr + i, was));
18684715Sru			goto fail;
18784715Sru		}
18884715Sru	}
18984715Sru
1901590Srgrimes	/*
1911590Srgrimes	 * Success, we've found a valid board, now fill in
19291661Sjmallett	 * the adapter structure.
1931590Srgrimes	 */
19478387Sdd	switch (type) {
1951590Srgrimes	case SIHOST2:
19691661Sjmallett		switch (isa_get_irq(dev)) {
1971590Srgrimes		case 11:
19878387Sdd		case 12:
1991590Srgrimes		case 15:
20091661Sjmallett			break;
2011590Srgrimes		default:
2021590Srgrimesbad_irq:
2031590Srgrimes			DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
20491661Sjmallett				"si%d: bad IRQ value - %d\n",
2051590Srgrimes				unit, isa_get_irq(dev)));
2061590Srgrimes			goto fail;
20791661Sjmallett		}
2081590Srgrimes		sc->sc_memsize = SIHOST2_MEMSIZE;
2091590Srgrimes		break;
21028564Scharnier	case SIHOST:
21128564Scharnier		switch (isa_get_irq(dev)) {
21291661Sjmallett		case 11:
2131590Srgrimes		case 12:
2141590Srgrimes		case 15:
21528564Scharnier			break;
21696438Smike		default:
2171590Srgrimes			goto bad_irq;
21896943Sjmallett		}
21996943Sjmallett		sc->sc_memsize = SIHOST_MEMSIZE;
22096943Sjmallett		break;
2211590Srgrimes	case SIJETISA:
2221590Srgrimes		switch (isa_get_irq(dev)) {
223		case 9:
224		case 10:
225		case 11:
226		case 12:
227		case 15:
228			break;
229		default:
230			goto bad_irq;
231		}
232		sc->sc_memsize = SIJETISA_MEMSIZE;
233		break;
234	case SIMCA:		/* MCA */
235	default:
236		printf("si%d: card type %d not supported\n", unit, type);
237		goto fail;
238	}
239	sc->sc_type = type;
240	bus_release_resource(dev, SYS_RES_MEMORY,
241			     sc->sc_mem_rid, sc->sc_mem_res);
242	sc->sc_mem_res = 0;
243	return (0);		/* success! */
244
245fail:
246	if (sc->sc_mem_res) {
247		bus_release_resource(dev, SYS_RES_MEMORY,
248				     sc->sc_mem_rid, sc->sc_mem_res);
249		sc->sc_mem_res = 0;
250	}
251	return(EINVAL);
252}
253
254static int
255si_isa_attach(device_t dev)
256{
257	int error;
258	void *ih;
259	struct si_softc *sc;
260
261	error = 0;
262	ih = NULL;
263	sc = device_get_softc(dev);
264
265	sc->sc_mem_rid = 0;
266	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
267					    &sc->sc_mem_rid,
268					    0, ~0, 1, RF_ACTIVE);
269	if (!sc->sc_mem_res) {
270		device_printf(dev, "couldn't map memory\n");
271		goto fail;
272	}
273	sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_mem_res);
274	sc->sc_maddr = rman_get_virtual(sc->sc_mem_res);
275
276	sc->sc_irq_rid = 0;
277	sc->sc_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irq_rid,
278					    0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
279	if (!sc->sc_irq_res) {
280		device_printf(dev, "couldn't allocate interrupt\n");
281		goto fail;
282	}
283	sc->sc_irq = rman_get_start(sc->sc_irq_res);
284	error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY,
285			       si_intr, sc,&ih);
286	if (error) {
287		device_printf(dev, "couldn't activate interrupt\n");
288		goto fail;
289	}
290
291	error = siattach(dev);
292	if (error)
293		goto fail;
294	return (0);		/* success */
295
296fail:
297	if (error == 0)
298		error = ENXIO;
299	if (sc->sc_irq_res) {
300		if (ih)
301			bus_teardown_intr(dev, sc->sc_irq_res, ih);
302		bus_release_resource(dev, SYS_RES_IRQ,
303				     sc->sc_irq_rid, sc->sc_irq_res);
304		sc->sc_irq_res = 0;
305	}
306	if (sc->sc_mem_res) {
307		bus_release_resource(dev, SYS_RES_MEMORY,
308				     sc->sc_mem_rid, sc->sc_mem_res);
309		sc->sc_mem_res = 0;
310	}
311	return (error);
312}
313
314static device_method_t si_isa_methods[] = {
315	/* Device interface */
316	DEVMETHOD(device_probe,		si_isa_probe),
317	DEVMETHOD(device_attach,	si_isa_attach),
318
319	{ 0, 0 }
320};
321
322static driver_t si_isa_driver = {
323	"si",
324	si_isa_methods,
325	sizeof(struct si_softc),
326};
327
328DRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0);
329