⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide_io.h

📁 外挂硬盘和FLASH的MP3播放器解决方案
💻 H
字号:

#define IDE_INTERRUPT					FALSE

//IDE basic I/O
#define IDE_ADDR_CTRL					0x00
#define IDE_ADDR_CMD					0x10

#define IDE_IO_RE						P3_7
#define IDE_IO_WE						P3_6
#define IDE_IO_CS0						0x80		//P4_2
#define IDE_IO_CS1						0x40		//P4_3
#define IDE_IO_DA0						0x01		//P4_1
#define IDE_IO_DA1						0x02		//P4_4
#define IDE_IO_DA2						0x04		//P4_0

#define IDE_IO_RESET						P5_0
#define IDE_ADDR_BASE						0x8000

#define IDE_ADDR_CTRL						0x1000
#define IDE_ADDR_CMD						0x0000

//IDE设备控制寄存器地址
#define IDE_ADDR_CTRL_STATUS				IDE_ADDR_BASE + IDE_ADDR_CTRL + IDE_IO_DA2 + IDE_IO_DA1
#define IDE_ADDR_CTRL_CONTROL				IDE_ADDR_BASE + IDE_ADDR_CTRL + IDE_IO_DA2 + IDE_IO_DA1

//IDE设备命令寄存器地址
#define IDE_ADDR_CMD_DATA					IDE_ADDR_BASE + IDE_ADDR_CMD
#define IDE_ADDR_CMD_ERROR					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA0
#define IDE_ADDR_CMD_SECCNT					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA1
#define IDE_ADDR_CMD_LBA0					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA1 + IDE_IO_DA0
#define IDE_ADDR_CMD_LBA1					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2
#define IDE_ADDR_CMD_LBA2					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2 + IDE_IO_DA0
#define IDE_ADDR_CMD_LBA3					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2 + IDE_IO_DA1
#define IDE_ADDR_CMD_STATUS					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2 + IDE_IO_DA1 + IDE_IO_DA0
#define IDE_ADDR_CMD_COMMAND				IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2 + IDE_IO_DA1 + IDE_IO_DA0
#define IDE_ADDR_CMD_SECTOR					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA1 + IDE_IO_DA0
#define IDE_ADDR_CMD_CYLMSB					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2
#define IDE_ADDR_CMD_CYLLSB					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2 + IDE_IO_DA0
#define IDE_ADDR_CMD_HEAD					IDE_ADDR_BASE + IDE_ADDR_CMD + IDE_IO_DA2 + IDE_IO_DA1

//IDE data port
#define IDE_PORT_DATLSB					ACC
#define IDE_PORT_DATMSB					DAT16H

//IDE status bit
#define IDE_STATUS_BSY					0x80
#define IDE_STATUS_DRDY					0x40
#define IDE_STATUS_DF					0x20
#define IDE_STATUS_DSC					0x10
#define IDE_STATUS_DRQ					0x08
#define IDE_STATUS_CORR					0x04	
#define IDE_STATUS_IDX					0x02	
#define IDE_STATUS_ERR					0x01

//IDE error bit
#define IDE_ERR_UNC						0x40
#define IDE_ERR_MC						0x20
#define IDE_ERR_IDNF					0x10	
#define IDE_ERR_MCR						0x08
#define IDE_ERR_ABRT					0x04	
#define IDE_ERR_TK0NF					0x02	
#define IDE_ERR_AMNF					0x01

//IDE control bit
#define IDE_CTRL_SRST					0x04
#define IDE_CTRL_nIEN					0x02	
#define IDE_CTRL_LBA					0x40	
#define IDE_CTRL_DEV					0x10	

//IDE device operate mode
#define IDE_MODE_DEVICE0_LBA			0xE0
#define IDE_MODE_DEVICE0_CHS			0xA0
#define IDE_MODE_DEVICE1_LBA			0xF0
#define IDE_MODE_DEVICE1_CHS			0xB0

//IDE command
#define IDE_CMD_RECAL					0x10
#define IDE_CMD_READ					0x20
#define IDE_CMD_WRITE					0x30
#define IDE_CMD_DEVDIAG					0x90
#define IDE_CMD_INIT					0x91
#define IDE_CMD_SPINDOWN				0xE0
#define IDE_CMD_SPINUP					0xE1
#define IDE_CMD_IDENTIFYDEV				0xEC

#define IDE_DEVICE0						0
#define IDE_DEVICE1						1

#define IDE_WAIT						TRUE
#define IDE_NOWAIT						FALSE

#define IDE_RESET_HARDWARE				0
#define IDE_RESET_SOFTWARE				1


//IDE function return value
#define IDE_SUCCESSFUL					0x00
#define IDE_ERROR_RESET					0x01
#define IDE_ERROR_DIAGNOSTIC			0x01
#define IDE_ERROR_BUSY					0x10
#define IDE_ERROR_NOREADY				0x11
#define IDE_ERROR_DEVFAULT				0x12
#define IDE_ERROR_NODATA				0x13

#define IDE_READ_LSB(addr,dat)			dat=*((BYTE xdata *)addr)
#define IDE_READ_MSB(addr)				SET_BIT_6(AUXR),*((BYTE xdata *)addr),CLEAR_BIT_6(AUXR),IDE_PORT_DATMSB
#define IDE_WRITE_LSB(addr,dat)			*((BYTE xdata *)addr)=dat
#define IDE_WRITE_MSB(addr,dat)			IDE_PORT_DATMSB=dat,EXT16=1,*((BYTE xdata *)addr|(dat<<8)),EXT16=0
#define IDE_READ_WORD(addr,lo,hi)		SET_BIT_6(AUXR);lo=*((BYTE xdata *)addr);hi=IDE_PORT_DATMSB;CLEAR_BIT_6(AUXR)
#define IDE_WRITE_WORD(addr,lo,hi)		SET_BIT_6(AUXR);IDE_PORT_DATMSB=hi;*((BYTE xdata *)addr)=lo;CLEAR_BIT_6(AUXR)

#define DRIVER_TYPE_HDD			0x00		//硬盘
#define DRIVER_TYPE_CDROM		0x01		//光驱
#define DRIVER_TYPE_FLASH		0x02		//FLASH

#define IDEReadSector(X)		IDE.CurrentSector=X; _IDEReadSector()
#define IDEWriteSector(X)		IDE.CurrentSector=X; _IDEWriteSector()

struct IDEStr					 
{
	BYTE	TotalDrivers;		//驱动器数量
	BYTE	CurrentDriver;		//当前驱动器
	BYTE	DriverType;			//驱动器类型
	WORD	BytesPerSec;		//每扇区字节数  512
	DWORD	CurrentSector;		//当前扇区号
}IDE;

struct HDDStr					//硬盘介质参数表
{
	BYTE	TotalPartitions;	//分区数
	BYTE	CurrentPartition;	//当前分区
}HDD;

BYTE IDEInit(void);
BYTE IDEReset(BYTE bRestMode);
int IDE_Busy();
BOOL IDEStatus(BYTE flag,BYTE wait,BYTE logic,WORD timeout);
void IDESpinUP();				//硬盘启动
void IDESpinDOWN();				//硬盘停止
BYTE _IDEReadSector();			//读一个扇区
BYTE _IDEWriteSector();			//写一个扇区


BYTE IDEInit(void)
{
	IDE.TotalDrivers=1;
	IDE.CurrentDriver=1;
	IDE.DriverType=DRIVER_TYPE_HDD;
	IDE.BytesPerSec=512;
    IDE_WRITE_LSB(IDE_ADDR_CMD_HEAD, 0xE0);			//SELECT MASTER HDD FOR LBA MODE
	IDE_WRITE_LSB(IDE_ADDR_CTRL_CONTROL,0x02);
	IDE_WRITE_LSB(IDE_ADDR_CMD_COMMAND,0x10);
	return(0);
/*	if (IDEReset(IDE_RESET_HARDWARE)) return(IDE_ERROR_RESET);		//IDE device reset

	if (!IDEStatus(IDE_STATUS_DRDY,IDE_WAIT,TRUE,255)) return(IDE_ERROR_NOREADY);
	#if (IDE_INTERRUPT)
		IDE_WRITE_LSB(IDE_ADDR_CTRL_CONTROL,0x00);						//enable interrupt mode
	#else
		IDE_WRITE_LSB(IDE_ADDR_CTRL_CONTROL,IDE_CTRL_nIEN);				//disable interrupt mode
	#endif
	
	//check device 0  (MASTER)
	if (IDEIdentifyDevice(IDE_DEVICE0)==IDE_SUCCESSFUL)
	{
		
	}
	else printf("Device 0 error!\n");

	//check device 1  (SLAVE)
	if (IDEIdentifyDevice(IDE_DEVICE1)==IDE_SUCCESSFUL)
	{

	}
	else printf("Device 1 error!\n");

	return(IDE_SUCCESSFUL);
*/
}


