1 /* $OpenBSD: i82365_isa.c,v 1.23 2017/09/08 05:36:52 deraadt Exp $ */ 2 /* $NetBSD: i82365_isa.c,v 1.11 1998/06/09 07:25:00 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1997 Marc Horowitz. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Marc Horowitz. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/device.h> 37 #include <sys/extent.h> 38 #include <sys/malloc.h> 39 40 #include <machine/bus.h> 41 #include <machine/intr.h> 42 43 #include <dev/isa/isareg.h> 44 #include <dev/isa/isavar.h> 45 46 #include <dev/pcmcia/pcmciareg.h> 47 #include <dev/pcmcia/pcmciavar.h> 48 #include <dev/pcmcia/pcmciachip.h> 49 50 #include <dev/ic/i82365reg.h> 51 #include <dev/ic/i82365var.h> 52 #include <dev/isa/i82365_isavar.h> 53 54 #ifdef PCICISADEBUG 55 #define DPRINTF(arg) printf arg; 56 #else 57 #define DPRINTF(arg) 58 #endif 59 60 int pcic_isa_probe(struct device *, void *, void *); 61 void pcic_isa_attach(struct device *, struct device *, void *); 62 63 struct cfattach pcic_isa_ca = { 64 sizeof(struct pcic_softc), pcic_isa_probe, pcic_isa_attach 65 }; 66 67 static struct pcmcia_chip_functions pcic_isa_functions = { 68 pcic_chip_mem_alloc, 69 pcic_chip_mem_free, 70 pcic_chip_mem_map, 71 pcic_chip_mem_unmap, 72 73 pcic_chip_io_alloc, 74 pcic_chip_io_free, 75 pcic_chip_io_map, 76 pcic_chip_io_unmap, 77 78 pcic_isa_chip_intr_establish, 79 pcic_isa_chip_intr_disestablish, 80 pcic_isa_chip_intr_string, 81 82 pcic_chip_socket_enable, 83 pcic_chip_socket_disable, 84 }; 85 86 int 87 pcic_isa_probe(parent, match, aux) 88 struct device *parent; 89 void *match, *aux; 90 { 91 struct isa_attach_args *ia = aux; 92 bus_space_tag_t memt = ia->ia_memt, iot = ia->ia_iot; 93 bus_space_handle_t ioh, memh; 94 bus_size_t msize; 95 int val, found; 96 97 /* Disallow wildcarded i/o address. */ 98 if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */) 99 return (0); 100 101 if (bus_space_map(iot, ia->ia_iobase, PCIC_IOSIZE, 0, &ioh)) 102 return (0); 103 104 if (ia->ia_msize == -1) 105 ia->ia_msize = PCIC_MEMSIZE; 106 107 msize = ia->ia_msize; 108 if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) { 109 if (ia->ia_msize > PCIC_MEMSIZE && 110 !bus_space_map(memt, ia->ia_maddr, PCIC_MEMSIZE, 0, &memh)) 111 msize = PCIC_MEMSIZE; 112 else 113 return (0); 114 } 115 found = 0; 116 117 /* 118 * this could be done with a loop, but it would violate the 119 * abstraction 120 */ 121 122 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA + PCIC_IDENT); 123 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 124 if (pcic_ident_ok(val)) 125 found++; 126 127 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB + PCIC_IDENT); 128 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 129 if (pcic_ident_ok(val)) 130 found++; 131 132 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA + PCIC_IDENT); 133 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 134 if (pcic_ident_ok(val)) 135 found++; 136 137 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB + PCIC_IDENT); 138 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 139 if (pcic_ident_ok(val)) 140 found++; 141 142 bus_space_unmap(iot, ioh, PCIC_IOSIZE); 143 bus_space_unmap(memt, memh, msize); 144 145 if (!found) 146 return (0); 147 ia->ia_iosize = PCIC_IOSIZE; 148 ia->ia_msize = msize; 149 return (1); 150 } 151 152 void 153 pcic_isa_attach(parent, self, aux) 154 struct device *parent, *self; 155 void *aux; 156 { 157 struct pcic_softc *sc = (void *)self; 158 struct pcic_handle *h; 159 struct isa_attach_args *ia = aux; 160 isa_chipset_tag_t ic = ia->ia_ic; 161 bus_space_tag_t iot = ia->ia_iot; 162 bus_space_tag_t memt = ia->ia_memt; 163 bus_space_handle_t ioh; 164 bus_space_handle_t memh; 165 int irq, i; 166 167 /* Map i/o space. */ 168 if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) { 169 printf(": can't map i/o space\n"); 170 return; 171 } 172 173 /* Map mem space. */ 174 if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) { 175 printf(": can't map mem space\n"); 176 return; 177 } 178 179 sc->membase = ia->ia_maddr; 180 sc->subregionmask = (1 << (ia->ia_msize / PCIC_MEM_PAGESIZE)) - 1; 181 182 sc->intr_est = ic; 183 sc->pct = (pcmcia_chipset_tag_t)&pcic_isa_functions; 184 185 sc->iot = iot; 186 sc->ioh = ioh; 187 sc->memt = memt; 188 sc->memh = memh; 189 190 printf("\n"); 191 192 pcic_attach(sc); 193 pcic_isa_bus_width_probe(sc, iot, ioh, ia->ia_iobase, ia->ia_iosize); 194 pcic_attach_sockets(sc); 195 196 /* 197 * Allocate an irq. It will be used by both controllers. I could 198 * use two different interrupts, but interrupts are relatively 199 * scarce, shareable, and for PCIC controllers, very infrequent. 200 */ 201 irq = ia->ia_irq; 202 if (irq == IRQUNK) 203 irq = pcic_intr_find(sc, IST_EDGE); 204 205 if (irq) { 206 sc->ih = isa_intr_establish(ic, irq, IST_EDGE, IPL_TTY, 207 pcic_intr, sc, sc->dev.dv_xname); 208 if (!sc->ih) 209 irq = 0; 210 } 211 sc->irq = irq; 212 213 if (irq) { 214 printf("%s: irq %d, ", sc->dev.dv_xname, irq); 215 216 /* Set up the pcic to interrupt on card detect. */ 217 for (i = 0; i < PCIC_NSLOTS; i++) { 218 h = &sc->handle[i]; 219 if (h->flags & PCIC_FLAG_SOCKETP) { 220 pcic_write(h, PCIC_CSC_INTR, 221 (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) | 222 PCIC_CSC_INTR_CD_ENABLE); 223 } 224 } 225 } else 226 printf("%s: no irq, ", sc->dev.dv_xname); 227 228 printf("polling enabled\n"); 229 if (sc->poll_established == 0) { 230 timeout_set(&sc->poll_timeout, pcic_poll_intr, sc); 231 timeout_add_msec(&sc->poll_timeout, 500); 232 sc->poll_established = 1; 233 } 234 } 235