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.9 2006/12/22 23:44:56 swildner Exp $
38 *---------------------------------------------------------------------------*/
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/socket.h>
50 #include <sys/thread2.h>
52 #include "../../include/i4b_mbuf.h"
55 #include <net/i4b/include/machine/i4b_debug.h>
56 #include <net/i4b/include/machine/i4b_ioctl.h>
57 #include <net/i4b/include/machine/i4b_trace.h>
59 #include "../i4b_l1.h"
60 #include "../i4b_hdlc.h"
62 #include "i4b_ihfc_ext.h"
63 #include "i4b_ihfc_drv.h"
65 /*---------------------------------------------------------------------------*
67 *---------------------------------------------------------------------------*/
68 void ihfc_loadconfig (ihfc_sc_t *sc);
70 static void ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan);
71 static void ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan);
72 static void ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan);
73 static void ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan);
74 static void ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan);
75 static void ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan);
77 static void ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan);
78 static void ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan);
80 void ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr);
81 void ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir);
83 void ihfc_sq (ihfc_sc_t *sc);
85 static void ihfc_test_Bread (ihfc_sc_t *sc, u_char chan);
86 static void ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan);
88 u_short ihfc_Bsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
89 u_int32_t ihfc_Dsel_fifo (ihfc_sc_t *sc, u_char chan, u_char flag);
92 /*---------------------------------------------------------------------------*
93 * Commonly used ISA bus commands
94 *---------------------------------------------------------------------------*/
95 #define IHFC_DATA_OFFSET 0
96 #define IHFC_REG_OFFSET 1
98 #define BUS_VAR bus_space_handle_t h = rman_get_bushandle(S_IOBASE[0]); \
99 bus_space_tag_t t = rman_get_bustag (S_IOBASE[0])
101 #define SET_REG(reg) bus_space_write_1(t,h, IHFC_REG_OFFSET, reg)
102 #define GET_STAT bus_space_read_1 (t,h, IHFC_REG_OFFSET)
104 #define READ_DATA_1 bus_space_read_1 (t,h, IHFC_DATA_OFFSET)
105 #define READ_BOTH_2 bus_space_read_2 (t,h, IHFC_DATA_OFFSET)
107 #define WRITE_DATA_1(data) bus_space_write_1(t,h, IHFC_DATA_OFFSET, data)
108 #define WRITE_BOTH_2(data) bus_space_write_2(t,h, IHFC_DATA_OFFSET, data)
110 #define DISBUSY(okcmd, tocmd) \
115 u_int to = IHFC_DISBUSYTO; \
117 while(((a = GET_STAT) & 1) && --to); \
121 NDBGL1(L1_ERROR, "DISBUSY-TIMEOUT! (a=%04x, " \
122 "unit=%d)", a, S_UNIT); \
136 #define WAITBUSY_2(okcmd, tocmd) \
139 u_int to = IHFC_NONBUSYTO; \
141 while((~(a = READ_BOTH_2) & 0x100) && --to); \
145 NDBGL1(L1_ERROR, "NONBUSY-TIMEOUT! (a=%04x, " \
146 "unit=%d)", a, S_UNIT); \
155 /*---------------------------------------------------------------------------*
156 * Control function (HFC-1/S/SP)
159 * 1: reset and unlock chip (at boot only)
160 * 2: prepare for shutdown (at shutdown only)
161 * 3: reset and resume
162 * 4: select TE-mode (boot default)
163 * 5: select NT-mode (only HFC-S/SP/PCI)
165 * Returns != 0 on errornous chip
166 *---------------------------------------------------------------------------*/
168 ihfc_control(ihfc_sc_t *sc, int flag)
172 if (flag == 3) goto reset0;
185 WRITE_BOTH_2(0x5400 | S_IIO); /* enable IO (HFC-1/S) */
189 /* HFC-S/SP configuration */
191 S_CIRM = S_IIRQ|0x10; /* IRQ, 8K fifo mode */
192 S_CLKDEL = 0x00; /* 12.288mhz */
193 S_CTMT = 0x03; /* transperant mode */
194 S_CONNECT = 0x00; /* B channel data flow */
195 S_INT_M1 = 0x40; /* interrupt mask */
196 S_INT_M2 = 0x08; /* enable interrupt output */
197 S_MST_MODE = 0x01; /* master mode */
198 S_SCTRL = 0x50; /* S/Q on, non cap. line mode */
199 S_SCTRL_R = 0x00; /* B channel receive disable */
200 S_TEST = 0x00; /* no need for awake enable */
202 if (S_HFC & (HFC_1 | HFC_S)) /* configure timer (50ms) */
211 /* HFC-1 ISAC configuration (IOM-2 mode) */
214 S_ADF2 = 0x80; /* select mode IOM-2 */
215 S_SPCR = 0x00; /* B channel send disable (0x10 for test loop) */
216 S_MASK = 0xfb; /* enable CISQ */
217 S_MODE = 0xc9; /* receiver enabled */
218 S_SQXR = 0x0f; /* master, clock always active */
219 S_STCR = 0x70; /* TIC bus address = 7 */
220 S_STAR2 = 0x04; /* enable S/Q */
223 if (S_NTMODE) /* configure NT- or TE-mode */
225 S_SCTRL |= 0x04; /* NT mode */
226 S_CLKDEL &= ~0x7f; /* clear delay */
227 S_CLKDEL |= 0x6c; /* set delay */
231 S_SCTRL &= ~0x04; /* TE mode */
232 S_STDEL &= 0x7f; /* use mask! */
233 S_CLKDEL &= ~0x7f; /* clear delay */
234 S_CLKDEL |= S_STDEL; /* set delay */
236 if (S_DLP) /* configure D-priority */
238 S_SCTRL |= 0x08; /* (10/11) */
242 S_SCTRL &= ~0x08; /* (8/9) */
246 /* chip reset (HFC-1/S/SP) */
250 SET_REG((S_CIRM | 0xc8) & 0xdf);
252 DELAY(10); /* HFC-2B manual recommends a 4 *
253 * clock cycle delay after CIRM *
254 * write with reset=1. A 1us *
255 * delay, should do for 7.68mhz,*
256 * but just in case I make that *
259 SET_REG((S_CIRM | 0xc0) & 0xdf);
261 DELAY(250); /* ISAC manual says reset pulse *
262 * length is 125us. Accessing *
263 * ISAC before those 125us, we *
264 * may risk chip corruption and *
265 * irq failure. The HFC-2B also *
266 * needs some delay to recover, *
267 * so we add some us. */
273 WRITE_DATA_1(S_CIRM | 8);
275 DELAY(10); /* HFC-2BDS0 manual recommends *
276 * a 4 clock cycle delay after *
277 * CIRM write with reset=1. *
278 * A 1us delay, should do for *
279 * 12.288mhz, but just in case *
280 * I make that 10us. */
282 WRITE_DATA_1(S_CIRM);
284 DELAY(25); /* HFC-2BDS0 needs some time to *
285 * recover after CIRM write *
286 * with reset=0. Experiments *
287 * show this delay should be *
288 * 8-9us. Just in case we make *
293 /* HFC-1/S/SP chip test *
295 * NOTE: after reset the HFC-1/S/SP should be *
296 * in a mode where it is always non-busy/non- *
297 * processing, and bit[0] of STATUS/DISBUSY *
298 * register, should always return binary '0' *
299 * until we configure the chips for normal *
302 kprintf("ihfc: GET_STAT value is: 0x%x\n", GET_STAT);
306 if ((GET_STAT & 1) || (READ_DATA_1 & 0xf)) goto f0;
311 if (S_HFC & HFC_1) ihfc_cmdr_hdlr(sc, 0x41); /* rres, xres */
319 if (S_HFC & HFC_1) S_CIRM &= ~0x03; /* disable interrupt */
321 S_SQXR |= 0x40; /* power down */
326 S_SPCR &= ~0x0f; /* send 1's only */
327 S_SCTRL &= ~0x83; /* send 1's only + enable oscillator */
332 return(0); /* success */
335 return(1); /* failure */
338 /*---------------------------------------------------------------------------*
339 * Softc initializer and hardware setup (HFC-1/S/SP)
341 * Returns: 0 on success
343 *---------------------------------------------------------------------------*/
345 ihfc_init (ihfc_sc_t *sc, u_char chan, int prot, int activate)
347 if (chan > 5) goto f0;
352 { if (chan < 2) /* D-Channel */
354 i4b_Dfreembuf(S_MBUF);
355 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Dcleanifq(&S_IFQUEUE);
357 RESET_SOFT_CHAN(sc, chan);
359 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
361 if (!activate) continue;
365 S_FILTER = (chan & 1) ? ihfc_isac_Dread :
370 S_FILTER = (chan & 1) ? ihfc_hdlc_Dread :
376 i4b_Bfreembuf(S_MBUF);
377 if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Bcleanifq(&S_IFQUEUE);
379 RESET_SOFT_CHAN(sc, chan);
381 S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
385 if (!activate) continue;
389 S_FILTER = (chan & 1) ?
394 S_FILTER = (chan & 1) ?
399 S_FILTER = (chan & 1) ?
405 } while (++chan & 1);
407 S_MASK |= 0xfb; /* disable all, but CISQ interrupt (ISAC) */
408 S_INT_M1 &= 0x40; /* disable all, but TE/NT state machine (HFC) */
409 S_SCTRL &= ~0x03; /* B1/B2 send disable (HFC) */
410 S_SPCR &= ~0x0f; /* B1/B2 send disable (ISAC) */
411 S_SCTRL_R &= ~0x03; /* B1/B2 receive disable (HFC) */
414 if (S_FILTER) /* D-Channel active */
416 S_MASK &= 0x2e; /* enable RME, RPF, XPR, EXI */
417 S_INT_M1 |= 0x24; /* enable D-receive, D-transmit */
421 if (S_FILTER) /* B1-Channel active */
423 S_SCTRL |= 1; /* send enable (HFC) */
424 S_SPCR |= 8; /* send enable (ISAC) */
425 S_SCTRL_R |= 1; /* receive enable (HFC) */
426 S_INT_M1 |= 0x80; /* timer enable (HFC) */
427 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
431 if (S_FILTER) /* B2-Channel active */
433 S_SCTRL |= 2; /* send enable (HFC) */
434 S_SPCR |= 2; /* send enable (ISAC) */
435 S_SCTRL_R |= 2; /* receive enable (HFC) */
436 S_INT_M1 |= 0x80; /* timer enable (HFC) */
437 S_INT_M1 &= ~0x04; /* let D-channel use timer too */
442 /* XXX reset timer? */
444 return 0; /* success */
446 return 1; /* failure */
449 /*---------------------------------------------------------------------------*
450 * Load configuration data (HFC-1/S/SP)
451 *---------------------------------------------------------------------------*/
453 ihfc_loadconfig(ihfc_sc_t *sc)
459 /* HFC-1 chips w/ISAC: */
461 const u_char *src = (void *)&S_ISAC_CONFIG;
462 const u_char *dst = (void *)&isac_configtable;
464 SET_REG((S_CIRM | 0xc0) & 0xdf);
466 S_CTMT = (S_CTMT & ~0x14) | ((S_INT_M1 >> 5) & 0x4);
468 SET_REG((S_CTMT | 0xe0) & 0xff);
472 SET_REG(*dst++); /* set register */
474 /* write configuration */
475 DISBUSY(WRITE_DATA_1(*src++), break);
480 /* HFC-S/SP chips: */
482 const u_char *src = (void *)&S_HFC_CONFIG;
483 const u_char *dst = (void *)&ihfc_configtable;
487 SET_REG(*dst++); /* set register */
488 WRITE_DATA_1(*src++); /* write configuration */
493 /*---------------------------------------------------------------------------*
494 * Function State Machine handler (PH layer) (HFC-1/S/SP)
496 * Flag: 0 = Refresh softc S_PHSTATE + take hints
500 * NOTE: HFC-1 only supports TE mode.
501 *---------------------------------------------------------------------------*/
503 ihfc_fsm(ihfc_sc_t *sc, int flag)
505 const struct ihfc_FSMtable *fsmtab;
511 /* get current state (rx/downstream) */
515 SET_REG(0x31); DISBUSY(tmp = (READ_DATA_1 >> 2) & 0xf, return);
517 fsmtab = (S_NTMODE) ? &ihfc_TEtable2[tmp]:
522 SET_REG(0x30); tmp = READ_DATA_1 & 0xf;
524 fsmtab = (S_NTMODE) ? &ihfc_NTtable[tmp]:
530 NDBGL1(L1_I_CICO, "%s (ind=0x%x, flag=%d, unit=%d).",
531 fsmtab->string, tmp, flag, S_UNIT);
535 NDBGL1(L1_I_ERR, "Illegal indicatation (ind=0x%x, "
536 "flag=%d, unit=%d).", tmp, flag, S_UNIT);
539 /* indication machine / state change *
541 * Whenever the state of the S0-line changes, we check to see in which *
542 * direction the change went. Generally upwards means activate, and *
543 * downwards means deactivate. *
544 * The test signal is used to ensure proper syncronization. */
546 if (fsmtab->state == 0) /* deactivated indication */
550 isac_cmd = 0x3c; /* deactivate DUI */
552 i4b_l1_ph_deactivate_ind(S_I4BUNIT);
555 if (fsmtab->state == 2) /* syncronized indication */
559 if (S_NTMODE) ihfc_cmd = 0x80;
562 if (fsmtab->state == 3) /* activated indication */
566 isac_cmd = (S_DLP) ? 0x24 /* activate AR10 */
567 : 0x20; /* activate AR8 */
569 i4b_l1_ph_activate_ind(S_I4BUNIT);
572 if (fsmtab->state == 4) /* error indication */
576 isac_cmd = 0x3c; /* deactivate DUI */
580 S_PHSTATE = fsmtab->state;
582 if ((flag == 1) && (fsmtab->state != 3))
584 isac_cmd = (S_DLP) ? 0x24 : 0x20;
587 if ((flag == 2) && (fsmtab->state != 0))
593 /* set new state (tx / upstream) *
595 * NOTE: HFC-S/SP and ISAC transmitters are always active when *
596 * activated state is reached. The bytes sent to the S0-bus are all *
597 * high impedance, so they do not disturb. *
598 * The HFC-1 has a separate SIEMENS S0-device. */
604 if (S_IOM2) isac_cmd |= 3;
606 SET_REG(0x31); DISBUSY(WRITE_DATA_1(isac_cmd), );
608 NDBGL1(L1_I_CICO, "(isac_cmd=0x%x, unit=%d).",
614 if (ihfc_cmd || (fsmtab->state == 5))
616 SET_REG(0x30); WRITE_DATA_1(ihfc_cmd);
618 NDBGL1(L1_I_CICO, "(ihfc_cmd=0x%x, unit=%d).",
624 /*---------------------------------------------------------------------------*
625 * S/Q - channel handler (read) (HFC-S/SP)
626 *---------------------------------------------------------------------------*/
628 ihfc_sq (ihfc_sc_t *sc)
630 const struct ihfc_SQtable *SQtab;
637 DISBUSY(a = READ_DATA_1, a = 0);
642 DISBUSY(a = READ_DATA_1, a = 0);
651 SQtab = (S_NTMODE) ? &ihfc_Qtable[a & 7]:
658 NDBGL1(L1_I_CICO, "%s (unit=%d, int=%x)",
659 SQtab->string, S_UNIT, S_INT_S1);
663 NDBGL1(L1_ERROR, "Unknown indication = %x (unit=%d)",
669 /*---------------------------------------------------------------------------*
670 * Interrupt handler (HFC-1)
671 *---------------------------------------------------------------------------*/
673 ihfc_intr1 (ihfc_sc_t *sc)
682 SET_REG(0x20); tmp = GET_STAT; DISBUSY(S_ISTA |= READ_DATA_1, );
684 if (S_ISTA & 0x04) /* CIRQ */
693 if (S_ISTA & 0xc0) /* RPF or RME */
696 if (S_FILTER) S_FILTER(sc, chan);
698 if (S_ISTA & 0x10) /* XPR */
701 if (S_FILTER) S_FILTER(sc, chan);
703 if (tmp & 0x04) /* Timer elapsed (50ms) */
705 SET_REG((S_CTMT | 0xf0) & 0xff);
710 if (chan == 1) break;
711 if (S_FILTER) S_FILTER(sc, chan);
721 if (S_ISTA & 0x01) /* EXIR */
723 SET_REG(0x24); DISBUSY(ihfc_exir_hdlr(sc, READ_DATA_1), );
726 S_ISTA &= ~(0x1 | 0x4);
731 /*---------------------------------------------------------------------------*
732 * Interrupt handler (HFC-S/SP)
733 *---------------------------------------------------------------------------*/
735 ihfc_intr2 (ihfc_sc_t *sc)
743 SET_REG(0x1e); S_INT_S1 = READ_DATA_1; /* this will enable new interrupts! */
747 HFC_FSM(sc, 0); /* statemachine changed */
754 if (S_INT_S1 & 0x20) /* D-Channel frame (rx) */
757 if (S_FILTER) S_FILTER(sc, chan);
759 if (S_INT_S1 & 0x04) /* D-Channel frame (tx) */
762 if (S_FILTER && (~S_INT_S1 & 0x80)) S_FILTER(sc, chan);
764 if (S_INT_S1 & 0x80) /* Timer elapsed (50ms) */
769 if (chan == 1) continue;
770 if (S_FILTER) S_FILTER(sc, chan);
783 /*---------------------------------------------------------------------------*
784 * Select a Bfifo (HFC-1/S/SP)
785 * and return bytes in FIFO
787 * (this code is optimized)
788 *---------------------------------------------------------------------------*/
790 ihfc_Bsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
792 u_char reg = 0x7e + chan;
799 if (S_HFC & (HFC_1 | HFC_S))
801 if (S_LAST_CHAN != chan)
804 DISBUSY(WAITBUSY_2( , return 0), return 0);
812 WRITE_DATA_1(chan - 2);
813 DISBUSY( , return 0);
816 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
817 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
819 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
820 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
821 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
822 SET_REG(reg += 4); FAST_STAT; z2 |= READ_DATA_1 << 8;
830 z1 = 0x5ff - (z2 = z1 - z2 + ((z2 <= z1) ? 0 : 0x600));
833 return(z2); /* receive channel */
835 return(z1); /* transmit channel */
838 /*---------------------------------------------------------------------------*
839 * Select a Dfifo (HFC-S/SP)
840 * and return bytes, and frames in FIFO
843 * 0x00: select new fifo + update counters
844 * 0x10: increment f1 + update counters
845 * 0x20: increment f2 + update counters
847 * NOTE: The upper 16bits holds the number of frames in the FIFO.
848 * NOTE: FIFO has to be selected before you can use flags 0x10/0x20.
849 *---------------------------------------------------------------------------*/
851 ihfc_Dsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
853 u_char reg = 0x90 + chan;
862 if (S_HFC & (HFC_1 | HFC_S))
870 WAITBUSY_2( , return 0);
872 SET_REG(0xa2 - (flag & 0x10) + chan);
873 DISBUSY(READ_DATA_1, return 0);
877 WAITBUSY_2( , return 0);
881 if (S_LAST_CHAN != chan)
884 DISBUSY(WAITBUSY_2( , return 0), return 0);
897 SET_REG(0xb8 - (flag & 0x10) + chan);
900 DISBUSY( , return 0);
904 /* Before reading a FIFO a change *
905 * FIFO operation must be done. *
906 * (see HFC-SP manual p.38) */
909 WRITE_DATA_1(chan | 4);
911 DISBUSY( , return 0);
917 WRITE_DATA_1(chan | 4);
919 DISBUSY( , return 0);
924 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
925 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
927 if (S_HFC & HFC_SP) reg = 0x80 + chan;
929 SET_REG(reg ); FAST_STAT; z1 = FAST_READ;
930 SET_REG(reg += 4); FAST_STAT; z1 |= FAST_READ << 8;
931 SET_REG(reg += 4); FAST_STAT; z2 = FAST_READ;
932 SET_REG(reg += 4); FAST_STAT; z2 |= FAST_READ << 8;
934 if (S_HFC & HFC_SP) reg += 0x26;
936 SET_REG(reg -= 2); FAST_STAT; f1 = FAST_READ;
937 SET_REG(reg += 4); FAST_STAT; f2 = READ_DATA_1;
944 S_HDLC_DZ_TAB[f1 & 0xf] = z2; /* We keep track of the 'Z' *
945 * values for D-channel (tx),*
946 * so we may calculate the # *
947 * of FIFO bytes free when *
949 z2 = S_HDLC_DZ_TAB[f2 & 0xf];
952 z1 = 0x1ff - (z2 = (z1 - z2) & 0x1ff);
953 f1 = 0xf - (f2 = (f1 - f2) & 0xf);
956 return(z2 | (f2 << 16)); /* receive channel */
958 return(z1 | (f1 << 16)); /* transmit channel */
962 /*---------------------------------------------------------------------------*
963 * Data handler for D channel(write) - chan 0 (HFC-S/SP)
964 *---------------------------------------------------------------------------*/
966 ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan)
974 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
976 sendlen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
977 * NOTE: the 16 higher bits *
978 * contain the # of frame- *
979 * etries free in the FIFO */
980 while (sendlen & ~0xffff)
984 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j1;
990 if (len >= 0x1ff) goto j0; /* frame is too big: skip! */
992 sendlen &= 0xffff; /* only keep # of *
995 SET_REG((S_HFC & HFC_SP) ? 0xac : 0x96);
1001 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1004 if (!++sendlen) /* out of fifo: suspend */
1011 sendlen = ihfc_Dsel_fifo(sc, chan, 0x10); /* inc F1 */
1013 i4b_Dfreembuf(S_MBUF);
1020 /*---------------------------------------------------------------------------*
1021 * Data handler for D channel(read) - chan 1 (HFC-S/SP)
1023 * NOTE: Max framelength is (511 - 3) = 508 bytes, when only one frame
1024 * is received at a time.
1025 *---------------------------------------------------------------------------*/
1027 ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan)
1038 reclen = ihfc_Dsel_fifo(sc, chan, 0); /* select new fifo *
1039 * NOTE: the higher 16 bits *
1040 * contain the # of frames *
1042 while ((reclen & ~0xffff) && to--)
1044 reclen &= 0xffff; /* only keep # of *
1045 * bytes to receive */
1047 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1048 panic("ihfc_hdlc_Dread: No mbufs(unit=%d)!\n", S_UNIT);
1050 SET_REG((S_HFC & HFC_SP) ? 0xbd : 0xa7);
1052 if ((reclen > 2) && (reclen <= (DCH_MAX_LEN+2)))
1055 len = S_MBUFLEN = (reclen += 1) - 3;
1063 crc = -1; /* NOTE: after a "F1" or "Z1" hardware overflow *
1064 * it appears not to be necessary to reset the *
1065 * HFC-1/S or SP chips to continue proper *
1066 * operation, only and only, if we always read *
1067 * "Z1-Z2+1" bytes when F1!=F2 followed by a *
1068 * F2-counter increment. The bi-effect of doing *
1069 * this is the "STAT" field may say frame is ok *
1070 * when the frame is actually bad. *
1071 * The simple solution is to re-CRC the frame *
1072 * including "STAT" field to see if we get *
1073 * CRC == 0x3933. Then we're 99% sure all *
1074 * frames received are good. */
1078 DISBUSY(tmp = READ_DATA_1, break);
1079 if (len) { len--; *dst++ = tmp; }
1081 crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8));
1088 ihfc_putmbuf(sc, chan, S_MBUF);
1093 NDBGL1(L1_ERROR, "Frame error (len=%d, stat=0x%x, "
1094 "crc=0x%x, unit=%d)", S_MBUFLEN, (u_char)tmp, crc,
1097 i4b_Dfreembuf(S_MBUF);
1101 reclen = ihfc_Dsel_fifo(sc, chan, 0x20);
1105 /*---------------------------------------------------------------------------*
1106 * EXIR error handler - ISAC (D - channel) (HFC-1)
1107 *---------------------------------------------------------------------------*/
1109 ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir)
1114 for (a = 0, cmd = 0; exir; a++, exir >>= 1)
1118 NDBGL1(L1_I_ERR, "%s. (unit=%d)",
1119 ihfc_EXIRtable[a].string, S_UNIT);
1120 cmd |= ihfc_EXIRtable[a].cmd;
1124 if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1127 /*---------------------------------------------------------------------------*
1128 * CMDR handler - ISAC (D - channel) (HFC-1)
1129 *---------------------------------------------------------------------------*/
1131 ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr)
1135 SET_REG(0x21); DISBUSY(WRITE_DATA_1(cmdr); DELAY(30), );
1138 /*---------------------------------------------------------------------------*
1139 * Data handler for D channel(write) - chan 0 (HFC-1)
1140 *---------------------------------------------------------------------------*/
1142 ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan)
1144 u_char sendlen = 32;
1151 if (~S_ISTA & 0x10) goto j0;
1154 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j0;
1161 while(sendlen--) /* write data */
1164 DISBUSY(WRITE_DATA_1(*src++), goto a0);
1169 if (!++sendlen) /* suspend */
1177 i4b_Dfreembuf(S_MBUF);
1183 if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1190 /*---------------------------------------------------------------------------*
1191 * Data handler for D channel(read) - chan 1 (HFC-1)
1192 *---------------------------------------------------------------------------*/
1194 ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan)
1204 if (!(S_ISTA & 0xc0)) goto j1; /* only receive data *
1209 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1210 panic("ihfc%d: (D) Out of mbufs!\n", S_UNIT);
1214 dst = S_MBUFDATA + (DCH_MAX_LEN - len);
1216 if (S_ISTA & 0x80) /* RME */
1218 SET_REG(0x27); DISBUSY(tmp = (READ_DATA_1 ^ 0x20), goto j0);
1220 if (tmp & 0x70) goto j0; /* error */
1222 SET_REG(0x25); DISBUSY(tmp = (READ_DATA_1 & 0x1f), goto j0);
1224 reclen = (tmp) ? tmp : 32;
1231 if ((len -= reclen) <= DCH_MAX_LEN) /* get data */
1237 DISBUSY(*dst++ = READ_DATA_1, goto j0);
1240 else /* soft rdo or error */
1242 j0: i4b_Dfreembuf(S_MBUF);
1247 NDBGL1(L1_I_ERR, "Frame error (unit=%d)", S_UNIT);
1250 if (S_ISTA & 0x80) /* frame complete */
1254 S_MBUFLEN = (DCH_MAX_LEN - len);
1255 ihfc_putmbuf(sc, chan, S_MBUF);
1260 if (S_MBUF) /* suspend */
1265 ihfc_cmdr_hdlr(sc, cmd | 0x80);
1272 /*---------------------------------------------------------------------------*
1273 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1275 * NOTE: No XDU checking!
1276 *---------------------------------------------------------------------------*/
1278 ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan)
1286 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
1288 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1290 SET_REG(0xaa + chan);
1296 S_MBUF = ihfc_getmbuf(sc, chan);
1307 DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1310 if (!++sendlen) /* out of fifo: Suspend */
1317 i4b_Dfreembuf(S_MBUF);
1322 /*---------------------------------------------------------------------------*
1323 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1324 * (this code is optimized)
1325 *---------------------------------------------------------------------------*/
1327 ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan)
1336 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1340 SET_REG(0xba + chan);
1345 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1346 panic("ihfc%d: (B) Out of mbufs!\n", S_UNIT);
1349 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1355 if (tmp & 0x100) DISBUSY( , reclen = -1; len++; break);
1356 *dst++ = (u_char)(tmp = READ_BOTH_2);
1362 READ_DATA_1; /* a read to the data port *
1363 * will disable the internal *
1364 * disbusy signal for HFC-1/S *
1365 * chips. This is neccessary *
1366 * to avvoid data loss. */
1369 if (!++reclen) /* out of fifo: suspend */
1375 S_MBUFLEN = (BCH_MAX_DATALEN - ++len);
1377 ihfc_putmbuf(sc, chan, S_MBUF);
1383 /*---------------------------------------------------------------------------*
1384 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1386 * NOTE: Software HDLC encoding!
1387 *---------------------------------------------------------------------------*/
1389 ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan)
1391 u_short blevel = S_HDLC_BLEVEL;
1392 u_char flag = S_HDLC_FLAG;
1393 u_int tmp = S_HDLC_TMP;
1394 u_short crc = S_HDLC_CRC;
1395 u_short ib = S_HDLC_IB;
1396 u_char * src = NULL;
1403 if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE) && (flag == 2)) return;
1405 sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1407 SET_REG(0xaa + chan);
1416 if (sendlen == 0x5ff)
1423 NDBGL1(L1_S_ERR, "XDU (unit=%d)", S_UNIT);
1429 HDLC_ENCODE(*src++, len, tmp, tmp2, blevel, ib, crc, flag,
1431 i4b_Bfreembuf(S_MBUF);
1432 S_MBUF = ihfc_getmbuf(sc, chan);
1441 sendlen = 0; /* Exit after final FS, *
1442 * else the buffer will *
1443 * only be filled with *
1449 DISBUSY(WRITE_DATA_1((u_char)tmp), sendlen = 0);
1454 if (S_MBUF) /* suspend */
1461 S_HDLC_BLEVEL = blevel;
1467 /*---------------------------------------------------------------------------*
1468 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1470 * NOTE: Software HDLC decoding!
1471 *---------------------------------------------------------------------------*/
1473 ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan)
1475 u_char blevel = S_HDLC_BLEVEL;
1476 u_char flag = S_HDLC_FLAG;
1477 u_short crc = S_HDLC_CRC;
1478 u_int tmp = S_HDLC_TMP;
1479 u_short ib = S_HDLC_IB;
1480 u_char * dst = NULL;
1481 u_short tmp2 = 0x100;
1492 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1495 reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1497 SET_REG(0xba + chan);
1501 HDLC_DECODE(*dst++, len, tmp, tmp2, blevel, ib, crc, flag,
1503 /* if (tmp2 & 0x100) while (GET_STAT & 1);
1504 * tmp2 = READ_BOTH_2;
1507 DISBUSY(tmp2 = READ_DATA_1, reclen = 0; tmp2 = 0);
1510 if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1511 panic("ihfc:(B) Out of mbufs!\n");
1514 len = BCH_MAX_DATALEN;
1517 len = (BCH_MAX_DATALEN - len);
1519 if ((!len) || (len > BCH_MAX_DATALEN))
1521 /* NOTE: frames without any data, *
1522 * only crc field, should be silently discared. */
1524 i4b_Bfreembuf(S_MBUF);
1525 NDBGL1(L1_S_MSG, "Bad frame (len=%d, unit=%d)", len, S_UNIT);
1530 { i4b_Bfreembuf(S_MBUF);
1531 NDBGL1(L1_S_ERR, "CRC (crc=0x%04x, len=%d, unit=%d)", crc, len, S_UNIT);
1537 ihfc_putmbuf(sc, chan, S_MBUF);
1542 i4b_Bfreembuf(S_MBUF);
1545 NDBGL1(L1_S_MSG, "Read Abort (unit=%d)", S_UNIT);
1548 i4b_Bfreembuf(S_MBUF);
1551 NDBGL1(L1_S_ERR, "RDO (unit=%d)", S_UNIT);
1558 * if (~tmp2 & 0x100) READ_DATA_1; kill disbusy signal
1561 if (S_MBUF) S_MBUFLEN = len; /* suspend */
1567 S_HDLC_BLEVEL = blevel;
1570 /*---------------------------------------------------------------------------*
1571 * Data handler for B channel(write) - chan 2 and 4 (HFC-1/S/SP)
1573 * This filter generates a pattern which is recognized
1574 * and examinated and verified by ihfc_test_Bread.
1576 * NOTE: This filter is only for testing purpose.
1577 *---------------------------------------------------------------------------*/
1579 ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan)
1584 u_short sendlen, tlen;
1585 u_short xlen = S_HDLC_IB;
1590 while((m = ihfc_getmbuf(sc, chan))) /* internal loop */
1593 ihfc_putmbuf(sc, 5, m);
1595 ihfc_putmbuf(sc, 3, m);
1600 sendlen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1602 if (sendlen == 0x5ff) kprintf("(send empty)");
1604 SET_REG(0xaa + chan);
1610 if (sendlen > 0x400) kprintf("(slow: %d)", sendlen);
1616 if (!tlen--) fb |= 0x20;
1620 while(GET_STAT & 1);
1626 while(GET_STAT & 1);
1627 WRITE_DATA_1((xlen + 1) & 0xef);
1636 /*---------------------------------------------------------------------------*
1637 * Data handler for B channel(read) - chan 3 and 5 (HFC-1/S/SP)
1639 * This filter examins and verifies the pattern
1640 * generated by ihfc_test_Bwrite.
1642 * NOTE: This filter is only for testing purpose.
1643 *---------------------------------------------------------------------------*/
1645 ihfc_test_Bread (ihfc_sc_t *sc, u_char chan)
1647 static u_short toterrors = 0;
1649 u_short reclen, len, tlen;
1652 u_short xlen = S_HDLC_IB;
1654 u_char error = S_HDLC_TMP;
1655 u_char ecount = S_HDLC_FLAG;
1659 if (S_UNIT != 0) return;
1661 reclen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1672 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1679 SET_REG(0xba + chan);
1683 /* if (tmp2 & 0x100) while(GET_STAT & 1);
1684 * tmp = (u_char)(tmp2 = READ_BOTH_2);
1688 /* if (!(++busy % 4)) reclen++; */
1689 while(GET_STAT & 1);
1694 if ((tmp & 0x3f) == 0x3e)
1696 if ((BCH_MAX_DATALEN - len) != 201) error |= 4;
1698 if ((S_MBUF) && (error))
1700 if (len) { len--; *dst++ = error; }
1701 if (len) { len--; *dst++ = xlen+1; }
1702 if (len) { len--; *dst++ = ecount; }
1704 S_MBUFLEN = BCH_MAX_DATALEN - len;
1706 if (S_TRACE & TRACE_B_RX)
1707 ihfc_putmbuf(sc, chan, S_MBUF);
1709 i4b_Bfreembuf(S_MBUF);
1712 kprintf("(error%d, %d, %d)", S_UNIT, ecount, toterrors++);
1715 i4b_Bfreembuf(S_MBUF);
1716 S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN);
1719 len = BCH_MAX_DATALEN;
1725 /* SET_REG(0xba + chan); */
1729 if (!xlen) error |= 2;
1730 if ((tmp ^ xlen--) & 0xef) { error |= 1; ecount++; }
1732 if (!tlen--) fb |= 0x20;
1736 *dst++ = (tmp | fb);
1753 S_HDLC_FLAG = ecount;
1756 #endif /* NIHFC > 0 */