Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / iwic_pci.c
blobc9d251949b63ab906bd612c1c07618a255effb28
1 /* $NetBSD: iwic_pci.c,v 1.15 2009/05/12 08:23:01 cegger Exp $ */
3 /*
4 * Copyright (c) 1999, 2000 Dave Boyce. All rights reserved.
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.
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.
27 *---------------------------------------------------------------------------
29 * i4b_iwic - isdn4bsd Winbond W6692 driver
30 * ----------------------------------------
32 * $FreeBSD$
34 * last edit-date: [Tue Jan 16 10:53:03 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: iwic_pci.c,v 1.15 2009/05/12 08:23:01 cegger Exp $");
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>
47 #include <sys/bus.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcidevs.h>
52 #include <netisdn/i4b_global.h>
54 #include <dev/pci/iwicreg.h>
55 #include <dev/pci/iwicvar.h>
57 /* Winbond PCI Configuration Space */
59 #define IWIC_PCI_IOBA (PCI_MAPREG_START+0x04)
61 static int iwic_pci_intr(void *sc);
62 static int iwic_pci_probe(device_t dev, cfdata_t match, void *aux);
63 static void iwic_pci_attach(device_t parent, device_t dev, void *aux);
64 static int iwic_pci_activate(device_t dev, enum devact);
66 CFATTACH_DECL(iwic_pci, sizeof(struct iwic_softc),
67 iwic_pci_probe, iwic_pci_attach, NULL, iwic_pci_activate);
69 static int iwic_attach_bri(struct iwic_softc * sc);
71 /*---------------------------------------------------------------------------*
72 * PCI ID list for ASUSCOM card got from Asuscom in March 2000:
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 *---------------------------------------------------------------------------*/
86 static struct winids {
87 pcireg_t type;
88 int sv;
89 int sd;
90 const char *desc;
91 } win_ids[] = {
93 PCI_ID_CODE(PCI_VENDOR_WINBOND,PCI_PRODUCT_WINBOND_W6692),
94 0x144F,
95 0x1707,
96 "Planet PCI ISDN Adapter (Model IA128P-STDV)"
99 PCI_ID_CODE(PCI_VENDOR_WINBOND,PCI_PRODUCT_WINBOND_W6692),
102 "Generic Winbond W6692 ISDN PCI"
105 PCI_ID_CODE(PCI_VENDOR_DYNALINK,PCI_PRODUCT_DYNALINK_IS64PH),
108 "ASUSCOM P-IN100-ST-D"
110 #if 0
111 /* XXX */
113 PCI_ID_CODE(PCI_VENDOR_DYNALINK,0x1703),
116 "ASUSCOM P-IN100-ST-D"
119 PCI_ID_CODE(PCI_VENDOR_DYNALINK,0x1707),
122 "ASUSCOM P-IN100-ST-D"
125 PCI_ID_CODE(PCI_VENDOR_CITICORP,0x105E),
128 "ASUSCOM P-IN100-ST-D"
130 #endif
132 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
133 0x144F,
134 0x2000,
135 "ASUSCOM P-IN100-ST-D"
138 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
139 0x144F,
140 0x1702,
141 "ASUSCOM P-IN100-ST-D"
144 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
145 0x144F,
146 0x1707,
147 "ASUSCOM P-IN100-ST-D"
150 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
151 0x1443,
152 0x1702,
153 "ASUSCOM P-IN100-ST-D"
156 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
157 0x1443,
158 0x1707,
159 "ASUSCOM P-IN100-ST-D"
162 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
163 0x144F,
164 0x2000,
165 "ASUSCOM P-IN100-ST-D"
168 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
169 0x144F,
170 0x2000,
171 "ASUSCOM P-IN100-ST-D"
174 PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
175 0x144F,
176 0x2000,
177 "ASUSCOM P-IN100-ST-D"
180 0x00000000,
183 NULL
187 static const char *
188 iwic_find_card(const struct pci_attach_args * pa)
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;
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;
202 ++wip;
205 if (wip->desc)
206 return wip->desc;
208 return 0;
210 /*---------------------------------------------------------------------------*
211 * iwic PCI probe
212 *---------------------------------------------------------------------------*/
213 static int
214 iwic_pci_probe(device_t dev,
215 cfdata_t match, void *aux)
217 if (iwic_find_card(aux))
218 return 1;
220 return 0;
222 /*---------------------------------------------------------------------------*
223 * PCI attach
224 *---------------------------------------------------------------------------*/
225 static void
226 iwic_pci_attach(device_t parent, device_t dev, void *aux)
228 struct iwic_softc *sc = device_private(dev);
229 struct iwic_bchan *bchan;
230 pci_intr_handle_t ih;
231 const char *intrstr;
232 struct pci_attach_args *pa = aux;
233 pci_chipset_tag_t pc = pa->pa_pc;
235 sc->sc_cardname = iwic_find_card(pa);
237 if (!sc->sc_cardname)
238 return; /* Huh? */
240 printf(": %s\n", sc->sc_cardname);
242 if (pci_mapreg_map(pa, IWIC_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0,
243 &sc->sc_io_bt, &sc->sc_io_bh, &sc->sc_iobase, &sc->sc_iosize)) {
244 aprint_error_dev(&sc->sc_dev, "unable to map registers\n");
245 return;
247 if (pci_intr_map(pa, &ih)) {
248 aprint_error_dev(&sc->sc_dev, "couldn't map interrupt\n");
249 return;
251 intrstr = pci_intr_string(pc, ih);
252 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, iwic_pci_intr, sc);
253 if (sc->sc_ih == NULL) {
254 aprint_error_dev(&sc->sc_dev, "couldn't establish interrupt");
255 if (intrstr != NULL)
256 aprint_error(" at %s", intrstr);
257 aprint_error("\n");
258 return;
260 sc->sc_pc = pc;
261 aprint_normal_dev(&sc->sc_dev, "interrupting at %s\n", intrstr);
263 /* disable interrupts */
264 IWIC_WRITE(sc, IWIC_IMASK, 0xff);
265 IWIC_READ(sc, ISTA);
267 iwic_dchan_init(sc);
269 bchan = &sc->sc_bchan[IWIC_BCH_A];
270 bchan->offset = B1_CHAN_OFFSET;
271 bchan->channel = IWIC_BCH_A;
272 bchan->state = ST_IDLE;
274 iwic_bchannel_setup(sc, IWIC_BCH_A, BPROT_NONE, 0);
276 bchan = &sc->sc_bchan[IWIC_BCH_B];
277 bchan->offset = B2_CHAN_OFFSET;
278 bchan->channel = IWIC_BCH_B;
279 bchan->state = ST_IDLE;
281 iwic_bchannel_setup(sc, IWIC_BCH_B, BPROT_NONE, 0);
283 iwic_init_linktab(sc);
285 iwic_attach_bri(sc);
287 /*---------------------------------------------------------------------------*
288 * IRQ handler
289 *---------------------------------------------------------------------------*/
290 static int
291 iwic_pci_intr(void *p)
293 struct iwic_softc *sc = p;
295 while (1) {
296 int irq_stat = IWIC_READ(sc, ISTA);
298 if (irq_stat == 0)
299 break;
301 if (irq_stat & (ISTA_D_RME | ISTA_D_RMR | ISTA_D_XFR)) {
302 iwic_dchan_xfer_irq(sc, irq_stat);
304 if (irq_stat & ISTA_D_EXI) {
305 iwic_dchan_xirq(sc);
307 if (irq_stat & ISTA_B1_EXI) {
308 iwic_bchan_xirq(sc, 0);
310 if (irq_stat & ISTA_B2_EXI) {
311 iwic_bchan_xirq(sc, 1);
315 return 0;
318 static int
319 iwic_pci_activate(device_t dev, enum devact act)
321 int error = EOPNOTSUPP;
323 return error;
326 int iwic_ph_data_req(isdn_layer1token t, struct mbuf * m, int freeflag);
327 int iwic_ph_activate_req(isdn_layer1token t);
328 int iwic_mph_command_req(isdn_layer1token t, int command, void *parm);
330 struct isdn_layer1_isdnif_driver iwic_bri_driver = {
331 iwic_ph_data_req,
332 iwic_ph_activate_req,
333 iwic_mph_command_req
336 void iwic_set_link(void *, int channel, const struct isdn_l4_driver_functions * l4_driver, void *l4_driver_softc);
337 isdn_link_t *iwic_ret_linktab(void *, int channel);
339 /* XXX Should be prototyped in some header, not here XXX */
340 void n_connect_request(struct call_desc * cd);
341 void n_connect_response(struct call_desc * cd, int response, int cause);
342 void n_disconnect_request(struct call_desc * cd, int cause);
343 void n_alert_request(struct call_desc * cd);
344 void n_mgmt_command(struct isdn_l3_driver * drv, int cmd, void *parm);
346 const struct isdn_l3_driver_functions iwic_l3_driver = {
347 iwic_ret_linktab,
348 iwic_set_link,
349 n_connect_request,
350 n_connect_response,
351 n_disconnect_request,
352 n_alert_request,
353 NULL,
354 NULL,
355 n_mgmt_command
358 static int
359 iwic_attach_bri(struct iwic_softc * sc)
361 struct isdn_l3_driver *drv;
363 drv = isdn_attach_isdnif(device_xname(&sc->sc_dev), sc->sc_cardname,
364 &sc->sc_l2, &iwic_l3_driver, NBCH_BRI);
366 sc->sc_l3token = drv;
367 sc->sc_l2.driver = &iwic_bri_driver;
368 sc->sc_l2.l1_token = sc;
369 sc->sc_l2.drv = drv;
371 isdn_layer2_status_ind(&sc->sc_l2, drv, STI_ATTACH, 1);
373 isdn_isdnif_ready(drv->isdnif);
375 return 1;
379 iwic_ph_data_req(isdn_layer1token t, struct mbuf * m, int freeflag)
381 struct iwic_softc *sc = t;
383 return iwic_dchan_data_req(sc, m, freeflag);
387 iwic_ph_activate_req(isdn_layer1token t)
389 struct iwic_softc *sc = t;
391 iwic_next_state(sc, EV_PHAR);
393 return 0;
397 iwic_mph_command_req(isdn_layer1token t, int command, void *parm)
399 struct iwic_softc *sc = t;
401 switch (command) {
402 case CMR_DOPEN: /* Daemon running */
403 NDBGL1(L1_PRIM, "CMR_DOPEN");
404 IWIC_WRITE(sc, IWIC_IMASK, IMASK_XINT0 | IMASK_XINT1);
405 break;
407 case CMR_DCLOSE: /* Daemon not running */
408 NDBGL1(L1_PRIM, "CMR_DCLOSE");
409 IWIC_WRITE(sc, IWIC_IMASK, 0xff);
410 break;
412 case CMR_SETTRACE:
413 sc->sc_trace = (int)(intptr_t)parm;
414 NDBGL1(L1_PRIM, "CMR_SETTRACE, parm = %d", sc->sc_trace);
415 break;
417 default:
418 NDBGL1(L1_PRIM, "unknown command = %d", command);
419 break;
422 return 0;
425 isdn_link_t *
426 iwic_ret_linktab(void *t, int channel)
428 struct l2_softc *l2sc = t;
429 struct iwic_softc *sc = l2sc->l1_token;
430 struct iwic_bchan *bchan = &sc->sc_bchan[channel];
432 return &bchan->iwic_isdn_linktab;
435 void
436 iwic_set_link(void *t, int channel, const struct isdn_l4_driver_functions * l4_driver, void *l4_driver_softc)
438 struct l2_softc *l2sc = t;
439 struct iwic_softc *sc = l2sc->l1_token;
440 struct iwic_bchan *bchan = &sc->sc_bchan[channel];
442 bchan->l4_driver = l4_driver;
443 bchan->l4_driver_softc = l4_driver_softc;