⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 example1.c

📁 pc机上经由pci连接的ata和atapi设备驱动
💻 C
字号:

// Example1.c -- A program showing how to use ADVDRVR with ATA devices.

#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. Currently I use Borland C/C++ 4.52 and
   Borland TASM 4.1.

   2) This code should work with any memory mode.  See the MEMMOD
   variable in the make file (EXAMPLE1.MAK).

   3) The EXAMPLE1.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 EXAMPLE1.EXE program from that floppy.

   4) Here is a very small program that shows how to use the
   driver code to issue some ATA commands.  This program has one
   required command line parameter to specify the device to run
   on:  P0, P1, S0 or S1.

#endif

#define INCL_LBA48   0     // set to 1 to include 48-bit LBA

#define INCL_PCI_DMA 0     // set to 1 to include PCI DMA

#define BMCR_IO_ADDR 0xFFA8   // YOU MUST SUPPLY THIS VALUE
                              // IF YOU WANT TO USE R/W DMA

// begin

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>

#include "advio.h"

//**********************************************

// Please read carefully -- To use ADVDRVR the caller (such as
// this program must provide a data area (struct ADVIO_DEVICE)
// for each device to be used and must provide the pointer
// to the current device data area (struct ADVIO_DEVICE * ADP)
// before calling any ADVDRVR function. In this program
// only a single device data area is used but 'devInfo' could
// be an array of struct - just make sure ADP is set correctly
// before calling any ADVDRVR function!

// This data area is used to configure a controller and device
// for ADVDRVR's use, to determine the result of a command and
// to implement the CHT and LLT traces. The entire device data
// area must be intiialized to zero. Note that this example
// is simple in that it uses only one device. When you have
// multiple devices, some may be on the same physical ATA
// channel. In this the calling program will need to serialize
// commands to the devices on those shared channels and may
// want to have I/O, CHT and LLT buffers that are shared.
// See the ADVDRVR.UG doc file for more information.

struct ADVIO_DEVICE devInfo;        // Allocate a device data area

struct ADVIO_DEVICE * ADP;          // Pointer to device data area

#define CHT_SIZE 20                 // command history trace buffer
struct CHT chtTrcBuf[CHT_SIZE];
#define LLT_SIZE 100                // low level trace buffer
struct LLT lltTrcBuf[LLT_SIZE];

//**********************************************

unsigned char * devTypeStr[]
       = { "no device found", "unknown type", "ATA", "ATAPI" };

#define BUFFER_SIZE 4096            // I/O buffer
unsigned char buffer[BUFFER_SIZE];
unsigned char far * bufferPtr;

//**********************************************

// a little function to display all the error
// and trace information from the driver

void ShowAll( void );

void ShowAll( void )

