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

📄 atadrv.c

📁 用于EQUATOR处理器上的FAT32文件系统(vxWorks5.5)
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ataDrv.c - ATA/IDE (LOCAL and PCMCIA) disk device driver */


/* Copyright 1989-1998 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01o,02oct01,clc  updated with WRS changes:
                 (01o,19sep99,jkf) Removed extra SYS_ATA_INIT_RTN, 
		                   now check wait in ataRW().
                 (01n,17jul99,jkf) using words 60-61 to determine LBA instead 
		                   of CHS calculation, for big drives, 
				   8.4Gb+. SPR#22830.
01n,04apr01,clc  MAPCA shark support
01m,04mar99,jkf  Added SYS_ATA_INIT_RTN.  _func_sysAtaInit. SPR#24378.
01l,09jun98,dat  fixed conflicting prototypes, removed ref to sysMsDelay()
01k,09jun98,ms   removed IMPORT prototypes conflicting with sysLib.h proto's
01j,31mar98,map  removed INCLUDE_ATA, redefined sys* prototypes.
01i,23mar98,map  renamed macros, made endian safe, added docs.
01h,30oct97,db   added cmd to reinitialize controller with params read. fixed
                 bug reported in SPR #9139. used PCI macros for input/output.
01g,21apr97,hdn  fixed a semaphore timeout problem(SPR 8394).
01f,28feb97,dat  fixed SPRs 8084, 3273 from ideDrv.
01e,06nov96,dgp  doc: final formatting
01d,01nov96,hdn  added support for PCMCIA.
01c,25sep96,hdn  added support for ATA-2.
01b,01mar96,hdn  cleaned up.
01a,02mar95,hdn  written based on ideDrv.c.
*/

/*
DESCRIPTION

This is a driver for ATA/IDE devices on PCMCIA, ISA, and other buses. The
driver can be customized via various macros to run on a variety of boards and
both big-endian, and little endian CPUs.

USER-CALLABLE ROUTINES

Most of the routines in this driver are accessible only through the I/O
system.  However, two routines must be called directly:  ataDrv() to
initialize the driver and ataDevCreate() to create devices.

Before the driver can be used, it must be initialized by calling ataDrv().
This routine must be called exactly once, before any reads, writes, or
calls to ataDevCreate().  Normally, it is called from usrRoot() in
usrConfig.c.

The routine ataRawio() supports physical I/O access. The first
argument is a drive number, 0 or 1; the second argument is a pointer
to an ATA_RAW structure.

During initialization this driver queries each disk to determine 
if the disk supports LBA.  16 bit words 0x60 and 0x61 (returned 
from the ATA IDENTIFY DEVICE command) may report a larger value 
than the product of the CHS fields on newer large disks (8.4Gb+).  
The driver will use strict LBA access commands and LBA geometry for 
drives reporting "total LBA sectors" greater than the product of CHS.
Although everyone should also be using strict LBA on LBA disks, some 
older systems (mostly PC's) do not and use only CHS.  Such system cannot 
view drives larger than 8GB.  VxWorks does not have such limitations.    
However, it may be desirable to force VxWorks ignore the LBA information 
in favor of CHS in order to mount a file system originally formatted on 
a CHS only system.  Setting the boolean ataForceCHSonLBA to TRUE will 
force the use of CHS parameters on all drives and the LBA parameters 
are ignored.  Again, setting this boolean may prevent access to the 
drives full capacity, since some manufacturers have stopped setting 
a drives CHS accurately in favor of LBA.

The routine ataMount() mounts a drive given ctrl, drive #, and a name.
This routine assumes that the drive has been formated using a call to AtaFormat.
The mount routine will configure the drive to use the full drive size, and 
isn't limited by the dos FS file system size.

PARAMETERS
The ataDrv() function requires a configuration flag as a parameter.
The configuration flag is one of the following:

.TS
tab(|);
l l .
Transfer mode 

ATA_PIO_DEF_0    | PIO default mode
ATA_PIO_DEF_1    | PIO default mode, no IORDY
ATA_PIO_0        | PIO mode 0
ATA_PIO_1        | PIO mode 1
ATA_PIO_2        | PIO mode 2
ATA_PIO_3        | PIO mode 3
ATA_PIO_4        | PIO mode 4
ATA_PIO_AUTO     | PIO max supported mode
ATA_DMA_0        | DMA mode 0
ATA_DMA_1        | DMA mode 1
ATA_DMA_2        | DMA mode 2
ATA_DMA_AUTO     | DMA max supported mode

Transfer bits

ATA_BITS_16      | RW bits size, 16 bits
ATA_BITS_32      | RW bits size, 32 bits

Transfer unit

ATA_PIO_SINGLE   | RW PIO single sector
ATA_PIO_MULTI    | RW PIO multi sector
ATA_DMA_SINGLE   | RW DMA single word
ATA_DMA_MULTI    | RW DMA multi word

Geometry parameters

ATA_GEO_FORCE    | set geometry in the table
ATA_GEO_PHYSICAL | set physical geometry
ATA_GEO_CURRENT  | set current geometry
.TE

If ATA_PIO_AUTO or ATA_DMA_AUTO
is specified, the driver automatically chooses the maximum mode supported by the
device.  If ATA_PIO_MULTI or ATA_DMA_MULTI is specified, and the device does
not support it, the driver automatically chooses single sector or word mode.
If ATA_BITS_32 is specified, the driver uses 32-bit transfer mode regardless of
the capability of the drive.  

If ATA_GEO_PHYSICAL is specified, the driver uses the physical geometry 
parameters stored in the drive.  If ATA_GEO_CURRENT is specified,
the driver uses current geometry parameters initialized by BIOS.  
If ATA_GEO_FORCE is specified, the driver uses geometry parameters stored 
in sysLib.c.

The geometry parameters are stored in the structure table
`ataTypes[]' in sysLib.c. That table has two entries, the first for
drive 0, the second for drive 1. The members of the structure
are:
.CS
    int cylinders;              /@ number of cylinders @/
    int heads;                  /@ number of heads @/
    int sectors;                /@ number of sectors per track @/
    int bytes;                  /@ number of bytes per sector @/
    int precomp;                /@ precompensation cylinder @/
.CE

This driver does not access the PCI-chip-set IDE interface, but rather takes
advantage of BIOS or VxWorks initialization.  Thus, the BIOS setting should 
match the modes specified by the configuration flag.

The BSP may provide a sysAtaInit() routine for situations where an ATA
controller RESET (0x1f6 or 0x3f6, bit 2 is set) clears ATA specific
functionality in a chipset that is not re-enabled per the ATA-2 spec.
 
This BSP routine should be declared in sysLib.c or sysAta.c as follows:
 
.CS
void sysAtaInit (BOOL ctrl)
    {
    /@ BSP SPECIFIC CODE HERE @/
    }
.CE

Then the BSP should perform the following operation
before ataDrv() is called, in sysHwInit for example:

.CS
    IMPORT VOIDFUNCPTR _func_sysAtaInit;
    /@ setup during initialization @/
    _func_sysAtaInit = (VOIDFUNCPTR) sysAtaInit;
.CE


 
It should contain chipset specific reset code, such as code which re-enables
PCI write posting for an integrated PCI-IDE device, for example.  This will
be executed during every ataDrv(), ataInit(), and ataReset() or equivalent  
block device routine.  If the sysAtaInit routine is not provided by the
BSP it is ignored by the driver, therefore it is not a required BSP routine.

SEE ALSO:
.pG "I/O System"
*/

