dos下取sata盘的型号与序列号问题,紧急求救

kinbo 2012-05-16 12:16:42
各位老大,

小弟遇到一个头疼的问题,在dos下读取sata硬盘的型号和序列号,

在网上找了不少资料,但是大多都是针对IDE硬盘来的,对于sata硬盘,尤其是AHCI模式的sata硬盘视乎有点无能为力,

在此向各位求救了。

目前参考的源码如下:

#include<stdio.h>
#include<conio.h>
#include <stdlib.h>
#include<dos.h>

main()
{
unsigned char p[512];
unsigned int i;
unsigned int j=0;
unsigned int flag2;
unsigned int flag;

outportb(0x1f6,0xa0);
outportb(0x1f2,0x1);
outportb(0x1f3,1);
outportb(0x1f4,1);
outportb(0x1f5,1);

outportb(0x1f7,0xec);

do
{
flag=inportb(0x1f7);
printf("ide status is %d\n",flag);
}while(flag!=0x58);

for(i=0;i<256;i++)
{
flag2=inport(0x1f0);

p[j++]=(flag2<<8)>>8;
printf("%c",p[j]);
p[j++]=(flag2>>8);
printf("%c",p[j]);
}




printf("disk sn number=");

for(i=20;i<40;i++)
if(i%2==0)
printf("%c",p[i+1]);
else
printf("%c",p[i-1]);

printf("\n\ndisk model=");
for(i=54;i<94;i++)
if(i%2==0)
printf("%c",p[i+1]);
else
printf("%c",p[i-1]);

}

结果一直都是
IDE status is 81

望各位老大帮忙分析一下,是否这段代码对sata硬盘不适用?该怎么调试或者修改?
...全文
172 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
liangbch 2012-05-16
  • 打赏
  • 举报
回复
试一试下面的代码。下面的代码来自http://topic.csdn.net/u/20101203/03/c31adc34-f4ab-400c-9c35-e18f9538a218.html

这是我以前搜到的一个类,虽然自己不懂原理,但能用就行呵呵,VS2005环境测试绝对没问题,其他环境自己调试调试
//MyDiskInfo.h头文件
#pragma once

class MyDiskInfo
{
public:
MyDiskInfo(void);
public:
~MyDiskInfo(void);
public:
int GetDiskInfo(int driver=0);
char szModelNumber[64];
char szSerialNumber[64];
};
//MyDiskInfo.cpp文件

// MyDiskInfo.cpp: implementation of the CMyDiskInfo class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MyDiskInfo.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

const WORD IDE_ATAPI_IDENTIFY = 0xA1; // 读取ATAPI设备的命令
const WORD IDE_ATA_IDENTIFY = 0xEC; // 读取ATA设备的命令

#define _WIN32_WINNT 0x0400
#include "winioctl.h"

//#include "NTDDSCSI.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

MyDiskInfo::MyDiskInfo(void)
{
}

MyDiskInfo::~MyDiskInfo(void)
{
}


BOOL __fastcall DoIdentify( HANDLE hPhysicalDriveIOCTL,
PSENDCMDINPARAMS pSCIP,
PSENDCMDOUTPARAMS pSCOP,
BYTE btIDCmd,
BYTE btDriveNum,
PDWORD pdwBytesReturned)
{
pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
pSCIP->irDriveRegs.bFeaturesReg = 0;
pSCIP->irDriveRegs.bSectorCountReg = 1;
pSCIP->irDriveRegs.bSectorNumberReg = 1;
pSCIP->irDriveRegs.bCylLowReg = 0;
pSCIP->irDriveRegs.bCylHighReg = 0;

pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
pSCIP->irDriveRegs.bCommandReg = btIDCmd;
pSCIP->bDriveNumber = btDriveNum;
pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;

return DeviceIoControl( hPhysicalDriveIOCTL,
SMART_RCV_DRIVE_DATA,
(LPVOID)pSCIP,
sizeof(SENDCMDINPARAMS) - 1,
(LPVOID)pSCOP,
sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
pdwBytesReturned, NULL);
}

char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
{
static char szResBuf[1024];
char ss[256];
int nIndex = 0;
int nPosition = 0;

for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
{
ss[nPosition] = (char)(dwDiskData[nIndex] / 256);
nPosition++;

// Get low BYTE for 2nd character
ss[nPosition] = (char)(dwDiskData[nIndex] % 256);
nPosition++;
}

// End the string
ss[nPosition] = '\0';

int i, index=0;
for(i=0; i <nPosition; i++)
{
if(ss[i]==0 || ss[i]==32) continue;
szResBuf[index]=ss[i];
index++;
}
szResBuf[index]=0;

return szResBuf;
}

int MyDiskInfo::GetDiskInfo(int driver)
{
char sFilePath[64]={0};
sprintf(sFilePath,"\\\\.\\PHYSICALDRIVE%d",driver);//modify by lonkil 2008-07-13

HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = ::CreateFile(sFilePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
0, NULL);
if (hFile == INVALID_HANDLE_VALUE) return -1;

DWORD dwBytesReturned;
GETVERSIONINPARAMS gvopVersionParams;
DeviceIoControl(hFile,
SMART_GET_VERSION,
NULL,
0,
&gvopVersionParams,
sizeof(gvopVersionParams),
&dwBytesReturned, NULL);

if(gvopVersionParams.bIDEDeviceMap <= 0) return -2;

// IDE or ATAPI IDENTIFY cmd
int btIDCmd = 0;
SENDCMDINPARAMS InParams;
int nDrive =0;
btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;


// 输出参数
BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];

if(DoIdentify(hFile,
&InParams,
(PSENDCMDOUTPARAMS)btIDOutCmd,
(BYTE)btIDCmd,
(BYTE)nDrive, &dwBytesReturned) == FALSE) return -3;
::CloseHandle(hFile);

DWORD dwDiskData[256];
USHORT *pIDSector; // 对应结构IDSECTOR,见头文件

pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
for(int i=0; i < 256; i++) dwDiskData[i] = pIDSector[i];

// 取系列号
ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

// 取模型号
ZeroMemory(szModelNumber, sizeof(szModelNumber));
strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

return 0;
}




W170532934 2012-05-16
  • 打赏
  • 举报
回复
楼主为什么不换一种方式呢?机器的配置信息存放在BIOS里面,而Window好像把BIOS映射到物理内存了。我们可以从内存读取BIOS信息,这个应该可以知道的吧?
http://topic.csdn.net/t/20040106/18/2639507.html
kinbo 2012-05-16
  • 打赏
  • 举报
回复
多谢两位高人啦,

俺是要在dos下实现,两位给的参考貌似都要在windows下跑,

另外,bios中关于硬盘参数的读取好像换是要用我那个代码的步骤,写3f7端口,但是为什么我的程序就通不过呢?

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