Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / isapnp / isic_isapnp_elsa_qs1i.c
blob1a68be489d3adb828bdea49531a421527feef28e
1 /*
2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
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.
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.
25 *---------------------------------------------------------------------------
27 * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro ISA
28 * =====================================================================
30 * $Id: isic_isapnp_elsa_qs1i.c,v 1.16 2007/10/19 12:00:32 ad Exp $
32 * last edit-date: [Fri Jan 5 11:38:29 2001]
34 *---------------------------------------------------------------------------*/
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: isic_isapnp_elsa_qs1i.c,v 1.15 2007/07/09 21:00:51 ad Exp $");
39 #include "opt_isicpnp.h"
40 #if defined(ISICPNP_ELSA_QS1ISA) || defined(ISICPNP_ELSA_PCC16)
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/systm.h>
45 #include <sys/mbuf.h>
46 #include <sys/socket.h>
47 #include <net/if.h>
49 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
50 #include <sys/callout.h>
51 #endif
53 #ifdef __FreeBSD__
54 #if __FreeBSD__ >= 3
55 #include <sys/ioccom.h>
56 #else
57 #include <sys/ioctl.h>
58 #endif
59 #include <machine/clock.h>
60 #include <i386/isa/isa_device.h>
61 #include <i386/isa/pnp.h>
62 #else
63 #include <sys/bus.h>
64 #include <sys/device.h>
65 #endif
67 #ifdef __FreeBSD__
68 #include <machine/i4b_debug.h>
69 #include <machine/i4b_ioctl.h>
70 #else
71 #include <netisdn/i4b_debug.h>
72 #include <netisdn/i4b_ioctl.h>
73 #endif
75 #include <netisdn/i4b_global.h>
76 #include <netisdn/i4b_l2.h>
77 #include <netisdn/i4b_l1l2.h>
78 #include <netisdn/i4b_mbuf.h>
80 #include <dev/ic/isic_l1.h>
81 #include <dev/ic/isac.h>
82 #include <dev/ic/hscx.h>
84 #ifdef __FreeBSD__
85 static void i4b_eq1i_clrirq(void* base);
86 #else
87 static void i4b_eq1i_clrirq(struct isic_softc *sc);
88 void isic_attach_Eqs1pi(struct isic_softc *sc);
89 static void elsa_command_req(struct isic_softc *sc, int command, void *data);
90 static void elsa_led_handler(void *);
91 #endif
93 /* masks for register encoded in base addr */
95 #define ELSA_BASE_MASK 0x0ffff
96 #define ELSA_OFF_MASK 0xf0000
98 /* register id's to be encoded in base addr */
100 #define ELSA_IDISAC 0x00000
101 #define ELSA_IDHSCXA 0x10000
102 #define ELSA_IDHSCXB 0x20000
104 /* offsets from base address */
106 #define ELSA_OFF_ISAC 0x00
107 #define ELSA_OFF_HSCX 0x02
108 #define ELSA_OFF_OFF 0x03
109 #define ELSA_OFF_CTRL 0x04
110 #define ELSA_OFF_CFG 0x05
111 #define ELSA_OFF_TIMR 0x06
112 #define ELSA_OFF_IRQ 0x07
114 /* control register (write access) */
116 #define ELSA_CTRL_LED_YELLOW 0x02
117 #define ELSA_CTRL_LED_GREEN 0x08
118 #define ELSA_CTRL_RESET 0x20
119 #define ELSA_CTRL_TIMEREN 0x80
120 #define ELSA_CTRL_SECRET 0x50
122 /*---------------------------------------------------------------------------*
123 * ELSA QuickStep 1000pro/ISA clear IRQ routine
124 *---------------------------------------------------------------------------*/
125 #ifdef __FreeBSD__
126 static void
127 i4b_eq1i_clrirq(void* base)
129 outb((u_int)base + ELSA_OFF_IRQ, 0);
132 #else
133 static void
134 i4b_eq1i_clrirq(struct isic_softc *sc)
136 bus_space_tag_t t = sc->sc_maps[0].t;
137 bus_space_handle_t h = sc->sc_maps[0].h;
138 bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
140 #endif
142 /*---------------------------------------------------------------------------*
143 * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
144 *---------------------------------------------------------------------------*/
145 #ifdef __FreeBSD__
147 static void
148 eqs1pi_read_fifo(void *buf, const void *base, size_t len)
150 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
152 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
153 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
155 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
157 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
158 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
160 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
162 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
163 insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
167 #else
169 static void
170 eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
172 bus_space_tag_t t = sc->sc_maps[0].t;
173 bus_space_handle_t h = sc->sc_maps[0].h;
174 switch (what) {
175 case ISIC_WHAT_ISAC:
176 bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
177 bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
178 break;
179 case ISIC_WHAT_HSCXA:
180 bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
181 bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
182 break;
183 case ISIC_WHAT_HSCXB:
184 bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
185 bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
186 break;
190 #endif
192 /*---------------------------------------------------------------------------*
193 * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
194 *---------------------------------------------------------------------------*/
195 #ifdef __FreeBSD__
197 static void
198 eqs1pi_write_fifo(void *base, const void *buf, size_t len)
200 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
202 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
203 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
205 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
207 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
208 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
210 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
212 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
213 outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
217 #else
219 static void
220 eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
222 bus_space_tag_t t = sc->sc_maps[0].t;
223 bus_space_handle_t h = sc->sc_maps[0].h;
224 switch (what) {
225 case ISIC_WHAT_ISAC:
226 bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
227 bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
228 break;
229 case ISIC_WHAT_HSCXA:
230 bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
231 bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
232 break;
233 case ISIC_WHAT_HSCXB:
234 bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
235 bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
236 break;
239 #endif
241 /*---------------------------------------------------------------------------*
242 * ELSA QuickStep 1000pro/ISA ISAC put register routine
243 *---------------------------------------------------------------------------*/
244 #ifdef __FreeBSD__
246 static void
247 eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
249 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
251 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
252 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
254 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
256 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
257 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
259 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
261 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
262 outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC, (u_char)v);
266 #else
268 static void
269 eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
271 bus_space_tag_t t = sc->sc_maps[0].t;
272 bus_space_handle_t h = sc->sc_maps[0].h;
273 switch (what) {
274 case ISIC_WHAT_ISAC:
275 bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
276 bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
277 break;
278 case ISIC_WHAT_HSCXA:
279 bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
280 bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
281 break;
282 case ISIC_WHAT_HSCXB:
283 bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
284 bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
285 break;
288 #endif
290 /*---------------------------------------------------------------------------*
291 * ELSA QuickStep 1000pro/ISA ISAC get register routine
292 *---------------------------------------------------------------------------*/
293 #ifdef __FreeBSD__
295 static u_char
296 eqs1pi_read_reg(u_char *base, u_int offset)
298 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
300 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
301 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
303 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
305 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
306 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
308 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
310 outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
311 return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC));
315 #else
317 static u_int8_t
318 eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
320 bus_space_tag_t t = sc->sc_maps[0].t;
321 bus_space_handle_t h = sc->sc_maps[0].h;
322 switch (what) {
323 case ISIC_WHAT_ISAC:
324 bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
325 return bus_space_read_1(t, h, ELSA_OFF_ISAC);
326 case ISIC_WHAT_HSCXA:
327 bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
328 return bus_space_read_1(t, h, ELSA_OFF_HSCX);
329 case ISIC_WHAT_HSCXB:
330 bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
331 return bus_space_read_1(t, h, ELSA_OFF_HSCX);
333 return 0;
336 #endif
338 #ifdef __FreeBSD__
340 /*---------------------------------------------------------------------------*
341 * isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
342 *---------------------------------------------------------------------------*/
344 isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
346 struct isic_softc *sc = &l1_sc[dev->id_unit];
348 /* check max unit range */
350 if(dev->id_unit >= ISIC_MAXUNIT)
352 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
353 dev->id_unit, dev->id_unit);
354 return(0);
356 sc->sc_unit = dev->id_unit;
358 /* check IRQ validity */
360 switch(ffs(dev->id_irq) - 1)
362 case 3:
363 case 4:
364 case 5:
365 case 7:
366 case 10:
367 case 11:
368 case 12:
369 case 15:
370 break;
372 default:
373 printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
374 dev->id_unit, ffs(dev->id_irq)-1);
375 return(0);
376 break;
378 sc->sc_irq = dev->id_irq;
380 /* check if memory addr specified */
382 if(dev->id_maddr)
384 printf("isic%d: Error, mem addr 0x%lx specified for ELSA QuickStep 1000pro/ISA!\n",
385 dev->id_unit, (u_long)dev->id_maddr);
386 return(0);
388 dev->id_msize = 0;
390 /* check if we got an iobase */
392 if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
394 printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
395 dev->id_unit, dev->id_iobase);
396 return(0);
398 sc->sc_port = dev->id_iobase;
400 /* setup access routines */
402 sc->clearirq = i4b_eq1i_clrirq;
403 sc->readreg = eqs1pi_read_reg;
404 sc->writereg = eqs1pi_write_reg;
406 sc->readfifo = eqs1pi_read_fifo;
407 sc->writefifo = eqs1pi_write_fifo;
409 /* setup card type */
411 sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
413 /* setup IOM bus type */
415 sc->sc_bustyp = BUS_TYPE_IOM2;
417 sc->sc_ipac = 0;
418 sc->sc_bfifolen = HSCX_FIFO_LEN;
420 /* setup ISAC and HSCX base addr */
422 ISAC_BASE = (void *) ((u_int)dev->id_iobase | ELSA_IDISAC);
423 HSCX_A_BASE = (void *) ((u_int)dev->id_iobase | ELSA_IDHSCXA);
424 HSCX_B_BASE = (void *) ((u_int)dev->id_iobase | ELSA_IDHSCXB);
427 * Read HSCX A/B VSTR. Expected value for the ELSA QuickStep 1000pro
428 * ISA card is 0x05 ( = version 2.1 ) in the least significant bits.
431 if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
432 ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
434 printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
435 dev->id_unit);
436 printf("isic%d: HSC0: VSTR: %#x\n",
437 dev->id_unit, HSCX_READ(0, H_VSTR));
438 printf("isic%d: HSC1: VSTR: %#x\n",
439 dev->id_unit, HSCX_READ(1, H_VSTR));
440 return (0);
443 return (1);
446 /*---------------------------------------------------------------------------*
447 * isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
448 *---------------------------------------------------------------------------*/
450 isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
452 u_char byte = ELSA_CTRL_SECRET;
454 byte &= ~ELSA_CTRL_RESET;
455 outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
456 DELAY(20);
457 byte |= ELSA_CTRL_RESET;
458 outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
460 DELAY(20);
461 outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
463 return(1);
466 #else /* !__FreeBSD__ */
468 static void
469 elsa_command_req(struct isic_softc *sc, int command, void *data)
471 int v, s, blink;
472 u_int8_t led_val;
474 switch (command) {
475 case CMR_DOPEN:
476 s = splnet();
478 v = ELSA_CTRL_SECRET & ~ELSA_CTRL_RESET;
479 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
480 ELSA_OFF_CTRL, v);
481 delay(20);
482 v |= ELSA_CTRL_RESET;
483 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
484 ELSA_OFF_CTRL, v);
485 delay(20);
486 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
487 ELSA_OFF_IRQ, 0xff);
489 splx(s);
490 break;
492 case CMR_DCLOSE:
493 s = splnet();
494 callout_stop(&sc->sc_driver_callout);
495 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
496 ELSA_OFF_IRQ, 0);
497 v = ELSA_CTRL_SECRET & ~ELSA_CTRL_RESET;
498 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
499 ELSA_OFF_CTRL, v);
500 delay(20);
501 v |= ELSA_CTRL_RESET;
502 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
503 ELSA_OFF_CTRL, v);
504 splx(s);
505 break;
507 case CMR_SETLEDS:
508 /* the magic value and keep reset off */
509 led_val = ELSA_CTRL_SECRET|ELSA_CTRL_RESET;
511 /* now see what LEDs we want to add */
512 v = (int)data;
513 if (v & CMRLEDS_TEI)
514 led_val |= ELSA_CTRL_LED_GREEN;
515 blink = 0;
516 if (v & (CMRLEDS_B0|CMRLEDS_B1)) {
517 led_val |= ELSA_CTRL_LED_YELLOW;
518 if ((v & (CMRLEDS_B0|CMRLEDS_B1)) == (CMRLEDS_B0|CMRLEDS_B1))
519 blink = hz/4;
520 else
521 blink = hz;
522 sc->sc_driver_specific = v;
525 s = splnet();
526 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
527 ELSA_OFF_CTRL, led_val);
528 callout_stop(&sc->sc_driver_callout);
529 if (blink)
530 callout_reset(&sc->sc_driver_callout, blink,
531 elsa_led_handler, sc);
532 splx(s);
534 break;
536 default:
537 return;
541 static void
542 elsa_led_handler(void *token)
544 struct isic_softc *sc = token;
545 int v, s, blink, off = 0;
546 u_int8_t led_val = ELSA_CTRL_SECRET|ELSA_CTRL_RESET;
548 s = splnet();
549 v = sc->sc_driver_specific;
550 if (v > 0) {
551 /* turn blinking LED off */
552 v = -sc->sc_driver_specific;
553 sc->sc_driver_specific = v;
554 off = 1;
555 } else {
556 sc->sc_driver_specific = -v;
558 if (v & CMRLEDS_TEI)
559 led_val |= ELSA_CTRL_LED_GREEN;
560 blink = 0;
561 if (off == 0) {
562 if (v & (CMRLEDS_B0|CMRLEDS_B1))
563 led_val |= ELSA_CTRL_LED_YELLOW;
565 if ((v & (CMRLEDS_B0|CMRLEDS_B1)) == (CMRLEDS_B0|CMRLEDS_B1))
566 blink = hz/4;
567 else
568 blink = hz;
570 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,
571 ELSA_OFF_CTRL, led_val);
572 if (blink)
573 callout_reset(&sc->sc_driver_callout, blink,
574 elsa_led_handler, sc);
575 splx(s);
578 void
579 isic_attach_Eqs1pi(struct isic_softc *sc)
581 /* setup access routines */
583 sc->clearirq = i4b_eq1i_clrirq;
584 sc->readreg = eqs1pi_read_reg;
585 sc->writereg = eqs1pi_write_reg;
587 sc->readfifo = eqs1pi_read_fifo;
588 sc->writefifo = eqs1pi_write_fifo;
590 sc->drv_command = elsa_command_req;
592 /* setup card type */
594 sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
596 /* setup IOM bus type */
598 sc->sc_bustyp = BUS_TYPE_IOM2;
600 sc->sc_ipac = 0;
601 sc->sc_bfifolen = HSCX_FIFO_LEN;
603 callout_init(&sc->sc_driver_callout, 0);
604 sc->sc_driver_specific = 0;
607 #endif
609 #endif /* ISICPNP_ELSA_QS1ISA or ISICPNP_ELSA_PCC16 */