kernels/linux-2.4.0/drivers/block/xd.c
/* xd_command: handle all data transfers necessary for a single command */
handle all data transfers necessary for a single command
handle all data transfers necessary for a single command
static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
{
	u_char cmdblk[6],csb,complete = 0;
#ifdef DEBUG_COMMAND
	printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
#endif 
	outb(0,XD_SELECT);
	outb(mode,XD_CONTROL);
	if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
		return (1);
	while (!complete) {
		if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
			return (1);
		switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
			case 0:
				if (mode == DMA_MODE) {
					if (xd_wait_for_IRQ())
						return (1);
				} else
					outb(outdata ? *outdata++ : 0,XD_DATA);
				break;
			case STAT_INPUT:
				if (mode == DMA_MODE) {
					if (xd_wait_for_IRQ())
						return (1);
				} else
					if (indata)
						*indata++ = inb(XD_DATA);
					else
						inb(XD_DATA);
				break;
			case STAT_COMMAND:
				outb(command ? *command++ : 0,XD_DATA);
				break;
			case STAT_COMMAND | STAT_INPUT:
				complete = 1;
				break;
		}
	}
	csb = inb(XD_DATA);
	if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout))					
		return (1);
	if (csb & CSB_ERROR) {									
		xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
		if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))
			printk("xd: warning! sense command failed!\n");
	}
#ifdef DEBUG_COMMAND
	printk("xd_command: completed with csb = 0x%X\n",csb);
#endif 
	return (csb & CSB_ERROR);
}
static u_int xd_command ( u_char * command , u_char mode , u_char * indata , u_char * outdata , u_char * sense , u_long timeout ) { u_char cmdblk [ 6 ] , csb , complete = 0 ; #ifdef DEBUG_COMMAND printk ( " \n " , command , mode , indata , outdata , sense ) ; #endif outb ( 0 , XD_SELECT ) ; outb ( mode , XD_CONTROL ) ; if ( xd_waitport ( XD_STATUS , STAT_SELECT , STAT_SELECT , timeout ) ) return ( 1 ) ; while ( ! complete ) { if ( xd_waitport ( XD_STATUS , STAT_READY , STAT_READY , timeout ) ) return ( 1 ) ; switch ( inb ( XD_STATUS ) & ( STAT_COMMAND | STAT_INPUT ) ) { case 0 : if ( mode == DMA_MODE ) { if ( xd_wait_for_IRQ ( ) ) return ( 1 ) ; } else outb ( outdata ? * outdata ++ : 0 , XD_DATA ) ; break ; case STAT_INPUT : if ( mode == DMA_MODE ) { if ( xd_wait_for_IRQ ( ) ) return ( 1 ) ; } else if ( indata ) * indata ++ = inb ( XD_DATA ) ; else inb ( XD_DATA ) ; break ; case STAT_COMMAND : outb ( command ? * command ++ : 0 , XD_DATA ) ; break ; case STAT_COMMAND | STAT_INPUT : complete = 1 ; break ; } } csb = inb ( XD_DATA ) ; if ( xd_waitport ( XD_STATUS , 0 , STAT_SELECT , timeout ) ) return ( 1 ) ; if ( csb & CSB_ERROR ) { xd_build ( cmdblk , CMD_SENSE , ( csb & CSB_LUN ) >> 5 , 0 , 0 , 0 , 0 , 0 ) ; if ( xd_command ( cmdblk , 0 , sense , 0 , 0 , XD_TIMEOUT ) ) printk ( " \n " ) ; } #ifdef DEBUG_COMMAND printk ( " \n " , csb ) ; #endif return ( csb & CSB_ERROR ) ; }
xd_command: handle all data transfers necessary for a single command
xd_command : handle all data transfers necessary for a single command
/* DEBUG_COMMAND */ /* wait until deselected */ /* read sense data if error */ /* DEBUG_COMMAND */