Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pcmcia / isic_pcmcia.c
blob72694ca7a2025e305bbbb89949b7df274849493d
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_pcmcia.c,v 1.39 2009/05/12 14:42:18 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/pcmcia/pcmciareg.h>
51 #include <dev/pcmcia/pcmciavar.h>
52 #include <dev/pcmcia/pcmciadevs.h>
54 #ifdef __FreeBSD__
55 #include <machine/i4b_ioctl.h>
56 #include <machine/i4b_trace.h>
57 #else
58 #include <netisdn/i4b_ioctl.h>
59 #include <netisdn/i4b_trace.h>
60 #include <netisdn/i4b_debug.h>
61 #include <netisdn/i4b_l2.h>
62 #include <netisdn/i4b_l1l2.h>
63 #endif
65 #include <dev/ic/isic_l1.h>
66 #include <dev/ic/ipac.h>
67 #include <dev/ic/isac.h>
68 #include <dev/ic/hscx.h>
70 #include <netisdn/i4b_l1l2.h>
71 #include <netisdn/i4b_global.h>
73 #include <dev/pcmcia/isic_pcmcia.h>
75 #include "opt_isicpcmcia.h"
77 extern const struct isdn_layer1_isdnif_driver isic_std_driver;
79 static int isic_pcmcia_match(device_t, cfdata_t, void *);
80 static void isic_pcmcia_attach(device_t, device_t, void *);
81 static const struct isic_pcmcia_card_entry * find_matching_card(struct pcmcia_attach_args *pa);
82 static int isic_pcmcia_isdn_attach(struct isic_softc *sc, const char*);
83 static int isic_pcmcia_detach(device_t self, int flags);
84 static int isic_pcmcia_activate(device_t self, enum devact act);
86 CFATTACH_DECL(isic_pcmcia, sizeof(struct pcmcia_isic_softc),
87 isic_pcmcia_match, isic_pcmcia_attach,
88 isic_pcmcia_detach, isic_pcmcia_activate);
90 struct isic_pcmcia_card_entry {
91 int32_t vendor; /* vendor ID */
92 int32_t product; /* product ID */
93 const char *cis1_info[4]; /* CIS info to match */
94 const char *name; /* name of controller */
95 int function; /* expected PCMCIA function type */
96 int card_type; /* card type found */
97 isic_pcmcia_attach_func attach; /* card initialization */
100 static const struct isic_pcmcia_card_entry card_list[] = {
102 #ifdef ISICPCMCIA_AVM_A1
103 { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
104 { "AVM", "ISDN A", NULL, NULL },
105 "AVM Fritz!Card", PCMCIA_FUNCTION_NETWORK,
106 CARD_TYPEP_PCFRITZ, isic_attach_fritzpcmcia },
107 #endif
109 #ifdef ISICPCMCIA_ELSA_ISDNMC
110 { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
111 { "ELSA GmbH, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
112 "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
113 CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
114 { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
115 { "ELSA AG, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
116 "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
117 CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
118 { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
119 { "ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", NULL, NULL },
120 "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
121 CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
122 #endif
124 #ifdef ISICPCMCIA_ELSA_MCALL
125 { 0x105, 0x410a,
126 { "ELSA", "MicroLink MC all", NULL, NULL },
127 "ELSA MicroLink MCall", PCMCIA_FUNCTION_NETWORK,
128 CARD_TYPEP_ELSAMLMCALL, isic_attach_elsamcall },
129 #endif
131 #ifdef ISICPCMCIA_SBSPEEDSTAR2
132 { 0x020e, 0x0002,
133 { "SEDLBAUER", "speed star II", NULL, NULL },
134 "SEDLBAUER speed star II", PCMCIA_FUNCTION_NETWORK,
135 CARD_TYPEP_SWS, isic_attach_sbspeedstar2 },
136 #endif
139 #define NUM_MATCH_ENTRIES (sizeof(card_list)/sizeof(card_list[0]))
141 static const struct isic_pcmcia_card_entry *
142 find_matching_card(struct pcmcia_attach_args *pa)
144 int i, j;
146 for (i = 0; i < NUM_MATCH_ENTRIES; i++) {
147 if (card_list[i].vendor != PCMCIA_VENDOR_INVALID && pa->card->manufacturer != card_list[i].vendor)
148 continue;
149 if (card_list[i].product != PCMCIA_PRODUCT_INVALID && pa->card->product != card_list[i].product)
150 continue;
151 if (pa->pf->function != card_list[i].function)
152 continue;
153 for (j = 0; j < 4; j++) {
154 if (card_list[i].cis1_info[j] == NULL)
155 continue; /* wildcard */
156 if (pa->card->cis1_info[j] == NULL)
157 break; /* not available */
158 if (strcmp(pa->card->cis1_info[j], card_list[i].cis1_info[j]) != 0)
159 break; /* mismatch */
161 if (j >= 4)
162 break;
164 if (i >= NUM_MATCH_ENTRIES)
165 return NULL;
167 return &card_list[i];
171 * Match card
173 static int
174 isic_pcmcia_match(device_t parent,
175 cfdata_t match, void *aux)
177 struct pcmcia_attach_args *pa = aux;
179 if (!find_matching_card(pa))
180 return 0;
182 return 1;
186 * Attach the card
188 static void
189 isic_pcmcia_attach(device_t parent,
190 device_t self, void *aux)
192 struct pcmcia_isic_softc *psc = (void*) self;
193 struct isic_softc *sc = &psc->sc_isic;
194 struct pcmcia_attach_args *pa = aux;
195 struct pcmcia_config_entry *cfe;
196 const struct isic_pcmcia_card_entry * cde;
198 psc->sc_pf = pa->pf;
199 cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head);
200 psc->sc_ih = NULL;
202 /* Which card is it? */
203 cde = find_matching_card(pa);
204 if (cde == NULL) {
205 aprint_error_dev(&psc->sc_isic.sc_dev, "attach failed, couldn't find matching card\n");
206 return;
208 printf("%s: %s\n", cde->name, device_xname(self));
210 /* Enable the card */
211 pcmcia_function_init(pa->pf, cfe);
212 psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, isicintr, sc);
213 pcmcia_function_enable(pa->pf);
215 if (!cde->attach(psc, cfe, pa)) {
216 aprint_error_dev(&psc->sc_isic.sc_dev, "attach failed, card-specific attach unsuccesful\n");
217 goto fail;
220 /* MI initilization */
221 sc->sc_cardtyp = cde->card_type;
222 if (isic_pcmcia_isdn_attach(sc, cde->name)) {
223 aprint_error_dev(&psc->sc_isic.sc_dev, "attach failed, generic attach unsuccesful\n");
224 goto fail;
227 return;
229 fail:
230 pcmcia_function_disable(psc->sc_pf);
231 pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
234 static int
235 isic_pcmcia_detach(device_t self, int flags)
237 struct pcmcia_isic_softc *psc = (struct pcmcia_isic_softc *)self;
239 pcmcia_function_disable(psc->sc_pf);
240 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
241 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
242 if (psc->sc_ih != NULL)
243 pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
245 return (0);
249 isic_pcmcia_activate(device_t self, enum devact act)
251 struct pcmcia_isic_softc *psc = device_private(self);
253 switch (act) {
254 case DVACT_DEACTIVATE:
255 psc->sc_isic.sc_intr_valid = ISIC_INTR_DYING;
256 if (psc->sc_isic.sc_l3token != NULL)
257 isic_detach_bri(&psc->sc_isic);
258 return 0;
259 default:
260 return EOPNOTSUPP;
264 /*---------------------------------------------------------------------------*
265 * card independend attach for pcmicia cards
266 *---------------------------------------------------------------------------*/
268 /* parameter and format for message producing e.g. "isic0: " */
270 #ifdef __FreeBSD__
271 #define ISIC_FMT "isic%d: "
272 #define ISIC_PARM dev->id_unit
273 #define TERMFMT " "
274 #else
275 #define ISIC_FMT "%s: "
276 #define ISIC_PARM device_xname(&sc->sc_dev)
277 #define TERMFMT "\n"
278 #endif
281 isic_pcmcia_isdn_attach(struct isic_softc *sc, const char *cardname)
283 static const char *ISACversion[] = {
284 "2085 Version A1/A2 or 2086/2186 Version 1.1",
285 "2085 Version B1",
286 "2085 Version B2",
287 "2085 Version V2.3 (B3)",
288 "Unknown Version"
291 static const char *HSCXversion[] = {
292 "82525 Version A1",
293 "Unknown (0x01)",
294 "82525 Version A2",
295 "Unknown (0x03)",
296 "82525 Version A3",
297 "82525 or 21525 Version 2.1",
298 "Unknown Version"
301 sc->sc_l3token = NULL;
302 sc->sc_isac_version = 0;
303 sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
305 switch(sc->sc_isac_version)
307 case ISAC_VA:
308 case ISAC_VB1:
309 case ISAC_VB2:
310 case ISAC_VB3:
311 break;
313 default:
314 printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
315 ISIC_PARM, sc->sc_isac_version);
316 return(EIO);
319 sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
321 switch(sc->sc_hscx_version)
323 case HSCX_VA1:
324 case HSCX_VA2:
325 case HSCX_VA3:
326 case HSCX_V21:
327 break;
329 default:
330 printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
331 ISIC_PARM, sc->sc_hscx_version);
332 return(EIO);
335 sc->sc_intr_valid = ISIC_INTR_DISABLED;
337 /* HSCX setup */
339 isic_bchannel_setup(sc, HSCX_CH_A, BPROT_NONE, 0);
341 isic_bchannel_setup(sc, HSCX_CH_B, BPROT_NONE, 0);
343 /* setup linktab */
345 isic_init_linktab(sc);
347 /* set trace level */
349 sc->sc_trace = TRACE_OFF;
351 sc->sc_state = ISAC_IDLE;
353 sc->sc_ibuf = NULL;
354 sc->sc_ib = NULL;
355 sc->sc_ilen = 0;
357 sc->sc_obuf = NULL;
358 sc->sc_op = NULL;
359 sc->sc_ol = 0;
360 sc->sc_freeflag = 0;
362 sc->sc_obuf2 = NULL;
363 sc->sc_freeflag2 = 0;
365 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
366 callout_init(&sc->sc_T3_callout, 0);
367 callout_init(&sc->sc_T4_callout, 0);
368 #endif
370 /* announce chip versions */
372 if(sc->sc_isac_version >= ISAC_UNKN)
374 printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
375 ISIC_PARM,
376 sc->sc_isac_version);
377 sc->sc_isac_version = ISAC_UNKN;
379 else
381 printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
382 ISIC_PARM,
383 ISACversion[sc->sc_isac_version],
384 sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
387 if(sc->sc_hscx_version >= HSCX_UNKN)
389 printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
390 ISIC_PARM,
391 sc->sc_hscx_version);
392 sc->sc_hscx_version = HSCX_UNKN;
394 else
396 printf(ISIC_FMT "HSCX %s" TERMFMT,
397 ISIC_PARM,
398 HSCXversion[sc->sc_hscx_version]);
401 /* init higher protocol layers */
402 isic_attach_bri(sc, cardname, &isic_std_driver);
404 return(0);