📄 ata.c
字号:
/*C**************************************************************************
* NAME: ata.c
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE: snd1c-demo-hdd-0_2_0
* REVISION: 1.1
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the high level ATA routines
*****************************************************************************/
/*_____ I N C L U D E S ____________________________________________________*/
#include "config.h" /* system configuration */
#include "lib_demob\board.h" /* board definition */
#include "lib\usb\usb_drv.h" /* usb driver definition */
#include "ide.h" /* ide definition */
#include "ata.h" /* ata definition */
/*_____ M A C R O S ________________________________________________________*/
/*_____ D E F I N I T I O N ________________________________________________*/
extern data Uint32 gl_ptr_mem; /* memory data pointer */
xdata Uint32 hdd_mem_size; /* HDD size in sector */
data Uint16 gl_cpt_page;
extern bdata bit ide_parity;
/* IDE registers */
/* name | RD# = 0 | WR# = 0 | */
extern xdata Byte volatile ide_data; /* | RD data | WR data | */
extern xdata Byte volatile ide_error; /* | Error | Features | */
extern xdata Byte ide_sector_count; /* | Sect. count | Sect. count | */
extern xdata Byte ide_sector_number; /* | Sect. No | Sect. No | */
extern xdata Byte ide_cylinder_low; /* | Cyl. Low | Cyl. Low | */
extern xdata Byte ide_cylinder_high; /* | Cyl. High | Cyl. High | */
extern xdata Byte ide_drive_head; /* | Drive/Head | Drive/Head | */
extern xdata Byte volatile ide_status; /* | Status | Command | */
extern xdata Byte volatile ide_alt_status; /* | Alt status | Device Ctrl | */
extern xdata Byte volatile ide_reset_on;
extern xdata Byte volatile ide_reset_off;
code Uint32 hdd_block_size = Hdd_block_size();
extern xdata Byte fat_buf_sector[]; /* 512 bytes buffer */
Byte previous_op;
Uint16 error;
/*_____ D E C L A R A T I O N ______________________________________________*/
extern void fat_format (void);
/*F**************************************************************************
* NAME: hdd_init
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
* OK if HDD is ready, KO else
*----------------------------------------------------------------------------
* PURPOSE:
* Hard Disk Drive initialisation
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit hdd_init(void)
{
Byte dummy;
Ide_set_ide_mode();
P2 = IDE_PORT_IDLE;
P5_2 = 1; /* P5_2 is RST# */
ide_device_control = ATA_RESET_CMD;
for (dummy = 255; dummy != 0; dummy--);
ide_device_control = 0xFA;
for (dummy = 255; dummy != 0; dummy--);
while (Ide_notbsy() == KO); /* Wait for BSY = 0 */
while (Ide_notbsy_drdy() == KO); /* Wait for BSY = 0 and DRDY = 1 */
error = ide_error;
Ide_set_drive_head(ATA_LBA_MODE); /* Select Drive/Head */
while (Ide_notbsy_drdy() == KO); /* Wait for BSY = 0 and DRDY = 1 */
dummy = Ide_get_status(); /* Read status byte */
if ( ((dummy & IDE_ERR) == IDE_ERR) || /* Check if there is an error */
((dummy & IDE_DRDY) != IDE_DRDY) ) /* or DRDY = 0 */
return KO;
dummy = Ide_get_status(); /* Clear pending interrupt */
P1_6 = P1_7 = 1;
previous_op = 3;
return OK;
}
/*F**************************************************************************
* NAME: ata_identify_device
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
* General Configuration Information
*----------------------------------------------------------------------------
* PURPOSE:
* Identifies a device and gives its characteristics
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Uint16 ata_identify_device (void)
{
Uint16 ata_gci;
Byte i;
Uint16 j;
while (Ide_notbsy_notdrq() == KO); /* Wait for BSY = 0 */
Ide_set_drive_head (ATA_LBA_MODE); /* Select Drive / Head */
while (Ide_notbsy_drdy() == KO); /* Wait for BSY = 0 and DRDY = 1 */
Ide_send_command(ATA_CMD_IDENTIFY_DRIVE); /* send command */
while (Ide_notbsy_drq() == KO ); /* Check if data request bit set */
ata_gci = ide_read_dataword(); /* General Configuration Information */
for (i = 56; i !=0 ; i--) /* dummy reads */
ide_read_dataword();
hdd_mem_size = ide_read_dataword(); /* Number of sectors */
hdd_mem_size |= (Uint32)(ide_read_dataword()) << 16;
while (Ide_notbsy_drq() == OK) /* While data request bit is set */
{
ide_read_dataword();
}
i = 3;
do
{
for (j = 0; j < 20; j++);
P1_6 = 0;
hdd_read_open(0,1);
hdd_read_close();
hdd_read_open(256, 1);
hdd_read_close();
hdd_read_open(512, 1);
hdd_read_close();
hdd_read_open(409600, 1);
hdd_read_close();
hdd_read_open(409601, 1);
hdd_read_close();
hdd_read_open(409602, 1);
hdd_read_close();
P1_6 = 1;
}
while (i == 3);
return (ata_gci);
}
/*F**************************************************************************
* NAME: hdd_read_open
*----------------------------------------------------------------------------
* PARAMS:
* sect: address of the logic sector to read (size 512 bytes)
* size : number of sector
* global: gl_ptr_mem
*
* return:
* open status: OK: open done
* KO: open not done
*----------------------------------------------------------------------------
* PURPOSE:
* Open memory card in read mode (read block)
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*
* drive/head register -> LBA 27-24
* cylinder high register -> LBA 23-16
* cylinder low register -> LBA 15-8
* sector number register -> LBA 7-0
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit hdd_read_open (Uint32 sect, Byte nb_sector)
{
Byte ata_status;
if (Ide_notbsy_drq() == OK)
{
if (previous_op == 0)
{
while (Ide_notbsy_drq() == OK)
ata_status = ide_data;
}
else
{
if (previous_op == 1)
{
while (Ide_notbsy_drq() == OK)
{
DAT16H = 0xFF;
ide_data = 0xFF;
}
}
}
}
while (Ide_notbsy_notdrq() == KO); /* Wait for BSY = 0 */
P1_7 = 0;
Ide_set_drive_head( ATA_LBA_MODE + (((Byte*)§)[0] & 0x0F)); /* LBA 27-24 */
gl_cpt_page = 0;
ide_parity = 0;
previous_op = 0;
while (Ide_notbsy_notdrq() == KO); /* Wait for BSY = 0 and DRQ = 0 */
Ide_set_sector_count ( nb_sector ); /* sending parameters */
Ide_set_sector_number(((Byte*)§)[3]); /* LBA 7-0 */
Ide_set_cylinder_low (((Byte*)§)[2]); /* LBA 15-8 */
Ide_set_cylinder_high(((Byte*)§)[1]); /* LBA 23-16 */
Ide_send_command(ATA_CMD_READ_SECTOR); /* send command */
gl_ptr_mem = sect; /* Initialize the global byte counter */
if (ide_status & IDE_ERR)
{
error = 1;
}
ata_status = ide_alt_status;
while (Ide_notbsy_drq() == KO);
P1_7 = 1;
return OK;
}
/*F**************************************************************************
* NAME: hdd_read_close
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* read close
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void hdd_read_close(void)
{
Byte status;
if (gl_cpt_page != 0)
if (gl_cpt_page != 512)
do
{
gl_cpt_page++;
ide_read_databyte();
}
while (gl_cpt_page != 512);
status = ide_alt_status;
status = ide_status;
}
/*F*************************************************************************
* NAME: hdd_read_byte
*---------------------------------------------------------------------------
* PARAMS:
* global: gl_ptr_mem
*
* return:
* Data read from media
*----------------------------------------------------------------------------
* PURPOSE:
* Byte read function
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*
*----------------------------------------------------------------------------
* REQUIREMENTS:
****************************************************************************/
Byte hdd_read_byte(void)
{
Byte status;
if (gl_cpt_page == 512)
{
status = ide_alt_status;
status = ide_status;
gl_ptr_mem++;
hdd_read_open(gl_ptr_mem, 1); /* open the next sector */
}
gl_cpt_page++;
return ide_read_databyte();
}
/*F*************************************************************************
* NAME: hdd_read_long_big_endian
*---------------------------------------------------------------------------
* PARAMS:
* global: gl_ptr_mem
*
* return:
* Data read from media
*----------------------------------------------------------------------------
* PURPOSE:
* Long word big endian coded read function
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*
*----------------------------------------------------------------------------
* REQUIREMENTS:
****************************************************************************/
Uint32 hdd_read_long_big_endian(void)
{
Uint32 temp;
if (gl_cpt_page == 512)
{
status = ide_alt_status;
status = ide_status;
gl_ptr_mem++;
hdd_read_open(gl_ptr_mem, 1); /* open the next sector */
}
((Byte*)&temp)[3] = ide_data;
((Byte*)&temp)[2] = DAT16H;
((Byte*)&temp)[1] = ide_data;
((Byte*)&temp)[0] = DAT16H;
gl_cpt_page += 4;
return temp;
}
/*F*************************************************************************
* NAME: hdd_read_one_sector
*---------------------------------------------------------------------------
* PARAMS:
* global: gl_ptr_mem
*
* return:
*
*----------------------------------------------------------------------------
* PURPOSE:
* Read one sector from media to buffer
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*
*----------------------------------------------------------------------------
* REQUIREMENTS:
****************************************************************************/
void hdd_read_one_sector(void)
{
if (gl_cpt_page == 512)
{
status = ide_alt_status;
status = ide_status;
gl_ptr_mem++;
hdd_read_open(gl_ptr_mem, 1); /* open the next sector */
}
ata_load_sector();
gl_cpt_page += 512;
}
/*F**************************************************************************
* NAME: hdd_read_sector
*----------------------------------------------------------------------------
* PARAMS:
* global: gl_ptr_mem
*
* return: OK read done
* KO read failure
*----------------------------------------------------------------------------
* PURPOSE:
* This function is an optimized function that writes 512 bytes from HDD
* to USB controller
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -