📄 ataioisa.c
字号:
{
unsigned char status;
unsigned long lw1, lw2;
// mark start of a R/W DMA command in low level trace
trc_llt( 0, 0, TRC_LLT_S_RWD );
// Quit now if the command is incorrect.
if ( ( reg_cmd_info.cmd != CMD_READ_DMA )
&& ( reg_cmd_info.cmd != CMD_READ_DMA_EXT )
&& ( reg_cmd_info.cmd != CMD_WRITE_DMA )
&& ( reg_cmd_info.cmd != CMD_WRITE_DMA_EXT ) )
{
reg_cmd_info.ec = 77;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
sub_trace_command();
trc_llt( 0, 0, TRC_LLT_E_RWD );
return 1;
}
// Quit now if no dma channel set up.
if ( ! dmaChan )
{
reg_cmd_info.ec = 70;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
sub_trace_command();
trc_llt( 0, 0, TRC_LLT_E_RWD );
return 1;
}
// Quit now if 1) I/O buffer overrun possible
// or 2) DMA can't handle the transfer size.
if ( ( numSect > 256L ) || ( ( numSect * 512L ) > reg_buffer_size ) )
{
reg_cmd_info.ec = 61;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
sub_trace_command();
trc_llt( 0, 0, TRC_LLT_E_PID );
return 1;
}
// set up the dma transfer
set_up_xfer( ( reg_cmd_info.cmd == CMD_WRITE_DMA )
||
( reg_cmd_info.cmd == CMD_WRITE_DMA_EXT ),
numSect * 512L, seg, off );
// Set command time out.
tmr_set_timeout();
// Select the drive - call the sub_select function.
// Quit now if this fails.
if ( sub_select( dev ) )
{
sub_trace_command();
trc_llt( 0, 0, TRC_LLT_E_RWD );
return 1;
}
// Set up all the registers except the command register.
sub_setup_command();
// For interrupt mode, install interrupt handler.
int_save_int_vect();
// program the dma channel for the first or only transfer.
prog_dma_chan( page1, addr1, count1, modeByte );
// Start the command by setting the Command register. The drive
// should immediately set BUSY status.
pio_outbyte( CB_CMD, reg_cmd_info.cmd );
// Waste some time by reading the alternate status a few times.
// This gives the drive time to set BUSY in the status register on
// really fast systems. If we don't do this, a slow drive on a fast
// system may not set BUSY fast enough and we would think it had
// completed the command when it really had not even started the
// command yet.
DELAY400NS;
// Data transfer...
// If this transfer requires two dma transfers,
// wait for the first transfer to complete and
// then program the dma channel for the second transfer.
if ( ( reg_cmd_info.ec == 0 ) && doTwo )
{
// Data transfer...
// wait for dma chan to transfer first part by monitoring
// the dma channel's terminal count status bit
// -or-
// watch for command completion due to an error
// -or-
// time out if this takes too long.
trc_llt( 0, 0, TRC_LLT_DMA2 );
while ( 1 )
{
if ( inportb( 0xd0 ) & dmaTCbit ) // terminal count yet ?
break; // yes - ok!
if ( chk_cmd_done() ) // cmd done ?
{
reg_cmd_info.ec = 71;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
break;
}
if ( tmr_chk_timeout() ) // time out yet ?
{
trc_llt( 0, 0, TRC_LLT_TOUT );
reg_cmd_info.to = 1;
reg_cmd_info.ec = 72;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
break;
}
}
// if no error, set up 2nd transfer
if ( reg_cmd_info.ec == 0 )
{
// update bytes transferred count
reg_cmd_info.totalBytesXfer += count1 << 1;
// program dma channel to transfer the second part
prog_dma_chan( page2, addr2, count2, modeByte );
count1 = count2;
}
}
// End of command...
// if no error,
// wait for drive to signal command completion
// -or-
// time out if this takes to long.
if ( reg_cmd_info.ec == 0 )
{
if ( int_use_intr_flag )
trc_llt( 0, 0, TRC_LLT_WINT );
else
trc_llt( 0, 0, TRC_LLT_PNBSY );
while ( 1 )
{
if ( chk_cmd_done() ) // cmd done ?
break; // yes
if ( tmr_chk_timeout() ) // time out yet ?
{
trc_llt( 0, 0, TRC_LLT_TOUT ); // yes
reg_cmd_info.to = 1;
reg_cmd_info.ec = 73;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
break;
}
}
}
// End of command...
// disable the dma channel
trc_llt( 0, 0, TRC_LLT_DMA3 );
disableChan();
// End of command...
// If polling or error read the Status register,
// otherwise use the Status register value that was read
// by the interrupt handler.
if ( ( ! int_use_intr_flag ) || ( reg_cmd_info.ec ) )
status = pio_inbyte( CB_STAT );
else
status = int_ata_status;
// Final status check...
// if no error, check final status...
// Error if BUSY, DEVICE FAULT, DRQ or ERROR status now.
if ( reg_cmd_info.ec == 0 )
{
if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_DRQ | CB_STAT_ERR ) )
{
reg_cmd_info.ec = 74;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
}
}
// Final status check...
// if no error, check dma channel terminal count flag
if ( ( reg_cmd_info.ec == 0 )
&&
( ( inportb( 0xd0 ) & dmaTCbit ) == 0 )
)
{
reg_cmd_info.ec = 71;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
}
// Final status check...
// update total bytes transferred
if ( reg_cmd_info.ec == 0 )
reg_cmd_info.totalBytesXfer += count1 << 1;
else
{
clearFF();
lw1 = inportb( dmaCntrReg );
lw2 = inportb( dmaCntrReg );
lw1 = ( ( lw2 << 8 ) | lw1 ) + 1;
lw1 = lw1 & 0x0000ffffL;
reg_cmd_info.totalBytesXfer += ( count1 - lw1 ) << 1;
}
// Done...
// Read the output registers and trace the command.
sub_trace_command();
// Done...
// For interrupt mode, remove interrupt handler.
int_restore_int_vect();
// Done...
// mark end of a R/W DMA command in low level trace
trc_llt( 0, 0, TRC_LLT_E_RWD );
// All done. The return values of this function are described in
// ATAIO.H.
if ( reg_cmd_info.ec )
return 1;
return 0;
}
//***********************************************************
//
// dma_isa_chs() - DMA in ISA Multiword for ATA R/W DMA
//
//***********************************************************
int dma_isa_chs( int dev, int cmd,
unsigned int fr, unsigned int sc,
unsigned int cyl, unsigned int head, unsigned int sect,
unsigned int seg, unsigned int off,
long numSect )
{
// Setup current command information.
sub_zero_return_data();
reg_cmd_info.flg = TRC_FLAG_ATA;
reg_cmd_info.ct = TRC_TYPE_ADMAI;
if ( ( cmd == CMD_WRITE_DMA ) || ( cmd == CMD_WRITE_DMA_EXT ) )
reg_cmd_info.ct = TRC_TYPE_ADMAO;
reg_cmd_info.cmd = cmd;
reg_cmd_info.fr1 = fr;
reg_cmd_info.sc1 = sc;
reg_cmd_info.sn1 = sect;
reg_cmd_info.cl1 = cyl & 0x00ff;
reg_cmd_info.ch1 = ( cyl & 0xff00 ) >> 8;
reg_cmd_info.dh1 = ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) | ( head & 0x0f );
reg_cmd_info.dc1 = int_use_intr_flag ? 0 : CB_DC_NIEN;
reg_cmd_info.ns = numSect;
reg_cmd_info.lbaSize = LBACHS;
// Execute the command.
return exec_isa_ata_cmd( dev, seg, off, numSect );
}
//***********************************************************
//
// dma_isa_lba28() - DMA in ISA Multiword for ATA R/W DMA
//
//***********************************************************
int dma_isa_lba28( int dev, int cmd,
unsigned int fr, unsigned int sc,
unsigned long lba,
unsigned int seg, unsigned int off,
long numSect )
{
// Setup current command information.
sub_zero_return_data();
reg_cmd_info.flg = TRC_FLAG_ATA;
reg_cmd_info.ct = TRC_TYPE_ADMAI;
reg_cmd_info.cmd = cmd;
if ( ( cmd == CMD_WRITE_DMA ) || ( cmd == CMD_WRITE_DMA_EXT ) )
reg_cmd_info.ct = TRC_TYPE_ADMAO;
reg_cmd_info.fr1 = fr;
reg_cmd_info.sc1 = sc;
reg_cmd_info.dh1 = CB_DH_LBA | (dev ? CB_DH_DEV1 : CB_DH_DEV0 );
reg_cmd_info.dc1 = int_use_intr_flag ? 0 : CB_DC_NIEN;
reg_cmd_info.ns = numSect;
reg_cmd_info.lbaSize = LBA28;
reg_cmd_info.lbaHigh1 = 0L;
reg_cmd_info.lbaLow1 = lba;
// Execute the command.
return exec_isa_ata_cmd( dev, seg, off, numSect );
}
//***********************************************************
//
// dma_isa_lba48() - DMA in ISA Multiword for ATA R/W DMA
//
//***********************************************************
int dma_isa_lba48( int dev, int cmd,
unsigned int fr, unsigned int sc,
unsigned long lbahi, unsigned long lbalo,
unsigned int seg, unsigned int off,
long numSect )
{
// Setup current command information.
sub_zero_return_data();
reg_cmd_info.flg = TRC_FLAG_ATA;
reg_cmd_info.ct = TRC_TYPE_ADMAI;
if ( ( cmd == CMD_WRITE_DMA ) || ( cmd == CMD_WRITE_DMA_EXT ) )
reg_cmd_info.ct = TRC_TYPE_ADMAO;
reg_cmd_info.cmd = cmd;
reg_cmd_info.fr1 = fr;
reg_cmd_info.sc1 = sc;
reg_cmd_info.dh1 = CB_DH_LBA | (dev ? CB_DH_DEV1 : CB_DH_DEV0 );
reg_cmd_info.dc1 = int_use_intr_flag ? 0 : CB_DC_NIEN;
reg_cmd_info.ns = numSect;
reg_cmd_info.lbaSize = LBA48;
reg_cmd_info.lbaHigh1 = lbahi;
reg_cmd_info.lbaLow1 = lbalo;
// Execute the command.
return exec_isa_ata_cmd( dev, seg, off, numSect );
}
//***********************************************************
//
// dma_isa_packet() - DMA in ISA Multiword for ATAPI Packet
//
//***********************************************************
int dma_isa_packet( int dev,
unsigned int cpbc,
unsigned int cpseg, unsigned int cpoff,
int dir,
long dpbc,
unsigned int dpseg, unsigned int dpoff,
unsigned long lba )
{
unsigned char status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -