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