2 * Copyright (c) 1997, 2001 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 * $FreeBSD: src/sys/i4b/layer1/isic/i4b_hscx.c,v 1.7.2.1 2001/08/10 14:08:38 obrien Exp $
31 * $DragonFly: src/sys/net/i4b/layer1/isic/i4b_hscx.c,v 1.2 2003/06/17 04:28:40 dillon Exp $
33 * last edit-date: [Wed Jan 24 09:09:42 2001]
35 *---------------------------------------------------------------------------*/
41 #include <sys/param.h>
42 #include <sys/systm.h>
44 #include <sys/socket.h>
48 #include <machine/i4b_debug.h>
49 #include <machine/i4b_ioctl.h>
50 #include <machine/i4b_trace.h>
52 #include <i4b/layer1/isic/i4b_isic.h>
53 #include <i4b/layer1/isic/i4b_hscx.h>
55 #include <i4b/layer1/i4b_l1.h>
57 #include <i4b/include/i4b_global.h>
58 #include <i4b/include/i4b_mbuf.h>
60 /*---------------------------------------------------------------------------*
62 *---------------------------------------------------------------------------*/
64 isic_hscx_irq(register struct l1_softc *sc, u_char ista, int h_chan, u_char ex_irq)
66 register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
71 NDBGL1(L1_H_IRQ, "%#x", ista);
75 /* get channel extended irq reg */
77 exir = HSCX_READ(h_chan, H_EXIR);
79 if(exir & HSCX_EXIR_RFO)
82 NDBGL1(L1_H_XFRERR, "ex_irq: receive data overflow");
85 if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
88 NDBGL1(L1_H_XFRERR, "ex_irq: xmit data underrun");
89 isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);
91 if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */
93 i4b_Bfreembuf(chan->out_mbuf_head);
94 chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
100 /* rx message end, end of frame */
102 if(ista & HSCX_ISTA_RME)
104 register int fifo_data_len;
108 rsta = HSCX_READ(h_chan, H_RSTA);
110 if((rsta & 0xf0) != 0xa0)
112 if((rsta & HSCX_RSTA_VFR) == 0)
115 cmd |= (HSCX_CMDR_RHR);
116 NDBGL1(L1_H_XFRERR, "received invalid Frame");
120 if(rsta & HSCX_RSTA_RDO)
123 NDBGL1(L1_H_XFRERR, "receive data overflow");
127 if((rsta & HSCX_RSTA_CRC) == 0)
130 cmd |= (HSCX_CMDR_RHR);
131 NDBGL1(L1_H_XFRERR, "CRC check failed");
135 if(rsta & HSCX_RSTA_RAB)
138 NDBGL1(L1_H_XFRERR, "Receive message aborted");
143 fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
144 ((sc->sc_bfifolen)-1));
146 if(fifo_data_len == 0)
147 fifo_data_len = sc->sc_bfifolen;
149 /* all error conditions checked, now decide and take action */
153 if(chan->in_mbuf == NULL)
155 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
156 panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n");
157 chan->in_cbptr = chan->in_mbuf->m_data;
161 fifo_data_len -= 1; /* last byte in fifo is RSTA ! */
163 if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
165 /* read data from HSCX fifo */
167 HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);
169 cmd |= (HSCX_CMDR_RMC);
170 isic_hscx_cmd(sc, h_chan, cmd);
173 chan->in_len += fifo_data_len;
174 chan->rxcount += fifo_data_len;
176 /* setup mbuf data length */
178 chan->in_mbuf->m_len = chan->in_len;
179 chan->in_mbuf->m_pkthdr.len = chan->in_len;
181 if(sc->sc_trace & TRACE_B_RX)
184 hdr.unit = L0ISICUNIT(sc->sc_unit);
185 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
187 hdr.count = ++sc->sc_trace_bcount;
189 i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
192 (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
196 /* mark buffer ptr as unused */
198 chan->in_mbuf = NULL;
199 chan->in_cbptr = NULL;
204 NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", chan->in_len, fifo_data_len);
205 chan->in_cbptr = chan->in_mbuf->m_data;
207 cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC);
212 if (chan->in_mbuf != NULL)
214 i4b_Bfreembuf(chan->in_mbuf);
215 chan->in_mbuf = NULL;
216 chan->in_cbptr = NULL;
219 cmd |= (HSCX_CMDR_RMC);
225 if(ista & HSCX_ISTA_RPF)
227 if(chan->in_mbuf == NULL)
229 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
230 panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n");
231 chan->in_cbptr = chan->in_mbuf->m_data;
235 chan->rxcount += sc->sc_bfifolen;
237 if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
239 /* read data from HSCX fifo */
241 HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
243 chan->in_cbptr += sc->sc_bfifolen;
244 chan->in_len += sc->sc_bfifolen;
248 if(chan->bprot == BPROT_NONE)
250 /* setup mbuf data length */
252 chan->in_mbuf->m_len = chan->in_len;
253 chan->in_mbuf->m_pkthdr.len = chan->in_len;
255 if(sc->sc_trace & TRACE_B_RX)
258 hdr.unit = L0ISICUNIT(sc->sc_unit);
259 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
261 hdr.count = ++sc->sc_trace_bcount;
263 i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
266 /* silence detection */
268 if(!(i4b_l1_bchan_tel_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
271 #if defined (__FreeBSD__) && __FreeBSD__ > 4
272 (void) IF_HANDOFF(&chan->rx_queue, chan->in_mbuf, NULL);
274 if(!(IF_QFULL(&chan->rx_queue)))
276 IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
280 i4b_Bfreembuf(chan->in_mbuf);
283 /* signal upper driver that data is available */
285 (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
287 /* alloc new buffer */
289 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
290 panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n");
292 /* setup new data ptr */
294 chan->in_cbptr = chan->in_mbuf->m_data;
296 /* read data from HSCX fifo */
298 HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
300 chan->in_cbptr += sc->sc_bfifolen;
301 chan->in_len = sc->sc_bfifolen;
303 chan->rxcount += sc->sc_bfifolen;
307 NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
308 chan->in_cbptr = chan->in_mbuf->m_data;
310 cmd |= (HSCX_CMDR_RHR);
314 /* command to release fifo space */
316 cmd |= HSCX_CMDR_RMC;
319 /* transmit fifo empty, new data can be written to fifo */
321 if(ista & HSCX_ISTA_XPR)
324 * for a description what is going on here, please have
325 * a look at isic_bchannel_start() in i4b_bchan.c !
332 NDBGL1(L1_H_IRQ, "unit %d, chan %d - XPR, Tx Fifo Empty!", sc->sc_unit, h_chan);
334 if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */
336 IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
338 if(chan->out_mbuf_head == NULL)
340 chan->state &= ~HSCX_TX_ACTIVE;
341 (*chan->isic_drvr_linktab->bch_tx_queue_empty)(chan->isic_drvr_linktab->unit);
345 chan->state |= HSCX_TX_ACTIVE;
346 chan->out_mbuf_cur = chan->out_mbuf_head;
347 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
348 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
350 if(sc->sc_trace & TRACE_B_TX)
353 hdr.unit = L0ISICUNIT(sc->sc_unit);
354 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
356 hdr.count = ++sc->sc_trace_bcount;
358 i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
361 if(chan->bprot == BPROT_NONE)
363 if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
375 while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
377 nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
380 printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
383 chan->out_mbuf_cur_ptr,
384 chan->out_mbuf_cur_len,
389 isic_hscx_waitxfw(sc, h_chan); /* necessary !!! */
391 HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
392 cmd |= HSCX_CMDR_XTF;
395 chan->txcount += nextlen;
397 chan->out_mbuf_cur_ptr += nextlen;
398 chan->out_mbuf_cur_len -= nextlen;
400 if(chan->out_mbuf_cur_len == 0)
402 if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
404 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
405 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
407 if(sc->sc_trace & TRACE_B_TX)
410 hdr.unit = L0ISICUNIT(sc->sc_unit);
411 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
413 hdr.count = ++sc->sc_trace_bcount;
415 i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
420 if (chan->bprot != BPROT_NONE)
421 cmd |= HSCX_CMDR_XME;
422 i4b_Bfreembuf(chan->out_mbuf_head);
423 chan->out_mbuf_head = NULL;
430 if(cmd) /* is there a command for the HSCX ? */
432 isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */
435 /* call timeout handling routine */
437 if(activity == ACT_RX || activity == ACT_TX)
438 (*chan->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity);
441 /*---------------------------------------------------------------------------*
442 * HSCX initialization
444 * for telephony: extended transparent mode 1
445 * for raw hdlc: transparent mode 0
446 *---------------------------------------------------------------------------*/
448 isic_hscx_init(struct l1_softc *sc, int h_chan, int activate)
450 l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
452 HSCX_WRITE(h_chan, H_MASK, 0xff); /* mask irq's */
456 /* CCR1: Power Up, Clock Mode 5 */
457 HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
458 HSCX_CCR1_CM1); /* IPAC clock mode 5 */
462 /* CCR1: Power Up, Clock Mode 5 */
463 HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
464 HSCX_CCR1_CM2 | /* HSCX clock mode 5 */
468 /* XAD1: Transmit Address Byte 1 */
469 HSCX_WRITE(h_chan, H_XAD1, 0xff);
471 /* XAD2: Transmit Address Byte 2 */
472 HSCX_WRITE(h_chan, H_XAD2, 0xff);
474 /* RAH2: Receive Address Byte High Reg. 2 */
475 HSCX_WRITE(h_chan, H_RAH2, 0xff);
477 /* XBCH: reset Transmit Byte Count High */
478 HSCX_WRITE(h_chan, H_XBCH, 0x00);
480 /* RLCR: reset Receive Length Check Register */
481 HSCX_WRITE(h_chan, H_RLCR, 0x00);
483 /* CCR2: set tx/rx clock shift bit 0 */
484 /* disable CTS irq, disable RIE irq*/
485 HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);
487 /* XCCR: tx bit count per time slot */
488 HSCX_WRITE(h_chan, H_XCCR, 0x07);
490 /* RCCR: rx bit count per time slot */
491 HSCX_WRITE(h_chan, H_RCCR, 0x07);
493 if(sc->sc_bustyp == BUS_TYPE_IOM2)
497 case HSCX_CH_A: /* Prepare HSCX channel A */
498 /* TSAX: tx clock shift bits 1 & 2 */
499 /* tx time slot number */
500 HSCX_WRITE(h_chan, H_TSAX, 0x2f);
502 /* TSAR: rx clock shift bits 1 & 2 */
503 /* rx time slot number */
504 HSCX_WRITE(h_chan, H_TSAR, 0x2f);
507 case HSCX_CH_B: /* Prepare HSCX channel B */
508 /* TSAX: tx clock shift bits 1 & 2 */
509 /* tx time slot number */
510 HSCX_WRITE(h_chan, H_TSAX, 0x03);
512 /* TSAR: rx clock shift bits 1 & 2 */
513 /* rx time slot number */
514 HSCX_WRITE(h_chan, H_TSAR, 0x03);
518 else /* IOM 1 setup */
520 /* TSAX: tx clock shift bits 1 & 2 */
521 /* tx time slot number */
522 HSCX_WRITE(h_chan, H_TSAX, 0x07);
524 /* TSAR: rx clock shift bits 1 & 2 */
525 /* rx time slot number */
526 HSCX_WRITE(h_chan, H_TSAR, 0x07);
531 if(chan->bprot == BPROT_RHDLC)
533 /* HDLC Frames, transparent mode 0 */
534 HSCX_WRITE(h_chan, H_MODE,
535 HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
539 /* Raw Telephony, extended transparent mode 1 */
540 HSCX_WRITE(h_chan, H_MODE,
541 HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
544 isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
546 isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR);
551 /* TSAX: tx time slot */
552 HSCX_WRITE(h_chan, H_TSAX, 0xff);
554 /* TSAR: rx time slot */
555 HSCX_WRITE(h_chan, H_TSAR, 0xff);
557 /* Raw Telephony, extended transparent mode 1 */
558 HSCX_WRITE(h_chan, H_MODE,
559 HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
562 /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */
563 /* always disable RSC and TIN */
565 chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;
570 chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
575 chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
578 /* handle ICA, EXA, and EXB via interrupt mask of channel b */
580 if (h_chan == HSCX_CH_A)
583 HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
585 HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
586 HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
587 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
592 HSCX_B_IMASK &= ~HSCX_MASK_EXB;
594 HSCX_B_IMASK |= HSCX_MASK_EXB;
595 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
598 /* clear spurious interrupts left over */
600 if(h_chan == HSCX_CH_A)
602 HSCX_READ(h_chan, H_EXIR);
603 HSCX_READ(h_chan, H_ISTA);
605 else /* mask ICA, because it must not be cleared by reading ISTA */
607 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
608 HSCX_READ(h_chan, H_EXIR);
609 HSCX_READ(h_chan, H_ISTA);
610 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
614 /*---------------------------------------------------------------------------*
615 * write command to HSCX command register
616 *---------------------------------------------------------------------------*/
618 isic_hscx_cmd(struct l1_softc *sc, int h_chan, unsigned char cmd)
622 while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
630 NDBGL1(L1_H_ERR, "HSCX wait for CEC timeout!");
633 HSCX_WRITE(h_chan, H_CMDR, cmd);
636 /*---------------------------------------------------------------------------*
637 * wait for HSCX transmit FIFO write enable
638 *---------------------------------------------------------------------------*/
640 isic_hscx_waitxfw(struct l1_softc *sc, int h_chan)
645 int timeout = WAITTO;
647 while((!(((HSCX_READ(h_chan, H_STAR)) &
648 (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
656 NDBGL1(L1_H_ERR, "HSCX wait for XFW timeout!");
658 else if (timeout != WAITTO)
660 NDBGL1(L1_H_XFRERR, "HSCX wait for XFW time: %d uS", (WAITTO-timeout)*50);
664 #endif /* NISIC > 0 */