1 /* ISDN4BSD code */
2 /*	$MirOS: src/sys/dev/ic/iavc.c,v 1.1.7.1 2005/03/06 16:33:43 tg Exp $	*/
3 /*	$NetBSD: iavc.c,v 1.1 2003/09/25 15:53:26 pooka Exp $	*/
4 
5 /*
6  * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	The AVM ISDN controllers' card specific support routines.
30  *
31  * $FreeBSD: src/sys/i4b/capi/iavc/iavc_card.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
32  */
33 
34 #include <sys/cdefs.h>
35 
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39 #include <sys/mbuf.h>
40 #include <sys/socket.h>
41 #include <sys/device.h>
42 #include <sys/timeout.h>
43 #include <sys/reboot.h>
44 #include <net/if.h>
45 
46 #include <machine/bus.h>
47 
48 #include <netisdn/i4b_debug.h>
49 #include <netisdn/i4b_ioctl.h>
50 #include <netisdn/i4b_trace.h>
51 #include <netisdn/i4b_global.h>
52 #include <netisdn/i4b_l3l4.h>
53 #include <netisdn/i4b_mbuf.h>
54 #include <netisdn/i4b_capi.h>
55 #include <netisdn/i4b_capi_msgs.h>
56 
57 #include <dev/ic/iavcvar.h>
58 #include <dev/ic/iavcreg.h>
59 
60 /*
61 //  AVM B1 (active BRI, PIO mode)
62 */
63 
64 int
iavc_b1_detect(iavc_softc_t * sc)65 iavc_b1_detect(iavc_softc_t *sc)
66 {
67     if ((iavc_read_port(sc, B1_INSTAT) & 0xfc) ||
68 	(iavc_read_port(sc, B1_OUTSTAT) & 0xfc))
69 	return (1);
70 
71     b1io_outp(sc, B1_INSTAT, 0x02);
72     b1io_outp(sc, B1_OUTSTAT, 0x02);
73     if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) != 2 ||
74 	(iavc_read_port(sc, B1_OUTSTAT) & 0xfe) != 2)
75 	return (2);
76 
77     b1io_outp(sc, B1_INSTAT, 0x00);
78     b1io_outp(sc, B1_OUTSTAT, 0x00);
79     if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) ||
80 	(iavc_read_port(sc, B1_OUTSTAT) & 0xfe))
81 	return (3);
82 
83     return (0); /* found */
84 }
85 
86 void
iavc_b1_disable_irq(iavc_softc_t * sc)87 iavc_b1_disable_irq(iavc_softc_t *sc)
88 {
89     b1io_outp(sc, B1_INSTAT, 0x00);
90 }
91 
92 void
iavc_b1_reset(iavc_softc_t * sc)93 iavc_b1_reset(iavc_softc_t *sc)
94 {
95     b1io_outp(sc, B1_RESET, 0);
96     DELAY(55*2*1000);
97 
98     b1io_outp(sc, B1_RESET, 1);
99     DELAY(55*2*1000);
100 
101     b1io_outp(sc, B1_RESET, 0);
102     DELAY(55*2*1000);
103 }
104 
105 /*
106 //  Newer PCI-based B1's, and T1's, supports DMA
107 */
108 
109 int
iavc_b1dma_detect(iavc_softc_t * sc)110 iavc_b1dma_detect(iavc_softc_t *sc)
111 {
112     AMCC_WRITE(sc, AMCC_MCSR, 0);
113     DELAY(10*1000);
114     AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
115     DELAY(10*1000);
116     AMCC_WRITE(sc, AMCC_MCSR, 0);
117     DELAY(42*1000);
118 
119     AMCC_WRITE(sc, AMCC_RXLEN, 0);
120     AMCC_WRITE(sc, AMCC_TXLEN, 0);
121     sc->sc_csr = 0;
122     AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
123 
124     if (AMCC_READ(sc, AMCC_INTCSR) != 0)
125 	return 1;
126 
127     AMCC_WRITE(sc, AMCC_RXPTR, 0xffffffff);
128     AMCC_WRITE(sc, AMCC_TXPTR, 0xffffffff);
129     if ((AMCC_READ(sc, AMCC_RXPTR) != 0xfffffffc) ||
130 	(AMCC_READ(sc, AMCC_TXPTR) != 0xfffffffc))
131 	return 2;
132 
133     AMCC_WRITE(sc, AMCC_RXPTR, 0);
134     AMCC_WRITE(sc, AMCC_TXPTR, 0);
135     if ((AMCC_READ(sc, AMCC_RXPTR) != 0) ||
136 	(AMCC_READ(sc, AMCC_TXPTR) != 0))
137 	return 3;
138 
139     iavc_write_port(sc, 0x10, 0x00);
140     iavc_write_port(sc, 0x07, 0x00);
141 
142     iavc_write_port(sc, 0x02, 0x02);
143     iavc_write_port(sc, 0x03, 0x02);
144 
145     if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x02) ||
146 	(iavc_read_port(sc, 0x03) != 0x03))
147 	return 4;
148 
149     iavc_write_port(sc, 0x02, 0x00);
150     iavc_write_port(sc, 0x03, 0x00);
151 
152     if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x00) ||
153 	(iavc_read_port(sc, 0x03) != 0x01))
154 	return 5;
155 
156     return (0); /* found */
157 }
158 
159 void
iavc_b1dma_reset(iavc_softc_t * sc)160 iavc_b1dma_reset(iavc_softc_t *sc)
161 {
162     int s = splnet();
163 
164     sc->sc_csr = 0;
165     AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
166     AMCC_WRITE(sc, AMCC_MCSR, 0);
167     AMCC_WRITE(sc, AMCC_RXLEN, 0);
168     AMCC_WRITE(sc, AMCC_TXLEN, 0);
169 
170     iavc_write_port(sc, 0x10, 0x00); /* XXX magic numbers from */
171     iavc_write_port(sc, 0x07, 0x00); /* XXX the linux driver */
172 
173     splx(s);
174 
175     AMCC_WRITE(sc, AMCC_MCSR, 0);
176     DELAY(10 * 1000);
177     AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
178     DELAY(10 * 1000);
179     AMCC_WRITE(sc, AMCC_MCSR, 0);
180     DELAY(42 * 1000);
181 }
182 
183 /*
184 //  AVM T1 (active PRI)
185 */
186 
187 #define b1dma_tx_empty(sc) (b1io_read_reg((sc), T1_OUTSTAT) & 1)
188 #define b1dma_rx_full(sc) (b1io_read_reg((sc), T1_INSTAT) & 1)
189 
b1dma_tolink(iavc_softc_t * sc,void * buf,int len)190 static int b1dma_tolink(iavc_softc_t *sc, void *buf, int len)
191 {
192     volatile int spin;
193     char *s = (char*) buf;
194     while (len--) {
195 	spin = 0;
196 	while (!b1dma_tx_empty(sc) && spin < 100000)
197 	    spin++;
198 	if (!b1dma_tx_empty(sc))
199 	    return -1;
200 	t1io_outp(sc, 1, *s++);
201     }
202     return 0;
203 }
204 
b1dma_fromlink(iavc_softc_t * sc,void * buf,int len)205 static int b1dma_fromlink(iavc_softc_t *sc, void *buf, int len)
206 {
207     volatile int spin;
208     char *s = (char*) buf;
209     while (len--) {
210 	spin = 0;
211 	while (!b1dma_rx_full(sc) && spin < 100000)
212 	    spin++;
213 	if (!b1dma_rx_full(sc))
214 	    return -1;
215 	*s++ = t1io_inp(sc, 0);
216     }
217     return 0;
218 }
219 
WriteReg(iavc_softc_t * sc,u_int32_t reg,u_int8_t val)220 static int WriteReg(iavc_softc_t *sc, u_int32_t reg, u_int8_t val)
221 {
222     u_int8_t cmd = 0;
223     if (b1dma_tolink(sc, &cmd, 1) == 0 &&
224 	b1dma_tolink(sc, &reg, 4) == 0) {
225 	u_int32_t tmp = val;
226 	return b1dma_tolink(sc, &tmp, 4);
227     }
228     return -1;
229 }
230 
ReadReg(iavc_softc_t * sc,u_int32_t reg)231 static u_int8_t ReadReg(iavc_softc_t *sc, u_int32_t reg)
232 {
233     u_int8_t cmd = 1;
234     if (b1dma_tolink(sc, &cmd, 1) == 0 &&
235 	b1dma_tolink(sc, &reg, 4) == 0) {
236 	u_int32_t tmp;
237 	if (b1dma_fromlink(sc, &tmp, 4) == 0)
238 	    return (u_int8_t) tmp;
239     }
240     return 0xff;
241 }
242 
243 int
iavc_t1_detect(iavc_softc_t * sc)244 iavc_t1_detect(iavc_softc_t *sc)
245 {
246     int ret = iavc_b1dma_detect(sc);
247     if (ret) return ret;
248 
249     if ((WriteReg(sc, 0x80001000, 0x11) != 0) ||
250 	(WriteReg(sc, 0x80101000, 0x22) != 0) ||
251 	(WriteReg(sc, 0x80201000, 0x33) != 0) ||
252 	(WriteReg(sc, 0x80301000, 0x44) != 0))
253 	return 6;
254 
255     if ((ReadReg(sc, 0x80001000) != 0x11) ||
256 	(ReadReg(sc, 0x80101000) != 0x22) ||
257 	(ReadReg(sc, 0x80201000) != 0x33) ||
258 	(ReadReg(sc, 0x80301000) != 0x44))
259 	return 7;
260 
261     if ((WriteReg(sc, 0x80001000, 0x55) != 0) ||
262 	(WriteReg(sc, 0x80101000, 0x66) != 0) ||
263 	(WriteReg(sc, 0x80201000, 0x77) != 0) ||
264 	(WriteReg(sc, 0x80301000, 0x88) != 0))
265 	return 8;
266 
267     if ((ReadReg(sc, 0x80001000) != 0x55) ||
268 	(ReadReg(sc, 0x80101000) != 0x66) ||
269 	(ReadReg(sc, 0x80201000) != 0x77) ||
270 	(ReadReg(sc, 0x80301000) != 0x88))
271 	return 9;
272 
273     return 0; /* found */
274 }
275 
276 void
iavc_t1_disable_irq(iavc_softc_t * sc)277 iavc_t1_disable_irq(iavc_softc_t *sc)
278 {
279     iavc_write_port(sc, T1_IRQMASTER, 0x00);
280 }
281 
282 void
iavc_t1_reset(iavc_softc_t * sc)283 iavc_t1_reset(iavc_softc_t *sc)
284 {
285     iavc_b1_reset(sc);
286     iavc_write_port(sc, B1_INSTAT, 0x00);
287     iavc_write_port(sc, B1_OUTSTAT, 0x00);
288     iavc_write_port(sc, T1_IRQMASTER, 0x00);
289     iavc_write_port(sc, T1_RESETBOARD, 0x0f);
290 }
291 
292 /* Forward declarations of local subroutines... */
293 
294 static int iavc_send_init(iavc_softc_t *);
295 
296 static void iavc_handle_rx(iavc_softc_t *);
297 static void iavc_start_tx(iavc_softc_t *);
298 
299 static uint32_t iavc_tx_capimsg(iavc_softc_t *, struct mbuf *);
300 static uint32_t iavc_tx_ctrlmsg(iavc_softc_t *, struct mbuf *);
301 
302 /*
303 //  Callbacks from the upper (capi) layer:
304 //  --------------------------------------
305 //
306 //  iavc_load
307 //      Resets the board and loads the firmware, then initiates
308 //      board startup.
309 //
310 //  iavc_register
311 //      Registers a CAPI application id.
312 //
313 //  iavc_release
314 //      Releases a CAPI application id.
315 //
316 //  iavc_send
317 //      Sends a capi message.
318 */
319 
iavc_load(capi_softc_t * capi_sc,int len,u_int8_t * cp)320 int iavc_load(capi_softc_t *capi_sc, int len, u_int8_t *cp)
321 {
322     iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
323     u_int8_t val;
324 
325     printf("%s: reset card ....\n", sc->sc_dev.dv_xname);
326 
327     if (sc->sc_dma)
328 	iavc_b1dma_reset(sc);	/* PCI cards */
329     else if (sc->sc_t1)
330 	iavc_t1_reset(sc);		/* ISA attachment T1 */
331     else
332 	iavc_b1_reset(sc);		/* ISA attachment B1 */
333 
334     DELAY(1000);
335 
336     printf("%s: start loading %d bytes firmware\n",
337       sc->sc_dev.dv_xname, len);
338 
339     while (len && b1io_save_put_byte(sc, *cp++) == 0)
340 	len--;
341 
342     if (len) {
343 	printf("%s: loading failed, can't write to card, len = %d\n",
344 	    sc->sc_dev.dv_xname, len);
345 	return (EIO);
346     }
347 
348     printf("%s: firmware loaded, wait for ACK\n", sc->sc_dev.dv_xname);
349 
350     if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
351 	    iavc_put_byte(sc, SEND_POLL);
352     else
353 	    iavc_put_byte(sc, SEND_POLLACK);
354 
355     for (len = 0; len < 1000 && !iavc_rx_full(sc); len++)
356 	DELAY(100);
357 
358     if (!iavc_rx_full(sc)) {
359 	printf("%s: loading failed, no ack\n", sc->sc_dev.dv_xname);
360 	return (EIO);
361     }
362 
363     val = iavc_get_byte(sc);
364 
365     if ((sc->sc_dma && val != RECEIVE_POLLDWORD) ||
366       (!sc->sc_dma && val != RECEIVE_POLL)) {
367 	printf("%s: loading failed, bad ack = %02x\n",
368 	  sc->sc_dev.dv_xname, val);
369 	return (EIO);
370     }
371 
372     printf("%s: got ACK = 0x%02x\n", sc->sc_dev.dv_xname, val);
373 
374     /* Start the DMA engine */
375     if (sc->sc_dma) {
376 	int s;
377 
378 	s = splnet();
379 
380 	sc->sc_csr = AVM_FLAG;
381 	AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
382 	AMCC_WRITE(sc, AMCC_MCSR, (EN_A2P_TRANSFERS|EN_P2A_TRANSFERS|
383 				   A2P_HI_PRIORITY|P2A_HI_PRIORITY|
384 				   RESET_A2P_FLAGS|RESET_P2A_FLAGS));
385 
386 	iavc_write_port(sc, 0x07, 0x30); /* XXX magic numbers from */
387 	iavc_write_port(sc, 0x10, 0xf0); /* XXX the linux driver */
388 
389 	bus_dmamap_sync(sc->dmat, sc->rx_map, 0, sc->rx_map->dm_mapsize,
390 	  BUS_DMASYNC_PREREAD);
391 
392 	sc->sc_recv1 = 0;
393 	AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr);
394 	AMCC_WRITE(sc, AMCC_RXLEN, 4);
395 	sc->sc_csr |= EN_RX_TC_INT|EN_TX_TC_INT;
396 	AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
397 
398 	splx(s);
399     }
400 
401 #ifdef notyet
402     /* good happy place */
403     if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
404 	b1isa_setup_irq(sc);
405 #endif
406 
407     iavc_send_init(sc);
408 
409     return 0;
410 }
411 
iavc_register(capi_softc_t * capi_sc,int applid,int nchan)412 int iavc_register(capi_softc_t *capi_sc, int applid, int nchan)
413 {
414     iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
415     struct mbuf *m = i4b_Dgetmbuf(23);
416     u_int8_t *p;
417 
418     if (!m) {
419 	printf("iavc%d: can't get memory\n", sc->sc_unit);
420 	return (ENOMEM);
421     }
422 
423     /*
424      * byte  0x12 = SEND_REGISTER
425      * dword ApplId
426      * dword NumMessages
427      * dword NumB3Connections 0..nbch
428      * dword NumB3Blocks
429      * dword B3Size
430      */
431 
432     p = amcc_put_byte(mtod(m, u_int8_t*), 0);
433     p = amcc_put_byte(p, 0);
434     p = amcc_put_byte(p, SEND_REGISTER);
435     p = amcc_put_word(p, applid);
436 #if 0
437     p = amcc_put_word(p, 1024 + (nchan + 1));
438 #else
439     p = amcc_put_word(p, 1024 * (nchan + 1));
440 #endif
441     p = amcc_put_word(p, nchan);
442     p = amcc_put_word(p, 8);
443     p = amcc_put_word(p, 2048);
444 
445     IF_ENQUEUE(&sc->sc_txq, m);
446 
447     iavc_start_tx(sc);
448 
449     return 0;
450 }
451 
iavc_release(capi_softc_t * capi_sc,int applid)452 int iavc_release(capi_softc_t *capi_sc, int applid)
453 {
454     iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
455     struct mbuf *m = i4b_Dgetmbuf(7);
456     u_int8_t *p;
457 
458     if (!m) {
459 	printf("%s: can't get memory\n", sc->sc_dev.dv_xname);
460 	return (ENOMEM);
461     }
462 
463     /*
464      * byte  0x14 = SEND_RELEASE
465      * dword ApplId
466      */
467 
468     p = amcc_put_byte(mtod(m, u_int8_t*), 0);
469     p = amcc_put_byte(p, 0);
470     p = amcc_put_byte(p, SEND_RELEASE);
471     p = amcc_put_word(p, applid);
472 
473     IF_ENQUEUE(&sc->sc_txq, m);
474 
475     iavc_start_tx(sc);
476     return 0;
477 }
478 
iavc_send(capi_softc_t * capi_sc,struct mbuf * m)479 int iavc_send(capi_softc_t *capi_sc, struct mbuf *m)
480 {
481     iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
482 
483     if (sc->sc_state != IAVC_UP) {
484 	printf("%s: attempt to send before device up\n", sc->sc_dev.dv_xname);
485 
486 	if (m->m_next) i4b_Bfreembuf(m->m_next);
487 	i4b_Dfreembuf(m);
488 
489 	return (ENXIO);
490     }
491 
492     if (IF_QFULL(&sc->sc_txq)) {
493 	IF_DROP(&sc->sc_txq);
494 
495 	printf("%s: tx overflow, message dropped\n", sc->sc_dev.dv_xname);
496 
497 	if (m->m_next) i4b_Bfreembuf(m->m_next);
498 	i4b_Dfreembuf(m);
499 
500     } else {
501 	IF_ENQUEUE(&sc->sc_txq, m);
502 
503 	iavc_start_tx(sc);
504     }
505 
506     return 0;
507 }
508 
509 /*
510 //  Functions called by ourself during the initialization sequence:
511 //  ---------------------------------------------------------------
512 //
513 //  iavc_send_init
514 //      Sends the system initialization message to a newly loaded
515 //      board, and sets state to INIT.
516 */
517 
iavc_send_init(iavc_softc_t * sc)518 static int iavc_send_init(iavc_softc_t *sc)
519 {
520     struct mbuf *m = i4b_Dgetmbuf(15);
521     u_int8_t *p;
522     int s;
523 
524     if (!m) {
525 	printf("%s: can't get memory\n", sc->sc_dev.dv_xname);
526 	return (ENOMEM);
527     }
528 
529     /*
530      * byte  0x11 = SEND_INIT
531      * dword NumApplications
532      * dword NumNCCIs
533      * dword BoardNumber
534      */
535 
536     p = amcc_put_byte(mtod(m, u_int8_t*), 0);
537     p = amcc_put_byte(p, 0);
538     p = amcc_put_byte(p, SEND_INIT);
539     p = amcc_put_word(p, 1); /* XXX MaxAppl XXX */
540     p = amcc_put_word(p, sc->sc_capi.sc_nbch);
541     p = amcc_put_word(p, sc->sc_unit);
542 
543     s = splnet();
544     IF_ENQUEUE(&sc->sc_txq, m);
545 
546     iavc_start_tx(sc);
547 
548     sc->sc_state = IAVC_INIT;
549     splx(s);
550     return 0;
551 }
552 
553 /*
554 //  Functions called during normal operation:
555 //  -----------------------------------------
556 //
557 //  iavc_receive_init
558 //      Reads the initialization reply and calls capi_ll_control().
559 //
560 //  iavc_receive_new_ncci
561 //      Reads a new NCCI notification and calls capi_ll_control().
562 //
563 //  iavc_receive_free_ncci
564 //      Reads a freed NCCI notification and calls capi_ll_control().
565 //
566 //  iavc_receive_task_ready
567 //      Reads a task ready message -- which should not occur XXX.
568 //
569 //  iavc_receive_debugmsg
570 //      Reads a debug message -- which should not occur XXX.
571 //
572 //  iavc_receive_start
573 //      Reads a START TRANSMIT message and unblocks device.
574 //
575 //  iavc_receive_stop
576 //      Reads a STOP TRANSMIT message and blocks device.
577 //
578 //  iavc_receive
579 //      Reads an incoming message and calls capi_ll_receive().
580 */
581 
iavc_receive_init(iavc_softc_t * sc,u_int8_t * dmabuf)582 static int iavc_receive_init(iavc_softc_t *sc, u_int8_t *dmabuf)
583 {
584     u_int32_t Length;
585     u_int8_t *p;
586     u_int8_t *cardtype, *serial, *profile, *version, *caps, *prot;
587 
588     if (sc->sc_dma) {
589 	p = amcc_get_word(dmabuf, &Length);
590     } else {
591 	Length = iavc_get_slice(sc, sc->sc_recvbuf);
592 	p = sc->sc_recvbuf;
593     }
594 
595 #if 0
596     {
597 	int len = 0;
598 	printf("%s: rx_init: ", sc->sc_dev.dv_xname);
599 	    while (len < Length) {
600 		printf(" %02x", p[len]);
601 		if (len && (len % 16) == 0) printf("\n");
602 		len++;
603 	    }
604 	    if (len % 16) printf("\n");
605     }
606 #endif
607 
608     version = (p + 1);
609     p += (*p + 1); /* driver version */
610     cardtype = (p + 1);
611     p += (*p + 1); /* card type */
612     p += (*p + 1); /* hardware ID */
613     serial = (p + 1);
614     p += (*p + 1); /* serial number */
615     caps = (p + 1);
616     p += (*p + 1); /* supported options */
617     prot = (p + 1);
618     p += (*p + 1); /* supported protocols */
619     profile = (p + 1);
620 
621     if (cardtype && serial && profile) {
622 	int nbch = ((profile[3]<<8) | profile[2]);
623 
624 	printf("%s: AVM %s, s/n %s, %d chans, f/w rev %s, prot %s\n",
625 		sc->sc_dev.dv_xname, cardtype, serial, nbch, version, prot);
626 	printf("%s: %s\n", sc->sc_dev.dv_xname, caps);
627 
628         capi_ll_control(&sc->sc_capi, CAPI_CTRL_PROFILE, (int) profile);
629 
630     } else {
631 	printf("%s: no profile data in info response?\n", sc->sc_dev.dv_xname);
632     }
633 
634     sc->sc_blocked = 1; /* controller will send START when ready */
635     return 0;
636 }
637 
iavc_receive_start(iavc_softc_t * sc,u_int8_t * dmabuf)638 static int iavc_receive_start(iavc_softc_t *sc, u_int8_t *dmabuf)
639 {
640     struct mbuf *m = i4b_Dgetmbuf(3);
641     u_int8_t *p;
642 
643     if (sc->sc_blocked && sc->sc_state == IAVC_UP)
644 	printf("%s: receive_start\n", sc->sc_dev.dv_xname);
645 
646     if (!m) {
647 	printf("%s: can't get memory\n", sc->sc_dev.dv_xname);
648 	return (ENOMEM);
649     }
650 
651     /*
652      * byte  0x73 = SEND_POLLACK
653      */
654 
655     p = amcc_put_byte(mtod(m, u_int8_t*), 0);
656     p = amcc_put_byte(p, 0);
657     p = amcc_put_byte(p, SEND_POLLACK);
658 
659     IF_PREPEND(&sc->sc_txq, m);
660 
661     NDBGL4(L4_IAVCDBG, "%s: blocked = %d, state = %d",
662       sc->sc_dev.dv_xname, sc->sc_blocked, sc->sc_state);
663 
664     sc->sc_blocked = 0;
665     iavc_start_tx(sc);
666 
667     /* If this was our first START, register our readiness */
668     if (sc->sc_state != IAVC_UP) {
669 	sc->sc_state = IAVC_UP;
670 	capi_ll_control(&sc->sc_capi, CAPI_CTRL_READY, 1);
671     }
672 
673     return 0;
674 }
675 
iavc_receive_stop(iavc_softc_t * sc,u_int8_t * dmabuf)676 static int iavc_receive_stop(iavc_softc_t *sc, u_int8_t *dmabuf)
677 {
678     printf("%s: receive_stop\n", sc->sc_dev.dv_xname);
679     sc->sc_blocked = 1;
680     return 0;
681 }
682 
iavc_receive_new_ncci(iavc_softc_t * sc,u_int8_t * dmabuf)683 static int iavc_receive_new_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
684 {
685     u_int32_t ApplId, NCCI, WindowSize;
686 
687     if (sc->sc_dma) {
688 	dmabuf = amcc_get_word(dmabuf, &ApplId);
689 	dmabuf = amcc_get_word(dmabuf, &NCCI);
690 	dmabuf = amcc_get_word(dmabuf, &WindowSize);
691     } else {
692 	ApplId = iavc_get_word(sc);
693 	NCCI   = iavc_get_word(sc);
694 	WindowSize = iavc_get_word(sc);
695     }
696 
697     capi_ll_control(&sc->sc_capi, CAPI_CTRL_NEW_NCCI, NCCI);
698     return 0;
699 }
700 
iavc_receive_free_ncci(iavc_softc_t * sc,u_int8_t * dmabuf)701 static int iavc_receive_free_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
702 {
703     u_int32_t ApplId, NCCI;
704 
705     if (sc->sc_dma) {
706 	dmabuf = amcc_get_word(dmabuf, &ApplId);
707 	dmabuf = amcc_get_word(dmabuf, &NCCI);
708     } else {
709 	ApplId = iavc_get_word(sc);
710 	NCCI   = iavc_get_word(sc);
711     }
712 
713     capi_ll_control(&sc->sc_capi, CAPI_CTRL_FREE_NCCI, NCCI);
714     return 0;
715 }
716 
iavc_receive_task_ready(iavc_softc_t * sc,u_int8_t * dmabuf)717 static int iavc_receive_task_ready(iavc_softc_t *sc, u_int8_t *dmabuf)
718 {
719     u_int32_t TaskId, Length;
720     u_int8_t *p;
721     printf("%s: receive_task_ready\n", sc->sc_dev.dv_xname);
722 
723     if (sc->sc_dma) {
724 	p = amcc_get_word(dmabuf, &TaskId);
725 	p = amcc_get_word(p, &Length);
726     } else {
727 	TaskId = iavc_get_word(sc);
728 	Length = iavc_get_slice(sc, sc->sc_recvbuf);
729 	p = sc->sc_recvbuf;
730     }
731 
732     /* XXX could show the message if trace enabled? XXX */
733     return 0;
734 }
735 
iavc_receive_debugmsg(iavc_softc_t * sc,u_int8_t * dmabuf)736 static int iavc_receive_debugmsg(iavc_softc_t *sc, u_int8_t *dmabuf)
737 {
738     u_int32_t Length;
739     u_int8_t *p;
740     printf("%s: receive_debugmsg\n", sc->sc_dev.dv_xname);
741 
742     if (sc->sc_dma) {
743 	p = amcc_get_word(dmabuf, &Length);
744     } else {
745 	Length = iavc_get_slice(sc, sc->sc_recvbuf);
746 	p = sc->sc_recvbuf;
747     }
748 
749     /* XXX could show the message if trace enabled? XXX */
750     return 0;
751 }
752 
iavc_receive(iavc_softc_t * sc,u_int8_t * dmabuf,int b3data)753 static int iavc_receive(iavc_softc_t *sc, u_int8_t *dmabuf, int b3data)
754 {
755     struct mbuf *m;
756     u_int32_t ApplId, Length;
757 
758     /*
759      * byte  0x21 = RECEIVE_MESSAGE
760      * dword ApplId
761      * dword length
762      * ...   CAPI msg
763      *
764      * --or--
765      *
766      * byte  0x22 = RECEIVE_DATA_B3_IND
767      * dword ApplId
768      * dword length
769      * ...   CAPI msg
770      * dword datalen
771      * ...   B3 data
772      */
773 
774     if (sc->sc_dma) {
775 	dmabuf = amcc_get_word(dmabuf, &ApplId);
776 	dmabuf = amcc_get_word(dmabuf, &Length);
777     } else {
778 	ApplId = iavc_get_word(sc);
779 	Length = iavc_get_slice(sc, sc->sc_recvbuf);
780 	dmabuf = sc->sc_recvbuf;
781     }
782 
783     m = i4b_Dgetmbuf(Length);
784     if (!m) {
785 	printf("%s: can't get memory for receive\n", sc->sc_dev.dv_xname);
786 	return (ENOMEM);
787     }
788 
789     memcpy(mtod(m, u_int8_t*), dmabuf, Length);
790 
791 #if 0
792 	{
793 	    u_int8_t *p = mtod(m, u_int8_t*);
794 	    int len = 0;
795 	    printf("%s: applid=%d, len=%d\n", sc->sc_dev.dv_xname,
796 	      ApplId, Length);
797 	    while (len < m->m_len) {
798 		printf(" %02x", p[len]);
799 		if (len && (len % 16) == 0) printf("\n");
800 		len++;
801 	    }
802 	    if (len % 16) printf("\n");
803 	}
804 #endif
805 
806     if (b3data) {
807 	if (sc->sc_dma) {
808 	    dmabuf = amcc_get_word(dmabuf + Length, &Length);
809 	} else {
810 	    Length = iavc_get_slice(sc, sc->sc_recvbuf);
811 	    dmabuf = sc->sc_recvbuf;
812 	}
813 
814 	m->m_next = i4b_Bgetmbuf(Length);
815 	if (!m->m_next) {
816 	    printf("%s: can't get memory for receive\n", sc->sc_dev.dv_xname);
817 	    i4b_Dfreembuf(m);
818 	    return (ENOMEM);
819 	}
820 
821 	memcpy(mtod(m->m_next, u_int8_t*), dmabuf, Length);
822     }
823 
824     capi_ll_receive(&sc->sc_capi, m);
825     return 0;
826 }
827 
828 /*
829 //  iavc_handle_intr
830 //      Checks device interrupt status and calls iavc_handle_{rx,tx}()
831 //      as necessary.
832 //
833 //  iavc_handle_rx
834 //      Reads in the command byte and calls the subroutines above.
835 //
836 //  iavc_start_tx
837 //      Initiates DMA on the next queued message if possible.
838 */
839 
iavc_handle_intr(iavc_softc_t * sc)840 int iavc_handle_intr(iavc_softc_t *sc)
841 {
842     u_int32_t status;
843     u_int32_t newcsr;
844 
845     if (!sc->sc_dma) {
846 	while (iavc_rx_full(sc))
847 	    iavc_handle_rx(sc);
848 	return 0;
849     }
850 
851     status = AMCC_READ(sc, AMCC_INTCSR);
852     if ((status & ANY_S5933_INT) == 0)
853 	return 0;
854 
855     newcsr = sc->sc_csr | (status & ALL_INT);
856     if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
857     if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
858     AMCC_WRITE(sc, AMCC_INTCSR, newcsr);
859     sc->sc_intr = 1;
860 
861     if (status & RX_TC_INT) {
862 	u_int32_t rxlen;
863 
864 	bus_dmamap_sync(sc->dmat, sc->rx_map, 0, sc->rx_map->dm_mapsize,
865 	  BUS_DMASYNC_POSTREAD);
866 
867 	if (sc->sc_recv1 == 0) {
868 	    sc->sc_recv1 = *(u_int32_t*)(sc->sc_recvbuf);
869 	    rxlen = (sc->sc_recv1 + 3) & ~3;
870 
871 	    AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr);
872 	    AMCC_WRITE(sc, AMCC_RXLEN, rxlen ? rxlen : 4);
873 	} else {
874 	    iavc_handle_rx(sc);
875 	    sc->sc_recv1 = 0;
876 	    AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr);
877 	    AMCC_WRITE(sc, AMCC_RXLEN, 4);
878 	}
879     }
880 
881     if (status & TX_TC_INT) {
882 	bus_dmamap_sync(sc->dmat, sc->tx_map, 0, sc->tx_map->dm_mapsize,
883 	  BUS_DMASYNC_POSTWRITE);
884 	sc->sc_csr &= ~EN_TX_TC_INT;
885 	iavc_start_tx(sc);
886     }
887 
888     AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
889     sc->sc_intr = 0;
890 
891     return 0;
892 }
893 
iavc_handle_rx(iavc_softc_t * sc)894 static void iavc_handle_rx(iavc_softc_t *sc)
895 {
896     u_int8_t *dmabuf = 0, cmd;
897 
898     if (sc->sc_dma) {
899 	dmabuf = amcc_get_byte(&sc->sc_recvbuf[0], &cmd);
900     } else {
901 	cmd = iavc_get_byte(sc);
902     }
903 
904     NDBGL4(L4_IAVCDBG, "iavc%d: command = 0x%02x", sc->sc_unit, cmd);
905 
906     switch (cmd) {
907     case RECEIVE_DATA_B3_IND:
908 	iavc_receive(sc, dmabuf, 1);
909 	break;
910 
911     case RECEIVE_MESSAGE:
912 	iavc_receive(sc, dmabuf, 0);
913 	break;
914 
915     case RECEIVE_NEW_NCCI:
916 	iavc_receive_new_ncci(sc, dmabuf);
917 	break;
918 
919     case RECEIVE_FREE_NCCI:
920 	iavc_receive_free_ncci(sc, dmabuf);
921 	break;
922 
923     case RECEIVE_START:
924 	iavc_receive_start(sc, dmabuf);
925 	break;
926 
927     case RECEIVE_STOP:
928 	iavc_receive_stop(sc, dmabuf);
929 	break;
930 
931     case RECEIVE_INIT:
932 	iavc_receive_init(sc, dmabuf);
933 	break;
934 
935     case RECEIVE_TASK_READY:
936 	iavc_receive_task_ready(sc, dmabuf);
937 	break;
938 
939     case RECEIVE_DEBUGMSG:
940 	iavc_receive_debugmsg(sc, dmabuf);
941 	break;
942 
943     default:
944 	printf("%s: unknown msg %02x\n", sc->sc_dev.dv_xname, cmd);
945     }
946 }
947 
iavc_start_tx(iavc_softc_t * sc)948 static void iavc_start_tx(iavc_softc_t *sc)
949 {
950     struct mbuf *m;
951     u_int32_t txlen;
952 
953     /* If device has put us on hold, punt. */
954 
955     if (sc->sc_blocked) {
956 	return;
957     }
958 
959     /* If using DMA and transmitter busy, punt. */
960     if (sc->sc_dma && (sc->sc_csr & EN_TX_TC_INT)) {
961 	return;
962     }
963 
964     /* Else, see if we have messages to send. */
965     IF_DEQUEUE(&sc->sc_txq, m);
966     if (!m) {
967 	return;
968     }
969 
970     /* Have message, will send. */
971     if (CAPIMSG_LEN(m->m_data)) {
972 	/* A proper CAPI message, possibly with B3 data */
973 	txlen = iavc_tx_capimsg(sc, m);
974     } else {
975 	/* A board control message to be sent as is */
976 	txlen = iavc_tx_ctrlmsg(sc, m);
977     }
978 
979     if (m->m_next) {
980 	i4b_Bfreembuf(m->m_next);
981 	m->m_next = NULL;
982     }
983     i4b_Dfreembuf(m);
984 
985     /* Kick DMA into motion if applicable */
986     if (sc->sc_dma) {
987 	txlen = (txlen + 3) & ~3;
988 
989 	bus_dmamap_sync(sc->dmat, sc->tx_map, 0, txlen,
990 	  BUS_DMASYNC_PREWRITE);
991 
992 	AMCC_WRITE(sc, AMCC_TXPTR, sc->tx_map->dm_segs[0].ds_addr);
993 	AMCC_WRITE(sc, AMCC_TXLEN, txlen);
994 	sc->sc_csr |= EN_TX_TC_INT;
995 
996 	if (!sc->sc_intr)
997 	    AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
998     }
999 }
1000 
1001 static uint32_t
iavc_tx_capimsg(iavc_softc_t * sc,struct mbuf * m)1002 iavc_tx_capimsg(iavc_softc_t *sc, struct mbuf *m)
1003 {
1004     uint32_t txlen = 0;
1005     u_int8_t *dmabuf;
1006 
1007     if (sc->sc_dma) {
1008 	/* Copy message to DMA buffer. */
1009 
1010 	if (m->m_next)
1011 	    dmabuf = amcc_put_byte(&sc->sc_sendbuf[0], SEND_DATA_B3_REQ);
1012 	else
1013 	    dmabuf = amcc_put_byte(&sc->sc_sendbuf[0], SEND_MESSAGE);
1014 
1015 	dmabuf = amcc_put_word(dmabuf, m->m_len);
1016 	memcpy(dmabuf, m->m_data, m->m_len);
1017 	dmabuf += m->m_len;
1018 	txlen = 5 + m->m_len;
1019 
1020 	if (m->m_next) {
1021 	    dmabuf = amcc_put_word(dmabuf, m->m_next->m_len);
1022 	    memcpy(dmabuf, m->m_next->m_data, m->m_next->m_len);
1023 	    txlen += 4 + m->m_next->m_len;
1024 	}
1025 
1026     } else {
1027 	/* Use PIO. */
1028 
1029 	if (m->m_next) {
1030 	    iavc_put_byte(sc, SEND_DATA_B3_REQ);
1031 	    NDBGL4(L4_IAVCDBG, "iavc%d: tx SDB3R msg, len = %d",
1032 	      sc->sc_unit, m->m_len);
1033 	} else {
1034 	    iavc_put_byte(sc, SEND_MESSAGE);
1035 	    NDBGL4(L4_IAVCDBG, "iavc%d: tx SM msg, len = %d",
1036 	      sc->sc_unit, m->m_len);
1037 	}
1038 #if 0
1039     {
1040 	u_int8_t *p = mtod(m, u_int8_t*);
1041 	int len;
1042 	for (len = 0; len < m->m_len; len++) {
1043 	    printf(" %02x", *p++);
1044 	    if (len && (len % 16) == 0)
1045 		printf("\n");
1046 	}
1047 	if (len % 16)
1048 	    printf("\n");
1049     }
1050 #endif
1051 
1052 	iavc_put_slice(sc, m->m_data, m->m_len);
1053 
1054 	if (m->m_next)
1055 	    iavc_put_slice(sc, m->m_next->m_data, m->m_next->m_len);
1056     }
1057 
1058     return txlen;
1059 }
1060 
1061 static uint32_t
iavc_tx_ctrlmsg(iavc_softc_t * sc,struct mbuf * m)1062 iavc_tx_ctrlmsg(iavc_softc_t *sc, struct mbuf *m)
1063 {
1064     uint32_t txlen = 0;
1065     uint8_t *dmabuf;
1066 
1067     if (sc->sc_dma) {
1068 	memcpy(&sc->sc_sendbuf[0], m->m_data + 2, m->m_len - 2);
1069 	txlen = m->m_len - 2;
1070     } else {
1071 
1072 #if 0
1073 	{
1074 	u_int8_t *p = mtod(m, u_int8_t*) + 2;
1075 	int len;
1076 
1077 	printf("%s: tx BDC msg, len = %d, msg =", sc->sc_dev.dv_xname,
1078 	  m->m_len-2);
1079 	for (len = 0; len < m->m_len-2; len++) {
1080 		printf(" %02x", *p++);
1081 		if (len && (len % 16) == 0) printf("\n");
1082 	}
1083 	if (len % 16)
1084 		printf("\n");
1085 	}
1086 #endif
1087 
1088 	/* no DMA */
1089 	txlen = m->m_len - 2;
1090 	dmabuf = mtod(m, char*) + 2;
1091 	while(txlen--)
1092 	    b1io_put_byte(sc, *dmabuf++);
1093     }
1094 
1095     return txlen;
1096 }
1097