FreeBSD/sys/dev/ppc/ppc_isa.c
/*
 * Call this function if you want to send data in any advanced mode
 * of your parallel port: FIFO, DMA
 *
 * If what you want is not possible (no ECP, no DMA...),
 * EINVAL is returned
 */
Call this function if you want to send data in any advanced mode
of your parallel port: FIFO, DMA

If what you want is not possible (no ECP, no DMA...),
EINVAL is returned
Call this function if you want to send data in any advanced mode of your parallel port : FIFO DMA If what you want is not possible ( no ECP no DMA ... ) EINVAL is returned
int
ppc_isa_write(device_t dev, char *buf, int len, int how)
{
	struct ppc_data *ppc = device_get_softc(dev);
	char ecr, ecr_sav, ctr, ctr_sav;
	int error = 0;
	int spin;
	PPC_ASSERT_LOCKED(ppc);
	if (!(ppc->ppc_avm & PPB_ECP))
		return (EINVAL);
	if (ppc->ppc_dmachan == 0)
		return (EINVAL);
#ifdef PPC_DEBUG
	printf("w");
#endif
	ecr_sav = r_ecr(ppc);
	ctr_sav = r_ctr(ppc);
	ecr = PPC_ECR_STD | PPC_DISABLE_INTR;
	w_ecr(ppc, ecr);
	ctr = r_ctr(ppc);
	ctr &= ~IRQENABLE;
	w_ctr(ppc, ctr);
	ppc->ppc_dmaflags = 0;
	ppc->ppc_dmaddr = (caddr_t)buf;
	ppc->ppc_dmacnt = (u_int)len;
	switch (ppc->ppc_mode) {
	case PPB_COMPATIBLE:
		ecr = PPC_ECR_FIFO | PPC_DISABLE_INTR | PPC_ENABLE_DMA;
		break;
	case PPB_ECP:
		ecr = PPC_ECR_ECP | PPC_DISABLE_INTR | PPC_ENABLE_DMA;
		break;
	default:
		error = EINVAL;
		goto error;
	}
	w_ecr(ppc, ecr);
	ecr = r_ecr(ppc);
	ppc->ppc_dmastat = PPC_DMA_INIT;
	ecr &= ~PPC_SERVICE_INTR;
	ppc->ppc_irqstat = PPC_IRQ_DMA;
	w_ecr(ppc, ecr);
	isa_dmastart(ppc->ppc_dmaflags, ppc->ppc_dmaddr, ppc->ppc_dmacnt,
		     ppc->ppc_dmachan);
	ppc->ppc_dmastat = PPC_DMA_STARTED;
#ifdef PPC_DEBUG
	printf("s%d", ppc->ppc_dmacnt);
#endif
	do {
		error = mtx_sleep(ppc, &ppc->ppc_lock, PPBPRI | PCATCH,
		    "ppcdma", 0);
	} while (error == EWOULDBLOCK);
	if (error) {
#ifdef PPC_DEBUG
		printf("i");
#endif
		isa_dmadone(ppc->ppc_dmaflags, ppc->ppc_dmaddr,
			    ppc->ppc_dmacnt, ppc->ppc_dmachan);
		w_ecr(ppc, PPC_ECR_RESET);
		ppc->ppc_dmastat = PPC_DMA_INTERRUPTED;
		goto error;
	}
	while (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) {
		for (spin=100; spin; spin--)
			if (r_ecr(ppc) & PPC_FIFO_EMPTY)
				goto fifo_empty;
#ifdef PPC_DEBUG
		printf("Z");
#endif
		error = mtx_sleep(ppc, &ppc->ppc_lock, PPBPRI | PCATCH,
		    "ppcfifo", hz / 100);
		if (error != EWOULDBLOCK) {
#ifdef PPC_DEBUG
			printf("I");
#endif
			w_ecr(ppc, PPC_ECR_RESET);
			ppc->ppc_dmastat = PPC_DMA_INTERRUPTED;
			error = EINTR;
			goto error;
		}
	}
fifo_empty:
	w_ecr(ppc, PPC_ECR_RESET);
error:
	DELAY(1);
	w_ecr(ppc, ecr_sav);
	w_ctr(ppc, ctr_sav);
	return (error);
}
int ppc_isa_write ( device_t dev , char * buf , int len , int how ) { struct ppc_data * ppc = device_get_softc ( dev ) ; char ecr , ecr_sav , ctr , ctr_sav ; int error = 0 ; int spin ; PPC_ASSERT_LOCKED ( ppc ) ; if ( ! ( ppc -> ppc_avm & PPB_ECP ) ) return ( EINVAL ) ; if ( ppc -> ppc_dmachan == 0 ) return ( EINVAL ) ; #ifdef PPC_DEBUG printf ( " " ) ; #endif ecr_sav = r_ecr ( ppc ) ; ctr_sav = r_ctr ( ppc ) ; ecr = PPC_ECR_STD | PPC_DISABLE_INTR ; w_ecr ( ppc , ecr ) ; ctr = r_ctr ( ppc ) ; ctr &= ~ IRQENABLE ; w_ctr ( ppc , ctr ) ; ppc -> ppc_dmaflags = 0 ; ppc -> ppc_dmaddr = ( caddr_t ) buf ; ppc -> ppc_dmacnt = ( u_int ) len ; switch ( ppc -> ppc_mode ) { case PPB_COMPATIBLE : ecr = PPC_ECR_FIFO | PPC_DISABLE_INTR | PPC_ENABLE_DMA ; break ; case PPB_ECP : ecr = PPC_ECR_ECP | PPC_DISABLE_INTR | PPC_ENABLE_DMA ; break ; default : error = EINVAL ; goto error ; } w_ecr ( ppc , ecr ) ; ecr = r_ecr ( ppc ) ; ppc -> ppc_dmastat = PPC_DMA_INIT ; ecr &= ~ PPC_SERVICE_INTR ; ppc -> ppc_irqstat = PPC_IRQ_DMA ; w_ecr ( ppc , ecr ) ; isa_dmastart ( ppc -> ppc_dmaflags , ppc -> ppc_dmaddr , ppc -> ppc_dmacnt , ppc -> ppc_dmachan ) ; ppc -> ppc_dmastat = PPC_DMA_STARTED ; #ifdef PPC_DEBUG printf ( " " , ppc -> ppc_dmacnt ) ; #endif do { error = mtx_sleep ( ppc , & ppc -> ppc_lock , PPBPRI | PCATCH , " " , 0 ) ; } while ( error == EWOULDBLOCK ) ; if ( error ) { #ifdef PPC_DEBUG printf ( " " ) ; #endif isa_dmadone ( ppc -> ppc_dmaflags , ppc -> ppc_dmaddr , ppc -> ppc_dmacnt , ppc -> ppc_dmachan ) ; w_ecr ( ppc , PPC_ECR_RESET ) ; ppc -> ppc_dmastat = PPC_DMA_INTERRUPTED ; goto error ; } while ( ! ( r_ecr ( ppc ) & PPC_FIFO_EMPTY ) ) { for ( spin = 100 ; spin ; spin -- ) if ( r_ecr ( ppc ) & PPC_FIFO_EMPTY ) goto fifo_empty ; #ifdef PPC_DEBUG printf ( " " ) ; #endif error = mtx_sleep ( ppc , & ppc -> ppc_lock , PPBPRI | PCATCH , " " , hz / 100 ) ; if ( error != EWOULDBLOCK ) { #ifdef PPC_DEBUG printf ( " " ) ; #endif w_ecr ( ppc , PPC_ECR_RESET ) ; ppc -> ppc_dmastat = PPC_DMA_INTERRUPTED ; error = EINTR ; goto error ; } } fifo_empty : w_ecr ( ppc , PPC_ECR_RESET ) ; error : DELAY ( 1 ) ; w_ecr ( ppc , ecr_sav ) ; w_ctr ( ppc , ctr_sav ) ; return ( error ) ; }
Call this function if you want to send data in any advanced mode
 of your parallel port: FIFO, DMA
Call this function if you want to send data in any advanced mode of your parallel port : FIFO DMA
/*
	 * Send buffer with DMA, FIFO and interrupts
	 */ /* byte mode, no intr, no DMA, dir=0, flush fifo */ /* disable nAck interrupts */ /* compatible mode with FIFO, no intr, DMA, dir=0 */ /* enable interrupts */ /* Wait for the DMA completed interrupt. We hope we won't
	 * miss it, otherwise a signal will be necessary to unlock the
	 * process.
	 */ /* release CPU */ /* stop DMA */ /* no dma, no interrupt, flush the fifo */ /* wait for an empty fifo */ /* no dma, no interrupt, flush the fifo */ /* no dma, no interrupt, flush the fifo */ /* PDRQ must be kept unasserted until nPDACK is
	 * deasserted for a minimum of 350ns (SMC datasheet)
	 *
	 * Consequence may be a FIFO that never empty
	 */