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