FreeBSD/Linux Kernel Cross Reference
sys/dev/si/si_isa.c
1 /*-
2 * Device driver for Specialix range (SI/XIO) of serial line multiplexors.
3 *
4 * Copyright (C) 2000, Peter Wemm <peter@netplex.com.au>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notices, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notices, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHORS BE LIABLE.
19 *
20 */
21
22 #include <sys/cdefs.h>
23 __FBSDID("$FreeBSD$");
24
25 #include "opt_debug_si.h"
26
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/kernel.h>
30 #include <sys/module.h>
31 #include <sys/bus.h>
32 #include <machine/bus.h>
33 #include <sys/rman.h>
34 #include <machine/resource.h>
35
36 #include <dev/si/sireg.h>
37 #include <dev/si/sivar.h>
38
39 #include <isa/isavar.h>
40
41 /* Look for a valid board at the given mem addr */
42 static int
43 si_isa_probe(device_t dev)
44 {
45 struct si_softc *sc;
46 int type;
47 u_int i, ramsize;
48 volatile unsigned char was, *ux;
49 volatile unsigned char *maddr;
50 unsigned char *paddr;
51 int unit;
52
53 /* No pnp support */
54 if (isa_get_vendorid(dev))
55 return (ENXIO);
56
57 sc = device_get_softc(dev);
58 unit = device_get_unit(dev);
59
60 sc->sc_mem_rid = 0;
61 sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
62 &sc->sc_mem_rid,
63 0, ~0, SIPROBEALLOC, RF_ACTIVE);
64 if (!sc->sc_mem_res) {
65 device_printf(dev, "cannot allocate memory resource\n");
66 return ENXIO;
67 }
68 paddr = (caddr_t)rman_get_start(sc->sc_mem_res);/* physical */
69 maddr = rman_get_virtual(sc->sc_mem_res); /* in kvm */
70
71 DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n",
72 unit, maddr, paddr));
73
74 /*
75 * this is a lie, but it's easier than trying to handle caching
76 * and ram conflicts in the >1M and <16M region.
77 */
78 if ((caddr_t)paddr < (caddr_t)0xA0000 ||
79 (caddr_t)paddr >= (caddr_t)0x100000) {
80 device_printf(dev, "maddr (%p) out of range\n", paddr);
81 goto fail;
82 }
83
84 if (((uintptr_t)paddr & 0x7fff) != 0) {
85 device_printf(dev, "maddr (%p) not on 32k boundary\n", paddr);
86 goto fail;
87 }
88
89 /* Is there anything out there? (0x17 is just an arbitrary number) */
90 *maddr = 0x17;
91 if (*maddr != 0x17) {
92 device_printf(dev, "0x17 check fail at phys %p\n", paddr);
93 goto fail;
94 }
95 /*
96 * Let's look first for a JET ISA card, since that's pretty easy
97 *
98 * All jet hosts are supposed to have this string in the IDROM,
99 * but it's not worth checking on self-IDing busses like PCI.
100 */
101 {
102 unsigned char *jet_chk_str = "JET HOST BY KEV#";
103
104 for (i = 0; i < strlen(jet_chk_str); i++)
105 if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i))
106 goto try_mk2;
107 }
108 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET first check - 0x%x\n",
109 unit, (*(maddr+SIJETIDBASE))));
110 if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff))
111 goto try_mk2;
112 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET second check - 0x%x\n",
113 unit, (*(maddr+SIJETIDBASE+2))));
114 if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8))
115 goto try_mk2;
116 /* It must be a Jet ISA or RIO card */
117 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, "si%d: JET id check - 0x%x\n",
118 unit, (*(maddr+SIUNIQID))));
119 if ((*(maddr+SIUNIQID) & 0xf0) != 0x20)
120 goto try_mk2;
121 /* It must be a Jet ISA SI/XIO card */
122 *(maddr + SIJETCONFIG) = 0;
123 type = SIJETISA;
124 ramsize = SIJET_RAMSIZE;
125 goto got_card;
126
127 try_mk2:
128 /*
129 * OK, now to see if whatever responded is really an SI card.
130 * Try for a MK II next (SIHOST2)
131 */
132 for (i = SIPLSIG; i < SIPLSIG + 8; i++)
133 if ((*(maddr+i) & 7) != (~(unsigned char)i & 7))
134 goto try_mk1;
135
136 /* It must be an SIHOST2 */
137 *(maddr + SIPLRESET) = 0;
138 *(maddr + SIPLIRQCLR) = 0;
139 *(maddr + SIPLIRQSET) = 0x10;
140 type = SIHOST2;
141 ramsize = SIHOST2_RAMSIZE;
142 goto got_card;
143
144 try_mk1:
145 /*
146 * Its not a MK II, so try for a MK I (SIHOST)
147 */
148 *(maddr+SIRESET) = 0x0; /* reset the card */
149 *(maddr+SIINTCL) = 0x0; /* clear int */
150 *(maddr+SIRAM) = 0x17;
151 if (*(maddr+SIRAM) != (unsigned char)0x17)
152 goto fail;
153 *(maddr+0x7ff8) = 0x17;
154 if (*(maddr+0x7ff8) != (unsigned char)0x17) {
155 device_printf(dev, "0x17 check fail at phys %p = 0x%x\n",
156 paddr+0x77f8, *(maddr+0x77f8));
157 goto fail;
158 }
159
160 /* It must be an SIHOST (maybe?) - there must be a better way XXX */
161 type = SIHOST;
162 ramsize = SIHOST_RAMSIZE;
163
164 got_card:
165 DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n",
166 unit, type));
167 /* Try the acid test */
168 ux = maddr + SIRAM;
169 for (i = 0; i < ramsize; i++, ux++)
170 *ux = (unsigned char)(i&0xff);
171 ux = maddr + SIRAM;
172 for (i = 0; i < ramsize; i++, ux++) {
173 if ((was = *ux) != (unsigned char)(i&0xff)) {
174 device_printf(dev,
175 "memtest fail at phys %p, was %x should be %x\n",
176 paddr + i, was, i & 0xff);
177 goto fail;
178 }
179 }
180
181 /* clear out the RAM */
182 ux = maddr + SIRAM;
183 for (i = 0; i < ramsize; i++)
184 *ux++ = 0;
185 ux = maddr + SIRAM;
186 for (i = 0; i < ramsize; i++) {
187 if ((was = *ux++) != 0) {
188 device_printf(dev, "clear fail at phys %p, was %x\n",
189 paddr + i, was);
190 goto fail;
191 }
192 }
193
194 /*
195 * Success, we've found a valid board, now fill in
196 * the adapter structure.
197 */
198 switch (type) {
199 case SIHOST2:
200 switch (isa_get_irq(dev)) {
201 case 11:
202 case 12:
203 case 15:
204 break;
205 default:
206 device_printf(dev,
207 "bad IRQ value - %d (11, 12, 15 allowed)\n",
208 isa_get_irq(dev));
209 goto fail;
210 }
211 sc->sc_memsize = SIHOST2_MEMSIZE;
212 break;
213 case SIHOST:
214 switch (isa_get_irq(dev)) {
215 case 11:
216 case 12:
217 case 15:
218 break;
219 default:
220 device_printf(dev,
221 "bad IRQ value - %d (11, 12, 15 allowed)\n",
222 isa_get_irq(dev));
223 goto fail;
224 }
225 sc->sc_memsize = SIHOST_MEMSIZE;
226 break;
227 case SIJETISA:
228 switch (isa_get_irq(dev)) {
229 case 9:
230 case 10:
231 case 11:
232 case 12:
233 case 15:
234 break;
235 default:
236 device_printf(dev,
237 "bad IRQ value - %d (9, 10, 11, 12, 15 allowed)\n",
238 isa_get_irq(dev));
239 goto fail;
240 }
241 sc->sc_memsize = SIJETISA_MEMSIZE;
242 break;
243 case SIMCA: /* MCA */
244 default:
245 device_printf(dev, "card type %d not supported\n", type);
246 goto fail;
247 }
248 sc->sc_type = type;
249 bus_release_resource(dev, SYS_RES_MEMORY,
250 sc->sc_mem_rid, sc->sc_mem_res);
251 sc->sc_mem_res = 0;
252 return (0); /* success! */
253
254 fail:
255 if (sc->sc_mem_res) {
256 bus_release_resource(dev, SYS_RES_MEMORY,
257 sc->sc_mem_rid, sc->sc_mem_res);
258 sc->sc_mem_res = 0;
259 }
260 return(EINVAL);
261 }
262
263 static int
264 si_isa_attach(device_t dev)
265 {
266 int error;
267 void *ih;
268 struct si_softc *sc;
269
270 error = 0;
271 ih = NULL;
272 sc = device_get_softc(dev);
273
274 sc->sc_mem_rid = 0;
275 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
276 &sc->sc_mem_rid,
277 RF_ACTIVE);
278 if (!sc->sc_mem_res) {
279 device_printf(dev, "couldn't map memory\n");
280 goto fail;
281 }
282 sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_mem_res);
283 sc->sc_maddr = rman_get_virtual(sc->sc_mem_res);
284
285 sc->sc_irq_rid = 0;
286 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
287 &sc->sc_irq_rid,
288 RF_ACTIVE | RF_SHAREABLE);
289 if (!sc->sc_irq_res) {
290 device_printf(dev, "couldn't allocate interrupt\n");
291 goto fail;
292 }
293 sc->sc_irq = rman_get_start(sc->sc_irq_res);
294 error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY,
295 si_intr, sc,&ih);
296 if (error) {
297 device_printf(dev, "couldn't activate interrupt\n");
298 goto fail;
299 }
300
301 error = siattach(dev);
302 if (error)
303 goto fail;
304 return (0); /* success */
305
306 fail:
307 if (error == 0)
308 error = ENXIO;
309 if (sc->sc_irq_res) {
310 if (ih)
311 bus_teardown_intr(dev, sc->sc_irq_res, ih);
312 bus_release_resource(dev, SYS_RES_IRQ,
313 sc->sc_irq_rid, sc->sc_irq_res);
314 sc->sc_irq_res = 0;
315 }
316 if (sc->sc_mem_res) {
317 bus_release_resource(dev, SYS_RES_MEMORY,
318 sc->sc_mem_rid, sc->sc_mem_res);
319 sc->sc_mem_res = 0;
320 }
321 return (error);
322 }
323
324 static device_method_t si_isa_methods[] = {
325 /* Device interface */
326 DEVMETHOD(device_probe, si_isa_probe),
327 DEVMETHOD(device_attach, si_isa_attach),
328
329 { 0, 0 }
330 };
331
332 static driver_t si_isa_driver = {
333 "si",
334 si_isa_methods,
335 sizeof(struct si_softc),
336 };
337
338 DRIVER_MODULE(si, isa, si_isa_driver, si_devclass, 0, 0);
Cache object: 1470c0ea0177562ec4b719d00d1c9cc7
|