1 /* $NetBSD: i82365_isasubr.c,v 1.3 1999/10/15 06:07:27 haya Exp $ */
2 /* $NetBSD: i82365_isa.c,v 1.11 1998/06/09 07:25:00 thorpej Exp $ */
6 * Copyright (c) 1998 Bill Sommerfeld. All rights reserved.
7 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Marc Horowitz.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/kernel.h>
40 #include <sys/queue.h>
41 #include <sys/types.h>
44 #include <machine/bus.h>
46 #include <machine/resource.h>
48 #include <isa/isavar.h>
50 #include <dev/pccard/pccardreg.h>
51 #include <dev/pccard/pccardvar.h>
53 #include <dev/pcic/i82365reg.h>
54 #include <dev/pcic/i82365var.h>
59 /*****************************************************************************
60 * Configurable parameters.
61 *****************************************************************************/
64 * Default I/O allocation range. If both are set to non-zero, these
65 * values will be used instead. Otherwise, the code attempts to probe
66 * the bus width. Systems with 10 address bits should use 0x300 and 0xff.
67 * Systems with 12 address bits (most) should use 0x400 and 0xbff.
70 #ifndef PCIC_ISA_ALLOC_IOBASE
71 #define PCIC_ISA_ALLOC_IOBASE 0
74 #ifndef PCIC_ISA_ALLOC_IOSIZE
75 #define PCIC_ISA_ALLOC_IOSIZE 0
78 int pcic_isa_alloc_iobase = PCIC_ISA_ALLOC_IOBASE;
79 int pcic_isa_alloc_iosize = PCIC_ISA_ALLOC_IOSIZE;
83 * Default IRQ allocation bitmask. This defines the range of allowable
84 * IRQs for PCCARD slots. Useful if order of probing would screw up other
85 * devices, or if PCIC hardware/cards have trouble with certain interrupt
88 * We disable IRQ 10 by default, since some common laptops (namely, the
89 * NEC Versa series) reserve IRQ 10 for the docking station SCSI interface.
92 #ifndef PCIC_ISA_INTR_ALLOC_MASK
93 #define PCIC_ISA_INTR_ALLOC_MASK 0xfbff
96 int pcic_isa_intr_alloc_mask = PCIC_ISA_INTR_ALLOC_MASK;
98 /*****************************************************************************
99 * End of configurable parameters.
100 *****************************************************************************/
102 #define PCICISADEBUG 1
105 int pcicisa_debug = PCICISADEBUG;
106 #define DPRINTF(arg) if (pcicisa_debug) printf arg;
107 #define DEVPRINTF(arg) if (pcicisa_debug) device_printf arg;
110 #define DEVPRINTF(arg)
113 static struct isa_pnp_id pcic_ids[] = {
114 {PCIC_PNP_ACTIONTEC, NULL}, /* AEI0218 */
115 {PCIC_PNP_IBM3765, NULL}, /* IBM3765 */
116 {PCIC_PNP_82365, NULL}, /* PNP0E00 */
117 {PCIC_PNP_CL_PD6720, NULL}, /* PNP0E01 */
118 {PCIC_PNP_VLSI_82C146, NULL}, /* PNP0E02 */
119 {PCIC_PNP_82365_CARDBUS, NULL}, /* PNP0E03 */
120 {PCIC_PNP_SCM_SWAPBOX, NULL}, /* SCM0469 */
125 pcic_isa_bus_width_probe (device_t dev)
127 struct pcic_softc *sc = PCIC_SOFTC(dev);
128 bus_space_handle_t ioh_high;
129 int i, iobuswidth, tmp1, tmp2;
134 bus_space_handle_t ioh;
137 base = rman_get_start(sc->port_res);
138 length = rman_get_size(sc->port_res);
143 * figure out how wide the isa bus is. Do this by checking if the
144 * pcic controller is mirrored 0x400 above where we expect it to be.
149 r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, base + 0x400,
150 base + 0x400 + length, length, RF_ACTIVE);
152 printf("Can't allocated mirror area for pcic bus width probe\n");
155 ioh_high = rman_get_bushandle(r);
156 for (i = 0; i < PCIC_NSLOTS; i++) {
157 if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) {
159 * read the ident flags from the normal space and
160 * from the mirror, and compare them
163 bus_space_write_1(iot, ioh, PCIC_REG_INDEX,
164 sc->handle[i].sock + PCIC_IDENT);
165 tmp1 = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
167 bus_space_write_1(iot, ioh_high, PCIC_REG_INDEX,
168 sc->handle[i].sock + PCIC_IDENT);
169 tmp2 = bus_space_read_1(iot, ioh_high, PCIC_REG_DATA);
175 bus_release_resource(dev, SYS_RES_IOPORT, rid, r);
178 * XXX mycroft recommends I/O space range 0x400-0xfff . I should put
179 * this in a header somewhere
183 * XXX some hardware doesn't seem to grok addresses in 0x400 range--
184 * apparently missing a bit or more of address lines. (e.g.
185 * CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
186 * TravelMate 5000--not clear which is at fault)
188 * Add a kludge to detect 10 bit wide buses and deal with them,
189 * and also a config file option to override the probe.
192 if (iobuswidth == 10) {
198 * This is what we'd like to use, but...
204 * ...the above bus width probe doesn't always work.
205 * So, experimentation has shown the following range
206 * to not lose on systems that 0x300-0x3ff loses on
207 * (e.g. the NEC Versa 6030X).
214 DEVPRINTF((dev, "bus_space_alloc range 0x%04lx-0x%04lx (probed)\n",
215 (long) sc->iobase, (long) sc->iobase + sc->iosize));
217 if (pcic_isa_alloc_iobase && pcic_isa_alloc_iosize) {
218 sc->iobase = pcic_isa_alloc_iobase;
219 sc->iosize = pcic_isa_alloc_iosize;
221 DEVPRINTF((dev, "bus_space_alloc range 0x%04lx-0x%04lx "
222 "(config override)\n", (long) sc->iobase,
223 (long) sc->iobase + sc->iosize));
229 pcic_isa_check(device_t dev, u_int16_t addr)
232 bus_space_handle_t ioh;
235 struct resource *res;
238 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, addr, addr,
239 PCIC_IOSIZE, RF_ACTIVE);
242 iot = rman_get_bustag(res);
243 ioh = rman_get_bushandle(res);
247 * this could be done with a loop, but it would violate the
250 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA + PCIC_IDENT);
251 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
252 if (pcic_ident_ok(val))
255 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB + PCIC_IDENT);
256 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
257 if (pcic_ident_ok(val))
260 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA + PCIC_IDENT);
261 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
262 if (pcic_ident_ok(val))
265 bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB + PCIC_IDENT);
266 val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
267 if (pcic_ident_ok(val))
270 bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
277 pcic_isa_probe(device_t dev)
280 struct resource *res;
285 /* Check isapnp ids */
286 error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids);
290 /* If we had some other problem. */
291 if (!(error == 0 || error == ENOENT))
294 /* If we have the resources we need then we're good to go. */
295 if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0)
298 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE);
301 * No IRQ specified, find one. This can be due to the PnP
302 * data not specifying any IRQ
304 for (i = 0; i < 16; i++) {
305 if (((1 << i) & PCIC_INTR_IRQ_VALIDMASK) == 0)
307 res = bus_alloc_resource(dev, SYS_RES_IRQ,
308 &rid, i, i, 1, RF_ACTIVE);
314 mem = rman_get_start(res);
315 bus_release_resource(dev, SYS_RES_IRQ, rid, res);
316 bus_set_resource(dev, SYS_RES_IRQ, 0, i, 1);
318 bus_release_resource(dev, SYS_RES_IRQ, rid, res);
320 /* XXX This might not be needed in future, get it directly from
323 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0,
327 * We failed to get memory. Since this XXX comment above
328 * indicates that this is transient, we try to get a hunk
329 * of memory in the isa hole. Sure would be nice if there
330 * were some MI constants for this.
332 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
333 0xa0000, 0xdffff, 1 << 13, RF_ACTIVE);
335 mem = rman_get_start(res);
336 bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
337 bus_set_resource(dev, SYS_RES_MEMORY, 0, mem, 1 << 13);
340 bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
343 device_printf(dev, "Cannot allocate mem\n");
350 pcic_isa_attach(device_t dev)
354 if ((err = pcic_attach(dev)) == 0)
355 pcic_isa_bus_width_probe (dev);
360 pcic_isa_detach(device_t dev)
366 static device_method_t pcic_isa_methods[] = {
367 /* Device interface */
368 DEVMETHOD(device_probe, pcic_isa_probe),
369 DEVMETHOD(device_attach, pcic_isa_attach),
370 DEVMETHOD(device_detach, pcic_isa_detach),
371 DEVMETHOD(device_shutdown, bus_generic_shutdown),
372 DEVMETHOD(device_suspend, pcic_suspend),
373 DEVMETHOD(device_resume, pcic_resume),
376 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
377 DEVMETHOD(bus_print_child, bus_generic_print_child),
378 DEVMETHOD(bus_alloc_resource, pcic_alloc_resource),
379 DEVMETHOD(bus_release_resource, pcic_release_resource),
380 DEVMETHOD(bus_activate_resource, pcic_activate_resource),
381 DEVMETHOD(bus_deactivate_resource, pcic_deactivate_resource),
382 DEVMETHOD(bus_setup_intr, pcic_setup_intr),
383 DEVMETHOD(bus_teardown_intr, pcic_teardown_intr),
385 /* pccard/cardbus interface */
386 DEVMETHOD(card_set_res_flags, pcic_set_res_flags),
387 DEVMETHOD(card_set_memory_offset, pcic_set_memory_offset),
389 /* Power Interface */
390 DEVMETHOD(power_enable_socket, pcic_enable_socket),
391 DEVMETHOD(power_disable_socket, pcic_disable_socket),
395 static driver_t pcic_driver = {
398 sizeof(struct pcic_softc)
401 static devclass_t pcic_devclass;
403 DRIVER_MODULE(pcic, isa, pcic_driver, pcic_devclass, 0, 0);
404 MODULE_DEPEND(pcic, pccard, 1, 1, 1);