1
/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator
3
Copyright (c) 1993-2004, Robert M. Supnik
5
Permission is hereby granted, free of charge, to any person obtaining a
6
copy of this software and associated documentation files (the "Software"),
7
to deal in the Software without restriction, including without limitation
8
the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
and/or sell copies of the Software, and to permit persons to whom the
10
Software is furnished to do so, subject to the following conditions:
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of Robert M Supnik shall not
23
be used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from Robert M Supnik.
26
ms 13181A 7970B 800bpi nine track magnetic tape
27
13183A 7970E 1600bpi nine track magnetic tape
29
25-Apr-03 RMS Revised for extended file support
30
28-Mar-03 RMS Added multiformat support
31
28-Feb-03 RMS Revised for magtape library
32
18-Oct-02 RMS Added BOOT command, added 13183A support
33
30-Sep-02 RMS Revamped error handling
34
29-Aug-02 RMS Added end of medium support
35
30-May-02 RMS Widened POS to 32b
36
22-Apr-02 RMS Added maximum record length test
38
Magnetic tapes are represented as a series of variable records
49
If the byte count is odd, the record is padded with an extra byte
50
of junk. File marks are represented by a byte count of 0.
52
Unusually among HP peripherals, the 12559 does not have a command flop,
53
and its flag and flag buffer power up as clear rather than set.
56
#include "hp2100_defs.h"
59
#define MS_NUMDR 4 /* number of drives */
60
#define DB_N_SIZE 16 /* max data buf */
61
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
62
#define FNC u3 /* function */
63
#define UST u4 /* unit status */
65
/* Command - msc_fnc */
67
#define FNC_CLR 00110 /* clear */
68
#define FNC_GAP 00015 /* write gap */
69
#define FNC_GFM 00215 /* gap+file mark */
70
#define FNC_RC 00023 /* read */
71
#define FNC_WC 00031 /* write */
72
#define FNC_FSR 00003 /* forward space */
73
#define FNC_BSR 00041 /* backward space */
74
#define FNC_FSF 00203 /* forward file */
75
#define FNC_BSF 00241 /* backward file */
76
#define FNC_REW 00101 /* rewind */
77
#define FNC_RWS 00105 /* rewind and offline */
78
#define FNC_WFM 00211 /* write file mark */
79
#define FNC_RFF 00223 /* "read file fwd" */
80
#define FNC_V_SEL 9 /* select */
82
#define FNC_GETSEL(x) (((x) >> FNC_V_SEL) & FNC_M_SEL)
84
#define FNF_MOT 00001 /* motion */
86
#define FNF_WRT 00010 /* write */
87
#define FNF_REV 00040 /* reverse */
88
#define FNF_RWD 00100 /* rewind */
89
#define FNF_CHS 00400 /* change select */
91
/* Status - stored in msc_sta, unit.UST (u), or dynamic (d) */
93
#define STA_PE 0100000 /* 1600 bpi (d) */
94
#define STA_V_SEL 13 /* unit sel (d) */
96
#define STA_SEL (STA_M_SEL << STA_V_SEL)
97
#define STA_ODD 0004000 /* odd bytes */
98
#define STA_REW 0002000 /* rewinding (u) */
99
#define STA_TBSY 0001000 /* transport busy (d) */
100
#define STA_BUSY 0000400 /* ctrl busy */
101
#define STA_EOF 0000200 /* end of file */
102
#define STA_BOT 0000100 /* beg of tape (u) */
103
#define STA_EOT 0000040 /* end of tape (u) */
104
#define STA_TIM 0000020 /* timing error */
105
#define STA_REJ 0000010 /* programming error */
106
#define STA_WLK 0000004 /* write locked (d) */
107
#define STA_PAR 0000002 /* parity error */
108
#define STA_LOCAL 0000001 /* local (d) */
109
#define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL)
112
extern uint32 PC, SR;
113
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
114
extern int32 sim_switches;
115
extern UNIT cpu_unit;
117
int32 ms_ctype = 0; /* ctrl type */
118
int32 msc_sta = 0; /* status */
119
int32 msc_buf = 0; /* buffer */
120
int32 msc_usl = 0; /* unit select */
122
int32 msc_ctime = 1000; /* command wait */
123
int32 msc_gtime = 1000; /* gap stop time */
124
int32 msc_rtime = 1000; /* rewind wait */
125
int32 msc_xtime = 15; /* data xfer time */
126
int32 msc_stopioe = 1; /* stop on error */
127
int32 msd_buf = 0; /* data buffer */
128
uint8 msxb[DBSIZE] = { 0 }; /* data buffer */
129
t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */
131
DEVICE msd_dev, msc_dev;
132
int32 msdio (int32 inst, int32 IR, int32 dat);
133
int32 mscio (int32 inst, int32 IR, int32 dat);
134
t_stat msc_svc (UNIT *uptr);
135
t_stat msc_reset (DEVICE *dptr);
136
t_stat msc_attach (UNIT *uptr, char *cptr);
137
t_stat msc_detach (UNIT *uptr);
138
t_stat msc_boot (int32 unitno, DEVICE *dptr);
139
t_stat ms_map_err (UNIT *uptr, t_stat st);
140
t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
141
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
143
/* MSD data structures
145
msd_dev MSD device descriptor
146
msd_unit MSD unit list
147
msd_reg MSD register list
151
{ MSD, 0, 0, 0, 0, &msdio },
152
{ MSC, 0, 0, 0, 0, &mscio } };
154
#define msd_dib ms_dib[0]
155
#define msc_dib ms_dib[1]
157
UNIT msd_unit = { UDATA (NULL, 0, 0) };
160
{ ORDATA (BUF, msd_buf, 16) },
161
{ FLDATA (CMD, msd_dib.cmd, 0), REG_HRO },
162
{ FLDATA (CTL, msd_dib.ctl, 0) },
163
{ FLDATA (FLG, msd_dib.flg, 0) },
164
{ FLDATA (FBF, msd_dib.fbf, 0) },
165
{ BRDATA (DBUF, msxb, 8, 8, DBSIZE) },
166
{ DRDATA (BPTR, ms_ptr, DB_N_SIZE + 1) },
167
{ DRDATA (BMAX, ms_max, DB_N_SIZE + 1) },
168
{ ORDATA (DEVNO, msd_dib.devno, 6), REG_HRO },
172
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
173
&hp_setdev, &hp_showdev, &msd_dev },
177
"MSD", &msd_unit, msd_reg, msd_mod,
178
1, 10, DB_N_SIZE, 1, 8, 8,
179
NULL, NULL, &msc_reset,
183
/* MSC data structures
185
msc_dev MSC device descriptor
186
msc_unit MSC unit list
187
msc_reg MSC register list
188
msc_mod MSC modifier list
192
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
193
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
194
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
195
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } };
198
{ ORDATA (STA, msc_sta, 12) },
199
{ ORDATA (BUF, msc_buf, 16) },
200
{ ORDATA (USEL, msc_usl, 2) },
201
{ FLDATA (FSVC, msc_1st, 0) },
202
{ FLDATA (CMD, msc_dib.cmd, 0), REG_HRO },
203
{ FLDATA (CTL, msc_dib.ctl, 0) },
204
{ FLDATA (FLG, msc_dib.flg, 0) },
205
{ FLDATA (FBF, msc_dib.fbf, 0) },
206
{ URDATA (POS, msc_unit[0].pos, 10, T_ADDR_W, 0, MS_NUMDR, PV_LEFT) },
207
{ URDATA (FNC, msc_unit[0].FNC, 8, 8, 0, MS_NUMDR, REG_HRO) },
208
{ URDATA (UST, msc_unit[0].UST, 8, 12, 0, MS_NUMDR, REG_HRO) },
209
{ DRDATA (CTIME, msc_ctime, 24), REG_NZ + PV_LEFT },
210
{ DRDATA (GTIME, msc_gtime, 24), REG_NZ + PV_LEFT },
211
{ DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT },
212
{ DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT },
213
{ FLDATA (STOP_IOE, msc_stopioe, 0) },
214
{ FLDATA (CTYPE, ms_ctype, 0), REG_HRO },
215
{ ORDATA (DEVNO, msc_dib.devno, 6), REG_HRO },
219
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
220
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
221
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
222
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
223
{ MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",
224
&ms_settype, NULL, NULL },
225
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",
226
&ms_settype, NULL, NULL },
227
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
228
NULL, &ms_showtype, NULL },
229
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
230
&hp_setdev, &hp_showdev, &msd_dev },
234
"MSC", msc_unit, msc_reg, msc_mod,
235
MS_NUMDR, 10, 31, 1, 8, 8,
236
NULL, NULL, &msc_reset,
237
&msc_boot, &msc_attach, &msc_detach,
238
&msc_dib, DEV_DISABLE };
242
int32 msdio (int32 inst, int32 IR, int32 dat)
246
devd = IR & I_DEVMASK; /* get device no */
247
switch (inst) { /* case on opcode */
248
case ioFLG: /* flag clear/set */
249
if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */
251
case ioSFC: /* skip flag clear */
252
if (FLG (devd) == 0) PC = (PC + 1) & VAMASK;
254
case ioSFS: /* skip flag set */
255
if (FLG (devd) != 0) PC = (PC + 1) & VAMASK;
257
case ioOTX: /* output */
258
msd_buf = dat; /* store data */
260
case ioMIX: /* merge */
263
case ioLIX: /* load */
266
case ioCTL: /* control clear/set */
267
if (IR & I_CTL) { /* CLC */
268
clrCTL (devd); /* clr ctl, cmd */
271
setCTL (devd); /* set ctl, cmd */
276
if (IR & I_HC) { clrFLG (devd); } /* H/C option */
280
int32 mscio (int32 inst, int32 IR, int32 dat)
284
UNIT *uptr = msc_dev.units + msc_usl;
285
static const uint8 map_sel[16] = {
286
0, 0, 1, 1, 2, 2, 2, 2,
287
3, 3, 3, 3, 3, 3, 3, 3 };
289
devc = IR & I_DEVMASK; /* get device no */
291
switch (inst) { /* case on opcode */
292
case ioFLG: /* flag clear/set */
293
if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */
295
case ioSFC: /* skip flag clear */
296
if (FLG (devc) == 0) PC = (PC + 1) & VAMASK;
298
case ioSFS: /* skip flag set */
299
if (FLG (devc) != 0) PC = (PC + 1) & VAMASK;
301
case ioOTX: /* output */
303
msc_sta = msc_sta & ~STA_REJ; /* clear reject */
304
if ((dat & 0377) == FNC_CLR) break; /* clear always ok */
305
if (msc_sta & STA_BUSY) { /* busy? reject */
306
msc_sta = msc_sta | STA_REJ; /* dont chg select */
308
if (dat & FNF_CHS) { /* select change */
309
msc_usl = map_sel[FNC_GETSEL (dat)]; /* is immediate */
310
uptr = msc_dev.units + msc_usl; }
311
if (((dat & FNF_MOT) && sim_is_active (uptr)) ||
312
((dat & FNF_REV) && (uptr->UST & STA_BOT)) ||
313
((dat & FNF_WRT) && sim_tape_wrp (uptr)))
314
msc_sta = msc_sta | STA_REJ; /* reject? */
316
case ioLIX: /* load */
318
case ioMIX: /* merge */
319
dat = dat | ((msc_sta | uptr->UST) & ~STA_DYN);
320
if (uptr->flags & UNIT_ATT) { /* online? */
321
if (sim_is_active (uptr)) /* busy */
322
dat = dat | STA_TBSY;
323
if (sim_tape_wrp (uptr)) /* write prot? */
324
dat = dat | STA_WLK; }
325
else dat = dat | STA_TBSY | STA_LOCAL;
326
if (ms_ctype) dat = dat | STA_PE | /* 13183A? */
327
(msc_usl << STA_V_SEL);
329
case ioCTL: /* control clear/set */
330
if (IR & I_CTL) { clrCTL (devc); } /* CLC */
332
if ((msc_buf & 0377) == FNC_CLR) { /* clear? */
333
for (i = 0; i < MS_NUMDR; i++) { /* loop thru units */
334
if (sim_is_active (&msc_unit[i]) && /* write in prog? */
335
(msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0)) {
336
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF))
337
ms_map_err (uptr, st); }
338
if ((msc_unit[i].UST & STA_REW) == 0)
339
sim_cancel (&msc_unit[i]); } /* stop if now rew */
340
clrCTL (devc); /* init device */
344
msc_sta = msd_buf = msc_buf = msc_1st = 0;
346
uptr->FNC = msc_buf & 0377; /* save function */
347
if (uptr->FNC & FNF_RWD) /* rewind? */
348
sim_activate (uptr, msc_rtime); /* fast response */
349
else sim_activate (uptr, msc_ctime); /* schedule op */
350
uptr->UST = 0; /* clear status */
351
msc_sta = STA_BUSY; /* ctrl is busy */
353
setCTL (devc); } /* go */
357
if (IR & I_HC) { clrFLG (devc); } /* H/C option */
363
If rewind done, reposition to start of tape, set status
364
else, do operation, set done, interrupt
366
Can't be write locked, can only write lock detached unit
369
t_stat msc_svc (UNIT *uptr)
373
t_stat st, r = SCPE_OK;
375
devc = msc_dib.devno; /* get device nos */
376
devd = msd_dib.devno;
378
if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
379
msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */
380
setFLG (devc); /* set cch flg */
381
return IORETURN (msc_stopioe, SCPE_UNATT); }
383
switch (uptr->FNC) { /* case on function */
384
case FNC_REW: /* rewind */
385
case FNC_RWS: /* rewind offline */
386
if (uptr->UST & STA_REW) { /* rewind in prog? */
387
sim_tape_rewind (uptr); /* done */
388
uptr->UST = STA_BOT; /* set BOT status */
389
if (uptr->FNC & FNF_OFL) detach_unit (uptr);
391
uptr->UST = STA_REW; /* set rewinding */
392
sim_activate (uptr, msc_ctime); /* sched completion */
395
case FNC_GFM: /* gap file mark */
396
case FNC_WFM: /* write file mark */
397
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
398
r = ms_map_err (uptr, st); /* map error */
399
msc_sta = STA_EOF; /* set EOF status */
402
case FNC_GAP: /* erase gap */
405
case FNC_FSR: /* space forward */
406
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
407
r = ms_map_err (uptr, st); /* map error */
408
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
409
else msc_sta = msc_sta & ~STA_ODD;
413
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
414
r = ms_map_err (uptr, st); /* map error */
415
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
416
else msc_sta = msc_sta & ~STA_ODD;
420
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
421
if (st == MTSE_TMK) /* stopped by tmk? */
422
msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */
423
else r = ms_map_err (uptr, st); /* map error */
427
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
428
if (st == MTSE_TMK) /* stopped by tmk? */
429
msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */
430
else r = ms_map_err (uptr, st); /* map error */
433
/* Unit service, continued */
435
case FNC_RFF: /* diagnostic read */
436
case FNC_RC: /* read */
437
if (msc_1st) { /* first svc? */
438
msc_1st = ms_ptr = 0; /* clr 1st flop */
439
st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */
440
if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */
441
else if (st != MTSE_OK) { /* other error? */
442
r = ms_map_err (uptr, st); /* map error */
443
if (r == SCPE_OK) { /* recoverable? */
444
sim_activate (uptr, msc_gtime); /* sched IRG */
445
uptr->FNC = 0; /* NOP func */
447
break; } /* err, done */
449
if (ms_ptr < ms_max) { /* more chars? */
450
if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR;
451
msd_buf = ((uint16) msxb[ms_ptr] << 8) | msxb[ms_ptr + 1];
453
setFLG (devd); /* set dch flg */
454
sim_activate (uptr, msc_xtime); /* re-activate */
456
sim_activate (uptr, msc_gtime); /* sched IRG */
457
if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */
458
else uptr->FNC = 0; /* NOP func */
461
case FNC_WC: /* write */
462
if (msc_1st) msc_1st = ms_ptr = 0; /* no xfer on first */
463
else { /* not 1st, next char */
464
if (ms_ptr < DBSIZE) { /* room in buffer? */
465
msxb[ms_ptr] = msd_buf >> 8; /* store 2 char */
466
msxb[ms_ptr + 1] = msd_buf & 0377;
469
else msc_sta = msc_sta | STA_PAR; }
470
if (CTL (devd)) { /* xfer flop set? */
471
setFLG (devd); /* set dch flag */
472
sim_activate (uptr, msc_xtime); /* re-activate */
474
if (ms_ptr) { /* any data? write */
475
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */
476
r = ms_map_err (uptr, st); /* map error */
478
sim_activate (uptr, msc_gtime); /* sched IRG */
479
uptr->FNC = 0; /* NOP func */
482
default: /* unknown */
485
setFLG (devc); /* set cch flg */
486
msc_sta = msc_sta & ~STA_BUSY; /* update status */
490
/* Map tape error status */
492
t_stat ms_map_err (UNIT *uptr, t_stat st)
495
case MTSE_FMT: /* illegal fmt */
496
case MTSE_UNATT: /* unattached */
497
msc_sta = msc_sta | STA_REJ; /* reject */
498
case MTSE_OK: /* no error */
499
return SCPE_IERR; /* never get here! */
500
case MTSE_TMK: /* end of file */
501
msc_sta = msc_sta | STA_EOF | STA_ODD; /* eof (also sets odd) */
503
case MTSE_INVRL: /* invalid rec lnt */
504
msc_sta = msc_sta | STA_PAR;
506
case MTSE_IOERR: /* IO error */
507
msc_sta = msc_sta | STA_PAR; /* error */
508
if (msc_stopioe) return SCPE_IOERR;
510
case MTSE_RECE: /* record in error */
511
case MTSE_EOM: /* end of medium */
512
msc_sta = msc_sta | STA_PAR; /* error */
514
case MTSE_BOT: /* reverse into BOT */
515
uptr->UST = STA_BOT; /* set status */
517
case MTSE_WRP: /* write protect */
518
msc_sta = msc_sta | STA_REJ; /* reject */
525
t_stat msc_reset (DEVICE *dptr)
530
hp_enbdis_pair (&msc_dev, &msd_dev); /* make pair cons */
531
msc_buf = msd_buf = 0;
532
msc_sta = msc_usl = 0;
534
msc_dib.cmd = msd_dib.cmd = 0; /* clear cmd */
535
msc_dib.ctl = msd_dib.ctl = 0; /* clear ctl */
536
msc_dib.flg = msd_dib.flg = 1; /* set flg */
537
msc_dib.fbf = msd_dib.fbf = 1; /* set fbf */
538
for (i = 0; i < MS_NUMDR; i++) {
539
uptr = msc_dev.units + i;
540
sim_tape_reset (uptr);
548
t_stat msc_attach (UNIT *uptr, char *cptr)
552
r = sim_tape_attach (uptr, cptr); /* attach unit */
553
if (r != SCPE_OK) return r; /* update status */
560
t_stat msc_detach (UNIT* uptr)
562
uptr->UST = 0; /* update status */
563
return sim_tape_detach (uptr); /* detach unit */
566
/* Set controller type */
568
t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc)
572
if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG;
573
for (i = 0; i < MS_NUMDR; i++) {
574
if (msc_unit[i].flags & UNIT_ATT) return SCPE_ALATT; }
579
/* Show controller type */
581
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc)
583
if (ms_ctype) fprintf (st, "13183A");
584
else fprintf (st, "13181A");
588
/* 7970B/7970E bootstrap routine (HP 12992D ROM) */
590
#define CHANGE_DEV (1 << 24)
592
static const int32 mboot[IBL_LNT] = {
593
0106501, /*ST LIB 1 ; read sw */
594
0006011, /* SLB,RSS ; bit 0 set? */
595
0027714, /* JMP RD ; no read */
596
0003004, /* CMA,INA ; A is ctr */
597
0073775, /* STA WC ; save */
598
0067772, /* LDA SL0RW ; sel 0, rew */
599
0017762, /*FF JSB CMD ; do cmd */
600
0102301+CHANGE_DEV, /* SFS CC ; done? */
601
0027707, /* JMP *-1 ; wait */
602
0067774, /* LDB FFC ; get file fwd */
603
0037775, /* ISZ WC ; done files? */
604
0027706, /* JMP FF ; no */
605
0067773, /*RD LDB RDCMD ; read cmd */
606
0017762, /* JSB CMD ; do cmd */
607
0103700+CHANGE_DEV, /* STC DC,C ; start dch */
608
0102201+CHANGE_DEV, /* SFC CC ; read done? */
609
0027752, /* JMP STAT ; no, get stat */
610
0102300+CHANGE_DEV, /* SFS DC ; any data? */
611
0027717, /* JMP *-3 ; wait */
612
0107500+CHANGE_DEV, /* LIB DC,C ; get rec cnt */
613
0005727, /* BLF,BLF ; move to lower */
614
0007000, /* CMB ; make neg */
615
0077775, /* STA WC ; save */
616
0102201+CHANGE_DEV, /* SFC CC ; read done? */
617
0027752, /* JMP STAT ; no, get stat */
618
0102300+CHANGE_DEV, /* SFS DC ; any data? */
619
0027727, /* JMP *-3 ; wait */
620
0107500+CHANGE_DEV, /* LIB DC,C ; get load addr */
621
0074000, /* STB 0 ; start csum */
622
0077762, /* STA CMD ; save address */
623
0027742, /* JMP *+4 */
624
0177762, /*NW STB CMD,I ; store data */
625
0040001, /* ADA 1 ; add to csum */
626
0037762, /* ISZ CMD ; adv addr ptr */
627
0102300+CHANGE_DEV, /* SFS DC ; any data? */
628
0027742, /* JMP *-1 ; wait */
629
0107500+CHANGE_DEV, /* LIB DC,C ; get word */
630
0037775, /* ISZ WC ; done? */
631
0027737, /* JMP NW ; no */
632
0054000, /* CPB 0 ; csum ok? */
633
0027717, /* JMP RD+3 ; yes, cont */
634
0102011, /* HLT 11 ; no, halt */
635
0102501+CHANGE_DEV, /*ST LIA CC ; get status */
636
0001727, /* ALF,ALF ; get eof bit */
637
0002020, /* SSA ; set? */
638
0102077, /* HLT 77 ; done */
639
0001727, /* ALF,ALF ; put status back */
640
0001310, /* RAR,SLA ; read ok? */
641
0102000, /* HLT 0 ; no */
642
0027714, /* JMP RD ; read next */
644
0106601+CHANGE_DEV, /* OTB CC ; output cmd */
645
0102501+CHANGE_DEV, /* LIA CC ; check for reject */
646
0001323, /* RAR,RAR */
647
0001310, /* RAR,SLA */
648
0027763, /* JMP CMD+1 ; try again */
649
0103701+CHANGE_DEV, /* STC CC,C ; start command */
650
0127762, /* JMP CMD,I ; exit */
651
0001501, /*SL0RW 001501 ; select 0, rewind */
652
0001423, /*RDCMD 001423 ; read record */
653
0000203, /*FFC 000203 ; space forward file */
654
0000000, /*WC 000000 */
658
t_stat msc_boot (int32 unitno, DEVICE *dptr)
662
if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */
663
dev = msd_dib.devno; /* get data chan dev */
664
PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */
665
SR = IBL_MS + (dev << IBL_V_DEV); /* set SR */
666
if ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */
667
for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */
668
if (mboot[i] & CHANGE_DEV) /* IO instr? */
669
M[PC + i] = (mboot[i] + dev) & DMASK;
670
else M[PC + i] = mboot[i]; }