Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* pdp11_tu.c - PDP-11 TM02/TU16 TM03/TU45/TU77 Massbus magnetic tape controller\r |
2 | \r | |
3 | Copyright (c) 1993-2007, 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 | tu TM02/TM03 magtape\r | |
27 | \r | |
28 | 17-May-07 RMS CS1 DVA resides in device, not MBA\r | |
29 | 29-Apr-07 RMS Fixed bug in setting FCE on TMK (found by Naoki Hamada)\r | |
30 | 16-Feb-06 RMS Added tape capacity checking\r | |
31 | 12-Nov-05 RMS Changed default formatter to TM03 (for VMS)\r | |
32 | 31-Oct-05 RMS Fixed address width for large files\r | |
33 | 16-Aug-05 RMS Fixed C++ declaration and cast problems\r | |
34 | 31-Mar-05 RMS Fixed inaccuracies in error reporting\r | |
35 | 18-Mar-05 RMS Added attached test to detach routine\r | |
36 | 10-Sep-04 RMS Cloned from pdp10_tu.c\r | |
37 | \r | |
38 | Magnetic tapes are represented as a series of variable 8b records\r | |
39 | of the form:\r | |
40 | \r | |
41 | 32b record length in bytes - exact number, sign = error\r | |
42 | byte 0\r | |
43 | byte 1\r | |
44 | :\r | |
45 | byte n-2\r | |
46 | byte n-1\r | |
47 | 32b record length in bytes - exact number, sign = error\r | |
48 | \r | |
49 | If the byte count is odd, the record is padded with an extra byte\r | |
50 | of junk. File marks are represented by a single record length of 0.\r | |
51 | End of tape is two consecutive end of file marks.\r | |
52 | */\r | |
53 | \r | |
54 | #if defined (VM_PDP10)\r | |
55 | #error "PDP-10 uses pdp10_tu.c!"\r | |
56 | \r | |
57 | #elif defined (VM_PDP11)\r | |
58 | #include "pdp11_defs.h"\r | |
59 | #define DEV_DIS_INIT DEV_DIS\r | |
60 | \r | |
61 | #elif defined (VM_VAX)\r | |
62 | #include "vax_defs.h"\r | |
63 | #define DEV_DIS_INIT 0\r | |
64 | #if (!UNIBUS)\r | |
65 | #error "Qbus not supported!"\r | |
66 | #endif\r | |
67 | \r | |
68 | #endif\r | |
69 | #include "sim_tape.h"\r | |
70 | \r | |
71 | #define TU_NUMFM 1 /* #formatters */\r | |
72 | #define TU_NUMDR 8 /* #drives */\r | |
73 | #define USTAT u3 /* unit status */\r | |
74 | #define UDENS u4 /* unit density */\r | |
75 | #define UD_UNK 0 /* unknown */\r | |
76 | #define MT_MAXFR (1 << 16) /* max data buf */\r | |
77 | #define DEV_V_TM03 (DEV_V_FFUF + 0) /* TM02/TM03 */\r | |
78 | #define DEV_TM03 (1 << DEV_V_TM03)\r | |
79 | #define UNIT_V_TYPE (MTUF_V_UF + 0)\r | |
80 | #define UNIT_M_TYPE 03\r | |
81 | #define UNIT_TYPE (UNIT_M_TYPE << UNIT_V_TYPE)\r | |
82 | #define UNIT_TE16 (0 << UNIT_V_TYPE)\r | |
83 | #define UNIT_TU45 (1 << UNIT_V_TYPE)\r | |
84 | #define UNIT_TU77 (2 << UNIT_V_TYPE)\r | |
85 | #define GET_TYPE(x) (((x) >> UNIT_V_TYPE) & UNIT_M_TYPE)\r | |
86 | \r | |
87 | /* CS1 - offset 0 */\r | |
88 | \r | |
89 | #define CS1_OF 0\r | |
90 | #define CS1_GO CSR_GO /* go */\r | |
91 | #define CS1_V_FNC 1 /* function pos */\r | |
92 | #define CS1_M_FNC 037 /* function mask */\r | |
93 | #define CS1_N_FNC (CS1_M_FNC + 1)\r | |
94 | #define FNC_NOP 000 /* no operation */\r | |
95 | #define FNC_UNLOAD 001 /* unload */\r | |
96 | #define FNC_REWIND 003 /* rewind */\r | |
97 | #define FNC_FCLR 004 /* formatter clear */\r | |
98 | #define FNC_RIP 010 /* read in preset */\r | |
99 | #define FNC_ERASE 012 /* erase tape */\r | |
100 | #define FNC_WREOF 013 /* write tape mark */\r | |
101 | #define FNC_SPACEF 014 /* space forward */\r | |
102 | #define FNC_SPACER 015 /* space reverse */\r | |
103 | #define FNC_XFER 024 /* >=? data xfr */\r | |
104 | #define FNC_WCHKF 024 /* write check */\r | |
105 | #define FNC_WCHKR 027 /* write check rev */\r | |
106 | #define FNC_WRITE 030 /* write */\r | |
107 | #define FNC_READF 034 /* read forward */\r | |
108 | #define FNC_READR 037 /* read reverse */\r | |
109 | #define CS1_RW 077\r | |
110 | #define CS1_DVA 04000 /* drive avail */\r | |
111 | #define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)\r | |
112 | \r | |
113 | /* TUFS - formatter status - offset 1\r | |
114 | + indicates kept in drive status\r | |
115 | ^ indicates calculated on the fly\r | |
116 | */\r | |
117 | \r | |
118 | #define FS_OF 1\r | |
119 | #define FS_SAT 0000001 /* slave attention */\r | |
120 | #define FS_BOT 0000002 /* ^beginning of tape */\r | |
121 | #define FS_TMK 0000004 /* end of file */\r | |
122 | #define FS_ID 0000010 /* ID burst detected */\r | |
123 | #define FS_SLOW 0000020 /* slowing down NI */\r | |
124 | #define FS_PE 0000040 /* ^PE status */\r | |
125 | #define FS_SSC 0000100 /* slave stat change */\r | |
126 | #define FS_RDY 0000200 /* ^formatter ready */\r | |
127 | #define FS_FPR 0000400 /* formatter present */\r | |
128 | #define FS_EOT 0002000 /* +end of tape */\r | |
129 | #define FS_WRL 0004000 /* ^write locked */\r | |
130 | #define FS_MOL 0010000 /* ^medium online */\r | |
131 | #define FS_PIP 0020000 /* +pos in progress */\r | |
132 | #define FS_ERR 0040000 /* ^error */\r | |
133 | #define FS_ATA 0100000 /* attention active */\r | |
134 | #define FS_REW 0200000 /* +rewinding */\r | |
135 | \r | |
136 | #define FS_DYN (FS_ERR | FS_PIP | FS_MOL | FS_WRL | FS_EOT | \\r | |
137 | FS_RDY | FS_PE | FS_BOT)\r | |
138 | \r | |
139 | /* TUER - error register - offset 2 */\r | |
140 | \r | |
141 | #define ER_OF 2\r | |
142 | #define ER_ILF 0000001 /* illegal func */\r | |
143 | #define ER_ILR 0000002 /* illegal register */\r | |
144 | #define ER_RMR 0000004 /* reg mod refused */\r | |
145 | #define ER_MCP 0000010 /* Mbus cpar err NI */\r | |
146 | #define ER_FER 0000020 /* format sel err */\r | |
147 | #define ER_MDP 0000040 /* Mbus dpar err NI */\r | |
148 | #define ER_VPE 0000100 /* vert parity err */\r | |
149 | #define ER_CRC 0000200 /* CRC err NI */\r | |
150 | #define ER_NSG 0000400 /* non std gap err NI */\r | |
151 | #define ER_FCE 0001000 /* frame count err */\r | |
152 | #define ER_ITM 0002000 /* inv tape mark NI */\r | |
153 | #define ER_NXF 0004000 /* wlock or fnc err */\r | |
154 | #define ER_DTE 0010000 /* time err NI */\r | |
155 | #define ER_OPI 0020000 /* op incomplete */\r | |
156 | #define ER_UNS 0040000 /* drive unsafe */\r | |
157 | #define ER_DCK 0100000 /* data check NI */\r | |
158 | \r | |
159 | /* TUMR - maintenance register - offset 03 */\r | |
160 | \r | |
161 | #define MR_OF 3\r | |
162 | #define MR_RW 0177637 /* read/write */\r | |
163 | \r | |
164 | /* TUAS - attention summary - offset 4 */\r | |
165 | \r | |
166 | #define AS_OF 4\r | |
167 | #define AS_U0 0000001 /* unit 0 flag */\r | |
168 | \r | |
169 | /* TUFC - offset 5 */\r | |
170 | \r | |
171 | #define FC_OF 5\r | |
172 | \r | |
173 | /* TUDT - drive type - offset 6 */\r | |
174 | \r | |
175 | #define DT_OF 6\r | |
176 | #define DT_NSA 0100000 /* not sect addr */\r | |
177 | #define DT_TAPE 0040000 /* tape */\r | |
178 | #define DT_PRES 0002000 /* slave present */\r | |
179 | #define DT_TM03 0000040 /* TM03 formatter */\r | |
180 | #define DT_OFF 0000010 /* drive off */\r | |
181 | #define DT_TU16 0000011 /* TE16 */\r | |
182 | #define DT_TU45 0000012 /* TU45 */\r | |
183 | #define DT_TU77 0000014 /* TU77 */\r | |
184 | \r | |
185 | /* TUCC - check character, read only - offset 7 */\r | |
186 | \r | |
187 | #define CC_OF 7\r | |
188 | #define CC_MBZ 0177000 /* must be zero */\r | |
189 | \r | |
190 | /* TUSN - serial number - offset 8 */\r | |
191 | \r | |
192 | #define SN_OF 8\r | |
193 | \r | |
194 | /* TUTC - tape control register - offset 9 */\r | |
195 | \r | |
196 | #define TC_OF 9\r | |
197 | #define TC_V_UNIT 0 /* unit select */\r | |
198 | #define TC_M_UNIT 07\r | |
199 | #define TC_V_EVN 0000010 /* even parity */\r | |
200 | #define TC_V_FMT 4 /* format select */\r | |
201 | #define TC_M_FMT 017\r | |
202 | #define TC_STD 014 /* standard */\r | |
203 | #define TC_CDUMP 015 /* core dump */\r | |
204 | #define TC_V_DEN 8 /* density select */\r | |
205 | #define TC_M_DEN 07\r | |
206 | #define TC_800 3 /* 800 bpi */\r | |
207 | #define TC_1600 4 /* 1600 bpi */\r | |
208 | #define TC_AER 0010000 /* abort on error */\r | |
209 | #define TC_SAC 0020000 /* slave addr change */\r | |
210 | #define TC_FCS 0040000 /* frame count status */\r | |
211 | #define TC_ACC 0100000 /* accelerating NI */\r | |
212 | #define TC_RW 0013777\r | |
213 | #define TC_MBZ 0004000\r | |
214 | #define TC_RIP ((TC_800 << TC_V_DEN) | (TC_STD << TC_V_FMT))\r | |
215 | #define GET_DEN(x) (((x) >> TC_V_DEN) & TC_M_DEN)\r | |
216 | #define GET_FMT(x) (((x) >> TC_V_FMT) & TC_M_FMT)\r | |
217 | #define GET_DRV(x) (((x) >> TC_V_UNIT) & TC_M_UNIT)\r | |
218 | \r | |
219 | int32 tucs1 = 0; /* control/status 1 */\r | |
220 | int32 tufc = 0; /* frame count */\r | |
221 | int32 tufs = 0; /* formatter status */\r | |
222 | int32 tuer = 0; /* error status */\r | |
223 | int32 tucc = 0; /* check character */\r | |
224 | int32 tumr = 0; /* maint register */\r | |
225 | int32 tutc = 0; /* tape control */\r | |
226 | int32 tu_time = 10; /* record latency */\r | |
227 | int32 tu_stopioe = 1; /* stop on error */\r | |
228 | static uint8 *xbuf = NULL; /* xfer buffer */\r | |
229 | static uint16 *wbuf = NULL;\r | |
230 | static int32 fmt_test[16] = { /* fmt valid */\r | |
231 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0\r | |
232 | };\r | |
233 | static int32 dt_map[3] = { DT_TU16, DT_TU45, DT_TU77 };\r | |
234 | static char *tu_fname[CS1_N_FNC] = {\r | |
235 | "NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7",\r | |
236 | "RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17",\r | |
237 | "20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR",\r | |
238 | "WRITE", "31", "32", "33", "READF", "35", "36" "READR"\r | |
239 | };\r | |
240 | \r | |
241 | extern int32 sim_switches;\r | |
242 | extern FILE *sim_deb;\r | |
243 | \r | |
244 | t_stat tu_mbrd (int32 *data, int32 PA, int32 fmtr);\r | |
245 | t_stat tu_mbwr (int32 data, int32 PA, int32 fmtr);\r | |
246 | t_stat tu_svc (UNIT *uptr);\r | |
247 | t_stat tu_reset (DEVICE *dptr);\r | |
248 | t_stat tu_attach (UNIT *uptr, char *cptr);\r | |
249 | t_stat tu_detach (UNIT *uptr);\r | |
250 | t_stat tu_boot (int32 unitno, DEVICE *dptr);\r | |
251 | t_stat tu_set_fmtr (UNIT *uptr, int32 val, char *cptr, void *desc);\r | |
252 | t_stat tu_show_fmtr (FILE *st, UNIT *uptr, int32 val, void *desc);\r | |
253 | t_stat tu_go (int32 drv);\r | |
254 | int32 tu_abort (void);\r | |
255 | void tu_set_er (int32 flg);\r | |
256 | void tu_clr_as (int32 mask);\r | |
257 | void tu_update_fs (int32 flg, int32 drv);\r | |
258 | t_stat tu_map_err (int32 drv, t_stat st, t_bool qdt);\r | |
259 | \r | |
260 | /* TU data structures\r | |
261 | \r | |
262 | tu_dev TU device descriptor\r | |
263 | tu_unit TU unit list\r | |
264 | tu_reg TU register list\r | |
265 | tu_mod TU modifier list\r | |
266 | */\r | |
267 | \r | |
268 | DIB tu_dib = { MBA_TU, 0, &tu_mbrd, &tu_mbwr,0, 0, 0, { &tu_abort } };\r | |
269 | \r | |
270 | UNIT tu_unit[] = {\r | |
271 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },\r | |
272 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },\r | |
273 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },\r | |
274 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },\r | |
275 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },\r | |
276 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },\r | |
277 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },\r | |
278 | { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }\r | |
279 | };\r | |
280 | \r | |
281 | REG tu_reg[] = {\r | |
282 | { GRDATA (CS1, tucs1, DEV_RDX, 6, 0) },\r | |
283 | { GRDATA (FC, tufc, DEV_RDX, 16, 0) },\r | |
284 | { GRDATA (FS, tufs, DEV_RDX, 16, 0) },\r | |
285 | { GRDATA (ER, tuer, DEV_RDX, 16, 0) },\r | |
286 | { GRDATA (CC, tucc, DEV_RDX, 16, 0) },\r | |
287 | { GRDATA (MR, tumr, DEV_RDX, 16, 0) },\r | |
288 | { GRDATA (TC, tutc, DEV_RDX, 16, 0) },\r | |
289 | { FLDATA (STOP_IOE, tu_stopioe, 0) },\r | |
290 | { DRDATA (TIME, tu_time, 24), PV_LEFT },\r | |
291 | { URDATA (UST, tu_unit[0].USTAT, DEV_RDX, 17, 0, TU_NUMDR, 0) },\r | |
292 | { URDATA (POS, tu_unit[0].pos, 10, T_ADDR_W, 0,\r | |
293 | TU_NUMDR, PV_LEFT | REG_RO) },\r | |
294 | { NULL }\r | |
295 | };\r | |
296 | \r | |
297 | MTAB tu_mod[] = {\r | |
298 | { MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num },\r | |
299 | #if defined (VM_PDP11)\r | |
300 | { MTAB_XTD|MTAB_VDV, 0, "FORMATTER", "TM02",\r | |
301 | &tu_set_fmtr, &tu_show_fmtr },\r | |
302 | { MTAB_XTD|MTAB_VDV, 1, NULL, "TM03",\r | |
303 | &tu_set_fmtr, NULL },\r | |
304 | #else\r | |
305 | { MTAB_XTD|MTAB_VDV, 0, "FORMATTER", NULL,\r | |
306 | NULL, &tu_show_fmtr },\r | |
307 | #endif\r | |
308 | { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },\r | |
309 | { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },\r | |
310 | { UNIT_TYPE, UNIT_TE16, "TE16", "TE16", NULL },\r | |
311 | { UNIT_TYPE, UNIT_TU45, "TU45", "TU45", NULL },\r | |
312 | { UNIT_TYPE, UNIT_TU77, "TU77", "TU77", NULL },\r | |
313 | { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",\r | |
314 | &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },\r | |
315 | { MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",\r | |
316 | &sim_tape_set_capac, &sim_tape_show_capac, NULL },\r | |
317 | { 0 }\r | |
318 | };\r | |
319 | \r | |
320 | DEVICE tu_dev = {\r | |
321 | "TU", tu_unit, tu_reg, tu_mod,\r | |
322 | TU_NUMDR, 10, T_ADDR_W, 1, DEV_RDX, 8,\r | |
323 | NULL, NULL, &tu_reset,\r | |
324 | &tu_boot, &tu_attach, &tu_detach,\r | |
325 | &tu_dib, DEV_MBUS|DEV_UBUS|DEV_QBUS|DEV_DEBUG|DEV_DISABLE|DEV_DIS_INIT|DEV_TM03\r | |
326 | };\r | |
327 | \r | |
328 | /* Massbus register read */\r | |
329 | \r | |
330 | t_stat tu_mbrd (int32 *data, int32 ofs, int32 fmtr)\r | |
331 | {\r | |
332 | int32 drv;\r | |
333 | \r | |
334 | if (fmtr != 0) { /* only one fmtr */\r | |
335 | *data = 0;\r | |
336 | return MBE_NXD;\r | |
337 | }\r | |
338 | drv = GET_DRV (tutc); /* get current unit */\r | |
339 | tu_update_fs (0, drv); /* update status */\r | |
340 | \r | |
341 | switch (ofs) { /* decode offset */\r | |
342 | \r | |
343 | case CS1_OF: /* MTCS1 */\r | |
344 | *data = (tucs1 & CS1_RW) | CS1_DVA; /* DVA always set */\r | |
345 | break;\r | |
346 | \r | |
347 | case FC_OF: /* MTFC */\r | |
348 | *data = tufc;\r | |
349 | break;\r | |
350 | \r | |
351 | case FS_OF: /* MTFS */\r | |
352 | *data = tufs & 0177777; /* mask off rewind */\r | |
353 | break;\r | |
354 | \r | |
355 | case ER_OF: /* MTER */\r | |
356 | *data = tuer;\r | |
357 | break;\r | |
358 | \r | |
359 | case AS_OF: /* MTAS */\r | |
360 | *data = (tufs & FS_ATA)? AS_U0: 0;\r | |
361 | break;\r | |
362 | \r | |
363 | case CC_OF: /* MTCC */\r | |
364 | *data = tucc = tucc & ~CC_MBZ;\r | |
365 | break;\r | |
366 | \r | |
367 | case MR_OF: /* MTMR */\r | |
368 | *data = tumr;\r | |
369 | break;\r | |
370 | \r | |
371 | case DT_OF: /* MTDT */\r | |
372 | *data = DT_NSA | DT_TAPE | /* fmtr flags */\r | |
373 | ((tu_dev.flags & DEV_TM03)? DT_TM03: 0);\r | |
374 | if (tu_unit[drv].flags & UNIT_DIS) *data |= DT_OFF;\r | |
375 | else *data |= DT_PRES | dt_map[GET_TYPE (tu_unit[drv].flags)];\r | |
376 | break;\r | |
377 | \r | |
378 | case SN_OF: /* MTSN */\r | |
379 | *data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1);\r | |
380 | break;\r | |
381 | \r | |
382 | case TC_OF: /* MTTC */\r | |
383 | *data = tutc = tutc & ~TC_MBZ;\r | |
384 | break;\r | |
385 | \r | |
386 | default: /* all others */\r | |
387 | return MBE_NXR;\r | |
388 | }\r | |
389 | \r | |
390 | return SCPE_OK;\r | |
391 | }\r | |
392 | \r | |
393 | /* Massbus register write */\r | |
394 | \r | |
395 | t_stat tu_mbwr (int32 data, int32 ofs, int32 fmtr)\r | |
396 | {\r | |
397 | int32 drv;\r | |
398 | \r | |
399 | if (fmtr != 0) return MBE_NXD; /* only one fmtr */\r | |
400 | drv = GET_DRV (tutc); /* get current unit */\r | |
401 | \r | |
402 | switch (ofs) { /* decode PA<4:1> */\r | |
403 | \r | |
404 | case CS1_OF: /* MTCS1 */\r | |
405 | if (tucs1 & CS1_GO) tu_set_er (ER_RMR);\r | |
406 | else {\r | |
407 | tucs1 = data & CS1_RW;\r | |
408 | if (tucs1 & CS1_GO) return tu_go (drv);\r | |
409 | }\r | |
410 | break; \r | |
411 | \r | |
412 | case FC_OF: /* MTFC */\r | |
413 | if (tucs1 & CS1_GO) tu_set_er (ER_RMR);\r | |
414 | else {\r | |
415 | tufc = data;\r | |
416 | tutc = tutc | TC_FCS; /* set fc flag */\r | |
417 | }\r | |
418 | break;\r | |
419 | \r | |
420 | case AS_OF: /* MTAS */\r | |
421 | tu_clr_as (data);\r | |
422 | break;\r | |
423 | \r | |
424 | case MR_OF: /* MTMR */\r | |
425 | tumr = (tumr & ~MR_RW) | (data & MR_RW);\r | |
426 | break;\r | |
427 | \r | |
428 | case TC_OF: /* MTTC */\r | |
429 | if (tucs1 & CS1_GO) tu_set_er (ER_RMR);\r | |
430 | else {\r | |
431 | tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC;\r | |
432 | drv = GET_DRV (tutc);\r | |
433 | }\r | |
434 | break;\r | |
435 | \r | |
436 | case FS_OF: /* MTFS */\r | |
437 | case ER_OF: /* MTER */\r | |
438 | case CC_OF: /* MTCC */\r | |
439 | case DT_OF: /* MTDT */\r | |
440 | case SN_OF: /* MTSN */\r | |
441 | if (tucs1 & CS1_GO) tu_set_er (ER_RMR);\r | |
442 | break; /* read only */\r | |
443 | \r | |
444 | default: /* all others */\r | |
445 | return MBE_NXR;\r | |
446 | } /* end switch */\r | |
447 | \r | |
448 | tu_update_fs (0, drv);\r | |
449 | return SCPE_OK;\r | |
450 | }\r | |
451 | \r | |
452 | /* New magtape command */\r | |
453 | \r | |
454 | t_stat tu_go (int32 drv)\r | |
455 | {\r | |
456 | int32 fnc, den;\r | |
457 | UNIT *uptr;\r | |
458 | \r | |
459 | fnc = GET_FNC (tucs1); /* get function */\r | |
460 | den = GET_DEN (tutc); /* get density */\r | |
461 | uptr = tu_dev.units + drv; /* get unit */\r | |
462 | if (DEBUG_PRS (tu_dev)) fprintf (sim_deb,\r | |
463 | ">>TU%d STRT: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n",\r | |
464 | drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos);\r | |
465 | \r | |
466 | if ((fnc != FNC_FCLR) && /* not clear & err */\r | |
467 | ((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */\r | |
468 | tu_set_er (ER_ILF); /* set err */\r | |
469 | tucs1 = tucs1 & ~CS1_GO; /* clear go */\r | |
470 | tu_update_fs (FS_ATA, drv); /* set attn */\r | |
471 | return MBE_GOE;\r | |
472 | }\r | |
473 | tu_clr_as (AS_U0); /* clear ATA */\r | |
474 | tutc = tutc & ~TC_SAC; /* clear addr change */\r | |
475 | \r | |
476 | switch (fnc) { /* case on function */\r | |
477 | \r | |
478 | case FNC_FCLR: /* drive clear */\r | |
479 | tuer = 0; /* clear errors */\r | |
480 | tutc = tutc & ~TC_FCS; /* clear fc status */\r | |
481 | tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_ERR);\r | |
482 | sim_cancel (uptr); /* reset drive */\r | |
483 | uptr->USTAT = 0;\r | |
484 | case FNC_NOP:\r | |
485 | tucs1 = tucs1 & ~CS1_GO; /* no operation */\r | |
486 | return SCPE_OK;\r | |
487 | \r | |
488 | case FNC_RIP: /* read-in preset */\r | |
489 | tutc = TC_RIP; /* set tutc */\r | |
490 | sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */\r | |
491 | tu_unit[0].USTAT = 0;\r | |
492 | tucs1 = tucs1 & ~CS1_GO;\r | |
493 | tufs = tufs & ~FS_TMK;\r | |
494 | return SCPE_OK;\r | |
495 | \r | |
496 | case FNC_UNLOAD: /* unload */\r | |
497 | if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */\r | |
498 | tu_set_er (ER_UNS);\r | |
499 | break;\r | |
500 | }\r | |
501 | detach_unit (uptr);\r | |
502 | uptr->USTAT = FS_REW;\r | |
503 | sim_activate (uptr, tu_time);\r | |
504 | tucs1 = tucs1 & ~CS1_GO;\r | |
505 | tufs = tufs & ~FS_TMK;\r | |
506 | return SCPE_OK; \r | |
507 | \r | |
508 | case FNC_REWIND:\r | |
509 | if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */\r | |
510 | tu_set_er (ER_UNS);\r | |
511 | break;\r | |
512 | }\r | |
513 | uptr->USTAT = FS_PIP | FS_REW;\r | |
514 | sim_activate (uptr, tu_time);\r | |
515 | tucs1 = tucs1 & ~CS1_GO;\r | |
516 | tufs = tufs & ~FS_TMK;\r | |
517 | return SCPE_OK;\r | |
518 | \r | |
519 | case FNC_SPACEF:\r | |
520 | if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */\r | |
521 | tu_set_er (ER_UNS);\r | |
522 | break;\r | |
523 | }\r | |
524 | if (sim_tape_eot (uptr) || ((tutc & TC_FCS) == 0)) {\r | |
525 | tu_set_er (ER_NXF);\r | |
526 | break;\r | |
527 | }\r | |
528 | uptr->USTAT = FS_PIP;\r | |
529 | goto GO_XFER;\r | |
530 | \r | |
531 | case FNC_SPACER:\r | |
532 | if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */\r | |
533 | tu_set_er (ER_UNS);\r | |
534 | break;\r | |
535 | }\r | |
536 | if (sim_tape_bot (uptr) || ((tutc & TC_FCS) == 0)) {\r | |
537 | tu_set_er (ER_NXF);\r | |
538 | break;\r | |
539 | }\r | |
540 | uptr->USTAT = FS_PIP;\r | |
541 | goto GO_XFER;\r | |
542 | \r | |
543 | case FNC_WCHKR: /* wchk = read */\r | |
544 | case FNC_READR: /* read rev */\r | |
545 | if (tufs & FS_BOT) { /* beginning of tape? */\r | |
546 | tu_set_er (ER_NXF);\r | |
547 | break;\r | |
548 | }\r | |
549 | goto DATA_XFER;\r | |
550 | \r | |
551 | case FNC_WRITE: /* write */\r | |
552 | if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */\r | |
553 | ((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */\r | |
554 | tu_set_er (ER_NXF);\r | |
555 | break;\r | |
556 | }\r | |
557 | case FNC_WREOF: /* write tape mark */\r | |
558 | case FNC_ERASE: /* erase */\r | |
559 | if (sim_tape_wrp (uptr)) { /* write locked? */\r | |
560 | tu_set_er (ER_NXF);\r | |
561 | break;\r | |
562 | }\r | |
563 | case FNC_WCHKF: /* wchk = read */\r | |
564 | case FNC_READF: /* read */\r | |
565 | DATA_XFER:\r | |
566 | if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */\r | |
567 | tu_set_er (ER_UNS);\r | |
568 | break;\r | |
569 | }\r | |
570 | if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */\r | |
571 | tu_set_er (ER_FER);\r | |
572 | break;\r | |
573 | }\r | |
574 | if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */\r | |
575 | uptr->USTAT = 0;\r | |
576 | GO_XFER:\r | |
577 | tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */\r | |
578 | sim_activate (uptr, tu_time);\r | |
579 | return SCPE_OK;\r | |
580 | \r | |
581 | default: /* all others */\r | |
582 | tu_set_er (ER_ILF); /* not supported */\r | |
583 | break;\r | |
584 | } /* end case function */\r | |
585 | \r | |
586 | tucs1 = tucs1 & ~CS1_GO; /* clear go */\r | |
587 | tu_update_fs (FS_ATA, drv); /* set attn */\r | |
588 | return MBE_GOE;\r | |
589 | }\r | |
590 | \r | |
591 | /* Abort transfer */\r | |
592 | \r | |
593 | t_stat tu_abort (void)\r | |
594 | {\r | |
595 | return tu_reset (&tu_dev);\r | |
596 | }\r | |
597 | \r | |
598 | /* Unit service\r | |
599 | \r | |
600 | Complete movement or data transfer command\r | |
601 | Unit must exist - can't remove an active unit\r | |
602 | Unit must be attached - detach cancels in progress operations\r | |
603 | */\r | |
604 | \r | |
605 | t_stat tu_svc (UNIT *uptr)\r | |
606 | {\r | |
607 | int32 fnc, fmt, j, xbc;\r | |
608 | int32 fc, drv;\r | |
609 | t_mtrlnt i, tbc;\r | |
610 | t_stat st, r = SCPE_OK;\r | |
611 | \r | |
612 | drv = (int32) (uptr - tu_dev.units); /* get drive # */\r | |
613 | if (uptr->USTAT & FS_REW) { /* rewind or unload? */\r | |
614 | sim_tape_rewind (uptr); /* rewind tape */\r | |
615 | uptr->USTAT = 0; /* clear status */\r | |
616 | tu_update_fs (FS_ATA | FS_SSC, drv);\r | |
617 | return SCPE_OK;\r | |
618 | }\r | |
619 | \r | |
620 | fnc = GET_FNC (tucs1); /* get command */\r | |
621 | fmt = GET_FMT (tutc); /* get format */\r | |
622 | fc = 0200000 - tufc; /* get frame count */\r | |
623 | uptr->USTAT = 0; /* clear status */\r | |
624 | \r | |
625 | if ((uptr->flags & UNIT_ATT) == 0) {\r | |
626 | tu_set_er (ER_UNS); /* set formatter error */\r | |
627 | if (fnc >= FNC_XFER) mba_set_don (tu_dib.ba);\r | |
628 | tu_update_fs (FS_ATA, drv);\r | |
629 | return (tu_stopioe? SCPE_UNATT: SCPE_OK);\r | |
630 | }\r | |
631 | switch (fnc) { /* case on function */\r | |
632 | \r | |
633 | /* Non-data transfer commands - set ATA when done */\r | |
634 | \r | |
635 | case FNC_SPACEF: /* space forward */\r | |
636 | do {\r | |
637 | tufc = (tufc + 1) & 0177777; /* incr fc */\r | |
638 | if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */\r | |
639 | r = tu_map_err (drv, st, 0); /* map error */\r | |
640 | break;\r | |
641 | }\r | |
642 | } while ((tufc != 0) && !sim_tape_eot (uptr));\r | |
643 | if (tufc) tu_set_er (ER_FCE);\r | |
644 | else tutc = tutc & ~TC_FCS;\r | |
645 | break;\r | |
646 | \r | |
647 | case FNC_SPACER: /* space reverse */\r | |
648 | do {\r | |
649 | tufc = (tufc + 1) & 0177777; /* incr wc */\r | |
650 | if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */\r | |
651 | r = tu_map_err (drv, st, 0); /* map error */\r | |
652 | break;\r | |
653 | }\r | |
654 | } while (tufc != 0);\r | |
655 | if (tufc) tu_set_er (ER_FCE);\r | |
656 | else tutc = tutc & ~TC_FCS;\r | |
657 | break;\r | |
658 | \r | |
659 | case FNC_WREOF: /* write end of file */\r | |
660 | if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */\r | |
661 | r = tu_map_err (drv, st, 0); /* map error */\r | |
662 | break;\r | |
663 | \r | |
664 | case FNC_ERASE:\r | |
665 | if (sim_tape_wrp (uptr)) /* write protected? */\r | |
666 | r = tu_map_err (drv, MTSE_WRP, 0); /* map error */\r | |
667 | break;\r | |
668 | \r | |
669 | /* Unit service - data transfer commands */\r | |
670 | \r | |
671 | case FNC_READF: /* read */\r | |
672 | case FNC_WCHKF: /* wcheck = read */\r | |
673 | tufc = 0; /* clear frame count */\r | |
674 | if ((uptr->UDENS == TC_1600) && sim_tape_bot (uptr))\r | |
675 | tufs = tufs | FS_ID; /* PE BOT? ID burst */\r | |
676 | if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */\r | |
677 | if (st == MTSE_TMK) tu_set_er (ER_FCE); /* tmk also sets FCE */\r | |
678 | r = tu_map_err (drv, st, 1); /* map error */\r | |
679 | break; /* done */\r | |
680 | }\r | |
681 | for (i = tbc; i < tbc + 4; i++) xbuf[i] = 0; /* pad with 0's */\r | |
682 | if (fmt == TC_CDUMP) { /* core dump? */\r | |
683 | for (i = j = 0; i < tbc; i = i + 4) {\r | |
684 | wbuf[j++] = ((uint16) xbuf[i] & 0xF) |\r | |
685 | (((uint16) (xbuf[i + 1] & 0xF)) << 4) |\r | |
686 | (((uint16) (xbuf[i + 2] & 0xF)) << 8) |\r | |
687 | (((uint16) (xbuf[i + 3] & 0xf)) << 12);\r | |
688 | }\r | |
689 | xbc = (tbc + 1) >> 1;\r | |
690 | }\r | |
691 | else { /* standard */\r | |
692 | for (i = j = 0; i < tbc; i = i + 2) {\r | |
693 | wbuf[j++] = ((uint16) xbuf[i]) |\r | |
694 | (((uint16) xbuf[i + 1]) << 8);\r | |
695 | }\r | |
696 | xbc = tbc;\r | |
697 | }\r | |
698 | if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */\r | |
699 | tu_set_er (ER_FCE); /* set FCE, ATN */\r | |
700 | if (fnc == FNC_WCHKF) mba_chbufW (tu_dib.ba, xbc, wbuf);\r | |
701 | else mba_wrbufW (tu_dib.ba, xbc, wbuf);\r | |
702 | tufc = tbc & 0177777;\r | |
703 | break;\r | |
704 | \r | |
705 | case FNC_WRITE: /* write */\r | |
706 | xbc = mba_rdbufW (tu_dib.ba, fc, wbuf); /* read buffer */\r | |
707 | if (xbc == 0) break; /* anything?? */\r | |
708 | if (fmt == TC_CDUMP) { /* core dump? */\r | |
709 | for (i = j = 0; j < xbc; j = j + 1) {\r | |
710 | xbuf[i++] = wbuf[j] & 0xF;\r | |
711 | xbuf[i++] = (wbuf[j] >> 4) & 0xF;\r | |
712 | xbuf[i++] = (wbuf[j] >> 8) & 0xF;\r | |
713 | xbuf[i++] = (wbuf[j] >> 12) & 0xF;\r | |
714 | }\r | |
715 | tbc = (xbc + 1) >> 1;\r | |
716 | }\r | |
717 | else { /* standard */\r | |
718 | for (i = j = 0; j < xbc; j = j + 1) {\r | |
719 | xbuf[i++] = wbuf[j] & 0377;\r | |
720 | xbuf[i++] = (wbuf[j] >> 8) & 0377;\r | |
721 | }\r | |
722 | tbc = xbc;\r | |
723 | }\r | |
724 | if (st = sim_tape_wrrecf (uptr, xbuf, tbc)) /* write rec, err? */\r | |
725 | r = tu_map_err (drv, st, 1); /* map error */\r | |
726 | else {\r | |
727 | tufc = (tufc + tbc) & 0177777;\r | |
728 | if (tufc == 0) tutc = tutc & ~TC_FCS;\r | |
729 | }\r | |
730 | break;\r | |
731 | \r | |
732 | case FNC_READR: /* read reverse */\r | |
733 | case FNC_WCHKR: /* wcheck = read */\r | |
734 | tufc = 0; /* clear frame count */\r | |
735 | if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */\r | |
736 | if (st == MTSE_TMK) tu_set_er (ER_FCE); /* tmk also sets FCE */\r | |
737 | r = tu_map_err (drv, st, 1); /* map error */\r | |
738 | break; /* done */\r | |
739 | }\r | |
740 | for (i = 0; i < 4; i++) xbuf[i] = 0; /* pad with 0's */\r | |
741 | if (fmt == TC_CDUMP) { /* core dump? */\r | |
742 | for (i = tbc + 3, j = 0; i > 3; i = i - 4) {\r | |
743 | wbuf[j++] = ((uint16) xbuf[i] & 0xF) |\r | |
744 | (((uint16) (xbuf[i - 1] & 0xF)) << 4) |\r | |
745 | (((uint16) (xbuf[i - 2] & 0xF)) << 8) |\r | |
746 | (((uint16) (xbuf[i - 3] & 0xf)) << 12);\r | |
747 | }\r | |
748 | xbc = (tbc + 1) >> 1;\r | |
749 | }\r | |
750 | else { /* standard */\r | |
751 | for (i = tbc + 3, j = 0; i > 3; i = i - 2) {\r | |
752 | wbuf[j++] = ((uint16) xbuf[i]) |\r | |
753 | (((uint16) xbuf[i - 1]) << 8);\r | |
754 | }\r | |
755 | xbc = tbc;\r | |
756 | }\r | |
757 | if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */\r | |
758 | tu_set_er (ER_FCE); /* set FCE, ATN */\r | |
759 | if (fnc == FNC_WCHKR) mba_chbufW (tu_dib.ba, xbc, wbuf);\r | |
760 | else mba_wrbufW (tu_dib.ba, xbc, wbuf);\r | |
761 | tufc = tbc & 0177777;\r | |
762 | break;\r | |
763 | } /* end case */\r | |
764 | \r | |
765 | tucs1 = tucs1 & ~CS1_GO; /* clear go */\r | |
766 | if (fnc >= FNC_XFER) { /* data xfer? */\r | |
767 | mba_set_don (tu_dib.ba); /* set done */\r | |
768 | tu_update_fs (0, drv); /* update fs */\r | |
769 | }\r | |
770 | else tu_update_fs (FS_ATA, drv); /* no, set attn */\r | |
771 | if (DEBUG_PRS (tu_dev)) fprintf (sim_deb,\r | |
772 | ">>TU%d DONE: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n",\r | |
773 | drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos);\r | |
774 | return SCPE_OK;\r | |
775 | }\r | |
776 | \r | |
777 | /* Set formatter error */\r | |
778 | \r | |
779 | void tu_set_er (int32 flg)\r | |
780 | {\r | |
781 | tuer = tuer | flg;\r | |
782 | tufs = tufs | FS_ATA;\r | |
783 | mba_upd_ata (tu_dib.ba, 1);\r | |
784 | return;\r | |
785 | }\r | |
786 | \r | |
787 | /* Clear attention */\r | |
788 | \r | |
789 | void tu_clr_as (int32 mask)\r | |
790 | {\r | |
791 | if (mask & AS_U0) tufs = tufs & ~FS_ATA;\r | |
792 | mba_upd_ata (tu_dib.ba, tufs & FS_ATA);\r | |
793 | return;\r | |
794 | }\r | |
795 | \r | |
796 | /* Formatter update status */\r | |
797 | \r | |
798 | void tu_update_fs (int32 flg, int32 drv)\r | |
799 | {\r | |
800 | int32 act = sim_is_active (&tu_unit[drv]);\r | |
801 | \r | |
802 | tufs = (tufs & ~FS_DYN) | FS_FPR | flg;\r | |
803 | if (tu_unit[drv].flags & UNIT_ATT) {\r | |
804 | tufs = tufs | FS_MOL | tu_unit[drv].USTAT;\r | |
805 | if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;\r | |
806 | if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL;\r | |
807 | if (!act) {\r | |
808 | if (sim_tape_bot (&tu_unit[drv]))\r | |
809 | tufs = tufs | FS_BOT;\r | |
810 | if (sim_tape_eot (&tu_unit[drv]))\r | |
811 | tufs = tufs | FS_EOT;\r | |
812 | }\r | |
813 | }\r | |
814 | if (tuer) tufs = tufs | FS_ERR;\r | |
815 | if (tufs && !act) tufs = tufs | FS_RDY;\r | |
816 | if (flg & FS_ATA) mba_upd_ata (tu_dib.ba, 1);\r | |
817 | return;\r | |
818 | }\r | |
819 | \r | |
820 | /* Map tape error status */\r | |
821 | \r | |
822 | t_stat tu_map_err (int32 drv, t_stat st, t_bool qdt)\r | |
823 | {\r | |
824 | switch (st) {\r | |
825 | \r | |
826 | case MTSE_FMT: /* illegal fmt */\r | |
827 | case MTSE_UNATT: /* not attached */\r | |
828 | tu_set_er (ER_NXF); /* can't execute */\r | |
829 | if (qdt) mba_set_exc (tu_dib.ba); /* set exception */\r | |
830 | break;\r | |
831 | \r | |
832 | case MTSE_TMK: /* end of file */\r | |
833 | tufs = tufs | FS_TMK;\r | |
834 | break;\r | |
835 | \r | |
836 | case MTSE_IOERR: /* IO error */\r | |
837 | tu_set_er (ER_VPE); /* flag error */\r | |
838 | if (qdt) mba_set_exc (tu_dib.ba); /* set exception */\r | |
839 | return (tu_stopioe? SCPE_IOERR: SCPE_OK);\r | |
840 | \r | |
841 | case MTSE_INVRL: /* invalid rec lnt */\r | |
842 | tu_set_er (ER_VPE); /* flag error */\r | |
843 | if (qdt) mba_set_exc (tu_dib.ba); /* set exception */\r | |
844 | return SCPE_MTRLNT;\r | |
845 | \r | |
846 | case MTSE_RECE: /* record in error */\r | |
847 | tu_set_er (ER_CRC); /* set crc err */\r | |
848 | if (qdt) mba_set_exc (tu_dib.ba); /* set exception */\r | |
849 | break;\r | |
850 | \r | |
851 | case MTSE_EOM: /* end of medium */\r | |
852 | tu_set_er (ER_OPI); /* incomplete */\r | |
853 | if (qdt) mba_set_exc (tu_dib.ba); /* set exception */\r | |
854 | break;\r | |
855 | \r | |
856 | case MTSE_BOT: /* reverse into BOT */\r | |
857 | return SCPE_OK;\r | |
858 | \r | |
859 | case MTSE_WRP: /* write protect */\r | |
860 | tu_set_er (ER_NXF); /* can't execute */\r | |
861 | if (qdt) mba_set_exc (tu_dib.ba); /* set exception */\r | |
862 | break;\r | |
863 | \r | |
864 | default: /* unknown error */\r | |
865 | return SCPE_IERR;\r | |
866 | }\r | |
867 | \r | |
868 | return SCPE_OK;\r | |
869 | }\r | |
870 | \r | |
871 | /* Reset routine */\r | |
872 | \r | |
873 | t_stat tu_reset (DEVICE *dptr)\r | |
874 | {\r | |
875 | int32 u;\r | |
876 | UNIT *uptr;\r | |
877 | \r | |
878 | mba_set_enbdis (MBA_TU, tu_dev.flags & DEV_DIS);\r | |
879 | tucs1 = 0;\r | |
880 | tufc = 0;\r | |
881 | tuer = 0;\r | |
882 | tufs = FS_FPR | FS_RDY;\r | |
883 | if (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */\r | |
884 | else tutc = tutc & ~TC_FCS; /* no, clr <fcs> */\r | |
885 | for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */\r | |
886 | uptr = tu_dev.units + u;\r | |
887 | sim_tape_reset (uptr); /* clear pos flag */\r | |
888 | sim_cancel (uptr); /* cancel activity */\r | |
889 | uptr->USTAT = 0;\r | |
890 | }\r | |
891 | if (xbuf == NULL) xbuf = (uint8 *) calloc (MT_MAXFR + 4, sizeof (uint8));\r | |
892 | if (xbuf == NULL) return SCPE_MEM;\r | |
893 | if (wbuf == NULL) wbuf = (uint16 *) calloc ((MT_MAXFR + 4) >> 1, sizeof (uint16));\r | |
894 | if (wbuf == NULL) return SCPE_MEM;\r | |
895 | return SCPE_OK;\r | |
896 | }\r | |
897 | \r | |
898 | /* Attach routine */\r | |
899 | \r | |
900 | t_stat tu_attach (UNIT *uptr, char *cptr)\r | |
901 | {\r | |
902 | int32 drv = uptr - tu_dev.units, flg;\r | |
903 | t_stat r;\r | |
904 | \r | |
905 | r = sim_tape_attach (uptr, cptr);\r | |
906 | if (r != SCPE_OK) return r;\r | |
907 | uptr->USTAT = 0; /* clear unit status */\r | |
908 | uptr->UDENS = UD_UNK; /* unknown density */\r | |
909 | flg = FS_ATA | FS_SSC; /* set attention */\r | |
910 | if (GET_DRV (tutc) == drv) flg = flg | FS_SAT; /* sel drv? set SAT */\r | |
911 | tu_update_fs (flg, drv); /* update status */\r | |
912 | return r;\r | |
913 | }\r | |
914 | \r | |
915 | /* Detach routine */\r | |
916 | \r | |
917 | t_stat tu_detach (UNIT* uptr)\r | |
918 | {\r | |
919 | int32 drv = uptr - tu_dev.units;\r | |
920 | \r | |
921 | if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */\r | |
922 | uptr->USTAT = 0; /* clear status flags */\r | |
923 | tu_update_fs (FS_ATA | FS_SSC, drv); /* update status */\r | |
924 | return sim_tape_detach (uptr);\r | |
925 | }\r | |
926 | \r | |
927 | /* Set/show formatter type */\r | |
928 | \r | |
929 | t_stat tu_set_fmtr (UNIT *uptr, int32 val, char *cptr, void *desc)\r | |
930 | {\r | |
931 | DEVICE *dptr = find_dev_from_unit (uptr);\r | |
932 | \r | |
933 | if (cptr != NULL) return SCPE_ARG;\r | |
934 | if (dptr == NULL) return SCPE_IERR;\r | |
935 | if (val) dptr->flags = dptr->flags | DEV_TM03;\r | |
936 | else dptr->flags = dptr->flags & ~DEV_TM03;\r | |
937 | return SCPE_OK;\r | |
938 | }\r | |
939 | \r | |
940 | t_stat tu_show_fmtr (FILE *st, UNIT *uptr, int32 val, void *desc)\r | |
941 | {\r | |
942 | DEVICE *dptr = find_dev_from_unit (uptr);\r | |
943 | \r | |
944 | if (dptr == NULL) return SCPE_IERR;\r | |
945 | fprintf (st, "TM0%d", (dptr->flags & DEV_TM03? 3: 2));\r | |
946 | return SCPE_OK;\r | |
947 | }\r | |
948 | \r | |
949 | /* Device bootstrap */\r | |
950 | \r | |
951 | #if defined (PDP11)\r | |
952 | \r | |
953 | #elif defined (VM_PDP11)\r | |
954 | \r | |
955 | #define BOOT_START 016000 /* start */\r | |
956 | #define BOOT_ENTRY (BOOT_START + 002) /* entry */\r | |
957 | #define BOOT_UNIT (BOOT_START + 010) /* unit number */\r | |
958 | #define BOOT_CSR (BOOT_START + 014) /* CSR */\r | |
959 | #define BOOT_LEN (sizeof (boot_rom) / sizeof (uint16))\r | |
960 | \r | |
961 | static const uint16 boot_rom[] = {\r | |
962 | 0046515, /* "MM" */\r | |
963 | 0012706, BOOT_START, /* mov #boot_start, sp */\r | |
964 | 0012700, 0000000, /* mov #unit, r0 */\r | |
965 | 0012701, 0172440, /* mov #TUCS1, r1 */\r | |
966 | 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */\r | |
967 | 0012711, 0000021, /* mov #RIP+GO, (r1) ; rip */\r | |
968 | 0010004, /* mov r0, r4 */\r | |
969 | 0052704, 0002300, /* bis #2300, r4 ; set den */\r | |
970 | 0010461, 0000032, /* mov r4, 32(r1) ; set unit */\r | |
971 | 0012761, 0177777, 0000006, /* mov #-1, 6(r1) ; set fc */\r | |
972 | 0012711, 0000031, /* mov #SPCF+GO, (r1) ; skip rec */\r | |
973 | 0105761, 0000012, /* tstb 12 (r1) ; fmtr rdy? */\r | |
974 | 0100375, /* bpl .-4 */\r | |
975 | 0012761, 0177000, 0000002, /* mov #-1000, 2(r1) ; set wc */\r | |
976 | 0005061, 0000004, /* clr 4(r1) ; clr ba */\r | |
977 | 0005061, 0000006, /* clr 6(r1) ; clr fc */\r | |
978 | 0012711, 0000071, /* mov #READ+GO, (r1) ; read */\r | |
979 | 0105711, /* tstb (r1) ; wait */\r | |
980 | 0100376, /* bpl .-2 */\r | |
981 | 0005002, /* clr R2 */\r | |
982 | 0005003, /* clr R3 */\r | |
983 | 0012704, BOOT_START+020, /* mov #start+020, r4 */\r | |
984 | 0005005, /* clr R5 */\r | |
985 | 0105011, /* clrb (r1) */\r | |
986 | 0005007 /* clr PC */\r | |
987 | };\r | |
988 | \r | |
989 | t_stat tu_boot (int32 unitno, DEVICE *dptr)\r | |
990 | {\r | |
991 | int32 i;\r | |
992 | extern int32 saved_PC;\r | |
993 | extern uint16 *M;\r | |
994 | \r | |
995 | for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i];\r | |
996 | M[BOOT_UNIT >> 1] = unitno & (TU_NUMDR - 1);\r | |
997 | M[BOOT_CSR >> 1] = mba_get_csr (tu_dib.ba) & DMASK;\r | |
998 | saved_PC = BOOT_ENTRY;\r | |
999 | return SCPE_OK;\r | |
1000 | }\r | |
1001 | \r | |
1002 | #else\r | |
1003 | \r | |
1004 | t_stat tu_boot (int32 unitno, DEVICE *dptr)\r | |
1005 | {\r | |
1006 | return SCPE_NOFNC;\r | |
1007 | }\r | |
1008 | \r | |
1009 | #endif\r |