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