]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer1/itjc/i4b_itjc_isac.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer1 / itjc / i4b_itjc_isac.c
1 /*-
2  * Copyright (c) 1997, 2001 Hellmuth Michaelis. 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_itjc_isac.c - i4b NetJet-S ISAC handler
29  *      --------------------------------------------
30  *      last edit-date: [Wed Jan 10 17:15:54 2001]
31  *
32  *---------------------------------------------------------------------------*/
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include "opt_i4b.h"
38
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44
45 #include <machine/stdarg.h>
46
47 #include <net/if.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
55 #include <i4b/layer1/isic/i4b_isic.h>
56 #include <i4b/layer1/isic/i4b_isac.h>
57
58 #include <i4b/layer1/itjc/i4b_itjc_ext.h>
59
60 #include <i4b/include/i4b_global.h>
61 #include <i4b/include/i4b_mbuf.h>
62
63 static u_char itjc_isac_exir_hdlr(register struct l1_softc *sc, u_char exir);
64 static void itjc_isac_ind_hdlr(register struct l1_softc *sc, int ind);
65
66 /*---------------------------------------------------------------------------*
67  *      ISAC interrupt service routine
68  *---------------------------------------------------------------------------*/
69 void
70 itjc_isac_irq(struct l1_softc *sc, int ista)
71 {
72         register u_char c = 0;
73         NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", sc->sc_unit, ista);
74
75         if(ista & ISAC_ISTA_EXI)        /* extended interrupt */
76         {
77                 c |= itjc_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
78         }
79         
80         if(ista & ISAC_ISTA_RME)        /* receive message end */
81         {
82                 register int rest;
83                 u_char rsta;
84
85                 /* get rx status register */
86                 
87                 rsta = ISAC_READ(I_RSTA);
88
89                 if((rsta & ISAC_RSTA_MASK) != 0x20)
90                 {
91                         int error = 0;
92                         
93                         if(!(rsta & ISAC_RSTA_CRC))     /* CRC error */
94                         {
95                                 error++;
96                                 NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit);
97                         }
98         
99                         if(rsta & ISAC_RSTA_RDO)        /* ReceiveDataOverflow */
100                         {
101                                 error++;
102                                 NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit);
103                         }
104         
105                         if(rsta & ISAC_RSTA_RAB)        /* ReceiveABorted */
106                         {
107                                 error++;
108                                 NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit);
109                         }
110
111                         if(error == 0)                  
112                                 NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", sc->sc_unit, rsta);
113
114                         i4b_Dfreembuf(sc->sc_ibuf);
115
116                         c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
117
118                         sc->sc_ibuf = NULL;
119                         sc->sc_ib = NULL;
120                         sc->sc_ilen = 0;
121
122                         ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
123                         ISACCMDRWRDELAY();
124
125                         return;
126                 }
127
128                 rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));
129
130                 if(rest == 0)
131                         rest = ISAC_FIFO_LEN;
132
133                 if(sc->sc_ibuf == NULL)
134                 {
135                         if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
136                                 sc->sc_ib = sc->sc_ibuf->m_data;
137                         else
138                                 panic("itjc_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n");
139                         sc->sc_ilen = 0;
140                 }
141
142                 if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
143                 {
144                         ISAC_RDFIFO(sc->sc_ib, rest);
145                         sc->sc_ilen += rest;
146                         
147                         sc->sc_ibuf->m_pkthdr.len =
148                                 sc->sc_ibuf->m_len = sc->sc_ilen;
149
150                         if(sc->sc_trace & TRACE_D_RX)
151                         {
152                                 i4b_trace_hdr_t hdr;
153                                 hdr.unit = L0ITJCUNIT(sc->sc_unit);
154                                 hdr.type = TRC_CH_D;
155                                 hdr.dir = FROM_NT;
156                                 hdr.count = ++sc->sc_trace_dcount;
157                                 MICROTIME(hdr.time);
158                                 i4b_l1_trace_ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
159                         }
160
161                         c |= ISAC_CMDR_RMC;
162
163                         if(sc->sc_enabled &&
164                            (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S))
165                         {
166                                 i4b_l1_ph_data_ind(L0ITJCUNIT(sc->sc_unit), sc->sc_ibuf);
167                         }
168                         else
169                         {
170                                 i4b_Dfreembuf(sc->sc_ibuf);
171                         }
172                 }
173                 else
174                 {
175                         NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
176                         i4b_Dfreembuf(sc->sc_ibuf);
177                         c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
178                 }
179
180                 sc->sc_ibuf = NULL;
181                 sc->sc_ib = NULL;
182                 sc->sc_ilen = 0;
183         }
184
185         if(ista & ISAC_ISTA_RPF)        /* receive fifo full */
186         {
187                 if(sc->sc_ibuf == NULL)
188                 {
189                         if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
190                                 sc->sc_ib= sc->sc_ibuf->m_data;
191                         else
192                                 panic("itjc_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
193                         sc->sc_ilen = 0;
194                 }
195
196                 if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
197                 {
198                         ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
199                         sc->sc_ilen += ISAC_FIFO_LEN;                   
200                         sc->sc_ib += ISAC_FIFO_LEN;
201                         c |= ISAC_CMDR_RMC;
202                 }
203                 else
204                 {
205                         NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
206                         i4b_Dfreembuf(sc->sc_ibuf);
207                         sc->sc_ibuf = NULL;
208                         sc->sc_ib = NULL;
209                         sc->sc_ilen = 0;
210                         c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;                      
211                 }
212         }
213
214         if(ista & ISAC_ISTA_XPR)        /* transmit fifo empty (XPR bit set) */
215         {
216                 if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
217                 {
218                         sc->sc_freeflag = sc->sc_freeflag2;
219                         sc->sc_obuf = sc->sc_obuf2;
220                         sc->sc_op = sc->sc_obuf->m_data;
221                         sc->sc_ol = sc->sc_obuf->m_len;
222                         sc->sc_obuf2 = NULL;
223                 }
224                 
225                 if(sc->sc_obuf)
226                 {                       
227                         ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));
228         
229                         if(sc->sc_ol > ISAC_FIFO_LEN)   /* length > 32 ? */
230                         {
231                                 sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
232                                 sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
233                                 c |= ISAC_CMDR_XTF;         /* set XTF bit */
234                         }
235                         else
236                         {
237                                 if(sc->sc_freeflag)
238                                 {
239                                         i4b_Dfreembuf(sc->sc_obuf);
240                                         sc->sc_freeflag = 0;
241                                 }
242                                 sc->sc_obuf = NULL;
243                                 sc->sc_op = NULL;
244                                 sc->sc_ol = 0;
245         
246                                 c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
247                         }
248                 }
249                 else
250                 {
251                         sc->sc_state &= ~ISAC_TX_ACTIVE;
252                 }
253         }
254         
255         if(ista & ISAC_ISTA_CISQ)       /* channel status change CISQ */
256         {
257                 register u_char ci;
258         
259                 /* get command/indication rx register*/
260         
261                 ci = ISAC_READ(I_CIRR);
262
263                 /* if S/Q IRQ, read SQC reg to clr SQC IRQ */
264         
265                 if(ci & ISAC_CIRR_SQC)
266                         (void) ISAC_READ(I_SQRR);
267
268                 /* C/I code change IRQ (flag already cleared by CIRR read) */
269         
270                 if(ci & ISAC_CIRR_CIC0)
271                         itjc_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
272         }
273         
274         if(c)
275         {
276                 ISAC_WRITE(I_CMDR, c);
277                 ISACCMDRWRDELAY();
278         }
279 }
280
281 /*---------------------------------------------------------------------------*
282  *      ISAC L1 Extended IRQ handler
283  *---------------------------------------------------------------------------*/
284 static u_char
285 itjc_isac_exir_hdlr(register struct l1_softc *sc, u_char exir)
286 {
287         u_char c = 0;
288         
289         if(exir & ISAC_EXIR_XMR)
290         {
291                 NDBGL1(L1_I_ERR, "EXIRQ Tx Message Repeat");
292
293                 c |= ISAC_CMDR_XRES;
294         }
295         
296         if(exir & ISAC_EXIR_XDU)
297         {
298                 NDBGL1(L1_I_ERR, "EXIRQ Tx Data Underrun");
299
300                 c |= ISAC_CMDR_XRES;
301         }
302
303         if(exir & ISAC_EXIR_PCE)
304         {
305                 NDBGL1(L1_I_ERR, "EXIRQ Protocol Error");
306         }
307
308         if(exir & ISAC_EXIR_RFO)
309         {
310                 NDBGL1(L1_I_ERR, "EXIRQ Rx Frame Overflow");
311
312                 c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
313         }
314
315         if(exir & ISAC_EXIR_SOV)
316         {
317                 NDBGL1(L1_I_ERR, "EXIRQ Sync Xfer Overflow");
318         }
319
320         if(exir & ISAC_EXIR_MOS)
321         {
322                 NDBGL1(L1_I_ERR, "EXIRQ Monitor Status");
323         }
324
325         if(exir & ISAC_EXIR_SAW)
326         {
327                 /* cannot happen, STCR:TSF is set to 0 */
328                 
329                 NDBGL1(L1_I_ERR, "EXIRQ Subscriber Awake");
330         }
331
332         if(exir & ISAC_EXIR_WOV)
333         {
334                 /* cannot happen, STCR:TSF is set to 0 */
335
336                 NDBGL1(L1_I_ERR, "EXIRQ Watchdog Timer Overflow");
337         }
338
339         return(c);
340 }
341
342 /*---------------------------------------------------------------------------*
343  *      ISAC L1 Indication handler
344  *---------------------------------------------------------------------------*/
345 static void
346 itjc_isac_ind_hdlr(register struct l1_softc *sc, int ind)
347 {
348         register int event;
349         
350         switch(ind)
351         {
352                 case ISAC_CIRR_IAI8:
353                         NDBGL1(L1_I_CICO, "rx AI8 in state %s", itjc_printstate(sc));
354                         itjc_isac_l1_cmd(sc, CMD_AR8);
355                         event = EV_INFO48;
356                         i4b_l1_mph_status_ind(L0ITJCUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
357                         break;
358                         
359                 case ISAC_CIRR_IAI10:
360                         NDBGL1(L1_I_CICO, "rx AI10 in state %s", itjc_printstate(sc));
361                         itjc_isac_l1_cmd(sc, CMD_AR10);
362                         event = EV_INFO410;
363                         i4b_l1_mph_status_ind(L0ITJCUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
364                         break;
365
366                 case ISAC_CIRR_IRSY:
367                         NDBGL1(L1_I_CICO, "rx RSY in state %s", itjc_printstate(sc));
368                         event = EV_RSY;
369                         break;
370
371                 case ISAC_CIRR_IPU:
372                         NDBGL1(L1_I_CICO, "rx PU in state %s", itjc_printstate(sc));
373                         event = EV_PU;
374                         break;
375
376                 case ISAC_CIRR_IDR:
377                         NDBGL1(L1_I_CICO, "rx DR in state %s", itjc_printstate(sc));
378                         itjc_isac_l1_cmd(sc, CMD_DIU);
379                         event = EV_DR;                  
380                         break;
381                         
382                 case ISAC_CIRR_IDID:
383                         NDBGL1(L1_I_CICO, "rx DID in state %s", itjc_printstate(sc));
384                         event = EV_INFO0;
385                         i4b_l1_mph_status_ind(L0ITJCUNIT(sc->sc_unit), STI_L1STAT, LAYER_IDLE, NULL);
386                         break;
387
388                 case ISAC_CIRR_IDIS:
389                         NDBGL1(L1_I_CICO, "rx DIS in state %s", itjc_printstate(sc));
390                         event = EV_DIS;
391                         break;
392
393                 case ISAC_CIRR_IEI:
394                         NDBGL1(L1_I_CICO, "rx EI in state %s", itjc_printstate(sc));
395                         itjc_isac_l1_cmd(sc, CMD_DIU);
396                         event = EV_EI;
397                         break;
398
399                 case ISAC_CIRR_IARD:
400                         NDBGL1(L1_I_CICO, "rx ARD in state %s", itjc_printstate(sc));
401                         event = EV_INFO2;
402                         break;
403
404                 case ISAC_CIRR_ITI:
405                         NDBGL1(L1_I_CICO, "rx TI in state %s", itjc_printstate(sc));
406                         event = EV_INFO0;
407                         break;
408
409                 case ISAC_CIRR_IATI:
410                         NDBGL1(L1_I_CICO, "rx ATI in state %s", itjc_printstate(sc));
411                         event = EV_INFO0;
412                         break;
413
414                 case ISAC_CIRR_ISD:
415                         NDBGL1(L1_I_CICO, "rx SD in state %s", itjc_printstate(sc));
416                         event = EV_INFO0;
417                         break;
418                 
419                 default:
420                         NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, itjc_printstate(sc));
421                         event = EV_INFO0;
422                         break;
423         }
424         itjc_next_state(sc, event);
425 }
426
427 /*---------------------------------------------------------------------------*
428  *      execute a layer 1 command
429  *---------------------------------------------------------------------------*/ 
430 void
431 itjc_isac_l1_cmd(struct l1_softc *sc, int command)
432 {
433         u_char cmd;
434
435         if(command < 0 || command > CMD_ILL)
436         {
437                 NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, itjc_printstate(sc));
438                 return;
439         }
440                                            
441         cmd = ISAC_CIX0_LOW;
442
443         switch(command)
444         {
445                 case CMD_TIM:
446                         NDBGL1(L1_I_CICO, "tx TIM in state %s", itjc_printstate(sc));
447                         cmd |= (ISAC_CIXR_CTIM << 2);
448                         break;
449
450                 case CMD_RS:
451                         NDBGL1(L1_I_CICO, "tx RS in state %s", itjc_printstate(sc));
452                         cmd |= (ISAC_CIXR_CRS << 2);
453                         break;
454
455                 case CMD_AR8:
456                         NDBGL1(L1_I_CICO, "tx AR8 in state %s", itjc_printstate(sc));
457                         cmd |= (ISAC_CIXR_CAR8 << 2);
458                         break;
459
460                 case CMD_AR10:
461                         NDBGL1(L1_I_CICO, "tx AR10 in state %s", itjc_printstate(sc));
462                         cmd |= (ISAC_CIXR_CAR10 << 2);
463                         break;
464
465                 case CMD_DIU:
466                         NDBGL1(L1_I_CICO, "tx DIU in state %s", itjc_printstate(sc));
467                         cmd |= (ISAC_CIXR_CDIU << 2);
468                         break;
469         }
470         ISAC_WRITE(I_CIXR, cmd);
471 }
472
473 /*---------------------------------------------------------------------------*
474  *      L1 ISAC initialization
475  *---------------------------------------------------------------------------*/
476 int
477 itjc_isac_init(struct l1_softc *sc)
478 {
479         ISAC_IMASK = 0xff;              /* disable all irqs */
480
481         ISAC_WRITE(I_MASK, ISAC_IMASK);
482
483         NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode");
484
485         /* ADF2: Select mode IOM-2 */           
486         ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS);
487
488         /* SPCR: serial port control register:
489          *      SPU - software power up = 0
490          *      SPM - timing mode 0
491          *      TLP - test loop = 0
492          *      C1C, C2C - B1 + C1 and B2 + IC2 monitoring
493          */
494         ISAC_WRITE(I_SPCR, 0x00);
495
496         /* SQXR: S/Q channel xmit register:
497          *      IDC  - IOM direction = 0 (master)
498          *      CFS  - Config Select = 0 (clock always active)
499          *      CI1E - C/I channel 1 IRQ enable = 0
500                  *      SQIE - S/Q IRQ enable = 0
501          *      SQX1-4 - Fa bits = 1
502          */
503         ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
504
505         /* ADF1: additional feature reg 1:
506          *      WTC - watchdog = 0
507          *      TEM - test mode = 0
508          *      PFS - pre-filter = 0
509          *      IOF - IOM i/f off = 0
510          *      ITF - interframe fill = idle
511          */     
512         ISAC_WRITE(I_ADF1, 0x00);
513
514         /* STCR: sync transfer control reg:
515          *      TSF - terminal secific functions = 0
516          *      TBA - TIC bus address = 7
517          *      STx/SCx = 0
518          */
519         ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
520
521         /* MODE: Mode Register:
522          *      MDSx - transparent mode 2
523          *      TMD  - timer mode = external
524          *      RAC  - Receiver enabled
525          *      DIMx - digital i/f mode
526          */
527         ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
528
529         /* enabled interrupts:
530          * ===================
531          * RME  - receive message end
532          * RPF  - receive pool full
533          * XPR  - transmit pool ready
534          * CISQ - CI or S/Q channel change
535          * EXI  - extended interrupt
536          */
537
538         ISAC_IMASK = ISAC_MASK_RSC |    /* auto mode only       */
539                      ISAC_MASK_TIN |    /* timer irq            */
540                      ISAC_MASK_SIN;     /* sync xfer irq        */
541
542         ISAC_WRITE(I_MASK, ISAC_IMASK);
543
544         return(0);
545 }