This source file includes following definitions.
- disk_show_nunits
- disk_set_nunits
- disk_show_type
- disk_set_type
- dsk_show_device_name
- dsk_set_device_name
- signal_disk_ready
- disk_set_ready
- unloadDisk
- loadDisk
- disk_reset
- disk_attach
- disk_init
- diskSeek64
- diskSeek512
- diskSeekSpecial
- diskRead
- diskWrite
- readStatusRegister
- diskRdCtrlReg
- read_configuration
- read_and_clear_statistics
- dsk_iom_cmd
- ipc_show_nunits
- ipc_set_nunits
- ipc_show_device_name
- ipc_set_device_name
- msp_show_nunits
- msp_set_nunits
- msp_show_device_name
- msp_set_device_name
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
27
28
29
30
31
32
33
34
35 #include <stdio.h>
36
37 #include "dps8.h"
38 #include "dps8_iom.h"
39 #include "dps8_disk.h"
40 #include "dps8_sys.h"
41 #include "dps8_cable.h"
42 #include "dps8_cpu.h"
43 #include "dps8_faults.h"
44 #include "dps8_scu.h"
45 #include "sim_disk.h"
46 #include "dps8_utils.h"
47
48 #if defined(LOCKLESS)
49 # include "threadz.h"
50 #endif
51
52 #define DBG_CTR 1
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 struct diskType_t diskTypes[] = {
145 { "3381", 451350, 0, false, seek_512, 512, 0 },
146 { "d500", 618640, 1, false, seek_64, 64, 200 },
147 { "d451", 616360, 1, true, seek_64, 64, 154 },
148 { "d400", 309320, 1, true, seek_64, 64, 84 },
149 { "d190", 239723, 1, true, seek_64, 64, 84 },
150 { "d181", 72000, 1, true, seek_64, 64, 0 },
151 { "d501", 1075200, 1, false, seek_64, 64, 201 },
152 { "3380", 225675, 0, false, seek_512, 512, 0 },
153 };
154 #define N_DISK_TYPES (sizeof (diskTypes) / sizeof (struct diskType_t))
155
156 static uint tAndDCapac[N_DISK_TYPES] = { 451860, 639920, 619400, 312360, 242250, 72360, 1077760, 225675 };
157
158 #define M3381_SECTORS (1770*255)
159
160
161
162
163
164
165
166
167
168
169
170
171
172 #define N_DISK_UNITS 2
173
174 struct dsk_state dsk_states [N_DSK_UNITS_MAX];
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 #if defined(POLTS_DISK_TESTING)
250 static int nCmds = 0;
251 #endif
252
253 #define UNIT_FLAGS ( UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | \
254 UNIT_DISABLE | UNIT_IDLE | DKUF_F_STD )
255 UNIT dsk_unit[N_DSK_UNITS_MAX] = {
256 #if defined(NO_C_ELLIPSIS)
257 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
258 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
259 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
260 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
261 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
262 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
263 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
264 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
265 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
266 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
267 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
268 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
269 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
270 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
271 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
272 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
273 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
274 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
275 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
276 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
277 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
278 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
279 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
280 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
281 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
282 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
283 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
284 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
285 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
286 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
287 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
288 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
289 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
290 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
291 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
292 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
293 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
294 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
295 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
296 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
297 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
298 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
299 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
300 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
301 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
302 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
303 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
304 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
305 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
306 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
307 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
308 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
309 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
310 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
311 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
312 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
313 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
314 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
315 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
316 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
317 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
318 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
319 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
320 { UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
321 #else
322 [0 ... N_DSK_UNITS_MAX-1] = {
323 UDATA ( NULL, UNIT_FLAGS, M3381_SECTORS), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
324 }
325 #endif
326 };
327
328 #define DSK_UNIT_IDX(uptr) ((uptr) - dsk_unit)
329
330 static DEBTAB disk_dt[] =
331 {
332 { "TRACE", DBG_TRACE, NULL },
333 { "NOTIFY", DBG_NOTIFY, NULL },
334 { "INFO", DBG_INFO, NULL },
335 { "ERR", DBG_ERR, NULL },
336 { "WARN", DBG_WARN, NULL },
337 { "DEBUG", DBG_DEBUG, NULL },
338 { "ALL", DBG_ALL, NULL },
339 { NULL, 0, NULL }
340 };
341
342 static t_stat disk_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val, UNUSED const void * desc)
343 {
344 sim_printf("Number of DISK units in system is %d\n", dsk_dev . numunits);
345 return SCPE_OK;
346 }
347
348 static t_stat disk_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value, const char * cptr, UNUSED void * desc)
349 {
350 if (! cptr)
351 return SCPE_ARG;
352 int n = atoi (cptr);
353 if (n < 1 || n > N_DSK_UNITS_MAX)
354 return SCPE_ARG;
355 dsk_dev . numunits = (uint32) n;
356 return SCPE_OK;
357 }
358
359 static t_stat disk_show_type (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val, UNUSED const void * desc)
360 {
361 int diskUnitIdx = (int) DSK_UNIT_IDX (uptr);
362 if (diskUnitIdx < 0 || diskUnitIdx >= N_DSK_UNITS_MAX)
363 {
364 sim_printf ("error: Invalid unit number %ld\n", (long) diskUnitIdx);
365 return SCPE_ARG;
366 }
367
368 sim_printf("type : %s", diskTypes[dsk_states[diskUnitIdx].typeIdx].typename);
369
370 return SCPE_OK;
371 }
372
373 static t_stat disk_set_type (UNUSED UNIT * uptr, UNUSED int32 value, const char * cptr, UNUSED void * desc)
374 {
375 int diskUnitIdx = (int) DSK_UNIT_IDX (uptr);
376 if (diskUnitIdx < 0 || diskUnitIdx >= N_DSK_UNITS_MAX)
377 {
378 sim_printf ("error: Invalid unit number %ld\n", (long) diskUnitIdx);
379 return SCPE_ARG;
380 }
381
382 uint i;
383 for (i = 0; i < N_DISK_TYPES; i++)
384 {
385 if (strcasecmp (cptr, diskTypes[i].typename) == 0)
386 break;
387 }
388 if (i >= N_DISK_TYPES)
389 {
390 sim_printf ("Disk type %s unrecognized, expected one of "
391 "%s %s %s %s %s %s %s %s\r\n",
392 cptr,
393 diskTypes[0].typename,
394 diskTypes[1].typename,
395 diskTypes[2].typename,
396 diskTypes[3].typename,
397 diskTypes[4].typename,
398 diskTypes[5].typename,
399 diskTypes[6].typename,
400 diskTypes[7].typename);
401 return SCPE_ARG;
402 }
403 dsk_states[diskUnitIdx].typeIdx = i;
404 dsk_unit[diskUnitIdx].capac = (t_addr) diskTypes[i].capac;
405 dsk_states[diskUnitIdx].tAndDCapac = tAndDCapac[i];
406 return SCPE_OK;
407 }
408
409 static t_stat dsk_show_device_name (UNUSED FILE * st, UNIT * uptr,
410 UNUSED int val, UNUSED const void * desc)
411 {
412 int n = (int) DSK_UNIT_IDX (uptr);
413 if (n < 0 || n >= N_DSK_UNITS_MAX)
414 return SCPE_ARG;
415 sim_printf("name : %s", dsk_states[n].device_name);
416 return SCPE_OK;
417 }
418
419 static t_stat dsk_set_device_name (UNIT * uptr, UNUSED int32 value,
420 const char * cptr, UNUSED void * desc)
421 {
422 int n = (int) DSK_UNIT_IDX (uptr);
423 if (n < 0 || n >= N_DSK_UNITS_MAX)
424 return SCPE_ARG;
425 if (cptr)
426 {
427 strncpy (dsk_states[n].device_name, cptr, MAX_DEV_NAME_LEN-1);
428 dsk_states[n].device_name[MAX_DEV_NAME_LEN-1] = 0;
429 }
430 else
431 dsk_states[n].device_name[0] = 0;
432 return SCPE_OK;
433 }
434
435
436
437
438
439
440
441 t_stat signal_disk_ready (uint dsk_unit_idx) {
442
443 if (! sim_is_running)
444 return SCPE_OK;
445
446
447
448
449
450
451
452
453
454
455
456
457
458 uint ctlr_unit_idx = cables->dsk_to_ctlr[dsk_unit_idx].ctlr_unit_idx;
459 enum ctlr_type_e ctlr_type = cables->dsk_to_ctlr[dsk_unit_idx].ctlr_type;
460 if (ctlr_type != CTLR_T_MSP && ctlr_type != CTLR_T_IPC) {
461
462 if (ctlr_type != CTLR_T_NONE) {
463 sim_warn ("loadDisk lost\n");
464 return SCPE_ARG;
465 }
466 return SCPE_OK;
467 }
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507 for (uint ctlr_port_num = 0; ctlr_port_num < MAX_CTLR_PORTS; ctlr_port_num ++) {
508 if (ctlr_type == CTLR_T_MSP) {
509 if (cables->msp_to_iom[ctlr_unit_idx][ctlr_port_num].in_use) {
510 uint iom_unit_idx = cables->msp_to_iom[ctlr_unit_idx][ctlr_port_num].iom_unit_idx;
511 uint chan_num = cables->msp_to_iom[ctlr_unit_idx][ctlr_port_num].chan_num;
512 uint dev_code = cables->dsk_to_ctlr[dsk_unit_idx].dev_code;
513
514 send_special_interrupt (iom_unit_idx, chan_num, dev_code, 0x40, 01 );
515 return SCPE_OK;
516 }
517 } else {
518 if (cables->ipc_to_iom[ctlr_unit_idx][ctlr_port_num].in_use) {
519 uint iom_unit_idx = cables->ipc_to_iom[ctlr_unit_idx][ctlr_port_num].iom_unit_idx;
520 uint chan_num = cables->ipc_to_iom[ctlr_unit_idx][ctlr_port_num].chan_num;
521 uint dev_code = cables->dsk_to_ctlr[dsk_unit_idx].dev_code;
522
523 send_special_interrupt (iom_unit_idx, chan_num, dev_code, 0x40, 01 );
524 return SCPE_OK;
525 }
526 }
527 }
528 return SCPE_ARG;
529
530 }
531
532 static t_stat disk_set_ready (UNIT * uptr, UNUSED int32 value,
533 UNUSED const char * cptr,
534 UNUSED void * desc)
535 {
536 long disk_unit_idx = DSK_UNIT_IDX (uptr);
537 if (disk_unit_idx >= (long) dsk_dev.numunits)
538 {
539 sim_warn ("%s: error: Invalid unit number %ld\n", __func__, (long) disk_unit_idx);
540 return SCPE_ARG;
541 }
542 return signal_disk_ready ((uint) disk_unit_idx);
543 }
544
545 t_stat unloadDisk (uint dsk_unit_idx) {
546 if (dsk_unit [dsk_unit_idx] . flags & UNIT_ATT) {
547 t_stat stat = sim_disk_detach (& dsk_unit [dsk_unit_idx]);
548 if (stat != SCPE_OK) {
549 sim_warn ("%s: sim_disk_detach returned %ld\n", __func__, (long) stat);
550 return SCPE_ARG;
551 }
552 }
553 return signal_disk_ready ((uint) dsk_unit_idx);
554 }
555
556 t_stat loadDisk (uint dsk_unit_idx, const char * disk_filename, bool ro) {
557 if (ro)
558 dsk_unit[dsk_unit_idx].flags |= MTUF_WRP;
559 else
560 dsk_unit[dsk_unit_idx].flags &= ~ MTUF_WRP;
561 t_stat stat = attach_unit (& dsk_unit [dsk_unit_idx], disk_filename);
562 if (stat != SCPE_OK) {
563 sim_printf ("%s: sim_disk_attach returned %d\n", __func__, stat);
564 return stat;
565 }
566 return signal_disk_ready ((uint) dsk_unit_idx);
567 }
568
569 #define UNIT_WATCH UNIT_V_UF
570
571 static MTAB disk_mod[] =
572 {
573 #if !defined(SPEED)
574 { UNIT_WATCH, 1, "WATCH", "WATCH", 0, 0, NULL, NULL },
575 { UNIT_WATCH, 0, "NOWATCH", "NOWATCH", 0, 0, NULL, NULL },
576 #endif
577 {
578 MTAB_dev_value,
579 0,
580 "NUNITS",
581 "NUNITS",
582 disk_set_nunits,
583 disk_show_nunits,
584 "Number of DISK units in the system",
585 NULL
586 },
587 {
588 MTAB_unit_value_show,
589 0,
590 "TYPE",
591 "TYPE",
592 disk_set_type,
593 disk_show_type,
594 "disk type",
595 "D500, D451, D400, D190, D181, D501, 3380, 3381",
596 },
597 {
598 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
599 0,
600 "NAME",
601 "NAME",
602 dsk_set_device_name,
603 dsk_show_device_name,
604 "Set the device name",
605 NULL
606 },
607 {
608 MTAB_XTD | MTAB_VUN | MTAB_NMO | MTAB_VALR,
609 0,
610 "READY",
611 "READY",
612 disk_set_ready,
613 NULL,
614 NULL,
615 NULL
616 },
617 MTAB_eol
618 };
619
620 static t_stat disk_reset (UNUSED DEVICE * dptr)
621 {
622 return SCPE_OK;
623 }
624
625 static t_stat disk_attach (UNIT *uptr, CONST char *cptr)
626 {
627 int diskUnitIdx = (int) DSK_UNIT_IDX (uptr);
628 if (diskUnitIdx < 0 || diskUnitIdx >= N_DSK_UNITS_MAX)
629 {
630 sim_printf ("error: Invalid unit number %ld\n", (long) diskUnitIdx);
631 return SCPE_ARG;
632 }
633
634 return loadDisk ((uint) diskUnitIdx, cptr, false);
635 }
636
637
638 DEVICE dsk_dev = {
639 "DISK",
640 dsk_unit,
641 NULL,
642 disk_mod,
643 N_DISK_UNITS,
644 10,
645 24,
646 1,
647 8,
648 36,
649 NULL,
650 NULL,
651 disk_reset,
652 NULL,
653 disk_attach,
654 NULL ,
655 NULL,
656 DEV_DEBUG,
657 0,
658 disk_dt,
659 NULL,
660 NULL,
661 NULL,
662 NULL,
663 NULL,
664 NULL,
665 NULL
666 };
667
668
669
670
671
672
673
674 void disk_init (void)
675 {
676
677 (void)memset (dsk_states, 0, sizeof (dsk_states));
678 #if defined(LOCKLESS)
679 # if defined(__FreeBSD__)
680 pthread_mutexattr_t scu_attr;
681 pthread_mutexattr_init (& scu_attr);
682 pthread_mutexattr_settype (& scu_attr, PTHREAD_MUTEX_ADAPTIVE_NP);
683 # endif
684 for (uint i = 0; i < N_DSK_UNITS_MAX; i ++)
685 {
686 # if defined(__FreeBSD__)
687 pthread_mutex_init (& dsk_states[i].dsk_lock, & scu_attr);
688 # else
689 pthread_mutex_init (& dsk_states[i].dsk_lock, NULL);
690 # endif
691 }
692 #endif
693 }
694
695 static iom_cmd_rc_t diskSeek64 (uint devUnitIdx, uint iomUnitIdx, uint chan)
696 {
697 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
698 struct dsk_state * disk_statep = & dsk_states[devUnitIdx];
699
700 uint typeIdx = disk_statep->typeIdx;
701 if (diskTypes[typeIdx].seekSize != seek_64)
702 sim_warn ("%s: disk%u sent a SEEK_64 but is 512 sized\n", __func__, typeIdx);
703
704 uint tally = p->DDCW_TALLY;
705
706
707
708 if (tally != 1)
709 {
710 sim_printf ("disk seek dazed by tally %d != 1\n", tally);
711 p->stati = 04510;
712 return IOM_CMD_ERROR;
713 }
714
715 word36 seekData[1];
716 uint count;
717 iom_indirect_data_service (iomUnitIdx, chan, seekData, &count, false);
718
719 p->initiate = true;
720 if (count != 1)
721 sim_warn ("%s: count %d not 1\n", __func__, count);
722
723 #if defined(POLTS_DISK_TESTING)
724 if_sim_debug (DBG_TRACE, & dsk_dev) { sim_printf ("// Seek address %012"PRIo64"\n", seekData[0]); }
725 #endif
726
727
728
729
730
731
732 seekData[0] &= MASK21;
733 if (seekData[0] >= diskTypes[typeIdx].capac)
734 {
735 disk_statep->seekValid = false;
736 p->stati = 04304;
737 return IOM_CMD_ERROR;
738 }
739 disk_statep->seekValid = true;
740 disk_statep->seekPosition = (uint) seekData[0];
741 p->stati = 04000;
742 return IOM_CMD_PROCEED;
743 }
744
745 static int diskSeek512 (uint devUnitIdx, uint iomUnitIdx, uint chan)
746 {
747 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
748 struct dsk_state * disk_statep = & dsk_states[devUnitIdx];
749 uint typeIdx = disk_statep->typeIdx;
750 if (diskTypes[typeIdx].seekSize != seek_512)
751 sim_warn ("%s: disk%u sent a SEEK_512 but is 64 sized\n", __func__, typeIdx);
752
753 uint tally = p->DDCW_TALLY;
754
755
756
757 if (tally != 1)
758 {
759 sim_printf ("disk seek dazed by tally %d != 1\n", tally);
760
761
762
763 tally = 1;
764 }
765
766 word36 seekData[1];
767 uint count;
768 iom_indirect_data_service (iomUnitIdx, chan, seekData, &count, false);
769
770 p->initiate = true;
771 if (count != 1)
772 sim_warn ("%s: count %d not 1\n", __func__, count);
773
774 seekData[0] &= MASK21;
775 if (seekData[0] >= diskTypes[typeIdx].capac)
776 {
777 disk_statep->seekValid = false;
778 p->stati = 04304;
779 return -1;
780 }
781 disk_statep->seekValid = true;
782 disk_statep->seekPosition = (uint)seekData[0];
783 p->stati = 04000;
784 return 0;
785 }
786
787 static iom_cmd_rc_t diskSeekSpecial (uint devUnitIdx, uint iomUnitIdx, uint chan)
788 {
789 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
790 struct dsk_state * disk_statep = & dsk_states[devUnitIdx];
791
792 uint typeIdx = disk_statep->typeIdx;
793
794
795
796 uint tally = p->DDCW_TALLY;
797
798
799
800 if (tally != 1)
801 {
802 sim_printf ("disk seek dazed by tally %d != 1\n", tally);
803
804
805
806 tally = 1;
807 }
808
809 word36 seekData[1];
810 uint count;
811 iom_indirect_data_service (iomUnitIdx, chan, seekData, &count, false);
812
813 p->initiate = true;
814 if (count != 1)
815 sim_warn ("%s: count %d not 1\n", __func__, count);
816
817 #if defined(POLTS_DISK_TESTING)
818 if_sim_debug (DBG_TRACE, & dsk_dev)
819 {
820 sim_printf ("// Seek address %012"PRIo64"\n", seekData[0]);
821 }
822 #endif
823
824 seekData[0] &= MASK21;
825 if (seekData[0] >= dsk_states[typeIdx].tAndDCapac)
826 {
827 p->stati = 04304;
828 disk_statep->seekValid = false;
829
830 return IOM_CMD_ERROR;
831 }
832 disk_statep->seekValid = true;
833 disk_statep->seekPosition = (uint) seekData[0];
834 p->stati = 04000;
835 return IOM_CMD_PROCEED;
836 }
837
838 static int diskRead (uint devUnitIdx, uint iomUnitIdx, uint chan)
839 {
840 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
841 UNIT * unitp = & dsk_unit[devUnitIdx];
842 struct dsk_state * disk_statep = & dsk_states[devUnitIdx];
843 uint typeIdx = disk_statep->typeIdx;
844 uint sectorSizeWords = diskTypes[typeIdx].sectorSizeWords;
845 uint sectorSizeBytes = ((36 * sectorSizeWords) / 8);
846
847 if (! unitp->fileref) {
848 p->stati = 04240;
849 #if defined(POLTS_TESTING)
850 if (chan == 014)
851 if_sim_debug (DBG_TRACE, & dsk_dev) sim_printf ("// diskRead device offline\r\n");
852 #endif
853 return -1;
854 }
855 if (! disk_statep->seekValid) {
856 p->stati = 04510;
857 disk_statep->seekValid = false;
858 #if defined(POLTS_TESTING)
859 if (chan == 014)
860 if_sim_debug (DBG_TRACE, & dsk_dev) sim_printf ("// diskRead seek invalid\r\n");
861 #endif
862 return IOM_CMD_ERROR;
863 }
864 uint tally = p->DDCW_TALLY;
865 if (tally == 0)
866 {
867 tally = 4096;
868 }
869
870 int rc = fseek (unitp->fileref,
871 (long) ((long)disk_statep->seekPosition * (long)sectorSizeBytes),
872 SEEK_SET);
873 if (rc)
874 {
875 sim_warn ("%s: fseek (read) returned %d, errno %d\n", __func__, rc, errno);
876 p->stati = 04202;
877 #if defined(POLTS_TESTING)
878 if (chan == 014)
879 if_sim_debug (DBG_TRACE, & dsk_dev) sim_printf ("// diskRead seek incomplete\r\n");
880 #endif
881 return -1;
882 }
883
884
885
886
887
888
889
890 uint tallySectors = (tally + sectorSizeWords - 1) /
891 sectorSizeWords;
892 uint tallyWords = tallySectors * sectorSizeWords;
893
894 uint p72ByteCnt = (tallyWords * 36) / 8;
895 uint8 diskBuffer[p72ByteCnt];
896 (void)memset (diskBuffer, 0, sizeof (diskBuffer));
897
898 (void)fflush (unitp->fileref);
899 rc = (int) fread (diskBuffer, sectorSizeBytes,
900 tallySectors,
901 unitp->fileref);
902
903 if (rc == 0)
904 {
905 if (ferror (unitp->fileref))
906 {
907 p->stati = 04202;
908
909 #if defined(POLTS_TESTING)
910 if (chan == 014)
911 if_sim_debug (DBG_TRACE, & dsk_dev) sim_printf ("// diskRead seek incomplete2\r\n");
912 #endif
913 return -1;
914 }
915
916
917
918 }
919 disk_statep->seekPosition += tallySectors;
920
921 uint wordsProcessed = 0;
922 word36 buffer[tally];
923 for (uint i = 0; i < tally; i ++)
924 {
925 word36 w;
926 extractWord36FromBuffer (diskBuffer, p72ByteCnt, & wordsProcessed,
927 & w);
928 buffer[i] = w;
929 }
930 iom_indirect_data_service (iomUnitIdx, chan, buffer,
931 & wordsProcessed, true);
932 p->stati = 04000;
933 #if defined(POLTS_TESTING)
934 if (chan == 014)
935 if_sim_debug (DBG_TRACE, & dsk_dev) sim_printf ("// diskRead ok\r\n");
936 #endif
937 return 0;
938 }
939
940 static int diskWrite (uint devUnitIdx, uint iomUnitIdx, uint chan)
941 {
942 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
943 UNIT * unitp = & dsk_unit[devUnitIdx];
944 struct dsk_state * disk_statep = & dsk_states[devUnitIdx];
945 uint typeIdx = disk_statep->typeIdx;
946 uint sectorSizeWords = diskTypes[typeIdx].sectorSizeWords;
947 uint sectorSizeBytes = ((36 * sectorSizeWords) / 8);
948
949 if (! unitp->fileref) {
950 p->stati = 04240;
951 return -1;
952 }
953
954 if (! disk_statep->seekValid) {
955 p->stati = 04510;
956 disk_statep->seekValid = false;
957 return IOM_CMD_ERROR;
958 }
959
960 uint tally = p->DDCW_TALLY;
961
962 if (tally == 0)
963 {
964 tally = 4096;
965 }
966
967 int rc = fseek (unitp->fileref,
968 (long) ((long)disk_statep->seekPosition * (long)sectorSizeBytes),
969 SEEK_SET);
970 if (rc)
971 {
972 sim_printf ("fseek (read) returned %d, errno %d\n", rc, errno);
973 p->stati = 04202;
974 return -1;
975 }
976
977
978
979
980
981
982
983 uint tallySectors = (tally + sectorSizeWords - 1) /
984 sectorSizeWords;
985 uint tallyWords = tallySectors * sectorSizeWords;
986 uint p72ByteCnt = (tallyWords * 36) / 8;
987 uint8 diskBuffer[p72ByteCnt];
988 (void)memset (diskBuffer, 0, sizeof (diskBuffer));
989 uint wordsProcessed = 0;
990
991 word36 buffer[tally];
992 iom_indirect_data_service (iomUnitIdx, chan, buffer,
993 & wordsProcessed, false);
994 wordsProcessed = 0;
995 for (uint i = 0; i < tally; i ++)
996 {
997 insertWord36toBuffer (diskBuffer, p72ByteCnt, & wordsProcessed,
998 buffer[i]);
999 }
1000
1001 rc = (int) fwrite (diskBuffer, sectorSizeBytes,
1002 tallySectors,
1003 unitp->fileref);
1004 (void)fflush (unitp->fileref);
1005
1006 if (rc != (int) tallySectors)
1007 {
1008 sim_printf ("fwrite returned %d, errno %d\n", rc, errno);
1009 p->stati = 04202;
1010 p->chanStatus = chanStatIncorrectDCW;
1011 return -1;
1012 }
1013
1014 disk_statep->seekPosition += tallySectors;
1015
1016 p->stati = 04000;
1017 return 0;
1018 }
1019
1020 static int readStatusRegister (uint devUnitIdx, uint iomUnitIdx, uint chan)
1021 {
1022 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
1023 UNIT * unitp = & dsk_unit[devUnitIdx];
1024
1025 uint tally = p->DDCW_TALLY;
1026
1027 if (tally != 4 && tally != 2)
1028 {
1029 sim_warn ("%s: RSR expected tally of 2 or 4, is %d\n",
1030 __func__, tally);
1031 }
1032 if (tally == 0)
1033 {
1034 tally = 4096;
1035 }
1036
1037
1038
1039
1040 #if defined(TESTING)
1041 sim_warn ("Need status register data format\n");
1042 #endif
1043 word36 buffer[tally];
1044 (void)memset (buffer, 0, sizeof (buffer));
1045 #if defined(POLTS_DISK_TESTING)
1046 buffer[0] = nCmds;
1047 #endif
1048 uint wordsProcessed = tally;
1049 iom_indirect_data_service (iomUnitIdx, chan, buffer,
1050 & wordsProcessed, true);
1051 p->charPos = 0;
1052 p->stati = 04000;
1053 if (! unitp->fileref)
1054 p->stati = 04240;
1055 return 0;
1056 }
1057
1058 static int diskRdCtrlReg (uint dev_unit_idx, uint iom_unit_idx, uint chan) {
1059 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1060 UNIT * unitp = & dsk_unit[dev_unit_idx];
1061 p->charPos = 0;
1062 p->stati = 04000;
1063 if (! unitp->fileref)
1064 p->stati = 04240;
1065 return 0;
1066 }
1067
1068 static int read_configuration (uint dev_unit_idx, uint iom_unit_idx, uint chan)
1069 {
1070 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1071 UNIT * unitp = & dsk_unit[dev_unit_idx];
1072
1073 uint tally = p->DDCW_TALLY;
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141 uint ctlr_unit_idx = get_ctlr_idx (iom_unit_idx, chan);
1142 struct ctlr_to_dev_s * dev_p;
1143 if (cables->iom_to_ctlr[iom_unit_idx][chan].ctlr_type == CTLR_T_IPC)
1144 dev_p = cables->ipc_to_dsk[ctlr_unit_idx];
1145 else
1146 dev_p = cables->msp_to_dsk[ctlr_unit_idx];
1147
1148
1149 word36 buffer[tally];
1150 (void)memset (buffer, 0, sizeof (buffer));
1151 putbits36_9 (& buffer[0], 0, 0x12);
1152 putbits36_9 (& buffer[0], 9, 1);
1153 putbits36_9 (& buffer[0], 18, '1');
1154 putbits36_9 (& buffer[0], 27, 'a');
1155
1156 for (word9 dev_num = 0; dev_num < N_DEV_CODES; dev_num ++)
1157 {
1158 if (! dev_p[dev_num].in_use)
1159 continue;
1160 uint dsk_unit_idx = dev_p[dev_num].unit_idx;
1161
1162
1163 word9 dau_type = (word9) diskTypes[dsk_states[dsk_unit_idx].typeIdx].dau_type;
1164 putbits36_9 (& buffer[1+dev_num], 0, dau_type);
1165 putbits36_9 (& buffer[1+dev_num], 9, dev_num);
1166 putbits36_9 (& buffer[1+dev_num], 18, 0);
1167 putbits36_9 (& buffer[1+dev_num], 27, dev_num);
1168 }
1169
1170 uint wordsProcessed = tally;
1171 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1172 & wordsProcessed, true);
1173 p->charPos = 0;
1174 p->stati = 04000;
1175 if (! unitp->fileref)
1176 p->stati = 04240;
1177 return 0;
1178 }
1179
1180 static int read_and_clear_statistics (uint dev_unit_idx, uint iom_unit_idx, uint chan)
1181 {
1182 #if defined(TESTING)
1183 cpu_state_t * cpup = _cpup;
1184 #endif
1185 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1186 UNIT * unitp = & dsk_unit[dev_unit_idx];
1187
1188 sim_debug (DBG_NOTIFY, & dsk_dev, "Read %d\n", dev_unit_idx);
1189
1190 p->charPos = 0;
1191 p->stati = 04000;
1192 if (! unitp->fileref)
1193 p->stati = 04240;
1194 return 0;
1195 }
1196
1197
1198
1199
1200
1201
1202
1203
1204 iom_cmd_rc_t dsk_iom_cmd (uint iomUnitIdx, uint chan) {
1205 #if defined(POLTS_DISK_TESTING)
1206 nCmds ++;
1207 #endif
1208 #if defined(TESTING)
1209 cpu_state_t * cpup = _cpup;
1210 #endif
1211 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
1212 uint ctlr_unit_idx = get_ctlr_idx (iomUnitIdx, chan);
1213 uint devUnitIdx;
1214
1215 #if defined(POLTS_DISK_TESTING)
1216 if (chan == 014) {if_sim_debug (DBG_TRACE, & dsk_dev) { dumpDCW (p->DCW, 0); }}
1217 #endif
1218 if (cables->iom_to_ctlr[iomUnitIdx][chan].ctlr_type == CTLR_T_IPC)
1219 devUnitIdx = cables->ipc_to_dsk[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
1220 else if (cables->iom_to_ctlr[iomUnitIdx][chan].ctlr_type == CTLR_T_MSP)
1221 devUnitIdx = cables->msp_to_dsk[ctlr_unit_idx][p->IDCW_DEV_CODE].unit_idx;
1222 else {
1223 sim_warn ("%s: Can't find controller (%d)\n", __func__, cables->iom_to_ctlr[iomUnitIdx][chan].ctlr_type);
1224 return IOM_CMD_ERROR;
1225 }
1226
1227 UNIT * unitp = & dsk_unit[devUnitIdx];
1228 struct dsk_state * disk_statep = & dsk_states[devUnitIdx];
1229
1230 iom_cmd_rc_t rc = IOM_CMD_PROCEED;
1231
1232 #if defined(LOCKLESS)
1233 lock_ptr (& dsk_states->dsk_lock);
1234 #endif
1235
1236
1237 if (p->DCW_18_20_CP == 7) {
1238
1239 disk_statep->io_mode = disk_no_mode;
1240 switch (p->IDCW_DEV_CMD) {
1241 case 000:
1242 #if defined(POLTS_DISK_TESTING)
1243
1244 #endif
1245 #if !defined(POLTS_DISK_TESTING)
1246 if_sim_debug (DBG_TRACE, & dsk_dev) {
1247 sim_printf ("// Disk Request Status\r\n");
1248 }
1249 #endif
1250
1251 p->stati = 04000;
1252 if (! unitp->fileref)
1253 p->stati = 04240;
1254 break;
1255
1256 case 016:
1257 #if defined(POLTS_DISK_TESTING)
1258 if (chan == 014)
1259 #endif
1260 if_sim_debug (DBG_TRACE, & dsk_dev) {
1261 sim_printf ("// Disk Read And Clear Statistics\r\n");
1262 }
1263 disk_statep->io_mode = disk_rd_clr_stats;
1264 p->recordResidue --;
1265 p->stati = 04000;
1266 if (! unitp->fileref)
1267 p->stati = 04240;
1268 break;
1269
1270 case 022:
1271 #if defined(POLTS_DISK_TESTING)
1272 if (chan == 014)
1273 #endif
1274 if_sim_debug (DBG_TRACE, & dsk_dev) {
1275 sim_printf ("// Disk Read Status Register\r\n");
1276 }
1277 disk_statep->io_mode = disk_rd_status_reg;
1278 p->recordResidue --;
1279 p->stati = 04000;
1280 if (! unitp->fileref)
1281 p->stati = 04240;
1282 break;
1283
1284 case 024:
1285 #if defined(POLTS_DISK_TESTING)
1286 if (chan == 014)
1287 #endif
1288 if_sim_debug (DBG_TRACE, & dsk_dev) {
1289 sim_printf ("// Disk Read Configuration\r\n");
1290 }
1291 disk_statep->io_mode = disk_rd_config;
1292 p->recordResidue --;
1293 p->stati = 04000;
1294 if (! unitp->fileref)
1295 p->stati = 04240;
1296 break;
1297
1298 case 025:
1299 #if defined(POLTS_DISK_TESTING)
1300 if (chan == 014)
1301 #endif
1302 if_sim_debug (DBG_TRACE, & dsk_dev) {
1303 sim_printf ("// Disk Read\r\n");
1304 }
1305 disk_statep->io_mode = disk_rd;
1306 p->recordResidue --;
1307 p->stati = 04000;
1308 if (! unitp->fileref)
1309 p->stati = 04240;
1310 break;
1311
1312 case 026:
1313 #if defined(POLTS_DISK_TESTING)
1314 if (chan == 014)
1315 #endif
1316 if_sim_debug (DBG_TRACE, & dsk_dev) {
1317 sim_printf ("// Disk Read Control Register\r\n");
1318 }
1319 disk_statep->io_mode = disk_rd_ctrl_reg;
1320 p->recordResidue --;
1321 p->stati = 04000;
1322 if (! unitp->fileref)
1323 p->stati = 04240;
1324 break;
1325
1326 case 030:
1327 #if defined(POLTS_DISK_TESTING)
1328 if (chan == 014)
1329 #endif
1330 if_sim_debug (DBG_TRACE, & dsk_dev) {
1331 sim_printf ("// Disk Seek 512\r\n");
1332 }
1333 disk_statep->io_mode = disk_seek_512;
1334 p->recordResidue --;
1335 p->stati = 04000;
1336 if (! unitp->fileref)
1337 p->stati = 04240;
1338 break;
1339
1340 case 031:
1341 case 033:
1342 #if defined(POLTS_DISK_TESTING)
1343 if (chan == 014)
1344 #endif
1345 if_sim_debug (DBG_TRACE, & dsk_dev) {
1346 sim_printf ("// Disk Write\r\n");
1347 }
1348 disk_statep->io_mode = disk_wr;
1349 p->recordResidue --;
1350 p->stati = 04000;
1351 if (! unitp->fileref)
1352 p->stati = 04240;
1353 break;
1354
1355 case 034:
1356 #if defined(POLTS_DISK_TESTING)
1357 if (chan == 014)
1358 #endif
1359 if_sim_debug (DBG_TRACE, & dsk_dev) {
1360 sim_printf ("// Disk Seek 64\r\n");
1361 }
1362 disk_statep->io_mode = disk_seek_64;
1363 p->recordResidue --;
1364 p->stati = 04000;
1365 if (! unitp->fileref)
1366 p->stati = 04240;
1367 break;
1368
1369 case 036:
1370
1371 #if defined(POLTS_DISK_TESTING)
1372 if (chan == 014)
1373 #endif
1374 if_sim_debug (DBG_TRACE, & dsk_dev) {
1375 sim_printf ("// Disk Special Seek\r\n");
1376 }
1377 disk_statep->io_mode = disk_special_seek;
1378 p->recordResidue --;
1379 p->stati = 04000;
1380 if (! unitp->fileref)
1381 p->stati = 04240;
1382 break;
1383
1384 case 040:
1385 #if defined(POLTS_DISK_TESTING)
1386 if (chan == 014)
1387 #endif
1388 if_sim_debug (DBG_TRACE, & dsk_dev) {
1389 sim_printf ("// Disk Reset Status\r\n");
1390 }
1391 p->stati = 04000;
1392
1393 p->recordResidue --;
1394 p->initiate = false;
1395 p->isRead = false;
1396
1397 if (p->IDCW_DEV_CODE == 077) {
1398 p->stati = 04502;
1399 #if defined(LOCKLESS)
1400 unlock_ptr (& dsk_states->dsk_lock);
1401 #endif
1402 return IOM_CMD_DISCONNECT;
1403 }
1404 if (! unitp->fileref)
1405 p->stati = 04240;
1406 break;
1407
1408 case 042:
1409 #if defined(POLTS_DISK_TESTING)
1410 if (chan == 014)
1411 #endif
1412 if_sim_debug (DBG_TRACE, & dsk_dev) {
1413 sim_printf ("// Disk Restore\r\n");
1414 }
1415 p->stati = 04000;
1416
1417 p->recordResidue --;
1418 p->initiate = false;
1419 if (! unitp->fileref)
1420 p->stati = 04240;
1421
1422 disk_statep->seekValid = false;
1423
1424 break;
1425
1426 case 072:
1427 #if defined(POLTS_DISK_TESTING)
1428 if (chan == 014)
1429 #endif
1430 if_sim_debug (DBG_TRACE, & dsk_dev) {
1431 sim_printf ("// Disk Set Standby\r\n");
1432 }
1433 p->stati = 04000;
1434 if (! unitp->fileref)
1435 p->stati = 04240;
1436 break;
1437
1438 default:
1439 #if defined(POLTS_DISK_TESTING)
1440 if (chan == 014)
1441 #endif
1442 if_sim_debug (DBG_TRACE, & dsk_dev) {
1443 sim_printf ("// Disk unknown command %o\r\n", p->IDCW_DEV_CMD);
1444 }
1445 p->stati = 04501;
1446 p->chanStatus = chanStatIncorrectDCW;
1447 if (p->IDCW_DEV_CMD != 051)
1448 sim_warn ("%s: Unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
1449 rc = IOM_CMD_ERROR;
1450 goto done;
1451 }
1452 goto done;
1453 }
1454
1455
1456 switch (disk_statep->io_mode) {
1457 case disk_no_mode:
1458 #if defined(POLTS_DISK_TESTING)
1459 if (chan == 014)
1460 #endif
1461 if_sim_debug (DBG_TRACE, & dsk_dev) {
1462 sim_printf ("// Disk IOT No Mode\r\n");
1463 }
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476 goto done;
1477
1478 case disk_rd_clr_stats: {
1479 #if defined(POLTS_DISK_TESTING)
1480 if (chan == 014)
1481 #endif
1482 if_sim_debug (DBG_TRACE, & dsk_dev) {
1483 sim_printf ("// Disk IOT Rd And Clr Stats\r\n");
1484 }
1485 int rc1 = read_and_clear_statistics (devUnitIdx, iomUnitIdx, chan);
1486 if (rc1) {
1487 rc = IOM_CMD_ERROR;
1488 goto done;
1489 }
1490 }
1491 break;
1492
1493 case disk_rd_status_reg: {
1494 #if defined(POLTS_DISK_TESTING)
1495 if (chan == 014)
1496 #endif
1497 if_sim_debug (DBG_TRACE, & dsk_dev) {
1498 sim_printf ("// Disk IOT Rd Status Reg\r\n");
1499 }
1500 int rc1 = readStatusRegister (devUnitIdx, iomUnitIdx, chan);
1501 if (rc1) {
1502 rc = IOM_CMD_ERROR;
1503 goto done;
1504 }
1505 }
1506 break;
1507
1508 case disk_rd_config: {
1509 #if defined(POLTS_DISK_TESTING)
1510 if (chan == 014)
1511 #endif
1512 if_sim_debug (DBG_TRACE, & dsk_dev) {
1513 sim_printf ("// Disk IOT Rd Config\r\n");
1514 }
1515
1516 int rc1 = read_configuration (devUnitIdx, iomUnitIdx, chan);
1517 if (rc1) {
1518 rc = IOM_CMD_ERROR;
1519 goto done;
1520 }
1521 }
1522 break;
1523
1524 case disk_rd: {
1525 #if defined(POLTS_DISK_TESTING)
1526 if (chan == 014)
1527 #endif
1528 if_sim_debug (DBG_TRACE, & dsk_dev) {
1529 sim_printf ("// Disk IOT Read\r\n");
1530 }
1531 int rc1 = diskRead (devUnitIdx, iomUnitIdx, chan);
1532 if (rc1) {
1533 rc = IOM_CMD_ERROR;
1534 goto done;
1535 }
1536 }
1537 break;
1538
1539 case disk_rd_ctrl_reg: {
1540 #if defined(POLTS_DISK_TESTING)
1541 if (chan == 014)
1542 #endif
1543 if_sim_debug (DBG_TRACE, & dsk_dev) {
1544 sim_printf ("// Disk IOT Read Control Register\r\n");
1545 }
1546 int rc1 = diskRdCtrlReg (devUnitIdx, iomUnitIdx, chan);
1547 if (rc1) {
1548 rc = IOM_CMD_ERROR;
1549 goto done;
1550 }
1551 }
1552 break;
1553
1554 case disk_seek_512: {
1555 #if defined(POLTS_DISK_TESTING)
1556 if (chan == 014)
1557 #endif
1558 if_sim_debug (DBG_TRACE, & dsk_dev) {
1559 sim_printf ("// Disk IOT Seek 512\r\n");
1560 }
1561 int rc1 = diskSeek512 (devUnitIdx, iomUnitIdx, chan);
1562 if (rc1) {
1563 rc = IOM_CMD_ERROR;
1564 goto done;
1565 }
1566 }
1567 break;
1568
1569 case disk_wr: {
1570 #if defined(POLTS_DISK_TESTING)
1571 if (chan == 014)
1572 #endif
1573 if_sim_debug (DBG_TRACE, & dsk_dev) {
1574 sim_printf ("// Disk IOT Write\r\n");
1575 }
1576 int rc1 = diskWrite (devUnitIdx, iomUnitIdx, chan);
1577 if (rc1) {
1578 rc = IOM_CMD_ERROR;
1579 goto done;
1580 }
1581 }
1582 break;
1583
1584 case disk_seek_64: {
1585 #if defined(POLTS_DISK_TESTING)
1586 if (chan == 014)
1587 #endif
1588 if_sim_debug (DBG_TRACE, & dsk_dev) {
1589 sim_printf ("// Disk IOT Seek 64\r\n");
1590 }
1591 int rc1 = diskSeek64 (devUnitIdx, iomUnitIdx, chan);
1592 if (rc1) {
1593 rc = IOM_CMD_ERROR;
1594 goto done;
1595 }
1596 }
1597 break;
1598
1599 case disk_special_seek: {
1600 #if defined(POLTS_DISK_TESTING)
1601 if (chan == 014)
1602 #endif
1603 if_sim_debug (DBG_TRACE, & dsk_dev) {
1604 sim_printf ("// Disk IOT special seek\r\n");
1605 }
1606 iom_cmd_rc_t rc1 = diskSeekSpecial (devUnitIdx, iomUnitIdx, chan);
1607 if (rc1) {
1608 rc = IOM_CMD_ERROR;
1609 goto done;
1610 }
1611 }
1612 break;
1613 }
1614
1615 done:
1616 #if defined(LOCKLESS)
1617 unlock_ptr (& dsk_states->dsk_lock);
1618 #endif
1619 return rc;
1620 }
1621
1622
1623
1624
1625
1626
1627
1628
1629 #define IPC_UNIT_IDX(uptr) ((uptr) - ipc_unit)
1630 #define N_IPC_UNITS 1
1631
1632 static struct ipc_state
1633 {
1634 char device_name[MAX_DEV_NAME_LEN];
1635 } ipc_states[N_IPC_UNITS_MAX];
1636
1637 UNIT ipc_unit[N_IPC_UNITS_MAX] = {
1638 #if defined(NO_C_ELLIPSIS)
1639 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1640 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1641 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1642 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1643 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1644 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1645 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1646 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1647 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1648 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1649 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1650 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1651 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1652 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1653 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1654 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
1655 #else
1656 [0 ... N_IPC_UNITS_MAX-1] = {
1657 UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
1658 }
1659 #endif
1660 };
1661
1662 static t_stat ipc_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
1663 UNUSED int val, UNUSED const void * desc)
1664 {
1665 sim_printf("Number of IPC units in system is %d\n", ipc_dev.numunits);
1666 return SCPE_OK;
1667 }
1668
1669 static t_stat ipc_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
1670 const char * cptr, UNUSED void * desc)
1671 {
1672 if (! cptr)
1673 return SCPE_ARG;
1674 int n = atoi (cptr);
1675 if (n < 0 || n > N_DSK_UNITS_MAX)
1676 return SCPE_ARG;
1677 ipc_dev.numunits = (uint32) n;
1678 return SCPE_OK;
1679 }
1680
1681 static t_stat ipc_show_device_name (UNUSED FILE * st, UNIT * uptr,
1682 UNUSED int val, UNUSED const void * desc)
1683 {
1684 int n = (int) IPC_UNIT_IDX (uptr);
1685 if (n < 0 || n >= N_IPC_UNITS_MAX)
1686 return SCPE_ARG;
1687 if (ipc_states[n].device_name[0] != 0)
1688 sim_printf("name : %s", ipc_states[n].device_name);
1689 else
1690 sim_printf("name : default");
1691 return SCPE_OK;
1692 }
1693
1694 static t_stat ipc_set_device_name (UNIT * uptr, UNUSED int32 value,
1695 const char * cptr, UNUSED void * desc)
1696 {
1697 int n = (int) IPC_UNIT_IDX (uptr);
1698 if (n < 0 || n >= N_IPC_UNITS_MAX)
1699 return SCPE_ARG;
1700 if (cptr)
1701 {
1702 strncpy (ipc_states[n].device_name, cptr, MAX_DEV_NAME_LEN-1);
1703 ipc_states[n].device_name[MAX_DEV_NAME_LEN-1] = 0;
1704 }
1705 else
1706 ipc_states[n].device_name[0] = 0;
1707 return SCPE_OK;
1708 }
1709
1710 static MTAB ipc_mod[] =
1711 {
1712 {
1713 MTAB_dev_value,
1714 0,
1715 "NUNITS",
1716 "NUNITS",
1717 ipc_set_nunits,
1718 ipc_show_nunits,
1719 "Number of DISK units in the system",
1720 NULL
1721 },
1722 {
1723 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
1724 0,
1725 "NAME",
1726 "NAME",
1727 ipc_set_device_name,
1728 ipc_show_device_name,
1729 "Set the device name",
1730 NULL
1731 },
1732 MTAB_eol
1733 };
1734
1735 DEVICE ipc_dev =
1736 {
1737 "IPC",
1738 ipc_unit,
1739 NULL,
1740 ipc_mod,
1741 N_IPC_UNITS,
1742 10,
1743 24,
1744 1,
1745 8,
1746 36,
1747 NULL,
1748 NULL,
1749 NULL,
1750 NULL,
1751 NULL,
1752 NULL ,
1753 NULL,
1754 0,
1755 0,
1756 NULL,
1757 NULL,
1758 NULL,
1759 NULL,
1760 NULL,
1761 NULL,
1762 NULL,
1763 NULL
1764 };
1765
1766
1767
1768
1769
1770
1771
1772
1773 #define MSP_UNIT_IDX(uptr) ((uptr) - msp_unit)
1774 #define N_MSP_UNITS 1
1775
1776 struct msp_state_s msp_states [N_MSP_UNITS_MAX];
1777
1778 UNIT msp_unit[N_MSP_UNITS_MAX] =
1779 {
1780 #if defined(NO_C_ELLIPSIS)
1781 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1782 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1783 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1784 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1785 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1786 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1787 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1788 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1789 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1790 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1791 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1792 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1793 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1794 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1795 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
1796 { UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
1797 #else
1798 [0 ... N_MSP_UNITS_MAX-1] = {
1799 UDATA (NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
1800 }
1801 #endif
1802 };
1803
1804 static t_stat msp_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
1805 UNUSED int val, UNUSED const void * desc)
1806 {
1807 sim_printf("Number of MSP units in system is %d\n", msp_dev.numunits);
1808 return SCPE_OK;
1809 }
1810
1811 static t_stat msp_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
1812 const char * cptr, UNUSED void * desc)
1813 {
1814 if (! cptr)
1815 return SCPE_ARG;
1816 int n = atoi (cptr);
1817 if (n < 0 || n > N_DSK_UNITS_MAX)
1818 return SCPE_ARG;
1819 msp_dev.numunits = (uint32) n;
1820 return SCPE_OK;
1821 }
1822
1823 static t_stat msp_show_device_name (UNUSED FILE * st, UNIT * uptr,
1824 UNUSED int val, UNUSED const void * desc)
1825 {
1826 int n = (int) MSP_UNIT_IDX (uptr);
1827 if (n < 0 || n >= N_MSP_UNITS_MAX)
1828 return SCPE_ARG;
1829 if (msp_states[n].device_name[0] != 0)
1830 sim_printf("name : %s", msp_states[n].device_name);
1831 else
1832 sim_printf("name : default");
1833 return SCPE_OK;
1834 }
1835
1836 static t_stat msp_set_device_name (UNIT * uptr, UNUSED int32 value,
1837 const char * cptr, UNUSED void * desc)
1838 {
1839 int n = (int) MSP_UNIT_IDX (uptr);
1840 if (n < 0 || n >= N_MSP_UNITS_MAX)
1841 return SCPE_ARG;
1842 if (cptr)
1843 {
1844 strncpy (msp_states[n].device_name, cptr, MAX_DEV_NAME_LEN-1);
1845 msp_states[n].device_name[MAX_DEV_NAME_LEN-1] = 0;
1846 }
1847 else
1848 msp_states[n].device_name[0] = 0;
1849 return SCPE_OK;
1850 }
1851
1852 static MTAB msp_mod[] =
1853 {
1854 {
1855 MTAB_dev_value,
1856 0,
1857 "NUNITS",
1858 "NUNITS",
1859 msp_set_nunits,
1860 msp_show_nunits,
1861 "Number of DISK units in the system",
1862 NULL
1863 },
1864 {
1865 MTAB_XTD | MTAB_VUN | \
1866 MTAB_VALR | MTAB_NC,
1867 0,
1868 "NAME",
1869 "NAME",
1870 msp_set_device_name,
1871 msp_show_device_name,
1872 "Set the device name",
1873 NULL
1874 },
1875 MTAB_eol
1876 };
1877
1878 DEVICE msp_dev =
1879 {
1880 "MSP",
1881 msp_unit,
1882 NULL,
1883 msp_mod,
1884 N_MSP_UNITS,
1885 10,
1886 24,
1887 1,
1888 8,
1889 36,
1890 NULL,
1891 NULL,
1892 NULL,
1893 NULL,
1894 NULL,
1895 NULL ,
1896 NULL,
1897 0,
1898 0,
1899 NULL,
1900 NULL,
1901 NULL,
1902 NULL,
1903 NULL,
1904 NULL,
1905 NULL,
1906 NULL
1907 };