genode/repos/os/src/drivers/atapi/contrib/mindrvr-guide.txt

388 lines
15 KiB
Plaintext

MINDRVR
Simple ATA/ATAPI Low Level Driver for Embedded Systems
User's Guide
by Hale Landis
Version 0G and higher
INTRODUCTION
------------
MINDRVR is a simple version of ATADRVR. ATADRVR is Hale Landis'
C code that shows the low level programming required to configure
and execute commands on ATA and ATAPI devices. MINDRVR is
suitable for embedded systems that have simple ATA interface
hardware that is memory mapped. MINDRVR does not have some
features of ATADRVR, such as, the command and low level trace
facility, no support for ATA CHS addressing, no and checking of
ATAPI command protocol errors.
MINDRVR is fully contained in two files: MINDRVR.H and
MINDRVR.C.
MINDRVR, like ATADRVR, supports all of the ATA and ATA/ATAPI
standards.
The MINDRVR C code has been placed into the public domain by Hale
Landis. This C code has no copyright or other restrictions on
how it is used.
USING MINDRVR
-------------
Normally a "file system" driver would call MINDRVR to perform actual
phyical I/O operations on ATA or ATAPI devices using PIO or DMA data
transfer modes. Any program or driver that calls MINDRVR must include
the MINDRVR.H header file. MINDRVR.H defines all the MINDRVR public
functions and public data.
The basics of using MINDRVR are:
1) Review the MINDRVR.H and MINDRVR.C files. In these files look
for comment lines that have the string '!!!'. These comments
explain the information you must provide at compile time, such
as, the memory addresses for the ATA registers in your
system's memory.
2) #include "mindrvr.h" in your program or driver that will call
MINDRVR.
3) Call reg_config() so that MINDRVR can determine what devices
are attached to the ATA host adapter.
4) Call reg_reset() or any of the other "reg_" functions to issue
ATA or ATAPI commands in PIO data transfer mode. If your
system can support ATA/ATAPI DMA then call the dma_pci_"
functions to issue ATA or ATAPI commands in DMA data transfer
mode.
Note that MINDRVR is designed for systems with a single ATA
controller (single ATA inteface). If you system has multiple ATA
controllers/interfaces then you will need to either: a) make a
separate MINDRVR for each controller, or b) switch between
controllers by swapping the MINDRVR configuration information
between calls to MINDRVR.
MINDRVR REFERENCE
-----------------
Each of the public functions and symbols of MINDRVR are described
below in alphabetical order.
Note that there is no "interrupt handler" defined by MINDRVR.
You must supply the appropriate interrupt handler as described in
MINDRVR.H and MINDRVR.C.
Public Data
-----------
unsigned char int_ata_status;
When using interrupts the interrupt handler must return this
data. This is the interrupting device's ATA status as read by
interrupt handler.
unsigned char int_bmide_status;
When using interrupts the interrupt handler must return this
data. This is the interrupting controller's BMIDE status read
by interrupt handler.
unsigned char int_use_intr_flag;
MINDRVR can be switched between polling mode and interrupt
mode. Note that interrupt mode is required for DMA data
transfers.
Make this value not zero to use interrupts.
unsigned char pio_xfer_width;
This variable controls the width of PIO data transfers.
This variable can have the following values:
8 = 8-bits. PIO transfers will use 8-bit memory write/read
when accessing the ATA Data register.
16 = 16-bits. PIO transfers will use 16-bit memory write/read
when accessing the ATA Data register.
32 = 32-bits. PIO transfers will 32-bit memory write/read
when accessing the ATA Data register.
Any other value is treated the same as 16.
struct REG_CMD_INFO
{
// command code
unsigned char cmd; // command code
// command parameters
unsigned int fr; // feature (8 or 16 bits)
unsigned int sc; // sec cnt (8 or 16 bits)
unsigned int sn; // sec num (8 or 16 bits)
unsigned int cl; // cyl low (8 or 16 bits)
unsigned int ch; // cyl high (8 or 16 bits)
unsigned char dh; // device head
unsigned char dc; // device control
long ns; // actual sector count
int mc; // current multiple block setting
unsigned char lbaSize; // size of LBA used
#define LBACHS 0 // last command used ATA CHS (not supported by MINDRVR)
// -or- last command was ATAPI PACKET command
#define LBA28 28 // last command used ATA 28-bit LBA
#define LBA48 48 // last command used ATA 48-bit LBA
unsigned long lbaLow; // lower 32-bits of ATA LBA
unsigned long lbaHigh; // upper 32-bits of ATA LBA
// status and error regs
unsigned char st; // status reg
unsigned char as; // alt status reg
unsigned char er ; // error reg
// driver error codes
unsigned char ec; // detailed error code
unsigned char to; // not zero if time out error
// additional result info
long totalBytesXfer; // total bytes transfered
long drqPackets; // number of PIO DRQ packets
} ;
struct REG_CMD_INFO reg_cmd_info;
This data structure contains information about the last reset or command
that was executed.
int reg_config( void );
This function shoul be called so that MINDRVR can correctly
configure itself. reg_config() sets the values into
reg_config_info[2].
Note that the program calling MINDRVR may bypass calling this
function as long as reg_config_info[] is set appropriately
before attempting to execute any resets or commands.
int reg_config_info[2];
This array is set by calling reg_config(). reg_config_info[0]
describes device 0 and reg_config_info[1] describes device 1.
The possible values in these words are (see MINDRVR.H):
REG_CONFIG_TYPE_NONE, REG_CONFIG_TYPE_UNKN,
REG_CONFIG_TYPE_ATA, REG_CONFIG_TYPE_ATAPI.
Note that MINDRVR is not able to determine the type of some
devices. However, after issuing some commands the calling
program may be able to determine the exact type of a device.
The calling program may change the values in this array but
this must be done very carefully:
a) DO NOT CHANGE the value REG_CONFIG_TYPE_NONE.
b) DO NOT CHANGE a value to REG_CONFIG_TYPE_NONE.
c) The value REG_CONFIG_TYPE_UNKN can be changed to either
REG_CONFIG_TYPE_ATA or REG_CONFIG_TYPE_ATAPI.
int reg_non_data_lba28( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lba ); // LBA
Execute an ATA Non-Data command using LBA sector addressing.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int reg_non_data_lba48( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lbahi, // LBA upper 16-bits
long lbalo ); // LBA lower 32 bits
Execute an ATA Non-Data command using LBA sector addressing.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int reg_packet( unsigned char dev, // device (0 or 1)
unsigned int cpbc, // command packet size
unsigned char * cdbBufAddr, // CDB buffer
int dir, // 0 for no data or read, 1 for write
unsigned int dpbc, // max data packet size
unsigned char * dataBufAddr ); // data packet buffer
Execute an ATAPI Packet (A0H) command in PIO mode. Note that
the first byte of the Commmand Packet buffer is the command
code of the "SCSI CDB" that is to be executed by the device.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int reg_pio_data_in_lba28( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lba, // LBA
unsigned char * bufAddr, // buffer address
int numSect, // number of sectors to transfer
int multiCnt ); // current multiple count
Execute an ATA PIO Data In command in LBA sector addressing
mode.
numSect is the actual number of sectors to be transferred.
This value may be different than the sc value.
If cmd is C4H (Read Multiple) then multiCnt MUST be set to the
current sectors per block.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int reg_pio_data_in_lba48( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lbahi, // LBA upper 16-bits
long lbalo, // LBA lower 32 bits
unsigned char * bufAddr, // buffer address
int numSect, // number of sectors to transfer
int multiCnt ); // current multiple count
Execute an ATA PIO Data In command in LBA sector addressing
mode.
numSect is the actual number of sectors to be transferred.
This value may be different than the sc value.
If cmd is C4H (Read Multiple) then multiCnt MUST be set to the
current sectors per block.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int reg_pio_data_out_lba28( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lba, // LBA
unsigned char * bufAddr, // buffer address
int numSect, // number of sectors to transfer
int multiCnt ); // current multiple count
Execute an ATA PIO Data Out command in LBA sector addressing
mode.
numSect is the actual number of sectors to be transferred.
This value may be different than the sc value.
If cmd is C5H (Write Multiple) then multiCnt MUST be set to
the current sectors per block.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int reg_pio_data_out_lba48( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lbahi, // LBA upper 16-bits
long lbalo, // LBA lower 32 bits
unsigned char * bufAddr, // buffer address
int numSect, // number of sectors to transfer
int multiCnt ); // current multiple count
Execute an ATA PIO Data Out command in LBA sector addressing
mode.
numSect is the actual number of sectors to be transferred.
This value may be different than the sc value.
If cmd is C5H (Write Multiple) then multiCnt MUST be set to
the current sectors per block.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int reg_reset( unsigned char devRtrn ); // device's data returned
Execute an ATA Soft Reset. Set devRtrn to 0 or 1 to determine
which device's register contents are returned in reg_cmd_info.
DMA Data Transfer Functions And Data
------------------------------------
These functions setup PCI bus DMA (ATA Multiword or Ultra DMA)
and perform ATA and ATAPI commands using DMA. The function
dma_pci_config() MUST be called with no error before any of the
other functions will attempt to execute a command.
int dma_pci_config( void );
Configure MINDRVR to use PCI bus DMA (ATA Multiword or Ultra
DMA) on a PCI Bus Mastering ATA controller.
This function may not be needed in your system - see the MINDRVR.H
and MINDRVR.C files.
int dma_pci_lba28( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lba, // LBA
unsigned char * bufAddr ); // buffer address
Execute an ATA Read DMA (C8H) or ATA Write DMA (CAH) command
using LBA sector addressing.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int dma_pci_lba48( unsigned char dev, // device (0 or 1)
unsigned char cmd, // command register
int fr, // feature register
int sc, // sector count
long lbahi, // LBA upper 16-bits
long lbalo, // LBA lower 32 bits
unsigned char * bufAddr ); // buffer address
Execute an ATA Read DMA (C8H) or ATA Write DMA (CAH) command
using LBA sector addressing.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
int dma_pci_packet( unsigned char dev, // device (0 or 1)
unsigned int cpbc, // command packet size
unsigned char * cdbBufAddr, // CDB buffer
int dir, // 0 for no data or read, 1 for write
unsigned int dpbc, // max data packet size
unsigned char * dataBufAddr ); // data packet buffer
Execute an ATAPI Packet (A0H) command in DMA mode. Note that
the first byte of the Commmand Packet buffer is the command
code of the "SCSI CDB" that is to be executed by the device.
Returns 0 if no error or 1 if there is an error. See the
contents of reg_cmd_info.
QUESTIONS OR PROBLEMS?
----------------------
Send your question(s) or problem description(s) to Hale Landis
via email at this address:
hlandis@ata-atapi.com
Visit Hale's web site:
www.ata-atapi.com
/end/