📄 ide_base.c
字号:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT32 File IO Library for AVR
// V0.1c
// Rob Riglar
// Copyright 2003,2004
//
// Email: rob@robriglar.com
//
// Compiled with Imagecraft C Compiler for the AVR series
//-----------------------------------------------------------------------------
//
// This file is part of FAT32 File IO Library.
//
// FAT32 File IO Library is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// FAT32 File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT32 File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Set_Address: Set the Address on A1 A0 A2 pins
//
// Parameters: Byte Address
//
// Returns: None
//
// Functions Used: None
//
//-----------------------------------------------------------------------------
void Set_Address(byte Address)
{
byte tempdata=0;
if (Address&0x80) tempdata = tempdata + IDESIG_RST;
if (Address&0x40) tempdata = tempdata + IDESIG_WR;
if (Address&0x20) tempdata = tempdata + IDESIG_RD;
if (Address&0x10) tempdata = tempdata + IDESIG_A0;
if (Address&0x08) tempdata = tempdata + IDESIG_A1;
if (Address&0x04) tempdata = tempdata + IDESIG_A2;
if (Address&0x02) tempdata = tempdata + IDESIG_CS0;
if (Address&0x01) tempdata = tempdata + IDESIG_CS1;
SetAddressOutput;
ADDRESS_PORT = tempdata; // Send out value passed in
}
//-----------------------------------------------------------------------------
// Wait_Ready: Pauses execution until Ready = 1 in the status register
// A timeout delay should be added to improve this function
//
// Parameters: None
//
// Returns: None
//
// Functions Used: ReadReg
//
//-----------------------------------------------------------------------------
void Wait_Ready(void)
{
byte statbyte;
byte flag = 0;
while (!flag)
{
statbyte = ReadReg(STATUS); // Read Status Register
if (statbyte & 0x40) flag = 1; // Ready bit is in pos 6
}
}
//-----------------------------------------------------------------------------
// ReadReg: Function for reading from a specified register of the ATA device
//
// Parameters: Byte Address of Register to be read
//
// Returns: Byte data read from register
//
// Functions Used: Set_Address
//
//-----------------------------------------------------------------------------
byte ReadReg(byte reg)
{
byte tempinput;
DATALOW_OUTPORT=PULLUPSON; // Activate pullups
DATALOW_DIR=ALLINPUT; // Make input
Set_Address(reg); // Send out address
SET_IDE_WR; // Make sure WR is high
CLR_IDE_RD; // Activate (low) RD
NOP(); // Wait
NOP();
NOP();
tempinput=DATALOW_INPORT; // Read D0-D7
NOP(); // Wait
SET_IDE_RD; // Deassert RD
NOP();
return(tempinput); // Return register value
}
//-----------------------------------------------------------------------------
// Wait_ReadyBusy: Halts further execution until Ready = 1 and Busy = 0 in
// status register
//
// Parameters: None
//
// Returns: None
//
// Functions Used: ReadReg
//
//-----------------------------------------------------------------------------
void Wait_ReadyBusy(void)
{
byte statbyte;
byte flag = 0;
while (!flag)
{
statbyte = ReadReg(STATUS); // Read Status register
// If RDY = 1 and BUSY = 0 leave loop
if ((statbyte & 0x40) && ((statbyte & 0x80)==0)) flag = 1;
}
}
//-----------------------------------------------------------------------------
// Wait_DRQ: Halts execution until DRQ is asserted
//
// Parameters: None
//
// Returns: None
//
// Functions Used: ReadReg
//
//-----------------------------------------------------------------------------
void Wait_DRQ(void)
{
byte statbyte;
byte flag = 0;
while (!flag)
{
statbyte = ReadReg(STATUS); // DRQ is in status register
if (statbyte & 0x08) flag = 1;
}
}
//-----------------------------------------------------------------------------
// WriteReg: Write a byte of data to a register specified
//
// Parameters: Byte Address of register and Byte data to be written
//
// Returns: None
//
// Functions Used: Wait_ReadyBusy, Set_Address
//
//-----------------------------------------------------------------------------
void WriteReg(byte Address, byte Data)
{
Wait_ReadyBusy(); // Wait for Drive to be Ready
DATALOW_DIR=ALLOUTPUT; // Make Data lines outputs
DATAHIGH_DIR=ALLOUTPUT;
Set_Address(Address); // Set Address
SET_IDE_RD; // RD must be high (inactive)
CLR_IDE_WR; // Assert WR (active low)
delay_us(1);
DATALOW_OUTPORT = Data; // Output Data onto Data bus
DATAHIGH_OUTPORT = 0x00; // As byte writing ignore MSByte
delay_us(1);
SET_IDE_WR; // Deassert WR
}
//-----------------------------------------------------------------------------
// ReadWord: Reads a word (16 bits) of data from a specified register
//
// Parameters: Byte Address of register to be read
//
// Returns: Word of data read
//
// Functions Used: Wait_ReadyBusy, Set_Address
//
//-----------------------------------------------------------------------------
word ReadWord(byte reg)
{
byte tempinputL;
word tempinputH;
DATALOW_OUTPORT=PULLUPSON; // Activate pullups
DATALOW_DIR=ALLINPUT; // Make input
DATAHIGH_OUTPORT=PULLUPSON; // Activate pullups
DATAHIGH_DIR=ALLINPUT; // Make input
Set_Address(reg); // Send out address
SET_IDE_WR; // Make sure WR is high
CLR_IDE_RD; // Activate (low) RD
NOP(); // Wait
NOP();
NOP();
tempinputL=DATALOW_INPORT; // Read D0-D7
tempinputH=DATAHIGH_INPORT; // Read D8-D15
NOP(); // Wait
SET_IDE_RD; // Deassert RD
NOP();
return (tempinputL + (tempinputH << 8)); // Return register value
}
//-----------------------------------------------------------------------------
// WriteWord: Write a word to a register address
//
// Parameters: Byte of Address, Word of data
//
// Returns: None
//
// Functions Used: Wait_ReadyBusy, Set_Address
//
//-----------------------------------------------------------------------------
void WriteWord(byte Address, word Data)
{
Wait_ReadyBusy(); // Wait for Drive to be Ready
DATALOW_DIR=ALLOUTPUT; // Make outputs
DATAHIGH_DIR=ALLOUTPUT;
Set_Address(Address); // Set Address
SET_IDE_RD; // RD must be high (inactive)
CLR_IDE_WR; // Assert WR (active low)
delay_us(2);
DATALOW_OUTPORT = (Data&0x00FF); // Output Data
DATAHIGH_OUTPORT = (Data&0xFF00);
delay_us(2);
SET_IDE_WR; // Deassert WR
}
//-----------------------------------------------------------------------------
// CheckforError: Reads status register, and if an error is preset then returns 0
// if no error has occurred then a 0 is returned
//
// Parameters: None
//
// Returns: Byte
//
// Functions Used: ReadReg
//
//-----------------------------------------------------------------------------
byte CheckforError(void)
{
byte statbyte;
statbyte = ReadReg(STATUS); // Read Status Register
if (statbyte & 0x01) return 1; // Is LSB (error bit) is set then return 1
else return 0;
}
//-----------------------------------------------------------------------------
// ReadErrors: If an error was detected, this function can be called to see which
// error flags were set.
// (TO DO: Put meaningfull Words In)
//
// Parameters: None
//
// Returns: None
//
// Functions Used: ReadReg, printf
//
//-----------------------------------------------------------------------------
void ReadErrors(void)
{
byte errors;
errors = ReadReg(ERROR); // Read Error Register
printf("\r\nError Report");
if (errors &0x80) printf("\r\nReserved bit....");
if (errors &0x40) printf("\r\nUNC bit: Uncorrectable data error");
if (errors &0x20) printf("\r\nMC bit: The media has changed");
if (errors &0x10) printf("\r\nIDNF bit: Sector ID not found");
if (errors &0x08) printf("\r\nMCR bit: Media Change Requested");
if (errors &0x04) printf("\r\nABRT bit: Bad Parameters for Rd/Wr; possible out of range IO");
if (errors &0x02) printf("\r\nTK0NF bit: Can't find track 0; possible disc failure");
if (errors &0x01) printf("\r\AMNF bit: Address mark not found");
while (1);
}
//-----------------------------------------------------------------------------
// DataInputSetup: Makes Data line D0 - D7, D8 - D15 as inputs with internal
// pullups enabled.
//
// Parameters: None
//
// Returns: None
//
// Functions Used: None
//
//-----------------------------------------------------------------------------
void DataInputSetup(void)
{
DATALOW_OUTPORT = PULLUPSON; // Switch internal Port pullups on
DATAHIGH_OUTPORT= PULLUPSON;
DATALOW_DIR=ALLINPUT; // Switch data lines to input
DATAHIGH_DIR=ALLINPUT;
}
//-----------------------------------------------------------------------------
// Fetch_ID_Max_LBA: Reads drive parameters and returns Max LBA address
//
// Parameters: If silent set then no terminal output, else prints results
//
// Returns: Max LBA address (32bits)
//
//-----------------------------------------------------------------------------
UI32 Fetch_ID_Max_LBA(byte silent)
{
byte i,cnt;
byte chardata;
word tempbuffer[65];
UI32 TotalLBAs=0;
// Wait till not busy and RDY?
Wait_ReadyBusy();
// Send Command for drive identification
WriteReg(COMMAND, DRIVEID);
// Wait for DRQ
Wait_DRQ();
// Read in first 62 bytes of the drive identification
for (i=0; i<62; i++)
{
// Read data words from drives buffer
tempbuffer[i] = ReadWord(DATA);
}
// Assuming drive supports LBA find max LBA sector
TotalLBAs = tempbuffer[61];
TotalLBAs = TotalLBAs << 16;
TotalLBAs = TotalLBAs + tempbuffer[60];
if (!silent)
{
printf("\r\nHard Disc Auto Detect Parameters");
printf("\r\n--------------------------------\r\n");
// Detect HDD or CDROM
printf("\r\nType of device: ");
if (tempbuffer[0]&0x8000) printf("ATA Device ");
else printf("ATAPI Device ");
// Detect removable media
if (tempbuffer[i]&0x0080) printf("which has removable media");
// Heads
printf("\r\nThe number of heads is = %d",tempbuffer[3]);
// Cylinders
printf("\r\nThe number of Cylinders is = %d",tempbuffer[1]);
// Sectors Per Track
printf("\r\nThe number of Sectors per track is = %d", tempbuffer[6]);
// Serial Number
printf("\r\nThe number of Serial Number of the device is = ");
for (cnt=10; cnt<19; cnt++)
{
chardata = tempbuffer[cnt]>>8;
putchar(chardata);
chardata = tempbuffer[cnt];
putchar(chardata);
}
// Model Number
printf("\r\nThe number of Model Number of the device is = ");
for (cnt=27; cnt<46; cnt++)
{
chardata = tempbuffer[cnt]>>8;
putchar(chardata);
chardata = tempbuffer[cnt];
putchar(chardata);
}
// CHS or LBA
if(!((tempbuffer[49] >> 8) & 0x1))
printf("\r\nCHS Mode Only (NO LBA)");
else
printf("\r\nLBA Supported");
// Report max lba address
printf("\r\nLBA sectors is 0x%lx", TotalLBAs);
}
// Return Max LBA sector address in global drive information
return TotalLBAs;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -