Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / isic_pci_elsa_qs1p.c
blob38aadfa46fdb1472b20b43e15e597ee5e2a1e486
1 /* $NetBSD: isic_pci_elsa_qs1p.c,v 1.18 2008/04/10 19:13:37 cegger Exp $ */
3 /*
4 * Copyright (c) 1997, 1999 Hellmuth Michaelis. 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 * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro PCI
30 * =====================================================================
32 *---------------------------------------------------------------------------*/
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: isic_pci_elsa_qs1p.c,v 1.18 2008/04/10 19:13:37 cegger Exp $");
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 #include <sys/mbuf.h>
41 #include <sys/socket.h>
42 #include <net/if.h>
43 #include <sys/callout.h>
45 #include <sys/bus.h>
46 #include <sys/device.h>
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcidevs.h>
52 #include <netisdn/i4b_debug.h>
53 #include <netisdn/i4b_ioctl.h>
54 #include <netisdn/i4b_global.h>
55 #include <netisdn/i4b_debug.h>
56 #include <netisdn/i4b_l2.h>
57 #include <netisdn/i4b_l1l2.h>
58 #include <netisdn/i4b_mbuf.h>
60 #include <dev/ic/isic_l1.h>
61 #include <dev/ic/isac.h>
62 #include <dev/ic/hscx.h>
63 #include <dev/ic/ipac.h>
64 #include <dev/pci/isic_pci.h>
66 /* masks for register encoded in base addr */
68 #define ELSA_BASE_MASK 0x0ffff
69 #define ELSA_OFF_MASK 0xf0000
71 /* register id's to be encoded in base addr */
73 #define ELSA_IDISAC 0x00000
74 #define ELSA_IDHSCXA 0x10000
75 #define ELSA_IDHSCXB 0x20000
76 #define ELSA_IDIPAC 0x40000
78 /* offsets from base address */
80 #define ELSA_OFF_ALE 0x00
81 #define ELSA_OFF_RW 0x01
83 /* LED values */
84 #define ELSA_NO_LED 0xff
85 #define ELSA_GREEN_LED 0x40
86 #define ELSA_YELLOW_LED 0x80
88 #define ELSA_PORT0_MEM_MAPOFF PCI_MAPREG_START
89 #define ELSA_PORT0_IO_MAPOFF PCI_MAPREG_START+4
90 #define ELSA_PORT1_MAPOFF PCI_MAPREG_START+12
93 static void elsa_cmd_req(struct isic_softc *sc, int cmd, void *data);
94 static void elsa_led_handler(void *token);
96 /*---------------------------------------------------------------------------*
97 * ELSA QuickStep 1000pro/PCI ISAC get fifo routine
98 *---------------------------------------------------------------------------*/
100 static void
101 eqs1pp_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
103 bus_space_tag_t t = sc->sc_maps[1].t;
104 bus_space_handle_t h = sc->sc_maps[1].h;
105 switch (what) {
106 case ISIC_WHAT_ISAC:
107 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
108 bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
109 break;
110 case ISIC_WHAT_HSCXA:
111 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
112 bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
113 break;
114 case ISIC_WHAT_HSCXB:
115 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
116 bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
117 break;
121 /*---------------------------------------------------------------------------*
122 * ELSA QuickStep 1000pro/PCI ISAC put fifo routine
123 *---------------------------------------------------------------------------*/
125 static void
126 eqs1pp_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
128 bus_space_tag_t t = sc->sc_maps[1].t;
129 bus_space_handle_t h = sc->sc_maps[1].h;
130 switch (what) {
131 case ISIC_WHAT_ISAC:
132 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
133 bus_space_write_multi_1(t, h, ELSA_OFF_RW, buf, size);
134 break;
135 case ISIC_WHAT_HSCXA:
136 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
137 bus_space_write_multi_1(t, h, ELSA_OFF_RW, buf, size);
138 break;
139 case ISIC_WHAT_HSCXB:
140 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
141 bus_space_write_multi_1(t, h, ELSA_OFF_RW, buf, size);
142 break;
146 /*---------------------------------------------------------------------------*
147 * ELSA QuickStep 1000pro/PCI ISAC put register routine
148 *---------------------------------------------------------------------------*/
150 static void
151 eqs1pp_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
153 bus_space_tag_t t = sc->sc_maps[1].t;
154 bus_space_handle_t h = sc->sc_maps[1].h;
155 switch (what) {
156 case ISIC_WHAT_ISAC:
157 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
158 bus_space_write_1(t, h, ELSA_OFF_RW, data);
159 break;
160 case ISIC_WHAT_HSCXA:
161 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
162 bus_space_write_1(t, h, ELSA_OFF_RW, data);
163 break;
164 case ISIC_WHAT_HSCXB:
165 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
166 bus_space_write_1(t, h, ELSA_OFF_RW, data);
167 break;
168 case ISIC_WHAT_IPAC:
169 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
170 bus_space_write_1(t, h, ELSA_OFF_RW, data);
171 break;
175 /*---------------------------------------------------------------------------*
176 * ELSA QuickStep 1000pro/PCI ISAC get register routine
177 *---------------------------------------------------------------------------*/
179 static u_int8_t
180 eqs1pp_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
182 bus_space_tag_t t = sc->sc_maps[1].t;
183 bus_space_handle_t h = sc->sc_maps[1].h;
184 switch (what) {
185 case ISIC_WHAT_ISAC:
186 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
187 return bus_space_read_1(t, h, ELSA_OFF_RW);
188 case ISIC_WHAT_HSCXA:
189 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
190 return bus_space_read_1(t, h, ELSA_OFF_RW);
191 case ISIC_WHAT_HSCXB:
192 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
193 return bus_space_read_1(t, h, ELSA_OFF_RW);
194 case ISIC_WHAT_IPAC:
196 bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
197 return bus_space_read_1(t, h, ELSA_OFF_RW);
201 return 0;
204 /*---------------------------------------------------------------------------*
205 * isic_attach_Eqs1pp - attach for ELSA QuickStep 1000pro/PCI
206 *---------------------------------------------------------------------------*/
209 isic_attach_Eqs1pp(struct pci_isic_softc *psc, struct pci_attach_args *pa)
211 struct isic_softc *sc = &psc->sc_isic;
213 /* setup io mappings */
214 sc->sc_num_mappings = 2;
215 MALLOC_MAPS(sc);
216 sc->sc_maps[0].size = 0;
217 if (pci_mapreg_map(pa, ELSA_PORT0_MEM_MAPOFF, PCI_MAPREG_TYPE_MEM, 0,
218 &sc->sc_maps[0].t, &sc->sc_maps[0].h, &psc->sc_base, &psc->sc_size) != 0
219 && pci_mapreg_map(pa, ELSA_PORT0_IO_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
220 &sc->sc_maps[0].t, &sc->sc_maps[0].h, &psc->sc_base, &psc->sc_size) != 0) {
221 aprint_error_dev(&sc->sc_dev, "can't map card registers\n");
222 return (0);
225 /* PLX9050 Errata #1 */
226 if (PCI_REVISION(pa->pa_class) == 1 && psc->sc_base & 0x00000080) {
227 #ifdef DEBUG
228 printf("%s: no LCR access\n", device_xname(&sc->sc_dev));
229 #endif
230 } else
231 psc->flags |= PCIISIC_LCROK;
233 sc->sc_maps[1].size = 0;
234 if (pci_mapreg_map(pa, ELSA_PORT1_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
235 &sc->sc_maps[1].t, &sc->sc_maps[1].h, NULL, NULL)) {
236 aprint_error_dev(&sc->sc_dev, "can't map i/o space\n");
237 return (0);
240 /* setup access routines */
242 sc->clearirq = NULL;
243 sc->readreg = eqs1pp_read_reg;
244 sc->writereg = eqs1pp_write_reg;
246 sc->readfifo = eqs1pp_read_fifo;
247 sc->writefifo = eqs1pp_write_fifo;
249 sc->drv_command = elsa_cmd_req;
251 /* setup card type */
253 sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
255 /* setup IOM bus type */
257 sc->sc_bustyp = BUS_TYPE_IOM2;
259 /* setup chip type = IPAC ! */
261 sc->sc_ipac = 1;
262 sc->sc_bfifolen = IPAC_BFIFO_LEN;
264 IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
265 IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
266 (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
267 IPAC_WRITE(IPAC_ATX, ELSA_NO_LED); /* set all output lines high */
268 callout_init(&((struct pci_isic_softc *)sc)->ledcallout, 0);
270 /* disable any interrupts */
271 IPAC_WRITE(IPAC_MASK, 0xff);
272 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 0x4c, 0x01);
274 return (1);
278 isic_intr_qs1p(void *vsc)
280 struct pci_isic_softc *psc = vsc;
281 struct isic_softc *sc = &psc->sc_isic;
282 u_int32_t intcsr;
285 * if we are not hit by the PLX bug we can try a shortcut
286 * (should improve speed for shared IRQs)
288 if (psc->flags & PCIISIC_LCROK) {
289 intcsr = bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h,
290 0x4c /* INTCSR */);
291 if (!(intcsr & 0x4 /* LINTi1STAT */))
292 return (0);
295 return (isicintr(sc));
298 static void
299 elsa_cmd_req(struct isic_softc *sc, int cmd, void *data)
301 intptr_t v;
302 int s;
303 struct pci_isic_softc *psc = (struct pci_isic_softc *)sc;
305 switch (cmd) {
306 case CMR_DOPEN:
307 s = splnet();
308 /* enable hscx/isac irq's */
309 IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
310 /* enable card interrupt */
311 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 0x4c, 0x41);
312 splx(s);
313 break;
314 case CMR_DCLOSE:
315 s = splnet();
316 callout_stop(&psc->ledcallout);
317 IPAC_WRITE(IPAC_ATX, ELSA_NO_LED);
318 IPAC_WRITE(IPAC_MASK, 0xff);
319 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 0x4c, 0x01);
320 splx(s);
321 break;
322 case CMR_SETLEDS:
323 v = (intptr_t)data;
324 callout_stop(&psc->ledcallout);
326 /* the magic value and keep reset off */
327 psc->ledstat = ELSA_NO_LED;
328 psc->ledblinkmask = 0;
329 psc->ledblinkfreq = 0;
331 /* now see what LEDs we want to add */
332 if (v & CMRLEDS_TEI)
333 psc->ledstat &= ~ELSA_GREEN_LED;
335 if (v & (CMRLEDS_B0|CMRLEDS_B1)) {
336 psc->ledstat &= ~ELSA_YELLOW_LED;
337 psc->ledblinkmask |= ELSA_YELLOW_LED;
338 if ((v & (CMRLEDS_B0|CMRLEDS_B1))
339 == (CMRLEDS_B0|CMRLEDS_B1))
340 psc->ledblinkfreq = hz/4;
341 else
342 psc->ledblinkfreq = hz;
345 elsa_led_handler(psc);
346 break;
350 static void
351 elsa_led_handler(void *token)
353 struct pci_isic_softc *psc = token;
354 struct isic_softc *sc = token; /* XXX */
355 int s;
357 s = splnet();
358 IPAC_WRITE(IPAC_ATX, psc->ledstat);
359 splx(s);
360 if (psc->ledblinkfreq) {
361 psc->ledstat ^= psc->ledblinkmask;
362 callout_reset(&psc->ledcallout, psc->ledblinkfreq,
363 elsa_led_handler, psc);