Sfoglia il codice sorgente

+ implemented dos.diskfree and disksize for i8086-msdos; cd-rom support not implemented yet

git-svn-id: trunk@24701 -
nickysn 12 anni fa
parent
commit
6c51bcae37
1 ha cambiato i file con 149 aggiunte e 2 eliminazioni
  1. 149 2
      rtl/msdos/dos.pp

+ 149 - 2
rtl/msdos/dos.pp

@@ -292,9 +292,156 @@ type
 
 
 
 
 function do_diskdata(drive : byte; Free : boolean) : Int64;
 function do_diskdata(drive : byte; Free : boolean) : Int64;
+var
+  blocksize, freeblocks, totblocks : longword;
+
+  { Get disk data via old int21/36 (GET FREE DISK SPACE). It's always supported
+    even if it returns wrong values for volumes > 2GB and for cdrom drives when
+    in pure DOS. Note that it's also the only way to get some data on WinNTs. }
+  function DiskData_36 : boolean;
+  begin
+    DiskData_36:=false;
+    dosregs.dl:=drive;
+    dosregs.ah:=$36;
+    msdos(dosregs);
+    if dosregs.ax=$FFFF then exit;
+
+    blocksize:=dosregs.ax*dosregs.cx;
+    freeblocks:=dosregs.bx;
+    totblocks:=dosregs.dx;
+    Diskdata_36:=true;
+  end;
+
+  { Get disk data via int21/7303 (FAT32 - GET EXTENDED FREE SPACE ON DRIVE).
+    It is supported by win9x even in pure DOS }
+  function DiskData_7303 : boolean;
+  var
+    s : shortstring;
+    rec : ExtendedFat32FreeSpaceRec;
+  begin
+    DiskData_7303:=false;
+    s:=chr(drive+$40)+':\'+#0;
+
+    rec.Strucversion:=0;
+    rec.RetSize := 0;
+    dosregs.dx:=Ofs(s[1]);
+    dosregs.ds:=Seg(s[1]);
+    dosregs.di:=Ofs(Rec);
+    dosregs.es:=Seg(Rec);
+    dosregs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
+    dosregs.ax:=$7303;
+    msdos(dosregs);
+    if (dosregs.flags and fcarry) <> 0 then
+      exit;
+    if Rec.RetSize = 0 then
+      exit;
+
+    blocksize:=rec.SecPerClus*rec.BytePerSec;
+    freeblocks:=rec.AvailAllocUnits;
+    totblocks:=rec.TotalAllocUnits;
+    DiskData_7303:=true;
+  end;
+
+  { Get disk data asking to MSCDEX. Pure DOS returns wrong values with
+    int21/7303 or int21/36 if the drive is a CDROM drive }
+  function DiskData_CDROM : boolean;
+  var req : TRequestHeader;
+      sectreq : TCDSectSizeReq;
+      sizereq : TCDVolSizeReq;
+      i : integer;
+      status,byteswritten : word;
+      drnum : byte;
+  begin
+    DiskData_CDROM:=false;
+    exit;
+    { TODO: implement }
+(*    drnum:=drive-1; //for MSCDEX, 0 = a, 1 = b etc, unlike int21/36
+
+    { Is this a CDROM drive? }
+    dosregs.ax:=$150b;
+    dosregs.cx:=drnum;
+    realintr($2f,dosregs);
+    if (dosregs.bx<>$ADAD) or (dosregs.ax=0) then
+      exit; // no, it isn't
+
+    { Prepare the request header to send to the cdrom driver }
+    FillByte(req,sizeof(req),0);
+    req.length:=sizeof(req);
+    req.command:=IOCTL_INPUT;
+    req.transf_ofs:=tb_offset+sizeof(req); //CDROM control block will follow
+    req.transf_seg:=tb_segment;            //the request header
+    req.numbytes:=sizeof(sectreq);
+
+    { We're asking the sector size }
+    sectreq.func:=CDFUNC_SECTSIZE;
+    sectreq.mode:=0; //cooked
+    sectreq.secsize:=0;
+
+    for i:=1 to 2 do
+    begin
+      { Send the request to the cdrom driver }
+      dosmemput(tb_segment,tb_offset,req,sizeof(req));
+      dosmemput(tb_segment,tb_offset+sizeof(req),sectreq,sizeof(sectreq));
+      dosregs.ax:=$1510;
+      dosregs.cx:=drnum;
+      dosregs.es:=tb_segment;
+      dosregs.bx:=tb_offset;
+      realintr($2f,dosregs);
+      dosmemget(tb_segment,tb_offset+3,status,2);
+      { status = $800F means "disk changed". Try once more. }
+      if (status and $800F) <> $800F then break;
+    end;
+    dosmemget(tb_segment,tb_offset+$12,byteswritten,2);
+    if (status<>$0100) or (byteswritten<>sizeof(sectreq)) then
+      exit; //An error occurred
+    dosmemget(tb_segment,tb_offset+sizeof(req),sectreq,sizeof(sectreq));
+
+  { Update the request header for the next request }
+    req.numbytes:=sizeof(sizereq);
+
+    { We're asking the volume size (in blocks) }
+    sizereq.func:=CDFUNC_VOLSIZE;
+    sizereq.size:=0;
+
+    { Send the request to the cdrom driver }
+    dosmemput(tb_segment,tb_offset,req,sizeof(req));
+    dosmemput(tb_segment,tb_offset+sizeof(req),sizereq,sizeof(sizereq));
+    dosregs.ax:=$1510;
+    dosregs.cx:=drnum;
+    dosregs.es:=tb_segment;
+    dosregs.bx:=tb_offset;
+    realintr($2f,dosregs);
+    dosmemget(tb_segment,tb_offset,req,sizeof(req));
+    if (req.status<>$0100) or (req.numbytes<>sizeof(sizereq)) then
+      exit; //An error occurred
+    dosmemget(tb_segment,tb_offset+sizeof(req)+1,sizereq.size,4);
+
+    blocksize:=sectreq.secsize;
+    freeblocks:=0; //always 0 for a cdrom
+    totblocks:=sizereq.size;
+    DiskData_CDROM:=true;*)
+  end;
+
 begin
 begin
-  {TODO: implement}
-  runerror(304);
+  if drive=0 then
+  begin
+    dosregs.ax:=$1900;    //get current default drive
+    msdos(dosregs);
+    drive:=dosregs.al+1;
+  end;
+
+  if not DiskData_CDROM then
+  if not DiskData_7303 then
+  if not DiskData_36 then
+  begin
+    do_diskdata:=-1;
+    exit;
+  end;
+  do_diskdata:=blocksize;
+  if free then
+    do_diskdata:=do_diskdata*freeblocks
+  else
+    do_diskdata:=do_diskdata*totblocks;
 end;
 end;
 
 
 function diskfree(drive : byte) : int64;
 function diskfree(drive : byte) : int64;