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 tape_reader: proc (p, n);
27
28 dcl p ptr,
29 n fixed bin (18);
30
31 dcl (cur_p, cur_dp, cur_tp) ptr,
32 exprec fixed bin (18),
33 datap ptr,
34 count fixed bin (18),
35 words_left fixed bin (18),
36 copy_words fixed bin (18),
37 nrecs fixed bin,
38 retries fixed bin,
39 majstat fixed bin (5),
40 checksum bit (36) aligned,
41 i fixed bin;
42
43 dcl tape_count fixed bin static;
44
45 dcl data (copy_words) fixed bin (35) based;
46
47 dcl 1 physical_record_buffer$ ext,
48 ( 2 index fixed bin (17),
49 2 pad fixed bin (17)) unal,
50 2 cur_rec (1040) fixed bin;
51
52 dcl (addr, addrel, divide, min, substr) builtin;
53
54 dcl syserr ext entry options (variable),
55 (boot_tape_io$read,
56 boot_tape_io$backspace,
57 boot_tape_io$rewind,
58 tape_checksum_ entry (ptr, ptr),
59 (boot_tape_io$init_tape,
60 boot_tape_io$final_tape)) entry;
61
62
63 %include mstr;
64
65
66
67
68
69 datap = p;
70 count = n;
71
72 cur_p = addr (physical_record_buffer$.cur_rec);
73 cur_dp = addr (cur_p -> mstr.data);
74
75 reader_loop:
76 words_left = divide (cur_p -> mstr_header.data_bits_used, 36, 18, 0) - physical_record_buffer$.index;
77
78 if words_left = 0 then do;
79 cur_tp = addr (cur_p -> mstr.trail);
80 exprec = cur_tp -> mstr_trailer.tot_rec + 1;
81 call get_next_buffer;
82 physical_record_buffer$.index = 0;
83 go to reader_loop;
84 end;
85
86 copy_words = min (count, words_left);
87 count = count - copy_words;
88 if copy_words > 0 then datap -> data = addrel (cur_dp, physical_record_buffer$.index) -> data;
89
90 physical_record_buffer$.index = physical_record_buffer$.index + copy_words;
91
92 datap = addrel (datap, copy_words);
93 if count > 0 then go to reader_loop;
94
95 return;
96
97
98
99
100 get_next_buffer: proc;
101
102
103 retries = 0;
104
105 retry: if retries > 64 then
106 call syserr (1, "tape_reader: Unable to read system tape.");
107 nrecs = 0;
108
109 again: nrecs = nrecs + 1;
110
111 eof: call do_io (boot_tape_io$read, "001100000010000"b);
112 if majstat ^= 0 then do;
113 if majstat = 3 then
114 go to again;
115 if majstat = 4 then
116 go to eof;
117 if majstat = 11 then
118 go to again;
119 end;
120
121 if cur_p -> mstr_header.c1 ^= header_c1 |
122 cur_p -> mstr_header.c2 ^= header_c2 |
123 cur_tp -> mstr_trailer.c1 ^= trailer_c1 |
124 cur_tp -> mstr_trailer.c2 ^= trailer_c2 then
125 go to again;
126
127 call tape_checksum_ (cur_p, addr (checksum));
128 if checksum ^= cur_p -> mstr_header.checksum then
129 go to again;
130 if cur_p -> mstr_header.flags.admin then
131 go to admin_record;
132 validate:
133 if cur_tp -> mstr_trailer.tot_rec < exprec then
134 go to retry;
135 if cur_tp -> mstr_trailer.tot_rec > exprec then
136 go to back_up;
137
138 return;
139
140
141 admin_record:
142 if cur_p -> mstr_header.flags.eor then
143 go to validate;
144 go to again;
145
146
147 back_up: retries = retries + 1;
148 do i = 1 to nrecs + 2;
149 call do_io (boot_tape_io$backspace, "000110000000000"b);
150 if majstat = 5 then go to retry;
151 end;
152 go to retry;
153
154 end get_next_buffer;
155
156
157
158 init: entry;
159
160 call boot_tape_io$init_tape;
161 tape_count = 0;
162 return;
163
164
165 final: entry;
166
167 call do_io (boot_tape_io$rewind, (15)"0"b);
168 call boot_tape_io$final_tape;
169 return;
170
171
172
173 do_io: proc (e, s);
174
175 dcl e entry (fixed bin (5)),
176 s bit (15) aligned;
177
178
179 call: call e (majstat);
180
181 if majstat ^= 0 then
182 if majstat >= 16 then
183 go to call;
184 else if substr (s, majstat, 1) then
185 return;
186 else if majstat <= 2 then
187 go to call;
188 else
189 call syserr (1, "tape_reader: bad major status = ^o", majstat);
190
191 return;
192
193
194 end do_io;
195 ^L
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 end tape_reader;