?? atadrv.c
字號:
/* ataDrv.c - ATA/IDE (LOCAL and PCMCIA) disk device driver */
/* Copyright 1989-1998 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01q,24jul00,jkf SPR#29571, nSectors reset change,fixed typo in 01p.
01p,12jul00,rcs Reset nSectors back to nSecs in ataRW on retryRW SPR#29571.
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.
01m,04mar99,jkf Added SYS_ATA_INIT_RTN. _func_sysAtaInit. SPR#24378.
02a,07dec98,mjc added support for ATAPI CD-ROMs (according to SFF-8020i);
changed driver initialization sequence to allow automatic
devices identification, and block device creation without
physical device presents, block device's reset procedure now
capable to initialize device, when it is actually attached to
the interface;
fixed SPR #22830;
removed seting of ATA_CTL_IDS bit from ataInit(), because this
is unnecessary and bring an unwanted interrupt;
replaced support for ATA_CMD_DIAGNOSE in ataCmd() by new
ataDiagnose(), because implementation of Execute Device
Diagnostic command in ataCmd() actually did nothing.
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.
NOTE
Format is not supported, because ATA/IDE disks are already formatted, and bad
sectors are mapped.
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.
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
DMA transfer is not supported in this release. 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 initialization. Thus, the BIOS setting should match
the modes specified by the configuration flag.
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 "logLib.h"
//#include "drv/hdisk/ataDrv.h"
#include "ataDrv.h"
#include "cdRawFsLib.h"
#ifdef INCLUDE_LEXAR_FORMAT
#include "h8051Drv.h"
#endif
#define VXDOS "VXDOS"
#define VXEXT "VXEXT"
#define MAX_TRANSFER 0xFFFE
#define MAX_PRD_ENTRIES 18
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 */
/* Delay to ensure Status Register content is valid */
#define ATA_WAIT_STATUS sysDelay () /* >= 400 ns */
/* ATA defined diagnostic codes */
#define ATA_DIAG_PASSED 0x01 /* Device passed diagnostics */
#define ATA_DIAG_FAILED 0x80 /* Device 1 failed diagnostics */
#define ATA_SIGNATURE(pCtrl) (ATA_IO_BYTE_READ ((pCtrl)->seccnt) == 0x01 && \
ATA_IO_BYTE_READ ((pCtrl)->sector) == 0x01 && \
ATA_IO_BYTE_READ ((pCtrl)->cylLo) == 0x00 && \
ATA_IO_BYTE_READ ((pCtrl)->cylHi) == 0x00)
#define ATAPI_SIGNATURE(pCtrl) (ATA_IO_BYTE_READ ((pCtrl)->seccnt) == 0x01 && \
ATA_IO_BYTE_READ ((pCtrl)->sector) == 0x01 && \
ATA_IO_BYTE_READ ((pCtrl)->cylLo) == 0x14 && \
ATA_IO_BYTE_READ ((pCtrl)->cylHi) == 0xeb)
/* definitions relating to ATAPI commands */
//#define PROMISE_HACK
//#define ATA_DEBUG 1
char pMode[0x100];
ATA_DEV *pgDevice[2][2] = {{NULL,NULL},{NULL,NULL}};
#ifdef ATA_DEBUG
#undef LOCAL
#define LOCAL
int ataDebugLevel = 1; /* debug verbosity level */
BOOL ataIntrDebug = 0; /* interrupt notification On */
char * ataErrStrs [ ] = /* error reason strings */
{
"Unknown Error", /* 0 */
"Wait for Command Packet request time expire", /* 1 */
"Error in Command Packet Request", /* 2 */
"Error in Command Packet Request", /* 3 */
"Wait for Data Request time expire", /* 4 */
"Data Request for NON Data command", /* 5 */
"Error in Data Request", /* 6 */
"Error in End of data transfer condition", /* 7 */
"Extra transfer request", /* 8 */
"Transfer size requested exceeds desired size", /* 9 */
"Transfer direction miscompare", /* 10 */
"No Sense", /* 11 */
"Recovered Error", /* 12 */
"Not Ready", /* 13 */
"Medium Error", /* 14 */
"Hardware Error", /* 15 */
"Illegal Request", /* 16 */
"Unit Attention", /* 17 */
"Data Protected", /* 18 */
"Aborted Command", /* 19 */
"Miscompare", /* 20 */
"\0", /* 21 */
"\0", /* 22 */
"\0", /* 23 */
"\0", /* 24 */
"\0", /* 25 */
"Overlapped commands are not emplemented", /* 26 */
"DMA transfer ERROR ", /* 27 */
};
char *SenseKeyDesc[] =
{
"NO SENSE", /* 0 */
"RECOVERED ERROR", /* 1 */
"NOT READY", /* 2 */
"MEDIUM ERROR", /* 3 */
"HARDWARE ERROR", /* 4 */
"ILLEGAL REQUEST", /* 5 */
"UNIT ATTENTION", /* 6 */
"DATA PROTECT", /* 7 */
"BLANK CHECK", /* 8 */
"Reserved", /* 9 */
"Reserved", /* A */
"ABORTED COMMAND", /* B */
"Reserved", /* C */
"Reserved", /* D */
"MISCOMPARE", /* E */
"Reserved" /* F */
};
# define ATA_DEBUG_MSG(lvl, fmt, a1, a2, a3, a4, a5, a6) \
if ((lvl) <= ataDebugLevel) \
logMsg (fmt, (int)(a1), (int)(a2), (int)(a3), (int)(a4), \
(int)(a5), (int)(a6));
# define ATA_INTR_MSG(fmt, a1, a2, a3, a4, a5, a6) \
if (ataIntrDebug) \
logMsg (fmt, (int)(a1), (int)(a2), (int)(a3), (int)(a4), \
(int)(a5), (int)(a6));
#else
# define ATA_DEBUG_MSG(lvl, fmt, a1, a2, a3, a4, a5, a6)
# define ATA_INTR_MSG(fmt, a1, a2, a3, a4, a5, a6)
#endif
/* typedefs */
#define ENDIAN_4(a, j) { u_long i=j; \
((u_char *)(a))[0] = (i) >> 24 & 0xFF;\
((u_char *)(a))[1] = (i) >> 16 & 0xFF;\
((u_char *)(a))[2] = (i) >> 8 & 0xFF;\
((u_char *)(a))[3] = (i) & 0xFF;}
static void ENDIAN_2(void *result, unsigned short i)
{
char *a = (char *)result;
a[0] = i >> 8 & 0xFF;
a[1] = i & 0xFF;
}
/* 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 */
/* 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[2] = {0,0}; // address bus master regs
static unsigned int atapiReg[2] = {0,0}; // atapi port - promise hack
static unsigned int clockReg[2] = {0,0}; // clock register - promise hack
#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[2]; // save BM status reg bits
static unsigned char rwControl[2]; // read/write control bit setting
/***********************************************************
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -