| 534 | } |
| 535 | |
| 536 | static int |
| 537 | zy7_devcfg_write(struct cdev *dev, struct uio *uio, int ioflag) |
| 538 | { |
| 539 | struct zy7_devcfg_softc *sc = dev->si_drv1; |
| 540 | void *dma_mem; |
| 541 | bus_addr_t dma_physaddr; |
| 542 | int segsz, err; |
| 543 | |
| 544 | DEVCFG_SC_LOCK(sc); |
| 545 | |
| 546 | /* First write? Reset PL. */ |
| 547 | if (uio->uio_offset == 0 && uio->uio_resid > 0) { |
| 548 | zy7_devcfg_init_hw(sc); |
| 549 | zy7_slcr_preload_pl(); |
| 550 | err = zy7_devcfg_reset_pl(sc); |
| 551 | if (err != 0) { |
| 552 | DEVCFG_SC_UNLOCK(sc); |
| 553 | return (err); |
| 554 | } |
| 555 | } |
| 556 | |
| 557 | /* Allocate dma memory and load. */ |
| 558 | err = bus_dmamem_alloc(sc->dma_tag, &dma_mem, BUS_DMA_NOWAIT, |
| 559 | &sc->dma_map); |
| 560 | if (err != 0) { |
| 561 | DEVCFG_SC_UNLOCK(sc); |
| 562 | return (err); |
| 563 | } |
| 564 | err = bus_dmamap_load(sc->dma_tag, sc->dma_map, dma_mem, PAGE_SIZE, |
| 565 | zy7_dma_cb2, &dma_physaddr, 0); |
| 566 | if (err != 0) { |
| 567 | bus_dmamem_free(sc->dma_tag, dma_mem, sc->dma_map); |
| 568 | DEVCFG_SC_UNLOCK(sc); |
| 569 | return (err); |
| 570 | } |
| 571 | |
| 572 | while (uio->uio_resid > 0) { |
| 573 | /* If DONE signal has been set, we shouldn't write anymore. */ |
| 574 | if ((RD4(sc, ZY7_DEVCFG_INT_STATUS) & |
| 575 | ZY7_DEVCFG_INT_PCFG_DONE) != 0) { |
| 576 | err = EIO; |
| 577 | break; |
| 578 | } |
| 579 | |
| 580 | /* uiomove the data from user buffer to our dma map. */ |
| 581 | segsz = MIN(PAGE_SIZE, uio->uio_resid); |
| 582 | DEVCFG_SC_UNLOCK(sc); |
| 583 | err = uiomove(dma_mem, segsz, uio); |
| 584 | DEVCFG_SC_LOCK(sc); |
| 585 | if (err != 0) |
| 586 | break; |
| 587 | |
| 588 | /* Flush the cache to memory. */ |
| 589 | bus_dmamap_sync(sc->dma_tag, sc->dma_map, |
| 590 | BUS_DMASYNC_PREWRITE); |
| 591 | |
| 592 | /* Program devcfg's DMA engine. The ordering of these |
| 593 | * register writes is critical. |
nothing calls this directly
no test coverage detected