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