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

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

早在2004,我当时正在写个wdm的驱动程序,因为软件的版本允许在windows 98, windows NT 4.0 , windows 2000windows 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的方式向磁盘驱动投递请求。

windows98Ios_SendCommand工作得像windows 2000下的IoCallDriver一样简单优雅,但是不幸的是,程序需要在驱动初始化的也要进行对磁盘的读取,在这个阶段Ios_SendCommand完全不能工作,是因为NTKERN.VXDWDM的驱动在IOS.SYS初始化完成一份硬盘驱动器表之前就初始化了,同时WDM的序动顺序也无法像在WINDOWS2000下面那样多的级别可以指定,而我驱动程序要刚好在系统加载SYSTEM32下面的RING3DLL之前,这样初始化动作才有效(事实上我需要修改那

SYSTEM32目录下的DLL,如果它们一旦给初始化,就无法进行写入的操作了)。而我不想使用直接IO的方式,没有办法,我只能求助于BIOSINT 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.     BYTE PacketSize;     // Packet Length(16bytes) 
  235.     BYTE Reserved;       // ==0 
  236.     WORD BlockCount;     // Transfer block count(Sector) 
  237.     DWORD BufferAddr;    // Transfer buffer pointer(segment:offset) 
  238.     QWORD BlockNum;      // Position To Start.
  239. }DISKADDRESSPACKETI13E; 
  240. typedef struct _tagDriveParametersPacket
  241.     WORD  InfoSize;         // Packet Leggth (26 Bytes) 
  242.     WORD  Flags;            // flag
  243.     DWORD Cylinders;        // 
  244.     DWORD Heads;            // 
  245.     DWORD SectorsPerTrack;  // Sectors per Track
  246.     QWORD Sectors;          // Amout of sectors.
  247.     WORD  SectorSize;       // Bytes per sector.
  248. }DRIVEPARAMETERSPACKETI13E; 
  249. #pragma pack()
  250. int LBAToCHS(ULONG LbaNum,
  251.              USHORT Sectors,
  252.              USHORT Heads,
  253.              PUSHORT pSectorNum,
  254.              PUSHORT pHeadNum,
  255.              PUSHORT pCylinderNum)
  256. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  257.     Routine Description:
  258.         convert the LBA address to CHS address.
  259.     Arguments:
  260.         LbaNum  -- The LBA address.
  261.         Sectors -- Sectors per Track 
  262.         Heads   -- Amount Heads,you should to use Get DiskParams
  263.                    To Get the sectors and heads.
  264.         pSectorNum  -- pointer to sector's result
  265.         pHeadNum    -- pointer to Head's result
  266.         pCylinderNum -- pointer to Cylinder's result
  267.     Return Value:
  268.         
  269.         if all thing ok return 1,else return 0.
  270.     **********************
  271.     
  272.     
  273. -------------------------------------------------------*/
  274. {
  275.     USHORT uSectorNum,uHeadNum,uCylinderNum;
  276.     _asm{
  277.         MOV     EAX,LbaNum
  278.         MOVZX   EBX,Sectors     
  279.         XOR     EDX,EDX
  280.         DIV     EBX         //LbaNum / sectors 
  281.         INC     EDX         //EDX is the remainder,EAX is the quotient 
  282.         MOV     ECX,EDX     
  283.         MOVZX   EBX,Heads   
  284.         XOR     EDX,EDX
  285.         DIV     EBX
  286.         MOV uCylinderNum,AX
  287.         MOV uHeadNum,DX
  288.         MOV uSectorNum,CX 
  289.     }
  290.     *pSectorNum =uSectorNum;
  291.     *pHeadNum = uHeadNum;
  292.     *pCylinderNum = uCylinderNum;
  293.     return 1;
  294. }
  295. int GetHardDiskParamsI13(UCHAR nDiskNumber,PUSHORT pCylinders,PUSHORT pHeads,PUSHORT pSectors)
  296. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  297.     Routine Description:
  298.         Get the Disk's params which specified by nDiskNumber using bios int 13h.
  299.     Arguments:
  300.         nDiskNumber --Disk ID,0-5 for   Fixed hardDisk.
  301.         pCylinders -- pointer for amount of the disk Cylinders.if 
  302.                      the disk bigger than 8GB(Should be greater the 1024), 
  303.                      it return only 1024.
  304.         pHeads     --  pointer for heads.
  305.         pSectors   --  pointer for Sectors.
  306.     Return Value:
  307.         
  308.         if all thing ok return 1,else return 0.
  309.     **********************
  310.     
  311.     
  312. -------------------------------------------------------*/
  313. {
  314.     USHORT Cylinders,Heads,Sectors;
  315.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  316.     UCHAR nDisk;
  317.     CLIENT_STRUCT saveregs; 
  318.     CLIENT_STRUCT *pClStru;
  319.     struct cb_s * hvm;
  320.     if(nDiskNumber > 5 )
  321.     {
  322.         return 0;
  323.     }
  324.     nDisk = DiskIDs[nDiskNumber];
  325.     GETVM_HANDLE_CLIENTSTRU(hvm,pClStru);
  326.     _SAVE_CLIENT_STATE(saveregs);
  327.     
  328.     //
  329.     //Fill the client struct.
  330.     //
  331.     pClStru->CBRS.Client_AH  = 0x08;
  332.     pClStru->CBRS.Client_DL  = nDisk;
  333.     _CALL_INT13_V86_(hvm,pClStru);
  334.     //
  335.     //Save the interest value to AX,DX,CX.
  336.     //
  337.     _asm mov ebx,pClStru
  338.     _asm mov AX,[ebx.Client_Flags]
  339.     _asm mov DX,[ebx.Client_DX]
  340.     _asm mov CX,[ebx.Client_CX]
  341.     _RESTORE_CLIENT_STATE(saveregs);
  342.     //
  343.     //Now Get the proper params from DX,CX
  344.     //
  345.     _asm{
  346.         test    AX,1
  347.         jnz    loc_error
  348.         MOV     AL,DH           //
  349.         XOR     AH,AH
  350.         INC     AX
  351.         MOV     Heads,AX        // save head count
  352.         MOV     AL,CL           // put sector number in AL
  353.         AND     AX,3FH          // and mask off cylinder bits
  354.         MOV     Sectors,AX      // save sector count
  355.         MOV     AL,CH           // AL = cylinder LO
  356.         MOV     AH,CL           // AH = cylinder HI...
  357.         MOV     CL,6
  358.         SHR     AH,CL           // shift the HI bits down
  359.         INC     AX
  360.         MOV     Cylinders,AX    // save cylinder count
  361.         jmp loc_success
  362.     }
  363. loc_error:
  364.     return 0;
  365. loc_success:
  366.     *pCylinders = Cylinders;
  367.     *pHeads = Heads;
  368.     *pSectors = Sectors;
  369.     return 1;
  370. }
  371. int absDiskReadI13(
  372. UCHAR nDiskNumber,  //0~5;
  373. USHORT nCylinders,
  374. USHORT nHeads,      // 
  375. USHORT nSectors,    // sector position
  376. USHORT wSectors,    //How many To read
  377. void* pBuffer)      //pointer to the buffer.
  378. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  379.     Routine Description:
  380.         Read the Disk which specified by nDiskNumber using bios int 13h.
  381.     Arguments:
  382.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  383.         nCylinders --  Starting Position's Cylinders .it should not be greater than 1024.
  384.         nHeads     --  Starting Position's heads.
  385.         nSectors   --  Starting Position's Sectors.
  386.         wSector    --  How many sector to read.
  387.         pBuffer    --  Buffer for receive the result of reading.
  388.     Return Value:
  389.         
  390.         if all thing ok return 1,else return 0.
  391.     **********************
  392.     
  393.     
  394. -------------------------------------------------------*/
  395. {
  396.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  397.     UCHAR nDisk;
  398.     CLIENT_STRUCT saveregs; 
  399.     CLIENT_STRUCT *pClStru;
  400.     struct cb_s * hvm;
  401.     WORD  nsegsel,noffset;
  402.     DWORD FarPtrBuffer = 0;
  403.     DWORD dwBytesCopied = 0;
  404.     DWORD dwAssumBuffLen = 0;
  405.     DWORD vmpnum = 0x10;
  406.     DWORD retu = 1;
  407.     if(nDiskNumber > 5 || wSectors == 0  )
  408.     {
  409.         return 0;
  410.     }
  411.     
  412.     dwAssumBuffLen = 512 *  wSectors;
  413.     nDisk =  DiskIDs[nDiskNumber];
  414.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  415.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  416.        
  417.     _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(hvm,pClStru,dwAssumBuffLen,
  418.         dwBytesCopied,FarPtrBuffer);
  419.     _asm jc Loc_ret_Failed ;
  420.     _SAVE_CLIENT_STATE(saveregs);
  421.     //
  422.     //Fill Int13 entries..
  423.     //
  424.     nsegsel = HIWORD(FarPtrBuffer);
  425.     noffset = LOWORD(FarPtrBuffer);
  426.     MAKE_INT13CHSD_IN_HS(nCylinders,nHeads,nSectors,nDisk);
  427.     pClStru->CWRS.Client_CX = nHeads;
  428.     pClStru->CWRS.Client_DX  = nSectors;
  429.     pClStru->CBRS.Client_AH  = 0x02; //To Read 
  430.     pClStru->CBRS.Client_AL = (UCHAR)wSectors;//How many to read.
  431.     pClStru->CRS.Client_ES  = nsegsel;
  432.     pClStru->CWRS.Client_BX = noffset;
  433.     
  434.     _CALL_INT13_V86_(hvm,pClStru)
  435.     
  436.     _asm{
  437.         mov ebx,pClStru
  438.         mov ax,[ebx.Client_Flags]
  439.         _asm mov  retu ,eax
  440.     }
  441.     _RESTORE_CLIENT_STATE(saveregs)
  442.     
  443.     _MICRO_V86MMGR_FREE_BUFFER_COPIED(hvm,pClStru,pBuffer,dwBytesCopied);
  444.     if(!(retu&1))
  445.     {
  446.         return 1;
  447.     }
  448. Loc_ret_Failed:
  449.     return 0;
  450. }
  451. int absDiskWriteI13(
  452. UCHAR nDiskNumber,           //0~5;
  453. USHORT nCylinders,
  454. USHORT nHeads,      // 
  455. USHORT nSectors,    //Where to start.
  456. USHORT wSectors,    //How many To read
  457. void* pBuffer)      // 
  458. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  459.     Routine Description:
  460.         Write the Disk which specified by nDiskNumber using bios int 13h.
  461.     Arguments:
  462.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  463.         nCylinders --  Starting Position's Cylinders .it should not be greater than 1024.
  464.         nHeads     --  Starting Position's heads.
  465.         nSectors   --  Starting Position's Sectors.
  466.         wSector    --  How many sector to Write.
  467.         pBuffer    --  Buffer for the content of writing.
  468.     Return Value:
  469.         
  470.         if all thing ok return 1,else return 0.
  471.     **********************
  472.     
  473.     
  474. -------------------------------------------------------*/
  475. {
  476.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  477.     UCHAR nDisk;
  478.     CLIENT_STRUCT saveregs; 
  479.     CLIENT_STRUCT *pClStru;
  480.     struct cb_s * hvm;
  481.     WORD  nsegsel,noffset;
  482.     DWORD FarPtrBuffer = 0;
  483.     DWORD dwBytesCopied = 0;
  484.     DWORD dwAssumBuffLen = 0;
  485.     DWORD vmpnum = 0x10;
  486.     DWORD retu = 1;
  487.     if(nDiskNumber > 5 || wSectors == 0  )
  488.     {
  489.         return 0;
  490.     }
  491.     
  492.     dwAssumBuffLen = 512 *  wSectors;
  493.     nDisk =  DiskIDs[nDiskNumber];
  494.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  495.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  496.        
  497.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,pClStru,pBuffer,dwAssumBuffLen,
  498.         dwBytesCopied,FarPtrBuffer);
  499.     _asm jc Loc_ret_Failed ;
  500.     _SAVE_CLIENT_STATE(saveregs);
  501.     //
  502.     //Fill Int13 entries..
  503.     //
  504.     nsegsel = HIWORD(FarPtrBuffer);
  505.     noffset = LOWORD(FarPtrBuffer);
  506.     MAKE_INT13CHSD_IN_HS(nCylinders,nHeads,nSectors,nDisk);
  507.     pClStru->CWRS.Client_CX = nHeads;
  508.     pClStru->CWRS.Client_DX  = nSectors;
  509.     pClStru->CBRS.Client_AH  = 0x03; //To Write
  510.     pClStru->CBRS.Client_AL = (UCHAR)wSectors;//How many to read.
  511.     pClStru->CRS.Client_ES  = nsegsel;
  512.     pClStru->CWRS.Client_BX = noffset;
  513.     
  514.     _CALL_INT13_V86_(hvm,pClStru)
  515.     
  516.     _asm{
  517.         mov ebx,pClStru
  518.         mov ax,[ebx.Client_Flags]
  519.         _asm mov  retu ,eax
  520.     }
  521.     _RESTORE_CLIENT_STATE(saveregs)
  522.     
  523.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,dwBytesCopied);
  524.     if(!(retu&1))
  525.     {
  526.         return 1;
  527.     }
  528. Loc_ret_Failed:
  529.     return 0;
  530. }
  531. int IsInt13ExtentHere(
  532.                       UCHAR nDiskNumber          //0~5;
  533.                       )
  534. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  535.     Routine Description:
  536.         Check if the Disk which specified by nDiskNumber support int 13h extent,
  537.         using bios int 13h.
  538.     Arguments:
  539.         nDiskNumber -- 0~5.
  540.     Return Value:
  541.         
  542.         if Int 13h exsist return 1,else return 0.
  543.     **********************
  544.     
  545.     
  546. -------------------------------------------------------*/
  547. {
  548.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  549.     UCHAR nDisk;
  550.     CLIENT_STRUCT saveregs; 
  551.     CLIENT_STRUCT *pClStru;
  552.     struct cb_s * hvm;
  553.     if(nDiskNumber > 5 )
  554.     {
  555.         return 0;
  556.     }
  557.     nDisk = DiskIDs[nDiskNumber];
  558.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  559.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  560.     _SAVE_CLIENT_STATE(saveregs)    
  561.     pClStru->CBRS.Client_AH =  0x41;
  562.     pClStru->CWRS.Client_BX =  0x55AA;
  563.     pClStru->CBRS.Client_DL = nDisk;
  564.     _CALL_INT13_V86_(hvm,pClStru)
  565.     _asm{
  566.         mov edx,pClStru;
  567.         mov ax,[edx.Client_Flags]
  568.         mov bx,[edx.Client_BX]
  569.         mov cx,[edx.Client_CX]
  570.     }
  571.     _RESTORE_CLIENT_STATE(saveregs)
  572.     
  573.     _asm
  574.     {
  575.         test ax,1
  576.         jnz loc_error
  577.         xor BX,0xAA55
  578.         JNZ loc_error
  579.         test cx,1
  580.         jnz loc_i13EHere
  581.     }
  582. loc_error:
  583.     return 0;
  584. loc_i13EHere:
  585.     return 1;
  586. }
  587. int absDiskReadI13Ex(
  588.                       UCHAR nDiskNumber,          //0~5;
  589.                       DISKADDRESSPACKETI13E *pAddressPacket
  590.                       )
  591. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  592.     Routine Description:
  593.         Read the Disk which specified by nDiskNumber using 
  594.     bios int 13h extent function 42h.
  595.     Arguments:
  596.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  597.         pAddressPacket -- pointer for DISKADDRESSPACKETI13E.
  598.     Return Value:
  599.         
  600.         if all thing ok return 1,else return 0.
  601.     **********************
  602.     
  603.     
  604. -------------------------------------------------------*/
  605. {
  606.     
  607.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  608.     CLIENT_STRUCT saveregs; 
  609.     CLIENT_STRUCT *pClStru;
  610.     struct cb_s * hvm;
  611.     DWORD PacketFarPtrBuffer = 0;
  612.     DWORD SizeOfAddrPacket  = 0;
  613.     DWORD PacketBuffAllocateNum = 0;
  614.     DWORD DataFarPtrBuffer = 0;
  615.     DWORD DataBuffAllocateNum = 0;
  616.     DWORD dwAssumBuffLen = 0;
  617.     DWORD pDataBuffer = 0;
  618.     int retcode = 1;
  619.     if(nDiskNumber > 5 )
  620.     {
  621.         return 0;
  622.     }
  623.     UCHAR nDisk = DiskIDs[nDiskNumber];
  624.     dwAssumBuffLen = 512 * (pAddressPacket->BlockCount);
  625.     SizeOfAddrPacket =sizeof(DISKADDRESSPACKETI13E);
  626.     
  627.     //
  628.     //Save the procted mode address.
  629.     //
  630.     pDataBuffer = pAddressPacket->BufferAddr;
  631.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  632.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  633.     
  634.     //
  635.     //Allocated the FarBuffer which below 1MB for data
  636.     //
  637.     _MICRO_V86MMGR_ALLOCATE_BUFFER_NOTCOPIED(hvm,
  638.         pClStru,
  639.         dwAssumBuffLen, //<--number of bytes to allocate.
  640.         DataBuffAllocateNum,//<--Allocate 
  641.         DataFarPtrBuffer);
  642.     _asm jc Loc_DataAddr_Failed;
  643.     pAddressPacket->BufferAddr = DataFarPtrBuffer;
  644.     //
  645.     //Allocated the FarBuffer which below 1MB for addressPacket,
  646.     //and Copy the data to it.
  647.     //
  648.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
  649.         pClStru,
  650.         pAddressPacket,
  651.         SizeOfAddrPacket,
  652.         PacketBuffAllocateNum,
  653.         PacketFarPtrBuffer);
  654.     _asm jc Loc_PackAddr_Failed ;
  655.     
  656.     _SAVE_CLIENT_STATE(saveregs)    
  657.     //
  658.     //fill int ext entries.
  659.     //
  660.     pClStru->CBRS.Client_AH = 0x42 ;
  661.     pClStru->CBRS.Client_DL = nDisk;
  662.     pClStru->CRS.Client_DS = HIWORD(PacketFarPtrBuffer);
  663.     pClStru->CWRS.Client_SI = LOWORD(PacketFarPtrBuffer);
  664.     _CALL_INT13_V86_(hvm,pClStru)
  665.     
  666.     retcode = pClStru->CWRS.Client_Flags;
  667.     
  668.     _RESTORE_CLIENT_STATE(saveregs)
  669.     //
  670.     //Free  the Packet  FarBuffer;
  671.     //The buffers are maintained as a stack. 
  672.     //Therefore, the last buffer allocated must 
  673.     //be the first buffer freed.
  674.     //
  675.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,PacketBuffAllocateNum);
  676.     //
  677.     //Restore the procted mode address.
  678.     //
  679.     pAddressPacket->BufferAddr = pDataBuffer;
  680.     
  681.     //
  682.     //Free and copy back the data FarBuffer.
  683.     //
  684.     _MICRO_V86MMGR_FREE_BUFFER_COPIED(hvm,pClStru,
  685.         pDataBuffer,DataBuffAllocateNum);
  686.     return !(retcode &1);
  687. Loc_DataAddr_Failed:
  688.     return 0;
  689. Loc_PackAddr_Failed:
  690.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataFarPtrBuffer);
  691.     return 0;
  692.     
  693. }
  694. int absDiskWriteI13Ex( 
  695.                       UCHAR nDiskNumber,          //0~5;
  696.                       DISKADDRESSPACKETI13E *pAddressPacket
  697.                       )
  698. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
  699.     Routine Description:
  700.         Write the Disk which specified by nDiskNumber using 
  701.     bios int 13h extent function 43h.
  702.     Arguments:
  703.         nDiskNumber -- Disk ID,0-5 for   Fixed hardDisk.
  704.         pAddressPacket -- pointer for DISKADDRESSPACKETI13E.
  705.     Return Value:
  706.         
  707.         if all thing ok return 1,else return 0.
  708.     **********************
  709.     
  710.     
  711. -------------------------------------------------------*/
  712. {
  713.     UCHAR DiskIDs[6] = {0x80,0x81,0x82,0x83,0x84,0x85};
  714.     CLIENT_STRUCT saveregs; 
  715.     CLIENT_STRUCT *pClStru;
  716.     struct cb_s * hvm;
  717.     DWORD PacketFarPtrBuffer = 0;
  718.     DWORD SizeOfAddrPacket  = 0;
  719.     DWORD PacketBuffAllocateNum = 0;
  720.     DWORD DataFarPtrBuffer = 0;
  721.     DWORD DataBuffAllocateNum = 0;
  722.     DWORD dwAssumBuffLen = 0;
  723.     DWORD pDataBuffer = 0;
  724.     int retcode = 1;
  725.     if(nDiskNumber > 5 )
  726.     {
  727.         return 0;
  728.     }
  729.     UCHAR nDisk = DiskIDs[nDiskNumber];
  730.     dwAssumBuffLen = 512 * (pAddressPacket->BlockCount);
  731.     SizeOfAddrPacket =sizeof(DISKADDRESSPACKETI13E);
  732.     
  733.     //
  734.     //Save the procted mode address.
  735.     //
  736.     pDataBuffer = pAddressPacket->BufferAddr;
  737.     hvm = (struct cb_s *)Get_Cur_VM_Handle();
  738.     pClStru = (CLIENT_STRUCT *)hvm->CB_Client_Pointer;
  739.     
  740.     //
  741.     //Allocated the FarBuffer which below 1MB for data
  742.     //
  743.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
  744.         pClStru,
  745.         pDataBuffer,
  746.         dwAssumBuffLen, //<--number of bytes to allocate.
  747.         DataBuffAllocateNum,//<--Allocate 
  748.         DataFarPtrBuffer);
  749.     _asm jc Loc_DataAddr_Failed;
  750.     pAddressPacket->BufferAddr = DataFarPtrBuffer;
  751.     //
  752.     //Allocated the FarBuffer for addressPacket,
  753.     //and Copy the data to it.
  754.     //
  755.     _MICRO_V86MMGR_ALLOCATE_BUFFER_COPIED(hvm,
  756.         pClStru,
  757.         pAddressPacket,
  758.         SizeOfAddrPacket,
  759.         PacketBuffAllocateNum,
  760.         PacketFarPtrBuffer);
  761.     _asm jc Loc_PackAddr_Failed ;
  762.     
  763.     _SAVE_CLIENT_STATE(saveregs)    
  764.     //
  765.     //fill int ext entries.
  766.     //
  767.     pClStru->CBRS.Client_AH = 0x43; //Extent Write.
  768.     pClStru->CBRS.Client_AL = 0 ;   //don't verify write.
  769.     pClStru->CBRS.Client_DL = nDisk;
  770.     pClStru->CRS.Client_DS = HIWORD(PacketFarPtrBuffer);
  771.     pClStru->CWRS.Client_SI = LOWORD(PacketFarPtrBuffer);
  772.     _CALL_INT13_V86_(hvm,pClStru)
  773.     
  774.     retcode = pClStru->CWRS.Client_Flags;
  775.     
  776.     _RESTORE_CLIENT_STATE(saveregs)
  777.     //
  778.     //Free  the Packet  FarBuffer;
  779.     //The buffers are maintained as a stack. 
  780.     //Therefore, the last buffer allocated must 
  781.     //be the first buffer freed.
  782.     //
  783.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,PacketBuffAllocateNum);
  784.     //
  785.     //Restore the procted mode address.
  786.     //
  787.     pAddressPacket->BufferAddr = pDataBuffer;
  788.     
  789.     //
  790.     //Free and copy back the data FarBuffer.
  791.     //
  792.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataBuffAllocateNum);
  793.     return !(retcode &1);
  794. Loc_DataAddr_Failed:
  795.     return 0;
  796. Loc_PackAddr_Failed:
  797.     _MICRO_V86MMGR_FREE_BUFFER_NOTCOPIED(hvm,pClStru,DataFarPtrBuffer);
  798.     return 0;
  799.     
  800. }

 

 

  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. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值