Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / iwic_dchan.c
blob8256a40731148d3b12ce424fcdf07733202be6be
1 /* $NetBSD: iwic_dchan.c,v 1.5 2007/10/19 12:00:50 ad 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 13:20:14 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: iwic_dchan.c,v 1.5 2007/10/19 12:00:50 ad Exp $");
41 #include <sys/param.h>
42 #include <sys/kernel.h>
43 #include <sys/systm.h>
44 #include <sys/mbuf.h>
45 #include <sys/callout.h>
46 #include <net/if.h>
48 #include <sys/bus.h>
50 #include <dev/pci/pcivar.h>
52 #include <dev/pci/iwicreg.h>
53 #include <dev/pci/iwicvar.h>
55 #include <netisdn/i4b_global.h>
56 #include <netisdn/i4b_mbuf.h>
58 #define MAX_DFRAME_LEN 264
60 static void dchan_receive(struct iwic_softc *sc, int ista);
62 /*---------------------------------------------------------------------------*
63 * initialize D-channel variables and registers
64 *---------------------------------------------------------------------------*/
65 void
66 iwic_dchan_init(struct iwic_softc *sc)
68 sc->sc_dchan.ibuf = NULL;
69 sc->sc_dchan.rx_count = 0;
71 sc->sc_dchan.obuf = NULL;
72 sc->sc_dchan.obuf2 = NULL;
73 sc->sc_dchan.tx_count = 0;
74 sc->sc_dchan.tx_ready = 0;
76 IWIC_WRITE(sc, D_CTL, D_CTL_SRST);
78 DELAY(5000);
80 IWIC_WRITE(sc, D_CTL, 0);
82 IWIC_WRITE(sc, SQX, SQX_SCIE);
84 IWIC_WRITE(sc, PCTL, 0x00);
85 IWIC_WRITE(sc, MOCR, 0x00);
86 IWIC_WRITE(sc, GCR, 0x00);
88 IWIC_WRITE(sc, D_CMDR, D_CMDR_RRST | D_CMDR_XRST);
89 IWIC_WRITE(sc, D_MODE, D_MODE_RACT);
91 IWIC_WRITE(sc, D_SAM, 0xff);
92 IWIC_WRITE(sc, D_TAM, 0xff);
94 IWIC_WRITE(sc, D_EXIM, 0x00);
97 /*---------------------------------------------------------------------------*
98 * Extended IRQ handler for the D-channel
99 *---------------------------------------------------------------------------*/
100 void
101 iwic_dchan_xirq(struct iwic_softc *sc)
103 int irq_stat;
104 int stat;
106 irq_stat = IWIC_READ(sc, D_EXIR);
108 if (irq_stat & D_EXIR_RDOV)
110 NDBGL1(L1_I_ERR, "RDOV in state %s", iwic_printstate(sc));
111 IWIC_WRITE(sc, D_CMDR, D_CMDR_RRST);
113 if (irq_stat & D_EXIR_XDUN)
115 NDBGL1(L1_I_ERR, "XDUN in state %s", iwic_printstate(sc));
116 sc->sc_dchan.tx_ready = 0;
118 if (irq_stat & D_EXIR_XCOL)
120 NDBGL1(L1_I_ERR, "XCOL in state %s", iwic_printstate(sc));
121 IWIC_WRITE(sc, D_CMDR, D_CMDR_XRST);
122 sc->sc_dchan.tx_ready = 0;
124 if (irq_stat & D_EXIR_TIN2)
126 NDBGL1(L1_I_ERR, "TIN2 in state %s", iwic_printstate(sc));
128 if (irq_stat & D_EXIR_MOC)
130 stat = IWIC_READ(sc, MOR);
131 NDBGL1(L1_I_ERR, "MOC in state %s, byte = 0x%x", iwic_printstate(sc), stat);
134 if (irq_stat & D_EXIR_ISC)
136 stat = (IWIC_READ(sc, CIR)) & 0x0f;
138 switch (stat)
140 case CIR_CE:
141 NDBGL1(L1_I_CICO, "rx CE in state %s", iwic_printstate(sc));
142 iwic_next_state(sc, EV_CE);
143 break;
144 case CIR_DRD:
145 NDBGL1(L1_I_CICO, "rx DRD in state %s", iwic_printstate(sc));
146 iwic_next_state(sc, EV_INFO0);
147 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_IDLE);
148 break;
149 case CIR_LD:
150 NDBGL1(L1_I_CICO, "rx LD in state %s", iwic_printstate(sc));
151 iwic_next_state(sc, EV_RSY);
152 break;
153 case CIR_ARD:
154 NDBGL1(L1_I_CICO, "rx ARD in state %s", iwic_printstate(sc));
155 iwic_next_state(sc, EV_INFO2);
156 break;
157 case CIR_TI:
158 NDBGL1(L1_I_CICO, "rx TI in state %s", iwic_printstate(sc));
159 iwic_next_state(sc, EV_INFO0);
160 break;
161 case CIR_ATI:
162 NDBGL1(L1_I_CICO, "rx ATI in state %s", iwic_printstate(sc));
163 iwic_next_state(sc, EV_INFO0);
164 break;
165 case CIR_AI8:
166 NDBGL1(L1_I_CICO, "rx AI8 in state %s", iwic_printstate(sc));
167 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
168 iwic_next_state(sc, EV_INFO48);
169 break;
170 case CIR_AI10:
171 NDBGL1(L1_I_CICO, "rx AI10 in state %s", iwic_printstate(sc));
172 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
173 iwic_next_state(sc, EV_INFO410);
174 break;
175 case CIR_CD:
176 NDBGL1(L1_I_CICO, "rx DIS in state %s", iwic_printstate(sc));
177 iwic_next_state(sc, EV_DIS);
178 break;
179 default:
180 NDBGL1(L1_I_ERR, "ERROR, unknown indication 0x%x in state %s", stat, iwic_printstate(sc));
181 iwic_next_state(sc, EV_INFO0);
182 break;
186 if (irq_stat & D_EXIR_TEXP)
188 NDBGL1(L1_I_ERR, "TEXP in state %s", iwic_printstate(sc));
191 if (irq_stat & D_EXIR_WEXP)
193 NDBGL1(L1_I_ERR, "WEXP in state %s", iwic_printstate(sc));
197 /*---------------------------------------------------------------------------*
198 * All receiving and transmitting takes place here.
199 *---------------------------------------------------------------------------*/
200 void
201 iwic_dchan_xfer_irq(struct iwic_softc *sc, int ista)
203 NDBGL1(L1_I_MSG, "ISTA = 0x%x", ista);
205 if (ista & (ISTA_D_RMR | ISTA_D_RME))
207 /* Receive message ready */
208 dchan_receive(sc, ista);
210 if (ista & ISTA_D_XFR)
212 /* Transmitter ready */
213 sc->sc_dchan.tx_ready = 1;
215 iwic_dchan_transmit(sc);
219 /*---------------------------------------------------------------------------*
220 * disable D-channel
221 *---------------------------------------------------------------------------*/
222 void
223 iwic_dchan_disable(struct iwic_softc *sc)
225 int s;
227 s = splnet();
229 if (sc->sc_dchan.obuf)
231 if (sc->sc_dchan.free_obuf)
232 i4b_Dfreembuf(sc->sc_dchan.obuf);
233 sc->sc_dchan.obuf = NULL;
236 if (sc->sc_dchan.obuf2)
238 if (sc->sc_dchan.free_obuf2)
239 i4b_Dfreembuf(sc->sc_dchan.obuf2);
240 sc->sc_dchan.obuf2 = NULL;
243 splx(s);
245 IWIC_WRITE(sc, CIX, CIX_DRC);
248 /*---------------------------------------------------------------------------*
249 * queue D-channel message for transmission
250 *---------------------------------------------------------------------------*/
252 iwic_dchan_data_req(struct iwic_softc *sc, struct mbuf *m, int freeflag)
254 int s;
256 if (!m)
257 return 0;
259 s = splnet();
261 /* Queue message */
263 if (sc->sc_dchan.obuf)
265 if (sc->sc_dchan.obuf2)
267 NDBGL1(L1_I_ERR, "no buffer space!");
269 else
271 sc->sc_dchan.obuf2 = m;
272 sc->sc_dchan.free_obuf2 = freeflag;
275 else
277 sc->sc_dchan.obuf = m;
278 sc->sc_dchan.obuf_ptr = m->m_data;
279 sc->sc_dchan.obuf_len = m->m_len;
280 sc->sc_dchan.free_obuf = freeflag;
283 iwic_dchan_transmit(sc);
285 splx(s);
287 return (0);
290 /*---------------------------------------------------------------------------*
291 * allocate an mbuf
292 *---------------------------------------------------------------------------*/
293 static void
294 dchan_get_mbuf(struct iwic_softc *sc, int len)
296 sc->sc_dchan.ibuf = i4b_Dgetmbuf(len);
298 if (!sc->sc_dchan.ibuf)
299 panic("dchan_get_mbuf: unable to allocate %d bytes for mbuf!", len);
301 sc->sc_dchan.ibuf_ptr = sc->sc_dchan.ibuf->m_data;
302 sc->sc_dchan.ibuf_max_len = sc->sc_dchan.ibuf->m_len;
303 sc->sc_dchan.ibuf_len = 0;
306 /*---------------------------------------------------------------------------*
307 * D-channel receive data interrupt
308 *---------------------------------------------------------------------------*/
309 static void
310 dchan_receive(struct iwic_softc *sc, int ista)
312 int command = D_CMDR_RACK;
314 if (ista & ISTA_D_RMR)
316 /* Got 64 bytes in FIFO */
318 if (!sc->sc_dchan.ibuf)
320 dchan_get_mbuf(sc, MAX_DFRAME_LEN);
323 else if ((sc->sc_dchan.ibuf_len + MAX_DFRAME_LEN) >
324 sc->sc_dchan.ibuf_max_len)
326 panic("dchan_receive: not enough space in buffer!");
329 IWIC_RDDFIFO(sc, sc->sc_dchan.ibuf_ptr, 64);
331 sc->sc_dchan.ibuf_ptr += 64;
332 sc->sc_dchan.ibuf_len += 64;
333 sc->sc_dchan.rx_count += 64;
335 if (ista & ISTA_D_RME)
337 /* Got end of frame */
338 int status;
340 status = IWIC_READ(sc, D_RSTA);
342 if (status & (D_RSTA_RDOV | D_RSTA_CRCE | D_RSTA_RMB))
344 if (status & D_RSTA_RDOV)
345 NDBGL1(L1_I_ERR, "%s: D-channel Receive Data Overflow", device_xname(&sc->sc_dev));
346 if (status & D_RSTA_CRCE)
347 NDBGL1(L1_I_ERR, "%s: D-channel CRC Error", device_xname(&sc->sc_dev));
348 if (status & D_RSTA_RMB)
349 NDBGL1(L1_I_ERR, "%s: D-channel Receive Message Aborted", device_xname(&sc->sc_dev));
350 command |= D_CMDR_RRST;
352 else
354 int hi, lo;
355 int total_frame_len;
357 lo = IWIC_READ(sc, D_RBCL);
358 hi = IWIC_READ(sc, D_RBCH);
359 total_frame_len = D_RBC(hi, lo);
360 lo = lo & 0x3f;
362 if (lo == 0)
363 lo = IWIC_DCHAN_FIFO_LEN;
365 if (!sc->sc_dchan.ibuf)
367 dchan_get_mbuf(sc, lo);
369 else if ((sc->sc_dchan.ibuf_len + lo) >
370 sc->sc_dchan.ibuf_max_len)
372 panic("dchan_receive: buffer not long enough");
375 IWIC_RDDFIFO(sc, sc->sc_dchan.ibuf_ptr, lo);
376 sc->sc_dchan.ibuf_len += lo;
377 sc->sc_dchan.rx_count += lo;
379 sc->sc_dchan.ibuf->m_len = sc->sc_dchan.ibuf_len;
381 if(sc->sc_trace & TRACE_D_RX)
383 i4b_trace_hdr hdr;
384 hdr.type = TRC_CH_D;
385 hdr.dir = FROM_NT;
386 hdr.count = ++sc->sc_dchan.trace_count;
387 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_dchan.ibuf->m_len, sc->sc_dchan.ibuf->m_data);
389 isdn_layer2_data_ind(&sc->sc_l2,sc->sc_l3token,sc->sc_dchan.ibuf);
391 sc->sc_dchan.ibuf = NULL;
394 IWIC_WRITE(sc, D_CMDR, command);
397 /*---------------------------------------------------------------------------*
398 * transmit D-channel frame
399 *---------------------------------------------------------------------------*/
400 void
401 iwic_dchan_transmit(struct iwic_softc *sc)
403 int cmd;
404 u_char *ptr;
405 int len;
407 if (!sc->sc_dchan.tx_ready)
408 return;
410 if (!sc->sc_dchan.obuf)
411 return;
413 if (sc->sc_I430state != ST_F7)
414 return;
416 ptr = sc->sc_dchan.obuf_ptr;
417 len = min(sc->sc_dchan.obuf_len, IWIC_DCHAN_FIFO_LEN);
419 if(sc->sc_trace & TRACE_D_TX)
421 i4b_trace_hdr hdr;
422 hdr.type = TRC_CH_D;
423 hdr.dir = FROM_TE;
424 hdr.count = ++sc->sc_dchan.trace_count;
425 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, len, ptr);
428 IWIC_WRDFIFO(sc, ptr, len);
430 sc->sc_dchan.tx_count += len;
432 if (len < sc->sc_dchan.obuf_len)
434 sc->sc_dchan.obuf_ptr += len;
435 sc->sc_dchan.obuf_len -= len;
437 cmd = D_CMDR_XMS;
440 else
442 if (sc->sc_dchan.free_obuf)
443 i4b_Dfreembuf(sc->sc_dchan.obuf);
445 sc->sc_dchan.obuf = NULL;
446 sc->sc_dchan.obuf_ptr = NULL;
447 sc->sc_dchan.obuf_len = 0;
449 if (sc->sc_dchan.obuf2)
451 sc->sc_dchan.obuf = sc->sc_dchan.obuf2;
452 sc->sc_dchan.obuf_ptr = sc->sc_dchan.obuf->m_data;
453 sc->sc_dchan.obuf_len = sc->sc_dchan.obuf->m_len;
454 sc->sc_dchan.free_obuf = sc->sc_dchan.free_obuf2;
456 sc->sc_dchan.obuf2 = NULL;
458 cmd = D_CMDR_XMS | D_CMDR_XME;
460 sc->sc_dchan.tx_ready = 0;
461 IWIC_WRITE(sc, D_CMDR, cmd);