📄 ide_base.c
字号:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ATA Disc Raw IO Library for AVR
// V0.1a
// Rob Riglar
// Copyright 2003,2004
//
// Email: rob@robriglar.com
//
// Compiled with Imagecraft C Compiler for the AVR series
//-----------------------------------------------------------------------------
//
// This file is part of ATA Disc Raw IO Library.
//
// ATA Disc Raw 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.
//
// ATA Disc Raw 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 ATA Disc Raw 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 templ, temph;
Wait_ReadyBusy(); // Wait for Drive to be Ready
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
templ = DATALOW_INPORT; // Read D0-D7
temph = DATAHIGH_INPORT; // Read D8-D15
delay_us(1); // Wait
SET_IDE_RD; // Deassert RD
delay_us(1);
return (templ + (temph << 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\nBit 7 Set");
else printf("\r\nBit 7 Clr");
if (errors &0x40) printf("\r\nBit 6 Set");
else printf("\r\nBit 6 Clr");
if (errors &0x20) printf("\r\nBit 5 Set");
else printf("\r\nBit 5 Clr");
if (errors &0x10) printf("\r\nBit 4 Set");
else printf("\r\nBit 4 Clr");
if (errors &0x08) printf("\r\nBit 3 Set");
else printf("\r\nBit 3 Clr");
if (errors &0x04) printf("\r\nBit 2 Set : Bad Parameters for Rd/Wr");
else printf("\r\nBit 2 Clr");
if (errors &0x02) printf("\r\nBit 1 Set");
else printf("\r\nBit 1 Clr");
if (errors &0x01) printf("\r\nBit 0 Set");
else printf("\r\nBit 0 Clr");
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -