si_isa.c revision 119419
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 119419 2003-08-24 18:03:45Z obrien $"); 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; 27456505Speter sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 27556505Speter &sc->sc_mem_rid, 27656505Speter 0, ~0, 1, 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; 28556505Speter sc->sc_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irq_rid, 28656505Speter 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 28756505Speter if (!sc->sc_irq_res) { 28856505Speter device_printf(dev, "couldn't allocate interrupt\n"); 28956505Speter goto fail; 29056505Speter } 29156505Speter sc->sc_irq = rman_get_start(sc->sc_irq_res); 29256505Speter error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY, 29356505Speter si_intr, sc,&ih); 29456505Speter if (error) { 29556505Speter device_printf(dev, "couldn't activate interrupt\n"); 29656505Speter goto fail; 29756505Speter } 29856505Speter 29956505Speter error = siattach(dev); 30056505Speter if (error) 30156505Speter goto fail; 30256505Speter return (0); /* success */ 30356505Speter 30456505Speterfail: 30556505Speter if (error == 0) 30656505Speter error = ENXIO; 30756505Speter if (sc->sc_irq_res) { 30856505Speter if (ih) 30956505Speter bus_teardown_intr(dev, sc->sc_irq_res, ih); 31056505Speter bus_release_resource(dev, SYS_RES_IRQ, 31156505Speter sc->sc_irq_rid, sc->sc_irq_res); 31256505Speter sc->sc_irq_res = 0; 31356505Speter } 31456505Speter if (sc->sc_mem_res) { 31556505Speter bus_release_resource(dev, SYS_RES_MEMORY, 31656505Speter sc->sc_mem_rid, sc->sc_mem_res); 31756505Speter sc->sc_mem_res = 0; 31856505Speter } 31956505Speter return (error); 32056505Speter} 32156505Speter 32256505Speterstatic device_method_t si_isa_methods[] = { 32356505Speter /* Device interface */ 32456505Speter DEVMETHOD(device_probe, si_isa_probe), 32556505Speter DEVMETHOD(device_attach, si_isa_attach), 32656505Speter 32756505Speter { 0, 0 } 32856505Speter}; 32956505Speter 33056505Speterstatic driver_t si_isa_driver = { 33156505Speter "si", 33256505Speter si_isa_methods, 33356505Speter sizeof(struct si_softc), 33456505Speter}; 33556505Speter 33656505SpeterDRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0); 337