summaryrefslogtreecommitdiff
path: root/system/dos/1.8.7/src/disk descriptor.dos
blob: 0b0d7fc07719038fb416f267140e244c67d3af4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
PACKET dos disk DEFINES                       (* Copyright (C) 1986, 87 *)
                                              (* Frank Klapper          *)
  (* Referenz: 3-22 *)                        (* 11.09.87               *)

  open dos disk,

  sectors per cluster,
  fat copies,
  dir sectors,
  media descriptor,
  fat sectors,

  begin of fat,
  fat entrys,
  begin of dir,
  begin of cluster,
  cluster size,

  bpb exists,
  write bpb,

  eu block,

  bpb dump modus:

INITFLAG VAR bpb ds initialisiert := FALSE;
DATASPACE VAR bpb ds;
BOUND STRUCT (ALIGN dummy, ROW 512 INT daten) VAR bpb;

BOOL VAR bpb dump flag := FALSE;

REAL VAR begin of data area;
INT  VAR sectors per track,
         heads;

IF exists ("shard interface")
  THEN load shard interface table
FI;

TEXT CONST bpb type 254 :: ""00""00""00"" +
                           ""69""85""77""69""76""66""80""66"" +
                           ""00""02"" +
                           ""01"" +
                           ""01""00"" +
                           ""02"" +
                           ""64""00"" +
                           ""64""01"" +
                           ""254"" +
                           ""01""00"" +
                           ""08""00"" +
                           ""01""00"" +
                           ""00""00"",
           bpb type 255 :: ""00""00""00"" +
                           ""69""85""77""69""76""66""80""66"" +
                           ""00""02"" +
                           ""02"" +
                           ""01""00"" +
                           ""02"" +
                           ""112""00"" +
                           ""128""02"" +
                           ""255"" +
                           ""01""00"" +
                           ""08""00"" +
                           ""02""00"" +
                           ""00""00"";

PROC open dos disk:
  enable stop;
  bpb ds an bound koppeln;
  bpb lesen;
  IF bpb ungueltig
    THEN versuche pseudo bpb zu verwenden
  FI;
  ueberpruefe bpb auf gueltigkeit;
  globale variablen initialisieren;
  IF bpb dump flag
    THEN dump schreiben
  FI.

bpb ds an bound koppeln:
  IF NOT initialized (bpb ds initialisiert)
    THEN bpb ds := nilspace;
         bpb := bpb ds
  FI.

bpb lesen:
  INT VAR return;
  check rerun;
  read block (bpb ds, 2, 0, return);
  IF return <> 0
    THEN lesefehler (return)
  FI.

bpb ungueltig:
  (* Byte 12 = Byte 13 = ... = Byte 23 <==> Word 6 = ... = Word 11 *)
  INT VAR word no;
  FOR word no FROM 6 UPTO 10 REP
    IF bpb.daten [word no + 1] <> bpb.daten [word no + 2]
      THEN LEAVE bpb ungueltig WITH FALSE
    FI
  PER;
  TRUE.

versuche pseudo bpb zu verwenden:
  lies ersten fat sektor;
  IF fat sektor gueltig und pseudo bpb vorhanden
    THEN pseudo bpb laden
    ELSE error stop ("Format unbekannt")
  FI.

lies ersten fat sektor:
  (* da der bpb in diesem Fall ungültig, lese ich den fat sektor in den bpb
     Datenraum                                                             *)
  check rerun;
  read block (bpb ds, 2, 1, return);
  IF return <> 0
    THEN lesefehler (return)
  FI.

fat sektor gueltig und pseudo bpb vorhanden:
  TEXT VAR fat start := "1234";
  replace (fat start, 1, bpb.daten [1]);
  replace (fat start, 2, bpb.daten [2]);
  (fat start SUB 2) = ""255"" CAND (fat start SUB 3) = ""255"" CAND
  pseudo bpb vorhanden.

pseudo bpb vorhanden:
  pos (""254""255"", fat start SUB 1) > 0.

pseudo bpb laden:
  INT VAR i;
  FOR i FROM 1 UPTO 15 REP
    bpb.daten [i] := bpb puffer ISUB i
  PER.

bpb puffer:
  IF pseudo bpb name = ""255""
    THEN bpb type 255
    ELSE bpb type 254
  FI.

pseudo bpb name:
  fat start SUB 1.

ueberpruefe bpb auf gueltigkeit:
  IF bytes per sector <> 512
    THEN error stop ("DOS Format nicht implementiert (unzulässige Sektorgröße)")
  FI;
  IF (fat sectors > 64)
    THEN error stop ("ungültige DOS Disk (BPB)")
  FI.

globale variablen initialisieren:
  sectors per track  := bpb byte (25) * 256 + bpb byte (24);
  heads              := bpb byte (27) * 256 + bpb byte (26);
  begin of data area := real (reserved sectors + fat copies * fat sectors + dir sectors).

