2 * Copyright (c) 1998 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/module.h>
34 #include <machine/bus.h>
35 #include <sys/malloc.h>
38 #include <sys/interrupt.h>
40 #include <isa/isareg.h>
41 #include <isa/isavar.h>
42 #include <isa/isa_common.h>
43 #include <alpha/isa/isavar.h>
44 #include <machine/intr.h>
45 #include <machine/intrcnt.h>
46 #include <machine/resource.h>
47 #include <machine/cpuconf.h>
49 static struct rman isa_irq_rman;
50 static struct rman isa_drq_rman;
53 isa_intr_enable(int irq)
57 outb(IO_ICU1+1, inb(IO_ICU1+1) & ~(1 << irq));
59 outb(IO_ICU2+1, inb(IO_ICU2+1) & ~(1 << (irq - 8)));
64 isa_intr_disable(int irq)
68 outb(IO_ICU1+1, inb(IO_ICU1+1) | (1 << irq));
70 outb(IO_ICU2+1, inb(IO_ICU2+1) | (1 << (irq - 8)));
82 return ((irr2 << 8) | irr1);
91 irr1 = inb(IO_ICU1+1);
92 irr2 = inb(IO_ICU2+1);
93 return ((irr2 << 8) | irr1);
105 static int initted = 0;
110 isa_irq_rman.rm_start = 0;
111 isa_irq_rman.rm_end = 15;
112 isa_irq_rman.rm_type = RMAN_ARRAY;
113 isa_irq_rman.rm_descr = "ISA Interrupt request lines";
114 if (rman_init(&isa_irq_rman)
115 || rman_manage_region(&isa_irq_rman, 0, 1)
116 || rman_manage_region(&isa_irq_rman, 3, 15))
117 panic("isa_probe isa_irq_rman");
119 isa_drq_rman.rm_start = 0;
120 isa_drq_rman.rm_end = 7;
121 isa_drq_rman.rm_type = RMAN_ARRAY;
122 isa_drq_rman.rm_descr = "ISA DMA request lines";
123 if (rman_init(&isa_drq_rman)
124 || rman_manage_region(&isa_drq_rman, 0, 7))
125 panic("isa_probe isa_drq_rman");
127 /* mask all isa interrupts */
128 outb(IO_ICU1+1, 0xff);
129 outb(IO_ICU2+1, 0xff);
131 /* make sure chaining irq is enabled */
136 isa_alloc_intr(device_t bus, device_t child, int irq)
138 return rman_reserve_resource(&isa_irq_rman, irq, irq, 1,
143 isa_alloc_intrs(device_t bus, device_t child, u_long start, u_long end)
145 return rman_reserve_resource(&isa_irq_rman, start, end,
146 end - start + 1, 0, child);
150 isa_release_intr(device_t bus, device_t child, struct resource *r)
152 return rman_release_resource(r);
156 * This implementation simply passes the request up to the parent
157 * bus, which in our case is the pci chipset device, substituting any
158 * configured values if the caller defaulted. We can get away with
159 * this because there is no special mapping for ISA resources on this
160 * platform. When porting this code to another architecture, it may be
161 * necessary to interpose a mapping layer here.
163 * We manage our own interrupt resources since ISA interrupts go through
164 * the ISA PIC, not the PCI interrupt controller.
167 isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
168 u_long start, u_long end, u_long count, u_int flags)
171 * Consider adding a resource definition. We allow rid 0-1 for
172 * irq and drq, 0-3 for memory and 0-7 for ports which is
173 * sufficient for isapnp.
175 int passthrough = (device_get_parent(child) != bus);
176 int isdefault = (start == 0UL && end == ~0UL);
177 struct isa_device* idev = DEVTOISA(child);
178 struct resource_list *rl = &idev->id_resources;
179 struct resource_list_entry *rle;
180 struct resource *res;
182 if (!passthrough && !isdefault) {
183 rle = resource_list_find(rl, type, *rid);
189 if (*rid >= ISA_NIRQ)
193 if (*rid >= ISA_NDRQ)
197 if (*rid >= ISA_NMEM)
201 if (*rid >= ISA_NPORT)
207 resource_list_add(rl, type, *rid, start, end, count);
211 if (type != SYS_RES_IRQ && type != SYS_RES_DRQ)
212 return resource_list_alloc(rl, bus, child, type, rid,
213 start, end, count, flags);
216 rl = device_get_ivars(child);
217 rle = resource_list_find(rl, type, *rid);
221 panic("isa_alloc_resource: resource entry is busy");
223 start = end = rle->start;
228 if (type == SYS_RES_IRQ)
229 res = rman_reserve_resource(&isa_irq_rman, start, start, 1,
232 res = rman_reserve_resource(&isa_drq_rman, start, start, 1,
235 if (res && !passthrough) {
236 rle = resource_list_find(rl, type, *rid);
237 rle->start = rman_get_start(res);
238 rle->end = rman_get_end(res);
247 isa_release_resource(device_t bus, device_t child, int type, int rid,
248 struct resource *res)
250 int passthrough = (device_get_parent(child) != bus);
251 struct isa_device* idev = DEVTOISA(child);
252 struct resource_list *rl = &idev->id_resources;
253 struct resource_list_entry *rle;
256 if (type != SYS_RES_IRQ)
257 return resource_list_release(rl, bus, child, type, rid, res);
259 error = rman_release_resource(res);
261 if (!passthrough && !error) {
262 rle = resource_list_find(rl, SYS_RES_IRQ, rid);
280 * Wrap ISA interrupt routines so that we can feed non-specific
285 isa_handle_intr(void *arg)
287 struct isa_intr *ii = arg;
293 outb(IO_ICU2, 0x20 | (irq & 7));
294 outb(IO_ICU1, 0x20 | (irq > 7 ? 2 : irq));
298 isa_setup_intr(device_t dev, device_t child,
299 struct resource *irq, int flags,
300 driver_intr_t *intr, void *arg, void **cookiep)
305 if (platform.isa_setup_intr)
306 return platform.isa_setup_intr(dev, child, irq, flags,
309 error = rman_activate_resource(irq);
313 ii = malloc(sizeof(struct isa_intr), M_DEVBUF, M_NOWAIT);
318 ii->irq = irq->r_start;
320 error = alpha_setup_intr(
321 device_get_nameunit(child ? child : dev),
322 0x800 + (irq->r_start << 4), isa_handle_intr, ii,
323 ithread_priority(flags), &ii->ih,
324 &intrcnt[INTRCNT_ISA_IRQ + irq->r_start],
330 isa_intr_enable(irq->r_start);
335 device_printf(child, "interrupting at ISA irq %d\n",
342 isa_teardown_intr(device_t dev, device_t child,
343 struct resource *irq, void *cookie)
345 struct isa_intr *ii = cookie;
347 if (platform.isa_teardown_intr) {
348 platform.isa_teardown_intr(dev, child, irq, cookie);
352 alpha_teardown_intr(ii->ih);
353 isa_intr_disable(irq->r_start);