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