a430f7169af305a964a68996082d34b18f194775
1 /* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator
3 Copyright (c) 1993-2007, 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 be
23 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 tu RH11/TM03/TU45 magtape
28 29-Apr-07 RMS Fixed bug in setting FCE on TMK (found by Naoki Hamada)
29 16-Feb-06 RMS Added tape capacity checking
30 16-Aug-05 RMS Fixed C++ declaration and cast problems
31 07-Jul-05 RMS Removed extraneous externs
32 31-Mar-05 RMS Fixed bug, ERASE/WREOF incorrectly clear CS1<done>
33 Fixed inaccuracies in error reporting
34 18-Mar-05 RMS Added attached test to detach routine
35 23-Oct-04 RMS Fixed setting done on non data transfers
36 01-Oct-04 RMS Modified to set FCE on read short record, eof
37 Implemented write check
38 TM03 uses only den<2> for validity test
39 TMK is cleared by new motion command, not DCLR
40 14-Sep-04 RMS Fixed RIP value
41 25-Apr-03 RMS Revised for extended file support
42 28-Mar-03 RMS Added multiformat support
43 28-Feb-03 RMS Revised for magtape library
44 27-Jan-03 RMS Changed to dynamically allocate buffer
45 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson)
46 Fixed bug in read (reported by Harris Newman)
47 29-Sep-02 RMS Added variable vector support
49 28-Aug-02 RMS Added end of medium support
50 30-May-02 RMS Widened POS to 32b
51 22-Apr-02 RMS Changed record length error code
52 06-Jan-02 RMS Revised enable/disable support
53 30-Nov-01 RMS Added read only unit, extended SET/SHOW support
54 24-Nov-01 RMS Changed POS, FLG, UST to arrays
55 23-Oct-01 RMS Fixed bug in error interrupts
56 New IO page address constants
57 05-Oct-01 RMS Rewrote interrupt handling from schematics
58 30-Sep-01 RMS Fixed handling of non-existent formatters
59 28-Sep-01 RMS Fixed interrupt handling for SC/ATA
60 4-May-01 RMS Fixed bug in odd address test
61 3-May-01 RMS Fixed drive reset to clear SSC
63 Magnetic tapes are represented as a series of variable 8b records
66 32b record length in bytes - exact number, sign = error
72 32b record length in bytes - exact number, sign = error
74 If the byte count is odd, the record is padded with an extra byte
75 of junk. File marks are represented by a single record length of 0.
76 End of tape is two consecutive end of file marks.
78 WARNING: The interupt logic of the RH11/RH70 is unusual and must be
79 simulated with great precision. The RH11 has an internal interrupt
80 request flop, CSTB INTR, which is controlled as follows:
81 - Writing IE and DONE simultaneously sets CSTB INTR
82 - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
84 - A transition of DONE from 0 to 1 sets CSTB from INTR
85 The output of INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
86 create the interrupt request signal. Thus,
87 - The DONE interrupt is edge sensitive, but the SC interrupt is
89 - The DONE interrupt, once set, is not disabled if IE is cleared,
90 but the SC interrupt is.
93 #include "pdp10_defs.h"
96 #define TU_NUMFM 1 /* #formatters */
97 #define TU_NUMDR 8 /* #drives */
98 #define USTAT u3 /* unit status */
99 #define UDENS u4 /* unit density */
100 #define UD_UNK 0 /* unknown */
101 #define MT_MAXFR (1 << 16) /* max data buf */
103 /* MTCS1 - 172440 - control/status 1 */
105 #define CS1_GO CSR_GO /* go */
106 #define CS1_V_FNC 1 /* function pos */
107 #define CS1_M_FNC 037 /* function mask */
108 #define CS1_N_FNC (CS1_M_FNC + 1)
109 #define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
110 #define FNC_NOP 000 /* no operation */
111 #define FNC_UNLOAD 001 /* unload */
112 #define FNC_REWIND 003 /* rewind */
113 #define FNC_FCLR 004 /* formatter clear */
114 #define FNC_RIP 010 /* read in preset */
115 #define FNC_ERASE 012 /* erase tape */
116 #define FNC_WREOF 013 /* write tape mark */
117 #define FNC_SPACEF 014 /* space forward */
118 #define FNC_SPACER 015 /* space reverse */
119 #define FNC_XFER 024 /* >=? data xfr */
120 #define FNC_WCHKF 024 /* write check */
121 #define FNC_WCHKR 027 /* write check rev */
122 #define FNC_WRITE 030 /* write */
123 #define FNC_READF 034 /* read forward */
124 #define FNC_READR 037 /* read reverse */
125 #define CS1_IE CSR_IE /* int enable */
126 #define CS1_DONE CSR_DONE /* ready */
127 #define CS1_V_UAE 8 /* Unibus addr ext */
129 #define CS1_UAE (CS1_M_UAE << CS1_V_UAE)
130 #define CS1_DVA 0004000 /* drive avail NI */
131 #define CS1_MCPE 0020000 /* Mbus par err NI */
132 #define CS1_TRE 0040000 /* transfer err */
133 #define CS1_SC 0100000 /* special cond */
134 #define CS1_MBZ 0012000
135 #define CS1_DRV (CS1_FNC | CS1_GO)
136 #define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
137 #define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE))
139 /* MTWC - 172442 - word count */
141 /* MTBA - 172444 - base address */
143 #define BA_MBZ 0000001 /* must be zero */
145 /* MTFC - 172446 - frame count */
147 /* MTCS2 - 172450 - control/status 2 */
149 #define CS2_V_FMTR 0 /* formatter select */
150 #define CS2_M_FMTR 07
151 #define CS2_FMTR (CS2_M_FMTR << CS2_V_FMTR)
152 #define CS2_UAI 0000010 /* addr inhibit NI */
153 #define CS2_PAT 0000020 /* parity test NI */
154 #define CS2_CLR 0000040 /* controller clear */
155 #define CS2_IR 0000100 /* input ready */
156 #define CS2_OR 0000200 /* output ready */
157 #define CS2_MDPE 0000400 /* Mbus par err NI */
158 #define CS2_MXF 0001000 /* missed xfer NI */
159 #define CS2_PGE 0002000 /* program err */
160 #define CS2_NEM 0004000 /* nx mem err */
161 #define CS2_NEF 0010000 /* nx fmter err */
162 #define CS2_PE 0020000 /* parity err NI */
163 #define CS2_WCE 0040000 /* write chk err */
164 #define CS2_DLT 0100000 /* data late NI */
165 #define CS2_MBZ (CS2_CLR | CS2_WCE)
166 #define CS2_RW (CS2_FMTR | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE)
167 #define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \
168 CS2_NEF | CS2_PE | CS2_DLT )
169 #define GET_FMTR(x) (((x) >> CS2_V_FMTR) & CS2_M_FMTR)
171 /* MTFS - 172452 - formatter status
172 + indicates kept in drive status
173 ^ indicates calculated on the fly
176 #define FS_SAT 0000001 /* slave attention */
177 #define FS_BOT 0000002 /* ^beginning of tape */
178 #define FS_TMK 0000004 /* end of file */
179 #define FS_ID 0000010 /* ID burst detected */
180 #define FS_SLOW 0000020 /* slowing down NI */
181 #define FS_PE 0000040 /* ^PE status */
182 #define FS_SSC 0000100 /* slave stat change */
183 #define FS_RDY 0000200 /* ^formatter ready */
184 #define FS_FPR 0000400 /* formatter present */
185 #define FS_EOT 0002000 /* +end of tape */
186 #define FS_WRL 0004000 /* ^write locked */
187 #define FS_MOL 0010000 /* ^medium online */
188 #define FS_PIP 0020000 /* +pos in progress */
189 #define FS_ERR 0040000 /* ^error */
190 #define FS_ATA 0100000 /* attention active */
191 #define FS_REW 0200000 /* +rewinding */
193 #define FS_DYN (FS_ERR | FS_PIP | FS_MOL | FS_WRL | FS_EOT | \
194 FS_RDY | FS_PE | FS_BOT)
196 /* MTER - 172454 - error register */
198 #define ER_ILF 0000001 /* illegal func */
199 #define ER_ILR 0000002 /* illegal register */
200 #define ER_RMR 0000004 /* reg mod refused */
201 #define ER_MCP 0000010 /* Mbus cpar err NI */
202 #define ER_FER 0000020 /* format sel err */
203 #define ER_MDP 0000040 /* Mbus dpar err NI */
204 #define ER_VPE 0000100 /* vert parity err */
205 #define ER_CRC 0000200 /* CRC err NI */
206 #define ER_NSG 0000400 /* non std gap err NI */
207 #define ER_FCE 0001000 /* frame count err */
208 #define ER_ITM 0002000 /* inv tape mark NI */
209 #define ER_NXF 0004000 /* wlock or fnc err */
210 #define ER_DTE 0010000 /* time err NI */
211 #define ER_OPI 0020000 /* op incomplete */
212 #define ER_UNS 0040000 /* drive unsafe */
213 #define ER_DCK 0100000 /* data check NI */
215 /* MTAS - 172456 - attention summary */
217 #define AS_U0 0000001 /* unit 0 flag */
219 /* MTCC - 172460 - check character, read only */
221 #define CC_MBZ 0177000 /* must be zero */
223 /* MTDB - 172462 - data buffer */
225 /* MTMR - 172464 - maintenance register */
227 #define MR_RW 0177637 /* read/write */
229 /* MTDT - 172466 - drive type */
231 #define DT_NSA 0100000 /* not sect addr */
232 #define DT_TAPE 0040000 /* tape */
233 #define DT_PRES 0002000 /* slave present */
234 #define DT_TM03 0000040 /* TM03 formatter */
235 #define DT_OFF 0000010 /* drive off */
236 #define DT_TE16 0000011 /* TE16 */
237 #define DT_TU45 0000012 /* TU45 */
238 #define DT_TU77 0000014 /* TU77 */
240 /* MTSN - 172470 - serial number */
242 /* MTTC - 172472 - tape control register */
244 #define TC_V_UNIT 0 /* unit select */
246 #define TC_V_EVN 0000010 /* even parity */
247 #define TC_V_FMT 4 /* format select */
249 #define TC_10C 00 /* PDP-10 core dump */
250 #define TC_IND 03 /* industry standard */
251 #define TC_V_DEN 8 /* density select */
253 #define TC_800 3 /* 800 bpi */
254 #define TC_1600 4 /* 1600 bpi */
255 #define TC_AER 0010000 /* abort on error */
256 #define TC_SAC 0020000 /* slave addr change */
257 #define TC_FCS 0040000 /* frame count status */
258 #define TC_ACC 0100000 /* accelerating NI */
259 #define TC_RW 0013777
260 #define TC_MBZ 0004000
261 #define TC_RIP ((TC_800 << TC_V_DEN) || (TC_10C << TC_V_FMT))
262 #define GET_DEN(x) (((x) >> TC_V_DEN) & TC_M_DEN)
263 #define GET_FMT(x) (((x) >> TC_V_FMT) & TC_M_FMT)
264 #define GET_DRV(x) (((x) >> TC_V_UNIT) & TC_M_UNIT)
268 #define XWC_MBZ 0000001 /* wc<0> mbz */
269 #define XBA_MBZ 0000001 /* addr<0> mbz */
270 #define XBA_ODD 0000002 /* odd address */
271 #define TXFR(b,w,od) if (((b) & XBA_MBZ) || ((w) & XWC_MBZ) || \
272 (((b) & XBA_ODD) != ((od) << 1))) { \
273 tucs2 = tucs2 | CS2_NEM; \
274 ubcs[1] = ubcs[1] | UBCS_TMO; \
275 tucs1 = tucs1 & ~CS1_GO; \
276 update_tucs (CS1_DONE, drv); \
279 #define NEWPAGE(v,m) (((v) & PAG_M_OFF) == (m))
280 #define MAPM(v,p,f) vpn = PAG_GETVPN (v); \
281 if ((vpn >= UMAP_MEMSIZE) || ((ubmap[1][vpn] & \
282 (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != \
284 tucs2 = tucs2 | CS2_NEM; \
285 ubcs[1] = ubcs[1] | UBCS_TMO; \
288 p = (ubmap[1][vpn] + PAG_GETOFF (v)) & PAMASK; \
289 if (MEM_ADDR_NXM (p)) { \
290 tucs2 = tucs2 | CS2_NEM; \
291 ubcs[1] = ubcs[1] | UBCS_TMO; \
295 extern d10
*M
; /* memory */
296 extern int32 int_req
;
297 extern int32 ubmap
[UBANUM
][UMAP_MEMSIZE
]; /* Unibus map */
298 extern int32 ubcs
[UBANUM
];
299 extern UNIT cpu_unit
;
300 extern int32 sim_switches
;
301 extern FILE *sim_deb
;
303 int32 tucs1
= 0; /* control/status 1 */
304 int32 tuwc
= 0; /* word count */
305 int32 tuba
= 0; /* bus address */
306 int32 tufc
= 0; /* frame count */
307 int32 tucs2
= 0; /* control/status 2 */
308 int32 tufs
= 0; /* formatter status */
309 int32 tuer
= 0; /* error status */
310 int32 tucc
= 0; /* check character */
311 int32 tudb
= 0; /* data buffer */
312 int32 tumr
= 0; /* maint register */
313 int32 tutc
= 0; /* tape control */
314 int32 tuiff
= 0; /* INTR flip/flop */
315 int32 tu_time
= 10; /* record latency */
316 int32 tu_stopioe
= 1; /* stop on error */
317 int32 tu_log
= 0; /* debug */
318 int32 reg_in_fmtr
[32] = { /* reg in formatter */
319 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1,
320 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
322 int32 reg_in_fmtr1
[32] = { /* rmr if write + go */
323 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1,
324 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
326 int32 fmt_test
[16] = { /* fmt bytes/10 wd */
327 5, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
329 static char *tu_fname
[CS1_N_FNC
] = {
330 "NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7",
331 "RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17",
332 "20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR",
333 "WRITE", "31", "32", "33", "READF", "35", "36" "READR"
335 static uint8
*xbuf
= NULL
; /* xfer buffer */
337 t_stat
tu_rd (int32
*data
, int32 PA
, int32 access
);
338 t_stat
tu_wr (int32 data
, int32 PA
, int32 access
);
339 int32
tu_inta (void);
340 t_stat
tu_svc (UNIT
*uptr
);
341 t_stat
tu_reset (DEVICE
*dptr
);
342 t_stat
tu_attach (UNIT
*uptr
, char *cptr
);
343 t_stat
tu_detach (UNIT
*uptr
);
344 t_stat
tu_boot (int32 unitno
, DEVICE
*dptr
);
345 void tu_go (int32 drv
);
346 void set_tuer (int32 flag
);
347 void update_tucs (int32 flag
, int32 drv
);
348 t_stat
tu_map_err (UNIT
*uptr
, t_stat st
, t_bool qdt
);
350 /* TU data structures
352 tu_dev TU device descriptor
354 tu_reg TU register list
355 tu_mod TU modifier list
359 IOBA_TU
, IOLN_TU
, &tu_rd
, &tu_wr
,
360 1, IVCL (TU
), VEC_TU
, { &tu_inta
}
364 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) },
365 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) },
366 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) },
367 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) },
368 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) },
369 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) },
370 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) },
371 { UDATA (&tu_svc
, UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_ROABLE
, 0) }
375 { ORDATA (MTCS1
, tucs1
, 16) },
376 { ORDATA (MTWC
, tuwc
, 16) },
377 { ORDATA (MTBA
, tuba
, 16) },
378 { ORDATA (MTFC
, tufc
, 16) },
379 { ORDATA (MTCS2
, tucs2
, 16) },
380 { ORDATA (MTFS
, tufs
, 16) },
381 { ORDATA (MTER
, tuer
, 16) },
382 { ORDATA (MTCC
, tucc
, 16) },
383 { ORDATA (MTDB
, tudb
, 16) },
384 { ORDATA (MTMR
, tumr
, 16) },
385 { ORDATA (MTTC
, tutc
, 16) },
386 { FLDATA (IFF
, tuiff
, 0) },
387 { FLDATA (INT
, int_req
, INT_V_TU
) },
388 { FLDATA (DONE
, tucs1
, CSR_V_DONE
) },
389 { FLDATA (IE
, tucs1
, CSR_V_IE
) },
390 { FLDATA (STOP_IOE
, tu_stopioe
, 0) },
391 { DRDATA (TIME
, tu_time
, 24), PV_LEFT
},
392 { URDATA (UST
, tu_unit
[0].USTAT
, 8, 17, 0, TU_NUMDR
, 0) },
393 { URDATA (POS
, tu_unit
[0].pos
, 10, T_ADDR_W
, 0,
394 TU_NUMDR
, PV_LEFT
| REG_RO
) },
395 { ORDATA (LOG
, tu_log
, 8), REG_HIDDEN
},
400 { MTUF_WLK
, 0, "write enabled", "WRITEENABLED", NULL
},
401 { MTUF_WLK
, MTUF_WLK
, "write locked", "LOCKED", NULL
},
402 { MTAB_XTD
|MTAB_VUN
, 0, "FORMAT", "FORMAT",
403 &sim_tape_set_fmt
, &sim_tape_show_fmt
, NULL
},
404 { MTAB_XTD
|MTAB_VUN
, 0, "CAPACITY", "CAPACITY",
405 &sim_tape_set_capac
, &sim_tape_show_capac
, NULL
},
406 { MTAB_XTD
|MTAB_VDV
, 0, "ADDRESS", NULL
,
407 NULL
, &show_addr
, NULL
},
408 { MTAB_XTD
|MTAB_VDV
, 0, "VECTOR", NULL
,
409 NULL
, &show_vec
, NULL
},
414 "TU", tu_unit
, tu_reg
, tu_mod
,
415 TU_NUMDR
, 10, 31, 1, 8, 8,
416 NULL
, NULL
, &tu_reset
,
417 &tu_boot
, &tu_attach
, &tu_detach
,
418 &tu_dib
, DEV_UBUS
| DEV_DEBUG
421 /* I/O dispatch routine, I/O addresses 17772440 - 17772472 */
423 t_stat
tu_rd (int32
*data
, int32 PA
, int32 access
)
427 fmtr
= GET_FMTR (tucs2
); /* get current fmtr */
428 drv
= GET_DRV (tutc
); /* get current drive */
429 j
= (PA
>> 1) & 017; /* get reg offset */
430 if (reg_in_fmtr
[j
] && (fmtr
!= 0)) { /* nx formatter */
431 tucs2
= tucs2
| CS2_NEF
; /* set error flag */
432 update_tucs (CS1_SC
, drv
); /* request intr */
437 update_tucs (0, drv
); /* update status */
438 switch (j
) { /* decode PA<4:1> */
440 case 000: /* MTCS1 */
441 if (fmtr
!= 0) *data
= tucs1
& ~CS1_DRV
;
450 *data
= tuba
= tuba
& ~BA_MBZ
;
457 case 004: /* MTCS2 */
458 *data
= tucs2
= (tucs2
& ~CS2_MBZ
) | CS2_IR
| CS2_OR
;
462 *data
= tufs
& 0177777; /* mask off rewind */
470 *data
= (tufs
& FS_ATA
)? AS_U0
: 0;
474 *data
= tucc
= tucc
& ~CC_MBZ
;
486 *data
= DT_NSA
| DT_TAPE
| DT_TM03
|
487 ((tu_unit
[drv
].flags
& UNIT_DIS
)? DT_OFF
: (DT_PRES
| DT_TU45
));
491 *data
= (tu_unit
[drv
].flags
& UNIT_DIS
)? 0: 040 | (drv
+ 1);
495 *data
= tutc
= tutc
& ~TC_MBZ
;
498 default: /* all others */
500 update_tucs (0, drv
);
507 t_stat
tu_wr (int32 data
, int32 PA
, int32 access
)
509 int32 cs1f
, fmtr
, drv
, j
;
511 cs1f
= 0; /* no int on cs1 upd */
512 fmtr
= GET_FMTR (tucs2
); /* get formatter */
513 drv
= GET_DRV (tutc
); /* get current unit */
514 j
= (PA
>> 1) & 017; /* get reg offset */
515 if (reg_in_fmtr
[j
] && (fmtr
!= 0)) { /* nx formatter */
516 tucs2
= tucs2
| CS2_NEF
; /* set error flag */
517 update_tucs (CS1_SC
, drv
); /* request intr */
520 if (reg_in_fmtr1
[j
] && ((tucs1
& CS1_DONE
) == 0)) { /* formatter busy? */
521 set_tuer (ER_RMR
); /* won't write */
522 update_tucs (0, drv
);
526 switch (j
) { /* decode PA<4:1> */
528 case 000: /* MTCS1 */
529 if ((access
== WRITEB
) && (PA
& 1)) data
= data
<< 8;
530 if (data
& CS1_TRE
) { /* error clear? */
531 tucs1
= tucs1
& ~CS1_TRE
; /* clr CS1<TRE> */
532 tucs2
= tucs2
& ~CS2_ERR
; /* clr CS2<15:8> */
534 if ((access
== WRITE
) || (PA
& 1)) { /* hi byte write? */
535 if (tucs1
& CS1_DONE
) /* done set? */
536 tucs1
= (tucs1
& ~CS1_UAE
) | (data
& CS1_UAE
);
538 if ((access
== WRITE
) || !(PA
& 1)) { /* lo byte write? */
539 if ((data
& CS1_DONE
) && (data
& CS1_IE
)) /* to DONE+IE? */
540 tuiff
= 1; /* set CSTB INTR */
541 tucs1
= (tucs1
& ~CS1_IE
) | (data
& CS1_IE
);
542 if (fmtr
!= 0) { /* nx formatter? */
543 tucs2
= tucs2
| CS2_NEF
; /* set error flag */
544 cs1f
= CS1_SC
; /* req interrupt */
546 else if (tucs1
& CS1_GO
) { /* busy? */
547 if (tucs1
& CS1_DONE
) set_tuer (ER_RMR
);
548 else tucs2
= tucs2
| CS2_PGE
;
551 tucs1
= (tucs1
& ~CS1_DRV
) | (data
& CS1_DRV
);
552 if (tucs1
& CS1_GO
) tu_go (drv
);
558 if (access
== WRITEB
) data
= (PA
& 1)?
559 (tuwc
& 0377) | (data
<< 8): (tuwc
& ~0377) | data
;
564 if (access
== WRITEB
) data
= (PA
& 1)?
565 (tuba
& 0377) | (data
<< 8): (tuba
& ~0377) | data
;
566 tuba
= data
& ~BA_MBZ
;
570 if (access
== WRITEB
) data
= (PA
& 1)?
571 (tufc
& 0377) | (data
<< 8): (tufc
& ~0377) | data
;
573 tutc
= tutc
| TC_FCS
; /* set fc flag */
576 case 004: /* MTCS2 */
577 if ((access
== WRITEB
) && (PA
& 1)) data
= data
<< 8;
578 if (data
& CS2_CLR
) tu_reset (&tu_dev
); /* init? */
580 if ((data
& ~tucs2
) & (CS2_PE
| CS2_MXF
))
581 cs1f
= CS1_SC
; /* diagn intr */
582 if (access
== WRITEB
) data
= (tucs2
& /* merge data */
583 ((PA
& 1)? 0377: 0177400)) | data
;
584 tucs2
= (tucs2
& ~CS2_RW
) | (data
& CS2_RW
) | CS2_IR
| CS2_OR
;
589 if ((access
== WRITEB
) && (PA
& 1)) break;
590 if (data
& AS_U0
) tufs
= tufs
& ~FS_ATA
;
594 if (access
== WRITEB
) data
= (PA
& 1)?
595 (tudb
& 0377) | (data
<< 8): (tudb
& ~0377) | data
;
600 if (access
== WRITEB
) data
= (PA
& 1)?
601 (tumr
& 0377) | (data
<< 8): (tumr
& ~0377) | data
;
602 tumr
= (tumr
& ~MR_RW
) | (data
& MR_RW
);
606 if (access
== WRITEB
) data
= (PA
& 1)?
607 (tutc
& 0377) | (data
<< 8): (tutc
& ~0377) | data
;
608 tutc
= (tutc
& ~TC_RW
) | (data
& TC_RW
) | TC_SAC
;
609 drv
= GET_DRV (tutc
);
617 break; /* read only */
619 default: /* all others */
624 update_tucs (cs1f
, drv
); /* update status */
628 /* New magtape command */
630 void tu_go (int32 drv
)
635 fnc
= GET_FNC (tucs1
); /* get function */
636 den
= GET_DEN (tutc
); /* get density */
637 uptr
= tu_dev
.units
+ drv
; /* get unit */
638 if (DEBUG_PRS (tu_dev
)) fprintf (sim_deb
,
639 ">>TU%d STRT: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n",
640 drv
, tu_fname
[fnc
], tucs1
, tucs2
, tuba
, tuwc
, tufc
, tufs
, tuer
, uptr
->pos
);
641 if ((fnc
!= FNC_FCLR
) && /* not clear & err */
642 ((tufs
& FS_ERR
) || sim_is_active (uptr
))) { /* or in motion? */
643 set_tuer (ER_ILF
); /* set err, ATN */
644 tucs1
= tucs1
& ~CS1_GO
; /* clear go */
645 update_tucs (CS1_SC
, drv
); /* request intr */
648 tufs
= tufs
& ~FS_ATA
; /* clear attention */
649 tutc
= tutc
& ~TC_SAC
; /* clear addr change */
651 switch (fnc
) { /* case on function */
652 case FNC_FCLR
: /* drive clear */
653 tuer
= 0; /* clear errors */
654 tutc
= tutc
& ~TC_FCS
; /* clear fc status */
655 tufs
= tufs
& ~(FS_SAT
| FS_SSC
| FS_ID
| FS_ERR
);
656 sim_cancel (uptr
); /* reset drive */
659 tucs1
= tucs1
& ~CS1_GO
; /* no operation */
662 case FNC_RIP
: /* read-in preset */
663 tutc
= TC_RIP
; /* density = 800 */
664 sim_tape_rewind (&tu_unit
[0]); /* rewind unit 0 */
665 tu_unit
[0].USTAT
= 0;
666 tucs1
= tucs1
& ~CS1_GO
;
667 tufs
= tufs
& ~FS_TMK
;
670 case FNC_UNLOAD
: /* unload */
671 if ((uptr
->flags
& UNIT_ATT
) == 0) { /* unattached? */
676 uptr
->USTAT
= FS_REW
;
677 sim_activate (uptr
, tu_time
);
678 tucs1
= tucs1
& ~CS1_GO
;
679 tufs
= tufs
& ~FS_TMK
;
683 if ((uptr
->flags
& UNIT_ATT
) == 0) { /* unattached? */
687 uptr
->USTAT
= FS_PIP
| FS_REW
;
688 sim_activate (uptr
, tu_time
);
689 tucs1
= tucs1
& ~CS1_GO
;
690 tufs
= tufs
& ~FS_TMK
;
694 if ((uptr
->flags
& UNIT_ATT
) == 0) { /* unattached? */
698 if (sim_tape_eot (uptr
) || ((tutc
& TC_FCS
) == 0)) {
702 uptr
->USTAT
= FS_PIP
;
706 if ((uptr
->flags
& UNIT_ATT
) == 0) { /* unattached? */
710 if (sim_tape_bot (uptr
) || ((tutc
& TC_FCS
) == 0)) {
714 uptr
->USTAT
= FS_PIP
;
717 case FNC_WREOF
: /* write tape mark */
718 case FNC_ERASE
: /* erase */
719 if ((uptr
->flags
& UNIT_ATT
) == 0) { /* unattached? */
723 if (sim_tape_wrp (uptr
)) { /* write locked? */
727 if (fmt_test
[GET_FMT (tutc
)] == 0) { /* invalid format? */
731 if (uptr
->UDENS
== UD_UNK
) uptr
->UDENS
= den
; /* set dens */
735 case FNC_WCHKR
: /* wchk = read */
736 case FNC_READR
: /* read rev */
737 if (tufs
& FS_BOT
) { /* beginning of tape? */
743 case FNC_WRITE
: /* write */
744 if (((tutc
& TC_FCS
) == 0) || /* frame cnt = 0? */
745 ((den
== TC_800
) && (tufc
> 0777765))) { /* NRZI, fc < 13? */
749 case FNC_WCHKF
: /* wchk = read */
750 case FNC_READF
: /* read */
752 if ((uptr
->flags
& UNIT_ATT
) == 0) { /* unattached? */
756 if (fmt_test
[GET_FMT (tutc
)] == 0) { /* invalid format? */
760 if (uptr
->UDENS
== UD_UNK
) uptr
->UDENS
= den
; /* set dens */
762 tucs1
= tucs1
& ~CS1_DONE
; /* clear done */
764 tucs2
= tucs2
& ~CS2_ERR
; /* clear errors */
765 tucs1
= tucs1
& ~(CS1_TRE
| CS1_MCPE
);
766 tufs
= tufs
& ~(FS_TMK
| FS_ID
); /* clear eof, id */
767 sim_activate (uptr
, tu_time
);
770 default: /* all others */
771 set_tuer (ER_ILF
); /* not supported */
773 } /* end case function */
775 tucs1
= tucs1
& ~CS1_GO
; /* clear go */
776 update_tucs (CS1_SC
, drv
); /* set intr */
782 Complete movement or data transfer command
783 Unit must exist - can't remove an active unit
784 Unit must be attached - detach cancels in progress operations
787 t_stat
tu_svc (UNIT
*uptr
)
789 int32 fnc
, fmt
, i
, j
, k
, wc10
, ba10
;
790 int32 ba
, fc
, wc
, drv
, mpa10
, vpn
;
793 t_stat st
, r
= SCPE_OK
;
795 drv
= (int32
) (uptr
- tu_dev
.units
); /* get drive # */
796 if (uptr
->USTAT
& FS_REW
) { /* rewind or unload? */
797 sim_tape_rewind (uptr
); /* rewind tape */
798 uptr
->USTAT
= 0; /* clear status */
799 tufs
= tufs
| FS_ATA
| FS_SSC
;
800 update_tucs (CS1_SC
, drv
); /* update status */
804 fnc
= GET_FNC (tucs1
); /* get command */
805 fmt
= GET_FMT (tutc
); /* get format */
806 ba
= GET_UAE (tucs1
) | tuba
; /* get bus address */
807 wc
= 0200000 - tuwc
; /* get word count */
808 fc
= 0200000 - tufc
; /* get frame count */
809 wc10
= wc
>> 1; /* 10 word count */
810 ba10
= ba
>> 2; /* 10 word addr */
811 uptr
->USTAT
= 0; /* clear status */
813 switch (fnc
) { /* case on function */
815 /* Non-data transfer commands - set ATA when done */
817 case FNC_SPACEF
: /* space forward */
819 tufc
= (tufc
+ 1) & 0177777; /* incr fc */
820 if (st
= sim_tape_sprecf (uptr
, &tbc
)) { /* space rec fwd, err? */
821 r
= tu_map_err (uptr
, st
, 0); /* map error */
824 } while ((tufc
!= 0) && !sim_tape_eot (uptr
));
825 if (tufc
) set_tuer (ER_FCE
);
826 else tutc
= tutc
& ~TC_FCS
;
827 tufs
= tufs
| FS_ATA
;
830 case FNC_SPACER
: /* space reverse */
832 tufc
= (tufc
+ 1) & 0177777; /* incr wc */
833 if (st
= sim_tape_sprecr (uptr
, &tbc
)) { /* space rec rev, err? */
834 r
= tu_map_err (uptr
, st
, 0); /* map error */
838 if (tufc
) set_tuer (ER_FCE
);
839 else tutc
= tutc
& ~TC_FCS
;
840 tufs
= tufs
| FS_ATA
;
843 case FNC_WREOF
: /* write end of file */
844 if (st
= sim_tape_wrtmk (uptr
)) /* write tmk, err? */
845 r
= tu_map_err (uptr
, st
, 0); /* map error */
846 tufs
= tufs
| FS_ATA
;
850 if (sim_tape_wrp (uptr
)) /* write protected? */
851 r
= tu_map_err (uptr
, MTSE_WRP
, 0); /* map error */
852 tufs
= tufs
| FS_ATA
;
855 /* Data transfer commands
857 These commands must take into account the action of the "bit fiddler", which
858 converts between PDP-10 format and tape format. Only two tape formats are
861 PDP-10 core dump: write 36b as byte 0/byte 1/byte 2/byte 3/0000'last nibble
862 industry mode: write hi 32b as byte 0/byte 1/byte 2/byte 3
864 These commands must also take into account the action of the Unibus adapter,
865 which munges PDP-10 addresses through the Unibus map.
868 case FNC_READF
: /* read */
869 case FNC_WCHKF
: /* wcheck = read */
870 tufc
= 0; /* clear frame count */
871 if ((uptr
->UDENS
== TC_1600
) && sim_tape_bot (uptr
))
872 tufs
= tufs
| FS_ID
; /* PE BOT? ID burst */
873 TXFR (ba
, wc
, 0); /* validate transfer */
874 if (st
= sim_tape_rdrecf (uptr
, xbuf
, &tbc
, MT_MAXFR
)) { /* read fwd */
875 if (st
== MTSE_TMK
) set_tuer (ER_FCE
); /* TMK also sets FCE */
876 r
= tu_map_err (uptr
, st
, 1); /* map error */
879 for (i
= j
= 0; (i
< wc10
) && (j
< ((int32
) tbc
)); i
++) {
880 if ((i
== 0) || NEWPAGE (ba10
+ i
, 0)) { /* map new page */
881 MAPM (ba10
+ i
, mpa10
, 0);
883 for (k
= 0; k
< 4; k
++) v
[k
] = xbuf
[j
++];
884 val
= (v
[0] << 28) | (v
[1] << 20) | (v
[2] << 12) | (v
[3] << 4);
885 if (fmt
== TC_10C
) val
= val
| ((d10
) xbuf
[j
++] & 017);
886 if (fnc
== FNC_READF
) M
[mpa10
] = val
; /* read? store */
887 else if (M
[mpa10
] != val
) { /* wchk, mismatch? */
888 tucs2
= tucs2
| CS2_WCE
; /* flag, stop */
893 tufc
= tbc
& 0177777;
894 tuwc
= (tuwc
+ (i
<< 1)) & 0177777;
896 if (tuwc
) set_tuer (ER_FCE
); /* short record? */
899 case FNC_WRITE
: /* write */
900 TXFR (ba
, wc
, 0); /* validate transfer */
901 for (i
= j
= 0; (i
< wc10
) && (j
< fc
); i
++) {
902 if ((i
== 0) || NEWPAGE (ba10
+ i
, 0)) { /* map new page */
903 MAPM (ba10
+ i
, mpa10
, 0);
906 xbuf
[j
++] = (uint8
) ((val
>> 28) & 0377);
907 xbuf
[j
++] = (uint8
) ((val
>> 20) & 0377);
908 xbuf
[j
++] = (uint8
) ((val
>> 12) & 0377);
909 xbuf
[j
++] = (uint8
) ((val
>> 4) & 0377);
910 if (fmt
== TC_10C
) xbuf
[j
++] = (uint8
) (val
& 017);
913 if (j
< fc
) fc
= j
; /* short record? */
914 if (st
= sim_tape_wrrecf (uptr
, xbuf
, fc
)) /* write rec, err? */
915 r
= tu_map_err (uptr
, st
, 1); /* map error */
917 tufc
= (tufc
+ fc
) & 0177777;
918 if (tufc
== 0) tutc
= tutc
& ~TC_FCS
;
919 tuwc
= (tuwc
+ (i
<< 1)) & 0177777;
924 case FNC_READR
: /* read reverse */
925 case FNC_WCHKR
: /* wcheck = read */
926 tufc
= 0; /* clear frame count */
927 TXFR (ba
, wc
, 1); /* validate xfer rev */
928 if (st
= sim_tape_rdrecr (uptr
, xbuf
+ 4, &tbc
, MT_MAXFR
)) { /* read rev */
929 if (st
== MTSE_TMK
) set_tuer (ER_FCE
); /* TMK also sets FCE */
930 r
= tu_map_err (uptr
, st
, 1); /* map error */
933 for (i
= 0; i
< 4; i
++) xbuf
[i
] = 0;
934 for (i
= 0, j
= tbc
+ 4; (i
< wc10
) && (j
>= 4); i
++) {
935 if ((i
== 0) || NEWPAGE (ba10
- i
, PAG_M_OFF
)) { /* map page */
936 MAPM (ba10
- i
, mpa10
, UMAP_RRV
);
938 val
= ((fmt
== TC_10C
)? (((d10
) xbuf
[--j
]) & 017): 0);
939 for (k
= 0; k
< 4; i
++) v
[k
] = xbuf
[--j
];
940 val
= val
| (v
[0] << 4) | (v
[1] << 12) | (v
[2] << 20) | (v
[3] << 28);
941 if (fnc
== FNC_READR
) M
[mpa10
] = val
; /* read? store */
942 else if (M
[mpa10
] != val
) { /* wchk, mismatch? */
943 tucs2
= tucs2
| CS2_WCE
; /* flag, stop */
948 tufc
= tbc
& 0177777;
949 tuwc
= (tuwc
+ (i
<< 1)) & 0177777;
951 if (tuwc
) set_tuer (ER_FCE
); /* short record? */
955 tucs1
= (tucs1
& ~CS1_UAE
) | ((ba
>> (16 - CS1_V_UAE
)) & CS1_UAE
);
956 tuba
= ba
& 0177777; /* update mem addr */
957 tucs1
= tucs1
& ~CS1_GO
; /* clear go */
958 if (fnc
>= FNC_XFER
) update_tucs (CS1_DONE
, drv
); /* data xfer? */
959 else update_tucs (CS1_SC
, drv
); /* no, set attn */
960 if (DEBUG_PRS (tu_dev
)) fprintf (sim_deb
,
961 ">>TU%d DONE: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n",
962 drv
, tu_fname
[fnc
], tucs1
, tucs2
, tuba
, tuwc
, tufc
, tufs
, tuer
, uptr
->pos
);
966 /* Formatter error */
968 void set_tuer (int32 flag
)
971 tufs
= tufs
| FS_ATA
;
972 tucs1
= tucs1
| CS1_SC
;
976 /* Controller status update
978 Check for done transition
981 Update interrupt request
984 void update_tucs (int32 flag
, int32 drv
)
986 int32 act
= sim_is_active (&tu_unit
[drv
]);
988 if ((flag
& ~tucs1
) & CS1_DONE
) /* DONE 0 to 1? */
989 tuiff
= (tucs1
& CS1_IE
)? 1: 0; /* CSTB INTR <- IE */
990 if (GET_FMTR (tucs2
) == 0) { /* formatter present? */
991 tufs
= (tufs
& ~FS_DYN
) | FS_FPR
;
992 if (tu_unit
[drv
].flags
& UNIT_ATT
) {
993 tufs
= tufs
| FS_MOL
| tu_unit
[drv
].USTAT
;
994 if (tu_unit
[drv
].UDENS
== TC_1600
) tufs
= tufs
| FS_PE
;
995 if (sim_tape_wrp (&tu_unit
[drv
])) tufs
= tufs
| FS_WRL
;
997 if (sim_tape_bot (&tu_unit
[drv
])) tufs
= tufs
| FS_BOT
;
998 if (sim_tape_eot (&tu_unit
[drv
])) tufs
= tufs
| FS_EOT
;
1001 if (tuer
) tufs
= tufs
| FS_ERR
;
1004 tucs1
= (tucs1
& ~(CS1_SC
| CS1_MCPE
| CS1_MBZ
)) | CS1_DVA
| flag
;
1005 if (tucs2
& CS2_ERR
) tucs1
= tucs1
| CS1_TRE
| CS1_SC
;
1006 else if (tucs1
& CS1_TRE
) tucs1
= tucs1
| CS1_SC
;
1007 if (tufs
& FS_ATA
) tucs1
= tucs1
| CS1_SC
;
1008 if (tuiff
|| ((tucs1
& CS1_SC
) && (tucs1
& CS1_DONE
) && (tucs1
& CS1_IE
)))
1009 int_req
= int_req
| INT_TU
;
1010 else int_req
= int_req
& ~INT_TU
;
1011 if ((tucs1
& CS1_DONE
) && tufs
&& !act
) tufs
= tufs
| FS_RDY
;
1015 /* Interrupt acknowledge */
1017 int32
tu_inta (void)
1019 tucs1
= tucs1
& ~CS1_IE
; /* clear int enable */
1020 tuiff
= 0; /* clear CSTB INTR */
1021 return VEC_TU
; /* acknowledge */
1024 /* Map tape error status */
1026 t_stat
tu_map_err (UNIT
*uptr
, t_stat st
, t_bool qdt
)
1030 case MTSE_FMT
: /* illegal fmt */
1031 case MTSE_UNATT
: /* not attached */
1032 set_tuer (ER_NXF
); /* can't execute */
1033 if (qdt
) tucs1
= tucs1
| CS1_TRE
; /* data xfr? set TRE */
1034 case MTSE_OK
: /* no error */
1037 case MTSE_TMK
: /* end of file */
1038 tufs
= tufs
| FS_TMK
;
1041 case MTSE_IOERR
: /* IO error */
1042 set_tuer (ER_VPE
); /* flag error */
1043 if (qdt
) tucs1
= tucs1
| CS1_TRE
; /* data xfr? set TRE */
1044 if (tu_stopioe
) return SCPE_IOERR
;
1047 case MTSE_INVRL
: /* invalid rec lnt */
1048 set_tuer (ER_VPE
); /* flag error */
1049 if (qdt
) tucs1
= tucs1
| CS1_TRE
; /* data xfr? set TRE */
1052 case MTSE_RECE
: /* record in error */
1053 set_tuer (ER_CRC
); /* set crc err */
1054 if (qdt
) tucs1
= tucs1
| CS1_TRE
; /* data xfr? set TRE */
1057 case MTSE_EOM
: /* end of medium */
1058 set_tuer (ER_OPI
); /* incomplete */
1059 if (qdt
) tucs1
= tucs1
| CS1_TRE
; /* data xfr? set TRE */
1062 case MTSE_BOT
: /* reverse into BOT */
1065 case MTSE_WRP
: /* write protect */
1066 set_tuer (ER_NXF
); /* can't execute */
1067 if (qdt
) tucs1
= tucs1
| CS1_TRE
; /* data xfr? set TRE */
1076 t_stat
tu_reset (DEVICE
*dptr
)
1081 tucs1
= CS1_DVA
| CS1_DONE
;
1082 tucs2
= CS2_IR
| CS2_OR
;
1087 tufs
= FS_FPR
| FS_RDY
;
1088 if (sim_switches
& SWMASK ('P')) tutc
= 0; /* powerup? clr TC */
1089 else tutc
= tutc
& ~TC_FCS
; /* no, clr <fcs> */
1090 tuiff
= 0; /* clear CSTB INTR */
1091 int_req
= int_req
& ~INT_TU
; /* clear interrupt */
1092 for (u
= 0; u
< TU_NUMDR
; u
++) { /* loop thru units */
1093 uptr
= tu_dev
.units
+ u
;
1094 sim_tape_reset (uptr
); /* clear pos flag */
1095 sim_cancel (uptr
); /* cancel activity */
1098 if (xbuf
== NULL
) xbuf
= (uint8
*) calloc (MT_MAXFR
+ 4, sizeof (uint8
));
1099 if (xbuf
== NULL
) return SCPE_MEM
;
1103 /* Attach routine */
1105 t_stat
tu_attach (UNIT
*uptr
, char *cptr
)
1107 int32 drv
= uptr
- tu_dev
.units
;
1110 r
= sim_tape_attach (uptr
, cptr
);
1111 if (r
!= SCPE_OK
) return r
;
1112 uptr
->USTAT
= 0; /* clear unit status */
1113 uptr
->UDENS
= UD_UNK
; /* unknown density */
1114 tufs
= tufs
| FS_ATA
| FS_SSC
; /* set attention */
1115 if ((GET_FMTR (tucs2
) == 0) && (GET_DRV (tutc
) == drv
)) /* selected drive? */
1116 tufs
= tufs
| FS_SAT
; /* set slave attn */
1117 update_tucs (CS1_SC
, drv
); /* update status */
1121 /* Detach routine */
1123 t_stat
tu_detach (UNIT
* uptr
)
1125 int32 drv
= uptr
- tu_dev
.units
;
1127 if (!(uptr
->flags
& UNIT_ATT
)) return SCPE_OK
; /* attached? */
1128 if (sim_is_active (uptr
)) { /* unit active? */
1129 sim_cancel (uptr
); /* cancel operation */
1130 tuer
= tuer
| ER_UNS
; /* set formatter error */
1131 if ((uptr
->USTAT
& FS_REW
) == 0) /* data transfer? */
1132 tucs1
= tucs1
| CS1_DONE
| CS1_TRE
; /* set done, err */
1134 uptr
->USTAT
= 0; /* clear status flags */
1135 tufs
= tufs
| FS_ATA
| FS_SSC
; /* set attention */
1136 update_tucs (CS1_SC
, drv
); /* update status */
1137 return sim_tape_detach (uptr
);
1140 /* Device bootstrap */
1142 #define BOOT_START 0377000 /* start */
1143 #define BOOT_LEN (sizeof (boot_rom_dec) / sizeof (d10))
1145 static const d10 boot_rom_dec
[] = {
1146 0515040000003, /* boot:hrlzi 1,3 ; uba # */
1147 0201000040001, /* movei 0,40001 ; vld,pg 1 */
1148 0713001000000+(IOBA_UBMAP
+1 & RMASK
), /* wrio 0,763001(1); set ubmap */
1149 0435040000000+(IOBA_TU
& RMASK
), /* iori 1,772440 ; rh addr */
1150 0202040000000+FE_RHBASE
, /* movem 1,FE_RHBASE */
1151 0201000000040, /* movei 0,40 ; ctrl reset */
1152 0713001000010, /* wrio 0,10(1) ; ->MTFS */
1153 0201100000031, /* movei 2,31 ; space f */
1154 0265740377014, /* jsp 17,tpop ; skip ucode */
1155 0201100000071, /* movei 2,71 ; read f */
1156 0265740377014, /* jsp 17,tpop ; read boot */
1157 0254000001000, /* jrst 1000 ; start */
1158 0200000000000+FE_MTFMT
, /* tpop:move 0,FE_MTFMT ; den,fmt,slv */
1159 0713001000032, /* wrio 0,32(1) ; ->MTTC */
1160 0201000000011, /* movei 0,11 ; clr+go */
1161 0713001000000, /* wrio 0,0(1) ; ->MTCS1 */
1162 0201140176000, /* movei 3,176000 ; wd cnt */
1163 0201200004000, /* movei 4,4000 ; addr */
1164 0200240000000+FE_MTFMT
, /* move 5,FE_MTFMT ; unit */
1165 0201300000000, /* movei 6,0 ; fmtr */
1166 0713141000002, /* wrio 3,2(1) ; ->MTWC */
1167 0713201000004, /* wrio 4,4(1) ; ->MTBA */
1168 0713301000006, /* wrio 6,6(1) ; ->MTFC */
1169 0713301000010, /* wrio 6,10(1) ; ->MTFS */
1170 0713241000032, /* wrio 5,32(1) ; ->MTTC */
1171 0713101000000, /* wrio 2,0(1) ; ->MTCS1 */
1172 0712341000012, /* rdio 7,12(1) ; read FS */
1173 0606340000200, /* trnn 7,200 ; test rdy */
1174 0254000377032, /* jrst .-2 ; loop */
1175 0606340040000, /* trnn 7,40000 ; test err */
1176 0254017000000, /* jrst 0(17) ; return */
1177 0712341000014, /* rdio 7,14(1) ; read err */
1178 0302340001000, /* caie 7,1000 ; fce? */
1179 0254200377052, /* halt */
1180 0254017000000, /* jrst 0(17) ; return */
1183 static const d10 boot_rom_its
[] = {
1184 0515040000003, /* boot:hrlzi 1,3 ; uba # - not used */
1185 0201000040001, /* movei 0,40001 ; vld,pg 1 */
1186 0714000000000+(IOBA_UBMAP
+1 & RMASK
), /* iowri 0,763001 ; set ubmap */
1187 0435040000000+(IOBA_TU
& RMASK
), /* iori 1,772440 ; rh addr */
1188 0202040000000+FE_RHBASE
, /* movem 1,FE_RHBASE */
1189 0201000000040, /* movei 0,40 ; ctrl reset */
1190 0714001000010, /* iowri 0,10(1) ; ->MTFS */
1191 0201100000031, /* movei 2,31 ; space f */
1192 0265740377014, /* jsp 17,tpop ; skip ucode */
1193 0201100000071, /* movei 2,71 ; read f */
1194 0265740377014, /* jsp 17,tpop ; read boot */
1195 0254000001000, /* jrst 1000 ; start */
1196 0200000000000+FE_MTFMT
, /* tpop:move 0,FE_MTFMT ; den,fmt,slv */
1197 0714001000032, /* iowri 0,32(1) ; ->MTTC */
1198 0201000000011, /* movei 0,11 ; clr+go */
1199 0714001000000, /* iowri 0,0(1) ; ->MTCS1 */
1200 0201140176000, /* movei 3,176000 ; wd cnt */
1201 0201200004000, /* movei 4,4000 ; addr */
1202 0200240000000+FE_MTFMT
, /* move 5,FE_MTFMT ; unit */
1203 0201300000000, /* movei 6,0 ; fmtr */
1204 0714141000002, /* iowri 3,2(1) ; ->MTWC */
1205 0714201000004, /* iowri 4,4(1) ; ->MTBA */
1206 0714301000006, /* iowri 6,6(1) ; ->MTFC */
1207 0714301000010, /* iowri 6,10(1) ; ->MTFS */
1208 0714241000032, /* iowri 5,32(1) ; ->MTTC */
1209 0714101000000, /* iowri 2,0(1) ; ->MTCS1 */
1210 0710341000012, /* iordi 7,12(1) ; read FS */
1211 0606340000200, /* trnn 7,200 ; test rdy */
1212 0254000377032, /* jrst .-2 ; loop */
1213 0606340040000, /* trnn 7,40000 ; test err */
1214 0254017000000, /* jrst 0(17) ; return */
1215 0710341000014, /* iordi 7,14(1) ; read err */
1216 0302340001000, /* caie 7,1000 ; fce? */
1217 0254200377052, /* halt */
1218 0254017000000, /* jrst 0(17) ; return */
1221 t_stat
tu_boot (int32 unitno
, DEVICE
*dptr
)
1224 extern a10 saved_PC
;
1227 M
[FE_MTFMT
] = (unitno
& TC_M_UNIT
) | (TC_1600
<< TC_V_DEN
) | (TC_10C
<< TC_V_FMT
);
1228 tu_unit
[unitno
].pos
= 0;
1229 for (i
= 0; i
< BOOT_LEN
; i
++)
1230 M
[BOOT_START
+ i
] = Q_ITS
? boot_rom_its
[i
]: boot_rom_dec
[i
];
1231 saved_PC
= BOOT_START
;