{
   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 );
   }

   // 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 );
   }

   // 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 );
   }

   // now 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 base;
   int dev;
   int numDev;
   int rc;

   printf( "ADVDRVR EXAMPLE1 Version " ADVIO_DRIVER_VERSION ".\n" );

   // initialize far pointer to the I/O buffer
   bufferPtr = (unsigned char far *) buffer;

   // process command line parameter
   if ( ac == 2 )
   {
      if ( ! strnicmp( av[1], "p0", 2 ) )
      {
         base = 0x1f0;
         dev = 0;
      }
      else
      if ( ! strnicmp( av[1], "p1", 2 ) )
      {
         base = 0x1f0;
         dev = 1;
      }
      else
      if ( ! strnicmp( av[1], "s0", 2 ) )
      {
         base = 0x170;
         dev = 0;
      }
      else
      if ( ! strnicmp( av[1], "s1", 2 ) )
      {
         base = 0x170;
         dev = 1;
      }
      else
      {
         printf( "\nInvalid command line parameter !\n" );
         return 1;
      }
   }
   else
   {
      printf( "\nMissing command line parameter !\n" );
      return 1;
   }
   printf( "\nUsing I/O base addresses %04X and %04X.\n",
           base, base + 0x200 );
   printf(   "Using device %d on this ATA interface.\n", dev );

   // Step 1) set ADP to point to our device data area
   ADP = & devInfo;

   // Step 2) initialize data ADVDRVR needs...
   ADP->devBit = dev ? 0x10 : 0x00;       // DEV bit value
   ADP->pio_xfer_width = 16;              // PIO Data register width
   ADP->reg_buffer_size = BUFFER_SIZE;    // buffer size
   ADP->tmr_time_out = 40;                // command timeout in seconds
   ADP->reg_atapi_cp_size = 12;           // ATAPI CDB size in bytes
   ADP->chtBuf = (struct CHT far *) & chtTrcBuf;   // init the command history
   ADP->chtSize = CHT_SIZE;
   trc_cht_dump0();
   ADP->lltBuf = (struct LLT far *) & lltTrcBuf;   // init the low level trace
   ADP->lltSize = LLT_SIZE;
   trc_llt_dump0();

   // Step 3) must tell the driver what the I/O port addresses.
   pio_set_iobase_addr( base, base + 0x200, BMCR_IO_ADDR );

   // Step 4) 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();
   if ( numDev )
   {
      printf( "\nFound a devices on this ATA interface:\n" );
      printf( "   The device type is %s.\n", devTypeStr[ ADP->devType ] );
   }
   else
   {
      printf( "\nNo device found !\n" );
      return 1;
   }

   // basic setup is done, now we can issue Software Resets
   // (SRST), ATA Non-Data and ATA PIO data transfer commands.

   // do an ATA soft reset (SRST)
   printf( "Soft Reset...\n" );
   rc = reg_reset( 0 );
   if ( rc )
      ShowAll();

   // do a seek command in CHS mode to CHS=100,2,5
   printf( "Seek, CHS...\n" );
   rc = reg_non_data_chs( CMD_SEEK, 0, 0, 100, 2, 5 );
   if ( rc )
      ShowAll();

   // do a seek command in LBA28 mode to LBA=5025
   printf( "Seek, LBA28...\n" );
   rc = reg_non_data_lba28( CMD_SEEK, 0, 0, 5025L );
   if ( rc )
      ShowAll();

   // do an ATA Identify command in CHS mode
   printf( "ATA Identify, CHS...\n" );
   memset( buffer, 0, sizeof( buffer ) );
   rc = reg_pio_data_in_chs(
               CMD_IDENTIFY_DEVICE,
               0, 0,
               0, 0, 0,
               FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
               1L, 0
               );
   if ( rc )
      ShowAll();
   else
      // display the first 16 bytes read
      printf( "   data read %02X%02X%02X%02X %02X%02X%02X%02X "
                           "%02X%02X%02X%02X %02X%02X%02X%02X\n",
               buffer[ 0], buffer[ 1], buffer[ 2], buffer[ 3],
               buffer[ 4], buffer[ 5], buffer[ 6], buffer[ 7],
               buffer[ 8], buffer[ 9], buffer[10], buffer[11],
               buffer[12], buffer[13], buffer[14], buffer[15] );

   // do an ATA Identify command in LBA28 mode
   printf( "ATA Identify, LBA28...\n" );
   memset( buffer, 0, sizeof( buffer ) );
   rc = reg_pio_data_in_lba28(
               CMD_IDENTIFY_DEVICE,
               0, 0,
               0L,
               FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
               1L, 0 );
   if ( rc )
      ShowAll();
   else
      // display the first 16 bytes read
      printf( "   data read %02X%02X%02X%02X %02X%02X%02X%02X "
                           "%02X%02X%02X%02X %02X%02X%02X%02X\n",
               buffer[ 0], buffer[ 1], buffer[ 2], buffer[ 3],
               buffer[ 4], buffer[ 5], buffer[ 6], buffer[ 7],
               buffer[ 8], buffer[ 9], buffer[10], buffer[11],
               buffer[12], buffer[13], buffer[14], buffer[15] );

   // do an ATA Read Sectors command in LBA28 mode
   // lets read 3 sectors starting at LBA=5
   printf( "ATA Read Sectors, LBA28...\n" );
   memset( buffer, 0, sizeof( buffer ) );
   rc = reg_pio_data_in_lba28(
               CMD_READ_SECTORS,
               0, 3,
               5L,
               FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
               3L, 0
               );
   if ( rc )
      ShowAll();
   else
      // display the first 16 bytes read
      printf( "   data read %02X%02X%02X%02X %02X%02X%02X%02X "
                           "%02X%02X%02X%02X %02X%02X%02X%02X\n",
               buffer[ 0], buffer[ 1], buffer[ 2], buffer[ 3],
               buffer[ 4], buffer[ 5], buffer[ 6], buffer[ 7],
               buffer[ 8], buffer[ 9], buffer[10], buffer[11],
               buffer[12], buffer[13], buffer[14], buffer[15] );

