Commit | Line | Data |
---|---|---|
d52f1552 TL |
1 | # define RP6CYL 815 /* no. RP06 cylinders/pack */ |
2 | # define RP6TRK 19 /* no. tracks/cyl */ | |
3 | # define RP6SEC 22 /* no. sectors/track */ | |
4 | # define RP6ST (RP6SEC*RP6TRK) /* no. sectors/cyl */ | |
5 | # define MAXSEC (RP6CYL*RP6TRK*RP6SEC) /* sectors/pack */ | |
6 | # define M0 0x20010000 /* phys addr MBA 0 */ | |
7 | # define M0_cr (M0+4) /* MBA 0 control reg addr */ | |
8 | # define M0_sr (M0+8) /* mba 0 status reg */ | |
9 | # define M0_map (M0+0x800) /* start MBA 0 map reg's */ | |
10 | # define M0_var (M0+0xc) /* MBA 0 virt addr reg */ | |
11 | # define M0_bc (M0+0x10) /* MBA 0 byte count reg */ | |
12 | # define MBAinit 01 /* MBA init bit */ | |
13 | /* */ | |
14 | # define RP (M0+0x400) /* base for RP06 reg's, drive 0 */ | |
15 | /* */ | |
16 | # define RP_cr 0 /* RP06 control reg offset, longword */ | |
17 | # define RP_sr 1 /* RP06 status reg offset */ | |
18 | # define RP_er1 02 /* RP error reg 1 */ | |
19 | # define RP_stk 5 /* RP06 sector/track reg offset */ | |
20 | # define RP_er2 010 /* RP error reg 2 */ | |
21 | # define RP_off 011 /* RP offset reg */ | |
22 | # define RP_cyl 012 /* RP06 cylinder reg offset */ | |
23 | # define RP_er3 015 /* RP error reg 3 */ | |
24 | /* */ | |
25 | # define RP_GO 1 /* go bit */ | |
26 | # define RP_RED 070 /* RP06 read function code */ | |
27 | # define RP_DC 010 /* drive clear function code */ | |
28 | # define RP_FMT 0x1000 /* format bit for offset reg */ | |
29 | # define RP_RIP 020 /* Read-in Preset RP06 function code */ | |
30 | # define RP_DRY 0200 /* drive ready, status reg */ | |
31 | # define RP_ERR 040000 /* composite error, status reg */ | |
32 | # define RP_MOL 0x1000 /* medium-online bit in status reg */ | |
33 | /* */ | |
34 | # define RXCS 32 /* receiver control/staus */ | |
35 | # define RXDB 33 /* receiver data */ | |
36 | # define TXCS 34 /* transmitter control/status */ | |
37 | # define TXDB 35 /* transmitter data */ | |
38 | # define RXCS_DONE 0x80 /* receiver done */ | |
39 | # define TXCS_RDY 0x80 /* transmitter ready */ | |
40 | /* */ | |
41 | # define BLKSIZ 512 | |
42 | # define MAXUNI 1 | |
43 | # define NL 012 | |
44 | # define CR 015 | |
45 | /* */ | |
46 | char input[BLKSIZ] ; /* disc input buffer */ | |
47 | struct { int reg , reg2 , reg3 ; } ; | |
48 | int count , dskoff , dunit , error , numbyt ; | |
49 | unsigned short bytoff ; | |
50 | int *RPptr ; /* ptr to start of RP reg's for desired drive */ | |
51 | main() { | |
52 | /* | |
53 | * Stand-alone program to dump RP06 disk to VAX LSI console | |
54 | * printer in hex format. | |
55 | * User specifies disk unit, start disk block and no. of blocks. | |
56 | */ | |
57 | int getcon() , putstr() , a2l() , l2a() ; | |
58 | ||
59 | putlin("ddump : disk-to-console hex dump") ; | |
60 | putnl() ; | |
61 | ||
62 | dun : | |
63 | putstr("disk unit : "); | |
64 | getcon(input) ; | |
65 | dunit = a2l(input) ; | |
66 | if ((dunit > MAXUNI) || (dunit < 0)) goto dun ; | |
67 | ||
68 | doff : | |
69 | putstr("start disk block : ") ; | |
70 | if (getcon(input)) goto fini ; | |
71 | dskoff = a2l(input) ; | |
72 | if (dskoff < 0) goto fini ; | |
73 | if (dskoff > MAXSEC-1) goto doff ; | |
74 | ||
75 | gknt : | |
76 | putstr("no. blocks : ") ; | |
77 | if (getcon(input)) goto fini ; | |
78 | count = a2l(input) ; | |
79 | if (count < 0) goto gknt ; | |
80 | if (count == 0) count = 1 ; | |
81 | ||
82 | gbyt : | |
83 | putstr("no. bytes : ") ; | |
84 | if (getcon(input)) goto fini ; | |
85 | numbyt = a2l(input) ; | |
86 | if ((numbyt < 0) || (numbyt > BLKSIZ)) goto gbyt ; | |
87 | if (numbyt == 0) numbyt = BLKSIZ ; | |
88 | ||
89 | error = 0 ; | |
90 | ||
91 | if (init()) goto dun ; | |
92 | ||
93 | putlin(" HI < - - LO") ; | |
94 | nullcon(3) ; | |
95 | putnl() ; | |
96 | ||
97 | while ((error == 0) && (count--)) { | |
98 | if (dread()) { | |
99 | putlin("disk i/o error") ; | |
100 | ioerr : | |
101 | error++ ; | |
102 | continue ; | |
103 | } | |
104 | if (prblk()) { | |
105 | putlin("console i/o error") ; | |
106 | goto ioerr ; | |
107 | } | |
108 | putnl() ; | |
109 | putnl() ; | |
110 | dskoff++ ; /* next sector */ | |
111 | } | |
112 | ||
113 | goto doff ; | |
114 | ||
115 | fini : | |
116 | return(0) ; | |
117 | } | |
118 | ||
119 | /* */ | |
120 | ||
121 | putstr(csp) | |
122 | register char *csp ; | |
123 | { | |
124 | if (putcon(csp)) return(-1) ; | |
125 | return(0) ; | |
126 | } | |
127 | ||
128 | /* */ | |
129 | ||
130 | putlin(sptr) | |
131 | register char *sptr ; | |
132 | { | |
133 | if (putcon(sptr)) return(-1) ; | |
134 | if (putnl()) return(-1) ; | |
135 | return(0) ; | |
136 | } | |
137 | ||
138 | /* */ | |
139 | ||
140 | nullcon(nn) | |
141 | register nn ; | |
142 | { | |
143 | /* | |
144 | * Output 'nn' nulls to console terminal - | |
145 | * used for delay. | |
146 | */ | |
147 | while (nn--) putc(0) ; | |
148 | } | |
149 | ||
150 | /* */ | |
151 | ||
152 | putnl() | |
153 | { | |
154 | if (putcon("\r\n")) return(-1) ; | |
155 | return(0) ; | |
156 | } | |
157 | ||
158 | /* */ | |
159 | ||
160 | putcon(csp) | |
161 | register char *csp ; | |
162 | { | |
163 | /* | |
164 | * Function to output null-terminated string pointed to | |
165 | * by 'csp' to the VAX LSI terminal. | |
166 | */ | |
167 | register c ; | |
168 | ||
169 | c = 0 ; | |
170 | while (c = (*csp++)) putc(c) ; | |
171 | return(0) ; | |
172 | } | |
173 | ||
174 | /* */ | |
175 | ||
176 | putc(c) | |
177 | { | |
178 | /* wait for LSI printer to be ready */ | |
179 | while ((mfpr(TXCS) & TXCS_RDY) == 0) ; | |
180 | /* output character */ | |
181 | mtpr(TXDB,c&0177) ; | |
182 | } | |
183 | ||
184 | /* */ | |
185 | ||
186 | getcon(cs) | |
187 | register char *cs ; | |
188 | { | |
189 | /* | |
190 | * Function to return char's from VAX LSI keyboard to | |
191 | * char array 'cs' - input stops when CR or LF received - | |
192 | * null char appended to end of input | |
193 | */ | |
194 | register int c , c2 ; | |
195 | int getc() ; | |
196 | ||
197 | inloop : | |
198 | c = getc() ; /* get 1 char from terminal */ | |
199 | putc(c) ; /* echo char */ | |
200 | if ((c == NL) || (c == CR)) { | |
201 | putc(CR) ; | |
202 | putc(0) ; | |
203 | putc(NL) ; | |
204 | (*cs++) = '\0' ; | |
205 | return(0) ; | |
206 | } | |
207 | else { | |
208 | (*cs++) = c ; | |
209 | goto inloop ; | |
210 | } | |
211 | } | |
212 | ||
213 | /* */ | |
214 | ||
215 | getc() | |
216 | { | |
217 | /* | |
218 | * Return char from VAX LSI terminal char buffer | |
219 | */ | |
220 | int mfpr() ; | |
221 | ||
222 | /* Wait for receiver done (user entered char) | |
223 | */ | |
224 | while ((mfpr(RXCS) & RXCS_DONE) == 0) ; | |
225 | return (mfpr(RXDB) & 0177) ; /* return char from receiver buffer */ | |
226 | } | |
227 | ||
228 | /* */ | |
229 | ||
230 | mtpr(regno,value) | |
231 | { | |
232 | asm(" mtpr 8(ap),4(ap)") ; | |
233 | } | |
234 | ||
235 | /* */ | |
236 | ||
237 | mfpr(regno) | |
238 | { | |
239 | asm(" mfpr 4(ap),r0") ; | |
240 | } | |
241 | ||
242 | /* */ | |
243 | ||
244 | a2l(as) | |
245 | register char *as ; | |
246 | { | |
247 | /* | |
248 | * Convert null-terminated ascii string to binary | |
249 | * and return value. | |
250 | * 1st char in string : | |
251 | * 0 -> octal | |
252 | * x -> hex | |
253 | * else decimal | |
254 | */ | |
255 | register value , base , sign , digit ; | |
256 | ||
257 | digit = value = sign = 0 ; | |
258 | base = 10 ; /* default base */ | |
259 | ||
260 | aloop : | |
261 | if ((digit = (*as++)) == 0) return(value) ; /* null */ | |
262 | ||
263 | if (digit == '-') { | |
264 | sign++ ; | |
265 | goto aloop ; | |
266 | } | |
267 | ||
268 | if (digit == '0') base = 8 ; /* octal base */ | |
269 | else { if (digit == 'x') base = 16 ; /* hex base */ | |
270 | else value = (digit-060) ; /* 060 = '0' */ | |
271 | } | |
272 | ||
273 | while (digit = (*as++)) { | |
274 | if (digit < '0') return(0) ; | |
275 | switch (base) { | |
276 | case 8 : { | |
277 | if (digit > '7') return(0) ; | |
278 | digit -= 060 ; | |
279 | break ; | |
280 | } | |
281 | case 10 : { | |
282 | if (digit > '9') return(0) ; | |
283 | digit -= 060 ; | |
284 | break ; | |
285 | } | |
286 | case 16 : { | |
287 | if (digit <= '9') { | |
288 | digit -= 060 ; | |
289 | break ; | |
290 | } | |
291 | if ((digit >= 'A') && (digit <= 'F')) { | |
292 | digit = (digit - 0101 + 10) ; | |
293 | break ; | |
294 | } | |
295 | if ((digit >= 'a') && (digit <= 'f')) { | |
296 | digit = digit - 0141 + 10 ; | |
297 | break ; | |
298 | } | |
299 | return(0) ; | |
300 | break ; | |
301 | } | |
302 | } | |
303 | value = (value * base) + digit ; | |
304 | } | |
305 | return (sign ? -value : value) ; | |
306 | } | |
307 | ||
308 | /* */ | |
309 | ||
310 | init() { | |
311 | /* | |
312 | * Initialization. | |
313 | * Initialize MBA 0 (disk) . | |
314 | * Set up MBA 0 map register to map a | |
315 | * transfer of 'BLKSIZ' bytes. | |
316 | */ | |
317 | register int page , *mp0 ; | |
318 | ||
319 | M0_cr->reg = MBAinit ; /* MBA 0 init */ | |
320 | RPptr = RP + (dunit * 32 * 4) ; /* start of RP reg's for drive */ | |
321 | if ((*(RPptr+RP_sr) & RP_MOL) == 0) { | |
322 | putlin("unit not online") ; | |
323 | return(-1) ; | |
324 | } | |
325 | *(RPptr+RP_cr) = RP_RIP | RP_GO ; /* drive preset - sets vv */ | |
326 | *(RPptr+RP_off) = RP_FMT ; /* set format bit */ | |
327 | ||
328 | bytoff = (int)(&input[0])&0777 ; /* byte offset of buffer addr */ | |
329 | page = ((int)&input[0] >> 9) & 07777777 ; /* start page of buffer */ | |
330 | mp0 = M0_map ; | |
331 | (*mp0++) = 0x80000000 | page++ ; | |
332 | (*mp0++) = 0x80000000 | page++ ; | |
333 | (*mp0++) = 0 ; | |
334 | return(0) ; | |
335 | } | |
336 | ||
337 | /* */ | |
338 | ||
339 | dread() | |
340 | { | |
341 | /* | |
342 | * Function to read 'BLKSIZ' bytes to buffer 'input[]'. | |
343 | */ | |
344 | register int i , j ; | |
345 | ||
346 | *(RPptr+RP_cr) = RP_DC | RP_GO ; /* RP06 drive clear function code */ | |
347 | *(RPptr+RP_cyl) = dskoff/RP6ST ; /* cylinder no. */ | |
348 | i = dskoff%RP6ST ; | |
349 | j = (i/RP6SEC)<<8 ; /* track */ | |
350 | *(RPptr+RP_stk) = j | (i%RP6SEC) ; /* sector : track */ | |
351 | M0_bc->reg = (-BLKSIZ) ; | |
352 | M0_var->reg = bytoff ; /* virt addr reg = map no. + byte off */ | |
353 | *(RPptr+RP_cr) = RP_RED | RP_GO ; /* read */ | |
354 | ||
355 | dwait() ; /* wait for i/o to finish */ | |
356 | if (derror()) return(-1) ; /* error */ | |
357 | return(0) ; /* normal return */ | |
358 | } | |
359 | ||
360 | /* */ | |
361 | ||
362 | dwait() { | |
363 | /* | |
364 | * Function to wait MBA 0 RP06 disc unit to be ready. | |
365 | */ | |
366 | while ((*(RPptr+RP_sr)&RP_DRY) == 0) ; | |
367 | } | |
368 | ||
369 | /* */ | |
370 | ||
371 | derror() | |
372 | { | |
373 | /* | |
374 | * Function to check for MBA 0 RP06 error. | |
375 | */ | |
376 | if (*(RPptr+RP_sr) & RP_ERR) return(-1) ; | |
377 | return(0) ; | |
378 | } | |
379 | ||
380 | /* */ | |
381 | ||
382 | halt() | |
383 | { | |
384 | asm(" halt") ; | |
385 | } | |
386 | ||
387 | /* */ | |
388 | ||
389 | l2a(val,rptr) | |
390 | register int val ; | |
391 | register char *rptr ; | |
392 | { | |
393 | register int i ; | |
394 | register char *tp ; | |
395 | int knt ; | |
396 | char tmp[20] , sign ; | |
397 | ||
398 | knt = sign = 0 ; | |
399 | if (val < 0) { | |
400 | sign++ ; | |
401 | val = (-val) ; | |
402 | } | |
403 | ||
404 | tp = tmp ; | |
405 | loop : | |
406 | knt++ ; | |
407 | i = val/10 ; /* quotient & base 10 */ | |
408 | (*tp++) = val%10 + '0' ; /* ascii remainder */ | |
409 | val = i ; | |
410 | if (val == 0) { | |
411 | /* done dividing */ | |
412 | if (sign) { knt++ ; (*tp++) = '-' ; } | |
413 | for (i = knt ; i ; i--) | |
414 | (*rptr++) = tmp[i-1] ; | |
415 | (*rptr++) = '\0' ; | |
416 | return(knt) ; | |
417 | } | |
418 | else goto loop ; | |
419 | } | |
420 | ||
421 | /* */ | |
422 | ||
423 | echo(lngword) | |
424 | register int lngword ; | |
425 | { | |
426 | char tmp[30] ; | |
427 | ||
428 | l2a(lngword,tmp) ; | |
429 | putlin(tmp) ; | |
430 | } | |
431 | ||
432 | /* */ | |
433 | ||
434 | prblk() | |
435 | { | |
436 | /* | |
437 | * Print 512 bytes on VAX LSI console as hex | |
438 | * characters. | |
439 | * Translate bytes in 'input[]' to hex char's | |
440 | * and out to console, 64 char's per line. | |
441 | */ | |
442 | register int i , j ; | |
443 | int k ; | |
444 | char c , *hp , *fr ; | |
445 | char tmp[1025] , ltmp[65] ; | |
446 | ||
447 | ltmp[64] = '\0' ; | |
448 | hp = "block # \0\0\0\0\0\0\0" ; | |
449 | l2a(dskoff,&hp[8]) ; | |
450 | putstr(hp) ; | |
451 | putnl() ; | |
452 | putnl() ; | |
453 | ||
454 | hxcnvt(input,512,tmp) ; /* convert bytes to hex char's */ | |
455 | ||
456 | j = numbyt ; | |
457 | for (i = 0 ; (i < 1024) && (j > 0) ; i=+64 ) { | |
458 | hp = ltmp ; | |
459 | fr = (&tmp[i+63]) ; | |
460 | for ( k = 32 ; k ; k--) { | |
461 | (*hp++) = *(fr-1) ; | |
462 | (*hp++) = (*fr--) ; | |
463 | fr-- ; | |
464 | } | |
465 | putstr(ltmp) ; | |
466 | putc(CR) ; | |
467 | nullcon(5) ; | |
468 | putc(NL) ; | |
469 | j -= 32 ; | |
470 | } | |
471 | return(0) ; | |
472 | } | |
473 | ||
474 | /* */ | |
475 | ||
476 | hxcnvt(in,knt,out) | |
477 | register char *in , *out ; | |
478 | int knt ; | |
479 | { | |
480 | /* | |
481 | * Convert 'knt' bytes in char array 'in' to 'knt*2' | |
482 | * hex char's and store in char array 'out'. | |
483 | */ | |
484 | register unsigned int bit4 , byte ; | |
485 | ||
486 | byte = 0 ; | |
487 | while (knt--) { | |
488 | byte = (*in++) ; | |
489 | bit4 = (byte>>4) & 017 ; | |
490 | (*out++) = (bit4<10?bit4+0x30:bit4+0x57) ; | |
491 | bit4 = byte & 017 ; | |
492 | (*out++) = (bit4<10?bit4+0x30:bit4+0x57) ; | |
493 | } | |
494 | return(0) ; | |
495 | } |