?? ataiopci.c
字號:
inportb( busMasterRegs + BM_STATUS_REG ),
TRC_LLT_DEBUG ); // for debugging
#endif
// End of command...
// now wait for the PCI BM DMA channel to flush the data.
while ( 1 )
{
if ( ( inportb( busMasterRegs + BM_STATUS_REG )
& BM_SR_MASK_INT )
) // done yet ?
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 = 71;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
break;
}
}
#if 0
trc_llt( 0,
inportb( busMasterRegs + BM_STATUS_REG ),
TRC_LLT_DEBUG ); // for debugging
#endif
// End of command...
// disable/stop the dma channel
trc_llt( 0, 0, TRC_LLT_DMA3 );
disableChan();
// End of command...
// Read the primary status register. In keeping with the rules
// stated above the primary status register is read only
// ONCE.
status = pio_inbyte( CB_STAT );
// 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 make sure the device asserted the INTRQ signal.
if ( ( reg_cmd_info.ec == 0 )
&&
( ( inportb( busMasterRegs + BM_STATUS_REG ) & BM_SR_MASK_INT ) == 0 )
)
{
reg_cmd_info.ec = 71;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
}
// Final status check...
// if any error, update total bytes transferred.
if ( reg_cmd_info.ec == 0 )
reg_cmd_info.totalBytesXfer = ns * 512L;
else
reg_cmd_info.totalBytesXfer = 0L;
// Done...
// Read the output registers and trace the command.
sub_trace_command();
// Done...
// For interrupt mode, restore the INT 7x vector.
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_pci_packet() - PCI Bus Master for ATAPI Packet command
//
//***********************************************************
int dma_pci_packet( int dev,
unsigned int cpbc,
unsigned int cpseg, unsigned int cpoff,
int dir,
long dpbc,
unsigned int dpseg, unsigned int dpoff )
{
unsigned char devCtrl;
unsigned char devHead;
unsigned char cylLow;
unsigned char cylHigh;
unsigned char fr;
unsigned char status;
unsigned char reason;
unsigned char lowCyl;
unsigned char highCyl;
int ndx;
unsigned char * cp;
unsigned char far * cfp;
// mark start of isa dma PI cmd in low level trace
trc_llt( 0, 0, TRC_LLT_S_PID );
// setup register values
devCtrl = 0; // in the old days we would set CB_DC_HD15 = 1
devHead = dev ? CB_DH_DEV1 : CB_DH_DEV0;
cylLow = dpbc & 0x00ff;
cylHigh = ( dpbc & 0xff00 ) >> 8;
fr = 0x01;
// Reset error return data.
sub_zero_return_data();
reg_cmd_info.flg = TRC_FLAG_CMD;
reg_cmd_info.ct = dir ? TRC_TYPE_PDMAO : TRC_TYPE_PDMAI;
reg_cmd_info.cmd = CMD_PACKET;
reg_cmd_info.fr1 = fr;
reg_cmd_info.sc1 = 0;
reg_cmd_info.sn1 = 0;
reg_cmd_info.cl1 = cylLow;
reg_cmd_info.ch1 = cylHigh;
reg_cmd_info.dh1 = devHead;
reg_cmd_info.dc1 = devCtrl;
// Make sure the command packet size is either 12 or 16
// and save the command packet size and data.
cpbc = cpbc < 12 ? 12 : cpbc;
cpbc = cpbc > 12 ? 16 : cpbc;
reg_atapi_cp_size = cpbc;
cp = reg_atapi_cp_data;
cfp = MK_FP( cpseg, cpoff );
for ( ndx = 0; ndx < cpbc; ndx ++ )
{
* cp = * cfp;
cp ++ ;
cfp ++ ;
}
// Quit now if no dma channel set up
if ( ! busMasterRegs )
{
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_PID );
reg_atapi_max_bytes = 32768L; // reset max bytes
return 1;
}
// set up the dma transfer(s) --
// the data packet byte count must be even
// and must not be zero
if ( dpbc == 0xffff )
dpbc = 0xfffe;
if ( dpbc < 2 )
dpbc = 2;
if ( dpbc & 0x0001 )
dpbc ++ ;
set_up_xfer( dir, dpbc, dpseg, dpoff );
// Set command time out.
tmr_set_timeout();
// Select the drive - call the reg_select function.
// Quit now if this fails.
if ( sub_select( dev ) )
{
sub_trace_command();
trc_llt( 0, 0, TRC_LLT_E_PID );
reg_atapi_max_bytes = 32768L; // reset max bytes
return 1;
}
// Set up all the registers except the command register.
pio_outbyte( CB_DC, devCtrl );
pio_outbyte( CB_FR, fr );
pio_outbyte( CB_SC, 0 );
pio_outbyte( CB_SN, 0 );
pio_outbyte( CB_CL, 0 );
pio_outbyte( CB_CH, 0 );
pio_outbyte( CB_DH, devHead );
// For interrupt mode,
// Take over INT 7x and initialize interrupt controller
// and reset interrupt flag.
int_save_int_vect();
// Start the command by setting the Command register. The drive
// should immediately set BUSY status.
pio_outbyte( CB_CMD, CMD_PACKET );
// 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;
// Command packet transfer...
// Check for protocol failures,
// the device should have BSY=1 or
// if BSY=0 then either DRQ=1 or CHK=1.
sub_atapi_delay( dev );
status = pio_inbyte( CB_ASTAT );
if ( status & CB_STAT_BSY )
{
// BSY=1 is OK
}
else
{
if ( status & ( CB_STAT_DRQ | CB_STAT_ERR ) )
{
// BSY=0 and DRQ=1 is OK
// BSY=0 and ERR=1 is OK
}
else
{
reg_cmd_info.failbits |= FAILBIT0; // not OK
}
}
// Command packet transfer...
// Poll Alternate Status for BSY=0.
trc_llt( 0, 0, TRC_LLT_PNBSY );
while ( 1 )
{
status = pio_inbyte( CB_ASTAT ); // poll for not busy
if ( ( status & CB_STAT_BSY ) == 0 )
break;
if ( tmr_chk_timeout() ) // time out yet ?
{
trc_llt( 0, 0, TRC_LLT_TOUT ); // yes
reg_cmd_info.to = 1;
reg_cmd_info.ec = 75;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
break;
}
}
// Command packet transfer...
// Check for protocol failures... no interrupt here please!
// Clear any interrupt the command packet transfer may have caused.
if ( int_intr_flag )
reg_cmd_info.failbits |= FAILBIT1;
int_intr_flag = 0;
// Command packet transfer...
// If no error, transfer the command packet.
if ( reg_cmd_info.ec == 0 )
{
// Command packet transfer...
// Read the primary status register and the other ATAPI registers.
status = pio_inbyte( CB_STAT );
reason = pio_inbyte( CB_SC );
lowCyl = pio_inbyte( CB_CL );
highCyl = pio_inbyte( CB_CH );
// Command packet transfer...
// check status: must have BSY=0, DRQ=1 now
if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR ) )
!= CB_STAT_DRQ
)
{
reg_cmd_info.ec = 76;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
}
else
{
// Command packet transfer...
// Check for protocol failures...
// check: C/nD=1, IO=0.
if ( ( reason & ( CB_SC_P_TAG | CB_SC_P_REL | CB_SC_P_IO ) )
|| ( ! ( reason & CB_SC_P_CD ) )
)
reg_cmd_info.failbits |= FAILBIT2;
if ( ( lowCyl != cylLow ) || ( highCyl != cylHigh ) )
reg_cmd_info.failbits |= FAILBIT3;
// Command packet transfer...
// trace cdb byte 0,
// xfer the command packet (the cdb)
trc_llt( 0, * (unsigned char far *) MK_FP( cpseg, cpoff ), TRC_LLT_P_CMD );
pio_rep_outword( CB_DATA, cpseg, cpoff, cpbc >> 1 );
}
}
// enable/start the dma channel.
trc_llt( 0, 0, TRC_LLT_DMA1 );
enableChan();
// Data transfer...
// the device and dma channel transfer the data here while we start
// checking for command completion...
// 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() ) // done yet ?
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;
}
}
}
#if 0
trc_llt( 0,
inportb( busMasterRegs + BM_STATUS_REG ),
TRC_LLT_DEBUG ); // for debugging
#endif
// End of command...
// now wait for the PCI BM DMA channel to flush the data.
while ( 1 )
{
if ( ( inportb( busMasterRegs + BM_STATUS_REG )
& BM_SR_MASK_INT )
) // done yet ?
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 = 71;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
break;
}
}
#if 0
trc_llt( 0,
inportb( busMasterRegs + BM_STATUS_REG ),
TRC_LLT_DEBUG ); // for debugging
#endif
// End of command...
// disable/stop the dma channel
trc_llt( 0, 0, TRC_LLT_DMA3 );
disableChan();
// End of command...
// Read the primary status register. In keeping with the rules
// stated above the primary status register is read only
// ONCE.
status = pio_inbyte( CB_STAT );
// 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_DRQ | CB_STAT_ERR ) )
{
reg_cmd_info.ec = 74;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
}
}
// Final status check...
// Check for protocol failures...
// check: C/nD=1, IO=1.
reason = pio_inbyte( CB_SC );
if ( ( reason & ( CB_SC_P_TAG | CB_SC_P_REL ) )
|| ( ! ( reason & CB_SC_P_IO ) )
|| ( ! ( reason & CB_SC_P_CD ) )
)
reg_cmd_info.failbits |= FAILBIT8;
// Final status check...
// if no error, check make sure the device asserted the INTRQ signal.
if ( ( reg_cmd_info.ec == 0 )
&&
( ( inportb( busMasterRegs + BM_STATUS_REG ) & BM_SR_MASK_INT ) == 0 )
)
{
reg_cmd_info.ec = 71;
trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
}
// Final status check...
// if any error, update total bytes transferred.
if ( reg_cmd_info.ec == 0 )
reg_cmd_info.totalBytesXfer = dpbc;
else
reg_cmd_info.totalBytesXfer = 0L;
// Done...
// Read the output registers and trace the command.
// Also put the command packet in the trace.
sub_trace_command();
trc_cht_pkt();
// Done...
// For interrupt mode, restore the INT 7x vector.
int_restore_int_vect();
// Done...
// mark end of isa dma PI cmd in low level trace
trc_llt( 0, 0, TRC_LLT_E_PID );
// All done. The return values of this function are described in
// ATAIO.H.
reg_atapi_max_bytes = 32768L; // reset max bytes
if ( reg_cmd_info.ec )
return 1;
return 0;
}
// end ataiopci.c
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -