2 * Copyright (c) 2001 Cubical Solutions Ltd. 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
26 /* capi/iavc/iavc_lli.c
27 * The AVM ISDN controllers' Low Level Interface.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/systm.h>
37 #include <sys/socket.h>
38 #include <sys/malloc.h>
42 #include <machine/bus.h>
48 #include <i4b/include/i4b_debug.h>
49 #include <i4b/include/i4b_ioctl.h>
50 #include <i4b/include/i4b_trace.h>
52 #include <i4b/include/i4b_global.h>
53 #include <i4b/include/i4b_l3l4.h>
54 #include <i4b/include/i4b_mbuf.h>
56 #include <i4b/capi/capi.h>
57 #include <i4b/capi/capi_msgs.h>
59 #include <i4b/capi/iavc/iavc.h>
61 /* Forward declarations of local subroutines... */
63 static int iavc_send_init(iavc_softc_t *);
65 static void iavc_handle_rx(iavc_softc_t *);
66 static void iavc_start_tx(iavc_softc_t *);
69 // Callbacks from the upper (capi) layer:
70 // --------------------------------------
73 // Resets the board and loads the firmware, then initiates
77 // Registers a CAPI application id.
80 // Releases a CAPI application id.
83 // Sends a capi message.
86 int iavc_load(capi_softc_t *capi_sc, int len, u_int8_t *cp)
88 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
92 printf("iavc%d: reset card ....\n", sc->sc_unit);
95 b1dma_reset(sc); /* PCI cards */
97 t1_reset(sc); /* ISA attachment T1 */
99 b1_reset(sc); /* ISA attachment B1 */
104 printf("iavc%d: start loading %d bytes firmware ....\n", sc->sc_unit, len);
106 while (len && b1io_save_put_byte(sc, *cp++) == 0)
110 printf("iavc%d: loading failed, can't write to card, len = %d\n",
116 printf("iavc%d: firmware loaded, wait for ACK ....\n", sc->sc_unit);
118 if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
119 iavc_put_byte(sc, SEND_POLL);
121 iavc_put_byte(sc, SEND_POLLACK);
123 for (len = 0; len < 1000 && !iavc_rx_full(sc); len++)
126 if (!iavc_rx_full(sc)) {
127 printf("iavc%d: loading failed, no ack\n", sc->sc_unit);
131 val = iavc_get_byte(sc);
133 if ((sc->sc_dma && val != RECEIVE_POLLDWORD) ||
134 (!sc->sc_dma && val != RECEIVE_POLL)) {
135 printf("iavc%d: loading failed, bad ack = %02x\n", sc->sc_unit, val);
140 printf("iavc%d: got ACK = 0x%02x\n", sc->sc_unit, val);
143 /* Start the DMA engine */
147 sc->sc_csr = AVM_FLAG;
148 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
149 AMCC_WRITE(sc, AMCC_MCSR, (EN_A2P_TRANSFERS|EN_P2A_TRANSFERS|
150 A2P_HI_PRIORITY|P2A_HI_PRIORITY|
151 RESET_A2P_FLAGS|RESET_P2A_FLAGS));
153 iavc_write_port(sc, 0x07, 0x30); /* XXX magic numbers from */
154 iavc_write_port(sc, 0x10, 0xf0); /* XXX the linux driver */
157 AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[0]));
158 AMCC_WRITE(sc, AMCC_RXLEN, 4);
159 sc->sc_csr |= EN_RX_TC_INT|EN_TX_TC_INT;
160 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
165 if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
173 int iavc_register(capi_softc_t *capi_sc, int applid, int nchan)
175 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
176 struct mbuf *m = i4b_Dgetmbuf(23);
180 printf("iavc%d: can't get memory\n", sc->sc_unit);
185 * byte 0x12 = SEND_REGISTER
188 * dword NumB3Connections 0..nbch
193 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
194 p = amcc_put_byte(p, 0);
195 p = amcc_put_byte(p, SEND_REGISTER);
196 p = amcc_put_word(p, applid);
198 p = amcc_put_word(p, 1024 + (nchan + 1));
200 p = amcc_put_word(p, 1024 * (nchan + 1));
202 p = amcc_put_word(p, nchan);
203 p = amcc_put_word(p, 8);
204 p = amcc_put_word(p, 2048);
206 _IF_ENQUEUE(&sc->sc_txq, m);
213 int iavc_release(capi_softc_t *capi_sc, int applid)
215 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
216 struct mbuf *m = i4b_Dgetmbuf(7);
220 printf("iavc%d: can't get memory\n", sc->sc_unit);
225 * byte 0x14 = SEND_RELEASE
229 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
230 p = amcc_put_byte(p, 0);
231 p = amcc_put_byte(p, SEND_RELEASE);
232 p = amcc_put_word(p, applid);
234 _IF_ENQUEUE(&sc->sc_txq, m);
240 int iavc_send(capi_softc_t *capi_sc, struct mbuf *m)
242 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
244 if (sc->sc_state != IAVC_UP) {
245 printf("iavc%d: attempt to send before device up\n", sc->sc_unit);
247 if (m->m_next) i4b_Bfreembuf(m->m_next);
253 if (_IF_QFULL(&sc->sc_txq)) {
255 _IF_DROP(&sc->sc_txq);
257 printf("iavc%d: tx overflow, message dropped\n", sc->sc_unit);
259 if (m->m_next) i4b_Bfreembuf(m->m_next);
263 _IF_ENQUEUE(&sc->sc_txq, m);
272 // Functions called by ourself during the initialization sequence:
273 // ---------------------------------------------------------------
276 // Sends the system initialization message to a newly loaded
277 // board, and sets state to INIT.
280 static int iavc_send_init(iavc_softc_t *sc)
282 struct mbuf *m = i4b_Dgetmbuf(15);
287 printf("iavc%d: can't get memory\n", sc->sc_unit);
292 * byte 0x11 = SEND_INIT
293 * dword NumApplications
298 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
299 p = amcc_put_byte(p, 0);
300 p = amcc_put_byte(p, SEND_INIT);
301 p = amcc_put_word(p, 1); /* XXX MaxAppl XXX */
302 p = amcc_put_word(p, sc->sc_capi.sc_nbch);
303 p = amcc_put_word(p, sc->sc_unit);
306 _IF_ENQUEUE(&sc->sc_txq, m);
310 sc->sc_state = IAVC_INIT;
316 // Functions called during normal operation:
317 // -----------------------------------------
320 // Reads the initialization reply and calls capi_ll_control().
322 // iavc_receive_new_ncci
323 // Reads a new NCCI notification and calls capi_ll_control().
325 // iavc_receive_free_ncci
326 // Reads a freed NCCI notification and calls capi_ll_control().
328 // iavc_receive_task_ready
329 // Reads a task ready message -- which should not occur XXX.
331 // iavc_receive_debugmsg
332 // Reads a debug message -- which should not occur XXX.
334 // iavc_receive_start
335 // Reads a START TRANSMIT message and unblocks device.
338 // Reads a STOP TRANSMIT message and blocks device.
341 // Reads an incoming message and calls capi_ll_receive().
344 static int iavc_receive_init(iavc_softc_t *sc, u_int8_t *dmabuf)
348 u_int8_t *cardtype, *serial, *profile, *version, *caps, *prot;
351 p = amcc_get_word(dmabuf, &Length);
353 Length = iavc_get_slice(sc, sc->sc_recvbuf);
360 printf("iavc%d: rx_init: ", sc->sc_unit);
361 while (len < Length) {
362 printf(" %02x", p[len]);
363 if (len && (len % 16) == 0) printf("\n");
366 if (len % 16) printf("\n");
371 p += (*p + 1); /* driver version */
373 p += (*p + 1); /* card type */
374 p += (*p + 1); /* hardware ID */
376 p += (*p + 1); /* serial number */
378 p += (*p + 1); /* supported options */
380 p += (*p + 1); /* supported protocols */
383 if (cardtype && serial && profile) {
384 int nbch = ((profile[3]<<8) | profile[2]);
386 printf("iavc%d: AVM %s, s/n %s, %d chans, f/w rev %s, prot %s\n",
387 sc->sc_unit, cardtype, serial, nbch, version, prot);
390 printf("iavc%d: %s\n", sc->sc_unit, caps);
392 capi_ll_control(&sc->sc_capi, CAPI_CTRL_PROFILE, (int) profile);
395 printf("iavc%d: no profile data in info response?\n", sc->sc_unit);
398 sc->sc_blocked = TRUE; /* controller will send START when ready */
402 static int iavc_receive_start(iavc_softc_t *sc, u_int8_t *dmabuf)
404 struct mbuf *m = i4b_Dgetmbuf(3);
407 if (sc->sc_blocked && sc->sc_state == IAVC_UP)
408 printf("iavc%d: receive_start\n", sc->sc_unit);
411 printf("iavc%d: can't get memory\n", sc->sc_unit);
416 * byte 0x73 = SEND_POLLACK
419 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
420 p = amcc_put_byte(p, 0);
421 p = amcc_put_byte(p, SEND_POLLACK);
423 _IF_PREPEND(&sc->sc_txq, m);
425 NDBGL4(L4_IAVCDBG, "iavc%d: blocked = %d, state = %d",
426 sc->sc_unit, sc->sc_blocked, sc->sc_state);
428 sc->sc_blocked = FALSE;
431 /* If this was our first START, register our readiness */
433 if (sc->sc_state != IAVC_UP) {
434 sc->sc_state = IAVC_UP;
435 capi_ll_control(&sc->sc_capi, CAPI_CTRL_READY, TRUE);
441 static int iavc_receive_stop(iavc_softc_t *sc, u_int8_t *dmabuf)
443 printf("iavc%d: receive_stop\n", sc->sc_unit);
444 sc->sc_blocked = TRUE;
448 static int iavc_receive_new_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
450 u_int32_t ApplId, NCCI, WindowSize;
453 dmabuf = amcc_get_word(dmabuf, &ApplId);
454 dmabuf = amcc_get_word(dmabuf, &NCCI);
455 dmabuf = amcc_get_word(dmabuf, &WindowSize);
457 ApplId = iavc_get_word(sc);
458 NCCI = iavc_get_word(sc);
459 WindowSize = iavc_get_word(sc);
462 capi_ll_control(&sc->sc_capi, CAPI_CTRL_NEW_NCCI, NCCI);
466 static int iavc_receive_free_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
468 u_int32_t ApplId, NCCI;
471 dmabuf = amcc_get_word(dmabuf, &ApplId);
472 dmabuf = amcc_get_word(dmabuf, &NCCI);
474 ApplId = iavc_get_word(sc);
475 NCCI = iavc_get_word(sc);
478 capi_ll_control(&sc->sc_capi, CAPI_CTRL_FREE_NCCI, NCCI);
482 static int iavc_receive_task_ready(iavc_softc_t *sc, u_int8_t *dmabuf)
484 u_int32_t TaskId, Length;
486 printf("iavc%d: receive_task_ready\n", sc->sc_unit);
489 p = amcc_get_word(dmabuf, &TaskId);
490 p = amcc_get_word(p, &Length);
492 TaskId = iavc_get_word(sc);
493 Length = iavc_get_slice(sc, sc->sc_recvbuf);
497 /* XXX could show the message if trace enabled? XXX */
501 static int iavc_receive_debugmsg(iavc_softc_t *sc, u_int8_t *dmabuf)
505 printf("iavc%d: receive_debugmsg\n", sc->sc_unit);
508 p = amcc_get_word(dmabuf, &Length);
510 Length = iavc_get_slice(sc, sc->sc_recvbuf);
514 /* XXX could show the message if trace enabled? XXX */
518 static int iavc_receive(iavc_softc_t *sc, u_int8_t *dmabuf, int b3data)
521 u_int32_t ApplId, Length;
524 * byte 0x21 = RECEIVE_MESSAGE
531 * byte 0x22 = RECEIVE_DATA_B3_IND
540 dmabuf = amcc_get_word(dmabuf, &ApplId);
541 dmabuf = amcc_get_word(dmabuf, &Length);
543 ApplId = iavc_get_word(sc);
544 Length = iavc_get_slice(sc, sc->sc_recvbuf);
545 dmabuf = sc->sc_recvbuf;
548 m = i4b_Dgetmbuf(Length);
550 printf("iavc%d: can't get memory for receive\n", sc->sc_unit);
554 bcopy(dmabuf, mtod(m, u_int8_t*), Length);
558 u_int8_t *p = mtod(m, u_int8_t*);
560 printf("iavc%d: applid=%d, len=%d\n", sc->sc_unit, ApplId, Length);
561 while (len < m->m_len) {
562 printf(" %02x", p[len]);
563 if (len && (len % 16) == 0) printf("\n");
566 if (len % 16) printf("\n");
572 dmabuf = amcc_get_word(dmabuf + Length, &Length);
574 Length = iavc_get_slice(sc, sc->sc_recvbuf);
575 dmabuf = sc->sc_recvbuf;
578 m->m_next = i4b_Bgetmbuf(Length);
580 printf("iavc%d: can't get memory for receive\n", sc->sc_unit);
585 bcopy(dmabuf, mtod(m->m_next, u_int8_t*), Length);
588 capi_ll_receive(&sc->sc_capi, m);
594 // Checks device interrupt status and calls iavc_handle_{rx,tx}()
598 // Reads in the command byte and calls the subroutines above.
601 // Initiates DMA on the next queued message if possible.
604 void iavc_handle_intr(iavc_softc_t *sc)
610 while (iavc_rx_full(sc))
615 status = AMCC_READ(sc, AMCC_INTCSR);
616 if ((status & ANY_S5933_INT) == 0)
619 newcsr = sc->sc_csr | (status & ALL_INT);
620 if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
621 if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
622 AMCC_WRITE(sc, AMCC_INTCSR, newcsr);
625 if (status & RX_TC_INT) {
628 if (sc->sc_recvlen == 0) {
629 sc->sc_recvlen = *((u_int32_t*)(&sc->sc_recvbuf[0]));
630 rxlen = (sc->sc_recvlen + 3) & ~3;
631 AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[4]));
632 AMCC_WRITE(sc, AMCC_RXLEN, rxlen);
636 AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[0]));
637 AMCC_WRITE(sc, AMCC_RXLEN, 4);
641 if (status & TX_TC_INT) {
642 sc->sc_csr &= ~EN_TX_TC_INT;
646 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
650 static void iavc_handle_rx(iavc_softc_t *sc)
652 u_int8_t *dmabuf = 0, cmd;
655 dmabuf = amcc_get_byte(&sc->sc_recvbuf[4], &cmd);
657 cmd = iavc_get_byte(sc);
660 NDBGL4(L4_IAVCDBG, "iavc%d: command = 0x%02x", sc->sc_unit, cmd);
663 case RECEIVE_DATA_B3_IND:
664 iavc_receive(sc, dmabuf, TRUE);
667 case RECEIVE_MESSAGE:
668 iavc_receive(sc, dmabuf, FALSE);
671 case RECEIVE_NEW_NCCI:
672 iavc_receive_new_ncci(sc, dmabuf);
675 case RECEIVE_FREE_NCCI:
676 iavc_receive_free_ncci(sc, dmabuf);
680 iavc_receive_start(sc, dmabuf);
684 iavc_receive_stop(sc, dmabuf);
688 iavc_receive_init(sc, dmabuf);
691 case RECEIVE_TASK_READY:
692 iavc_receive_task_ready(sc, dmabuf);
695 case RECEIVE_DEBUGMSG:
696 iavc_receive_debugmsg(sc, dmabuf);
700 printf("iavc%d: unknown msg %02x\n", sc->sc_unit, cmd);
704 static void iavc_start_tx(iavc_softc_t *sc)
710 /* If device has put us on hold, punt. */
712 if (sc->sc_blocked) {
716 /* If using DMA and transmitter busy, punt. */
718 if (sc->sc_dma && (sc->sc_csr & EN_TX_TC_INT)) {
722 /* Else, see if we have messages to send. */
724 _IF_DEQUEUE(&sc->sc_txq, m);
729 /* Have message, will send. */
731 if (CAPIMSG_LEN(m->m_data)) {
732 /* A proper CAPI message, possibly with B3 data */
735 /* Copy message to DMA buffer. */
738 dmabuf = amcc_put_byte(&sc->sc_sendbuf[0], SEND_DATA_B3_REQ);
740 dmabuf = amcc_put_byte(&sc->sc_sendbuf[0], SEND_MESSAGE);
743 dmabuf = amcc_put_word(dmabuf, m->m_len);
744 bcopy(m->m_data, dmabuf, m->m_len);
746 txlen = 5 + m->m_len;
749 dmabuf = amcc_put_word(dmabuf, m->m_next->m_len);
750 bcopy(m->m_next->m_data, dmabuf, m->m_next->m_len);
751 txlen += 4 + m->m_next->m_len;
758 iavc_put_byte(sc, SEND_DATA_B3_REQ);
759 NDBGL4(L4_IAVCDBG, "iavc%d: tx SDB3R msg, len = %d", sc->sc_unit, m->m_len);
761 iavc_put_byte(sc, SEND_MESSAGE);
762 NDBGL4(L4_IAVCDBG, "iavc%d: tx SM msg, len = %d", sc->sc_unit, m->m_len);
766 u_int8_t *p = mtod(m, u_int8_t*);
768 for (len = 0; len < m->m_len; len++) {
769 printf(" %02x", *p++);
770 if (len && (len % 16) == 0) printf("\n");
772 if (len % 16) printf("\n");
776 iavc_put_slice(sc, m->m_data, m->m_len);
779 iavc_put_slice(sc, m->m_next->m_data, m->m_next->m_len);
784 /* A board control message to be sent as is */
787 bcopy(m->m_data + 2, &sc->sc_sendbuf[0], m->m_len - 2);
788 txlen = m->m_len - 2;
793 u_int8_t *p = mtod(m, u_int8_t*) + 2;
795 printf("iavc%d: tx BDC msg, len = %d, msg =", sc->sc_unit, m->m_len-2);
796 for (len = 0; len < m->m_len-2; len++) {
797 printf(" %02x", *p++);
798 if (len && (len % 16) == 0) printf("\n");
800 if (len % 16) printf("\n");
804 txlen = m->m_len - 2;
805 dmabuf = mtod(m, char*) + 2;
807 b1io_put_byte(sc, *dmabuf++);
812 i4b_Bfreembuf(m->m_next);
818 /* Start transmitter */
820 txlen = (txlen + 3) & ~3;
821 AMCC_WRITE(sc, AMCC_TXPTR, vtophys(&sc->sc_sendbuf[0]));
822 AMCC_WRITE(sc, AMCC_TXLEN, txlen);
823 sc->sc_csr |= EN_TX_TC_INT;
826 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
830 int t1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
833 len = i = b1io_get_word(sc);
834 if (t1io_isfastlink(sc)) {
837 status = t1io_fifostatus(sc) & (T1F_IREADY|T1F_IHALF);
838 if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
841 case T1F_IREADY|T1F_IHALF|T1F_IFULL:
842 bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
843 T1_READ, dp, FIFO_INPBSIZE);
848 case T1F_IREADY|T1F_IHALF:
849 bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
856 *dp++ = b1io_get_byte(sc);
860 } else { /* not fastlink */
861 if (i--) *dp++ = b1io_get_byte(sc);
866 void t1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
869 b1io_put_word(sc, i);
870 if (t1io_isfastlink(sc)) {
873 status = t1io_fifostatus(sc) & (T1F_OREADY|T1F_OHALF);
874 if (i >= FIFO_OUTBSIZE) status |= T1F_OFULL;
877 case T1F_OREADY|T1F_OHALF|T1F_OFULL:
878 bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
879 T1_WRITE, dp, FIFO_OUTBSIZE);
884 case T1F_OREADY|T1F_OHALF:
885 bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
892 b1io_put_byte(sc, *dp++);
897 while (i--) b1io_put_byte(sc, *dp++);
901 u_int32_t b1io_get_word(iavc_softc_t *sc)
904 val |= b1io_get_byte(sc);
905 val |= (b1io_get_byte(sc) << 8);
906 val |= (b1io_get_byte(sc) << 16);
907 val |= (b1io_get_byte(sc) << 24);
911 void b1io_put_word(iavc_softc_t *sc, u_int32_t val)
913 b1io_put_byte(sc, (val & 0xff));
914 b1io_put_byte(sc, (val >> 8) & 0xff);
915 b1io_put_byte(sc, (val >> 16) & 0xff);
916 b1io_put_byte(sc, (val >> 24) & 0xff);
919 int b1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
922 len = i = b1io_get_word(sc);
923 while (i--) *dp++ = b1io_get_byte(sc);
927 void b1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
929 b1io_put_word(sc, len);
930 while (len--) b1io_put_byte(sc, *dp++);
933 u_int32_t b1io_read_reg(iavc_softc_t *sc, int reg)
935 b1io_put_byte(sc, READ_REGISTER);
936 b1io_put_word(sc, reg);
937 return b1io_get_word(sc);
940 u_int32_t b1io_write_reg(iavc_softc_t *sc, int reg, u_int32_t val)
942 b1io_put_byte(sc, WRITE_REGISTER);
943 b1io_put_word(sc, reg);
944 b1io_put_word(sc, val);
945 return b1io_get_word(sc);
948 u_int8_t b1io_get_byte(iavc_softc_t *sc)
951 while (!b1io_rx_full(sc) && spin < B1IO_WAIT_MAX) {
952 spin++; DELAY(B1IO_WAIT_DLY);
954 if (b1io_rx_full(sc))
955 return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_READ);
956 printf("iavc%d: rx not completed\n", sc->sc_unit);
960 int b1io_put_byte(iavc_softc_t *sc, u_int8_t val)
963 while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
964 spin++; DELAY(B1IO_WAIT_DLY);
966 if (b1io_tx_empty(sc)) {
967 bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, B1_WRITE, val);
970 printf("iavc%d: tx not emptied\n", sc->sc_unit);
974 int b1io_save_put_byte(iavc_softc_t *sc, u_int8_t val)
977 while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
978 spin++; DELAY(B1IO_WAIT_DLY);
980 if (b1io_tx_empty(sc)) {
981 b1io_outp(sc, B1_WRITE, val);
984 printf("iavc%d: tx not emptied\n", sc->sc_unit);