📄 nwatadrv.c
字号:
/* ataDrv.c - ATA/IDE (LOCAL and PCMCIA) disk device driver */
/* Copyright 1989-1998 Wind River Systems, Inc. */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <asm/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include "nwAtaDrv.h"
#include "ks8695p.h"
#include "../Vxworks2Linux/Vxworks2Linux.h"
#define VXDOS "VXDOS"
#define VXEXT "VXEXT"
#undef ATA_MAX_CTRLS
#define ATA_MAX_CTRLS 1
#define ATA0_IO_START0 (EXT_IO_BANK_2 | 0x00) /* io for ATA0 */
#define ATA0_IO_STOP0 (EXT_IO_BANK_2 | 0x1c)
#define ATA0_IO_START1 (EXT_IO_BANK_2 | 0x20)
#define ATA0_IO_STOP1 (EXT_IO_BANK_2 | 0x2c)
#define ATA0_INT_LVL INT_LVL_EXTI1S
#define ATA0_INT_VEC INT_VEC_EXTI1S
#define ATA0_CONFIG (ATA_GEO_PHYSICAL | ATA_PIO_AUTO \
| ATA_BITS_16 | ATA_PIO_MULTI)
/*
#define ATA1_IO_START0 (EXT_IO_BANK_2 | 0x00) // io for ATA1
#define ATA1_IO_STOP0 (EXT_IO_BANK_2 | 0x0e)
#define ATA1_IO_START1 (EXT_IO_BANK_2 | 0x10)
#define ATA1_IO_STOP1 (EXT_IO_BANK_2 | 0x1e)
#define ATA1_INT_LVL INT_LVL_EXTI1S
#define ATA1_INT_VEC INT_VEC_EXTI1S
#define ATA1_CONFIG (ATA_GEO_PHYSICAL | ATA_PIO_AUTO | \
ATA_BITS_16 | ATA_PIO_MULTI)*/
#define ATA_SEM_TIMEOUT 1 /* timeout for ATA sync sem */
#define ATA_WDG_TIMEOUT 2 /* timeout for ATA watch dog */
/* imports */
ATA_TYPE ataTypes[ATA_MAX_CTRLS][ATA_MAX_DRIVES] =
{
{{761, 8, 39, 512, 0xff}, /* ctrl 0 drive 0 */
{761, 8, 39, 512, 0xff}} /* ctrl 0 drive 1 */
};
ATA_RESOURCE ataResources[ATA_MAX_CTRLS] =
{
{
{
5, 0,
{ATA0_IO_START0, ATA0_IO_START1}, {ATA0_IO_STOP0, ATA0_IO_STOP1}, 0,
0, 0, 0, 0, 0
},
IDE_LOCAL, 1, 0/*ATA0_INT_VEC*/, ATA0_INT_LVL, ATA0_CONFIG,
ATA_SEM_TIMEOUT, ATA_WDG_TIMEOUT, 0, 0
} /* ctrl 0 */
};
/*IMPORT ATA_TYPE ataTypes [ATA_MAX_CTRLS][ATA_MAX_DRIVES];
IMPORT ATA_RESOURCE ataResources [ATA_MAX_CTRLS];*/
/* add by wangb for ultra dma mode 2005-11-2 14:17*/
// first entry bytes before 64K boundry
#define MAX_TRANSFER (0x10000)
#define MAX_PRD_ENTRIES (4)
/* DMA */
static unsigned int busMasterRegs[2] = {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
/* gloab */
UINT32 g_dwAtaCbio[2][2] = { {0,0}, {0,0} };
UINT32 g_dwAtaHDAllBlocks[2][2] = { {0,0}, {0,0} };
static unsigned char statReg[2]; // save BM status reg bits
static unsigned char rwControl[2]; // read/write control bit setting
#define ATA_DEBUG
#undef ATA_DEBUG
//***********************************************************
//
// pci bus master control macros
//
//***********************************************************
typedef struct {
char * address;
struct {
unsigned long count:16;
unsigned long reserved:15;
unsigned long EOT:1;
}bits;
} PRD_ENTRY,*PPRD_ENTRY;
static PRD_ENTRY prdTable[2][MAX_PRD_ENTRIES];
STATUS ataDmaSetupXfer(int ctrl, int dir, char *buffer, int count);
int ataDmaConfig(int ctrl, UINT32 regAddr );
unsigned char atpRDByt(UINT32 ioAdrs);
void atpWRByt(UINT32 ioAdrs, UINT8 byte);
/* end by wangb for ultra dma mode 2005-11-2 14:17 */
/* Byte swapping version of sysInWordString(), big-endian CPUs only */
/*IMPORT void sysInWordStringRev (int port, short *pData, int count);*/
void sysInWordString( ULONG ioAddr, UINT16 * bufPtr,int nWords);
void sysOutWordString(ULONG ioAddr,UINT16 * bufPtr,int nWords);
void sysInLongString(ULONG ioAddr,ULONG * bufPtr,int nLongs);
void sysOutLongString(ULONG ioAddr,ULONG * bufPtr,int nLongs);
/* defines */
/* Read a BYTE from IO port, `ioAdrs' */
#ifndef ATA_IO_BYTE_READ
#define ATA_IO_BYTE_READ(ioAdrs) atpRDByt (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) atpWRByt (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
#define ATA_IO_NWORD_READ_SWAP(ioAdrs, pData, nWords) \
ATA_IO_NWORD_READ (ioAdrs, pData, nWords)
#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 */
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];
/* 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);
LOCAL void ataIntr (int ctrl);
LOCAL 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);
STATUS ataRW (int ctrl, int drive, int cylinder, int head, int sec,
void *p, int nSecs, int direction);
STATUS sysAtaDevIdGet(void)
{
printf("sysAtaDevIdGet\n");
return 1;
}
/* add by wangb 2005-10-18 14:10 */
void enableChan(int ctrl)
{
if(ctrl > ATA_MAX_CTRLS)
return;
atpWRByt(busMasterRegs[ctrl] + BM_COMMAND_REG,rwControl[ctrl] | BM_CR_MASK_START);
return;
}
void disableChan(int ctrl)
{
if(ctrl > ATA_MAX_CTRLS)
return;
atpWRByt( busMasterRegs[ctrl] + BM_COMMAND_REG,BM_CR_MASK_STOP);
return;
}
void clearChan(int ctrl)
{
if(ctrl > ATA_MAX_CTRLS)
return;
atpWRByt( busMasterRegs[ctrl] + BM_STATUS_REG,statReg[ctrl] | BM_SR_MASK_INT | BM_SR_MASK_ERR );
return;
}
/***********************************************************************
*
* ideDelayFun - ide delay function
*
************************************************************************/
LOCAL ideDelayFun()
{
volatile unsigned int i =0;
volatile unsigned int j =0;
for(i =0; i< 2000; i++)
{
j++;
}
}
int min(int a,int b)
{
if(a>b)
return b;
else
return a;
}
/*******************************************************************************
*
* ataDrv - initialize the ATA driver
*
* This routine initializes the ATA/IDE driver, sets up interrupt vectors,
* and performs hardware initialization of the ATA/IDE chip.
*
* This routine must be called exactly once, before any reads, writes,
* or calls to ataDevCreate(). Normally, it is called by usrRoot()
* in usrConfig.c.
*
* RETURNS: OK, or ERROR if initialization fails.
*
* SEE ALSO: ataDevCreate()
*/
STATUS ataDrv(
int ctrl, /* controller no. */
int drives, /* number of drives */
int vector, /* interrupt vector */
int level, /* interrupt level */
BOOL configType, /* configuration type */
int semTimeout, /* timeout seconds for sync semaphore */
int wdgTimeout /* timeout seconds for watch dog */
)
{
ATA_CTRL *pCtrl = &ataCtrl[ctrl];
ATA_RESOURCE *pAta = &ataResources[ctrl];
PCCARD_RESOURCE *pResource = &pAta->resource;
ATA_DRIVE *pDrive;
ATA_PARAM *pParam;
ATA_TYPE *pType;
int drive;
int ix;
if ((ctrl >= ATA_MAX_CTRLS) || (drives > ATA_MAX_DRIVES))
return (ERROR);
if (!ataDrvInstalled)
{
for (ix = 0; ix < ATA_MAX_CTRLS; ix++)
{
ataCtrl[ix].wdgId = wdCreate ();
}
ataDrvInstalled = TRUE;
}
if (!pCtrl->installed)
{
if (semTimeout == 0)
pCtrl->semTimeout = ATA_SEM_TIMEOUT_DEF;
else
pCtrl->semTimeout = semTimeout;
if (wdgTimeout == 0)
pCtrl->wdgTimeout = ATA_WDG_TIMEOUT_DEF;
else
pCtrl->wdgTimeout = wdgTimeout;
pCtrl->syncSem=semBCreate(SEM_Q_FIFO, SEM_EMPTY);
pCtrl->muteSem=semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE |
SEM_INVERSION_SAFE);
pCtrl->data = ATA_DATA (pResource->ioStart[0]);
pCtrl->error = ATA_ERROR (pResource->ioStart[0]);
pCtrl->feature = ATA_FEATURE (pResource->ioStart[0]);
pCtrl->seccnt = ATA_SECCNT (pResource->ioStart[0]);
pCtrl->sector = ATA_SECTOR (pResource->ioStart[0]);
pCtrl->cylLo = ATA_CYL_LO (pResource->ioStart[0]);
pCtrl->cylHi = ATA_CYL_HI (pResource->ioStart[0]);
pCtrl->sdh = ATA_SDH (pResource->ioStart[0]);
pCtrl->command = ATA_COMMAND (pResource->ioStart[0]);
pCtrl->status = ATA_STATUS (pResource->ioStart[0]);
pCtrl->aStatus = ATA_A_STATUS (pResource->ioStart[1]);
pCtrl->dControl = ATA_D_CONTROL (pResource->ioStart[1]);
pCtrl->dAddress = ATA_D_ADDRESS (pResource->ioStart[1]);
#if 0
(void) sysAtaIntConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (vector),
(VOIDFUNCPTR)ataIntr, ctrl);
#if (CPU_FAMILY==I80X86)
sysIntEnablePIC (level); /* unmask the interrupt level */
#elif (CPU_FAMILY==PPC)
sysAtaIntEnable (level); /* unmask the interrupt level */
#else
#err
#endif
#endif
/*intConnect((VOIDFUNCPTR *)INUM_TO_IVEC (INT_LVL_EXTI1S), (VOIDFUNCPTR )ataIntr, ctrl);quy del int 2006-3-24 8:32*/
/*intEnable(INT_LVL_EXTI1S);quy del int 2006-3-24 8:31*/
pCtrl->intLevel = level;
pCtrl->wdgOkay = TRUE;
semTake (&pCtrl->muteSem, WAIT_FOREVER);
if (ataInit (ctrl) != OK)
{
semGive (&pCtrl->muteSem);
return (ERROR);
}
/*added by youyan 2005-11-19 10:58*/
ataLbaTotalSecs[ctrl][0]=0;
ataLbaTotalSecs[ctrl][1]=0;
/*end of added by youyan 2005-11-19 10:59*/
for (drive = 0; drive < drives; drive++)
{
pType = &ataTypes[ctrl][drive];
pDrive = &pCtrl->drive[drive];
pParam = &pDrive->param;
if (pType->cylinders == 0)
return ERROR;
if ((pCtrl->ctrlType == ATA_PCMCIA) ||
((pCtrl->ctrlType != ATA_PCMCIA) && (drive == 0)))
{
if (ataCmd (ctrl, drive, ATA_CMD_DIAGNOSE, 0, 0) != OK)
{
semGive (&pCtrl->muteSem);
return (ERROR);
}
}
/* find out geometry */
if ((configType & ATA_GEO_MASK) == ATA_GEO_FORCE)
{
if(ataCmd (ctrl, drive, ATA_CMD_INITP, 0, 0) != OK)
break;
if(ataPread (ctrl, drive, (char *)pParam) != OK)
break;
}
else if ((configType & ATA_GEO_MASK) == ATA_GEO_PHYSICAL)
{
if(ataPread (ctrl, drive, (char *)pParam) != OK)
break;
pType->cylinders = pParam->cylinders - 1;
pType->heads = pParam->heads;
pType->sectors = pParam->sectors;
// pType->bytes = pParam->bytesSec;
/*modify start by wb 2005-6-20 10:20*/
if(pParam->capabilities & 0x0200) /* if (drive supports LBA) */
{
if (((pParam->feature & 0x0400 ) >> 10) == 0)
{
ataLbaTotalSecs[ctrl][drive] = (unsigned int)((unsigned int)pParam->sectors0 | (((unsigned int)pParam->sectors1) << 16));
/*printf("ataLbaTotalSecs is %d \n", ataLbaTotalSecs[ctrl][drive]);
printf("sectors0 is %d \n", pParam->sectors0);
printf("sectors1 is %d \n", pParam->sectors1);*/
}
else
{
ataLbaTotalSecs[ctrl][drive] = (unsigned int)(pParam->sectorsExt0 | \
((unsigned int)(pParam->sectorsExt1) << 16)| \
((unsigned int)(pParam->sectorsExt2) << 24));
}
pDrive->lba48bit = (ataLbaTotalSecs[ctrl][drive] > 268435455);
}
/*end by wb 2005-6-20 10:20*/
}
else if ((configType & ATA_GEO_MASK) == ATA_GEO_CURRENT)
{
if(ataPread (ctrl, drive, (char *)pParam) != OK)
break;
if ((pParam->currentCylinders != 0) &&
(pParam->currentHeads != 0) &&
(pParam->currentSectors != 0))
{
pType->cylinders = pParam->currentCylinders - 1;
pType->heads = pParam->currentHeads;
pType->sectors = pParam->currentSectors;
}
else
{
pType->cylinders = pParam->cylinders - 1;
pType->heads = pParam->heads;
pType->sectors = pParam->sectors;
}
}
/*
* reinitialize the controller with parameters read from the
* controller.
*/
(void) ataCmd (ctrl, drive, ATA_CMD_INITP, 0, 0);
/* recalibrate */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -