UPDATING: Note that aic(4) was deISAized (forgot to mention at the time).
[dragonfly.git] / sys / bus / isa / i386 / isa_compat.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1998 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: src/sys/i386/isa/isa_compat.c,v 1.18.2.1 2001/05/17 23:05:06 imp Exp $
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/kernel.h>
32#include <sys/bus.h>
33#include <sys/malloc.h>
34#include <sys/module.h>
984263bc 35#include <sys/rman.h>
b47b3275 36#include <sys/machintr.h>
984263bc
MD
37
38#include <machine/vmparam.h>
39#include <vm/vm.h>
40#include <vm/pmap.h>
41#include <machine/pmap.h>
42#include <machine/md_var.h>
43
1f2de5d4
MD
44#include "../isavar.h"
45#include "isa_compat.h"
46#include "isa_device.h"
984263bc
MD
47
48struct isa_compat_resources {
49 struct resource *ports;
50 struct resource *memory;
51 struct resource *drq;
52 struct resource *irq;
53};
54
e1bc6fbb
JS
55struct isa_compat_driver {
56 driver_t driver;
57 struct old_isa_driver *op;
58};
59
984263bc
MD
60int
61isa_compat_nextid(void)
62{
63 static int id = 2; /* id_id of -1, 0 and 1 are "used" */
64
65 return id++;
66}
67
68static void
69isa_compat_alloc_resources(device_t dev, struct isa_compat_resources *res)
70{
71 int rid;
72 u_long start, count;
73
74 if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
75 &start, &count) == 0) {
76 rid = 0;
77 res->ports = bus_alloc_resource(dev, SYS_RES_IOPORT,
78 &rid, 0ul, ~0ul, 1,
79 RF_ACTIVE);
80 if (res->ports == NULL && bootverbose)
85f8e2ea 81 kprintf("isa_compat: didn't get ports for %s\n",
984263bc
MD
82 device_get_name(dev));
83 } else
4090d6ff 84 res->ports = NULL;
984263bc
MD
85
86 if (bus_get_resource(dev, SYS_RES_MEMORY, 0,
87 &start, &count) == 0
88 && start != 0) {
89 rid = 0;
90 res->memory = bus_alloc_resource(dev, SYS_RES_MEMORY,
91 &rid, 0ul, ~0ul, 1,
92 RF_ACTIVE);
93 if (res->memory == NULL && bootverbose)
85f8e2ea 94 kprintf("isa_compat: didn't get memory for %s\n",
984263bc
MD
95 device_get_name(dev));
96 } else
4090d6ff 97 res->memory = NULL;
984263bc
MD
98
99 if (bus_get_resource(dev, SYS_RES_DRQ, 0,
100 &start, &count) == 0) {
101 rid = 0;
102 res->drq = bus_alloc_resource(dev, SYS_RES_DRQ,
103 &rid, 0ul, ~0ul, 1,
104 RF_ACTIVE);
105 if (res->drq == NULL && bootverbose)
85f8e2ea 106 kprintf("isa_compat: didn't get drq for %s\n",
984263bc
MD
107 device_get_name(dev));
108 } else
4090d6ff 109 res->drq = NULL;
984263bc
MD
110
111 if (bus_get_resource(dev, SYS_RES_IRQ, 0,
112 &start, &count) == 0) {
113 rid = 0;
114 res->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
115 &rid, 0ul, ~0ul, 1,
116 RF_SHAREABLE | RF_ACTIVE);
117 if (res->irq == NULL && bootverbose)
85f8e2ea 118 kprintf("isa_compat: didn't get irq for %s\n",
984263bc
MD
119 device_get_name(dev));
120 } else
4090d6ff 121 res->irq = NULL;
984263bc
MD
122}
123
124static void
125isa_compat_release_resources(device_t dev, struct isa_compat_resources *res)
126{
127 if (res->ports) {
128 bus_release_resource(dev, SYS_RES_IOPORT, 0, res->ports);
4090d6ff 129 res->ports = NULL;
984263bc
MD
130 }
131 if (res->memory) {
132 bus_release_resource(dev, SYS_RES_MEMORY, 0, res->memory);
4090d6ff 133 res->memory = NULL;
984263bc
MD
134 }
135 if (res->drq) {
136 bus_release_resource(dev, SYS_RES_DRQ, 0, res->drq);
4090d6ff 137 res->drq = NULL;
984263bc
MD
138 }
139 if (res->irq) {
140 bus_release_resource(dev, SYS_RES_IRQ, 0, res->irq);
4090d6ff 141 res->irq = NULL;
984263bc
MD
142 }
143}
144
145#define irqmask(x) ((x) < 0 ? 0 : (1 << (x)))
146
147static int
148isa_compat_probe(device_t dev)
149{
150 struct isa_device *dvp = device_get_softc(dev);
151 struct isa_compat_resources res;
152 struct old_isa_driver *op;
153 u_long start, count;
154
155 /* No pnp support */
156 if (isa_get_vendorid(dev))
157 return (ENXIO);
158
159 bzero(&res, sizeof(res));
160 /*
161 * Fill in the isa_device fields.
162 */
e1bc6fbb 163 op = ((struct isa_compat_driver *)device_get_driver(dev))->op;
984263bc
MD
164 dvp->id_id = isa_compat_nextid();
165 dvp->id_driver = op->driver;
166 if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
167 &start, &count) == 0)
168 dvp->id_iobase = start;
169 else
170 dvp->id_iobase = -1;
171 if (bus_get_resource(dev, SYS_RES_IRQ, 0,
172 &start, &count) == 0)
173 dvp->id_irq = irqmask(start);
174 else
175 dvp->id_irq = 0;
176 if (bus_get_resource(dev, SYS_RES_DRQ, 0,
177 &start, &count) == 0)
178 dvp->id_drq = start;
179 else
180 dvp->id_drq = -1;
181 if (bus_get_resource(dev, SYS_RES_MEMORY,
182 0, &start, &count) == 0) {
183 dvp->id_maddr = (void *)(uintptr_t)start;
184 dvp->id_msize = count;
185 } else {
186 dvp->id_maddr = NULL;
187 dvp->id_msize = 0;
188 }
189 dvp->id_unit = device_get_unit(dev);
190 dvp->id_flags = device_get_flags(dev);
191 dvp->id_enabled = device_is_enabled(dev); /* XXX unused */
192 dvp->id_device = dev;
193
194 /*
195 * Do the wrapped probe.
196 */
197 if (dvp->id_driver->probe) {
198 int portsize;
199 void *maddr;
200 struct isa_device old;
201
202 isa_compat_alloc_resources(dev, &res);
203 if (res.memory)
204 maddr = rman_get_virtual(res.memory);
205 else
4090d6ff 206 maddr = NULL;
984263bc
MD
207 dvp->id_maddr = maddr;
208 old = *dvp;
209 portsize = dvp->id_driver->probe(dvp);
210 isa_compat_release_resources(dev, &res);
211 if (portsize != 0) {
b47b3275
SZ
212 if (portsize > 0 || dvp->id_iobase != old.id_iobase) {
213 bus_set_resource(dev, SYS_RES_IOPORT, 0,
214 dvp->id_iobase, portsize, -1);
215 }
216 if (dvp->id_irq != old.id_irq) {
217 int intr = ffs(dvp->id_irq) - 1;
218
219 bus_set_resource(dev, SYS_RES_IRQ, 0, intr, 1,
bec969af 220 machintr_legacy_intr_cpuid(intr));
b47b3275
SZ
221 }
222 if (dvp->id_drq != old.id_drq) {
984263bc 223 bus_set_resource(dev, SYS_RES_DRQ, 0,
b47b3275
SZ
224 dvp->id_drq, 1, -1);
225 }
984263bc
MD
226 if (dvp->id_maddr != old.id_maddr
227 || dvp->id_msize != old.id_msize) {
228 maddr = dvp->id_maddr;
b47b3275
SZ
229 if (maddr != NULL) {
230 bus_set_resource(dev, SYS_RES_MEMORY, 0,
231 kvtop(maddr), dvp->id_msize, -1);
232 } else {
984263bc 233 bus_delete_resource(dev,
b47b3275
SZ
234 SYS_RES_MEMORY, 0);
235 }
984263bc
MD
236 }
237 return 0;
238 }
239 }
240 return ENXIO;
241}
242
243static int
244isa_compat_attach(device_t dev)
245{
246 struct isa_device *dvp = device_get_softc(dev);
247 struct isa_compat_resources res;
248 int error;
249
250 bzero(&res, sizeof(res));
251 isa_compat_alloc_resources(dev, &res);
252 if (dvp->id_driver->attach)
253 dvp->id_driver->attach(dvp);
254 if (res.irq && dvp->id_irq && dvp->id_intr) {
255 struct old_isa_driver *op;
256 void *ih;
257
e1bc6fbb 258 op = ((struct isa_compat_driver *)device_get_driver(dev))->op;
984263bc
MD
259 error = BUS_SETUP_INTR(device_get_parent(dev), dev,
260 res.irq, op->type,
261 dvp->id_intr,
262 (void *)(uintptr_t)dvp->id_unit,
0e6f0e28 263 &ih, NULL, NULL);
984263bc 264 if (error)
85f8e2ea 265 kprintf("isa_compat_attach: failed to setup intr: %d\n",
984263bc
MD
266 error);
267 }
9a7c6212 268 device_printf(dev, "driver is using old-style compatibility shims\n");
984263bc
MD
269 return 0;
270}
271
272static device_method_t isa_compat_methods[] = {
273 /* Device interface */
274 DEVMETHOD(device_probe, isa_compat_probe),
275 DEVMETHOD(device_attach, isa_compat_attach),
276
277 { 0, 0 }
278};
279
280/*
281 * Create a new style driver around each old isa driver.
282 */
283void
284isa_wrap_old_drivers(void)
285{
286 int i;
287 struct old_isa_driver *op;
288 devclass_t isa_devclass = devclass_find("isa");
e1bc6fbb 289 struct isa_compat_driver *driver;
984263bc
MD
290
291 for (i = 0, op = &old_drivers[0]; i < old_drivers_count; i++, op++) {
efda3bd0 292 driver = kmalloc(sizeof(struct isa_compat_driver), M_DEVBUF, M_WAITOK | M_ZERO);
e1bc6fbb
JS
293 driver->driver.name = op->driver->name;
294 driver->driver.methods = isa_compat_methods;
295 driver->driver.size = sizeof(struct isa_device);
296 driver->op = op;
984263bc
MD
297 if (op->driver->sensitive_hw)
298 resource_set_int(op->driver->name, -1, "sensitive", 1);
e1bc6fbb 299 devclass_add_driver(isa_devclass, (driver_t *)driver);
984263bc
MD
300 }
301}