blob: 991584379705d5a4e9eb3045e27c07bed22ea790 [file] [log] [blame] [raw]
Bob Supnik59aa4a72008-06-24 14:21:00 -07001/* pdp11_rc.c: RC11/RS64 fixed head disk simulator
2
Mark Pizzolato4e5f9102013-09-04 19:50:47 -07003 Copyright (c) 2007-2013, John A. Dundas III
Bob Supnik59aa4a72008-06-24 14:21:00 -07004
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:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
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.
21
22 Except as contained in this notice, the name of the author 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 the author.
25
26 rc RC11/RS64 fixed head disk
27
Mark Pizzolato4e5f9102013-09-04 19:50:47 -070028 03-Dec-13 RMS Added explicit void * cast
Bob Supnik59aa4a72008-06-24 14:21:00 -070029 28-Dec-07 JAD Correct extraction of unit number from da in rc_svc.
30 Clear _all_ error bits when a new operation starts.
31 Passes all diagnostics in all configurations.
32 25-Dec-07 JAD Compute the CRC-16 of the last sector read via
33 a READ or WCHK.
34 20-Dec-07 JAD Correctly simulate rotation over the selected
35 track for RCLA. Also update the register
36 correctly during I/O operations.
37 Insure function activation time is non-zero.
38 Handle unit number wrap correctly.
39 19-Dec-07 JAD Iterate over a full sector regardless of the
40 actual word count so that RCDA ends correctly.
41 Honor the read-only vs. read-write status of the
42 attached file.
43 16-Dec-07 JAD The RCDA must be checked for validity when it is
44 written to, not just when GO is received.
45 15-Dec-07 JAD Better handling of disk address errors and the RCLA
46 register.
47 Add more registers to the visible device state.
48 07-Jan-07 JAD Initial creation and testing. Adapted from pdp11_rf.c.
49
50 The RS64 is a head-per-track disk. To minimize overhead, the entire RC11
51 is buffered in memory. Up to 4 RS64 "platters" may be controlled by one
52 RC11 for a total of 262,144 words (65536kW/platter). [Later in time the
53 RK611 was assigned the same CSR address.]
54
55 Diagnostic routines:
56 ZRCAB0.BIC - passes w/1-4 platters
57 ZRCBB0.BIC - passes w/1-4 platters
58 ZRCCB0.BIC - passes w/1-4 platters
59 Note that the diagnostics require R/W disks (i.e., will destroy any
60 existing data).
61
62 For regression, must pass all three diagnostics configured for 1-4
63 platters for a total of 12 tests.
64
65 Information necessary to create this simulation was gathered from the
66 PDP11 Peripherals Handbook, 1973-74 edition.
67
68 One timing parameter is provided:
69
70 rc_time Minimum I/O operation time, must be non-zero
71*/
72
73#if !defined (VM_PDP11)
74#error "RC11 is not supported!"
75#endif
76#include "pdp11_defs.h"
77#include <math.h>
78
79#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
80#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
81#define UNIT_M_PLAT 03
82#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
83#define UNIT_AUTO (1 << UNIT_V_AUTO)
84#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
85
86/* Constants */
87
88#define RC_NUMWD (32*64) /* words/track */
89#define RC_NUMTR 32 /* tracks/disk */
90#define RC_DKSIZE (RC_NUMTR * RC_NUMWD) /* words/disk */
91#define RC_NUMDK 4 /* disks/controller */
92#define RC_WMASK (RC_NUMWD - 1) /* word mask */
93
94/* Parameters in the unit descriptor */
95
96#define FUNC u4 /* function */
97
98/* Control and status register (RCCS) */
99
100#define RCCS_ERR (CSR_ERR) /* error */
101#define RCCS_DATA 0040000 /* data error */
102#define RCCS_ADDR 0020000 /* address error */
103#define RCCS_WLK 0010000 /* write lock */
104#define RCCS_NED 0004000 /* nx disk */
105#define RCCS_WCHK 0002000 /* write check */
106#define RCCS_INH 0001000 /* inhibit CA incr */
107#define RCCS_ABO 0000400 /* abort */
108#define RCCS_DONE (CSR_DONE)
109#define RCCS_IE (CSR_IE)
110#define RCCS_M_MEX 0000003 /* memory extension */
111#define RCCS_V_MEX 4
112#define RCCS_MEX (RCCS_M_MEX << RCCS_V_MEX)
113#define RCCS_MAINT 0000010 /* maint */
114#define RCCS_M_FUNC 0000003 /* function */
115#define RFNC_LAH 0
116#define RFNC_WRITE 1
117#define RFNC_READ 2
118#define RFNC_WCHK 3
119#define RCCS_V_FUNC 1
120#define RCCS_FUNC (RCCS_M_FUNC << RCCS_V_FUNC)
121#define RCCS_GO 0000001
122
123#define RCCS_ALLERR (RCCS_DATA|RCCS_ADDR|RCCS_WLK|RCCS_NED|RCCS_WCHK)
124#define RCCS_W (RCCS_INH | RCCS_ABO |RCCS_IE | RCCS_MEX | RCCS_MAINT | \
125 RCCS_FUNC | RCCS_GO)
126
127/* Disk error status register (RCER) */
128
129#define RCER_DLT 0100000 /* data late */
130#define RCER_CHK 0040000 /* block check */
131#define RCER_SYNC 0020000 /* data sync */
132#define RCER_NXM 0010000 /* nonexistant memory */
133#define RCER_TRK 0001000 /* track error */
134#define RCER_APAR 0000200 /* address parity */
135#define RCER_SADDR 0000100 /* sync address */
136#define RCER_OVFL 0000040 /* disk overflow */
137#define RCER_MIS 0000020 /* missed transfer */
138
139/* Lood Ahead Register (RCLA) */
140
141#define RCLA_BADD 0100000 /* bad address */
142
143/* extract device operation code */
144#define GET_FUNC(x) (((x) >> RCCS_V_FUNC) & RCCS_M_FUNC)
145/* extract memory extension address (bits 17,18) */
146#define GET_MEX(x) (((x) & RCCS_MEX) << (16 - RCCS_V_MEX))
147#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
148 ((double) RC_NUMWD)))
149
Bob Supnik59aa4a72008-06-24 14:21:00 -0700150extern int32 R[];
151
152static uint32 rc_la = 0; /* look-ahead */
153static uint32 rc_da = 0; /* disk address */
154static uint32 rc_er = 0; /* error status */
155static uint32 rc_cs = 0; /* command and status */
156static uint32 rc_wc = 0; /* word count */
157static uint32 rc_ca = 0; /* current address */
158static uint32 rc_maint = 0; /* maintenance */
159static uint32 rc_db = 0; /* data buffer */
160static uint32 rc_wlk = 0; /* write lock */
161static uint32 rc_time = 16; /* inter-word time: 16us */
162static uint32 rc_stopioe = 1; /* stop on error */
163
164/* forward references */
165
Bob Supnik59aa4a72008-06-24 14:21:00 -0700166static t_stat rc_rd (int32 *, int32, int32);
167static t_stat rc_wr (int32, int32, int32);
168static t_stat rc_svc (UNIT *);
169static t_stat rc_reset (DEVICE *);
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700170static t_stat rc_attach (UNIT *, CONST char *);
171static t_stat rc_set_size (UNIT *, int32, CONST char *, void *);
Bob Supnik59aa4a72008-06-24 14:21:00 -0700172static uint32 update_rccs (uint32, uint32);
Mark Pizzolatoef9d1ad2015-02-13 06:18:24 -0800173static const char *rc_description (DEVICE *dptr);
Bob Supnik59aa4a72008-06-24 14:21:00 -0700174
175/* RC11 data structures
176
177 rc_dev RC device descriptor
178 rc_unit RC unit descriptor
179 rc_reg RC register list
180*/
181
Mark Pizzolato7bed0912012-12-20 13:58:11 -0800182#define IOLN_RC 020
183
Bob Supnik59aa4a72008-06-24 14:21:00 -0700184static DIB rc_dib = {
Mark Pizzolato7bed0912012-12-20 13:58:11 -0800185 IOBA_AUTO,
Bob Supnik59aa4a72008-06-24 14:21:00 -0700186 IOLN_RC,
187 &rc_rd,
188 &rc_wr,
Timothe Litt91c7d262013-07-11 15:39:15 -0400189 1, IVCL (RC), VEC_AUTO, { NULL }, IOLN_RC,
Bob Supnik59aa4a72008-06-24 14:21:00 -0700190};
191
192static UNIT rc_unit = {
193 UDATA (&rc_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_BUFABLE +
194 UNIT_MUSTBUF + UNIT_ROABLE + UNIT_BINK, RC_DKSIZE)
195};
196
197static const REG rc_reg[] = {
198 { ORDATA (RCLA, rc_la, 16) },
199 { ORDATA (RCDA, rc_da, 16) },
200 { ORDATA (RCER, rc_er, 16) },
201 { ORDATA (RCCS, rc_cs, 16) },
202 { ORDATA (RCWC, rc_wc, 16) },
203 { ORDATA (RCCA, rc_ca, 16) },
204 { ORDATA (RCMN, rc_maint, 16) },
205 { ORDATA (RCDB, rc_db, 16) },
206 { ORDATA (RCWLK, rc_wlk, 32) },
207 { FLDATA (INT, IREQ (RC), INT_V_RC) },
208 { FLDATA (ERR, rc_cs, CSR_V_ERR) },
209 { FLDATA (DONE, rc_cs, CSR_V_DONE) },
210 { FLDATA (IE, rc_cs, CSR_V_IE) },
211 { DRDATA (TIME, rc_time, 24), REG_NZ + PV_LEFT },
212 { FLDATA (STOP_IOE, rc_stopioe, 0) },
213 { ORDATA (DEVADDR, rc_dib.ba, 32), REG_HRO },
214 { ORDATA (DEVVEC, rc_dib.vec, 16), REG_HRO },
215 { NULL }
216};
217
218static const MTAB rc_mod[] = {
Mark Pizzolato7bd01a52013-02-04 13:52:59 -0800219 { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P",
220 &rc_set_size, NULL, NULL, "Set to 1 platter device" },
221 { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P",
222 &rc_set_size, NULL, NULL, "Set to 2 platter device" },
223 { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P",
224 &rc_set_size, NULL, NULL, "Set to 3 platter device" },
225 { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P",
226 &rc_set_size, NULL, NULL, "Set to 4 platter device" },
227 { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE",
228 NULL, NULL, NULL, "set platters based on file size at ATTACH" },
229 { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0020, "ADDRESS", "ADDRESS",
230 &set_addr, &show_addr, NULL, "Bus address" },
231 { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "VECTOR", "VECTOR",
232 &set_vec, &show_vec, NULL, "Interrupt vector" },
Bob Supnik59aa4a72008-06-24 14:21:00 -0700233 { 0 }
234};
235
236DEVICE rc_dev = {
237 "RC", &rc_unit, (REG *) rc_reg, (MTAB *) rc_mod,
238 1, 8, 21, 1, 8, 16,
239 NULL, /* examine */
240 NULL, /* deposit */
241 &rc_reset, /* reset */
242 NULL, /* boot */
243 &rc_attach, /* attach */
244 NULL, /* detach */
245 &rc_dib,
Mark Pizzolato7bd01a52013-02-04 13:52:59 -0800246 DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_DEBUG, 0,
Mark Pizzolatoef9d1ad2015-02-13 06:18:24 -0800247 NULL, NULL, NULL, NULL, NULL, NULL,
Mark Pizzolato7bd01a52013-02-04 13:52:59 -0800248 &rc_description
Bob Supnik59aa4a72008-06-24 14:21:00 -0700249};
250
251/* I/O dispatch routine, I/O addresses 17777440 - 17777456 */
252
253static t_stat rc_rd (int32 *data, int32 PA, int32 access)
254{
255 uint32 t;
256
257 switch ((PA >> 1) & 07) { /* decode PA<3:1> */
258
259 case 0: /* RCLA */
260 t = rc_la & 017777;
261 if ((rc_cs & RCCS_NED) || (rc_er & RCER_OVFL))
262 t |= RCLA_BADD;
263 *data = t;
264 /* simulate sequential rotation about the current track */
265 rc_la = (rc_la & ~077) | ((rc_la + 1) & 077);
266 if (DEBUG_PRS (rc_dev))
267 fprintf (sim_deb, ">>RC rd: RCLA %06o\n", rc_la);
268 break;
269
270 case 1: /* RCDA */
271 *data = rc_da;
272 if (DEBUG_PRS (rc_dev))
273 fprintf (sim_deb, ">>RC rd: RCDA %06o, PC %06o\n",
274 rc_da, PC);
275 break;
276
277 case 2: /* RCER */
278 *data = rc_er;
279 if (DEBUG_PRS (rc_dev))
280 fprintf (sim_deb, ">>RC rd: RCER %06o\n", rc_er);
281 break;
282
283 case 3: /* RCCS */
284 *data = update_rccs (0, 0) & ~(RCCS_ABO | RCCS_GO);
285 if (DEBUG_PRS (rc_dev))
286 fprintf (sim_deb, ">>RC rd: RCCS %06o\n", *data);
287 break;
288
289 case 4: /* RCWC */
290 *data = rc_wc;
291 if (DEBUG_PRS (rc_dev))
292 fprintf (sim_deb, ">>RC rd: RCWC %06o\n", rc_wc);
293 break;
294
295 case 5: /* RCCA */
296 *data = rc_ca;
297 if (DEBUG_PRS (rc_dev))
298 fprintf (sim_deb, ">>RC rd: RCCA %06o\n", rc_ca);
299 break;
300
301 case 6: /* RCMN */
302 *data = rc_maint;
303 if (DEBUG_PRS (rc_dev))
304 fprintf (sim_deb, ">>RC rd: RCMN %06o\n", rc_maint);
305 break;
306
307 case 7: /* RCDB */
308 *data = rc_db;
309 if (DEBUG_PRS (rc_dev))
310 fprintf (sim_deb, ">>RC rd: RCDB %06o\n", rc_db);
311 break;
312
313 default:
314 return (SCPE_NXM); /* can't happen */
315 } /* end switch */
316 return (SCPE_OK);
317}
318
319static t_stat rc_wr (int32 data, int32 PA, int32 access)
320{
321 int32 t;
322
323 switch ((PA >> 1) & 07) { /* decode PA<3:1> */
324
325 case 0: /* RCLA */
326 if (DEBUG_PRS (rc_dev))
327 fprintf (sim_deb, ">>RC wr: RCLA\n");
328 break; /* read only */
329
330 case 1: /* RCDA */
331 if (access == WRITEB)
332 data = (PA & 1) ?
333 (rc_da & 0377) | (data << 8) :
334 (rc_da & ~0377) | data;
335 rc_da = data & 017777;
336 rc_cs &= ~RCCS_NED;
337 update_rccs (0, 0);
338 /* perform unit select */
339 if (((rc_da >> 11) & 03) >= UNIT_GETP(rc_unit.flags))
340 update_rccs (RCCS_NED, 0);
341 else
342 rc_la = rc_da;
343 if (DEBUG_PRS (rc_dev))
344 fprintf (sim_deb, ">>RC wr: RCDA %06o, PC %06o\n",
345 rc_da, PC);
346 break;
347
348 case 2: /* RCER */
349 if (DEBUG_PRS (rc_dev))
350 fprintf (sim_deb, ">>RC wr: RCER\n");
351 break; /* read only */
352
353 case 3: /* RCCS */
354 if (access == WRITEB)
355 data = (PA & 1) ?
356 (rc_cs & 0377) | (data << 8) :
357 (rc_cs & ~0377) | data;
358 if (data & RCCS_ABO) {
359 update_rccs (RCCS_DONE, 0);
360 sim_cancel (&rc_unit);
361 }
362 if ((data & RCCS_IE) == 0) /* int disable? */
363 CLR_INT (RC); /* clr int request */
364 else if ((rc_cs & (RCCS_DONE | RCCS_IE)) == RCCS_DONE)
365 SET_INT (RC); /* set int request */
366 rc_cs = (rc_cs & ~RCCS_W) | (data & RCCS_W); /* merge */
367 if ((rc_cs & RCCS_DONE) && (data & RCCS_GO)) { /* new function? */
368 rc_unit.FUNC = GET_FUNC (data); /* save function */
369 t = (rc_da & RC_WMASK) - GET_POS (rc_time); /* delta to new loc */
370 if (t <= 0) /* wrap around? */
371 t = t + RC_NUMWD;
372 sim_activate (&rc_unit, t * rc_time); /* schedule op */
373 /* clear error indicators for new operation */
374 rc_cs &= ~(RCCS_ALLERR | RCCS_ERR | RCCS_DONE);
375 rc_er = 0;
376 CLR_INT (RC);
377 if (DEBUG_PRS (rc_dev))
378 fprintf (sim_deb, ">>RC start: cs = %o, da = %o, ma = %o, wc = %o\n",
379 update_rccs (0, 0), rc_da,
380 GET_MEX (rc_cs) | rc_ca, rc_wc);
381 }
382 break;
383
384 case 4: /* RCWC */
385 if (access == WRITEB)
386 data = (PA & 1) ?
387 (rc_wc & 0377) | (data << 8) :
388 (rc_wc & ~0377) | data;
389 rc_wc = data & DMASK;
390 if (DEBUG_PRS (rc_dev))
391 fprintf (sim_deb, ">>RC wr: RCWC %06o, PC %06o\n",
392 rc_wc, PC);
393 break;
394
395 case 5: /* RCCA */
396 /* TBD: write byte fixup? */
397 rc_ca = data & 0177776;
398 if (DEBUG_PRS (rc_dev))
399 fprintf (sim_deb, ">>RC wr: RCCA %06o\n", rc_ca);
400 break;
401
402 case 6: /* RCMN */
403 /* TBD: write byte fixup? */
404 rc_maint = data & 0177700;
405 if (DEBUG_PRS (rc_dev))
406 fprintf (sim_deb, ">>RC wr: RCMN %06o\n", rc_maint);
407 break;
408
409 case 7: /* RCDB */
410 if (DEBUG_PRS (rc_dev))
411 fprintf (sim_deb, ">>RC wr: RCDB\n");
412 break; /* read only */
413
414 default: /* can't happen */
415 return (SCPE_NXM);
416 } /* end switch */
417 update_rccs (0, 0);
418 return (SCPE_OK);
419}
420
421/* sector (32W) CRC-16 */
422
423static uint32 sectorCRC (const uint16 *data)
424{
425 uint32 crc, i, j, d;
426
427 crc = 0;
428 for (i = 0; i < 32; i++) {
429 d = *data++;
430 /* cribbed from KG11-A */
431 for (j = 0; j < 16; j++) {
432 crc = (crc & ~01) | ((crc & 01) ^ (d & 01));
433 crc = (crc & 01) ? (crc >> 1) ^ 0120001 : crc >> 1;
434 d >>= 1;
435 }
436 }
437 return (crc);
438}
439
440/* Unit service
441
442 Note that for reads and writes, memory addresses wrap around in the
443 current field. This code assumes the entire disk is buffered.
444*/
445
446static t_stat rc_svc (UNIT *uptr)
447{
Mark Pizzolatoc71e0c32012-12-13 15:21:07 -0800448 uint32 ma, da, t, u_old, u_new, last_da = 0;
Bob Supnik59aa4a72008-06-24 14:21:00 -0700449 uint16 dat;
Mark Pizzolato4e5f9102013-09-04 19:50:47 -0700450 uint16 *fbuf = (uint16 *) uptr->filebuf;
Bob Supnik59aa4a72008-06-24 14:21:00 -0700451
452 if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
453 update_rccs (RCCS_NED | RCCS_DONE, 0); /* nx disk */
454 return (IORETURN (rc_stopioe, SCPE_UNATT));
455 }
456
457 ma = GET_MEX (rc_cs) | rc_ca; /* 18b mem addr */
458 da = rc_da * RC_NUMTR; /* sector->word offset */
459 u_old = (da >> 16) & 03; /* save starting unit# */
460 do {
461 u_new = (da >> 16) & 03;
462 if (u_new < u_old) { /* unit # overflow? */
463 update_rccs (RCCS_NED, RCER_OVFL);
464 break;
465 }
466 if (u_new >= UNIT_GETP(uptr->flags)) { /* disk overflow? */
467 update_rccs (RCCS_NED, 0);
468 break;
469 }
470 if (uptr->FUNC == RFNC_READ) { /* read? */
471 last_da = da & ~037;
472 dat = fbuf[da]; /* get disk data */
473 rc_db = dat;
474 if (Map_WriteW (ma, 2, &dat)) { /* store mem, nxm? */
475 update_rccs (0, RCER_NXM);
476 break;
477 }
478 } else if (uptr->FUNC == RFNC_WCHK) { /* write check? */
479 last_da = da & ~037;
480 rc_db = fbuf[da]; /* get disk data */
481 if (Map_ReadW (ma, 2, &dat)) { /* read mem, nxm? */
482 update_rccs (0, RCER_NXM);
483 break;
484 }
485 if (rc_db != dat) { /* miscompare? */
486 update_rccs (RCCS_WCHK, 0);
487 break;
488 }
489 } else if (uptr->FUNC == RFNC_WRITE) { /* write */
490 t = (da >> 15) & 037;
491 if (((rc_wlk >> t) & 1) ||
492 (uptr->flags & UNIT_RO)) { /* write locked? */
493 update_rccs (RCCS_WLK, 0);
494 break;
495 }
496 /* not locked */
497 if (Map_ReadW (ma, 2, &dat)) { /* read mem, nxm? */
498 update_rccs (0, RCER_NXM);
499 break;
500 }
501 fbuf[da] = dat; /* write word */
502 rc_db = dat;
503 if (da >= uptr->hwmark)
504 uptr->hwmark = da + 1;
505 } else { /* look ahead */
506 break; /* no op for now */
507 }
508 rc_wc = (rc_wc + 1) & DMASK; /* incr word count */
509 da = (da + 1) & 0777777; /* incr disk addr */
510 if ((rc_cs & RCCS_INH) == 0) /* inhibit clear? */
511 ma = (ma + 2) & UNIMASK; /* incr mem addr */
512 } while (rc_wc != 0); /* brk if wc */
513 rc_ca = ma & DMASK; /* split ma */
514 rc_cs = (rc_cs & ~RCCS_MEX) | ((ma >> (16 - RCCS_V_MEX)) & RCCS_MEX);
515 da += 31;
516 rc_da = (da >> 5) & 017777;
517 /* CRC of last 32W, if necessary */
518 if ((uptr->FUNC == RFNC_READ) || (uptr->FUNC == RFNC_WCHK))
519 rc_db = sectorCRC (&fbuf[last_da]);
520 if (uptr->FUNC != RFNC_LAH)
521 rc_la = rc_da;
522 update_rccs (RCCS_DONE, 0);
523 if (DEBUG_PRS (rc_dev))
524 fprintf (sim_deb, ">>RC done: cs = %o, da = %o, ma = %o, wc = %o\n",
525 rc_cs, rc_da, rc_ca, rc_wc);
526 return (SCPE_OK);
527}
528
529/* Update CS register */
530
531static uint32 update_rccs (uint32 newcs, uint32 newer)
532{
533 uint32 oldcs = rc_cs;
534
535 rc_er |= newer; /* update RCER */
536 rc_cs |= newcs; /* update CS */
537 if ((rc_cs & RCCS_ALLERR) || (rc_er != 0)) /* update CS<err> */
538 rc_cs |= RCCS_ERR;
539 else
540 rc_cs &= ~RCCS_ERR;
541 if ((rc_cs & RCCS_IE) && /* IE and */
542 (rc_cs & RCCS_DONE) && !(oldcs & RCCS_DONE)) /* done 0->1? */
543 SET_INT (RC);
544 return (rc_cs);
545}
546
547/* Reset routine */
548
549static t_stat rc_reset (DEVICE *dptr)
550{
551 rc_cs = RCCS_DONE;
552 rc_la = rc_da = 0;
553 rc_er = 0;
554 rc_wc = 0;
555 rc_ca = 0;
556 rc_maint = 0;
557 rc_db = 0;
558 CLR_INT (RC);
559 sim_cancel (&rc_unit);
Mark Pizzolato7bed0912012-12-20 13:58:11 -0800560 return auto_config(0, 0);
Bob Supnik59aa4a72008-06-24 14:21:00 -0700561}
562
563/* Attach routine */
564
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700565static t_stat rc_attach (UNIT *uptr, CONST char *cptr)
Bob Supnik59aa4a72008-06-24 14:21:00 -0700566{
567 uint32 sz, p;
568 static const uint32 ds_bytes = RC_DKSIZE * sizeof (int16);
569
570 if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
571 p = (sz + ds_bytes - 1) / ds_bytes;
572 if (p >= RC_NUMDK)
573 p = RC_NUMDK - 1;
574 uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT);
575 }
576 uptr->capac = UNIT_GETP (uptr->flags) * RC_DKSIZE;
577 return (attach_unit (uptr, cptr));
578}
579
580/* Change disk size */
581
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700582static t_stat rc_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
Bob Supnik59aa4a72008-06-24 14:21:00 -0700583{
584 if (val < 0)
585 return (SCPE_IERR);
586 if (uptr->flags & UNIT_ATT)
587 return (SCPE_ALATT);
588 uptr->capac = UNIT_GETP (val) * RC_DKSIZE;
589 uptr->flags = uptr->flags & ~UNIT_AUTO;
590 return (SCPE_OK);
591}
Mark Pizzolato7bd01a52013-02-04 13:52:59 -0800592
Mark Pizzolatoef9d1ad2015-02-13 06:18:24 -0800593static const char *rc_description (DEVICE *dptr)
Mark Pizzolato7bd01a52013-02-04 13:52:59 -0800594{
595 return "RC11/RS64 fixed head disk controller";
596}