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