1/*- 2 * Device driver for Specialix range (SI/XIO) of serial line multiplexors. 3 * 4 * Copyright (C) 2000, Peter Wemm <peter@netplex.com.au> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notices, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notices, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 18 * NO EVENT SHALL THE AUTHORS BE LIABLE. 19 * 20 */ 21 22#include <sys/cdefs.h> 23__FBSDID("$FreeBSD: stable/11/sys/dev/si/si_isa.c 335087 2018-06-13 20:33:52Z dim $"); 24 25#include "opt_debug_si.h" 26 27#include <sys/param.h> 28#include <sys/systm.h> 29#include <sys/kernel.h> 30#include <sys/module.h> 31#include <sys/bus.h> 32#include <machine/bus.h> 33#include <sys/rman.h> 34#include <machine/resource.h> 35 36#include <dev/si/sireg.h> 37#include <dev/si/sivar.h> 38 39#include <isa/isavar.h> 40 41/* Look for a valid board at the given mem addr */ 42static int 43si_isa_probe(device_t dev) 44{ 45 struct si_softc *sc; 46 int type; 47 u_int i, ramsize; 48 volatile unsigned char was, *ux; 49 volatile unsigned char *maddr; 50 unsigned char *paddr; 51 int unit; 52 53 /* No pnp support */ 54 if (isa_get_vendorid(dev)) 55 return (ENXIO); 56 57 sc = device_get_softc(dev); 58 unit = device_get_unit(dev); 59 60 sc->sc_mem_rid = 0; 61 sc->sc_mem_res = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, 62 &sc->sc_mem_rid, 63 SIPROBEALLOC, RF_ACTIVE); 64 if (!sc->sc_mem_res) { 65 device_printf(dev, "cannot allocate memory resource\n"); 66 return ENXIO; 67 } 68 paddr = (caddr_t)(uintptr_t)rman_get_start(sc->sc_mem_res);/* physical */ 69 maddr = rman_get_virtual(sc->sc_mem_res); /* in kvm */ 70 71 DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n", 72 unit, maddr, paddr)); 73 74 /* 75 * this is a lie, but it's easier than trying to handle caching 76 * and ram conflicts in the >1M and <16M region. 77 */ 78 if ((caddr_t)paddr < (caddr_t)0xA0000 || 79 (caddr_t)paddr >= (caddr_t)0x100000) { 80 device_printf(dev, "maddr (%p) out of range\n", paddr); 81 goto fail; 82 } 83 84 if (((uintptr_t)paddr & 0x7fff) != 0) { 85 device_printf(dev, "maddr (%p) not on 32k boundary\n", paddr); 86 goto fail; 87 } 88 89 /* Is there anything out there? (0x17 is just an arbitrary number) */ 90 *maddr = 0x17; 91 if (*maddr != 0x17) { 92 device_printf(dev, "0x17 check fail at phys %p\n", paddr); 93 goto fail; 94 } 95 /* 96 * Let's look first for a JET ISA card, since that's pretty easy 97 * 98 * All jet hosts are supposed to have this string in the IDROM, 99 * but it's not worth checking on self-IDing busses like PCI. 100 */ 101 { 102 unsigned char *jet_chk_str = "JET HOST BY KEV#"; 103 104 for (i = 0; i < strlen(jet_chk_str); i++) 105 if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i)) 106 goto try_mk2; 107 } 108 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET first check - 0x%x\n", 109 unit, (*(maddr+SIJETIDBASE)))); 110 if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff)) 111 goto try_mk2; 112 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET second check - 0x%x\n", 113 unit, (*(maddr+SIJETIDBASE+2)))); 114 if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8)) 115 goto try_mk2; 116 /* It must be a Jet ISA or RIO card */ 117 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET id check - 0x%x\n", 118 unit, (*(maddr+SIUNIQID)))); 119 if ((*(maddr+SIUNIQID) & 0xf0) != 0x20) 120 goto try_mk2; 121 /* It must be a Jet ISA SI/XIO card */ 122 *(maddr + SIJETCONFIG) = 0; 123 type = SIJETISA; 124 ramsize = SIJET_RAMSIZE; 125 goto got_card; 126 127try_mk2: 128 /* 129 * OK, now to see if whatever responded is really an SI card. 130 * Try for a MK II next (SIHOST2) 131 */ 132 for (i = SIPLSIG; i < SIPLSIG + 8; i++) 133 if ((*(maddr+i) & 7) != (~(unsigned char)i & 7)) 134 goto try_mk1; 135 136 /* It must be an SIHOST2 */ 137 *(maddr + SIPLRESET) = 0; 138 *(maddr + SIPLIRQCLR) = 0; 139 *(maddr + SIPLIRQSET) = 0x10; 140 type = SIHOST2; 141 ramsize = SIHOST2_RAMSIZE; 142 goto got_card; 143 144try_mk1: 145 /* 146 * Its not a MK II, so try for a MK I (SIHOST) 147 */ 148 *(maddr+SIRESET) = 0x0; /* reset the card */ 149 *(maddr+SIINTCL) = 0x0; /* clear int */ 150 *(maddr+SIRAM) = 0x17; 151 if (*(maddr+SIRAM) != (unsigned char)0x17) 152 goto fail; 153 *(maddr+0x7ff8) = 0x17; 154 if (*(maddr+0x7ff8) != (unsigned char)0x17) { 155 device_printf(dev, "0x17 check fail at phys %p = 0x%x\n", 156 paddr+0x77f8, *(maddr+0x77f8)); 157 goto fail; 158 } 159 160 /* It must be an SIHOST (maybe?) - there must be a better way XXX */ 161 type = SIHOST; 162 ramsize = SIHOST_RAMSIZE; 163 164got_card: 165 DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n", 166 unit, type)); 167 /* Try the acid test */ 168 ux = maddr + SIRAM; 169 for (i = 0; i < ramsize; i++, ux++) 170 *ux = (unsigned char)(i&0xff); 171 ux = maddr + SIRAM; 172 for (i = 0; i < ramsize; i++, ux++) { 173 if ((was = *ux) != (unsigned char)(i&0xff)) { 174 device_printf(dev, 175 "memtest fail at phys %p, was %x should be %x\n", 176 paddr + i, was, i & 0xff); 177 goto fail; 178 } 179 } 180 181 /* clear out the RAM */ 182 ux = maddr + SIRAM; 183 for (i = 0; i < ramsize; i++) 184 *ux++ = 0; 185 ux = maddr + SIRAM; 186 for (i = 0; i < ramsize; i++) { 187 if ((was = *ux++) != 0) { 188 device_printf(dev, "clear fail at phys %p, was %x\n", 189 paddr + i, was); 190 goto fail; 191 } 192 } 193 194 /* 195 * Success, we've found a valid board, now fill in 196 * the adapter structure. 197 */ 198 switch (type) { 199 case SIHOST2: 200 switch (isa_get_irq(dev)) { 201 case 11: 202 case 12: 203 case 15: 204 break; 205 default: 206 device_printf(dev, 207 "bad IRQ value - %d (11, 12, 15 allowed)\n", 208 isa_get_irq(dev)); 209 goto fail; 210 } 211 sc->sc_memsize = SIHOST2_MEMSIZE; 212 break; 213 case SIHOST: 214 switch (isa_get_irq(dev)) { 215 case 11: 216 case 12: 217 case 15: 218 break; 219 default: 220 device_printf(dev, 221 "bad IRQ value - %d (11, 12, 15 allowed)\n", 222 isa_get_irq(dev)); 223 goto fail; 224 } 225 sc->sc_memsize = SIHOST_MEMSIZE; 226 break; 227 case SIJETISA: 228 switch (isa_get_irq(dev)) { 229 case 9: 230 case 10: 231 case 11: 232 case 12: 233 case 15: 234 break; 235 default: 236 device_printf(dev, 237 "bad IRQ value - %d (9, 10, 11, 12, 15 allowed)\n", 238 isa_get_irq(dev)); 239 goto fail; 240 } 241 sc->sc_memsize = SIJETISA_MEMSIZE; 242 break; 243 case SIMCA: /* MCA */ 244 default: 245 device_printf(dev, "card type %d not supported\n", type); 246 goto fail; 247 } 248 sc->sc_type = type; 249 bus_release_resource(dev, SYS_RES_MEMORY, 250 sc->sc_mem_rid, sc->sc_mem_res); 251 sc->sc_mem_res = 0; 252 return (0); /* success! */ 253 254fail: 255 if (sc->sc_mem_res) { 256 bus_release_resource(dev, SYS_RES_MEMORY, 257 sc->sc_mem_rid, sc->sc_mem_res); 258 sc->sc_mem_res = 0; 259 } 260 return(EINVAL); 261} 262 263static int 264si_isa_attach(device_t dev) 265{ 266 int error; 267 void *ih; 268 struct si_softc *sc; 269 270 error = 0; 271 ih = NULL; 272 sc = device_get_softc(dev); 273 274 sc->sc_mem_rid = 0; 275 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 276 &sc->sc_mem_rid, 277 RF_ACTIVE); 278 if (!sc->sc_mem_res) { 279 device_printf(dev, "couldn't map memory\n"); 280 goto fail; 281 } 282 sc->sc_paddr = (caddr_t)(uintptr_t)rman_get_start(sc->sc_mem_res); 283 sc->sc_maddr = rman_get_virtual(sc->sc_mem_res); 284 285 sc->sc_irq_rid = 0; 286 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 287 &sc->sc_irq_rid, 288 RF_ACTIVE | RF_SHAREABLE); 289 if (!sc->sc_irq_res) { 290 device_printf(dev, "couldn't allocate interrupt\n"); 291 goto fail; 292 } 293 sc->sc_irq = rman_get_start(sc->sc_irq_res); 294 error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY, 295 NULL, si_intr, sc, &ih); 296 if (error) { 297 device_printf(dev, "couldn't activate interrupt\n"); 298 goto fail; 299 } 300 301 error = siattach(dev); 302 if (error) 303 goto fail; 304 return (0); /* success */ 305 306fail: 307 if (error == 0) 308 error = ENXIO; 309 if (sc->sc_irq_res) { 310 if (ih) 311 bus_teardown_intr(dev, sc->sc_irq_res, ih); 312 bus_release_resource(dev, SYS_RES_IRQ, 313 sc->sc_irq_rid, sc->sc_irq_res); 314 sc->sc_irq_res = 0; 315 } 316 if (sc->sc_mem_res) { 317 bus_release_resource(dev, SYS_RES_MEMORY, 318 sc->sc_mem_rid, sc->sc_mem_res); 319 sc->sc_mem_res = 0; 320 } 321 return (error); 322} 323 324static device_method_t si_isa_methods[] = { 325 /* Device interface */ 326 DEVMETHOD(device_probe, si_isa_probe), 327 DEVMETHOD(device_attach, si_isa_attach), 328 329 { 0, 0 } 330}; 331 332static driver_t si_isa_driver = { 333 "si", 334 si_isa_methods, 335 sizeof(struct si_softc), 336}; 337 338DRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0); 339