BYTE IDEReset(BYTE bRestMode)
{
	register BYTE i;
	if (bRestMode==IDE_RESET_HARDWARE)			//hardware reset
	{
		IDE_IO_RESET=0;
		for (i=0;i<10;i++);
		IDE_IO_RESET=1;
	}
	else if (bRestMode==IDE_RESET_SOFTWARE)		//software reset
	{
		#if (IDE_INTERRUPT)
			IDE_WRITE_LSB(IDE_ADDR_CTRL_CONTROL,IDE_CTRL_SRST);					//enable interrupt mode
		#else
			IDE_WRITE_LSB(IDE_ADDR_CTRL_CONTROL,IDE_CTRL_SRST|IDE_CTRL_nIEN);	//disable interrupt mode
		#endif
	}

	if (IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,1000))	//wait for device reset
		return(IDE_SUCCESSFUL);
	else
		return(IDE_ERROR_RESET);
}
BOOL IDEStatus(BYTE flag,BYTE wait,BYTE logic,WORD timeout)
{
	register BYTE i,status;
	IDE_READ_LSB(IDE_ADDR_CTRL_STATUS,status);
	if (wait)
	{
		while((BOOL)((status&flag))^logic)
		{
			for(i=0;i<255;i++); timeout--;
			if (timeout==0) return(FALSE);
			IDE_READ_LSB(IDE_ADDR_CTRL_STATUS,status);
		}
		return(TRUE);
	}
	else
    	return(status&flag|0);
}    

int IDE_Busy()
{
    register int res,i = 0,j;
    do
    {
        IDE_READ_LSB(IDE_ADDR_CTRL_STATUS,res);
        for(j=0;j<100;j++);
        if(i++>5000) return -1;
    }while(res&0x80);

    return res;
}

void IDESpinUp(void)
{
    IDE_WRITE_LSB(IDE_ADDR_CMD_COMMAND,IDE_CMD_SPINUP);
    IDE_Busy();
}

void IDESpinDown(void)
{
    IDE_Busy();
    IDE_WRITE_LSB(IDE_ADDR_CMD_COMMAND,IDE_CMD_SPINDOWN);
    IDE_Busy();
}

BYTE _IDEReadSector(void)
{
	register BYTE *sector;
	register WORD i;

	sector=(BYTE *)&IDE.CurrentSector;

	if (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255)) {printf("BSY error\n"); return(0);}
	if (!IDEStatus(IDE_STATUS_DRDY,IDE_WAIT,TRUE,255)) {printf("DRDY error\n"); return(0);}
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA0,sector[3]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA1,sector[2]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA2,sector[1]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA3,0xe0|(sector[0]&0x0f));
	IDE_WRITE_LSB(IDE_ADDR_CMD_SECCNT,0x01);
	IDE_WRITE_LSB(IDE_ADDR_CMD_COMMAND,IDE_CMD_READ);
	if (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255)) {printf("BSY error\n"); return(0);}
	if (!IDEStatus(IDE_STATUS_DRQ,IDE_WAIT,TRUE,255)) {printf("DRQ error\n"); return(0);}
	for(i=0;i<512;)
	{
		IDE_READ_WORD(IDE_ADDR_CMD_DATA,DiskBuffer[i++],DiskBuffer[i++]);
	}
	return(0);
}

BYTE _IDEWriteSector(void)
{
	register BYTE *sector;
	register WORD i;

	sector=(BYTE *)&IDE.CurrentSector;

	if (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255)) {printf("BSY error\n"); return(0);}
	if (!IDEStatus(IDE_STATUS_DRDY,IDE_WAIT,TRUE,255)) {printf("DRDY error\n"); return(0);}
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA0,sector[3]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA1,sector[2]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA2,sector[1]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA3,0xe0|(sector[0]&0x0f));
	IDE_WRITE_LSB(IDE_ADDR_CMD_SECCNT,0x01);
	IDE_WRITE_LSB(IDE_ADDR_CMD_COMMAND,IDE_CMD_WRITE);
	if (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255)) {printf("BSY error\n"); return(0);}
	if (!IDEStatus(IDE_STATUS_DRQ,IDE_WAIT,TRUE,255)) {printf("DRQ error\n"); return(0);}
	for(i=0;i<512;)
	{
		IDE_WRITE_WORD(IDE_ADDR_CMD_DATA,DiskBuffer[i++],DiskBuffer[i++]);
	}
	return(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -