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: i4b_elsa_qs1i.c,v 1.15 1999/03/16 14:57:53 hm Exp $
32 * last edit-date: [Tue Mar 16 15:42:10 1999]
34 *---------------------------------------------------------------------------*/
50 * this driver works for both the ELSA QuickStep 1000 PNP and the ELSA
53 #if (NISIC > 0) && (((NPNP > 0) && defined(ELSA_QS1ISA)) || defined(ELSA_PCC16))
55 #include <sys/param.h>
56 #include <sys/kernel.h>
57 #include <sys/systm.h>
59 #include <sys/socket.h>
64 #include <sys/ioccom.h>
66 #include <sys/ioctl.h>
68 #include <machine/clock.h>
69 #include <i386/isa/isa_device.h>
70 #include <i386/isa/pnp.h>
72 #include <machine/bus.h>
73 #include <sys/device.h>
77 #include <machine/i4b_debug.h>
78 #include <machine/i4b_ioctl.h>
80 #include <i4b/i4b_debug.h>
81 #include <i4b/i4b_ioctl.h>
84 #include <i4b/include/i4b_global.h>
85 #include <i4b/include/i4b_l1l2.h>
86 #include <i4b/include/i4b_mbuf.h>
88 #include <i4b/layer1/i4b_l1.h>
89 #include <i4b/layer1/i4b_isac.h>
90 #include <i4b/layer1/i4b_hscx.h>
93 static void i4b_eq1i_clrirq(void* base);
95 static void i4b_eq1i_clrirq(struct isic_softc *sc);
96 void isic_attach_Eqs1pi __P((struct isic_softc *sc));
99 /* masks for register encoded in base addr */
101 #define ELSA_BASE_MASK 0x0ffff
102 #define ELSA_OFF_MASK 0xf0000
104 /* register id's to be encoded in base addr */
106 #define ELSA_IDISAC 0x00000
107 #define ELSA_IDHSCXA 0x10000
108 #define ELSA_IDHSCXB 0x20000
110 /* offsets from base address */
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
120 /* control register (write access) */
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
128 /*---------------------------------------------------------------------------*
129 * ELSA QuickStep 1000pro/ISA clear IRQ routine
130 *---------------------------------------------------------------------------*/
133 i4b_eq1i_clrirq(void* base)
135 outb((u_int)base + ELSA_OFF_IRQ, 0);
140 i4b_eq1i_clrirq(struct isic_softc *sc)
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);
148 /*---------------------------------------------------------------------------*
149 * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
150 *---------------------------------------------------------------------------*/
154 eqs1pi_read_fifo(void *buf, const void *base, size_t len)
156 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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);
161 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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);
166 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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);
176 eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
178 bus_space_tag_t t = sc->sc_maps[0].t;
179 bus_space_handle_t h = sc->sc_maps[0].h;
182 bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
183 bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
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);
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);
198 /*---------------------------------------------------------------------------*
199 * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
200 *---------------------------------------------------------------------------*/
204 eqs1pi_write_fifo(void *base, const void *buf, size_t len)
206 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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);
211 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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);
216 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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);
226 eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
228 bus_space_tag_t t = sc->sc_maps[0].t;
229 bus_space_handle_t h = sc->sc_maps[0].h;
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);
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);
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);
247 /*---------------------------------------------------------------------------*
248 * ELSA QuickStep 1000pro/ISA ISAC put register routine
249 *---------------------------------------------------------------------------*/
253 eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
255 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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);
260 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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);
265 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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);
275 eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
277 bus_space_tag_t t = sc->sc_maps[0].t;
278 bus_space_handle_t h = sc->sc_maps[0].h;
281 bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
282 bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
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);
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);
296 /*---------------------------------------------------------------------------*
297 * ELSA QuickStep 1000pro/ISA ISAC get register routine
298 *---------------------------------------------------------------------------*/
302 eqs1pi_read_reg(u_char *base, u_int offset)
304 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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));
309 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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));
314 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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));
324 eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
326 bus_space_tag_t t = sc->sc_maps[0].t;
327 bus_space_handle_t h = sc->sc_maps[0].h;
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);
346 /*---------------------------------------------------------------------------*
347 * isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
348 *---------------------------------------------------------------------------*/
350 isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
352 struct isic_softc *sc = &isic_sc[dev->id_unit];
354 /* check max unit range */
356 if(dev->id_unit >= ISIC_MAXUNIT)
358 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
359 dev->id_unit, dev->id_unit);
362 sc->sc_unit = dev->id_unit;
364 /* check IRQ validity */
366 switch(ffs(dev->id_irq) - 1)
379 printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
380 dev->id_unit, ffs(dev->id_irq)-1);
384 sc->sc_irq = dev->id_irq;
386 /* check if memory addr specified */
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);
396 /* check if we got an iobase */
398 if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
400 printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
401 dev->id_unit, dev->id_iobase);
404 sc->sc_port = dev->id_iobase;
406 /* setup access routines */
408 sc->clearirq = i4b_eq1i_clrirq;
409 sc->readreg = eqs1pi_read_reg;
410 sc->writereg = eqs1pi_write_reg;
412 sc->readfifo = eqs1pi_read_fifo;
413 sc->writefifo = eqs1pi_write_fifo;
415 /* setup card type */
417 sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
419 /* setup IOM bus type */
421 sc->sc_bustyp = BUS_TYPE_IOM2;
424 sc->sc_bfifolen = HSCX_FIFO_LEN;
426 /* setup ISAC and HSCX base addr */
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);
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.
437 if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
438 ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
440 printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
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));
452 /*---------------------------------------------------------------------------*
453 * isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
454 *---------------------------------------------------------------------------*/
456 isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
458 u_char byte = ELSA_CTRL_SECRET;
460 byte &= ~ELSA_CTRL_RESET;
461 outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
463 byte |= ELSA_CTRL_RESET;
464 outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
467 outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
472 #else /* !__FreeBSD__ */
475 isic_attach_Eqs1pi(struct isic_softc *sc)
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;
481 byte &= ~ELSA_CTRL_RESET;
482 bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
484 byte |= ELSA_CTRL_RESET;
485 bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
488 bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff);
490 /* setup access routines */
492 sc->clearirq = i4b_eq1i_clrirq;
493 sc->readreg = eqs1pi_read_reg;
494 sc->writereg = eqs1pi_write_reg;
496 sc->readfifo = eqs1pi_read_fifo;
497 sc->writefifo = eqs1pi_write_fifo;
499 /* setup card type */
501 sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
503 /* setup IOM bus type */
505 sc->sc_bustyp = BUS_TYPE_IOM2;
508 sc->sc_bfifolen = HSCX_FIFO_LEN;
513 #endif /* (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) */