1 /* ISDN4BSD code */
2 /*
3  * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *---------------------------------------------------------------------------
27  *
28  *	i4b - Siemens HSCX chip (B-channel) handling
29  *
30  *---------------------------------------------------------------------------*/
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$MirOS: src/sys/dev/ic/hscx.c,v 1.1.7.1 2005/03/06 16:33:43 tg Exp $");
34 
35 #include <sys/param.h>
36 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
37 #include <sys/ioccom.h>
38 #else
39 #include <sys/ioctl.h>
40 #endif
41 #include <sys/kernel.h>
42 #include <sys/systm.h>
43 #include <sys/mbuf.h>
44 #include <sys/stdarg.h>
45 
46 #ifdef __FreeBSD__
47 #include <machine/clock.h>
48 #include <i386/isa/isa_device.h>
49 #else
50 #ifndef __bsdi__
51 #include <machine/bus.h>
52 #endif
53 #include <sys/device.h>
54 #endif
55 
56 #include <sys/socket.h>
57 #include <net/if.h>
58 
59 #include <sys/timeout.h>
60 
61 #ifdef __FreeBSD__
62 #include <machine/i4b_debug.h>
63 #include <machine/i4b_ioctl.h>
64 #include <machine/i4b_trace.h>
65 #else
66 #include <netisdn/i4b_debug.h>
67 #include <netisdn/i4b_ioctl.h>
68 #include <netisdn/i4b_trace.h>
69 #endif
70 
71 #include <netisdn/i4b_l2.h>
72 #include <netisdn/i4b_l1l2.h>
73 #include <netisdn/i4b_global.h>
74 #include <netisdn/i4b_mbuf.h>
75 
76 #include <dev/ic/isic_l1.h>
77 #include <dev/ic/isac.h>
78 #include <dev/ic/hscx.h>
79 
80 /*---------------------------------------------------------------------------*
81  *	HSCX IRQ Handler
82  *---------------------------------------------------------------------------*/
83 void
isic_hscx_irq(register struct isic_softc * sc,u_char ista,int h_chan,u_char ex_irq)84 isic_hscx_irq(register struct isic_softc *sc, u_char ista, int h_chan, u_char ex_irq)
85 {
86 	register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
87 	u_char exir = 0;
88 	int activity = -1;
89 	u_char cmd = 0;
90 
91 	NDBGL1(L1_H_IRQ, "%#x", ista);
92 
93 	if(ex_irq)
94 	{
95 		/* get channel extended irq reg */
96 
97 		exir = HSCX_READ(h_chan, H_EXIR);
98 
99 		if(exir & HSCX_EXIR_RFO)
100 		{
101 			chan->stat_RFO++;
102 			NDBGL1(L1_H_XFRERR, "ex_irq: receive data overflow");
103 		}
104 
105 		if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
106 		{
107 			chan->stat_XDU++;
108 			NDBGL1(L1_H_XFRERR, "ex_irq: xmit data underrun");
109 			isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);
110 
111 			if (chan->out_mbuf_head != NULL)  /* don't continue to transmit this buffer */
112 			{
113 				i4b_Bfreembuf(chan->out_mbuf_head);
114 				chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
115 			}
116 		}
117 
118 	}
119 
120 	/* rx message end, end of frame */
121 
122 	if(ista & HSCX_ISTA_RME)
123 	{
124 		register int fifo_data_len;
125 		u_char rsta;
126 		int error = 0;
127 
128 		rsta = HSCX_READ(h_chan, H_RSTA);
129 
130 		if((rsta & 0xf0) != 0xa0)
131 		{
132 			if((rsta & HSCX_RSTA_VFR) == 0)
133 			{
134 				chan->stat_VFR++;
135 				cmd |= (HSCX_CMDR_RHR);
136 				NDBGL1(L1_H_XFRERR, "received invalid Frame");
137 				error++;
138 			}
139 
140 			if(rsta & HSCX_RSTA_RDO)
141 			{
142 				chan->stat_RDO++;
143 				NDBGL1(L1_H_XFRERR, "receive data overflow");
144 				error++;
145 			}
146 
147 			if((rsta & HSCX_RSTA_CRC) == 0)
148 			{
149 				chan->stat_CRC++;
150 				cmd |= (HSCX_CMDR_RHR);
151 				NDBGL1(L1_H_XFRERR, "CRC check failed");
152 				error++;
153 			}
154 
155 			if(rsta & HSCX_RSTA_RAB)
156 			{
157 				chan->stat_RAB++;
158 				NDBGL1(L1_H_XFRERR, "Receive message aborted");
159 				error++;
160 			}
161 		}
162 
163 		fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
164 						((sc->sc_bfifolen)-1));
165 
166 		if(fifo_data_len == 0)
167 			fifo_data_len = sc->sc_bfifolen;
168 
169 		/* all error conditions checked, now decide and take action */
170 
171 		if(error == 0)
172 		{
173 			if(chan->in_mbuf == NULL)
174 			{
175 				if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
176 					panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!");
177 				chan->in_cbptr = chan->in_mbuf->m_data;
178 				chan->in_len = 0;
179 			}
180 
181 			fifo_data_len -= 1; /* last byte in fifo is RSTA ! */
182 
183 			if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
184 			{
185 				/* read data from HSCX fifo */
186 
187 				HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);
188 
189 				cmd |= (HSCX_CMDR_RMC);
190 				isic_hscx_cmd(sc, h_chan, cmd);
191 				cmd = 0;
192 
193 		                chan->in_len += fifo_data_len;
194 				chan->rxcount += fifo_data_len;
195 
196 				/* setup mbuf data length */
197 
198 				chan->in_mbuf->m_len = chan->in_len;
199 				chan->in_mbuf->m_pkthdr.len = chan->in_len;
200 
201 				if(sc->sc_trace & TRACE_B_RX)
202 				{
203 					i4b_trace_hdr hdr;
204 					hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
205 					hdr.dir = FROM_NT;
206 					hdr.count = ++sc->sc_trace_bcount;
207 					isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
208 				}
209 
210 				(*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
211 
212 				activity = ACT_RX;
213 
214 				/* mark buffer ptr as unused */
215 
216 				chan->in_mbuf = NULL;
217 				chan->in_cbptr = NULL;
218 				chan->in_len = 0;
219 			}
220 			else
221 			{
222 				NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", chan->in_len, fifo_data_len);
223 				chan->in_cbptr = chan->in_mbuf->m_data;
224 				chan->in_len = 0;
225 				cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC);
226 			}
227 		}
228 		else
229 		{
230 			if (chan->in_mbuf != NULL)
231 			{
232 				i4b_Bfreembuf(chan->in_mbuf);
233 				chan->in_mbuf = NULL;
234 				chan->in_cbptr = NULL;
235 				chan->in_len = 0;
236 			}
237 			cmd |= (HSCX_CMDR_RMC);
238 		}
239 	}
240 
241 	/* rx fifo full */
242 
243 	if(ista & HSCX_ISTA_RPF)
244 	{
245 		if(chan->in_mbuf == NULL)
246 		{
247 			if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
248 				panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!");
249 			chan->in_cbptr = chan->in_mbuf->m_data;
250 			chan->in_len = 0;
251 		}
252 
253 		chan->rxcount += sc->sc_bfifolen;
254 
255 		if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
256 		{
257 			/* read data from HSCX fifo */
258 
259 			HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
260 
261 			chan->in_cbptr += sc->sc_bfifolen;
262 	                chan->in_len += sc->sc_bfifolen;
263 		}
264 		else
265 		{
266 			if(chan->bprot == BPROT_NONE)
267 			{
268 				/* setup mbuf data length */
269 
270 				chan->in_mbuf->m_len = chan->in_len;
271 				chan->in_mbuf->m_pkthdr.len = chan->in_len;
272 
273 				if(sc->sc_trace & TRACE_B_RX)
274 				{
275 					i4b_trace_hdr hdr;
276 					hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
277 					hdr.dir = FROM_NT;
278 					hdr.count = ++sc->sc_trace_bcount;
279 					isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr,chan->in_mbuf->m_len, chan->in_mbuf->m_data);
280 				}
281 
282 				/* silence detection */
283 
284 				if(!(isdn_bchan_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
285 					activity = ACT_RX;
286 
287 				if(!(IF_QFULL(&chan->rx_queue)))
288 				{
289 					IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
290 				}
291 				else
292 				{
293 					i4b_Bfreembuf(chan->in_mbuf);
294 				}
295 
296 				/* signal upper driver that data is available */
297 
298 				(*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
299 
300 				/* alloc new buffer */
301 
302 				if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
303 					panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!");
304 
305 				/* setup new data ptr */
306 
307 				chan->in_cbptr = chan->in_mbuf->m_data;
308 
309 				/* read data from HSCX fifo */
310 
311 				HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
312 
313 				chan->in_cbptr += sc->sc_bfifolen;
314 				chan->in_len = sc->sc_bfifolen;
315 
316 				chan->rxcount += sc->sc_bfifolen;
317 			}
318 			else
319 			{
320 				NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
321 				chan->in_cbptr = chan->in_mbuf->m_data;
322 				chan->in_len = 0;
323 				cmd |= (HSCX_CMDR_RHR);
324 			}
325 		}
326 
327 		/* command to release fifo space */
328 
329 		cmd |= HSCX_CMDR_RMC;
330 	}
331 
332 	/* transmit fifo empty, new data can be written to fifo */
333 
334 	if(ista & HSCX_ISTA_XPR)
335 	{
336 		/*
337 		 * for a description what is going on here, please have
338 		 * a look at isic_bchannel_start() in i4b_bchan.c !
339 		 */
340 
341 		int activity = -1;
342 		int len;
343 		int nextlen;
344 
345 		NDBGL1(L1_H_IRQ, "%s, chan %d - XPR, Tx Fifo Empty!", sc->sc_dev.dv_xname, h_chan);
346 
347 		if(chan->out_mbuf_cur == NULL) 	/* last frame is transmitted */
348 		{
349 			IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
350 
351 			if(chan->out_mbuf_head == NULL)
352 			{
353 				chan->state &= ~HSCX_TX_ACTIVE;
354 				(*chan->l4_driver->bch_tx_queue_empty)(chan->l4_driver_softc);
355 			}
356 			else
357 			{
358 				chan->state |= HSCX_TX_ACTIVE;
359 				chan->out_mbuf_cur = chan->out_mbuf_head;
360 				chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
361 				chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
362 
363 				if(sc->sc_trace & TRACE_B_TX)
364 				{
365 					i4b_trace_hdr hdr;
366 					hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
367 					hdr.dir = FROM_TE;
368 					hdr.count = ++sc->sc_trace_bcount;
369 					isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
370 				}
371 
372 				if(chan->bprot == BPROT_NONE)
373 				{
374 					if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
375 						activity = ACT_TX;
376 				}
377 				else
378 				{
379 					activity = ACT_TX;
380 				}
381 			}
382 		}
383 
384 		len = 0;
385 
386 		while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
387 		{
388 			nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
389 
390 #ifdef NOTDEF
391 			printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
392 				chan->out_mbuf_head,
393 				chan->out_mbuf_cur,
394 				chan->out_mbuf_cur_ptr,
395 				chan->out_mbuf_cur_len,
396 				len,
397 				next_len);
398 #endif
399 
400 			isic_hscx_waitxfw(sc, h_chan);	/* necessary !!! */
401 
402 			HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
403 			cmd |= HSCX_CMDR_XTF;
404 
405 			len += nextlen;
406 			chan->txcount += nextlen;
407 
408 			chan->out_mbuf_cur_ptr += nextlen;
409 			chan->out_mbuf_cur_len -= nextlen;
410 
411 			if(chan->out_mbuf_cur_len == 0)
412 			{
413 				if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
414 				{
415 					chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
416 					chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
417 
418 					if(sc->sc_trace & TRACE_B_TX)
419 					{
420 						i4b_trace_hdr hdr;
421 						hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
422 						hdr.dir = FROM_TE;
423 						hdr.count = ++sc->sc_trace_bcount;
424 						isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
425 					}
426 				}
427 				else
428 				{
429 					if (chan->bprot != BPROT_NONE)
430 						cmd |= HSCX_CMDR_XME;
431 					i4b_Bfreembuf(chan->out_mbuf_head);
432 					chan->out_mbuf_head = NULL;
433 				}
434 
435 			}
436 		}
437 	}
438 
439 	if(cmd)		/* is there a command for the HSCX ? */
440 	{
441 		isic_hscx_cmd(sc, h_chan, cmd);	/* yes, to HSCX */
442 	}
443 
444 	/* call timeout handling routine */
445 
446 	if(activity == ACT_RX || activity == ACT_TX)
447 		(*chan->l4_driver->bch_activity)(chan->l4_driver_softc, activity);
448 }
449 
450 /*---------------------------------------------------------------------------*
451  *	HSCX initialization
452  *
453  *	for telephony: extended transparent mode 1
454  *	for raw hdlc:  transparent mode 0
455  *---------------------------------------------------------------------------*/
456 void
isic_hscx_init(struct isic_softc * sc,int h_chan,int activate)457 isic_hscx_init(struct isic_softc *sc, int h_chan, int activate)
458 {
459 	l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
460 
461 	HSCX_WRITE(h_chan, H_MASK, 0xff);		/* mask irq's */
462 
463 	if(sc->sc_ipac)
464 	{
465 		/* CCR1: Power Up, Clock Mode 5 */
466 		HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU  |	/* power up */
467 			      HSCX_CCR1_CM1);	/* IPAC clock mode 5 */
468 	}
469 	else
470 	{
471 		/* CCR1: Power Up, Clock Mode 5 */
472 		HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU  |	/* power up */
473 			      HSCX_CCR1_CM2 |	/* HSCX clock mode 5 */
474 			      HSCX_CCR1_CM0);
475 	}
476 
477 	/* XAD1: Transmit Address Byte 1 */
478 	HSCX_WRITE(h_chan, H_XAD1, 0xff);
479 
480 	/* XAD2: Transmit Address Byte 2 */
481 	HSCX_WRITE(h_chan, H_XAD2, 0xff);
482 
483 	/* RAH2: Receive Address Byte High Reg. 2 */
484 	HSCX_WRITE(h_chan, H_RAH2, 0xff);
485 
486 	/* XBCH: reset Transmit Byte Count High */
487 	HSCX_WRITE(h_chan, H_XBCH, 0x00);
488 
489 	/* RLCR: reset Receive Length Check Register */
490 	HSCX_WRITE(h_chan, H_RLCR, 0x00);
491 
492 	/* CCR2: set tx/rx clock shift bit 0	*/
493 	/*       disable CTS irq, disable RIE irq*/
494 	HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);
495 
496 	/* XCCR: tx bit count per time slot */
497 	HSCX_WRITE(h_chan, H_XCCR, 0x07);
498 
499 	/* RCCR: rx bit count per time slot */
500 	HSCX_WRITE(h_chan, H_RCCR, 0x07);
501 
502 	if(sc->sc_bustyp == BUS_TYPE_IOM2)
503 	{
504 		switch(h_chan)
505 		{
506 			case HSCX_CH_A:	/* Prepare HSCX channel A */
507 				/* TSAX: tx clock shift bits 1 & 2	*/
508 				/*       tx time slot number		*/
509 		        	HSCX_WRITE(h_chan, H_TSAX, 0x2f);
510 
511 				/* TSAR: rx clock shift bits 1 & 2	*/
512 				/*       rx time slot number		*/
513 				HSCX_WRITE(h_chan, H_TSAR, 0x2f);
514 				break;
515 
516 			case HSCX_CH_B: /* Prepare HSCX channel B */
517 				/* TSAX: tx clock shift bits 1 & 2	*/
518 				/*       tx time slot number		*/
519 				HSCX_WRITE(h_chan, H_TSAX, 0x03);
520 
521 				/* TSAR: rx clock shift bits 1 & 2	*/
522 				/*       rx time slot number		*/
523 				HSCX_WRITE(h_chan, H_TSAR, 0x03);
524 				break;
525 		}
526 	}
527 	else	/* IOM 1 setup */
528 	{
529 		/* TSAX: tx clock shift bits 1 & 2	*/
530 		/*       tx time slot number		*/
531 		HSCX_WRITE(h_chan, H_TSAX, 0x07);
532 
533 		/* TSAR: rx clock shift bits 1 & 2	*/
534 		/*       rx time slot number		*/
535 		HSCX_WRITE(h_chan, H_TSAR, 0x07);
536 	}
537 
538 	if(activate)
539 	{
540 		if(chan->bprot == BPROT_RHDLC)
541 		{
542 		  /* HDLC Frames, transparent mode 0 */
543 		  HSCX_WRITE(h_chan, H_MODE,
544 		     HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
545 		}
546 		else
547 		{
548 		  /* Raw Telephony, extended transparent mode 1 */
549 		  HSCX_WRITE(h_chan, H_MODE,
550 		     HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
551 		}
552 
553 		isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
554 	}
555 	else
556 	{
557 		/* TSAX: tx time slot */
558 		HSCX_WRITE(h_chan, H_TSAX, 0xff);
559 
560 		/* TSAR: rx time slot */
561 		HSCX_WRITE(h_chan, H_TSAR, 0xff);
562 
563 		/* Raw Telephony, extended transparent mode 1 */
564 		HSCX_WRITE(h_chan, H_MODE,
565 		   HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
566 	}
567 
568  	/* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */
569 	/* always disable RSC and TIN */
570 
571 	chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;
572 
573 	if(activate)
574 	{
575 		/* enable */
576 		chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
577 	}
578 	else
579 	{
580 		/* disable */
581 		chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
582 	}
583 
584 	/* handle ICA, EXA, and EXB via interrupt mask of channel b */
585 
586 	if (h_chan == HSCX_CH_A)
587 	{
588 		if (activate)
589 			HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
590 		else
591 			HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
592 		HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
593 		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
594 	}
595 	else
596 	{
597 		if (activate)
598 			HSCX_B_IMASK &= ~HSCX_MASK_EXB;
599 		else
600 			HSCX_B_IMASK |= HSCX_MASK_EXB;
601 		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
602 	}
603 
604 	/* clear spurious interrupts left over */
605 
606 	if(h_chan == HSCX_CH_A)
607 	{
608 		HSCX_READ(h_chan, H_EXIR);
609 		HSCX_READ(h_chan, H_ISTA);
610 	}
611 	else  /* mask ICA, because it must not be cleared by reading ISTA */
612 	{
613 		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
614 		HSCX_READ(h_chan, H_EXIR);
615 		HSCX_READ(h_chan, H_ISTA);
616 		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
617 	}
618 }
619 
620 /*---------------------------------------------------------------------------*
621  *	write command to HSCX command register
622  *---------------------------------------------------------------------------*/
623 void
isic_hscx_cmd(struct isic_softc * sc,int h_chan,unsigned char cmd)624 isic_hscx_cmd(struct isic_softc *sc, int h_chan, unsigned char cmd)
625 {
626 	int timeout = 20;
627 
628 	while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
629 	{
630 		DELAY(10);
631 		timeout--;
632 	}
633 
634 	if(timeout == 0)
635 	{
636 		NDBGL1(L1_H_ERR, "HSCX wait for CEC timeout!");
637 	}
638 
639 	HSCX_WRITE(h_chan, H_CMDR, cmd);
640 }
641 
642 /*---------------------------------------------------------------------------*
643  *	wait for HSCX transmit FIFO write enable
644  *---------------------------------------------------------------------------*/
645 void
isic_hscx_waitxfw(struct isic_softc * sc,int h_chan)646 isic_hscx_waitxfw(struct isic_softc *sc, int h_chan)
647 {
648 #define WAITVAL 50
649 #define WAITTO	200
650 
651 	int timeout = WAITTO;
652 
653 	while((!(((HSCX_READ(h_chan, H_STAR)) &
654 		(HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
655 	{
656 		DELAY(WAITVAL);
657 		timeout--;
658 	}
659 
660 	if(timeout == 0)
661 	{
662 		NDBGL1(L1_H_ERR, "HSCX wait for XFW timeout!");
663 	}
664 	else if (timeout != WAITTO)
665 	{
666 		NDBGL1(L1_H_XFRERR, "HSCX wait for XFW time: %d uS", (WAITTO-timeout)*50);
667 	}
668 }
669 
670