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