#include"ramdisk_driver.h"
#include<linux/genhd.h>
#include<linux/blkdev.h>
#include<linux/bio.h>
#include<linux/hdreg.h> //// for struct hd_geometry Allen add 2012/06/11
#define DEVICE_MAJOR 240
#define DEVICE_NAME "ramdisk"
#define SECTOR_SIZE 512 //扇区大小
//#define DISK_SIZE (3*1024*1024) //虚拟磁盘大小
#define SECTOR_ALL (DISK_SIZE/SECTOR_SIZE) //虚拟磁盘的扇区数
static struct gendisk *p_disk; //用来指向申请的gendisk结构体
static struct request_queue *p_queue; //用来指向请求队列
//static unsigned char mem_start[DISK_SIZE]; //分配一块3M 的内存作为虚拟磁盘
UINT8 *mem;
static int _init_flag = 0;
struct file*filp;
unsigned char oemBuf[8*1024*1024]; //分配一块8M 的内存作为虚拟磁盘
unsigned char *oemBuf_phy=NULL; //
unsigned char *oem_mem=NULL;
unsigned long ramdiskaddr;// virtual addr of ramdisk buffer
unsigned long addr,phy_addr;
unsigned long* dwordpntr=NULL;
unsigned long RAM_DISK_SIZE=0;
unsigned long RAM_DISK_SECTOR_ALL=0;
#define RAM_DISK_SECTOR_SIZE 512
unsigned char * buf_virt_addr=NULL;
unsigned char * buf_phy_addr=NULL;
static int _Init(void)
{
FIRMWARE_STATUS status = FIRMWARE_STATUS_SUCCESSFUL;
unsigned long i=0;
unsigned long* FIRMWARE_head_point;
unsigned long FIRMWARE_head_checksum = 0;
unsigned long FIRMWARE_head_offset = 0;
unsigned long FIRMWARE_head_length = 0;
unsigned long FIRMWARE_hhm_temperature_entrypoint = 0;
unsigned long FIRMWARE_INTERRUPT_flash_init_entrypoint = 0;
unsigned long FIRMWARE_INTERRUPT_flash_read_entrypoint = 0;
unsigned long FIRMWARE_INTERRUPT_flash_write_entrypoint = 0;
unsigned long FIRMWARE_INTERRUPT_flash_exit_entrypoint = 0;
unsigned char* pntr=NULL;
if (_init_flag != 0)
{ return (_STATUS_SUCCESSFUL);}
filp=filp_open("/dev/mem",O_RDWR,S_IRWXU);
mem=do_mmap(filp,0x0,0xe0000,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,0xfff00000);
for(i=0;i<0x100000;i++)
{
if(mem[i]==0x24&&mem[1+i]==0x55&&mem[2+i]==0x55&&mem[3+i]==0x61)
{
FIRMWARE_head_offset=i;
//printk("%d\n",FIRMWARE_head_offset);
break;
}
}
pRuntime = ioremap(0xF0000,0x10000); //map runtime memory
FIRMWARE_head_point = (unsigned long*)(mem + FIRMWARE_head_offset);
i = FIRMWARE_HEAD_LENGTH_OFFSET/4;
FIRMWARE_head_length = *(FIRMWARE_head_point+i) ;
for(i=0;i<(FIRMWARE_head_length/4);i++)
{ FIRMWARE_head_checksum += *(FIRMWARE_head_point + i);}
if(FIRMWARE_head_checksum != 0)
{
printk(" not supported. Checksum is not 0.\n");
return _STATUS_UNSUPPORT;
}
i = FIRMWARE_INTERRUPT_Flash_Init_EntryPoint_offset/4;
FIRMWARE_INTERRUPT_flash_init_entrypoint = *(FIRMWARE_head_point + i)+FIRMWARE_head_offset;
i = FIRMWARE_INTERRUPT_Flash_Read_EntryPoint_offset/4;
FIRMWARE_INTERRUPT_flash_read_entrypoint = *(FIRMWARE_head_point + i)+FIRMWARE_head_offset;
i = FIRMWARE_INTERRUPT_Flash_Write_EntryPoint_offset/4;
FIRMWARE_INTERRUPT_flash_write_entrypoint = *(FIRMWARE_head_point + i)+FIRMWARE_head_offset;
i = FIRMWARE_INTERRUPT_Flash_Exit_EntryPoint_offset/4;
FIRMWARE_INTERRUPT_flash_exit_entrypoint = *(FIRMWARE_head_point + i)+FIRMWARE_head_offset;
FIRMWARE_INTERRUPT_Flash_Init = (FIRMWARE_STATUS(*)(UINT8*, INTERRUPTFlashInfo*))(mem+FIRMWARE_INTERRUPT_flash_init_entrypoint);
FIRMWARE_INTERRUPT_Flash_Read = (void(*)(UINT8*, UINT8*, UINT32, UINT32, UINT32))(mem+FIRMWARE_INTERRUPT_flash_read_entrypoint);
FIRMWARE_INTERRUPT_Flash_Write = (void(*)(UINT8*, UINT8*, UINT32, UINT32, UINT32))(mem+FIRMWARE_INTERRUPT_flash_write_entrypoint);
FIRMWARE_INTERRUPT_Flash_Exit = (void(*)(UINT8*, UINT8*, UINT32))(mem+FIRMWARE_INTERRUPT_flash_exit_entrypoint);
pINTERRUPTFlashTable = NULL;
#if 0
i=0;
while(i<0x10000)
{
dwordpntr=pRuntime+i;
if((*dwordpntr)==0x46534124)
{
printk("find $asf:%2x\n",i);
break;
}
i++;
}
#endif
status = FIRMWARE_INTERRUPT_Flash_Init(pRuntime, &flash_info);
if(status == FIRMWARE_STATUS_SUCCESSFUL)
{
pINTERRUPTFlashTable =pRuntime+flash_info.INTERRUPTFlashTableOffset;
RAM_DISK_SIZE=flash_info.OEMROMHoleSize;
RAM_DISK_SECTOR_ALL=RAM_DISK_SIZE/RAM_DISK_SECTOR_SIZE;
#if 0 //Fixed address to read FIRMWARE rom hole start
oem_mem=ioremap(0xffe88000,2*flash_info.OEMROMHoleSize);//2*flash_info.OEMROMHoleSize);
for(i=0;i<flash_info.OEMROMHoleSize;i++)
{
oemBuf[i]=oem_mem[i];
}
#endif //Fixed address to read FIRMWARE rom hole End
// Allocate 8KBytes Buffer start
addr=kmalloc(0x2000,GFP_KERNEL|__GFP_DMA);
if(!addr){return -ENOMEM;}
phy_addr=virt_to_phys(addr);
pOEMROMHoleBuffer=(unsigned char*)(addr);
if(pOEMROMHoleBuffer==-1)
{
pINTERRUPTFlashTable = NULL; //map buffer failed, disable flash program.
}
// Allocate 8KBytes Buffer End
// Read FIRMWARE RomHole value by call function start
pntr=(unsigned char*)oemBuf;
for(i=0;i<flash_info.OEMROMHoleSize/0x1000;i++)
{
_Flash_ReadRomHole(i*0x1000,pntr+(i*0x1000),0x1000);
}
// Read FIRMWARE RomHole value by call function end
// Write2Flash();
_init_flag = 1;
return 0;
}//FIRMWARE INTERRUPT Flash Init Successfully end
}
int __attribute__((regparm(0))) _Flash_ReadRomHole(unsigned long Offset,unsigned char *pBuf,unsigned long Length)
{
unsigned char *poem_rom_hole_base;
//unsigned char *buf_phy_addr,*buf_virt_addr;
buf_phy_addr=(unsigned char *)(phy_addr);
buf_virt_addr=(unsigned char*)(addr);
if(Offset>=flash_info.OEMROMHoleSize)
{
printk(KERN_INFO"Offset is a invalid parameter.\n");
return _STATUS_FAILED; //invalid parameter
}
FIRMWARE_INTERRUPT_Flash_Read(pINTERRUPTFlashTable, buf_virt_addr,buf_phy_addr, flash_info.OEMROMHoleAddr+Offset,Length);// flash_info.OEMROMHoleSize);
poem_rom_hole_base =buf_virt_addr+0x100;// pOEMROMHoleBuffer+0x100;
memcpy(pBuf, poem_rom_hole_base, Length);
// printk("*pBuf=%02x *poem_rom_hole_base=%02x \n",*pBuf,*poem_rom_hole_base);
return _STATUS_SUCCESSFUL;
}
int __attribute__((regparm(0))) _Flash_WriteRomHole(unsigned long Offset,unsigned char *pBuf,unsigned long Length)
{
unsigned char *poem_rom_hole_base;
// unsigned char *buf_phy_addr,*buf_virt_addr;
buf_phy_addr=(unsigned char *)(phy_addr);
buf_virt_addr=(unsigned char*)(addr);
if(Offset >= flash_info.OEMROMHoleSize)
{
printk(KERN_INFO"Offset is a invalid parameter.\n");
return _STATUS_FAILED; //invalid parameter
}
poem_rom_hole_base =buf_virt_addr+0x100;
memcpy(poem_rom_hole_base, pBuf, Length);
// printk("buf_virt_addr +0x100 value=%04x\n ",*(buf_virt_addr+0x100));
// printk("Offest=%04x\n *pBuf=%02x\n Length=%04x\n ",Offset,*pBuf,Length);
// printk("flash_info.OEMROMHoleAddr+Offset=%04x\n ",flash_info.OEMROMHoleAddr+Offset);
// printk(KERN_INFO "%08x\n",*(mem+0x1000));
FIRMWARE_INTERRUPT_Flash_Write(pINTERRUPTFlashTable, buf_virt_addr,buf_phy_addr,flash_info.OEMROMHoleAddr+Offset,Length);
return _STATUS_SUCCESSFUL;
}
/***********************************************************************
对于ram、loop、网络设备等使用自己编写的make_request函数来处理bio
省去使用内核I/O调度器的过程,make_request返回值是0
**********************************************************************/
static int ramdisk_make_request(struct request_queue *q,struct bio *bio)
{
struct bio_vec *bvec; //bio结构中包含多个bio_vec结构
int i; //用于循环的变量,不需要赋值
void *disk_mem; //指向虚拟磁盘正在读写的位置
if((bio->bi_sector*RAM_DISK_SECTOR_SIZE)+bio->bi_size>RAM_DISK_SIZE)
{
//检查超出容量的情况
printk("ramdisk over flowed!/n");
bio_endio(bio,1); //第二个参数为1通知内核bio处理出错
return 0;
}
// disk_mem=mem_start+bio->bi_sector*SECTOR_SIZE; //mem_start是虚拟磁盘的起始地址
disk_mem=oemBuf+bio->bi_sector*RAM_DI