1 /* $NetBSD: iavc.c,v 1.7 2008/04/08 12:07:26 cegger Exp $ */
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * The AVM ISDN controllers' card specific support routines.
29 * $FreeBSD: src/sys/i4b/capi/iavc/iavc_card.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: iavc.c,v 1.7 2008/04/08 12:07:26 cegger Exp $");
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
39 #include <sys/socket.h>
40 #include <sys/device.h>
41 #include <sys/callout.h>
42 #include <sys/reboot.h>
47 #include <netisdn/i4b_debug.h>
48 #include <netisdn/i4b_ioctl.h>
49 #include <netisdn/i4b_trace.h>
50 #include <netisdn/i4b_global.h>
51 #include <netisdn/i4b_l3l4.h>
52 #include <netisdn/i4b_mbuf.h>
53 #include <netisdn/i4b_capi.h>
54 #include <netisdn/i4b_capi_msgs.h>
56 #include <dev/ic/iavcvar.h>
57 #include <dev/ic/iavcreg.h>
60 // AVM B1 (active BRI, PIO mode)
64 iavc_b1_detect(iavc_softc_t
*sc
)
66 if ((iavc_read_port(sc
, B1_INSTAT
) & 0xfc) ||
67 (iavc_read_port(sc
, B1_OUTSTAT
) & 0xfc))
70 b1io_outp(sc
, B1_INSTAT
, 0x02);
71 b1io_outp(sc
, B1_OUTSTAT
, 0x02);
72 if ((iavc_read_port(sc
, B1_INSTAT
) & 0xfe) != 2 ||
73 (iavc_read_port(sc
, B1_OUTSTAT
) & 0xfe) != 2)
76 b1io_outp(sc
, B1_INSTAT
, 0x00);
77 b1io_outp(sc
, B1_OUTSTAT
, 0x00);
78 if ((iavc_read_port(sc
, B1_INSTAT
) & 0xfe) ||
79 (iavc_read_port(sc
, B1_OUTSTAT
) & 0xfe))
82 return (0); /* found */
86 iavc_b1_disable_irq(iavc_softc_t
*sc
)
88 b1io_outp(sc
, B1_INSTAT
, 0x00);
92 iavc_b1_reset(iavc_softc_t
*sc
)
94 b1io_outp(sc
, B1_RESET
, 0);
97 b1io_outp(sc
, B1_RESET
, 1);
100 b1io_outp(sc
, B1_RESET
, 0);
105 // Newer PCI-based B1's, and T1's, supports DMA
109 iavc_b1dma_detect(iavc_softc_t
*sc
)
111 AMCC_WRITE(sc
, AMCC_MCSR
, 0);
113 AMCC_WRITE(sc
, AMCC_MCSR
, 0x0f000000);
115 AMCC_WRITE(sc
, AMCC_MCSR
, 0);
118 AMCC_WRITE(sc
, AMCC_RXLEN
, 0);
119 AMCC_WRITE(sc
, AMCC_TXLEN
, 0);
121 AMCC_WRITE(sc
, AMCC_INTCSR
, sc
->sc_csr
);
123 if (AMCC_READ(sc
, AMCC_INTCSR
) != 0)
126 AMCC_WRITE(sc
, AMCC_RXPTR
, 0xffffffff);
127 AMCC_WRITE(sc
, AMCC_TXPTR
, 0xffffffff);
128 if ((AMCC_READ(sc
, AMCC_RXPTR
) != 0xfffffffc) ||
129 (AMCC_READ(sc
, AMCC_TXPTR
) != 0xfffffffc))
132 AMCC_WRITE(sc
, AMCC_RXPTR
, 0);
133 AMCC_WRITE(sc
, AMCC_TXPTR
, 0);
134 if ((AMCC_READ(sc
, AMCC_RXPTR
) != 0) ||
135 (AMCC_READ(sc
, AMCC_TXPTR
) != 0))
138 iavc_write_port(sc
, 0x10, 0x00);
139 iavc_write_port(sc
, 0x07, 0x00);
141 iavc_write_port(sc
, 0x02, 0x02);
142 iavc_write_port(sc
, 0x03, 0x02);
144 if (((iavc_read_port(sc
, 0x02) & 0xfe) != 0x02) ||
145 (iavc_read_port(sc
, 0x03) != 0x03))
148 iavc_write_port(sc
, 0x02, 0x00);
149 iavc_write_port(sc
, 0x03, 0x00);
151 if (((iavc_read_port(sc
, 0x02) & 0xfe) != 0x00) ||
152 (iavc_read_port(sc
, 0x03) != 0x01))
155 return (0); /* found */
159 iavc_b1dma_reset(iavc_softc_t
*sc
)
164 AMCC_WRITE(sc
, AMCC_INTCSR
, sc
->sc_csr
);
165 AMCC_WRITE(sc
, AMCC_MCSR
, 0);
166 AMCC_WRITE(sc
, AMCC_RXLEN
, 0);
167 AMCC_WRITE(sc
, AMCC_TXLEN
, 0);
169 iavc_write_port(sc
, 0x10, 0x00); /* XXX magic numbers from */
170 iavc_write_port(sc
, 0x07, 0x00); /* XXX the linux driver */
174 AMCC_WRITE(sc
, AMCC_MCSR
, 0);
176 AMCC_WRITE(sc
, AMCC_MCSR
, 0x0f000000);
178 AMCC_WRITE(sc
, AMCC_MCSR
, 0);
183 // AVM T1 (active PRI)
186 #define b1dma_tx_empty(sc) (b1io_read_reg((sc), T1_OUTSTAT) & 1)
187 #define b1dma_rx_full(sc) (b1io_read_reg((sc), T1_INSTAT) & 1)
189 static int b1dma_tolink(iavc_softc_t
*sc
, void *buf
, int len
)
192 char *s
= (char*) buf
;
195 while (!b1dma_tx_empty(sc
) && spin
< 100000)
197 if (!b1dma_tx_empty(sc
))
199 t1io_outp(sc
, 1, *s
++);
204 static int b1dma_fromlink(iavc_softc_t
*sc
, void *buf
, int len
)
207 char *s
= (char*) buf
;
210 while (!b1dma_rx_full(sc
) && spin
< 100000)
212 if (!b1dma_rx_full(sc
))
214 *s
++ = t1io_inp(sc
, 0);
219 static int WriteReg(iavc_softc_t
*sc
, u_int32_t reg
, u_int8_t val
)
222 if (b1dma_tolink(sc
, &cmd
, 1) == 0 &&
223 b1dma_tolink(sc
, ®
, 4) == 0) {
225 return b1dma_tolink(sc
, &tmp
, 4);
230 static u_int8_t
ReadReg(iavc_softc_t
*sc
, u_int32_t reg
)
233 if (b1dma_tolink(sc
, &cmd
, 1) == 0 &&
234 b1dma_tolink(sc
, ®
, 4) == 0) {
236 if (b1dma_fromlink(sc
, &tmp
, 4) == 0)
237 return (u_int8_t
) tmp
;
243 iavc_t1_detect(iavc_softc_t
*sc
)
245 int ret
= iavc_b1dma_detect(sc
);
248 if ((WriteReg(sc
, 0x80001000, 0x11) != 0) ||
249 (WriteReg(sc
, 0x80101000, 0x22) != 0) ||
250 (WriteReg(sc
, 0x80201000, 0x33) != 0) ||
251 (WriteReg(sc
, 0x80301000, 0x44) != 0))
254 if ((ReadReg(sc
, 0x80001000) != 0x11) ||
255 (ReadReg(sc
, 0x80101000) != 0x22) ||
256 (ReadReg(sc
, 0x80201000) != 0x33) ||
257 (ReadReg(sc
, 0x80301000) != 0x44))
260 if ((WriteReg(sc
, 0x80001000, 0x55) != 0) ||
261 (WriteReg(sc
, 0x80101000, 0x66) != 0) ||
262 (WriteReg(sc
, 0x80201000, 0x77) != 0) ||
263 (WriteReg(sc
, 0x80301000, 0x88) != 0))
266 if ((ReadReg(sc
, 0x80001000) != 0x55) ||
267 (ReadReg(sc
, 0x80101000) != 0x66) ||
268 (ReadReg(sc
, 0x80201000) != 0x77) ||
269 (ReadReg(sc
, 0x80301000) != 0x88))
272 return 0; /* found */
276 iavc_t1_disable_irq(iavc_softc_t
*sc
)
278 iavc_write_port(sc
, T1_IRQMASTER
, 0x00);
282 iavc_t1_reset(iavc_softc_t
*sc
)
285 iavc_write_port(sc
, B1_INSTAT
, 0x00);
286 iavc_write_port(sc
, B1_OUTSTAT
, 0x00);
287 iavc_write_port(sc
, T1_IRQMASTER
, 0x00);
288 iavc_write_port(sc
, T1_RESETBOARD
, 0x0f);
291 /* Forward declarations of local subroutines... */
293 static int iavc_send_init(iavc_softc_t
*);
295 static void iavc_handle_rx(iavc_softc_t
*);
296 static void iavc_start_tx(iavc_softc_t
*);
298 static uint32_t iavc_tx_capimsg(iavc_softc_t
*, struct mbuf
*);
299 static uint32_t iavc_tx_ctrlmsg(iavc_softc_t
*, struct mbuf
*);
302 // Callbacks from the upper (capi) layer:
303 // --------------------------------------
306 // Resets the board and loads the firmware, then initiates
310 // Registers a CAPI application id.
313 // Releases a CAPI application id.
316 // Sends a capi message.
319 int iavc_load(capi_softc_t
*capi_sc
, int len
, u_int8_t
*cp
)
321 iavc_softc_t
*sc
= (iavc_softc_t
*) capi_sc
->ctx
;
324 aprint_debug_dev(&sc
->sc_dev
, "reset card ....\n");
327 iavc_b1dma_reset(sc
); /* PCI cards */
329 iavc_t1_reset(sc
); /* ISA attachment T1 */
331 iavc_b1_reset(sc
); /* ISA attachment B1 */
335 aprint_debug_dev(&sc
->sc_dev
, "start loading %d bytes firmware\n", len
);
337 while (len
&& b1io_save_put_byte(sc
, *cp
++) == 0)
341 aprint_error_dev(&sc
->sc_dev
, "loading failed, can't write to card, len = %d\n", len
);
345 aprint_debug_dev(&sc
->sc_dev
, "firmware loaded, wait for ACK\n");
347 if(sc
->sc_capi
.card_type
== CARD_TYPEC_AVM_B1_ISA
)
348 iavc_put_byte(sc
, SEND_POLL
);
350 iavc_put_byte(sc
, SEND_POLLACK
);
352 for (len
= 0; len
< 1000 && !iavc_rx_full(sc
); len
++)
355 if (!iavc_rx_full(sc
)) {
356 aprint_error_dev(&sc
->sc_dev
, "loading failed, no ack\n");
360 val
= iavc_get_byte(sc
);
362 if ((sc
->sc_dma
&& val
!= RECEIVE_POLLDWORD
) ||
363 (!sc
->sc_dma
&& val
!= RECEIVE_POLL
)) {
364 aprint_error_dev(&sc
->sc_dev
, "loading failed, bad ack = %02x\n", val
);
368 aprint_debug_dev(&sc
->sc_dev
, "got ACK = 0x%02x\n", val
);
370 /* Start the DMA engine */
376 sc
->sc_csr
= AVM_FLAG
;
377 AMCC_WRITE(sc
, AMCC_INTCSR
, sc
->sc_csr
);
378 AMCC_WRITE(sc
, AMCC_MCSR
, (EN_A2P_TRANSFERS
|EN_P2A_TRANSFERS
|
379 A2P_HI_PRIORITY
|P2A_HI_PRIORITY
|
380 RESET_A2P_FLAGS
|RESET_P2A_FLAGS
));
382 iavc_write_port(sc
, 0x07, 0x30); /* XXX magic numbers from */
383 iavc_write_port(sc
, 0x10, 0xf0); /* XXX the linux driver */
385 bus_dmamap_sync(sc
->dmat
, sc
->rx_map
, 0, sc
->rx_map
->dm_mapsize
,
386 BUS_DMASYNC_PREREAD
);
389 AMCC_WRITE(sc
, AMCC_RXPTR
, sc
->rx_map
->dm_segs
[0].ds_addr
);
390 AMCC_WRITE(sc
, AMCC_RXLEN
, 4);
391 sc
->sc_csr
|= EN_RX_TC_INT
|EN_TX_TC_INT
;
392 AMCC_WRITE(sc
, AMCC_INTCSR
, sc
->sc_csr
);
398 /* good happy place */
399 if(sc
->sc_capi
.card_type
== CARD_TYPEC_AVM_B1_ISA
)
408 int iavc_register(capi_softc_t
*capi_sc
, int applid
, int nchan
)
410 iavc_softc_t
*sc
= (iavc_softc_t
*) capi_sc
->ctx
;
411 struct mbuf
*m
= i4b_Dgetmbuf(23);
415 aprint_error("iavc%d: can't get memory\n", sc
->sc_unit
);
420 * byte 0x12 = SEND_REGISTER
423 * dword NumB3Connections 0..nbch
428 p
= amcc_put_byte(mtod(m
, u_int8_t
*), 0);
429 p
= amcc_put_byte(p
, 0);
430 p
= amcc_put_byte(p
, SEND_REGISTER
);
431 p
= amcc_put_word(p
, applid
);
433 p
= amcc_put_word(p
, 1024 + (nchan
+ 1));
435 p
= amcc_put_word(p
, 1024 * (nchan
+ 1));
437 p
= amcc_put_word(p
, nchan
);
438 p
= amcc_put_word(p
, 8);
439 p
= amcc_put_word(p
, 2048);
441 IF_ENQUEUE(&sc
->sc_txq
, m
);
448 int iavc_release(capi_softc_t
*capi_sc
, int applid
)
450 iavc_softc_t
*sc
= (iavc_softc_t
*) capi_sc
->ctx
;
451 struct mbuf
*m
= i4b_Dgetmbuf(7);
455 aprint_error_dev(&sc
->sc_dev
, "can't get memory\n");
460 * byte 0x14 = SEND_RELEASE
464 p
= amcc_put_byte(mtod(m
, u_int8_t
*), 0);
465 p
= amcc_put_byte(p
, 0);
466 p
= amcc_put_byte(p
, SEND_RELEASE
);
467 p
= amcc_put_word(p
, applid
);
469 IF_ENQUEUE(&sc
->sc_txq
, m
);
475 int iavc_send(capi_softc_t
*capi_sc
, struct mbuf
*m
)
477 iavc_softc_t
*sc
= (iavc_softc_t
*) capi_sc
->ctx
;
479 if (sc
->sc_state
!= IAVC_UP
) {
480 aprint_error_dev(&sc
->sc_dev
, "attempt to send before device up\n");
482 if (m
->m_next
) i4b_Bfreembuf(m
->m_next
);
488 if (IF_QFULL(&sc
->sc_txq
)) {
489 IF_DROP(&sc
->sc_txq
);
491 aprint_error_dev(&sc
->sc_dev
, "tx overflow, message dropped\n");
493 if (m
->m_next
) i4b_Bfreembuf(m
->m_next
);
497 IF_ENQUEUE(&sc
->sc_txq
, m
);
506 // Functions called by ourself during the initialization sequence:
507 // ---------------------------------------------------------------
510 // Sends the system initialization message to a newly loaded
511 // board, and sets state to INIT.
514 static int iavc_send_init(iavc_softc_t
*sc
)
516 struct mbuf
*m
= i4b_Dgetmbuf(15);
521 aprint_error_dev(&sc
->sc_dev
, "can't get memory\n");
526 * byte 0x11 = SEND_INIT
527 * dword NumApplications
532 p
= amcc_put_byte(mtod(m
, u_int8_t
*), 0);
533 p
= amcc_put_byte(p
, 0);
534 p
= amcc_put_byte(p
, SEND_INIT
);
535 p
= amcc_put_word(p
, 1); /* XXX MaxAppl XXX */
536 p
= amcc_put_word(p
, sc
->sc_capi
.sc_nbch
);
537 p
= amcc_put_word(p
, sc
->sc_unit
);
540 IF_ENQUEUE(&sc
->sc_txq
, m
);
544 sc
->sc_state
= IAVC_INIT
;
550 // Functions called during normal operation:
551 // -----------------------------------------
554 // Reads the initialization reply and calls capi_ll_control().
556 // iavc_receive_new_ncci
557 // Reads a new NCCI notification and calls capi_ll_control().
559 // iavc_receive_free_ncci
560 // Reads a freed NCCI notification and calls capi_ll_control().
562 // iavc_receive_task_ready
563 // Reads a task ready message -- which should not occur XXX.
565 // iavc_receive_debugmsg
566 // Reads a debug message -- which should not occur XXX.
568 // iavc_receive_start
569 // Reads a START TRANSMIT message and unblocks device.
572 // Reads a STOP TRANSMIT message and blocks device.
575 // Reads an incoming message and calls capi_ll_receive().
578 static int iavc_receive_init(iavc_softc_t
*sc
, u_int8_t
*dmabuf
)
582 u_int8_t
*cardtype
, *serial
, *profile
, *vers
, *caps
, *prot
;
585 p
= amcc_get_word(dmabuf
, &Length
);
587 Length
= iavc_get_slice(sc
, sc
->sc_recvbuf
);
594 printf("%s: rx_init: ", device_xname(&sc
->sc_dev
));
595 while (len
< Length
) {
596 printf(" %02x", p
[len
]);
597 if (len
&& (len
% 16) == 0) printf("\n");
600 if (len
% 16) printf("\n");
605 p
+= (*p
+ 1); /* driver version */
607 p
+= (*p
+ 1); /* card type */
608 p
+= (*p
+ 1); /* hardware ID */
610 p
+= (*p
+ 1); /* serial number */
612 p
+= (*p
+ 1); /* supported options */
614 p
+= (*p
+ 1); /* supported protocols */
617 if (cardtype
&& serial
&& profile
) {
618 int nbch
= ((profile
[3]<<8) | profile
[2]);
620 aprint_normal_dev(&sc
->sc_dev
, "AVM %s, s/n %s, %d chans, f/w rev %s, prot %s\n",
621 cardtype
, serial
, nbch
, vers
, prot
);
622 aprint_verbose_dev(&sc
->sc_dev
, "%s\n", caps
);
624 capi_ll_control(&sc
->sc_capi
, CAPI_CTRL_PROFILE
, (int) profile
);
627 printf("%s: no profile data in info response?\n", device_xname(&sc
->sc_dev
));
630 sc
->sc_blocked
= 1; /* controller will send START when ready */
634 static int iavc_receive_start(iavc_softc_t
*sc
)
636 struct mbuf
*m
= i4b_Dgetmbuf(3);
639 if (sc
->sc_blocked
&& sc
->sc_state
== IAVC_UP
)
640 printf("%s: receive_start\n", device_xname(&sc
->sc_dev
));
643 aprint_error_dev(&sc
->sc_dev
, "can't get memory\n");
648 * byte 0x73 = SEND_POLLACK
651 p
= amcc_put_byte(mtod(m
, u_int8_t
*), 0);
652 p
= amcc_put_byte(p
, 0);
653 p
= amcc_put_byte(p
, SEND_POLLACK
);
655 IF_PREPEND(&sc
->sc_txq
, m
);
657 NDBGL4(L4_IAVCDBG
, "%s: blocked = %d, state = %d",
658 device_xname(&sc
->sc_dev
), sc
->sc_blocked
, sc
->sc_state
);
663 /* If this was our first START, register our readiness */
664 if (sc
->sc_state
!= IAVC_UP
) {
665 sc
->sc_state
= IAVC_UP
;
666 capi_ll_control(&sc
->sc_capi
, CAPI_CTRL_READY
, 1);
672 static int iavc_receive_stop(iavc_softc_t
*sc
)
674 printf("%s: receive_stop\n", device_xname(&sc
->sc_dev
));
679 static int iavc_receive_new_ncci(iavc_softc_t
*sc
, u_int8_t
*dmabuf
)
681 u_int32_t ApplId
, NCCI
, WindowSize
;
684 dmabuf
= amcc_get_word(dmabuf
, &ApplId
);
685 dmabuf
= amcc_get_word(dmabuf
, &NCCI
);
686 dmabuf
= amcc_get_word(dmabuf
, &WindowSize
);
688 ApplId
= iavc_get_word(sc
);
689 NCCI
= iavc_get_word(sc
);
690 WindowSize
= iavc_get_word(sc
);
693 capi_ll_control(&sc
->sc_capi
, CAPI_CTRL_NEW_NCCI
, NCCI
);
697 static int iavc_receive_free_ncci(iavc_softc_t
*sc
, u_int8_t
*dmabuf
)
699 u_int32_t ApplId
, NCCI
;
702 dmabuf
= amcc_get_word(dmabuf
, &ApplId
);
703 dmabuf
= amcc_get_word(dmabuf
, &NCCI
);
705 ApplId
= iavc_get_word(sc
);
706 NCCI
= iavc_get_word(sc
);
709 capi_ll_control(&sc
->sc_capi
, CAPI_CTRL_FREE_NCCI
, NCCI
);
713 static int iavc_receive_task_ready(iavc_softc_t
*sc
, u_int8_t
*dmabuf
)
715 u_int32_t TaskId
, Length
;
717 printf("%s: receive_task_ready\n", device_xname(&sc
->sc_dev
));
720 p
= amcc_get_word(dmabuf
, &TaskId
);
721 p
= amcc_get_word(p
, &Length
);
723 TaskId
= iavc_get_word(sc
);
724 Length
= iavc_get_slice(sc
, sc
->sc_recvbuf
);
728 /* XXX could show the message if trace enabled? XXX */
732 static int iavc_receive_debugmsg(iavc_softc_t
*sc
, u_int8_t
*dmabuf
)
736 printf("%s: receive_debugmsg\n", device_xname(&sc
->sc_dev
));
739 p
= amcc_get_word(dmabuf
, &Length
);
741 Length
= iavc_get_slice(sc
, sc
->sc_recvbuf
);
745 /* XXX could show the message if trace enabled? XXX */
749 static int iavc_receive(iavc_softc_t
*sc
, u_int8_t
*dmabuf
, int b3data
)
752 u_int32_t ApplId
, Length
;
755 * byte 0x21 = RECEIVE_MESSAGE
762 * byte 0x22 = RECEIVE_DATA_B3_IND
771 dmabuf
= amcc_get_word(dmabuf
, &ApplId
);
772 dmabuf
= amcc_get_word(dmabuf
, &Length
);
774 ApplId
= iavc_get_word(sc
);
775 Length
= iavc_get_slice(sc
, sc
->sc_recvbuf
);
776 dmabuf
= sc
->sc_recvbuf
;
779 m
= i4b_Dgetmbuf(Length
);
781 aprint_error_dev(&sc
->sc_dev
, "can't get memory for receive\n");
785 memcpy(mtod(m
, u_int8_t
*), dmabuf
, Length
);
789 u_int8_t
*p
= mtod(m
, u_int8_t
*);
791 printf("%s: applid=%d, len=%d\n", device_xname(&sc
->sc_dev
),
793 while (len
< m
->m_len
) {
794 printf(" %02x", p
[len
]);
795 if (len
&& (len
% 16) == 0) printf("\n");
798 if (len
% 16) printf("\n");
804 dmabuf
= amcc_get_word(dmabuf
+ Length
, &Length
);
806 Length
= iavc_get_slice(sc
, sc
->sc_recvbuf
);
807 dmabuf
= sc
->sc_recvbuf
;
810 m
->m_next
= i4b_Bgetmbuf(Length
);
812 aprint_error_dev(&sc
->sc_dev
, "can't get memory for receive\n");
817 memcpy(mtod(m
->m_next
, u_int8_t
*), dmabuf
, Length
);
820 capi_ll_receive(&sc
->sc_capi
, m
);
826 // Checks device interrupt status and calls iavc_handle_{rx,tx}()
830 // Reads in the command byte and calls the subroutines above.
833 // Initiates DMA on the next queued message if possible.
836 int iavc_handle_intr(iavc_softc_t
*sc
)
842 while (iavc_rx_full(sc
))
847 status
= AMCC_READ(sc
, AMCC_INTCSR
);
848 if ((status
& ANY_S5933_INT
) == 0)
851 newcsr
= sc
->sc_csr
| (status
& ALL_INT
);
852 if (status
& TX_TC_INT
) newcsr
&= ~EN_TX_TC_INT
;
853 if (status
& RX_TC_INT
) newcsr
&= ~EN_RX_TC_INT
;
854 AMCC_WRITE(sc
, AMCC_INTCSR
, newcsr
);
857 if (status
& RX_TC_INT
) {
860 bus_dmamap_sync(sc
->dmat
, sc
->rx_map
, 0, sc
->rx_map
->dm_mapsize
,
861 BUS_DMASYNC_POSTREAD
);
863 if (sc
->sc_recv1
== 0) {
864 sc
->sc_recv1
= *(u_int32_t
*)(sc
->sc_recvbuf
);
865 rxlen
= (sc
->sc_recv1
+ 3) & ~3;
867 AMCC_WRITE(sc
, AMCC_RXPTR
, sc
->rx_map
->dm_segs
[0].ds_addr
);
868 AMCC_WRITE(sc
, AMCC_RXLEN
, rxlen
? rxlen
: 4);
872 AMCC_WRITE(sc
, AMCC_RXPTR
, sc
->rx_map
->dm_segs
[0].ds_addr
);
873 AMCC_WRITE(sc
, AMCC_RXLEN
, 4);
877 if (status
& TX_TC_INT
) {
878 bus_dmamap_sync(sc
->dmat
, sc
->tx_map
, 0, sc
->tx_map
->dm_mapsize
,
879 BUS_DMASYNC_POSTWRITE
);
880 sc
->sc_csr
&= ~EN_TX_TC_INT
;
884 AMCC_WRITE(sc
, AMCC_INTCSR
, sc
->sc_csr
);
890 static void iavc_handle_rx(iavc_softc_t
*sc
)
892 u_int8_t
*dmabuf
= 0, cmd
;
895 dmabuf
= amcc_get_byte(sc
->sc_recvbuf
, &cmd
);
897 cmd
= iavc_get_byte(sc
);
900 NDBGL4(L4_IAVCDBG
, "iavc%d: command = 0x%02x", sc
->sc_unit
, cmd
);
903 case RECEIVE_DATA_B3_IND
:
904 iavc_receive(sc
, dmabuf
, 1);
907 case RECEIVE_MESSAGE
:
908 iavc_receive(sc
, dmabuf
, 0);
911 case RECEIVE_NEW_NCCI
:
912 iavc_receive_new_ncci(sc
, dmabuf
);
915 case RECEIVE_FREE_NCCI
:
916 iavc_receive_free_ncci(sc
, dmabuf
);
920 iavc_receive_start(sc
);
924 iavc_receive_stop(sc
);
928 iavc_receive_init(sc
, dmabuf
);
931 case RECEIVE_TASK_READY
:
932 iavc_receive_task_ready(sc
, dmabuf
);
935 case RECEIVE_DEBUGMSG
:
936 iavc_receive_debugmsg(sc
, dmabuf
);
940 aprint_error_dev(&sc
->sc_dev
, "unknown msg %02x\n", cmd
);
944 static void iavc_start_tx(iavc_softc_t
*sc
)
949 /* If device has put us on hold, punt. */
951 if (sc
->sc_blocked
) {
955 /* If using DMA and transmitter busy, punt. */
956 if (sc
->sc_dma
&& (sc
->sc_csr
& EN_TX_TC_INT
)) {
960 /* Else, see if we have messages to send. */
961 IF_DEQUEUE(&sc
->sc_txq
, m
);
966 /* Have message, will send. */
967 if (CAPIMSG_LEN(m
->m_data
)) {
968 /* A proper CAPI message, possibly with B3 data */
969 txlen
= iavc_tx_capimsg(sc
, m
);
971 /* A board control message to be sent as is */
972 txlen
= iavc_tx_ctrlmsg(sc
, m
);
976 i4b_Bfreembuf(m
->m_next
);
981 /* Kick DMA into motion if applicable */
983 txlen
= (txlen
+ 3) & ~3;
985 bus_dmamap_sync(sc
->dmat
, sc
->tx_map
, 0, txlen
,
986 BUS_DMASYNC_PREWRITE
);
988 AMCC_WRITE(sc
, AMCC_TXPTR
, sc
->tx_map
->dm_segs
[0].ds_addr
);
989 AMCC_WRITE(sc
, AMCC_TXLEN
, txlen
);
990 sc
->sc_csr
|= EN_TX_TC_INT
;
993 AMCC_WRITE(sc
, AMCC_INTCSR
, sc
->sc_csr
);
998 iavc_tx_capimsg(iavc_softc_t
*sc
, struct mbuf
*m
)
1004 /* Copy message to DMA buffer. */
1007 dmabuf
= amcc_put_byte(sc
->sc_sendbuf
, SEND_DATA_B3_REQ
);
1009 dmabuf
= amcc_put_byte(sc
->sc_sendbuf
, SEND_MESSAGE
);
1011 dmabuf
= amcc_put_word(dmabuf
, m
->m_len
);
1012 memcpy(dmabuf
, m
->m_data
, m
->m_len
);
1014 txlen
= 5 + m
->m_len
;
1017 dmabuf
= amcc_put_word(dmabuf
, m
->m_next
->m_len
);
1018 memcpy(dmabuf
, m
->m_next
->m_data
, m
->m_next
->m_len
);
1019 txlen
+= 4 + m
->m_next
->m_len
;
1026 iavc_put_byte(sc
, SEND_DATA_B3_REQ
);
1027 NDBGL4(L4_IAVCDBG
, "iavc%d: tx SDB3R msg, len = %d",
1028 sc
->sc_unit
, m
->m_len
);
1030 iavc_put_byte(sc
, SEND_MESSAGE
);
1031 NDBGL4(L4_IAVCDBG
, "iavc%d: tx SM msg, len = %d",
1032 sc
->sc_unit
, m
->m_len
);
1036 u_int8_t
*p
= mtod(m
, u_int8_t
*);
1038 for (len
= 0; len
< m
->m_len
; len
++) {
1039 printf(" %02x", *p
++);
1040 if (len
&& (len
% 16) == 0)
1048 iavc_put_slice(sc
, m
->m_data
, m
->m_len
);
1051 iavc_put_slice(sc
, m
->m_next
->m_data
, m
->m_next
->m_len
);
1058 iavc_tx_ctrlmsg(iavc_softc_t
*sc
, struct mbuf
*m
)
1064 memcpy(sc
->sc_sendbuf
, m
->m_data
+ 2, m
->m_len
- 2);
1065 txlen
= m
->m_len
- 2;
1070 u_int8_t
*p
= mtod(m
, u_int8_t
*) + 2;
1073 printf("%s: tx BDC msg, len = %d, msg =", device_xname(&sc
->sc_dev
),
1075 for (len
= 0; len
< m
->m_len
-2; len
++) {
1076 printf(" %02x", *p
++);
1077 if (len
&& (len
% 16) == 0) printf("\n");
1085 txlen
= m
->m_len
- 2;
1086 dmabuf
= mtod(m
, char*) + 2;
1088 b1io_put_byte(sc
, *dmabuf
++);