]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i4b/layer1/i4b_elsa_qs1i.c
This commit was generated by cvs2svn to compensate for changes in r48907,
[FreeBSD/FreeBSD.git] / sys / i4b / layer1 / i4b_elsa_qs1i.c
1 /*
2  * Copyright (c) 1997, 1999 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  *      isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro ISA
28  *      =====================================================================
29  *
30  *      $Id: i4b_elsa_qs1i.c,v 1.15 1999/03/16 14:57:53 hm Exp $
31  *
32  *      last edit-date: [Tue Mar 16 15:42:10 1999]
33  *
34  *---------------------------------------------------------------------------*/
35
36 #ifdef __FreeBSD__
37
38 #include "isic.h"
39 #include "opt_i4b.h"
40 #include "pnp.h"
41
42 #else
43
44 #define NISIC   1
45 #define NPNP    1
46
47 #endif
48
49 /* 
50  * this driver works for both the ELSA QuickStep 1000 PNP and the ELSA
51  * PCC-16
52  */
53 #if (NISIC > 0) && (((NPNP > 0) && defined(ELSA_QS1ISA)) || defined(ELSA_PCC16))
54
55 #include <sys/param.h>
56 #include <sys/kernel.h>
57 #include <sys/systm.h>
58 #include <sys/mbuf.h>
59 #include <sys/socket.h>
60 #include <net/if.h>
61
62 #ifdef __FreeBSD__
63 #if __FreeBSD__ >= 3
64 #include <sys/ioccom.h>
65 #else
66 #include <sys/ioctl.h>
67 #endif
68 #include <machine/clock.h>
69 #include <i386/isa/isa_device.h>
70 #include <i386/isa/pnp.h>
71 #else
72 #include <machine/bus.h>
73 #include <sys/device.h>
74 #endif
75
76 #ifdef __FreeBSD__
77 #include <machine/i4b_debug.h>
78 #include <machine/i4b_ioctl.h>
79 #else
80 #include <i4b/i4b_debug.h>
81 #include <i4b/i4b_ioctl.h>
82 #endif
83
84 #include <i4b/include/i4b_global.h>
85 #include <i4b/include/i4b_l1l2.h>
86 #include <i4b/include/i4b_mbuf.h>
87
88 #include <i4b/layer1/i4b_l1.h>
89 #include <i4b/layer1/i4b_isac.h>
90 #include <i4b/layer1/i4b_hscx.h>
91
92 #ifdef __FreeBSD__
93 static void i4b_eq1i_clrirq(void* base);
94 #else
95 static void i4b_eq1i_clrirq(struct isic_softc *sc);
96 void isic_attach_Eqs1pi __P((struct isic_softc *sc));
97 #endif
98
99 /* masks for register encoded in base addr */
100
101 #define ELSA_BASE_MASK          0x0ffff
102 #define ELSA_OFF_MASK           0xf0000
103
104 /* register id's to be encoded in base addr */
105
106 #define ELSA_IDISAC             0x00000
107 #define ELSA_IDHSCXA            0x10000
108 #define ELSA_IDHSCXB            0x20000
109
110 /* offsets from base address */
111
112 #define ELSA_OFF_ISAC           0x00
113 #define ELSA_OFF_HSCX           0x02
114 #define ELSA_OFF_OFF            0x03
115 #define ELSA_OFF_CTRL           0x04
116 #define ELSA_OFF_CFG            0x05
117 #define ELSA_OFF_TIMR           0x06
118 #define ELSA_OFF_IRQ            0x07
119
120 /* control register (write access) */
121
122 #define ELSA_CTRL_LED_YELLOW    0x02
123 #define ELSA_CTRL_LED_GREEN     0x08
124 #define ELSA_CTRL_RESET         0x20
125 #define ELSA_CTRL_TIMEREN       0x80
126 #define ELSA_CTRL_SECRET        0x50
127
128 /*---------------------------------------------------------------------------*
129  *      ELSA QuickStep 1000pro/ISA clear IRQ routine
130  *---------------------------------------------------------------------------*/
131 #ifdef __FreeBSD__
132 static void
133 i4b_eq1i_clrirq(void* base)
134 {
135         outb((u_int)base + ELSA_OFF_IRQ, 0);
136 }
137
138 #else
139 static void
140 i4b_eq1i_clrirq(struct isic_softc *sc)
141 {
142         bus_space_tag_t t = sc->sc_maps[0].t;
143         bus_space_handle_t h = sc->sc_maps[0].h;
144         bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
145 }
146 #endif
147
148 /*---------------------------------------------------------------------------*
149  *      ELSA QuickStep 1000pro/ISA ISAC get fifo routine
150  *---------------------------------------------------------------------------*/
151 #ifdef __FreeBSD__
152
153 static void             
154 eqs1pi_read_fifo(void *buf, const void *base, size_t len)
155 {
156         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
157         {
158                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
159                 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
160         }
161         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
162         {
163                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
164                 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
165         }               
166         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
167         {
168                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
169                 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
170         }               
171 }
172
173 #else
174
175 static void
176 eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
177 {
178         bus_space_tag_t t = sc->sc_maps[0].t;
179         bus_space_handle_t h = sc->sc_maps[0].h;
180         switch (what) {
181                 case ISIC_WHAT_ISAC:
182                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
183                         bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
184                         break;
185                 case ISIC_WHAT_HSCXA:
186                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
187                         bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
188                         break;
189                 case ISIC_WHAT_HSCXB:
190                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
191                         bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
192                         break;
193         }
194 }
195
196 #endif
197
198 /*---------------------------------------------------------------------------*
199  *      ELSA QuickStep 1000pro/ISA ISAC put fifo routine
200  *---------------------------------------------------------------------------*/
201 #ifdef __FreeBSD__
202
203 static void
204 eqs1pi_write_fifo(void *base, const void *buf, size_t len)
205 {
206         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
207         {
208                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
209                 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
210         }
211         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
212         {
213                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
214                 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
215         }               
216         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
217         {
218                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
219                 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
220         }
221 }
222
223 #else
224
225 static void
226 eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
227 {
228         bus_space_tag_t t = sc->sc_maps[0].t;
229         bus_space_handle_t h = sc->sc_maps[0].h;
230         switch (what) {
231                 case ISIC_WHAT_ISAC:
232                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
233                         bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, (u_int8_t*)buf, size);
234                         break;
235                 case ISIC_WHAT_HSCXA:
236                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
237                         bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
238                         break;
239                 case ISIC_WHAT_HSCXB:
240                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
241                         bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
242                         break;
243         }
244 }
245 #endif
246
247 /*---------------------------------------------------------------------------*
248  *      ELSA QuickStep 1000pro/ISA ISAC put register routine
249  *---------------------------------------------------------------------------*/
250 #ifdef __FreeBSD__
251
252 static void
253 eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
254 {
255         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
256         {
257                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
258                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
259         }               
260         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
261         {
262                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
263                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
264         }               
265         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
266         {
267                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
268                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC, (u_char)v);
269         }               
270 }
271
272 #else
273
274 static void
275 eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
276 {
277         bus_space_tag_t t = sc->sc_maps[0].t;
278         bus_space_handle_t h = sc->sc_maps[0].h;
279         switch (what) {
280                 case ISIC_WHAT_ISAC:
281                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
282                         bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
283                         break;
284                 case ISIC_WHAT_HSCXA:
285                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
286                         bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
287                         break;
288                 case ISIC_WHAT_HSCXB:
289                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
290                         bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
291                         break;
292         }
293 }
294 #endif
295
296 /*---------------------------------------------------------------------------*
297  *      ELSA QuickStep 1000pro/ISA ISAC get register routine
298  *---------------------------------------------------------------------------*/
299 #ifdef __FreeBSD__
300
301 static u_char
302 eqs1pi_read_reg(u_char *base, u_int offset)
303 {
304         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
305         {
306                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
307                 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
308         }
309         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
310         {
311                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
312                 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
313         }               
314         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
315         {
316                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
317                 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC));
318         }               
319 }
320
321 #else
322
323 static u_int8_t
324 eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
325 {
326         bus_space_tag_t t = sc->sc_maps[0].t;
327         bus_space_handle_t h = sc->sc_maps[0].h;
328         switch (what) {
329                 case ISIC_WHAT_ISAC:
330                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
331                         return bus_space_read_1(t, h, ELSA_OFF_ISAC);
332                 case ISIC_WHAT_HSCXA:
333                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
334                         return bus_space_read_1(t, h, ELSA_OFF_HSCX);
335                 case ISIC_WHAT_HSCXB:
336                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
337                         return bus_space_read_1(t, h, ELSA_OFF_HSCX);
338         }
339         return 0;
340 }
341
342 #endif
343
344 #ifdef __FreeBSD__
345
346 /*---------------------------------------------------------------------------*
347  *      isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
348  *---------------------------------------------------------------------------*/
349 int
350 isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
351 {
352         struct isic_softc *sc = &isic_sc[dev->id_unit];
353         
354         /* check max unit range */
355         
356         if(dev->id_unit >= ISIC_MAXUNIT)
357         {
358                 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
359                                 dev->id_unit, dev->id_unit);
360                 return(0);      
361         }       
362         sc->sc_unit = dev->id_unit;
363
364         /* check IRQ validity */
365
366         switch(ffs(dev->id_irq) - 1)
367         {
368                 case 3:
369                 case 4:         
370                 case 5:
371                 case 7:
372                 case 10:
373                 case 11:
374                 case 12:
375                 case 15:                
376                         break;
377                         
378                 default:
379                         printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
380                                 dev->id_unit, ffs(dev->id_irq)-1);
381                         return(0);
382                         break;
383         }
384         sc->sc_irq = dev->id_irq;
385
386         /* check if memory addr specified */
387
388         if(dev->id_maddr)
389         {
390                 printf("isic%d: Error, mem addr 0x%lx specified for ELSA QuickStep 1000pro/ISA!\n",
391                         dev->id_unit, (u_long)dev->id_maddr);
392                 return(0);
393         }
394         dev->id_msize = 0;
395         
396         /* check if we got an iobase */
397
398         if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
399         {
400                 printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
401                         dev->id_unit, dev->id_iobase);
402                 return(0);
403         }
404         sc->sc_port = dev->id_iobase;
405
406         /* setup access routines */
407
408         sc->clearirq = i4b_eq1i_clrirq;
409         sc->readreg = eqs1pi_read_reg;
410         sc->writereg = eqs1pi_write_reg;
411
412         sc->readfifo = eqs1pi_read_fifo;
413         sc->writefifo = eqs1pi_write_fifo;
414
415         /* setup card type */
416         
417         sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
418
419         /* setup IOM bus type */
420         
421         sc->sc_bustyp = BUS_TYPE_IOM2;
422
423         sc->sc_ipac = 0;
424         sc->sc_bfifolen = HSCX_FIFO_LEN;        
425
426         /* setup ISAC and HSCX base addr */
427         
428         ISAC_BASE   = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDISAC);
429         HSCX_A_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXA);
430         HSCX_B_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXB);
431
432         /* 
433          * Read HSCX A/B VSTR.  Expected value for the ELSA QuickStep 1000pro
434          * ISA card is 0x05 ( = version 2.1 ) in the least significant bits.
435          */
436
437         if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
438             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
439         {
440                 printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
441                         dev->id_unit);
442                 printf("isic%d: HSC0: VSTR: %#x\n",
443                         dev->id_unit, HSCX_READ(0, H_VSTR));
444                 printf("isic%d: HSC1: VSTR: %#x\n",
445                         dev->id_unit, HSCX_READ(1, H_VSTR));
446                 return (0);
447         }                   
448
449         return (1);
450 }
451
452 /*---------------------------------------------------------------------------*
453  *      isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
454  *---------------------------------------------------------------------------*/
455 int
456 isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
457 {
458         u_char byte = ELSA_CTRL_SECRET;
459
460         byte &= ~ELSA_CTRL_RESET;
461         outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
462         DELAY(20);
463         byte |= ELSA_CTRL_RESET;
464         outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
465
466         DELAY(20);
467         outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
468
469         return(1);
470 }
471
472 #else /* !__FreeBSD__ */
473
474 void
475 isic_attach_Eqs1pi(struct isic_softc *sc)
476 {
477         bus_space_tag_t t = sc->sc_maps[0].t;
478         bus_space_handle_t h = sc->sc_maps[0].h;
479         u_char byte = ELSA_CTRL_SECRET;
480
481         byte &= ~ELSA_CTRL_RESET;
482         bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
483         DELAY(20);
484         byte |= ELSA_CTRL_RESET;
485         bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
486
487         DELAY(20);
488         bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff);
489
490         /* setup access routines */
491
492         sc->clearirq = i4b_eq1i_clrirq;
493         sc->readreg = eqs1pi_read_reg;
494         sc->writereg = eqs1pi_write_reg;
495
496         sc->readfifo = eqs1pi_read_fifo;
497         sc->writefifo = eqs1pi_write_fifo;
498
499         /* setup card type */
500         
501         sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
502
503         /* setup IOM bus type */
504         
505         sc->sc_bustyp = BUS_TYPE_IOM2;
506
507         sc->sc_ipac = 0;
508         sc->sc_bfifolen = HSCX_FIFO_LEN;        
509 }
510
511 #endif
512
513 #endif /* (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) */