First Commit of my working state
[simh.git] / HP2100 / hp2100_ms.c
CommitLineData
196ba1fc
PH
1/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator\r
2\r
3 Copyright (c) 1993-2006, Robert M. Supnik\r
4\r
5 Permission is hereby granted, free of charge, to any person obtaining a\r
6 copy of this software and associated documentation files (the "Software"),\r
7 to deal in the Software without restriction, including without limitation\r
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
9 and/or sell copies of the Software, and to permit persons to whom the\r
10 Software is furnished to do so, subject to the following conditions:\r
11\r
12 The above copyright notice and this permission notice shall be included in\r
13 all copies or substantial portions of the Software.\r
14\r
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21\r
22 Except as contained in this notice, the name of Robert M Supnik shall not be\r
23 used in advertising or otherwise to promote the sale, use or other dealings\r
24 in this Software without prior written authorization from Robert M Supnik.\r
25\r
26 ms 13181A 7970B 800bpi nine track magnetic tape\r
27 13183A 7970E 1600bpi nine track magnetic tape\r
28\r
29 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)\r
30 18-Sep-06 JDB Fixed 2nd CLR after WC causing another write\r
31 Improve debug reporting, add debug flags\r
32 14-Sep-06 JDB Removed local BOT flag, now uses sim_tape_bot\r
33 30-Aug-06 JDB Added erase gap support, improved tape lib err reporting\r
34 07-Jul-06 JDB Added CAPACITY as alternate for REEL\r
35 Fixed EOT test for unlimited reel size\r
36 16-Feb-06 RMS Revised for new EOT test\r
37 22-Jul-05 RMS Fixed compiler warning on Solaris (from Doug Glyn)\r
38 01-Mar-05 JDB Added SET OFFLINE; rewind/offline now does not detach\r
39 07-Oct-04 JDB Fixed enable/disable from either device\r
40 14-Aug-04 JDB Fixed many functional and timing problems (from Dave Bryan)\r
41 - fixed erroneous execution of rejected command\r
42 - fixed erroneous execution of select-only command\r
43 - fixed erroneous execution of clear command\r
44 - fixed odd byte handling for read\r
45 - fixed spurious odd byte status on 13183A EOF\r
46 - modified handling of end of medium\r
47 - added detailed timing, with fast and realistic modes\r
48 - added reel sizes to simulate end of tape\r
49 - added debug printouts\r
50 06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan)\r
51 26-Apr-04 RMS Fixed SFS x,C and SFC x,C\r
52 Fixed SR setting in IBL\r
53 Revised IBL loader\r
54 Implemented DMA SRQ (follows FLG)\r
55 25-Apr-03 RMS Revised for extended file support\r
56 28-Mar-03 RMS Added multiformat support\r
57 28-Feb-03 RMS Revised for magtape library\r
58 18-Oct-02 RMS Added BOOT command, added 13183A support\r
59 30-Sep-02 RMS Revamped error handling\r
60 29-Aug-02 RMS Added end of medium support\r
61 30-May-02 RMS Widened POS to 32b\r
62 22-Apr-02 RMS Added maximum record length test\r
63\r
64 Magnetic tapes are represented as a series of variable records\r
65 of the form:\r
66\r
67 32b byte count\r
68 byte 0\r
69 byte 1\r
70 :\r
71 byte n-2\r
72 byte n-1\r
73 32b byte count\r
74\r
75 If the byte count is odd, the record is padded with an extra byte\r
76 of junk. File marks are represented by a byte count of 0.\r
77\r
78 References:\r
79 - 13181B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual\r
80 (13181-90901, Nov-1982)\r
81 - 13183B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual\r
82 (13183-90901, Nov-1983)\r
83*/\r
84\r
85#include "hp2100_defs.h"\r
86#include "sim_tape.h"\r
87\r
88#define UNIT_V_OFFLINE (MTUF_V_UF + 0) /* unit offline */\r
89#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)\r
90\r
91#define MS_NUMDR 4 /* number of drives */\r
92#define DB_N_SIZE 16 /* max data buf */\r
93#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */\r
94#define FNC u3 /* function */\r
95#define UST u4 /* unit status */\r
96#define REEL u5 /* tape reel size */\r
97\r
98#define BPI_13181 800 /* 800 bpi for 13181 cntlr */\r
99#define BPI_13183 1600 /* 1600 bpi for 13183 cntlr */\r
100#define GAP_13181 48 /* gap is 4.8 inches for 13181 cntlr */\r
101#define GAP_13183 30 /* gap is 3.0 inches for 13183 cntlr */\r
102#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800 bpi */\r
103\r
104/* Debug flags */\r
105\r
106#define DEB_CMDS (1 << 0) /* command init and compl */\r
107#define DEB_CPU (1 << 1) /* CPU I/O */\r
108#define DEB_RWS (1 << 2) /* tape reads, writes, status */\r
109\r
110/* Command - msc_fnc */\r
111\r
112#define FNC_CLR 00110 /* clear */\r
113#define FNC_GAP 00015 /* write gap */\r
114#define FNC_GFM 00215 /* gap+file mark */\r
115#define FNC_RC 00023 /* read */\r
116#define FNC_WC 00031 /* write */\r
117#define FNC_FSR 00003 /* forward space */\r
118#define FNC_BSR 00041 /* backward space */\r
119#define FNC_FSF 00203 /* forward file */\r
120#define FNC_BSF 00241 /* backward file */\r
121#define FNC_REW 00101 /* rewind */\r
122#define FNC_RWS 00105 /* rewind and offline */\r
123#define FNC_WFM 00211 /* write file mark */\r
124#define FNC_RFF 00223 /* read file fwd (diag) */\r
125#define FNC_RRR 00061 /* read record rev (diag) */\r
126#define FNC_CMPL 00400 /* completion state */\r
127#define FNC_V_SEL 9 /* select */\r
128#define FNC_M_SEL 017\r
129#define FNC_GETSEL(x) (((x) >> FNC_V_SEL) & FNC_M_SEL)\r
130\r
131#define FNF_MOT 00001 /* motion */\r
132#define FNF_OFL 00004\r
133#define FNF_WRT 00010 /* write */\r
134#define FNF_REV 00040 /* reverse */\r
135#define FNF_RWD 00100 /* rewind */\r
136#define FNF_CHS 00400 /* change select */\r
137\r
138#define FNC_SEL ((FNC_M_SEL << FNC_V_SEL) | FNF_CHS)\r
139\r
140/* Status - stored in msc_sta, unit.UST (u), or dynamic (d) */\r
141\r
142#define STA_PE 0100000 /* 1600 bpi (d) */\r
143#define STA_V_SEL 13 /* unit sel (d) */\r
144#define STA_M_SEL 03\r
145#define STA_SEL (STA_M_SEL << STA_V_SEL)\r
146#define STA_ODD 0004000 /* odd bytes */\r
147#define STA_REW 0002000 /* rewinding (u) */\r
148#define STA_TBSY 0001000 /* transport busy (d) */\r
149#define STA_BUSY 0000400 /* ctrl busy */\r
150#define STA_EOF 0000200 /* end of file */\r
151#define STA_BOT 0000100 /* beg of tape (d) */\r
152#define STA_EOT 0000040 /* end of tape (d) */\r
153#define STA_TIM 0000020 /* timing error */\r
154#define STA_REJ 0000010 /* programming error */\r
155#define STA_WLK 0000004 /* write locked (d) */\r
156#define STA_PAR 0000002 /* parity error */\r
157#define STA_LOCAL 0000001 /* local (d) */\r
158#define STA_DYN (STA_PE | STA_SEL | STA_TBSY | STA_BOT | \\r
159 STA_EOT | STA_WLK | STA_LOCAL)\r
160\r
161extern uint32 PC, SR;\r
162extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];\r
163extern int32 sim_switches;\r
164extern FILE *sim_deb;\r
165\r
166int32 ms_ctype = 0; /* ctrl type */\r
167int32 ms_timing = 1; /* timing type */\r
168int32 msc_sta = 0; /* status */\r
169int32 msc_buf = 0; /* buffer */\r
170int32 msc_usl = 0; /* unit select */\r
171int32 msc_1st = 0; /* first service */\r
172int32 msc_stopioe = 1; /* stop on error */\r
173int32 msd_buf = 0; /* data buffer */\r
174uint8 msxb[DBSIZE] = { 0 }; /* data buffer */\r
175t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */\r
176\r
177/* Hardware timing at 45 IPS 13181 13183\r
178 (based on 1580 instr/msec) instr msec SCP instr msec SCP\r
179 -------------------- --------------------\r
180 - BOT start delay : btime = 161512 102.22 184 252800 160.00 288\r
181 - motion cmd start delay : ctime = 14044 8.89 16 17556 11.11 20\r
182 - GAP traversal time : gtime = 175553 111.11 200 105333 66.67 120\r
183 - IRG traversal time : itime = 24885 15.75 - 27387 17.33 -\r
184 - rewind initiation time : rtime = 878 0.56 1 878 0.56 1\r
185 - data xfer time / word : xtime = 88 55.56us - 44 27.78us -\r
186\r
187 NOTE: The 13181-60001 Rev. 1629 tape diagnostic fails test 17B subtest 6 with\r
188 "E116 BYTE TIME SHORT" if the correct data transfer time is used for\r
189 13181A interface. Set "xtime" to 115 (instructions) to pass that\r
190 diagnostic. Rev. 2040 of the tape diagnostic fixes this problem and\r
191 passes with the correct data transfer time.\r
192*/\r
193\r
194int32 msc_btime = 0; /* BOT start delay */\r
195int32 msc_ctime = 0; /* motion cmd start delay */\r
196int32 msc_gtime = 0; /* GAP traversal time */\r
197int32 msc_itime = 0; /* IRG traversal time */\r
198int32 msc_rtime = 0; /* rewind initiation time */\r
199int32 msc_xtime = 0; /* data xfer time / word */\r
200\r
201typedef int32 TIMESET[6]; /* set of controller times */\r
202\r
203int32 *const timers[] = { &msc_btime, &msc_ctime, &msc_gtime,\r
204 &msc_itime, &msc_rtime, &msc_xtime };\r
205\r
206const TIMESET msc_times[3] = {\r
207 { 161512, 14044, 175553, 24885, 878, 88 }, /* 13181A */\r
208 { 252800, 17556, 105333, 27387, 878, 44 }, /* 13183A */\r
209 { 1, 1000, 1, 1, 100, 10 } /* FAST */\r
210 };\r
211\r
212DEVICE msd_dev, msc_dev;\r
213int32 msdio (int32 inst, int32 IR, int32 dat);\r
214int32 mscio (int32 inst, int32 IR, int32 dat);\r
215t_stat msc_svc (UNIT *uptr);\r
216t_stat msc_reset (DEVICE *dptr);\r
217t_stat msc_attach (UNIT *uptr, char *cptr);\r
218t_stat msc_detach (UNIT *uptr);\r
219t_stat msc_online (UNIT *uptr, int32 value, char *cptr, void *desc);\r
220t_stat msc_boot (int32 unitno, DEVICE *dptr);\r
221t_stat ms_write_gap (UNIT *uptr);\r
222t_stat ms_map_err (UNIT *uptr, t_stat st);\r
223t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc);\r
224t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);\r
225t_stat ms_set_timing (UNIT *uptr, int32 val, char *cptr, void *desc);\r
226t_stat ms_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc);\r
227t_stat ms_set_reelsize (UNIT *uptr, int32 val, char *cptr, void *desc);\r
228t_stat ms_show_reelsize (FILE *st, UNIT *uptr, int32 val, void *desc);\r
229void ms_config_timing (void);\r
230char *ms_cmd_name (uint32 cmd);\r
231\r
232/* MSD data structures\r
233\r
234 msd_dev MSD device descriptor\r
235 msd_unit MSD unit list\r
236 msd_reg MSD register list\r
237*/\r
238\r
239DIB ms_dib[] = {\r
240 { MSD, 0, 0, 0, 0, 0, &msdio },\r
241 { MSC, 0, 0, 0, 0, 0, &mscio }\r
242 };\r
243\r
244#define msd_dib ms_dib[0]\r
245#define msc_dib ms_dib[1]\r
246\r
247UNIT msd_unit = { UDATA (NULL, 0, 0) };\r
248\r
249REG msd_reg[] = {\r
250 { ORDATA (BUF, msd_buf, 16) },\r
251 { FLDATA (CMD, msd_dib.cmd, 0), REG_HRO },\r
252 { FLDATA (CTL, msd_dib.ctl, 0) },\r
253 { FLDATA (FLG, msd_dib.flg, 0) },\r
254 { FLDATA (FBF, msd_dib.fbf, 0) },\r
255 { FLDATA (SRQ, msd_dib.srq, 0) },\r
256 { BRDATA (DBUF, msxb, 8, 8, DBSIZE) },\r
257 { DRDATA (BPTR, ms_ptr, DB_N_SIZE + 1) },\r
258 { DRDATA (BMAX, ms_max, DB_N_SIZE + 1) },\r
259 { ORDATA (DEVNO, msd_dib.devno, 6), REG_HRO },\r
260 { NULL }\r
261 };\r
262\r
263MTAB msd_mod[] = {\r
264 { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",\r
265 &hp_setdev, &hp_showdev, &msd_dev },\r
266 { 0 }\r
267 };\r
268\r
269DEVICE msd_dev = {\r
270 "MSD", &msd_unit, msd_reg, msd_mod,\r
271 1, 10, DB_N_SIZE, 1, 8, 8,\r
272 NULL, NULL, &msc_reset,\r
273 NULL, NULL, NULL,\r
274 &msd_dib, DEV_DISABLE\r
275 };\r
276\r
277/* MSC data structures\r
278\r
279 msc_dev MSC device descriptor\r
280 msc_unit MSC unit list\r
281 msc_reg MSC register list\r
282 msc_mod MSC modifier list\r
283 msc_deb MSC debug flags\r
284*/\r
285\r
286UNIT msc_unit[] = {\r
287 { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |\r
288 UNIT_DISABLE | UNIT_OFFLINE, 0) },\r
289 { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |\r
290 UNIT_DISABLE | UNIT_OFFLINE, 0) },\r
291 { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |\r
292 UNIT_DISABLE | UNIT_OFFLINE, 0) },\r
293 { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |\r
294 UNIT_DISABLE | UNIT_OFFLINE, 0) }\r
295 };\r
296\r
297REG msc_reg[] = {\r
298 { ORDATA (STA, msc_sta, 12) },\r
299 { ORDATA (BUF, msc_buf, 16) },\r
300 { ORDATA (USEL, msc_usl, 2) },\r
301 { FLDATA (FSVC, msc_1st, 0) },\r
302 { FLDATA (CMD, msc_dib.cmd, 0), REG_HRO },\r
303 { FLDATA (CTL, msc_dib.ctl, 0) },\r
304 { FLDATA (FLG, msc_dib.flg, 0) },\r
305 { FLDATA (FBF, msc_dib.fbf, 0) },\r
306 { FLDATA (SRQ, msc_dib.srq, 0) },\r
307 { URDATA (POS, msc_unit[0].pos, 10, T_ADDR_W, 0, MS_NUMDR, PV_LEFT) },\r
308 { URDATA (FNC, msc_unit[0].FNC, 8, 8, 0, MS_NUMDR, REG_HRO) },\r
309 { URDATA (UST, msc_unit[0].UST, 8, 12, 0, MS_NUMDR, REG_HRO) },\r
310 { URDATA (REEL, msc_unit[0].REEL, 10, 2, 0, MS_NUMDR, REG_HRO) },\r
311 { DRDATA (BTIME, msc_btime, 24), REG_NZ + PV_LEFT },\r
312 { DRDATA (CTIME, msc_ctime, 24), REG_NZ + PV_LEFT },\r
313 { DRDATA (GTIME, msc_gtime, 24), REG_NZ + PV_LEFT },\r
314 { DRDATA (ITIME, msc_itime, 24), REG_NZ + PV_LEFT },\r
315 { DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT },\r
316 { DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT },\r
317 { FLDATA (TIMING, ms_timing, 0), REG_HRO },\r
318 { FLDATA (STOP_IOE, msc_stopioe, 0) },\r
319 { FLDATA (CTYPE, ms_ctype, 0), REG_HRO },\r
320 { ORDATA (DEVNO, msc_dib.devno, 6), REG_HRO },\r
321 { NULL }\r
322 };\r
323\r
324MTAB msc_mod[] = {\r
325 { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },\r
326 { UNIT_OFFLINE, 0, "online", "ONLINE", msc_online },\r
327 { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },\r
328 { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },\r
329 { MTAB_XTD | MTAB_VUN, 0, "CAPACITY", "CAPACITY",\r
330 &ms_set_reelsize, &ms_show_reelsize, NULL },\r
331 { MTAB_XTD | MTAB_VUN | MTAB_NMO, 1, "REEL", "REEL",\r
332 &ms_set_reelsize, &ms_show_reelsize, NULL },\r
333 { MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT",\r
334 &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },\r
335 { MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",\r
336 &ms_settype, NULL, NULL },\r
337 { MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",\r
338 &ms_settype, NULL, NULL },\r
339 { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,\r
340 NULL, &ms_showtype, NULL },\r
341 { MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME",\r
342 &ms_set_timing, NULL, NULL },\r
343 { MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME",\r
344 &ms_set_timing, NULL, NULL },\r
345 { MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL,\r
346 NULL, &ms_show_timing, NULL },\r
347 { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",\r
348 &hp_setdev, &hp_showdev, &msd_dev },\r
349 { 0 }\r
350 };\r
351\r
352DEBTAB msc_deb[] = {\r
353 { "CMDS", DEB_CMDS },\r
354 { "CPU", DEB_CPU },\r
355 { "RWS", DEB_RWS },\r
356 { NULL, 0 }\r
357 };\r
358\r
359DEVICE msc_dev = {\r
360 "MSC", msc_unit, msc_reg, msc_mod,\r
361 MS_NUMDR, 10, 31, 1, 8, 8,\r
362 NULL, NULL, &msc_reset,\r
363 &msc_boot, &msc_attach, &msc_detach,\r
364 &msc_dib, DEV_DISABLE | DEV_DEBUG,\r
365 0, msc_deb, NULL, NULL\r
366 };\r
367\r
368/* IO instructions */\r
369\r
370int32 msdio (int32 inst, int32 IR, int32 dat)\r
371{\r
372int32 devd;\r
373\r
374devd = IR & I_DEVMASK; /* get device no */\r
375switch (inst) { /* case on opcode */\r
376\r
377 case ioFLG: /* flag clear/set */\r
378 if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */\r
379 break;\r
380\r
381 case ioSFC: /* skip flag clear */\r
382 if (FLG (devd) == 0) PC = (PC + 1) & VAMASK;\r
383 break;\r
384\r
385 case ioSFS: /* skip flag set */\r
386 if (FLG (devd) != 0) PC = (PC + 1) & VAMASK;\r
387 break;\r
388\r
389 case ioOTX: /* output */\r
390 msd_buf = dat; /* store data */\r
391 break;\r
392\r
393 case ioMIX: /* merge */\r
394 dat = dat | msd_buf;\r
395 break;\r
396\r
397 case ioLIX: /* load */\r
398 dat = msd_buf;\r
399 break;\r
400\r
401 case ioCRS: /* control reset (action unverif) */\r
402 case ioCTL: /* control clear/set */\r
403 if (IR & I_CTL) { /* CLC */\r
404 clrCTL (devd); /* clr ctl, cmd */\r
405 clrCMD (devd);\r
406 }\r
407 else { /* STC */\r
408 setCTL (devd); /* set ctl, cmd */\r
409 setCMD (devd);\r
410 }\r
411 break;\r
412\r
413 case ioEDT: /* DMA end */\r
414 clrFSR (devd); /* same as CLF */\r
415 break;\r
416\r
417 default:\r
418 break;\r
419 }\r
420\r
421if (IR & I_HC) { clrFSR (devd); } /* H/C option */\r
422return dat;\r
423}\r
424\r
425int32 mscio (int32 inst, int32 IR, int32 dat)\r
426{\r
427int32 i, devc, devd, sched_time;\r
428t_stat st;\r
429UNIT *uptr = msc_dev.units + msc_usl;\r
430static const uint8 map_sel[16] = {\r
431 0, 0, 1, 1, 2, 2, 2, 2,\r
432 3, 3, 3, 3, 3, 3, 3, 3\r
433 };\r
434\r
435devc = IR & I_DEVMASK; /* get device no */\r
436devd = devc - 1;\r
437switch (inst) { /* case on opcode */\r
438\r
439 case ioFLG: /* flag clear/set */\r
440 if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */\r
441 break;\r
442\r
443 case ioSFC: /* skip flag clear */\r
444 if (FLG (devc) == 0) PC = (PC + 1) & VAMASK;\r
445 break;\r
446\r
447 case ioSFS: /* skip flag set */\r
448 if (FLG (devc) != 0) PC = (PC + 1) & VAMASK;\r
449 break;\r
450\r
451 case ioOTX: /* output */\r
452 if (DEBUG_PRI (msc_dev, DEB_CPU))\r
453 fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", dat);\r
454 msc_buf = dat;\r
455 msc_sta = msc_sta & ~STA_REJ; /* clear reject */\r
456 if ((dat & 0377) == FNC_CLR) break; /* clear always ok */\r
457 if (msc_sta & STA_BUSY) { /* busy? reject */\r
458 msc_sta = msc_sta | STA_REJ; /* dont chg select */\r
459 break;\r
460 }\r
461 if (dat & FNF_CHS) { /* select change */\r
462 msc_usl = map_sel[FNC_GETSEL (dat)]; /* is immediate */\r
463 uptr = msc_dev.units + msc_usl;\r
464 if (DEBUG_PRI (msc_dev, DEB_CMDS))\r
465 fprintf (sim_deb, ">>MSC OTx: Unit %d selected\n", msc_usl);\r
466 }\r
467 if (((dat & FNF_MOT) && sim_is_active (uptr)) ||\r
468 ((dat & FNF_REV) && sim_tape_bot (uptr)) ||\r
469 ((dat & FNF_WRT) && sim_tape_wrp (uptr)))\r
470 msc_sta = msc_sta | STA_REJ; /* reject? */\r
471 break;\r
472\r
473 case ioLIX: /* load */\r
474 dat = 0;\r
475 case ioMIX: /* merge */\r
476 dat = dat | (msc_sta & ~STA_DYN); /* get card status */\r
477 if ((uptr->flags & UNIT_OFFLINE) == 0) { /* online? */\r
478 dat = dat | uptr->UST; /* add unit status */\r
479 if (sim_tape_bot (uptr)) /* BOT? */\r
480 dat = dat | STA_BOT;\r
481 if (sim_is_active (uptr) && /* TBSY unless RWD at BOT */\r
482 !((uptr->FNC & FNF_RWD) && sim_tape_bot (uptr)))\r
483 dat = dat | STA_TBSY;\r
484 if (sim_tape_wrp (uptr)) /* write prot? */\r
485 dat = dat | STA_WLK;\r
486 if (sim_tape_eot (uptr)) /* EOT? */\r
487 dat = dat | STA_EOT;\r
488 }\r
489 else dat = dat | STA_TBSY | STA_LOCAL;\r
490 if (ms_ctype) dat = dat | STA_PE | /* 13183A? */\r
491 (msc_usl << STA_V_SEL);\r
492 if (DEBUG_PRI (msc_dev, DEB_CPU))\r
493 fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", dat);\r
494 break;\r
495\r
496 case ioCRS: /* control reset (action unverif) */\r
497 case ioCTL: /* control clear/set */\r
498 if (IR & I_CTL) { clrCTL (devc); } /* CLC */\r
499 else if (!(msc_sta & STA_REJ)) { /* STC, last cmd rejected? */\r
500 if ((msc_buf & 0377) == FNC_CLR) { /* clear? */\r
501 for (i = 0; i < MS_NUMDR; i++) { /* look for write in progr */\r
502 if (sim_is_active (&msc_unit[i]) && /* unit active? */\r
503 (msc_unit[i].FNC == FNC_WC) && /* last cmd write? */\r
504 (ms_ptr > 0)) { /* partial buffer? */\r
505 if (DEBUG_PRI (msc_dev, DEB_RWS))\r
506 fprintf (sim_deb,\r
507 ">>MSC STC: Unit %d wrote %d word partial record\n",\r
508 i, ms_ptr / 2);\r
509 if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF))\r
510 ms_map_err (uptr, st); /* discard any error */\r
511 ms_ptr = 0; /* clear partial */\r
512 }\r
513 if ((msc_unit[i].UST & STA_REW) == 0)\r
514 sim_cancel (&msc_unit[i]); /* stop if not rew */\r
515 }\r
516 setCTL (devc); /* set CTL for STC */\r
517 setFSR (devc); /* set FLG for completion */\r
518 msc_sta = msc_1st = 0; /* clr ctlr status */\r
519 if (DEBUG_PRI (msc_dev, DEB_CMDS))\r
520 fputs (">>MSC STC: Controller cleared\n", sim_deb);\r
521 return SCPE_OK;\r
522 }\r
523 uptr->FNC = msc_buf & 0377; /* save function */\r
524 if (uptr->FNC & FNF_RWD) { /* rewind? */\r
525 if (!sim_tape_bot (uptr)) /* not at BOT? */\r
526 uptr->UST = STA_REW; /* set rewinding */\r
527 sched_time = msc_rtime; /* set response time */\r
528 }\r
529 else {\r
530 if (sim_tape_bot (uptr)) /* at BOT? */\r
531 sched_time = msc_btime; /* use BOT start time */\r
532 else if ((uptr->FNC == FNC_GAP) || (uptr->FNC == FNC_GFM))\r
533 sched_time = msc_gtime; /* use gap traversal time */\r
534 else sched_time = 0;\r
535 if (uptr->FNC != FNC_GAP)\r
536 sched_time += msc_ctime; /* add base command time */\r
537 }\r
538 if (msc_buf & ~FNC_SEL) { /* NOP for unit sel alone */\r
539 sim_activate (uptr, sched_time); /* else schedule op */\r
540 if (DEBUG_PRI (msc_dev, DEB_CMDS))\r
541 fprintf (sim_deb,\r
542 ">>MSC STC: Unit %d command %03o (%s) scheduled, "\r
543 "pos = %d, time = %d\n",\r
544 msc_usl, uptr->FNC, ms_cmd_name (uptr->FNC),\r
545 uptr->pos, sched_time);\r
546 }\r
547 else if (DEBUG_PRI (msc_dev, DEB_CMDS))\r
548 fputs (">>MSC STC: Unit select (NOP)\n", sim_deb);\r
549 msc_sta = STA_BUSY; /* ctrl is busy */\r
550 msc_1st = 1;\r
551 setCTL (devc); /* go */\r
552 }\r
553 break;\r
554\r
555 case ioEDT: /* DMA end */\r
556 clrFSR (devc); /* same as CLF */\r
557 break;\r
558\r
559 default:\r
560 break;\r
561 }\r
562\r
563if (IR & I_HC) { clrFSR (devc); } /* H/C option */\r
564return dat;\r
565}\r
566\r
567/* Unit service\r
568\r
569 If rewind done, reposition to start of tape, set status\r
570 else, do operation, set done, interrupt.\r
571\r
572 In addition to decreasing the timing intervals, the FASTTIME option enables\r
573 two additional optimizations: WFM for GFM substitution, and BOT gap\r
574 elimination. If FASTTIME is selected, gap and file mark (GFM) commands are\r
575 processed as WFM (write file mark) commands. That is, the preceding GAP is\r
576 not performed. Also, the initial gap that normally precedes the first data\r
577 record or EOF mark at the beginning of the tape is omitted. These omissions\r
578 result in smaller tape image files. If REALTIME is selected, the gaps are\r
579 included. Note that the gaps (and realistic timing) are necessary to pass\r
580 the 7970 diagnostics.\r
581*/\r
582\r
583t_stat msc_svc (UNIT *uptr)\r
584{\r
585int32 devc, devd, unum;\r
586t_mtrlnt tbc;\r
587t_stat st, r = SCPE_OK;\r
588\r
589devc = msc_dib.devno; /* get device nos */\r
590devd = msd_dib.devno;\r
591unum = uptr - msc_dev.units; /* get unit number */\r
592\r
593if ((uptr->FNC != FNC_RWS) && (uptr->flags & UNIT_OFFLINE)) { /* offline? */\r
594 msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */\r
595 setFSR (devc); /* set cch flg */\r
596 return IORETURN (msc_stopioe, SCPE_UNATT);\r
597 }\r
598\r
599switch (uptr->FNC) { /* case on function */\r
600\r
601 case FNC_RWS: /* rewind offline */\r
602 sim_tape_rewind (uptr); /* rewind tape */\r
603 uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */\r
604 uptr->UST = 0; /* clear REW status */\r
605 break; /* we're done */\r
606\r
607 case FNC_REW: /* rewind */\r
608 if (uptr->UST & STA_REW) { /* rewind in prog? */\r
609 uptr->FNC |= FNC_CMPL; /* set compl state */\r
610 sim_activate (uptr, msc_ctime); /* sched completion */\r
611 }\r
612 break; /* anyway, ctrl done */\r
613\r
614 case FNC_REW | FNC_CMPL: /* complete rewind */\r
615 sim_tape_rewind (uptr); /* rewind tape */\r
616 uptr->UST = 0; /* clear REW status */\r
617 return SCPE_OK; /* drive is free */\r
618\r
619 case FNC_GFM: /* gap + file mark */\r
620 if (ms_timing == 1) /* fast timing? */\r
621 goto DO_WFM; /* do plain file mark */\r
622 /* else fall into GAP */\r
623 case FNC_GAP: /* erase gap */\r
624 if (DEBUG_PRI (msc_dev, DEB_RWS))\r
625 fprintf (sim_deb,\r
626 ">>MSC svc: Unit %d wrote gap\n",\r
627 unum);\r
628 if ((r = ms_write_gap (uptr)) || /* write tape gap; error? */\r
629 (uptr->FNC != FNC_GFM)) /* not GFM? */\r
630 break; /* bail out now */\r
631 /* else drop into WFM */\r
632 case FNC_WFM: /* write file mark */\r
633 if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */\r
634 if (DEBUG_PRI (msc_dev, DEB_RWS))\r
635 fprintf (sim_deb,\r
636 ">>MSC svc: Unit %d wrote initial gap\n",\r
637 unum);\r
638 if (st = ms_write_gap (uptr)) { /* write initial gap; error? */\r
639 r = ms_map_err (uptr, st); /* map error */\r
640 break; /* terminate operation */\r
641 }\r
642 }\r
643 DO_WFM:\r
644 if (DEBUG_PRI (msc_dev, DEB_RWS))\r
645 fprintf (sim_deb,\r
646 ">>MSC svc: Unit %d wrote file mark\n",\r
647 unum);\r
648 if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */\r
649 r = ms_map_err (uptr, st); /* map error */\r
650 msc_sta = STA_EOF; /* set EOF status */\r
651 break;\r
652\r
653 case FNC_FSR: /* space forward */\r
654 if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */\r
655 r = ms_map_err (uptr, st); /* map error */\r
656 if (tbc & 1) msc_sta = msc_sta | STA_ODD;\r
657 else msc_sta = msc_sta & ~STA_ODD;\r
658 break;\r
659\r
660 case FNC_BSR: /* space reverse */\r
661 if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */\r
662 r = ms_map_err (uptr, st); /* map error */\r
663 if (tbc & 1) msc_sta = msc_sta | STA_ODD;\r
664 else msc_sta = msc_sta & ~STA_ODD;\r
665 break;\r
666\r
667 case FNC_FSF: /* space fwd file */\r
668 while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) {\r
669 if (sim_tape_eot (uptr)) break; /* EOT stops */\r
670 }\r
671 r = ms_map_err (uptr, st); /* map error */\r
672 break;\r
673\r
674 case FNC_BSF: /* space rev file */\r
675 while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;\r
676 r = ms_map_err (uptr, st); /* map error */\r
677 break;\r
678\r
679 case FNC_RFF: /* diagnostic read */\r
680 case FNC_RC: /* read */\r
681 if (msc_1st) { /* first svc? */\r
682 msc_1st = ms_ptr = ms_max = 0; /* clr 1st flop */\r
683 st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */\r
684 if (DEBUG_PRI (msc_dev, DEB_RWS))\r
685 fprintf (sim_deb,\r
686 ">>MSC svc: Unit %d read %d word record\n",\r
687 unum, ms_max / 2);\r
688 if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */\r
689 else if (st != MTSE_OK) { /* other error? */\r
690 r = ms_map_err (uptr, st); /* map error */\r
691 if (r == SCPE_OK) { /* recoverable? */\r
692 sim_activate (uptr, msc_itime); /* sched IRG */\r
693 uptr->FNC |= FNC_CMPL; /* set completion */\r
694 return SCPE_OK;\r
695 }\r
696 break; /* err, done */\r
697 }\r
698 if (ms_ctype) msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */\r
699 }\r
700 if (CTL (devd) && (ms_ptr < ms_max)) { /* DCH on, more data? */\r
701 if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR;\r
702 msd_buf = ((uint16) msxb[ms_ptr] << 8) |\r
703 ((ms_ptr + 1 == ms_max) ? 0 : msxb[ms_ptr + 1]);\r
704 ms_ptr = ms_ptr + 2;\r
705 setFSR (devd); /* set dch flg */\r
706 sim_activate (uptr, msc_xtime); /* re-activate */\r
707 return SCPE_OK;\r
708 }\r
709 if (ms_max & 1) msc_sta = msc_sta | STA_ODD; /* set ODD by rec len */\r
710 else msc_sta = msc_sta & ~STA_ODD;\r
711 sim_activate (uptr, msc_itime); /* sched IRG */\r
712 if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */\r
713 else uptr->FNC |= FNC_CMPL; /* set completion */\r
714 return SCPE_OK;\r
715\r
716 case FNC_RFF | FNC_CMPL: /* diagnostic read completion */\r
717 case FNC_RC | FNC_CMPL: /* read completion */\r
718 break;\r
719\r
720 case FNC_WC: /* write */\r
721 if (msc_1st) { /* first service? */\r
722 msc_1st = ms_ptr = 0; /* no data xfer on first svc */\r
723 if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */\r
724 if (DEBUG_PRI (msc_dev, DEB_RWS))\r
725 fprintf (sim_deb,\r
726 ">>MSC svc: Unit %d wrote initial gap\n",\r
727 unum);\r
728 if (st = ms_write_gap (uptr)) { /* write initial gap; error? */\r
729 r = ms_map_err (uptr, st); /* map error */\r
730 break; /* terminate operation */\r
731 }\r
732 }\r
733 }\r
734 else { /* not 1st, next char */\r
735 if (ms_ptr < DBSIZE) { /* room in buffer? */\r
736 msxb[ms_ptr] = msd_buf >> 8; /* store 2 char */\r
737 msxb[ms_ptr + 1] = msd_buf & 0377;\r
738 ms_ptr = ms_ptr + 2;\r
739 }\r
740 else msc_sta = msc_sta | STA_PAR;\r
741 }\r
742 if (CTL (devd)) { /* xfer flop set? */\r
743 setFSR (devd); /* set dch flag */\r
744 sim_activate (uptr, msc_xtime); /* re-activate */\r
745 return SCPE_OK;\r
746 }\r
747 if (ms_ptr) { /* any data? write */\r
748 if (DEBUG_PRI (msc_dev, DEB_RWS))\r
749 fprintf (sim_deb,\r
750 ">>MSC svc: Unit %d wrote %d word record\n",\r
751 unum, ms_ptr / 2);\r
752 if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */\r
753 r = ms_map_err (uptr, st); /* map error */\r
754 break;\r
755 }\r
756 }\r
757 sim_activate (uptr, msc_itime); /* sched IRG */\r
758 uptr->FNC |= FNC_CMPL; /* set completion */\r
759 return SCPE_OK;\r
760\r
761 case FNC_WC | FNC_CMPL: /* write completion */\r
762 break;\r
763\r
764 case FNC_RRR: /* not supported */\r
765 default: /* unknown command */\r
766 if (DEBUG_PRI (msc_dev, DEB_CMDS))\r
767 fprintf (sim_deb,\r
768 ">>MSC svc: Unit %d command %03o is unknown (NOP)\n",\r
769 unum, uptr->FNC);\r
770 break;\r
771 }\r
772\r
773setFSR (devc); /* set cch flg */\r
774msc_sta = msc_sta & ~STA_BUSY; /* update status */\r
775if (DEBUG_PRI (msc_dev, DEB_CMDS))\r
776 fprintf (sim_deb,\r
777 ">>MSC svc: Unit %d command %03o (%s) complete\n",\r
778 unum, uptr->FNC & 0377, ms_cmd_name (uptr->FNC));\r
779return r;\r
780}\r
781\r
782/* Write an erase gap */\r
783\r
784t_stat ms_write_gap (UNIT *uptr)\r
785{\r
786t_stat st;\r
787uint32 gap_len = ms_ctype ? GAP_13183 : GAP_13181; /* establish gap length */\r
788uint32 tape_bpi = ms_ctype ? BPI_13183 : BPI_13181; /* establish nominal bpi */\r
789\r
790if (st = sim_tape_wrgap (uptr, gap_len, tape_bpi)) /* write gap */\r
791 return ms_map_err (uptr, st); /* map error if failure */\r
792else\r
793 return SCPE_OK;\r
794}\r
795\r
796/* Map tape error status */\r
797\r
798t_stat ms_map_err (UNIT *uptr, t_stat st)\r
799{\r
800int32 unum = uptr - msc_dev.units; /* get unit number */\r
801\r
802if (DEBUG_PRI (msc_dev, DEB_RWS))\r
803 fprintf (sim_deb,\r
804 ">>MSC err: Unit %d tape library status = %d\n",\r
805 unum, st);\r
806\r
807switch (st) {\r
808\r
809 case MTSE_FMT: /* illegal fmt */\r
810 msc_sta = msc_sta | STA_REJ; /* reject cmd */\r
811 return SCPE_FMT; /* format error */\r
812\r
813 case MTSE_UNATT: /* unattached */\r
814 msc_detach (uptr); /* resync status (ignore rtn) */\r
815 msc_sta = msc_sta | STA_REJ; /* reject cmd */\r
816 return SCPE_UNATT; /* unit unattached */\r
817\r
818 case MTSE_OK: /* no error */\r
819 return SCPE_IERR; /* never get here! */\r
820\r
821 case MTSE_EOM: /* end of medium */\r
822 case MTSE_TMK: /* end of file */\r
823 msc_sta = msc_sta | STA_EOF | (ms_ctype ? 0 : STA_ODD);\r
824 break; /* EOF also sets ODD for 13181A */\r
825\r
826 case MTSE_INVRL: /* invalid rec lnt */\r
827 msc_sta = msc_sta | STA_PAR;\r
828 return SCPE_MTRLNT;\r
829\r
830 case MTSE_IOERR: /* IO error */\r
831 msc_sta = msc_sta | STA_PAR; /* error */\r
832 if (msc_stopioe) return SCPE_IOERR;\r
833 break;\r
834\r
835 case MTSE_RECE: /* record in error */\r
836 msc_sta = msc_sta | STA_PAR; /* error */\r
837 break;\r
838\r
839 case MTSE_WRP: /* write protect */\r
840 msc_sta = msc_sta | STA_REJ; /* reject */\r
841 break;\r
842 }\r
843\r
844return SCPE_OK;\r
845}\r
846\r
847/* Reset routine */\r
848\r
849t_stat msc_reset (DEVICE *dptr)\r
850{\r
851int32 i;\r
852UNIT *uptr;\r
853\r
854hp_enbdis_pair (dptr, /* make pair cons */\r
855 (dptr == &msd_dev)? &msc_dev: &msd_dev);\r
856msc_buf = msd_buf = 0;\r
857msc_sta = msc_usl = 0;\r
858msc_1st = 0;\r
859msc_dib.cmd = msd_dib.cmd = 0; /* clear cmd */\r
860msc_dib.ctl = msd_dib.ctl = 0; /* clear ctl */\r
861msc_dib.flg = msd_dib.flg = 1; /* set flg */\r
862msc_dib.fbf = msd_dib.fbf = 1; /* set fbf */\r
863msc_dib.srq = msd_dib.srq = 1; /* srq follows flg */\r
864for (i = 0; i < MS_NUMDR; i++) {\r
865 uptr = msc_dev.units + i;\r
866 sim_tape_reset (uptr);\r
867 sim_cancel (uptr);\r
868 uptr->UST = 0;\r
869 }\r
870ms_config_timing ();\r
871return SCPE_OK;\r
872}\r
873\r
874/* Attach routine */\r
875\r
876t_stat msc_attach (UNIT *uptr, char *cptr)\r
877{\r
878t_stat r;\r
879\r
880r = sim_tape_attach (uptr, cptr); /* attach unit */\r
881if (r == SCPE_OK)\r
882 uptr->flags = uptr->flags & ~UNIT_OFFLINE; /* set online */\r
883return r;\r
884}\r
885\r
886/* Detach routine */\r
887\r
888t_stat msc_detach (UNIT* uptr)\r
889{\r
890uptr->UST = 0; /* clear status */\r
891uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */\r
892return sim_tape_detach (uptr); /* detach unit */\r
893}\r
894\r
895/* Online routine */\r
896\r
897t_stat msc_online (UNIT *uptr, int32 value, char *cptr, void *desc)\r
898{\r
899if (uptr->flags & UNIT_ATT) return SCPE_OK;\r
900else return SCPE_UNATT;\r
901}\r
902\r
903/* Configure timing */\r
904\r
905void ms_config_timing (void)\r
906{\r
907uint32 i, tset;\r
908\r
909tset = (ms_timing << 1) | (ms_timing? 0 : ms_ctype); /* select timing set */\r
910for (i = 0; i < (sizeof (timers) / sizeof (timers[0])); i++)\r
911 *timers[i] = msc_times[tset][i]; /* assign times */\r
912}\r
913\r
914/* Set controller timing */\r
915\r
916t_stat ms_set_timing (UNIT *uptr, int32 val, char *cptr, void *desc)\r
917{\r
918if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG;\r
919ms_timing = val;\r
920ms_config_timing ();\r
921return SCPE_OK;\r
922}\r
923\r
924/* Show controller timing */\r
925\r
926t_stat ms_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc)\r
927{\r
928if (ms_timing) fputs ("fast timing", st);\r
929else fputs ("realistic timing", st);\r
930return SCPE_OK;\r
931}\r
932\r
933/* Set controller type */\r
934\r
935t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc)\r
936{\r
937int32 i;\r
938\r
939if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG;\r
940for (i = 0; i < MS_NUMDR; i++) {\r
941 if (msc_unit[i].flags & UNIT_ATT) return SCPE_ALATT;\r
942 }\r
943ms_ctype = val;\r
944ms_config_timing (); /* update for new type */\r
945return SCPE_OK;\r
946}\r
947\r
948/* Show controller type */\r
949\r
950t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc)\r
951{\r
952if (ms_ctype) fprintf (st, "13183A");\r
953else fprintf (st, "13181A");\r
954return SCPE_OK;\r
955}\r
956\r
957/* Set unit reel size\r
958\r
959 val = 0 -> SET MSCn CAPACITY=n\r
960 val = 1 -> SET MSCn REEL=n */\r
961\r
962t_stat ms_set_reelsize (UNIT *uptr, int32 val, char *cptr, void *desc)\r
963{\r
964int32 reel;\r
965t_stat status;\r
966\r
967if (val == 0) {\r
968 status = sim_tape_set_capac (uptr, val, cptr, desc);\r
969 if (status == SCPE_OK) uptr->REEL = 0;\r
970 return status;\r
971 }\r
972\r
973if (cptr == NULL) return SCPE_ARG;\r
974reel = (int32) get_uint (cptr, 10, 2400, &status);\r
975if (status != SCPE_OK) return status;\r
976else switch (reel) {\r
977\r
978 case 0:\r
979 uptr->REEL = 0; /* type 0 = unlimited/custom */\r
980 break;\r
981\r
982 case 600:\r
983 uptr->REEL = 1; /* type 1 = 600 foot */\r
984 break;\r
985\r
986 case 1200:\r
987 uptr->REEL = 2; /* type 2 = 1200 foot */\r
988 break;\r
989\r
990 case 2400:\r
991 uptr->REEL = 3; /* type 3 = 2400 foot */\r
992 break;\r
993\r
994 default:\r
995 return SCPE_ARG;\r
996 }\r
997\r
998uptr->capac = uptr->REEL? (TCAP << uptr->REEL) << ms_ctype: 0;\r
999return SCPE_OK;\r
1000}\r
1001\r
1002/* Show unit reel size\r
1003\r
1004 val = 0 -> SHOW MSC or SHOW MSCn or SHOW MSCn CAPACITY\r
1005 val = 1 -> SHOW MSCn REEL */\r
1006\r
1007t_stat ms_show_reelsize (FILE *st, UNIT *uptr, int32 val, void *desc)\r
1008{\r
1009t_stat status = SCPE_OK;\r
1010\r
1011if (uptr->REEL == 0) status = sim_tape_show_capac (st, uptr, val, desc);\r
1012else fprintf (st, "%4d foot reel", 300 << uptr->REEL);\r
1013if (val == 1) fputc ('\n', st); /* MTAB_NMO omits \n */\r
1014return status;\r
1015}\r
1016\r
1017/* Translate command to mnemonic for debug logging\r
1018\r
1019 The command names and descriptions are taken from the 13181 interface\r
1020 manual. */\r
1021\r
1022char *ms_cmd_name (uint32 cmd)\r
1023{\r
1024\r
1025switch (cmd & 0377) {\r
1026 case FNC_WC: return "WCC"; /* Write command */\r
1027 case FNC_WFM: return "WFM"; /* Write file mark */\r
1028 case FNC_RC: return "RRF"; /* Read record forward */\r
1029 case FNC_FSR: return "FSR"; /* Forward space record */\r
1030 case FNC_FSF: return "FSF"; /* Forward space file */\r
1031 case FNC_GAP: return "GAP"; /* Write gap */\r
1032 case FNC_BSR: return "BSR"; /* Backspace record */\r
1033 case FNC_BSF: return "BSF"; /* Backspace file */\r
1034 case FNC_REW: return "REW"; /* Rewind */\r
1035 case FNC_RWS: return "RWO"; /* Rewind off-line */\r
1036 case FNC_CLR: return "CLR"; /* Clear controller */\r
1037 case FNC_GFM: return "GFM"; /* Gap file mark */\r
1038 case FNC_RFF: return "RFF"; /* Read forward until file mark (diag) */\r
1039 case FNC_RRR: return "RRR"; /* Read record in reverse (diag) */\r
1040\r
1041 default: return "???"; /* Unknown command */\r
1042 }\r
1043}\r
1044\r
1045/* 7970B/7970E bootstrap routine (HP 12992D ROM) */\r
1046\r
1047const uint16 ms_rom[IBL_LNT] = {\r
1048 0106501, /*ST LIB 1 ; read sw */\r
1049 0006011, /* SLB,RSS ; bit 0 set? */\r
1050 0027714, /* JMP RD ; no read */\r
1051 0003004, /* CMA,INA ; A is ctr */\r
1052 0073775, /* STA WC ; save */\r
1053 0067772, /* LDA SL0RW ; sel 0, rew */\r
1054 0017762, /*FF JSB CMD ; do cmd */\r
1055 0102311, /* SFS CC ; done? */\r
1056 0027707, /* JMP *-1 ; wait */\r
1057 0067774, /* LDB FFC ; get file fwd */\r
1058 0037775, /* ISZ WC ; done files? */\r
1059 0027706, /* JMP FF ; no */\r
1060 0067773, /*RD LDB RDCMD ; read cmd */\r
1061 0017762, /* JSB CMD ; do cmd */\r
1062 0103710, /* STC DC,C ; start dch */\r
1063 0102211, /* SFC CC ; read done? */\r
1064 0027752, /* JMP STAT ; no, get stat */\r
1065 0102310, /* SFS DC ; any data? */\r
1066 0027717, /* JMP *-3 ; wait */\r
1067 0107510, /* LIB DC,C ; get rec cnt */\r
1068 0005727, /* BLF,BLF ; move to lower */\r
1069 0007000, /* CMB ; make neg */\r
1070 0077775, /* STA WC ; save */\r
1071 0102211, /* SFC CC ; read done? */\r
1072 0027752, /* JMP STAT ; no, get stat */\r
1073 0102310, /* SFS DC ; any data? */\r
1074 0027727, /* JMP *-3 ; wait */\r
1075 0107510, /* LIB DC,C ; get load addr */\r
1076 0074000, /* STB 0 ; start csum */\r
1077 0077762, /* STA CMD ; save address */\r
1078 0027742, /* JMP *+4 */\r
1079 0177762, /*NW STB CMD,I ; store data */\r
1080 0040001, /* ADA 1 ; add to csum */\r
1081 0037762, /* ISZ CMD ; adv addr ptr */\r
1082 0102310, /* SFS DC ; any data? */\r
1083 0027742, /* JMP *-1 ; wait */\r
1084 0107510, /* LIB DC,C ; get word */\r
1085 0037775, /* ISZ WC ; done? */\r
1086 0027737, /* JMP NW ; no */\r
1087 0054000, /* CPB 0 ; csum ok? */\r
1088 0027717, /* JMP RD+3 ; yes, cont */\r
1089 0102011, /* HLT 11 ; no, halt */\r
1090 0102511, /*ST LIA CC ; get status */\r
1091 0001727, /* ALF,ALF ; get eof bit */\r
1092 0002020, /* SSA ; set? */\r
1093 0102077, /* HLT 77 ; done */\r
1094 0001727, /* ALF,ALF ; put status back */\r
1095 0001310, /* RAR,SLA ; read ok? */\r
1096 0102000, /* HLT 0 ; no */\r
1097 0027714, /* JMP RD ; read next */\r
1098 0000000, /*CMD 0 */\r
1099 0106611, /* OTB CC ; output cmd */\r
1100 0102511, /* LIA CC ; check for reject */\r
1101 0001323, /* RAR,RAR */\r
1102 0001310, /* RAR,SLA */\r
1103 0027763, /* JMP CMD+1 ; try again */\r
1104 0103711, /* STC CC,C ; start command */\r
1105 0127762, /* JMP CMD,I ; exit */\r
1106 0001501, /*SL0RW 001501 ; select 0, rewind */\r
1107 0001423, /*RDCMD 001423 ; read record */\r
1108 0000203, /*FFC 000203 ; space forward file */\r
1109 0000000, /*WC 000000 */\r
1110 0000000,\r
1111 0000000\r
1112 };\r
1113\r
1114t_stat msc_boot (int32 unitno, DEVICE *dptr)\r
1115{\r
1116int32 dev;\r
1117extern uint32 saved_AR;\r
1118\r
1119if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */\r
1120dev = msd_dib.devno; /* get data chan dev */\r
1121if (ibl_copy (ms_rom, dev)) return SCPE_IERR; /* copy boot to memory */\r
1122SR = (SR & IBL_OPT) | IBL_MS | (dev << IBL_V_DEV); /* set SR */\r
1123if ((sim_switches & SWMASK ('S')) && saved_AR) SR = SR | 1; /* skip? */\r
1124return SCPE_OK;\r
1125}\r
1126\r