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