2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
25 *---------------------------------------------------------------------------
27 * i4b - Siemens HSCX chip (B-channel) handling
28 * --------------------------------------------
30 * $Id: i4b_hscx.c,v 1.2 1999/12/13 21:25:26 hm Exp $
34 * last edit-date: [Mon Dec 13 21:59:58 1999]
36 *---------------------------------------------------------------------------*/
42 #include <sys/param.h>
43 #include <sys/systm.h>
45 #include <sys/socket.h>
47 #include <machine/stdarg.h>
48 #include <machine/clock.h>
52 #include <machine/i4b_debug.h>
53 #include <machine/i4b_ioctl.h>
54 #include <machine/i4b_trace.h>
56 #include <i4b/layer1/i4b_l1.h>
57 #include <i4b/layer1/i4b_isac.h>
58 #include <i4b/layer1/i4b_hscx.h>
60 #include <i4b/include/i4b_l1l2.h>
61 #include <i4b/include/i4b_global.h>
62 #include <i4b/include/i4b_mbuf.h>
64 /*---------------------------------------------------------------------------*
66 *---------------------------------------------------------------------------*/
68 isic_hscx_irq(register struct l1_softc *sc, u_char ista, int h_chan, u_char ex_irq)
70 register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
75 DBGL1(L1_H_IRQ, "isic_hscx_irq", ("%#x\n", ista));
79 /* get channel extended irq reg */
81 exir = HSCX_READ(h_chan, H_EXIR);
83 if(exir & HSCX_EXIR_RFO)
86 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: receive data overflow\n"));
89 if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
92 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: xmit data underrun\n"));
93 isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);
95 if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */
97 i4b_Bfreembuf(chan->out_mbuf_head);
98 chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
104 /* rx message end, end of frame */
106 if(ista & HSCX_ISTA_RME)
108 register int fifo_data_len;
112 rsta = HSCX_READ(h_chan, H_RSTA);
114 if((rsta & 0xf0) != 0xa0)
116 if((rsta & HSCX_RSTA_VFR) == 0)
119 cmd |= (HSCX_CMDR_RHR);
120 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("received invalid Frame\n"));
124 if(rsta & HSCX_RSTA_RDO)
127 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("receive data overflow\n"));
131 if((rsta & HSCX_RSTA_CRC) == 0)
134 cmd |= (HSCX_CMDR_RHR);
135 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("CRC check failed\n"));
139 if(rsta & HSCX_RSTA_RAB)
142 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("Receive message aborted\n"));
147 fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
148 ((sc->sc_bfifolen)-1));
150 if(fifo_data_len == 0)
151 fifo_data_len = sc->sc_bfifolen;
153 /* all error conditions checked, now decide and take action */
157 if(chan->in_mbuf == NULL)
159 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
160 panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n");
161 chan->in_cbptr = chan->in_mbuf->m_data;
165 fifo_data_len -= 1; /* last byte in fifo is RSTA ! */
167 if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
169 /* read data from HSCX fifo */
171 HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);
173 cmd |= (HSCX_CMDR_RMC);
174 isic_hscx_cmd(sc, h_chan, cmd);
177 chan->in_len += fifo_data_len;
178 chan->rxcount += fifo_data_len;
180 /* setup mbuf data length */
182 chan->in_mbuf->m_len = chan->in_len;
183 chan->in_mbuf->m_pkthdr.len = chan->in_len;
185 if(sc->sc_trace & TRACE_B_RX)
188 hdr.unit = sc->sc_unit;
189 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
191 hdr.count = ++sc->sc_trace_bcount;
193 MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
196 (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
200 /* mark buffer ptr as unused */
202 chan->in_mbuf = NULL;
203 chan->in_cbptr = NULL;
208 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d\n", chan->in_len, fifo_data_len));
209 chan->in_cbptr = chan->in_mbuf->m_data;
211 cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC);
216 if (chan->in_mbuf != NULL)
218 i4b_Bfreembuf(chan->in_mbuf);
219 chan->in_mbuf = NULL;
220 chan->in_cbptr = NULL;
223 cmd |= (HSCX_CMDR_RMC);
229 if(ista & HSCX_ISTA_RPF)
231 if(chan->in_mbuf == NULL)
233 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
234 panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n");
235 chan->in_cbptr = chan->in_mbuf->m_data;
239 chan->rxcount += sc->sc_bfifolen;
241 if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
243 /* read data from HSCX fifo */
245 HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
247 chan->in_cbptr += sc->sc_bfifolen;
248 chan->in_len += sc->sc_bfifolen;
252 if(chan->bprot == BPROT_NONE)
254 /* setup mbuf data length */
256 chan->in_mbuf->m_len = chan->in_len;
257 chan->in_mbuf->m_pkthdr.len = chan->in_len;
259 if(sc->sc_trace & TRACE_B_RX)
262 hdr.unit = sc->sc_unit;
263 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
265 hdr.count = ++sc->sc_trace_bcount;
267 MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
270 /* silence detection */
272 if(!(isic_hscx_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
275 if(!(IF_QFULL(&chan->rx_queue)))
277 IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
281 i4b_Bfreembuf(chan->in_mbuf);
284 /* signal upper driver that data is available */
286 (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
288 /* alloc new buffer */
290 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
291 panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n");
293 /* setup new data ptr */
295 chan->in_cbptr = chan->in_mbuf->m_data;
297 /* read data from HSCX fifo */
299 HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
301 chan->in_cbptr += sc->sc_bfifolen;
302 chan->in_len = sc->sc_bfifolen;
304 chan->rxcount += sc->sc_bfifolen;
308 DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RPF, in_len=%d\n", chan->in_len));
309 chan->in_cbptr = chan->in_mbuf->m_data;
311 cmd |= (HSCX_CMDR_RHR);
315 /* command to release fifo space */
317 cmd |= HSCX_CMDR_RMC;
320 /* transmit fifo empty, new data can be written to fifo */
322 if(ista & HSCX_ISTA_XPR)
325 * for a description what is going on here, please have
326 * a look at isic_bchannel_start() in i4b_bchan.c !
333 DBGL1(L1_H_IRQ, "isic_hscx_irq", ("unit %d, chan %d - XPR, Tx Fifo Empty!\n", sc->sc_unit, h_chan));
335 if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */
337 IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
339 if(chan->out_mbuf_head == NULL)
341 chan->state &= ~HSCX_TX_ACTIVE;
342 (*chan->drvr_linktab->bch_tx_queue_empty)(chan->drvr_linktab->unit);
346 chan->state |= HSCX_TX_ACTIVE;
347 chan->out_mbuf_cur = chan->out_mbuf_head;
348 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
349 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
351 if(sc->sc_trace & TRACE_B_TX)
354 hdr.unit = sc->sc_unit;
355 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
357 hdr.count = ++sc->sc_trace_bcount;
359 MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
362 if(chan->bprot == BPROT_NONE)
364 if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
376 while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
378 nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
381 printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
384 chan->out_mbuf_cur_ptr,
385 chan->out_mbuf_cur_len,
390 isic_hscx_waitxfw(sc, h_chan); /* necessary !!! */
392 HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
393 cmd |= HSCX_CMDR_XTF;
396 chan->txcount += nextlen;
398 chan->out_mbuf_cur_ptr += nextlen;
399 chan->out_mbuf_cur_len -= nextlen;
401 if(chan->out_mbuf_cur_len == 0)
403 if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
405 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
406 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
408 if(sc->sc_trace & TRACE_B_TX)
411 hdr.unit = sc->sc_unit;
412 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
414 hdr.count = ++sc->sc_trace_bcount;
416 MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
421 if (chan->bprot != BPROT_NONE)
422 cmd |= HSCX_CMDR_XME;
423 i4b_Bfreembuf(chan->out_mbuf_head);
424 chan->out_mbuf_head = NULL;
431 if(cmd) /* is there a command for the HSCX ? */
433 isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */
436 /* call timeout handling routine */
438 if(activity == ACT_RX || activity == ACT_TX)
439 (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
442 /*---------------------------------------------------------------------------*
443 * HSCX initialization
445 * for telephony: extended transparent mode 1
446 * for raw hdlc: transparent mode 0
447 *---------------------------------------------------------------------------*/
449 isic_hscx_init(struct l1_softc *sc, int h_chan, int activate)
451 l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
453 HSCX_WRITE(h_chan, H_MASK, 0xff); /* mask irq's */
457 /* CCR1: Power Up, Clock Mode 5 */
458 HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
459 HSCX_CCR1_CM1); /* IPAC clock mode 5 */
463 /* CCR1: Power Up, Clock Mode 5 */
464 HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
465 HSCX_CCR1_CM2 | /* HSCX clock mode 5 */
469 /* XAD1: Transmit Address Byte 1 */
470 HSCX_WRITE(h_chan, H_XAD1, 0xff);
472 /* XAD2: Transmit Address Byte 2 */
473 HSCX_WRITE(h_chan, H_XAD2, 0xff);
475 /* RAH2: Receive Address Byte High Reg. 2 */
476 HSCX_WRITE(h_chan, H_RAH2, 0xff);
478 /* XBCH: reset Transmit Byte Count High */
479 HSCX_WRITE(h_chan, H_XBCH, 0x00);
481 /* RLCR: reset Receive Length Check Register */
482 HSCX_WRITE(h_chan, H_RLCR, 0x00);
484 /* CCR2: set tx/rx clock shift bit 0 */
485 /* disable CTS irq, disable RIE irq*/
486 HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);
488 /* XCCR: tx bit count per time slot */
489 HSCX_WRITE(h_chan, H_XCCR, 0x07);
491 /* RCCR: rx bit count per time slot */
492 HSCX_WRITE(h_chan, H_RCCR, 0x07);
494 if(sc->sc_bustyp == BUS_TYPE_IOM2)
498 case HSCX_CH_A: /* Prepare HSCX channel A */
499 /* TSAX: tx clock shift bits 1 & 2 */
500 /* tx time slot number */
501 HSCX_WRITE(h_chan, H_TSAX, 0x2f);
503 /* TSAR: rx clock shift bits 1 & 2 */
504 /* rx time slot number */
505 HSCX_WRITE(h_chan, H_TSAR, 0x2f);
508 case HSCX_CH_B: /* Prepare HSCX channel B */
509 /* TSAX: tx clock shift bits 1 & 2 */
510 /* tx time slot number */
511 HSCX_WRITE(h_chan, H_TSAX, 0x03);
513 /* TSAR: rx clock shift bits 1 & 2 */
514 /* rx time slot number */
515 HSCX_WRITE(h_chan, H_TSAR, 0x03);
519 else /* IOM 1 setup */
521 /* TSAX: tx clock shift bits 1 & 2 */
522 /* tx time slot number */
523 HSCX_WRITE(h_chan, H_TSAX, 0x07);
525 /* TSAR: rx clock shift bits 1 & 2 */
526 /* rx time slot number */
527 HSCX_WRITE(h_chan, H_TSAR, 0x07);
532 if(chan->bprot == BPROT_RHDLC)
534 /* HDLC Frames, transparent mode 0 */
535 HSCX_WRITE(h_chan, H_MODE,
536 HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
540 /* Raw Telephony, extended transparent mode 1 */
541 HSCX_WRITE(h_chan, H_MODE,
542 HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
545 isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
549 /* TSAX: tx time slot */
550 HSCX_WRITE(h_chan, H_TSAX, 0xff);
552 /* TSAR: rx time slot */
553 HSCX_WRITE(h_chan, H_TSAR, 0xff);
555 /* Raw Telephony, extended transparent mode 1 */
556 HSCX_WRITE(h_chan, H_MODE,
557 HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
560 /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */
561 /* always disable RSC and TIN */
563 chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;
568 chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
573 chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
576 /* handle ICA, EXA, and EXB via interrupt mask of channel b */
578 if (h_chan == HSCX_CH_A)
581 HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
583 HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
584 HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
585 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
590 HSCX_B_IMASK &= ~HSCX_MASK_EXB;
592 HSCX_B_IMASK |= HSCX_MASK_EXB;
593 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
596 /* clear spurious interrupts left over */
598 if(h_chan == HSCX_CH_A)
600 HSCX_READ(h_chan, H_EXIR);
601 HSCX_READ(h_chan, H_ISTA);
603 else /* mask ICA, because it must not be cleared by reading ISTA */
605 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
606 HSCX_READ(h_chan, H_EXIR);
607 HSCX_READ(h_chan, H_ISTA);
608 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
612 /*---------------------------------------------------------------------------*
613 * write command to HSCX command register
614 *---------------------------------------------------------------------------*/
616 isic_hscx_cmd(struct l1_softc *sc, int h_chan, unsigned char cmd)
620 while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
628 DBGL1(L1_H_ERR, "isic_hscx_cmd", ("HSCX wait for CEC timeout!\n"));
631 HSCX_WRITE(h_chan, H_CMDR, cmd);
634 /*---------------------------------------------------------------------------*
635 * wait for HSCX transmit FIFO write enable
636 *---------------------------------------------------------------------------*/
638 isic_hscx_waitxfw(struct l1_softc *sc, int h_chan)
643 int timeout = WAITTO;
645 while((!(((HSCX_READ(h_chan, H_STAR)) &
646 (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
654 DBGL1(L1_H_ERR, "isic_hscx_waitxfw", ("HSCX wait for XFW timeout!\n"));
656 else if (timeout != WAITTO)
658 DBGL1(L1_H_XFRERR, "isic_hscx_waitxfw", ("HSCX wait for XFW time: %d uS\n", (WAITTO-timeout)*50));
662 #endif /* NISIC > 0 */