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 $
37 *---------------------------------------------------------------------------*/
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/socket.h>
50 #include <i4b/include/i4b_mbuf.h>
52 #include <machine/i4b_debug.h>
53 #include <machine/i4b_ioctl.h>
54 #include <machine/i4b_trace.h>
56 #include <i4b/layer1/i4b_l1.h>
57 #include <i4b/layer1/i4b_hdlc.h>
58 #include <i4b/layer1/ihfc/i4b_ihfc.h>
59 #include <i4b/layer1/ihfc/i4b_ihfc_ext.h>
60 #include <i4b/layer1/ihfc/i4b_ihfc_drv.h>
62 #include <machine/bus.h>
66 /*---------------------------------------------------------------------------*
68 *---------------------------------------------------------------------------*/
69 void ihfc_loadconfig (ihfc_sc_t *sc);
71 static void ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan);
72 static void ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan);
73 static void ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan);
74 static void ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan);
75 static void ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan);
76 static void ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan);
78 static void ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan);
79 static void ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan);
81 void ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr);
82 void ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir);
84 void ihfc_sq (ihfc_sc_t *sc);
86 static void ihfc_test_Bread (ihfc_sc_t *sc, u_char chan);
87 static void ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan);
89 u_short ihfc_Bsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
90 u_int32_t ihfc_Dsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
93 /*---------------------------------------------------------------------------*
94 * Commonly used ISA bus commands
95 *---------------------------------------------------------------------------*/
96 #define IHFC_DATA_OFFSET 0
97 #define IHFC_REG_OFFSET 1
99 #define BUS_VAR bus_space_handle_t h = rman_get_bushandle(S_IOBASE[0]); \
100 bus_space_tag_t t = rman_get_bustag (S_IOBASE[0])
102 #define SET_REG(reg) bus_space_write_1(t,h, IHFC_REG_OFFSET, reg)
103 #define GET_STAT bus_space_read_1 (t,h, IHFC_REG_OFFSET)
105 #define READ_DATA_1 bus_space_read_1 (t,h, IHFC_DATA_OFFSET)
106 #define READ_BOTH_2 bus_space_read_2 (t,h, IHFC_DATA_OFFSET)
108 #define WRITE_DATA_1(data) bus_space_write_1(t,h, IHFC_DATA_OFFSET, data)
109 #define WRITE_BOTH_2(data) bus_space_write_2(t,h, IHFC_DATA_OFFSET, data)
111 #define DISBUSY(okcmd, tocmd) \
116 register u_int to = IHFC_DISBUSYTO; \
118 while(((a = GET_STAT) & 1) && --to); \
122 NDBGL1(L1_ERROR, "DISBUSY-TIMEOUT! (a=%04x, " \
123 "unit=%d)", a, S_UNIT); \
137 #define WAITBUSY_2(okcmd, tocmd) \
139 register u_short a; \
140 register u_int to = IHFC_NONBUSYTO; \
142 while((~(a = READ_BOTH_2) & 0x100) && --to); \
146 NDBGL1(L1_ERROR, "NONBUSY-TIMEOUT! (a=%04x, " \
147 "unit=%d)", a, S_UNIT); \
156 /*---------------------------------------------------------------------------*
157 * Control function (HFC-1/S/SP)
160 * 1: reset and unlock chip (at boot only)
161 * 2: prepare for shutdown (at shutdown only)
162 * 3: reset and resume
163 * 4: select TE-mode (boot default)
164 * 5: select NT-mode (only HFC-S/SP/PCI)
166 * Returns != 0 on errornous chip
167 *---------------------------------------------------------------------------*/
169 ihfc_control(ihfc_sc_t *sc, int flag)
173 if (flag == 3) goto reset0;
186 WRITE_BOTH_2(0x5400 | S_IIO); /* enable IO (HFC-1/S) */
190 /* HFC-S/SP configuration */
192 S_CIRM = S_IIRQ|0x10; /* IRQ, 8K fifo mode */
193 S_CLKDEL = 0x00; /* 12.288mhz */
194 S_CTMT = 0x03; /* transperant mode */
195 S_CONNECT = 0x00; /* B channel data flow */
196 S_INT_M1 = 0x40; /* interrupt mask */
197 S_INT_M2 = 0x08; /* enable interrupt output */
198 S_MST_MODE = 0x01; /* master mode */
199 S_SCTRL = 0x50; /* S/Q on, non cap. line mode */
200 S_SCTRL_R = 0x00; /* B channel receive disable */
201 S_TEST = 0x00; /* no need for awake enable */
203 if (S_HFC & (HFC_1 | HFC_S)) /* configure timer (50ms) */
212 /* HFC-1 ISAC configuration (IOM-2 mode) */
215 S_ADF2 = 0x80; /* select mode IOM-2 */
216 S_SPCR = 0x00; /* B channel send disable (0x10 for test loop) */
217 S_MASK = 0xfb; /* enable CISQ */
218 S_MODE = 0xc9; /* receiver enabled */
219 S_SQXR = 0x0f; /* master, clock always active */
220 S_STCR = 0x70; /* TIC bus address = 7 */
221 S_STAR2 = 0x04; /* enable S/Q */
224 if (S_NTMODE) /* configure NT- or TE-mode */
226 S_SCTRL |= 0x04; /* NT mode */
227 S_CLKDEL &= ~0x7f; /* clear delay */
228 S_CLKDEL |= 0x6c; /* set delay */
232 S_SCTRL &= ~0x04; /* TE mode */
233 S_STDEL &= 0x7f; /* use mask! */
234 S_CLKDEL &= ~0x7f; /* clear delay */
235 S_CLKDEL |= S_STDEL; /* set delay */
237 if (S_DLP) /* configure D-priority */
239 S_SCTRL |= 0x08; /* (10/11) */
243 S_SCTRL &= ~0x08; /* (8/9) */
247 /* chip reset (HFC-1/S/SP) */
251 SET_REG((S_CIRM | 0xc8) & 0xdf);
253 DELAY(10); /* HFC-2B manual recommends a 4 *
254 * clock cycle delay after CIRM *
255 * write with reset=1. A 1us *
256 * delay, should do for 7.68mhz,*
257 * but just in case I make that *
260 SET_REG((S_CIRM | 0xc0) & 0xdf);
262 DELAY(250); /* ISAC manual says reset pulse *
263 * length is 125us. Accessing *
264 * ISAC before those 125us, we *
265 * may risk chip corruption and *
266 * irq failure. The HFC-2B also *
267 * needs some delay to recover, *
268 * so we add some us. */
274 WRITE_DATA_1(S_CIRM | 8);
276 DELAY(10); /* HFC-2BDS0 manual recommends *
277 * a 4 clock cycle delay after *
278 * CIRM write with reset=1. *
279 * A 1us delay, should do for *
280 * 12.288mhz, but just in case *
281 * I make that 10us. */
283 WRITE_DATA_1(S_CIRM);
285 DELAY(25); /* HFC-2BDS0 needs some time to *
286 * recover after CIRM write *
287 * with reset=0. Experiments *
288 * show this delay should be *
289 * 8-9us. Just in case we make *
294 /* HFC-1/S/SP chip test *
296 * NOTE: after reset the HFC-1/S/SP should be *
297 * in a mode where it is always non-busy/non- *
298 * processing, and bit[0] of STATUS/DISBUSY *
299 * register, should always return binary '0' *
300 * until we configure the chips for normal *
303 printf("ihfc: GET_STAT value is: 0x%x\n", GET_STAT);
307 if ((GET_STAT & 1) || (READ_DATA_1 & 0xf)) goto f0;
312 if (S_HFC & HFC_1) ihfc_cmdr_hdlr(sc, 0x41); /* rres, xres */
320 if (S_HFC & HFC_1) S_CIRM &= ~0x03; /* disable interrupt */
322 S_SQXR |= 0x40; /* power down */
327 S_SPCR &= ~0x0f; /* send 1's only */
328 S_SCTRL &= ~0x83; /* send 1's only + enable oscillator */
333 return(0); /* success */
336 return(1); /* failure */
339 /*---------------------------------------------------------------------------*
340 * Softc initializer and hardware setup (HFC-1/S/SP)
342 * Returns: 0 on success
344 *---------------------------------------------------------------------------*/
346 ihfc_init (ihfc_sc_t *sc, u_char chan, int prot, int activate)
348 if (chan > 5) goto f0;
353 { if (chan < 2) /* D-Channel */
355 i4b_Dfreembuf(S_MBUF);
356 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Dcleanifq(&S_IFQUEUE);
358 RESET_SOFT_CHAN(sc, chan);
360 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
362 #if defined (__FreeBSD__) && __FreeBSD__ > 4
363 mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", MTX_DEF);
365 if (!activate) continue;
369 S_FILTER = (chan & 1) ? ihfc_isac_Dread :
374 S_FILTER = (chan & 1) ? ihfc_hdlc_Dread :
380 i4b_Bfreembuf(S_MBUF);
381 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Bcleanifq(&S_IFQUEUE);
383 RESET_SOFT_CHAN(sc, chan);
385 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
387 #if defined (__FreeBSD__) && __FreeBSD__ > 4
388 mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", MTX_DEF);
392 if (!activate) continue;
396 S_FILTER = (chan & 1) ?
401 S_FILTER = (chan & 1) ?
406 S_FILTER = (chan & 1) ?
412 } while (++chan & 1);
414 S_MASK |= 0xfb; /* disable all, but CISQ interrupt (ISAC) */
415 S_INT_M1 &= 0x40; /* disable all, but TE/NT state machine (HFC) */
416 S_SCTRL &= ~0x03; /* B1/B2 send disable (HFC) */
417 S_SPCR &= ~0x0f; /* B1/B2 send disable (ISAC) */
418 S_SCTRL_R &= ~0x03; /* B1/B2 receive disable (HFC) */
421 if (S_FILTER) /* D-Channel active */
423 S_MASK &= 0x2e; /* enable RME, RPF, XPR, EXI */
424 S_INT_M1 |= 0x24; /* enable D-receive, D-transmit */
428 if (S_FILTER) /* B1-Channel active */
430 S_SCTRL |= 1; /* send enable (HFC) */
431 S_SPCR |= 8; /* send enable (ISAC) */
432 S_SCTRL_R |= 1; /* receive enable (HFC) */
433 S_INT_M1 |= 0x80; /* timer enable (HFC) */
434 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
438 if (S_FILTER) /* B2-Channel active */
440 S_SCTRL |= 2; /* send enable (HFC) */
441 S_SPCR |= 2; /* send enable (ISAC) */
442 S_SCTRL_R |= 2; /* receive enable (HFC) */
443 S_INT_M1 |= 0x80; /* timer enable (HFC) */
444 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
449 /* XXX reset timer? */
451 return 0; /* success */
453 return 1; /* failure */
456 /*---------------------------------------------------------------------------*
457 * Load configuration data (HFC-1/S/SP)
458 *---------------------------------------------------------------------------*/
460 ihfc_loadconfig(ihfc_sc_t *sc)
466 /* HFC-1 chips w/ISAC: */
468 const u_char *src = (void *)&S_ISAC_CONFIG;
469 const u_char *dst = (void *)&isac_configtable;
471 SET_REG((S_CIRM | 0xc0) & 0xdf);
473 S_CTMT = (S_CTMT & ~0x14) | ((S_INT_M1 >> 5) & 0x4);
475 SET_REG((S_CTMT | 0xe0) & 0xff);
479 SET_REG(*dst++); /* set register */
481 /* write configuration */
482 DISBUSY(WRITE_DATA_1(*src++), break);
487 /* HFC-S/SP chips: */
489 const u_char *src = (void *)&S_HFC_CONFIG;
490 const u_char *dst = (void *)&ihfc_configtable;
494 SET_REG(*dst++); /* set register */
495 WRITE_DATA_1(*src++); /* write configuration */
500 /*---------------------------------------------------------------------------*
501 * Function State Machine handler (PH layer) (HFC-1/S/SP)
503 * Flag: 0 = Refresh softc S_PHSTATE + take hints
507 * NOTE: HFC-1 only supports TE mode.
508 *---------------------------------------------------------------------------*/
510 ihfc_fsm(ihfc_sc_t *sc, int flag)
512 const struct ihfc_FSMtable *fsmtab;
518 /* get current state (rx/downstream) */
522 SET_REG(0x31); DISBUSY(tmp = (READ_DATA_1 >> 2) & 0xf, return);
524 fsmtab = (S_NTMODE) ? &ihfc_TEtable2[tmp]:
529 SET_REG(0x30); tmp = READ_DATA_1 & 0xf;
531 fsmtab = (S_NTMODE) ? &ihfc_NTtable[tmp]:
537 NDBGL1(L1_I_CICO, "%s (ind=0x%x, flag=%d, unit=%d).",
538 fsmtab->string, tmp, flag, S_UNIT);
542 NDBGL1(L1_I_ERR, "Illegal indicatation (ind=0x%x, "
543 "flag=%d, unit=%d).", tmp, flag, S_UNIT);
546 /* indication machine / state change *
548 * Whenever the state of the S0-line changes, we check to see in which *
549 * direction the change went. Generally upwards means activate, and *
550 * downwards means deactivate. *
551 * The test signal is used to ensure proper syncronization. */
553 if (fsmtab->state == 0) /* deactivated indication */
557 isac_cmd = 0x3c; /* deactivate DUI */
559 i4b_l1_ph_deactivate_ind(S_I4BUNIT);
562 if (fsmtab->state == 2) /* syncronized indication */
566 if (S_NTMODE) ihfc_cmd = 0x80;
569 if (fsmtab->state == 3) /* activated indication */
573 isac_cmd = (S_DLP) ? 0x24 /* activate AR10 */
574 : 0x20; /* activate AR8 */
576 i4b_l1_ph_activate_ind(S_I4BUNIT);
579 if (fsmtab->state == 4) /* error indication */
583 isac_cmd = 0x3c; /* deactivate DUI */
587 S_PHSTATE = fsmtab->state;
589 if ((flag == 1) && (fsmtab->state != 3))
591 isac_cmd = (S_DLP) ? 0x24 : 0x20;
594 if ((flag == 2) && (fsmtab->state != 0))
600 /* set new state (tx / upstream) *
602 * NOTE: HFC-S/SP and ISAC transmitters are always active when *
603 * activated state is reached. The bytes sent to the S0-bus are all *
604 * high impedance, so they do not disturb. *
605 * The HFC-1 has a separate SIEMENS S0-device. */
611 if (S_IOM2) isac_cmd |= 3;
613 SET_REG(0x31); DISBUSY(WRITE_DATA_1(isac_cmd), );
615 NDBGL1(L1_I_CICO, "(isac_cmd=0x%x, unit=%d).",
621 if (ihfc_cmd || (fsmtab->state == 5))
623 SET_REG(0x30); WRITE_DATA_1(ihfc_cmd);
625 NDBGL1(L1_I_CICO, "(ihfc_cmd=0x%x, unit=%d).",
631 /*---------------------------------------------------------------------------*
632 * S/Q - channel handler (read) (HFC-S/SP)
633 *---------------------------------------------------------------------------*/
635 ihfc_sq (ihfc_sc_t *sc)
637 const struct ihfc_SQtable *SQtab;
638 register u_char a = 0;
644 DISBUSY(a = READ_DATA_1, a = 0);
649 DISBUSY(a = READ_DATA_1, a = 0);
658 SQtab = (S_NTMODE) ? &ihfc_Qtable[a & 7]:
665 NDBGL1(L1_I_CICO, "%s (unit=%d, int=%x)",
666 SQtab->string, S_UNIT, S_INT_S1);
670 NDBGL1(L1_ERROR, "Unknown indication = %x (unit=%d)",
676 /*---------------------------------------------------------------------------*
677 * Interrupt handler (HFC-1)
678 *---------------------------------------------------------------------------*/
680 ihfc_intr1 (ihfc_sc_t *sc)
689 SET_REG(0x20); tmp = GET_STAT; DISBUSY(S_ISTA |= READ_DATA_1, );
691 if (S_ISTA & 0x04) /* CIRQ */
700 if (S_ISTA & 0xc0) /* RPF or RME */
703 if (S_FILTER) S_FILTER(sc, chan);
705 if (S_ISTA & 0x10) /* XPR */
708 if (S_FILTER) S_FILTER(sc, chan);
710 if (tmp & 0x04) /* Timer elapsed (50ms) */
712 SET_REG((S_CTMT | 0xf0) & 0xff);
717 if (chan == 1) break;
718 if (S_FILTER) S_FILTER(sc, chan);
728 if (S_ISTA & 0x01) /* EXIR */
730 SET_REG(0x24); DISBUSY(ihfc_exir_hdlr(sc, READ_DATA_1), );
733 S_ISTA &= ~(0x1 | 0x4);
738 /*---------------------------------------------------------------------------*
739 * Interrupt handler (HFC-S/SP)
740 *---------------------------------------------------------------------------*/
742 ihfc_intr2 (ihfc_sc_t *sc)
750 SET_REG(0x1e); S_INT_S1 = READ_DATA_1; /* this will enable new interrupts! */
754 HFC_FSM(sc, 0); /* statemachine changed */
761 if (S_INT_S1 & 0x20) /* D-Channel frame (rx) */
764 if (S_FILTER) S_FILTER(sc, chan);
766 if (S_INT_S1 & 0x04) /* D-Channel frame (tx) */
769 if (S_FILTER && (~S_INT_S1 & 0x80)) S_FILTER(sc, chan);
771 if (S_INT_S1 & 0x80) /* Timer elapsed (50ms) */
776 if (chan == 1) continue;
777 if (S_FILTER) S_FILTER(sc, chan);
790 /*---------------------------------------------------------------------------*
791 * Select a Bfifo (HFC-1/S/SP)
792 * and return bytes in FIFO
794 * (this code is optimized)
795 *---------------------------------------------------------------------------*/
797 ihfc_Bsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
799 register u_char reg = 0x7e + chan;
800 register u_short tmp = 0x100;
806 if (S_HFC & (HFC_1 | HFC_S))
808 if (S_LAST_CHAN != chan)
811 DISBUSY(WAITBUSY_2( , return 0), return 0);
819 WRITE_DATA_1(chan - 2);
820 DISBUSY( , return 0);
823 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
824 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
826 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
827 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
828 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
829 SET_REG(reg += 4); FAST_STAT; z2 |= READ_DATA_1 << 8;
837 z1 = 0x5ff - (z2 = z1 - z2 + ((z2 <= z1) ? 0 : 0x600));
840 return(z2); /* receive channel */
842 return(z1); /* transmit channel */
845 /*---------------------------------------------------------------------------*
846 * Select a Dfifo (HFC-S/SP)
847 * and return bytes, and frames in FIFO
850 * 0x00: select new fifo + update counters
851 * 0x10: increment f1 + update counters
852 * 0x20: increment f2 + update counters
854 * NOTE: The upper 16bits holds the number of frames in the FIFO.
855 * NOTE: FIFO has to be selected before you can use flags 0x10/0x20.
856 *---------------------------------------------------------------------------*/
858 ihfc_Dsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
860 register u_char reg = 0x90 + chan;
861 register u_short tmp = 0x100;
869 if (S_HFC & (HFC_1 | HFC_S))
877 WAITBUSY_2( , return 0);
879 SET_REG(0xa2 - (flag & 0x10) + chan);
880 DISBUSY(READ_DATA_1, return 0);
884 WAITBUSY_2( , return 0);
888 if (S_LAST_CHAN != chan)
891 DISBUSY(WAITBUSY_2( , return 0), return 0);
904 SET_REG(0xb8 - (flag & 0x10) + chan);
907 DISBUSY( , return 0);
911 /* Before reading a FIFO a change *
912 * FIFO operation must be done. *
913 * (see HFC-SP manual p.38) */
916 WRITE_DATA_1(chan | 4);
918 DISBUSY( , return 0);
924 WRITE_DATA_1(chan | 4);
926 DISBUSY( , return 0);
931 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
932 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
934 if (S_HFC & HFC_SP) reg = 0x80 + chan;
936 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
937 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
938 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
939 SET_REG(reg += 4); FAST_STAT; z2 |= FAST_READ << 8;
941 if (S_HFC & HFC_SP) reg += 0x26;
943 SET_REG(reg -= 2); FAST_STAT; f1 = FAST_READ;
944 SET_REG(reg += 4); FAST_STAT; f2 = READ_DATA_1;
951 S_HDLC_DZ_TAB[f1 & 0xf] = z2; /* We keep track of the 'Z' *
952 * values for D-channel (tx),*
953 * so we may calculate the # *
954 * of FIFO bytes free when *
956 z2 = S_HDLC_DZ_TAB[f2 & 0xf];
959 z1 = 0x1ff - (z2 = (z1 - z2) & 0x1ff);
960 f1 = 0xf - (f2 = (f1 - f2) & 0xf);
963 return(z2 | (f2 << 16)); /* receive channel */
965 return(z1 | (f1 << 16)); /* transmit channel */
969 /*---------------------------------------------------------------------------*
970 * Data handler for D channel(write) - chan 0 (HFC-S/SP)
971 *---------------------------------------------------------------------------*/
973 ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan)
975 register u_int32_t sendlen;
976 register u_short len;
977 register u_char * src;
981 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
983 sendlen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
984 * NOTE: the 16 higher bits *
985 * contain the # of frame- *
986 * etries free in the FIFO */
987 while (sendlen & ~0xffff)
991 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j1;
997 if (len >= 0x1ff) goto j0; /* frame is too big: skip! */
999 sendlen &= 0xffff; /* only keep # of *
1002 SET_REG((S_HFC & HFC_SP) ? 0xac : 0x96);
1008 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1011 if (!++sendlen) /* out of fifo: suspend */
1018 sendlen = ihfc_Dsel_fifo(sc, chan, 0x10); /* inc F1 */
1020 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);
1195 /*---------------------------------------------------------------------------*
1196 * Data handler for D channel(read) - chan 1 (HFC-1)
1197 *---------------------------------------------------------------------------*/
1199 ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan)
1201 register u_char cmd = 0;
1202 register u_char reclen;
1203 register u_short tmp;
1204 register u_short len;
1205 register u_char * dst;
1209 if (!(S_ISTA & 0xc0)) goto j1; /* only receive data *
1214 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1215 panic("ihfc%d: (D) Out of mbufs!\n", S_UNIT);
1219 dst = S_MBUFDATA + (DCH_MAX_LEN - len);
1221 if (S_ISTA & 0x80) /* RME */
1223 SET_REG(0x27); DISBUSY(tmp = (READ_DATA_1 ^ 0x20), goto j0);
1225 if (tmp & 0x70) goto j0; /* error */
1227 SET_REG(0x25); DISBUSY(tmp = (READ_DATA_1 & 0x1f), goto j0);
1229 reclen = (tmp) ? tmp : 32;
1236 if ((len -= reclen) <= DCH_MAX_LEN) /* get data */
1242 DISBUSY(*dst++ = READ_DATA_1, goto j0);
1245 else /* soft rdo or error */
1247 j0: i4b_Dfreembuf(S_MBUF);
1252 NDBGL1(L1_I_ERR, "Frame error (unit=%d)", S_UNIT);
1255 if (S_ISTA & 0x80) /* frame complete */
1259 S_MBUFLEN = (DCH_MAX_LEN - len);
1260 ihfc_putmbuf(sc, chan, S_MBUF);
1265 if (S_MBUF) /* suspend */
1270 ihfc_cmdr_hdlr(sc, cmd | 0x80);
1276 /*---------------------------------------------------------------------------*
1277 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1279 * NOTE: No XDU checking!
1280 *---------------------------------------------------------------------------*/
1282 ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan)
1284 register u_short sendlen;
1285 register u_short len;
1286 register u_char * src;
1290 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
1292 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1294 SET_REG(0xaa + chan);
1300 S_MBUF = ihfc_getmbuf(sc, chan);
1311 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1314 if (!++sendlen) /* out of fifo: Suspend */
1321 i4b_Dfreembuf(S_MBUF);
1326 /*---------------------------------------------------------------------------*
1327 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1328 * (this code is optimized)
1329 *---------------------------------------------------------------------------*/
1331 ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan)
1333 register u_short reclen;
1334 register u_short tmp;
1335 register u_short len;
1336 register u_char * dst;
1340 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1344 SET_REG(0xba + chan);
1349 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1350 panic("ihfc%d: (B) Out of mbufs!\n", S_UNIT);
1353 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1359 if (tmp & 0x100) DISBUSY( , reclen = -1; len++; break);
1360 *dst++ = (u_char)(tmp = READ_BOTH_2);
1366 READ_DATA_1; /* a read to the data port *
1367 * will disable the internal *
1368 * disbusy signal for HFC-1/S *
1369 * chips. This is neccessary *
1370 * to avvoid data loss. */
1373 if (!++reclen) /* out of fifo: suspend */
1379 S_MBUFLEN = (BCH_MAX_DATALEN - ++len);
1381 ihfc_putmbuf(sc, chan, S_MBUF);
1387 /*---------------------------------------------------------------------------*
1388 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1390 * NOTE: Software HDLC encoding!
1391 *---------------------------------------------------------------------------*/
1393 ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan)
1395 register u_short blevel = S_HDLC_BLEVEL;
1396 register u_char flag = S_HDLC_FLAG;
1397 register u_int tmp = S_HDLC_TMP;
1398 register u_short crc = S_HDLC_CRC;
1399 register u_short ib = S_HDLC_IB;
1400 register u_char * src = NULL;
1401 register u_short len = 0;
1402 register u_short sendlen;
1403 register u_short tmp2;
1407 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE) && (flag == 2)) return;
1409 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1411 SET_REG(0xaa + chan);
1420 if (sendlen == 0x5ff)
1427 NDBGL1(L1_S_ERR, "XDU (unit=%d)", S_UNIT);
1433 HDLC_ENCODE(*src++, len, tmp, tmp2, blevel, ib, crc, flag,
1435 i4b_Bfreembuf(S_MBUF);
1436 S_MBUF = ihfc_getmbuf(sc, chan);
1445 sendlen = 0; /* Exit after final FS, *
1446 * else the buffer will *
1447 * only be filled with *
1453 DISBUSY(WRITE_DATA_1((u_char)tmp), sendlen = 0);
1458 if (S_MBUF) /* suspend */
1465 S_HDLC_BLEVEL = blevel;
1471 /*---------------------------------------------------------------------------*
1472 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1474 * NOTE: Software HDLC decoding!
1475 *---------------------------------------------------------------------------*/
1477 ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan)
1479 register u_char blevel = S_HDLC_BLEVEL;
1480 u_char flag = S_HDLC_FLAG;
1481 register u_short crc = S_HDLC_CRC;
1482 register u_int tmp = S_HDLC_TMP;
1483 register u_short ib = S_HDLC_IB;
1484 register u_char * dst = NULL;
1485 register u_short tmp2 = 0x100;
1486 register u_short len = 0;
1487 register u_short reclen;
1496 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1499 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1501 SET_REG(0xba + chan);
1505 HDLC_DECODE(*dst++, len, tmp, tmp2, blevel, ib, crc, flag,
1507 /* if (tmp2 & 0x100) while (GET_STAT & 1);
1508 * tmp2 = READ_BOTH_2;
1511 DISBUSY(tmp2 = READ_DATA_1, reclen = 0; tmp2 = 0);
1514 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1515 panic("ihfc:(B) Out of mbufs!\n");
1518 len = BCH_MAX_DATALEN;
1521 len = (BCH_MAX_DATALEN - len);
1523 if ((!len) || (len > BCH_MAX_DATALEN))
1525 /* NOTE: frames without any data, *
1526 * only crc field, should be silently discared. */
1528 i4b_Bfreembuf(S_MBUF);
1529 NDBGL1(L1_S_MSG, "Bad frame (len=%d, unit=%d)", len, S_UNIT);
1534 { i4b_Bfreembuf(S_MBUF);
1535 NDBGL1(L1_S_ERR, "CRC (crc=0x%04x, len=%d, unit=%d)", crc, len, S_UNIT);
1541 ihfc_putmbuf(sc, chan, S_MBUF);
1546 i4b_Bfreembuf(S_MBUF);
1549 NDBGL1(L1_S_MSG, "Read Abort (unit=%d)", S_UNIT);
1552 i4b_Bfreembuf(S_MBUF);
1555 NDBGL1(L1_S_ERR, "RDO (unit=%d)", S_UNIT);
1562 * if (~tmp2 & 0x100) READ_DATA_1; kill disbusy signal
1565 if (S_MBUF) S_MBUFLEN = len; /* suspend */
1571 S_HDLC_BLEVEL = blevel;
1574 /*---------------------------------------------------------------------------*
1575 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1577 * This filter generates a pattern which is recognized
1578 * and examinated and verified by ihfc_test_Bread.
1580 * NOTE: This filter is only for testing purpose.
1581 *---------------------------------------------------------------------------*/
1583 ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan)
1588 register u_short sendlen, tlen;
1589 register u_short xlen = S_HDLC_IB;
1594 while((m = ihfc_getmbuf(sc, chan))) /* internal loop */
1597 ihfc_putmbuf(sc, 5, m);
1599 ihfc_putmbuf(sc, 3, m);
1604 sendlen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1606 if (sendlen == 0x5ff) printf("(send empty)");
1608 SET_REG(0xaa + chan);
1614 if (sendlen > 0x400) printf("(slow: %d)", sendlen);
1620 if (!tlen--) fb |= 0x20;
1624 while(GET_STAT & 1);
1630 while(GET_STAT & 1);
1631 WRITE_DATA_1((xlen + 1) & 0xef);
1640 /*---------------------------------------------------------------------------*
1641 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1643 * This filter examins and verifies the pattern
1644 * generated by ihfc_test_Bwrite.
1646 * NOTE: This filter is only for testing purpose.
1647 *---------------------------------------------------------------------------*/
1649 ihfc_test_Bread (ihfc_sc_t *sc, u_char chan)
1651 static u_short toterrors = 0;
1653 register u_short reclen, len, tlen;
1654 register u_char fb, tmp;
1656 register u_short xlen = S_HDLC_IB;
1657 register u_char *dst = NULL;
1658 register u_char error = S_HDLC_TMP;
1659 register u_char ecount = S_HDLC_FLAG;
1663 if (S_UNIT != 0) return;
1665 reclen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1676 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1683 SET_REG(0xba + chan);
1687 /* if (tmp2 & 0x100) while(GET_STAT & 1);
1688 * tmp = (u_char)(tmp2 = READ_BOTH_2);
1692 /* if (!(++busy % 4)) reclen++; */
1693 while(GET_STAT & 1);
1698 if ((tmp & 0x3f) == 0x3e)
1700 if ((BCH_MAX_DATALEN - len) != 201) error |= 4;
1702 if ((S_MBUF) && (error))
1704 if (len) { len--; *dst++ = error; }
1705 if (len) { len--; *dst++ = xlen+1; }
1706 if (len) { len--; *dst++ = ecount; }
1708 S_MBUFLEN = BCH_MAX_DATALEN - len;
1710 if (S_TRACE & TRACE_B_RX)
1711 ihfc_putmbuf(sc, chan, S_MBUF);
1713 i4b_Bfreembuf(S_MBUF);
1716 printf("(error%d, %d, %d)", S_UNIT, ecount, toterrors++);
1719 i4b_Bfreembuf(S_MBUF);
1720 S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN);
1723 len = BCH_MAX_DATALEN;
1729 /* SET_REG(0xba + chan); */
1733 if (!xlen) error |= 2;
1734 if ((tmp ^ xlen--) & 0xef) { error |= 1; ecount++; }
1736 if (!tlen--) fb |= 0x20;
1740 *dst++ = (tmp | fb);
1757 S_HDLC_FLAG = ecount;
1760 #endif /* NIHFC > 0 */