📄 cf_ide.c
字号:
//##############################################################
//#
//# CF_IDE.C
//#
//# ADSP-21535 Embedded Web Server Project
//#
//# (c) ANALOG DEVICES 2002
//# eDSP Division
//# Stefan Hacker
//# 23-DEC-2002
//#
//# History
//# 04-APR-2003 last fixes
//# 16-APR-2003 HS release 1.0
//#
#include "cf_ide.h"
#include "stdio.h"
#include "ez_lan_types.h"
#include "io_sprt.h"
#include "globals.h"
#include "string.h"
#define MC section("L1_code")
/******************************************************************************
* CF_IDE: ATA_reset()
*
* Purpose:
* performs a soft reset on the drive
*
* Actions:
*
*****************************************************************************/
void ATA_reset()
{
int i;
_outpw(IDE_CTRL, 0x04);
// set timeout 1 sec.
Timeout_DISK = 4;
// wait for occurence of IRQ
while(Timeout_DISK);
_outpw(IDE_CTRL, 0x00);
}
/******************************************************************************
* CF_IDE: ATA_wait_for_it()
*
* Purpose:
* waits for the IRQ or Timeout
*
* Actions:
*
*****************************************************************************/
int ATA_wait_for_it()
{
int status;
// set timeout to 3 sec.
Timeout_DISK = 12;
while(Timeout_DISK)
{
if (IRQ_DISK)
{
// media active, clear IRQ occurred
IRQ_DISK = 0;
return 1;
}
}
return -1;
}
/******************************************************************************
* CF_IDE: ATA_send_command()
*
* Purpose:
* send ATA Command Block to the drive
*
* Actions:
*
*****************************************************************************/
MC void ATA_send_command()
{
// write command to CF
_outpw(IDE_SCNT, ATA_CMD.SC); // Sector Count
_outpw(IDE_SNUM, ATA_CMD.SN); // Sector Number
_outpw(IDE_CYLL, ATA_CMD.CL); // Cylinder low
_outpw(IDE_CYLH, ATA_CMD.CH); // Cylinder High
_outpw(IDE_CDH, ATA_CMD.DH); // Drive Head
_outpw(IDE_CMD, ATA_CMD.CMD); // Command Register
// prepare waiting for IRQ
IRQ_DISK = 0;
}
/******************************************************************************
* CF_IDE: ATA_identify()
*
* Purpose:
* gets the first information from drive
*
* Actions:
*
*****************************************************************************/
MC void ATA_identify()
{
int i;
WORD stmp;
BYTE bytes[40];
BYTE* pd = (BYTE*) ATA_buffer;
// Identify drive
ATA_CMD.DH = 0xA0;
ATA_CMD.CMD = 0xEC;
// Send ATA Command
ATA_send_command();
// Wait for IRQ
// check media inserted and ready
if (ATA_wait_for_it())
{
// good - our media is responding
ATA_media_present = 1;
}
else
{
// bad - no response
ATA_media_present = 0;
// flag error
ATA_ERROR = 1;
// stop function
return;
}
// Collect Buffer
for(i=0; i<256; i++)
ATA_buffer[i] = _inpw(IDE_RDD);
#if 1//A_DP
for (i=0; i<4; i++)
{
stmp = ATA_buffer[23+i];
bytes[2*i] = stmp>>8;
bytes[2*i+1] = stmp&0xff;
}
printf("\n");
for (i=0; i<8; i++)
printf("%c", bytes[i]);
for (i=0; i<20; i++)
{
stmp = ATA_buffer[27+i];
bytes[2*i] = stmp>>8;
bytes[2*i+1] = stmp&0xff;
}
printf("\n");
for (i=0; i<40; i++)
if (bytes[i] == 0) bytes[i] = 0x20;
for (i=0; i<40; i++)
printf("%c", bytes[i]);
printf("\n");
#endif //A_DP
// extract drive parameters
memcpy(&ATA_N_Cyl , pd+ 2, 2);
memcpy(&ATA_N_Head , pd+ 6, 2);
memcpy(&ATA_N_Sec , pd+ 12, 2);
memcpy(&ATA_N_LBA , pd+114, 4);
return;
}
/******************************************************************************
* CF_IDE: ATA_get_boot_block()
*
* Purpose:
* parses the boot block of the drive and sets parameters accordingly
*
* Actions:
*
*****************************************************************************/
MC int ATA_get_boot_block()
{
int i;
WORD stmp;
BYTE* pd = (BYTE*) ATA_buffer;
// read sectors command
// 1 sector, sector 1
ATA_CMD.SC = 1; // one 512 byte sector
ATA_CMD.SN = 1; // sec number
ATA_CMD.CL = 0; // cyl low
ATA_CMD.CH = 0; // cyl high
ATA_CMD.DH = 0xA1; // head 1
ATA_CMD.CMD = 0x20; // read command
// Send ATA Command
ATA_send_command();
// Wait for IRQ
ATA_wait_for_it();
// Collect Buffer
for(i=0; i<256; i++)
ATA_buffer[i] = _inpw(IDE_RDD);
// first signature should be 0x3ceb
memcpy(&ATA_P.BPB_id1 , pd+ 0, 2);
// second signature should be 0xaa55
memcpy(&ATA_P.BPB_id2 , pd+510, 2);
// check for formatted drive
if (ATA_P.BPB_id2 != 0xaa55)
{
#if 1//A_DP
printf("ERROR: Drive is not formatted - ABORT! \n");
#endif // A_DP
// if not, so flag error condition
return -1;
}
// parse Boot Sector Information
memcpy(&ATA_P.BS_jmpBoot , pd+ 0, 3);
memcpy(&ATA_P.BS_OEMName , pd+ 3, 8);
memcpy(&ATA_P.BPB_BytsPerSec , pd+11, 2);
memcpy(&ATA_P.BPB_SecPerClus , pd+13, 1);
memcpy(&ATA_P.BPB_RsvdSecCnt , pd+14, 2);
memcpy(&ATA_P.BPB_NumFATs , pd+16, 1);
memcpy(&ATA_P.BPB_RootEntCnt , pd+17, 2);
memcpy(&ATA_P.BPB_TotSec16 , pd+19, 2);
memcpy(&ATA_P.BPB_Media , pd+21, 1);
memcpy(&ATA_P.BPB_FATSz16 , pd+22, 2);
memcpy(&ATA_P.BPB_SecPerTrk , pd+24, 2);
memcpy(&ATA_P.BPB_NumHeads , pd+26, 2);
memcpy(&ATA_P.BPB_HiddSec , pd+28, 4);
memcpy(&ATA_P.BPB_TotSec32 , pd+32, 4);
memcpy(&ATA_P.BS_DrvNum , pd+36, 1);
memcpy(&ATA_P.BS_Reserved1 , pd+37, 1);
memcpy(&ATA_P.BS_BootSig , pd+38, 1);
memcpy(&ATA_P.BS_VolID , pd+39, 4);
memcpy(&ATA_P.BS_VolLab , pd+43, 11);
memcpy(&ATA_P.BS_FileSysType , pd+54, 8);
// we support only FAT16
if (ATA_P.BPB_FATSz16)
ATA_FATSz = ATA_P.BPB_FATSz16;
else
{
#if 1//A_DP
printf("ERROR: Drive is not FAT16 - ABORT! \n");
#endif // A_DP
// flag error condition
return -1;
}
// calculate Root Dir sectors
ATA_RootDirSectors = ((ATA_P.BPB_RootEntCnt<<5) + (ATA_P.BPB_BytsPerSec - 1)) / ATA_P.BPB_BytsPerSec;
// calculate Data Region Start and Root Sector Number
ATA_RootDirSecCnt = ATA_P.BPB_RsvdSecCnt + (ATA_P.BPB_NumFATs * ATA_FATSz);
ATA_FirstDataSector = ATA_RootDirSecCnt + ATA_RootDirSectors;
// ATA LBA Offset
ATA_LBAHidden = ATA_P.BPB_HiddSec;
// get Total Sector Count
if (ATA_P.BPB_TotSec16)
ATA_TotSec = ATA_P.BPB_TotSec16;
else
ATA_TotSec = ATA_P.BPB_TotSec32;
// calculate Data Sectors
ATA_DataSec = ATA_TotSec - (ATA_P.BPB_RsvdSecCnt + (ATA_P.BPB_NumFATs * ATA_FATSz) + ATA_RootDirSectors);
// calculate Cluster Count
ATA_CountOfClusters = ATA_DataSec / ATA_P.BPB_SecPerClus;
// Detect File System
if (ATA_CountOfClusters < 65525)
{
#if 1//A_DP
printf("\nInfo : FAT 16 Drive detected\n");
#endif // A_DP
ATA_FAT16_detected = 1;
}
else
{
#if 1//A_DP
printf("\nERROR: FAT32 filesystem detected - ABORT!\n");
#endif // A_DP
ATA_FAT16_detected = 0;
return -1;
}
return 1;
}
/******************************************************************************
* CF_IDE: ATA_read_sector()
*
* Purpose:
* expects a LBA sector number to read and fetch from CF
*
* Actions:
*
*****************************************************************************/
MC void ATA_read_sector(DWORD LBAsec)
{
int i;
BYTE asn, acl, ach, adh;
// add offset to data area and add hidden sectors for LBA
LBAsec += ATA_FirstDataSector + ATA_LBAHidden;
#if 1//A_DP
printf("LBA: %d\n", LBAsec);
#endif
// prepare command buffer
ATA_CMD.SC = 1; // one 512 byte sector
ATA_CMD.SN = (LBAsec & 0x000000ff); // sec number
ATA_CMD.CL = (LBAsec & 0x0000ff00)>> 8; // cyl low
ATA_CMD.CH = (LBAsec & 0x00ff0000)>>16; // cyl high
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -