Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / isapnp / isic_isapnp_dynalink.c
bloba775c635d4d66e40c1fd958e5b11a65d45f66ee9
1 /*
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
6 * are met:
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
29 * SUCH DAMAGE.
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
44 * -hm FreeBSD PnP
45 * -mp 17 dec 1998 made it compile again
47 *---------------------------------------------------------------------------*/
49 /* NOTES:
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
57 chips:
58 Siemens PSB 21525N, HSCX TE V2.1
59 Siemens PSB 2186N, ISAC-S TE V1.1
60 95MS14, PNP
62 plug-and-play info:
63 device id "ASU1688"
64 vendor id 0x88167506
65 serial 0x00000044
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
83 /* HEADERS
86 #include <sys/param.h>
87 #include <sys/kernel.h>
88 #include <sys/systm.h>
89 #include <sys/mbuf.h>
90 #include <sys/socket.h>
91 #include <net/if.h>
93 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
94 #include <sys/callout.h>
95 #endif
97 #ifdef __FreeBSD__
98 #if __FreeBSD__ >= 3
99 #include <sys/ioccom.h>
100 #else
101 #include <sys/ioctl.h>
102 #endif
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>
108 #else
109 #include <sys/bus.h>
110 #include <sys/device.h>
111 #endif
113 #ifdef __FreeBSD__
114 #include <machine/i4b_debug.h>
115 #include <machine/i4b_ioctl.h>
116 #else
117 #include <netisdn/i4b_debug.h>
118 #include <netisdn/i4b_ioctl.h>
119 #endif
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);
135 #endif
137 #ifdef __FreeBSD__
138 extern struct isa_driver isicdriver;
139 #endif
140 #ifdef __bsdi__
141 extern struct cfdriver isiccd;
142 #endif
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);
150 #endif
152 /* io address mapping */
153 #define ISAC 0
154 #define HSCX 1
155 #define ADDR 2
157 /* ADDR bits */
158 #define ADDRMASK 0x7F
159 #define RESET 0x80
161 /* HSCX register offsets */
162 #define HSCXA 0x00
163 #define HSCXB 0x40
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)
171 #endif
173 #ifdef __FreeBSD__
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);
187 return(0);
189 sc->sc_unit = dev->id_unit;
191 /* check IRQ validity */
193 switch(ffs(dev->id_irq) - 1)
195 case 3:
196 case 4:
197 case 5:
198 case 9:
199 case 10:
200 case 11:
201 case 12:
202 case 15:
203 break;
205 default:
206 printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
207 dev->id_unit, ffs(dev->id_irq)-1);
208 return(0);
209 break;
211 sc->sc_irq = dev->id_irq;
213 /* check if memory addr specified */
215 if(dev->id_maddr)
217 printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
218 dev->id_unit, (u_long)dev->id_maddr);
219 return (0);
221 dev->id_msize = 0;
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);
229 return(0);
231 sc->sc_port = dev->id_iobase;
233 /* setup access routines */
234 sc->clearirq = NULL;
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;
246 sc->sc_ipac = 0;
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",
259 dev->id_unit);
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));
264 return (0);
267 return (1);
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);
277 return(1);
280 #elif defined(__bsdi__)
282 /* ISIC probe and attach
285 static int
286 set_softc(struct isic_softc *sc, struct isa_attach_args *ia, int unit)
288 if (unit >= NISIC)
289 return 0;
290 sc->sc_unit = unit;
291 switch(ffs(ia->ia_irq) - 1)
293 case 3:
294 case 4:
295 case 5:
296 case 9:
297 case 10:
298 case 11:
299 case 12:
300 case 15:
301 break;
303 default:
304 printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
305 unit, ffs(ia->ia_irq)-1);
306 return(0);
307 break;
309 sc->sc_irq = ia->ia_irq;
311 /* check if memory addr specified */
313 if(ia->ia_maddr)
315 printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
316 unit, (u_long)ia->ia_maddr);
317 return (0);
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);
326 return(0);
328 sc->sc_port = ia->ia_iobase;
330 /* setup access routines */
331 sc->clearirq = NULL;
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;
343 sc->sc_ipac = 0;
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;
350 return 1;
354 isapnp_match_dynalink(device_t parent, cfdata_t cf,
355 struct isa_attach_args *ia)
357 struct isic_softc dummysc, *sc = &dummysc;
358 pnp_resource_t res;
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))
366 return (0);
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)
373 return 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",
380 cf->cf_unit);
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));
385 return (0);
388 cf->cf_flags = FLAG_DYNALINK;
389 return (1);
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);
407 return(1);
410 #else
412 void isic_attach_Dyn(struct isic_softc *sc)
414 /* setup access routines */
415 sc->clearirq = NULL;
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;
427 sc->sc_ipac = 0;
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));
439 return;
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);
448 #endif
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__)
460 static void
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);
466 #else
467 static void
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;
472 switch (what) {
473 case ISIC_WHAT_ISAC:
474 bus_space_write_1(t, h, ADDR, 0);
475 bus_space_read_multi_1(t, h, ISAC, buf, size);
476 break;
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);
480 break;
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);
484 break;
487 #endif
489 #if defined(__FreeBSD__) || defined(__bsdi__)
490 static void
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);
496 #else
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;
501 switch (what) {
502 case ISIC_WHAT_ISAC:
503 bus_space_write_1(t, h, ADDR, 0);
504 bus_space_write_multi_1(t, h, ISAC, buf, size);
505 break;
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);
509 break;
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);
513 break;
516 #endif
518 #if defined(__FreeBSD__) || defined(__bsdi__)
519 static void
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);
525 #else
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;
530 switch (what) {
531 case ISIC_WHAT_ISAC:
532 bus_space_write_1(t, h, ADDR, offs);
533 bus_space_write_1(t, h, ISAC, data);
534 break;
535 case ISIC_WHAT_HSCXA:
536 bus_space_write_1(t, h, ADDR, HSCXA+offs);
537 bus_space_write_1(t, h, HSCX, data);
538 break;
539 case ISIC_WHAT_HSCXB:
540 bus_space_write_1(t, h, ADDR, HSCXB+offs);
541 bus_space_write_1(t, h, HSCX, data);
542 break;
545 #endif
547 #if defined(__FreeBSD__) || defined(__bsdi__)
548 static u_char
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)));
554 #else
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;
559 switch (what) {
560 case ISIC_WHAT_ISAC:
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);
570 return 0;
572 #endif
574 #endif /* ISICPNP_DYNALINK */