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_drv.c - ihfc ISA PnP-bus interface
28 * -------------------------------------------
30 * Everything which has got anything to do with the
31 * HFC-1/S/SP chips has been put here.
33 * last edit-date: [Fri Jan 12 17:06:52 2001]
35 * $FreeBSD: src/sys/i4b/layer1/ihfc/i4b_ihfc_drv.c,v 1.9.2.1 2001/08/10 14:08:37 obrien Exp $
36 * $DragonFly: src/sys/net/i4b/layer1/ihfc/i4b_ihfc_drv.c,v 1.7 2005/06/15 11:56:03 joerg Exp $
38 *---------------------------------------------------------------------------*/
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/socket.h>
47 #include <sys/thread2.h>
52 #include "../../include/i4b_mbuf.h"
54 #include <net/i4b/include/machine/i4b_debug.h>
55 #include <net/i4b/include/machine/i4b_ioctl.h>
56 #include <net/i4b/include/machine/i4b_trace.h>
58 #include "../i4b_l1.h"
59 #include "../i4b_hdlc.h"
61 #include "i4b_ihfc_ext.h"
62 #include "i4b_ihfc_drv.h"
64 #include <machine/bus.h>
68 /*---------------------------------------------------------------------------*
70 *---------------------------------------------------------------------------*/
71 void ihfc_loadconfig (ihfc_sc_t *sc);
73 static void ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan);
74 static void ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan);
75 static void ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan);
76 static void ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan);
77 static void ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan);
78 static void ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan);
80 static void ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan);
81 static void ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan);
83 void ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr);
84 void ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir);
86 void ihfc_sq (ihfc_sc_t *sc);
88 static void ihfc_test_Bread (ihfc_sc_t *sc, u_char chan);
89 static void ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan);
91 u_short ihfc_Bsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
92 u_int32_t ihfc_Dsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
95 /*---------------------------------------------------------------------------*
96 * Commonly used ISA bus commands
97 *---------------------------------------------------------------------------*/
98 #define IHFC_DATA_OFFSET 0
99 #define IHFC_REG_OFFSET 1
101 #define BUS_VAR bus_space_handle_t h = rman_get_bushandle(S_IOBASE[0]); \
102 bus_space_tag_t t = rman_get_bustag (S_IOBASE[0])
104 #define SET_REG(reg) bus_space_write_1(t,h, IHFC_REG_OFFSET, reg)
105 #define GET_STAT bus_space_read_1 (t,h, IHFC_REG_OFFSET)
107 #define READ_DATA_1 bus_space_read_1 (t,h, IHFC_DATA_OFFSET)
108 #define READ_BOTH_2 bus_space_read_2 (t,h, IHFC_DATA_OFFSET)
110 #define WRITE_DATA_1(data) bus_space_write_1(t,h, IHFC_DATA_OFFSET, data)
111 #define WRITE_BOTH_2(data) bus_space_write_2(t,h, IHFC_DATA_OFFSET, data)
113 #define DISBUSY(okcmd, tocmd) \
118 u_int to = IHFC_DISBUSYTO; \
120 while(((a = GET_STAT) & 1) && --to); \
124 NDBGL1(L1_ERROR, "DISBUSY-TIMEOUT! (a=%04x, " \
125 "unit=%d)", a, S_UNIT); \
139 #define WAITBUSY_2(okcmd, tocmd) \
142 u_int to = IHFC_NONBUSYTO; \
144 while((~(a = READ_BOTH_2) & 0x100) && --to); \
148 NDBGL1(L1_ERROR, "NONBUSY-TIMEOUT! (a=%04x, " \
149 "unit=%d)", a, S_UNIT); \
158 /*---------------------------------------------------------------------------*
159 * Control function (HFC-1/S/SP)
162 * 1: reset and unlock chip (at boot only)
163 * 2: prepare for shutdown (at shutdown only)
164 * 3: reset and resume
165 * 4: select TE-mode (boot default)
166 * 5: select NT-mode (only HFC-S/SP/PCI)
168 * Returns != 0 on errornous chip
169 *---------------------------------------------------------------------------*/
171 ihfc_control(ihfc_sc_t *sc, int flag)
175 if (flag == 3) goto reset0;
188 WRITE_BOTH_2(0x5400 | S_IIO); /* enable IO (HFC-1/S) */
192 /* HFC-S/SP configuration */
194 S_CIRM = S_IIRQ|0x10; /* IRQ, 8K fifo mode */
195 S_CLKDEL = 0x00; /* 12.288mhz */
196 S_CTMT = 0x03; /* transperant mode */
197 S_CONNECT = 0x00; /* B channel data flow */
198 S_INT_M1 = 0x40; /* interrupt mask */
199 S_INT_M2 = 0x08; /* enable interrupt output */
200 S_MST_MODE = 0x01; /* master mode */
201 S_SCTRL = 0x50; /* S/Q on, non cap. line mode */
202 S_SCTRL_R = 0x00; /* B channel receive disable */
203 S_TEST = 0x00; /* no need for awake enable */
205 if (S_HFC & (HFC_1 | HFC_S)) /* configure timer (50ms) */
214 /* HFC-1 ISAC configuration (IOM-2 mode) */
217 S_ADF2 = 0x80; /* select mode IOM-2 */
218 S_SPCR = 0x00; /* B channel send disable (0x10 for test loop) */
219 S_MASK = 0xfb; /* enable CISQ */
220 S_MODE = 0xc9; /* receiver enabled */
221 S_SQXR = 0x0f; /* master, clock always active */
222 S_STCR = 0x70; /* TIC bus address = 7 */
223 S_STAR2 = 0x04; /* enable S/Q */
226 if (S_NTMODE) /* configure NT- or TE-mode */
228 S_SCTRL |= 0x04; /* NT mode */
229 S_CLKDEL &= ~0x7f; /* clear delay */
230 S_CLKDEL |= 0x6c; /* set delay */
234 S_SCTRL &= ~0x04; /* TE mode */
235 S_STDEL &= 0x7f; /* use mask! */
236 S_CLKDEL &= ~0x7f; /* clear delay */
237 S_CLKDEL |= S_STDEL; /* set delay */
239 if (S_DLP) /* configure D-priority */
241 S_SCTRL |= 0x08; /* (10/11) */
245 S_SCTRL &= ~0x08; /* (8/9) */
249 /* chip reset (HFC-1/S/SP) */
253 SET_REG((S_CIRM | 0xc8) & 0xdf);
255 DELAY(10); /* HFC-2B manual recommends a 4 *
256 * clock cycle delay after CIRM *
257 * write with reset=1. A 1us *
258 * delay, should do for 7.68mhz,*
259 * but just in case I make that *
262 SET_REG((S_CIRM | 0xc0) & 0xdf);
264 DELAY(250); /* ISAC manual says reset pulse *
265 * length is 125us. Accessing *
266 * ISAC before those 125us, we *
267 * may risk chip corruption and *
268 * irq failure. The HFC-2B also *
269 * needs some delay to recover, *
270 * so we add some us. */
276 WRITE_DATA_1(S_CIRM | 8);
278 DELAY(10); /* HFC-2BDS0 manual recommends *
279 * a 4 clock cycle delay after *
280 * CIRM write with reset=1. *
281 * A 1us delay, should do for *
282 * 12.288mhz, but just in case *
283 * I make that 10us. */
285 WRITE_DATA_1(S_CIRM);
287 DELAY(25); /* HFC-2BDS0 needs some time to *
288 * recover after CIRM write *
289 * with reset=0. Experiments *
290 * show this delay should be *
291 * 8-9us. Just in case we make *
296 /* HFC-1/S/SP chip test *
298 * NOTE: after reset the HFC-1/S/SP should be *
299 * in a mode where it is always non-busy/non- *
300 * processing, and bit[0] of STATUS/DISBUSY *
301 * register, should always return binary '0' *
302 * until we configure the chips for normal *
305 printf("ihfc: GET_STAT value is: 0x%x\n", GET_STAT);
309 if ((GET_STAT & 1) || (READ_DATA_1 & 0xf)) goto f0;
314 if (S_HFC & HFC_1) ihfc_cmdr_hdlr(sc, 0x41); /* rres, xres */
322 if (S_HFC & HFC_1) S_CIRM &= ~0x03; /* disable interrupt */
324 S_SQXR |= 0x40; /* power down */
329 S_SPCR &= ~0x0f; /* send 1's only */
330 S_SCTRL &= ~0x83; /* send 1's only + enable oscillator */
335 return(0); /* success */
338 return(1); /* failure */
341 /*---------------------------------------------------------------------------*
342 * Softc initializer and hardware setup (HFC-1/S/SP)
344 * Returns: 0 on success
346 *---------------------------------------------------------------------------*/
348 ihfc_init (ihfc_sc_t *sc, u_char chan, int prot, int activate)
350 if (chan > 5) goto f0;
355 { if (chan < 2) /* D-Channel */
357 i4b_Dfreembuf(S_MBUF);
358 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Dcleanifq(&S_IFQUEUE);
360 RESET_SOFT_CHAN(sc, chan);
362 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
364 if (!activate) continue;
368 S_FILTER = (chan & 1) ? ihfc_isac_Dread :
373 S_FILTER = (chan & 1) ? ihfc_hdlc_Dread :
379 i4b_Bfreembuf(S_MBUF);
380 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Bcleanifq(&S_IFQUEUE);
382 RESET_SOFT_CHAN(sc, chan);
384 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
388 if (!activate) continue;
392 S_FILTER = (chan & 1) ?
397 S_FILTER = (chan & 1) ?
402 S_FILTER = (chan & 1) ?
408 } while (++chan & 1);
410 S_MASK |= 0xfb; /* disable all, but CISQ interrupt (ISAC) */
411 S_INT_M1 &= 0x40; /* disable all, but TE/NT state machine (HFC) */
412 S_SCTRL &= ~0x03; /* B1/B2 send disable (HFC) */
413 S_SPCR &= ~0x0f; /* B1/B2 send disable (ISAC) */
414 S_SCTRL_R &= ~0x03; /* B1/B2 receive disable (HFC) */
417 if (S_FILTER) /* D-Channel active */
419 S_MASK &= 0x2e; /* enable RME, RPF, XPR, EXI */
420 S_INT_M1 |= 0x24; /* enable D-receive, D-transmit */
424 if (S_FILTER) /* B1-Channel active */
426 S_SCTRL |= 1; /* send enable (HFC) */
427 S_SPCR |= 8; /* send enable (ISAC) */
428 S_SCTRL_R |= 1; /* receive enable (HFC) */
429 S_INT_M1 |= 0x80; /* timer enable (HFC) */
430 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
434 if (S_FILTER) /* B2-Channel active */
436 S_SCTRL |= 2; /* send enable (HFC) */
437 S_SPCR |= 2; /* send enable (ISAC) */
438 S_SCTRL_R |= 2; /* receive enable (HFC) */
439 S_INT_M1 |= 0x80; /* timer enable (HFC) */
440 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
445 /* XXX reset timer? */
447 return 0; /* success */
449 return 1; /* failure */
452 /*---------------------------------------------------------------------------*
453 * Load configuration data (HFC-1/S/SP)
454 *---------------------------------------------------------------------------*/
456 ihfc_loadconfig(ihfc_sc_t *sc)
462 /* HFC-1 chips w/ISAC: */
464 const u_char *src = (void *)&S_ISAC_CONFIG;
465 const u_char *dst = (void *)&isac_configtable;
467 SET_REG((S_CIRM | 0xc0) & 0xdf);
469 S_CTMT = (S_CTMT & ~0x14) | ((S_INT_M1 >> 5) & 0x4);
471 SET_REG((S_CTMT | 0xe0) & 0xff);
475 SET_REG(*dst++); /* set register */
477 /* write configuration */
478 DISBUSY(WRITE_DATA_1(*src++), break);
483 /* HFC-S/SP chips: */
485 const u_char *src = (void *)&S_HFC_CONFIG;
486 const u_char *dst = (void *)&ihfc_configtable;
490 SET_REG(*dst++); /* set register */
491 WRITE_DATA_1(*src++); /* write configuration */
496 /*---------------------------------------------------------------------------*
497 * Function State Machine handler (PH layer) (HFC-1/S/SP)
499 * Flag: 0 = Refresh softc S_PHSTATE + take hints
503 * NOTE: HFC-1 only supports TE mode.
504 *---------------------------------------------------------------------------*/
506 ihfc_fsm(ihfc_sc_t *sc, int flag)
508 const struct ihfc_FSMtable *fsmtab;
514 /* get current state (rx/downstream) */
518 SET_REG(0x31); DISBUSY(tmp = (READ_DATA_1 >> 2) & 0xf, return);
520 fsmtab = (S_NTMODE) ? &ihfc_TEtable2[tmp]:
525 SET_REG(0x30); tmp = READ_DATA_1 & 0xf;
527 fsmtab = (S_NTMODE) ? &ihfc_NTtable[tmp]:
533 NDBGL1(L1_I_CICO, "%s (ind=0x%x, flag=%d, unit=%d).",
534 fsmtab->string, tmp, flag, S_UNIT);
538 NDBGL1(L1_I_ERR, "Illegal indicatation (ind=0x%x, "
539 "flag=%d, unit=%d).", tmp, flag, S_UNIT);
542 /* indication machine / state change *
544 * Whenever the state of the S0-line changes, we check to see in which *
545 * direction the change went. Generally upwards means activate, and *
546 * downwards means deactivate. *
547 * The test signal is used to ensure proper syncronization. */
549 if (fsmtab->state == 0) /* deactivated indication */
553 isac_cmd = 0x3c; /* deactivate DUI */
555 i4b_l1_ph_deactivate_ind(S_I4BUNIT);
558 if (fsmtab->state == 2) /* syncronized indication */
562 if (S_NTMODE) ihfc_cmd = 0x80;
565 if (fsmtab->state == 3) /* activated indication */
569 isac_cmd = (S_DLP) ? 0x24 /* activate AR10 */
570 : 0x20; /* activate AR8 */
572 i4b_l1_ph_activate_ind(S_I4BUNIT);
575 if (fsmtab->state == 4) /* error indication */
579 isac_cmd = 0x3c; /* deactivate DUI */
583 S_PHSTATE = fsmtab->state;
585 if ((flag == 1) && (fsmtab->state != 3))
587 isac_cmd = (S_DLP) ? 0x24 : 0x20;
590 if ((flag == 2) && (fsmtab->state != 0))
596 /* set new state (tx / upstream) *
598 * NOTE: HFC-S/SP and ISAC transmitters are always active when *
599 * activated state is reached. The bytes sent to the S0-bus are all *
600 * high impedance, so they do not disturb. *
601 * The HFC-1 has a separate SIEMENS S0-device. */
607 if (S_IOM2) isac_cmd |= 3;
609 SET_REG(0x31); DISBUSY(WRITE_DATA_1(isac_cmd), );
611 NDBGL1(L1_I_CICO, "(isac_cmd=0x%x, unit=%d).",
617 if (ihfc_cmd || (fsmtab->state == 5))
619 SET_REG(0x30); WRITE_DATA_1(ihfc_cmd);
621 NDBGL1(L1_I_CICO, "(ihfc_cmd=0x%x, unit=%d).",
627 /*---------------------------------------------------------------------------*
628 * S/Q - channel handler (read) (HFC-S/SP)
629 *---------------------------------------------------------------------------*/
631 ihfc_sq (ihfc_sc_t *sc)
633 const struct ihfc_SQtable *SQtab;
640 DISBUSY(a = READ_DATA_1, a = 0);
645 DISBUSY(a = READ_DATA_1, a = 0);
654 SQtab = (S_NTMODE) ? &ihfc_Qtable[a & 7]:
661 NDBGL1(L1_I_CICO, "%s (unit=%d, int=%x)",
662 SQtab->string, S_UNIT, S_INT_S1);
666 NDBGL1(L1_ERROR, "Unknown indication = %x (unit=%d)",
672 /*---------------------------------------------------------------------------*
673 * Interrupt handler (HFC-1)
674 *---------------------------------------------------------------------------*/
676 ihfc_intr1 (ihfc_sc_t *sc)
685 SET_REG(0x20); tmp = GET_STAT; DISBUSY(S_ISTA |= READ_DATA_1, );
687 if (S_ISTA & 0x04) /* CIRQ */
696 if (S_ISTA & 0xc0) /* RPF or RME */
699 if (S_FILTER) S_FILTER(sc, chan);
701 if (S_ISTA & 0x10) /* XPR */
704 if (S_FILTER) S_FILTER(sc, chan);
706 if (tmp & 0x04) /* Timer elapsed (50ms) */
708 SET_REG((S_CTMT | 0xf0) & 0xff);
713 if (chan == 1) break;
714 if (S_FILTER) S_FILTER(sc, chan);
724 if (S_ISTA & 0x01) /* EXIR */
726 SET_REG(0x24); DISBUSY(ihfc_exir_hdlr(sc, READ_DATA_1), );
729 S_ISTA &= ~(0x1 | 0x4);
734 /*---------------------------------------------------------------------------*
735 * Interrupt handler (HFC-S/SP)
736 *---------------------------------------------------------------------------*/
738 ihfc_intr2 (ihfc_sc_t *sc)
746 SET_REG(0x1e); S_INT_S1 = READ_DATA_1; /* this will enable new interrupts! */
750 HFC_FSM(sc, 0); /* statemachine changed */
757 if (S_INT_S1 & 0x20) /* D-Channel frame (rx) */
760 if (S_FILTER) S_FILTER(sc, chan);
762 if (S_INT_S1 & 0x04) /* D-Channel frame (tx) */
765 if (S_FILTER && (~S_INT_S1 & 0x80)) S_FILTER(sc, chan);
767 if (S_INT_S1 & 0x80) /* Timer elapsed (50ms) */
772 if (chan == 1) continue;
773 if (S_FILTER) S_FILTER(sc, chan);
786 /*---------------------------------------------------------------------------*
787 * Select a Bfifo (HFC-1/S/SP)
788 * and return bytes in FIFO
790 * (this code is optimized)
791 *---------------------------------------------------------------------------*/
793 ihfc_Bsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
795 u_char reg = 0x7e + chan;
802 if (S_HFC & (HFC_1 | HFC_S))
804 if (S_LAST_CHAN != chan)
807 DISBUSY(WAITBUSY_2( , return 0), return 0);
815 WRITE_DATA_1(chan - 2);
816 DISBUSY( , return 0);
819 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
820 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
822 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
823 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
824 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
825 SET_REG(reg += 4); FAST_STAT; z2 |= READ_DATA_1 << 8;
833 z1 = 0x5ff - (z2 = z1 - z2 + ((z2 <= z1) ? 0 : 0x600));
836 return(z2); /* receive channel */
838 return(z1); /* transmit channel */
841 /*---------------------------------------------------------------------------*
842 * Select a Dfifo (HFC-S/SP)
843 * and return bytes, and frames in FIFO
846 * 0x00: select new fifo + update counters
847 * 0x10: increment f1 + update counters
848 * 0x20: increment f2 + update counters
850 * NOTE: The upper 16bits holds the number of frames in the FIFO.
851 * NOTE: FIFO has to be selected before you can use flags 0x10/0x20.
852 *---------------------------------------------------------------------------*/
854 ihfc_Dsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
856 u_char reg = 0x90 + chan;
865 if (S_HFC & (HFC_1 | HFC_S))
873 WAITBUSY_2( , return 0);
875 SET_REG(0xa2 - (flag & 0x10) + chan);
876 DISBUSY(READ_DATA_1, return 0);
880 WAITBUSY_2( , return 0);
884 if (S_LAST_CHAN != chan)
887 DISBUSY(WAITBUSY_2( , return 0), return 0);
900 SET_REG(0xb8 - (flag & 0x10) + chan);
903 DISBUSY( , return 0);
907 /* Before reading a FIFO a change *
908 * FIFO operation must be done. *
909 * (see HFC-SP manual p.38) */
912 WRITE_DATA_1(chan | 4);
914 DISBUSY( , return 0);
920 WRITE_DATA_1(chan | 4);
922 DISBUSY( , return 0);
927 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
928 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
930 if (S_HFC & HFC_SP) reg = 0x80 + chan;
932 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
933 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
934 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
935 SET_REG(reg += 4); FAST_STAT; z2 |= FAST_READ << 8;
937 if (S_HFC & HFC_SP) reg += 0x26;
939 SET_REG(reg -= 2); FAST_STAT; f1 = FAST_READ;
940 SET_REG(reg += 4); FAST_STAT; f2 = READ_DATA_1;
947 S_HDLC_DZ_TAB[f1 & 0xf] = z2; /* We keep track of the 'Z' *
948 * values for D-channel (tx),*
949 * so we may calculate the # *
950 * of FIFO bytes free when *
952 z2 = S_HDLC_DZ_TAB[f2 & 0xf];
955 z1 = 0x1ff - (z2 = (z1 - z2) & 0x1ff);
956 f1 = 0xf - (f2 = (f1 - f2) & 0xf);
959 return(z2 | (f2 << 16)); /* receive channel */
961 return(z1 | (f1 << 16)); /* transmit channel */
965 /*---------------------------------------------------------------------------*
966 * Data handler for D channel(write) - chan 0 (HFC-S/SP)
967 *---------------------------------------------------------------------------*/
969 ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan)
977 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
979 sendlen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
980 * NOTE: the 16 higher bits *
981 * contain the # of frame- *
982 * etries free in the FIFO */
983 while (sendlen & ~0xffff)
987 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j1;
993 if (len >= 0x1ff) goto j0; /* frame is too big: skip! */
995 sendlen &= 0xffff; /* only keep # of *
998 SET_REG((S_HFC & HFC_SP) ? 0xac : 0x96);
1004 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1007 if (!++sendlen) /* out of fifo: suspend */
1014 sendlen = ihfc_Dsel_fifo(sc, chan, 0x10); /* inc F1 */
1016 i4b_Dfreembuf(S_MBUF);
1023 /*---------------------------------------------------------------------------*
1024 * Data handler for D channel(read) - chan 1 (HFC-S/SP)
1026 * NOTE: Max framelength is (511 - 3) = 508 bytes, when only one frame
1027 * is received at a time.
1028 *---------------------------------------------------------------------------*/
1030 ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan)
1041 reclen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
1042 * NOTE: the higher 16 bits *
1043 * contain the # of frames *
1045 while ((reclen & ~0xffff) && to--)
1047 reclen &= 0xffff; /* only keep # of *
1048 * bytes to receive */
1050 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1051 panic("ihfc_hdlc_Dread: No mbufs(unit=%d)!\n", S_UNIT);
1053 SET_REG((S_HFC & HFC_SP) ? 0xbd : 0xa7);
1055 if ((reclen > 2) && (reclen <= (DCH_MAX_LEN+2)))
1058 len = S_MBUFLEN = (reclen += 1) - 3;
1066 crc = -1; /* NOTE: after a "F1" or "Z1" hardware overflow *
1067 * it appears not to be necessary to reset the *
1068 * HFC-1/S or SP chips to continue proper *
1069 * operation, only and only, if we always read *
1070 * "Z1-Z2+1" bytes when F1!=F2 followed by a *
1071 * F2-counter increment. The bi-effect of doing *
1072 * this is the "STAT" field may say frame is ok *
1073 * when the frame is actually bad. *
1074 * The simple solution is to re-CRC the frame *
1075 * including "STAT" field to see if we get *
1076 * CRC == 0x3933. Then we're 99% sure all *
1077 * frames received are good. */
1081 DISBUSY(tmp = READ_DATA_1, break);
1082 if (len) { len--; *dst++ = tmp; }
1084 crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8));
1091 ihfc_putmbuf(sc, chan, S_MBUF);
1096 NDBGL1(L1_ERROR, "Frame error (len=%d, stat=0x%x, "
1097 "crc=0x%x, unit=%d)", S_MBUFLEN, (u_char)tmp, crc,
1100 i4b_Dfreembuf(S_MBUF);
1104 reclen = ihfc_Dsel_fifo(sc, chan, 0x20);
1108 /*---------------------------------------------------------------------------*
1109 * EXIR error handler - ISAC (D - channel) (HFC-1)
1110 *---------------------------------------------------------------------------*/
1112 ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir)
1117 for (a = 0, cmd = 0; exir; a++, exir >>= 1)
1121 NDBGL1(L1_I_ERR, "%s. (unit=%d)",
1122 ihfc_EXIRtable[a].string, S_UNIT);
1123 cmd |= ihfc_EXIRtable[a].cmd;
1127 if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1130 /*---------------------------------------------------------------------------*
1131 * CMDR handler - ISAC (D - channel) (HFC-1)
1132 *---------------------------------------------------------------------------*/
1134 ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr)
1138 SET_REG(0x21); DISBUSY(WRITE_DATA_1(cmdr); DELAY(30), );
1141 /*---------------------------------------------------------------------------*
1142 * Data handler for D channel(write) - chan 0 (HFC-1)
1143 *---------------------------------------------------------------------------*/
1145 ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan)
1147 u_char sendlen = 32;
1154 if (~S_ISTA & 0x10) goto j0;
1157 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j0;
1164 while(sendlen--) /* write data */
1167 DISBUSY(WRITE_DATA_1(*src++), goto a0);
1172 if (!++sendlen) /* suspend */
1180 i4b_Dfreembuf(S_MBUF);
1186 if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1193 /*---------------------------------------------------------------------------*
1194 * Data handler for D channel(read) - chan 1 (HFC-1)
1195 *---------------------------------------------------------------------------*/
1197 ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan)
1207 if (!(S_ISTA & 0xc0)) goto j1; /* only receive data *
1212 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1213 panic("ihfc%d: (D) Out of mbufs!\n", S_UNIT);
1217 dst = S_MBUFDATA + (DCH_MAX_LEN - len);
1219 if (S_ISTA & 0x80) /* RME */
1221 SET_REG(0x27); DISBUSY(tmp = (READ_DATA_1 ^ 0x20), goto j0);
1223 if (tmp & 0x70) goto j0; /* error */
1225 SET_REG(0x25); DISBUSY(tmp = (READ_DATA_1 & 0x1f), goto j0);
1227 reclen = (tmp) ? tmp : 32;
1234 if ((len -= reclen) <= DCH_MAX_LEN) /* get data */
1240 DISBUSY(*dst++ = READ_DATA_1, goto j0);
1243 else /* soft rdo or error */
1245 j0: i4b_Dfreembuf(S_MBUF);
1250 NDBGL1(L1_I_ERR, "Frame error (unit=%d)", S_UNIT);
1253 if (S_ISTA & 0x80) /* frame complete */
1257 S_MBUFLEN = (DCH_MAX_LEN - len);
1258 ihfc_putmbuf(sc, chan, S_MBUF);
1263 if (S_MBUF) /* suspend */
1268 ihfc_cmdr_hdlr(sc, cmd | 0x80);
1275 /*---------------------------------------------------------------------------*
1276 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1278 * NOTE: No XDU checking!
1279 *---------------------------------------------------------------------------*/
1281 ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan)
1289 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
1291 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1293 SET_REG(0xaa + chan);
1299 S_MBUF = ihfc_getmbuf(sc, chan);
1310 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1313 if (!++sendlen) /* out of fifo: Suspend */
1320 i4b_Dfreembuf(S_MBUF);
1325 /*---------------------------------------------------------------------------*
1326 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1327 * (this code is optimized)
1328 *---------------------------------------------------------------------------*/
1330 ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan)
1339 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1343 SET_REG(0xba + chan);
1348 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1349 panic("ihfc%d: (B) Out of mbufs!\n", S_UNIT);
1352 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1358 if (tmp & 0x100) DISBUSY( , reclen = -1; len++; break);
1359 *dst++ = (u_char)(tmp = READ_BOTH_2);
1365 READ_DATA_1; /* a read to the data port *
1366 * will disable the internal *
1367 * disbusy signal for HFC-1/S *
1368 * chips. This is neccessary *
1369 * to avvoid data loss. */
1372 if (!++reclen) /* out of fifo: suspend */
1378 S_MBUFLEN = (BCH_MAX_DATALEN - ++len);
1380 ihfc_putmbuf(sc, chan, S_MBUF);
1386 /*---------------------------------------------------------------------------*
1387 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1389 * NOTE: Software HDLC encoding!
1390 *---------------------------------------------------------------------------*/
1392 ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan)
1394 u_short blevel = S_HDLC_BLEVEL;
1395 u_char flag = S_HDLC_FLAG;
1396 u_int tmp = S_HDLC_TMP;
1397 u_short crc = S_HDLC_CRC;
1398 u_short ib = S_HDLC_IB;
1399 u_char * src = NULL;
1406 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE) && (flag == 2)) return;
1408 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1410 SET_REG(0xaa + chan);
1419 if (sendlen == 0x5ff)
1426 NDBGL1(L1_S_ERR, "XDU (unit=%d)", S_UNIT);
1432 HDLC_ENCODE(*src++, len, tmp, tmp2, blevel, ib, crc, flag,
1434 i4b_Bfreembuf(S_MBUF);
1435 S_MBUF = ihfc_getmbuf(sc, chan);
1444 sendlen = 0; /* Exit after final FS, *
1445 * else the buffer will *
1446 * only be filled with *
1452 DISBUSY(WRITE_DATA_1((u_char)tmp), sendlen = 0);
1457 if (S_MBUF) /* suspend */
1464 S_HDLC_BLEVEL = blevel;
1470 /*---------------------------------------------------------------------------*
1471 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1473 * NOTE: Software HDLC decoding!
1474 *---------------------------------------------------------------------------*/
1476 ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan)
1478 u_char blevel = S_HDLC_BLEVEL;
1479 u_char flag = S_HDLC_FLAG;
1480 u_short crc = S_HDLC_CRC;
1481 u_int tmp = S_HDLC_TMP;
1482 u_short ib = S_HDLC_IB;
1483 u_char * dst = NULL;
1484 u_short tmp2 = 0x100;
1495 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1498 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1500 SET_REG(0xba + chan);
1504 HDLC_DECODE(*dst++, len, tmp, tmp2, blevel, ib, crc, flag,
1506 /* if (tmp2 & 0x100) while (GET_STAT & 1);
1507 * tmp2 = READ_BOTH_2;
1510 DISBUSY(tmp2 = READ_DATA_1, reclen = 0; tmp2 = 0);
1513 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1514 panic("ihfc:(B) Out of mbufs!\n");
1517 len = BCH_MAX_DATALEN;
1520 len = (BCH_MAX_DATALEN - len);
1522 if ((!len) || (len > BCH_MAX_DATALEN))
1524 /* NOTE: frames without any data, *
1525 * only crc field, should be silently discared. */
1527 i4b_Bfreembuf(S_MBUF);
1528 NDBGL1(L1_S_MSG, "Bad frame (len=%d, unit=%d)", len, S_UNIT);
1533 { i4b_Bfreembuf(S_MBUF);
1534 NDBGL1(L1_S_ERR, "CRC (crc=0x%04x, len=%d, unit=%d)", crc, len, S_UNIT);
1540 ihfc_putmbuf(sc, chan, S_MBUF);
1545 i4b_Bfreembuf(S_MBUF);
1548 NDBGL1(L1_S_MSG, "Read Abort (unit=%d)", S_UNIT);
1551 i4b_Bfreembuf(S_MBUF);
1554 NDBGL1(L1_S_ERR, "RDO (unit=%d)", S_UNIT);
1561 * if (~tmp2 & 0x100) READ_DATA_1; kill disbusy signal
1564 if (S_MBUF) S_MBUFLEN = len; /* suspend */
1570 S_HDLC_BLEVEL = blevel;
1573 /*---------------------------------------------------------------------------*
1574 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1576 * This filter generates a pattern which is recognized
1577 * and examinated and verified by ihfc_test_Bread.
1579 * NOTE: This filter is only for testing purpose.
1580 *---------------------------------------------------------------------------*/
1582 ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan)
1587 u_short sendlen, tlen;
1588 u_short xlen = S_HDLC_IB;
1593 while((m = ihfc_getmbuf(sc, chan))) /* internal loop */
1596 ihfc_putmbuf(sc, 5, m);
1598 ihfc_putmbuf(sc, 3, m);
1603 sendlen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1605 if (sendlen == 0x5ff) printf("(send empty)");
1607 SET_REG(0xaa + chan);
1613 if (sendlen > 0x400) printf("(slow: %d)", sendlen);
1619 if (!tlen--) fb |= 0x20;
1623 while(GET_STAT & 1);
1629 while(GET_STAT & 1);
1630 WRITE_DATA_1((xlen + 1) & 0xef);
1639 /*---------------------------------------------------------------------------*
1640 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1642 * This filter examins and verifies the pattern
1643 * generated by ihfc_test_Bwrite.
1645 * NOTE: This filter is only for testing purpose.
1646 *---------------------------------------------------------------------------*/
1648 ihfc_test_Bread (ihfc_sc_t *sc, u_char chan)
1650 static u_short toterrors = 0;
1652 u_short reclen, len, tlen;
1655 u_short xlen = S_HDLC_IB;
1657 u_char error = S_HDLC_TMP;
1658 u_char ecount = S_HDLC_FLAG;
1662 if (S_UNIT != 0) return;
1664 reclen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1675 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1682 SET_REG(0xba + chan);
1686 /* if (tmp2 & 0x100) while(GET_STAT & 1);
1687 * tmp = (u_char)(tmp2 = READ_BOTH_2);
1691 /* if (!(++busy % 4)) reclen++; */
1692 while(GET_STAT & 1);
1697 if ((tmp & 0x3f) == 0x3e)
1699 if ((BCH_MAX_DATALEN - len) != 201) error |= 4;
1701 if ((S_MBUF) && (error))
1703 if (len) { len--; *dst++ = error; }
1704 if (len) { len--; *dst++ = xlen+1; }
1705 if (len) { len--; *dst++ = ecount; }
1707 S_MBUFLEN = BCH_MAX_DATALEN - len;
1709 if (S_TRACE & TRACE_B_RX)
1710 ihfc_putmbuf(sc, chan, S_MBUF);
1712 i4b_Bfreembuf(S_MBUF);
1715 printf("(error%d, %d, %d)", S_UNIT, ecount, toterrors++);
1718 i4b_Bfreembuf(S_MBUF);
1719 S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN);
1722 len = BCH_MAX_DATALEN;
1728 /* SET_REG(0xba + chan); */
1732 if (!xlen) error |= 2;
1733 if ((tmp ^ xlen--) & 0xef) { error |= 1; ecount++; }
1735 if (!tlen--) fb |= 0x20;
1739 *dst++ = (tmp | fb);
1756 S_HDLC_FLAG = ecount;
1759 #endif /* NIHFC > 0 */