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: releng/5.0/sys/i386/isa/isa_compat.c 78135 2001-06-12 09:40:04Z peter $
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>
35 #include <machine/bus.h>
36 #include <sys/rman.h>
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
44 #include <machine/resource.h>
45 #include <isa/isavar.h>
46 #include <i386/isa/isa_device.h>
47
48 struct isa_compat_resources {
49 struct resource *ports;
50 struct resource *memory;
51 struct resource *drq;
52 struct resource *irq;
53 };
54
55 static void
56 isa_compat_alloc_resources(device_t dev, struct isa_compat_resources *res)
57 {
58 int rid;
59 u_long start, count;
60
61 if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
62 &start, &count) == 0) {
63 rid = 0;
64 res->ports = bus_alloc_resource(dev, SYS_RES_IOPORT,
65 &rid, 0ul, ~0ul, 1,
66 RF_ACTIVE);
67 if (res->ports == NULL && bootverbose)
68 printf("isa_compat: didn't get ports for %s\n",
69 device_get_name(dev));
70 } else
71 res->ports = 0;
72
73 if (bus_get_resource(dev, SYS_RES_MEMORY, 0,
74 &start, &count) == 0
75 && start != 0) {
76 rid = 0;
77 res->memory = bus_alloc_resource(dev, SYS_RES_MEMORY,
78 &rid, 0ul, ~0ul, 1,
79 RF_ACTIVE);
80 if (res->memory == NULL && bootverbose)
81 printf("isa_compat: didn't get memory for %s\n",
82 device_get_name(dev));
83 } else
84 res->memory = 0;
85
86 if (bus_get_resource(dev, SYS_RES_DRQ, 0,
87 &start, &count) == 0) {
88 rid = 0;
89 res->drq = bus_alloc_resource(dev, SYS_RES_DRQ,
90 &rid, 0ul, ~0ul, 1,
91 RF_ACTIVE);
92 if (res->drq == NULL && bootverbose)
93 printf("isa_compat: didn't get drq for %s\n",
94 device_get_name(dev));
95 } else
96 res->drq = 0;
97
98 if (bus_get_resource(dev, SYS_RES_IRQ, 0,
99 &start, &count) == 0) {
100 rid = 0;
101 res->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
102 &rid, 0ul, ~0ul, 1,
103 RF_SHAREABLE | RF_ACTIVE);
104 if (res->irq == NULL && bootverbose)
105 printf("isa_compat: didn't get irq for %s\n",
106 device_get_name(dev));
107 } else
108 res->irq = 0;
109 }
110
111 static void
112 isa_compat_release_resources(device_t dev, struct isa_compat_resources *res)
113 {
114 if (res->ports) {
115 bus_release_resource(dev, SYS_RES_IOPORT, 0, res->ports);
116 res->ports = 0;
117 }
118 if (res->memory) {
119 bus_release_resource(dev, SYS_RES_MEMORY, 0, res->memory);
120 res->memory = 0;
121 }
122 if (res->drq) {
123 bus_release_resource(dev, SYS_RES_DRQ, 0, res->drq);
124 res->drq = 0;
125 }
126 if (res->irq) {
127 bus_release_resource(dev, SYS_RES_IRQ, 0, res->irq);
128 res->irq = 0;
129 }
130 }
131
132 #define irqmask(x) ((x) < 0 ? 0 : (1 << (x)))
133
134 static int
135 isa_compat_probe(device_t dev)
136 {
137 struct isa_device *dvp = device_get_softc(dev);
138 struct isa_compat_resources res;
139 u_long start, count;
140
141 /* No pnp support */
142 if (isa_get_vendorid(dev))
143 return (ENXIO);
144
145 bzero(&res, sizeof(res));
146 /*
147 * Fill in the isa_device fields.
148 */
149 dvp->id_driver = device_get_driver(dev)->priv;
150 if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
151 &start, &count) == 0)
152 dvp->id_iobase = start;
153 else
154 dvp->id_iobase = -1;
155 if (bus_get_resource(dev, SYS_RES_IRQ, 0,
156 &start, &count) == 0)
157 dvp->id_irq = irqmask(start);
158 else
159 dvp->id_irq = 0;
160 if (bus_get_resource(dev, SYS_RES_DRQ, 0,
161 &start, &count) == 0)
162 dvp->id_drq = start;
163 else
164 dvp->id_drq = -1;
165 if (bus_get_resource(dev, SYS_RES_MEMORY,
166 0, &start, &count) == 0) {
167 dvp->id_maddr = (void *)(uintptr_t)start;
168 dvp->id_msize = count;
169 } else {
170 dvp->id_maddr = NULL;
171 dvp->id_msize = 0;
172 }
173 dvp->id_unit = device_get_unit(dev);
174 dvp->id_flags = device_get_flags(dev);
175 dvp->id_enabled = device_is_enabled(dev); /* XXX unused */
176 dvp->id_device = dev;
177
178 /*
179 * Do the wrapped probe.
180 */
181 if (dvp->id_driver->probe) {
182 int portsize;
183 void *maddr;
184 struct isa_device old;
185
186 isa_compat_alloc_resources(dev, &res);
187 if (res.memory)
188 maddr = rman_get_virtual(res.memory);
189 else
190 maddr = 0;
191 dvp->id_maddr = maddr;
192 old = *dvp;
193 portsize = dvp->id_driver->probe(dvp);
194 isa_compat_release_resources(dev, &res);
195 if (portsize != 0) {
196 if (portsize > 0 || dvp->id_iobase != old.id_iobase)
197 bus_set_resource(dev, SYS_RES_IOPORT,
198 0, dvp->id_iobase, portsize);
199 if (dvp->id_irq != old.id_irq)
200 bus_set_resource(dev, SYS_RES_IRQ, 0,
201 ffs(dvp->id_irq) - 1, 1);
202 if (dvp->id_drq != old.id_drq)
203 bus_set_resource(dev, SYS_RES_DRQ, 0,
204 dvp->id_drq, 1);
205 if (dvp->id_maddr != old.id_maddr
206 || dvp->id_msize != old.id_msize) {
207 maddr = dvp->id_maddr;
208 if (maddr != NULL)
209 bus_set_resource(dev,
210 SYS_RES_MEMORY,
211 0,
212 kvtop(maddr),
213 dvp->id_msize);
214 else
215 bus_delete_resource(dev,
216 SYS_RES_MEMORY,
217 0);
218 }
219 return 0;
220 }
221 }
222 return ENXIO;
223 }
224
225 static int
226 isa_compat_attach(device_t dev)
227 {
228 struct isa_device *dvp = device_get_softc(dev);
229 struct isa_compat_resources res;
230 int error;
231
232 bzero(&res, sizeof(res));
233 isa_compat_alloc_resources(dev, &res);
234 if (dvp->id_driver->attach)
235 dvp->id_driver->attach(dvp);
236 if (res.irq && dvp->id_irq && dvp->id_intr) {
237 void *ih;
238
239 error = BUS_SETUP_INTR(device_get_parent(dev), dev,
240 res.irq, dvp->id_driver->intrflags,
241 dvp->id_intr,
242 (void *)(uintptr_t)dvp->id_unit,
243 &ih);
244 if (error)
245 printf("isa_compat_attach: failed to setup intr: %d\n",
246 error);
247 }
248 device_printf(dev, "driver is using old-style compatibility shims\n");
249 return 0;
250 }
251
252 static device_method_t isa_compat_methods[] = {
253 /* Device interface */
254 DEVMETHOD(device_probe, isa_compat_probe),
255 DEVMETHOD(device_attach, isa_compat_attach),
256
257 { 0, 0 }
258 };
259
260 /*
261 * Create a new style driver around each old isa driver.
262 */
263 int
264 compat_isa_handler(module_t mod, int type, void *data)
265 {
266 struct isa_driver *id = (struct isa_driver *)data;
267 driver_t *driver;
268 devclass_t isa_devclass = devclass_find("isa");
269
270 switch (type) {
271 case MOD_LOAD:
272 driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT | M_ZERO);
273 if (!driver)
274 return ENOMEM;
275 driver->name = id->name;
276 driver->methods = isa_compat_methods;
277 driver->size = sizeof(struct isa_device);
278 driver->priv = id;
279 if (id->sensitive_hw) {
280 #if 0
281 resource_set_int(id->name, -1, "sensitive", 1);
282 #else
283 printf("WARNING: isa driver %s is sensitive, but cannot set it!\n",
284 driver->name);
285 #endif
286 }
287 devclass_add_driver(isa_devclass, driver);
288 break;
289 case MOD_UNLOAD:
290 printf("%s: module unload not supported!\n", id->name);
291 return EOPNOTSUPP;
292 default:
293 break;
294 }
295 return 0;
296 }
Cache object: 9f71f0fb3aa6230595a2acde3afb4899
|