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.14 1999/02/14 11:02:04 hm Exp $
32 * last edit-date: [Sun Feb 14 11:59:45 1999]
34 *---------------------------------------------------------------------------*/
49 #if (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA)
51 #include <sys/param.h>
52 #include <sys/kernel.h>
53 #include <sys/systm.h>
55 #include <sys/socket.h>
60 #include <sys/ioccom.h>
62 #include <sys/ioctl.h>
64 #include <machine/clock.h>
65 #include <i386/isa/isa_device.h>
66 #include <i386/isa/pnp.h>
68 #include <machine/bus.h>
69 #include <sys/device.h>
73 #include <machine/i4b_debug.h>
74 #include <machine/i4b_ioctl.h>
76 #include <i4b/i4b_debug.h>
77 #include <i4b/i4b_ioctl.h>
80 #include <i4b/include/i4b_global.h>
81 #include <i4b/include/i4b_l1l2.h>
82 #include <i4b/include/i4b_mbuf.h>
84 #include <i4b/layer1/i4b_l1.h>
85 #include <i4b/layer1/i4b_isac.h>
86 #include <i4b/layer1/i4b_hscx.h>
89 static void i4b_eq1i_clrirq(void* base);
91 static void i4b_eq1i_clrirq(struct isic_softc *sc);
92 void isic_attach_Eqs1pi __P((struct isic_softc *sc));
95 /* masks for register encoded in base addr */
97 #define ELSA_BASE_MASK 0x0ffff
98 #define ELSA_OFF_MASK 0xf0000
100 /* register id's to be encoded in base addr */
102 #define ELSA_IDISAC 0x00000
103 #define ELSA_IDHSCXA 0x10000
104 #define ELSA_IDHSCXB 0x20000
106 /* offsets from base address */
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
116 /* control register (write access) */
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
124 /*---------------------------------------------------------------------------*
125 * ELSA QuickStep 1000pro/ISA clear IRQ routine
126 *---------------------------------------------------------------------------*/
129 i4b_eq1i_clrirq(void* base)
131 outb((u_int)base + ELSA_OFF_IRQ, 0);
136 i4b_eq1i_clrirq(struct isic_softc *sc)
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);
144 /*---------------------------------------------------------------------------*
145 * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
146 *---------------------------------------------------------------------------*/
150 eqs1pi_read_fifo(void *buf, const void *base, size_t len)
152 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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);
157 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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);
162 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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);
172 eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
174 bus_space_tag_t t = sc->sc_maps[0].t;
175 bus_space_handle_t h = sc->sc_maps[0].h;
178 bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
179 bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
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);
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);
194 /*---------------------------------------------------------------------------*
195 * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
196 *---------------------------------------------------------------------------*/
200 eqs1pi_write_fifo(void *base, const void *buf, size_t len)
202 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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);
207 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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);
212 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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);
222 eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
224 bus_space_tag_t t = sc->sc_maps[0].t;
225 bus_space_handle_t h = sc->sc_maps[0].h;
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);
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);
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);
243 /*---------------------------------------------------------------------------*
244 * ELSA QuickStep 1000pro/ISA ISAC put register routine
245 *---------------------------------------------------------------------------*/
249 eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
251 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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);
256 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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);
261 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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);
271 eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
273 bus_space_tag_t t = sc->sc_maps[0].t;
274 bus_space_handle_t h = sc->sc_maps[0].h;
277 bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
278 bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
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);
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);
292 /*---------------------------------------------------------------------------*
293 * ELSA QuickStep 1000pro/ISA ISAC get register routine
294 *---------------------------------------------------------------------------*/
298 eqs1pi_read_reg(u_char *base, u_int offset)
300 if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
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));
305 else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
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));
310 else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
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));
320 eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
322 bus_space_tag_t t = sc->sc_maps[0].t;
323 bus_space_handle_t h = sc->sc_maps[0].h;
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);
342 /*---------------------------------------------------------------------------*
343 * isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
344 *---------------------------------------------------------------------------*/
346 isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
348 struct isic_softc *sc = &isic_sc[dev->id_unit];
350 /* check max unit range */
352 if(dev->id_unit >= ISIC_MAXUNIT)
354 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
355 dev->id_unit, dev->id_unit);
358 sc->sc_unit = dev->id_unit;
360 /* check IRQ validity */
362 switch(ffs(dev->id_irq) - 1)
375 printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
376 dev->id_unit, ffs(dev->id_irq)-1);
380 sc->sc_irq = dev->id_irq;
382 /* check if memory addr specified */
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);
392 /* check if we got an iobase */
394 if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
396 printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
397 dev->id_unit, dev->id_iobase);
400 sc->sc_port = dev->id_iobase;
402 /* setup access routines */
404 sc->clearirq = i4b_eq1i_clrirq;
405 sc->readreg = eqs1pi_read_reg;
406 sc->writereg = eqs1pi_write_reg;
408 sc->readfifo = eqs1pi_read_fifo;
409 sc->writefifo = eqs1pi_write_fifo;
411 /* setup card type */
413 sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
415 /* setup IOM bus type */
417 sc->sc_bustyp = BUS_TYPE_IOM2;
420 sc->sc_bfifolen = HSCX_FIFO_LEN;
422 /* setup ISAC and HSCX base addr */
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);
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.
433 if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
434 ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
436 printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
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));
448 /*---------------------------------------------------------------------------*
449 * isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
450 *---------------------------------------------------------------------------*/
452 isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
454 u_char byte = ELSA_CTRL_SECRET;
456 byte &= ~ELSA_CTRL_RESET;
457 outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
459 byte |= ELSA_CTRL_RESET;
460 outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
463 outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
468 #else /* !__FreeBSD__ */
471 isic_attach_Eqs1pi(struct isic_softc *sc)
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;
477 byte &= ~ELSA_CTRL_RESET;
478 bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
480 byte |= ELSA_CTRL_RESET;
481 bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
484 bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff);
486 /* setup access routines */
488 sc->clearirq = i4b_eq1i_clrirq;
489 sc->readreg = eqs1pi_read_reg;
490 sc->writereg = eqs1pi_write_reg;
492 sc->readfifo = eqs1pi_read_fifo;
493 sc->writefifo = eqs1pi_write_fifo;
495 /* setup card type */
497 sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
499 /* setup IOM bus type */
501 sc->sc_bustyp = BUS_TYPE_IOM2;
504 sc->sc_bfifolen = HSCX_FIFO_LEN;
509 #endif /* (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) */