First Commit of my working state
[simh.git] / S3 / s3_disk.c
1 /* s3_disk.c: IBM 5444 Disk Drives
2
3 Copyright (c) 2001-2005, Charles E. Owen
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Charles E. Owen shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Charles E. Owen.
25
26 r1 Removeable disk 1
27 f1 Fixed disk 1
28 r2 Removeable disk 2
29 f2 Fixed disk 2
30
31 25-Apr-03 RMS Revised for extended file support
32 08-Oct-02 RMS Added impossible function catcher
33 */
34
35 #include "s3_defs.h"
36 #include <ctype.h>
37
38 extern uint8 M[];
39 extern int32 IAR[], level;
40 extern FILE *trace;
41 extern int32 debug_reg;
42 char dbuf[DSK_SECTSIZE]; /* Disk buffer */
43 int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data);
44 int32 read_sector(UNIT *uptr, char *dbuf, int32 sect);
45 int32 write_sector(UNIT *uptr, char *dbuf, int32 sect);
46 t_stat r1_svc (UNIT *uptr);
47 t_stat r1_boot (int32 unitno, DEVICE *dptr);
48 t_stat r1_attach (UNIT *uptr, char *cptr);
49 t_stat r1_reset (DEVICE *dptr);
50 t_stat f1_svc (UNIT *uptr);
51 t_stat f1_boot (int32 unitno, DEVICE *dptr);
52 t_stat f1_attach (UNIT *uptr, char *cptr);
53 t_stat f1_reset (DEVICE *dptr);
54 t_stat r2_svc (UNIT *uptr);
55 t_stat r2_boot (int32 unitno, DEVICE *dptr);
56 t_stat r2_attach (UNIT *uptr, char *cptr);
57 t_stat r2_reset (DEVICE *dptr);
58 t_stat f2_svc (UNIT *uptr);
59 t_stat f2_boot (int32 unitno, DEVICE *dptr);
60 t_stat f2_attach (UNIT *uptr, char *cptr);
61 t_stat f2_reset (DEVICE *dptr);
62 extern int32 GetMem(int32 addr);
63 extern int32 PutMem(int32 addr, int32 data);
64
65 char opstr[5][5] = { "SIO", "LIO", "TIO", "SNS", "APL" };
66
67 int32 DDAR[2]; /* Data address register */
68 int32 DCAR[2]; /* Disk Control Address Register */
69 int32 diskerr[2] = { 0, 0 }; /* Error status */
70 int32 notrdy[2] = { 0, 0 }; /* Not ready error */
71 int32 seekbusy[2] = { 0, 0 }; /* Drive busy flags */
72 int32 seekhead[2] = { 0, 0 }; /* Disk head 0,1 */
73 int32 found[2] = { 0, 0 }; /* Scan found bit */
74 int32 RIDsect[2] = { 0, 0 }; /* for Read ID */
75
76 /* Disk data structures
77
78 xy_dev CDR descriptor
79 xy_unit CDR unit descriptor
80 xy_reg CDR register list
81
82 x = F or R
83 y = 1 or 2
84 */
85
86 UNIT r1_unit = { UDATA (&r1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
87
88 REG r1_reg[] = {
89 { FLDATA (NOTRDY, notrdy[0], 0) },
90 { FLDATA (SEEK, seekbusy[0], 0) },
91 { HRDATA (DAR, DDAR[0], 16) },
92 { HRDATA (CAR, DCAR[0], 16) },
93 { HRDATA (ERR, diskerr[0], 16) },
94 { DRDATA (CYL, r1_unit.u3, 8) },
95 { DRDATA (HEAD, seekhead[0], 8) },
96 { DRDATA (POS, r1_unit.pos, T_ADDR_W), PV_LEFT },
97 { DRDATA (TIME, r1_unit.wait, 24), PV_LEFT },
98 { BRDATA (BUF, dbuf, 8, 8, 256) },
99 { NULL }
100 };
101
102 DEVICE r1_dev = {
103 "R1", &r1_unit, r1_reg, NULL,
104 1, 10, 31, 1, 8, 7,
105 NULL, NULL, &r1_reset,
106 &r1_boot, &r1_attach, NULL
107 };
108
109 UNIT f1_unit = { UDATA (&f1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
110
111 REG f1_reg[] = {
112 { FLDATA (NOTRDY, notrdy[0], 0) },
113 { FLDATA (SEEK, seekbusy[0], 0) },
114 { HRDATA (DAR, DDAR[0], 16) },
115 { HRDATA (CAR, DCAR[0], 16) },
116 { HRDATA (ERR, diskerr[0], 16) },
117 { DRDATA (CYL, f1_unit.u3, 8) },
118 { DRDATA (HEAD, seekhead[0], 8) },
119 { DRDATA (POS, f1_unit.pos, 32), PV_LEFT },
120 { DRDATA (TIME, f1_unit.wait, 24), PV_LEFT },
121 { BRDATA (BUF, dbuf, 8, 8, 256) },
122 { NULL }
123 };
124
125 DEVICE f1_dev = {
126 "F1", &f1_unit, f1_reg, NULL,
127 1, 10, 31, 1, 8, 7,
128 NULL, NULL, &f1_reset,
129 &f1_boot, &f1_attach, NULL
130 };
131
132 UNIT r2_unit = { UDATA (&r2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
133
134 REG r2_reg[] = {
135 { FLDATA (NOTRDY, notrdy[1], 0) },
136 { FLDATA (SEEK, seekbusy[1], 0) },
137 { HRDATA (DAR, DDAR[1], 16) },
138 { HRDATA (CAR, DCAR[1], 16) },
139 { HRDATA (ERR, diskerr[1], 16) },
140 { DRDATA (CYL, r2_unit.u3, 8) },
141 { DRDATA (HEAD, seekhead[1], 8) },
142 { DRDATA (POS, r2_unit.pos, 32), PV_LEFT },
143 { DRDATA (TIME, r2_unit.wait, 24), PV_LEFT },
144 { BRDATA (BUF, dbuf, 8, 8, 256) },
145 { NULL }
146 };
147
148 DEVICE r2_dev = {
149 "R2", &r2_unit, r2_reg, NULL,
150 1, 10, 31, 1, 8, 7,
151 NULL, NULL, &r2_reset,
152 &r2_boot, &r2_attach, NULL
153 };
154
155 UNIT f2_unit = { UDATA (&f2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
156
157 REG f2_reg[] = {
158 { FLDATA (NOTRDY, notrdy[1], 0) },
159 { FLDATA (SEEK, seekbusy[1], 0) },
160 { HRDATA (DAR, DDAR[1], 16) },
161 { HRDATA (CAR, DCAR[1], 16) },
162 { HRDATA (ERR, diskerr[1], 16) },
163 { DRDATA (CYL, f2_unit.u3, 8) },
164 { DRDATA (HEAD, seekhead[1], 8) },
165 { DRDATA (POS, f2_unit.pos, 32), PV_LEFT },
166 { DRDATA (TIME, f2_unit.wait, 24), PV_LEFT },
167 { BRDATA (BUF, dbuf, 8, 8, 256) },
168 { NULL }
169 };
170
171 DEVICE f2_dev = {
172 "F2", &f2_unit, f2_reg, NULL,
173 1, 10, 31, 1, 8, 7,
174 NULL, NULL, &f2_reset,
175 &f2_boot, &f2_attach, NULL
176 };
177
178 /* -------------------------------------------------------------------- */
179
180 /* 5444: master routines */
181
182 int32 dsk1 (int32 op, int32 m, int32 n, int32 data)
183 {
184 int32 r;
185
186 r = dsk(0, op, m, n, data);
187 return (r);
188 }
189
190 int32 dsk2 (int32 op, int32 m, int32 n, int32 data)
191 {
192 int32 r;
193
194 r = dsk(1, op, m, n, data);
195 return (r);
196 }
197
198 /* 5444: operational routine */
199
200 int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data)
201 {
202 int32 iodata, i, j, u, sect, nsects, addr, r, c, res;
203 int32 F, C, S, N, usave;
204 UNIT *uptr;
205
206 u = m;
207 if (disk == 1) u += 2;
208 F = GetMem(DCAR[disk]+0); /* Flag bits */
209 C = GetMem(DCAR[disk]+1); /* Cylinder */
210 S = GetMem(DCAR[disk]+2); /* Sector */
211 N = GetMem(DCAR[disk]+3); /* Number of sectors */
212 switch (u) {
213 case 0:
214 uptr = r1_dev.units;
215 break;
216 case 1:
217 uptr = f1_dev.units;
218 break;
219 case 2:
220 uptr = r2_dev.units;
221 break;
222 case 3:
223 uptr = f2_dev.units;
224 break;
225 default:
226 break;
227 }
228 if (debug_reg & 0x02)
229 fprintf(trace, "==> %04X %s %01X,%d,%04X DAR=%04X CAR=%04X C=%02X, S=%02X, N=%02X\n",
230 IAR[level],
231 opstr[op],
232 m, n, data,
233 DDAR[disk],
234 DCAR[disk],
235 C, S, N);
236
237 switch (op) {
238
239 /* SIO 5444 */
240 case 0:
241 if ((uptr->flags & UNIT_ATT) == 0)
242 return SCPE_UNATT;
243 diskerr[disk] = 0; /* SIO resets errors */
244 found[disk] = 0; /* ... and found bit */
245 iodata = 0;
246 switch (n) {
247 case 0x00: /* Seek */
248 if (S & 0x80)
249 seekhead[disk] = 1;
250 else
251 seekhead[disk] = 0;
252 if (S & 1) {
253 uptr -> u3 += N;
254 } else {
255 uptr -> u3 -= N;
256 }
257 if (uptr -> u3 < 0)
258 uptr -> u3 = 0;
259 if (uptr -> u3 > 203) {
260 uptr -> u3 = 0;
261 diskerr[disk] |= 0x0100;
262 if (debug_reg & 0x02)
263 fprintf(trace, "==> Seek Past End of Disk\n");
264 }
265
266 /*sim_activate(uptr, uptr -> wait);*/
267 sim_activate(uptr, 1);
268
269 /* Seek arms are the same for both disks on a drive:
270 update the other arm */
271
272 usave = uptr -> u3;
273 if (u == 0) uptr = f1_dev.units;
274 if (u == 1) uptr = r1_dev.units;
275 if (u == 2) uptr = f2_dev.units;
276 if (u == 3) uptr = r2_dev.units;
277 uptr -> u3 = usave;
278
279 seekbusy[disk] = 1;
280 iodata = SCPE_OK;
281 break;
282
283 case 0x01: /* Read */
284 switch (data) {
285 case 0: /* Read data */
286 sect = (S >> 2) & 0x3F;
287 nsects = N + 1;
288 addr = DDAR[disk];
289
290 for (i = 0; i < nsects; i++) {
291 r = read_sector(uptr, dbuf, sect);
292 if (r != 1 || uptr->u3 != C) {
293 diskerr[disk] |= 0x0800;
294 break;
295 }
296 for (j = 0; j < DSK_SECTSIZE; j++) {
297 PutMem(addr, dbuf[j]);
298 addr++;
299 }
300
301 if ((sect == 55) ) { /* HJS MODS */
302 S = sect;
303 N = nsects - i - 2;
304 if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
305 DDAR[disk] = addr & 0xFFFF; /* HJS mod */
306 PutMem(DCAR[disk]+2, S << 2);
307 PutMem(DCAR[disk]+3, N);
308 sim_activate(uptr, 1);
309 iodata = SCPE_OK;
310 break;
311 }
312
313 sect++;
314 S = sect - 1;
315 N = nsects - i - 2;
316 if (sect == 24)
317 sect = 32;
318 }
319 DDAR[disk] = addr & 0xFFFF; /* HJS mod */
320 PutMem(DCAR[disk]+2, S << 2);
321 PutMem(DCAR[disk]+3, N);
322 /*sim_activate(uptr, uptr -> wait);*/
323 sim_activate(uptr, 1);
324 iodata = SCPE_OK;
325 break;
326 case 1: /* Read ID */
327 if (uptr -> u3 > 0 && uptr -> u3 < 4)
328 PutMem(DCAR[disk], 1);
329 else
330 PutMem(DCAR[disk], 0);
331 PutMem(DCAR[disk]+1, uptr -> u3);
332 PutMem(DCAR[disk]+2, RIDsect[disk]);
333 RIDsect[disk]++;
334 if (RIDsect[disk] > 23)
335 RIDsect[disk] = 32;
336 if (RIDsect[disk] > 55)
337 RIDsect[disk] = 0;
338 break;
339 case 2: /* Read Diagnostic */
340 iodata = STOP_INVDEV;
341 break;
342 case 3: /* Verify */
343 sect = (S >> 2) & 0x3F;
344 nsects = N + 1;
345 addr = DDAR[disk];
346 for (i = 0; i < nsects; i++) {
347 r = read_sector(uptr, dbuf, sect);
348 if (r != 1 || uptr->u3 != C) {
349 diskerr[disk] |= 0x0800;
350 break;
351 }
352 if ((sect == 55) ) { /* HJS MODS */
353 S = sect;
354 N = nsects - i - 2;
355 if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
356 DDAR[disk] = addr & 0xFFFF;
357 PutMem(DCAR[disk]+2, S << 2);
358 PutMem(DCAR[disk]+3, N);
359 sim_activate(uptr, 1);
360 iodata = SCPE_OK;
361 break;
362 }
363 sect++;
364 S = sect - 1;
365 N = nsects - i - 2;
366 if (sect == 24)
367 sect = 32;
368 }
369 DDAR[disk] = addr & 0xFFFF;
370 PutMem(DCAR[disk]+2, S << 2);
371 PutMem(DCAR[disk]+3, N);
372 /*sim_activate(uptr, uptr -> wait);*/
373 sim_activate(uptr, 1);
374 break;
375 default:
376 return STOP_INVDEV;
377 }
378 break;
379 case 0x02: /* Write */
380 switch (data) {
381 case 0: /* Write Data */
382 sect = (S >> 2) & 0x3F;
383 nsects = N + 1;
384 addr = DDAR[disk];
385 for (i = 0; i < nsects; i++) {
386 for (j = 0; j < DSK_SECTSIZE; j++) {
387 dbuf[j] = GetMem(addr);
388 addr++;
389 }
390 r = write_sector(uptr, dbuf, sect);
391 if (r != 1 || uptr->u3 != C) {
392 diskerr[disk] |= 0x0400;
393 break;
394 }
395 if ((sect == 55) ) { /* HJS MODS */
396 S = sect;
397 N = nsects - i - 2;
398 if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
399 DDAR[disk] = addr & 0xFFFF;
400 PutMem(DCAR[disk]+2, S << 2);
401 PutMem(DCAR[disk]+3, N);
402 sim_activate(uptr, 1);
403 iodata = SCPE_OK;
404 break;
405 }
406 sect++;
407 S = sect - 1;
408 N = nsects - i - 2;
409 if (sect == 24)
410 sect = 32;
411 }
412 DDAR[disk] = addr & 0xFFFF; /* HJS mod */
413 PutMem(DCAR[disk]+2, S << 2);
414 PutMem(DCAR[disk]+3, N);
415 /*sim_activate(uptr, uptr -> wait);*/
416 sim_activate(uptr, 1);
417 break;
418 case 1: /* Write identifier */
419 if (seekhead[disk] == 0)
420 S = 0;
421 else
422 S = 0x80;
423 N = 23;
424
425 sect = (S >> 2) & 0x3F;
426 nsects = N + 1;
427 addr = DDAR[disk];
428 for (i = 0; i < nsects; i++) {
429 for (j = 0; j < DSK_SECTSIZE; j++) {
430 dbuf[j] = GetMem(addr);
431 }
432 r = write_sector(uptr, dbuf, sect);
433 if (r != 1) {
434 diskerr[disk] |= 0x0400;
435 break;
436 }
437 if ((sect == 55) ) {
438 S = sect;
439 N = nsects - i - 2;
440 if (N > 0) diskerr[disk] |= 0x0020;
441 DDAR[disk] = addr & 0xFFFF;
442 PutMem(DCAR[disk]+2, S << 2);
443 PutMem(DCAR[disk]+3, N);
444 sim_activate(uptr, 1);
445 iodata = SCPE_OK;
446 break;
447 }
448 sect++;
449 S = sect - 1;
450 N = nsects - i - 2;
451 if (sect == 24)
452 sect = 32;
453 }
454 DDAR[disk] = addr & 0xFFFF;
455 PutMem(DCAR[disk]+2, S << 2);
456 PutMem(DCAR[disk]+3, N);
457 /*sim_activate(uptr, uptr -> wait);*/
458 sim_activate(uptr, 1);
459 break;
460 default:
461 return STOP_INVDEV;
462 }
463 break;
464 case 0x03: /* Scan */
465 sect = (S >> 2) & 0x3F;
466 nsects = N + 1;
467 addr = DDAR[disk];
468 for (i = 0; i < nsects; i++) {
469 r = read_sector(uptr, dbuf, sect);
470 if (r != 1 || uptr->u3 != C) {
471 diskerr[disk] |= 0x0800;
472 break;
473 }
474 res = 0;
475 for (j = 0; j < DSK_SECTSIZE; j++) {
476 c = GetMem(addr);
477 if (j != 0xff) {
478 if (dbuf[i] < c)
479 res = 1;
480 if (dbuf[i] > c)
481 res = 3;
482 }
483 addr++;
484 }
485 if (res == 0)
486 found[disk] = 1;
487 if (res == data)
488 break;
489 if ((sect == 55) ) { /* HJS MODS */
490 S = sect;
491 N = nsects - i - 2;
492 if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
493 DDAR[disk] = addr & 0xFFFF;
494 PutMem(DCAR[disk]+2, S << 2);
495 PutMem(DCAR[disk]+3, N);
496 sim_activate(uptr, 1);
497 iodata = SCPE_OK;
498 break;
499 }
500 sect++;
501 S = sect - 1;
502 N = nsects - i - 2;
503 if (sect == 24)
504 sect = 32;
505 }
506 PutMem(DCAR[disk]+2, S << 2);
507 PutMem(DCAR[disk]+3, N);
508 /*sim_activate(uptr, uptr -> wait);*/
509 sim_activate(uptr, 1);
510 break;
511 default:
512 return STOP_INVDEV;
513 }
514 return iodata;
515
516 /* LIO 5444 */
517 case 1:
518 if ((uptr->flags & UNIT_ATT) == 0)
519 return SCPE_UNATT;
520 switch (n) {
521 case 0x04: /* Data Addr */
522 DDAR[disk] = data;
523 break;
524 case 0x06: /* Control Addr */
525 DCAR[disk] = data;
526 break;
527 default:
528 return STOP_INVDEV;
529 }
530 return SCPE_OK;
531 /* TIO 5444 */
532 case 2:
533 if ((uptr->flags & UNIT_ATT) == 0)
534 return SCPE_UNATT << 16;
535 iodata = 0;
536 switch (n) {
537 case 0x00: /* Error */
538 if (diskerr[disk] || notrdy[disk])
539 iodata = 1;
540 if ((uptr -> flags & UNIT_ATT) == 0)
541 iodata = 1;
542 break;
543 case 0x02: /* Busy */
544 if (sim_is_active (uptr))
545 iodata = 1;
546 break;
547 case 0x04:
548 if (found[disk])
549 iodata = 1;
550 break;
551 default:
552 return (STOP_INVDEV << 16);
553 }
554 return ((SCPE_OK << 16) | iodata);
555
556 /* SNS 5444 */
557 case 3:
558 if ((uptr->flags & UNIT_ATT) == 0)
559 return SCPE_UNATT << 16;
560 iodata = 0;
561 switch (n) {
562 case 0x01:
563 break;
564 case 0x02:
565 iodata = diskerr[disk];
566 if (notrdy[disk])
567 iodata |= 0x4000;
568 if ((uptr -> flags & UNIT_ATT) == 0)
569 iodata |= 0x4000;
570 if (seekbusy[disk])
571 iodata |= 0x0010;
572 if (uptr -> u3 == 0)
573 iodata |= 0x0040;
574 break;
575 case 0x03:
576 iodata = 0;
577 break;
578 case 0x04:
579 iodata = DDAR[disk];
580 break;
581 case 0x06:
582 iodata = DCAR[disk];
583 break;
584 default:
585 return (STOP_INVDEV << 16);
586 }
587 iodata |= ((SCPE_OK << 16) & 0xffff0000);
588 return (iodata);
589
590 /* APL 5444 */
591 case 4:
592 if ((uptr->flags & UNIT_ATT) == 0)
593 return SCPE_UNATT << 16;
594 iodata = 0;
595 switch (n) {
596 case 0x00: /* Error */
597 if (diskerr[disk] || notrdy[disk])
598 iodata = 1;
599 if ((uptr -> flags & UNIT_ATT) == 0)
600 iodata = 1;
601 break;
602 case 0x02: /* Busy */
603 if (sim_is_active (uptr))
604 iodata = 1;
605 break;
606 default:
607 return (STOP_INVDEV << 16);
608 }
609 return ((SCPE_OK << 16) | iodata);
610 default:
611 break;
612 }
613 printf (">>DSK%d non-existent function %d\n", disk, op);
614 return SCPE_OK;
615 }
616
617 /* Disk unit service. If a stacker select is active, copy to the
618 selected stacker. Otherwise, copy to the normal stacker. If the
619 unit is unattached, simply exit.
620 */
621
622 t_stat r1_svc (UNIT *uptr)
623 {
624 seekbusy[0] = 0;
625 return SCPE_OK;
626 }
627 t_stat f1_svc (UNIT *uptr)
628 {
629 seekbusy[0] = 0;
630 return SCPE_OK;
631 }
632 t_stat r2_svc (UNIT *uptr)
633 {
634 seekbusy[1] = 0;
635 return SCPE_OK;
636 }
637 t_stat f2_svc (UNIT *uptr)
638 {
639 seekbusy[1] = 0;
640 return SCPE_OK;
641 }
642
643
644 /* Disk reset */
645
646 t_stat r1_reset (DEVICE *dptr)
647 {
648 diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */
649 found[0] = 0;
650 sim_cancel (&r1_unit); /* clear event */
651 r1_unit.u3 = 0; /* cylinder 0 */
652 return SCPE_OK;
653 }
654 t_stat f1_reset (DEVICE *dptr)
655 {
656 diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */
657 found[0] = 0;
658 sim_cancel (&f1_unit); /* clear event */
659 f1_unit.u3 = 0; /* cylinder 0 */
660 return SCPE_OK;
661 }
662 t_stat r2_reset (DEVICE *dptr)
663 {
664 diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */
665 found[1] = 0;
666 sim_cancel (&r2_unit); /* clear event */
667 r2_unit.u3 = 0; /* cylinder 0 */
668 return SCPE_OK;
669 }
670 t_stat f2_reset (DEVICE *dptr)
671 {
672 diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */
673 found[1] = 0;
674 sim_cancel (&f2_unit); /* clear event */
675 f2_unit.u3 = 0; /* cylinder 0 */
676 return SCPE_OK;
677 }
678
679 /* Disk unit attach */
680
681 t_stat r1_attach (UNIT *uptr, char *cptr)
682 {
683 diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */
684 found[0] = 0;
685 uptr -> u3 = 0; /* cylinder 0 */
686 return attach_unit (uptr, cptr);
687 }
688 t_stat f1_attach (UNIT *uptr, char *cptr)
689 {
690 diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */
691 found[0] = 0;
692 uptr -> u3 = 0; /* cylinder 0 */
693 return attach_unit (uptr, cptr);
694 }
695 t_stat r2_attach (UNIT *uptr, char *cptr)
696 {
697 diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */
698 found[1] = 0;
699 uptr -> u3 = 0; /* cylinder 0 */
700 return attach_unit (uptr, cptr);
701 }
702 t_stat f2_attach (UNIT *uptr, char *cptr)
703 {
704 diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */
705 found[1] = 0;
706 uptr -> u3 = 0; /* cylinder 0 */
707 return attach_unit (uptr, cptr);
708 }
709
710 /* Bootstrap routine */
711
712 t_stat r1_boot (int32 unitno, DEVICE *dptr)
713 {
714 int i;
715 r1_unit.u3 = 0;
716 read_sector(r1_dev.units, dbuf, 0);
717 for (i = 0; i < 256; i++) {
718 M[i] = dbuf[i];
719 }
720 return SCPE_OK;
721 }
722 t_stat f1_boot (int32 unitno, DEVICE *dptr)
723 {
724 int i;
725 f1_unit.u3 = 0;
726 read_sector(f1_dev.units, dbuf, 0);
727 for (i = 0; i < 256; i++) {
728 M[i] = dbuf[i];
729 }
730 return SCPE_OK;
731 }
732 t_stat r2_boot (int32 unitno, DEVICE *dptr)
733 {
734 int i;
735 r2_unit.u3 = 0;
736 read_sector(r2_dev.units, dbuf, 0);
737 for (i = 0; i < 256; i++) {
738 M[i] = dbuf[i];
739 }
740 return SCPE_OK;
741 }
742 t_stat f2_boot (int32 unitno, DEVICE *dptr)
743 {
744 int i;
745 f2_unit.u3 = 0;
746 read_sector(f2_dev.units, dbuf, 0);
747 for (i = 0; i < 256; i++) {
748 M[i] = dbuf[i];
749 }
750 return SCPE_OK;
751 }
752
753
754 /* Raw Disk Data In/Out */
755
756 int32 read_sector(UNIT *uptr, char *dbuf, int32 sect)
757 {
758 static int32 rtn, realsect;
759 static long pos;
760
761 /* calculate real sector no */
762 if (sect > 23)
763 realsect = sect - 8;
764 else
765 realsect = sect;
766 /* physically read the sector */
767 pos = DSK_CYLSIZE * uptr -> u3;
768 pos += DSK_SECTSIZE * realsect;
769 rtn = fseek(uptr -> fileref, pos, 0);
770 rtn = fread(dbuf, DSK_SECTSIZE, 1, uptr -> fileref);
771 return (rtn);
772 }
773
774 int32 write_sector(UNIT *uptr, char *dbuf, int32 sect)
775 {
776 static int32 rtn, realsect;
777 static long pos;
778
779 /* calculate real sector no */
780 if (sect > 23)
781 realsect = sect - 8;
782 else
783 realsect = sect;
784 if (uptr -> u3 == 0 && realsect == 32)
785 rtn = 0;
786 /* physically write the sector */
787 pos = DSK_CYLSIZE * uptr -> u3;
788 pos += DSK_SECTSIZE * realsect;
789 rtn = fseek(uptr -> fileref, pos, 0);
790 rtn = fwrite(dbuf, DSK_SECTSIZE, 1, uptr -> fileref);
791 return (rtn);
792 }