2 * Copyright (c) 2000 Hans Petter Selasky. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_ihfc_l1.c - hfc layer 1 handler
28 * -----------------------------------
30 * The idea of this file is to separate hfcs/sp/pci data/signal
31 * handling and the I4B data/signal handling.
33 * Everything which has got anything to do with I4B has been put here!
35 * last edit-date: [Wed Jul 19 09:41:03 2000]
37 * $Id: i4b_ihfc_l1if.c,v 1.10 2000/09/19 13:50:36 hm Exp $
39 * $FreeBSD: src/sys/i4b/layer1/ihfc/i4b_ihfc_l1if.c,v 1.7.2.1 2001/08/10 14:08:37 obrien Exp $
40 * $DragonFly: src/sys/net/i4b/layer1/ihfc/i4b_ihfc_l1if.c,v 1.4 2003/08/07 21:17:26 dillon Exp $
42 *---------------------------------------------------------------------------*/
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
52 #include <sys/socket.h>
57 #include <net/i4b/include/machine/i4b_debug.h>
58 #include <net/i4b/include/machine/i4b_ioctl.h>
59 #include <net/i4b/include/machine/i4b_trace.h>
61 #include "../../include/i4b_mbuf.h"
62 #include "../../include/i4b_global.h"
64 #include "../i4b_l1.h"
66 #include "i4b_ihfc_ext.h"
68 /*---------------------------------------------------------------------------*
71 * NOTE: The prototypes for get/putmbuf and B_linkinit
72 * have been put in i4b_hfc_ext.h for global hfc use.
74 * NOTE: channel != chan
75 *---------------------------------------------------------------------------*/
77 isdn_link_t * ihfc_B_ret_linktab (int unit, int channel);
78 static void ihfc_B_set_linktab (int unit, int channel, drvr_link_t *B_linktab);
80 static void ihfc_B_start (int unit, int chan);
81 static void ihfc_B_stat (int unit, int chan, bchan_statistics_t *bsp);
82 void ihfc_B_setup (int unit, int chan, int bprot, int activate);
84 static int ihfc_mph_command_req (int unit, int command, void *parm);
86 static int ihfc_ph_activate_req (int unit);
87 static int ihfc_ph_data_req (int unit, struct mbuf *m, int freeflag);
89 static void ihfc_T3_expired (ihfc_sc_t *sc);
91 /*---------------------------------------------------------------------------*
92 * Our I4B L1 mulitplexer link
93 *---------------------------------------------------------------------------*/
94 struct i4b_l1mux_func ihfc_l1mux_func = {
102 /*---------------------------------------------------------------------------*
103 * L2 -> L1: PH-DATA-REQUEST (D-Channel)
105 * NOTE: We may get called here from ihfc_hdlc_Dread or isac_hdlc_Dread
106 * via the upper layers.
107 *---------------------------------------------------------------------------*/
109 ihfc_ph_data_req(int unit, struct mbuf *m, int freeflag)
111 ihfc_sc_t *sc = &ihfc_softc[unit];
121 NDBGL1(L1_PRIM, "L1 was not running: "
122 "ihfc_ph_activate_req(unit = %d)!", unit);
124 ihfc_ph_activate_req(unit);
127 /* "Allow" I-frames (-hp) */
129 if (freeflag == MBUF_DONTFREE) m = m_copypacket(m, M_DONTWAIT);
131 if (!_IF_QFULL(&S_IFQUEUE) && m)
133 IF_ENQUEUE(&S_IFQUEUE, m);
135 ihfc_B_start(unit, chan); /* (recycling) */
139 NDBGL1(L1_ERROR, "No frame out (unit = %d)", unit);
140 if (m) i4b_Dfreembuf(m);
146 if (S_INTR_ACTIVE) S_INT_S1 |= 0x04;
153 /*---------------------------------------------------------------------------*
154 * L2 -> L1: PH-ACTIVATE-REQUEST (B-channel and D-channel)
155 *---------------------------------------------------------------------------*/
157 ihfc_ph_activate_req(int unit)
159 ihfc_sc_t *sc = &ihfc_softc[unit];
164 if ((!S_STM_T3) && (S_PHSTATE != 3))
169 S_STM_T3CALLOUT = timeout((TIMEOUT_FUNC_T)
170 ihfc_T3_expired, (ihfc_sc_t *)sc,
171 IHFC_ACTIVATION_TIMEOUT);
177 /*---------------------------------------------------------------------------*
178 * T3 timeout - persistant deactivation
179 *---------------------------------------------------------------------------*/
181 ihfc_T3_expired(ihfc_sc_t *sc)
190 if (S_PHSTATE != 3) /* line was not activated */
192 i4b_Dcleanifq(&S_IFQUEUE);
193 i4b_l1_ph_deactivate_ind(S_I4BUNIT);
195 i4b_l1_mph_status_ind(S_I4BUNIT, STI_PDEACT, 0, 0);
197 HFC_FSM(sc, 2); /* L1 deactivate */
203 /*---------------------------------------------------------------------------*
204 * Command from the upper layers (B-channel and D-channel)
205 *---------------------------------------------------------------------------*/
207 ihfc_mph_command_req(int unit, int command, void *parm)
209 ihfc_sc_t *sc = &ihfc_softc[unit];
213 case CMR_DOPEN: /* daemon running */
215 "unit %d, command = CMR_DOPEN", unit);
219 case CMR_DCLOSE: /* daemon not running */
221 "unit %d, command = CMR_DCLOSE", unit);
225 case CMR_SETTRACE: /* set new trace mask */
227 "unit %d, command = CMR_SETTRACE, parm = %d",
228 unit, (unsigned int)parm);
229 S_TRACE = (unsigned int)parm;
232 case CMR_GCST: /* get chip statistic */
234 "unit %d, command = CMR_GCST, parm = %d",
235 unit, (unsigned int)parm);
237 #define CST ((struct chipstat *)parm)
239 CST->driver_type = L1DRVR_IHFC;
241 /* XXX CST->xxxx_stat = xxx; */
248 "ERROR, unknown command = %d, unit = %d, parm = %d",
249 command, unit, (unsigned int)parm);
256 /*---------------------------------------------------------------------------*
257 * Data source switch for Read channels - 1, 3 and 5 (B and D-Channel)
258 *---------------------------------------------------------------------------*/
260 ihfc_putmbuf (ihfc_sc_t *sc, u_char chan, struct mbuf *m)
266 if(S_TRACE & TRACE_D_RX)
268 hdr.count = ++S_DTRACECOUNT;
271 hdr.unit = S_I4BUNIT;
275 i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
278 if (!S_ENABLED) { i4b_Dfreembuf(m); return; }
280 m->m_pkthdr.len = m->m_len;
282 i4b_l1_ph_data_ind(S_I4BUNIT, m);
286 if(S_TRACE & TRACE_B_RX)
288 hdr.count = ++S_BTRACECOUNT;
290 hdr.type = (chan < 4) ? TRC_CH_B1 : TRC_CH_B2;
291 hdr.unit = S_I4BUNIT;
295 i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
298 if (!S_ENABLED) { i4b_Bfreembuf(m); return; }
300 if (S_PROT == BPROT_NONE)
302 if(!i4b_l1_bchan_tel_silence(m->m_data, m->m_len))
304 S_BDRVLINK->bch_activity(S_BDRVLINK->unit, ACT_RX);
307 if (!_IF_QFULL(&S_IFQUEUE))
310 IF_ENQUEUE(&S_IFQUEUE, m);
311 S_BDRVLINK->bch_rx_data_ready(S_BDRVLINK->unit);
317 if (S_PROT == BPROT_RHDLC)
320 S_BYTES += m->m_pkthdr.len = m->m_len;
321 S_BDRVLINK->bch_rx_data_ready(S_BDRVLINK->unit);
327 NDBGL1(L1_ERROR, "Unknown protocol: %d", S_PROT);
331 /*---------------------------------------------------------------------------*
332 * Data destinator switch for write channels - 0, 2 and 4
333 *---------------------------------------------------------------------------*/
335 ihfc_getmbuf (ihfc_sc_t *sc, u_char chan)
342 IF_DEQUEUE(&S_IFQUEUE, m);
344 if((S_TRACE & TRACE_D_TX) && m)
346 hdr.count = ++S_DTRACECOUNT;
349 hdr.unit = S_I4BUNIT;
353 i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
358 IF_DEQUEUE(&S_IFQUEUE, m);
362 S_BDRVLINK->bch_tx_queue_empty(S_BDRVLINK->unit);
364 IF_DEQUEUE(&S_IFQUEUE, m);
368 if(!i4b_l1_bchan_tel_silence(m->m_data, m->m_len))
370 S_BDRVLINK->bch_activity(S_BDRVLINK->unit, ACT_TX);
375 if(S_TRACE & TRACE_B_TX)
377 hdr.count = ++S_BTRACECOUNT;
379 hdr.type = (chan < 4) ? TRC_CH_B1 : TRC_CH_B2;
380 hdr.unit = S_I4BUNIT;
384 i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
392 /*---------------------------------------------------------------------------*
393 * Initialize rx/tx data structures (B-channel)
394 *---------------------------------------------------------------------------*/
396 ihfc_B_setup(int unit, int chan, int bprot, int activate)
398 ihfc_sc_t *sc = &ihfc_softc[unit];
401 if (((u_int)chan > 5) || ((u_int)chan < 2)) return;
405 HFC_INIT(sc, chan, bprot, activate);
410 /*---------------------------------------------------------------------------*
411 * Start transmission (B-channel or D-channel tx)
412 * NOTE: if "chan" variable is corrupted, it will not cause any harm,
413 * but data may be lost and there may be software sync. errors.
414 *---------------------------------------------------------------------------*/
416 ihfc_B_start(int unit, int chan)
418 ihfc_sc_t *sc = &ihfc_softc[unit];
421 if ((u_int)chan > 5) return;
425 if (S_FILTER && !S_MBUF && !S_INTR_ACTIVE)
427 S_INTR_ACTIVE |= 2; /* never know what *
431 S_FILTER(sc, chan); /* quick tx */
439 /*---------------------------------------------------------------------------*
440 * Fill statistics struct (B-channel)
441 *---------------------------------------------------------------------------*/
443 ihfc_B_stat(int unit, int chan, bchan_statistics_t *bsp)
445 ihfc_sc_t *sc = &ihfc_softc[unit];
448 if ((u_int)chan > 5) return;
454 bsp->inbytes = S_BYTES; S_BYTES = 0;
458 bsp->outbytes = S_BYTES; S_BYTES = 0;
463 /*---------------------------------------------------------------------------*
464 * Return the address of IHFC linktab to I4B (B-channel)
465 *---------------------------------------------------------------------------*/
467 ihfc_B_ret_linktab(int unit, int channel)
469 ihfc_sc_t *sc = &ihfc_softc[unit];
472 return(&sc->sc_blinktab[channel]);
477 /*---------------------------------------------------------------------------*
478 * Set the I4B driver linktab for IHFC use (B-channel)
479 *---------------------------------------------------------------------------*/
481 ihfc_B_set_linktab(int unit, int channel, drvr_link_t *B_linktab)
483 ihfc_sc_t *sc = &ihfc_softc[unit];
486 sc->sc_bdrvlinktab[channel] = B_linktab;
489 /*---------------------------------------------------------------------------*
490 * Initialize linktab for I4B use (B-channel)
491 *---------------------------------------------------------------------------*/
493 ihfc_B_linkinit(ihfc_sc_t *sc)
497 /* make sure the hardware driver is known to layer 4 */
498 ctrl_types[CTRL_PASSIVE].set_linktab = i4b_l1_set_linktab;
499 ctrl_types[CTRL_PASSIVE].get_linktab = i4b_l1_ret_linktab;
501 for (chan = 2; chan < 6; chan++)
503 S_BLINK.unit = S_UNIT;
504 S_BLINK.channel = chan; /* point to tx-chan */
505 S_BLINK.bch_config = ihfc_B_setup;
506 S_BLINK.bch_tx_start = ihfc_B_start;
507 S_BLINK.bch_stat = ihfc_B_stat;
509 /* This is a transmit channel (even) */
510 S_BLINK.tx_queue = &S_IFQUEUE;
512 /* This is a receive channel (odd) */
513 S_BLINK.rx_queue = &S_IFQUEUE;
514 S_BLINK.rx_mbuf = &S_MBUFDUMMY;
518 #endif /* NIHFC > 0 */