dump schreiben:
  dump ("Sektoren pro Cluster", sectors per cluster);
  dump ("Fat Kopien          ", fat copies);
  dump ("Dir Sektoren        ", dir sectors);
  dump ("Media Descriptor    ", media descriptor);
  dump ("Sektoren pro Fat    ", fat sectors);
  dump ("Fat Anfang (0)      ", begin of fat (0));
  dump ("Fat Einträge        ", fat entrys);
  dump ("Dir Anfang          ", begin of dir).

END PROC open dos disk;

PROC lesefehler (INT CONST fehler code):
  error stop (fehlertext).

fehlertext:
  SELECT fehler code OF
    CASE 1: "Diskettenlaufwerk nicht betriebsbereit"
    CASE 2: "Lesefehler"
    OTHERWISE "Lesefehler " + text (fehler code)
  END SELECT.

END PROC lesefehler;

TEXT VAR konvertier puffer := "12";

INT PROC bpb byte (INT CONST byte no):
  replace (konvertier puffer, 1, bpb.daten [byte no DIV 2 + 1]);
  code (konvertier puffer SUB puffer pos).

puffer pos:
  IF even byte no
    THEN 1
    ELSE 2
  FI.

even byte no:
  (byte no MOD 2) = 0.

END PROC bpb byte;

INT PROC bytes per sector:
  bpb byte (12) * 256 + bpb byte (11)

END PROC bytes per sector;

INT PROC sectors per cluster:
  bpb byte (13)

END PROC sectors per cluster;

INT PROC reserved sectors:
  bpb byte (15) * 256 + bpb byte (14)

END PROC reserved sectors;

INT PROC fat copies:
  bpb byte (16)

END PROC fat copies;

INT PROC dir sectors:
  dir entrys DIV dir entrys per sector.

dir entrys:
  bpb byte (18) * 256 + bpb byte (17).

dir entrys per sector:
  16.

END PROC dir sectors;

REAL PROC dos sectors:
  real (bpb byte (20)) * 256.0 + real (bpb byte (19))

END PROC dos sectors;

INT PROC media descriptor:
  bpb byte (21)

END PROC media descriptor;

INT PROC fat sectors:
  bpb byte (23) * 256 + bpb byte (22)

END PROC fat sectors;

INT PROC begin of fat (INT CONST fat copy no):
  (* 0 <= fat copy no <= fat copies - 1 *)
  reserved sectors + fat copy no * fat sectors

END PROC begin of fat;

INT PROC fat entrys:
  anzahl daten cluster + 2.

anzahl daten cluster:
  int ((dos sectors - tabellen sektoren) / real (sectors per cluster)).

tabellen sektoren:
  real (reserved sectors + fat copies * fat sectors + dir sectors).

END PROC fat entrys;

INT PROC begin of dir:
  reserved sectors + fat copies * fat sectors.

END PROC begin of dir;

REAL PROC begin of cluster (REAL CONST cluster no):
  begin of data area + (cluster no - 2.0) * real (sectors per cluster)

END PROC begin of cluster;

INT PROC cluster size:
  512 * sectors per cluster

END PROC cluster size;

BOOL PROC bpb exists (INT CONST no):

  exists ("bpb ds") AND no > 0 AND no < 4.

END PROC bpb exists;

PROC write bpb (INT CONST no):
  INT VAR return;
  write block (old ("bpb ds"), no + 1, 0, 0, return);
  IF return <> 0
    THEN error stop ("Schreibfehler")
  FI.

END PROC write bpb;

(* Da DOS-Partitionen maximal 32 MByte groß sein können, können die Blocknummern
   durch 16 BIT unsigned Integer dargestellt werden. Die Werte die die 'eublock'-
   Prozeduren liefern sind als solche zu verstehen                          *)

INT PROC eu block (INT CONST dos block no):
  IF hd version
    THEN dos block no
    ELSE dos block no floppy format
  FI.

dos block no floppy format:
  IF page format
    THEN head * eu sectors per head + trac * eu sectors + sector
    ELSE head * eu sectors + trac * abs (eu heads) * eu sectors + sector
  FI.

page format:
  eu heads < 0.

sector:
  dos block no MOD sectors per track.

trac:
  (dos block no DIV sectors per track) DIV heads.

head:
  (dos block no DIV sectors per track) MOD heads.

eu sectors per head:
  eu sectors * eu tracks.

eu sectors:
  eu last sector - eu first sector + 1.

END PROC eu block;

INT PROC eu block (REAL CONST dos block no):
  eublock (low word (dos block no)).

END PROC eublock;

PROC bpb dump modus (BOOL CONST status):
  bpb dump flag := status

END PROC bpb dump modus;

END PACKET dos disk;