Merge from vendor branch GROFF:
[dragonfly.git] / sys / dev / netif / sr / if_sr_isa.c
1 /*
2  * Copyright (c) 1996 - 2001 John Hay.
3  * Copyright (c) 1996 SDL Communications, Inc.
4  * All rights reserved.
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  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the author nor the names of any co-contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD: src/sys/dev/sr/if_sr_isa.c,v 1.46.2.1 2002/06/17 15:10:58 jhay Exp $
31  * $DragonFly: src/sys/dev/netif/sr/if_sr_isa.c,v 1.3 2003/08/07 21:17:05 dillon Exp $
32  */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>           /* cdevsw stuff */
37 #include <sys/kernel.h>         /* SYSINIT stuff */
38 #include <sys/uio.h>            /* SYSINIT stuff */
39 #include <sys/malloc.h>         /* malloc region definitions */
40 #include <sys/module.h>
41 #include <sys/bus.h>
42 #include <machine/bus.h>
43 #include <machine/resource.h>
44 #include <machine/bus_pio.h>
45 #include <machine/bus_memio.h>
46 #include <sys/rman.h>
47 #include <sys/time.h>
48
49 #include <bus/isa/isavar.h>
50 #include "isa_if.h"
51
52 #include "../ic_layer/hd64570.h"
53 #include "if_srregs.h"
54
55 /*
56  * List of valid interrupt numbers for the N2 ISA card.
57  */
58 static int sr_irqtable[16] = {
59         0,      /*  0 */
60         0,      /*  1 */
61         0,      /*  2 */
62         1,      /*  3 */
63         1,      /*  4 */
64         1,      /*  5 */
65         0,      /*  6 */
66         1,      /*  7 */
67         0,      /*  8 */
68         0,      /*  9 */
69         1,      /* 10 */
70         1,      /* 11 */
71         1,      /* 12 */
72         0,      /* 13 */
73         0,      /* 14 */
74         1       /* 15 */
75 };
76
77 static int sr_isa_probe (device_t);
78 static int sr_isa_attach (device_t);
79
80 static struct isa_pnp_id sr_ids[] = {
81         {0,             NULL}
82 };
83
84 static device_method_t sr_methods[] = {
85         DEVMETHOD(device_probe,         sr_isa_probe),
86         DEVMETHOD(device_attach,        sr_isa_attach),
87         DEVMETHOD(device_detach,        sr_detach),
88         { 0, 0 }
89 };
90
91 static driver_t sr_isa_driver = {
92         "sr",
93         sr_methods,
94         sizeof (struct sr_hardc)
95 };
96
97 DRIVER_MODULE(if_sr, isa, sr_isa_driver, sr_devclass, 0, 0);
98
99 static u_int    src_get8_io(u_int base, u_int off);
100 static u_int    src_get16_io(u_int base, u_int off);
101 static void     src_put8_io(u_int base, u_int off, u_int val);
102 static void     src_put16_io(u_int base, u_int off, u_int val);
103 static u_int    src_dpram_size(device_t device);
104
105 /*
106  * Probe for an ISA card. If it is there, size its memory. Then get the
107  * rest of its information and fill it in.
108  */
109 static int
110 sr_isa_probe (device_t device)
111 {
112         struct sr_hardc *hc;
113         int error;
114         u_int32_t flags;
115         u_int i, tmp;
116         u_short port;
117         u_long irq, junk, membase, memsize, port_start, port_count;
118         sca_regs *sca = 0;
119
120         error = ISA_PNP_PROBE(device_get_parent(device), device, sr_ids);
121         if (error == ENXIO || error == 0)
122                 return (error);
123
124         hc = device_get_softc(device);
125         bzero(hc, sizeof(struct sr_hardc));
126
127         if (sr_allocate_ioport(device, 0, SRC_IO_SIZ)) {
128                 return (ENXIO);
129         }
130
131         /*
132          * Now see if the card is realy there.
133          */
134         error = bus_get_resource(device, SYS_RES_IOPORT, 0, &port_start,
135             &port_count);
136         port = port_start;
137
138         hc->cardtype = SR_CRD_N2;
139         hc->cunit = device_get_unit(device);
140         hc->iobase = port_start;
141         /*
142          * We have to fill these in early because the SRC_PUT* and SRC_GET*
143          * macros use them.
144          */
145         hc->src_get8 = src_get8_io;
146         hc->src_get16 = src_get16_io;
147         hc->src_put8 = src_put8_io;
148         hc->src_put16 = src_put16_io;
149
150         hc->sca = 0;
151         hc->numports = NCHAN;   /* assumed # of channels on the card */
152
153         flags = device_get_flags(device);
154         if (flags & SR_FLAGS_NCHAN_MSK)
155                 hc->numports = flags & SR_FLAGS_NCHAN_MSK;
156
157         outb(port + SR_PCR, 0); /* turn off the card */
158
159         /*
160          * Next, we'll test the Base Address Register to retension of
161          * data... ... seeing if we're *really* talking to an N2.
162          */
163         for (i = 0; i < 0x100; i++) {
164                 outb(port + SR_BAR, i);
165                 inb(port + SR_PCR);
166                 tmp = inb(port + SR_BAR);
167                 if (tmp != i) {
168                         printf("sr%d: probe failed BAR %x, %x.\n",
169                                hc->cunit, i, tmp);
170                         goto errexit;
171                 }
172         }
173
174         /*
175          * Now see if we can see the SCA.
176          */
177         outb(port + SR_PCR, SR_PCR_SCARUN | inb(port + SR_PCR));
178         SRC_PUT8(port, sca->wcrl, 0);
179         SRC_PUT8(port, sca->wcrm, 0);
180         SRC_PUT8(port, sca->wcrh, 0);
181         SRC_PUT8(port, sca->pcr, 0);
182         SRC_PUT8(port, sca->msci[0].tmc, 0);
183         inb(port);
184
185         tmp = SRC_GET8(port, sca->msci[0].tmc);
186         if (tmp != 0) {
187                 printf("sr%d: Error reading SCA 0, %x\n", hc->cunit, tmp);
188                 goto errexit;
189         }
190         SRC_PUT8(port, sca->msci[0].tmc, 0x5A);
191         inb(port);
192
193         tmp = SRC_GET8(port, sca->msci[0].tmc);
194         if (tmp != 0x5A) {
195                 printf("sr%d: Error reading SCA 0x5A, %x\n", hc->cunit, tmp);
196                 goto errexit;
197         }
198         SRC_PUT16(port, sca->dmac[0].cda, 0);
199         inb(port);
200
201         tmp = SRC_GET16(port, sca->dmac[0].cda);
202         if (tmp != 0) {
203                 printf("sr%d: Error reading SCA 0, %x\n", hc->cunit, tmp);
204                 goto errexit;
205         }
206         SRC_PUT16(port, sca->dmac[0].cda, 0x55AA);
207         inb(port);
208
209         tmp = SRC_GET16(port, sca->dmac[0].cda);
210         if (tmp != 0x55AA) {
211                 printf("sr%d: Error reading SCA 0x55AA, %x\n",
212                        hc->cunit, tmp);
213                 goto errexit;
214         }
215
216         membase = bus_get_resource_start(device, SYS_RES_MEMORY, 0);
217         memsize = SRC_WIN_SIZ;
218         if (bus_set_resource(device, SYS_RES_MEMORY, 0, membase, memsize))
219                 goto errexit;
220
221         if (sr_allocate_memory(device, 0, SRC_WIN_SIZ))
222                 goto errexit;
223
224         if (src_dpram_size(device) < 4)
225                 goto errexit;
226
227         if (sr_allocate_irq(device, 0, 1))
228                 goto errexit;
229
230         if (bus_get_resource(device, SYS_RES_IRQ, 0, &irq, &junk)) {
231                 goto errexit;
232         }
233         /*
234          * Do a little sanity check.
235          */
236         if (sr_irqtable[irq] == 0)
237                 printf("sr%d: Warning: illegal interrupt %ld chosen.\n",
238                        hc->cunit, irq);
239
240         /*
241          * Bogus card configuration
242          */
243         if ((hc->numports > NCHAN)      /* only 2 ports/card */
244             ||(hc->memsize > (512 * 1024)))     /* no more than 256K */
245                 goto errexit;
246
247         sr_deallocate_resources(device);
248         return (0);
249
250 errexit:
251         sr_deallocate_resources(device);
252         return (ENXIO);
253 }
254
255 /*
256  * srattach_isa and srattach_pci allocate memory for hardc, softc and
257  * data buffers. It also does any initialization that is bus specific.
258  * At the end they call the common srattach() function.
259  */
260 static int
261 sr_isa_attach (device_t device)
262 {
263         u_char mar;
264         u_int32_t flags;
265         struct sr_hardc *hc;
266
267         hc = device_get_softc(device);
268         bzero(hc, sizeof(struct sr_hardc));
269
270         if (sr_allocate_ioport(device, 0, SRC_IO_SIZ))
271                 goto errexit;
272         if (sr_allocate_memory(device, 0, SRC_WIN_SIZ))
273                 goto errexit;
274         if (sr_allocate_irq(device, 0, 1))
275                 goto errexit;
276
277         /*
278          * We have to fill these in early because the SRC_PUT* and SRC_GET*
279          * macros use them.
280          */
281         hc->src_get8 = src_get8_io;
282         hc->src_get16 = src_get16_io;
283         hc->src_put8 = src_put8_io;
284         hc->src_put16 = src_put16_io;
285
286         hc->cardtype = SR_CRD_N2;
287         hc->cunit = device_get_unit(device);
288         hc->sca = 0;
289         hc->numports = NCHAN;   /* assumed # of channels on the card */
290         flags = device_get_flags(device);
291         if (flags & SR_FLAGS_NCHAN_MSK)
292                 hc->numports = flags & SR_FLAGS_NCHAN_MSK;
293
294         hc->iobase = rman_get_start(hc->res_ioport);
295         hc->sca_base = hc->iobase;
296         hc->mem_start = (caddr_t)rman_get_virtual(hc->res_memory);
297         hc->mem_end = hc->mem_start + SRC_WIN_SIZ;
298         hc->mem_pstart = 0;
299         hc->winmsk = SRC_WIN_MSK;
300
301         hc->mempages = src_dpram_size(device);
302         hc->memsize = hc->mempages * SRC_WIN_SIZ;
303
304         outb(hc->iobase + SR_PCR, inb(hc->iobase + SR_PCR) | SR_PCR_SCARUN);
305         outb(hc->iobase + SR_PSR, inb(hc->iobase + SR_PSR) | SR_PSR_EN_SCA_DMA);
306         outb(hc->iobase + SR_MCR,
307              SR_MCR_DTR0 | SR_MCR_DTR1 | SR_MCR_TE0 | SR_MCR_TE1);
308
309         SRC_SET_ON(hc->iobase);
310
311         /*
312          * Configure the card. Mem address, irq,
313          */
314         mar = (rman_get_start(hc->res_memory) >> 16) & SR_PCR_16M_SEL;
315         outb(hc->iobase + SR_PCR,
316              mar | (inb(hc->iobase + SR_PCR) & ~SR_PCR_16M_SEL));
317         mar = rman_get_start(hc->res_memory) >> 12;
318         outb(hc->iobase + SR_BAR, mar);
319
320         return sr_attach(device);
321
322 errexit:
323         sr_deallocate_resources(device);
324         return (ENXIO);
325 }
326
327 /*
328  * I/O for ISA N2 card(s)
329  */
330 #define SRC_REG(iobase,y)       ((((y) & 0xf) + (((y) & 0xf0) << 6) +       \
331                                 (iobase)) | 0x8000)
332
333 static u_int
334 src_get8_io(u_int base, u_int off)
335 {
336         return inb(SRC_REG(base, off));
337 }
338
339 static u_int
340 src_get16_io(u_int base, u_int off)
341 {
342         return inw(SRC_REG(base, off));
343 }
344
345 static void
346 src_put8_io(u_int base, u_int off, u_int val)
347 {
348         outb(SRC_REG(base, off), val);
349 }
350
351 static void
352 src_put16_io(u_int base, u_int off, u_int val)
353 {
354         outw(SRC_REG(base, off), val);
355 }
356
357 static u_int
358 src_dpram_size(device_t device)
359 {
360         u_int pgs, i;
361         u_short port;
362         u_short *smem;
363         u_char mar;
364         u_long membase;
365         struct sr_hardc *hc;
366
367         hc = device_get_softc(device);
368         port = hc->iobase;
369
370         /*
371          * OK, the board's interface registers seem to work. Now we'll see
372          * if the Dual-Ported RAM is fully accessible...
373          */
374         outb(port + SR_PCR, SR_PCR_EN_VPM | SR_PCR_ISA16);
375         outb(port + SR_PSR, SR_PSR_WIN_16K);
376
377         /*
378          * Take the kernel "virtual" address supplied to us and convert
379          * it to a "real" address. Then program the card to use that.
380          */
381         membase = rman_get_start(hc->res_memory);
382         mar = (membase >> 16) & SR_PCR_16M_SEL;
383         outb(port + SR_PCR, mar | inb(port + SR_PCR));
384         mar = membase >> 12;
385         outb(port + SR_BAR, mar);
386         outb(port + SR_PCR, inb(port + SR_PCR) | SR_PCR_MEM_WIN);
387         smem = (u_short *)rman_get_virtual(hc->res_memory);/* DP RAM Address */
388         /*
389          * Here we will perform the memory scan to size the device.
390          *
391          * This is done by marking each potential page with a magic number.
392          * We then loop through the pages looking for that magic number. As
393          * soon as we no longer see that magic number, we'll quit the scan,
394          * knowing that no more memory is present. This provides the number
395          * of pages present on the card.
396          *
397          * Note: We're sizing 16K memory granules.
398          */
399         for (i = 0; i <= SR_PSR_PG_SEL; i++) {
400                 outb(port + SR_PSR,
401                      (inb(port + SR_PSR) & ~SR_PSR_PG_SEL) | i);
402
403                 *smem = 0xAA55;
404         }
405
406         for (i = 0; i <= SR_PSR_PG_SEL; i++) {
407                 outb(port + SR_PSR,
408                      (inb(port + SR_PSR) & ~SR_PSR_PG_SEL) | i);
409
410                 if (*smem != 0xAA55) {
411                         /*
412                          * If we have less than 64k of memory, give up. That
413                          * is 4 x 16k pages.
414                          */
415                         if (i < 4) {
416                                 printf("sr%d: Bad mem page %d, mem %x, %x.\n",
417                                        hc->cunit, i, 0xAA55, *smem);
418                                 return 0;
419                         }
420                         break;
421                 }
422                 *smem = i;
423         }
424
425         hc->mempages = i;
426         hc->memsize = i * SRC_WIN_SIZ;
427         hc->winmsk = SRC_WIN_MSK;
428         pgs = i;                /* final count of 16K pages */
429
430         /*
431          * This next loop erases the contents of that page in DPRAM
432          */
433         for (i = 0; i <= pgs; i++) {
434                 outb(port + SR_PSR,
435                      (inb(port + SR_PSR) & ~SR_PSR_PG_SEL) | i);
436                 bzero(smem, SRC_WIN_SIZ);
437         }
438
439         SRC_SET_OFF(port);
440         return (pgs);
441 }