Get rid of bus_{disable,enable}_intr(), it wasn't generic enough for
[dragonfly.git] / sys / net / i4b / layer1 / isic / i4b_usr_sti.c
1 /*
2  * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_usr_sti.c - USRobotics Sportster ISDN TA intern (Tina-pp)
28  *      -------------------------------------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_usr_sti.c,v 1.5.2.1 2001/08/10 14:08:39 obrien Exp $
31  * $DragonFly: src/sys/net/i4b/layer1/isic/i4b_usr_sti.c,v 1.5 2005/05/24 20:59:05 dillon Exp $
32  *
33  *      last edit-date: [Wed Jan 24 09:28:12 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #include "use_isic.h"
38 #include "opt_i4b.h"
39
40 #if (NISIC > 0) && defined(USR_STI)
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/bus.h>
45 #include <machine/bus.h>
46 #include <sys/rman.h>
47
48 #include <sys/socket.h>
49 #include <net/if.h>
50
51 #include <net/i4b/include/machine/i4b_ioctl.h>
52 #include <net/i4b/include/machine/i4b_trace.h>
53
54 #include "../i4b_l1.h"
55 #include "i4b_isic.h"
56 #include "i4b_hscx.h"
57
58 /*---------------------------------------------------------------------------*
59  *      USR Sportster TA intern special registers
60  *---------------------------------------------------------------------------*/
61 #define USR_HSCXA_OFF   0x0000
62 #define USR_HSCXB_OFF   0x4000
63 #define USR_INTL_OFF    0x8000
64 #define USR_ISAC_OFF    0xc000
65
66 #define USR_RES_BIT     0x80    /* 0 = normal, 1 = reset ISAC/HSCX      */
67 #define USR_INTE_BIT    0x40    /* 0 = IRQ disabled, 1 = IRQ's enabled  */
68 #define USR_IL_MASK     0x07    /* IRQ level config                     */
69
70 static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 };
71
72 #define ADDR(reg)       \
73         (((reg/4) * 1024) + ((reg%4) * 2))
74
75 #ifdef USRTA_DEBUG_PORTACCESS
76 int debugcntr;
77 #define USRTA_DEBUG(fmt) \
78                 if (++debugcntr < 1000) printf fmt;
79 #else
80 #define USRTA_DEBUG(fmt)
81 #endif
82
83 /*---------------------------------------------------------------------------*
84  *      USRobotics read fifo routine
85  *---------------------------------------------------------------------------*/
86 static void             
87 usrtai_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
88 {
89         int offset = 0;
90         unsigned int base = 0;
91
92 USRTA_DEBUG(("usrtai_read_fifo: what %d size %d\n", what, size))
93         switch (what)
94         {
95                 case ISIC_WHAT_ISAC:
96                         base = (unsigned int)ISAC_BASE;
97                         break;
98                 case ISIC_WHAT_HSCXA:
99                         base = (unsigned int)HSCX_A_BASE;
100                         break;
101                 case ISIC_WHAT_HSCXB:
102                         base = (unsigned int)HSCX_B_BASE;
103                         break;
104                 default:
105                         printf("usrtai_read_fifo: invalid what %d\n", what);
106                         return;
107         }
108
109         for(;size > 0; size--, offset++)        
110         {
111                 *((u_char *)buf + offset) = inb(base + ADDR(offset));
112         }
113 }
114
115 /*---------------------------------------------------------------------------*
116  *      USRobotics write fifo routine
117  *---------------------------------------------------------------------------*/
118 static void
119 usrtai_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
120 {
121         int offset = 0;
122         unsigned int base = 0;
123
124 USRTA_DEBUG(("usrtai_write_fifo: what %d size %d\n", what, size))
125         switch (what)
126         {
127                 case ISIC_WHAT_ISAC:
128                         base = (unsigned int)ISAC_BASE;
129                         break;
130                 case ISIC_WHAT_HSCXA:
131                         base = (unsigned int)HSCX_A_BASE;
132                         break;
133                 case ISIC_WHAT_HSCXB:
134                         base = (unsigned int)HSCX_B_BASE;
135                         break;
136                 default:
137                         printf("usrtai_write_fifo: invalid what %d\n", what);
138                         return;
139         }
140
141         
142         for(;size > 0; size--, offset++)
143         {
144                 outb(base + ADDR(offset), *((u_char *)data + offset));
145         }
146 }
147
148 /*---------------------------------------------------------------------------*
149  *      USRobotics write register routine
150  *---------------------------------------------------------------------------*/
151 static void
152 usrtai_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
153 {
154         unsigned int base = 0;
155
156 USRTA_DEBUG(("usrtai_write_reg: what %d ADDR(%d) %d data %#x\n", what, offs, ADDR(offs), data))
157         switch (what)
158         {
159                 case ISIC_WHAT_ISAC:
160                         base = (unsigned int)ISAC_BASE;
161                         break;
162                 case ISIC_WHAT_HSCXA:
163                         base = (unsigned int)HSCX_A_BASE;
164                         break;
165                 case ISIC_WHAT_HSCXB:
166                         base = (unsigned int)HSCX_B_BASE;
167                         break;
168                 default:
169                         printf("usrtai_write_reg invalid what %d\n", what);
170                         return;
171         }
172
173         outb(base + ADDR(offs), (u_char)data);
174 }
175
176 /*---------------------------------------------------------------------------*
177  *      USRobotics read register routine
178  *---------------------------------------------------------------------------*/
179 static u_int8_t
180 usrtai_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
181 {
182         unsigned int base = 0;
183         u_int8_t byte;
184
185 USRTA_DEBUG(("usrtai_read_reg: what %d ADDR(%d) %d..", what, offs, ADDR(offs)))
186         switch (what)
187         {
188                 case ISIC_WHAT_ISAC:
189                         base = (unsigned int)ISAC_BASE;
190                         break;
191                 case ISIC_WHAT_HSCXA:
192                         base = (unsigned int)HSCX_A_BASE;
193                         break;
194                 case ISIC_WHAT_HSCXB:
195                         base = (unsigned int)HSCX_B_BASE;
196                         break;
197                 default:
198                         printf("usrtai_read_reg: invalid what %d\n", what);
199                         return(0);
200         }
201
202         byte = inb(base + ADDR(offs));
203 USRTA_DEBUG(("usrtai_read_reg: got %#x\n", byte))
204         return(byte);
205 }
206
207 /*---------------------------------------------------------------------------*
208  *      allocate an io port - based on code in isa_isic.c
209  *---------------------------------------------------------------------------*/
210 static int
211 usrtai_alloc_port(device_t dev)
212
213         size_t unit = device_get_unit(dev);
214         struct l1_softc *sc = &l1_sc[unit];
215         int i, num = 0;
216         bus_size_t base;
217
218         /* 49 io mappings: 1 config and 48x8 registers */
219
220         /* config at offset 0x8000 */
221         base = sc->sc_port + 0x8000;
222         if (base < 0 || base > 0x0ffff)
223                 return 1;
224         sc->sc_resources.io_rid[num] = num;
225
226         bus_set_resource(dev, SYS_RES_IOPORT, num, base, 1);
227
228         if(!(sc->sc_resources.io_base[num] =
229                 bus_alloc_resource(dev, SYS_RES_IOPORT,
230                                    &sc->sc_resources.io_rid[num],
231                                    0ul, ~0ul, 1, RF_ACTIVE)))
232         {
233                 printf("isic%d: Error, failed to reserve io #%dport %#x!\n", unit, num, base);
234                 isic_detach_common(dev);
235                 return(ENXIO);
236         }
237         num++;
238
239         /* HSCX A at offset 0 */
240         base = sc->sc_port;
241         for (i = 0; i < 16; i++) {
242                 if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
243                         return 1;
244                 sc->sc_resources.io_rid[num] = num;
245
246                 bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
247
248                 if(!(sc->sc_resources.io_base[num] =
249                         bus_alloc_resource(dev, SYS_RES_IOPORT,
250                                            &sc->sc_resources.io_rid[num],
251                                            0ul, ~0ul, 1, RF_ACTIVE)))
252                 {
253                         printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
254                         isic_detach_common(dev);
255                         return(ENXIO);
256                 }
257                 ++num;
258         }
259
260         /* HSCX B at offset 0x4000 */
261         base = sc->sc_port + 0x4000;
262         for (i = 0; i < 16; i++) {
263                 if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
264                         return 1;
265                 sc->sc_resources.io_rid[num] = num;
266
267                 bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
268
269                 if(!(sc->sc_resources.io_base[num] =
270                         bus_alloc_resource(dev, SYS_RES_IOPORT,
271                                            &sc->sc_resources.io_rid[num],
272                                            0ul, ~0ul, 1, RF_ACTIVE)))
273                 {
274                         printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
275                         isic_detach_common(dev);
276                         return(ENXIO);
277                 }
278                 ++num;
279         }
280
281         /* ISAC at offset 0xc000 */
282         base = sc->sc_port + 0xc000;
283         for (i = 0; i < 16; i++) {
284                 if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
285                         return 1;
286                 sc->sc_resources.io_rid[num] = num;
287
288                 bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
289
290                 if(!(sc->sc_resources.io_base[num] =
291                         bus_alloc_resource(dev, SYS_RES_IOPORT,
292                                            &sc->sc_resources.io_rid[num],
293                                            0ul, ~0ul, 1, RF_ACTIVE)))
294                 {
295                         printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
296                         isic_detach_common(dev);
297                         return(ENXIO);
298                 }
299                 ++num;
300         }
301
302         return(0);
303 }
304
305 /*---------------------------------------------------------------------------*
306  *      isic_probe_usrtai - probe for USR
307  *---------------------------------------------------------------------------*/
308 int
309 isic_probe_usrtai(device_t dev)
310 {
311         size_t unit = device_get_unit(dev);     /* get unit */
312         struct l1_softc *sc = 0;        /* pointer to softc */
313         void *ih = 0;                   /* dummy */
314
315         /* check max unit range */
316
317         if(unit >= ISIC_MAXUNIT)
318         {
319                 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for USR Sportster TA!\n",
320                                 unit, unit);
321                 return(ENXIO);  
322         }
323
324         sc = &l1_sc[unit];                      /* get pointer to softc */
325         sc->sc_unit = unit;                     /* set unit */
326
327         /* see if an io base was supplied */
328         
329         if(!(sc->sc_resources.io_base[0] =
330                         bus_alloc_resource(dev, SYS_RES_IOPORT,
331                                            &sc->sc_resources.io_rid[0],
332                                            0ul, ~0ul, 1, RF_ACTIVE)))
333         {
334                 printf("isic%d: Could not get iobase for USR Sportster TA!\n",
335                                 unit);
336                 return(ENXIO);
337         }
338
339         /* set io base */
340
341         sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
342         
343         /* release io base */
344         
345         bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
346                 sc->sc_resources.io_base[0]);
347
348
349         /* check if we got an iobase */
350
351         switch(sc->sc_port)
352         {
353                 case 0x200:
354                 case 0x208:
355                 case 0x210:
356                 case 0x218:
357                 case 0x220:
358                 case 0x228:
359                 case 0x230:
360                 case 0x238:
361                 case 0x240:
362                 case 0x248:
363                 case 0x250:
364                 case 0x258:
365                 case 0x260:
366                 case 0x268:
367                 case 0x270:
368                 case 0x278:
369                         break;
370                         
371                 default:
372                         printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n",
373                                 unit, sc->sc_port);
374                         return(0);
375                         break;
376         }
377
378         /* allocate all the ports needed */
379
380         if(usrtai_alloc_port(dev))
381         {
382                 printf("isic%d: Could not get the ports for USR Sportster TA!\n", unit);
383                 isic_detach_common(dev);
384                 return(ENXIO);
385         }
386
387         /* get our irq */
388
389         if(!(sc->sc_resources.irq =
390                 bus_alloc_resource(dev, SYS_RES_IRQ,
391                                    &sc->sc_resources.irq_rid,
392                                    0ul, ~0ul, 1, RF_ACTIVE)))
393         {
394                 printf("isic%d: Could not get an irq for USR Sportster TA!\n",unit);
395                 isic_detach_common(dev);
396                 return ENXIO;
397         }
398
399         /* get the irq number */
400         sc->sc_irq = rman_get_start(sc->sc_resources.irq);
401
402         /* register interrupt routine */
403         bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
404                         (void(*)(void *))(isicintr),
405                         sc, &ih, NULL);
406
407         /* check IRQ validity */
408
409         if(intr_no[sc->sc_irq] == 0)
410         {
411                 printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
412                         unit, sc->sc_irq);
413                 return(1);
414         }
415
416         /* setup ISAC access routines */
417
418         sc->clearirq = NULL;
419         sc->readreg = usrtai_read_reg;
420         sc->writereg = usrtai_write_reg;
421
422         sc->readfifo = usrtai_read_fifo;
423         sc->writefifo = usrtai_write_fifo;
424
425         /* setup card type */
426
427         sc->sc_cardtyp = CARD_TYPEP_USRTA;
428
429         /* setup IOM bus type */
430         
431         sc->sc_bustyp = BUS_TYPE_IOM2;
432
433         sc->sc_ipac = 0;
434         sc->sc_bfifolen = HSCX_FIFO_LEN;
435         
436         /* setup ISAC and HSCX base addr */
437         
438         ISAC_BASE   = (caddr_t)sc->sc_port + USR_ISAC_OFF;
439         HSCX_A_BASE = (caddr_t)sc->sc_port + USR_HSCXA_OFF;
440         HSCX_B_BASE = (caddr_t)sc->sc_port + USR_HSCXB_OFF;
441
442         /* 
443          * Read HSCX A/B VSTR.  Expected value for USR Sportster TA based
444          * boards is 0x05 in the least significant bits.
445          */
446
447         if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
448             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
449         {
450                 printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n",
451                         unit);
452                 printf("isic%d: HSC0: VSTR: %#x\n",
453                         unit, HSCX_READ(0, H_VSTR));
454                 printf("isic%d: HSC1: VSTR: %#x\n",
455                         unit, HSCX_READ(1, H_VSTR));
456                 return (1);
457         }                   
458         
459         return (0);
460 }
461
462 /*---------------------------------------------------------------------------*
463  *      isic_attach_usrtai - attach USR
464  *---------------------------------------------------------------------------*/
465 int
466 isic_attach_usrtai(device_t dev)
467 {
468         u_char irq = 0;
469         size_t unit = device_get_unit(dev);     /* get unit */
470         struct l1_softc *sc = 0;        /* pointer to softc */
471         
472         sc = &l1_sc[unit];                      /* get pointer to softc */
473
474         /* reset the HSCX and ISAC chips */
475         
476         outb(sc->sc_port + USR_INTL_OFF, USR_RES_BIT);
477         DELAY(SEC_DELAY / 10);
478
479         outb(sc->sc_port + USR_INTL_OFF, 0x00);
480         DELAY(SEC_DELAY / 10);
481
482         /* setup IRQ */
483
484         if((irq = intr_no[sc->sc_irq]) == 0)
485         {
486                 printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n",
487                         unit, sc->sc_irq);
488                 return(1);
489         }
490
491         /* configure and enable irq */
492
493         outb(sc->sc_port + USR_INTL_OFF, irq | USR_INTE_BIT);
494         DELAY(SEC_DELAY / 10);
495
496         return (0);
497 }
498
499 #endif /* ISIC > 0 */