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
26 /*---------------------------------------------------------------------------
28 * i4b_ihfc_drv.c - ihfc ISA PnP-bus interface
29 * -------------------------------------------
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 *---------------------------------------------------------------------------*/
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/socket.h>
47 #include <i4b/include/i4b_mbuf.h>
49 #include <i4b/include/i4b_debug.h>
50 #include <i4b/include/i4b_ioctl.h>
51 #include <i4b/include/i4b_trace.h>
53 #include <i4b/layer1/i4b_l1.h>
54 #include <i4b/layer1/i4b_hdlc.h>
55 #include <i4b/layer1/ihfc/i4b_ihfc.h>
56 #include <i4b/layer1/ihfc/i4b_ihfc_ext.h>
57 #include <i4b/layer1/ihfc/i4b_ihfc_drv.h>
59 #include <machine/bus.h>
63 /*---------------------------------------------------------------------------*
65 *---------------------------------------------------------------------------*/
66 void ihfc_loadconfig (ihfc_sc_t *sc);
68 static void ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan);
69 static void ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan);
70 static void ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan);
71 static void ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan);
72 static void ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan);
73 static void ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan);
75 static void ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan);
76 static void ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan);
78 void ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr);
79 void ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir);
81 void ihfc_sq (ihfc_sc_t *sc);
83 static void ihfc_test_Bread (ihfc_sc_t *sc, u_char chan);
84 static void ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan);
86 u_short ihfc_Bsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
87 u_int32_t ihfc_Dsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
90 /*---------------------------------------------------------------------------*
91 * Commonly used ISA bus commands
92 *---------------------------------------------------------------------------*/
93 #define IHFC_DATA_OFFSET 0
94 #define IHFC_REG_OFFSET 1
96 #define BUS_VAR bus_space_handle_t h = rman_get_bushandle(S_IOBASE[0]); \
97 bus_space_tag_t t = rman_get_bustag (S_IOBASE[0])
99 #define SET_REG(reg) bus_space_write_1(t,h, IHFC_REG_OFFSET, reg)
100 #define GET_STAT bus_space_read_1 (t,h, IHFC_REG_OFFSET)
102 #define READ_DATA_1 bus_space_read_1 (t,h, IHFC_DATA_OFFSET)
103 #define READ_BOTH_2 bus_space_read_2 (t,h, IHFC_DATA_OFFSET)
105 #define WRITE_DATA_1(data) bus_space_write_1(t,h, IHFC_DATA_OFFSET, data)
106 #define WRITE_BOTH_2(data) bus_space_write_2(t,h, IHFC_DATA_OFFSET, data)
108 #define DISBUSY(okcmd, tocmd) \
113 register u_int to = IHFC_DISBUSYTO; \
115 while(((a = GET_STAT) & 1) && --to); \
119 NDBGL1(L1_ERROR, "DISBUSY-TIMEOUT! (a=%04x, " \
120 "unit=%d)", a, S_UNIT); \
134 #define WAITBUSY_2(okcmd, tocmd) \
136 register u_short a; \
137 register u_int to = IHFC_NONBUSYTO; \
139 while((~(a = READ_BOTH_2) & 0x100) && --to); \
143 NDBGL1(L1_ERROR, "NONBUSY-TIMEOUT! (a=%04x, " \
144 "unit=%d)", a, S_UNIT); \
153 /*---------------------------------------------------------------------------*
154 * Control function (HFC-1/S/SP)
157 * 1: reset and unlock chip (at boot only)
158 * 2: prepare for shutdown (at shutdown only)
159 * 3: reset and resume
160 * 4: select TE-mode (boot default)
161 * 5: select NT-mode (only HFC-S/SP/PCI)
163 * Returns != 0 on errornous chip
164 *---------------------------------------------------------------------------*/
166 ihfc_control(ihfc_sc_t *sc, int flag)
170 if (flag == 3) goto reset0;
183 WRITE_BOTH_2(0x5400 | S_IIO); /* enable IO (HFC-1/S) */
187 /* HFC-S/SP configuration */
189 S_CIRM = S_IIRQ|0x10; /* IRQ, 8K fifo mode */
190 S_CLKDEL = 0x00; /* 12.288mhz */
191 S_CTMT = 0x03; /* transperant mode */
192 S_CONNECT = 0x00; /* B channel data flow */
193 S_INT_M1 = 0x40; /* interrupt mask */
194 S_INT_M2 = 0x08; /* enable interrupt output */
195 S_MST_MODE = 0x01; /* master mode */
196 S_SCTRL = 0x50; /* S/Q on, non cap. line mode */
197 S_SCTRL_R = 0x00; /* B channel receive disable */
198 S_TEST = 0x00; /* no need for awake enable */
200 if (S_HFC & (HFC_1 | HFC_S)) /* configure timer (50ms) */
209 /* HFC-1 ISAC configuration (IOM-2 mode) */
212 S_ADF2 = 0x80; /* select mode IOM-2 */
213 S_SPCR = 0x00; /* B channel send disable (0x10 for test loop) */
214 S_MASK = 0xfb; /* enable CISQ */
215 S_MODE = 0xc9; /* receiver enabled */
216 S_SQXR = 0x0f; /* master, clock always active */
217 S_STCR = 0x70; /* TIC bus address = 7 */
218 S_STAR2 = 0x04; /* enable S/Q */
221 if (S_NTMODE) /* configure NT- or TE-mode */
223 S_SCTRL |= 0x04; /* NT mode */
224 S_CLKDEL &= ~0x7f; /* clear delay */
225 S_CLKDEL |= 0x6c; /* set delay */
229 S_SCTRL &= ~0x04; /* TE mode */
230 S_STDEL &= 0x7f; /* use mask! */
231 S_CLKDEL &= ~0x7f; /* clear delay */
232 S_CLKDEL |= S_STDEL; /* set delay */
234 if (S_DLP) /* configure D-priority */
236 S_SCTRL |= 0x08; /* (10/11) */
240 S_SCTRL &= ~0x08; /* (8/9) */
244 /* chip reset (HFC-1/S/SP) */
248 SET_REG((S_CIRM | 0xc8) & 0xdf);
250 DELAY(10); /* HFC-2B manual recommends a 4 *
251 * clock cycle delay after CIRM *
252 * write with reset=1. A 1us *
253 * delay, should do for 7.68mhz,*
254 * but just in case I make that *
257 SET_REG((S_CIRM | 0xc0) & 0xdf);
259 DELAY(250); /* ISAC manual says reset pulse *
260 * length is 125us. Accessing *
261 * ISAC before those 125us, we *
262 * may risk chip corruption and *
263 * irq failure. The HFC-2B also *
264 * needs some delay to recover, *
265 * so we add some us. */
271 WRITE_DATA_1(S_CIRM | 8);
273 DELAY(10); /* HFC-2BDS0 manual recommends *
274 * a 4 clock cycle delay after *
275 * CIRM write with reset=1. *
276 * A 1us delay, should do for *
277 * 12.288mhz, but just in case *
278 * I make that 10us. */
280 WRITE_DATA_1(S_CIRM);
282 DELAY(25); /* HFC-2BDS0 needs some time to *
283 * recover after CIRM write *
284 * with reset=0. Experiments *
285 * show this delay should be *
286 * 8-9us. Just in case we make *
291 /* HFC-1/S/SP chip test *
293 * NOTE: after reset the HFC-1/S/SP should be *
294 * in a mode where it is always non-busy/non- *
295 * processing, and bit[0] of STATUS/DISBUSY *
296 * register, should always return binary '0' *
297 * until we configure the chips for normal *
300 printf("ihfc: GET_STAT value is: 0x%x\n", GET_STAT);
304 if ((GET_STAT & 1) || (READ_DATA_1 & 0xf)) goto f0;
309 if (S_HFC & HFC_1) ihfc_cmdr_hdlr(sc, 0x41); /* rres, xres */
317 if (S_HFC & HFC_1) S_CIRM &= ~0x03; /* disable interrupt */
319 S_SQXR |= 0x40; /* power down */
324 S_SPCR &= ~0x0f; /* send 1's only */
325 S_SCTRL &= ~0x83; /* send 1's only + enable oscillator */
330 return(0); /* success */
333 return(1); /* failure */
336 /*---------------------------------------------------------------------------*
337 * Softc initializer and hardware setup (HFC-1/S/SP)
339 * Returns: 0 on success
341 *---------------------------------------------------------------------------*/
343 ihfc_init (ihfc_sc_t *sc, u_char chan, int prot, int activate)
345 if (chan > 5) goto f0;
350 { if (chan < 2) /* D-Channel */
352 i4b_Dfreembuf(S_MBUF);
353 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Dcleanifq(&S_IFQUEUE);
355 RESET_SOFT_CHAN(sc, chan);
357 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
359 #if defined (__FreeBSD__) && __FreeBSD__ > 4
360 if(!mtx_initialized(&S_IFQUEUE.ifq_mtx))
361 mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", NULL, MTX_DEF);
363 if (!activate) continue;
367 S_FILTER = (chan & 1) ? ihfc_isac_Dread :
372 S_FILTER = (chan & 1) ? ihfc_hdlc_Dread :
378 i4b_Bfreembuf(S_MBUF);
379 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Bcleanifq(&S_IFQUEUE);
381 RESET_SOFT_CHAN(sc, chan);
383 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
385 #if defined (__FreeBSD__) && __FreeBSD__ > 4
386 if(!mtx_initialized(&S_IFQUEUE.ifq_mtx))
387 mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", NULL, MTX_DEF);
391 if (!activate) continue;
395 S_FILTER = (chan & 1) ?
400 S_FILTER = (chan & 1) ?
405 S_FILTER = (chan & 1) ?
411 } while (++chan & 1);
413 S_MASK |= 0xfb; /* disable all, but CISQ interrupt (ISAC) */
414 S_INT_M1 &= 0x40; /* disable all, but TE/NT state machine (HFC) */
415 S_SCTRL &= ~0x03; /* B1/B2 send disable (HFC) */
416 S_SPCR &= ~0x0f; /* B1/B2 send disable (ISAC) */
417 S_SCTRL_R &= ~0x03; /* B1/B2 receive disable (HFC) */
420 if (S_FILTER) /* D-Channel active */
422 S_MASK &= 0x2e; /* enable RME, RPF, XPR, EXI */
423 S_INT_M1 |= 0x24; /* enable D-receive, D-transmit */
427 if (S_FILTER) /* B1-Channel active */
429 S_SCTRL |= 1; /* send enable (HFC) */
430 S_SPCR |= 8; /* send enable (ISAC) */
431 S_SCTRL_R |= 1; /* receive enable (HFC) */
432 S_INT_M1 |= 0x80; /* timer enable (HFC) */
433 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
437 if (S_FILTER) /* B2-Channel active */
439 S_SCTRL |= 2; /* send enable (HFC) */
440 S_SPCR |= 2; /* send enable (ISAC) */
441 S_SCTRL_R |= 2; /* receive enable (HFC) */
442 S_INT_M1 |= 0x80; /* timer enable (HFC) */
443 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
448 /* XXX reset timer? */
450 return 0; /* success */
452 return 1; /* failure */
455 /*---------------------------------------------------------------------------*
456 * Load configuration data (HFC-1/S/SP)
457 *---------------------------------------------------------------------------*/
459 ihfc_loadconfig(ihfc_sc_t *sc)
465 /* HFC-1 chips w/ISAC: */
467 const u_char *src = (void *)&S_ISAC_CONFIG;
468 const u_char *dst = (void *)&isac_configtable;
470 SET_REG((S_CIRM | 0xc0) & 0xdf);
472 S_CTMT = (S_CTMT & ~0x14) | ((S_INT_M1 >> 5) & 0x4);
474 SET_REG((S_CTMT | 0xe0) & 0xff);
478 SET_REG(*dst++); /* set register */
480 /* write configuration */
481 DISBUSY(WRITE_DATA_1(*src++), break);
486 /* HFC-S/SP chips: */
488 const u_char *src = (void *)&S_HFC_CONFIG;
489 const u_char *dst = (void *)&ihfc_configtable;
493 SET_REG(*dst++); /* set register */
494 WRITE_DATA_1(*src++); /* write configuration */
499 /*---------------------------------------------------------------------------*
500 * Function State Machine handler (PH layer) (HFC-1/S/SP)
502 * Flag: 0 = Refresh softc S_PHSTATE + take hints
506 * NOTE: HFC-1 only supports TE mode.
507 *---------------------------------------------------------------------------*/
509 ihfc_fsm(ihfc_sc_t *sc, int flag)
511 const struct ihfc_FSMtable *fsmtab;
517 /* get current state (rx/downstream) */
521 SET_REG(0x31); DISBUSY(tmp = (READ_DATA_1 >> 2) & 0xf, return);
523 fsmtab = (S_NTMODE) ? &ihfc_TEtable2[tmp]:
528 SET_REG(0x30); tmp = READ_DATA_1 & 0xf;
530 fsmtab = (S_NTMODE) ? &ihfc_NTtable[tmp]:
536 NDBGL1(L1_I_CICO, "%s (ind=0x%x, flag=%d, unit=%d).",
537 fsmtab->string, tmp, flag, S_UNIT);
541 NDBGL1(L1_I_ERR, "Illegal indicatation (ind=0x%x, "
542 "flag=%d, unit=%d).", tmp, flag, S_UNIT);
545 /* indication machine / state change *
547 * Whenever the state of the S0-line changes, we check to see in which *
548 * direction the change went. Generally upwards means activate, and *
549 * downwards means deactivate. *
550 * The test signal is used to ensure proper syncronization. */
552 if (fsmtab->state == 0) /* deactivated indication */
556 isac_cmd = 0x3c; /* deactivate DUI */
558 i4b_l1_ph_deactivate_ind(S_I4BUNIT);
561 if (fsmtab->state == 2) /* syncronized indication */
565 if (S_NTMODE) ihfc_cmd = 0x80;
568 if (fsmtab->state == 3) /* activated indication */
572 isac_cmd = (S_DLP) ? 0x24 /* activate AR10 */
573 : 0x20; /* activate AR8 */
575 i4b_l1_ph_activate_ind(S_I4BUNIT);
578 if (fsmtab->state == 4) /* error indication */
582 isac_cmd = 0x3c; /* deactivate DUI */
586 S_PHSTATE = fsmtab->state;
588 if ((flag == 1) && (fsmtab->state != 3))
590 isac_cmd = (S_DLP) ? 0x24 : 0x20;
593 if ((flag == 2) && (fsmtab->state != 0))
599 /* set new state (tx / upstream) *
601 * NOTE: HFC-S/SP and ISAC transmitters are always active when *
602 * activated state is reached. The bytes sent to the S0-bus are all *
603 * high impedance, so they do not disturb. *
604 * The HFC-1 has a separate SIEMENS S0-device. */
610 if (S_IOM2) isac_cmd |= 3;
612 SET_REG(0x31); DISBUSY(WRITE_DATA_1(isac_cmd), );
614 NDBGL1(L1_I_CICO, "(isac_cmd=0x%x, unit=%d).",
620 if (ihfc_cmd || (fsmtab->state == 5))
622 SET_REG(0x30); WRITE_DATA_1(ihfc_cmd);
624 NDBGL1(L1_I_CICO, "(ihfc_cmd=0x%x, unit=%d).",
630 /*---------------------------------------------------------------------------*
631 * S/Q - channel handler (read) (HFC-S/SP)
632 *---------------------------------------------------------------------------*/
634 ihfc_sq (ihfc_sc_t *sc)
636 const struct ihfc_SQtable *SQtab;
637 register u_char a = 0;
643 DISBUSY(a = READ_DATA_1, a = 0);
648 DISBUSY(a = READ_DATA_1, a = 0);
657 SQtab = (S_NTMODE) ? &ihfc_Qtable[a & 7]:
664 NDBGL1(L1_I_CICO, "%s (unit=%d, int=%x)",
665 SQtab->string, S_UNIT, S_INT_S1);
669 NDBGL1(L1_ERROR, "Unknown indication = %x (unit=%d)",
675 /*---------------------------------------------------------------------------*
676 * Interrupt handler (HFC-1)
677 *---------------------------------------------------------------------------*/
679 ihfc_intr1 (ihfc_sc_t *sc)
688 SET_REG(0x20); tmp = GET_STAT; DISBUSY(S_ISTA |= READ_DATA_1, );
690 if (S_ISTA & 0x04) /* CIRQ */
699 if (S_ISTA & 0xc0) /* RPF or RME */
702 if (S_FILTER) S_FILTER(sc, chan);
704 if (S_ISTA & 0x10) /* XPR */
707 if (S_FILTER) S_FILTER(sc, chan);
709 if (tmp & 0x04) /* Timer elapsed (50ms) */
711 SET_REG((S_CTMT | 0xf0) & 0xff);
716 if (chan == 1) break;
717 if (S_FILTER) S_FILTER(sc, chan);
727 if (S_ISTA & 0x01) /* EXIR */
729 SET_REG(0x24); DISBUSY(ihfc_exir_hdlr(sc, READ_DATA_1), );
732 S_ISTA &= ~(0x1 | 0x4);
737 /*---------------------------------------------------------------------------*
738 * Interrupt handler (HFC-S/SP)
739 *---------------------------------------------------------------------------*/
741 ihfc_intr2 (ihfc_sc_t *sc)
749 SET_REG(0x1e); S_INT_S1 = READ_DATA_1; /* this will enable new interrupts! */
753 HFC_FSM(sc, 0); /* statemachine changed */
760 if (S_INT_S1 & 0x20) /* D-Channel frame (rx) */
763 if (S_FILTER) S_FILTER(sc, chan);
765 if (S_INT_S1 & 0x04) /* D-Channel frame (tx) */
768 if (S_FILTER && (~S_INT_S1 & 0x80)) S_FILTER(sc, chan);
770 if (S_INT_S1 & 0x80) /* Timer elapsed (50ms) */
775 if (chan == 1) continue;
776 if (S_FILTER) S_FILTER(sc, chan);
789 /*---------------------------------------------------------------------------*
790 * Select a Bfifo (HFC-1/S/SP)
791 * and return bytes in FIFO
793 * (this code is optimized)
794 *---------------------------------------------------------------------------*/
796 ihfc_Bsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
798 register u_char reg = 0x7e + chan;
799 register u_short tmp = 0x100;
805 if (S_HFC & (HFC_1 | HFC_S))
807 if (S_LAST_CHAN != chan)
810 DISBUSY(WAITBUSY_2( , return 0), return 0);
818 WRITE_DATA_1(chan - 2);
819 DISBUSY( , return 0);
822 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
823 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
825 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
826 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
827 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
828 SET_REG(reg += 4); FAST_STAT; z2 |= READ_DATA_1 << 8;
836 z1 = 0x5ff - (z2 = z1 - z2 + ((z2 <= z1) ? 0 : 0x600));
839 return(z2); /* receive channel */
841 return(z1); /* transmit channel */
844 /*---------------------------------------------------------------------------*
845 * Select a Dfifo (HFC-S/SP)
846 * and return bytes, and frames in FIFO
849 * 0x00: select new fifo + update counters
850 * 0x10: increment f1 + update counters
851 * 0x20: increment f2 + update counters
853 * NOTE: The upper 16bits holds the number of frames in the FIFO.
854 * NOTE: FIFO has to be selected before you can use flags 0x10/0x20.
855 *---------------------------------------------------------------------------*/
857 ihfc_Dsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
859 register u_char reg = 0x90 + chan;
860 register u_short tmp = 0x100;
868 if (S_HFC & (HFC_1 | HFC_S))
876 WAITBUSY_2( , return 0);
878 SET_REG(0xa2 - (flag & 0x10) + chan);
879 DISBUSY(READ_DATA_1, return 0);
883 WAITBUSY_2( , return 0);
887 if (S_LAST_CHAN != chan)
890 DISBUSY(WAITBUSY_2( , return 0), return 0);
903 SET_REG(0xb8 - (flag & 0x10) + chan);
906 DISBUSY( , return 0);
910 /* Before reading a FIFO a change *
911 * FIFO operation must be done. *
912 * (see HFC-SP manual p.38) */
915 WRITE_DATA_1(chan | 4);
917 DISBUSY( , return 0);
923 WRITE_DATA_1(chan | 4);
925 DISBUSY( , return 0);
930 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
931 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
933 if (S_HFC & HFC_SP) reg = 0x80 + chan;
935 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
936 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
937 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
938 SET_REG(reg += 4); FAST_STAT; z2 |= FAST_READ << 8;
940 if (S_HFC & HFC_SP) reg += 0x26;
942 SET_REG(reg -= 2); FAST_STAT; f1 = FAST_READ;
943 SET_REG(reg += 4); FAST_STAT; f2 = READ_DATA_1;
950 S_HDLC_DZ_TAB[f1 & 0xf] = z2; /* We keep track of the 'Z' *
951 * values for D-channel (tx),*
952 * so we may calculate the # *
953 * of FIFO bytes free when *
955 z2 = S_HDLC_DZ_TAB[f2 & 0xf];
958 z1 = 0x1ff - (z2 = (z1 - z2) & 0x1ff);
959 f1 = 0xf - (f2 = (f1 - f2) & 0xf);
962 return(z2 | (f2 << 16)); /* receive channel */
964 return(z1 | (f1 << 16)); /* transmit channel */
968 /*---------------------------------------------------------------------------*
969 * Data handler for D channel(write) - chan 0 (HFC-S/SP)
970 *---------------------------------------------------------------------------*/
972 ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan)
974 register u_int32_t sendlen;
975 register u_short len;
976 register u_char * src;
980 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
982 sendlen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
983 * NOTE: the 16 higher bits *
984 * contain the # of frame- *
985 * etries free in the FIFO */
986 while (sendlen & ~0xffff)
990 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j1;
996 if (len >= 0x1ff) goto j0; /* frame is too big: skip! */
998 sendlen &= 0xffff; /* only keep # of *
1001 SET_REG((S_HFC & HFC_SP) ? 0xac : 0x96);
1007 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1010 if (!++sendlen) /* out of fifo: suspend */
1017 sendlen = ihfc_Dsel_fifo(sc, chan, 0x10); /* inc F1 */
1019 i4b_Dfreembuf(S_MBUF);
1026 /*---------------------------------------------------------------------------*
1027 * Data handler for D channel(read) - chan 1 (HFC-S/SP)
1029 * NOTE: Max framelength is (511 - 3) = 508 bytes, when only one frame
1030 * is received at a time.
1031 *---------------------------------------------------------------------------*/
1033 ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan)
1035 register u_char tmp = -1;
1036 register u_char to = 15;
1037 register u_int32_t reclen;
1038 register u_short crc;
1039 register u_short len;
1040 register u_char * dst;
1044 reclen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
1045 * NOTE: the higher 16 bits *
1046 * contain the # of frames *
1048 while ((reclen & ~0xffff) && to--)
1050 reclen &= 0xffff; /* only keep # of *
1051 * bytes to receive */
1053 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1054 panic("ihfc_hdlc_Dread: No mbufs(unit=%d)!\n", S_UNIT);
1056 SET_REG((S_HFC & HFC_SP) ? 0xbd : 0xa7);
1058 if ((reclen > 2) && (reclen <= (DCH_MAX_LEN+2)))
1061 len = S_MBUFLEN = (reclen += 1) - 3;
1069 crc = -1; /* NOTE: after a "F1" or "Z1" hardware overflow *
1070 * it appears not to be necessary to reset the *
1071 * HFC-1/S or SP chips to continue proper *
1072 * operation, only and only, if we always read *
1073 * "Z1-Z2+1" bytes when F1!=F2 followed by a *
1074 * F2-counter increment. The bi-effect of doing *
1075 * this is the "STAT" field may say frame is ok *
1076 * when the frame is actually bad. *
1077 * The simple solution is to re-CRC the frame *
1078 * including "STAT" field to see if we get *
1079 * CRC == 0x3933. Then we're 99% sure all *
1080 * frames received are good. */
1084 DISBUSY(tmp = READ_DATA_1, break);
1085 if (len) { len--; *dst++ = tmp; }
1087 crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8));
1094 ihfc_putmbuf(sc, chan, S_MBUF);
1099 NDBGL1(L1_ERROR, "Frame error (len=%d, stat=0x%x, "
1100 "crc=0x%x, unit=%d)", S_MBUFLEN, (u_char)tmp, crc,
1103 i4b_Dfreembuf(S_MBUF);
1107 reclen = ihfc_Dsel_fifo(sc, chan, 0x20);
1111 /*---------------------------------------------------------------------------*
1112 * EXIR error handler - ISAC (D - channel) (HFC-1)
1113 *---------------------------------------------------------------------------*/
1115 ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir)
1118 register u_char cmd;
1120 for (a = 0, cmd = 0; exir; a++, exir >>= 1)
1124 NDBGL1(L1_I_ERR, "%s. (unit=%d)",
1125 ihfc_EXIRtable[a].string, S_UNIT);
1126 cmd |= ihfc_EXIRtable[a].cmd;
1130 if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1133 /*---------------------------------------------------------------------------*
1134 * CMDR handler - ISAC (D - channel) (HFC-1)
1135 *---------------------------------------------------------------------------*/
1137 ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr)
1141 SET_REG(0x21); DISBUSY(WRITE_DATA_1(cmdr); DELAY(30), );
1144 /*---------------------------------------------------------------------------*
1145 * Data handler for D channel(write) - chan 0 (HFC-1)
1146 *---------------------------------------------------------------------------*/
1148 ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan)
1150 register u_char sendlen = 32;
1151 register u_char cmd = 0;
1152 register u_short len;
1153 register u_char * src;
1157 if (~S_ISTA & 0x10) goto j0;
1160 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j0;
1167 while(sendlen--) /* write data */
1170 DISBUSY(WRITE_DATA_1(*src++), goto a0);
1175 if (!++sendlen) /* suspend */
1183 i4b_Dfreembuf(S_MBUF);
1189 if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1196 /*---------------------------------------------------------------------------*
1197 * Data handler for D channel(read) - chan 1 (HFC-1)
1198 *---------------------------------------------------------------------------*/
1200 ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan)
1202 register u_char cmd = 0;
1203 register u_char reclen;
1204 register u_short tmp;
1205 register u_short len;
1206 register u_char * dst;
1210 if (!(S_ISTA & 0xc0)) goto j1; /* only receive data *
1215 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1216 panic("ihfc%d: (D) Out of mbufs!\n", S_UNIT);
1220 dst = S_MBUFDATA + (DCH_MAX_LEN - len);
1222 if (S_ISTA & 0x80) /* RME */
1224 SET_REG(0x27); DISBUSY(tmp = (READ_DATA_1 ^ 0x20), goto j0);
1226 if (tmp & 0x70) goto j0; /* error */
1228 SET_REG(0x25); DISBUSY(tmp = (READ_DATA_1 & 0x1f), goto j0);
1230 reclen = (tmp) ? tmp : 32;
1237 if ((len -= reclen) <= DCH_MAX_LEN) /* get data */
1243 DISBUSY(*dst++ = READ_DATA_1, goto j0);
1246 else /* soft rdo or error */
1248 j0: i4b_Dfreembuf(S_MBUF);
1253 NDBGL1(L1_I_ERR, "Frame error (unit=%d)", S_UNIT);
1256 if (S_ISTA & 0x80) /* frame complete */
1260 S_MBUFLEN = (DCH_MAX_LEN - len);
1261 ihfc_putmbuf(sc, chan, S_MBUF);
1266 if (S_MBUF) /* suspend */
1271 ihfc_cmdr_hdlr(sc, cmd | 0x80);
1278 /*---------------------------------------------------------------------------*
1279 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1281 * NOTE: No XDU checking!
1282 *---------------------------------------------------------------------------*/
1284 ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan)
1286 register u_short sendlen;
1287 register u_short len;
1288 register u_char * src;
1292 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
1294 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1296 SET_REG(0xaa + chan);
1302 S_MBUF = ihfc_getmbuf(sc, chan);
1313 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1316 if (!++sendlen) /* out of fifo: Suspend */
1323 i4b_Dfreembuf(S_MBUF);
1328 /*---------------------------------------------------------------------------*
1329 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1330 * (this code is optimized)
1331 *---------------------------------------------------------------------------*/
1333 ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan)
1335 register u_short reclen;
1336 register u_short tmp;
1337 register u_short len;
1338 register u_char * dst;
1342 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1346 SET_REG(0xba + chan);
1351 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1352 panic("ihfc%d: (B) Out of mbufs!\n", S_UNIT);
1355 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1361 if (tmp & 0x100) DISBUSY( , reclen = -1; len++; break);
1362 *dst++ = (u_char)(tmp = READ_BOTH_2);
1368 READ_DATA_1; /* a read to the data port *
1369 * will disable the internal *
1370 * disbusy signal for HFC-1/S *
1371 * chips. This is neccessary *
1372 * to avvoid data loss. */
1375 if (!++reclen) /* out of fifo: suspend */
1381 S_MBUFLEN = (BCH_MAX_DATALEN - ++len);
1383 ihfc_putmbuf(sc, chan, S_MBUF);
1389 /*---------------------------------------------------------------------------*
1390 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1392 * NOTE: Software HDLC encoding!
1393 *---------------------------------------------------------------------------*/
1395 ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan)
1397 register u_short blevel = S_HDLC_BLEVEL;
1398 register u_char flag = S_HDLC_FLAG;
1399 register u_int tmp = S_HDLC_TMP;
1400 register u_short crc = S_HDLC_CRC;
1401 register u_short ib = S_HDLC_IB;
1402 register u_char * src = NULL;
1403 register u_short len = 0;
1404 register u_short sendlen;
1405 register u_short tmp2;
1409 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE) && (flag == 2)) return;
1411 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1413 SET_REG(0xaa + chan);
1422 if (sendlen == 0x5ff)
1429 NDBGL1(L1_S_ERR, "XDU (unit=%d)", S_UNIT);
1435 HDLC_ENCODE(*src++, len, tmp, tmp2, blevel, ib, crc, flag,
1437 i4b_Bfreembuf(S_MBUF);
1438 S_MBUF = ihfc_getmbuf(sc, chan);
1447 sendlen = 0; /* Exit after final FS, *
1448 * else the buffer will *
1449 * only be filled with *
1455 DISBUSY(WRITE_DATA_1((u_char)tmp), sendlen = 0);
1460 if (S_MBUF) /* suspend */
1467 S_HDLC_BLEVEL = blevel;
1473 /*---------------------------------------------------------------------------*
1474 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1476 * NOTE: Software HDLC decoding!
1477 *---------------------------------------------------------------------------*/
1479 ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan)
1481 register u_char blevel = S_HDLC_BLEVEL;
1482 u_char flag = S_HDLC_FLAG;
1483 register u_short crc = S_HDLC_CRC;
1484 register u_int tmp = S_HDLC_TMP;
1485 register u_short ib = S_HDLC_IB;
1486 register u_char * dst = NULL;
1487 register u_short tmp2 = 0x100;
1488 register u_short len = 0;
1489 register u_short reclen;
1498 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1501 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1503 SET_REG(0xba + chan);
1507 HDLC_DECODE(*dst++, len, tmp, tmp2, blevel, ib, crc, flag,
1509 /* if (tmp2 & 0x100) while (GET_STAT & 1);
1510 * tmp2 = READ_BOTH_2;
1513 DISBUSY(tmp2 = READ_DATA_1, reclen = 0; tmp2 = 0);
1516 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1517 panic("ihfc:(B) Out of mbufs!\n");
1520 len = BCH_MAX_DATALEN;
1523 len = (BCH_MAX_DATALEN - len);
1525 if ((!len) || (len > BCH_MAX_DATALEN))
1527 /* NOTE: frames without any data, *
1528 * only crc field, should be silently discared. */
1530 i4b_Bfreembuf(S_MBUF);
1531 NDBGL1(L1_S_MSG, "Bad frame (len=%d, unit=%d)", len, S_UNIT);
1536 { i4b_Bfreembuf(S_MBUF);
1537 NDBGL1(L1_S_ERR, "CRC (crc=0x%04x, len=%d, unit=%d)", crc, len, S_UNIT);
1543 ihfc_putmbuf(sc, chan, S_MBUF);
1548 i4b_Bfreembuf(S_MBUF);
1551 NDBGL1(L1_S_MSG, "Read Abort (unit=%d)", S_UNIT);
1554 i4b_Bfreembuf(S_MBUF);
1557 NDBGL1(L1_S_ERR, "RDO (unit=%d)", S_UNIT);
1564 * if (~tmp2 & 0x100) READ_DATA_1; kill disbusy signal
1567 if (S_MBUF) S_MBUFLEN = len; /* suspend */
1573 S_HDLC_BLEVEL = blevel;
1576 /*---------------------------------------------------------------------------*
1577 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1579 * This filter generates a pattern which is recognized
1580 * and examinated and verified by ihfc_test_Bread.
1582 * NOTE: This filter is only for testing purpose.
1583 *---------------------------------------------------------------------------*/
1585 ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan)
1590 register u_short sendlen, tlen;
1591 register u_short xlen = S_HDLC_IB;
1596 while((m = ihfc_getmbuf(sc, chan))) /* internal loop */
1599 ihfc_putmbuf(sc, 5, m);
1601 ihfc_putmbuf(sc, 3, m);
1606 sendlen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1608 if (sendlen == 0x5ff) printf("(send empty)");
1610 SET_REG(0xaa + chan);
1616 if (sendlen > 0x400) printf("(slow: %d)", sendlen);
1622 if (!tlen--) fb |= 0x20;
1626 while(GET_STAT & 1);
1632 while(GET_STAT & 1);
1633 WRITE_DATA_1((xlen + 1) & 0xef);
1642 /*---------------------------------------------------------------------------*
1643 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1645 * This filter examins and verifies the pattern
1646 * generated by ihfc_test_Bwrite.
1648 * NOTE: This filter is only for testing purpose.
1649 *---------------------------------------------------------------------------*/
1651 ihfc_test_Bread (ihfc_sc_t *sc, u_char chan)
1653 static u_short toterrors = 0;
1655 register u_short reclen, len, tlen;
1656 register u_char fb, tmp;
1658 register u_short xlen = S_HDLC_IB;
1659 register u_char *dst = NULL;
1660 register u_char error = S_HDLC_TMP;
1661 register u_char ecount = S_HDLC_FLAG;
1665 if (S_UNIT != 0) return;
1667 reclen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1678 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1685 SET_REG(0xba + chan);
1689 /* if (tmp2 & 0x100) while(GET_STAT & 1);
1690 * tmp = (u_char)(tmp2 = READ_BOTH_2);
1694 /* if (!(++busy % 4)) reclen++; */
1695 while(GET_STAT & 1);
1700 if ((tmp & 0x3f) == 0x3e)
1702 if ((BCH_MAX_DATALEN - len) != 201) error |= 4;
1704 if ((S_MBUF) && (error))
1706 if (len) { len--; *dst++ = error; }
1707 if (len) { len--; *dst++ = xlen+1; }
1708 if (len) { len--; *dst++ = ecount; }
1710 S_MBUFLEN = BCH_MAX_DATALEN - len;
1712 if (S_TRACE & TRACE_B_RX)
1713 ihfc_putmbuf(sc, chan, S_MBUF);
1715 i4b_Bfreembuf(S_MBUF);
1718 printf("(error%d, %d, %d)", S_UNIT, ecount, toterrors++);
1721 i4b_Bfreembuf(S_MBUF);
1722 S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN);
1725 len = BCH_MAX_DATALEN;
1731 /* SET_REG(0xba + chan); */
1735 if (!xlen) error |= 2;
1736 if ((tmp ^ xlen--) & 0xef) { error |= 1; ecount++; }
1738 if (!tlen--) fb |= 0x20;
1742 *dst++ = (tmp | fb);
1759 S_HDLC_FLAG = ecount;