#if INCL_LBA48

   // do an ATA Read Sectors command in LBA48 mode
   // lets read 3 sectors starting at LBA=5
   printf( "ATA Read Sectors, LBA48...\n" );
   memset( buffer, 0, sizeof( buffer ) );
   rc = reg_pio_data_in_lba48(
               CMD_READ_SECTORS_EXT,
               0, 3,
               0L, 5L,
               FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
               3L, 0
               );
   if ( rc )
      ShowAll();
   else
      // display the first 16 bytes read
      printf( "   data read %02X%02X%02X%02X %02X%02X%02X%02X "
                           "%02X%02X%02X%02X %02X%02X%02X%02X\n",
               buffer[ 0], buffer[ 1], buffer[ 2], buffer[ 3],
               buffer[ 4], buffer[ 5], buffer[ 6], buffer[ 7],
               buffer[ 8], buffer[ 9], buffer[10], buffer[11],
               buffer[12], buffer[13], buffer[14], buffer[15] );

#endif

#if INCL_PCI_DMA

   // If you set INCL_PCI_DMA to 1 AND you have read the Driver
   // User's Guide AND you have an PCI bus ATA host adapter and
   // you must know the I/O address of the Bus Master Control
   // Registers (BMCR) registers. This address is
   // found by scanning all the PCI bus devices and finding the
   // ATA host adapter you want to use. The BMCR I/O address
   // is at offset 20H of the PCI configuration space for the
   // ATA host adapter.

   // first, tell the driver where the BMCR is located.

   dma_pci_config( BMCR_IO_ADDR );

   #if 0
      // DO NOT DO THIS SET FEATURES UNLESS REQUIRED!
      // YOU MUST KNOW WHICH MODE THE HOST ADAPTER HAS
      // BEEN PROGRAMMED TO USE!
      // do a set features to turn on Ultra DMA (or MW DMA)
      printf( "Set Feature, FR=03H, SC=40H...\n" );
      rc = reg_non_data_chs( CMD_SET_FEATURES, 0x03, 0x40, 0, 0, 0 );
      if ( rc )
         ShowAll();
   #endif

   // do an ATA Read DMA command in LBA28 mode
   // lets read 3 sectors starting at LBA=5
   printf( "ATA Read DMA, LBA28...\n" );
   memset( buffer, 0, sizeof( buffer ) );
   rc = dma_pci_lba28(
               CMD_READ_DMA,
               0, 3,
               5L,
               FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
               3L );
   if ( rc )
      ShowAll();
   else
      // display the first 16 bytes read
      printf( "   data read %02X%02X%02X%02X %02X%02X%02X%02X "
                           "%02X%02X%02X%02X %02X%02X%02X%02X\n",
               buffer[ 0], buffer[ 1], buffer[ 2], buffer[ 3],
               buffer[ 4], buffer[ 5], buffer[ 6], buffer[ 7],
               buffer[ 8], buffer[ 9], buffer[10], buffer[11],
               buffer[12], buffer[13], buffer[14], buffer[15] );

#endif

   return 0;
}

// end example1.c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -