This source file includes following definitions.
- _sim_tape_io_flush
- sim_tape_attach
- sim_tape_attach_ex
- sim_tape_detach
- sim_tape_attach_help
- sim_tape_data_trace
- sim_tape_rdlntf
- sim_tape_rdlntr
- sim_tape_rdrecf
- sim_tape_rdrecf_a
- sim_tape_rdrecr
- sim_tape_rdrecr_a
- sim_tape_wrrecf
- sim_tape_wrrecf_a
- sim_tape_wrdata
- sim_tape_wrtmk
- sim_tape_wrtmk_a
- sim_tape_wreom
- sim_tape_wreom_a
- sim_tape_wreomrw
- sim_tape_wreomrw_a
- sim_tape_wrgap
- sim_tape_wrgap_a
- sim_tape_sprecf
- sim_tape_sprecf_a
- sim_tape_sprecsf
- sim_tape_sprecsf_a
- sim_tape_sprecr
- sim_tape_sprecr_a
- sim_tape_sprecsr
- sim_tape_sprecsr_a
- sim_tape_spfilebyrecf
- sim_tape_spfilebyrecf_a
- sim_tape_spfilef
- sim_tape_spfilef_a
- sim_tape_spfilebyrecr
- sim_tape_spfilebyrecr_a
- sim_tape_spfiler
- sim_tape_spfiler_a
- sim_tape_rewind
- sim_tape_rewind_a
- sim_tape_position
- sim_tape_position_a
- sim_tape_reset
- sim_tape_bot
- sim_tape_eot
- sim_tape_wrp
- sim_tape_ioerr
- sim_tape_set_fmt
- sim_tape_show_fmt
- sim_tape_tpc_map
- sim_tape_simh_check
- sim_tape_e11_check
- sim_tape_tpc_fnd
- sim_tape_set_capac
- sim_tape_show_capac
- sim_tape_set_dens
- sim_tape_show_dens
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 #include "sim_defs.h"
73 #include "sim_tape.h"
74 #include <ctype.h>
75 #include <signal.h>
76
77 #ifdef TESTING
78 # undef FREE
79 # define FREE(p) free(p)
80 #endif
81
82 struct sim_tape_fmt {
83 const char *name;
84 int32 uflags;
85 t_addr bot;
86 };
87
88 static struct sim_tape_fmt fmts[MTUF_N_FMT] = {
89 { "SIMH", 0, sizeof (t_mtrlnt) - 1 },
90 { "E11", 0, sizeof (t_mtrlnt) - 1 },
91 { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1 },
92 { "P7B", 0, 0 },
93
94 { NULL, 0, 0 }
95 };
96
97 static const uint32 bpi [] = {
98 0,
99 200,
100 556,
101 800,
102 1600,
103 6250
104 };
105
106 #define BPI_COUNT (sizeof (bpi) / sizeof (bpi [0]))
107
108 static t_stat sim_tape_ioerr (UNIT *uptr);
109 static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat);
110 static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize);
111 static t_stat sim_tape_simh_check (UNIT *uptr);
112 static t_stat sim_tape_e11_check (UNIT *uptr);
113 static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map);
114 static void sim_tape_data_trace (UNIT *uptr, const uint8 *data, size_t len, const char* txt, int detail, uint32 reason);
115
116 struct tape_context {
117 DEVICE *dptr;
118 uint32 dbit;
119 uint32 auto_format;
120 };
121 #define tape_ctx up8
122
123
124
125
126
127 static void _sim_tape_io_flush (UNIT *uptr)
128 {
129 fflush (uptr->fileref);
130 }
131
132
133
134 t_stat sim_tape_attach (UNIT *uptr, CONST char *cptr)
135 {
136 DEVICE *dptr;
137
138 if ((dptr = find_dev_from_unit (uptr)) == NULL)
139 return SCPE_NOATT;
140 return sim_tape_attach_ex (uptr, cptr, (dptr->flags & DEV_DEBUG) ? 0xFFFFFFFF : 0, 0);
141 }
142
143 t_stat sim_tape_attach_ex (UNIT *uptr, const char *cptr, uint32 dbit, int completion_delay)
144 {
145 struct tape_context *ctx;
146 uint32 objc;
147 DEVICE *dptr;
148 char gbuf[CBUFSIZE];
149 t_stat r;
150 t_bool auto_format = FALSE;
151
152 if ((dptr = find_dev_from_unit (uptr)) == NULL)
153 return SCPE_NOATT;
154 if (sim_switches & SWMASK ('F')) {
155 cptr = get_glyph (cptr, gbuf, 0);
156 if (*cptr == 0)
157 return SCPE_2FARG;
158 if (sim_tape_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK)
159 return sim_messagef (SCPE_ARG, "Invalid Tape Format: %s\n", gbuf);
160 sim_switches = sim_switches & ~(SWMASK ('F'));
161 auto_format = TRUE;
162 }
163 if (MT_GET_FMT (uptr) == MTUF_F_TPC)
164 sim_switches |= SWMASK ('R');
165 r = attach_unit (uptr, (CONST char *)cptr);
166 if (r != SCPE_OK)
167 return sim_messagef (r, "Can't open tape image: %s\n", cptr);
168 switch (MT_GET_FMT (uptr)) {
169
170 case MTUF_F_STD:
171 if (SCPE_OK != sim_tape_simh_check (uptr)) {
172 sim_tape_detach (uptr);
173 return SCPE_FMT;
174 }
175 break;
176
177 case MTUF_F_E11:
178 if (SCPE_OK != sim_tape_e11_check (uptr)) {
179 sim_tape_detach (uptr);
180 return SCPE_FMT;
181 }
182 break;
183
184 case MTUF_F_TPC:
185 objc = sim_tape_tpc_map (uptr, NULL, 0);
186 if (objc == 0) {
187 sim_tape_detach (uptr);
188 return SCPE_FMT;
189 }
190 uptr->filebuf = calloc (objc + 1, sizeof (t_addr));
191 if (uptr->filebuf == NULL) {
192 sim_tape_detach (uptr);
193 return SCPE_MEM;
194 }
195 uptr->hwmark = objc + 1;
196 sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf, objc);
197 break;
198
199 default:
200 break;
201 }
202
203 uptr->tape_ctx = ctx = (struct tape_context *)calloc(1, sizeof(struct tape_context));
204 if (!ctx)
205 {
206 fprintf(stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
207 __func__, __FILE__, __LINE__);
208 #if defined(USE_BACKTRACE)
209 # ifdef SIGUSR2
210 (void)raise(SIGUSR2);
211
212 # endif
213 #endif
214 abort();
215 }
216 ctx->dptr = dptr;
217 ctx->dbit = dbit;
218 ctx->auto_format = auto_format;
219
220 sim_tape_rewind (uptr);
221
222 uptr->io_flush = _sim_tape_io_flush;
223
224 return SCPE_OK;
225 }
226
227
228
229 t_stat sim_tape_detach (UNIT *uptr)
230 {
231 struct tape_context *ctx;
232 uint32 f = 0;
233 t_stat r;
234 t_bool auto_format = FALSE;
235
236 if (uptr == NULL)
237 return SCPE_IERR;
238
239 if (!(uptr->flags & UNIT_ATT))
240 return SCPE_UNATT;
241
242 ctx = (struct tape_context *)uptr->tape_ctx;
243 f = MT_GET_FMT (uptr);
244
245 if (uptr->io_flush)
246 uptr->io_flush (uptr);
247 if (ctx)
248 auto_format = ctx->auto_format;
249
250 r = detach_unit (uptr);
251 if (r != SCPE_OK)
252 return r;
253 switch (f) {
254
255 case MTUF_F_TPC:
256 if (uptr->filebuf)
257 FREE (uptr->filebuf);
258 uptr->filebuf = NULL;
259 uptr->hwmark = 0;
260 break;
261
262 default:
263 break;
264 }
265
266 sim_tape_rewind (uptr);
267 FREE (uptr->tape_ctx);
268 uptr->tape_ctx = NULL;
269 uptr->io_flush = NULL;
270 if (auto_format)
271 sim_tape_set_fmt (uptr, 0, "SIMH", NULL);
272 return SCPE_OK;
273 }
274
275 t_stat sim_tape_attach_help(FILE *st, DEVICE *dptr, const UNIT *uptr, int32 flag, const char *cptr)
276 {
277 fprintf (st, "%s Tape Attach Help\n\n", dptr->name);
278 if (0 == (uptr-dptr->units)) {
279 if (dptr->numunits > 1) {
280 uint32 i;
281
282 for (i=0; i < dptr->numunits; ++i)
283 if (dptr->units[i].flags & UNIT_ATTABLE)
284 fprintf (st, " sim> ATTACH {switches} %s%lu tapefile\n\n", dptr->name, (unsigned long)i);
285 }
286 else
287 fprintf (st, " sim> ATTACH {switches} %s tapefile\n\n", dptr->name);
288 }
289 else
290 fprintf (st, " sim> ATTACH {switches} %s tapefile\n\n", dptr->name);
291 fprintf (st, "Attach command switches\n");
292 fprintf (st, " -R Attach Read Only.\n");
293 fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n");
294 fprintf (st, " virtual tape will be attempted).\n");
295 fprintf (st, " -F Open the indicated tape container in a specific format (default\n");
296 fprintf (st, " is SIMH, alternatives are E11, TPC and P7B)\n");
297 return SCPE_OK;
298 }
299
300 static void sim_tape_data_trace(UNIT *uptr, const uint8 *data, size_t len, const char* txt, int detail, uint32 reason)
301 {
302 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
303
304 if (ctx == NULL)
305 return;
306 if (sim_deb && (ctx->dptr->dctrl & reason))
307 sim_data_trace(ctx->dptr, uptr, (detail ? data : NULL), "", len, txt, reason);
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395 static t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc)
396 {
397 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
398 uint8 c;
399 t_bool all_eof;
400 uint32 f = MT_GET_FMT (uptr);
401 t_mtrlnt sbc;
402 t_tpclnt tpcbc;
403 t_mtrlnt buffer [256];
404 uint32 bufcntr, bufcap;
405 int32 runaway_counter, sizeof_gap;
406 t_stat r = MTSE_OK;
407
408 MT_CLR_PNU (uptr);
409
410 if ((uptr->flags & UNIT_ATT) == 0)
411 return MTSE_UNATT;
412 if (ctx == NULL)
413 return sim_messagef (SCPE_IERR, "Bad Attach\n");
414
415 sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
416
417 switch (f) {
418
419 case MTUF_F_STD:
420 case MTUF_F_E11:
421 runaway_counter = 25 * 12 * bpi [MT_DENS (uptr->dynflags)];
422
423 if (runaway_counter == 0) {
424 sizeof_gap = 0;
425 runaway_counter = INT_MAX;
426 }
427 else
428 sizeof_gap = sizeof (t_mtrlnt);
429
430 bufcntr = 0;
431 bufcap = 0;
432
433 do {
434 if (bufcntr == bufcap) {
435 if (feof (uptr->fileref)) {
436 if (sizeof_gap > 0)
437 r = MTSE_RUNAWAY;
438 else
439 r = MTSE_EOM;
440 break;
441 }
442
443 else if (bufcap == 0)
444 bufcap = 1;
445
446 else
447 bufcap = sizeof (buffer)
448 / sizeof (buffer [0]);
449
450 bufcap = sim_fread (buffer,
451 sizeof (t_mtrlnt),
452 bufcap,
453 uptr->fileref);
454
455 if (ferror (uptr->fileref)) {
456 if (bufcntr == 0)
457 MT_SET_PNU (uptr);
458
459 r = sim_tape_ioerr (uptr);
460 break;
461 }
462
463 else if (bufcap == 0
464 || buffer [0] == MTR_EOM)
465 if (bufcntr == 0) {
466 MT_SET_PNU (uptr);
467 r = MTSE_EOM;
468 break;
469 }
470
471 else {
472 if (sizeof_gap > 0)
473 r = MTSE_RUNAWAY;
474 else
475 r = MTSE_EOM;
476 break;
477 }
478
479 else
480 bufcntr = 0;
481 }
482
483 *bc = buffer [bufcntr++];
484
485 if (*bc == MTR_EOM) {
486 if (sizeof_gap > 0)
487 r = MTSE_RUNAWAY;
488 else
489 r = MTSE_EOM;
490 break;
491 }
492
493 uptr->pos = uptr->pos + sizeof (t_mtrlnt);
494
495 if (*bc == MTR_TMK) {
496 r = MTSE_TMK;
497 break;
498 }
499
500 else if (*bc == MTR_GAP)
501 runaway_counter -= sizeof_gap;
502
503 else if (*bc == MTR_FHGAP) {
504 uptr->pos = uptr->pos - sizeof (t_mtrlnt) / 2;
505 (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
506 bufcntr = bufcap;
507
508 *bc = MTR_GAP;
509 runaway_counter -= sizeof_gap / 2;
510 }
511
512 else {
513 if (bufcntr < bufcap)
514 (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
515
516 sbc = MTR_L (*bc);
517 uptr->pos = uptr->pos + sizeof (t_mtrlnt)
518 + (f == MTUF_F_STD ? (sbc + 1) & ~1 : sbc);
519 }
520 }
521 while (*bc == MTR_GAP && runaway_counter > 0);
522
523 if (r == MTSE_OK && runaway_counter <= 0)
524 r = MTSE_RUNAWAY;
525
526 break;
527
528 case MTUF_F_TPC:
529 (void)sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref);
530 *bc = tpcbc;
531 if (ferror (uptr->fileref)) {
532 MT_SET_PNU (uptr);
533 return sim_tape_ioerr (uptr);
534 }
535 if (feof (uptr->fileref)) {
536 MT_SET_PNU (uptr);
537 r = MTSE_EOM;
538 break;
539 }
540 uptr->pos = uptr->pos + sizeof (t_tpclnt);
541 if (tpcbc == TPC_TMK)
542 r = MTSE_TMK;
543 uptr->pos = uptr->pos + ((tpcbc + 1) & ~1);
544 break;
545
546 case MTUF_F_P7B:
547 for (sbc = 0, all_eof = 1; ; sbc++) {
548 (void)sim_fread (&c, sizeof (uint8), 1, uptr->fileref);
549 if (ferror (uptr->fileref)) {
550 MT_SET_PNU (uptr);
551 return sim_tape_ioerr (uptr);
552 }
553 if (feof (uptr->fileref)) {
554 if (sbc == 0)
555 return MTSE_EOM;
556 break;
557 }
558 if ((sbc != 0) && (c & P7B_SOR))
559 break;
560 if ((c & P7B_DPAR) != P7B_EOF)
561 all_eof = 0;
562 }
563 *bc = sbc;
564 (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
565 uptr->pos = uptr->pos + sbc;
566 if (all_eof)
567 r = MTSE_TMK;
568 break;
569
570 default:
571 return MTSE_FMT;
572 }
573 #ifdef TESTING
574 sim_debug (MTSE_DBG_STR, ctx->dptr, "rd_lnt: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", r, *bc, uptr->pos);
575 #endif
576 return r;
577 }
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608 static t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc)
609 {
610 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
611 uint8 c;
612 t_bool all_eof;
613 uint32 f = MT_GET_FMT (uptr);
614 t_addr ppos;
615 t_mtrlnt sbc;
616 t_tpclnt tpcbc;
617 t_mtrlnt buffer [256];
618 uint32 bufcntr, bufcap;
619 int32 runaway_counter, sizeof_gap;
620 t_stat r = MTSE_OK;
621
622 MT_CLR_PNU (uptr);
623 *bc = 0;
624
625 if ((uptr->flags & UNIT_ATT) == 0)
626 return MTSE_UNATT;
627 if (ctx == NULL)
628 return sim_messagef (SCPE_IERR, "Bad Attach\n");
629
630 if (sim_tape_bot (uptr))
631 return MTSE_BOT;
632
633 switch (f) {
634
635 case MTUF_F_STD:
636 case MTUF_F_E11:
637 runaway_counter = 25 * 12 * bpi [MT_DENS (uptr->dynflags)];
638
639 if (runaway_counter == 0) {
640 sizeof_gap = 0;
641 runaway_counter = INT_MAX;
642 }
643
644 else
645 sizeof_gap = sizeof (t_mtrlnt);
646
647 bufcntr = 0;
648 bufcap = 1;
649
650 do {
651 if (bufcntr == 0) {
652 if (sim_tape_bot (uptr)) {
653 r = MTSE_BOT;
654 break;
655 }
656
657 else if (uptr->pos < sizeof (buffer))
658 bufcap = (uint32) uptr->pos
659 / sizeof (t_mtrlnt);
660
661 (void)sim_fseek (uptr->fileref,
662 uptr->pos - bufcap * sizeof (t_mtrlnt),
663 SEEK_SET);
664
665 bufcntr = sim_fread (buffer, sizeof (t_mtrlnt),
666 bufcap, uptr->fileref);
667
668 if (ferror (uptr->fileref)) {
669 MT_SET_PNU (uptr);
670 r = sim_tape_ioerr (uptr);
671 break;
672 }
673
674 else
675 bufcap = sizeof (buffer)
676 / sizeof (buffer [0]);
677 }
678
679 *bc = buffer [--bufcntr];
680
681 uptr->pos = uptr->pos - sizeof (t_mtrlnt);
682
683 if (*bc == MTR_TMK) {
684 r = MTSE_TMK;
685 break;
686 }
687
688 else if (*bc == MTR_GAP)
689 runaway_counter -= sizeof_gap;
690
691 else if ((*bc & MTR_M_RHGAP) == MTR_RHGAP
692 || *bc == MTR_RRGAP) {
693 uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2;
694 bufcntr = 0;
695
696 *bc = MTR_GAP;
697 runaway_counter -= sizeof_gap / 2;
698 }
699
700 else {
701 sbc = MTR_L (*bc);
702 uptr->pos = uptr->pos - sizeof (t_mtrlnt)
703 - (f == MTUF_F_STD ? (sbc + 1) & ~1 : sbc);
704 (void)sim_fseek (uptr->fileref,
705 uptr->pos + sizeof (t_mtrlnt), SEEK_SET);
706 }
707 }
708 while (*bc == MTR_GAP && runaway_counter > 0);
709
710 if (r == MTSE_OK && runaway_counter <= 0)
711 r = MTSE_RUNAWAY;
712
713 break;
714
715 case MTUF_F_TPC:
716 ppos = sim_tape_tpc_fnd (uptr, (t_addr *) uptr->filebuf);
717 (void)sim_fseek (uptr->fileref, ppos, SEEK_SET);
718 (void)sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref);
719 *bc = tpcbc;
720 if (ferror (uptr->fileref))
721 return sim_tape_ioerr (uptr);
722 if (feof (uptr->fileref)) {
723 r = MTSE_EOM;
724 break;
725 }
726 uptr->pos = ppos;
727 if (*bc == MTR_TMK) {
728 r = MTSE_TMK;
729 break;
730 }
731 (void)sim_fseek (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET);
732 break;
733
734 case MTUF_F_P7B:
735 for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) {
736 (void)sim_fseek (uptr->fileref, uptr->pos - sbc, SEEK_SET);
737 (void)sim_fread (&c, sizeof (uint8), 1, uptr->fileref);
738 if (ferror (uptr->fileref))
739 return sim_tape_ioerr (uptr);
740 if (feof (uptr->fileref)) {
741 r = MTSE_EOM;
742 break;
743 }
744 if ((c & P7B_DPAR) != P7B_EOF)
745 all_eof = 0;
746 if (c & P7B_SOR)
747 break;
748 }
749 uptr->pos = uptr->pos - sbc;
750 *bc = sbc;
751 (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
752 if (all_eof)
753 r = MTSE_TMK;
754 break;
755
756 default:
757 return MTSE_FMT;
758 }
759 sim_debug (MTSE_DBG_STR, ctx->dptr, "rd_lnt: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", r, *bc, uptr->pos);
760 return r;
761 }
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784 t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max)
785 {
786 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
787 uint32 f = MT_GET_FMT (uptr);
788 t_mtrlnt i, tbc, rbc;
789 t_addr opos;
790 t_stat st;
791
792 if (ctx == NULL)
793 return sim_messagef (SCPE_IERR, "Bad Attach\n");
794 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_rdrecf(unit=%d, buf=%p, max=%d)\n", (int)(uptr-ctx->dptr->units), buf, max);
795
796 opos = uptr->pos;
797 if (MTSE_OK != (st = sim_tape_rdlntf (uptr, &tbc)))
798 return st;
799 *bc = rbc = MTR_L (tbc);
800 if (rbc > max) {
801 MT_SET_PNU (uptr);
802 uptr->pos = opos;
803 return MTSE_INVRL;
804 }
805 i = (t_mtrlnt)sim_fread (buf, sizeof (uint8), rbc, uptr->fileref);
806 if (ferror (uptr->fileref)) {
807 MT_SET_PNU (uptr);
808 uptr->pos = opos;
809 return sim_tape_ioerr (uptr);
810 }
811 for ( ; i < rbc; i++)
812 buf[i] = 0;
813 if (f == MTUF_F_P7B)
814 buf[0] = buf[0] & P7B_DPAR;
815 sim_tape_data_trace(uptr, buf, rbc, "Record Read", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
816 return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
817 }
818
819 t_stat sim_tape_rdrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback)
820 {
821 t_stat r = SCPE_OK;
822 r = sim_tape_rdrecf (uptr, buf, bc, max);
823 return r;
824 }
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848 t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max)
849 {
850 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
851 uint32 f = MT_GET_FMT (uptr);
852 t_mtrlnt i, rbc, tbc;
853 t_stat st;
854
855 if (ctx == NULL)
856 return sim_messagef (SCPE_IERR, "Bad Attach\n");
857 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_rdrecr(unit=%d, buf=%p, max=%d)\n", (int)(uptr-ctx->dptr->units), buf, max);
858
859 if (MTSE_OK != (st = sim_tape_rdlntr (uptr, &tbc)))
860 return st;
861 *bc = rbc = MTR_L (tbc);
862 if (rbc > max)
863 return MTSE_INVRL;
864 i = (t_mtrlnt)sim_fread (buf, sizeof (uint8), rbc, uptr->fileref);
865 if (ferror (uptr->fileref))
866 return sim_tape_ioerr (uptr);
867 for ( ; i < rbc; i++)
868 buf[i] = 0;
869 if (f == MTUF_F_P7B)
870 buf[0] = buf[0] & P7B_DPAR;
871 sim_tape_data_trace(uptr, buf, rbc, "Record Read Reverse", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
872 return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
873 }
874
875 t_stat sim_tape_rdrecr_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback)
876 {
877 t_stat r = SCPE_OK;
878 r = sim_tape_rdrecr (uptr, buf, bc, max);
879 return r;
880 }
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899 t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc)
900 {
901 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
902 uint32 f = MT_GET_FMT (uptr);
903 t_mtrlnt sbc;
904
905 if (ctx == NULL)
906 return sim_messagef (SCPE_IERR, "Bad Attach\n");
907 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wrrecf(unit=%d, buf=%p, bc=%d)\n", (int)(uptr-ctx->dptr->units), buf, bc);
908
909 sim_tape_data_trace(uptr, buf, bc, "Record Write", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
910 MT_CLR_PNU (uptr);
911 sbc = MTR_L (bc);
912 if ((uptr->flags & UNIT_ATT) == 0)
913 return MTSE_UNATT;
914 if (sim_tape_wrp (uptr))
915 return MTSE_WRP;
916 if (sbc == 0)
917 return MTSE_OK;
918 (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
919 switch (f) {
920
921 case MTUF_F_STD:
922 sbc = MTR_L ((bc + 1) & ~1);
923
924 case MTUF_F_E11:
925 (void)sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
926 (void)sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref);
927 (void)sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
928 if (ferror (uptr->fileref)) {
929 MT_SET_PNU (uptr);
930 return sim_tape_ioerr (uptr);
931 }
932 uptr->pos = uptr->pos + sbc + (2 * sizeof (t_mtrlnt));
933 break;
934
935 case MTUF_F_P7B:
936 buf[0] = buf[0] | P7B_SOR;
937 (void)sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref);
938 (void)sim_fwrite (buf, sizeof (uint8), 1, uptr->fileref);
939 if (ferror (uptr->fileref)) {
940 MT_SET_PNU (uptr);
941 return sim_tape_ioerr (uptr);
942 }
943 uptr->pos = uptr->pos + sbc;
944 break;
945 }
946 sim_tape_data_trace(uptr, buf, sbc, "Record Written", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
947 return MTSE_OK;
948 }
949
950 t_stat sim_tape_wrrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt bc, TAPE_PCALLBACK callback)
951 {
952 t_stat r = SCPE_OK;
953 r = sim_tape_wrrecf (uptr, buf, bc);
954 return r;
955 }
956
957
958
959 static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat)
960 {
961 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
962
963 MT_CLR_PNU (uptr);
964 if ((uptr->flags & UNIT_ATT) == 0)
965 return MTSE_UNATT;
966 if (ctx == NULL)
967 return sim_messagef (SCPE_IERR, "Bad Attach\n");
968 if (sim_tape_wrp (uptr))
969 return MTSE_WRP;
970 (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
971 (void)sim_fwrite (&dat, sizeof (t_mtrlnt), 1, uptr->fileref);
972 if (ferror (uptr->fileref)) {
973 MT_SET_PNU (uptr);
974 return sim_tape_ioerr (uptr);
975 }
976 sim_debug (MTSE_DBG_STR, ctx->dptr, "wr_lnt: lnt: %d, pos: %" T_ADDR_FMT "u\n", dat, uptr->pos);
977 uptr->pos = uptr->pos + sizeof (t_mtrlnt);
978 return MTSE_OK;
979 }
980
981
982
983 t_stat sim_tape_wrtmk (UNIT *uptr)
984 {
985 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
986
987 if (ctx == NULL)
988 return sim_messagef (SCPE_IERR, "Bad Attach\n");
989 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wrtmk(unit=%d)\n", (int)(uptr-ctx->dptr->units));
990 if (MT_GET_FMT (uptr) == MTUF_F_P7B) {
991 uint8 buf = P7B_EOF;
992 return sim_tape_wrrecf (uptr, &buf, 1);
993 }
994 return sim_tape_wrdata (uptr, MTR_TMK);
995 }
996
997 t_stat sim_tape_wrtmk_a (UNIT *uptr, TAPE_PCALLBACK callback)
998 {
999 t_stat r = MTSE_OK;
1000 r = sim_tape_wrtmk (uptr);
1001 return r;
1002 }
1003
1004
1005
1006 t_stat sim_tape_wreom (UNIT *uptr)
1007 {
1008 t_stat result;
1009 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1010
1011 if (ctx == NULL)
1012 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1013 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wreom(unit=%d)\n", (int)(uptr-ctx->dptr->units));
1014 if (MT_GET_FMT (uptr) == MTUF_F_P7B)
1015 return MTSE_FMT;
1016
1017 result = sim_tape_wrdata (uptr, MTR_EOM);
1018
1019 uptr->pos = uptr->pos - sizeof (t_mtrlnt);
1020 MT_SET_PNU (uptr);
1021
1022 return result;
1023 }
1024
1025 t_stat sim_tape_wreom_a (UNIT *uptr, TAPE_PCALLBACK callback)
1026 {
1027 t_stat r = MTSE_OK;
1028 r = sim_tape_wreom (uptr);
1029 return r;
1030 }
1031
1032
1033
1034 t_stat sim_tape_wreomrw (UNIT *uptr)
1035 {
1036 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1037 t_stat r;
1038
1039 if (ctx == NULL)
1040 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1041 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wreomrw(unit=%d)\n", (int)(uptr-ctx->dptr->units));
1042 if (MT_GET_FMT (uptr) == MTUF_F_P7B)
1043 return MTSE_FMT;
1044 r = sim_tape_wrdata (uptr, MTR_EOM);
1045 if (r == MTSE_OK)
1046 r = sim_tape_rewind (uptr);
1047 return r;
1048 }
1049
1050 t_stat sim_tape_wreomrw_a (UNIT *uptr, TAPE_PCALLBACK callback)
1051 {
1052 t_stat r = MTSE_OK;
1053 r = sim_tape_wreomrw (uptr);
1054 return r;
1055 }
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
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
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157 t_stat sim_tape_wrgap (UNIT *uptr, uint32 gaplen)
1158 {
1159 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1160 t_stat st;
1161 t_mtrlnt meta, sbc, new_len, rec_size;
1162 t_addr gap_pos = uptr->pos;
1163 uint32 file_size, marker_count, tape_density;
1164 int32 gap_needed;
1165 uint32 gap_alloc = 0;
1166 const uint32 format = MT_GET_FMT (uptr);
1167 const uint32 meta_size = sizeof (t_mtrlnt);
1168 const uint32 min_rec_size = 2 + sizeof (t_mtrlnt) * 2;
1169
1170 if (ctx == NULL)
1171 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1172 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_wrgap(unit=%d, gaplen=%u)\n", (int)(uptr-ctx->dptr->units), gaplen);
1173
1174 MT_CLR_PNU (uptr);
1175
1176 if ((uptr->flags & UNIT_ATT) == 0)
1177 return MTSE_UNATT;
1178
1179 else if (sim_tape_wrp (uptr))
1180 return MTSE_WRP;
1181
1182 tape_density = bpi [MT_DENS (uptr->dynflags)];
1183
1184 if (format != MTUF_F_STD)
1185 return MTSE_OK;
1186 else if (tape_density == 0)
1187 return MTSE_IOERR;
1188 else
1189 gap_needed = (gaplen * tape_density) / 10;
1190
1191 file_size = sim_fsize (uptr->fileref);
1192 sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205 do {
1206 (void)sim_fread (&meta, meta_size, 1, uptr->fileref);
1207
1208 if (ferror (uptr->fileref)) {
1209 uptr->pos = gap_pos;
1210 MT_SET_PNU (uptr);
1211 return sim_tape_ioerr (uptr);
1212 }
1213 else
1214 uptr->pos = uptr->pos + meta_size;
1215
1216 if (feof (uptr->fileref) || (meta == MTR_EOM)) {
1217 gap_alloc = gap_alloc + gap_needed;
1218 gap_needed = 0;
1219 }
1220
1221 else if ((meta == MTR_GAP) || (meta == MTR_TMK)) {
1222 gap_alloc = gap_alloc + meta_size;
1223 gap_needed = gap_needed - meta_size;
1224 }
1225
1226 else if (meta == MTR_FHGAP) {
1227 uptr->pos = uptr->pos - meta_size / 2;
1228 sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
1229 gap_alloc = gap_alloc + meta_size / 2;
1230 gap_needed = gap_needed - meta_size / 2;
1231 }
1232
1233 else if (uptr->pos +
1234 MTR_L (meta) + meta_size > file_size) {
1235 gap_alloc = gap_alloc + gap_needed;
1236 gap_needed = 0;
1237 }
1238
1239
1240
1241
1242
1243
1244
1245 else {
1246 sbc = MTR_L (meta);
1247 rec_size = ((sbc + 1) & ~1) + meta_size * 2;
1248
1249 if (rec_size < gap_needed + min_rec_size) {
1250 uptr->pos = uptr->pos - meta_size + rec_size;
1251 sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
1252 gap_alloc = gap_alloc + rec_size;
1253 gap_needed = gap_needed - rec_size;
1254 }
1255
1256 else {
1257 uptr->pos = uptr->pos - meta_size + gap_needed;
1258 new_len = MTR_F (meta) | (sbc - gap_needed);
1259 st = sim_tape_wrdata (uptr, new_len);
1260
1261 if (st != MTSE_OK) {
1262 uptr->pos = gap_pos;
1263 return st;
1264 }
1265
1266 uptr->pos = uptr->pos + sbc - gap_needed;
1267 st = sim_tape_wrdata (uptr, new_len);
1268
1269 if (st != MTSE_OK) {
1270 uptr->pos = gap_pos;
1271 return st;
1272 }
1273
1274 gap_alloc = gap_alloc + gap_needed;
1275 gap_needed = 0;
1276 }
1277 }
1278 }
1279 while (gap_needed > 0);
1280
1281 uptr->pos = gap_pos;
1282
1283 if (gap_alloc & (meta_size - 1)) {
1284 st = sim_tape_wrdata (uptr, MTR_FHGAP);
1285 if (st != MTSE_OK) {
1286 uptr->pos = gap_pos;
1287 return st;
1288 }
1289 uptr->pos = uptr->pos - meta_size / 2;
1290 gap_alloc = gap_alloc - 2;
1291 }
1292
1293 marker_count = gap_alloc / meta_size;
1294
1295 do {
1296 st = sim_tape_wrdata (uptr, MTR_GAP);
1297 if (st != MTSE_OK) {
1298 uptr->pos = gap_pos;
1299 return st;
1300 }
1301 }
1302 while (--marker_count > 0);
1303
1304 return MTSE_OK;
1305 }
1306
1307 t_stat sim_tape_wrgap_a (UNIT *uptr, uint32 gaplen, TAPE_PCALLBACK callback)
1308 {
1309 t_stat r = MTSE_OK;
1310 return r;
1311 }
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc)
1332 {
1333 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1334 t_stat st;
1335
1336 *bc = 0;
1337 if (ctx == NULL)
1338 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1339 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecf(unit=%d)\n", (int)(uptr-ctx->dptr->units));
1340
1341 st = sim_tape_rdlntf (uptr, bc);
1342 *bc = MTR_L (*bc);
1343 return st;
1344 }
1345
1346 t_stat sim_tape_sprecf_a (UNIT *uptr, t_mtrlnt *bc, TAPE_PCALLBACK callback)
1347 {
1348 t_stat r = MTSE_OK;
1349 r = sim_tape_sprecf (uptr, bc);
1350 return r;
1351 }
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372 t_stat sim_tape_sprecsf (UNIT *uptr, uint32 count, uint32 *skipped)
1373 {
1374 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1375 t_stat st;
1376 t_mtrlnt tbc;
1377
1378 if (ctx == NULL)
1379 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1380 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecsf(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
1381
1382 *skipped = 0;
1383 while (*skipped < count) {
1384 st = sim_tape_sprecf (uptr, &tbc);
1385 if (st != MTSE_OK)
1386 return st;
1387 *skipped = *skipped + 1;
1388 }
1389 return MTSE_OK;
1390 }
1391
1392 t_stat sim_tape_sprecsf_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback)
1393 {
1394 t_stat r = MTSE_OK;
1395 r = sim_tape_sprecsf (uptr, count, skipped);
1396 return r;
1397 }
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418 t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc)
1419 {
1420 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1421 t_stat st;
1422
1423 if (ctx == NULL)
1424 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1425 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecr(unit=%d)\n", (int)(uptr-ctx->dptr->units));
1426
1427 if (MT_TST_PNU (uptr)) {
1428 MT_CLR_PNU (uptr);
1429 *bc = 0;
1430 return MTSE_OK;
1431 }
1432 st = sim_tape_rdlntr (uptr, bc);
1433 *bc = MTR_L (*bc);
1434 return st;
1435 }
1436
1437 t_stat sim_tape_sprecr_a (UNIT *uptr, t_mtrlnt *bc, TAPE_PCALLBACK callback)
1438 {
1439 t_stat r = MTSE_OK;
1440 r = sim_tape_sprecr (uptr, bc);
1441 return r;
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464 t_stat sim_tape_sprecsr (UNIT *uptr, uint32 count, uint32 *skipped)
1465 {
1466 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1467 t_stat st;
1468 t_mtrlnt tbc;
1469
1470 if (ctx == NULL)
1471 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1472 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_sprecsr(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
1473
1474 *skipped = 0;
1475 while (*skipped < count) {
1476 st = sim_tape_sprecr (uptr, &tbc);
1477 if (st != MTSE_OK)
1478 return st;
1479 *skipped = *skipped + 1;
1480 }
1481 return MTSE_OK;
1482 }
1483
1484 t_stat sim_tape_sprecsr_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback)
1485 {
1486 t_stat r = MTSE_OK;
1487 r = sim_tape_sprecsr (uptr, count, skipped);
1488 return r;
1489 }
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512 t_stat sim_tape_spfilebyrecf (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, t_bool check_leot)
1513 {
1514 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1515 t_stat st;
1516 t_bool last_tapemark = FALSE;
1517 uint32 filerecsskipped = 0;
1518 *skipped = *recsskipped = 0;
1519 if (ctx == NULL)
1520 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1521 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfilebyrecf(unit=%d, count=%d, check_leot=%d)\n", (int)(uptr-ctx->dptr->units), count, check_leot);
1522
1523 if (check_leot) {
1524 t_mtrlnt rbc;
1525
1526 st = sim_tape_rdlntr (uptr, &rbc);
1527 last_tapemark = (MTSE_TMK == st);
1528 if ((st == MTSE_OK) || (st == MTSE_TMK))
1529 sim_tape_rdlntf (uptr, &rbc);
1530 }
1531 *skipped = 0;
1532 *recsskipped = 0;
1533 while (*skipped < count) {
1534 while (1) {
1535 st = sim_tape_sprecsf (uptr, 0x1ffffff, &filerecsskipped);
1536 *recsskipped += filerecsskipped;
1537 if (st != MTSE_OK)
1538 break;
1539 }
1540 if (st == MTSE_TMK) {
1541 *skipped = *skipped + 1;
1542 if (check_leot && (filerecsskipped == 0) && last_tapemark) {
1543 uint32 filefileskipped;
1544 sim_tape_spfilebyrecr (uptr, 1, &filefileskipped, &filerecsskipped);
1545 *skipped = *skipped - 1;
1546 return MTSE_LEOT;
1547 }
1548 last_tapemark = TRUE;
1549 }
1550 else
1551 return st;
1552 }
1553 return MTSE_OK;
1554 }
1555
1556 t_stat sim_tape_spfilebyrecf_a (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, t_bool check_leot, TAPE_PCALLBACK callback)
1557 {
1558 t_stat r = MTSE_OK;
1559 r = sim_tape_spfilebyrecf (uptr, count, skipped, recsskipped, check_leot);
1560 return r;
1561 }
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582 t_stat sim_tape_spfilef (UNIT *uptr, uint32 count, uint32 *skipped)
1583 {
1584 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1585 uint32 totalrecsskipped;
1586
1587 if (ctx == NULL)
1588 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1589 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfilef(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
1590
1591 return sim_tape_spfilebyrecf (uptr, count, skipped, &totalrecsskipped, FALSE);
1592 }
1593
1594 t_stat sim_tape_spfilef_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback)
1595 {
1596 t_stat r = MTSE_OK;
1597 r = sim_tape_spfilef (uptr, count, skipped);
1598 return r;
1599 }
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622 t_stat sim_tape_spfilebyrecr (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped)
1623 {
1624 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1625 t_stat st;
1626 uint32 filerecsskipped = 0;
1627
1628 *skipped = 0;
1629 *recsskipped = 0;
1630 if (ctx == NULL)
1631 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1632 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfilebyrecr(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
1633
1634 while (*skipped < count) {
1635 while (1) {
1636 st = sim_tape_sprecsr (uptr, 0x1ffffff, &filerecsskipped);
1637 *recsskipped += filerecsskipped;
1638 if (st != MTSE_OK)
1639 break;
1640 }
1641 if (st == MTSE_TMK)
1642 *skipped = *skipped + 1;
1643 else
1644 return st;
1645 }
1646 return MTSE_OK;
1647 }
1648
1649 t_stat sim_tape_spfilebyrecr_a (UNIT *uptr, uint32 count, uint32 *skipped, uint32 *recsskipped, TAPE_PCALLBACK callback)
1650 {
1651 t_stat r = MTSE_OK;
1652 r = sim_tape_spfilebyrecr (uptr, count, skipped, recsskipped);
1653 return r;
1654 }
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676 t_stat sim_tape_spfiler (UNIT *uptr, uint32 count, uint32 *skipped)
1677 {
1678 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1679 uint32 totalrecsskipped;
1680
1681 if (ctx == NULL)
1682 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1683 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_spfiler(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
1684
1685 return sim_tape_spfilebyrecr (uptr, count, skipped, &totalrecsskipped);
1686 }
1687
1688 t_stat sim_tape_spfiler_a (UNIT *uptr, uint32 count, uint32 *skipped, TAPE_PCALLBACK callback)
1689 {
1690 t_stat r = MTSE_OK;
1691 r = sim_tape_spfiler (uptr, count, skipped);
1692 return r;
1693 }
1694
1695
1696
1697 t_stat sim_tape_rewind (UNIT *uptr)
1698 {
1699 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1700
1701 if (uptr->flags & UNIT_ATT) {
1702 if (ctx == NULL)
1703 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1704 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_rewind(unit=%d)\n", (int)(uptr-ctx->dptr->units));
1705 }
1706 uptr->pos = 0;
1707 MT_CLR_PNU (uptr);
1708 return MTSE_OK;
1709 }
1710
1711 t_stat sim_tape_rewind_a (UNIT *uptr, TAPE_PCALLBACK callback)
1712 {
1713 t_stat r = MTSE_OK;
1714 r = sim_tape_rewind (uptr);
1715 return r;
1716 }
1717
1718
1719
1720 t_stat sim_tape_position (UNIT *uptr, uint32 flags, uint32 recs, uint32 *recsskipped, uint32 files, uint32 *filesskipped, uint32 *objectsskipped)
1721 {
1722 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1723 t_stat r = MTSE_OK;
1724
1725 if (ctx == NULL)
1726 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1727 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_position(unit=%d, flags=0x%X, recs=%d, files=%d)\n", (int)(uptr-ctx->dptr->units), flags, recs, files);
1728
1729 *recsskipped = *filesskipped = *objectsskipped = 0;
1730 if (flags & MTPOS_M_REW)
1731 r = sim_tape_rewind (uptr);
1732 if (r != MTSE_OK)
1733 return r;
1734 if (flags & MTPOS_M_OBJ) {
1735 uint32 objs = recs;
1736 uint32 skipped;
1737 uint32 objsremaining = objs;
1738
1739 while (*objectsskipped < objs) {
1740 if (flags & MTPOS_M_REV)
1741 r = sim_tape_sprecsr (uptr, objsremaining, &skipped);
1742 else
1743 r = sim_tape_sprecsf (uptr, objsremaining, &skipped);
1744 objsremaining = objsremaining - (skipped + ((r == MTSE_TMK) ? 1 : 0));
1745 if ((r == MTSE_TMK) || (r == MTSE_OK))
1746 *objectsskipped = *objectsskipped + skipped + ((r == MTSE_TMK) ? 1 : 0);
1747 else
1748 return r;
1749 }
1750 r = MTSE_OK;
1751 }
1752 else {
1753 uint32 fileskiprecs;
1754
1755 if (flags & MTPOS_M_REV)
1756 r = sim_tape_spfilebyrecr (uptr, files, filesskipped, &fileskiprecs);
1757 else
1758 r = sim_tape_spfilebyrecf (uptr, files, filesskipped, &fileskiprecs, (flags & MTPOS_M_DLE));
1759 if (r != MTSE_OK)
1760 return r;
1761 if (flags & MTPOS_M_REV)
1762 r = sim_tape_sprecsr (uptr, recs, recsskipped);
1763 else
1764 r = sim_tape_sprecsf (uptr, recs, recsskipped);
1765 if (r == MTSE_TMK)
1766 *filesskipped = *filesskipped + 1;
1767 *objectsskipped = fileskiprecs + *filesskipped + *recsskipped;
1768 }
1769 return r;
1770 }
1771
1772 t_stat sim_tape_position_a (UNIT *uptr, uint32 flags, uint32 recs, uint32 *recsskipped, uint32 files, uint32 *filesskipped, uint32 *objectsskipped, TAPE_PCALLBACK callback)
1773 {
1774 t_stat r = MTSE_OK;
1775 r = sim_tape_position (uptr, flags, recs, recsskipped, files, filesskipped, objectsskipped);
1776 return r;
1777 }
1778
1779
1780
1781 t_stat sim_tape_reset (UNIT *uptr)
1782 {
1783 struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
1784
1785 MT_CLR_PNU (uptr);
1786 if (!(uptr->flags & UNIT_ATT))
1787 return SCPE_OK;
1788
1789 if (ctx == NULL)
1790 return sim_messagef (SCPE_IERR, "Bad Attach\n");
1791 sim_debug (ctx->dbit, ctx->dptr, "sim_tape_reset(unit=%d)\n", (int)(uptr-ctx->dptr->units));
1792
1793 _sim_tape_io_flush(uptr);
1794 return SCPE_OK;
1795 }
1796
1797
1798
1799 t_bool sim_tape_bot (UNIT *uptr)
1800 {
1801 uint32 f = MT_GET_FMT (uptr);
1802
1803 return (uptr->pos <= fmts[f].bot)? TRUE: FALSE;
1804 }
1805
1806
1807
1808 t_bool sim_tape_eot (UNIT *uptr)
1809 {
1810 return (uptr->capac && (uptr->pos >= uptr->capac))? TRUE: FALSE;
1811 }
1812
1813
1814
1815 t_bool sim_tape_wrp (UNIT *uptr)
1816 {
1817 return ((uptr->flags & MTUF_WRP) || (MT_GET_FMT (uptr) == MTUF_F_TPC))? TRUE: FALSE;
1818 }
1819
1820
1821
1822 static t_stat sim_tape_ioerr (UNIT *uptr)
1823 {
1824 sim_printf ("%s: Magtape library I/O error: %s\n", sim_uname (uptr), strerror (errno));
1825 clearerr (uptr->fileref);
1826 return MTSE_IOERR;
1827 }
1828
1829
1830
1831 t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
1832 {
1833 uint32 f;
1834
1835 if (uptr == NULL)
1836 return SCPE_IERR;
1837 if (uptr->flags & UNIT_ATT)
1838 return SCPE_ALATT;
1839 if (cptr == NULL)
1840 return SCPE_ARG;
1841 for (f = 0; f < MTUF_N_FMT; f++) {
1842 if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) {
1843 uptr->flags = (uptr->flags & ~MTUF_FMT) |
1844 (f << MTUF_V_FMT) | fmts[f].uflags;
1845 return SCPE_OK;
1846 }
1847 }
1848 return SCPE_ARG;
1849 }
1850
1851
1852
1853 t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
1854 {
1855 int32 f = MT_GET_FMT (uptr);
1856
1857 if (fmts[f].name)
1858 fprintf (st, "%s format", fmts[f].name);
1859 else fprintf (st, "invalid format");
1860 return SCPE_OK;
1861 }
1862
1863
1864
1865 static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize)
1866 {
1867 t_addr tpos, leot = 0;
1868 t_addr tape_size;
1869 t_tpclnt bc, last_bc = 0xFFFF;
1870 uint32 had_double_tape_mark = 0;
1871 size_t i;
1872 uint32 objc, sizec;
1873 uint32 *countmap = NULL;
1874 uint8 *recbuf = NULL;
1875 DEVICE *dptr = find_dev_from_unit (uptr);
1876
1877 if ((uptr == NULL) || (uptr->fileref == NULL))
1878 return 0;
1879 countmap = (uint32 *)calloc (65536, sizeof(*countmap));
1880 if (!countmap)
1881 {
1882 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1883 __func__, __FILE__, __LINE__);
1884 #if defined(USE_BACKTRACE)
1885 # ifdef SIGUSR2
1886 (void)raise(SIGUSR2);
1887
1888 # endif
1889 #endif
1890 abort();
1891 }
1892 recbuf = (uint8 *)malloc (65536);
1893 if (!recbuf)
1894 {
1895 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1896 __func__, __FILE__, __LINE__);
1897 #if defined(USE_BACKTRACE)
1898 # ifdef SIGUSR2
1899 (void)raise(SIGUSR2);
1900
1901 # endif
1902 #endif
1903 abort();
1904 }
1905 tape_size = (t_addr)sim_fsize (uptr->fileref);
1906 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape_size: %" T_ADDR_FMT "u\n", tape_size);
1907 for (objc = 0, sizec = 0, tpos = 0;; ) {
1908 sim_fseek (uptr->fileref, tpos, SEEK_SET);
1909 i = sim_fread (&bc, sizeof (t_tpclnt), 1, uptr->fileref);
1910 if (i == 0)
1911 break;
1912 if (countmap[bc] == 0)
1913 sizec++;
1914 ++countmap[bc];
1915 if (map && (objc < mapsize))
1916 map[objc] = tpos;
1917 if (bc) {
1918 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: %d byte count at pos: %" T_ADDR_FMT "u\n", bc, tpos);
1919 if (sim_deb && (dptr->dctrl & MTSE_DBG_STR)) {
1920 (void)sim_fread (recbuf, 1, bc, uptr->fileref);
1921 sim_data_trace(dptr, uptr, ((dptr->dctrl & MTSE_DBG_DAT) ? recbuf : NULL), "", bc, "Data Record", MTSE_DBG_STR);
1922 }
1923 }
1924 else
1925 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape mark at pos: %" T_ADDR_FMT "u\n", tpos);
1926 objc++;
1927 tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt);
1928 if ((bc == 0) && (last_bc == 0)) {
1929 had_double_tape_mark = objc;
1930 leot = tpos;
1931 }
1932 last_bc = bc;
1933 }
1934 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: objc: %u, different record sizes: %u\n", objc, sizec);
1935 for (i=0; i<65535; i++) {
1936 if (countmap[i]) {
1937 if (i == 0)
1938 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u tape marks\n", countmap[i]);
1939 else
1940 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u %d byte record%s\n", countmap[i], (int)i, (countmap[i] > 1) ? "s" : "");
1941 }
1942 }
1943 if (((last_bc != 0xffff) &&
1944 (tpos > tape_size) &&
1945 (!had_double_tape_mark)) ||
1946 (!had_double_tape_mark) ||
1947 ((objc == countmap[0]) &&
1948 (countmap[0] != 2))) {
1949 if (last_bc != 0xffff)
1950 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR unexpected EOT byte count: %d\n", last_bc);
1951 if (tpos > tape_size)
1952 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR next record position %" T_ADDR_FMT "u beyond EOT: %" T_ADDR_FMT "u\n", tpos, tape_size);
1953 if (objc == countmap[0])
1954 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR tape cnly contains tape marks\n");
1955 FREE (countmap);
1956 FREE (recbuf);
1957 return 0;
1958 }
1959
1960 if ((last_bc != 0xffff) && (tpos > tape_size)) {
1961 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: WARNING unexpected EOT byte count: %d, double tape mark before %" T_ADDR_FMT "u provides logical EOT\n", last_bc, leot);
1962 objc = had_double_tape_mark;
1963 tpos = leot;
1964 }
1965 if (map)
1966 map[objc] = tpos;
1967 sim_debug (MTSE_DBG_STR, dptr, "tpc_map: OK objc: %d\n", objc);
1968 FREE (countmap);
1969 FREE (recbuf);
1970 return objc;
1971 }
1972
1973
1974
1975 static t_stat sim_tape_simh_check (UNIT *uptr)
1976 {
1977 return SCPE_OK;
1978 }
1979
1980
1981
1982 static t_stat sim_tape_e11_check (UNIT *uptr)
1983 {
1984 return SCPE_OK;
1985 }
1986
1987
1988
1989 static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map)
1990 {
1991 uint32 lo, hi, p;
1992
1993 if (map == NULL)
1994 return 0;
1995 lo = 0;
1996 hi = uptr->hwmark - 1;
1997 do {
1998 p = (lo + hi) >> 1;
1999 if (uptr->pos == map[p])
2000 return ((p == 0)? map[p]: map[p - 1]);
2001 else if (uptr->pos < map[p])
2002 hi = p - 1;
2003 else lo = p + 1;
2004 }
2005 while (lo <= hi);
2006 return ((p == 0)? map[p]: map[p - 1]);
2007 }
2008
2009
2010
2011 t_stat sim_tape_set_capac (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
2012 {
2013 t_addr cap;
2014 t_stat r;
2015
2016 if ((cptr == NULL) || (*cptr == 0))
2017 return SCPE_ARG;
2018 if (uptr->flags & UNIT_ATT)
2019 return SCPE_ALATT;
2020 cap = (t_addr) get_uint (cptr, 10, sim_taddr_64? 2000000: 2000, &r);
2021 if (r != SCPE_OK)
2022 return SCPE_ARG;
2023 uptr->capac = cap * ((t_addr) 1000000);
2024 return SCPE_OK;
2025 }
2026
2027
2028
2029 t_stat sim_tape_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
2030 {
2031 if (uptr->capac) {
2032 if (uptr->capac >= (t_addr) 1000000)
2033 fprintf (st, "capacity : %luMB", (unsigned long)(uptr->capac / ((t_addr) 1000000)));
2034 else {
2035 if (uptr->capac >= (t_addr) 1000)
2036 fprintf (st, "capacity : %luKB", (unsigned long)(uptr->capac / ((t_addr) 1000)));
2037 else
2038 fprintf (st, "capacity : %luB", (unsigned long)uptr->capac);
2039 }
2040 }
2041 else
2042 fprintf (st, "capacity : unlimited");
2043 return SCPE_OK;
2044 }
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065 t_stat sim_tape_set_dens (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
2066 {
2067 uint32 density, new_bpi;
2068 t_stat result = SCPE_OK;
2069
2070 if (uptr == NULL)
2071 return SCPE_IERR;
2072
2073 else if (desc == NULL)
2074 if (val > 0 && val < (int32) BPI_COUNT)
2075 uptr->dynflags = (uptr->dynflags & ~MTVF_DENS_MASK)
2076 | (val << UNIT_V_DF_TAPE);
2077 else
2078 return SCPE_ARG;
2079
2080 else {
2081 if (cptr == NULL || *cptr == 0)
2082 return SCPE_MISVAL;
2083
2084 new_bpi = (uint32) get_uint (cptr, 10, UINT_MAX, &result);
2085
2086 if (result != SCPE_OK)
2087 return SCPE_ARG;
2088
2089 else for (density = 0; density < BPI_COUNT; density++)
2090 if (new_bpi == bpi [density]
2091 && ((1 << density) & *(const int32 *) desc)) {
2092 uptr->dynflags = (uptr->dynflags & ~MTVF_DENS_MASK)
2093 | density << UNIT_V_DF_TAPE;
2094 return SCPE_OK;
2095 }
2096
2097 result = SCPE_ARG;
2098 }
2099
2100 return result;
2101 }
2102
2103
2104
2105 t_stat sim_tape_show_dens (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
2106 {
2107 uint32 tape_density;
2108
2109 if (uptr == NULL)
2110 return SCPE_IERR;
2111
2112 else {
2113 tape_density = bpi [MT_DENS (uptr->dynflags)];
2114
2115 if (tape_density)
2116 fprintf (st, "density=%lu bpi",
2117 (unsigned long)tape_density);
2118 else
2119 fprintf (st, "density not set");
2120 }
2121
2122 return SCPE_OK;
2123 }