Annotation of sys/dev/isa/tcic2_isa.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: tcic2_isa.c,v 1.7 2005/01/27 17:03:23 millert Exp $ */
! 2: /* $NetBSD: tcic2_isa.c,v 1.2 1999/04/08 16:14:29 bad Exp $ */
! 3:
! 4: #undef TCICISADEBUG
! 5:
! 6: /*
! 7: *
! 8: * Copyright (c) 1998, 1999 Christoph Badura. All rights reserved.
! 9: * Copyright (c) 1997 Marc Horowitz. All rights reserved.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by Marc Horowitz.
! 22: * 4. The name of the author may not be used to endorse or promote products
! 23: * derived from this software without specific prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 26: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 27: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 28: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 29: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 30: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 31: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 32: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 33: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 34: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 35: */
! 36:
! 37:
! 38: #include <sys/types.h>
! 39: #include <sys/param.h>
! 40: #include <sys/systm.h>
! 41: #include <sys/device.h>
! 42: #include <sys/extent.h>
! 43: #include <sys/malloc.h>
! 44:
! 45: #include <machine/bus.h>
! 46: #include <machine/intr.h>
! 47:
! 48: #include <dev/isa/isareg.h>
! 49: #include <dev/isa/isavar.h>
! 50:
! 51: #include <dev/pcmcia/pcmciareg.h>
! 52: #include <dev/pcmcia/pcmciavar.h>
! 53: #include <dev/pcmcia/pcmciachip.h>
! 54:
! 55: #include <dev/ic/tcic2reg.h>
! 56: #include <dev/ic/tcic2var.h>
! 57:
! 58: /*****************************************************************************
! 59: * Configurable parameters.
! 60: *****************************************************************************/
! 61:
! 62: /*
! 63: * Default I/O allocation range. If both are set to non-zero, these
! 64: * values will be used instead. Otherwise, the code attempts to probe
! 65: * the bus width. Systems with 10 address bits should use 0x300 and 0xff.
! 66: * Systems with 12 address bits (most) should use 0x400 and 0xbff.
! 67: */
! 68:
! 69: #ifndef TCIC_ISA_ALLOC_IOBASE
! 70: #define TCIC_ISA_ALLOC_IOBASE 0
! 71: #endif
! 72:
! 73: #ifndef TCIC_ISA_ALLOC_IOSIZE
! 74: #define TCIC_ISA_ALLOC_IOSIZE 0
! 75: #endif
! 76:
! 77: int tcic_isa_alloc_iobase = TCIC_ISA_ALLOC_IOBASE;
! 78: int tcic_isa_alloc_iosize = TCIC_ISA_ALLOC_IOSIZE;
! 79:
! 80: /*
! 81: * Default IRQ allocation bitmask. This defines the range of allowable
! 82: * IRQs for PCMCIA slots. Useful if order of probing would screw up other
! 83: * devices, or if TCIC hardware/cards have trouble with certain interrupt
! 84: * lines.
! 85: *
! 86: * We disable IRQ 10 by default, since some common laptops (namely, the
! 87: * NEC Versa series) reserve IRQ 10 for the docking station SCSI interface.
! 88: *
! 89: * XXX Do we care about this? the Versa doesn't use a tcic. -chb
! 90: */
! 91:
! 92: #ifndef TCIC_ISA_INTR_ALLOC_MASK
! 93: #define TCIC_ISA_INTR_ALLOC_MASK 0xffff
! 94: #endif
! 95:
! 96: int tcic_isa_intr_alloc_mask = TCIC_ISA_INTR_ALLOC_MASK;
! 97:
! 98: /*****************************************************************************
! 99: * End of configurable parameters.
! 100: *****************************************************************************/
! 101:
! 102: #ifdef TCICISADEBUG
! 103: int tcic_isa_debug = 1;
! 104: #define DPRINTF(arg) if (tcic_isa_debug) printf arg;
! 105: #else
! 106: #define DPRINTF(arg)
! 107: #endif
! 108:
! 109: int tcic_isa_probe(struct device *, void *, void *);
! 110: void tcic_isa_attach(struct device *, struct device *, void *);
! 111:
! 112: void *tcic_isa_chip_intr_establish(pcmcia_chipset_handle_t,
! 113: struct pcmcia_function *, int, int (*) (void *), void *, char *);
! 114: void tcic_isa_chip_intr_disestablish(pcmcia_chipset_handle_t, void *);
! 115: const char *tcic_isa_chip_intr_string(pcmcia_chipset_handle_t, void *);
! 116:
! 117: struct cfattach tcic_isa_ca = {
! 118: sizeof(struct tcic_softc), tcic_isa_probe, tcic_isa_attach
! 119: };
! 120:
! 121: static struct pcmcia_chip_functions tcic_isa_functions = {
! 122: tcic_chip_mem_alloc,
! 123: tcic_chip_mem_free,
! 124: tcic_chip_mem_map,
! 125: tcic_chip_mem_unmap,
! 126:
! 127: tcic_chip_io_alloc,
! 128: tcic_chip_io_free,
! 129: tcic_chip_io_map,
! 130: tcic_chip_io_unmap,
! 131:
! 132: tcic_isa_chip_intr_establish,
! 133: tcic_isa_chip_intr_disestablish,
! 134: tcic_isa_chip_intr_string,
! 135:
! 136: tcic_chip_socket_enable,
! 137: tcic_chip_socket_disable,
! 138: };
! 139:
! 140: int
! 141: tcic_isa_probe(parent, match, aux)
! 142: struct device *parent;
! 143: void *match;
! 144: void *aux;
! 145: {
! 146: struct isa_attach_args *ia = aux;
! 147: bus_space_tag_t iot = ia->ia_iot;
! 148: bus_space_handle_t ioh, memh;
! 149: int val, found;
! 150:
! 151: /* Disallow wildcarded i/o address. */
! 152: if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */)
! 153: return (0);
! 154:
! 155: if (bus_space_map(iot, ia->ia_iobase, TCIC_IOSIZE, 0, &ioh))
! 156: return (0);
! 157:
! 158: if (ia->ia_msize == 0)
! 159: ia->ia_msize = TCIC_MEMSIZE;
! 160:
! 161: if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
! 162: return (0);
! 163:
! 164: DPRINTF(("tcic probing 0x%03x\n", ia->ia_iobase));
! 165: found = 0;
! 166:
! 167: /*
! 168: * First, check for the reserved bits to be zero.
! 169: */
! 170: if (tcic_check_reserved_bits(iot, ioh)) {
! 171: DPRINTF(("tcic: reserved bits checked OK\n"));
! 172: /* Second, check whether the we know how to handle the chip. */
! 173: if ((val = tcic_chipid(iot, ioh))) {
! 174: DPRINTF(("tcic id: 0x%02x\n", val));
! 175: if (tcic_chipid_known(val))
! 176: found++;
! 177: }
! 178: }
! 179: else
! 180: DPRINTF(("tcic: reserved bits didn't check OK\n"));
! 181:
! 182: bus_space_unmap(iot, ioh, TCIC_IOSIZE);
! 183: bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
! 184:
! 185: if (!found)
! 186: return (0);
! 187:
! 188: ia->ia_iosize = TCIC_IOSIZE;
! 189:
! 190: return (1);
! 191: }
! 192:
! 193: void
! 194: tcic_isa_attach(parent, self, aux)
! 195: struct device *parent, *self;
! 196: void *aux;
! 197: {
! 198: struct tcic_softc *sc = (void *) self;
! 199: struct isa_attach_args *ia = aux;
! 200: isa_chipset_tag_t ic = ia->ia_ic;
! 201: bus_space_tag_t iot = ia->ia_iot;
! 202: bus_space_tag_t memt = ia->ia_memt;
! 203: bus_space_handle_t ioh;
! 204: bus_space_handle_t memh;
! 205:
! 206: /* Map i/o space. */
! 207: if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) {
! 208: printf(": can't map i/o space\n");
! 209: return;
! 210: }
! 211:
! 212: /* Map mem space. */
! 213: if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) {
! 214: printf(": can't map mem space\n");
! 215: return;
! 216: }
! 217:
! 218: sc->membase = ia->ia_maddr;
! 219: sc->subregionmask = (1 << (ia->ia_msize / TCIC_MEM_PAGESIZE)) - 1;
! 220: sc->memsize2 = tcic_log2((u_int)ia->ia_msize);
! 221:
! 222: sc->intr_est = ic;
! 223: sc->pct = (pcmcia_chipset_tag_t) &tcic_isa_functions;
! 224:
! 225: sc->iot = iot;
! 226: sc->ioh = ioh;
! 227: sc->memt = memt;
! 228: sc->memh = memh;
! 229:
! 230: /*
! 231: * determine chip type and initialise some chip type dependend
! 232: * parameters in softc.
! 233: */
! 234: sc->chipid = tcic_chipid(iot, ioh);
! 235: sc->validirqs = tcic_validirqs(sc->chipid);
! 236:
! 237: /*
! 238: * allocate an irq. interrupts are relatively
! 239: * scarce but for TCIC controllers very infrequent.
! 240: */
! 241:
! 242: if ((sc->irq = ia->ia_irq) == IRQUNK) {
! 243: if (isa_intr_alloc(ic,
! 244: sc->validirqs & (tcic_isa_intr_alloc_mask & 0xff00),
! 245: IST_EDGE, &sc->irq)) {
! 246: printf("\n%s: can't allocate interrupt\n",
! 247: sc->dev.dv_xname);
! 248: return;
! 249: }
! 250: printf(": using irq %d", sc->irq);
! 251: }
! 252: printf("\n");
! 253:
! 254: tcic_attach(sc);
! 255:
! 256:
! 257: /*
! 258: * XXX mycroft recommends I/O space range 0x400-0xfff.
! 259: */
! 260:
! 261: /*
! 262: * XXX some hardware doesn't seem to grok addresses in 0x400 range--
! 263: * apparently missing a bit or more of address lines. (e.g.
! 264: * CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
! 265: * TravelMate 5000--not clear which is at fault)
! 266: *
! 267: * Add a kludge to detect 10 bit wide buses and deal with them,
! 268: * and also a config file option to override the probe.
! 269: */
! 270:
! 271: #if 0
! 272: /*
! 273: * This is what we'd like to use, but...
! 274: */
! 275: sc->iobase = 0x400;
! 276: sc->iosize = 0xbff;
! 277: #else
! 278: /*
! 279: * ...the above bus width probe doesn't always work.
! 280: * So, experimentation has shown the following range
! 281: * to not lose on systems that 0x300-0x3ff loses on
! 282: * (e.g. the NEC Versa 6030X).
! 283: */
! 284: sc->iobase = 0x330;
! 285: sc->iosize = 0x0cf;
! 286: #endif
! 287:
! 288: DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx)\n",
! 289: sc->dev.dv_xname, (long) sc->iobase,
! 290: (long) sc->iobase + sc->iosize));
! 291:
! 292: if (tcic_isa_alloc_iobase && tcic_isa_alloc_iosize) {
! 293: sc->iobase = tcic_isa_alloc_iobase;
! 294: sc->iosize = tcic_isa_alloc_iosize;
! 295:
! 296: DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx "
! 297: "(config override)\n", sc->dev.dv_xname, (long) sc->iobase,
! 298: (long) sc->iobase + sc->iosize));
! 299: }
! 300: sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY,
! 301: tcic_intr, sc, sc->dev.dv_xname);
! 302: if (sc->ih == NULL) {
! 303: printf("%s: can't establish interrupt\n", sc->dev.dv_xname);
! 304: return;
! 305: }
! 306:
! 307: tcic_attach_sockets(sc);
! 308: }
! 309:
! 310: void *
! 311: tcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg, xname)
! 312: pcmcia_chipset_handle_t pch;
! 313: struct pcmcia_function *pf;
! 314: int ipl;
! 315: int (*fct)(void *);
! 316: void *arg;
! 317: char *xname;
! 318: {
! 319: struct tcic_handle *h = (struct tcic_handle *) pch;
! 320: int irq, ist, val, reg;
! 321: void *ih;
! 322: int irqmap[] = {
! 323: 0, 0, 0, TCIC_SCF1_IRQ3, TCIC_SCF1_IRQ4, TCIC_SCF1_IRQ5,
! 324: TCIC_SCF1_IRQ6, TCIC_SCF1_IRQ7, 0, TCIC_SCF1_IRQ9,
! 325: TCIC_SCF1_IRQ10, TCIC_SCF1_IRQ11, TCIC_SCF1_IRQ12, 0,
! 326: TCIC_SCF1_IRQ14, TCIC_SCF1_IRQ15
! 327: };
! 328:
! 329: DPRINTF(("%s: tcic_isa_chip_intr_establish\n", h->sc->dev.dv_xname));
! 330:
! 331: /* XXX should we convert level to pulse? -chb */
! 332: if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
! 333: ist = IST_LEVEL;
! 334: else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
! 335: ist = IST_PULSE;
! 336: else
! 337: ist = IST_LEVEL;
! 338:
! 339: if (isa_intr_alloc(h->sc->intr_est,
! 340: h->sc->validirqs & tcic_isa_intr_alloc_mask, ist, &irq))
! 341: return (NULL);
! 342: if ((ih = isa_intr_establish(h->sc->intr_est, irq, ist, ipl,
! 343: fct, arg, h->pcmcia->dv_xname)) == NULL)
! 344: return (NULL);
! 345:
! 346: DPRINTF(("%s: intr established\n", h->sc->dev.dv_xname));
! 347:
! 348: h->ih_irq = irq;
! 349:
! 350: reg = TCIC_IR_SCF1_N(h->sock);
! 351: val = (tcic_read_ind_2(h, reg) & (~TCIC_SCF1_IRQ_MASK)) | irqmap[irq];
! 352: tcic_write_ind_2(h, reg, val);
! 353:
! 354: printf(" irq %d", irq);
! 355: return (ih);
! 356: }
! 357:
! 358: void
! 359: tcic_isa_chip_intr_disestablish(pch, ih)
! 360: pcmcia_chipset_handle_t pch;
! 361: void *ih;
! 362: {
! 363: struct tcic_handle *h = (struct tcic_handle *) pch;
! 364: int val, reg;
! 365:
! 366: DPRINTF(("%s: tcic_isa_chip_intr_disestablish\n", h->sc->dev.dv_xname));
! 367:
! 368: h->ih_irq = 0;
! 369:
! 370: reg = TCIC_IR_SCF1_N(h->sock);
! 371: val = tcic_read_ind_2(h, reg);
! 372: val &= ~TCIC_SCF1_IRQ_MASK;
! 373: tcic_write_ind_2(h, reg, val);
! 374:
! 375: isa_intr_disestablish(h->sc->intr_est, ih);
! 376: }
! 377:
! 378: const char *
! 379: tcic_isa_chip_intr_string(pch, ih)
! 380: pcmcia_chipset_handle_t pch;
! 381: void *ih;
! 382: {
! 383: struct tcic_handle *h = (struct tcic_handle *) pch;
! 384: static char irqstr[64];
! 385:
! 386: if (ih == NULL)
! 387: snprintf(irqstr, sizeof(irqstr), "couldn't establish interrupt");
! 388: else
! 389: snprintf(irqstr, sizeof(irqstr), "irq %d", h->ih_irq);
! 390: return (irqstr);
! 391: }
CVSweb