← 返回目录

回顾 WINDOWS98 NEST V8086模式和中断服务调用

发布时间: 2008-12-31 00:30:00
浏览量: 9048
标签: windows, buffer, struct, 磁盘, ios, system
新的一年到了,不禁回头望了一下,写些老掉牙的东西以作纪念。早在2004年,我当时正在写个wdm的驱动程序,因为软件的版本允许在windows 98, windows NT 4.0 , windows 2000和windows XP上运行,我不想每个写了一个wdm后,再实现一个相同功能的Vxd,在当时我的想法里,这是不利行维护,是不明智的行为,于是我决定让我的WDM程序可以在上面所说的所有win

新的一年到了,不禁回头望了一下,写些老掉牙的东西以作纪念。

早在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 保护模式两种模式下交换数据。

呵呵,当初有趣的尝试,带来了不少的乐趣和新知识。

以下附录一些代码:

  1. //WINDOWS nt/2000使用IRP的IoCallDriver来访问硬盘
  2. //
  3.  // Initialize unicode string
  4.     //
  5.     RtlInitUnicodeString(&uszDeviceName, L"//DosDevices//PhysicalDrive0");
  6.     ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  7.     // Get a pointer to PhysicalDrive0
  8.     //
  9.     ntStatus = IoGetDeviceObjectPointer(&uszDeviceName,
  10.                                         FILE_ANY_ACCESS,
  11.                                         &fileObject,
  12.                                         &pDriveDeviceObject);
  13.     // If the device object pointer is valid...
  14.     //
  15.     if(NT_SUCCESS(ntStatus))
  16.     {
  17.         IO_STATUS_BLOCK    ioStatus; 
  18.         KEVENT             event; 
  19.         PIRP               pIrp;
  20.                    
  21.         KeInitializeEvent(event, NotificationEvent, FALSE); 
  22.             
  23.         pIrp = IoBuildSynchronousFsdRequest(bRead?IRP_MJ_READ:IRP_MJ_WRITE,
  24.                                             pDriveDeviceObject,
  25.                                             pBuffer,
  26.                                             512,
  27.                                             &llSectorNum,
  28.                                             event,
  29.                                             &ioStatus);
  30.         if(!pIrp)
  31.         {
  32.            ObDereferenceObject(fileObject);
  33.            return STATUS_BAD_STACK; 
  34.         }
  35.         ntStatus = IoCallDriver(pDriveDeviceObject, pIrp);
  36.         if(ntStatus == STATUS_PENDING)
  37.         {
  38.             KeWaitForSingleObject(event, Suspended, KernelMode, FALSE, NULL);
  39.             ntStatus = ioStatus.Status;
  40.         } 
  41.             
  42.         // Ditch the fileObject pointer created earlier
  43.         //
  44.         ObDereferenceObject(fileObject);
  45.     }
  46. //WINDOWS98使用ios_sendCommand来访问硬盘
  47. //
  48. #include "ior.h"
  49. int TestIos_SendCmd(void * pbuffer)
  50. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  51.     Routine Description:
  52.         Just a testing for Ios_SendCommand,I try to pass the
  53.     request to ios.sys.
  54.     Arguments:
  55.         pbuffer -- a buffer.        
  56.     Return Value:
  57.         
  58.         if all thing ok return 1,else return 0.
  59. -------------------------------------------------------*/
  60. {
  61.     IOR iorStru;
  62.     UCHAR nDisk = 0x80;
  63.     
  64. readBein:
  65.     memset(&iorStru,0,sizeof(iorStru));
  66.     iorStru.IOR_func  =IOR_READ; 
  67.     iorStru.IOR_flags  =IORF_PHYS_CMD|IORF_VERSION_002|IORF_SYNC_COMMAND|IORF_HIGH_PRIORITY|IORF_WIN32;
  68.     iorStru.IOR_start_addr[0]=0;    //start position los
  69.     iorStru.IOR_start_addr[1]=0;    //start position high
  70.     iorStru.IOR_xfer_count = 1;     //num of sector to read.
  71.     iorStru.IOR_buffer_ptr = (ULONG)pbuffer; //Address of the buffer
  72.     iorStru.IOR_vol_designtr = nDisk;   //disknum.
  73.     _asm {
  74.         push esi;
  75.         lea esi,iorStru
  76.         _asm _emit 0xcd 
  77.         _asm _emit 0x20 
  78.         _asm _emit (0x00100004 & 0xff) 
  79.         _asm _emit (0x00100004) >> 8 & 0xff 
  80.         _asm _emit (0x00100004) >> 16 & 0xff 
  81.         _asm _emit (0x00100004) >> 24 & 0xff    //Ios_SendCommand
  82.         pop esi;
  83.     }
  84.     if(iorStru.IOR_status == 0x17)
  85.     {
  86.         if(nDisk == 0x80)
  87.         {
  88.             nDisk = 0x81;
  89.             goto readBein;
  90.         }
  91.         else if (nDisk == 0x81)
  92.         {
  93.             nDisk = 0x2;
  94.             goto readBein;
  95.         }
  96.     }
  97.     else
  98.         return 1;
  99. }
  100. //使用BIOS INT 13扩展功能来访问硬盘
  101. //
  102. //
  103. /**
  104.         purpose:    define Some Useful defines and structure for using int 13h
  105.       here's the v86mgr real data.
  106.  */
  107. FFFFFFFF    V86MMGR
  108. 00060000    V86MMGR_Get_Version
  109. 00060001    V86MMGR_Allocate_V86_Pages
  110. 00060002    V86MMGR_Set_EMS_XMS_Limits
  111. 00060003    V86MMGR_Get_EMS_XMS_Limits
  112. 00060004    V86MMGR_Set_Mapping_Info
  113. 00060005    V86MMGR_Get_Mapping_Info
  114. 00060006    V86MMGR_Xlat_API
  115. 00060007    V86MMGR_Load_Client_Ptr
  116. 00060008    V86MMGR_Allocate_Buffer
  117. 00060009    V86MMGR_Free_Buffer
  118. 0006000A    V86MMGR_Get_Xlat_Buff_State
  119. 0006000B    V86MMGR_Set_Xlat_Buff_State
  120. 0006000C    V86MMGR_Get_VM_Flat_Sel
  121. 0006000D    V86MMGR_Map_Pages
  122. 0006000E    V86MMGR_Free_Page_Map_Region
  123. 0006000F    V86MMGR_LocalGlobalReg
  124. 00060010    V86MMGR_GetPgStatus
  125. 00060011    V86MMGR_SetLocalA20
  126. 00060012    V86MMGR_ResetBasePages
  127. 00060013    V86MMGR_SetAvailMapPgs
  128. 00060014    V86MMGR_NoUMBInitCalls
  129. 00060015    V86MMGR_Get_EMS_XMS_Avail
  130. 00060016    V86MMGR_Toggle_HMA
  131. 00060017    V86MMGR_Dev_Init
  132. 00060018    V86MMGR_Alloc_UM_Page
  133.  */
  134. #define  _VMMCALL_V86MMGR_Allocate_Buffer   _asm _emit 0xcd /
  135.     _asm _emit 0x20 /
  136.     _asm _emit (0x00060008 & 0xff) /
  137.     _asm _emit (0x00060008 >> 8) & 0xff /
  138.     _asm _emit (0x00060008 >> 16) & 0xff /
  139.     _asm _emit (0x00060008 >> 24) & 0xff /
  140. #define  _VMMCALL_V86MMGR_Free_Buffer  _asm _emit 0xcd /
  141.     _asm _emit 0x20 /
  142.     _asm _emit (0x00060009 & 0xff) /
  143.     _asm _emit (0x00060009  >> 8) & 0xff /
  144.     _asm _emit (0x00060009  >> 16) & 0xff /
  145.     _asm _emit (0x00060009  >> 24) & 0xff /
  146. #define _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(VMHANDLE,PCLIENTSTRU,LPBUFFER,CONST_NUM,NUMCOPIED,FPTR)   /
  147.     _asm{mov ebx,VMHANDLE} /
  148.     _asm{push   esi} /
  149.     _asm{mov    esi,LPBUFFER} /
  150.     _asm{mov    ecx,CONST_NUM} /
  151.     _asm{push   ebp } /
  152.     _asm{mov    ebp,PCLIENTSTRU} /
  153.     _asm{STC    } /
  154.     _asm{push   ds} /
  155.     _asm{pop    fs} /
  156.     {_VMMCALL_V86MMGR_Allocate_Buffer} /
  157.     _asm{pop ebp} /
  158.     _asm{pop esi} /
  159.     _asm{mov NUMCOPIED,ECX} /
  160.     _asm{mov FPTR,EDI} /
  161. #define _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(VMHANDLE,PCLIENTSTRU,CONST_NUM,NUMALLOCATED,FPTR)  /
  162.     _asm{mov    ebx,VMHANDLE} /
  163.     _asm{mov    ecx,CONST_NUM} /
  164.     _asm{push   ebp } /
  165.     _asm{mov    ebp,PCLIENTSTRU} /
  166.     _asm{CLC    } /
  167.     {_VMMCALL_V86MMGR_Allocate_Buffer} /
  168.     _asm{pop ebp} /
  169.     _asm{mov NUMALLOCATED,ECX} /
  170.     _asm{mov FPTR,EDI} /
  171. #define _MICRO_V86MMGR_FREE_BUFFER_COPIED(VMHANDLE,PCLIENTSTRU,LPBUFFER,NUMCOPIED)  /
  172.     _asm{mov  ebx, VMHANDLE} /
  173.     _asm{push   esi} /
  174.     _asm{mov    esi, LPBUFFER} /
  175.     _asm{mov    ecx, NUMCOPIED} /
  176.     _asm{push   ebp} /
  177.     _asm{mov    ebp, PCLIENTSTRU} /
  178.     _asm{push   ds} /
  179.     _asm{pop    fs} /
  180.     _asm{stc    } /
  181.     {_VMMCALL_V86MMGR_Free_Buffer} /
  182.     _asm{pop    ebp} /
  183.     _asm{pop    esi} /
  184. #define _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(VMHANDLE,PCLIENTSTRU,NUMCOPIED)    /
  185.     _asm{mov    ebx, VMHANDLE} /
  186.     _asm{mov    ecx, NUMCOPIED} /
  187.     _asm{push   ebp} /
  188.     _asm{mov    ebp, PCLIENTSTRU} /
  189.     _asm{CLC    } /
  190.     {_VMMCALL_V86MMGR_Free_Buffer} /
  191.     _asm{pop    ebp} /
  192.     
  193. #define _SAVE_CLIENT_STATE(SAVEREGS)  /
  194.     _asm{push edi}/
  195.     _asm{lea edi,SAVEREGS} /
  196.     VMMCall(Save_Client_State) /
  197.     _asm{pop edi}
  198. #define _RESTORE_CLIENT_STATE(SAVEREGS) /
  199.     _asm push esi /
  200.     _asm lea esi,SAVEREGS /
  201.     VMMCall(Restore_Client_State) /
  202.     _asm pop esi /
  203. #define _CALL_INT13_V86_(VMHANDLE,PCLIENTSTRU) /
  204.     _asm{mov ebx,VMHANDLE}/
  205.     _asm{push ebp}/
  206.     _asm{mov ebp,PCLIENTSTRU} /
  207.     VMMCall(Begin_Nest_V86_Exec) /
  208.     _asm{mov eax,13h} /
  209.     {VMMCall(Exec_Int)} /
  210.     End_Nest_Exec();/
  211.     _asm{pop ebp}/
  212. #define GETVM_HANDLE_CLIENTSTRU(VMHANDLE,PCLIENTSTRU) /
  213.     VMHANDLE = (struct cb_s *)Get_Cur_VM_Handle();/
  214.     _asm{mov ebx,VMHANDLE} /
  215.     PCLIENTSTRU = (CLIENT_STRUCT *)VMHANDLE->CB_Client_Pointer;/
  216. //
  217. //The next few lines, will map the values into
  218. //the registers as need by INT13
  219. //
  220. #define  MAKE_INT13CHSD_IN_HS(CYL,HEA,SEC,DISK) /
  221.     _asm{MOVZX EAX ,CYL}/
  222.     _asm{MOVZX EDX ,HEA}/
  223.     _asm{MOVZX ECX ,SEC}/
  224.     _asm{MOV   CH,AL}/
  225.     _asm{ROR   AH,1}/
  226.     _asm{ROR   AH,1}/
  227.     _asm{OR    CL,AH}/
  228.     _asm{MOV   DH,DL}/
  229.     _asm{MOV   DL,DISK} /
  230.     _asm{MOV   HEA,CX}/
  231.     _asm{MOV   SEC,DX} /
  232. #pragma pack(1)
  233. typedef struct _tagDiskAddressPacket 
  234. { 
  235.     BYTE PacketSize;     // Packet Length(16bytes) 
  236.     BYTE Reserved;       // ==0 
  237.     WORD BlockCount;     // Transfer block count(Sector) 
  238.     DWORD BufferAddr;    // Transfer buffer pointer(segment:offset) 
  239.     QWORD BlockNum;      // Position To Start.
  240. }DISKADDRESSPACKETI13E; 
  241. typedef struct _tagDriveParametersPacket
  242. { 
  243.     WORD  InfoSize;         // Packet Leggth (26 Bytes) 
  244.     WORD  Flags;            // flag
  245.     DWORD Cylinders;        // 
  246.     DWORD Heads;            // 
  247.     DWORD SectorsPerTrack;  // Sectors per Track
  248.     QWORD Sectors;          // Amout of sectors.
  249.     WORD  SectorSize;       // Bytes per sector.
  250. }DRIVEPARAMETERSPACKETI13E; 
  251. #pragma pack()
  252. int LBAToCHS(ULONG LbaNum,
  253.              USHORT Sectors,
  254.              USHORT Heads,
  255.              PUSHORT pSectorNum,
  256.              PUSHORT pHeadNum,
  257.              PUSHORT pCylinderNum)
  258. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  259.     Routine Description:
  260.         convert the LBA address to CHS address.
  261.     Arguments:
  262.         LbaNum  -- The LBA address.
  263.         Sectors -- Sectors per Track 
  264.         Heads   -- Amount Heads,you should to use Get DiskParams
  265.                    To Get the sectors and heads.
  266.         pSectorNum  -- pointer to sector's result
  267.         pHeadNum    -- pointer to Head's result
  268.         pCylinderNum -- pointer to Cylinder's result
  269.     Return Value:
  270.         
  271.         if all thing ok return 1,else return 0.
  272.     **********************
  273.     
  274.     
  275. -------------------------------------------------------*/
  276. {
  277.     USHORT uSectorNum,uHeadNum,uCylinderNum;
  278.     _asm{
  279.         MOV     EAX,LbaNum
  280.         MOVZX   EBX,Sectors     
  281.         XOR     EDX,EDX
  282.         DIV     EBX         //LbaNum / sectors 
  283.         INC     EDX         //EDX is the remainder,EAX is the quotient 
  284.         MOV     ECX,EDX     
  285.         MOVZX   EBX,Heads   
  286.         XOR     EDX,EDX
  287.         DIV     EBX
  288.         MOV uCylinderNum,AX
  289.         MOV uHeadNum,DX
  290.         MOV uSectorNum,CX 
  291.     }
  292.     *pSectorNum =uSectorNum;
  293.     *pHeadNum = uHeadNum;
  294.     *pCylinderNum = uCylinderNum;
  295.     return 1;
  296. }
  297. int GetHardDiskParamsI13(UCHAR nDiskNumber,PUSHORT pCylinders,PUSHORT pHeads,PUSHORT pSectors)
  298. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  299.     Routine Description:
  300.         Get the Disk's params which specified by nDiskNumber using bios int 13h.
  301.     Arguments:
  302.         nDiskNumber --Disk ID,0-5 for   Fixed hardDisk.
  303.         pCylinders -- pointer for amount of the disk Cylinders.if 
  304.                      the disk bigger than 8GB(Should be greater the 1024), 
  305.                      it return only 1024.
  306.         pHeads     --  pointer for heads.
  307.         pSectors   --  pointer for Sectors.
  308.     Return Value:
  309.         
  310.         if all thing ok return 1,else return 0.
  311.     **********************
  312.     
  313.     
  314. -------------------------------------------------------*/
  315. {
  316.     USHORT Cylinders,Heads,Sectors;
  317.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  318.     UCHAR nDisk;
  319.     CLIENT_STRUCT saveregs; 
  320.     CLIENT_STRUCT *pClStru;
  321.     struct cb_s * hvm;
  322.     if(nDiskNumber > 5 )
  323.     {
  324.         return 0;
  325.     }
  326.     nDisk = DiskIDs[nDiskNumber];
  327.     GETVM_HANDLE_CLIENTSTRU(hvm,pClStru);
  328.     _SAVE_CLIENT_STATE(saveregs);
  329.     
  330.     //
  331.     //Fill the client struct.
  332.     //
  333.     pClStru->CBRS.Client_AH  = 0x08;
  334.     pClStru->CBRS.Client_DL  = nDisk;
  335.     _CALL_INT13_V86_(hvm,pClStru);
  336.     //
  337.     //Save the interest value to AX,DX,CX.
  338.     //
  339.     _asm mov ebx,pClStru
  340.     _asm mov AX,[ebx.Client_Flags]
  341.     _asm mov DX,[ebx.Client_DX]
  342.     _asm mov CX,[ebx.Client_CX]
  343.     _RESTORE_CLIENT_STATE(saveregs);
  344.     //
  345.     //Now Get the proper params from DX,CX
  346.     //
  347.     _asm{
  348.         test    AX,1
  349.         jnz    loc_error
  350.         MOV     AL,DH           //
  351.         XOR     AH,AH
  352.         INC     AX
  353.         MOV     Heads,AX        // save head count
  354.         MOV     AL,CL           // put sector number in AL
  355.         AND     AX,3FH          // and mask off cylinder bits
  356.         MOV     Sectors,AX      // save sector count
  357.         MOV     AL,CH           // AL = cylinder LO
  358.         MOV     AH,CL           // AH = cylinder HI...
  359.         MOV     CL,6
  360.         SHR     AH,CL           // shift the HI bits down
  361.         INC     AX
  362.         MOV     Cylinders,AX    // save cylinder count
  363.         jmp loc_success
  364.     }
  365. loc_error:
  366.     return 0;
  367. loc_success:
  368.     *pCylinders = Cylinders;
  369.     *pHeads = Heads;
  370.     *pSectors = Sectors;
  371.     return 1;
  372. }
  373. int absDiskReadI13(
  374. UCHAR nDiskNumber,  //0~5;
  375. USHORT nCylinders,
  376. USHORT nHeads,      // 
  377. USHORT nSectors,    // sector position
  378. USHORT wSectors,    //How many To read
  379. void* pBuffer)      //pointer to the buffer.
  380. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  381.     Routine Description:
  382.         Read the Disk which specified by nDiskNumber using bios int 13h.
  383.     Arguments:
  384.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  385.         nCylinders --  Starting Position's Cylinders .it should not be greater than 1024.
  386.         nHeads     --  Starting Position's heads.
  387.         nSectors   --  Starting Position's Sectors.
  388.         wSector    --  How many sector to read.
  389.         pBuffer    --  Buffer for receive the result of reading.
  390.     Return Value:
  391.         
  392.         if all thing ok return 1,else return 0.
  393.     **********************
  394.     
  395.     
  396. -------------------------------------------------------*/
  397. {
  398.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  399.     UCHAR nDisk;
  400.     CLIENT_STRUCT saveregs; 
  401.     CLIENT_STRUCT *pClStru;
  402.     struct cb_s * hvm;
  403.     WORD  nsegsel,noffset;
  404.     DWORD FarPtrBuffer = 0;
  405.     DWORD dwBytesCopied = 0;
  406.     DWORD dwAssumBuffLen = 0;
  407.     DWORD vmpnum = 0x10;
  408.     DWORD retu = 1;
  409.     if(nDiskNumber > 5 || wSectors == 0  )
  410.     {
  411.         return 0;
  412.     }
  413.     
  414.     dwAssumBuffLen = 512 *  wSectors;
  415.     nDisk =  DiskIDs[nDiskNumber];
  416.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  417.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  418.        
  419.     _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(hvm,pClStru,dwAssumBuffLen,
  420.         dwBytesCopied,FarPtrBuffer);
  421.     _asm jc Loc_ret_Failed ;
  422.     _SAVE_CLIENT_STATE(saveregs);
  423.     //
  424.     //Fill Int13 entries..
  425.     //
  426.     nsegsel = HIWORD(FarPtrBuffer);
  427.     noffset = LOWORD(FarPtrBuffer);
  428.     MAKE_INT13CHSD_IN_HS(nCylinders,nHeads,nSectors,nDisk);
  429.     pClStru->CWRS.Client_CX = nHeads;
  430.     pClStru->CWRS.Client_DX  = nSectors;
  431.     pClStru->CBRS.Client_AH  = 0x02; //To Read 
  432.     pClStru->CBRS.Client_AL = (UCHAR)wSectors;//How many to read.
  433.     pClStru->CRS.Client_ES  = nsegsel;
  434.     pClStru->CWRS.Client_BX = noffset;
  435.     
  436.     _CALL_INT13_V86_(hvm,pClStru)
  437.     
  438.     _asm{
  439.         mov ebx,pClStru
  440.         mov ax,[ebx.Client_Flags]
  441.         _asm mov  retu ,eax
  442.     }
  443.     _RESTORE_CLIENT_STATE(saveregs)
  444.     
  445.     _MICRO_V86MMGR_FREE_BUFFER_COPIED(hvm,pClStru,pBuffer,dwBytesCopied);
  446.     if(!(retu&1))
  447.     {
  448.         return 1;
  449.     }
  450. Loc_ret_Failed:
  451.     return 0;
  452. }
  453. int absDiskWriteI13(
  454. UCHAR nDiskNumber,           //0~5;
  455. USHORT nCylinders,
  456. USHORT nHeads,      // 
  457. USHORT nSectors,    //Where to start.
  458. USHORT wSectors,    //How many To read
  459. void* pBuffer)      // 
  460. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  461.     Routine Description:
  462.         Write the Disk which specified by nDiskNumber using bios int 13h.
  463.     Arguments:
  464.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  465.         nCylinders --  Starting Position's Cylinders .it should not be greater than 1024.
  466.         nHeads     --  Starting Position's heads.
  467.         nSectors   --  Starting Position's Sectors.
  468.         wSector    --  How many sector to Write.
  469.         pBuffer    --  Buffer for the content of writing.
  470.     Return Value:
  471.         
  472.         if all thing ok return 1,else return 0.
  473.     **********************
  474.     
  475.     
  476. -------------------------------------------------------*/
  477. {
  478.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  479.     UCHAR nDisk;
  480.     CLIENT_STRUCT saveregs; 
  481.     CLIENT_STRUCT *pClStru;
  482.     struct cb_s * hvm;
  483.     WORD  nsegsel,noffset;
  484.     DWORD FarPtrBuffer = 0;
  485.     DWORD dwBytesCopied = 0;
  486.     DWORD dwAssumBuffLen = 0;
  487.     DWORD vmpnum = 0x10;
  488.     DWORD retu = 1;
  489.     if(nDiskNumber > 5 || wSectors == 0  )
  490.     {
  491.         return 0;
  492.     }
  493.     
  494.     dwAssumBuffLen = 512 *  wSectors;
  495.     nDisk =  DiskIDs[nDiskNumber];
  496.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  497.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  498.        
  499.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,pClStru,pBuffer,dwAssumBuffLen,
  500.         dwBytesCopied,FarPtrBuffer);
  501.     _asm jc Loc_ret_Failed ;
  502.     _SAVE_CLIENT_STATE(saveregs);
  503.     //
  504.     //Fill Int13 entries..
  505.     //
  506.     nsegsel = HIWORD(FarPtrBuffer);
  507.     noffset = LOWORD(FarPtrBuffer);
  508.     MAKE_INT13CHSD_IN_HS(nCylinders,nHeads,nSectors,nDisk);
  509.     pClStru->CWRS.Client_CX = nHeads;
  510.     pClStru->CWRS.Client_DX  = nSectors;
  511.     pClStru->CBRS.Client_AH  = 0x03; //To Write
  512.     pClStru->CBRS.Client_AL = (UCHAR)wSectors;//How many to read.
  513.     pClStru->CRS.Client_ES  = nsegsel;
  514.     pClStru->CWRS.Client_BX = noffset;
  515.     
  516.     _CALL_INT13_V86_(hvm,pClStru)
  517.     
  518.     _asm{
  519.         mov ebx,pClStru
  520.         mov ax,[ebx.Client_Flags]
  521.         _asm mov  retu ,eax
  522.     }
  523.     _RESTORE_CLIENT_STATE(saveregs)
  524.     
  525.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,dwBytesCopied);
  526.     if(!(retu&1))
  527.     {
  528.         return 1;
  529.     }
  530. Loc_ret_Failed:
  531.     return 0;
  532. }
  533. int IsInt13ExtentHere(
  534.                       UCHAR nDiskNumber          //0~5;
  535.                       )
  536. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  537.     Routine Description:
  538.         Check if the Disk which specified by nDiskNumber support int 13h extent,
  539.         using bios int 13h.
  540.     Arguments:
  541.         nDiskNumber -- 0~5.
  542.     Return Value:
  543.         
  544.         if Int 13h exsist return 1,else return 0.
  545.     **********************
  546.     
  547.     
  548. -------------------------------------------------------*/
  549. {
  550.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  551.     UCHAR nDisk;
  552.     CLIENT_STRUCT saveregs; 
  553.     CLIENT_STRUCT *pClStru;
  554.     struct cb_s * hvm;
  555.     if(nDiskNumber > 5 )
  556.     {
  557.         return 0;
  558.     }
  559.     nDisk = DiskIDs[nDiskNumber];
  560.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  561.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  562.     _SAVE_CLIENT_STATE(saveregs)    
  563.     pClStru->CBRS.Client_AH =  0x41;
  564.     pClStru->CWRS.Client_BX =  0x55AA;
  565.     pClStru->CBRS.Client_DL = nDisk;
  566.     _CALL_INT13_V86_(hvm,pClStru)
  567.     _asm{
  568.         mov edx,pClStru;
  569.         mov ax,[edx.Client_Flags]
  570.         mov bx,[edx.Client_BX]
  571.         mov cx,[edx.Client_CX]
  572.     }
  573.     _RESTORE_CLIENT_STATE(saveregs)
  574.     
  575.     _asm
  576.     {
  577.         test ax,1
  578.         jnz loc_error
  579.         xor BX,0xAA55
  580.         JNZ loc_error
  581.         test cx,1
  582.         jnz loc_i13EHere
  583.     }
  584. loc_error:
  585.     return 0;
  586. loc_i13EHere:
  587.     return 1;
  588. }
  589. int absDiskReadI13Ex(
  590.                       UCHAR nDiskNumber,          //0~5;
  591.                       DISKADDRESSPACKETI13E *pAddressPacket
  592.                       )
  593. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  594.     Routine Description:
  595.         Read the Disk which specified by nDiskNumber using 
  596.     bios int 13h extent function 42h.
  597.     Arguments:
  598.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  599.         pAddressPacket -- pointer for DISKADDRESSPACKETI13E.
  600.     Return Value:
  601.         
  602.         if all thing ok return 1,else return 0.
  603.     **********************
  604.     
  605.     
  606. -------------------------------------------------------*/
  607. {
  608.     
  609.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  610.     CLIENT_STRUCT saveregs; 
  611.     CLIENT_STRUCT *pClStru;
  612.     struct cb_s * hvm;
  613.     DWORD PacketFarPtrBuffer = 0;
  614.     DWORD SizeOfAddrPacket  = 0;
  615.     DWORD PacketBuffAllocateNum = 0;
  616.     DWORD DataFarPtrBuffer = 0;
  617.     DWORD DataBuffAllocateNum = 0;
  618.     DWORD dwAssumBuffLen = 0;
  619.     DWORD pDataBuffer = 0;
  620.     int retcode = 1;
  621.     if(nDiskNumber > 5 )
  622.     {
  623.         return 0;
  624.     }
  625.     UCHAR nDisk = DiskIDs[nDiskNumber];
  626.     dwAssumBuffLen = 512 * (pAddressPacket->BlockCount);
  627.     SizeOfAddrPacket =sizeof(DISKADDRESSPACKETI13E);
  628.     
  629.     //
  630.     //Save the procted mode address.
  631.     //
  632.     pDataBuffer = pAddressPacket->BufferAddr;
  633.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  634.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  635.     
  636.     //
  637.     //Allocated the FarBuffer which below 1MB for data
  638.     //
  639.     _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(hvm,
  640.         pClStru,
  641.         dwAssumBuffLen, //<--number of bytes to allocate.
  642.         DataBuffAllocateNum,//<--Allocate 
  643.         DataFarPtrBuffer);
  644.     _asm jc Loc_DataAddr_Failed;
  645.     pAddressPacket->BufferAddr = DataFarPtrBuffer;
  646.     //
  647.     //Allocated the FarBuffer which below 1MB for addressPacket,
  648.     //and Copy the data to it.
  649.     //
  650.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
  651.         pClStru,
  652.         pAddressPacket,
  653.         SizeOfAddrPacket,
  654.         PacketBuffAllocateNum,
  655.         PacketFarPtrBuffer);
  656.     _asm jc Loc_PackAddr_Failed ;
  657.     
  658.     _SAVE_CLIENT_STATE(saveregs)    
  659.     //
  660.     //fill int ext entries.
  661.     //
  662.     pClStru->CBRS.Client_AH = 0x42 ;
  663.     pClStru->CBRS.Client_DL = nDisk;
  664.     pClStru->CRS.Client_DS = HIWORD(PacketFarPtrBuffer);
  665.     pClStru->CWRS.Client_SI = LOWORD(PacketFarPtrBuffer);
  666.     _CALL_INT13_V86_(hvm,pClStru)
  667.     
  668.     retcode = pClStru->CWRS.Client_Flags;
  669.     
  670.     _RESTORE_CLIENT_STATE(saveregs)
  671.     //
  672.     //Free  the Packet  FarBuffer;
  673.     //The buffers are maintained as a stack. 
  674.     //Therefore, the last buffer allocated must 
  675.     //be the first buffer freed.
  676.     //
  677.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,PacketBuffAllocateNum);
  678.     //
  679.     //Restore the procted mode address.
  680.     //
  681.     pAddressPacket->BufferAddr = pDataBuffer;
  682.     
  683.     //
  684.     //Free and copy back the data FarBuffer.
  685.     //
  686.     _MICRO_V86MMGR_FREE_BUFFER_COPIED(hvm,pClStru,
  687.         pDataBuffer,DataBuffAllocateNum);
  688.     return !(retcode &1);
  689. Loc_DataAddr_Failed:
  690.     return 0;
  691. Loc_PackAddr_Failed:
  692.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataFarPtrBuffer);
  693.     return 0;
  694.     
  695. }
  696. int absDiskWriteI13Ex( 
  697.                       UCHAR nDiskNumber,          //0~5;
  698.                       DISKADDRESSPACKETI13E *pAddressPacket
  699.                       )
  700. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  701.     Routine Description:
  702.         Write the Disk which specified by nDiskNumber using 
  703.     bios int 13h extent function 43h.
  704.     Arguments:
  705.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  706.         pAddressPacket -- pointer for DISKADDRESSPACKETI13E.
  707.     Return Value:
  708.         
  709.         if all thing ok return 1,else return 0.
  710.     **********************
  711.     
  712.     
  713. -------------------------------------------------------*/
  714. {
  715.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  716.     CLIENT_STRUCT saveregs; 
  717.     CLIENT_STRUCT *pClStru;
  718.     struct cb_s * hvm;
  719.     DWORD PacketFarPtrBuffer = 0;
  720.     DWORD SizeOfAddrPacket  = 0;
  721.     DWORD PacketBuffAllocateNum = 0;
  722.     DWORD DataFarPtrBuffer = 0;
  723.     DWORD DataBuffAllocateNum = 0;
  724.     DWORD dwAssumBuffLen = 0;
  725.     DWORD pDataBuffer = 0;
  726.     int retcode = 1;
  727.     if(nDiskNumber > 5 )
  728.     {
  729.         return 0;
  730.     }
  731.     UCHAR nDisk = DiskIDs[nDiskNumber];
  732.     dwAssumBuffLen = 512 * (pAddressPacket->BlockCount);
  733.     SizeOfAddrPacket =sizeof(DISKADDRESSPACKETI13E);
  734.     
  735.     //
  736.     //Save the procted mode address.
  737.     //
  738.     pDataBuffer = pAddressPacket->BufferAddr;
  739.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  740.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  741.     
  742.     //
  743.     //Allocated the FarBuffer which below 1MB for data
  744.     //
  745.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
  746.         pClStru,
  747.         pDataBuffer,
  748.         dwAssumBuffLen, //<--number of bytes to allocate.
  749.         DataBuffAllocateNum,//<--Allocate 
  750.         DataFarPtrBuffer);
  751.     _asm jc Loc_DataAddr_Failed;
  752.     pAddressPacket->BufferAddr = DataFarPtrBuffer;
  753.     //
  754.     //Allocated the FarBuffer for addressPacket,
  755.     //and Copy the data to it.
  756.     //
  757.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
  758.         pClStru,
  759.         pAddressPacket,
  760.         SizeOfAddrPacket,
  761.         PacketBuffAllocateNum,
  762.         PacketFarPtrBuffer);
  763.     _asm jc Loc_PackAddr_Failed ;
  764.     
  765.     _SAVE_CLIENT_STATE(saveregs)    
  766.     //
  767.     //fill int ext entries.
  768.     //
  769.     pClStru->CBRS.Client_AH = 0x43; //Extent Write.
  770.     pClStru->CBRS.Client_AL = 0 ;   //don't verify write.
  771.     pClStru->CBRS.Client_DL = nDisk;
  772.     pClStru->CRS.Client_DS = HIWORD(PacketFarPtrBuffer);
  773.     pClStru->CWRS.Client_SI = LOWORD(PacketFarPtrBuffer);
  774.     _CALL_INT13_V86_(hvm,pClStru)
  775.     
  776.     retcode = pClStru->CWRS.Client_Flags;
  777.     
  778.     _RESTORE_CLIENT_STATE(saveregs)
  779.     //
  780.     //Free  the Packet  FarBuffer;
  781.     //The buffers are maintained as a stack. 
  782.     //Therefore, the last buffer allocated must 
  783.     //be the first buffer freed.
  784.     //
  785.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,PacketBuffAllocateNum);
  786.     //
  787.     //Restore the procted mode address.
  788.     //
  789.     pAddressPacket->BufferAddr = pDataBuffer;
  790.     
  791.     //
  792.     //Free and copy back the data FarBuffer.
  793.     //
  794.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataBuffAllocateNum);
  795.     return !(retcode &1);
  796. Loc_DataAddr_Failed:
  797.     return 0;
  798. Loc_PackAddr_Failed:
  799.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataFarPtrBuffer);
  800.     return 0;
  801.     
  802. }

 

 

  1. //直接端口读写的方式来访问硬盘扇区
  2. //
  3. //       Commented codes Below that were use to Read write the harddisk with direct i/o,
  4. //Because It highly depend the hardware with the high risk of failure.
  5. //
  6. UCHAR inportb(USHORT ports)
  7. {
  8.    return READ_PORT_UCHAR((PUCHAR)ports);
  9. }
  10. VOID outportb(USHORT ports,UCHAR cchar)
  11. {
  12.     WRITE_PORT_UCHAR((PUCHAR)ports,cchar);
  13. }
  14. #define  WAIT_WHILE_BUSY /
  15.     for(i=0;i<WAITING_TIMES;i++) {/
  16.         rt = inportb((USHORT)(BasePort+7));/
  17.         if((rt&cDriveBusy)==0)/
  18.             break; /
  19.     }  /
  20.     if(i>=WAITING_TIMES) return FALSE/
  21. #define  WAIT_WHILE_BUSY_NOTREADY /
  22.     for(i=0;i<WAITING_TIMES;i++) {/
  23.         rt = inportb((USHORT)(BasePort+7));/
  24.         if(rt & cDriveERR) return FALSE;/
  25.         if((rt&cDriveBusy)==0 && (rt&cDriveReady)) break; /
  26.     }  /
  27.     if(i>=WAITING_TIMES) return FALSE/
  28. ULONG  IOReadHardDisk(PUSHORT params,USHORT idePorts,PLBASECTORSTRU  psecNum)
  29. {
  30.     
  31.     int i;
  32.     USHORT BasePort = idePorts;
  33.     UCHAR SectorCount = 1;
  34.     UCHAR SectorNum   = psecNum->LBA0_7;
  35.     UCHAR cylinderLow = psecNum->LBA8_15;
  36.     UCHAR cylinderHi  = psecNum->LBA16_23;
  37.     UCHAR hd_devSel = psecNum->LBA24_27;
  38.     
  39.     UCHAR rt = inportb((USHORT)(BasePort+7));
  40.     if(rt == 0xff || rt == 0x7f)
  41.     {
  42.         return FALSE;   //when the ide port not exsist;
  43.     }
  44.     WAIT_WHILE_BUSY;
  45.     outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
  46.     WAIT_WHILE_BUSY;
  47.     if(rt&cDriveERR)
  48.     {
  49.         return FALSE;
  50.     }
  51.     outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
  52.     WAIT_WHILE_BUSY;
  53.     
  54.     if(inportb((USHORT)(BasePort+7))!=0x50)
  55.         return FALSE;//HDD ready: 0101 0000
  56.     
  57.     outportb((USHORT)(BasePort+6), hd_devSel);          //master or slave hard disk
  58.     outportb((USHORT)(BasePort+2), SectorCount);            //读一个扇区  
  59.     outportb((USHORT)(BasePort+3), SectorNum);          //扇区号为1
  60.     outportb((USHORT)(BasePort+4), cylinderLow);            //要读写的柱面的低8位
  61.     outportb((USHORT)(BasePort+5), cylinderHi);         //用来存放读写柱面的高2位字节(其高6位恒为0)
  62.     outportb((USHORT)(BasePort+7), 0x20);                   //读硬盘
  63.         
  64.     for(i=0;i<WAITING_TIMES;i++) //Get HDD Status, wait until HDD not busy
  65.     {
  66.         if(inportb((USHORT)(BasePort+7))==0x58) //retrieved OK
  67.             break;
  68.     }
  69.     if(i>=WAITING_TIMES)
  70.         return FALSE;
  71.     _asm cli;
  72.     READ_PORT_BUFFER_USHORT((PUSHORT)BasePort,(PUSHORT)params,256);
  73.     _asm sti;
  74.     return TRUE;
  75. }
  76. ULONG IOWriteHardDisk(PUSHORT params,USHORT idePorts,PLBASECTORSTRU  psecNum)
  77. {
  78.     int i;
  79.     USHORT BasePort = idePorts;
  80.     UCHAR SectorCount = 1;
  81.     UCHAR SectorNum   = psecNum->LBA0_7;
  82.     UCHAR cylinderLow = psecNum->LBA8_15;
  83.     UCHAR cylinderHi  = psecNum->LBA16_23;
  84.     UCHAR hd_devSel = psecNum->LBA24_27;
  85.     
  86.     UCHAR rt = inportb((USHORT)(BasePort+7));
  87.     if(rt == 0xff || rt == 0x7f)
  88.     {
  89.         return FALSE;   //when the ide port not exsist;
  90.     }
  91.     WAIT_WHILE_BUSY;
  92.     outportb((USHORT)(BasePort+6), hd_devSel); //master or slave hard disk
  93.     WAIT_WHILE_BUSY_NOTREADY;
  94.     if(inportb((USHORT)(BasePort+7))!=0x50) return FALSE;//HDD ready: 0101 0000
  95.     outportb((USHORT)(BasePort+6), hd_devSel);          //master or slave hard disk
  96.     outportb((USHORT)(BasePort+2), SectorCount);            //读一个扇区  
  97.     outportb((USHORT)(BasePort+3), SectorNum);          //扇区号为1
  98.     outportb((USHORT)(BasePort+4), cylinderLow);            //要读写的柱面的低8位
  99.     outportb((USHORT)(BasePort+5), cylinderHi);         //用来存放读写柱面的高2位字节(其高6位恒为0)
  100.     outportb((USHORT)(BasePort+7), 0x30);                   //写硬盘
  101.     
  102.     for(i=0;i<WAITING_TIMES;i++) //Get HDD Status, wait until HDD not busy
  103.     {
  104.         if(inportb((USHORT)(BasePort+7))==0x58) //retrieved OK
  105.             break;
  106.     }
  107.     if(i>=WAITING_TIMES)
  108.         return FALSE;
  109.     _asm cli;
  110.     WRITE_PORT_BUFFER_USHORT((PUSHORT)BasePort,(PUSHORT)params,256);
  111.     _asm sti;
  112.     return TRUE;
  113. }