2 * Copyright (c) 1998 Martijn Plak. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 * 4. Altered versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software and/or documentation.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 *---------------------------------------------------------------------------
33 * isdn4bsd layer1 driver for Dynalink IS64PH isdn TA
34 * ==================================================
36 * $Id: isic_isapnp_dynalink.c,v 1.13 2009/05/12 10:16:35 cegger Exp $
38 * last edit-date: [Fri Jan 5 11:38:29 2001]
40 * written by Martijn Plak (martijn@be3.com)
42 * -mp 11 jun 1998 first try, code borrowed from Creatix driver
43 * -mp 18 jun 1998 cleaned up code
45 * -mp 17 dec 1998 made it compile again
47 *---------------------------------------------------------------------------*/
51 This driver was written for the Dynalink IS64PH ISDN TA, based on two
52 Siemens chips (HSCX 21525 and ISAC 2186). It is sold in the Netherlands.
54 model numbers found on (my) card:
55 IS64PH, TAS100H-N, P/N:89590555, TA200S100045521
58 Siemens PSB 21525N, HSCX TE V2.1
59 Siemens PSB 2186N, ISAC-S TE V1.1
66 i/o port 4 byte alignment, 4 bytes requested,
67 10 bit i/o decoding, 0x100-0x3f8 (?)
68 irq 3,4,5,9,10,11,12,15, high true, edge sensitive
70 At the moment I'm writing this Dynalink is replacing this card with
71 one based on a single Siemens chip (IPAC). It will apparently be sold
72 under the same model name.
74 This driver might also work for Asuscom cards.
77 #include <sys/cdefs.h>
78 __KERNEL_RCSID(0, "$NetBSD: isic_isapnp_dynalink.c,v 1.12 2009/05/12 10:07:55 cegger Exp $");
80 #include "opt_isicpnp.h"
81 #ifdef ISICPNP_DYNALINK
86 #include <sys/param.h>
87 #include <sys/kernel.h>
88 #include <sys/systm.h>
90 #include <sys/socket.h>
93 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
94 #include <sys/callout.h>
99 #include <sys/ioccom.h>
101 #include <sys/ioctl.h>
103 #include <machine/clock.h>
104 #include <i386/isa/isa_device.h>
105 #include <i386/isa/pnp.h>
106 #elif defined(__bsdi__)
107 #include <i386/isa/pnp.h>
110 #include <sys/device.h>
114 #include <machine/i4b_debug.h>
115 #include <machine/i4b_ioctl.h>
117 #include <netisdn/i4b_debug.h>
118 #include <netisdn/i4b_ioctl.h>
121 #include <netisdn/i4b_global.h>
122 #include <netisdn/i4b_l2.h>
123 #include <netisdn/i4b_l1l2.h>
124 #include <netisdn/i4b_mbuf.h>
126 #include <dev/ic/isic_l1.h>
127 #include <dev/ic/isac.h>
128 #include <dev/ic/hscx.h>
130 #if defined(__FreeBSD__) || defined(__bsdi__)
131 static void dynalink_read_fifo(void *buf
, const void *base
, size_t len
);
132 static void dynalink_write_fifo(void *base
, const void *buf
, size_t len
);
133 static void dynalink_write_reg(u_char
*base
, u_int offset
, u_int v
);
134 static u_char
dynalink_read_reg(u_char
*base
, u_int offset
);
138 extern struct isa_driver isicdriver
;
141 extern struct cfdriver isiccd
;
144 #if !defined(__FreeBSD__) && !defined(__bsdi__)
145 static void dynalink_read_fifo(struct isic_softc
*sc
, int what
, void *buf
, size_t size
);
146 static void dynalink_write_fifo(struct isic_softc
*sc
, int what
, const void *buf
, size_t size
);
147 static void dynalink_write_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
, u_int8_t data
);
148 static u_int8_t
dynalink_read_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
);
149 void isic_attach_Dyn(struct isic_softc
*sc
);
152 /* io address mapping */
158 #define ADDRMASK 0x7F
161 /* HSCX register offsets */
165 #if defined(__FreeBSD__) || defined(__bsdi__)
166 /* base address juggling */
167 #define HSCXB_HACK 0x400
168 #define IOBASE(addr) (((int)addr)&0x3FC)
169 #define IOADDR(addr) (((int)addr)&0x3FF)
170 #define IS_HSCXB_HACK(addr) ((((int)addr)&HSCXB_HACK)?HSCXB:HSCXA)
174 /* ISIC probe and attach
178 isic_probe_Dyn(struct isa_device
*dev
, unsigned int iobase2
)
181 struct isic_softc
*sc
= &l1_sc
[dev
->id_unit
];
183 if(dev
->id_unit
>= ISIC_MAXUNIT
)
185 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dynalink IS64PH.\n",
186 dev
->id_unit
, dev
->id_unit
);
189 sc
->sc_unit
= dev
->id_unit
;
191 /* check IRQ validity */
193 switch(ffs(dev
->id_irq
) - 1)
206 printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
207 dev
->id_unit
, ffs(dev
->id_irq
)-1);
211 sc
->sc_irq
= dev
->id_irq
;
213 /* check if memory addr specified */
217 printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
218 dev
->id_unit
, (u_long
)dev
->id_maddr
);
223 /* check if we got an iobase */
224 if ( (dev
->id_iobase
< 0x100) ||
225 (dev
->id_iobase
> 0x3f8) ||
226 (dev
->id_iobase
& 3) )
228 printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", dev
->id_unit
, dev
->id_iobase
);
231 sc
->sc_port
= dev
->id_iobase
;
233 /* setup access routines */
235 sc
->readreg
= dynalink_read_reg
;
236 sc
->writereg
= dynalink_write_reg
;
237 sc
->readfifo
= dynalink_read_fifo
;
238 sc
->writefifo
= dynalink_write_fifo
;
240 /* setup card type */
241 sc
->sc_cardtyp
= CARD_TYPEP_DYNALINK
;
243 /* setup IOM bus type */
244 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
247 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
249 /* setup ISAC and HSCX base addr */
250 ISAC_BASE
= (void *) sc
->sc_port
;
251 HSCX_A_BASE
= (void *) sc
->sc_port
+ 1;
252 HSCX_B_BASE
= (void *) sc
->sc_port
+ 1 + HSCXB_HACK
;
254 /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
255 if( ((HSCX_READ(0, H_VSTR
) & 0xf) != 0x5) ||
256 ((HSCX_READ(1, H_VSTR
) & 0xf) != 0x5) )
258 printf("isic%d: HSCX VSTR test failed for Dynalink\n",
260 printf("isic%d: HSC0: VSTR: %#x\n",
261 dev
->id_unit
, HSCX_READ(0, H_VSTR
));
262 printf("isic%d: HSC1: VSTR: %#x\n",
263 dev
->id_unit
, HSCX_READ(1, H_VSTR
));
271 isic_attach_Dyn(struct isa_device
*dev
, unsigned int iobase2
)
273 outb((dev
->id_iobase
)+ADDR
, RESET
);
274 DELAY(SEC_DELAY
/ 10);
275 outb((dev
->id_iobase
)+ADDR
, 0);
276 DELAY(SEC_DELAY
/ 10);
280 #elif defined(__bsdi__)
282 /* ISIC probe and attach
286 set_softc(struct isic_softc
*sc
, struct isa_attach_args
*ia
, int unit
)
291 switch(ffs(ia
->ia_irq
) - 1)
304 printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
305 unit
, ffs(ia
->ia_irq
)-1);
309 sc
->sc_irq
= ia
->ia_irq
;
311 /* check if memory addr specified */
315 printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
316 unit
, (u_long
)ia
->ia_maddr
);
320 /* check if we got an iobase */
321 if ( (ia
->ia_iobase
< 0x100) ||
322 (ia
->ia_iobase
> 0x3f8) ||
323 (ia
->ia_iobase
& 3) )
325 printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", unit
, ia
->ia_iobase
);
328 sc
->sc_port
= ia
->ia_iobase
;
330 /* setup access routines */
332 sc
->readreg
= dynalink_read_reg
;
333 sc
->writereg
= dynalink_write_reg
;
334 sc
->readfifo
= dynalink_read_fifo
;
335 sc
->writefifo
= dynalink_write_fifo
;
337 /* setup card type */
338 sc
->sc_cardtyp
= CARD_TYPEP_DYNALINK
;
340 /* setup IOM bus type */
341 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
344 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
346 /* setup ISAC and HSCX base addr */
347 ISAC_BASE
= (void *) sc
->sc_port
;
348 HSCX_A_BASE
= (void *) sc
->sc_port
+ 1;
349 HSCX_B_BASE
= (void *) sc
->sc_port
+ 1 + HSCXB_HACK
;
354 isapnp_match_dynalink(device_t parent
, cfdata_t cf
,
355 struct isa_attach_args
*ia
)
357 struct isic_softc dummysc
, *sc
= &dummysc
;
359 char *ids
[] = {"ASU1688", NULL
};
360 memset(&res
, 0, sizeof res
);
361 res
.res_irq
[0].irq_level
= ia
->ia_irq
;
362 res
.res_port
[0].prt_base
= ia
->ia_iobase
;
363 res
.res_port
[0].prt_length
= 4;
365 if (!pnp_assigndev(ids
, isiccd
.cd_name
, &res
))
368 ia
->ia_irq
= res
.res_irq
[0].irq_level
;
369 ia
->ia_iobase
= res
.res_port
[0].prt_base
;
370 ia
->ia_iosize
= res
.res_port
[0].prt_length
;
372 if (set_softc(sc
, ia
, cf
->cf_unit
) == 0)
375 /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
376 if( ((HSCX_READ(0, H_VSTR
) & 0xf) != 0x5) ||
377 ((HSCX_READ(1, H_VSTR
) & 0xf) != 0x5) )
379 printf("isic%d: HSCX VSTR test failed for Dynalink\n",
381 printf("isic%d: HSC0: VSTR: %#x\n",
382 cf
->cf_unit
, HSCX_READ(0, H_VSTR
));
383 printf("isic%d: HSC1: VSTR: %#x\n",
384 cf
->cf_unit
, HSCX_READ(1, H_VSTR
));
388 cf
->cf_flags
= FLAG_DYNALINK
;
393 isic_attach_Dyn(device_t parent
, device_t self
,
394 struct isa_attach_args
*ia
)
396 struct isic_softc
*sc
= (struct isic_softc
*)self
;
397 int unit
= sc
->sc_dev
.dv_unit
;
399 /* Commit the probed attachment values */
400 if (set_softc(sc
, ia
, unit
) == 0)
401 panic("isic_attach_Dyn: set_softc");
403 outb((ia
->ia_iobase
)+ADDR
, RESET
);
404 DELAY(SEC_DELAY
/ 10);
405 outb((ia
->ia_iobase
)+ADDR
, 0);
406 DELAY(SEC_DELAY
/ 10);
412 void isic_attach_Dyn(struct isic_softc
*sc
)
414 /* setup access routines */
416 sc
->readreg
= dynalink_read_reg
;
417 sc
->writereg
= dynalink_write_reg
;
418 sc
->readfifo
= dynalink_read_fifo
;
419 sc
->writefifo
= dynalink_write_fifo
;
421 /* setup card type */
422 sc
->sc_cardtyp
= CARD_TYPEP_DYNALINK
;
424 /* setup IOM bus type */
425 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
428 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
430 /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
431 if( ((HSCX_READ(0, H_VSTR
) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR
) & 0xf) != 0x5) )
433 printf("%s: HSCX VSTR test failed for Dynalink PnP\n",
434 device_xname(&sc
->sc_dev
));
435 printf("%s: HSC0: VSTR: %#x\n",
436 device_xname(&sc
->sc_dev
), HSCX_READ(0, H_VSTR
));
437 printf("%s: HSC1: VSTR: %#x\n",
438 device_xname(&sc
->sc_dev
), HSCX_READ(1, H_VSTR
));
442 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
, ADDR
, RESET
);
443 DELAY(SEC_DELAY
/ 10);
444 bus_space_write_1(sc
->sc_maps
[0].t
, sc
->sc_maps
[0].h
, ADDR
, 0);
445 DELAY(SEC_DELAY
/ 10);
450 /* LOW-LEVEL DEVICE ACCESS
452 NOTE: The isdn4bsd code expects the two HSCX channels at different
453 base addresses. I'm faking this, and remap them to the same address
454 in the low-level routines. Search for HSCXB_HACK and IS_HSCXB_HACK.
456 REM: this is only true for the FreeBSD version of I4B!
459 #if defined(__FreeBSD__) || defined(__bsdi__)
461 dynalink_read_fifo(void *buf
, const void *base
, size_t len
)
463 outb(IOBASE(base
)+ADDR
, 0+IS_HSCXB_HACK(base
));
464 insb(IOADDR(base
), (u_char
*)buf
, (u_int
)len
);
468 dynalink_read_fifo(struct isic_softc
*sc
, int what
, void *buf
, size_t size
)
470 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
471 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
474 bus_space_write_1(t
, h
, ADDR
, 0);
475 bus_space_read_multi_1(t
, h
, ISAC
, buf
, size
);
477 case ISIC_WHAT_HSCXA
:
478 bus_space_write_1(t
, h
, ADDR
, HSCXA
);
479 bus_space_read_multi_1(t
, h
, HSCX
, buf
, size
);
481 case ISIC_WHAT_HSCXB
:
482 bus_space_write_1(t
, h
, ADDR
, HSCXB
);
483 bus_space_read_multi_1(t
, h
, HSCX
, buf
, size
);
489 #if defined(__FreeBSD__) || defined(__bsdi__)
491 dynalink_write_fifo(void *base
, const void *buf
, size_t len
)
493 outb(IOBASE(base
)+ADDR
, 0+IS_HSCXB_HACK(base
));
494 outsb(IOADDR(base
), (u_char
*)buf
, (u_int
)len
);
497 static void dynalink_write_fifo(struct isic_softc
*sc
, int what
, const void *buf
, size_t size
)
499 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
500 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
503 bus_space_write_1(t
, h
, ADDR
, 0);
504 bus_space_write_multi_1(t
, h
, ISAC
, buf
, size
);
506 case ISIC_WHAT_HSCXA
:
507 bus_space_write_1(t
, h
, ADDR
, HSCXA
);
508 bus_space_write_multi_1(t
, h
, HSCX
, buf
, size
);
510 case ISIC_WHAT_HSCXB
:
511 bus_space_write_1(t
, h
, ADDR
, HSCXB
);
512 bus_space_write_multi_1(t
, h
, HSCX
, buf
, size
);
518 #if defined(__FreeBSD__) || defined(__bsdi__)
520 dynalink_write_reg(u_char
*base
, u_int offset
, u_int v
)
522 outb(IOBASE(base
)+ADDR
, (offset
+IS_HSCXB_HACK(base
))&ADDRMASK
);
523 outb(IOADDR(base
), (u_char
)v
);
526 static void dynalink_write_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
, u_int8_t data
)
528 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
529 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
532 bus_space_write_1(t
, h
, ADDR
, offs
);
533 bus_space_write_1(t
, h
, ISAC
, data
);
535 case ISIC_WHAT_HSCXA
:
536 bus_space_write_1(t
, h
, ADDR
, HSCXA
+offs
);
537 bus_space_write_1(t
, h
, HSCX
, data
);
539 case ISIC_WHAT_HSCXB
:
540 bus_space_write_1(t
, h
, ADDR
, HSCXB
+offs
);
541 bus_space_write_1(t
, h
, HSCX
, data
);
547 #if defined(__FreeBSD__) || defined(__bsdi__)
549 dynalink_read_reg(u_char
*base
, u_int offset
)
551 outb(IOBASE(base
)+ADDR
, (offset
+IS_HSCXB_HACK(base
))&ADDRMASK
);
552 return (inb(IOADDR(base
)));
555 static u_int8_t
dynalink_read_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
)
557 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
558 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
561 bus_space_write_1(t
, h
, ADDR
, offs
);
562 return bus_space_read_1(t
, h
, ISAC
);
563 case ISIC_WHAT_HSCXA
:
564 bus_space_write_1(t
, h
, ADDR
, HSCXA
+offs
);
565 return bus_space_read_1(t
, h
, HSCX
);
566 case ISIC_WHAT_HSCXB
:
567 bus_space_write_1(t
, h
, ADDR
, HSCXB
+offs
);
568 return bus_space_read_1(t
, h
, HSCX
);
574 #endif /* ISICPNP_DYNALINK */