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