]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/sr/if_sr_isa.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / 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  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/conf.h>           /* cdevsw stuff */
38 #include <sys/kernel.h>         /* SYSINIT stuff */
39 #include <sys/uio.h>            /* SYSINIT stuff */
40 #include <sys/malloc.h>         /* malloc region definitions */
41 #include <sys/module.h>
42 #include <sys/bus.h>
43 #include <machine/bus.h>
44 #include <machine/resource.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(sr, isa, sr_isa_driver, sr_devclass, 0, 0);
97 MODULE_DEPEND(sr, isa, 1, 1, 1);
98
99 static u_int    src_get8_io(struct sr_hardc *hc, u_int off);
100 static u_int    src_get16_io(struct sr_hardc *hc, u_int off);
101 static void     src_put8_io(struct sr_hardc *hc, u_int off, u_int val);
102 static void     src_put16_io(struct sr_hardc *hc, 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_long irq, junk, membase, memsize;
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         hc->cardtype = SR_CRD_N2;
134         hc->cunit = device_get_unit(device);
135         /*
136          * We have to fill these in early because the SRC_PUT* and SRC_GET*
137          * macros use them.
138          */
139         hc->src_get8 = src_get8_io;
140         hc->src_get16 = src_get16_io;
141         hc->src_put8 = src_put8_io;
142         hc->src_put16 = src_put16_io;
143
144         hc->sca = 0;
145         hc->numports = NCHAN;   /* assumed # of channels on the card */
146
147         flags = device_get_flags(device);
148         if (flags & SR_FLAGS_NCHAN_MSK)
149                 hc->numports = flags & SR_FLAGS_NCHAN_MSK;
150
151         sr_outb(hc, SR_PCR, 0); /* turn off the card */
152
153         /*
154          * Next, we'll test the Base Address Register to retension of
155          * data... ... seeing if we're *really* talking to an N2.
156          */
157         for (i = 0; i < 0x100; i++) {
158                 sr_outb(hc, SR_BAR, i);
159                 sr_inb(hc, SR_PCR);
160                 tmp = sr_inb(hc, SR_BAR);
161                 if (tmp != i) {
162                         printf("sr%d: probe failed BAR %x, %x.\n",
163                                hc->cunit, i, tmp);
164                         goto errexit;
165                 }
166         }
167
168         /*
169          * Now see if we can see the SCA.
170          */
171         sr_outb(hc, SR_PCR, SR_PCR_SCARUN | sr_inb(hc, SR_PCR));
172         SRC_PUT8(hc, sca->wcrl, 0);
173         SRC_PUT8(hc, sca->wcrm, 0);
174         SRC_PUT8(hc, sca->wcrh, 0);
175         SRC_PUT8(hc, sca->pcr, 0);
176         SRC_PUT8(hc, sca->msci[0].tmc, 0);
177         sr_inb(hc, 0);
178
179         tmp = SRC_GET8(hc, sca->msci[0].tmc);
180         if (tmp != 0) {
181                 printf("sr%d: Error reading SCA 0, %x\n", hc->cunit, tmp);
182                 goto errexit;
183         }
184         SRC_PUT8(hc, sca->msci[0].tmc, 0x5A);
185         sr_inb(hc, 0);
186
187         tmp = SRC_GET8(hc, sca->msci[0].tmc);
188         if (tmp != 0x5A) {
189                 printf("sr%d: Error reading SCA 0x5A, %x\n", hc->cunit, tmp);
190                 goto errexit;
191         }
192         SRC_PUT16(hc, sca->dmac[0].cda, 0);
193         sr_inb(hc, 0);
194
195         tmp = SRC_GET16(hc, sca->dmac[0].cda);
196         if (tmp != 0) {
197                 printf("sr%d: Error reading SCA 0, %x\n", hc->cunit, tmp);
198                 goto errexit;
199         }
200         SRC_PUT16(hc, sca->dmac[0].cda, 0x55AA);
201         sr_inb(hc, 0);
202
203         tmp = SRC_GET16(hc, sca->dmac[0].cda);
204         if (tmp != 0x55AA) {
205                 printf("sr%d: Error reading SCA 0x55AA, %x\n",
206                        hc->cunit, tmp);
207                 goto errexit;
208         }
209
210         membase = bus_get_resource_start(device, SYS_RES_MEMORY, 0);
211         memsize = SRC_WIN_SIZ;
212         if (bus_set_resource(device, SYS_RES_MEMORY, 0, membase, memsize))
213                 goto errexit;
214
215         if (sr_allocate_memory(device, 0, SRC_WIN_SIZ))
216                 goto errexit;
217
218         if (src_dpram_size(device) < 4)
219                 goto errexit;
220
221         if (sr_allocate_irq(device, 0, 1))
222                 goto errexit;
223
224         if (bus_get_resource(device, SYS_RES_IRQ, 0, &irq, &junk)) {
225                 goto errexit;
226         }
227         /*
228          * Do a little sanity check.
229          */
230         if (sr_irqtable[irq] == 0)
231                 printf("sr%d: Warning: illegal interrupt %ld chosen.\n",
232                        hc->cunit, irq);
233
234         /*
235          * Bogus card configuration
236          */
237         if ((hc->numports > NCHAN)      /* only 2 ports/card */
238             ||(hc->memsize > (512 * 1024)))     /* no more than 256K */
239                 goto errexit;
240
241         sr_deallocate_resources(device);
242         return (0);
243
244 errexit:
245         sr_deallocate_resources(device);
246         return (ENXIO);
247 }
248
249 /*
250  * srattach_isa and srattach_pci allocate memory for hardc, softc and
251  * data buffers. It also does any initialization that is bus specific.
252  * At the end they call the common srattach() function.
253  */
254 static int
255 sr_isa_attach (device_t device)
256 {
257         u_char mar;
258         u_int32_t flags;
259         struct sr_hardc *hc;
260
261         hc = device_get_softc(device);
262         bzero(hc, sizeof(struct sr_hardc));
263
264         if (sr_allocate_ioport(device, 0, SRC_IO_SIZ))
265                 goto errexit;
266         if (sr_allocate_memory(device, 0, SRC_WIN_SIZ))
267                 goto errexit;
268         if (sr_allocate_irq(device, 0, 1))
269                 goto errexit;
270
271         /*
272          * We have to fill these in early because the SRC_PUT* and SRC_GET*
273          * macros use them.
274          */
275         hc->src_get8 = src_get8_io;
276         hc->src_get16 = src_get16_io;
277         hc->src_put8 = src_put8_io;
278         hc->src_put16 = src_put16_io;
279
280         hc->cardtype = SR_CRD_N2;
281         hc->cunit = device_get_unit(device);
282         hc->sca = 0;
283         hc->numports = NCHAN;   /* assumed # of channels on the card */
284         flags = device_get_flags(device);
285         if (flags & SR_FLAGS_NCHAN_MSK)
286                 hc->numports = flags & SR_FLAGS_NCHAN_MSK;
287
288         hc->mem_start = (caddr_t)rman_get_virtual(hc->res_memory);
289         hc->mem_end = hc->mem_start + SRC_WIN_SIZ;
290         hc->mem_pstart = 0;
291         hc->winmsk = SRC_WIN_MSK;
292
293         hc->mempages = src_dpram_size(device);
294         hc->memsize = hc->mempages * SRC_WIN_SIZ;
295
296         sr_outb(hc, SR_PCR, sr_inb(hc, SR_PCR) | SR_PCR_SCARUN);
297         sr_outb(hc, SR_PSR, sr_inb(hc, SR_PSR) | SR_PSR_EN_SCA_DMA);
298         sr_outb(hc, SR_MCR,
299              SR_MCR_DTR0 | SR_MCR_DTR1 | SR_MCR_TE0 | SR_MCR_TE1);
300
301         SRC_SET_ON(hc);
302
303         /*
304          * Configure the card. Mem address, irq,
305          */
306         mar = (rman_get_start(hc->res_memory) >> 16) & SR_PCR_16M_SEL;
307         sr_outb(hc, SR_PCR, mar | (sr_inb(hc, SR_PCR) & ~SR_PCR_16M_SEL));
308         mar = rman_get_start(hc->res_memory) >> 12;
309         sr_outb(hc, SR_BAR, mar);
310
311         return sr_attach(device);
312
313 errexit:
314         sr_deallocate_resources(device);
315         return (ENXIO);
316 }
317
318 /*
319  * I/O for ISA N2 card(s)
320  */
321 #define SRC_REG(y)      ((((y) & 0xf) + (((y) & 0xf0) << 6)) | 0x8000)
322
323 static u_int
324 src_get8_io(struct sr_hardc *hc, u_int off)
325 {
326         return bus_space_read_1(hc->bt_ioport, hc->bh_ioport, SRC_REG(off));
327 }
328
329 static u_int
330 src_get16_io(struct sr_hardc *hc, u_int off)
331 {
332         return bus_space_read_2(hc->bt_ioport, hc->bh_ioport, SRC_REG(off));
333 }
334
335 static void
336 src_put8_io(struct sr_hardc *hc, u_int off, u_int val)
337 {
338         bus_space_write_1(hc->bt_ioport, hc->bh_ioport, SRC_REG(off), val);
339 }
340
341 static void
342 src_put16_io(struct sr_hardc *hc, u_int off, u_int val)
343 {
344         bus_space_write_2(hc->bt_ioport, hc->bh_ioport, SRC_REG(off), val);
345 }
346
347 static u_int
348 src_dpram_size(device_t device)
349 {
350         u_int pgs, i;
351         u_short *smem;
352         u_char mar;
353         u_long membase;
354         struct sr_hardc *hc;
355
356         hc = device_get_softc(device);
357
358         /*
359          * OK, the board's interface registers seem to work. Now we'll see
360          * if the Dual-Ported RAM is fully accessible...
361          */
362         sr_outb(hc, SR_PCR, SR_PCR_EN_VPM | SR_PCR_ISA16);
363         sr_outb(hc, SR_PSR, SR_PSR_WIN_16K);
364
365         /*
366          * Take the kernel "virtual" address supplied to us and convert
367          * it to a "real" address. Then program the card to use that.
368          */
369         membase = rman_get_start(hc->res_memory);
370         mar = (membase >> 16) & SR_PCR_16M_SEL;
371         sr_outb(hc, SR_PCR, mar | sr_inb(hc, SR_PCR));
372         mar = membase >> 12;
373         sr_outb(hc, SR_BAR, mar);
374         sr_outb(hc, SR_PCR, sr_inb(hc, SR_PCR) | SR_PCR_MEM_WIN);
375         smem = (u_short *)rman_get_virtual(hc->res_memory);/* DP RAM Address */
376         /*
377          * Here we will perform the memory scan to size the device.
378          *
379          * This is done by marking each potential page with a magic number.
380          * We then loop through the pages looking for that magic number. As
381          * soon as we no longer see that magic number, we'll quit the scan,
382          * knowing that no more memory is present. This provides the number
383          * of pages present on the card.
384          *
385          * Note: We're sizing 16K memory granules.
386          */
387         for (i = 0; i <= SR_PSR_PG_SEL; i++) {
388                 sr_outb(hc, SR_PSR, (sr_inb(hc, SR_PSR) & ~SR_PSR_PG_SEL) | i);
389                 *smem = 0xAA55;
390         }
391
392         for (i = 0; i <= SR_PSR_PG_SEL; i++) {
393                 sr_outb(hc, SR_PSR, (sr_inb(hc, SR_PSR) & ~SR_PSR_PG_SEL) | i);
394                 if (*smem != 0xAA55) {
395                         /*
396                          * If we have less than 64k of memory, give up. That
397                          * is 4 x 16k pages.
398                          */
399                         if (i < 4) {
400                                 printf("sr%d: Bad mem page %d, mem %x, %x.\n",
401                                        hc->cunit, i, 0xAA55, *smem);
402                                 return 0;
403                         }
404                         break;
405                 }
406                 *smem = i;
407         }
408
409         hc->mempages = i;
410         hc->memsize = i * SRC_WIN_SIZ;
411         hc->winmsk = SRC_WIN_MSK;
412         pgs = i;                /* final count of 16K pages */
413
414         /*
415          * This next loop erases the contents of that page in DPRAM
416          */
417         for (i = 0; i <= pgs; i++) {
418                 sr_outb(hc, SR_PSR, (sr_inb(hc, SR_PSR) & ~SR_PSR_PG_SEL) | i);
419                 bzero(smem, SRC_WIN_SIZ);
420         }
421
422         SRC_SET_OFF(hc);
423         return (pgs);
424 }