1139749Simp/*- 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: stable/11/sys/dev/si/si_isa.c 335087 2018-06-13 20:33:52Z dim $"); 24119419Sobrien 2556505Speter#include "opt_debug_si.h" 2656505Speter 2756505Speter#include <sys/param.h> 2856505Speter#include <sys/systm.h> 2956505Speter#include <sys/kernel.h> 30129879Sphk#include <sys/module.h> 3156505Speter#include <sys/bus.h> 3256505Speter#include <machine/bus.h> 3356505Speter#include <sys/rman.h> 3456505Speter#include <machine/resource.h> 3556505Speter 3656505Speter#include <dev/si/sireg.h> 3756505Speter#include <dev/si/sivar.h> 3856505Speter 3956505Speter#include <isa/isavar.h> 4056505Speter 4156505Speter/* Look for a valid board at the given mem addr */ 4256505Speterstatic int 4356505Spetersi_isa_probe(device_t dev) 4456505Speter{ 4556505Speter struct si_softc *sc; 4656505Speter int type; 4756505Speter u_int i, ramsize; 4856505Speter volatile unsigned char was, *ux; 4956505Speter volatile unsigned char *maddr; 5056505Speter unsigned char *paddr; 5156505Speter int unit; 5256505Speter 53100744Speter /* No pnp support */ 54100744Speter if (isa_get_vendorid(dev)) 55100744Speter return (ENXIO); 56100744Speter 5756505Speter sc = device_get_softc(dev); 5856505Speter unit = device_get_unit(dev); 5956505Speter 6056505Speter sc->sc_mem_rid = 0; 61296137Sjhibbits sc->sc_mem_res = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, 62296137Sjhibbits &sc->sc_mem_rid, 63296137Sjhibbits SIPROBEALLOC, RF_ACTIVE); 64100744Speter if (!sc->sc_mem_res) { 65100744Speter device_printf(dev, "cannot allocate memory resource\n"); 6656505Speter return ENXIO; 67100744Speter } 68335087Sdim paddr = (caddr_t)(uintptr_t)rman_get_start(sc->sc_mem_res);/* physical */ 6956505Speter maddr = rman_get_virtual(sc->sc_mem_res); /* in kvm */ 7056505Speter 7156505Speter DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n", 7256505Speter unit, maddr, paddr)); 7356505Speter 7456505Speter /* 7556505Speter * this is a lie, but it's easier than trying to handle caching 7656505Speter * and ram conflicts in the >1M and <16M region. 7756505Speter */ 7856505Speter if ((caddr_t)paddr < (caddr_t)0xA0000 || 7956505Speter (caddr_t)paddr >= (caddr_t)0x100000) { 80100744Speter device_printf(dev, "maddr (%p) out of range\n", paddr); 8156505Speter goto fail; 8256505Speter } 8356505Speter 84106572Sjhb if (((uintptr_t)paddr & 0x7fff) != 0) { 85100744Speter device_printf(dev, "maddr (%p) not on 32k boundary\n", paddr); 8656505Speter goto fail; 8756505Speter } 8856505Speter 8956505Speter /* Is there anything out there? (0x17 is just an arbitrary number) */ 9056505Speter *maddr = 0x17; 9156505Speter if (*maddr != 0x17) { 92100744Speter device_printf(dev, "0x17 check fail at phys %p\n", paddr); 9356505Speter goto fail; 9456505Speter } 9556505Speter /* 9656505Speter * Let's look first for a JET ISA card, since that's pretty easy 9756505Speter * 9856505Speter * All jet hosts are supposed to have this string in the IDROM, 9956505Speter * but it's not worth checking on self-IDing busses like PCI. 10056505Speter */ 10156505Speter { 10256505Speter unsigned char *jet_chk_str = "JET HOST BY KEV#"; 10356505Speter 10456505Speter for (i = 0; i < strlen(jet_chk_str); i++) 10556505Speter if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i)) 10656505Speter goto try_mk2; 10756505Speter } 10856505Speter DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET first check - 0x%x\n", 10956505Speter unit, (*(maddr+SIJETIDBASE)))); 11056505Speter if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff)) 11156505Speter goto try_mk2; 11256505Speter DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET second check - 0x%x\n", 11356505Speter unit, (*(maddr+SIJETIDBASE+2)))); 11456505Speter if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8)) 11556505Speter goto try_mk2; 11656505Speter /* It must be a Jet ISA or RIO card */ 11756505Speter DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET id check - 0x%x\n", 11856505Speter unit, (*(maddr+SIUNIQID)))); 11956505Speter if ((*(maddr+SIUNIQID) & 0xf0) != 0x20) 12056505Speter goto try_mk2; 12156505Speter /* It must be a Jet ISA SI/XIO card */ 12256505Speter *(maddr + SIJETCONFIG) = 0; 12356505Speter type = SIJETISA; 12456505Speter ramsize = SIJET_RAMSIZE; 12556505Speter goto got_card; 12656505Speter 12756505Spetertry_mk2: 12856505Speter /* 12956505Speter * OK, now to see if whatever responded is really an SI card. 13056505Speter * Try for a MK II next (SIHOST2) 13156505Speter */ 13256505Speter for (i = SIPLSIG; i < SIPLSIG + 8; i++) 13356505Speter if ((*(maddr+i) & 7) != (~(unsigned char)i & 7)) 13456505Speter goto try_mk1; 13556505Speter 13656505Speter /* It must be an SIHOST2 */ 13756505Speter *(maddr + SIPLRESET) = 0; 13856505Speter *(maddr + SIPLIRQCLR) = 0; 13956505Speter *(maddr + SIPLIRQSET) = 0x10; 14056505Speter type = SIHOST2; 14156505Speter ramsize = SIHOST2_RAMSIZE; 14256505Speter goto got_card; 14356505Speter 14456505Spetertry_mk1: 14556505Speter /* 14656505Speter * Its not a MK II, so try for a MK I (SIHOST) 14756505Speter */ 14856505Speter *(maddr+SIRESET) = 0x0; /* reset the card */ 14956505Speter *(maddr+SIINTCL) = 0x0; /* clear int */ 15056505Speter *(maddr+SIRAM) = 0x17; 15156505Speter if (*(maddr+SIRAM) != (unsigned char)0x17) 15256505Speter goto fail; 15356505Speter *(maddr+0x7ff8) = 0x17; 15456505Speter if (*(maddr+0x7ff8) != (unsigned char)0x17) { 155100744Speter device_printf(dev, "0x17 check fail at phys %p = 0x%x\n", 156100744Speter paddr+0x77f8, *(maddr+0x77f8)); 15756505Speter goto fail; 15856505Speter } 15956505Speter 16056505Speter /* It must be an SIHOST (maybe?) - there must be a better way XXX */ 16156505Speter type = SIHOST; 16256505Speter ramsize = SIHOST_RAMSIZE; 16356505Speter 16456505Spetergot_card: 16556505Speter DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n", 16656505Speter unit, type)); 16756505Speter /* Try the acid test */ 16856505Speter ux = maddr + SIRAM; 16956505Speter for (i = 0; i < ramsize; i++, ux++) 17056505Speter *ux = (unsigned char)(i&0xff); 17156505Speter ux = maddr + SIRAM; 17256505Speter for (i = 0; i < ramsize; i++, ux++) { 17356505Speter if ((was = *ux) != (unsigned char)(i&0xff)) { 174100744Speter device_printf(dev, 175100744Speter "memtest fail at phys %p, was %x should be %x\n", 176100744Speter paddr + i, was, i & 0xff); 17756505Speter goto fail; 17856505Speter } 17956505Speter } 18056505Speter 18156505Speter /* clear out the RAM */ 18256505Speter ux = maddr + SIRAM; 18356505Speter for (i = 0; i < ramsize; i++) 18456505Speter *ux++ = 0; 18556505Speter ux = maddr + SIRAM; 18656505Speter for (i = 0; i < ramsize; i++) { 18756505Speter if ((was = *ux++) != 0) { 188100744Speter device_printf(dev, "clear fail at phys %p, was %x\n", 189100744Speter paddr + i, was); 19056505Speter goto fail; 19156505Speter } 19256505Speter } 19356505Speter 19456505Speter /* 19556505Speter * Success, we've found a valid board, now fill in 19656505Speter * the adapter structure. 19756505Speter */ 19856505Speter switch (type) { 19956505Speter case SIHOST2: 20056505Speter switch (isa_get_irq(dev)) { 20156505Speter case 11: 20256505Speter case 12: 20356505Speter case 15: 20456505Speter break; 20556505Speter default: 206100744Speter device_printf(dev, 207100744Speter "bad IRQ value - %d (11, 12, 15 allowed)\n", 208100744Speter isa_get_irq(dev)); 20956505Speter goto fail; 21056505Speter } 21156505Speter sc->sc_memsize = SIHOST2_MEMSIZE; 21256505Speter break; 21356505Speter case SIHOST: 21456505Speter switch (isa_get_irq(dev)) { 21556505Speter case 11: 21656505Speter case 12: 21756505Speter case 15: 21856505Speter break; 21956505Speter default: 220100744Speter device_printf(dev, 221100744Speter "bad IRQ value - %d (11, 12, 15 allowed)\n", 222100744Speter isa_get_irq(dev)); 223100744Speter goto fail; 22456505Speter } 22556505Speter sc->sc_memsize = SIHOST_MEMSIZE; 22656505Speter break; 22756505Speter case SIJETISA: 22856505Speter switch (isa_get_irq(dev)) { 22956505Speter case 9: 23056505Speter case 10: 23156505Speter case 11: 23256505Speter case 12: 23356505Speter case 15: 23456505Speter break; 23556505Speter default: 236100744Speter device_printf(dev, 237100744Speter "bad IRQ value - %d (9, 10, 11, 12, 15 allowed)\n", 238100744Speter isa_get_irq(dev)); 239100744Speter goto fail; 24056505Speter } 24156505Speter sc->sc_memsize = SIJETISA_MEMSIZE; 24256505Speter break; 24356505Speter case SIMCA: /* MCA */ 24456505Speter default: 245100744Speter device_printf(dev, "card type %d not supported\n", type); 24656505Speter goto fail; 24756505Speter } 24856505Speter sc->sc_type = type; 24956505Speter bus_release_resource(dev, SYS_RES_MEMORY, 25056505Speter sc->sc_mem_rid, sc->sc_mem_res); 25156505Speter sc->sc_mem_res = 0; 25256505Speter return (0); /* success! */ 25356505Speter 25456505Speterfail: 25556505Speter if (sc->sc_mem_res) { 25656505Speter bus_release_resource(dev, SYS_RES_MEMORY, 25756505Speter sc->sc_mem_rid, sc->sc_mem_res); 25856505Speter sc->sc_mem_res = 0; 25956505Speter } 26056505Speter return(EINVAL); 26156505Speter} 26256505Speter 26356505Speterstatic int 26456505Spetersi_isa_attach(device_t dev) 26556505Speter{ 26656505Speter int error; 26756505Speter void *ih; 26856505Speter struct si_softc *sc; 26956505Speter 27056505Speter error = 0; 27156505Speter ih = NULL; 27256505Speter sc = device_get_softc(dev); 27356505Speter 27456505Speter sc->sc_mem_rid = 0; 275127135Snjl sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 276127135Snjl &sc->sc_mem_rid, 277127135Snjl RF_ACTIVE); 27856505Speter if (!sc->sc_mem_res) { 27956505Speter device_printf(dev, "couldn't map memory\n"); 28056505Speter goto fail; 28156505Speter } 282335087Sdim sc->sc_paddr = (caddr_t)(uintptr_t)rman_get_start(sc->sc_mem_res); 28356505Speter sc->sc_maddr = rman_get_virtual(sc->sc_mem_res); 28456505Speter 28556505Speter sc->sc_irq_rid = 0; 286127135Snjl sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 287127135Snjl &sc->sc_irq_rid, 288127135Snjl RF_ACTIVE | RF_SHAREABLE); 28956505Speter if (!sc->sc_irq_res) { 29056505Speter device_printf(dev, "couldn't allocate interrupt\n"); 29156505Speter goto fail; 29256505Speter } 29356505Speter sc->sc_irq = rman_get_start(sc->sc_irq_res); 29456505Speter error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY, 295166914Simp NULL, si_intr, sc, &ih); 29656505Speter if (error) { 29756505Speter device_printf(dev, "couldn't activate interrupt\n"); 29856505Speter goto fail; 29956505Speter } 30056505Speter 30156505Speter error = siattach(dev); 30256505Speter if (error) 30356505Speter goto fail; 30456505Speter return (0); /* success */ 30556505Speter 30656505Speterfail: 30756505Speter if (error == 0) 30856505Speter error = ENXIO; 30956505Speter if (sc->sc_irq_res) { 31056505Speter if (ih) 31156505Speter bus_teardown_intr(dev, sc->sc_irq_res, ih); 31256505Speter bus_release_resource(dev, SYS_RES_IRQ, 31356505Speter sc->sc_irq_rid, sc->sc_irq_res); 31456505Speter sc->sc_irq_res = 0; 31556505Speter } 31656505Speter if (sc->sc_mem_res) { 31756505Speter bus_release_resource(dev, SYS_RES_MEMORY, 31856505Speter sc->sc_mem_rid, sc->sc_mem_res); 31956505Speter sc->sc_mem_res = 0; 32056505Speter } 32156505Speter return (error); 32256505Speter} 32356505Speter 32456505Speterstatic device_method_t si_isa_methods[] = { 32556505Speter /* Device interface */ 32656505Speter DEVMETHOD(device_probe, si_isa_probe), 32756505Speter DEVMETHOD(device_attach, si_isa_attach), 32856505Speter 32956505Speter { 0, 0 } 33056505Speter}; 33156505Speter 33256505Speterstatic driver_t si_isa_driver = { 33356505Speter "si", 33456505Speter si_isa_methods, 33556505Speter sizeof(struct si_softc), 33656505Speter}; 33756505Speter 33856505SpeterDRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0); 339