home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / podstawy / dos / format / fdform18.exe / DISKIO.PAS < prev    next >
Pascal/Delphi Source File  |  1991-07-21  |  14KB  |  415 lines

  1. {$A+,B-,D+,E-,F+,I-,L+,N-,O+,R-,S-,V-,X+}
  2.  
  3. UNIT diskio;
  4.  
  5. INTERFACE
  6.  
  7. USES dos,auxdos;
  8.  
  9. TYPE Split      = RECORD
  10.                     O: Word;
  11.                     S: Word;
  12.                   END;
  13.  
  14. TYPE filtyp     = FILE OF ARRAY[0..511] OF Byte;
  15.      fileptr    = ^filtyp;
  16.      boottyp    = ARRAY[62..511] OF Byte;
  17.  
  18. TYPE bpbtyp     =  RECORD
  19.                      jmp: ARRAY[1..3] OF Byte;                     {Die ersten drei Bytes für JUMP}
  20.                      oem: ARRAY[1..8] OF Char;                                        {OEM-Eintrag}
  21.                      bps: Word;                                                  {Bytes pro Sektor}
  22.                      spc: Byte;                                              {Sektoren pro Cluster}
  23.                      res: Word;                                                     {BOOT-Sektoren}
  24.                      fat: Byte;                                                  {Anzahl der FAT's}
  25.                      rde: Word;                                          {Basisverzeichniseinträge}
  26.                      sec: Word;                                       {Gesamtsektoren der Diskette}
  27.                      mds: Byte;                                                  {Media-Deskriptor}
  28.                      spf: Word;                                                  {Sektoren pro FAT}
  29.                      spt: Word;                                                 {Sektoren pro Spur}
  30.                      hds: Word;                                                            {Seiten}
  31.                      shh: Longint;                                            {Versteckte Sektoren}
  32.                      lsc: Longint;                     {Anzahl der Sektoren bei großen Partitionen}
  33.                      pdn: Word;                                             {Physical Drive Number}
  34.                      ebs: Byte;                                           {Extended Boot Signature}
  35.                      vsn: LongInt;                                           {Volume Serial-Number}
  36.                      vlb: ARRAY[1..11] OF Char;                                      {Volume Label}
  37.                      fsi: ARRAY[1..8] OF Char;                                     {File System Id}
  38.                      boot_code: boottyp;                                     {Puffer für BOOT-Code}
  39.                    END;
  40.  
  41.       bdib      = RECORD
  42.                     flag   : Byte;                                                {Bitmapped flags}
  43.                     dtyp   : Byte;                                                     {Drive Type}
  44.                     dflag  : Word;                                                {Bitmapped flags}
  45.                     noc    : Word;                                            {Number of cylinders}
  46.                     mt     : Byte;                                                     {Media Type}
  47.                     bpb    : ARRAY[0..30] OF Byte;                                            {BPB}
  48.                     nos    : Word;                                    {Number of sectors per track}
  49.                     sly    : ARRAY[0..63] OF RECORD                                 {sector layout}
  50.                                                  num: Word;                         {Sector Number}
  51.                                                  siz: Word;                        {Size of sector}
  52.                                                END;
  53.                   END;
  54.  
  55.       dos4rw    = RECORD                                                   {Disk Read/Write Packet}
  56.                     sector   : LongInt;                                     {für Partitionen >=32M}
  57.                     count    : Word;
  58.                     Transfer : Pointer;
  59.                   END;
  60.  
  61. TYPE  SectorTyp = Object
  62.                     data: Pointer;
  63.                     Start: LongInt;
  64.                     datalen: Word;
  65.                     Constructor init(VAR allocated: Boolean);
  66.                     PROCEDURE Error(lw,rw,err:Byte; VAR er:Boolean; Sector:Longint); virtual;
  67.                     PROCEDURE DiskRw(rw,lw:Byte; Sector:LongInt; Count:Byte; Transfer:Pointer);
  68.                     PROCEDURE Readx(lw: Byte; x: LongInt);
  69.                     PROCEDURE Writex(lw: Byte; x: LongInt);
  70.                     Destructor Done;
  71.                   END;
  72.  
  73.  
  74. TYPE CylTyp    = Object (SectorTyp)
  75.                    Constructor init(spcyl: Word; VAR allocated: Boolean);
  76.                    PROCEDURE Readx(lw: Byte; x: Word);
  77.                    PROCEDURE Writex(lw: Byte; x: Word);
  78.                  END;
  79.  
  80.  
  81. TYPE BootSecTyp = Object(SectorTyp)
  82.                     bpb: ^bpbtyp;
  83.                     status: Word;
  84.                     Media: Byte;
  85.                     UnknownDrive: Boolean;
  86.                     dos4: Boolean;
  87.                     Constructor init(VAR allocated: Boolean);
  88.                     PROCEDURE Readx(lw: Byte);
  89.                     PROCEDURE Writex(lw: Byte);
  90.                     PROCEDURE Remount(lw: Byte);
  91.                   END;
  92.  
  93. TYPE STyp       = ARRAY[0..0] OF ^SectorTyp;
  94.      CTyp       = ARRAY[0..0] OF ^CylTyp;
  95.      Smtyp      = ^Styp;
  96.      Cmtyp      = ^CTyp;
  97.  
  98.  
  99.  
  100. VAR BootSec         : BootSecTyp;
  101.   maxsec            : Word;
  102.   maxcyl            : Word;
  103.  
  104.  
  105.   PROCEDURE CheckDrive(lw:Byte; VAR Status:Word; VAR error1:Boolean; VAR Media:Byte);
  106.   PROCEDURE DeallocCyl(Var Cylmem:Cmtyp; Stop:Word);
  107.   PROCEDURE DeallocSec(Var Secmem:Smtyp; Stop:Word);
  108.   FUNCTION AllocCyl(VAR Cylmem:Cmtyp; Stop:Word): Word;
  109.   FUNCTION AllocSec(VAR secmem:Smtyp; stop:Word): Word;
  110.   FUNCTION ReadKey: Char;
  111.  
  112. IMPLEMENTATION
  113.  
  114.   FUNCTION ReadKey:Char; Assembler;
  115.     ASM
  116.       mov   ah,8
  117.       int   21h
  118.     END;
  119.  
  120.   PROCEDURE Sectortyp.error(lw,rw,err:Byte; VAR er:Boolean; Sector:Longint);
  121.   VAR chx: Char;
  122.   BEGIN
  123.     WITH BootSec DO BEGIN
  124.       WriteLn(stderr);
  125.       IF rw=0 THEN
  126.         Write(stderr,'Read')
  127.       ELSE
  128.         Write(stderr,'Write');
  129.       Write(stderr,'-Error Drive ',chr(lw+$40),': ');
  130.       CASE err OF
  131.         $00: Write(stderr,'Disk is write protected');
  132.         $01: Write(stderr,'Unknown unit');
  133.         $02: Write(stderr,'Drive not ready');
  134.         $03: Write(stderr,'Unknown command');
  135.         $04: Write(stderr,'Bad CRC');
  136.         $05: Write(stderr,'Bad request structure length');
  137.         $06: Write(stderr,'Seek error');
  138.         $07: Write(stderr,'Unknown media type');
  139.         $08: Write(stderr,'Sector not found');
  140.         $09: Write(stderr,'Printer out of paper');
  141.         $0A: Write(stderr,'Write fault');
  142.         $0B: Write(stderr,'Read fault');
  143.         $0C: Write(stderr,'General failure');
  144.         $0D: Write(stderr,'Sharing violation');
  145.         $0E: Write(stderr,'Lock violation');
  146.         $0F: Write(stderr,'Invalid disk change');
  147.         $10: Write(stderr,'FCB unavailable');
  148.         $11: Write(stderr,'Sharing buffer overflow');
  149.         ELSE Write(stderr,'Unknown error');
  150.       END;
  151.       Writeln(stderr,'.');
  152.       Write(stderr,'Error ',err,': Sector: ',Sector,' ');
  153.       IF Sector=0 THEN
  154.         WriteLn(stderr,'BOOT-Sector')
  155.       ELSE BEGIN
  156.         IF (Sector>=1) and (Sector<=bpb^.spf) THEN
  157.           WriteLn(stderr,'FAT 1');
  158.         IF (Sector>=bpb^.spf+1) and (sector<=Longint(bpb^.spf) shl 1) THEN
  159.           WriteLn(stderr,'FAT 2');
  160.       END;
  161.       REPEAT
  162.         Write(stderr,'(A)bort, (R)etry, (I)gnore ? ');
  163.         chx:=Upcase(ReadKey); WriteLn(stderr,chx);
  164.       UNTIL chx IN ['A','I','R'];
  165.       CASE chx OF
  166.         'A': Halt(255);
  167.         'I': BEGIN
  168.                er:=False;
  169.              END;
  170.         'R': er:=True;
  171.       END;
  172.     END;
  173.   END;
  174.  
  175.   Constructor SectorTyp.init(VAR allocated: Boolean);
  176.   BEGIN
  177.     allocated:=True;
  178.     IF MaxAvail<512 THEN allocated:=False;
  179.     IF allocated THEN BEGIN
  180.       GetMem(self.data,512);
  181.       datalen:=512;
  182.     END;
  183.   END;
  184.  
  185.   PROCEDURE int2526(rw,lw:Byte; Sector:Longint; Count:Word; Transfer:Pointer; Var flags,rax: Word); Far;
  186.   LABEL common;
  187.   VAR rwpacket: dos4rw;
  188.   BEGIN
  189.     IF NOT(BootSec.Dos4) THEN BEGIN
  190.       ASM
  191.         @start: mov   dx,ss:[bp+20]            {Low half of Sector}
  192.                 mov   cx,count
  193.                 push  ds
  194.                 lds   bx,transfer
  195.         common: mov   al,lw
  196.                 cmp   byte ptr ss:[bp+26],1    {rw}
  197.                 push  bp                       {DOS 3 alters BP, grrrr...}
  198.                 jz    @write
  199.                 int   25h
  200.                 jmp   @all
  201.         @write: int   26h
  202.         @all:   pop   cx
  203.                 pop   bp
  204.                 pop   ds
  205.                 les   bx,flags
  206.                 pushf
  207.                 pop   cx
  208.                 mov   es:[bx],cx
  209.                 les   bx,rax
  210.                 mov   es:[bx],ax
  211.       END;
  212.     END ELSE BEGIN
  213.       rwpacket.sector:=sector;
  214.       rwpacket.count:=count;
  215.       rwpacket.Transfer:=Transfer;
  216.       ASM
  217.         @start: mov   cx,0ffffh
  218.                 push  ds
  219.                 push  ss
  220.                 pop   ds
  221.                 lea   bx,rwpacket
  222.                 jmp   common
  223.       END;
  224.     END;
  225.   END;
  226.  
  227.   PROCEDURE SectorTyp.DiskRw(rw,lw:Byte; Sector:Longint; Count:Byte; Transfer:Pointer);
  228.   VAR flags,rax: Word;
  229.     er         : Boolean;
  230.     i          : Word;
  231.   BEGIN
  232.     int2526(rw,lw-1,Sector,Count,Transfer,flags,rax);
  233.       IF (FCarry AND Flags) <> 0 THEN
  234.         FOR i:=0 TO Count-1 DO
  235.           REPEAT
  236.             int2526(rw,lw-1,Sector+i,1,ptr(Split(Transfer).S,Split(Transfer).O+(i shl 9)),flags,rax);
  237.             er:=False;
  238.             IF (FCarry AND Flags) <> 0 THEN error(lw,rw,lo(rax),er,Sector+i);
  239.           UNTIL NOT er;
  240.   END;
  241.  
  242.   PROCEDURE SectorTyp.Readx(lw: Byte; x: LongInt);
  243.   BEGIN
  244.     self.DiskRw(0,lw,x,1,self.data);
  245.   END;
  246.  
  247.   PROCEDURE SectorTyp.Writex(lw: Byte; x: LongInt);
  248.   BEGIN
  249.     self.DiskRw(1,lw,x,1,self.data);
  250.   END;
  251.  
  252.   Constructor CylTyp.init(spcyl: Word; VAR allocated: Boolean);
  253.   BEGIN
  254.     allocated:=True;
  255.     datalen:=spcyl SHL 9;
  256.     IF MaxAvail<datalen THEN allocated:=False;
  257.     IF allocated THEN BEGIN
  258.       GetMem(self.data,datalen);
  259.     END;
  260.   END;
  261.  
  262.   PROCEDURE CylTyp.Readx(lw: Byte; x:Word);
  263.   BEGIN
  264.     self.DiskRw(0,lw,LongInt(x)*(datalen SHR 9),datalen SHR 9,self.data);
  265.   END;
  266.  
  267.   PROCEDURE CylTyp.Writex(lw: Byte; x:Word);
  268.   BEGIN
  269.     self.DiskRw(1,lw,LongInt(x)*(datalen SHR 9),datalen SHR 9,self.data);
  270.   END;
  271.  
  272.   Constructor BootSecTyp.init(VAR allocated: Boolean);
  273.   BEGIN
  274.     allocated:=True;
  275.     IF MaxAvail<512 THEN allocated:=False;
  276.     IF allocated THEN BEGIN
  277.       GetMem(self.data,512);
  278.       self.bpb:=self.data;
  279.       datalen:=512;
  280.     END;
  281.   END;
  282.  
  283.   PROCEDURE BootSecTyp.Readx(lw: Byte);
  284.   BEGIN
  285.     CheckDrive(lw,self.status,self.UnknownDrive,self.Media);
  286.     self.dos4:=false;
  287.     if not(UnknownDrive) and ((self.status and $9202)=2) then
  288.       self.dos4:=true;
  289.     if not(UnknownDrive) and ((self.status and $9200)=0) then
  290.     self.DiskRw(0,lw,0,1,self.data);
  291.   END;
  292.  
  293.   PROCEDURE BootSecTyp.Writex(lw: Byte);
  294.   BEGIN
  295.     self.DiskRw(1,lw,0,1,self.data);
  296.   END;
  297.  
  298.   Destructor SectorTyp.Done;
  299.   BEGIN
  300.     FreeMem(self.data,datalen);
  301.   END;
  302.  
  303.   PROCEDURE BootSecTyp.Remount(lw: Byte);
  304.   VAR buffer: bdib;
  305.    regs     : Registers;
  306.    er       : Boolean;
  307.   BEGIN
  308.     Self.Readx(lw);
  309.     er:=False;
  310.     REPEAT
  311.       regs.bx:=lw;
  312.       regs.ax:=$440D;
  313.       regs.cx:=$860;
  314.       regs.ds:=Seg(buffer);
  315.       regs.dx:=Ofs(buffer);
  316.       buffer.flag:=5;
  317.       msdos(regs);
  318.       IF (regs.Flags AND FCarry) <> 0 THEN self.Error(lw,0,regs.al,er,0);
  319.     UNTIL not(er);
  320.     Move(bpb^.bps,buffer.bpb,31);
  321.     REPEAT
  322.       regs.bx:=lw;
  323.       regs.ax:=$440D;
  324.       regs.cx:=$840;
  325.       regs.ds:=Seg(buffer);
  326.       regs.dx:=Ofs(buffer);
  327.       buffer.flag:=4;
  328.       buffer.nos:=0;
  329.       msdos(regs);
  330.       IF (regs.Flags AND FCarry) <> 0 THEN self.Error(lw,0,regs.al,er,0);
  331.     UNTIL not(er);
  332.   END;
  333.  
  334.  
  335.   FUNCTION AllocSec(VAR secmem:Smtyp; Stop:Word): Word;
  336.   VAR i: Word;
  337.     ok: Boolean;
  338.   BEGIN
  339.     GetMem(secmem,(Stop+1)*4);
  340.     FOR i:=0 to Stop do Secmem^[i]:=NIL;
  341.     i:=0;
  342.     REPEAT
  343.       IF (4512>MaxAvail) OR (secmem^[i]<>NIL) THEN
  344.         ok:=False
  345.       ELSE BEGIN
  346.         New(secmem^[i],init(ok));
  347.         IF ok THEN Inc(i);
  348.       END;
  349.     UNTIL NOT(ok) OR (i>stop);
  350.     Dec(i);
  351.     AllocSec:=i;
  352.   END;
  353.  
  354.   FUNCTION AllocCyl(VAR Cylmem:Cmtyp; Stop:Word): Word;
  355.   VAR i: Word;
  356.     ok: Boolean;
  357.   BEGIN
  358.     GetMem(cylmem,(Stop+1)*4);
  359.     FOR i:=0 to Stop do Cylmem^[i]:=NIL;
  360.     i:=0;
  361.     REPEAT
  362.       IF (((BootSec.bpb^.spt*BootSec.bpb^.hds) SHL 9)+4000>MaxAvail) OR
  363.       (cylmem^[i]<>NIL) THEN
  364.         ok:=False
  365.       ELSE BEGIN
  366.         New(cylmem^[i],init(BootSec.bpb^.spt*BootSec.bpb^.hds,ok));
  367.         IF ok THEN Inc(i);
  368.       END;
  369.     UNTIL NOT(ok) OR (i>stop);
  370.     Dec(i);
  371.     AllocCyl:=i;
  372.   END;
  373.  
  374.   PROCEDURE DeallocCyl(Var Cylmem:Cmtyp; Stop:Word);
  375.   VAR i: Word;
  376.   BEGIN
  377.     FOR i:=0 TO stop DO BEGIN
  378.       Dispose(cylmem^[i],Done);
  379.     END;
  380.     FreeMem(cylmem,(Stop+1)*4);
  381.   END;
  382.  
  383.   PROCEDURE DeallocSec(Var Secmem:Smtyp; Stop:Word);
  384.   VAR i: Word;
  385.   BEGIN
  386.     FOR i:=0 TO stop DO BEGIN
  387.       Dispose(secmem^[i],Done);
  388.     END;
  389.     FreeMem(secmem,(Stop+1)*4);
  390.   END;
  391.  
  392.   PROCEDURE CheckDrive(lw:Byte; VAR Status:Word; VAR error1:Boolean; VAR Media:Byte);
  393.   VAR regs: registers;
  394.     driveinfo : ARRAY[0..48] OF Byte;
  395.   BEGIN
  396.     WITH regs DO BEGIN
  397.       ax:=$4409;
  398.       bl:=lw;
  399.       bh:=0;
  400.       intr($21,regs);
  401.       error1:=(FCarry AND Flags) <> 0;
  402.       Status:=dx;
  403.       ax:=$440d;
  404.       cx:=$860;
  405.       bl:=lw;
  406.       bh:=0;
  407.       dx:=Ofs(driveinfo);
  408.       ds:=Seg(driveinfo);
  409.       intr($21,regs);
  410.       Media:=driveinfo[1];
  411.     END;
  412.   END;
  413.  
  414. END.
  415.