1 /* $OpenBSD: i82365_isa.c,v 1.20 2005/03/25 16:41:18 mickey 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/types.h> 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/device.h> 38 #include <sys/extent.h> 39 #include <sys/malloc.h> 40 41 #include <machine/bus.h> 42 #include <machine/intr.h> 43 44 #include <dev/isa/isareg.h> 45 #include <dev/isa/isavar.h> 46 47 #include <dev/pcmcia/pcmciareg.h> 48 #include <dev/pcmcia/pcmciavar.h> 49 #include <dev/pcmcia/pcmciachip.h> 50 51 #include <dev/ic/i82365reg.h> 52 #include <dev/ic/i82365var.h> 53 #include <dev/isa/i82365_isavar.h> 54 55 #ifdef PCICISADEBUG 56 #define DPRINTF(arg) printf arg; 57 #else 58 #define DPRINTF(arg) 59 #endif 60 61 int pcic_isa_probe(struct device *, void *, void *); 62 void pcic_isa_attach(struct device *, struct device *, void *); 63 64 struct cfattach pcic_isa_ca = { 65 sizeof(struct pcic_softc), pcic_isa_probe, pcic_isa_attach 66 }; 67 68 static struct pcmcia_chip_functions pcic_isa_functions = { 69 pcic_chip_mem_alloc, 70 pcic_chip_mem_free, 71 pcic_chip_mem_map, 72 pcic_chip_mem_unmap, 73 74 pcic_chip_io_alloc, 75 pcic_chip_io_free, 76 pcic_chip_io_map, 77 pcic_chip_io_unmap, 78 79 pcic_isa_chip_intr_establish, 80 pcic_isa_chip_intr_disestablish, 81 pcic_isa_chip_intr_string, 82 83 pcic_chip_socket_enable, 84 pcic_chip_socket_disable, 85 }; 86 87 int 88 pcic_isa_probe(parent, match, aux) 89 struct device *parent; 90 void *match, *aux; 91 { 92 struct isa_attach_args *ia = aux; 93 bus_space_tag_t memt = ia->ia_memt, iot = ia->ia_iot; 94 bus_space_handle_t ioh, memh; 95 bus_size_t msize; 96 int val, found; 97 98 /* Disallow wildcarded i/o address. */ 99 if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */) 100 return (0); 101 102 if (bus_space_map(iot, ia->ia_iobase, PCIC_IOSIZE, 0, &ioh)) 103 return (0); 104 105 if (ia->ia_msize == -1) 106 ia->ia_msize = PCIC_MEMSIZE; 107 108 msize = ia->ia_msize; 109 if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) { 110 if (ia->ia_msize > PCIC_MEMSIZE && 111 !bus_space_map(memt, ia->ia_maddr, PCIC_MEMSIZE, 0, &memh)) 112 msize = PCIC_MEMSIZE; 113 else 114 return (0); 115 } 116 found = 0; 117 118 /* 119 * this could be done with a loop, but it would violate the 120 * abstraction 121 */ 122 123 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA + PCIC_IDENT); 124 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 125 if (pcic_ident_ok(val)) 126 found++; 127 128 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB + PCIC_IDENT); 129 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 130 if (pcic_ident_ok(val)) 131 found++; 132 133 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA + PCIC_IDENT); 134 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 135 if (pcic_ident_ok(val)) 136 found++; 137 138 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB + PCIC_IDENT); 139 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); 140 if (pcic_ident_ok(val)) 141 found++; 142 143 bus_space_unmap(iot, ioh, PCIC_IOSIZE); 144 bus_space_unmap(memt, memh, msize); 145 146 if (!found) 147 return (0); 148 ia->ia_iosize = PCIC_IOSIZE; 149 ia->ia_msize = msize; 150 return (1); 151 } 152 153 void 154 pcic_isa_attach(parent, self, aux) 155 struct device *parent, *self; 156 void *aux; 157 { 158 struct pcic_softc *sc = (void *)self; 159 struct pcic_handle *h; 160 struct isa_attach_args *ia = aux; 161 isa_chipset_tag_t ic = ia->ia_ic; 162 bus_space_tag_t iot = ia->ia_iot; 163 bus_space_tag_t memt = ia->ia_memt; 164 bus_space_handle_t ioh; 165 bus_space_handle_t memh; 166 int irq, i; 167 168 /* Map i/o space. */ 169 if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) { 170 printf(": can't map i/o space\n"); 171 return; 172 } 173 174 /* Map mem space. */ 175 if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) { 176 printf(": can't map mem space\n"); 177 return; 178 } 179 180 sc->membase = ia->ia_maddr; 181 sc->subregionmask = (1 << (ia->ia_msize / PCIC_MEM_PAGESIZE)) - 1; 182 183 sc->intr_est = ic; 184 sc->pct = (pcmcia_chipset_tag_t)&pcic_isa_functions; 185 186 sc->iot = iot; 187 sc->ioh = ioh; 188 sc->memt = memt; 189 sc->memh = memh; 190 191 printf("\n"); 192 193 pcic_attach(sc); 194 pcic_isa_bus_width_probe(sc, iot, ioh, ia->ia_iobase, ia->ia_iosize); 195 pcic_attach_sockets(sc); 196 197 /* 198 * Allocate an irq. It will be used by both controllers. I could 199 * use two different interrupts, but interrupts are relatively 200 * scarce, shareable, and for PCIC controllers, very infrequent. 201 */ 202 irq = ia->ia_irq; 203 if (irq == IRQUNK) 204 irq = pcic_intr_find(sc, IST_EDGE); 205 206 if (irq) { 207 sc->ih = isa_intr_establish(ic, irq, IST_EDGE, IPL_TTY, 208 pcic_intr, sc, sc->dev.dv_xname); 209 if (!sc->ih) 210 irq = 0; 211 } 212 sc->irq = irq; 213 214 if (irq) { 215 printf("%s: irq %d, ", sc->dev.dv_xname, irq); 216 217 /* Set up the pcic to interrupt on card detect. */ 218 for (i = 0; i < PCIC_NSLOTS; i++) { 219 h = &sc->handle[i]; 220 if (h->flags & PCIC_FLAG_SOCKETP) { 221 pcic_write(h, PCIC_CSC_INTR, 222 (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) | 223 PCIC_CSC_INTR_CD_ENABLE); 224 powerhook_establish(pcic_power, h); 225 } 226 } 227 } else 228 printf("%s: no irq, ", sc->dev.dv_xname); 229 230 printf("polling enabled\n"); 231 if (sc->poll_established == 0) { 232 timeout_set(&sc->poll_timeout, pcic_poll_intr, sc); 233 timeout_add(&sc->poll_timeout, hz / 2); 234 sc->poll_established = 1; 235 } 236 } 237