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
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
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>
46 #include <sys/socket.h>
49 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
50 #include <sys/callout.h>
55 #include <sys/ioccom.h>
57 #include <sys/ioctl.h>
59 #include <machine/clock.h>
60 #include <i386/isa/isa_device.h>
61 #include <i386/isa/pnp.h>
64 #include <sys/device.h>
68 #include <machine/i4b_debug.h>
69 #include <machine/i4b_ioctl.h>
71 #include <netisdn/i4b_debug.h>
72 #include <netisdn/i4b_ioctl.h>
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>
85 static void i4b_eq1i_clrirq(void* base
);
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 *);
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 *---------------------------------------------------------------------------*/
127 i4b_eq1i_clrirq(void* base
)
129 outb((u_int
)base
+ ELSA_OFF_IRQ
, 0);
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);
142 /*---------------------------------------------------------------------------*
143 * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
144 *---------------------------------------------------------------------------*/
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
);
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
;
176 bus_space_write_1(t
, h
, ELSA_OFF_OFF
, 0);
177 bus_space_read_multi_1(t
, h
, ELSA_OFF_ISAC
, buf
, size
);
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
);
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
);
192 /*---------------------------------------------------------------------------*
193 * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
194 *---------------------------------------------------------------------------*/
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
);
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
;
226 bus_space_write_1(t
, h
, ELSA_OFF_OFF
, 0);
227 bus_space_write_multi_1(t
, h
, ELSA_OFF_ISAC
, buf
, size
);
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
);
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
);
241 /*---------------------------------------------------------------------------*
242 * ELSA QuickStep 1000pro/ISA ISAC put register routine
243 *---------------------------------------------------------------------------*/
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
);
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
;
275 bus_space_write_1(t
, h
, ELSA_OFF_OFF
, offs
);
276 bus_space_write_1(t
, h
, ELSA_OFF_ISAC
, data
);
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
);
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
);
290 /*---------------------------------------------------------------------------*
291 * ELSA QuickStep 1000pro/ISA ISAC get register routine
292 *---------------------------------------------------------------------------*/
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
));
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
;
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
);
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
);
356 sc
->sc_unit
= dev
->id_unit
;
358 /* check IRQ validity */
360 switch(ffs(dev
->id_irq
) - 1)
373 printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
374 dev
->id_unit
, ffs(dev
->id_irq
)-1);
378 sc
->sc_irq
= dev
->id_irq
;
380 /* check if memory addr specified */
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
);
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
);
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
;
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",
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
));
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
);
457 byte
|= ELSA_CTRL_RESET
;
458 outb(dev
->id_iobase
+ ELSA_OFF_CTRL
, byte
);
461 outb(dev
->id_iobase
+ ELSA_OFF_IRQ
, 0xff);
466 #else /* !__FreeBSD__ */
469 elsa_command_req(struct isic_softc
*sc
, int command
, void *data
)
478 v
= ELSA_CTRL_SECRET
& ~ELSA_CTRL_RESET
;
479 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
,
482 v
|= ELSA_CTRL_RESET
;
483 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
,
486 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
,
494 callout_stop(&sc
->sc_driver_callout
);
495 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
,
497 v
= ELSA_CTRL_SECRET
& ~ELSA_CTRL_RESET
;
498 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
,
501 v
|= ELSA_CTRL_RESET
;
502 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
,
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 */
514 led_val
|= ELSA_CTRL_LED_GREEN
;
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
))
522 sc
->sc_driver_specific
= v
;
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
);
530 callout_reset(&sc
->sc_driver_callout
, blink
,
531 elsa_led_handler
, sc
);
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
;
549 v
= sc
->sc_driver_specific
;
551 /* turn blinking LED off */
552 v
= -sc
->sc_driver_specific
;
553 sc
->sc_driver_specific
= v
;
556 sc
->sc_driver_specific
= -v
;
559 led_val
|= ELSA_CTRL_LED_GREEN
;
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
))
570 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
,
571 ELSA_OFF_CTRL
, led_val
);
573 callout_reset(&sc
->sc_driver_callout
, blink
,
574 elsa_led_handler
, sc
);
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
;
601 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
603 callout_init(&sc
->sc_driver_callout
, 0);
604 sc
->sc_driver_specific
= 0;
609 #endif /* ISICPNP_ELSA_QS1ISA or ISICPNP_ELSA_PCC16 */