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 
dsk1(int32 op,int32 m,int32 n,int32 data)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 
dsk2(int32 op,int32 m,int32 n,int32 data)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 
dsk(int32 disk,int32 op,int32 m,int32 n,int32 data)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 
r1_svc(UNIT * uptr)622 t_stat r1_svc (UNIT *uptr)
623 {
624 seekbusy[0] = 0;
625 return SCPE_OK;
626 }
f1_svc(UNIT * uptr)627 t_stat f1_svc (UNIT *uptr)
628 {
629 seekbusy[0] = 0;
630 return SCPE_OK;
631 }
r2_svc(UNIT * uptr)632 t_stat r2_svc (UNIT *uptr)
633 {
634 seekbusy[1] = 0;
635 return SCPE_OK;
636 }
f2_svc(UNIT * uptr)637 t_stat f2_svc (UNIT *uptr)
638 {
639 seekbusy[1] = 0;
640 return SCPE_OK;
641 }
642 
643 
644 /* Disk reset */
645 
r1_reset(DEVICE * dptr)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 }
f1_reset(DEVICE * dptr)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 }
r2_reset(DEVICE * dptr)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 }
f2_reset(DEVICE * dptr)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 
r1_attach(UNIT * uptr,char * cptr)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 }
f1_attach(UNIT * uptr,char * cptr)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 }
r2_attach(UNIT * uptr,char * cptr)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 }
f2_attach(UNIT * uptr,char * cptr)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 
r1_boot(int32 unitno,DEVICE * dptr)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 }
f1_boot(int32 unitno,DEVICE * dptr)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 }
r2_boot(int32 unitno,DEVICE * dptr)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 }
f2_boot(int32 unitno,DEVICE * dptr)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 
read_sector(UNIT * uptr,char * dbuf,int32 sect)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 
write_sector(UNIT * uptr,char * dbuf,int32 sect)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 }
793