kernels/linux-2.4.0/drivers/ide/ide-dma.c
/*
 * ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
 *
 * The caller is assumed to have selected the drive and programmed the drive's
 * sector address using CHS or LBA.  All that remains is to prepare for DMA
 * and then issue the actual read/write DMA/PIO command to the drive.
 *
 * For ATAPI devices, we just prepare for DMA and return. The caller should
 * then issue the packet command to the drive and call us again with
 * ide_dma_begin afterwards.
 *
 * Returns 0 if all went well.
 * Returns 1 if DMA read/write could not be started, in which case
 * the caller should revert to PIO for the current request.
 * May also be invoked from trm290.c
 */
ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
The caller is assumed to have selected the drive and programmed the drive's
sector address using CHS or LBA.  All that remains is to prepare for DMA
and then issue the actual read/write DMA/PIO command to the drive.

For ATAPI devices, we just prepare for DMA and return. The caller should
then issue the packet command to the drive and call us again with
ide_dma_begin afterwards.

Returns 0 if all went well.
Returns 1 if DMA read/write could not be started, in which case
the caller should revert to PIO for the current request.
May also be invoked from trm290.c
ide_dmaproc () initiates / aborts DMA read / write operations on a drive . The caller is assumed to have selected the drive and programmed the drive ' s sector address using CHS or LBA . All that remains is to prepare for DMA and then issue the actual read / write DMA / PIO command to the drive . For ATAPI devices we just prepare for DMA and return . The caller should then issue the packet command to the drive and call us again with ide_dma_begin afterwards . Returns 0 if all went well . Returns 1 if DMA read / write could not be started in which case the caller should revert to PIO for the current request . May also be invoked from trm290 . c
int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
{
	ide_hwif_t *hwif = HWIF(drive);
	unsigned long dma_base = hwif->dma_base;
	byte unit = (drive->select.b.unit & 0x01);
	unsigned int count, reading = 0;
	byte dma_stat;
	switch (func) {
		case ide_dma_off:
			printk("%s: DMA disabled\n", drive->name);
		case ide_dma_off_quietly:
			outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
		case ide_dma_on:
			drive->using_dma = (func == ide_dma_on);
			if (drive->using_dma)
				outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
			return 0;
		case ide_dma_check:
			return config_drive_for_dma (drive);
		case ide_dma_read:
			reading = 1 << 3;
		case ide_dma_write:
			SELECT_READ_WRITE(hwif,drive,func);
			if (!(count = ide_build_dmatable(drive, func)))
				return 1;	
			outl(hwif->dmatable_dma, dma_base + 4); 
			outb(reading, dma_base);			
			outb(inb(dma_base+2)|6, dma_base+2);		
			drive->waiting_for_dma = 1;
			if (drive->media != ide_disk)
				return 0;
			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry);	
			OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
		case ide_dma_begin:
			outb(inb(dma_base)|1, dma_base);		
			return 0;
		case ide_dma_end: 
			drive->waiting_for_dma = 0;
			outb(inb(dma_base)&~1, dma_base);	
			dma_stat = inb(dma_base+2);		
			outb(dma_stat|6, dma_base+2);	
			ide_destroy_dmatable(drive);	
			return (dma_stat & 7) != 4;	
		case ide_dma_test_irq: 
			dma_stat = inb(dma_base+2);
#if 0	
			if (dma_stat & 4) {
				byte stat = GET_STAT();
				outb(dma_base+2, dma_stat & 0xE4);
			}
#endif
			return (dma_stat & 4) == 4;	
		case ide_dma_bad_drive:
		case ide_dma_good_drive:
			return check_drive_lists(drive, (func == ide_dma_good_drive));
		case ide_dma_verbose:
			return report_drive_dmaing(drive);
		case ide_dma_timeout:
#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
#endif 
		case ide_dma_retune:
		case ide_dma_lostirq:
			printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func),  func);
			return 1;
		default:
			printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
			return 1;
	}
}
int ide_dmaproc ( ide_dma_action_t func , ide_drive_t * drive ) { ide_hwif_t * hwif = HWIF ( drive ) ; unsigned long dma_base = hwif -> dma_base ; byte unit = ( drive -> select . b . unit & 0x01 ) ; unsigned int count , reading = 0 ; byte dma_stat ; switch ( func ) { case ide_dma_off : printk ( " \n " , drive -> name ) ; case ide_dma_off_quietly : outb ( inb ( dma_base + 2 ) & ~ ( 1 << ( 5 + unit ) ) , dma_base + 2 ) ; case ide_dma_on : drive -> using_dma = ( func == ide_dma_on ) ; if ( drive -> using_dma ) outb ( inb ( dma_base + 2 ) | ( 1 << ( 5 + unit ) ) , dma_base + 2 ) ; return 0 ; case ide_dma_check : return config_drive_for_dma ( drive ) ; case ide_dma_read : reading = 1 << 3 ; case ide_dma_write : SELECT_READ_WRITE ( hwif , drive , func ) ; if ( ! ( count = ide_build_dmatable ( drive , func ) ) ) return 1 ; outl ( hwif -> dmatable_dma , dma_base + 4 ) ; outb ( reading , dma_base ) ; outb ( inb ( dma_base + 2 ) | 6 , dma_base + 2 ) ; drive -> waiting_for_dma = 1 ; if ( drive -> media != ide_disk ) return 0 ; ide_set_handler ( drive , & ide_dma_intr , WAIT_CMD , dma_timer_expiry ) ; OUT_BYTE ( reading ? WIN_READDMA : WIN_WRITEDMA , IDE_COMMAND_REG ) ; case ide_dma_begin : outb ( inb ( dma_base ) | 1 , dma_base ) ; return 0 ; case ide_dma_end : drive -> waiting_for_dma = 0 ; outb ( inb ( dma_base ) & ~ 1 , dma_base ) ; dma_stat = inb ( dma_base + 2 ) ; outb ( dma_stat | 6 , dma_base + 2 ) ; ide_destroy_dmatable ( drive ) ; return ( dma_stat & 7 ) != 4 ; case ide_dma_test_irq : dma_stat = inb ( dma_base + 2 ) ; #if 0 if ( dma_stat & 4 ) { byte stat = GET_STAT ( ) ; outb ( dma_base + 2 , dma_stat & 0xE4 ) ; } #endif return ( dma_stat & 4 ) == 4 ; case ide_dma_bad_drive : case ide_dma_good_drive : return check_drive_lists ( drive , ( func == ide_dma_good_drive ) ) ; case ide_dma_verbose : return report_drive_dmaing ( drive ) ; case ide_dma_timeout : #ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT #endif case ide_dma_retune : case ide_dma_lostirq : printk ( " \n " , ide_dmafunc_verbose ( func ) , func ) ; return 1 ; default : printk ( " \n " , ide_dmafunc_verbose ( func ) , func ) ; return 1 ; } }
ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
ide_dmaproc () initiates / aborts DMA read / write operations on a drive .
/* try PIO instead of DMA */ /* PRD table */ /* specify r/w */ /* clear INTR & ERROR flags */ /* issue cmd to drive */ /* Note that this is done *after* the cmd has
			 * been issued to the drive, as per the BM-IDE spec.
			 * The Promise Ultra33 doesn't work correctly when
			 * we do this part before issuing the drive cmd.
			 */ /* start DMA */ /* returns 1 on error, 0 otherwise */ /* stop DMA */ /* get DMA status */ /* clear the INTR & ERROR bits */ /* purge DMA mappings */ /* verify good DMA status */ /* returns 1 if dma irq issued, 0 otherwise */ /* do not set unless you know what you are doing */ /* return 1 if INTR asserted */ /*
			 * Have to issue an abort and requeue the request
			 * DMA engine got turned off by a goofy ASIC, and
			 * we have to clean up the mess, and here is as good
			 * as any.  Do it globally for all chipsets.
			 */ /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */