No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / isa / isic_isa.c
blob155cfd297a0da6ef0a46622083466030c309d5fd
1 /*-
2 * Copyright (c) 2002 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Martin Husemann <martin@NetBSD.org>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: isic_isa.c,v 1.34 2009/05/12 08:44:19 cegger Exp $");
33 #include <sys/param.h>
34 #include <sys/errno.h>
35 #include <sys/syslog.h>
36 #include <sys/device.h>
37 #include <sys/socket.h>
38 #include <net/if.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
42 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
43 #include <sys/callout.h>
44 #endif
46 #include <sys/cpu.h>
47 #include <sys/intr.h>
48 #include <sys/bus.h>
50 #include <dev/isa/isavar.h>
52 #ifdef __FreeBSD__
53 #include <machine/i4b_ioctl.h>
54 #else
55 #include <netisdn/i4b_ioctl.h>
56 #endif
58 #include "opt_isicisa.h"
60 #include <netisdn/i4b_debug.h>
61 #include <netisdn/i4b_ioctl.h>
62 #include <netisdn/i4b_trace.h>
64 #include <netisdn/i4b_l2.h>
65 #include <netisdn/i4b_l1l2.h>
66 #include <dev/ic/isic_l1.h>
67 #include <dev/ic/ipac.h>
68 #include <dev/ic/isac.h>
69 #include <dev/ic/hscx.h>
71 #include <netisdn/i4b_mbuf.h>
72 #include <netisdn/i4b_global.h>
74 extern const struct isdn_layer1_isdnif_driver isic_std_driver;
76 /* local functions */
77 static int isic_isa_probe(device_t, cfdata_t, void *);
79 static void isic_isa_attach(device_t, device_t, void *);
80 static int setup_io_map(int flags, bus_space_tag_t iot,
81 bus_space_tag_t memt, bus_size_t iobase, bus_size_t maddr,
82 int *num_mappings, struct isic_io_map *maps, int *iosize,
83 int *msize);
84 static void args_unmap(int *num_mappings, struct isic_io_map *maps);
86 CFATTACH_DECL(isic_isa, sizeof(struct isic_softc),
87 isic_isa_probe, isic_isa_attach, NULL, NULL);
89 #define ISIC_FMT "%s: "
90 #define ISIC_PARM device_xname(&sc->sc_dev)
91 #define TERMFMT "\n"
94 * Probe card
96 static int
97 isic_isa_probe(device_t parent, cfdata_t cf, void *aux)
99 struct isa_attach_args *ia = aux;
100 bus_space_tag_t memt = ia->ia_memt, iot = ia->ia_iot;
101 int flags = cf->cf_flags;
102 struct isic_attach_args args;
103 int ret = 0, iobase, iosize, maddr, msize;
105 #if 0
106 printf("isic%d: enter isic_isa_probe\n", cf->cf_unit);
107 #endif
109 if (ia->ia_nio < 1)
110 return (0);
111 if (ia->ia_niomem < 1)
112 return (0);
113 if (ia->ia_nirq < 1)
114 return (0);
116 if (ISA_DIRECT_CONFIG(ia))
117 return (0);
119 /* check irq */
120 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) {
121 printf("isic%d: config error: no IRQ specified\n", cf->cf_unit);
122 return 0;
125 iobase = ia->ia_io[0].ir_addr;
126 iosize = ia->ia_io[0].ir_size;
128 maddr = ia->ia_iomem[0].ir_addr;
129 msize = ia->ia_iomem[0].ir_size;
131 /* setup MI attach args */
132 memset(&args, 0, sizeof(args));
133 args.ia_flags = flags;
135 /* if card type specified setup io map for that card */
136 switch(flags)
138 case FLAG_TELES_S0_8:
139 case FLAG_TELES_S0_16:
140 case FLAG_TELES_S0_163:
141 case FLAG_AVM_A1:
142 case FLAG_USR_ISDN_TA_INT:
143 case FLAG_ITK_IX1:
144 if (setup_io_map(flags, iot, memt, iobase, maddr,
145 &args.ia_num_mappings, &args.ia_maps[0],
146 &iosize, &msize)) {
147 ret = 0;
148 goto done;
150 break;
152 default:
153 /* no io map now, will figure card type later */
154 break;
157 /* probe card */
158 switch(flags)
160 #ifdef ISICISA_DYNALINK
161 #ifdef __bsdi__
162 case FLAG_DYNALINK:
163 ret = isic_probe_Dyn(&args);
164 break;
165 #endif
166 #endif
168 #ifdef ISICISA_TEL_S0_8
169 case FLAG_TELES_S0_8:
170 ret = isic_probe_s08(&args);
171 break;
172 #endif
174 #ifdef ISICISA_TEL_S0_16
175 case FLAG_TELES_S0_16:
176 ret = isic_probe_s016(&args);
177 break;
178 #endif
180 #ifdef ISICISA_TEL_S0_16_3
181 case FLAG_TELES_S0_163:
182 ret = isic_probe_s0163(&args);
183 break;
184 #endif
186 #ifdef ISICISA_AVM_A1
187 case FLAG_AVM_A1:
188 ret = isic_probe_avma1(&args);
189 break;
190 #endif
192 #ifdef ISICISA_USR_STI
193 case FLAG_USR_ISDN_TA_INT:
194 ret = isic_probe_usrtai(&args);
195 break;
196 #endif
198 #ifdef ISICISA_ITKIX1
199 case FLAG_ITK_IX1:
200 ret = isic_probe_itkix1(&args);
201 break;
202 #endif
204 default:
205 /* No card type given, try to figure ... */
206 if (iobase == ISA_UNKNOWN_PORT) {
207 ret = 0;
208 #ifdef ISICISA_TEL_S0_8
209 /* only Teles S0/8 will work without IO */
210 args.ia_flags = FLAG_TELES_S0_8;
211 if (setup_io_map(args.ia_flags, iot, memt,
212 iobase, maddr, &args.ia_num_mappings,
213 &args.ia_maps[0], &iosize, &msize) == 0)
215 ret = isic_probe_s08(&args);
217 #endif /* ISICISA_TEL_S0_8 */
218 } else if (maddr == ISA_UNKNOWN_IOMEM) {
219 ret = 0;
220 #ifdef ISICISA_TEL_S0_16_3
221 /* no shared memory, only a 16.3 based card,
222 AVM A1, the usr sportster or an ITK would work */
223 args.ia_flags = FLAG_TELES_S0_163;
224 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
225 &args.ia_num_mappings, &args.ia_maps[0],
226 &iosize, &msize) == 0)
228 ret = isic_probe_s0163(&args);
229 if (ret)
230 break;
232 #endif /* ISICISA_TEL_S0_16_3 */
233 #ifdef ISICISA_AVM_A1
234 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
235 args.ia_flags = FLAG_AVM_A1;
236 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
237 &args.ia_num_mappings, &args.ia_maps[0],
238 &iosize, &msize) == 0)
240 ret = isic_probe_avma1(&args);
241 if (ret)
242 break;
244 #endif /* ISICISA_AVM_A1 */
245 #ifdef ISICISA_USR_STI
246 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
247 args.ia_flags = FLAG_USR_ISDN_TA_INT;
248 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
249 &args.ia_num_mappings, &args.ia_maps[0],
250 &iosize, &msize) == 0)
252 ret = isic_probe_usrtai(&args);
253 if (ret)
254 break;
256 #endif /* ISICISA_USR_STI */
258 #ifdef ISICISA_ITKIX1
259 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
260 args.ia_flags = FLAG_ITK_IX1;
261 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
262 &args.ia_num_mappings, &args.ia_maps[0],
263 &iosize, &msize) == 0)
265 ret = isic_probe_itkix1(&args);
266 if (ret)
267 break;
269 #endif /* ISICISA_ITKIX1 */
271 } else {
272 #ifdef ISICISA_TEL_S0_16_3
273 /* could be anything */
274 args.ia_flags = FLAG_TELES_S0_163;
275 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
276 &args.ia_num_mappings, &args.ia_maps[0],
277 &iosize, &msize) == 0)
279 ret = isic_probe_s0163(&args);
280 if (ret)
281 break;
283 #endif /* ISICISA_TEL_S0_16_3 */
284 #ifdef ISICISA_TEL_S0_16
285 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
286 args.ia_flags = FLAG_TELES_S0_16;
287 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
288 &args.ia_num_mappings, &args.ia_maps[0],
289 &iosize, &msize) == 0)
291 ret = isic_probe_s016(&args);
292 if (ret)
293 break;
295 #endif /* ISICISA_TEL_S0_16 */
296 #ifdef ISICISA_AVM_A1
297 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
298 args.ia_flags = FLAG_AVM_A1;
299 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
300 &args.ia_num_mappings, &args.ia_maps[0],
301 &iosize, &msize) == 0)
303 ret = isic_probe_avma1(&args);
304 if (ret)
305 break;
307 #endif /* ISICISA_AVM_A1 */
308 #ifdef ISICISA_TEL_S0_8
309 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
310 args.ia_flags = FLAG_TELES_S0_8;
311 if (setup_io_map(args.ia_flags, iot, memt, iobase, maddr,
312 &args.ia_num_mappings, &args.ia_maps[0],
313 &iosize, &msize) == 0)
315 ret = isic_probe_s08(&args);
317 #endif /* ISICISA_TEL_S0_8 */
319 break;
322 done:
323 /* unmap resources */
324 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
326 #if 0
327 printf("isic%d: exit isic_isa_probe, return = %d\n", cf->cf_unit, ret);
328 #endif
330 if (ret) {
331 if (iosize != 0) {
332 ia->ia_nio = 1;
333 ia->ia_io[0].ir_addr = iobase;
334 ia->ia_io[0].ir_size = iosize;
335 } else
336 ia->ia_nio = 0;
337 if (msize != 0) {
338 ia->ia_niomem = 1;
339 ia->ia_iomem[0].ir_addr = maddr;
340 ia->ia_iomem[0].ir_size = msize;
341 } else
342 ia->ia_niomem = 0;
343 ia->ia_nirq = 1;
345 ia->ia_ndrq = 0;
348 return ret;
351 static int
352 isicattach(int flags, struct isic_softc *sc)
354 int ret = 0;
355 const char *drvid;
357 #ifdef __FreeBSD__
359 struct isic_softc *sc = &l1_sc[dev->id_unit];
360 #define PARM dev
361 #define PARM2 dev, iobase2
362 #define FLAGS dev->id_flags
364 #elif defined(__bsdi__)
366 struct isic_softc *sc = (struct isic_softc *)self;
367 #define PARM parent, self, ia
368 #define PARM2 parent, self, ia
369 #define FLAGS sc->sc_flags
371 #else
373 #define PARM sc
374 #define PARM2 sc
375 #define FLAGS flags
377 #endif /* __FreeBSD__ */
379 static const char *ISACversion[] = {
380 "2085 Version A1/A2 or 2086/2186 Version 1.1",
381 "2085 Version B1",
382 "2085 Version B2",
383 "2085 Version V2.3 (B3)",
384 "Unknown Version"
387 static const char *HSCXversion[] = {
388 "82525 Version A1",
389 "Unknown (0x01)",
390 "82525 Version A2",
391 "Unknown (0x03)",
392 "82525 Version A3",
393 "82525 or 21525 Version 2.1",
394 "Unknown Version"
397 /* card dependent setup */
398 switch(FLAGS)
400 #ifdef ISICISA_DYNALINK
401 #if defined(__bsdi__) || defined(__FreeBSD__)
402 case FLAG_DYNALINK:
403 ret = isic_attach_Dyn(PARM2);
404 break;
405 #endif
406 #endif
408 #ifdef ISICISA_TEL_S0_8
409 case FLAG_TELES_S0_8:
410 ret = isic_attach_s08(PARM);
411 break;
412 #endif
414 #ifdef ISICISA_TEL_S0_16
415 case FLAG_TELES_S0_16:
416 ret = isic_attach_s016(PARM);
417 break;
418 #endif
420 #ifdef ISICISA_TEL_S0_16_3
421 case FLAG_TELES_S0_163:
422 ret = isic_attach_s0163(PARM);
423 break;
424 #endif
426 #ifdef ISICISA_AVM_A1
427 case FLAG_AVM_A1:
428 ret = isic_attach_avma1(PARM);
429 break;
430 #endif
432 #ifdef ISICISA_USR_STI
433 case FLAG_USR_ISDN_TA_INT:
434 ret = isic_attach_usrtai(PARM);
435 break;
436 #endif
438 #ifdef ISICISA_ITKIX1
439 case FLAG_ITK_IX1:
440 ret = isic_attach_itkix1(PARM);
441 break;
442 #endif
444 #ifdef ISICISA_ELSA_PCC16
445 case FLAG_ELSA_PCC16:
446 ret = isic_attach_Eqs1pi(dev, 0);
447 break;
448 #endif
450 #ifdef amiga
451 case FLAG_BLMASTER:
452 ret = 1; /* full detection was done in caller */
453 break;
454 #endif
456 /* ======================================================================
457 * Only P&P cards follow below!!!
460 #ifdef __FreeBSD__ /* we've already splitted all non-ISA stuff
461 out of this ISA specific part for the other
462 OS */
464 #ifdef AVM_A1_PCMCIA
465 case FLAG_AVM_A1_PCMCIA:
466 ret = isic_attach_fritzpcmcia(PARM);
467 break;
468 #endif
470 #ifdef TEL_S0_16_3_P
471 case FLAG_TELES_S0_163_PnP:
472 ret = isic_attach_s0163P(PARM2);
473 break;
474 #endif
476 #ifdef CRTX_S0_P
477 case FLAG_CREATIX_S0_PnP:
478 ret = isic_attach_Cs0P(PARM2);
479 break;
480 #endif
482 #ifdef DRN_NGO
483 case FLAG_DRN_NGO:
484 ret = isic_attach_drnngo(PARM2);
485 break;
486 #endif
488 #ifdef SEDLBAUER
489 case FLAG_SWS:
490 ret = isic_attach_sws(PARM);
491 break;
492 #endif
494 #ifdef ELSA_QS1ISA
495 case FLAG_ELSA_QS1P_ISA:
496 ret = isic_attach_Eqs1pi(PARM2);
497 break;
498 #endif
500 #ifdef AVM_PNP
501 case FLAG_AVM_PNP:
502 ret = isic_attach_avm_pnp(PARM2);
503 ret = 0;
504 break;
505 #endif
507 #ifdef SIEMENS_ISURF2
508 case FLAG_SIEMENS_ISURF2:
509 ret = isic_attach_siemens_isurf(PARM2);
510 break;
511 #endif
513 #ifdef ASUSCOM_IPAC
514 case FLAG_ASUSCOM_IPAC:
515 ret = isic_attach_asi(PARM2);
516 break;
517 #endif
519 #endif /* __FreeBSD__ / P&P specific part */
521 default:
522 break;
525 if(ret == 0)
526 return(0);
528 if(sc->sc_ipac)
530 sc->sc_ipac_version = IPAC_READ(IPAC_ID);
532 switch(sc->sc_ipac_version)
534 case IPAC_V11:
535 case IPAC_V12:
536 break;
538 default:
539 aprint_error_dev(&sc->sc_dev, "Error, IPAC version %d unknown!\n", ret);
540 return(0);
541 break;
544 else
546 sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
548 switch(sc->sc_isac_version)
550 case ISAC_VA:
551 case ISAC_VB1:
552 case ISAC_VB2:
553 case ISAC_VB3:
554 break;
556 default:
557 printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
558 ISIC_PARM, sc->sc_isac_version);
559 return(0);
560 break;
563 sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
565 switch(sc->sc_hscx_version)
567 case HSCX_VA1:
568 case HSCX_VA2:
569 case HSCX_VA3:
570 case HSCX_V21:
571 break;
573 default:
574 printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
575 ISIC_PARM, sc->sc_hscx_version);
576 return(0);
577 break;
581 sc->sc_intr_valid = ISIC_INTR_DISABLED;
583 /* HSCX setup */
585 isic_bchannel_setup(sc, HSCX_CH_A, BPROT_NONE, 0);
587 isic_bchannel_setup(sc, HSCX_CH_B, BPROT_NONE, 0);
589 /* setup linktab */
591 isic_init_linktab(sc);
593 /* set trace level */
595 sc->sc_trace = TRACE_OFF;
597 sc->sc_state = ISAC_IDLE;
599 sc->sc_ibuf = NULL;
600 sc->sc_ib = NULL;
601 sc->sc_ilen = 0;
603 sc->sc_obuf = NULL;
604 sc->sc_op = NULL;
605 sc->sc_ol = 0;
606 sc->sc_freeflag = 0;
608 sc->sc_obuf2 = NULL;
609 sc->sc_freeflag2 = 0;
611 #if defined(__FreeBSD__) && __FreeBSD__ >=3
612 callout_handle_init(&sc->sc_T3_callout);
613 callout_handle_init(&sc->sc_T4_callout);
614 #endif
616 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
617 callout_init(&sc->sc_T3_callout, 0);
618 callout_init(&sc->sc_T4_callout, 0);
619 #endif
621 /* announce manufacturer and card type */
623 switch(FLAGS)
625 case FLAG_TELES_S0_8:
626 drvid = "Teles S0/8 or Niccy 1008";
627 break;
629 case FLAG_TELES_S0_16:
630 drvid = "Teles S0/16, Creatix ISDN S0-16 or Niccy 1016";
631 break;
633 case FLAG_TELES_S0_163:
634 drvid = "Teles S0/16.3";
635 break;
637 case FLAG_AVM_A1:
638 drvid = "AVM A1 or AVM Fritz!Card";
639 break;
641 case FLAG_AVM_A1_PCMCIA:
642 drvid = "AVM PCMCIA Fritz!Card";
643 break;
645 case FLAG_TELES_S0_163_PnP:
646 drvid = "Teles S0/PnP";
647 break;
649 case FLAG_CREATIX_S0_PnP:
650 drvid = "Creatix ISDN S0-16 P&P";
651 break;
653 case FLAG_USR_ISDN_TA_INT:
654 drvid = "USRobotics Sportster ISDN TA intern";
655 break;
657 case FLAG_DRN_NGO:
658 drvid = "Dr. Neuhaus NICCY Go@";
659 break;
661 case FLAG_DYNALINK:
662 drvid = "Dynalink IS64PH";
663 break;
665 case FLAG_SWS:
666 drvid = "Sedlbauer WinSpeed";
667 break;
669 case FLAG_BLMASTER:
670 /* board announcement was done by caller */
671 drvid = (char *)0;
672 break;
674 case FLAG_ELSA_QS1P_ISA:
675 drvid = "ELSA QuickStep 1000pro (ISA)";
676 break;
678 case FLAG_ITK_IX1:
679 drvid = "ITK ix1 micro";
680 break;
682 case FLAG_ELSA_PCC16:
683 drvid = "ELSA PCC-16";
684 break;
686 case FLAG_ASUSCOM_IPAC:
687 drvid = "Asuscom ISDNlink 128K PnP";
688 break;
690 case FLAG_SIEMENS_ISURF2:
691 drvid = "Siemens I-Surf 2.0";
692 break;
694 default:
695 drvid = "ERROR, unknown flag used";
696 break;
698 #ifndef __FreeBSD__
699 printf("\n");
700 #endif
701 if (drvid)
702 printf(ISIC_FMT "%s\n", ISIC_PARM, drvid);
704 /* announce chip versions */
706 if(sc->sc_ipac)
708 if(sc->sc_ipac_version == IPAC_V11)
709 printf(ISIC_FMT "IPAC PSB2115 Version 1.1\n", ISIC_PARM);
710 else
711 printf(ISIC_FMT "IPAC PSB2115 Version 1.2\n", ISIC_PARM);
713 else
715 if(sc->sc_isac_version >= ISAC_UNKN)
717 printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
718 ISIC_PARM,
719 sc->sc_isac_version);
720 sc->sc_isac_version = ISAC_UNKN;
722 else
724 printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
725 ISIC_PARM,
726 ISACversion[sc->sc_isac_version],
727 sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
730 #ifdef __FreeBSD__
731 printf("(Addr=0x%lx)\n", (u_long)ISAC_BASE);
732 #endif
734 if(sc->sc_hscx_version >= HSCX_UNKN)
736 printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
737 ISIC_PARM,
738 sc->sc_hscx_version);
739 sc->sc_hscx_version = HSCX_UNKN;
741 else
743 printf(ISIC_FMT "HSCX %s" TERMFMT,
744 ISIC_PARM,
745 HSCXversion[sc->sc_hscx_version]);
748 #ifdef __FreeBSD__
749 printf("(AddrA=0x%lx, AddrB=0x%lx)\n", (u_long)HSCX_A_BASE, (u_long)HSCX_B_BASE);
751 #endif /* __FreeBSD__ */
754 #ifdef __FreeBSD__
755 next_isic_unit++;
757 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300003
759 /* set the interrupt handler - no need to change isa_device.h */
760 dev->id_intr = (inthand2_t *)isicintr;
762 #endif
764 #endif /* __FreeBSD__ */
766 /* init higher protocol layers */
767 isic_attach_bri(sc, drvid, &isic_std_driver);
769 return(1);
770 #undef PARM
771 #undef FLAGS
775 * Attach the card
777 static void
778 isic_isa_attach(device_t parent, device_t self, void *aux)
780 struct isic_softc *sc = (void *)self;
781 struct isa_attach_args *ia = aux;
782 int flags = device_cfdata(&sc->sc_dev)->cf_flags;
783 int ret = 0, iobase, iosize, maddr, msize;
784 struct isic_attach_args args;
786 if (ia->ia_nio > 0) {
787 iobase = ia->ia_io[0].ir_addr;
788 iosize = ia->ia_io[0].ir_size;
789 } else {
790 iobase = ISA_UNKNOWN_PORT;
791 iosize = 0;
793 if (ia->ia_niomem > 0) {
794 maddr = ia->ia_iomem[0].ir_addr;
795 msize = ia->ia_iomem[0].ir_size;
796 } else {
797 maddr = ISA_UNKNOWN_IOMEM;
798 msize = 0;
801 /* Setup parameters */
802 sc->sc_irq = ia->ia_irq[0].ir_irq;
803 sc->sc_maddr = maddr;
804 sc->sc_num_mappings = 0;
805 sc->sc_maps = NULL;
806 switch(flags)
808 case FLAG_TELES_S0_8:
809 case FLAG_TELES_S0_16:
810 case FLAG_TELES_S0_163:
811 case FLAG_AVM_A1:
812 case FLAG_USR_ISDN_TA_INT:
813 setup_io_map(flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
814 &(sc->sc_num_mappings), NULL, NULL, NULL);
815 MALLOC_MAPS(sc);
816 setup_io_map(flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
817 &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
818 break;
820 default:
821 /* No card type given, try to figure ... */
823 /* setup MI attach args */
824 memset(&args, 0, sizeof(args));
825 args.ia_flags = flags;
827 /* Probe cards */
828 if (iobase == ISA_UNKNOWN_PORT) {
829 ret = 0;
830 #ifdef ISICISA_TEL_S0_8
831 /* only Teles S0/8 will work without IO */
832 args.ia_flags = FLAG_TELES_S0_8;
833 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
834 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
835 ret = isic_probe_s08(&args);
836 if (ret)
837 goto found;
838 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
839 #endif /* ISICISA_TEL_S0_8 */
840 } else if (maddr == ISA_UNKNOWN_IOMEM) {
841 /* no shared memory, only a 16.3 based card,
842 AVM A1, the usr sportster or an ITK would work */
843 ret = 0;
844 #ifdef ISICISA_TEL_S0_16_3
845 args.ia_flags = FLAG_TELES_S0_163;
846 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
847 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
848 ret = isic_probe_s0163(&args);
849 if (ret)
850 goto found;
851 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
852 #endif /* ISICISA_TEL_S0_16_3 */
853 #ifdef ISICISA_AVM_A1
854 args.ia_flags = FLAG_AVM_A1;
855 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
856 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
857 ret = isic_probe_avma1(&args);
858 if (ret)
859 goto found;
860 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
861 #endif /* ISICISA_AVM_A1 */
862 #ifdef ISICISA_USR_STI
863 args.ia_flags = FLAG_USR_ISDN_TA_INT;
864 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
865 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
866 ret = isic_probe_usrtai(&args);
867 if (ret)
868 goto found;
869 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
870 #endif /* ISICISA_USR_STI */
871 #ifdef ISICISA_ITKIX1
872 args.ia_flags = FLAG_ITK_IX1;
873 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
874 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
875 ret = isic_probe_itkix1(&args);
876 if (ret)
877 goto found;
878 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
879 #endif /* ISICISA_ITKIX1 */
880 } else {
881 /* could be anything */
882 ret = 0;
883 #ifdef ISICISA_TEL_S0_16_3
884 args.ia_flags = FLAG_TELES_S0_163;
885 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
886 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
887 ret = isic_probe_s0163(&args);
888 if (ret)
889 goto found;
890 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
891 #endif /* ISICISA_TEL_S0_16_3 */
892 #ifdef ISICISA_TEL_S0_16
893 args.ia_flags = FLAG_TELES_S0_16;
894 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
895 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
896 ret = isic_probe_s016(&args);
897 if (ret)
898 goto found;
899 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
900 #endif /* ISICISA_TEL_S0_16 */
901 #ifdef ISICISA_AVM_A1
902 args.ia_flags = FLAG_AVM_A1;
903 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
904 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
905 ret = isic_probe_avma1(&args);
906 if (ret)
907 goto found;
908 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
909 #endif /* ISICISA_AVM_A1 */
910 #ifdef ISICISA_TEL_S0_8
911 args.ia_flags = FLAG_TELES_S0_8;
912 setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
913 &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
914 ret = isic_probe_s08(&args);
915 if (ret)
916 goto found;
917 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
918 #endif /* ISICISA_TEL_S0_8 */
920 break;
922 found:
923 flags = args.ia_flags;
924 sc->sc_num_mappings = args.ia_num_mappings;
925 args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
926 if (ret) {
927 MALLOC_MAPS(sc);
928 setup_io_map(flags, ia->ia_iot, ia->ia_memt, iobase, maddr,
929 &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
930 } else {
931 printf(": could not determine card type - not configured!\n");
932 return;
934 break;
937 /* MI initialization of card */
938 isicattach(flags, sc);
941 * Try to get a level-triggered interrupt first. If that doesn't
942 * work (like on NetBSD/Atari, try to establish an edge triggered
943 * interrupt.
945 if (isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, IST_LEVEL,
946 IPL_NET, isicintr, sc) == NULL) {
947 if(isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, IST_EDGE,
948 IPL_NET, isicintr, sc) == NULL) {
949 args_unmap(&(sc->sc_num_mappings), &(sc->sc_maps[0]));
950 free((sc)->sc_maps, M_DEVBUF);
952 else {
954 * XXX: This is a hack that probably needs to be
955 * solved by setting an interrupt type in the sc
956 * structure. I don't feel familiar enough with the
957 * code to do this currently. Feel free to contact
958 * me about it (leo@NetBSD.org).
960 isicintr(sc);
966 * Setup card specific io mapping. Return 0 on success,
967 * any other value on config error.
968 * Be prepared to get NULL as maps array.
969 * Make sure to keep *num_mappings in sync with the real
970 * mappings already setup when returning!
972 static int
973 setup_io_map(int flags, bus_space_tag_t iot, bus_space_tag_t memt, bus_size_t iobase, bus_size_t maddr, int *num_mappings, struct isic_io_map *maps, int *iosize, int *msize)
975 /* nothing mapped yet */
976 *num_mappings = 0;
978 /* which resources do we need? */
979 switch(flags)
981 case FLAG_TELES_S0_8:
982 if (maddr == ISA_UNKNOWN_IOMEM) {
983 printf("isic: config error: no shared memory specified for Teles S0/8!\n");
984 return 1;
986 if (iosize) *iosize = 0; /* no i/o ports */
987 if (msize) *msize = 0x1000; /* shared memory size */
989 /* this card uses a single memory mapping */
990 if (maps == NULL) {
991 *num_mappings = 1;
992 return 0;
994 *num_mappings = 0;
995 maps[0].t = memt;
996 maps[0].offset = 0;
997 maps[0].size = 0x1000;
998 if (bus_space_map(maps[0].t, maddr,
999 maps[0].size, 0, &maps[0].h)) {
1000 return 1;
1002 (*num_mappings)++;
1003 break;
1005 case FLAG_TELES_S0_16:
1006 if (iobase == ISA_UNKNOWN_PORT) {
1007 printf("isic: config error: no i/o address specified for Teles S0/16!\n");
1008 return 1;
1010 if (maddr == ISA_UNKNOWN_IOMEM) {
1011 printf("isic: config error: no shared memory specified for Teles S0/16!\n");
1012 return 1;
1014 if (iosize) *iosize = 8; /* i/o ports */
1015 if (msize) *msize = 0x1000; /* shared memory size */
1017 /* one io and one memory mapping */
1018 if (maps == NULL) {
1019 *num_mappings = 2;
1020 return 0;
1022 *num_mappings = 0;
1023 maps[0].t = iot;
1024 maps[0].offset = 0;
1025 maps[0].size = 8;
1026 if (bus_space_map(maps[0].t, iobase,
1027 maps[0].size, 0, &maps[0].h)) {
1028 return 1;
1030 (*num_mappings)++;
1031 maps[1].t = memt;
1032 maps[1].offset = 0;
1033 maps[1].size = 0x1000;
1034 if (bus_space_map(maps[1].t, maddr,
1035 maps[1].size, 0, &maps[1].h)) {
1036 return 1;
1038 (*num_mappings)++;
1039 break;
1041 case FLAG_TELES_S0_163:
1042 if (iobase == ISA_UNKNOWN_PORT) {
1043 printf("isic: config error: no i/o address specified for Teles S0/16!\n");
1044 return 1;
1046 if (iosize) *iosize = 8; /* only some i/o ports shown */
1047 if (msize) *msize = 0; /* no shared memory */
1049 /* Four io mappings: config, isac, 2 * hscx */
1050 if (maps == NULL) {
1051 *num_mappings = 4;
1052 return 0;
1054 *num_mappings = 0;
1055 maps[0].t = iot;
1056 maps[0].offset = 0;
1057 maps[0].size = 8;
1058 if (bus_space_map(maps[0].t, iobase,
1059 maps[0].size, 0, &maps[0].h)) {
1060 return 1;
1062 (*num_mappings)++;
1063 maps[1].t = iot;
1064 maps[1].offset = 0;
1065 maps[1].size = 0x40; /* XXX - ??? */
1066 if ((iobase - 0xd80 + 0x980) > 0x0ffff)
1067 return 1;
1068 if (bus_space_map(maps[1].t, iobase - 0xd80 + 0x980,
1069 maps[1].size, 0, &maps[1].h)) {
1070 return 1;
1072 (*num_mappings)++;
1073 maps[2].t = iot;
1074 maps[2].offset = 0;
1075 maps[2].size = 0x40; /* XXX - ??? */
1076 if ((iobase - 0xd80 + 0x180) > 0x0ffff)
1077 return 1;
1078 if (bus_space_map(maps[2].t, iobase - 0xd80 + 0x180,
1079 maps[2].size, 0, &maps[2].h)) {
1080 return 1;
1082 (*num_mappings)++;
1083 maps[3].t = iot;
1084 maps[3].offset = 0;
1085 maps[3].size = 0x40; /* XXX - ??? */
1086 if ((iobase - 0xd80 + 0x580) > 0x0ffff)
1087 return 1;
1088 if (bus_space_map(maps[3].t, iobase - 0xd80 + 0x580,
1089 maps[3].size, 0, &maps[3].h)) {
1090 return 1;
1092 (*num_mappings)++;
1093 break;
1095 case FLAG_AVM_A1:
1096 if (iobase == ISA_UNKNOWN_PORT) {
1097 printf("isic: config error: no i/o address specified for AVM A1/Fritz! card!\n");
1098 return 1;
1100 if (iosize) *iosize = 8; /* only some i/o ports shown */
1101 if (msize) *msize = 0; /* no shared memory */
1103 /* Seven io mappings: config, isac, 2 * hscx,
1104 isac-fifo, 2 * hscx-fifo */
1105 if (maps == NULL) {
1106 *num_mappings = 7;
1107 return 0;
1109 *num_mappings = 0;
1110 maps[0].t = iot; /* config */
1111 maps[0].offset = 0;
1112 maps[0].size = 8;
1113 if ((iobase + 0x1800) > 0x0ffff)
1114 return 1;
1115 if (bus_space_map(maps[0].t, iobase + 0x1800, maps[0].size, 0, &maps[0].h))
1116 return 1;
1117 (*num_mappings)++;
1118 maps[1].t = iot; /* isac */
1119 maps[1].offset = 0;
1120 maps[1].size = 0x80; /* XXX - ??? */
1121 if ((iobase + 0x1400 - 0x20) > 0x0ffff)
1122 return 1;
1123 if (bus_space_map(maps[1].t, iobase + 0x1400 - 0x20, maps[1].size, 0, &maps[1].h))
1124 return 1;
1125 (*num_mappings)++;
1126 maps[2].t = iot; /* hscx 0 */
1127 maps[2].offset = 0;
1128 maps[2].size = 0x40; /* XXX - ??? */
1129 if ((iobase + 0x400 - 0x20) > 0x0ffff)
1130 return 1;
1131 if (bus_space_map(maps[2].t, iobase + 0x400 - 0x20, maps[2].size, 0, &maps[2].h))
1132 return 1;
1133 (*num_mappings)++;
1134 maps[3].t = iot; /* hscx 1 */
1135 maps[3].offset = 0;
1136 maps[3].size = 0x40; /* XXX - ??? */
1137 if ((iobase + 0xc00 - 0x20) > 0x0ffff)
1138 return 1;
1139 if (bus_space_map(maps[3].t, iobase + 0xc00 - 0x20, maps[3].size, 0, &maps[3].h))
1140 return 1;
1141 (*num_mappings)++;
1142 maps[4].t = iot; /* isac-fifo */
1143 maps[4].offset = 0;
1144 maps[4].size = 1;
1145 if ((iobase + 0x1400 - 0x20 -0x3e0) > 0x0ffff)
1146 return 1;
1147 if (bus_space_map(maps[4].t, iobase + 0x1400 - 0x20 -0x3e0, maps[4].size, 0, &maps[4].h))
1148 return 1;
1149 (*num_mappings)++;
1150 maps[5].t = iot; /* hscx 0 fifo */
1151 maps[5].offset = 0;
1152 maps[5].size = 1;
1153 if ((iobase + 0x400 - 0x20 -0x3e0) > 0x0ffff)
1154 return 1;
1155 if (bus_space_map(maps[5].t, iobase + 0x400 - 0x20 -0x3e0, maps[5].size, 0, &maps[5].h))
1156 return 1;
1157 (*num_mappings)++;
1158 maps[6].t = iot; /* hscx 1 fifo */
1159 maps[6].offset = 0;
1160 maps[6].size = 1;
1161 if ((iobase + 0xc00 - 0x20 -0x3e0) > 0x0ffff)
1162 return 1;
1163 if (bus_space_map(maps[6].t, iobase + 0xc00 - 0x20 -0x3e0, maps[6].size, 0, &maps[6].h))
1164 return 1;
1165 (*num_mappings)++;
1166 break;
1168 case FLAG_USR_ISDN_TA_INT:
1169 if (iobase == ISA_UNKNOWN_PORT) {
1170 printf("isic: config error: no I/O base specified for USR Sportster TA intern!\n");
1171 return 1;
1173 if (iosize) *iosize = 8; /* scattered ports, only some shown */
1174 if (msize) *msize = 0; /* no shared memory */
1176 /* 49 io mappings: 1 config and 48x8 registers */
1177 if (maps == NULL) {
1178 *num_mappings = 49;
1179 return 0;
1181 *num_mappings = 0;
1183 int i, num;
1184 bus_size_t base;
1186 /* config at offset 0x8000 */
1187 base = iobase + 0x8000;
1188 maps[0].size = 1;
1189 maps[0].t = iot;
1190 maps[0].offset = 0;
1191 if (base > 0x0ffff)
1192 return 1;
1193 if (bus_space_map(iot, base, 1, 0, &maps[0].h)) {
1194 return 1;
1196 *num_mappings = num = 1;
1198 /* HSCX A at offset 0 */
1199 base = iobase;
1200 for (i = 0; i < 16; i++) {
1201 maps[num].size = 8;
1202 maps[num].offset = 0;
1203 maps[num].t = iot;
1204 if (base+i*1024+8 > 0x0ffff)
1205 return 1;
1206 if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
1207 return 1;
1209 *num_mappings = ++num;
1211 /* HSCX B at offset 0x4000 */
1212 base = iobase + 0x4000;
1213 for (i = 0; i < 16; i++) {
1214 maps[num].size = 8;
1215 maps[num].offset = 0;
1216 maps[num].t = iot;
1217 if (base+i*1024+8 > 0x0ffff)
1218 return 1;
1219 if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
1220 return 1;
1222 *num_mappings = ++num;
1224 /* ISAC at offset 0xc000 */
1225 base = iobase + 0xc000;
1226 for (i = 0; i < 16; i++) {
1227 maps[num].size = 8;
1228 maps[num].offset = 0;
1229 maps[num].t = iot;
1230 if (base+i*1024+8 > 0x0ffff)
1231 return 1;
1232 if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
1233 return 1;
1235 *num_mappings = ++num;
1238 break;
1240 case FLAG_ITK_IX1:
1241 if (iobase == ISA_UNKNOWN_PORT) {
1242 printf("isic: config error: no I/O base specified for ITK ix1 micro!\n");
1243 return 1;
1245 if (iosize) *iosize = 4;
1246 if (msize) *msize = 0;
1247 if (maps == NULL) {
1248 *num_mappings = 1;
1249 return 0;
1251 *num_mappings = 0;
1252 maps[0].size = 4;
1253 maps[0].t = iot;
1254 maps[0].offset = 0;
1255 if (bus_space_map(iot, iobase, 4, 0, &maps[0].h)) {
1256 return 1;
1258 *num_mappings = 1;
1259 break;
1261 default:
1262 printf("isic: config error: flags do not specify any known card!\n");
1263 return 1;
1264 break;
1267 return 0;
1270 static void
1271 args_unmap(int *num_mappings, struct isic_io_map *maps)
1273 int i, n;
1274 for (i = 0, n = *num_mappings; i < n; i++)
1275 if (maps[i].size)
1276 bus_space_unmap(maps[i].t, maps[i].h, maps[i].size);
1277 *num_mappings = 0;