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