FreeBSD/sys/x86/isa/isa_dma.c
/*
 * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
 * problems by using a bounce buffer.
 */
program 8237 DMA controller channel, avoid page alignment
problems by using a bounce buffer.
program 8237 DMA controller channel avoid page alignment problems by using a bounce buffer .
void
isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)
{
	vm_paddr_t phys;
	int waport;
	caddr_t newaddr;
	int dma_range_checked;
	dma_range_checked = isa_dmarangecheck(addr, nbytes, chan);
#ifdef DIAGNOSTIC
	if (chan & ~VALID_DMA_MASK)
		panic("isa_dmastart: channel out of range");
	if ((chan < 4 && nbytes > (1<<16))
	    || (chan >= 4 && (nbytes > (1<<17) || (uintptr_t)addr & 1)))
		panic("isa_dmastart: impossible request");
	mtx_lock(&isa_dma_lock);
	if ((dma_inuse & (1 << chan)) == 0)
		printf("isa_dmastart: channel %d not acquired\n", chan);
#else
	mtx_lock(&isa_dma_lock);
#endif
#if 0
	if (dma_busy & (1 << chan))
		printf("isa_dmastart: channel %d busy\n", chan);
#endif
	dma_busy |= (1 << chan);
	if (dma_range_checked) {
		if (dma_bouncebuf[chan] == NULL
		    || dma_bouncebufsize[chan] < nbytes)
			panic("isa_dmastart: bad bounce buffer"); 
		dma_bounced |= (1 << chan);
		newaddr = dma_bouncebuf[chan];
		if (!(flags & ISADMA_READ))
			bcopy(addr, newaddr, nbytes);
		addr = newaddr;
	}
	phys = pmap_extract(kernel_pmap, (vm_offset_t)addr);
	if (flags & ISADMA_RAW) {
	    dma_auto_mode |= (1 << chan);
	} else { 
	    dma_auto_mode &= ~(1 << chan);
	}
	if ((chan & 4) == 0) {
		if (flags & ISADMA_RAW) {
		  if (flags & ISADMA_READ)
			outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan);
		  else
			outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan);
		}
		else
		if (flags & ISADMA_READ)
			outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan);
		else
			outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan);
		outb(DMA1_FFC, 0);
		waport =  DMA1_CHN(chan);
		outb(waport, phys);
		outb(waport, phys>>8);
		outb(dmapageport[chan], phys>>16);
		outb(waport + 1, --nbytes);
		outb(waport + 1, nbytes>>8);
		outb(DMA1_SMSK, chan);
	} else {
		if (flags & ISADMA_RAW) {
		  if (flags & ISADMA_READ)
			outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3));
		  else
			outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3));
		}
		else
		if (flags & ISADMA_READ)
			outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3));
		else
			outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3));
		outb(DMA2_FFC, 0);
		waport = DMA2_CHN(chan - 4);
		outb(waport, phys>>1);
		outb(waport, phys>>9);
		outb(dmapageport[chan], phys>>16);
		nbytes >>= 1;
		outb(waport + 2, --nbytes);
		outb(waport + 2, nbytes>>8);
		outb(DMA2_SMSK, chan & 3);
	}
	mtx_unlock(&isa_dma_lock);
}
void isa_dmastart ( int flags , caddr_t addr , u_int nbytes , int chan ) { vm_paddr_t phys ; int waport ; caddr_t newaddr ; int dma_range_checked ; dma_range_checked = isa_dmarangecheck ( addr , nbytes , chan ) ; #ifdef DIAGNOSTIC if ( chan & ~ VALID_DMA_MASK ) panic ( " " ) ; if ( ( chan < 4 && nbytes > ( 1 << 16 ) ) || ( chan >= 4 && ( nbytes > ( 1 << 17 ) || ( uintptr_t ) addr & 1 ) ) ) panic ( " " ) ; mtx_lock ( & isa_dma_lock ) ; if ( ( dma_inuse & ( 1 << chan ) ) == 0 ) printf ( " \n " , chan ) ; #else mtx_lock ( & isa_dma_lock ) ; #endif #if 0 if ( dma_busy & ( 1 << chan ) ) printf ( " \n " , chan ) ; #endif dma_busy |= ( 1 << chan ) ; if ( dma_range_checked ) { if ( dma_bouncebuf [ chan ] == NULL || dma_bouncebufsize [ chan ] < nbytes ) panic ( " " ) ; dma_bounced |= ( 1 << chan ) ; newaddr = dma_bouncebuf [ chan ] ; if ( ! ( flags & ISADMA_READ ) ) bcopy ( addr , newaddr , nbytes ) ; addr = newaddr ; } phys = pmap_extract ( kernel_pmap , ( vm_offset_t ) addr ) ; if ( flags & ISADMA_RAW ) { dma_auto_mode |= ( 1 << chan ) ; } else { dma_auto_mode &= ~ ( 1 << chan ) ; } if ( ( chan & 4 ) == 0 ) { if ( flags & ISADMA_RAW ) { if ( flags & ISADMA_READ ) outb ( DMA1_MODE , DMA37MD_AUTO | DMA37MD_WRITE | chan ) ; else outb ( DMA1_MODE , DMA37MD_AUTO | DMA37MD_READ | chan ) ; } else if ( flags & ISADMA_READ ) outb ( DMA1_MODE , DMA37MD_SINGLE | DMA37MD_WRITE | chan ) ; else outb ( DMA1_MODE , DMA37MD_SINGLE | DMA37MD_READ | chan ) ; outb ( DMA1_FFC , 0 ) ; waport = DMA1_CHN ( chan ) ; outb ( waport , phys ) ; outb ( waport , phys >> 8 ) ; outb ( dmapageport [ chan ] , phys >> 16 ) ; outb ( waport + 1 , -- nbytes ) ; outb ( waport + 1 , nbytes >> 8 ) ; outb ( DMA1_SMSK , chan ) ; } else { if ( flags & ISADMA_RAW ) { if ( flags & ISADMA_READ ) outb ( DMA2_MODE , DMA37MD_AUTO | DMA37MD_WRITE | ( chan & 3 ) ) ; else outb ( DMA2_MODE , DMA37MD_AUTO | DMA37MD_READ | ( chan & 3 ) ) ; } else if ( flags & ISADMA_READ ) outb ( DMA2_MODE , DMA37MD_SINGLE | DMA37MD_WRITE | ( chan & 3 ) ) ; else outb ( DMA2_MODE , DMA37MD_SINGLE | DMA37MD_READ | ( chan & 3 ) ) ; outb ( DMA2_FFC , 0 ) ; waport = DMA2_CHN ( chan - 4 ) ; outb ( waport , phys >> 1 ) ; outb ( waport , phys >> 9 ) ; outb ( dmapageport [ chan ] , phys >> 16 ) ; nbytes >>= 1 ; outb ( waport + 2 , -- nbytes ) ; outb ( waport + 2 , nbytes >> 8 ) ; outb ( DMA2_SMSK , chan & 3 ) ; } mtx_unlock ( & isa_dma_lock ) ; }
isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
 problems by using a bounce buffer.
isa_dmastart () : program 8237 DMA controller channel avoid page alignment problems by using a bounce buffer .
/*
	 * XXX This should be checked, but drivers like ad1848 only call
	 * isa_dmastart() once because they use Auto DMA mode.  If we
	 * leave this in, drivers that do this will print this continuously.
	 */ /* copy bounce buffer on write */ /* translate to physical */ /*
		 * Program one of DMA channels 0..3.  These are
		 * byte mode channels.
		 */ /* set dma channel mode, and reset address ff */ /* If ISADMA_RAW flag is set, then use autoinitialise mode */ /* send start address */ /* send count */ /* unmask channel */ /*
		 * Program one of DMA channels 4..7.  These are
		 * word mode channels.
		 */ /* set dma channel mode, and reset address ff */ /* If ISADMA_RAW flag is set, then use autoinitialise mode */ /* send start address */ /* send count */ /* unmask channel */