#include "vxWorks.h"
#include "taskLib.h"
#include "ioLib.h"
#include "memLib.h"
#include "stdlib.h"
#include "errnoLib.h"
#include "stdio.h"
#include "string.h"
#include "private/semLibP.h"
#include "intLib.h"
#include "iv.h"
#include "wdLib.h"
#include "sysLib.h"
#include "sys/fcntlcom.h"
#include "drv/pcmcia/pcmciaLib.h"
#include "ataDrv.h"
#include "time.h"


#define VXDOS                           "VXDOS"
#define VXEXT                           "VXEXT"
// first entry bytes before 64K boundry
#define MAX_TRANSFER    0xFFFE 
#define MAX_PRD_ENTRIES 4
//#define ATA_DEBUG
typedef struct
{
 int setup;
 int active;
 int recovery;
} TIMING_PARAMETERS;
 
TIMING_PARAMETERS Tparams[5] = {
{70,165,365}, 
{50,125,208},
{30,100,110},
{30,80,70},
{25,70,25} };

#define PCI_BUS_PERIOD            30
#define ALI_VENDOR_ID             0x10B9
#define IDE_DEVICE_ID             0x5229


/* imports */

IMPORT ATA_TYPE		ataTypes [ATA_MAX_CTRLS][ATA_MAX_DRIVES];
IMPORT ATA_RESOURCE	ataResources [ATA_MAX_CTRLS];

/* Byte swapping version of sysInWordString(), big-endian CPUs only */

IMPORT void	sysInWordStringRev (int port, short *pData, int count);

/* defines */

/* Read a BYTE from IO port, `ioAdrs' */

#ifndef ATA_IO_BYTE_READ
#define ATA_IO_BYTE_READ(ioAdrs)	sysInByte (ioAdrs)
#endif	/* ATA_IO_BYTE_READ */

