📄 systemace_drv.c
字号:
/*
**********************************************************************
* Micrium, Inc.
* 949 Crestview Circle
* Weston, FL 33327-1848
*
* uC/FS
*
* (c) Copyright 2001 - 2003, Micrium, Inc.
* All rights reserved.
*
***********************************************************************
----------------------------------------------------------------------
File : SystemAce_drv.h
Purpose : Example driver for the XILINK SystemAce CompactFlash
driver chip. This driver exampe should give you an easy
start for the SystemAce chip. Originally this driver
was designed for the XILINK Multimedia Board II.
---------------------------END-OF-HEADER------------------------------
*/
/*********************************************************************
*
* #include Section
*
**********************************************************************
*/
#include "FS_ConfDefaults.h" /* FS Configuration */
#include "fs_dev.h"
#include "fs_lbl.h"
#if FS_USE_IDE_DRIVER
#include "fs_api.h"
/**** SYSTEM ACE SPECIFIC CODE ****/
/*
#include "xsysace.h"
#include "xsysace_l.h"
*/
#define XSysAce int
#define Xboolean int
/**********************************/
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
/**** SYSTEM ACE SPECIFIC CODE ****/
/* IMPORTANT: Include xsysace_g.c to create a list of available devices. */
#define FS__DEV_MBRFLAG_CLI 0xFA
#define FS__DEV_MBRFLAG_JUMP1 0xEB
#define FS__DEV_MBRFLAG_JUMP2 0xE9
#define FS__DEV_MBRSECTORFLAG_L 0x55
#define FS__DEV_MBRSECTORFLAG_H 0xAA
#define FS__DEV_PART_0_TABLE 0x01BE
/*********************************************************************
*
* Local Variables
*
**********************************************************************
*/
static FS_U32 _FS_SYSACE_logicalstart[FS_IDE_MAXUNIT]; /* start of partition */
static char _FS_SYSACE_mbrbuffer [0x200]; /* buffer for reading MBR */
static char _FS_SYSACE_diskchange [FS_IDE_MAXUNIT]; /* signal flag for driver */
static char _FS_SYSACE_busycnt [FS_IDE_MAXUNIT]; /* counter for BSY LED on/off */
/**** SYSTEM ACE SPECIFIC CODE ****/
static XSysAce _FS_XSYSTEMACE; /* the SystemAce context */
static XSysAce *Addr_Of_Ace = &_FS_XSYSTEMACE;
/**********************************/
/*********************************************************************
*
* Local functions
*
**********************************************************************
*/
/*********************************************************************
*
* FS_GetMediaStartSec
*
* Description:
* FS api function. Get logical start sector from master boot record
* or partition table.
*
* Parameters:
* DevIndex - DevIndex number.
* pBuffer - A pointer to a buffer containing the first
* sector of the media. This should contain the
* master boot record (MBR) or Bios Parameter Block
* (BPB) if the device has no partition table.
*
* Return value:
* < 0xFFFF - Number of the first sector of the medium.
* ==0xFFFF - No valid MBR/BPB found.
*/
FS_U32 FS_GetMediaStartSec(const FS_U8 *pBuffer) {
FS_U8 c;
FS_U32 StartSec;
c = pBuffer[0x1FE]; /* check first part of the signature */
if (c != FS__DEV_MBRSECTORFLAG_L) {
return 0xFFFFFFFF;
}
c = pBuffer[0x1FF]; /* check second part of the signature */
if (c != FS__DEV_MBRSECTORFLAG_H) {
return 0xFFFFFFFF;
}
c = pBuffer[0x000]; /* check if boot or partition record */
if (c == FS__DEV_MBRFLAG_JUMP1) {
return 0; /* if first byte is a jump command, there is no partition table */
}
if (c == FS__DEV_MBRFLAG_JUMP2) {
return 0; /* if first byte is a jump command, there is no partition table */
} /* this calculation makes sure big/little endian system get the right value from the table */
/* read first entry of the partition table */
StartSec = (FS_U32)pBuffer[FS__DEV_PART_0_TABLE + 11] & 0xFFUL;
StartSec <<= 8;
StartSec += (FS_U32)pBuffer[FS__DEV_PART_0_TABLE + 10] & 0xFFUL;
StartSec <<= 8;
StartSec += (FS_U32)pBuffer[FS__DEV_PART_0_TABLE + 9] & 0xFFUL;
StartSec <<= 8;
StartSec += (FS_U32)pBuffer[FS__DEV_PART_0_TABLE + 8] & 0xFFUL;
return StartSec;
}
/*********************************************************************
*
* _FS_SYSACE_DevStatus
*
Description:
FS driver function. Get status of the media.
Parameters:
Unit - Unit number.
Return value:
==1 (FS_LBL_MEDIACHANGED) - The media of the device has changed.
==0 - Device okay and ready for operation.
<0 - An error has occured.
*/
static int _FS_SYSACE_DevStatus(FS_U8 Unit) {
static int init=0;
char a;
Xboolean CFdetected;
int BytesRead;
FS_U32 ul;
if (!init) {
/*
The function is called the first time. For each unit,
the flag for 'diskchange' is set. That makes sure, that
FS_LBL_MEDIACHANGED is returned, if there is already a
media in the reader.
*/
for (init = 0; init < FS_IDE_MAXUNIT; init++) {
_FS_SYSACE_diskchange[init] = 1;
}
/**** uC/FS CF CODE **************/
/* None. */
/**** SYSTEM ACE SPECIFIC CODE ****/
XSysAce_Initialize(Addr_Of_Ace, Unit); /* init the SystemAce */
/* PG THIS IS A MULTIMEDIA BOARD SPECIFIC ACTION */
/* PG Writing Control Reg FORCECFGMODE Bit To Overide ON-BOARD CFGMODE Pin */
XSysAce_RegWrite32((Addr_Of_Ace->BaseAddress) + XSA_CR_OFFSET, (0x00000808));
/* RESET THE ACE CONFIG CONTROLLER TO REMOVE ANY EXISTING ERRORS */
XSysAce_ResetCfg (Addr_Of_Ace);
/* IT TAKES SOME TIME FOR THE CF TO RECOVER FROM THE RESET */
/* WAIT FOR RESET RECOVERY */
while (!XSysAce_mIsReadyForCmd(Addr_Of_Ace->BaseAddress));
/**********************************/
init = 1;
}
/**** uC/FS CF CODE **************/
/* Check if a card is present */
/*
a = FS_IDE_HW_X_DetectStatus(Unit);
if (a) {
return -1; No card in reader
}
*/
/**** SYSTEM ACE SPECIFIC CODE ****/
CFdetected = (XSysAce_mGetStatusReg(_FS_XSYSTEMACE.BaseAddress) &
XSA_SR_CFDETECT_MASK);
if (!CFdetected) {
return -1; /* No card in reader */
}
/**********************************/
/* When you get here, then there is a card in the reader */
a = _FS_SYSACE_diskchange[Unit]; /* Check if the media has changed */
if (a) {
/*
A diskchange took place. The following code reads the MBR of the
card to get its partition information.
*/
_FS_SYSACE_diskchange[Unit] = 0; /* Reset 'diskchange' flag */
/**** uC/FS CF CODE **************/
/*
FS__IDE_Init(Unit);
x = FS__IDE_ReadSector(Unit, 0, (unsigned char*)&_FS_ide_mbrbuffer[0]);
if (x != 0) {
return -1;
}
*/
/**** SYSTEM ACE SPECIFIC CODE ****/
/*READ (1) 512 BYTE SECTOR */
BytesRead = XSysAce_ReadSector(_FS_XSYSTEMACE.BaseAddress, 0,
(unsigned char*)&_FS_SYSACE_mbrbuffer[0]);
/* VERIFY FULL SECTOR RECEIVED */
if (BytesRead != 512) {
return -1;
}
/* Calculate start sector of the first partition */
ul = FS_GetMediaStartSec((unsigned char*)_FS_SYSACE_mbrbuffer);
if (ul == 0xFFFFFFFF) { /* check if MBR was invalid */
return (int)FS_ERR_INVALIDDESC;
}
_FS_SYSACE_logicalstart[Unit] = ul;
return FS_LBL_MEDIA_CHANGED;
}
return 0;
}
/*********************************************************************
*
* _FS_SYSACE_DevRead
*
Description:
FS driver function. Read a sector from the media.
Parameters:
Unit - Unit number.
Sector - Sector to be read from the device.
pBuffer - Pointer to buffer for storing the data.
Return value:
==0 - Sector has been read and copied to pBuffer.
<0 - An error has occured.
*/
static int _FS_SYSACE_DevRead(FS_U8 Unit, FS_U32 Sector, void *pBuffer) {
int BytesRead;
/**** uC/FS CF CODE **************/
/* x = FS__IDE_ReadSector(Unit, Sector + _FS_ide_logicalstart[Unit], (unsigned char*)pBuffer); */
/*
if (x != 0) {
x = -1;
}
*/
/**** SYSTEM ACE SPECIFIC CODE ****/
/* READ (1) 512 BYTE SECTOR */
BytesRead = XSysAce_ReadSector(_FS_XSYSTEMACE.BaseAddress, Sector + _FS_SYSACE_logicalstart[Unit], (unsigned char*) pBuffer);
/* VERIFY FULL SECTOR RECEIVED */
if (BytesRead != 512) {
return -1;
}
return 0;
}
/*********************************************************************
*
* _FS_SYSACE_DevWrite
*
Description:
FS driver function. Write sector to the media.
Parameters:
Unit - Unit number.
Sector - Sector to be written to the device.
pBuffer - Pointer to data to be stored.
Return value:
==0 - Sector has been written to the device.
<0 - An error has occured.
*/
static int _FS_SYSACE_DevWrite(FS_U8 Unit, FS_U32 Sector, void *pBuffer) {
int BytesWritten;
/* WAIT FOR ACE READY */
while (!XSysAce_mIsReadyForCmd(Addr_Of_Ace->BaseAddress));
/* FORCE MPU LOCK */
XSysAce_Lock(Addr_Of_Ace, XTRUE);
/* WRITE THE SECTOR LOGICAL BLOCK ADDRESS (LBA) */
XSysAce_RegWrite32(Addr_Of_Ace->BaseAddress + XSA_MLR_OFFSET, Sector);
/* SEND WRITE COMMAND FOR (1) 512 BYTE SECTOR */
XSysAce_RegWrite16(Addr_Of_Ace->BaseAddress + XSA_SCCR_OFFSET, 0x401);
/* RESET ACE ASIC CONFIG CONTROLLER DUE TO A SILICON BUG */
XSysAce_mOrControlReg(Addr_Of_Ace->BaseAddress, XSA_CR_CFGRESET_MASK);
BytesWritten = XSysAce_WriteDataBuffer(Addr_Of_Ace->BaseAddress, (unsigned char*)pBuffer, 512);
/* CLEAR RESET AND UNLOCK ACE */
XSysAce_mAndControlReg(Addr_Of_Ace->BaseAddress, ~(XSA_CR_CFGRESET_MASK | XSA_CR_LOCKREQ_MASK));
/* LET CF FINISH WRITE BEFORE RETURNING CONTROL TO CALLING FUNCTION */
while (!XSysAce_mIsReadyForCmd(Addr_Of_Ace->BaseAddress));
/* VERIFY FULL SECTOR TRANSFER */
if (BytesWritten != 512) {
return -1;
}
return 0;
}
/*********************************************************************
*
* _FS_SYSACE_DevIoCtl
*
Description:
FS driver function. Execute device command.
Parameters:
Unit - Unit number.
Cmd - Command to be executed.
Aux - Parameter depending on command.
pBuffer - Pointer to a buffer used for the command.
Return value:
Command specific. In general a negative value means an error.
*/
static int _FS_SYSACE_DevIoCtl(FS_U8 Unit, FS_I32 Cmd, FS_I32 Aux, void *pBuffer) {
FS_DEV_INFO *pInfo;
FS_U32 ul;
int BytesRead;
Xboolean CFdetected;
FS_USE_PARA(Aux);
switch (Cmd) {
case FS_CMD_INC_BUSYCNT:
_FS_SYSACE_busycnt[Unit]++;
break;
case FS_CMD_DEC_BUSYCNT:
_FS_SYSACE_busycnt[Unit]--;
if (_FS_SYSACE_busycnt[Unit] <= 0) {
_FS_SYSACE_busycnt[Unit] = 0;
}
break;
case FS_CMD_CHK_DSKCHANGE:
/**********************************/
CFdetected = (XSysAce_mGetStatusReg(_FS_XSYSTEMACE.BaseAddress) &
XSA_SR_CFDETECT_MASK);
if (!CFdetected) {
_FS_SYSACE_diskchange[Unit] = 1; /* No card in reader */
}
/**********************************/
break;
case FS_CMD_GET_DEVINFO:
if (!pBuffer) {
return -1;
}
pInfo = (FS_DEV_INFO *)pBuffer;
XSysAce_Initialize(Addr_Of_Ace, Unit); /* init the SystemAce */
/* THIS IS A MULTIMEDIA BOARD SPECIFIC ACTION
Writing Control Reg FORCECFGMODE Bit To Overide ON-BOARD CFGMODE Pin */
XSysAce_RegWrite32((Addr_Of_Ace->BaseAddress) + XSA_CR_OFFSET, (0x00000808));
/* RESET THE ACE CONFIG CONTROLLER TO REMOVE ANY EXISTING ERRORS */
XSysAce_ResetCfg (Addr_Of_Ace);
/* IT TAKES SOME TIME FOR THE CF TO RECOVER FROM THE RESET */
/* WAIT FOR RESET RECOVERY */
while (!XSysAce_mIsReadyForCmd(Addr_Of_Ace->BaseAddress));
/**** SYSTEM ACE SPECIFIC CODE ****/
/* READ (1) 512 BYTE SECTOR */
BytesRead = XSysAce_ReadSector(_FS_XSYSTEMACE.BaseAddress, 0,
(unsigned char*)&_FS_SYSACE_mbrbuffer[0]);
/* VERIFY FULL SECTOR RECEIVED */
if (BytesRead != 512) {
return -1;
}
/**********************************/
ul = FS_GetMediaStartSec((unsigned char*)_FS_SYSACE_mbrbuffer);
if (ul == 0xFFFFFFFF) { /* check if MBR was invalid */
return (int)FS_ERR_INVALIDDESC;
}
if (ul != 0) {
/**** SYSTEM ACE SPECIFIC CODE ****/
/* READ (1) 512 BYTE SECTOR */
BytesRead = XSysAce_ReadSector(_FS_XSYSTEMACE.BaseAddress, ul, (unsigned char*)&_FS_SYSACE_mbrbuffer[0]);
}
/* VERIFY FULL SECTOR RECEIVED */
if (BytesRead != 512) {
return -1;
}
pInfo->NumHeads = _FS_SYSACE_mbrbuffer[_FS_BPB_HEADNUM]; /* heads */
pInfo->SectorsPerTrack = _FS_SYSACE_mbrbuffer[_FS_BPB_SECPERTRK]; /* sec per track */
pInfo->NumSectors = FS_ReadU16(&_FS_SYSACE_mbrbuffer[_FS_BPB_TOTALSEC16]); /* size */
if (pInfo->NumSectors == 0) {
pInfo->NumSectors = FS_ReadU32(&_FS_SYSACE_mbrbuffer[_FS_BPB_TOTALSEC32]);
}
break;
default:
break;
}
return 0;
}
/*********************************************************************
*
* Global variables
*
**********************************************************************
*/
const FS_DEVICE_TYPE FS_sysacedevice_driver = {
"ide",
FS_IDE_MAXUNIT,
_FS_SYSACE_DevStatus,
_FS_SYSACE_DevRead,
_FS_SYSACE_DevWrite,
_FS_SYSACE_DevIoCtl
};
#endif /* FS_USE_IDE_DRIVER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -