Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / net / i4b / layer1 / ihfc / i4b_ihfc_drv.c
1 /*
2  * Copyright (c) 2000 Hans Petter Selasky. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_ihfc_drv.c - ihfc ISA PnP-bus interface
28  *      -------------------------------------------
29  *
30  *      Everything which has got anything to do with the
31  *      HFC-1/S/SP chips has been put here.
32  *
33  *      last edit-date: [Fri Jan 12 17:06:52 2001]
34  *
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  *
37  *---------------------------------------------------------------------------*/
38
39 #include "ihfc.h"
40
41 #if (NIHFC > 0)
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/socket.h>
46 #include <net/if.h>
47
48 #include <sys/mbuf.h>
49
50 #include <i4b/include/i4b_mbuf.h>
51
52 #include <machine/i4b_debug.h>
53 #include <machine/i4b_ioctl.h>
54 #include <machine/i4b_trace.h>
55
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>
61
62 #include <machine/bus.h>
63 #include <sys/rman.h>
64
65
66 /*---------------------------------------------------------------------------*
67  *      Local prototypes
68  *---------------------------------------------------------------------------*/
69         void    ihfc_loadconfig   (ihfc_sc_t *sc);
70
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);
77
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);
80
81         void    ihfc_cmdr_hdlr    (ihfc_sc_t *sc, u_char cmdr);
82         void    ihfc_exir_hdlr    (ihfc_sc_t *sc, u_char exir);
83
84         void    ihfc_sq           (ihfc_sc_t *sc);
85
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);
88
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);
91
92
93 /*---------------------------------------------------------------------------*
94  *      Commonly used ISA bus commands
95  *---------------------------------------------------------------------------*/
96 #define IHFC_DATA_OFFSET        0
97 #define IHFC_REG_OFFSET         1
98
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])
101
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)
104
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)
107
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)
110
111 #define DISBUSY(okcmd, tocmd)                                           \
112 {                                                                       \
113         if (GET_STAT & 1)                                               \
114         {                                                               \
115                 register u_char a;                                      \
116                 register u_int to = IHFC_DISBUSYTO;                     \
117                                                                         \
118                 while(((a = GET_STAT) & 1) && --to);                    \
119                                                                         \
120                 if (!to)                                                \
121                 {                                                       \
122                         NDBGL1(L1_ERROR, "DISBUSY-TIMEOUT! (a=%04x, "   \
123                         "unit=%d)", a, S_UNIT);                         \
124                         tocmd;                                          \
125                 }                                                       \
126                 else                                                    \
127                 {                                                       \
128                         okcmd;                                          \
129                 }                                                       \
130         }                                                               \
131         else                                                            \
132         {                                                               \
133                 okcmd;                                                  \
134         }                                                               \
135 }
136
137 #define WAITBUSY_2(okcmd, tocmd)                                        \
138         {                                                               \
139                 register u_short a;                                     \
140                 register u_int to = IHFC_NONBUSYTO;                     \
141                                                                         \
142                 while((~(a = READ_BOTH_2) & 0x100) && --to);            \
143                                                                         \
144                 if (!to)                                                \
145                 {                                                       \
146                         NDBGL1(L1_ERROR, "NONBUSY-TIMEOUT! (a=%04x, "   \
147                         "unit=%d)", a, S_UNIT);                         \
148                         tocmd;                                          \
149                 }                                                       \
150                 else                                                    \
151                 {                                                       \
152                         okcmd;                                          \
153                 }                                                       \
154         }
155
156 /*---------------------------------------------------------------------------*
157  *      Control function                                        (HFC-1/S/SP)
158  *      
159  *      Flag:
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)
165  *
166  *      Returns != 0 on errornous chip
167  *---------------------------------------------------------------------------*/
168 int
169 ihfc_control(ihfc_sc_t *sc, int flag)
170 {
171         BUS_VAR;
172
173         if (flag == 3) goto reset0;
174         if (flag == 4)
175         {
176                 S_NTMODE = 0;
177                 goto mode0;
178         }
179         if (flag == 5)
180         {
181                 S_NTMODE = 1;
182                 goto mode0;
183         }
184         if (flag == 1)
185         {
186                 WRITE_BOTH_2(0x5400 | S_IIO);   /* enable IO (HFC-1/S) */
187
188                 S_LAST_CHAN = -1;
189
190                 /* HFC-S/SP configuration */
191
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   */
202
203                 if (S_HFC & (HFC_1 | HFC_S))    /* configure timer (50ms) */
204                 {
205                         S_CTMT   |= 0x08;
206                 }
207                 else
208                 {
209                         S_CTMT   |= 0x14;
210                 }
211
212                 /* HFC-1 ISAC configuration (IOM-2 mode) */
213
214                 S_ADF1     = 0x00;      /* */
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                   */
222
223           mode0:
224                 if (S_NTMODE)           /* configure NT- or TE-mode */
225                 {
226                         S_SCTRL  |=  0x04;      /* NT mode      */
227                         S_CLKDEL &= ~0x7f;      /* clear delay  */
228                         S_CLKDEL |=  0x6c;      /* set delay    */
229                 }
230                 else
231                 {
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    */
236                 }
237                 if (S_DLP)              /* configure D-priority */
238                 {
239                         S_SCTRL  |= 0x08;       /* (10/11) */
240                 }
241                 else
242                 {
243                         S_SCTRL  &= ~0x08;      /* (8/9) */
244                 }
245
246           reset0:
247                 /* chip reset (HFC-1/S/SP) */
248
249                 if (S_HFC & HFC_1)
250                 {
251                         SET_REG((S_CIRM | 0xc8) & 0xdf);
252
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 *
258                                          * 10us.                        */
259
260                         SET_REG((S_CIRM | 0xc0) & 0xdf);
261
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.           */
269                 }
270                 else
271                 {
272                         SET_REG(0x18);
273
274                         WRITE_DATA_1(S_CIRM | 8);
275
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.            */
282
283                         WRITE_DATA_1(S_CIRM);
284
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  *
290                                          * that 25us.                   */
291                 }
292
293                 {
294                         /* HFC-1/S/SP chip test                         *
295                          *                                              *
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      *
301                          * operation.                                   */
302 #ifdef IHFC_DEBUG
303                         printf("ihfc: GET_STAT value is: 0x%x\n", GET_STAT);
304 #endif
305                         SET_REG(0x30);
306
307                         if ((GET_STAT & 1) || (READ_DATA_1 & 0xf)) goto f0;
308                 }
309
310                 ihfc_loadconfig(sc);
311                 
312                 if (S_HFC & HFC_1) ihfc_cmdr_hdlr(sc, 0x41);    /* rres, xres */
313
314                 S_PHSTATE = 0;
315                 HFC_FSM(sc, 0);
316         }
317
318         if (flag == 2)
319         {
320                 if (S_HFC & HFC_1) S_CIRM &= ~0x03;     /* disable interrupt */
321
322                 S_SQXR     |=  0x40;    /* power down */
323
324                 S_INT_M2   &= ~0x01;
325                 S_MASK     |=  0x02;
326
327                 S_SPCR     &= ~0x0f;    /* send 1's only */
328                 S_SCTRL    &= ~0x83;    /* send 1's only + enable oscillator */
329
330                 ihfc_loadconfig(sc);
331         }
332
333         return(0);      /* success */
334
335   f0:
336         return(1);      /* failure */
337 }
338
339 /*---------------------------------------------------------------------------*
340  *      Softc initializer and hardware setup                    (HFC-1/S/SP)
341  *
342  *      Returns: 0 on success
343  *               1 on failure
344  *---------------------------------------------------------------------------*/
345 int
346 ihfc_init (ihfc_sc_t *sc, u_char chan, int prot, int activate)
347 {
348         if (chan > 5) goto f0;
349
350         chan &= ~1;
351
352         do
353         {       if (chan < 2)                   /* D-Channel */
354                 {
355                         i4b_Dfreembuf(S_MBUF);
356                         if (!IF_QEMPTY(&S_IFQUEUE)) i4b_Dcleanifq(&S_IFQUEUE);
357
358                         RESET_SOFT_CHAN(sc, chan);
359
360                         S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
361
362 #if defined (__FreeBSD__) && __FreeBSD__ > 4
363                         mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", MTX_DEF);
364 #endif
365                         if (!activate) continue;
366
367                         if (S_HFC & HFC_1)
368                         {
369                                 S_FILTER  = (chan & 1) ? ihfc_isac_Dread :
370                                                          ihfc_isac_Dwrite;
371                         }
372                         else
373                         {
374                                 S_FILTER  = (chan & 1) ? ihfc_hdlc_Dread :
375                                                          ihfc_hdlc_Dwrite;
376                         }
377                 }
378                 else                            /* B-Channel */
379                 {
380                         i4b_Bfreembuf(S_MBUF);
381                         if (!IF_QEMPTY(&S_IFQUEUE))  i4b_Bcleanifq(&S_IFQUEUE);
382
383                         RESET_SOFT_CHAN(sc, chan);
384
385                         S_IFQUEUE.ifq_maxlen = IFQ_MAXLEN;
386
387 #if defined (__FreeBSD__) && __FreeBSD__ > 4
388                         mtx_init(&S_IFQUEUE.ifq_mtx, "i4b_ihfc", MTX_DEF);
389 #endif
390                         S_PROT = prot;
391
392                         if (!activate) continue;
393
394                         switch(prot)
395                         {       case(BPROT_NONE):
396                                         S_FILTER = (chan & 1) ? 
397                                                 ihfc_trans_Bread : 
398                                                 ihfc_trans_Bwrite;
399                                         break;
400                                 case(BPROT_RHDLC):
401                                         S_FILTER = (chan & 1) ? 
402                                                 ihfc_hdlc_Bread : 
403                                                 ihfc_hdlc_Bwrite;
404                                         break;
405                                 case(5):
406                                         S_FILTER = (chan & 1) ? 
407                                                 ihfc_test_Bread : 
408                                                 ihfc_test_Bwrite;
409                                         break;
410                         }
411                 }
412         } while (++chan & 1);
413
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)                  */
419
420         chan = 0;
421         if (S_FILTER)                   /* D-Channel active             */
422         {
423                 S_MASK   &= 0x2e;       /* enable RME, RPF, XPR, EXI    */
424                 S_INT_M1 |= 0x24;       /* enable D-receive, D-transmit */
425         }
426
427         chan = 2;
428         if (S_FILTER)                   /* B1-Channel active            */
429         {
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  */
435         }
436
437         chan = 4;
438         if (S_FILTER)                   /* B2-Channel active            */
439         {
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  */
445         }
446
447         ihfc_loadconfig(sc);
448
449         /* XXX  reset timer? */
450
451         return 0;       /* success */
452   f0:
453         return 1;       /* failure */
454 }
455
456 /*---------------------------------------------------------------------------*
457  *      Load configuration data                                 (HFC-1/S/SP)
458  *---------------------------------------------------------------------------*/
459 void 
460 ihfc_loadconfig(ihfc_sc_t *sc)
461 {
462         BUS_VAR;
463
464         if (S_HFC & HFC_1)
465         {
466                 /* HFC-1 chips w/ISAC: */
467
468                 const u_char *src = (void *)&S_ISAC_CONFIG;
469                 const u_char *dst = (void *)&isac_configtable;
470
471                 SET_REG((S_CIRM | 0xc0) & 0xdf);
472
473                 S_CTMT = (S_CTMT & ~0x14) | ((S_INT_M1 >> 5) & 0x4);
474
475                 SET_REG((S_CTMT | 0xe0) & 0xff);
476
477                 while(*dst)
478                 {
479                         SET_REG(*dst++);        /* set register */
480
481                         /* write configuration */       
482                         DISBUSY(WRITE_DATA_1(*src++), break);
483                 }
484         }
485         else
486         {
487                 /* HFC-S/SP chips: */
488
489                 const u_char *src = (void *)&S_HFC_CONFIG;
490                 const u_char *dst = (void *)&ihfc_configtable;
491
492                 while(*dst)
493                 {
494                         SET_REG(*dst++);        /* set register         */
495                         WRITE_DATA_1(*src++);   /* write configuration  */
496                 }
497         }
498 }
499
500 /*---------------------------------------------------------------------------*
501  *      Function State Machine handler (PH layer)               (HFC-1/S/SP)
502  *
503  *      Flag: 0 = Refresh softc S_PHSTATE + take hints
504  *            1 = Activate
505  *            2 = Deactivate
506  *
507  *      NOTE: HFC-1 only supports TE mode.
508  *---------------------------------------------------------------------------*/
509 void
510 ihfc_fsm(ihfc_sc_t *sc, int flag)
511 {
512         const struct ihfc_FSMtable *fsmtab;
513         u_char ihfc_cmd = 0;
514         u_char isac_cmd = 0;
515         u_char tmp;
516         BUS_VAR;
517
518         /* get current state (rx/downstream) */
519
520         if (S_HFC & HFC_1)
521         {
522                 SET_REG(0x31); DISBUSY(tmp = (READ_DATA_1 >> 2) & 0xf, return);
523
524                 fsmtab = (S_NTMODE) ? &ihfc_TEtable2[tmp]:
525                                       &ihfc_TEtable2[tmp];
526         }
527         else
528         {
529                 SET_REG(0x30); tmp = READ_DATA_1 & 0xf;
530
531                 fsmtab = (S_NTMODE) ? &ihfc_NTtable[tmp]:
532                                       &ihfc_TEtable[tmp];
533         }
534
535         if (fsmtab->string)
536         {
537                 NDBGL1(L1_I_CICO, "%s (ind=0x%x, flag=%d, unit=%d).",
538                         fsmtab->string, tmp, flag, S_UNIT);
539         }
540         else
541         {
542                 NDBGL1(L1_I_ERR, "Illegal indicatation (ind=0x%x, "
543                         "flag=%d, unit=%d).", tmp, flag, S_UNIT);
544         }
545
546         /* indication machine / state change                                    *
547          *                                                                      *
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.             */
552
553         if (fsmtab->state == 0) /* deactivated indication */
554         {
555                 if (S_PHSTATE != 0)
556                 {
557                         isac_cmd = 0x3c; /* deactivate DUI */
558
559                         i4b_l1_ph_deactivate_ind(S_I4BUNIT);
560                 }
561         }
562         if (fsmtab->state == 2) /* syncronized indication */
563         {
564                 if (S_PHSTATE != 2)
565                 {
566                         if (S_NTMODE) ihfc_cmd = 0x80;
567                 }
568         }
569         if (fsmtab->state == 3) /* activated indication */
570         {
571                 if (S_PHSTATE != 3)
572                 {
573                         isac_cmd = (S_DLP) ? 0x24  /* activate AR10 */
574                                            : 0x20; /* activate AR8  */
575
576                         i4b_l1_ph_activate_ind(S_I4BUNIT);
577                 }
578         }
579         if (fsmtab->state == 4) /* error indication */
580         {
581                 if (S_PHSTATE < 4)
582                 {
583                         isac_cmd = 0x3c; /* deactivate DUI */
584                 }
585         }
586
587         S_PHSTATE = fsmtab->state;
588
589         if ((flag == 1) && (fsmtab->state != 3))
590         {
591                 isac_cmd = (S_DLP) ? 0x24 : 0x20;
592                 ihfc_cmd = 0x60;
593         }
594         if ((flag == 2) && (fsmtab->state != 0))
595         {
596                 isac_cmd = 0x3c;
597                 ihfc_cmd = 0x40;
598         }
599
600         /* set new state (tx / upstream)                                      *
601          *                                                                    *
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.                        */
606
607         if (S_HFC & HFC_1)
608         {
609                 if (isac_cmd)
610                 {
611                         if (S_IOM2) isac_cmd |= 3;
612
613                         SET_REG(0x31); DISBUSY(WRITE_DATA_1(isac_cmd), );
614
615                         NDBGL1(L1_I_CICO, "(isac_cmd=0x%x, unit=%d).",
616                                 isac_cmd, S_UNIT);
617                 }
618         }
619         else
620         {
621                 if (ihfc_cmd || (fsmtab->state == 5))
622                 {
623                         SET_REG(0x30); WRITE_DATA_1(ihfc_cmd);
624
625                         NDBGL1(L1_I_CICO, "(ihfc_cmd=0x%x, unit=%d).",
626                                 ihfc_cmd, S_UNIT);
627                 }
628         }
629 }
630
631 /*---------------------------------------------------------------------------*
632  *      S/Q - channel handler (read)                            (HFC-S/SP)
633  *---------------------------------------------------------------------------*/
634 void
635 ihfc_sq (ihfc_sc_t *sc)
636 {
637         const struct ihfc_SQtable *SQtab;
638         register u_char a = 0;
639         BUS_VAR;
640
641         if (S_HFC & HFC_1)
642         {
643                 SET_REG(0x31);
644                 DISBUSY(a = READ_DATA_1, a = 0);
645
646                 if (a & 0x80)
647                 {
648                         SET_REG(0x3b);
649                         DISBUSY(a = READ_DATA_1, a = 0);
650                 }
651         }
652         else
653         {
654                 SET_REG(0x34);
655                 a = READ_DATA_1;
656         }
657
658         SQtab = (S_NTMODE) ? &ihfc_Qtable[a & 7]:
659                              &ihfc_Stable[a & 7];
660
661         if (a & 0x10)
662         {
663                 if (SQtab->string)
664                 {
665                         NDBGL1(L1_I_CICO, "%s (unit=%d, int=%x)",
666                                 SQtab->string, S_UNIT, S_INT_S1);
667                 }
668                 else
669                 {
670                         NDBGL1(L1_ERROR, "Unknown indication = %x (unit=%d)",
671                                  a & 7, S_UNIT);
672                 }
673         }
674 }
675
676 /*---------------------------------------------------------------------------*
677  *      Interrupt handler                                       (HFC-1)
678  *---------------------------------------------------------------------------*/
679 void
680 ihfc_intr1 (ihfc_sc_t *sc)
681 {
682         u_char chan;
683         u_char tmp;
684         BUS_VAR;
685         HFC_VAR;
686
687         HFC_BEG;
688
689         SET_REG(0x20); tmp = GET_STAT; DISBUSY(S_ISTA |= READ_DATA_1, );
690
691         if (S_ISTA & 0x04)      /* CIRQ */
692         {
693                 HFC_FSM(sc, 0);
694
695                 ihfc_sq(sc);
696         }
697
698         S_INTR_ACTIVE = 1;
699
700         if (S_ISTA & 0xc0)      /* RPF or RME */
701         {
702                 chan = 1;
703                 if (S_FILTER) S_FILTER(sc, chan);
704         }
705         if (S_ISTA & 0x10)      /* XPR */
706         {
707                 chan = 0;
708                 if (S_FILTER) S_FILTER(sc, chan);
709         }
710         if (tmp & 0x04)         /* Timer elapsed (50ms) */
711         {
712                 SET_REG((S_CTMT | 0xf0) & 0xff);
713
714                 chan = 6;
715                 while(chan--)
716                 {
717                         if (chan == 1) break;
718                         if (S_FILTER) S_FILTER(sc, chan);
719
720                         HFC_END;
721                         DELAY(10);
722                         HFC_BEG;
723                 }
724         }
725
726         S_INTR_ACTIVE = 0;
727                 
728         if (S_ISTA & 0x01)      /* EXIR */
729         {
730                 SET_REG(0x24); DISBUSY(ihfc_exir_hdlr(sc, READ_DATA_1), );
731         }
732
733         S_ISTA &= ~(0x1 | 0x4);
734
735         HFC_END;
736 }
737
738 /*---------------------------------------------------------------------------*
739  *      Interrupt handler                                       (HFC-S/SP)
740  *---------------------------------------------------------------------------*/
741 void
742 ihfc_intr2 (ihfc_sc_t *sc)
743 {
744         u_char chan;
745         BUS_VAR;
746         HFC_VAR;
747
748         HFC_BEG;
749
750         SET_REG(0x1e); S_INT_S1 = READ_DATA_1;  /* this will enable new interrupts! */
751
752         if (S_INT_S1 & 0x40)
753         {
754                 HFC_FSM(sc, 0);         /* statemachine changed */
755
756                 ihfc_sq(sc);
757         }
758
759         S_INTR_ACTIVE = 1;
760
761         if (S_INT_S1 & 0x20)            /* D-Channel frame (rx) */
762         {
763                 chan = 1;
764                 if (S_FILTER) S_FILTER(sc, chan);
765         }
766         if (S_INT_S1 & 0x04)            /* D-Channel frame (tx) */
767         {
768                 chan = 0;
769                 if (S_FILTER && (~S_INT_S1 & 0x80)) S_FILTER(sc, chan);
770         }
771         if (S_INT_S1 & 0x80)            /* Timer elapsed (50ms) */
772         {
773                 chan = 6;
774                 while(chan--)
775                 {
776                         if (chan == 1) continue;
777                         if (S_FILTER) S_FILTER(sc, chan);
778
779                         HFC_END;
780                         DELAY(10);
781                         HFC_BEG;
782                 }
783         }
784
785         S_INTR_ACTIVE = 0;
786
787         HFC_END;
788 }
789
790 /*---------------------------------------------------------------------------*
791  *      Select a Bfifo                                          (HFC-1/S/SP)
792  *      and return bytes in FIFO
793  *
794  *      (this code is optimized)
795  *---------------------------------------------------------------------------*/
796 u_short
797 ihfc_Bsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
798 {
799         register u_char  reg = 0x7e + chan;
800         register u_short tmp = 0x100;
801         register u_short z1;
802         register u_short z2;
803
804         BUS_VAR;
805
806         if (S_HFC & (HFC_1 | HFC_S))
807         {
808                 if (S_LAST_CHAN != chan)
809                 {
810                         SET_REG(reg);
811                         DISBUSY(WAITBUSY_2( , return 0), return 0);
812
813                         S_LAST_CHAN = chan;
814                 }
815         }
816         else
817         {
818                 SET_REG(0x10);
819                 WRITE_DATA_1(chan - 2);
820                 DISBUSY( , return 0);
821         }
822
823 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
824 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
825
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;
830
831 #undef FAST_READ
832 #undef FAST_STAT
833
834         z1 &= 0x1fff;
835         z2 &= 0x1fff;
836         
837         z1 = 0x5ff - (z2 = z1 - z2 + ((z2 <= z1) ? 0 : 0x600));
838
839         if (chan & 1)
840                 return(z2);     /* receive channel */
841         else
842                 return(z1);     /* transmit channel */
843 }
844
845 /*---------------------------------------------------------------------------*
846  *      Select a Dfifo                                          (HFC-S/SP)
847  *      and return bytes, and frames in FIFO
848  *
849  *      Flag values:
850  *              0x00: select new fifo + update counters
851  *              0x10: increment f1 + update counters
852  *              0x20: increment f2 + update counters
853  *
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  *---------------------------------------------------------------------------*/
857 u_int32_t
858 ihfc_Dsel_fifo(ihfc_sc_t *sc, u_char chan, u_char flag)
859 {
860         register u_char  reg = 0x90 + chan;
861         register u_short tmp = 0x100;
862         register u_char  f1;
863         register u_char  f2;
864         register u_short z1;
865         register u_short z2;
866
867         BUS_VAR;
868
869         if (S_HFC & (HFC_1 | HFC_S))
870         {
871                 switch(flag)
872                 {
873                         case(0x10):
874                         case(0x20):
875                                 SET_REG(reg);
876                                 if (~GET_STAT & 1)
877                                         WAITBUSY_2( , return 0);
878
879                                 SET_REG(0xa2 - (flag & 0x10) + chan);
880                                 DISBUSY(READ_DATA_1, return 0);
881
882                                 SET_REG(reg);
883                                 if (~GET_STAT & 1)
884                                         WAITBUSY_2( , return 0);
885                                 break;
886
887                         default:
888                                 if (S_LAST_CHAN != chan)
889                                 {
890                                         SET_REG(reg);
891                                         DISBUSY(WAITBUSY_2( , return 0), return 0);
892
893                                         S_LAST_CHAN = chan;
894                                 }
895                                 break;
896                 }
897         }
898         else
899         {
900                 switch(flag)
901                 {
902                         case(0x10):
903                         case(0x20):
904                                 SET_REG(0xb8 - (flag & 0x10) + chan);
905                                 READ_DATA_1;
906
907                                 DISBUSY( , return 0);
908
909                                 if (chan & 1)
910                                 {
911                                         /* Before reading a FIFO a change *
912                                          * FIFO operation must be done.   *
913                                          * (see HFC-SP manual p.38)       */
914
915                                         SET_REG(0x10);
916                                         WRITE_DATA_1(chan | 4);
917
918                                         DISBUSY( , return 0);
919                                 }
920                                 break;
921
922                         default:
923                                 SET_REG(0x10);
924                                 WRITE_DATA_1(chan | 4);
925
926                                 DISBUSY( , return 0);
927                                 break;
928                 }
929         }
930
931 #define FAST_READ (u_char)(tmp = READ_BOTH_2)
932 #define FAST_STAT if (tmp & 0x100) DISBUSY( , return 0);
933
934                 if (S_HFC & HFC_SP) reg = 0x80 + chan;
935
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;
940
941                 if (S_HFC & HFC_SP) reg += 0x26;
942
943                 SET_REG(reg -= 2); FAST_STAT; f1  = FAST_READ;
944                 SET_REG(reg += 4); FAST_STAT; f2  = READ_DATA_1;
945
946 #undef FAST_READ
947 #undef FAST_STAT
948
949         if (~chan & 1)
950         {                                       /* XXX was Z1                */
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   *
955                                                  * f1 != f2.                 */
956                 z2 = S_HDLC_DZ_TAB[f2 & 0xf];
957         }
958
959         z1 = 0x1ff - (z2 = (z1 - z2) & 0x1ff);
960         f1 = 0xf   - (f2 = (f1 - f2) & 0xf);
961
962         if (chan & 1)
963                 return(z2 | (f2 << 16));        /* receive channel */
964         else
965                 return(z1 | (f1 << 16));        /* transmit channel */
966 }
967
968
969 /*---------------------------------------------------------------------------*
970  *      Data handler for D channel(write) - chan 0              (HFC-S/SP)
971  *---------------------------------------------------------------------------*/
972 void
973 ihfc_hdlc_Dwrite (ihfc_sc_t *sc, u_char chan)
974 {
975         register u_int32_t  sendlen;
976         register u_short    len;
977         register u_char   * src;
978
979         BUS_VAR;
980
981         if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
982
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)
988         {
989                 if (!S_MBUF)
990                 {
991                         if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j1;
992                 }
993
994                 src = S_MBUFDATA;
995                 len = S_MBUFLEN;
996
997                 if (len >= 0x1ff) goto j0;      /* frame is too big: skip! */
998
999                 sendlen &= 0xffff;              /* only keep # of *
1000                                                  * bytes free     */
1001
1002                 SET_REG((S_HFC & HFC_SP) ? 0xac : 0x96);
1003
1004                 while (sendlen--)
1005                 {
1006                         if (!len--) break;
1007
1008                         DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1009                 }
1010
1011                 if (!++sendlen)                 /* out of fifo: suspend */
1012                 {
1013                         S_MBUFDATA = src;
1014                         S_MBUFLEN  = len;
1015                         break;
1016                 }
1017
1018                 sendlen = ihfc_Dsel_fifo(sc, chan, 0x10);       /* inc F1 */
1019            j0:
1020                 i4b_Dfreembuf(S_MBUF);
1021                 S_MBUF = NULL;
1022         }
1023   j1:
1024 }
1025
1026 /*---------------------------------------------------------------------------*
1027  *      Data handler for D channel(read) - chan 1               (HFC-S/SP)
1028  *
1029  *      NOTE: Max framelength is (511 - 3) = 508 bytes, when only one frame
1030  *            is received at a time.
1031  *---------------------------------------------------------------------------*/
1032 void
1033 ihfc_hdlc_Dread (ihfc_sc_t *sc, u_char chan)
1034 {
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;
1041
1042         BUS_VAR;
1043
1044         reclen = ihfc_Dsel_fifo(sc, chan, 0);   /* select new fifo          *
1045                                                  * NOTE: the higher 16 bits *
1046                                                  * contain the # of frames  *
1047                                                  * to receive.              */
1048         while ((reclen & ~0xffff) && to--)
1049         {
1050                 reclen &= 0xffff;               /* only keep # of       *
1051                                                  * bytes to receive     */
1052
1053                 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1054                         panic("ihfc_hdlc_Dread: No mbufs(unit=%d)!\n", S_UNIT);
1055
1056                 SET_REG((S_HFC & HFC_SP) ? 0xbd : 0xa7);
1057
1058                 if ((reclen > 2) && (reclen <= (DCH_MAX_LEN+2)))
1059                 {
1060                         dst = S_MBUFDATA;
1061                         len = S_MBUFLEN = (reclen += 1) - 3;
1062                 }
1063                 else
1064                 {
1065                         len = 0;
1066                         dst = NULL;
1067                 }
1068
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.                    */
1081
1082                 while(reclen--)
1083                 {
1084                         DISBUSY(tmp = READ_DATA_1, break);
1085                         if (len) { len--; *dst++ = tmp; }
1086
1087                         crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8));
1088                 }
1089
1090                 crc ^= 0x3933;
1091
1092                 if (!tmp && !crc)
1093                 {
1094                         ihfc_putmbuf(sc, chan, S_MBUF);
1095                         S_MBUF = NULL;
1096                 }
1097                 else
1098                 {
1099                         NDBGL1(L1_ERROR, "Frame error (len=%d, stat=0x%x, "
1100                                 "crc=0x%x, unit=%d)", S_MBUFLEN, (u_char)tmp, crc,
1101                                 S_UNIT);
1102
1103                         i4b_Dfreembuf(S_MBUF);
1104                         S_MBUF = NULL;
1105                 }
1106
1107                 reclen = ihfc_Dsel_fifo(sc, chan, 0x20);
1108         }
1109 }
1110
1111 /*---------------------------------------------------------------------------*
1112  *      EXIR error handler - ISAC       (D - channel)           (HFC-1)
1113  *---------------------------------------------------------------------------*/
1114 void
1115 ihfc_exir_hdlr (ihfc_sc_t *sc, u_char exir)
1116 {
1117         register u_char a;
1118         register u_char cmd;
1119
1120         for (a = 0, cmd = 0; exir; a++, exir >>= 1)
1121         {
1122                 if (exir & 1)
1123                 {
1124                         NDBGL1(L1_I_ERR, "%s. (unit=%d)",
1125                                 ihfc_EXIRtable[a].string, S_UNIT);
1126                         cmd |= ihfc_EXIRtable[a].cmd;
1127                 }
1128         }
1129
1130         if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1131 }
1132
1133 /*---------------------------------------------------------------------------*
1134  *      CMDR handler - ISAC     (D - channel)                   (HFC-1)
1135  *---------------------------------------------------------------------------*/
1136 void
1137 ihfc_cmdr_hdlr (ihfc_sc_t *sc, u_char cmdr)
1138 {
1139         BUS_VAR;
1140
1141         SET_REG(0x21); DISBUSY(WRITE_DATA_1(cmdr); DELAY(30), );
1142 }
1143
1144 /*---------------------------------------------------------------------------*
1145  *      Data handler for D channel(write) - chan 0              (HFC-1)
1146  *---------------------------------------------------------------------------*/
1147 void
1148 ihfc_isac_Dwrite (ihfc_sc_t *sc, u_char chan)
1149 {
1150         register u_char   sendlen = 32;
1151         register u_char   cmd = 0;
1152         register u_short  len;
1153         register u_char * src;
1154
1155         BUS_VAR;
1156
1157         if (~S_ISTA & 0x10) goto j0;
1158
1159         if (!S_MBUF)
1160                 if (!(S_MBUF = ihfc_getmbuf(sc, chan))) goto j0;
1161
1162         len = S_MBUFLEN;
1163         src = S_MBUFDATA;
1164
1165         SET_REG(0x00);
1166
1167         while(sendlen--)        /* write data */
1168         {
1169                 if (!len--) break;
1170                 DISBUSY(WRITE_DATA_1(*src++), goto a0);
1171         }
1172
1173         cmd |= 0x08;
1174         
1175         if (!++sendlen)         /* suspend */
1176         {
1177                 S_MBUFLEN  = len;
1178                 S_MBUFDATA = src;
1179         }
1180         else
1181         {
1182            a0:
1183                 i4b_Dfreembuf(S_MBUF);
1184                 S_MBUF = NULL;
1185
1186                 cmd |= 0x02;
1187         }
1188
1189         if (cmd) ihfc_cmdr_hdlr(sc, cmd);
1190
1191         S_ISTA &= ~0x10;
1192   j0:
1193 }
1194
1195 /*---------------------------------------------------------------------------*
1196  *      Data handler for D channel(read) - chan 1               (HFC-1)
1197  *---------------------------------------------------------------------------*/
1198 void
1199 ihfc_isac_Dread (ihfc_sc_t *sc, u_char chan)
1200 {
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;
1206
1207         BUS_VAR;
1208
1209         if (!(S_ISTA & 0xc0)) goto j1;  /* only receive data *
1210                                          * on interrupt      */
1211
1212         if (!S_MBUF)
1213         {
1214                 if (!(S_MBUF = i4b_Dgetmbuf(DCH_MAX_LEN)))
1215                         panic("ihfc%d: (D) Out of mbufs!\n", S_UNIT);
1216         }
1217
1218         len = S_MBUFLEN;
1219         dst = S_MBUFDATA + (DCH_MAX_LEN - len);
1220
1221         if (S_ISTA & 0x80)      /* RME */
1222         {
1223                 SET_REG(0x27); DISBUSY(tmp = (READ_DATA_1 ^ 0x20), goto j0);
1224
1225                 if (tmp & 0x70) goto j0;        /* error */
1226
1227                 SET_REG(0x25); DISBUSY(tmp = (READ_DATA_1 & 0x1f), goto j0);
1228
1229                 reclen = (tmp) ? tmp : 32;
1230         }
1231         else                    /* RPF */
1232         {
1233                 reclen = 32;
1234         }
1235
1236         if ((len -= reclen) <= DCH_MAX_LEN)     /* get data */
1237         {
1238                 SET_REG(0x00);
1239
1240                 while(reclen--)
1241                 {
1242                         DISBUSY(*dst++ = READ_DATA_1, goto j0);
1243                 }
1244         }
1245         else            /* soft rdo or error */
1246         {
1247           j0:   i4b_Dfreembuf(S_MBUF);
1248                 S_MBUF = NULL;
1249                 
1250                 cmd |= 0x40;
1251
1252                 NDBGL1(L1_I_ERR, "Frame error (unit=%d)", S_UNIT);
1253         }
1254
1255         if (S_ISTA & 0x80)      /* frame complete */
1256         {
1257                 if (S_MBUF)
1258                 {
1259                         S_MBUFLEN = (DCH_MAX_LEN - len);
1260                         ihfc_putmbuf(sc, chan, S_MBUF);
1261                         S_MBUF = NULL;
1262                 }
1263         }
1264
1265         if (S_MBUF)     /* suspend */
1266         {
1267                 S_MBUFLEN = len;
1268         }
1269
1270         ihfc_cmdr_hdlr(sc, cmd | 0x80);
1271
1272         S_ISTA &= ~0xc0;
1273   j1:
1274 }
1275
1276 /*---------------------------------------------------------------------------*
1277  *      Data handler for B channel(write) - chan 2 and 4        (HFC-1/S/SP)
1278  *
1279  *      NOTE: No XDU checking!
1280  *---------------------------------------------------------------------------*/
1281 void
1282 ihfc_trans_Bwrite (ihfc_sc_t *sc, u_char chan)
1283 {
1284         register u_short  sendlen;
1285         register u_short  len;
1286         register u_char * src;
1287
1288         BUS_VAR;
1289
1290         if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE)) return;
1291
1292         sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1293
1294         SET_REG(0xaa + chan);
1295
1296         while (1)
1297         {
1298                 if (!S_MBUF)
1299                 {
1300                         S_MBUF = ihfc_getmbuf(sc, chan);
1301                         if (!S_MBUF) break;
1302                 }
1303
1304                 src = S_MBUFDATA;
1305                 len = S_MBUFLEN;
1306
1307                 while (sendlen--)
1308                 {
1309                         if (!len--) break;
1310
1311                         DISBUSY(WRITE_DATA_1(*src++), sendlen = -1; len++; break);
1312                 }
1313
1314                 if (!++sendlen)         /* out of fifo: Suspend */
1315                 {
1316                         S_MBUFDATA = src;
1317                         S_MBUFLEN  = len;
1318                         break;
1319                 }
1320
1321                 i4b_Dfreembuf(S_MBUF);
1322                 S_MBUF = NULL;
1323         }
1324 }
1325
1326 /*---------------------------------------------------------------------------*
1327  *      Data handler for B channel(read) - chan 3 and 5         (HFC-1/S/SP)
1328  *      (this code is optimized)
1329  *---------------------------------------------------------------------------*/
1330 void
1331 ihfc_trans_Bread (ihfc_sc_t *sc, u_char chan)
1332 {
1333         register u_short  reclen;
1334         register u_short  tmp;
1335         register u_short  len;
1336         register u_char * dst;
1337
1338         BUS_VAR;
1339
1340         reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1341
1342         while (1)
1343         {
1344                 SET_REG(0xba + chan);
1345
1346                 tmp = 0x100;
1347
1348                 if (!S_MBUF)
1349                         if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1350                                 panic("ihfc%d: (B) Out of mbufs!\n", S_UNIT);
1351
1352                 len   = S_MBUFLEN;
1353                 dst   = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1354
1355                 while (reclen--)
1356                 {
1357                         if (!len--) break;
1358
1359                         if (tmp & 0x100) DISBUSY( , reclen = -1; len++; break);
1360                         *dst++ = (u_char)(tmp = READ_BOTH_2);
1361                 }
1362
1363                 if (~tmp & 0x100)
1364                 {
1365                         SET_REG(0x30);
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.         */
1371                 }
1372
1373                 if (!++reclen)          /* out of fifo: suspend */
1374                 {
1375                         S_MBUFLEN = len;
1376                         break;
1377                 }
1378
1379                 S_MBUFLEN = (BCH_MAX_DATALEN - ++len);
1380
1381                 ihfc_putmbuf(sc, chan, S_MBUF);
1382
1383                 S_MBUF = NULL;
1384         }
1385 }
1386
1387 /*---------------------------------------------------------------------------*
1388  *      Data handler for B channel(write) - chan 2 and 4        (HFC-1/S/SP)
1389  *      
1390  *      NOTE: Software HDLC encoding!
1391  *---------------------------------------------------------------------------*/
1392 void
1393 ihfc_hdlc_Bwrite (ihfc_sc_t *sc, u_char chan)
1394 {
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;
1404
1405         BUS_VAR;
1406
1407         if (!S_MBUF && IF_QEMPTY(&S_IFQUEUE) && (flag == 2)) return;
1408
1409         sendlen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1410
1411         SET_REG(0xaa + chan);
1412
1413         if (S_MBUF)
1414         {
1415                 /* resume */
1416
1417                 src = S_MBUFDATA; 
1418                 len = S_MBUFLEN;
1419
1420                 if (sendlen == 0x5ff)
1421                 { 
1422                         /* XDU */
1423
1424                         flag = -2;
1425                         len  = 0;
1426
1427                         NDBGL1(L1_S_ERR, "XDU (unit=%d)", S_UNIT);
1428                 }
1429         }
1430
1431         while (sendlen--)
1432         {
1433                 HDLC_ENCODE(*src++, len, tmp, tmp2, blevel, ib, crc, flag,
1434                 {/* gfr */
1435                         i4b_Bfreembuf(S_MBUF);
1436                         S_MBUF = ihfc_getmbuf(sc, chan);
1437
1438                         if (S_MBUF)
1439                         {
1440                                 src = S_MBUFDATA;
1441                                 len = S_MBUFLEN;
1442                         }
1443                         else
1444                         {
1445                                 sendlen = 0;    /* Exit after final FS, *
1446                                                  * else the buffer will *
1447                                                  * only be filled with  *
1448                                                  * "0x7e"-bytes!        */
1449                         }
1450                 },
1451                 {/* wrd */
1452                         
1453                         DISBUSY(WRITE_DATA_1((u_char)tmp), sendlen = 0);
1454                 },
1455                 d );
1456         }
1457
1458         if (S_MBUF)             /* suspend */
1459         {
1460                 S_MBUFDATA = src;
1461                 S_MBUFLEN  = len;
1462         }
1463
1464         S_HDLC_IB       = ib;
1465         S_HDLC_BLEVEL   = blevel;
1466         S_HDLC_TMP      = tmp;
1467         S_HDLC_FLAG     = flag;
1468         S_HDLC_CRC      = crc;
1469 }
1470
1471 /*---------------------------------------------------------------------------*
1472  *      Data handler for B channel(read) - chan 3 and 5         (HFC-1/S/SP)
1473  *      
1474  *      NOTE: Software HDLC decoding!
1475  *---------------------------------------------------------------------------*/
1476 void
1477 ihfc_hdlc_Bread (ihfc_sc_t *sc, u_char chan)
1478 {
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;
1488
1489         BUS_VAR;
1490
1491         if (S_MBUF)
1492         {
1493                 /* resume */
1494
1495                 len = S_MBUFLEN;
1496                 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1497         }
1498
1499         reclen = (u_short)ihfc_Bsel_fifo(sc, chan, 0);
1500
1501         SET_REG(0xba + chan);
1502
1503         while (reclen--)
1504         {
1505                 HDLC_DECODE(*dst++, len, tmp, tmp2, blevel, ib, crc, flag,
1506                 {/* rdd */
1507                         /* if (tmp2 & 0x100) while (GET_STAT & 1);
1508                          * tmp2 = READ_BOTH_2;
1509                          */
1510
1511                         DISBUSY(tmp2 = READ_DATA_1, reclen = 0; tmp2 = 0);
1512                 },
1513                 {/* nfr */
1514                         if (!(S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN)))
1515                                 panic("ihfc:(B) Out of mbufs!\n");
1516                                 
1517                         dst = S_MBUFDATA;
1518                         len = BCH_MAX_DATALEN;
1519                 },
1520                 {/* cfr */
1521                         len = (BCH_MAX_DATALEN - len);
1522
1523                         if ((!len) || (len > BCH_MAX_DATALEN))
1524                         {
1525                                 /* NOTE: frames without any data,               *
1526                                  * only crc field, should be silently discared. */
1527
1528                                 i4b_Bfreembuf(S_MBUF);
1529                                 NDBGL1(L1_S_MSG, "Bad frame (len=%d, unit=%d)", len, S_UNIT);
1530                                 goto s0;
1531                         }
1532
1533                         if (crc)
1534                         {       i4b_Bfreembuf(S_MBUF);
1535                                 NDBGL1(L1_S_ERR, "CRC (crc=0x%04x, len=%d, unit=%d)", crc, len, S_UNIT);
1536                                 goto s0;
1537                         }
1538
1539                         S_MBUFLEN = len;
1540
1541                         ihfc_putmbuf(sc, chan, S_MBUF);
1542                  s0:
1543                         S_MBUF = NULL;
1544                 },
1545                 {/* rab */
1546                         i4b_Bfreembuf(S_MBUF);
1547                         S_MBUF = NULL;
1548
1549                         NDBGL1(L1_S_MSG, "Read Abort (unit=%d)", S_UNIT);
1550                 },
1551                 {/* rdo */
1552                         i4b_Bfreembuf(S_MBUF);
1553                         S_MBUF = NULL;
1554
1555                         NDBGL1(L1_S_ERR, "RDO (unit=%d)", S_UNIT);
1556                 },
1557                 continue,
1558                 d);
1559         }
1560
1561         /* SET_REG(0x30);
1562          * if (~tmp2 & 0x100) READ_DATA_1;      kill disbusy signal
1563          */
1564
1565         if (S_MBUF) S_MBUFLEN = len;    /* suspend */
1566
1567         S_HDLC_IB       = ib;
1568         S_HDLC_CRC      = crc;
1569         S_HDLC_TMP      = tmp;
1570         S_HDLC_FLAG     = flag;
1571         S_HDLC_BLEVEL   = blevel;
1572 }
1573
1574 /*---------------------------------------------------------------------------*
1575  *      Data handler for B channel(write) - chan 2 and 4        (HFC-1/S/SP)
1576  *
1577  *      This filter generates a pattern which is recognized
1578  *      and examinated and verified by ihfc_test_Bread.
1579  *
1580  *      NOTE: This filter is only for testing purpose.
1581  *---------------------------------------------------------------------------*/
1582 void
1583 ihfc_test_Bwrite (ihfc_sc_t *sc, u_char chan)
1584 {
1585         struct mbuf *m;
1586
1587         register u_char  fb;
1588         register u_short sendlen, tlen;
1589         register u_short xlen = S_HDLC_IB;
1590         BUS_VAR;
1591
1592         goto j0;
1593
1594         while((m = ihfc_getmbuf(sc, chan)))     /* internal loop */
1595         {
1596                 if (chan == 2)
1597                         ihfc_putmbuf(sc, 5, m);
1598                 else
1599                         ihfc_putmbuf(sc, 3, m);
1600         }
1601
1602         j0:
1603
1604         sendlen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1605
1606         if (sendlen == 0x5ff) printf("(send empty)");
1607
1608         SET_REG(0xaa + chan);
1609
1610         S_BYTES += sendlen;
1611
1612         tlen    = S_HDLC_CRC;
1613
1614         if (sendlen > 0x400) printf("(slow: %d)", sendlen);
1615
1616         fb = 0x80;
1617
1618         while (sendlen--)
1619         {
1620                 if (!tlen--) fb |= 0x20;
1621
1622                 if (!xlen--)
1623                 {
1624                         while(GET_STAT & 1);
1625                         WRITE_DATA_1(0x3e);
1626                         xlen = 200;
1627                 }
1628                 else
1629                 {
1630                         while(GET_STAT & 1);
1631                         WRITE_DATA_1((xlen + 1) & 0xef);
1632                 }
1633
1634                 fb = 0;
1635         }
1636
1637         S_HDLC_IB = xlen;
1638 }
1639
1640 /*---------------------------------------------------------------------------*
1641  *      Data handler for B channel(read) - chan 3 and 5         (HFC-1/S/SP)
1642  *
1643  *      This filter examins and verifies the pattern
1644  *      generated by ihfc_test_Bwrite.
1645  *
1646  *      NOTE: This filter is only for testing purpose.
1647  *---------------------------------------------------------------------------*/
1648 void
1649 ihfc_test_Bread (ihfc_sc_t *sc, u_char chan)
1650 {
1651         static u_short toterrors = 0;
1652
1653         register u_short reclen, len, tlen;
1654         register u_char fb, tmp;
1655
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;
1660
1661         BUS_VAR;
1662
1663         if (S_UNIT != 0) return;
1664
1665         reclen = /* (u_short)ihfc_Bsel_fifo(sc, chan, 0); */ 0;
1666
1667         S_BYTES += reclen;
1668
1669         tlen   = S_HDLC_CRC;
1670
1671         fb = 0x40;
1672
1673         if (S_MBUF)
1674         {
1675                 len = S_MBUFLEN;
1676                 dst = S_MBUFDATA + (BCH_MAX_DATALEN - len);
1677         }
1678         else
1679         {
1680                 len = 0;
1681         }
1682
1683         SET_REG(0xba + chan);
1684
1685         while (reclen--)
1686         {
1687 /*              if (tmp2 & 0x100) while(GET_STAT & 1);
1688  *              tmp = (u_char)(tmp2 = READ_BOTH_2);
1689  */
1690                 if (GET_STAT & 1)
1691                 {       
1692                         /* if (!(++busy % 4)) reclen++; */
1693                         while(GET_STAT & 1);
1694                 }
1695
1696                 tmp = READ_DATA_1;
1697
1698                 if ((tmp & 0x3f) == 0x3e)
1699                 {
1700                         if ((BCH_MAX_DATALEN - len) != 201) error |= 4;
1701
1702                         if ((S_MBUF) && (error))
1703                         {
1704                                 if (len) { len--; *dst++ = error; }
1705                                 if (len) { len--; *dst++ = xlen+1; }
1706                                 if (len) { len--; *dst++ = ecount; }
1707
1708                                 S_MBUFLEN = BCH_MAX_DATALEN - len;
1709
1710                                 if (S_TRACE & TRACE_B_RX)
1711                                         ihfc_putmbuf(sc, chan, S_MBUF);
1712                                 else
1713                                         i4b_Bfreembuf(S_MBUF);
1714
1715                                 S_MBUF = NULL;
1716                                 printf("(error%d, %d, %d)", S_UNIT, ecount, toterrors++);
1717                         }
1718
1719                         i4b_Bfreembuf(S_MBUF);
1720                         S_MBUF = i4b_Bgetmbuf(BCH_MAX_DATALEN);
1721
1722                         dst = S_MBUFDATA;
1723                         len = BCH_MAX_DATALEN;
1724
1725                         xlen = 200;
1726                         error = 0;
1727                         ecount = 0;
1728
1729                 /*      SET_REG(0xba + chan); */
1730                 }
1731                 else
1732                 {
1733                         if (!xlen) error |= 2;
1734                         if ((tmp ^ xlen--) & 0xef) { error |= 1; ecount++; }
1735                 }
1736                 if (!tlen--) fb |= 0x20;
1737
1738                 if (len--)
1739                 {
1740                         *dst++ = (tmp | fb);
1741                 }
1742                 else
1743                 {
1744                         len++;
1745                 }
1746
1747                 fb = 0;
1748         }
1749
1750         if (S_MBUF)
1751         {
1752                 S_MBUFLEN = len;
1753         }
1754
1755         S_HDLC_IB = xlen;
1756         S_HDLC_TMP = error;
1757         S_HDLC_FLAG = ecount;
1758 }
1759
1760 #endif /* NIHFC > 0 */