新的一年到了,不禁回头望了一下,写些老掉牙的东西以作纪念。
早在2004年,我当时正在写个wdm的驱动程序,因为软件的版本允许在windows 98, windows NT 4.0 , windows 2000和windows XP上运行,我不想每个写了一个wdm后,再实现一个相同功能的Vxd,在当时我的想法里,这是不利行维护,是不明智的行为,于是我决定让我的WDM程序可以在上面所说的所有windows版本上正确运行。想法是美好的,但实现的过程中吃不少苦头。
其中有一项功能是涉及到对磁盘扇区的直接读写取的,有很多种方式的来解决这个问题,在NT系统下,最简单莫过直接构造IRP传递给磁盘驱动程序,或者最直接的IO PORT操作,BIOS 中断 INT 13等。 使用IO PORT,这适用于NT 和windows 98,看来完美解决方案,但问题的是兼容性比较差,实际的效果表明驱动使用这种方式也表现得很不稳定。而最偷懒最简单最稳定的方式却是直接构造IRP传递给磁盘驱动程序,可惜只能用于NT,原因是虽然windows 98 ntkern.vxd这个系统模块中包括有大量NT内核支持函数的windoes 98实现,号称wdm程序几乎区别不了这两个环境,但事实上却没有这样高度的统一,没有像NT一样所有的内核模式都使用一个公用的数据结构(IRP),如串口的驱动程序要遵从VCOMM.vxd规定的port驱动程序函数调用规范,而磁盘驱动程序则遵从IOS.vxd实现的包驱动层次结构,NTKERN.VXD实事上遗留了不少未实现的函数。所以当时最开始的打算是在NT 系统下使用IRP传递给磁盘驱动程序的方式,而windows 98则采用类似的Ios_SendCommand的方式向磁盘驱动投递请求。
在windows98下Ios_SendCommand工作得像windows 2000下的IoCallDriver一样简单优雅,但是不幸的是,程序需要在驱动初始化的也要进行对磁盘的读取,在这个阶段Ios_SendCommand完全不能工作,是因为NTKERN.VXD把WDM的驱动在IOS.SYS初始化完成一份硬盘驱动器表之前就初始化了,同时WDM的序动顺序也无法像在WINDOWS2000下面那样多的级别可以指定,而我驱动程序要刚好在系统加载SYSTEM32下面的RING3层DLL之前,这样初始化动作才有效(事实上我需要修改那
些SYSTEM32目录下的DLL,如果它们一旦给初始化,就无法进行写入的操作了)。而我不想使用直接IO的方式,没有办法,我只能求助于BIOS的INT 13H(及INT 13H的对于大硬盘的扩展功能)。
在这里我使用了nest_v86_execute来进入16bit的实模式环境来执行INT 13h,使用了VMMGR 的服务接口来申请1MB以下的内存,并在16 bit实模式和32 bit 保护模式两种模式下交换数据。
呵呵,当初有趣的尝试,带来了不少的乐趣和新知识。
以下附录一些代码:
- //WINDOWS nt/2000使用IRP的IoCallDriver来访问硬盘
- //
- // Initialize unicode string
- //
- RtlInitUnicodeString(&uszDeviceName, L"//DosDevices//PhysicalDrive0");
- ntStatus = STATUS_INSUFFICIENT_RESOURCES;
- // Get a pointer to PhysicalDrive0
- //
- ntStatus = IoGetDeviceObjectPointer(&uszDeviceName,
- FILE_ANY_ACCESS,
- &fileObject,
- &pDriveDeviceObject);
- // If the device object pointer is valid...
- //
- if(NT_SUCCESS(ntStatus))
- {
- IO_STATUS_BLOCK ioStatus;
- KEVENT event;
- PIRP pIrp;
- KeInitializeEvent(event, NotificationEvent, FALSE);
- pIrp = IoBuildSynchronousFsdRequest(bRead?IRP_MJ_READ:IRP_MJ_WRITE,
- pDriveDeviceObject,
- pBuffer,
- 512,
- &llSectorNum,
- event,
- &ioStatus);
- if(!pIrp)
- {
- ObDereferenceObject(fileObject);
- return STATUS_BAD_STACK;
- }
- ntStatus = IoCallDriver(pDriveDeviceObject, pIrp);
- if(ntStatus == STATUS_PENDING)
- {
- KeWaitForSingleObject(event, Suspended, KernelMode, FALSE, NULL);
- ntStatus = ioStatus.Status;
- }
- // Ditch the fileObject pointer created earlier
- //
- ObDereferenceObject(fileObject);
- }
- //WINDOWS98使用ios_sendCommand来访问硬盘
- //
- #include "ior.h"
- int TestIos_SendCmd(void * pbuffer)
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- Just a testing for Ios_SendCommand,I try to pass the
- request to ios.sys.
- Arguments:
- pbuffer -- a buffer.
- Return Value:
- if all thing ok return 1,else return 0.
- -------------------------------------------------------*/
- {
- IOR iorStru;
- UCHAR nDisk = 0x80;
- readBein:
- memset(&iorStru,0,sizeof(iorStru));
- iorStru.IOR_func =IOR_READ;
- iorStru.IOR_flags =IORF_PHYS_CMD|IORF_VERSION_002|IORF_SYNC_COMMAND|IORF_HIGH_PRIORITY|IORF_WIN32;
- iorStru.IOR_start_addr[0]=0; //start position los
- iorStru.IOR_start_addr[1]=0; //start position high
- iorStru.IOR_xfer_count = 1; //num of sector to read.
- iorStru.IOR_buffer_ptr = (ULONG)pbuffer; //Address of the buffer
- iorStru.IOR_vol_designtr = nDisk; //disknum.
- _asm {
- push esi;
- lea esi,iorStru
- _asm _emit 0xcd
- _asm _emit 0x20
- _asm _emit (0x00100004 & 0xff)
- _asm _emit (0x00100004) >> 8 & 0xff
- _asm _emit (0x00100004) >> 16 & 0xff
- _asm _emit (0x00100004) >> 24 & 0xff //Ios_SendCommand
- pop esi;
- }
- if(iorStru.IOR_status == 0x17)
- {
- if(nDisk == 0x80)
- {
- nDisk = 0x81;
- goto readBein;
- }
- else if (nDisk == 0x81)
- {
- nDisk = 0x2;
- goto readBein;
- }
- }
- else
- return 1;
- }
- //使用BIOS INT 13扩展功能来访问硬盘
- //
- //
- /**
- purpose: define Some Useful defines and structure for using int 13h
- here's the v86mgr real data.
- */
- FFFFFFFF V86MMGR
- 00060000 V86MMGR_Get_Version
- 00060001 V86MMGR_Allocate_V86_Pages
- 00060002 V86MMGR_Set_EMS_XMS_Limits
- 00060003 V86MMGR_Get_EMS_XMS_Limits
- 00060004 V86MMGR_Set_Mapping_Info
- 00060005 V86MMGR_Get_Mapping_Info
- 00060006 V86MMGR_Xlat_API
- 00060007 V86MMGR_Load_Client_Ptr
- 00060008 V86MMGR_Allocate_Buffer
- 00060009 V86MMGR_Free_Buffer
- 0006000A V86MMGR_Get_Xlat_Buff_State
- 0006000B V86MMGR_Set_Xlat_Buff_State
- 0006000C V86MMGR_Get_VM_Flat_Sel
- 0006000D V86MMGR_Map_Pages
- 0006000E V86MMGR_Free_Page_Map_Region
- 0006000F V86MMGR_LocalGlobalReg
- 00060010 V86MMGR_GetPgStatus
- 00060011 V86MMGR_SetLocalA20
- 00060012 V86MMGR_ResetBasePages
- 00060013 V86MMGR_SetAvailMapPgs
- 00060014 V86MMGR_NoUMBInitCalls
- 00060015 V86MMGR_Get_EMS_XMS_Avail
- 00060016 V86MMGR_Toggle_HMA
- 00060017 V86MMGR_Dev_Init
- 00060018 V86MMGR_Alloc_UM_Page
- */
- #define _VMMCALL_V86MMGR_Allocate_Buffer _asm _emit 0xcd /
- _asm _emit 0x20 /
- _asm _emit (0x00060008 & 0xff) /
- _asm _emit (0x00060008 >> 8) & 0xff /
- _asm _emit (0x00060008 >> 16) & 0xff /
- _asm _emit (0x00060008 >> 24) & 0xff /
- #define _VMMCALL_V86MMGR_Free_Buffer _asm _emit 0xcd /
- _asm _emit 0x20 /
- _asm _emit (0x00060009 & 0xff) /
- _asm _emit (0x00060009 >> 8) & 0xff /
- _asm _emit (0x00060009 >> 16) & 0xff /
- _asm _emit (0x00060009 >> 24) & 0xff /
- #define _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(VMHANDLE,PCLIENTSTRU,LPBUFFER,CONST_NUM,NUMCOPIED,FPTR) /
- _asm{mov ebx,VMHANDLE} /
- _asm{push esi} /
- _asm{mov esi,LPBUFFER} /
- _asm{mov ecx,CONST_NUM} /
- _asm{push ebp } /
- _asm{mov ebp,PCLIENTSTRU} /
- _asm{STC } /
- _asm{push ds} /
- _asm{pop fs} /
- {_VMMCALL_V86MMGR_Allocate_Buffer} /
- _asm{pop ebp} /
- _asm{pop esi} /
- _asm{mov NUMCOPIED,ECX} /
- _asm{mov FPTR,EDI} /
- #define _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(VMHANDLE,PCLIENTSTRU,CONST_NUM,NUMALLOCATED,FPTR) /
- _asm{mov ebx,VMHANDLE} /
- _asm{mov ecx,CONST_NUM} /
- _asm{push ebp } /
- _asm{mov ebp,PCLIENTSTRU} /
- _asm{CLC } /
- {_VMMCALL_V86MMGR_Allocate_Buffer} /
- _asm{pop ebp} /
- _asm{mov NUMALLOCATED,ECX} /
- _asm{mov FPTR,EDI} /
- #define _MICRO_V86MMGR_FREE_BUFFER_COPIED(VMHANDLE,PCLIENTSTRU,LPBUFFER,NUMCOPIED) /
- _asm{mov ebx, VMHANDLE} /
- _asm{push esi} /
- _asm{mov esi, LPBUFFER} /
- _asm{mov ecx, NUMCOPIED} /
- _asm{push ebp} /
- _asm{mov ebp, PCLIENTSTRU} /
- _asm{push ds} /
- _asm{pop fs} /
- _asm{stc } /
- {_VMMCALL_V86MMGR_Free_Buffer} /
- _asm{pop ebp} /
- _asm{pop esi} /
- #define _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(VMHANDLE,PCLIENTSTRU,NUMCOPIED) /
- _asm{mov ebx, VMHANDLE} /
- _asm{mov ecx, NUMCOPIED} /
- _asm{push ebp} /
- _asm{mov ebp, PCLIENTSTRU} /
- _asm{CLC } /
- {_VMMCALL_V86MMGR_Free_Buffer} /
- _asm{pop ebp} /
- #define _SAVE_CLIENT_STATE(SAVEREGS) /
- _asm{push edi}/
- _asm{lea edi,SAVEREGS} /
- VMMCall(Save_Client_State) /
- _asm{pop edi}
- #define _RESTORE_CLIENT_STATE(SAVEREGS) /
- _asm push esi /
- _asm lea esi,SAVEREGS /
- VMMCall(Restore_Client_State) /
- _asm pop esi /
- #define _CALL_INT13_V86_(VMHANDLE,PCLIENTSTRU) /
- _asm{mov ebx,VMHANDLE}/
- _asm{push ebp}/
- _asm{mov ebp,PCLIENTSTRU} /
- VMMCall(Begin_Nest_V86_Exec) /
- _asm{mov eax,13h} /
- {VMMCall(Exec_Int)} /
- End_Nest_Exec();/
- _asm{pop ebp}/
- #define GETVM_HANDLE_CLIENTSTRU(VMHANDLE,PCLIENTSTRU) /
- VMHANDLE = (struct cb_s *)Get_Cur_VM_Handle();/
- _asm{mov ebx,VMHANDLE} /
- PCLIENTSTRU = (CLIENT_STRUCT *)VMHANDLE->CB_Client_Pointer;/
- //
- //The next few lines, will map the values into
- //the registers as need by INT13
- //
- #define MAKE_INT13CHSD_IN_HS(CYL,HEA,SEC,DISK) /
- _asm{MOVZX EAX ,CYL}/
- _asm{MOVZX EDX ,HEA}/
- _asm{MOVZX ECX ,SEC}/
- _asm{MOV CH,AL}/
- _asm{ROR AH,1}/
- _asm{ROR AH,1}/
- _asm{OR CL,AH}/
- _asm{MOV DH,DL}/
- _asm{MOV DL,DISK} /
- _asm{MOV HEA,CX}/
- _asm{MOV SEC,DX} /
- #pragma pack(1)
- typedef struct _tagDiskAddressPacket
- {
- BYTE PacketSize; // Packet Length(16bytes)
- BYTE Reserved; // ==0
- WORD BlockCount; // Transfer block count(Sector)
- DWORD BufferAddr; // Transfer buffer pointer(segment:offset)
- QWORD BlockNum; // Position To Start.
- }DISKADDRESSPACKETI13E;
- typedef struct _tagDriveParametersPacket
- {
- WORD InfoSize; // Packet Leggth (26 Bytes)
- WORD Flags; // flag
- DWORD Cylinders; //
- DWORD Heads; //
- DWORD SectorsPerTrack; // Sectors per Track
- QWORD Sectors; // Amout of sectors.
- WORD SectorSize; // Bytes per sector.
- }DRIVEPARAMETERSPACKETI13E;
- #pragma pack()
- int LBAToCHS(ULONG LbaNum,
- USHORT Sectors,
- USHORT Heads,
- PUSHORT pSectorNum,
- PUSHORT pHeadNum,
- PUSHORT pCylinderNum)
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- convert the LBA address to CHS address.
- Arguments:
- LbaNum -- The LBA address.
- Sectors -- Sectors per Track
- Heads -- Amount Heads,you should to use Get DiskParams
- To Get the sectors and heads.
- pSectorNum -- pointer to sector's result
- pHeadNum -- pointer to Head's result
- pCylinderNum -- pointer to Cylinder's result
- Return Value:
- if all thing ok return 1,else return 0.
- **********************
- -------------------------------------------------------*/
- {
- USHORT uSectorNum,uHeadNum,uCylinderNum;
- _asm{
- MOV EAX,LbaNum
- MOVZX EBX,Sectors
- XOR EDX,EDX
- DIV EBX //LbaNum / sectors
- INC EDX //EDX is the remainder,EAX is the quotient
- MOV ECX,EDX
- MOVZX EBX,Heads
- XOR EDX,EDX
- DIV EBX
- MOV uCylinderNum,AX
- MOV uHeadNum,DX
- MOV uSectorNum,CX
- }
- *pSectorNum =uSectorNum;
- *pHeadNum = uHeadNum;
- *pCylinderNum = uCylinderNum;
- return 1;
- }
- int GetHardDiskParamsI13(UCHAR nDiskNumber,PUSHORT pCylinders,PUSHORT pHeads,PUSHORT pSectors)
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- Get the Disk's params which specified by nDiskNumber using bios int 13h.
- Arguments:
- nDiskNumber --Disk ID,0-5 for Fixed hardDisk.
- pCylinders -- pointer for amount of the disk Cylinders.if
- the disk bigger than 8GB(Should be greater the 1024),
- it return only 1024.
- pHeads -- pointer for heads.
- pSectors -- pointer for Sectors.
- Return Value:
- if all thing ok return 1,else return 0.
- **********************
- -------------------------------------------------------*/
- {
- USHORT Cylinders,Heads,Sectors;
- UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
- UCHAR nDisk;
- CLIENT_STRUCT saveregs;
- CLIENT_STRUCT *pClStru;
- struct cb_s * hvm;
- if(nDiskNumber > 5 )
- {
- return 0;
- }
- nDisk = DiskIDs[nDiskNumber];
- GETVM_HANDLE_CLIENTSTRU(hvm,pClStru);
- _SAVE_CLIENT_STATE(saveregs);
- //
- //Fill the client struct.
- //
- pClStru->CBRS.Client_AH = 0x08;
- pClStru->CBRS.Client_DL = nDisk;
- _CALL_INT13_V86_(hvm,pClStru);
- //
- //Save the interest value to AX,DX,CX.
- //
- _asm mov ebx,pClStru
- _asm mov AX,[ebx.Client_Flags]
- _asm mov DX,[ebx.Client_DX]
- _asm mov CX,[ebx.Client_CX]
- _RESTORE_CLIENT_STATE(saveregs);
- //
- //Now Get the proper params from DX,CX
- //
- _asm{
- test AX,1
- jnz loc_error
- MOV AL,DH //
- XOR AH,AH
- INC AX
- MOV Heads,AX // save head count
- MOV AL,CL // put sector number in AL
- AND AX,3FH // and mask off cylinder bits
- MOV Sectors,AX // save sector count
- MOV AL,CH // AL = cylinder LO
- MOV AH,CL // AH = cylinder HI...
- MOV CL,6
- SHR AH,CL // shift the HI bits down
- INC AX
- MOV Cylinders,AX // save cylinder count
- jmp loc_success
- }
- loc_error:
- return 0;
- loc_success:
- *pCylinders = Cylinders;
- *pHeads = Heads;
- *pSectors = Sectors;
- return 1;
- }
- int absDiskReadI13(
- UCHAR nDiskNumber, //0~5;
- USHORT nCylinders,
- USHORT nHeads, //
- USHORT nSectors, // sector position
- USHORT wSectors, //How many To read
- void* pBuffer) //pointer to the buffer.
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- Read the Disk which specified by nDiskNumber using bios int 13h.
- Arguments:
- nDiskNumber -- Disk ID,0-5 for Fixed hardDisk.
- nCylinders -- Starting Position's Cylinders .it should not be greater than 1024.
- nHeads -- Starting Position's heads.
- nSectors -- Starting Position's Sectors.
- wSector -- How many sector to read.
- pBuffer -- Buffer for receive the result of reading.
- Return Value:
- if all thing ok return 1,else return 0.
- **********************
- -------------------------------------------------------*/
- {
- UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
- UCHAR nDisk;
- CLIENT_STRUCT saveregs;
- CLIENT_STRUCT *pClStru;
- struct cb_s * hvm;
- WORD nsegsel,noffset;
- DWORD FarPtrBuffer = 0;
- DWORD dwBytesCopied = 0;
- DWORD dwAssumBuffLen = 0;
- DWORD vmpnum = 0x10;
- DWORD retu = 1;
- if(nDiskNumber > 5 || wSectors == 0 )
- {
- return 0;
- }
- dwAssumBuffLen = 512 * wSectors;
- nDisk = DiskIDs[nDiskNumber];
- hvm = (struct cb_s *)Get_Cur_VM_Handle();
- pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
- _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(hvm,pClStru,dwAssumBuffLen,
- dwBytesCopied,FarPtrBuffer);
- _asm jc Loc_ret_Failed ;
- _SAVE_CLIENT_STATE(saveregs);
- //
- //Fill Int13 entries..
- //
- nsegsel = HIWORD(FarPtrBuffer);
- noffset = LOWORD(FarPtrBuffer);
- MAKE_INT13CHSD_IN_HS(nCylinders,nHeads,nSectors,nDisk);
- pClStru->CWRS.Client_CX = nHeads;
- pClStru->CWRS.Client_DX = nSectors;
- pClStru->CBRS.Client_AH = 0x02; //To Read
- pClStru->CBRS.Client_AL = (UCHAR)wSectors;//How many to read.
- pClStru->CRS.Client_ES = nsegsel;
- pClStru->CWRS.Client_BX = noffset;
- _CALL_INT13_V86_(hvm,pClStru)
- _asm{
- mov ebx,pClStru
- mov ax,[ebx.Client_Flags]
- _asm mov retu ,eax
- }
- _RESTORE_CLIENT_STATE(saveregs)
- _MICRO_V86MMGR_FREE_BUFFER_COPIED(hvm,pClStru,pBuffer,dwBytesCopied);
- if(!(retu&1))
- {
- return 1;
- }
- Loc_ret_Failed:
- return 0;
- }
- int absDiskWriteI13(
- UCHAR nDiskNumber, //0~5;
- USHORT nCylinders,
- USHORT nHeads, //
- USHORT nSectors, //Where to start.
- USHORT wSectors, //How many To read
- void* pBuffer) //
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- Write the Disk which specified by nDiskNumber using bios int 13h.
- Arguments:
- nDiskNumber -- Disk ID,0-5 for Fixed hardDisk.
- nCylinders -- Starting Position's Cylinders .it should not be greater than 1024.
- nHeads -- Starting Position's heads.
- nSectors -- Starting Position's Sectors.
- wSector -- How many sector to Write.
- pBuffer -- Buffer for the content of writing.
- Return Value:
- if all thing ok return 1,else return 0.
- **********************
- -------------------------------------------------------*/
- {
- UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
- UCHAR nDisk;
- CLIENT_STRUCT saveregs;
- CLIENT_STRUCT *pClStru;
- struct cb_s * hvm;
- WORD nsegsel,noffset;
- DWORD FarPtrBuffer = 0;
- DWORD dwBytesCopied = 0;
- DWORD dwAssumBuffLen = 0;
- DWORD vmpnum = 0x10;
- DWORD retu = 1;
- if(nDiskNumber > 5 || wSectors == 0 )
- {
- return 0;
- }
- dwAssumBuffLen = 512 * wSectors;
- nDisk = DiskIDs[nDiskNumber];
- hvm = (struct cb_s *)Get_Cur_VM_Handle();
- pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
- _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,pClStru,pBuffer,dwAssumBuffLen,
- dwBytesCopied,FarPtrBuffer);
- _asm jc Loc_ret_Failed ;
- _SAVE_CLIENT_STATE(saveregs);
- //
- //Fill Int13 entries..
- //
- nsegsel = HIWORD(FarPtrBuffer);
- noffset = LOWORD(FarPtrBuffer);
- MAKE_INT13CHSD_IN_HS(nCylinders,nHeads,nSectors,nDisk);
- pClStru->CWRS.Client_CX = nHeads;
- pClStru->CWRS.Client_DX = nSectors;
- pClStru->CBRS.Client_AH = 0x03; //To Write
- pClStru->CBRS.Client_AL = (UCHAR)wSectors;//How many to read.
- pClStru->CRS.Client_ES = nsegsel;
- pClStru->CWRS.Client_BX = noffset;
- _CALL_INT13_V86_(hvm,pClStru)
- _asm{
- mov ebx,pClStru
- mov ax,[ebx.Client_Flags]
- _asm mov retu ,eax
- }
- _RESTORE_CLIENT_STATE(saveregs)
- _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,dwBytesCopied);
- if(!(retu&1))
- {
- return 1;
- }
- Loc_ret_Failed:
- return 0;
- }
- int IsInt13ExtentHere(
- UCHAR nDiskNumber //0~5;
- )
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- Check if the Disk which specified by nDiskNumber support int 13h extent,
- using bios int 13h.
- Arguments:
- nDiskNumber -- 0~5.
- Return Value:
- if Int 13h exsist return 1,else return 0.
- **********************
- -------------------------------------------------------*/
- {
- UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
- UCHAR nDisk;
- CLIENT_STRUCT saveregs;
- CLIENT_STRUCT *pClStru;
- struct cb_s * hvm;
- if(nDiskNumber > 5 )
- {
- return 0;
- }
- nDisk = DiskIDs[nDiskNumber];
- hvm = (struct cb_s *)Get_Cur_VM_Handle();
- pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
- _SAVE_CLIENT_STATE(saveregs)
- pClStru->CBRS.Client_AH = 0x41;
- pClStru->CWRS.Client_BX = 0x55AA;
- pClStru->CBRS.Client_DL = nDisk;
- _CALL_INT13_V86_(hvm,pClStru)
- _asm{
- mov edx,pClStru;
- mov ax,[edx.Client_Flags]
- mov bx,[edx.Client_BX]
- mov cx,[edx.Client_CX]
- }
- _RESTORE_CLIENT_STATE(saveregs)
- _asm
- {
- test ax,1
- jnz loc_error
- xor BX,0xAA55
- JNZ loc_error
- test cx,1
- jnz loc_i13EHere
- }
- loc_error:
- return 0;
- loc_i13EHere:
- return 1;
- }
- int absDiskReadI13Ex(
- UCHAR nDiskNumber, //0~5;
- DISKADDRESSPACKETI13E *pAddressPacket
- )
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- Read the Disk which specified by nDiskNumber using
- bios int 13h extent function 42h.
- Arguments:
- nDiskNumber -- Disk ID,0-5 for Fixed hardDisk.
- pAddressPacket -- pointer for DISKADDRESSPACKETI13E.
- Return Value:
- if all thing ok return 1,else return 0.
- **********************
- -------------------------------------------------------*/
- {
- UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
- CLIENT_STRUCT saveregs;
- CLIENT_STRUCT *pClStru;
- struct cb_s * hvm;
- DWORD PacketFarPtrBuffer = 0;
- DWORD SizeOfAddrPacket = 0;
- DWORD PacketBuffAllocateNum = 0;
- DWORD DataFarPtrBuffer = 0;
- DWORD DataBuffAllocateNum = 0;
- DWORD dwAssumBuffLen = 0;
- DWORD pDataBuffer = 0;
- int retcode = 1;
- if(nDiskNumber > 5 )
- {
- return 0;
- }
- UCHAR nDisk = DiskIDs[nDiskNumber];
- dwAssumBuffLen = 512 * (pAddressPacket->BlockCount);
- SizeOfAddrPacket =sizeof(DISKADDRESSPACKETI13E);
- //
- //Save the procted mode address.
- //
- pDataBuffer = pAddressPacket->BufferAddr;
- hvm = (struct cb_s *)Get_Cur_VM_Handle();
- pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
- //
- //Allocated the FarBuffer which below 1MB for data
- //
- _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(hvm,
- pClStru,
- dwAssumBuffLen, //<--number of bytes to allocate.
- DataBuffAllocateNum,//<--Allocate
- DataFarPtrBuffer);
- _asm jc Loc_DataAddr_Failed;
- pAddressPacket->BufferAddr = DataFarPtrBuffer;
- //
- //Allocated the FarBuffer which below 1MB for addressPacket,
- //and Copy the data to it.
- //
- _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
- pClStru,
- pAddressPacket,
- SizeOfAddrPacket,
- PacketBuffAllocateNum,
- PacketFarPtrBuffer);
- _asm jc Loc_PackAddr_Failed ;
- _SAVE_CLIENT_STATE(saveregs)
- //
- //fill int ext entries.
- //
- pClStru->CBRS.Client_AH = 0x42 ;
- pClStru->CBRS.Client_DL = nDisk;
- pClStru->CRS.Client_DS = HIWORD(PacketFarPtrBuffer);
- pClStru->CWRS.Client_SI = LOWORD(PacketFarPtrBuffer);
- _CALL_INT13_V86_(hvm,pClStru)
- retcode = pClStru->CWRS.Client_Flags;
- _RESTORE_CLIENT_STATE(saveregs)
- //
- //Free the Packet FarBuffer;
- //The buffers are maintained as a stack.
- //Therefore, the last buffer allocated must
- //be the first buffer freed.
- //
- _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,PacketBuffAllocateNum);
- //
- //Restore the procted mode address.
- //
- pAddressPacket->BufferAddr = pDataBuffer;
- //
- //Free and copy back the data FarBuffer.
- //
- _MICRO_V86MMGR_FREE_BUFFER_COPIED(hvm,pClStru,
- pDataBuffer,DataBuffAllocateNum);
- return !(retcode &1);
- Loc_DataAddr_Failed:
- return 0;
- Loc_PackAddr_Failed:
- _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataFarPtrBuffer);
- return 0;
- }
- int absDiskWriteI13Ex(
- UCHAR nDiskNumber, //0~5;
- DISKADDRESSPACKETI13E *pAddressPacket
- )
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Routine Description:
- Write the Disk which specified by nDiskNumber using
- bios int 13h extent function 43h.
- Arguments:
- nDiskNumber -- Disk ID,0-5 for Fixed hardDisk.
- pAddressPacket -- pointer for DISKADDRESSPACKETI13E.
- Return Value:
- if all thing ok return 1,else return 0.
- **********************
- -------------------------------------------------------*/
- {
- UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
- CLIENT_STRUCT saveregs;
- CLIENT_STRUCT *pClStru;
- struct cb_s * hvm;
- DWORD PacketFarPtrBuffer = 0;
- DWORD SizeOfAddrPacket = 0;
- DWORD PacketBuffAllocateNum = 0;
- DWORD DataFarPtrBuffer = 0;
- DWORD DataBuffAllocateNum = 0;
- DWORD dwAssumBuffLen = 0;
- DWORD pDataBuffer = 0;
- int retcode = 1;
- if(nDiskNumber > 5 )
- {
- return 0;
- }
- UCHAR nDisk = DiskIDs[nDiskNumber];
- dwAssumBuffLen = 512 * (pAddressPacket->BlockCount);
- SizeOfAddrPacket =sizeof(DISKADDRESSPACKETI13E);
- //
- //Save the procted mode address.
- //
- pDataBuffer = pAddressPacket->BufferAddr;
- hvm = (struct cb_s *)Get_Cur_VM_Handle();
- pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
- //
- //Allocated the FarBuffer which below 1MB for data
- //
- _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
- pClStru,
- pDataBuffer,
- dwAssumBuffLen, //<--number of bytes to allocate.
- DataBuffAllocateNum,//<--Allocate
- DataFarPtrBuffer);
- _asm jc Loc_DataAddr_Failed;
- pAddressPacket->BufferAddr = DataFarPtrBuffer;
- //
- //Allocated the FarBuffer for addressPacket,
- //and Copy the data to it.
- //
- _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
- pClStru,
- pAddressPacket,
- SizeOfAddrPacket,
- PacketBuffAllocateNum,
- PacketFarPtrBuffer);
- _asm jc Loc_PackAddr_Failed ;
- _SAVE_CLIENT_STATE(saveregs)
- //
- //fill int ext entries.
- //
- pClStru->CBRS.Client_AH = 0x43; //Extent Write.
- pClStru->CBRS.Client_AL = 0 ; //don't verify write.
- pClStru->CBRS.Client_DL = nDisk;
- pClStru->CRS.Client_DS = HIWORD(PacketFarPtrBuffer);
- pClStru->CWRS.Client_SI = LOWORD(PacketFarPtrBuffer);
- _CALL_INT13_V86_(hvm,pClStru)
- retcode = pClStru->CWRS.Client_Flags;
- _RESTORE_CLIENT_STATE(saveregs)
- //
- //Free the Packet FarBuffer;
- //The buffers are maintained as a stack.
- //Therefore, the last buffer allocated must
- //be the first buffer freed.
- //
- _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,PacketBuffAllocateNum);
- //
- //Restore the procted mode address.
- //
- pAddressPacket->BufferAddr = pDataBuffer;
- //
- //Free and copy back the data FarBuffer.
- //
- _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataBuffAllocateNum);
- return !(retcode &1);
- Loc_DataAddr_Failed:
- return 0;
- Loc_PackAddr_Failed:
- _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataFarPtrBuffer);
- return 0;
- }
- //直接端口读写的方式来访问硬盘扇区
- //
- // Commented codes Below that were use to Read write the harddisk with direct i/o,
- //Because It highly depend the hardware with the high risk of failure.
- //
- UCHAR inportb(USHORT ports)
- {
- return READ_PORT_UCHAR((PUCHAR)ports);
- }
- VOID outportb(USHORT ports,UCHAR cchar)
- {
- WRITE_PORT_UCHAR((PUCHAR)ports,cchar);
- }
- #define WAIT_WHILE_BUSY /
- for(i=0;i<WAITING_TIMES;i++) {/
- rt = inportb((USHORT)(BasePort+7));/
- if((rt&cDriveBusy)==0)/
- break; /
- } /
- if(i>=WAITING_TIMES) return FALSE/
- #define WAIT_WHILE_BUSY_NOTREADY /
- for(i=0;i<WAITING_TIMES;i++) {/
- rt = inportb((USHORT)(BasePort+7));/
- if(rt & cDriveERR) return FALSE;/
- if((rt&cDriveBusy)==0 && (rt&cDriveReady)) break; /
- } /
- if(i>=WAITING_TIMES) return FALSE/
- ULONG IOReadHardDisk(PUSHORT params,USHORT idePorts,PLBASECTORSTRU psecNum)
- {
- int i;
- USHORT BasePort = idePorts;
- UCHAR SectorCount = 1;
- UCHAR SectorNum = psecNum->LBA0_7;
- UCHAR cylinderLow = psecNum->LBA8_15;
- UCHAR cylinderHi = psecNum->LBA16_23;
- UCHAR hd_devSel = psecNum->LBA24_27;
- UCHAR rt = inportb((USHORT)(BasePort+7));
- if(rt == 0xff || rt == 0x7f)
- {
- return FALSE; //when the ide port not exsist;
- }
- WAIT_WHILE_BUSY;
- outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
- WAIT_WHILE_BUSY;
- if(rt&cDriveERR)
- {
- return FALSE;
- }
- outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
- WAIT_WHILE_BUSY;
- if(inportb((USHORT)(BasePort+7))!=0x50)
- return FALSE;//HDD ready: 0101 0000
- outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
- outportb((USHORT)(BasePort+2), SectorCount); //读一个扇区
- outportb((USHORT)(BasePort+3), SectorNum); //扇区号为1
- outportb((USHORT)(BasePort+4), cylinderLow); //要读写的柱面的低8位
- outportb((USHORT)(BasePort+5), cylinderHi); //用来存放读写柱面的高2位字节(其高6位恒为0)
- outportb((USHORT)(BasePort+7), 0x20); //读硬盘
- for(i=0;i<WAITING_TIMES;i++) //Get HDD Status, wait until HDD not busy
- {
- if(inportb((USHORT)(BasePort+7))==0x58) //retrieved OK
- break;
- }
- if(i>=WAITING_TIMES)
- return FALSE;
- _asm cli;
- READ_PORT_BUFFER_USHORT((PUSHORT)BasePort,(PUSHORT)params,256);
- _asm sti;
- return TRUE;
- }
- ULONG IOWriteHardDisk(PUSHORT params,USHORT idePorts,PLBASECTORSTRU psecNum)
- {
- int i;
- USHORT BasePort = idePorts;
- UCHAR SectorCount = 1;
- UCHAR SectorNum = psecNum->LBA0_7;
- UCHAR cylinderLow = psecNum->LBA8_15;
- UCHAR cylinderHi = psecNum->LBA16_23;
- UCHAR hd_devSel = psecNum->LBA24_27;
- UCHAR rt = inportb((USHORT)(BasePort+7));
- if(rt == 0xff || rt == 0x7f)
- {
- return FALSE; //when the ide port not exsist;
- }
- WAIT_WHILE_BUSY;
- outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
- WAIT_WHILE_BUSY_NOTREADY;
- if(inportb((USHORT)(BasePort+7))!=0x50) return FALSE;//HDD ready: 0101 0000
- outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
- outportb((USHORT)(BasePort+2), SectorCount); //读一个扇区
- outportb((USHORT)(BasePort+3), SectorNum); //扇区号为1
- outportb((USHORT)(BasePort+4), cylinderLow); //要读写的柱面的低8位
- outportb((USHORT)(BasePort+5), cylinderHi); //用来存放读写柱面的高2位字节(其高6位恒为0)
- outportb((USHORT)(BasePort+7), 0x30); //写硬盘
- for(i=0;i<WAITING_TIMES;i++) //Get HDD Status, wait until HDD not busy
- {
- if(inportb((USHORT)(BasePort+7))==0x58) //retrieved OK
- break;
- }
- if(i>=WAITING_TIMES)
- return FALSE;
- _asm cli;
- WRITE_PORT_BUFFER_USHORT((PUSHORT)BasePort,(PUSHORT)params,256);
- _asm sti;
- return TRUE;
- }