1 /* $NetBSD: iwic_pci.c,v 1.15 2009/05/12 08:23:01 cegger Exp $ */
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
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
27 *---------------------------------------------------------------------------
29 * i4b_iwic - isdn4bsd Winbond W6692 driver
30 * ----------------------------------------
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>
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
{
93 PCI_ID_CODE(PCI_VENDOR_WINBOND
,PCI_PRODUCT_WINBOND_W6692
),
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"
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"
132 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
135 "ASUSCOM P-IN100-ST-D"
138 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
141 "ASUSCOM P-IN100-ST-D"
144 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
147 "ASUSCOM P-IN100-ST-D"
150 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
153 "ASUSCOM P-IN100-ST-D"
156 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
159 "ASUSCOM P-IN100-ST-D"
162 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
165 "ASUSCOM P-IN100-ST-D"
168 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
171 "ASUSCOM P-IN100-ST-D"
174 PCI_ID_CODE(PCI_VENDOR_ASUSTEK
,PCI_PRODUCT_ASUSTEK_HFCPCI
),
177 "ASUSCOM P-IN100-ST-D"
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
;
197 if (wip
->type
== type
) {
198 if (((wip
->sv
== -1) && (wip
->sd
== -1)) ||
199 ((wip
->sv
== sv
) && (wip
->sd
== sd
)))
210 /*---------------------------------------------------------------------------*
212 *---------------------------------------------------------------------------*/
214 iwic_pci_probe(device_t dev
,
215 cfdata_t match
, void *aux
)
217 if (iwic_find_card(aux
))
222 /*---------------------------------------------------------------------------*
224 *---------------------------------------------------------------------------*/
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
;
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
)
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");
247 if (pci_intr_map(pa
, &ih
)) {
248 aprint_error_dev(&sc
->sc_dev
, "couldn't map interrupt\n");
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");
256 aprint_error(" at %s", intrstr
);
261 aprint_normal_dev(&sc
->sc_dev
, "interrupting at %s\n", intrstr
);
263 /* disable interrupts */
264 IWIC_WRITE(sc
, IWIC_IMASK
, 0xff);
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
);
287 /*---------------------------------------------------------------------------*
289 *---------------------------------------------------------------------------*/
291 iwic_pci_intr(void *p
)
293 struct iwic_softc
*sc
= p
;
296 int irq_stat
= IWIC_READ(sc
, ISTA
);
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
) {
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);
319 iwic_pci_activate(device_t dev
, enum devact act
)
321 int error
= EOPNOTSUPP
;
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
= {
332 iwic_ph_activate_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
= {
351 n_disconnect_request
,
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
;
371 isdn_layer2_status_ind(&sc
->sc_l2
, drv
, STI_ATTACH
, 1);
373 isdn_isdnif_ready(drv
->isdnif
);
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
);
397 iwic_mph_command_req(isdn_layer1token t
, int command
, void *parm
)
399 struct iwic_softc
*sc
= t
;
402 case CMR_DOPEN
: /* Daemon running */
403 NDBGL1(L1_PRIM
, "CMR_DOPEN");
404 IWIC_WRITE(sc
, IWIC_IMASK
, IMASK_XINT0
| IMASK_XINT1
);
407 case CMR_DCLOSE
: /* Daemon not running */
408 NDBGL1(L1_PRIM
, "CMR_DCLOSE");
409 IWIC_WRITE(sc
, IWIC_IMASK
, 0xff);
413 sc
->sc_trace
= (int)(intptr_t)parm
;
414 NDBGL1(L1_PRIM
, "CMR_SETTRACE, parm = %d", sc
->sc_trace
);
418 NDBGL1(L1_PRIM
, "unknown command = %d", command
);
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
;
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
;