]> 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 r44777,
[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.14 1999/02/14 11:02:04 hm Exp $
31  *
32  *      last edit-date: [Sun Feb 14 11:59:45 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 #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 static void
129 i4b_eq1i_clrirq(void* base)
130 {
131         outb((u_int)base + ELSA_OFF_IRQ, 0);
132 }
133
134 #else
135 static void
136 i4b_eq1i_clrirq(struct isic_softc *sc)
137 {
138         bus_space_tag_t t = sc->sc_maps[0].t;
139         bus_space_handle_t h = sc->sc_maps[0].h;
140         bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
141 }
142 #endif
143
144 /*---------------------------------------------------------------------------*
145  *      ELSA QuickStep 1000pro/ISA ISAC get fifo routine
146  *---------------------------------------------------------------------------*/
147 #ifdef __FreeBSD__
148
149 static void             
150 eqs1pi_read_fifo(void *buf, const void *base, size_t len)
151 {
152         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
153         {
154                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
155                 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
156         }
157         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
158         {
159                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
160                 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
161         }               
162         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
163         {
164                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
165                 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
166         }               
167 }
168
169 #else
170
171 static void
172 eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
173 {
174         bus_space_tag_t t = sc->sc_maps[0].t;
175         bus_space_handle_t h = sc->sc_maps[0].h;
176         switch (what) {
177                 case ISIC_WHAT_ISAC:
178                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
179                         bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
180                         break;
181                 case ISIC_WHAT_HSCXA:
182                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
183                         bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
184                         break;
185                 case ISIC_WHAT_HSCXB:
186                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
187                         bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
188                         break;
189         }
190 }
191
192 #endif
193
194 /*---------------------------------------------------------------------------*
195  *      ELSA QuickStep 1000pro/ISA ISAC put fifo routine
196  *---------------------------------------------------------------------------*/
197 #ifdef __FreeBSD__
198
199 static void
200 eqs1pi_write_fifo(void *base, const void *buf, size_t len)
201 {
202         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
203         {
204                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
205                 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
206         }
207         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
208         {
209                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
210                 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
211         }               
212         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
213         {
214                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
215                 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
216         }
217 }
218
219 #else
220
221 static void
222 eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
223 {
224         bus_space_tag_t t = sc->sc_maps[0].t;
225         bus_space_handle_t h = sc->sc_maps[0].h;
226         switch (what) {
227                 case ISIC_WHAT_ISAC:
228                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
229                         bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, (u_int8_t*)buf, size);
230                         break;
231                 case ISIC_WHAT_HSCXA:
232                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
233                         bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
234                         break;
235                 case ISIC_WHAT_HSCXB:
236                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
237                         bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
238                         break;
239         }
240 }
241 #endif
242
243 /*---------------------------------------------------------------------------*
244  *      ELSA QuickStep 1000pro/ISA ISAC put register routine
245  *---------------------------------------------------------------------------*/
246 #ifdef __FreeBSD__
247
248 static void
249 eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
250 {
251         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
252         {
253                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
254                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
255         }               
256         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
257         {
258                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
259                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
260         }               
261         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
262         {
263                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
264                 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC, (u_char)v);
265         }               
266 }
267
268 #else
269
270 static void
271 eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
272 {
273         bus_space_tag_t t = sc->sc_maps[0].t;
274         bus_space_handle_t h = sc->sc_maps[0].h;
275         switch (what) {
276                 case ISIC_WHAT_ISAC:
277                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
278                         bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
279                         break;
280                 case ISIC_WHAT_HSCXA:
281                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
282                         bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
283                         break;
284                 case ISIC_WHAT_HSCXB:
285                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
286                         bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
287                         break;
288         }
289 }
290 #endif
291
292 /*---------------------------------------------------------------------------*
293  *      ELSA QuickStep 1000pro/ISA ISAC get register routine
294  *---------------------------------------------------------------------------*/
295 #ifdef __FreeBSD__
296
297 static u_char
298 eqs1pi_read_reg(u_char *base, u_int offset)
299 {
300         if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
301         {
302                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
303                 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
304         }
305         else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
306         {
307                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
308                 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
309         }               
310         else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
311         {
312                 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
313                 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC));
314         }               
315 }
316
317 #else
318
319 static u_int8_t
320 eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
321 {
322         bus_space_tag_t t = sc->sc_maps[0].t;
323         bus_space_handle_t h = sc->sc_maps[0].h;
324         switch (what) {
325                 case ISIC_WHAT_ISAC:
326                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
327                         return bus_space_read_1(t, h, ELSA_OFF_ISAC);
328                 case ISIC_WHAT_HSCXA:
329                         bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
330                         return bus_space_read_1(t, h, ELSA_OFF_HSCX);
331                 case ISIC_WHAT_HSCXB:
332                         bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
333                         return bus_space_read_1(t, h, ELSA_OFF_HSCX);
334         }
335         return 0;
336 }
337
338 #endif
339
340 #ifdef __FreeBSD__
341
342 /*---------------------------------------------------------------------------*
343  *      isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
344  *---------------------------------------------------------------------------*/
345 int
346 isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
347 {
348         struct isic_softc *sc = &isic_sc[dev->id_unit];
349         
350         /* check max unit range */
351         
352         if(dev->id_unit >= ISIC_MAXUNIT)
353         {
354                 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
355                                 dev->id_unit, dev->id_unit);
356                 return(0);      
357         }       
358         sc->sc_unit = dev->id_unit;
359
360         /* check IRQ validity */
361
362         switch(ffs(dev->id_irq) - 1)
363         {
364                 case 3:
365                 case 4:         
366                 case 5:
367                 case 7:
368                 case 10:
369                 case 11:
370                 case 12:
371                 case 15:                
372                         break;
373                         
374                 default:
375                         printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
376                                 dev->id_unit, ffs(dev->id_irq)-1);
377                         return(0);
378                         break;
379         }
380         sc->sc_irq = dev->id_irq;
381
382         /* check if memory addr specified */
383
384         if(dev->id_maddr)
385         {
386                 printf("isic%d: Error, mem addr 0x%lx specified for ELSA QuickStep 1000pro/ISA!\n",
387                         dev->id_unit, (u_long)dev->id_maddr);
388                 return(0);
389         }
390         dev->id_msize = 0;
391         
392         /* check if we got an iobase */
393
394         if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
395         {
396                 printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
397                         dev->id_unit, dev->id_iobase);
398                 return(0);
399         }
400         sc->sc_port = dev->id_iobase;
401
402         /* setup access routines */
403
404         sc->clearirq = i4b_eq1i_clrirq;
405         sc->readreg = eqs1pi_read_reg;
406         sc->writereg = eqs1pi_write_reg;
407
408         sc->readfifo = eqs1pi_read_fifo;
409         sc->writefifo = eqs1pi_write_fifo;
410
411         /* setup card type */
412         
413         sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
414
415         /* setup IOM bus type */
416         
417         sc->sc_bustyp = BUS_TYPE_IOM2;
418
419         sc->sc_ipac = 0;
420         sc->sc_bfifolen = HSCX_FIFO_LEN;        
421
422         /* setup ISAC and HSCX base addr */
423         
424         ISAC_BASE   = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDISAC);
425         HSCX_A_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXA);
426         HSCX_B_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXB);
427
428         /* 
429          * Read HSCX A/B VSTR.  Expected value for the ELSA QuickStep 1000pro
430          * ISA card is 0x05 ( = version 2.1 ) in the least significant bits.
431          */
432
433         if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
434             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
435         {
436                 printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
437                         dev->id_unit);
438                 printf("isic%d: HSC0: VSTR: %#x\n",
439                         dev->id_unit, HSCX_READ(0, H_VSTR));
440                 printf("isic%d: HSC1: VSTR: %#x\n",
441                         dev->id_unit, HSCX_READ(1, H_VSTR));
442                 return (0);
443         }                   
444
445         return (1);
446 }
447
448 /*---------------------------------------------------------------------------*
449  *      isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
450  *---------------------------------------------------------------------------*/
451 int
452 isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
453 {
454         u_char byte = ELSA_CTRL_SECRET;
455
456         byte &= ~ELSA_CTRL_RESET;
457         outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
458         DELAY(20);
459         byte |= ELSA_CTRL_RESET;
460         outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
461
462         DELAY(20);
463         outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
464
465         return(1);
466 }
467
468 #else /* !__FreeBSD__ */
469
470 void
471 isic_attach_Eqs1pi(struct isic_softc *sc)
472 {
473         bus_space_tag_t t = sc->sc_maps[0].t;
474         bus_space_handle_t h = sc->sc_maps[0].h;
475         u_char byte = ELSA_CTRL_SECRET;
476
477         byte &= ~ELSA_CTRL_RESET;
478         bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
479         DELAY(20);
480         byte |= ELSA_CTRL_RESET;
481         bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
482
483         DELAY(20);
484         bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff);
485
486         /* setup access routines */
487
488         sc->clearirq = i4b_eq1i_clrirq;
489         sc->readreg = eqs1pi_read_reg;
490         sc->writereg = eqs1pi_write_reg;
491
492         sc->readfifo = eqs1pi_read_fifo;
493         sc->writefifo = eqs1pi_write_fifo;
494
495         /* setup card type */
496         
497         sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
498
499         /* setup IOM bus type */
500         
501         sc->sc_bustyp = BUS_TYPE_IOM2;
502
503         sc->sc_ipac = 0;
504         sc->sc_bfifolen = HSCX_FIFO_LEN;        
505 }
506
507 #endif
508
509 #endif /* (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) */