/* Write a BYTE `byte' to IO port, `ioAdrs' */

#ifndef ATA_IO_BYTE_WRITE
#define ATA_IO_BYTE_WRITE(ioAdrs, byte)	sysOutByte (ioAdrs, byte)
#endif	/* ATA_IO_BYTE_WRITE */

/* Read 16-bit little-endian `nWords' into `pData' from IO port, `ioAdrs' */

#ifndef ATA_IO_NWORD_READ
#define ATA_IO_NWORD_READ(ioAdrs, pData, nWords)                        \
	sysInWordString (ioAdrs, pData, nWords)
#endif	/* ATA_IO_NWORD_READ */

/* Write 16-bit little-endian `nWords' from `pData' into IO port, `ioAdrs' */

#ifndef ATA_IO_NWORD_WRITE
#define ATA_IO_NWORD_WRITE(ioAdrs, pData, nWords)                       \
	sysOutWordString (ioAdrs, pData, nWords)
#endif /* ATA_IO_NWORD_WRITE */
    
/* Read 32-bit little-endian `nLongs' into `pData' from IO port, `ioAdrs' */

#ifndef ATA_IO_NLONG_READ
#define ATA_IO_NLONG_READ(ioAdrs, pData, nLongs)                        \
	sysInLongString (ioAdrs, pData, nLongs)
#endif	/* ATA_IO_NLONG_READ */

/* Write 32-bit little-endian `nLongs' from `pData' into IO port, `ioAdrs' */

#ifndef ATA_IO_NLONG_WRITE
#define ATA_IO_NLONG_WRITE(ioAdrs, pData, nLongs)                       \
	sysOutLongString (ioAdrs, pData, nLongs)
#endif	/* ATA_IO_NLONG_WRITE */

/* Read 32-bit CPU-endian `nWords' into `pData' from IO port, `ioAdrs' */

#ifndef	ATA_IO_NWORD_READ_SWAP
#  if (_BYTE_ORDER == _BIG_ENDIAN)
#  define ATA_IO_NWORD_READ_SWAP(ioAdrs, pData, nWords)                 \
	sysInWordStringRev (ioAdrs, pData, nWords)
#  else	/* (_BYTE_ORDER == _BIG_ENDIAN)	*/
#  define ATA_IO_NWORD_READ_SWAP(ioAdrs, pData, nWords)                 \
	ATA_IO_NWORD_READ (ioAdrs, pData, nWords)
#  endif /* (_BYTE_ORDER == _BIG_ENDIAN) */
#endif	/* ATA_IO_NLONG_READ_SWAP */

/* Special BSP INIT After ATA Reset */

/* Special BSP INIT After ATA Reset */
#ifndef SYS_ATA_INIT_RTN
#define SYS_ATA_INIT_RTN(ctrl)  if (_func_sysAtaInit != NULL)    \
                                    {                            \
                                    ((*_func_sysAtaInit)(ctrl)); \
                                    }
#endif

/* globals */

BOOL	  ataDrvInstalled = FALSE;	/* TRUE if installed */
BOOL	  ataForceCHSonLBA = FALSE;	/* hack, forces use of CHS params */

ATA_CTRL  ataCtrl [ATA_MAX_CTRLS];

/* BSP specific ATA Init/Reset routine */
VOIDFUNCPTR       _func_sysAtaInit = NULL;


/* locals */

LOCAL int       ataRetry = 3;		/* max retry count 3 */

/* Used to hold LBA information, if larger than calculated CHS value */

LOCAL UINT32 ataLbaTotalSecs [ATA_MAX_CTRLS][ATA_MAX_DRIVES];

/* DMA */
static unsigned int busMasterRegs[ATA_MAX_CTRLS] = {0,0}; // address bus master regs

#define BM_COMMAND_REG    0            // offset to command reg
#define BM_CR_MASK_READ    0x08           // read from memory
#define BM_CR_MASK_WRITE   0x00           // write to memory
#define BM_CR_MASK_START   0x01           // start transfer
#define BM_CR_MASK_STOP    0x00           // stop transfer

#define BM_STATUS_REG     2            // offset to status reg
#define BM_SR_MASK_SIMPLEX 0x80           // simplex only
#define BM_SR_MASK_DRV1    0x40           // drive 1 can do dma
#define BM_SR_MASK_DRV0    0x20           // drive 0 can do dma
#define BM_SR_MASK_INT     0x04           // INTRQ signal asserted
#define BM_SR_MASK_ERR     0x02           // error
#define BM_SR_MASK_ACT     0x01           // active

