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

📄 cf_io.c

📁 Nokia3510i手机液晶屏驱动程序
💻 C
字号:
#include "CF_IO.h"

uint8_t CF_Initialize(void)
{
	CF_DataOffset = 0;
	CF_CurrentLBA = 0;
	outb(CF_COMMAND_REG, CF_CMD_DIAGNOSTIC);	//执行诊断指令,判断CF卡是否可用
	loop_until_bit_is_clear(CF_STATUS_REG, 7);	//等待BUSY位清空
	if(inb(CF_ERROR_REG) == 0x01)				//返回0x01表示成功
	{
		outb(CF_FEATURE_REG, 0x01);
		outb(CF_DRIVER_REG, 0xa0);
		outb(CF_COMMAND_REG, CF_CMD_SETFEATURE);	//设置驱动器特性
		loop_until_bit_is_clear(CF_STATUS_REG, 7);
		return inb(CF_ERROR_REG);
	}
	else
		return inb(CF_ERROR_REG);
}

void CF_ChangeDrive(unsigned char d)
{
	if(d)
		sbi(CF_DRIVER_REG, 4);		//从盘
	else
		cbi(CF_DRIVER_REG, 4);		//主盘
}

uint8_t CF_GetCardInfo(CF_TInfo *I)
{
	uint8_t i;
	outb(CF_COMMAND_REG, CF_CMD_IDENTITY);	//执行获取CF卡信息的指令
	loop_until_bit_is_clear(CF_STATUS_REG, 7);
	if(inb(CF_ERROR_REG))
		return inb(CF_ERROR_REG);
	else
	{
		loop_until_bit_is_set(CF_STATUS_REG, 3);
		I->Signature = inw(CF_DATA_REG);
		I->Cylinders = inw(CF_DATA_REG);
		inw(CF_DATA_REG);
		I->Heads = inw(CF_DATA_REG);
		inw(CF_DATA_REG);
		inw(CF_DATA_REG);
		I->SectorsPerTrack = inw(CF_DATA_REG);
		I->TotalSectors = ((uint32_t)inw(CF_DATA_REG)) << 16;
		I->TotalSectors += inw(CF_DATA_REG);
		inw(CF_DATA_REG);
		for(i = 0; i < 20; i ++)
			I->SerialNumber[i] = inb(CF_DATA_REG);
		for(i = 0; i < 7; i ++)
			inw(CF_DATA_REG);
		for(i = 0; i < 40; i ++)
			I->ModelNumber[i] = inb(CF_DATA_REG);
		for(i = 0; i < 13; i ++)
			inw(CF_DATA_REG);
		I->LBAs = inw(CF_DATA_REG);
		I->LBAs += ((uint32_t)inw(CF_DATA_REG)) << 16;
		for(i = 0; i < 194; i ++)
			inw(CF_DATA_REG);
		I->TotalSize = I->TotalSectors << 9;
		return 0;
	}
}

uint8_t CF_ReadSector(uint16_t cylinder, uint8_t head, uint8_t sector, uint8_t sectorcount, char *buf)
{
	uint8_t i = 0;
	cbi(CF_DRIVER_REG, 6);		//以柱面号/磁头号/扇区号的方式访问
	outb(CF_SECTOR_COUNT_REG, sectorcount);		//要读取的扇区数
	outb(CF_SECTOR_REG, sector);	//扇区号
	outb(CF_CYLINDER_L_REG, *(uint8_t *)(&cylinder));		//柱面号低位
	outb(CF_CYLINDER_H_REG, *(((uint8_t *)(&cylinder)) + 1));		//柱面号高位
	(*(uint8_t *)(CF_HEAD_REG)) &= 0b11110000;
	(*(uint8_t *)(CF_HEAD_REG)) |= head & 0b00001111;		//设置磁头号(CF_HEAD_REG低4位为磁头号)
	outb(CF_COMMAND_REG, CF_CMD_READSECTOR);	//执行读取指令
	loop_until_bit_is_clear(CF_STATUS_REG, 7);		//等待BUSY位清空
	if(inb(CF_ERROR_REG))		//不返回0x00表示有错
		return inb(CF_ERROR_REG);
	else
	{
		do
		{
			loop_until_bit_is_set(CF_STATUS_REG, 3);	//等待DataRequest位置位
			do
			{
				*(buf ++) = inb(CF_DATA_REG);	//顺序把数据寄存器的值放到buf中
				*(buf ++) = inb(CF_DATA_REG);
			}while(--i);
		}while(--sectorcount);
		return 0;
	}
}

uint8_t CF_LBAReadSector(uint32_t LBA, uint8_t sectorcount, char *buf)
{
	uint8_t i = 0;
	sbi(CF_DRIVER_REG, 6);		//以LBA方式访问
	outb(CF_SECTOR_COUNT_REG, sectorcount);
	outb(CF_LBA_0_7_REG, *(uint8_t *)(&LBA));
	outb(CF_LBA_8_15_REG, *(((uint8_t *)(&LBA)) + 1));
	outb(CF_LBA_16_23_REG, *(((uint8_t *)(&LBA)) + 2));
	(*(uint8_t *)(CF_LBA_24_27_REG)) &= 0b11110000;
	(*(uint8_t *)(CF_LBA_24_27_REG)) |= *(((uint8_t *)(&LBA)) + 3) & 0b00001111;
	outb(CF_COMMAND_REG, CF_CMD_READSECTOR);
	loop_until_bit_is_clear(CF_STATUS_REG, 7);
	if(inb(CF_ERROR_REG))
		return inb(CF_ERROR_REG);
	else
	{
		do
		{
			loop_until_bit_is_set(CF_STATUS_REG, 3);
			do
			{
				*(buf ++) = inb(CF_DATA_REG);
				*(buf ++) = inb(CF_DATA_REG);
			}while(--i);
		}while(--sectorcount);
		return 0;
	}
}

uint8_t CF_WriteSector(uint16_t cylinder, uint8_t head, uint8_t sector, uint8_t sectorcount, char *buf)
{
	uint8_t i = 0;
	cbi(CF_DRIVER_REG, 6);
	outb(CF_SECTOR_COUNT_REG, sectorcount);
	outb(CF_SECTOR_REG, sector);
	outb(CF_CYLINDER_L_REG, *(uint8_t *)(&cylinder));
	outb(CF_CYLINDER_H_REG, *(((uint8_t *)(&cylinder)) + 1));
	(*(uint8_t *)(CF_HEAD_REG)) &= 0b11110000;
	(*(uint8_t *)(CF_HEAD_REG)) |= head & 0b00001111;
	outb(CF_COMMAND_REG, CF_CMD_WRITESECTOR);
	loop_until_bit_is_clear(CF_STATUS_REG, 7);
	if(inb(CF_ERROR_REG))
		return inb(CF_ERROR_REG);
	else
	{
		do
		{
			loop_until_bit_is_set(CF_STATUS_REG, 3);	//等待DataRequest位置位
			do
			{
				outb(CF_DATA_REG, *(buf ++));		//顺序把buf中的内容送到数据寄存器
				outb(CF_DATA_REG, *(buf ++));
			}while(--i);
		}while(--sectorcount);
		loop_until_bit_is_clear(CF_STATUS_REG, 7);		//等待BUSY位清空
		return inb(CF_ERROR_REG);
	}
}

uint8_t CF_LBAWriteSector(uint32_t LBA, uint8_t sectorcount, char *buf)
{
	uint8_t i = 0;
	sbi(CF_DRIVER_REG, 6);
	outb(CF_SECTOR_COUNT_REG, sectorcount);
	outb(CF_LBA_0_7_REG, *(uint8_t *)(&LBA));
	outb(CF_LBA_8_15_REG, *(((uint8_t *)(&LBA)) + 1));
	outb(CF_LBA_16_23_REG, *(((uint8_t *)(&LBA)) + 2));
	(*(uint8_t *)(CF_LBA_24_27_REG)) &= 0b11110000;
	(*(uint8_t *)(CF_LBA_24_27_REG)) |= *(((uint8_t *)(&LBA)) + 3) & 0b00001111;
	outb(CF_COMMAND_REG, CF_CMD_WRITESECTOR);
	loop_until_bit_is_clear(CF_STATUS_REG, 7);
	if(inb(CF_ERROR_REG))
		return inb(CF_ERROR_REG);
	else
	{
		do
		{
			loop_until_bit_is_set(CF_STATUS_REG, 3);
			do
			{
				outb(CF_DATA_REG, *(buf ++));
				outb(CF_DATA_REG, *(buf ++));
			}while(--i);
		}while(--sectorcount);
		loop_until_bit_is_clear(CF_STATUS_REG, 7);
		return inb(CF_ERROR_REG);
	}
}

void CF_Sleep(void)
{
	outb(CF_COMMAND_REG, CF_CMD_SLEEP);
}

void CF_Standby(void)
{
	outb(CF_COMMAND_REG, CF_CMD_STANDBY);
}


uint8_t CF_LBAOpen(uint32_t LBA)
{
	CF_DataOffset = 0;
	CF_CurrentLBA = LBA;
	sbi(CF_DRIVER_REG, 6);
	outb(CF_SECTOR_COUNT_REG, 1);
	outb(CF_LBA_0_7_REG, *(uint8_t *)(&LBA));
	outb(CF_LBA_8_15_REG, *(((uint8_t *)(&LBA)) + 1));
	outb(CF_LBA_16_23_REG, *(((uint8_t *)(&LBA)) + 2));
	(*(uint8_t *)(CF_LBA_24_27_REG)) &= 0b11110000;
	(*(uint8_t *)(CF_LBA_24_27_REG)) |= *(((uint8_t *)(&LBA)) + 3) & 0b00001111;
	outb(CF_COMMAND_REG, CF_CMD_READSECTOR);
	loop_until_bit_is_clear(CF_STATUS_REG, 7);
	return inb(CF_ERROR_REG);
}

uint8_t CF_LBAReadb(void)
{
	CF_DataOffset ++;
	return inb(CF_DATA_REG);
}

uint16_t CF_LBAReadw(void)
{
	CF_DataOffset += 2;
	return inw(CF_DATA_REG);
}

uint32_t CF_LBAReadl(void)
{
	uint32_t r;
	CF_DataOffset += 4;
	r = inw(CF_DATA_REG);
	r += ((uint32_t)inw(CF_DATA_REG)) << 16;
	return r;
}

void CF_LBASeek(uint16_t o)
{
	uint16_t i;
	if(o < CF_DataOffset)
	{
		CF_LBAOpen(CF_CurrentLBA);
		for(i = 0; i < o; i ++)
			inb(CF_DATA_REG);
	}
	else
		for(i = CF_DataOffset; i < o; i ++)
			inb(CF_DATA_REG);
	CF_DataOffset = o;
}

void CF_LBAClose(void)
{
	CF_LBASeek(0x200);
}

⌨️ 快捷键说明

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