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

📄 example2.c

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

// Example2.c -- A program showing how to use ADVDRVR with ATAPI 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 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

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

#define BMCR_IO_ADDR 0xFF00   // 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 CDB_SIZE 16                 // local buffer for SCSI command blocks
unsigned char cdb[CDB_SIZE];
unsigned char far * cdbPtr;

#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;
   int ndx;

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

   // initialize far pointer to the CDB buffer
   cdbPtr = (unsigned char far *) cdb;

   // 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 an ATAPI Identify command in LBA mode
   printf( "ATAPI Identify...\n" );
   memset( buffer, 0, sizeof( buffer ) );
   rc = reg_pio_data_in_lba28(
               CMD_IDENTIFY_DEVICE_PACKET,
               0, 0,
               0L,
               FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
               1L, 0 );
   if ( rc )
      ShowAll();
   else
      // you get to add the code here to display all the ID data
      // 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 three ATAPI Request Sense command and display some of the data
   for ( ndx = 0; ndx < 3; ndx ++ )
   {
      printf( "ATAPI Request Sense...\n" );
      memset( cdb, 0, sizeof( cdb ) );
      cdb[0] = 0x03;    // RS command code
      cdb[4] = 32;      // allocation length
      memset( buffer, 0, sizeof( buffer ) );
      rc = reg_packet(
                       12, FP_SEG( cdbPtr ), FP_OFF( cdbPtr ),
                       0,
                       4096, FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
                       0L    // lba for tracing
                     );
      if ( rc )
         ShowAll();
      else
      {
         // here I'll give you some help -- lets look at the RS data
         // first a problem with ATAPI device: how much data was
         // really transferred?  You can never really be sure...
         if ( ADP->totalBytesXfer != ( 8U + buffer[7] ) )
            printf( "Number of bytes transferred (%ld) does not match \n"
                    "8 + byte 7 in the RS data received (%u) ! \n",
                    ADP->totalBytesXfer,
                    8U + buffer[7] );
         // display some of the RS data
         printf( "Error code=%02X, Sense Key=%02X, ASC=%02X, ASCQ=%02X\n",
                 buffer[0], buffer[2] & 0x0f, buffer[12], buffer[13] );
      }
   }

   // do an ATAPI Read TOC command and display the TOC data
   printf( "ATAPI CD-ROM Read TOC...\n" );
   memset( cdb, 0, sizeof( cdb ) );
   cdb[0] = 0x43;    // command code
   cdb[1] = 0x02;    // MSF flag
   cdb[7] = 0x10;    // allocation length
   cdb[8] = 0x00;    //    of 4096
   cdb[9] = 0x80;    // TOC format
   memset( buffer, 0, sizeof( buffer ) );
   rc = reg_packet(
                    12, FP_SEG( cdbPtr ), FP_OFF( cdbPtr ),
                    0,
                    4096, FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
                    0L    // lba for tracing
                  );
   if ( rc )
      ShowAll();
   else
   {
      // and here too I'll give you some help looking at the TOC data
      // again, check the number of bytes transferred (notice
      // how every SCSI like command is different here)
      if ( ADP->totalBytesXfer
           !=
           ( 2U + ( buffer[0] * 256U ) + buffer[1] )
         )
         printf( "Number of bytes transferred (%ld) does not match \n"
                 "2 + bytes 0-1 in the TOC data received (%u) ! \n",
                 ADP->totalBytesXfer,
                 2U + ( buffer[0] * 256U ) + buffer[1] );
      // display the TOC data
      printf( "First Session=%02X, Last Session=%02X\n",
               buffer[2], buffer[3] );
      printf( "TOC entries (11 bytes each)... \n" );
      rc = ( ( buffer[0] * 256U ) + buffer[1] - 2U ) / 11;
      ndx = 4;
      while ( rc > 0 )
      {
         printf( "   %02X %02X %02X "
                    "%02X %02x %02X "
                    "%02X %02X %02X "
                    "%02X %02x \n",
                     buffer[ndx+0], buffer[ndx+1], buffer[ndx+2],
                     buffer[ndx+3], buffer[ndx+4], buffer[ndx+5],
                     buffer[ndx+6], buffer[ndx+7], buffer[ndx+8],
                     buffer[ndx+9], buffer[ndx+10], buffer[ndx+11]
               );
         rc -- ;
         ndx = ndx + 11;
      }
   }

#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 ATAPI Read TOC command and display the TOC data
   // but do it in DMA mode
   printf( "ATAPI CD-ROM Read TOC in DMA...\n" );
   memset( cdb, 0, sizeof( cdb ) );
   cdb[0] = 0x43;    // command code
   cdb[1] = 0x02;    // MSF flag
   cdb[7] = 0x10;    // allocation length
   cdb[8] = 0x00;    //    of 4096
   cdb[9] = 0x80;    // TOC format
   memset( buffer, 0, sizeof( buffer ) );
   rc = dma_pci_packet(
                        12, FP_SEG( cdbPtr ), FP_OFF( cdbPtr ),
                        0,
                        4096, FP_SEG( bufferPtr ), FP_OFF( bufferPtr ),
                        0L    // lba for tracing
                      );
   if ( rc )
      ShowAll();
   else
   {
      // and here too I'll give you some help looking at the TOC data
      // again, check the number of bytes transferred (notice
      // how every SCSI like command is different here?
      if ( ADP->totalBytesXfer
           !=
           ( 2U + ( buffer[0] * 256U ) + buffer[1] )
         )
         printf( "Number of bytes transferred (%ld) does not match \n"
                 "2 + bytes 0-1 in the TOC data received (%u) ! \n",
                 ADP->totalBytesXfer,
                 2U + ( buffer[0] * 256U ) + buffer[1] );
      // display the TOC data
      printf( "First Session=%02X, Last Session=%02X\n",
               buffer[2], buffer[3] );
      printf( "TOC entries (11 bytes each)... \n" );
      rc = ( ( buffer[0] * 256U ) + buffer[1] - 2U ) / 11;
      ndx = 4;
      while ( rc > 0 )
      {
         printf( "   %02X %02X %02X "
                    "%02X %02x %02X "
                    "%02X %02X %02X "
                    "%02X %02x \n",
                     buffer[ndx+0], buffer[ndx+1], buffer[ndx+2],
                     buffer[ndx+3], buffer[ndx+4], buffer[ndx+5],
                     buffer[ndx+6], buffer[ndx+7], buffer[ndx+8],
                     buffer[ndx+9], buffer[ndx+10], buffer[ndx+11]
               );
         rc -- ;
         ndx = ndx + 11;
      }
   }

#endif

   return 0;
}

// end example2.c

⌨️ 快捷键说明

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