#define BM_PRD_ADDR  4                // offset to prd addr reg low 16 bits


static unsigned char statReg[ATA_MAX_CTRLS];          // save BM status reg bits
static unsigned char rwControl[ATA_MAX_CTRLS];        // read/write control bit setting

//***********************************************************
//
// pci bus master control macros
//
//***********************************************************

#define enableChan(ctrl)  sysOutByte(busMasterRegs[ctrl] + BM_COMMAND_REG, \
                                rwControl[ctrl] | BM_CR_MASK_START )
#define disableChan(ctrl) sysOutByte( busMasterRegs[ctrl] + BM_COMMAND_REG, \
                                BM_CR_MASK_STOP )
#define clearChan(ctrl) sysOutByte( busMasterRegs[ctrl] + BM_STATUS_REG, \
                              statReg[ctrl] | BM_SR_MASK_INT | BM_SR_MASK_ERR )




typedef struct {
   char *  address;
   struct {
     unsigned long count:16;
     unsigned long reserved:15;
     unsigned long EOT:1;
   }bits;             
} PRD_ENTRY,*PPRD_ENTRY;

static STATUS ataDmaSetupXfer(int ctrl, int dir, char *buffer, int count);
static int  ataDmaConfig(int ctrl, UINT32 regAddr );


/* function prototypes */

LOCAL STATUS ataBlkRd	(ATA_DEV *pDev, int startBlk, int nBlks, char *p);
LOCAL STATUS ataBlkWrt	(ATA_DEV *pDev, int startBlk, int nBlks, char *p);
LOCAL STATUS ataReset	(ATA_DEV *pDev);
LOCAL STATUS ataStatus	(ATA_DEV *pDev);
LOCAL STATUS ataIoctl	(ATA_DEV *pDev, int function, int arg);
LOCAL STATUS ataBlkRW	(ATA_DEV *pDev, int startBlk, int nBlks, char *p,
			 int direction);
LOCAL void   ataWdog	(int ctrl);
void   ataIntr	(int ctrl);
STATUS ataInit	(int ctrl);
LOCAL void   ataWait	(int ctrl, int request);
LOCAL STATUS ataCmd	(int ctrl, int drive, int cmd, int arg0, int arg1);
LOCAL STATUS ataPread	(int ctrl, int drive, void *p);
LOCAL STATUS ataRW	(int ctrl, int drive, int cylinder, int head, int sec, 
	 		 void *p, int nSecs, int direction);
LOCAL STATUS ataDmaRW	(int ctrl, int drive, int cylinder, int head, int sec, 
	 		 void *p, int nSecs, int direction);
LOCAL STATUS ataTuneDrive(int ctrl, int drive);
LOCAL STATUS ataEnableDma(int ctrl, int drive);


void    sysInWordString
    (
    ULONG port,
    UINT16 *pData,
    int count
    ) 
    {
    UINT32 volatile_noncached *x;
    UINT32 volatile_noncached *y;
    int    status;
    int     i;

    x = (UINT32 volatile_noncached *)PCIA_PIO_CMD;
    y = (((UINT32)port & 0x4) == 0) ? 
          (UINT32 volatile_noncached *)PCIA_PIO_DATA_E : 
          (UINT32 volatile_noncached *)PCIA_PIO_DATA_O;

    status = intLock();
    *x = PCI_CMD_IO_READ;
    *(x+1) = (UINT32)port;
    for (i=0;i<count;i++) {

   

       *(pData + i) = *((UINT16 volatile_noncached *)(((UINT32)y) | ((UINT32)port & 0x3)));
    }
    intUnlock(status);

    return; 

    }


void    sysInLongString
    (
    ULONG port,
    ULONG *pData,
    int count
    )
    {
    int i;
    for(i=0;i<count;i++)
        *(pData + i) = sysInLong(port);
    }

void    sysOutWordString
    (
    ULONG port,
    UINT16 *pData,
    int count
    )
{
     int i;
     UINT32 volatile_noncached *x;
     UINT32 volatile_noncached *y;
     int    status;

     x = (UINT32 volatile_noncached *)PCIA_PIO_CMD;
     y = (((UINT32)port & 0x4) == 0) ? 
          (UINT32 volatile_noncached *)PCIA_PIO_DATA_E : 
          (UINT32 volatile_noncached *)PCIA_PIO_DATA_O;

     status = intLock();



     for(i=0;i<count;i++) {
        *x = PCI_CMD_IO_WRITE;
        *(x+1) = (UINT32)port;
        *((UINT16 volatile_noncached *)(((UINT32)y) | ((UINT32)port & 0x3))) = *(pData + i);
    }
    intUnlock(status);

⌨️ 快捷键说明

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