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.4 2003/08/07 21:17:26 dillon Exp $
38 *---------------------------------------------------------------------------*/
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/socket.h>
51 #include "../../include/i4b_mbuf.h"
53 #include <net/i4b/include/machine/i4b_debug.h>
54 #include <net/i4b/include/machine/i4b_ioctl.h>
55 #include <net/i4b/include/machine/i4b_trace.h>
57 #include "../i4b_l1.h"
58 #include "../i4b_hdlc.h"
60 #include "i4b_ihfc_ext.h"
61 #include "i4b_ihfc_drv.h"
63 #include <machine/bus.h>
67 /*---------------------------------------------------------------------------*
69 *---------------------------------------------------------------------------*/
70 void ihfc_loadconfig (ihfc_sc_t *sc);
72 static void ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan);
73 static void ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan);
74 static void ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan);
75 static void ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan);
76 static void ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan);
77 static void ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan);
79 static void ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan);
80 static void ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan);
82 void ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr);
83 void ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir);
85 void ihfc_sq (ihfc_sc_t *sc);
87 static void ihfc_test_Bread (ihfc_sc_t *sc, u_char chan);
88 static void ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan);
90 u_short ihfc_Bsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
91 u_int32_t ihfc_Dsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
94 /*---------------------------------------------------------------------------*
95 * Commonly used ISA bus commands
96 *---------------------------------------------------------------------------*/
97 #define IHFC_DATA_OFFSET 0
98 #define IHFC_REG_OFFSET 1
100 #define BUS_VAR bus_space_handle_t h = rman_get_bushandle(S_IOBASE[0]); \
101 bus_space_tag_t t = rman_get_bustag (S_IOBASE[0])
103 #define SET_REG(reg) bus_space_write_1(t,h, IHFC_REG_OFFSET, reg)
104 #define GET_STAT bus_space_read_1 (t,h, IHFC_REG_OFFSET)
106 #define READ_DATA_1 bus_space_read_1 (t,h, IHFC_DATA_OFFSET)
107 #define READ_BOTH_2 bus_space_read_2 (t,h, IHFC_DATA_OFFSET)
109 #define WRITE_DATA_1(data) bus_space_write_1(t,h, IHFC_DATA_OFFSET, data)
110 #define WRITE_BOTH_2(data) bus_space_write_2(t,h, IHFC_DATA_OFFSET, data)
112 #define DISBUSY(okcmd, tocmd) \
117 u_int to = IHFC_DISBUSYTO; \
119 while(((a = GET_STAT) & 1) && --to); \
123 NDBGL1(L1_ERROR, "DISBUSY-TIMEOUT! (a=%04x, " \
124 "unit=%d)", a, S_UNIT); \
138 #define WAITBUSY_2(okcmd, tocmd) \
141 u_int to = IHFC_NONBUSYTO; \
143 while((~(a = READ_BOTH_2) & 0x100) && --to); \
147 NDBGL1(L1_ERROR, "NONBUSY-TIMEOUT! (a=%04x, " \
148 "unit=%d)", a, S_UNIT); \
157 /*---------------------------------------------------------------------------*
158 * Control function (HFC-1/S/SP)
161 * 1: reset and unlock chip (at boot only)
162 * 2: prepare for shutdown (at shutdown only)
163 * 3: reset and resume
164 * 4: select TE-mode (boot default)
165 * 5: select NT-mode (only HFC-S/SP/PCI)
167 * Returns != 0 on errornous chip
168 *---------------------------------------------------------------------------*/
170 ihfc_control(ihfc_sc_t *sc, int flag)
174 if (flag == 3) goto reset0;
187 WRITE_BOTH_2(0x5400 | S_IIO); /* enable IO (HFC-1/S) */
191 /* HFC-S/SP configuration */
193 S_CIRM = S_IIRQ|0x10; /* IRQ, 8K fifo mode */
194 S_CLKDEL = 0x00; /* 12.288mhz */
195 S_CTMT = 0x03; /* transperant mode */
196 S_CONNECT = 0x00; /* B channel data flow */
197 S_INT_M1 = 0x40; /* interrupt mask */
198 S_INT_M2 = 0x08; /* enable interrupt output */
199 S_MST_MODE = 0x01; /* master mode */
200 S_SCTRL = 0x50; /* S/Q on, non cap. line mode */
201 S_SCTRL_R = 0x00; /* B channel receive disable */
202 S_TEST = 0x00; /* no need for awake enable */
204 if (S_HFC & (HFC_1 | HFC_S)) /* configure timer (50ms) */
213 /* HFC-1 ISAC configuration (IOM-2 mode) */
216 S_ADF2 = 0x80; /* select mode IOM-2 */
217 S_SPCR = 0x00; /* B channel send disable (0x10 for test loop) */
218 S_MASK = 0xfb; /* enable CISQ */
219 S_MODE = 0xc9; /* receiver enabled */
220 S_SQXR = 0x0f; /* master, clock always active */
221 S_STCR = 0x70; /* TIC bus address = 7 */
222 S_STAR2 = 0x04; /* enable S/Q */
225 if (S_NTMODE) /* configure NT- or TE-mode */
227 S_SCTRL |= 0x04; /* NT mode */
228 S_CLKDEL &= ~0x7f; /* clear delay */
229 S_CLKDEL |= 0x6c; /* set delay */
233 S_SCTRL &= ~0x04; /* TE mode */
234 S_STDEL &= 0x7f; /* use mask! */
235 S_CLKDEL &= ~0x7f; /* clear delay */
236 S_CLKDEL |= S_STDEL; /* set delay */
238 if (S_DLP) /* configure D-priority */
240 S_SCTRL |= 0x08; /* (10/11) */
244 S_SCTRL &= ~0x08; /* (8/9) */
248 /* chip reset (HFC-1/S/SP) */
252 SET_REG((S_CIRM | 0xc8) & 0xdf);
254 DELAY(10); /* HFC-2B manual recommends a 4 *
255 * clock cycle delay after CIRM *
256 * write with reset=1. A 1us *
257 * delay, should do for 7.68mhz,*
258 * but just in case I make that *
261 SET_REG((S_CIRM | 0xc0) & 0xdf);
263 DELAY(250); /* ISAC manual says reset pulse *
264 * length is 125us. Accessing *
265 * ISAC before those 125us, we *
266 * may risk chip corruption and *
267 * irq failure. The HFC-2B also *
268 * needs some delay to recover, *
269 * so we add some us. */
275 WRITE_DATA_1(S_CIRM | 8);
277 DELAY(10); /* HFC-2BDS0 manual recommends *
278 * a 4 clock cycle delay after *
279 * CIRM write with reset=1. *
280 * A 1us delay, should do for *
281 * 12.288mhz, but just in case *
282 * I make that 10us. */
284 WRITE_DATA_1(S_CIRM);
286 DELAY(25); /* HFC-2BDS0 needs some time to *
287 * recover after CIRM write *
288 * with reset=0. Experiments *
289 * show this delay should be *
290 * 8-9us. Just in case we make *
295 /* HFC-1/S/SP chip test *
297 * NOTE: after reset the HFC-1/S/SP should be *
298 * in a mode where it is always non-busy/non- *
299 * processing, and bit[0] of STATUS/DISBUSY *
300 * register, should always return binary '0' *
301 * until we configure the chips for normal *
304 printf("ihfc: GET_STAT value is: 0x%x\n", GET_STAT);
308 if ((GET_STAT & 1) || (READ_DATA_1 & 0xf)) goto f0;
313 if (S_HFC & HFC_1) ihfc_cmdr_hdlr(sc, 0x41); /* rres, xres */
321 if (S_HFC & HFC_1) S_CIRM &= ~0x03; /* disable interrupt */
323 S_SQXR |= 0x40; /* power down */
328 S_SPCR &= ~0x0f; /* send 1's only */
329 S_SCTRL &= ~0x83; /* send 1's only + enable oscillator */
334 return(0); /* success */
337 return(1); /* failure */
340 /*---------------------------------------------------------------------------*
341 * Softc initializer and hardware setup (HFC-1/S/SP)
343 * Returns: 0 on success
345 *---------------------------------------------------------------------------*/
347 ihfc_init (ihfc_sc_t *sc, u_char chan, int prot, int activate)
349 if (chan > 5) goto f0;
354 { if (chan < 2) /* D-Channel */
356 i4b_Dfreembuf(S_MBUF);
357 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Dcleanifq(&S_IFQUEUE);
359 RESET_SOFT_CHAN(sc, chan);
361 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
363 #if defined (__FreeBSD__) && __FreeBSD__ > 4
364 mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", MTX_DEF);
366 if (!activate) continue;
370 S_FILTER = (chan & 1) ? ihfc_isac_Dread :
375 S_FILTER = (chan & 1) ? ihfc_hdlc_Dread :
381 i4b_Bfreembuf(S_MBUF);
382 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Bcleanifq(&S_IFQUEUE);
384 RESET_SOFT_CHAN(sc, chan);
386 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
388 #if defined (__FreeBSD__) && __FreeBSD__ > 4
389 mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", MTX_DEF);
393 if (!activate) continue;
397 S_FILTER = (chan & 1) ?
402 S_FILTER = (chan & 1) ?
407 S_FILTER = (chan & 1) ?
413 } while (++chan & 1);
415 S_MASK |= 0xfb; /* disable all, but CISQ interrupt (ISAC) */
416 S_INT_M1 &= 0x40; /* disable all, but TE/NT state machine (HFC) */
417 S_SCTRL &= ~0x03; /* B1/B2 send disable (HFC) */
418 S_SPCR &= ~0x0f; /* B1/B2 send disable (ISAC) */
419 S_SCTRL_R &= ~0x03; /* B1/B2 receive disable (HFC) */
422 if (S_FILTER) /* D-Channel active */
424 S_MASK &= 0x2e; /* enable RME, RPF, XPR, EXI */
425 S_INT_M1 |= 0x24; /* enable D-receive, D-transmit */
429 if (S_FILTER) /* B1-Channel active */
431 S_SCTRL |= 1; /* send enable (HFC) */
432 S_SPCR |= 8; /* send enable (ISAC) */
433 S_SCTRL_R |= 1; /* receive enable (HFC) */
434 S_INT_M1 |= 0x80; /* timer enable (HFC) */
435 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
439 if (S_FILTER) /* B2-Channel active */
441 S_SCTRL |= 2; /* send enable (HFC) */
442 S_SPCR |= 2; /* send enable (ISAC) */
443 S_SCTRL_R |= 2; /* receive enable (HFC) */
444 S_INT_M1 |= 0x80; /* timer enable (HFC) */
445 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
450 /* XXX reset timer? */
452 return 0; /* success */
454 return 1; /* failure */
457 /*---------------------------------------------------------------------------*
458 * Load configuration data (HFC-1/S/SP)
459 *---------------------------------------------------------------------------*/
461 ihfc_loadconfig(ihfc_sc_t *sc)
467 /* HFC-1 chips w/ISAC: */
469 const u_char *src = (void *)&S_ISAC_CONFIG;
470 const u_char *dst = (void *)&isac_configtable;
472 SET_REG((S_CIRM | 0xc0) & 0xdf);
474 S_CTMT = (S_CTMT & ~0x14) | ((S_INT_M1 >> 5) & 0x4);
476 SET_REG((S_CTMT | 0xe0) & 0xff);
480 SET_REG(*dst++); /* set register */
482 /* write configuration */
483 DISBUSY(WRITE_DATA_1(*src++), break);
488 /* HFC-S/SP chips: */
490 const u_char *src = (void *)&S_HFC_CONFIG;
491 const u_char *dst = (void *)&ihfc_configtable;
495 SET_REG(*dst++); /* set register */
496 WRITE_DATA_1(*src++); /* write configuration */
501 /*---------------------------------------------------------------------------*
502 * Function State Machine handler (PH layer) (HFC-1/S/SP)
504 * Flag: 0 = Refresh softc S_PHSTATE + take hints
508 * NOTE: HFC-1 only supports TE mode.
509 *---------------------------------------------------------------------------*/
511 ihfc_fsm(ihfc_sc_t *sc, int flag)
513 const struct ihfc_FSMtable *fsmtab;
519 /* get current state (rx/downstream) */
523 SET_REG(0x31); DISBUSY(tmp = (READ_DATA_1 >> 2) & 0xf, return);
525 fsmtab = (S_NTMODE) ? &ihfc_TEtable2[tmp]:
530 SET_REG(0x30); tmp = READ_DATA_1 & 0xf;
532 fsmtab = (S_NTMODE) ? &ihfc_NTtable[tmp]:
538 NDBGL1(L1_I_CICO, "%s (ind=0x%x, flag=%d, unit=%d).",
539 fsmtab->string, tmp, flag, S_UNIT);
543 NDBGL1(L1_I_ERR, "Illegal indicatation (ind=0x%x, "
544 "flag=%d, unit=%d).", tmp, flag, S_UNIT);
547 /* indication machine / state change *
549 * Whenever the state of the S0-line changes, we check to see in which *
550 * direction the change went. Generally upwards means activate, and *
551 * downwards means deactivate. *
552 * The test signal is used to ensure proper syncronization. */
554 if (fsmtab->state == 0) /* deactivated indication */
558 isac_cmd = 0x3c; /* deactivate DUI */
560 i4b_l1_ph_deactivate_ind(S_I4BUNIT);
563 if (fsmtab->state == 2) /* syncronized indication */
567 if (S_NTMODE) ihfc_cmd = 0x80;
570 if (fsmtab->state == 3) /* activated indication */
574 isac_cmd = (S_DLP) ? 0x24 /* activate AR10 */
575 : 0x20; /* activate AR8 */
577 i4b_l1_ph_activate_ind(S_I4BUNIT);
580 if (fsmtab->state == 4) /* error indication */
584 isac_cmd = 0x3c; /* deactivate DUI */
588 S_PHSTATE = fsmtab->state;
590 if ((flag == 1) && (fsmtab->state != 3))
592 isac_cmd = (S_DLP) ? 0x24 : 0x20;
595 if ((flag == 2) && (fsmtab->state != 0))
601 /* set new state (tx / upstream) *
603 * NOTE: HFC-S/SP and ISAC transmitters are always active when *
604 * activated state is reached. The bytes sent to the S0-bus are all *
605 * high impedance, so they do not disturb. *
606 * The HFC-1 has a separate SIEMENS S0-device. */
612 if (S_IOM2) isac_cmd |= 3;
614 SET_REG(0x31); DISBUSY(WRITE_DATA_1(isac_cmd), );
616 NDBGL1(L1_I_CICO, "(isac_cmd=0x%x, unit=%d).",
622 if (ihfc_cmd || (fsmtab->state == 5))
624 SET_REG(0x30); WRITE_DATA_1(ihfc_cmd);
626 NDBGL1(L1_I_CICO, "(ihfc_cmd=0x%x, unit=%d).",
632 /*---------------------------------------------------------------------------*
633 * S/Q - channel handler (read) (HFC-S/SP)
634 *---------------------------------------------------------------------------*/
636 ihfc_sq (ihfc_sc_t *sc)
638 const struct ihfc_SQtable *SQtab;
645 DISBUSY(a = READ_DATA_1, a = 0);
650 DISBUSY(a = READ_DATA_1, a = 0);
659 SQtab = (S_NTMODE) ? &ihfc_Qtable[a & 7]:
666 NDBGL1(L1_I_CICO, "%s (unit=%d, int=%x)",
667 SQtab->string, S_UNIT, S_INT_S1);
671 NDBGL1(L1_ERROR, "Unknown indication = %x (unit=%d)",
677 /*---------------------------------------------------------------------------*
678 * Interrupt handler (HFC-1)
679 *---------------------------------------------------------------------------*/
681 ihfc_intr1 (ihfc_sc_t *sc)
690 SET_REG(0x20); tmp = GET_STAT; DISBUSY(S_ISTA |= READ_DATA_1, );
692 if (S_ISTA & 0x04) /* CIRQ */
701 if (S_ISTA & 0xc0) /* RPF or RME */
704 if (S_FILTER) S_FILTER(sc, chan);
706 if (S_ISTA & 0x10) /* XPR */
709 if (S_FILTER) S_FILTER(sc, chan);
711 if (tmp & 0x04) /* Timer elapsed (50ms) */
713 SET_REG((S_CTMT | 0xf0) & 0xff);
718 if (chan == 1) break;
719 if (S_FILTER) S_FILTER(sc, chan);
729 if (S_ISTA & 0x01) /* EXIR */
731 SET_REG(0x24); DISBUSY(ihfc_exir_hdlr(sc, READ_DATA_1), );
734 S_ISTA &= ~(0x1 | 0x4);
739 /*---------------------------------------------------------------------------*
740 * Interrupt handler (HFC-S/SP)
741 *---------------------------------------------------------------------------*/
743 ihfc_intr2 (ihfc_sc_t *sc)
751 SET_REG(0x1e); S_INT_S1 = READ_DATA_1; /* this will enable new interrupts! */
755 HFC_FSM(sc, 0); /* statemachine changed */
762 if (S_INT_S1 & 0x20) /* D-Channel frame (rx) */
765 if (S_FILTER) S_FILTER(sc, chan);
767 if (S_INT_S1 & 0x04) /* D-Channel frame (tx) */
770 if (S_FILTER && (~S_INT_S1 & 0x80)) S_FILTER(sc, chan);
772 if (S_INT_S1 & 0x80) /* Timer elapsed (50ms) */
777 if (chan == 1) continue;
778 if (S_FILTER) S_FILTER(sc, chan);
791 /*---------------------------------------------------------------------------*
792 * Select a Bfifo (HFC-1/S/SP)
793 * and return bytes in FIFO
795 * (this code is optimized)
796 *---------------------------------------------------------------------------*/
798 ihfc_Bsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
800 u_char reg = 0x7e + chan;
807 if (S_HFC & (HFC_1 | HFC_S))
809 if (S_LAST_CHAN != chan)
812 DISBUSY(WAITBUSY_2( , return 0), return 0);
820 WRITE_DATA_1(chan - 2);
821 DISBUSY( , return 0);
824 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
825 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
827 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
828 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
829 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
830 SET_REG(reg += 4); FAST_STAT; z2 |= READ_DATA_1 << 8;
838 z1 = 0x5ff - (z2 = z1 - z2 + ((z2 <= z1) ? 0 : 0x600));
841 return(z2); /* receive channel */
843 return(z1); /* transmit channel */
846 /*---------------------------------------------------------------------------*
847 * Select a Dfifo (HFC-S/SP)
848 * and return bytes, and frames in FIFO
851 * 0x00: select new fifo + update counters
852 * 0x10: increment f1 + update counters
853 * 0x20: increment f2 + update counters
855 * NOTE: The upper 16bits holds the number of frames in the FIFO.
856 * NOTE: FIFO has to be selected before you can use flags 0x10/0x20.
857 *---------------------------------------------------------------------------*/
859 ihfc_Dsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
861 u_char reg = 0x90 + chan;
870 if (S_HFC & (HFC_1 | HFC_S))
878 WAITBUSY_2( , return 0);
880 SET_REG(0xa2 - (flag & 0x10) + chan);
881 DISBUSY(READ_DATA_1, return 0);
885 WAITBUSY_2( , return 0);
889 if (S_LAST_CHAN != chan)
892 DISBUSY(WAITBUSY_2( , return 0), return 0);
905 SET_REG(0xb8 - (flag & 0x10) + chan);
908 DISBUSY( , return 0);
912 /* Before reading a FIFO a change *
913 * FIFO operation must be done. *
914 * (see HFC-SP manual p.38) */
917 WRITE_DATA_1(chan | 4);
919 DISBUSY( , return 0);
925 WRITE_DATA_1(chan | 4);
927 DISBUSY( , return 0);
932 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
933 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
935 if (S_HFC & HFC_SP) reg = 0x80 + chan;
937 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
938 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
939 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
940 SET_REG(reg += 4); FAST_STAT; z2 |= FAST_READ << 8;
942 if (S_HFC & HFC_SP) reg += 0x26;
944 SET_REG(reg -= 2); FAST_STAT; f1 = FAST_READ;
945 SET_REG(reg += 4); FAST_STAT; f2 = READ_DATA_1;
952 S_HDLC_DZ_TAB[f1 & 0xf] = z2; /* We keep track of the 'Z' *
953 * values for D-channel (tx),*
954 * so we may calculate the # *
955 * of FIFO bytes free when *
957 z2 = S_HDLC_DZ_TAB[f2 & 0xf];
960 z1 = 0x1ff - (z2 = (z1 - z2) & 0x1ff);
961 f1 = 0xf - (f2 = (f1 - f2) & 0xf);
964 return(z2 | (f2 << 16)); /* receive channel */
966 return(z1 | (f1 << 16)); /* transmit channel */
970 /*---------------------------------------------------------------------------*
971 * Data handler for D channel(write) - chan 0 (HFC-S/SP)
972 *---------------------------------------------------------------------------*/
974 ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan)
982 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
984 sendlen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
985 * NOTE: the 16 higher bits *
986 * contain the # of frame- *
987 * etries free in the FIFO */
988 while (sendlen & ~0xffff)
992 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j1;
998 if (len >= 0x1ff) goto j0; /* frame is too big: skip! */
1000 sendlen &= 0xffff; /* only keep # of *
1003 SET_REG((S_HFC & HFC_SP) ? 0xac : 0x96);
1009 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1012 if (!++sendlen) /* out of fifo: suspend */
1019 sendlen = ihfc_Dsel_fifo(sc, chan, 0x10); /* inc F1 */
1021 i4b_Dfreembuf(S_MBUF);
1027 /*---------------------------------------------------------------------------*
1028 * Data handler for D channel(read) - chan 1 (HFC-S/SP)
1030 * NOTE: Max framelength is (511 - 3) = 508 bytes, when only one frame
1031 * is received at a time.
1032 *---------------------------------------------------------------------------*/
1034 ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan)
1045 reclen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
1046 * NOTE: the higher 16 bits *
1047 * contain the # of frames *
1049 while ((reclen & ~0xffff) && to--)
1051 reclen &= 0xffff; /* only keep # of *
1052 * bytes to receive */
1054 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1055 panic("ihfc_hdlc_Dread: No mbufs(unit=%d)!\n", S_UNIT);
1057 SET_REG((S_HFC & HFC_SP) ? 0xbd : 0xa7);
1059 if ((reclen > 2) && (reclen <= (DCH_MAX_LEN+2)))
1062 len = S_MBUFLEN = (reclen += 1) - 3;
1070 crc = -1; /* NOTE: after a "F1" or "Z1" hardware overflow *
1071 * it appears not to be necessary to reset the *
1072 * HFC-1/S or SP chips to continue proper *
1073 * operation, only and only, if we always read *
1074 * "Z1-Z2+1" bytes when F1!=F2 followed by a *
1075 * F2-counter increment. The bi-effect of doing *
1076 * this is the "STAT" field may say frame is ok *
1077 * when the frame is actually bad. *
1078 * The simple solution is to re-CRC the frame *
1079 * including "STAT" field to see if we get *
1080 * CRC == 0x3933. Then we're 99% sure all *
1081 * frames received are good. */
1085 DISBUSY(tmp = READ_DATA_1, break);
1086 if (len) { len--; *dst++ = tmp; }
1088 crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8));
1095 ihfc_putmbuf(sc, chan, S_MBUF);
1100 NDBGL1(L1_ERROR, "Frame error (len=%d, stat=0x%x, "
1101 "crc=0x%x, unit=%d)", S_MBUFLEN, (u_char)tmp, crc,
1104 i4b_Dfreembuf(S_MBUF);
1108 reclen = ihfc_Dsel_fifo(sc, chan, 0x20);
1112 /*---------------------------------------------------------------------------*
1113 * EXIR error handler - ISAC (D - channel) (HFC-1)
1114 *---------------------------------------------------------------------------*/
1116 ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir)
1121 for (a = 0, cmd = 0; exir; a++, exir >>= 1)
1125 NDBGL1(L1_I_ERR, "%s. (unit=%d)",
1126 ihfc_EXIRtable[a].string, S_UNIT);
1127 cmd |= ihfc_EXIRtable[a].cmd;
1131 if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1134 /*---------------------------------------------------------------------------*
1135 * CMDR handler - ISAC (D - channel) (HFC-1)
1136 *---------------------------------------------------------------------------*/
1138 ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr)
1142 SET_REG(0x21); DISBUSY(WRITE_DATA_1(cmdr); DELAY(30), );
1145 /*---------------------------------------------------------------------------*
1146 * Data handler for D channel(write) - chan 0 (HFC-1)
1147 *---------------------------------------------------------------------------*/
1149 ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan)
1151 u_char sendlen = 32;
1158 if (~S_ISTA & 0x10) goto j0;
1161 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j0;
1168 while(sendlen--) /* write data */
1171 DISBUSY(WRITE_DATA_1(*src++), goto a0);
1176 if (!++sendlen) /* suspend */
1184 i4b_Dfreembuf(S_MBUF);
1190 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)
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);
1277 /*---------------------------------------------------------------------------*
1278 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1280 * NOTE: No XDU checking!
1281 *---------------------------------------------------------------------------*/
1283 ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan)
1291 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
1293 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1295 SET_REG(0xaa + chan);
1301 S_MBUF = ihfc_getmbuf(sc, chan);
1312 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1315 if (!++sendlen) /* out of fifo: Suspend */
1322 i4b_Dfreembuf(S_MBUF);
1327 /*---------------------------------------------------------------------------*
1328 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1329 * (this code is optimized)
1330 *---------------------------------------------------------------------------*/
1332 ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan)
1341 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1345 SET_REG(0xba + chan);
1350 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1351 panic("ihfc%d: (B) Out of mbufs!\n", S_UNIT);
1354 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1360 if (tmp & 0x100) DISBUSY( , reclen = -1; len++; break);
1361 *dst++ = (u_char)(tmp = READ_BOTH_2);
1367 READ_DATA_1; /* a read to the data port *
1368 * will disable the internal *
1369 * disbusy signal for HFC-1/S *
1370 * chips. This is neccessary *
1371 * to avvoid data loss. */
1374 if (!++reclen) /* out of fifo: suspend */
1380 S_MBUFLEN = (BCH_MAX_DATALEN - ++len);
1382 ihfc_putmbuf(sc, chan, S_MBUF);
1388 /*---------------------------------------------------------------------------*
1389 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1391 * NOTE: Software HDLC encoding!
1392 *---------------------------------------------------------------------------*/
1394 ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan)
1396 u_short blevel = S_HDLC_BLEVEL;
1397 u_char flag = S_HDLC_FLAG;
1398 u_int tmp = S_HDLC_TMP;
1399 u_short crc = S_HDLC_CRC;
1400 u_short ib = S_HDLC_IB;
1401 u_char * src = NULL;
1408 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE) && (flag == 2)) return;
1410 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1412 SET_REG(0xaa + chan);
1421 if (sendlen == 0x5ff)
1428 NDBGL1(L1_S_ERR, "XDU (unit=%d)", S_UNIT);
1434 HDLC_ENCODE(*src++, len, tmp, tmp2, blevel, ib, crc, flag,
1436 i4b_Bfreembuf(S_MBUF);
1437 S_MBUF = ihfc_getmbuf(sc, chan);
1446 sendlen = 0; /* Exit after final FS, *
1447 * else the buffer will *
1448 * only be filled with *
1454 DISBUSY(WRITE_DATA_1((u_char)tmp), sendlen = 0);
1459 if (S_MBUF) /* suspend */
1466 S_HDLC_BLEVEL = blevel;
1472 /*---------------------------------------------------------------------------*
1473 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1475 * NOTE: Software HDLC decoding!
1476 *---------------------------------------------------------------------------*/
1478 ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan)
1480 u_char blevel = S_HDLC_BLEVEL;
1481 u_char flag = S_HDLC_FLAG;
1482 u_short crc = S_HDLC_CRC;
1483 u_int tmp = S_HDLC_TMP;
1484 u_short ib = S_HDLC_IB;
1485 u_char * dst = NULL;
1486 u_short tmp2 = 0x100;
1497 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1500 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1502 SET_REG(0xba + chan);
1506 HDLC_DECODE(*dst++, len, tmp, tmp2, blevel, ib, crc, flag,
1508 /* if (tmp2 & 0x100) while (GET_STAT & 1);
1509 * tmp2 = READ_BOTH_2;
1512 DISBUSY(tmp2 = READ_DATA_1, reclen = 0; tmp2 = 0);
1515 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1516 panic("ihfc:(B) Out of mbufs!\n");
1519 len = BCH_MAX_DATALEN;
1522 len = (BCH_MAX_DATALEN - len);
1524 if ((!len) || (len > BCH_MAX_DATALEN))
1526 /* NOTE: frames without any data, *
1527 * only crc field, should be silently discared. */
1529 i4b_Bfreembuf(S_MBUF);
1530 NDBGL1(L1_S_MSG, "Bad frame (len=%d, unit=%d)", len, S_UNIT);
1535 { i4b_Bfreembuf(S_MBUF);
1536 NDBGL1(L1_S_ERR, "CRC (crc=0x%04x, len=%d, unit=%d)", crc, len, S_UNIT);
1542 ihfc_putmbuf(sc, chan, S_MBUF);
1547 i4b_Bfreembuf(S_MBUF);
1550 NDBGL1(L1_S_MSG, "Read Abort (unit=%d)", S_UNIT);
1553 i4b_Bfreembuf(S_MBUF);
1556 NDBGL1(L1_S_ERR, "RDO (unit=%d)", S_UNIT);
1563 * if (~tmp2 & 0x100) READ_DATA_1; kill disbusy signal
1566 if (S_MBUF) S_MBUFLEN = len; /* suspend */
1572 S_HDLC_BLEVEL = blevel;
1575 /*---------------------------------------------------------------------------*
1576 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1578 * This filter generates a pattern which is recognized
1579 * and examinated and verified by ihfc_test_Bread.
1581 * NOTE: This filter is only for testing purpose.
1582 *---------------------------------------------------------------------------*/
1584 ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan)
1589 u_short sendlen, tlen;
1590 u_short xlen = S_HDLC_IB;
1595 while((m = ihfc_getmbuf(sc, chan))) /* internal loop */
1598 ihfc_putmbuf(sc, 5, m);
1600 ihfc_putmbuf(sc, 3, m);
1605 sendlen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1607 if (sendlen == 0x5ff) printf("(send empty)");
1609 SET_REG(0xaa + chan);
1615 if (sendlen > 0x400) printf("(slow: %d)", sendlen);
1621 if (!tlen--) fb |= 0x20;
1625 while(GET_STAT & 1);
1631 while(GET_STAT & 1);
1632 WRITE_DATA_1((xlen + 1) & 0xef);
1641 /*---------------------------------------------------------------------------*
1642 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1644 * This filter examins and verifies the pattern
1645 * generated by ihfc_test_Bwrite.
1647 * NOTE: This filter is only for testing purpose.
1648 *---------------------------------------------------------------------------*/
1650 ihfc_test_Bread (ihfc_sc_t *sc, u_char chan)
1652 static u_short toterrors = 0;
1654 u_short reclen, len, tlen;
1657 u_short xlen = S_HDLC_IB;
1659 u_char error = S_HDLC_TMP;
1660 u_char ecount = S_HDLC_FLAG;
1664 if (S_UNIT != 0) return;
1666 reclen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1677 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1684 SET_REG(0xba + chan);
1688 /* if (tmp2 & 0x100) while(GET_STAT & 1);
1689 * tmp = (u_char)(tmp2 = READ_BOTH_2);
1693 /* if (!(++busy % 4)) reclen++; */
1694 while(GET_STAT & 1);
1699 if ((tmp & 0x3f) == 0x3e)
1701 if ((BCH_MAX_DATALEN - len) != 201) error |= 4;
1703 if ((S_MBUF) && (error))
1705 if (len) { len--; *dst++ = error; }
1706 if (len) { len--; *dst++ = xlen+1; }
1707 if (len) { len--; *dst++ = ecount; }
1709 S_MBUFLEN = BCH_MAX_DATALEN - len;
1711 if (S_TRACE & TRACE_B_RX)
1712 ihfc_putmbuf(sc, chan, S_MBUF);
1714 i4b_Bfreembuf(S_MBUF);
1717 printf("(error%d, %d, %d)", S_UNIT, ecount, toterrors++);
1720 i4b_Bfreembuf(S_MBUF);
1721 S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN);
1724 len = BCH_MAX_DATALEN;
1730 /* SET_REG(0xba + chan); */
1734 if (!xlen) error |= 2;
1735 if ((tmp ^ xlen--) & 0xef) { error |= 1; ecount++; }
1737 if (!tlen--) fb |= 0x20;
1741 *dst++ = (tmp | fb);
1758 S_HDLC_FLAG = ecount;
1761 #endif /* NIHFC > 0 */