static void iavc_pci_attach(device_t parent, device_t self, void *aux) { struct iavc_pci_softc *psc = device_private(self); struct iavc_softc *sc = &psc->sc_iavc; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; const struct iavc_pci_product *pp; pci_intr_handle_t ih; const char *intrstr; int ret; char intrbuf[PCI_INTRSTR_LEN]; pp = find_cardname(pa); if (pp == NULL) return; sc->sc_dev = self; sc->sc_t1 = 0; sc->sc_dma = 0; sc->dmat = pa->pa_dmat; if (pci_mapreg_map(pa, IAVC_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, &sc->sc_io_bt, &sc->sc_io_bh, &psc->io_base, &psc->io_size)) { aprint_error(": unable to map i/o registers\n"); return; } if (pci_mapreg_map(pa, IAVC_PCI_MMBA, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem_bt, &sc->sc_mem_bh, &psc->mem_base, &psc->mem_size)) { aprint_error(": unable to map mem registers\n"); return; } aprint_normal(": %s\n", pp->name); iavc_b1dma_reset(sc); if (pp->npp_product == PCI_PRODUCT_AVM_T1) { aprint_error_dev(sc->sc_dev, "sorry, PRI not yet supported\n"); return; #if 0 sc->sc_capi.card_type = CARD_TYPEC_AVM_T1_PCI; sc->sc_capi.sc_nbch = NBCH_PRI; ret = iavc_t1_detect(sc); if (ret) { if (ret < 6) { aprint_error_dev(sc->sc_dev, "no card detected?\n"); } else { aprint_error_dev(sc->sc_dev, "black box not on\n"); } return; } else { sc->sc_dma = 1; sc->sc_t1 = 1; } #endif } else if (pp->npp_product == PCI_PRODUCT_AVM_B1) { sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_PCI; sc->sc_capi.sc_nbch = NBCH_BRI; ret = iavc_b1dma_detect(sc); if (ret) { ret = iavc_b1_detect(sc); if (ret) { aprint_error_dev(sc->sc_dev, "no card detected?\n"); return; } } else { sc->sc_dma = 1; } } if (sc->sc_dma) iavc_b1dma_reset(sc); #if 0 /* * XXX: should really be done this way, but this freezes the card */ if (sc->sc_t1) iavc_t1_reset(sc); else iavc_b1_reset(sc); #endif if (pci_intr_map(pa, &ih)) { aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, iavc_pci_intr, psc); if (psc->sc_ih == NULL) { aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); return; } psc->sc_pc = pc; aprint_normal("%s: interrupting at %s\n", device_xname(sc->sc_dev), intrstr); memset(&sc->sc_txq, 0, sizeof(struct ifqueue)); sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4; sc->sc_intr = 0; sc->sc_state = IAVC_DOWN; sc->sc_blocked = 0; /* setup capi link */ sc->sc_capi.load = iavc_load; sc->sc_capi.reg_appl = iavc_register; sc->sc_capi.rel_appl = iavc_release; sc->sc_capi.send = iavc_send; sc->sc_capi.ctx = (void *) sc; /* lock & load DMA for TX */ if ((ret = bus_dmamem_alloc(sc->dmat, IAVC_DMA_SIZE, PAGE_SIZE, 0, &sc->txseg, 1, &sc->ntxsegs, BUS_DMA_ALLOCNOW)) != 0) { aprint_error_dev(sc->sc_dev, "can't allocate tx DMA memory, error = %d\n", ret); goto fail1; } if ((ret = bus_dmamem_map(sc->dmat, &sc->txseg, sc->ntxsegs, IAVC_DMA_SIZE, &sc->sc_sendbuf, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(sc->sc_dev, "can't map tx DMA memory, error = %d\n", ret); goto fail2; } if ((ret = bus_dmamap_create(sc->dmat, IAVC_DMA_SIZE, 1, IAVC_DMA_SIZE, 0, BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT, &sc->tx_map)) != 0) { aprint_error_dev(sc->sc_dev, "can't create tx DMA map, error = %d\n", ret); goto fail3; } if ((ret = bus_dmamap_load(sc->dmat, sc->tx_map, sc->sc_sendbuf, IAVC_DMA_SIZE, NULL, BUS_DMA_WRITE | BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(sc->sc_dev, "can't load tx DMA map, error = %d\n", ret); goto fail4; } /* do the same for RX */ if ((ret = bus_dmamem_alloc(sc->dmat, IAVC_DMA_SIZE, PAGE_SIZE, 0, &sc->rxseg, 1, &sc->nrxsegs, BUS_DMA_ALLOCNOW)) != 0) { aprint_error_dev(sc->sc_dev, "can't allocate rx DMA memory, error = %d\n", ret); goto fail5; } if ((ret = bus_dmamem_map(sc->dmat, &sc->rxseg, sc->nrxsegs, IAVC_DMA_SIZE, &sc->sc_recvbuf, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(sc->sc_dev, "can't map rx DMA memory, error = %d\n", ret); goto fail6; } if ((ret = bus_dmamap_create(sc->dmat, IAVC_DMA_SIZE, 1, IAVC_DMA_SIZE, 0, BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT, &sc->rx_map)) != 0) { aprint_error_dev(sc->sc_dev, "can't create rx DMA map, error = %d\n", ret); goto fail7; } if ((ret = bus_dmamap_load(sc->dmat, sc->rx_map, sc->sc_recvbuf, IAVC_DMA_SIZE, NULL, BUS_DMA_READ | BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(sc->sc_dev, "can't load rx DMA map, error = %d\n", ret); goto fail8; } if (capi_ll_attach(&sc->sc_capi, device_xname(sc->sc_dev), pp->name)) { aprint_error_dev(sc->sc_dev, "capi attach failed\n"); goto fail9; } return; /* release resources in case of failed attach */ fail9: bus_dmamap_unload(sc->dmat, sc->rx_map); fail8: bus_dmamap_destroy(sc->dmat, sc->rx_map); fail7: bus_dmamem_unmap(sc->dmat, sc->sc_recvbuf, IAVC_DMA_SIZE); fail6: bus_dmamem_free(sc->dmat, &sc->rxseg, sc->nrxsegs); fail5: bus_dmamap_unload(sc->dmat, sc->tx_map); fail4: bus_dmamap_destroy(sc->dmat, sc->tx_map); fail3: bus_dmamem_unmap(sc->dmat, sc->sc_sendbuf, IAVC_DMA_SIZE); fail2: bus_dmamem_free(sc->dmat, &sc->txseg, sc->ntxsegs); fail1: pci_intr_disestablish(psc->sc_pc, psc->sc_ih); return; }
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; }