static void iavc_start_tx(iavc_softc_t *sc) { struct mbuf *m; u_int32_t txlen; /* If device has put us on hold, punt. */ if (sc->sc_blocked) { return; } /* If using DMA and transmitter busy, punt. */ if (sc->sc_dma && (sc->sc_csr & EN_TX_TC_INT)) { return; } /* Else, see if we have messages to send. */ IF_DEQUEUE(&sc->sc_txq, m); if (!m) { return; } /* Have message, will send. */ if (CAPIMSG_LEN(m->m_data)) { /* A proper CAPI message, possibly with B3 data */ txlen = iavc_tx_capimsg(sc, m); } else { /* A board control message to be sent as is */ txlen = iavc_tx_ctrlmsg(sc, m); } if (m->m_next) { i4b_Bfreembuf(m->m_next); m->m_next = NULL; } i4b_Dfreembuf(m); /* Kick DMA into motion if applicable */ if (sc->sc_dma) { txlen = (txlen + 3) & ~3; bus_dmamap_sync(sc->dmat, sc->tx_map, 0, txlen, BUS_DMASYNC_PREWRITE); AMCC_WRITE(sc, AMCC_TXPTR, sc->tx_map->dm_segs[0].ds_addr); AMCC_WRITE(sc, AMCC_TXLEN, txlen); sc->sc_csr |= EN_TX_TC_INT; if (!sc->sc_intr) AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); } }
int iavc_b1dma_detect(iavc_softc_t *sc) { AMCC_WRITE(sc, AMCC_MCSR, 0); DELAY(10*1000); AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000); DELAY(10*1000); AMCC_WRITE(sc, AMCC_MCSR, 0); DELAY(42*1000); AMCC_WRITE(sc, AMCC_RXLEN, 0); AMCC_WRITE(sc, AMCC_TXLEN, 0); sc->sc_csr = 0; AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); if (AMCC_READ(sc, AMCC_INTCSR) != 0) return 1; AMCC_WRITE(sc, AMCC_RXPTR, 0xffffffff); AMCC_WRITE(sc, AMCC_TXPTR, 0xffffffff); if ((AMCC_READ(sc, AMCC_RXPTR) != 0xfffffffc) || (AMCC_READ(sc, AMCC_TXPTR) != 0xfffffffc)) return 2; AMCC_WRITE(sc, AMCC_RXPTR, 0); AMCC_WRITE(sc, AMCC_TXPTR, 0); if ((AMCC_READ(sc, AMCC_RXPTR) != 0) || (AMCC_READ(sc, AMCC_TXPTR) != 0)) return 3; iavc_write_port(sc, 0x10, 0x00); iavc_write_port(sc, 0x07, 0x00); iavc_write_port(sc, 0x02, 0x02); iavc_write_port(sc, 0x03, 0x02); if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x02) || (iavc_read_port(sc, 0x03) != 0x03)) return 4; iavc_write_port(sc, 0x02, 0x00); iavc_write_port(sc, 0x03, 0x00); if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x00) || (iavc_read_port(sc, 0x03) != 0x01)) return 5; return (0); /* found */ }
int iavc_handle_intr(iavc_softc_t *sc) { u_int32_t status; u_int32_t newcsr; if (!sc->sc_dma) { while (iavc_rx_full(sc)) iavc_handle_rx(sc); return 0; } status = AMCC_READ(sc, AMCC_INTCSR); if ((status & ANY_S5933_INT) == 0) return 0; newcsr = sc->sc_csr | (status & ALL_INT); if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT; AMCC_WRITE(sc, AMCC_INTCSR, newcsr); sc->sc_intr = 1; if (status & RX_TC_INT) { u_int32_t rxlen; bus_dmamap_sync(sc->dmat, sc->rx_map, 0, sc->rx_map->dm_mapsize, BUS_DMASYNC_POSTREAD); if (sc->sc_recv1 == 0) { sc->sc_recv1 = *(u_int32_t*)(sc->sc_recvbuf); rxlen = (sc->sc_recv1 + 3) & ~3; AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr); AMCC_WRITE(sc, AMCC_RXLEN, rxlen ? rxlen : 4); } else { iavc_handle_rx(sc); sc->sc_recv1 = 0; AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr); AMCC_WRITE(sc, AMCC_RXLEN, 4); } } if (status & TX_TC_INT) { bus_dmamap_sync(sc->dmat, sc->tx_map, 0, sc->tx_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); sc->sc_csr &= ~EN_TX_TC_INT; iavc_start_tx(sc); } AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); sc->sc_intr = 0; return 0; }
void iavc_handle_intr(iavc_softc_t *sc) { u_int32_t status; u_int32_t newcsr; if (!sc->sc_dma) { while (iavc_rx_full(sc)) iavc_handle_rx(sc); return; } status = AMCC_READ(sc, AMCC_INTCSR); if ((status & ANY_S5933_INT) == 0) return; newcsr = sc->sc_csr | (status & ALL_INT); if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT; AMCC_WRITE(sc, AMCC_INTCSR, newcsr); sc->sc_intr = TRUE; if (status & RX_TC_INT) { u_int32_t rxlen; if (sc->sc_recvlen == 0) { sc->sc_recvlen = *((u_int32_t*)(&sc->sc_recvbuf[0])); rxlen = (sc->sc_recvlen + 3) & ~3; AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[4])); AMCC_WRITE(sc, AMCC_RXLEN, rxlen); } else { iavc_handle_rx(sc); sc->sc_recvlen = 0; AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[0])); AMCC_WRITE(sc, AMCC_RXLEN, 4); } } if (status & TX_TC_INT) { sc->sc_csr &= ~EN_TX_TC_INT; iavc_start_tx(sc); } AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); sc->sc_intr = FALSE; }
void b1dma_reset(iavc_softc_t *sc) { int s = SPLI4B(); sc->sc_csr = 0; AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); AMCC_WRITE(sc, AMCC_MCSR, 0); AMCC_WRITE(sc, AMCC_RXLEN, 0); AMCC_WRITE(sc, AMCC_TXLEN, 0); iavc_write_port(sc, 0x10, 0x00); /* XXX magic numbers from */ iavc_write_port(sc, 0x07, 0x00); /* XXX the linux driver */ splx(s); AMCC_WRITE(sc, AMCC_MCSR, 0); DELAY(10 * 1000); AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000); DELAY(10 * 1000); AMCC_WRITE(sc, AMCC_MCSR, 0); DELAY(42 * 1000); }
int iavc_load(capi_softc_t *capi_sc, int len, u_int8_t *cp) { iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx; u_int8_t val; aprint_debug_dev(&sc->sc_dev, "reset card ....\n"); if (sc->sc_dma) iavc_b1dma_reset(sc); /* PCI cards */ else if (sc->sc_t1) iavc_t1_reset(sc); /* ISA attachment T1 */ else iavc_b1_reset(sc); /* ISA attachment B1 */ DELAY(1000); aprint_debug_dev(&sc->sc_dev, "start loading %d bytes firmware\n", len); while (len && b1io_save_put_byte(sc, *cp++) == 0) len--; if (len) { aprint_error_dev(&sc->sc_dev, "loading failed, can't write to card, len = %d\n", len); return (EIO); } aprint_debug_dev(&sc->sc_dev, "firmware loaded, wait for ACK\n"); if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA) iavc_put_byte(sc, SEND_POLL); else iavc_put_byte(sc, SEND_POLLACK); for (len = 0; len < 1000 && !iavc_rx_full(sc); len++) DELAY(100); if (!iavc_rx_full(sc)) { aprint_error_dev(&sc->sc_dev, "loading failed, no ack\n"); return (EIO); } val = iavc_get_byte(sc); if ((sc->sc_dma && val != RECEIVE_POLLDWORD) || (!sc->sc_dma && val != RECEIVE_POLL)) { aprint_error_dev(&sc->sc_dev, "loading failed, bad ack = %02x\n", val); return (EIO); } aprint_debug_dev(&sc->sc_dev, "got ACK = 0x%02x\n", val); /* Start the DMA engine */ if (sc->sc_dma) { int s; s = splnet(); sc->sc_csr = AVM_FLAG; AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); AMCC_WRITE(sc, AMCC_MCSR, (EN_A2P_TRANSFERS|EN_P2A_TRANSFERS| A2P_HI_PRIORITY|P2A_HI_PRIORITY| RESET_A2P_FLAGS|RESET_P2A_FLAGS)); iavc_write_port(sc, 0x07, 0x30); /* XXX magic numbers from */ iavc_write_port(sc, 0x10, 0xf0); /* XXX the linux driver */ bus_dmamap_sync(sc->dmat, sc->rx_map, 0, sc->rx_map->dm_mapsize, BUS_DMASYNC_PREREAD); sc->sc_recv1 = 0; AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr); AMCC_WRITE(sc, AMCC_RXLEN, 4); sc->sc_csr |= EN_RX_TC_INT|EN_TX_TC_INT; AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); splx(s); } #ifdef notyet /* good happy place */ if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA) b1isa_setup_irq(sc); #endif iavc_send_init(sc); return 0; }
int iavc_load(capi_softc_t *capi_sc, int len, u_int8_t *cp) { iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx; u_int8_t val; if(bootverbose) printf("iavc%d: reset card ....\n", sc->sc_unit); if (sc->sc_dma) b1dma_reset(sc); /* PCI cards */ else if (sc->sc_t1) t1_reset(sc); /* ISA attachment T1 */ else b1_reset(sc); /* ISA attachment B1 */ DELAY(1000); if(bootverbose) printf("iavc%d: start loading %d bytes firmware ....\n", sc->sc_unit, len); while (len && b1io_save_put_byte(sc, *cp++) == 0) len--; if (len) { printf("iavc%d: loading failed, can't write to card, len = %d\n", sc->sc_unit, len); return (EIO); } if(bootverbose) printf("iavc%d: firmware loaded, wait for ACK ....\n", sc->sc_unit); if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA) iavc_put_byte(sc, SEND_POLL); else iavc_put_byte(sc, SEND_POLLACK); for (len = 0; len < 1000 && !iavc_rx_full(sc); len++) DELAY(100); if (!iavc_rx_full(sc)) { printf("iavc%d: loading failed, no ack\n", sc->sc_unit); return (EIO); } val = iavc_get_byte(sc); if ((sc->sc_dma && val != RECEIVE_POLLDWORD) || (!sc->sc_dma && val != RECEIVE_POLL)) { printf("iavc%d: loading failed, bad ack = %02x\n", sc->sc_unit, val); return (EIO); } if(bootverbose) printf("iavc%d: got ACK = 0x%02x\n", sc->sc_unit, val); if (sc->sc_dma) { /* Start the DMA engine */ int s = SPLI4B(); sc->sc_csr = AVM_FLAG; AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); AMCC_WRITE(sc, AMCC_MCSR, (EN_A2P_TRANSFERS|EN_P2A_TRANSFERS| A2P_HI_PRIORITY|P2A_HI_PRIORITY| RESET_A2P_FLAGS|RESET_P2A_FLAGS)); iavc_write_port(sc, 0x07, 0x30); /* XXX magic numbers from */ iavc_write_port(sc, 0x10, 0xf0); /* XXX the linux driver */ sc->sc_recvlen = 0; AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[0])); AMCC_WRITE(sc, AMCC_RXLEN, 4); sc->sc_csr |= EN_RX_TC_INT|EN_TX_TC_INT; AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr); splx(s); } if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA) b1isa_setup_irq(sc); iavc_send_init(sc); return 0; }