Deleted Added
full compact
digi_isa.c (272904) digi_isa.c (296137)
1/*-
2 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Slawa Olhovchenkov
4 * John Prince <johnp@knight-trosoft.com>
5 * Eric Hernes
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Slawa Olhovchenkov
4 * John Prince <johnp@knight-trosoft.com>
5 * Eric Hernes
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/digi/digi_isa.c 272904 2014-10-10 19:12:04Z jhb $");
32__FBSDID("$FreeBSD: head/sys/dev/digi/digi_isa.c 296137 2016-02-27 03:38:01Z jhibbits $");
33
34/*-
35 * TODO:
36 * Figure out how to make the non-Xi boards use memory addresses other
37 * than 0xd0000 !!!
38 */
39
40#include <sys/param.h>
41
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/module.h>
45#include <sys/tty.h>
46#include <sys/bus.h>
47#include <machine/bus.h>
48#include <sys/rman.h>
49#include <machine/resource.h>
50#include <vm/vm.h>
51#include <vm/pmap.h>
52
53#include <sys/digiio.h>
54#include <dev/digi/digireg.h>
55#include <dev/digi/digi.h>
56
57/* Valid i/o addresses are any of these with either 0 or 4 added */
58static u_long digi_validio[] = {
59 0x100, 0x110, 0x120, 0x200, 0x220, 0x300, 0x320
60};
61#define DIGI_NVALIDIO (sizeof(digi_validio) / sizeof(digi_validio[0]))
62#define IO_SIZE 0x04
63
64static u_long digi_validmem[] = {
65 0x80000, 0x88000, 0x90000, 0x98000, 0xa0000, 0xa8000, 0xb0000, 0xb8000,
66 0xc0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000, 0xe8000, 0xf0000, 0xf8000,
67 0xf0000000, 0xf1000000, 0xf2000000, 0xf3000000, 0xf4000000, 0xf5000000,
68 0xf6000000, 0xf7000000, 0xf8000000, 0xf9000000, 0xfa000000, 0xfb000000,
69 0xfc000000, 0xfd000000, 0xfe000000, 0xff000000
70};
71#define DIGI_NVALIDMEM (sizeof(digi_validmem) / sizeof(digi_validmem[0]))
72
73static u_char *
74digi_isa_setwin(struct digi_softc *sc, unsigned int addr)
75{
76 outb(sc->wport, sc->window = FEPWIN | (addr >> sc->win_bits));
77 return (sc->vmem + (addr % sc->win_size));
78}
79
80static u_char *
81digi_xi_setwin(struct digi_softc *sc, unsigned int addr)
82{
83 outb(sc->wport, sc->window = FEPMEM);
84 return (sc->vmem + addr);
85}
86
87static void
88digi_isa_hidewin(struct digi_softc *sc)
89{
90 outb(sc->wport, sc->window = 0);
91 /* outb(sc->port, 0); */
92}
93
94static void
95digi_isa_towin(struct digi_softc *sc, int win)
96{
97 outb(sc->wport, sc->window = win);
98}
99
100static void
101digi_xi_towin(struct digi_softc *sc, int win)
102{
103 outb(sc->wport, sc->window = FEPMEM);
104}
105
106/*
107 * sc->port should be set and its resource allocated.
108 */
109static int
110digi_isa_check(struct digi_softc *sc)
111{
112 int i, ident;
113
114 sc->name = NULL;
115
116 /* Invasive probe - reset the card */
117 outb(sc->port, FEPRST);
118 for (i = 0; (inb(sc->port) & FEPMASK) != FEPRST; i++) {
119 if (i == hz / 10)
120 return (0);
121 digi_delay(sc, "digirst", 1);
122 }
123 DLOG(DIGIDB_INIT, (sc->dev, "got reset after %d iterations\n", i));
124
125 ident = inb(sc->port);
126
127 /*
128 * NOTE, this probe is all wrong. I haven't got the data sheets !
129 */
130
131 DLOG(DIGIDB_INIT, (sc->dev, "board type is 0x%x\n", ident));
132 if (ident & 0x1) {
133 switch (ident) {
134 case 0x05:
135 case 0x15:
136 case 0x25:
137 case 0x35:
138 sc->model = PCXI;
139 sc->csigs = &digi_xixe_signals;
140 switch (ident & 0x30) {
141 case 0:
142 sc->name = "Digiboard PC/Xi 64K";
143 sc->mem_seg = 0xf000;
144 sc->win_size = 0x10000;
145 sc->win_bits = 16;
146 break;
147 case 0x10:
148 sc->name = "Digiboard PC/Xi 128K";
149 sc->mem_seg = 0xE000;
150 sc->win_size = 0x20000;
151 sc->win_bits = 17;
152 break;
153 case 0x20:
154 sc->name = "Digiboard PC/Xi 256K";
155 sc->mem_seg = 0xC000;
156 sc->win_size = 0x40000;
157 sc->win_bits = 18;
158 break;
159 case 0x30:
160 sc->name = "Digiboard PC/Xi 512K";
161 sc->mem_seg = 0x8000;
162 sc->win_size = 0x80000;
163 sc->win_bits = 19;
164 break;
165 }
166 sc->wport = sc->port;
167 sc->module = "Xe";
168
169 sc->setwin = digi_xi_setwin;
170 sc->hidewin = digi_isa_hidewin;
171 sc->towin = digi_xi_towin;
172 break;
173
174 case 0xf5:
175 sc->name = "Digiboard PC/Xem";
176 sc->model = PCXEM;
177 sc->csigs = &digi_normal_signals;
178 sc->win_size = 0x8000;
179 sc->win_bits = 15;
180 sc->wport = sc->port + 1;
181 sc->module = "Xem";
182
183 sc->setwin = digi_isa_setwin;
184 sc->hidewin = digi_isa_hidewin;
185 sc->towin = digi_isa_towin;
186 break;
187 }
188 } else {
189 outb(sc->port, 1);
190 ident = inb(sc->port);
191
192 if (ident & 0x1) {
193 device_printf(sc->dev, "PC/Xm is unsupported\n");
194 return (0);
195 }
196
197 sc->mem_seg = 0xf000;
198
199 if (!(ident & 0xc0)) {
200 sc->name = "Digiboard PC/Xe 64K";
201 sc->model = PCXE;
202 sc->csigs = &digi_xixe_signals;
203 sc->win_size = 0x10000;
204 sc->win_bits = 16;
205 sc->wport = sc->port;
206 } else {
207 sc->name = "Digiboard PC/Xe 64/8K (windowed)";
208 sc->model = PCXEVE;
209 sc->csigs = &digi_normal_signals;
210 sc->win_size = 0x2000;
211 sc->win_bits = 13;
212 sc->wport = sc->port + 1;
213 }
214 sc->module = "Xe";
215
216 sc->setwin = digi_isa_setwin;
217 sc->hidewin = digi_isa_hidewin;
218 sc->towin = digi_isa_towin;
219 }
220
221 return (sc->name != NULL);
222}
223
224static int
225digi_isa_probe(device_t dev)
226{
227 struct digi_softc *sc = device_get_softc(dev);
228 int i;
229
230 KASSERT(sc, ("digi%d: softc not allocated in digi_isa_probe\n",
231 device_get_unit(dev)));
232
233 bzero(sc, sizeof(*sc));
234 sc->status = DIGI_STATUS_NOTINIT;
235 sc->dev = dev;
236 sc->res.unit = device_get_unit(dev);
237 if (sc->res.unit >= 16) {
238 /* Don't overflow our control mask */
239 device_printf(dev, "At most 16 digiboards may be used\n");
240 return (ENXIO);
241 }
242 DLOG(DIGIDB_INIT, (sc->dev, "probing on isa bus\n"));
243
244 /* Check that we've got a valid i/o address */
245 if ((sc->port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) {
246 DLOG(DIGIDB_INIT, (sc->dev, "io address not given\n"));
247 return (ENXIO);
248 }
249 for (i = 0; i < DIGI_NVALIDIO; i++)
250 if (sc->port == digi_validio[i] ||
251 sc->port == digi_validio[i] + 4)
252 break;
253 if (i == DIGI_NVALIDIO) {
254 device_printf(dev, "0x%03x: Invalid i/o address\n", sc->port);
255 return (ENXIO);
256 }
257
258 /* Ditto for our memory address */
259 if ((sc->pmem = bus_get_resource_start(dev, SYS_RES_MEMORY, 0)) == 0)
260 return (ENXIO);
261 for (i = 0; i < DIGI_NVALIDMEM; i++)
262 if (sc->pmem == digi_validmem[i])
263 break;
264 if (i == DIGI_NVALIDMEM) {
265 device_printf(dev, "0x%lx: Invalid memory address\n", sc->pmem);
266 return (ENXIO);
267 }
268 if ((sc->pmem & 0xfffffful) != sc->pmem) {
269 device_printf(dev, "0x%lx: Memory address not supported\n",
270 sc->pmem);
271 return (ENXIO);
272 }
273 sc->vmem = (u_char *)sc->pmem;
274
275 DLOG(DIGIDB_INIT, (sc->dev, "isa? port 0x%03x mem 0x%lx\n",
276 sc->port, sc->pmem));
277
278 /* Temporarily map our io ports */
279 sc->res.iorid = 0;
33
34/*-
35 * TODO:
36 * Figure out how to make the non-Xi boards use memory addresses other
37 * than 0xd0000 !!!
38 */
39
40#include <sys/param.h>
41
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/module.h>
45#include <sys/tty.h>
46#include <sys/bus.h>
47#include <machine/bus.h>
48#include <sys/rman.h>
49#include <machine/resource.h>
50#include <vm/vm.h>
51#include <vm/pmap.h>
52
53#include <sys/digiio.h>
54#include <dev/digi/digireg.h>
55#include <dev/digi/digi.h>
56
57/* Valid i/o addresses are any of these with either 0 or 4 added */
58static u_long digi_validio[] = {
59 0x100, 0x110, 0x120, 0x200, 0x220, 0x300, 0x320
60};
61#define DIGI_NVALIDIO (sizeof(digi_validio) / sizeof(digi_validio[0]))
62#define IO_SIZE 0x04
63
64static u_long digi_validmem[] = {
65 0x80000, 0x88000, 0x90000, 0x98000, 0xa0000, 0xa8000, 0xb0000, 0xb8000,
66 0xc0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000, 0xe8000, 0xf0000, 0xf8000,
67 0xf0000000, 0xf1000000, 0xf2000000, 0xf3000000, 0xf4000000, 0xf5000000,
68 0xf6000000, 0xf7000000, 0xf8000000, 0xf9000000, 0xfa000000, 0xfb000000,
69 0xfc000000, 0xfd000000, 0xfe000000, 0xff000000
70};
71#define DIGI_NVALIDMEM (sizeof(digi_validmem) / sizeof(digi_validmem[0]))
72
73static u_char *
74digi_isa_setwin(struct digi_softc *sc, unsigned int addr)
75{
76 outb(sc->wport, sc->window = FEPWIN | (addr >> sc->win_bits));
77 return (sc->vmem + (addr % sc->win_size));
78}
79
80static u_char *
81digi_xi_setwin(struct digi_softc *sc, unsigned int addr)
82{
83 outb(sc->wport, sc->window = FEPMEM);
84 return (sc->vmem + addr);
85}
86
87static void
88digi_isa_hidewin(struct digi_softc *sc)
89{
90 outb(sc->wport, sc->window = 0);
91 /* outb(sc->port, 0); */
92}
93
94static void
95digi_isa_towin(struct digi_softc *sc, int win)
96{
97 outb(sc->wport, sc->window = win);
98}
99
100static void
101digi_xi_towin(struct digi_softc *sc, int win)
102{
103 outb(sc->wport, sc->window = FEPMEM);
104}
105
106/*
107 * sc->port should be set and its resource allocated.
108 */
109static int
110digi_isa_check(struct digi_softc *sc)
111{
112 int i, ident;
113
114 sc->name = NULL;
115
116 /* Invasive probe - reset the card */
117 outb(sc->port, FEPRST);
118 for (i = 0; (inb(sc->port) & FEPMASK) != FEPRST; i++) {
119 if (i == hz / 10)
120 return (0);
121 digi_delay(sc, "digirst", 1);
122 }
123 DLOG(DIGIDB_INIT, (sc->dev, "got reset after %d iterations\n", i));
124
125 ident = inb(sc->port);
126
127 /*
128 * NOTE, this probe is all wrong. I haven't got the data sheets !
129 */
130
131 DLOG(DIGIDB_INIT, (sc->dev, "board type is 0x%x\n", ident));
132 if (ident & 0x1) {
133 switch (ident) {
134 case 0x05:
135 case 0x15:
136 case 0x25:
137 case 0x35:
138 sc->model = PCXI;
139 sc->csigs = &digi_xixe_signals;
140 switch (ident & 0x30) {
141 case 0:
142 sc->name = "Digiboard PC/Xi 64K";
143 sc->mem_seg = 0xf000;
144 sc->win_size = 0x10000;
145 sc->win_bits = 16;
146 break;
147 case 0x10:
148 sc->name = "Digiboard PC/Xi 128K";
149 sc->mem_seg = 0xE000;
150 sc->win_size = 0x20000;
151 sc->win_bits = 17;
152 break;
153 case 0x20:
154 sc->name = "Digiboard PC/Xi 256K";
155 sc->mem_seg = 0xC000;
156 sc->win_size = 0x40000;
157 sc->win_bits = 18;
158 break;
159 case 0x30:
160 sc->name = "Digiboard PC/Xi 512K";
161 sc->mem_seg = 0x8000;
162 sc->win_size = 0x80000;
163 sc->win_bits = 19;
164 break;
165 }
166 sc->wport = sc->port;
167 sc->module = "Xe";
168
169 sc->setwin = digi_xi_setwin;
170 sc->hidewin = digi_isa_hidewin;
171 sc->towin = digi_xi_towin;
172 break;
173
174 case 0xf5:
175 sc->name = "Digiboard PC/Xem";
176 sc->model = PCXEM;
177 sc->csigs = &digi_normal_signals;
178 sc->win_size = 0x8000;
179 sc->win_bits = 15;
180 sc->wport = sc->port + 1;
181 sc->module = "Xem";
182
183 sc->setwin = digi_isa_setwin;
184 sc->hidewin = digi_isa_hidewin;
185 sc->towin = digi_isa_towin;
186 break;
187 }
188 } else {
189 outb(sc->port, 1);
190 ident = inb(sc->port);
191
192 if (ident & 0x1) {
193 device_printf(sc->dev, "PC/Xm is unsupported\n");
194 return (0);
195 }
196
197 sc->mem_seg = 0xf000;
198
199 if (!(ident & 0xc0)) {
200 sc->name = "Digiboard PC/Xe 64K";
201 sc->model = PCXE;
202 sc->csigs = &digi_xixe_signals;
203 sc->win_size = 0x10000;
204 sc->win_bits = 16;
205 sc->wport = sc->port;
206 } else {
207 sc->name = "Digiboard PC/Xe 64/8K (windowed)";
208 sc->model = PCXEVE;
209 sc->csigs = &digi_normal_signals;
210 sc->win_size = 0x2000;
211 sc->win_bits = 13;
212 sc->wport = sc->port + 1;
213 }
214 sc->module = "Xe";
215
216 sc->setwin = digi_isa_setwin;
217 sc->hidewin = digi_isa_hidewin;
218 sc->towin = digi_isa_towin;
219 }
220
221 return (sc->name != NULL);
222}
223
224static int
225digi_isa_probe(device_t dev)
226{
227 struct digi_softc *sc = device_get_softc(dev);
228 int i;
229
230 KASSERT(sc, ("digi%d: softc not allocated in digi_isa_probe\n",
231 device_get_unit(dev)));
232
233 bzero(sc, sizeof(*sc));
234 sc->status = DIGI_STATUS_NOTINIT;
235 sc->dev = dev;
236 sc->res.unit = device_get_unit(dev);
237 if (sc->res.unit >= 16) {
238 /* Don't overflow our control mask */
239 device_printf(dev, "At most 16 digiboards may be used\n");
240 return (ENXIO);
241 }
242 DLOG(DIGIDB_INIT, (sc->dev, "probing on isa bus\n"));
243
244 /* Check that we've got a valid i/o address */
245 if ((sc->port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) {
246 DLOG(DIGIDB_INIT, (sc->dev, "io address not given\n"));
247 return (ENXIO);
248 }
249 for (i = 0; i < DIGI_NVALIDIO; i++)
250 if (sc->port == digi_validio[i] ||
251 sc->port == digi_validio[i] + 4)
252 break;
253 if (i == DIGI_NVALIDIO) {
254 device_printf(dev, "0x%03x: Invalid i/o address\n", sc->port);
255 return (ENXIO);
256 }
257
258 /* Ditto for our memory address */
259 if ((sc->pmem = bus_get_resource_start(dev, SYS_RES_MEMORY, 0)) == 0)
260 return (ENXIO);
261 for (i = 0; i < DIGI_NVALIDMEM; i++)
262 if (sc->pmem == digi_validmem[i])
263 break;
264 if (i == DIGI_NVALIDMEM) {
265 device_printf(dev, "0x%lx: Invalid memory address\n", sc->pmem);
266 return (ENXIO);
267 }
268 if ((sc->pmem & 0xfffffful) != sc->pmem) {
269 device_printf(dev, "0x%lx: Memory address not supported\n",
270 sc->pmem);
271 return (ENXIO);
272 }
273 sc->vmem = (u_char *)sc->pmem;
274
275 DLOG(DIGIDB_INIT, (sc->dev, "isa? port 0x%03x mem 0x%lx\n",
276 sc->port, sc->pmem));
277
278 /* Temporarily map our io ports */
279 sc->res.iorid = 0;
280 sc->res.io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->res.iorid,
281 0ul, ~0ul, IO_SIZE, RF_ACTIVE);
280 sc->res.io = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
281 &sc->res.iorid, IO_SIZE, RF_ACTIVE);
282 if (sc->res.io == NULL)
283 return (ENXIO);
284
285 /* Check the type of card and get internal memory characteristics */
286 if (!digi_isa_check(sc)) {
287 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
288 sc->res.io);
289 return (ENXIO);
290 }
291
292 /* Temporarily map our memory */
293 sc->res.mrid = 0;
282 if (sc->res.io == NULL)
283 return (ENXIO);
284
285 /* Check the type of card and get internal memory characteristics */
286 if (!digi_isa_check(sc)) {
287 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
288 sc->res.io);
289 return (ENXIO);
290 }
291
292 /* Temporarily map our memory */
293 sc->res.mrid = 0;
294 sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid,
295 0ul, ~0ul, sc->win_size, 0);
294 sc->res.mem = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY,
295 &sc->res.mrid, sc->win_size, 0);
296 if (sc->res.mem == NULL) {
297 device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
298 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
299 sc->res.io);
300 return (ENXIO);
301 }
302
303 outb(sc->port, FEPCLR); /* drop RESET */
304 sc->hidewin(sc); /* set initial sc->window */
305
306 bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid, sc->res.mem);
307 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid, sc->res.io);
308
309 /* Let digi_isa_attach() know what we've found */
310 bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port, IO_SIZE);
311 bus_set_resource(dev, SYS_RES_MEMORY, 0, sc->pmem, sc->win_size);
312
313 DLOG(DIGIDB_INIT, (sc->dev, "Probe returns -10\n"));
314
315 return (-10); /* Other drivers are preferred for now */
316}
317
318static int
319digi_isa_attach(device_t dev)
320{
321 struct digi_softc *sc = device_get_softc(dev);
322 int i, t, res;
323 u_char *ptr;
324 int reset;
325 u_long msize, iosize;
326 long scport;
327
328 KASSERT(sc, ("digi%d: softc not allocated in digi_isa_attach\n",
329 device_get_unit(dev)));
330
331 res = ENXIO;
332 bzero(sc, sizeof(*sc));
333 sc->status = DIGI_STATUS_NOTINIT;
334 sc->dev = dev;
335 sc->res.unit = device_get_unit(dev);
336 DLOG(DIGIDB_INIT, (sc->dev, "attaching\n"));
337
338 bus_get_resource(dev, SYS_RES_IOPORT, 0, &scport, &iosize);
339 bus_get_resource(dev, SYS_RES_MEMORY, 0, &sc->pmem, &msize);
340 sc->port = scport;
341 /* sc->altpin = !!(device_get_flags(dev) & DGBFLAG_ALTPIN); */
342
343 /* Allocate resources (verified in digi_isa_probe()) */
344 sc->res.iorid = 0;
296 if (sc->res.mem == NULL) {
297 device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
298 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
299 sc->res.io);
300 return (ENXIO);
301 }
302
303 outb(sc->port, FEPCLR); /* drop RESET */
304 sc->hidewin(sc); /* set initial sc->window */
305
306 bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid, sc->res.mem);
307 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid, sc->res.io);
308
309 /* Let digi_isa_attach() know what we've found */
310 bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port, IO_SIZE);
311 bus_set_resource(dev, SYS_RES_MEMORY, 0, sc->pmem, sc->win_size);
312
313 DLOG(DIGIDB_INIT, (sc->dev, "Probe returns -10\n"));
314
315 return (-10); /* Other drivers are preferred for now */
316}
317
318static int
319digi_isa_attach(device_t dev)
320{
321 struct digi_softc *sc = device_get_softc(dev);
322 int i, t, res;
323 u_char *ptr;
324 int reset;
325 u_long msize, iosize;
326 long scport;
327
328 KASSERT(sc, ("digi%d: softc not allocated in digi_isa_attach\n",
329 device_get_unit(dev)));
330
331 res = ENXIO;
332 bzero(sc, sizeof(*sc));
333 sc->status = DIGI_STATUS_NOTINIT;
334 sc->dev = dev;
335 sc->res.unit = device_get_unit(dev);
336 DLOG(DIGIDB_INIT, (sc->dev, "attaching\n"));
337
338 bus_get_resource(dev, SYS_RES_IOPORT, 0, &scport, &iosize);
339 bus_get_resource(dev, SYS_RES_MEMORY, 0, &sc->pmem, &msize);
340 sc->port = scport;
341 /* sc->altpin = !!(device_get_flags(dev) & DGBFLAG_ALTPIN); */
342
343 /* Allocate resources (verified in digi_isa_probe()) */
344 sc->res.iorid = 0;
345 sc->res.io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->res.iorid,
346 0ul, ~0ul, iosize, RF_ACTIVE);
345 sc->res.io = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
346 &sc->res.iorid, iosize, RF_ACTIVE);
347 if (sc->res.io == NULL)
348 return (ENXIO);
349
350 /* Check the type of card and get internal memory characteristics */
351 DLOG(DIGIDB_INIT, (sc->dev, "Checking card type\n"));
352 if (!digi_isa_check(sc))
353 goto failed;
354
355 callout_handle_init(&sc->callout);
356 callout_handle_init(&sc->inttest);
357
358 sc->res.mrid = 0;
347 if (sc->res.io == NULL)
348 return (ENXIO);
349
350 /* Check the type of card and get internal memory characteristics */
351 DLOG(DIGIDB_INIT, (sc->dev, "Checking card type\n"));
352 if (!digi_isa_check(sc))
353 goto failed;
354
355 callout_handle_init(&sc->callout);
356 callout_handle_init(&sc->inttest);
357
358 sc->res.mrid = 0;
359 sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid,
360 0ul, ~0ul, msize, RF_ACTIVE);
359 sc->res.mem = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY,
360 &sc->res.mrid, msize, RF_ACTIVE);
361 if (sc->res.mem == NULL) {
362 device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
363 sc->hidewin(sc);
364 goto failed;
365 }
366
367 /* map memory */
368 sc->vmem = pmap_mapdev(sc->pmem, msize);
369
370 DLOG(DIGIDB_INIT, (sc->dev, "internal memory segment 0x%x\n",
371 sc->mem_seg));
372
373 /* Start by resetting the card */
374 reset = FEPRST;
375 if (sc->model == PCXI)
376 reset |= FEPMEM;
377
378 outb(sc->port, reset);
379 for (i = 0; (inb(sc->port) & FEPMASK) != reset; i++) {
380 if (i == hz / 10) {
381 device_printf(dev, "1st reset failed\n");
382 sc->hidewin(sc);
383 goto failed;
384 }
385 digi_delay(sc, "digirst1", 1);
386 }
387 DLOG(DIGIDB_INIT, (sc->dev, "got reset after %d iterations\n", i));
388
389 if (sc->model != PCXI) {
390 t = (sc->pmem >> 8) & 0xffe0;
391 if (sc->model == PCXEVE)
392 t |= 0x10; /* enable windowing */
393 outb(sc->port + 2, t & 0xff);
394 outb(sc->port + 3, t >> 8);
395 }
396
397 if (sc->model == PCXI || sc->model == PCXE) {
398 outb(sc->port, FEPRST | FEPMEM);
399 for (i = 0; (inb(sc->port) & FEPMASK) != FEPRST; i++) {
400 if (i == hz / 10) {
401 device_printf(dev,
402 "memory reservation failed (0x%02x)\n",
403 inb(sc->port));
404 sc->hidewin(sc);
405 goto failed;
406 }
407 digi_delay(sc, "digirst2", 1);
408 }
409 DLOG(DIGIDB_INIT, (sc->dev, "got memory after %d iterations\n",
410 i));
411 }
412
413 DLOG(DIGIDB_INIT, (sc->dev, "short memory test\n"));
414 ptr = sc->setwin(sc, BOTWIN);
415 vD(ptr) = 0xA55A3CC3;
416 if (vD(ptr) != 0xA55A3CC3) {
417 device_printf(dev, "1st memory test failed\n");
418 sc->hidewin(sc);
419 goto failed;
420 }
421 DLOG(DIGIDB_INIT, (sc->dev, "1st memory test ok\n"));
422
423 ptr = sc->setwin(sc, TOPWIN);
424 vD(ptr) = 0x5AA5C33C;
425 if (vD(ptr) != 0x5AA5C33C) {
426 device_printf(dev, "2nd memory test failed\n");
427 sc->hidewin(sc);
428 goto failed;
429 }
430 DLOG(DIGIDB_INIT, (sc->dev, "2nd memory test ok\n"));
431
432 ptr = sc->setwin(sc, BIOSCODE + ((0xf000 - sc->mem_seg) << 4));
433 vD(ptr) = 0x5AA5C33C;
434 if (vD(ptr) != 0x5AA5C33C) {
435 device_printf(dev, "3rd (BIOS) memory test failed\n");
436 sc->hidewin(sc);
437 goto failed;
438 }
439 DLOG(DIGIDB_INIT, (sc->dev, "3rd memory test ok\n"));
440
441 if ((res = digi_attach(sc)) == 0)
442 return (0);
443
444failed:
445 if (sc->res.mem != NULL) {
446 bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid,
447 sc->res.mem);
448 sc->res.mem = NULL;
449 }
450 if (sc->res.io != NULL) {
451 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
452 sc->res.io);
453 sc->res.io = NULL;
454 }
455
456 return (res);
457}
458
459static device_method_t digi_isa_methods[] = {
460 /* Device interface */
461 DEVMETHOD(device_probe, digi_isa_probe),
462 DEVMETHOD(device_attach, digi_isa_attach),
463 DEVMETHOD(device_detach, digi_detach),
464 DEVMETHOD(device_shutdown, digi_shutdown),
465
466 DEVMETHOD_END
467};
468
469static driver_t digi_isa_drv = {
470 "digi",
471 digi_isa_methods,
472 sizeof(struct digi_softc),
473};
474DRIVER_MODULE(digi, isa, digi_isa_drv, digi_devclass, 0, 0);
361 if (sc->res.mem == NULL) {
362 device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
363 sc->hidewin(sc);
364 goto failed;
365 }
366
367 /* map memory */
368 sc->vmem = pmap_mapdev(sc->pmem, msize);
369
370 DLOG(DIGIDB_INIT, (sc->dev, "internal memory segment 0x%x\n",
371 sc->mem_seg));
372
373 /* Start by resetting the card */
374 reset = FEPRST;
375 if (sc->model == PCXI)
376 reset |= FEPMEM;
377
378 outb(sc->port, reset);
379 for (i = 0; (inb(sc->port) & FEPMASK) != reset; i++) {
380 if (i == hz / 10) {
381 device_printf(dev, "1st reset failed\n");
382 sc->hidewin(sc);
383 goto failed;
384 }
385 digi_delay(sc, "digirst1", 1);
386 }
387 DLOG(DIGIDB_INIT, (sc->dev, "got reset after %d iterations\n", i));
388
389 if (sc->model != PCXI) {
390 t = (sc->pmem >> 8) & 0xffe0;
391 if (sc->model == PCXEVE)
392 t |= 0x10; /* enable windowing */
393 outb(sc->port + 2, t & 0xff);
394 outb(sc->port + 3, t >> 8);
395 }
396
397 if (sc->model == PCXI || sc->model == PCXE) {
398 outb(sc->port, FEPRST | FEPMEM);
399 for (i = 0; (inb(sc->port) & FEPMASK) != FEPRST; i++) {
400 if (i == hz / 10) {
401 device_printf(dev,
402 "memory reservation failed (0x%02x)\n",
403 inb(sc->port));
404 sc->hidewin(sc);
405 goto failed;
406 }
407 digi_delay(sc, "digirst2", 1);
408 }
409 DLOG(DIGIDB_INIT, (sc->dev, "got memory after %d iterations\n",
410 i));
411 }
412
413 DLOG(DIGIDB_INIT, (sc->dev, "short memory test\n"));
414 ptr = sc->setwin(sc, BOTWIN);
415 vD(ptr) = 0xA55A3CC3;
416 if (vD(ptr) != 0xA55A3CC3) {
417 device_printf(dev, "1st memory test failed\n");
418 sc->hidewin(sc);
419 goto failed;
420 }
421 DLOG(DIGIDB_INIT, (sc->dev, "1st memory test ok\n"));
422
423 ptr = sc->setwin(sc, TOPWIN);
424 vD(ptr) = 0x5AA5C33C;
425 if (vD(ptr) != 0x5AA5C33C) {
426 device_printf(dev, "2nd memory test failed\n");
427 sc->hidewin(sc);
428 goto failed;
429 }
430 DLOG(DIGIDB_INIT, (sc->dev, "2nd memory test ok\n"));
431
432 ptr = sc->setwin(sc, BIOSCODE + ((0xf000 - sc->mem_seg) << 4));
433 vD(ptr) = 0x5AA5C33C;
434 if (vD(ptr) != 0x5AA5C33C) {
435 device_printf(dev, "3rd (BIOS) memory test failed\n");
436 sc->hidewin(sc);
437 goto failed;
438 }
439 DLOG(DIGIDB_INIT, (sc->dev, "3rd memory test ok\n"));
440
441 if ((res = digi_attach(sc)) == 0)
442 return (0);
443
444failed:
445 if (sc->res.mem != NULL) {
446 bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid,
447 sc->res.mem);
448 sc->res.mem = NULL;
449 }
450 if (sc->res.io != NULL) {
451 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
452 sc->res.io);
453 sc->res.io = NULL;
454 }
455
456 return (res);
457}
458
459static device_method_t digi_isa_methods[] = {
460 /* Device interface */
461 DEVMETHOD(device_probe, digi_isa_probe),
462 DEVMETHOD(device_attach, digi_isa_attach),
463 DEVMETHOD(device_detach, digi_detach),
464 DEVMETHOD(device_shutdown, digi_shutdown),
465
466 DEVMETHOD_END
467};
468
469static driver_t digi_isa_drv = {
470 "digi",
471 digi_isa_methods,
472 sizeof(struct digi_softc),
473};
474DRIVER_MODULE(digi, isa, digi_isa_drv, digi_devclass, 0, 0);