FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/iwic_pci.c
1 /* $NetBSD: iwic_pci.c,v 1.7 2003/10/03 16:38:44 pooka Exp $ */
2
3 /*
4 * Copyright (c) 1999, 2000 Dave Boyce. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *---------------------------------------------------------------------------
28 *
29 * i4b_iwic - isdn4bsd Winbond W6692 driver
30 * ----------------------------------------
31 *
32 * $FreeBSD$
33 *
34 * last edit-date: [Tue Jan 16 10:53:03 2001]
35 *
36 *---------------------------------------------------------------------------*/
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: iwic_pci.c,v 1.7 2003/10/03 16:38:44 pooka Exp $");
40
41 #include <sys/param.h>
42 #include <sys/kernel.h>
43 #include <sys/systm.h>
44 #include <sys/callout.h>
45 #include <net/if.h>
46
47 #include <machine/bus.h>
48
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcidevs.h>
51
52 #include <netisdn/i4b_global.h>
53
54 #include <dev/pci/iwicreg.h>
55 #include <dev/pci/iwicvar.h>
56
57 /* Winbond PCI Configuration Space */
58
59 #define IWIC_PCI_IOBA (PCI_MAPREG_START+0x04)
60
61 static int iwic_pci_intr(void *sc);
62 static int iwic_pci_probe(struct device * dev, struct cfdata * match, void *aux);
63 static void iwic_pci_attach(struct device * parent, struct device * dev, void *aux);
64 static int iwic_pci_activate(struct device * dev, enum devact);
65
66 CFATTACH_DECL(iwic_pci, sizeof(struct iwic_softc),
67 iwic_pci_probe, iwic_pci_attach, NULL, iwic_pci_activate);
68
69 static int iwic_attach_bri(struct iwic_softc * sc);
70
71 /*---------------------------------------------------------------------------*
72 * PCI ID list for ASUSCOM card got from Asuscom in March 2000:
73 *
74 * Vendor ID: 0675 Device ID: 1702
75 * Vendor ID: 0675 Device ID: 1703
76 * Vendor ID: 0675 Device ID: 1707
77 * Vendor ID: 10CF Device ID: 105E
78 * Vendor ID: 1043 Device ID: 0675 SubVendor: 144F SubDevice ID: 2000
79 * Vendor ID: 1043 Device ID: 0675 SubVendor: 144F SubDevice ID: 1702
80 * Vendor ID: 1043 Device ID: 0675 SubVendor: 144F SubDevice ID: 1707
81 * Vendor ID: 1043 Device ID: 0675 SubVendor: 1043 SubDevice ID: 1702
82 * Vendor ID: 1043 Device ID: 0675 SubVendor: 1043 SubDevice ID: 1707
83 * Vendor ID: 1050 Device ID: 6692 SubVendor: 0675 SubDevice ID: 1702
84 *---------------------------------------------------------------------------*/
85
86 static struct winids {
87 pcireg_t type;
88 int sv;
89 int sd;
90 const char *desc;
91 } win_ids[] = {
92 {
93 PCI_ID_CODE(PCI_VENDOR_WINBOND,PCI_PRODUCT_WINBOND_W6692),
94 0x144F,
95 0x1707,
96 "Planet PCI ISDN Adapter (Model IA128P-STDV)"
97 },
98 {
99 PCI_ID_CODE(PCI_VENDOR_WINBOND,PCI_PRODUCT_WINBOND_W6692),
100 -1,
101 -1,
102 "Generic Winbond W6692 ISDN PCI"
103 },
104 {
105 PCI_ID_CODE(PCI_VENDOR_DYNALINK,PCI_PRODUCT_DYNALINK_IS64PH),
106 -1,
107 -1,
108 "ASUSCOM P-IN100-ST-D"
109 },
110 #if 0
111 /* XXX */
112 {
113 PCI_ID_CODE(PCI_VENDOR_DYNALINK,0x1703),
114 -1,
115 -1,
116 "ASUSCOM P-IN100-ST-D"
117 },
118 {
119 PCI_ID_CODE(PCI_VENDOR_DYNALINK,0x1707),
120 -1,
121 -1,
122 "ASUSCOM P-IN100-ST-D"
123 },
124 {
125 PCI_ID_CODE(PCI_VENDOR_CITICORP,0x105E),
126 -1,
127 -1,
128 "ASUSCOM P-IN100-ST-D"
129 },
130 #endif
131 {
132 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
133 0x144F,
134 0x2000,
135 "ASUSCOM P-IN100-ST-D"
136 },
137 {
138 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
139 0x144F,
140 0x1702,
141 "ASUSCOM P-IN100-ST-D"
142 },
143 {
144 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
145 0x144F,
146 0x1707,
147 "ASUSCOM P-IN100-ST-D"
148 },
149 {
150 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
151 0x1443,
152 0x1702,
153 "ASUSCOM P-IN100-ST-D"
154 },
155 {
156 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
157 0x1443,
158 0x1707,
159 "ASUSCOM P-IN100-ST-D"
160 },
161 {
162 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
163 0x144F,
164 0x2000,
165 "ASUSCOM P-IN100-ST-D"
166 },
167 {
168 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
169 0x144F,
170 0x2000,
171 "ASUSCOM P-IN100-ST-D"
172 },
173 {
174 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
175 0x144F,
176 0x2000,
177 "ASUSCOM P-IN100-ST-D"
178 },
179 {
180 0x00000000,
181 0,
182 0,
183 NULL
184 }
185 };
186
187 static const char *
188 iwic_find_card(const struct pci_attach_args * pa)
189 {
190 pcireg_t type = pa->pa_id;
191 pcireg_t reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
192 int sv = PCI_VENDOR(reg);
193 int sd = PCI_PRODUCT(reg);
194 struct winids *wip = win_ids;
195
196 while (wip->type) {
197 if (wip->type == type) {
198 if (((wip->sv == -1) && (wip->sd == -1)) ||
199 ((wip->sv == sv) && (wip->sd == sd)))
200 break;
201 }
202 ++wip;
203 }
204
205 if (wip->desc)
206 return wip->desc;
207
208 return 0;
209 }
210 /*---------------------------------------------------------------------------*
211 * iwic PCI probe
212 *---------------------------------------------------------------------------*/
213 static int
214 iwic_pci_probe(struct device * dev, struct cfdata * match, void *aux)
215 {
216 if (iwic_find_card(aux))
217 return 1;
218
219 return 0;
220 }
221 /*---------------------------------------------------------------------------*
222 * PCI attach
223 *---------------------------------------------------------------------------*/
224 static void
225 iwic_pci_attach(struct device * parent, struct device * dev, void *aux)
226 {
227 struct iwic_softc *sc = (void *) dev;
228 struct iwic_bchan *bchan;
229 pci_intr_handle_t ih;
230 const char *intrstr;
231 struct pci_attach_args *pa = aux;
232 pci_chipset_tag_t pc = pa->pa_pc;
233
234 sc->sc_cardname = iwic_find_card(pa);
235
236 if (!sc->sc_cardname)
237 return; /* Huh? */
238
239 printf(": %s\n", sc->sc_cardname);
240
241 if (pci_mapreg_map(pa, IWIC_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0,
242 &sc->sc_io_bt, &sc->sc_io_bh, &sc->sc_iobase, &sc->sc_iosize)) {
243 printf("%s: unable to map registers\n", sc->sc_dev.dv_xname);
244 return;
245 }
246 if (pci_intr_map(pa, &ih)) {
247 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
248 return;
249 }
250 intrstr = pci_intr_string(pc, ih);
251 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, iwic_pci_intr, sc);
252 if (sc->sc_ih == NULL) {
253 printf("%s: couldn't establish interrupt", sc->sc_dev.dv_xname);
254 if (intrstr != NULL)
255 printf(" at %s", intrstr);
256 printf("\n");
257 return;
258 }
259 sc->sc_pc = pc;
260 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
261
262 /* disable interrupts */
263 IWIC_WRITE(sc, IWIC_IMASK, 0xff);
264 IWIC_READ(sc, ISTA);
265
266 iwic_dchan_init(sc);
267
268 bchan = &sc->sc_bchan[IWIC_BCH_A];
269 bchan->offset = B1_CHAN_OFFSET;
270 bchan->channel = IWIC_BCH_A;
271 bchan->state = ST_IDLE;
272
273 iwic_bchannel_setup(sc, IWIC_BCH_A, BPROT_NONE, 0);
274
275 bchan = &sc->sc_bchan[IWIC_BCH_B];
276 bchan->offset = B2_CHAN_OFFSET;
277 bchan->channel = IWIC_BCH_B;
278 bchan->state = ST_IDLE;
279
280 iwic_bchannel_setup(sc, IWIC_BCH_B, BPROT_NONE, 0);
281
282 iwic_init_linktab(sc);
283
284 iwic_attach_bri(sc);
285 }
286 /*---------------------------------------------------------------------------*
287 * IRQ handler
288 *---------------------------------------------------------------------------*/
289 static int
290 iwic_pci_intr(void *p)
291 {
292 struct iwic_softc *sc = p;
293
294 while (1) {
295 int irq_stat = IWIC_READ(sc, ISTA);
296
297 if (irq_stat == 0)
298 break;
299
300 if (irq_stat & (ISTA_D_RME | ISTA_D_RMR | ISTA_D_XFR)) {
301 iwic_dchan_xfer_irq(sc, irq_stat);
302 }
303 if (irq_stat & ISTA_D_EXI) {
304 iwic_dchan_xirq(sc);
305 }
306 if (irq_stat & ISTA_B1_EXI) {
307 iwic_bchan_xirq(sc, 0);
308 }
309 if (irq_stat & ISTA_B2_EXI) {
310 iwic_bchan_xirq(sc, 1);
311 }
312 }
313
314 return 0;
315 }
316
317 static int
318 iwic_pci_activate(struct device * dev, enum devact act)
319 {
320 int error = EOPNOTSUPP;
321
322 return error;
323 }
324
325 int iwic_ph_data_req(isdn_layer1token t, struct mbuf * m, int freeflag);
326 int iwic_ph_activate_req(isdn_layer1token t);
327 int iwic_mph_command_req(isdn_layer1token t, int command, void *parm);
328
329 struct isdn_layer1_isdnif_driver iwic_bri_driver = {
330 iwic_ph_data_req,
331 iwic_ph_activate_req,
332 iwic_mph_command_req
333 };
334
335 void iwic_set_link(void *, int channel, const struct isdn_l4_driver_functions * l4_driver, void *l4_driver_softc);
336 isdn_link_t *iwic_ret_linktab(void *, int channel);
337
338 /* XXX Should be prototyped in some header, not here XXX */
339 void n_connect_request(struct call_desc * cd);
340 void n_connect_response(struct call_desc * cd, int response, int cause);
341 void n_disconnect_request(struct call_desc * cd, int cause);
342 void n_alert_request(struct call_desc * cd);
343 void n_mgmt_command(struct isdn_l3_driver * drv, int cmd, void *parm);
344
345 const struct isdn_l3_driver_functions iwic_l3_driver = {
346 iwic_ret_linktab,
347 iwic_set_link,
348 n_connect_request,
349 n_connect_response,
350 n_disconnect_request,
351 n_alert_request,
352 NULL,
353 NULL,
354 n_mgmt_command
355 };
356
357 static int
358 iwic_attach_bri(struct iwic_softc * sc)
359 {
360 struct isdn_l3_driver *drv;
361
362 drv = isdn_attach_isdnif(sc->sc_dev.dv_xname, sc->sc_cardname,
363 &sc->sc_l2, &iwic_l3_driver, NBCH_BRI);
364
365 sc->sc_l3token = drv;
366 sc->sc_l2.driver = &iwic_bri_driver;
367 sc->sc_l2.l1_token = sc;
368 sc->sc_l2.drv = drv;
369
370 isdn_layer2_status_ind(&sc->sc_l2, drv, STI_ATTACH, 1);
371
372 isdn_isdnif_ready(drv->isdnif);
373
374 return 1;
375 }
376
377 int
378 iwic_ph_data_req(isdn_layer1token t, struct mbuf * m, int freeflag)
379 {
380 struct iwic_softc *sc = t;
381
382 return iwic_dchan_data_req(sc, m, freeflag);
383 }
384
385 int
386 iwic_ph_activate_req(isdn_layer1token t)
387 {
388 struct iwic_softc *sc = t;
389
390 iwic_next_state(sc, EV_PHAR);
391
392 return 0;
393 }
394
395 int
396 iwic_mph_command_req(isdn_layer1token t, int command, void *parm)
397 {
398 struct iwic_softc *sc = t;
399
400 switch (command) {
401 case CMR_DOPEN: /* Daemon running */
402 NDBGL1(L1_PRIM, "CMR_DOPEN");
403 IWIC_WRITE(sc, IWIC_IMASK, IMASK_XINT0 | IMASK_XINT1);
404 break;
405
406 case CMR_DCLOSE: /* Daemon not running */
407 NDBGL1(L1_PRIM, "CMR_DCLOSE");
408 IWIC_WRITE(sc, IWIC_IMASK, 0xff);
409 break;
410
411 case CMR_SETTRACE:
412 sc->sc_trace = (int)(intptr_t)parm;
413 NDBGL1(L1_PRIM, "CMR_SETTRACE, parm = %d", sc->sc_trace);
414 break;
415
416 default:
417 NDBGL1(L1_PRIM, "unknown command = %d", command);
418 break;
419 }
420
421 return 0;
422 }
423
424 isdn_link_t *
425 iwic_ret_linktab(void *t, int channel)
426 {
427 struct l2_softc *l2sc = t;
428 struct iwic_softc *sc = l2sc->l1_token;
429 struct iwic_bchan *bchan = &sc->sc_bchan[channel];
430
431 return &bchan->iwic_isdn_linktab;
432 }
433
434 void
435 iwic_set_link(void *t, int channel, const struct isdn_l4_driver_functions * l4_driver, void *l4_driver_softc)
436 {
437 struct l2_softc *l2sc = t;
438 struct iwic_softc *sc = l2sc->l1_token;
439 struct iwic_bchan *bchan = &sc->sc_bchan[channel];
440
441 bchan->l4_driver = l4_driver;
442 bchan->l4_driver_softc = l4_driver_softc;
443 }
Cache object: d87b9fa8996dc901a4ac2709f099a2ee
|