b1365304665809004a1944e4289f8bb1e6898e47
[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.8 2006/12/22 23:44:56 swildner 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 <sys/rman.h>
46 #include <sys/socket.h>
47
48 #include <net/if.h>
49 #include <net/i4b/include/machine/i4b_ioctl.h>
50 #include <net/i4b/include/machine/i4b_trace.h>
51
52 #include "../i4b_l1.h"
53 #include "i4b_isic.h"
54 #include "i4b_hscx.h"
55
56 /*---------------------------------------------------------------------------*
57  *      USR Sportster TA intern special registers
58  *---------------------------------------------------------------------------*/
59 #define USR_HSCXA_OFF   0x0000
60 #define USR_HSCXB_OFF   0x4000
61 #define USR_INTL_OFF    0x8000
62 #define USR_ISAC_OFF    0xc000
63
64 #define USR_RES_BIT     0x80    /* 0 = normal, 1 = reset ISAC/HSCX      */
65 #define USR_INTE_BIT    0x40    /* 0 = IRQ disabled, 1 = IRQ's enabled  */
66 #define USR_IL_MASK     0x07    /* IRQ level config                     */
67
68 static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 };
69
70 #define ADDR(reg)       \
71         (((reg/4) * 1024) + ((reg%4) * 2))
72
73 #ifdef USRTA_DEBUG_PORTACCESS
74 int debugcntr;
75 #define USRTA_DEBUG(fmt) \
76                 if (++debugcntr < 1000) kprintf fmt;
77 #else
78 #define USRTA_DEBUG(fmt)
79 #endif
80
81 /*---------------------------------------------------------------------------*
82  *      USRobotics read fifo routine
83  *---------------------------------------------------------------------------*/
84 static void             
85 usrtai_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
86 {
87         int offset = 0;
88         unsigned int base = 0;
89
90 USRTA_DEBUG(("usrtai_read_fifo: what %d size %d\n", what, size))
91         switch (what)
92         {
93                 case ISIC_WHAT_ISAC:
94                         base = (unsigned int)ISAC_BASE;
95                         break;
96                 case ISIC_WHAT_HSCXA:
97                         base = (unsigned int)HSCX_A_BASE;
98                         break;
99                 case ISIC_WHAT_HSCXB:
100                         base = (unsigned int)HSCX_B_BASE;
101                         break;
102                 default:
103                         kprintf("usrtai_read_fifo: invalid what %d\n", what);
104                         return;
105         }
106
107         for(;size > 0; size--, offset++)        
108         {
109                 *((u_char *)buf + offset) = inb(base + ADDR(offset));
110         }
111 }
112
113 /*---------------------------------------------------------------------------*
114  *      USRobotics write fifo routine
115  *---------------------------------------------------------------------------*/
116 static void
117 usrtai_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
118 {
119         int offset = 0;
120         unsigned int base = 0;
121
122 USRTA_DEBUG(("usrtai_write_fifo: what %d size %d\n", what, size))
123         switch (what)
124         {
125                 case ISIC_WHAT_ISAC:
126                         base = (unsigned int)ISAC_BASE;
127                         break;
128                 case ISIC_WHAT_HSCXA:
129                         base = (unsigned int)HSCX_A_BASE;
130                         break;
131                 case ISIC_WHAT_HSCXB:
132                         base = (unsigned int)HSCX_B_BASE;
133                         break;
134                 default:
135                         kprintf("usrtai_write_fifo: invalid what %d\n", what);
136                         return;
137         }
138
139         
140         for(;size > 0; size--, offset++)
141         {
142                 outb(base + ADDR(offset), *((u_char *)data + offset));
143         }
144 }
145
146 /*---------------------------------------------------------------------------*
147  *      USRobotics write register routine
148  *---------------------------------------------------------------------------*/
149 static void
150 usrtai_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
151 {
152         unsigned int base = 0;
153
154 USRTA_DEBUG(("usrtai_write_reg: what %d ADDR(%d) %d data %#x\n", what, offs, ADDR(offs), data))
155         switch (what)
156         {
157                 case ISIC_WHAT_ISAC:
158                         base = (unsigned int)ISAC_BASE;
159                         break;
160                 case ISIC_WHAT_HSCXA:
161                         base = (unsigned int)HSCX_A_BASE;
162                         break;
163                 case ISIC_WHAT_HSCXB:
164                         base = (unsigned int)HSCX_B_BASE;
165                         break;
166                 default:
167                         kprintf("usrtai_write_reg invalid what %d\n", what);
168                         return;
169         }
170
171         outb(base + ADDR(offs), (u_char)data);
172 }
173
174 /*---------------------------------------------------------------------------*
175  *      USRobotics read register routine
176  *---------------------------------------------------------------------------*/
177 static u_int8_t
178 usrtai_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
179 {
180         unsigned int base = 0;
181         u_int8_t byte;
182
183 USRTA_DEBUG(("usrtai_read_reg: what %d ADDR(%d) %d..", what, offs, ADDR(offs)))
184         switch (what)
185         {
186                 case ISIC_WHAT_ISAC:
187                         base = (unsigned int)ISAC_BASE;
188                         break;
189                 case ISIC_WHAT_HSCXA:
190                         base = (unsigned int)HSCX_A_BASE;
191                         break;
192                 case ISIC_WHAT_HSCXB:
193                         base = (unsigned int)HSCX_B_BASE;
194                         break;
195                 default:
196                         kprintf("usrtai_read_reg: invalid what %d\n", what);
197                         return(0);
198         }
199
200         byte = inb(base + ADDR(offs));
201 USRTA_DEBUG(("usrtai_read_reg: got %#x\n", byte))
202         return(byte);
203 }
204
205 /*---------------------------------------------------------------------------*
206  *      allocate an io port - based on code in isa_isic.c
207  *---------------------------------------------------------------------------*/
208 static int
209 usrtai_alloc_port(device_t dev)
210
211         size_t unit = device_get_unit(dev);
212         struct l1_softc *sc = &l1_sc[unit];
213         int i, num = 0;
214         bus_size_t base;
215
216         /* 49 io mappings: 1 config and 48x8 registers */
217
218         /* config at offset 0x8000 */
219         base = sc->sc_port + 0x8000;
220         if (base < 0 || base > 0x0ffff)
221                 return 1;
222         sc->sc_resources.io_rid[num] = num;
223
224         bus_set_resource(dev, SYS_RES_IOPORT, num, base, 1);
225
226         if(!(sc->sc_resources.io_base[num] =
227                 bus_alloc_resource(dev, SYS_RES_IOPORT,
228                                    &sc->sc_resources.io_rid[num],
229                                    0ul, ~0ul, 1, RF_ACTIVE)))
230         {
231                 kprintf("isic%d: Error, failed to reserve io #%dport %#x!\n", unit, num, base);
232                 isic_detach_common(dev);
233                 return(ENXIO);
234         }
235         num++;
236
237         /* HSCX A at offset 0 */
238         base = sc->sc_port;
239         for (i = 0; i < 16; i++) {
240                 if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
241                         return 1;
242                 sc->sc_resources.io_rid[num] = num;
243
244                 bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
245
246                 if(!(sc->sc_resources.io_base[num] =
247                         bus_alloc_resource(dev, SYS_RES_IOPORT,
248                                            &sc->sc_resources.io_rid[num],
249                                            0ul, ~0ul, 1, RF_ACTIVE)))
250                 {
251                         kprintf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
252                         isic_detach_common(dev);
253                         return(ENXIO);
254                 }
255                 ++num;
256         }
257
258         /* HSCX B at offset 0x4000 */
259         base = sc->sc_port + 0x4000;
260         for (i = 0; i < 16; i++) {
261                 if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
262                         return 1;
263                 sc->sc_resources.io_rid[num] = num;
264
265                 bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
266
267                 if(!(sc->sc_resources.io_base[num] =
268                         bus_alloc_resource(dev, SYS_RES_IOPORT,
269                                            &sc->sc_resources.io_rid[num],
270                                            0ul, ~0ul, 1, RF_ACTIVE)))
271                 {
272                         kprintf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
273                         isic_detach_common(dev);
274                         return(ENXIO);
275                 }
276                 ++num;
277         }
278
279         /* ISAC at offset 0xc000 */
280         base = sc->sc_port + 0xc000;
281         for (i = 0; i < 16; i++) {
282                 if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
283                         return 1;
284                 sc->sc_resources.io_rid[num] = num;
285
286                 bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
287
288                 if(!(sc->sc_resources.io_base[num] =
289                         bus_alloc_resource(dev, SYS_RES_IOPORT,
290                                            &sc->sc_resources.io_rid[num],
291                                            0ul, ~0ul, 1, RF_ACTIVE)))
292                 {
293                         kprintf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
294                         isic_detach_common(dev);
295                         return(ENXIO);
296                 }
297                 ++num;
298         }
299
300         return(0);
301 }
302
303 /*---------------------------------------------------------------------------*
304  *      isic_probe_usrtai - probe for USR
305  *---------------------------------------------------------------------------*/
306 int
307 isic_probe_usrtai(device_t dev)
308 {
309         size_t unit = device_get_unit(dev);     /* get unit */
310         struct l1_softc *sc = 0;        /* pointer to softc */
311         void *ih = 0;                   /* dummy */
312
313         /* check max unit range */
314
315         if(unit >= ISIC_MAXUNIT)
316         {
317                 kprintf("isic%d: Error, unit %d >= ISIC_MAXUNIT for USR Sportster TA!\n",
318                                 unit, unit);
319                 return(ENXIO);  
320         }
321
322         sc = &l1_sc[unit];                      /* get pointer to softc */
323         sc->sc_unit = unit;                     /* set unit */
324
325         /* see if an io base was supplied */
326         
327         if(!(sc->sc_resources.io_base[0] =
328                         bus_alloc_resource(dev, SYS_RES_IOPORT,
329                                            &sc->sc_resources.io_rid[0],
330                                            0ul, ~0ul, 1, RF_ACTIVE)))
331         {
332                 kprintf("isic%d: Could not get iobase for USR Sportster TA!\n",
333                                 unit);
334                 return(ENXIO);
335         }
336
337         /* set io base */
338
339         sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
340         
341         /* release io base */
342         
343         bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
344                 sc->sc_resources.io_base[0]);
345
346
347         /* check if we got an iobase */
348
349         switch(sc->sc_port)
350         {
351                 case 0x200:
352                 case 0x208:
353                 case 0x210:
354                 case 0x218:
355                 case 0x220:
356                 case 0x228:
357                 case 0x230:
358                 case 0x238:
359                 case 0x240:
360                 case 0x248:
361                 case 0x250:
362                 case 0x258:
363                 case 0x260:
364                 case 0x268:
365                 case 0x270:
366                 case 0x278:
367                         break;
368                         
369                 default:
370                         kprintf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n",
371                                 unit, sc->sc_port);
372                         return(0);
373                         break;
374         }
375
376         /* allocate all the ports needed */
377
378         if(usrtai_alloc_port(dev))
379         {
380                 kprintf("isic%d: Could not get the ports for USR Sportster TA!\n", unit);
381                 isic_detach_common(dev);
382                 return(ENXIO);
383         }
384
385         /* get our irq */
386
387         if(!(sc->sc_resources.irq =
388                 bus_alloc_resource(dev, SYS_RES_IRQ,
389                                    &sc->sc_resources.irq_rid,
390                                    0ul, ~0ul, 1, RF_ACTIVE)))
391         {
392                 kprintf("isic%d: Could not get an irq for USR Sportster TA!\n",unit);
393                 isic_detach_common(dev);
394                 return ENXIO;
395         }
396
397         /* get the irq number */
398         sc->sc_irq = rman_get_start(sc->sc_resources.irq);
399
400         /* register interrupt routine */
401         bus_setup_intr(dev, sc->sc_resources.irq, 0,
402                         (void(*)(void *))(isicintr), sc, &ih, NULL);
403
404         /* check IRQ validity */
405
406         if(intr_no[sc->sc_irq] == 0)
407         {
408                 kprintf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
409                         unit, sc->sc_irq);
410                 return(1);
411         }
412
413         /* setup ISAC access routines */
414
415         sc->clearirq = NULL;
416         sc->readreg = usrtai_read_reg;
417         sc->writereg = usrtai_write_reg;
418
419         sc->readfifo = usrtai_read_fifo;
420         sc->writefifo = usrtai_write_fifo;
421
422         /* setup card type */
423
424         sc->sc_cardtyp = CARD_TYPEP_USRTA;
425
426         /* setup IOM bus type */
427         
428         sc->sc_bustyp = BUS_TYPE_IOM2;
429
430         sc->sc_ipac = 0;
431         sc->sc_bfifolen = HSCX_FIFO_LEN;
432         
433         /* setup ISAC and HSCX base addr */
434         
435         ISAC_BASE   = (caddr_t)sc->sc_port + USR_ISAC_OFF;
436         HSCX_A_BASE = (caddr_t)sc->sc_port + USR_HSCXA_OFF;
437         HSCX_B_BASE = (caddr_t)sc->sc_port + USR_HSCXB_OFF;
438
439         /* 
440          * Read HSCX A/B VSTR.  Expected value for USR Sportster TA based
441          * boards is 0x05 in the least significant bits.
442          */
443
444         if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
445             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
446         {
447                 kprintf("isic%d: HSCX VSTR test failed for USR Sportster TA\n",
448                         unit);
449                 kprintf("isic%d: HSC0: VSTR: %#x\n",
450                         unit, HSCX_READ(0, H_VSTR));
451                 kprintf("isic%d: HSC1: VSTR: %#x\n",
452                         unit, HSCX_READ(1, H_VSTR));
453                 return (1);
454         }                   
455         
456         return (0);
457 }
458
459 /*---------------------------------------------------------------------------*
460  *      isic_attach_usrtai - attach USR
461  *---------------------------------------------------------------------------*/
462 int
463 isic_attach_usrtai(device_t dev)
464 {
465         u_char irq = 0;
466         size_t unit = device_get_unit(dev);     /* get unit */
467         struct l1_softc *sc = 0;        /* pointer to softc */
468         
469         sc = &l1_sc[unit];                      /* get pointer to softc */
470
471         /* reset the HSCX and ISAC chips */
472         
473         outb(sc->sc_port + USR_INTL_OFF, USR_RES_BIT);
474         DELAY(SEC_DELAY / 10);
475
476         outb(sc->sc_port + USR_INTL_OFF, 0x00);
477         DELAY(SEC_DELAY / 10);
478
479         /* setup IRQ */
480
481         if((irq = intr_no[sc->sc_irq]) == 0)
482         {
483                 kprintf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n",
484                         unit, sc->sc_irq);
485                 return(1);
486         }
487
488         /* configure and enable irq */
489
490         outb(sc->sc_port + USR_INTL_OFF, irq | USR_INTE_BIT);
491         DELAY(SEC_DELAY / 10);
492
493         return (0);
494 }
495
496 #endif /* ISIC > 0 */