📄 example2.c
字号:
// Example2.c -- Some ATAPI command examples
#if 0
Some simple instructions for those of you that would like to
compile my driver code and try it.
1) I've always used Borland C (or C++, the driver code is plain C
code). One file contains a few lines of embedded ASM code. You will
need Borland's TASM too.
2) I've always used small memory model but I think the driver code
will work with any memory mode. See the MEMMOD variable in the
make file (EXAMPLE2.MAK).
3) The EXAMPLE2.EXE program is a DOS real mode program. It will
not execute in a DOS session (a virtual x86 session) under Windows!
You should make a DOS boot floppy and boot your system for it and
execute the EXAMPLE2.EXE program from that floppy.
4) Here is a very small program that shows how to use the driver
code to issue some ATAPI commands.
This program has one required command line parameter to specify
the device to run on: P0, P1, S0 or S1.
#endif
//---------- option to include PCI Bus Mastering DMA
#define INCL_PCI_DMA 0 // set to 1 to include PCI DMA
//---------- begin
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <conio.h>
#include "ataio.h"
int pciBus = -1;
int pciDev = -1;
int pciFun = -1;
int priSec = -1;
int dev = -1;
int irqNum = -1;
unsigned int cmdBase = 0xffff;
unsigned int ctrlBase = 0xffff;
unsigned int bmcrBase = 0xffff;
unsigned char * devTypeStr[]
= { "NO DEVICE", "UNKNOWN TYPE", "ATA", "ATAPI" };
unsigned char cdb[16];
unsigned char far * cdbPtr;
#define BUFFER_SIZE 4096
unsigned char buffer[BUFFER_SIZE];
unsigned char far * bufferPtr;
/*********************************************************/
static void pause( void );
static void pause( void )
{
// clear any queued up keys
while ( kbhit() )
{
if ( getch() == 0 )
getch();
}
// pause until key hit
printf( "Press any key to continue...\n" );
while ( ! kbhit() )
/* do nothing */ ;
// clear any queued up keys
while ( kbhit() )
{
if ( getch() == 0 )
getch();
}
}
/*********************************************************/
static long get_dnumber( unsigned char * s );
static long get_dnumber( unsigned char * s )
{
char * cp;
long val;
strupr( s );
if ( strspn( s, "0123456789" ) != strlen( s ) )
return -1L;
val = strtol( s, & cp, 0 );
if ( * cp != 0 )
return -1L;
return val;
}
/**********************************************************
**
** get a word of PCI config data from BIOS INT 1AH
**
**********************************************************/
unsigned int GetPciWord( unsigned int busNum, unsigned int devNum,
unsigned int funNum, unsigned int regNum );
unsigned int GetPciWord( unsigned int busNum, unsigned int devNum,
unsigned int funNum, unsigned int regNum )
{
union REGS ir, or;
if ( regNum & 0x0001 )
return 0xffff;
ir.x.ax = 0xb109;
ir.x.bx = ( busNum << 8 ) | ( devNum << 3 ) | funNum;
ir.x.di = regNum;
int86( 0x1a, & ir, & or );
if ( or.x.cflag )
return 0xffff;
return or.x.cx;
}
//**********************************************
// a little function to display all the error
// and trace information from the driver
void ShowAll( void );
void ShowAll( void )
{
int lc = 0;
unsigned char * cp;
printf( "ERROR !\n" );
// display the command error information
trc_err_dump1(); // start
while ( 1 )
{
cp = trc_err_dump2(); // get and display a line
if ( cp == NULL )
break;
printf( "* %s\n", cp );
}
pause();
// display the command history
trc_cht_dump1(); // start
while ( 1 )
{
cp = trc_cht_dump2(); // get and display a line
if ( cp == NULL )
break;
printf( "* %s\n", cp );
lc ++ ;
if ( ! ( lc & 0x000f ) )
pause();
}
// display the low level trace
trc_llt_dump1(); // start
while ( 1 )
{
cp = trc_llt_dump2(); // get and display a line
if ( cp == NULL )
break;
printf( "* %s\n", cp );
lc ++ ;
if ( ! ( lc & 0x000f ) )
pause();
}
if ( lc & 0x000f )
pause();
}
//**********************************************
void ClearTrace( void );
void ClearTrace( void )
{
// clear the command history and low level traces
trc_cht_dump0(); // zero the command history
trc_llt_dump0(); // zero the low level trace
}
//**********************************************
int main( int ac, char * av[] )
{
int numDev;
int ndx;
int rc;
printf( "ATADRVR EXAMPLE2 Version " ATA_DRIVER_VERSION ".\n" );
//---------- initialization and command line option processing
printf( "Usage: EXAMPLE2 pciBus pciDev pciFun dev irqNum\n" );
// av[n] 1 2 3 4 5
printf( " If irqNum is zero it will be defaulted.\n" );
if ( ac != 6 )
{
printf( "Missing or extra command line options !\n" );
return 1;
}
pciBus = (int) get_dnumber( av[1] );
pciDev = (int) get_dnumber( av[2] );
pciFun = (int) get_dnumber( av[3] );
if ( ! stricmp( av[4], "P0" ) )
{ priSec = 0; dev = 0; }
if ( ! stricmp( av[4], "P1" ) )
{ priSec = 0; dev = 1; }
if ( ! stricmp( av[4], "S0" ) )
{ priSec = 1; dev = 0; }
if ( ! stricmp( av[4], "S1" ) )
{ priSec = 1; dev = 1; }
irqNum = (int) get_dnumber( av[5] );
printf( "Device %d %d %d %s%d, IRQ %d in not shared mode.\n",
pciBus, pciDev, pciFun,
priSec ? "S" : "P", dev,
irqNum );
if ( ( pciBus < 0 ) || ( pciDev < 0 ) || ( pciFun < 0 )
|| ( priSec < 0 ) || ( dev < 0 ) || ( irqNum < 0 ) )
{
printf( "Invalid command line option(s) !\n" );
return 1;
}
cmdBase = GetPciWord( pciBus, pciDev, pciFun, 0x10 + ( 8 * priSec ) );
ctrlBase = GetPciWord( pciBus, pciDev, pciFun, 0x14 + ( 8 * priSec ) );
bmcrBase = GetPciWord( pciBus, pciDev, pciFun, 0x20 );
if ( ( cmdBase == 0xffff )
|| ( ctrlBase == 0xffff )
|| ( bmcrBase == 0xffff ) )
{
printf( "PCI information invalid !\n" );
return 1;
}
cmdBase &= 0xfffe;
ctrlBase &= 0xfffe;
bmcrBase &= 0xfffe;
if ( cmdBase == 0 )
{
cmdBase = priSec ? 0x170 : 0x1f0;
ctrlBase = priSec ? 0x370 : 0x3f0;
irqNum = priSec ? 15 : 14;
}
else
{
ctrlBase -= 4;
}
if ( priSec )
bmcrBase += 8;
printf( "ATA CMD base %04X, ATA CTRL base %04X, BMCR base %04X\n",
cmdBase, ctrlBase, bmcrBase );
if ( ! irqNum )
{
irqNum = GetPciWord( pciBus, pciDev, pciFun, 0x3c );
irqNum &= 0x00ff;
printf( "IRQ defaulted to %d\n", irqNum );
}
//---------- initialization
// initialize far pointer to the I/O buffer
bufferPtr = (unsigned char far *) buffer;
// tell ATADRVR how big the buffer is
reg_buffer_size = BUFFER_SIZE;
// set the ATADRVR command timeout (in seconds)
tmr_time_out = 20;
// initialize far pointer to the CBD buffer
cdbPtr = (unsigned char far *) cdb;
//---------- ATADRVR initialization
// 1) must tell the driver what the I/O port addresses.
// note that the driver also supports all the PCMCIA
// PC Card modes (I/O and memory).
pio_set_iobase_addr( cmdBase, ctrlBase, bmcrBase );
printf( "Using I/O base addresses %04X and %04X.\n", cmdBase, ctrlBase );
// 2) find out what devices are present -- this is the step
// many driver writers ignore. You really can't just do
// resets and commands without first knowing what is out there.
// Even if you don't care the driver does care.
numDev = reg_config();
printf( "Found %d devices, dev 0 is %s, dev 1 is %s.\n",
numDev,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -