|
原帖由 天风 于 2008-7-28 10:37 发表
照抄一个给需要的朋友:
设置硬盘最大可读取扇区源码:
======================================
/* setmax.c - aeb, 000326 - use on 2.4.0test9 or newer */
/* I ...
这个资料有点老了,新的需要用READ_NATIVE_MAX_ADDR_EXT、SET_MAX_ADDR_EXT
并且LBA地址也变成48位了。
使用SET_MAX_ADDR_EXT还是SET_MAX_ADDR,要对get_identity取得的参数块中的id[83]和id[86]进行判断。
原来的两个函数要改一下:
- #define READ_NATIVE_MAX_ADDR_EXT 0x27
- #define SET_MAX_ADDR_EXT 0x37
- #define TASKFILE_CMD_REQ_NODATA 0
- #define TASKFILE_XFER_METHOD_NONE 0
- static __u64 get_native_max_address(int fd,__u16 **id_p)
- {
- struct hdio_taskfile r;
- __u16 *id;
- *id_p=id=get_identify_data(fd,*id_p);
- if(id&&((id[83]&0xc400)==0x4400)&&(id[86]&0x0400)){
- memset(&r,0,sizeof(r));
- r.cmd_req=TASKFILE_CMD_REQ_NODATA;
- r.xfer_method=TASKFILE_XFER_METHOD_NONE;
- r.lob.command=READ_NATIVE_MAX_ADDR_EXT;
- r.lob.dev=0x40;
- taskfile_std_flags(&r,1);
- if(!do_taskfile_cmd(fd,&r,10))
- return((__u64)((r.hob.lbah<<16)|(r.hob.lbam<<8)|r.hob.lbal)|((r.lob.lbah<<16)|(r.lob.lbam<<8)|r.lob.lbal))+1;
- perror ("读取硬盘真实容量失败!");
- }
- memset(&r,0,sizeof(r));
- r.cmd_req=TASKFILE_CMD_REQ_NODATA;
- r.xfer_method=TASKFILE_XFER_METHOD_NONE;
- r.lob.command=READ_NATIVE_MAX_ADDR;
- r.lob.dev=0x40;
- taskfile_std_flags(&r,0);
- if (!do_taskfile_cmd(fd,&r,10))
- return ((r.lob.lbah<<16)|(r.lob.lbam<<8)|r.lob.lbal)+1;
- perror ("读取硬盘真实容量失败!");
- return 0;
- }
- static void set_max_address (int fd, __u16 **id_p, __u64 secs, int nonvolat)
- {
- struct hdio_taskfile r;
- __u16 *id;
- __u64 addr=secs-1;
- *id_p=id=get_identify_data(fd,*id_p);
- if(id&&((id[83]&0xc400)==0x4400)&&(id[86]&0x0400)){
- memset(&r,0,sizeof(r));
- r.cmd_req=TASKFILE_CMD_REQ_NODATA;
- r.xfer_method=TASKFILE_XFER_METHOD_NONE;
- r.lob.command=SET_MAX_ADDR_EXT;
- r.lob.feat=0;
- r.lob.dev=0x40;
- r.lob.nsect=nonvolat ? 1 : 0;
- r.lob.lbal=addr&0xff;
- r.lob.lbam=(addr>>8)&0xff;
- r.lob.lbah=(addr>>16)&0xff;
- r.hob.lbal=(addr>>24)&0xff;
- r.hob.lbam=(addr>>32)&0xff;
- r.hob.lbah=(addr>>40)&0xff;
- taskfile_std_flags(&r,1);
- if(!do_taskfile_cmd(fd,&r,10))
- return;
- perror ("设置HPA失败!");
- }
- if(addr&0xfffffffff0000000LLU){
- fprintf(stderr,"不支持LBA28!\n");
- return;
- }
- memset(&r,0,sizeof(r));
- r.cmd_req=TASKFILE_CMD_REQ_NODATA;
- r.xfer_method=TASKFILE_XFER_METHOD_NONE;
- r.lob.command=SET_MAX_ADDR;
- r.lob.feat=0;
- r.lob.dev=0x40|((addr>>24)&0x0f);
- r.lob.nsect=nonvolat ? 1 : 0;
- r.lob.lbal=addr&0xff;
- r.lob.lbam=(addr>>8)&0xff;
- r.lob.lbah=(addr>>16)&0xff;
- taskfile_std_flags(&r,0);
- if (do_taskfile_cmd(fd,&r,10))
- perror ("设置HPA失败!");
- return;
- }
复制代码 ***addr的单位是扇区不是字节***
下面是LBA28和LBA48对照表,LBA28只有左边部分(字节),LBA48扩展成字,并且bit24~27也不放原来LBA28的那个位置了(原来在dev reg的低4位)。ATA命令放在这个表下面的一个字节/字。
另外,为了避免被病毒利用加口令部分俺就不提供了:)其实还有一个比较麻烦的是要先取得硬盘I/O口基址,这个要从PCICFG取得。
[ 本帖最后由 netwinxp 于 2008-8-1 08:56 编辑 ] |
评分
-
查看全部评分
|