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