Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1 | /* vax630_sysdev.c: MicroVAX II system-specific logic
|
| 2 |
|
| 3 | Copyright (c) 2009-2012, Matt Burke
|
| 4 | This module incorporates code from SimH, Copyright (c) 1998-2008, Robert M Supnik
|
| 5 |
|
| 6 | Permission is hereby granted, free of charge, to any person obtaining a
|
| 7 | copy of this software and associated documentation files (the "Software"),
|
| 8 | to deal in the Software without restriction, including without limitation
|
| 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
| 10 | and/or sell copies of the Software, and to permit persons to whom the
|
| 11 | Software is furnished to do so, subject to the following conditions:
|
| 12 |
|
| 13 | The above copyright notice and this permission notice shall be included in
|
| 14 | all copies or substantial portions of the Software.
|
| 15 |
|
| 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
| 19 | THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
| 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
| 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| 22 |
|
| 23 | Except as contained in this notice, the name(s) of the author(s) shall not be
|
| 24 | used in advertising or otherwise to promote the sale, use or other dealings
|
| 25 | in this Software without prior written authorization from the author(s).
|
| 26 |
|
| 27 | This module contains the MicroVAX II system-specific registers and devices.
|
| 28 |
|
| 29 | rom bootstrap ROM (no registers)
|
| 30 | nvr non-volatile ROM (no registers)
|
| 31 | sysd system devices
|
| 32 |
|
| 33 | 08-Nov-2012 MB First version
|
| 34 | */
|
| 35 |
|
| 36 | #include "vax_defs.h"
|
| 37 | #include <time.h>
|
| 38 |
|
| 39 | #ifdef DONT_USE_INTERNAL_ROM
|
| 40 | #if defined(VAX_620)
|
| 41 | #define BOOT_CODE_FILENAME "ka620.bin"
|
| 42 | #else
|
| 43 | #define BOOT_CODE_FILENAME "ka320.bin"
|
| 44 | #endif
|
| 45 | #else /* !DONT_USE_INTERNAL_ROM */
|
| 46 | #if defined(VAX_620)
|
| 47 | #include "vax_ka620_bin.h" /* Defines BOOT_CODE_FILENAME and BOOT_CODE_ARRAY, etc */
|
| 48 | #else
|
| 49 | #include "vax_ka630_bin.h" /* Defines BOOT_CODE_FILENAME and BOOT_CODE_ARRAY, etc */
|
| 50 | #endif
|
| 51 | #endif /* DONT_USE_INTERNAL_ROM */
|
| 52 |
|
| 53 |
|
| 54 | #define UNIT_V_NODELAY (UNIT_V_UF + 0) /* ROM access equal to RAM access */
|
| 55 | #define UNIT_NODELAY (1u << UNIT_V_NODELAY)
|
| 56 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 57 | t_stat vax630_boot (int32 flag, char *ptr);
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 58 | int32 sys_model = 0; /* MicroVAX or VAXstation */
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 59 |
|
| 60 | /* Special boot command, overrides regular boot */
|
| 61 |
|
| 62 | CTAB vax630_cmd[] = {
|
| 63 | { "BOOT", &vax630_boot, RU_BOOT,
|
Mark Pizzolato | eaae194 | 2014-02-01 07:04:44 -0800 | [diff] [blame] | 64 | "bo{ot} boot simulator\n", NULL, &run_cmd_message },
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 65 | { NULL }
|
| 66 | };
|
| 67 |
|
| 68 | /* KA630 boot/diagnostic register */
|
| 69 |
|
| 70 | #define BDR_DISP 0x0000000F /* LED display */
|
| 71 | #define BDR_V_BDC 8 /* boot/diag code */
|
| 72 | #define BDR_M_BDC 0x3
|
| 73 | #define BDR_BDC (BDR_M_BDC << BDR_V_BDC)
|
| 74 | #define BDR_V_CPUC 11 /* cpu code */
|
| 75 | #define BDR_M_CPUC 0x3
|
| 76 | #define BDR_CPUC (BDR_M_CPUC << BDR_V_CPUC)
|
| 77 | #define BDR_BRKENB 0x00004000 /* break enable */
|
| 78 | #define BDR_POK 0x00008000 /* power ok */
|
| 79 | #define BDR_RD (BDR_DISP | BDR_BDC | BDR_CPUC | BDR_BRKENB | BDR_POK)
|
| 80 | #define BDR_WR (BDR_DISP)
|
| 81 |
|
| 82 | /* BDR boot/diagnostic codes */
|
| 83 |
|
| 84 | #define BDC_NORM 0x0 /* normal startup */
|
| 85 | #define BDC_LNGI 0x1 /* language inquiry */
|
| 86 | #define BDC_TSTL 0x2 /* test loop */
|
| 87 | #define BDC_SKPM 0x3 /* skip mem test */
|
| 88 |
|
| 89 | /* BDR CPU codes */
|
| 90 |
|
| 91 | #define CPUC_ARB 0x0 /* arbiter */
|
| 92 | #define CPUC_AUX1 0x1 /* auxiliary 1 */
|
| 93 | #define CPUC_AUX2 0x2 /* auxiliary 2 */
|
| 94 | #define CPUC_AUX3 0x3 /* auxiliary 3 */
|
| 95 |
|
| 96 | /* KA630 Memory system error register */
|
| 97 |
|
| 98 | #define MSER_PE 0x00000001 /* Parity Enable */
|
| 99 | #define MSER_WWP 0x00000002 /* Write Wrong Parity */
|
| 100 | #define MSER_LEB 0x00000008 /* Lost Error Bit */
|
| 101 | #define MSER_DQPE 0x00000010 /* DMA Q22 Parity Err */
|
| 102 | #define MSER_CQPE 0x00000020 /* CPU Q22 Parity Err */
|
| 103 | #define MSER_CLPE 0x00000040 /* CPU Mem Parity Err */
|
| 104 | #define MSER_NXM 0x00000080 /* CPU NXM */
|
| 105 | #define MSER_MCD0 0x00000100 /* Mem Code 0 */
|
| 106 | #define MSER_MCD1 0x00000200 /* Mem Code 1 */
|
| 107 | #define MSER_MBZ 0xFFFFFC04
|
| 108 | #define MSER_RD (MSER_PE | MSER_WWP | MSER_LEB | \
|
Mark Pizzolato | 651780c | 2013-06-03 06:29:01 -0700 | [diff] [blame] | 109 | MSER_DQPE | MSER_CQPE | MSER_CLPE | \
|
| 110 | MSER_NXM | MSER_MCD0 | MSER_MCD1)
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 111 | #define MSER_WR (MSER_PE | MSER_WWP)
|
| 112 | #define MSER_RS (MSER_LEB | MSER_DQPE | MSER_CQPE | MSER_CLPE | MSER_NXM)
|
| 113 |
|
| 114 | /* KA630 CPU error address reg */
|
| 115 |
|
| 116 | #define CEAR_LMADD 0x00007FFF /* local mem addr */
|
| 117 | #define CEAR_RD (CEAR_LMADD)
|
| 118 |
|
| 119 | /* KA630 DMA error address reg */
|
| 120 |
|
| 121 | #define DEAR_LMADD 0x00007FFF /* local mem addr */
|
| 122 | #define DEAR_RD (DEAR_LMADD)
|
| 123 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 124 | extern UNIT clk_unit;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 125 | extern int32 tmr_poll;
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 126 | extern DEVICE vc_dev, lk_dev, vs_dev;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 127 |
|
| 128 | uint32 *rom = NULL; /* boot ROM */
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 129 | uint8 *nvr = NULL; /* non-volatile mem */
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 130 | int32 conisp, conpc, conpsl; /* console reg */
|
| 131 | int32 ka_bdr = BDR_BRKENB; /* KA630 boot diag */
|
| 132 | int32 ka_mser = 0; /* KA630 mem sys err */
|
| 133 | int32 ka_cear = 0; /* KA630 cpu err */
|
| 134 | int32 ka_dear = 0; /* KA630 dma err */
|
| 135 | static uint32 rom_delay = 0;
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 136 | t_bool ka_diag_full = FALSE;
|
| 137 | t_bool ka_hltenab = TRUE; /* Halt Enable / Autoboot flag */
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 138 |
|
| 139 | t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
|
| 140 | t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
|
| 141 | t_stat rom_reset (DEVICE *dptr);
|
| 142 | t_stat rom_set_diag (UNIT *uptr, int32 val, char *cptr, void *desc);
|
| 143 | t_stat rom_show_diag (FILE *st, UNIT *uptr, int32 val, void *desc);
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 144 | t_stat rom_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
| 145 | const char *rom_description (DEVICE *dptr);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 146 | t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
|
| 147 | t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
|
| 148 | t_stat nvr_reset (DEVICE *dptr);
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 149 | t_stat nvr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 150 | t_stat nvr_attach (UNIT *uptr, char *cptr);
|
| 151 | t_stat nvr_detach (UNIT *uptr);
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 152 | const char *nvr_description (DEVICE *dptr);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 153 | t_stat sysd_reset (DEVICE *dptr);
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 154 | t_stat sysd_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
| 155 | const char *sysd_description (DEVICE *dptr);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 156 |
|
| 157 | int32 rom_rd (int32 pa);
|
| 158 | int32 nvr_rd (int32 pa);
|
| 159 | void nvr_wr (int32 pa, int32 val, int32 lnt);
|
| 160 | int32 ka_rd (int32 pa);
|
| 161 | void ka_wr (int32 pa, int32 val, int32 lnt);
|
| 162 | t_stat sysd_powerup (void);
|
| 163 | int32 con_halt (int32 code, int32 cc);
|
| 164 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 165 | extern int32 qbmap_rd (int32 pa);
|
| 166 | extern void qbmap_wr (int32 pa, int32 val, int32 lnt);
|
| 167 | extern int32 qbmem_rd (int32 pa);
|
| 168 | extern void qbmem_wr (int32 pa, int32 val, int32 lnt);
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 169 | extern int32 vc_mem_rd (int32 pa);
|
| 170 | extern void vc_mem_wr (int32 pa, int32 val, int32 lnt);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 171 | extern int32 wtc_rd (int32 pa);
|
| 172 | extern void wtc_wr (int32 pa, int32 val, int32 lnt);
|
| 173 | extern void wtc_set_valid (void);
|
| 174 | extern void wtc_set_invalid (void);
|
| 175 | extern int32 iccs_rd (void);
|
| 176 | extern int32 todr_rd (void);
|
| 177 | extern int32 rxcs_rd (void);
|
| 178 | extern int32 rxdb_rd (void);
|
| 179 | extern int32 txcs_rd (void);
|
| 180 | extern void iccs_wr (int32 dat);
|
| 181 | extern void todr_wr (int32 dat);
|
| 182 | extern void rxcs_wr (int32 dat);
|
| 183 | extern void txcs_wr (int32 dat);
|
| 184 | extern void txdb_wr (int32 dat);
|
| 185 | extern void ioreset_wr (int32 dat);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 186 |
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 187 | /* debugging bitmaps */
|
| 188 | #define DBG_REG 0x0001 /* trace read/write registers */
|
| 189 |
|
| 190 | DEBTAB nvr_debug[] = {
|
| 191 | {"REG", DBG_REG},
|
| 192 | {0}
|
| 193 | };
|
| 194 |
|
| 195 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 196 | /* ROM data structures
|
| 197 |
|
| 198 | rom_dev ROM device descriptor
|
| 199 | rom_unit ROM units
|
| 200 | rom_reg ROM register list
|
| 201 | */
|
| 202 |
|
| 203 | UNIT rom_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK, ROMSIZE) };
|
| 204 |
|
| 205 | REG rom_reg[] = {
|
| 206 | { NULL }
|
| 207 | };
|
| 208 |
|
| 209 | MTAB rom_mod[] = {
|
Mark Pizzolato | 28b9055 | 2013-02-02 16:29:38 -0800 | [diff] [blame] | 210 | { UNIT_NODELAY, UNIT_NODELAY, "fast access", "NODELAY", NULL, NULL, NULL, "Disable calibrated ROM access speed" },
|
| 211 | { UNIT_NODELAY, 0, "1usec calibrated access", "DELAY", NULL, NULL, NULL, "Enable calibrated ROM access speed" },
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 212 | { 0 }
|
| 213 | };
|
| 214 |
|
| 215 | DEVICE rom_dev = {
|
| 216 | "ROM", &rom_unit, rom_reg, rom_mod,
|
| 217 | 1, 16, ROMAWIDTH, 4, 16, 32,
|
| 218 | &rom_ex, &rom_dep, &rom_reset,
|
| 219 | NULL, NULL, NULL,
|
Mark Pizzolato | 28b9055 | 2013-02-02 16:29:38 -0800 | [diff] [blame] | 220 | NULL, 0, 0, NULL, NULL, NULL, &rom_help, NULL, NULL,
|
Mark Pizzolato | cbe1114 | 2013-01-25 12:04:25 -0800 | [diff] [blame] | 221 | &rom_description
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 222 | };
|
| 223 |
|
| 224 | /* NVR data structures
|
| 225 |
|
| 226 | nvr_dev NVR device descriptor
|
| 227 | nvr_unit NVR units
|
| 228 | nvr_reg NVR register list
|
| 229 | */
|
| 230 |
|
| 231 | UNIT nvr_unit =
|
| 232 | { UDATA (NULL, UNIT_FIX+UNIT_BINK, NVRSIZE) };
|
| 233 |
|
| 234 | REG nvr_reg[] = {
|
| 235 | { NULL }
|
| 236 | };
|
| 237 |
|
| 238 | DEVICE nvr_dev = {
|
| 239 | "NVR", &nvr_unit, nvr_reg, NULL,
|
| 240 | 1, 16, NVRAWIDTH, 4, 16, 32,
|
| 241 | &nvr_ex, &nvr_dep, &nvr_reset,
|
| 242 | NULL, &nvr_attach, &nvr_detach,
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 243 | NULL, DEV_DEBUG, 0, nvr_debug, NULL, NULL, &nvr_help, NULL, NULL,
|
Mark Pizzolato | cbe1114 | 2013-01-25 12:04:25 -0800 | [diff] [blame] | 244 | &nvr_description
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 245 | };
|
| 246 |
|
| 247 | /* SYSD data structures
|
| 248 |
|
| 249 | sysd_dev SYSD device descriptor
|
| 250 | sysd_unit SYSD units
|
| 251 | sysd_reg SYSD register list
|
| 252 | */
|
| 253 |
|
| 254 | UNIT sysd_unit = { UDATA (NULL, 0, 0) };
|
| 255 |
|
| 256 | REG sysd_reg[] = {
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 257 | { HRDATAD (CONISP, conisp, 32, "console ISP") },
|
| 258 | { HRDATAD (CONPC, conpc, 32, "console PD") },
|
| 259 | { HRDATAD (CONPSL, conpsl, 32, "console PSL") },
|
| 260 | { HRDATAD (BDR, ka_bdr, 16, "KA630 boot diag") },
|
| 261 | { HRDATAD (MSER, ka_mser, 8, "KA630 mem sys err") },
|
| 262 | { HRDATAD (CEAR, ka_cear, 8, "KA630 cpu err") },
|
| 263 | { HRDATAD (DEAR, ka_dear, 8, "KA630 dma err") },
|
| 264 | { HRDATAD (DEAR, ka_dear, 8, "KA630 dma err") },
|
| 265 | { FLDATAD (DIAG, ka_diag_full, 0, "KA630 Full Boot diagnostics") },
|
| 266 | { FLDATAD (HLTENAB, ka_hltenab, 0, "KA630 Autoboot/Halt Enable") },
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 267 | { NULL }
|
| 268 | };
|
| 269 |
|
| 270 | DEVICE sysd_dev = {
|
| 271 | "SYSD", &sysd_unit, sysd_reg, NULL,
|
| 272 | 1, 16, 16, 1, 16, 8,
|
| 273 | NULL, NULL, &sysd_reset,
|
| 274 | NULL, NULL, NULL,
|
Mark Pizzolato | cbe1114 | 2013-01-25 12:04:25 -0800 | [diff] [blame] | 275 | NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
|
| 276 | &sysd_description
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 277 | };
|
| 278 |
|
| 279 | /* ROM: read only memory - stored in a buffered file
|
| 280 | Register space access routines see ROM twice
|
| 281 |
|
| 282 | ROM access has been 'regulated' to about 1Mhz to avoid issues
|
| 283 | with testing the interval timers in self-test. Specifically,
|
| 284 | the VAX boot ROM (ka630.bin) contains code which presumes that
|
| 285 | the VAX runs at a particular slower speed when code is running
|
| 286 | from ROM (which is not cached). These assumptions are built
|
| 287 | into instruction based timing loops. As the host platform gets
|
| 288 | much faster than the original VAX, the assumptions embedded in
|
| 289 | these code loops are no longer valid.
|
| 290 |
|
| 291 | Code has been added to the ROM implementation to limit CPU speed
|
| 292 | to about 500K instructions per second. This heads off any future
|
| 293 | issues with the embedded timing loops.
|
| 294 | */
|
| 295 |
|
| 296 | int32 rom_swapb(int32 val)
|
| 297 | {
|
| 298 | return ((val << 24) & 0xff000000) | (( val << 8) & 0xff0000) |
|
| 299 | ((val >> 8) & 0xff00) | ((val >> 24) & 0xff);
|
| 300 | }
|
| 301 |
|
Mark Pizzolato | 89ca7bd | 2014-08-02 15:43:39 -0700 | [diff] [blame] | 302 | volatile int32 rom_loopval = 0;
|
| 303 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 304 | int32 rom_read_delay (int32 val)
|
| 305 | {
|
| 306 | uint32 i, l = rom_delay;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 307 |
|
| 308 | if (rom_unit.flags & UNIT_NODELAY)
|
| 309 | return val;
|
| 310 |
|
| 311 | /* Calibrate the loop delay factor when first used.
|
| 312 | Do this 4 times to and use the largest value computed. */
|
| 313 |
|
| 314 | if (rom_delay == 0) {
|
| 315 | uint32 ts, te, c = 10000, samples = 0;
|
| 316 | while (1) {
|
| 317 | c = c * 2;
|
| 318 | te = sim_os_msec();
|
| 319 | while (te == (ts = sim_os_msec ())); /* align on ms tick */
|
| 320 |
|
| 321 | /* This is merely a busy wait with some "work" that won't get optimized
|
| 322 | away by a good compiler. loopval always is zero. To avoid smart compilers,
|
| 323 | the loopval variable is referenced in the function arguments so that the
|
| 324 | function expression is not loop invariant. It also must be referenced
|
| 325 | by subsequent code or to avoid the whole computation being eliminated. */
|
| 326 |
|
| 327 | for (i = 0; i < c; i++)
|
Mark Pizzolato | 89ca7bd | 2014-08-02 15:43:39 -0700 | [diff] [blame] | 328 | rom_loopval |= (rom_loopval + ts) ^ rom_swapb (rom_swapb (rom_loopval + ts));
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 329 | te = sim_os_msec ();
|
| 330 | if ((te - ts) < 50) /* sample big enough? */
|
| 331 | continue;
|
Mark Pizzolato | 89ca7bd | 2014-08-02 15:43:39 -0700 | [diff] [blame] | 332 | if (rom_delay < (rom_loopval + (c / (te - ts) / 1000) + 1))
|
| 333 | rom_delay = rom_loopval + (c / (te - ts) / 1000) + 1;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 334 | if (++samples >= 4)
|
| 335 | break;
|
| 336 | c = c / 2;
|
| 337 | }
|
| 338 | if (rom_delay < 5)
|
| 339 | rom_delay = 5;
|
| 340 | }
|
| 341 |
|
| 342 | for (i = 0; i < l; i++)
|
Mark Pizzolato | 89ca7bd | 2014-08-02 15:43:39 -0700 | [diff] [blame] | 343 | rom_loopval |= (rom_loopval + val) ^ rom_swapb (rom_swapb (rom_loopval + val));
|
| 344 | return val + rom_loopval;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 345 | }
|
| 346 |
|
| 347 | int32 rom_rd (int32 pa)
|
| 348 | {
|
| 349 | int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2;
|
| 350 |
|
| 351 | return rom_read_delay (rom[rg]);
|
| 352 | }
|
| 353 |
|
| 354 | void rom_wr_B (int32 pa, int32 val)
|
| 355 | {
|
| 356 | int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2;
|
| 357 | int32 sc = (pa & 3) << 3;
|
| 358 |
|
| 359 | rom[rg] = ((val & 0xFF) << sc) | (rom[rg] & ~(0xFF << sc));
|
| 360 | return;
|
| 361 | }
|
| 362 |
|
| 363 | /* ROM examine */
|
| 364 |
|
| 365 | t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
|
| 366 | {
|
| 367 | uint32 addr = (uint32) exta;
|
| 368 |
|
| 369 | if ((vptr == NULL) || (addr & 03))
|
| 370 | return SCPE_ARG;
|
| 371 | if (addr >= ROMSIZE)
|
| 372 | return SCPE_NXM;
|
| 373 | *vptr = rom[addr >> 2];
|
| 374 | return SCPE_OK;
|
| 375 | }
|
| 376 |
|
| 377 | /* ROM deposit */
|
| 378 |
|
| 379 | t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
|
| 380 | {
|
| 381 | uint32 addr = (uint32) exta;
|
| 382 |
|
| 383 | if (addr & 03)
|
| 384 | return SCPE_ARG;
|
| 385 | if (addr >= ROMSIZE)
|
| 386 | return SCPE_NXM;
|
| 387 | rom[addr >> 2] = (uint32) val;
|
| 388 | return SCPE_OK;
|
| 389 | }
|
| 390 |
|
| 391 | /* ROM reset */
|
| 392 |
|
| 393 | t_stat rom_reset (DEVICE *dptr)
|
| 394 | {
|
| 395 | if (rom == NULL)
|
| 396 | rom = (uint32 *) calloc (ROMSIZE >> 2, sizeof (uint32));
|
| 397 | if (rom == NULL)
|
| 398 | return SCPE_MEM;
|
| 399 | return SCPE_OK;
|
| 400 | }
|
| 401 |
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 402 | t_stat rom_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
Mark Pizzolato | 28b9055 | 2013-02-02 16:29:38 -0800 | [diff] [blame] | 403 | {
|
| 404 | fprintf (st, "Read-only memory (ROM)\n\n");
|
| 405 | fprintf (st, "The boot ROM consists of a single unit, simulating the 64KB boot ROM. It has\n");
|
| 406 | fprintf (st, "no registers. The boot ROM is loaded with a binary byte stream using the \n");
|
| 407 | fprintf (st, "LOAD -r command:\n\n");
|
Mark Pizzolato | 651780c | 2013-06-03 06:29:01 -0700 | [diff] [blame] | 408 | fprintf (st, " LOAD -r KA630.BIN load ROM image KA630.BIN\n\n");
|
Mark Pizzolato | 864b581 | 2013-02-05 13:59:59 -0800 | [diff] [blame] | 409 | fprintf (st, "When the simulator starts running (via the BOOT command), if the ROM has\n");
|
| 410 | fprintf (st, "not yet been loaded, an attempt will be made to automatically load the\n");
|
| 411 | fprintf (st, "ROM image from the file ka655x.bin in the current working directory.\n");
|
| 412 | fprintf (st, "If that load attempt fails, then a copy of the missing ROM file is\n");
|
| 413 | fprintf (st, "written to the current directory and the load attempt is retried.\n\n");
|
| 414 | fprintf (st, "ROM accesses a use a calibrated delay that slows ROM-based execution to\n");
|
| 415 | fprintf (st, "about 500K instructions per second. This delay is required to make the\n");
|
| 416 | fprintf (st, "power-up self-test routines run correctly on very fast hosts.\n");
|
| 417 | fprint_set_help (st, dptr);
|
| 418 | fprintf (st, "By default the memory power-up self-tests are skipped as they take a long\n");
|
| 419 | fprintf (st, "time to complete. The self-test sequence can be controlled with the\n");
|
| 420 | fprintf (st, "following commands:\n\n");
|
| 421 | fprintf (st, " SET CPU DIAG=MIN Run minimal diagnostics (skip memory test)\n");
|
| 422 | fprintf (st, " SET CPU DIAG=FULL Run full diagnostics\n\n");
|
Mark Pizzolato | 28b9055 | 2013-02-02 16:29:38 -0800 | [diff] [blame] | 423 | return SCPE_OK;
|
| 424 | }
|
| 425 |
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 426 | const char *rom_description (DEVICE *dptr)
|
Mark Pizzolato | cbe1114 | 2013-01-25 12:04:25 -0800 | [diff] [blame] | 427 | {
|
| 428 | return "read-only memory";
|
| 429 | }
|
| 430 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 431 | /* NVR: non-volatile RAM - stored in a buffered file */
|
| 432 |
|
| 433 | int32 nvr_rd (int32 pa)
|
| 434 | {
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 435 | int32 rg = (pa - NVRBASE) >> 1;
|
| 436 | int32 result;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 437 |
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 438 | if (rg < 14) /* watch chip */
|
| 439 | result = wtc_rd (pa);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 440 | else
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 441 | if (rg & 1)
|
| 442 | result = ((int32)nvr[rg]) << 16;
|
| 443 | else
|
| 444 | result = nvr[rg] | (((int32)nvr[rg+1]) << 16);
|
| 445 |
|
| 446 | sim_debug (DBG_REG, &nvr_dev, "nvr_rd(pa=0x%X) returns: 0x%X\n", pa, result);
|
| 447 |
|
| 448 | return result;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 449 | }
|
| 450 |
|
| 451 | void nvr_wr (int32 pa, int32 val, int32 lnt)
|
| 452 | {
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 453 | int32 rg = (pa - NVRBASE) >> 1;
|
| 454 | uint32 orig_nvr = nvr[rg] | (nvr[rg+1] << 8);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 455 |
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 456 | if (rg < 14) /* watch chip */
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 457 | wtc_wr (pa, val, lnt);
|
| 458 | else {
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 459 | int32 v = val;
|
| 460 | int32 r = rg;
|
| 461 | int32 l = lnt;
|
| 462 |
|
| 463 | while (l > 0) {
|
| 464 | nvr[r] = (uint8)v;
|
| 465 | ++r;
|
| 466 | l -= 2;
|
| 467 | v = (v >> 16);
|
| 468 | }
|
| 469 |
|
| 470 | sim_debug (DBG_REG, &nvr_dev, "nvr_wr(pa=0x%X,val=0x%04X,lnt=%d) nvr[%02X] was %04X now %04X\n", pa, val, lnt, rg, orig_nvr, nvr[rg] | (nvr[rg+1] << 8));
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 471 | }
|
| 472 | }
|
| 473 |
|
| 474 | /* NVR examine */
|
| 475 |
|
| 476 | t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
|
| 477 | {
|
| 478 | uint32 addr = (uint32) exta;
|
| 479 |
|
| 480 | if ((vptr == NULL) || (addr & 03))
|
| 481 | return SCPE_ARG;
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 482 | if (addr >= NVRBASE+NVRASIZE)
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 483 | return SCPE_NXM;
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 484 | *vptr = nvr[addr >> 1] | (nvr[(addr >> 1) + 1] << 8);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 485 | return SCPE_OK;
|
| 486 | }
|
| 487 |
|
| 488 | /* NVR deposit */
|
| 489 |
|
| 490 | t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
|
| 491 | {
|
| 492 | uint32 addr = (uint32) exta;
|
| 493 |
|
| 494 | if (addr & 03)
|
| 495 | return SCPE_ARG;
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 496 | if (addr >= NVRBASE+NVRASIZE)
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 497 | return SCPE_NXM;
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 498 | nvr[addr >> 1] = (uint8) val;
|
| 499 | nvr[(addr >> 1) + 1] = (uint8) (val >> 8);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 500 | return SCPE_OK;
|
| 501 | }
|
| 502 |
|
| 503 | /* NVR reset */
|
| 504 |
|
| 505 | t_stat nvr_reset (DEVICE *dptr)
|
| 506 | {
|
| 507 | if (nvr == NULL) {
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 508 | nvr = (uint8 *) calloc (NVRSIZE, sizeof (*nvr));
|
| 509 | nvr_unit.filebuf = (void *)nvr;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 510 | }
|
| 511 | if (nvr == NULL)
|
| 512 | return SCPE_MEM;
|
| 513 | return SCPE_OK;
|
| 514 | }
|
| 515 |
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 516 | t_stat nvr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
Mark Pizzolato | 28b9055 | 2013-02-02 16:29:38 -0800 | [diff] [blame] | 517 | {
|
| 518 | fprintf (st, "Non-volatile Memory (NVR)\n\n");
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 519 | fprintf (st, "The NVR simulates %d bytes of battery-backed up memory.\n", NVRSIZE);
|
Mark Pizzolato | 28b9055 | 2013-02-02 16:29:38 -0800 | [diff] [blame] | 520 | fprintf (st, "When the simulator starts, NVR is cleared to 0, and the battery-low indicator\n");
|
| 521 | fprintf (st, "is set. Alternately, NVR can be attached to a file. This allows the NVR\n");
|
| 522 | fprintf (st, "state to be preserved across simulator runs. Successfully attaching an NVR\n");
|
| 523 | fprintf (st, "image clears the battery-low indicator.\n\n");
|
| 524 | return SCPE_OK;
|
| 525 | }
|
| 526 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 527 | /* NVR attach */
|
| 528 |
|
Mark Pizzolato | 1a48d85 | 2013-08-21 14:31:31 -0700 | [diff] [blame] | 529 | /* Valid NVRAM contents are required for the Boot ROM to respect the
|
| 530 | watch chip's CSRD VRT bit. This empty NVRAM image avoids inconsistent
|
| 531 | ROM behavior the first time the NVR device is attached (to an empty
|
| 532 | file). Attaching a already existing file will overwrite this initial
|
| 533 | contents with whatever the NVRAM file contains. */
|
| 534 | uint8 nvr_empty_valid[NVRSIZE] = {
|
| 535 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
|
| 536 | 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
| 537 | 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x48, 0x45, 0x41, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| 538 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| 539 | };
|
| 540 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 541 | t_stat nvr_attach (UNIT *uptr, char *cptr)
|
| 542 | {
|
| 543 | t_stat r;
|
| 544 |
|
Mark Pizzolato | 1a48d85 | 2013-08-21 14:31:31 -0700 | [diff] [blame] | 545 | memcpy (nvr, nvr_empty_valid, NVRSIZE);
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 546 | uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE);
|
| 547 | r = attach_unit (uptr, cptr);
|
| 548 | if (r != SCPE_OK)
|
| 549 | uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
|
| 550 | else {
|
| 551 | uptr->hwmark = (uint32) uptr->capac;
|
| 552 | wtc_set_valid ();
|
| 553 | }
|
| 554 | return r;
|
| 555 | }
|
| 556 |
|
| 557 | /* NVR detach */
|
| 558 |
|
| 559 | t_stat nvr_detach (UNIT *uptr)
|
| 560 | {
|
| 561 | t_stat r;
|
| 562 |
|
| 563 | r = detach_unit (uptr);
|
| 564 | if ((uptr->flags & UNIT_ATT) == 0) {
|
| 565 | uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
|
| 566 | wtc_set_invalid ();
|
| 567 | }
|
| 568 | return r;
|
Mark Pizzolato | cbe1114 | 2013-01-25 12:04:25 -0800 | [diff] [blame] | 569 | }
|
| 570 |
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 571 | const char *nvr_description (DEVICE *dptr)
|
Mark Pizzolato | cbe1114 | 2013-01-25 12:04:25 -0800 | [diff] [blame] | 572 | {
|
| 573 | return "non-volatile memory";
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 574 | }
|
| 575 |
|
| 576 | /* Read KA630 specific IPR's */
|
| 577 |
|
| 578 | int32 ReadIPR (int32 rg)
|
| 579 | {
|
| 580 | int32 val;
|
| 581 |
|
| 582 | switch (rg) {
|
| 583 |
|
| 584 | case MT_ICCS: /* ICCS */
|
| 585 | val = iccs_rd ();
|
| 586 | break;
|
| 587 |
|
| 588 | case MT_RXCS: /* RXCS */
|
| 589 | val = rxcs_rd ();
|
| 590 | break;
|
| 591 |
|
| 592 | case MT_RXDB: /* RXDB */
|
| 593 | val = rxdb_rd ();
|
| 594 | break;
|
| 595 |
|
| 596 | case MT_TXCS: /* TXCS */
|
| 597 | val = txcs_rd ();
|
| 598 | break;
|
| 599 |
|
| 600 | case MT_TXDB: /* TXDB */
|
| 601 | val = 0;
|
| 602 | break;
|
| 603 |
|
| 604 | case MT_CONISP: /* console ISP */
|
| 605 | val = conisp;
|
| 606 | break;
|
| 607 |
|
| 608 | case MT_CONPC: /* console PC */
|
| 609 | val = conpc;
|
| 610 | break;
|
| 611 |
|
| 612 | case MT_CONPSL: /* console PSL */
|
| 613 | val = conpsl;
|
| 614 | break;
|
| 615 |
|
| 616 | case MT_SID: /* SID */
|
| 617 | #if defined(VAX_620)
|
| 618 | val = VAX620_SID;
|
| 619 | #else
|
| 620 | val = VAX630_SID;
|
| 621 | #endif
|
| 622 | break;
|
| 623 |
|
| 624 | case MT_NICR: /* NICR */
|
| 625 | case MT_ICR: /* ICR */
|
| 626 | case MT_TODR: /* TODR */
|
| 627 | case MT_CSRS: /* CSRS */
|
| 628 | case MT_CSRD: /* CSRD */
|
| 629 | case MT_CSTS: /* CSTS */
|
| 630 | case MT_CSTD: /* CSTD */
|
| 631 | case MT_TBDR: /* TBDR */
|
| 632 | case MT_CADR: /* CADR */
|
| 633 | case MT_MCESR: /* MCESR */
|
| 634 | case MT_CAER: /* CAER */
|
| 635 | case MT_SBIFS: /* SBIFS */
|
| 636 | case MT_SBIS: /* SBIS */
|
| 637 | case MT_SBISC: /* SBISC */
|
| 638 | case MT_SBIMT: /* SBIMT */
|
| 639 | case MT_SBIER: /* SBIER */
|
| 640 | case MT_SBITA: /* SBITA */
|
| 641 | case MT_SBIQC: /* SBIQC */
|
| 642 | case MT_TBDATA: /* TBDATA */
|
| 643 | case MT_MBRK: /* MBRK */
|
| 644 | case MT_PME: /* PME */
|
| 645 | val = 0;
|
| 646 | break;
|
| 647 |
|
| 648 | default:
|
| 649 | RSVD_OPND_FAULT;
|
| 650 | }
|
| 651 |
|
| 652 | return val;
|
| 653 | }
|
| 654 |
|
| 655 | /* Write KA630 specific IPR's */
|
| 656 |
|
| 657 | void WriteIPR (int32 rg, int32 val)
|
| 658 | {
|
| 659 | switch (rg) {
|
| 660 |
|
| 661 | case MT_ICCS: /* ICCS */
|
| 662 | iccs_wr (val);
|
| 663 | break;
|
| 664 |
|
| 665 | case MT_RXCS: /* RXCS */
|
| 666 | rxcs_wr (val);
|
| 667 | break;
|
| 668 |
|
| 669 | case MT_RXDB: /* RXDB */
|
| 670 | break;
|
| 671 |
|
| 672 | case MT_TXCS: /* TXCS */
|
| 673 | txcs_wr (val);
|
| 674 | break;
|
| 675 |
|
| 676 | case MT_TXDB: /* TXDB */
|
| 677 | txdb_wr (val);
|
| 678 | break;
|
| 679 |
|
| 680 | case MT_IORESET: /* IORESET */
|
| 681 | ioreset_wr (val);
|
| 682 | break;
|
| 683 |
|
| 684 | case MT_SID:
|
| 685 | case MT_CONISP:
|
| 686 | case MT_CONPC:
|
| 687 | case MT_CONPSL: /* halt reg */
|
| 688 | RSVD_OPND_FAULT;
|
| 689 |
|
| 690 | case MT_NICR: /* NICR */
|
| 691 | case MT_ICR: /* ICR */
|
| 692 | case MT_TODR: /* TODR */
|
| 693 | case MT_CSRS: /* CSRS */
|
| 694 | case MT_CSRD: /* CSRD */
|
| 695 | case MT_CSTS: /* CSTS */
|
| 696 | case MT_CSTD: /* CSTD */
|
| 697 | case MT_TBDR: /* TBDR */
|
| 698 | case MT_CADR: /* CADR */
|
| 699 | case MT_MCESR: /* MCESR */
|
| 700 | case MT_CAER: /* CAER */
|
| 701 | case MT_SBIFS: /* SBIFS */
|
| 702 | case MT_SBIS: /* SBIS */
|
| 703 | case MT_SBISC: /* SBISC */
|
| 704 | case MT_SBIMT: /* SBIMT */
|
| 705 | case MT_SBIER: /* SBIER */
|
| 706 | case MT_SBITA: /* SBITA */
|
| 707 | case MT_SBIQC: /* SBIQC */
|
| 708 | case MT_TBDATA: /* TBDATA */
|
| 709 | case MT_MBRK: /* MBRK */
|
| 710 | case MT_PME: /* PME */
|
| 711 | break;
|
| 712 |
|
| 713 | default:
|
| 714 | RSVD_OPND_FAULT;
|
| 715 | }
|
| 716 |
|
| 717 | return;
|
| 718 | }
|
| 719 |
|
| 720 | /* Read/write I/O register space
|
| 721 |
|
| 722 | These routines are the 'catch all' for address space map. Any
|
| 723 | address that doesn't explicitly belong to memory, I/O, or ROM
|
| 724 | is given to these routines for processing.
|
| 725 | */
|
| 726 |
|
| 727 | struct reglink { /* register linkage */
|
| 728 | uint32 low; /* low addr */
|
| 729 | uint32 high; /* high addr */
|
Mark Pizzolato | 3346f4a | 2012-12-19 12:45:03 -0800 | [diff] [blame] | 730 | int32 (*read)(int32 pa); /* read routine */
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 731 | void (*write)(int32 pa, int32 val, int32 lnt); /* write routine */
|
| 732 | };
|
| 733 |
|
| 734 | struct reglink regtable[] = {
|
| 735 | { QBMAPBASE, QBMAPBASE+QBMAPSIZE, &qbmap_rd, &qbmap_wr },
|
| 736 | { ROMBASE, ROMBASE+ROMSIZE+ROMSIZE, &rom_rd, NULL },
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 737 | { NVRBASE, NVRBASE+NVRASIZE, &nvr_rd, &nvr_wr },
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 738 | { KABASE, KABASE+KASIZE, &ka_rd, &ka_wr },
|
Mark Pizzolato | 0b89e63 | 2014-09-20 18:50:39 -0700 | [diff] [blame] | 739 | #if !defined(VAX_620)
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 740 | { QVMBASE, QVMBASE+QVMSIZE, &vc_mem_rd, &vc_mem_wr },
|
Mark Pizzolato | 0b89e63 | 2014-09-20 18:50:39 -0700 | [diff] [blame] | 741 | #endif
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 742 | { QBMBASE, QBMBASE+QBMSIZE, &qbmem_rd, &qbmem_wr },
|
| 743 | { 0, 0, NULL, NULL }
|
| 744 | };
|
| 745 |
|
| 746 | /* ReadReg - read register space
|
| 747 |
|
| 748 | Inputs:
|
| 749 | pa = physical address
|
| 750 | lnt = length (BWLQ) - ignored
|
| 751 | Output:
|
| 752 | longword of data
|
| 753 | */
|
| 754 |
|
| 755 | int32 ReadReg (uint32 pa, int32 lnt)
|
| 756 | {
|
| 757 | struct reglink *p;
|
| 758 |
|
| 759 | for (p = ®table[0]; p->low != 0; p++) {
|
| 760 | if ((pa >= p->low) && (pa < p->high) && p->read)
|
| 761 | return p->read (pa);
|
| 762 | }
|
| 763 |
|
| 764 | MACH_CHECK (MCHK_READ);
|
| 765 | }
|
| 766 |
|
Mark Pizzolato | bf58edf | 2013-12-22 04:10:01 -0800 | [diff] [blame] | 767 | /* ReadRegU - read register space, unaligned
|
| 768 |
|
| 769 | Inputs:
|
| 770 | pa = physical address
|
| 771 | lnt = length in bytes (1, 2, or 3)
|
| 772 | Output:
|
| 773 | returned data, not shifted
|
| 774 | */
|
| 775 |
|
| 776 | int32 ReadRegU (uint32 pa, int32 lnt)
|
| 777 | {
|
| 778 | return ReadReg (pa & ~03, L_LONG);
|
| 779 | }
|
| 780 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 781 | /* WriteReg - write register space
|
| 782 |
|
| 783 | Inputs:
|
| 784 | pa = physical address
|
| 785 | val = data to write, right justified in 32b longword
|
| 786 | lnt = length (BWLQ)
|
| 787 | Outputs:
|
| 788 | none
|
| 789 | */
|
| 790 |
|
| 791 | void WriteReg (uint32 pa, int32 val, int32 lnt)
|
| 792 | {
|
| 793 | struct reglink *p;
|
| 794 |
|
| 795 | for (p = ®table[0]; p->low != 0; p++) {
|
| 796 | if ((pa >= p->low) && (pa < p->high) && p->write) {
|
| 797 | p->write (pa, val, lnt);
|
| 798 | return;
|
| 799 | }
|
| 800 | }
|
| 801 |
|
| 802 | MACH_CHECK (MCHK_WRITE);
|
| 803 | }
|
| 804 |
|
Mark Pizzolato | bf58edf | 2013-12-22 04:10:01 -0800 | [diff] [blame] | 805 | /* WriteRegU - write register space, unaligned
|
| 806 |
|
| 807 | Inputs:
|
| 808 | pa = physical address
|
| 809 | val = data to write, right justified in 32b longword
|
| 810 | lnt = length (1, 2, or 3)
|
| 811 | Outputs:
|
| 812 | none
|
| 813 | */
|
| 814 |
|
| 815 | void WriteRegU (uint32 pa, int32 val, int32 lnt)
|
| 816 | {
|
| 817 | int32 sc = (pa & 03) << 3;
|
| 818 | int32 dat = ReadReg (pa & ~03, L_LONG);
|
| 819 |
|
| 820 | dat = (dat & ~(insert[lnt] << sc)) | ((val & insert[lnt]) << sc);
|
| 821 | WriteReg (pa & ~03, dat, L_LONG);
|
| 822 | return;
|
| 823 | }
|
| 824 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 825 | /* KA630 registers */
|
| 826 |
|
| 827 | int32 ka_rd (int32 pa)
|
| 828 | {
|
| 829 | int32 rg = (pa - KABASE) >> 2;
|
| 830 |
|
| 831 | switch (rg) {
|
| 832 |
|
| 833 | case 0: /* BDR */
|
| 834 | return ka_bdr & BDR_RD;
|
| 835 |
|
| 836 | case 1: /* MSER */
|
| 837 | return ka_mser & MSER_RD;
|
| 838 |
|
| 839 | case 2: /* CEAR */
|
| 840 | return ka_cear & CEAR_RD;
|
| 841 |
|
| 842 | case 3: /* DEAR */
|
| 843 | return ka_dear & DEAR_RD;
|
| 844 | }
|
| 845 |
|
| 846 | return 0;
|
| 847 | }
|
| 848 |
|
| 849 | void ka_wr (int32 pa, int32 val, int32 lnt)
|
| 850 | {
|
| 851 | int32 rg = (pa - KABASE) >> 2;
|
| 852 |
|
| 853 | switch (rg) {
|
| 854 |
|
| 855 | case 0: /* BDR */
|
| 856 | ka_bdr = (ka_bdr & ~BDR_WR) | (val & BDR_WR);
|
| 857 | break;
|
| 858 |
|
| 859 | case 1: /* MSER */
|
| 860 | ka_mser = (ka_mser & ~MSER_WR) | (val & MSER_WR);
|
| 861 | ka_mser = ka_mser & ~(val & MSER_RS);
|
| 862 | break;
|
| 863 |
|
| 864 | case 2: /* CEAR */
|
| 865 | case 3: /* DEAR */
|
| 866 | break;
|
| 867 | }
|
| 868 | return;
|
| 869 | }
|
| 870 |
|
| 871 | int32 sysd_hlt_enb (void)
|
| 872 | {
|
| 873 | return ka_bdr & BDR_BRKENB;
|
| 874 | }
|
| 875 |
|
| 876 | /* Machine check */
|
| 877 |
|
| 878 | int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta)
|
| 879 | {
|
| 880 | int32 st, p2, acc;
|
| 881 |
|
| 882 | if (in_ie) {
|
| 883 | in_ie = 0;
|
| 884 | return con_halt(CON_DBLMCK, cc); /* double machine check */
|
| 885 | }
|
| 886 | if (p1 & 0x80) /* mref? set v/p */
|
| 887 | p1 = p1 + mchk_ref;
|
| 888 | p2 = mchk_va + 4; /* save vap */
|
| 889 | st = 0;
|
Mark Pizzolato | 478ff3d | 2015-03-30 10:37:41 -0700 | [diff] [blame] | 890 | cc = intexc (SCB_MCHK, cc, 0, IE_EXC); /* take normal exception */
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 891 | if (p1 & 0x80) { /* mref? */
|
Mark Pizzolato | 651780c | 2013-06-03 06:29:01 -0700 | [diff] [blame] | 892 | if (!(ka_mser & MSER_CQPE) && !(ka_mser & MSER_CLPE))
|
| 893 | ka_mser |= MSER_NXM;
|
Mark Pizzolato | 478ff3d | 2015-03-30 10:37:41 -0700 | [diff] [blame] | 894 | }
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 895 | acc = ACC_MASK (KERN); /* in kernel mode */
|
| 896 | in_ie = 1;
|
| 897 | SP = SP - 16; /* push 4 words */
|
| 898 | Write (SP, 12, L_LONG, WA); /* # bytes */
|
| 899 | Write (SP + 4, p1, L_LONG, WA); /* mcheck type */
|
| 900 | Write (SP + 8, p2, L_LONG, WA); /* address */
|
| 901 | Write (SP + 12, st, L_LONG, WA); /* state */
|
| 902 | in_ie = 0;
|
| 903 | return cc;
|
| 904 | }
|
| 905 |
|
| 906 | /* Console entry */
|
| 907 |
|
| 908 | int32 con_halt (int32 code, int32 cc)
|
| 909 | {
|
| 910 | int32 temp;
|
| 911 |
|
| 912 | conisp = IS; /* save ISP */
|
| 913 | conpc = PC; /* save PC */
|
| 914 | conpsl = ((PSL | cc) & 0xFFFF00FF) | code; /* PSL, param */
|
| 915 | temp = (PSL >> PSL_V_CUR) & 0x7; /* get is'cur */
|
| 916 | if (temp > 4) /* invalid? */
|
| 917 | conpsl = conpsl | CON_BADPSL;
|
| 918 | else STK[temp] = SP; /* save stack */
|
| 919 | if (mapen) /* mapping on? */
|
| 920 | conpsl = conpsl | CON_MAPON;
|
| 921 | mapen = 0; /* turn off map */
|
| 922 | SP = IS; /* set SP from IS */
|
| 923 | PSL = PSL_IS | PSL_IPL1F; /* PSL = 41F0000 */
|
| 924 | JUMP (ROMBASE); /* PC = 20040000 */
|
| 925 | return 0; /* new cc = 0 */
|
| 926 | }
|
| 927 |
|
| 928 |
|
| 929 | /* Special boot command - linked into SCP by initial reset
|
| 930 |
|
| 931 | Syntax: BOOT {CPU}
|
| 932 |
|
| 933 | */
|
| 934 |
|
| 935 | t_stat vax630_boot (int32 flag, char *ptr)
|
| 936 | {
|
| 937 | char gbuf[CBUFSIZE];
|
| 938 |
|
| 939 | get_glyph (ptr, gbuf, 0); /* get glyph */
|
| 940 | if (gbuf[0] && strcmp (gbuf, "CPU"))
|
| 941 | return SCPE_ARG; /* Only can specify CPU device */
|
| 942 | return run_cmd (flag, "CPU");
|
| 943 | }
|
| 944 |
|
| 945 |
|
| 946 | /* Bootstrap */
|
| 947 |
|
| 948 | t_stat cpu_boot (int32 unitno, DEVICE *dptr)
|
| 949 | {
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 950 | t_stat r;
|
| 951 |
|
| 952 | PC = ROMBASE;
|
| 953 | PSL = PSL_IS | PSL_IPL1F;
|
| 954 | conisp = 0;
|
| 955 | conpc = 0;
|
| 956 | conpsl = PSL_IS | PSL_IPL1F | CON_PWRUP;
|
| 957 | if (rom == NULL)
|
| 958 | return SCPE_IERR;
|
| 959 | if (*rom == 0) { /* no boot? */
|
| 960 | r = cpu_load_bootcode (BOOT_CODE_FILENAME, BOOT_CODE_ARRAY, BOOT_CODE_SIZE, TRUE, 0);
|
| 961 | if (r != SCPE_OK)
|
| 962 | return r;
|
| 963 | }
|
| 964 | return SCPE_OK;
|
| 965 | }
|
| 966 |
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 967 | t_stat sysd_set_diag (UNIT *uptr, int32 val, char *cptr, void *desc)
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 968 | {
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 969 | if (cptr != NULL) ka_diag_full = strcmp(cptr, "MIN");
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 970 | return SCPE_OK;
|
| 971 | }
|
| 972 |
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 973 | t_stat sysd_show_diag (FILE *st, UNIT *uptr, int32 val, void *desc)
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 974 | {
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 975 | fprintf(st, "DIAG=%s", (ka_diag_full ? "full" :"min"));
|
| 976 | return SCPE_OK;
|
| 977 | }
|
| 978 |
|
| 979 | t_stat sysd_set_halt (UNIT *uptr, int32 val, char *cptr, void *desc)
|
| 980 | {
|
| 981 | ka_hltenab = val;
|
| 982 | return SCPE_OK;
|
| 983 | }
|
| 984 |
|
| 985 | t_stat sysd_show_halt (FILE *st, UNIT *uptr, int32 val, void *desc)
|
| 986 | {
|
| 987 | fprintf(st, "%s", ka_hltenab ? "NOAUTOBOOT" : "AUTOBOOT");
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 988 | return SCPE_OK;
|
| 989 | }
|
| 990 |
|
Mark Pizzolato | d3135b7 | 2013-08-21 13:59:22 -0700 | [diff] [blame] | 991 | t_stat sysd_show_leds (FILE *st, UNIT *uptr, int32 val, void *desc)
|
| 992 | {
|
| 993 | fprintf (st, "leds=(%s,%s,%s,%s)", ka_bdr&8 ? "ON" : "OFF",
|
| 994 | ka_bdr&4 ? "ON" : "OFF",
|
| 995 | ka_bdr&2 ? "ON" : "OFF",
|
| 996 | ka_bdr&1 ? "ON" : "OFF");
|
| 997 | return SCPE_OK;
|
| 998 | }
|
| 999 |
|
| 1000 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1001 | /* SYSD reset */
|
| 1002 |
|
| 1003 | t_stat sysd_reset (DEVICE *dptr)
|
| 1004 | {
|
| 1005 | if (sim_switches & SWMASK ('P')) sysd_powerup (); /* powerup? */
|
| 1006 | ka_bdr = (BDR_POK | \
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 1007 | ((ka_diag_full ? BDC_NORM : BDC_SKPM) << BDR_V_BDC) | \
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1008 | (CPUC_ARB << BDR_V_CPUC) | \
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 1009 | (ka_hltenab ? BDR_BRKENB : 0) | \
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1010 | 0xF);
|
| 1011 | ka_mser = 0;
|
| 1012 | ka_cear = 0;
|
| 1013 | ka_dear = 0;
|
| 1014 |
|
| 1015 | sim_vm_cmd = vax630_cmd;
|
| 1016 |
|
| 1017 | return SCPE_OK;
|
| 1018 | }
|
| 1019 |
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 1020 | const char *sysd_description (DEVICE *dptr)
|
Mark Pizzolato | cbe1114 | 2013-01-25 12:04:25 -0800 | [diff] [blame] | 1021 | {
|
| 1022 | return "system devices";
|
| 1023 | }
|
| 1024 |
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1025 | /* SYSD powerup */
|
| 1026 |
|
| 1027 | t_stat sysd_powerup (void)
|
| 1028 | {
|
Mark Pizzolato | c729942 | 2013-01-26 17:07:27 -0800 | [diff] [blame] | 1029 | ka_diag_full = 0;
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1030 | return SCPE_OK;
|
| 1031 | }
|
| 1032 |
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 1033 | t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc)
|
| 1034 | {
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 1035 | char gbuf[CBUFSIZE];
|
| 1036 |
|
| 1037 | if ((cptr == NULL) || (!*cptr))
|
| 1038 | return SCPE_ARG;
|
| 1039 | cptr = get_glyph (cptr, gbuf, 0);
|
| 1040 | if (MATCH_CMD(gbuf, "MICROVAX") == 0) {
|
Mark Pizzolato | a7a8f3d | 2013-06-13 07:00:32 -0700 | [diff] [blame] | 1041 | sys_model = 0;
|
Mark Pizzolato | 688416a | 2016-01-21 07:37:06 -0800 | [diff] [blame] | 1042 | #if defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL)
|
Mark Pizzolato | a7a8f3d | 2013-06-13 07:00:32 -0700 | [diff] [blame] | 1043 | vc_dev.flags = vc_dev.flags | DEV_DIS; /* disable QVSS */
|
| 1044 | lk_dev.flags = lk_dev.flags | DEV_DIS; /* disable keyboard */
|
| 1045 | vs_dev.flags = vs_dev.flags | DEV_DIS; /* disable mouse */
|
Mark Pizzolato | 688416a | 2016-01-21 07:37:06 -0800 | [diff] [blame] | 1046 | #endif
|
Mark Pizzolato | a7a8f3d | 2013-06-13 07:00:32 -0700 | [diff] [blame] | 1047 | strcpy (sim_name, "MicroVAX II (KA630)");
|
| 1048 | reset_all (0); /* reset everything */
|
| 1049 | }
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 1050 | else if (MATCH_CMD(gbuf, "VAXSTATION") == 0) {
|
Mark Pizzolato | 688416a | 2016-01-21 07:37:06 -0800 | [diff] [blame] | 1051 | #if defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL)
|
Mark Pizzolato | a7a8f3d | 2013-06-13 07:00:32 -0700 | [diff] [blame] | 1052 | sys_model = 1;
|
| 1053 | vc_dev.flags = vc_dev.flags & ~DEV_DIS; /* enable QVSS */
|
| 1054 | lk_dev.flags = lk_dev.flags & ~DEV_DIS; /* enable keyboard */
|
| 1055 | vs_dev.flags = vs_dev.flags & ~DEV_DIS; /* enable mouse */
|
| 1056 | strcpy (sim_name, "VAXStation II (KA630)");
|
| 1057 | reset_all (0); /* reset everything */
|
Mark Pizzolato | 688416a | 2016-01-21 07:37:06 -0800 | [diff] [blame] | 1058 | #else
|
| 1059 | return sim_messagef(SCPE_ARG, "Simulator built without Graphic Device Support");
|
| 1060 | #endif
|
Mark Pizzolato | a7a8f3d | 2013-06-13 07:00:32 -0700 | [diff] [blame] | 1061 | }
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 1062 | else
|
Mark Pizzolato | a7a8f3d | 2013-06-13 07:00:32 -0700 | [diff] [blame] | 1063 | return SCPE_ARG;
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 1064 | return SCPE_OK;
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 1065 | }
|
| 1066 |
|
Mark Pizzolato | 923d541 | 2013-01-15 10:18:49 -0800 | [diff] [blame] | 1067 | t_stat cpu_print_model (FILE *st)
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1068 | {
|
| 1069 | #if defined(VAX_620)
|
Mark Pizzolato | 923d541 | 2013-01-15 10:18:49 -0800 | [diff] [blame] | 1070 | fprintf (st, "rtVAX 1000");
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1071 | #else
|
Mark Pizzolato | b3a9a0d | 2013-06-12 17:10:23 -0700 | [diff] [blame] | 1072 | fprintf (st, (sys_model ? "VAXstation II" : "MicroVAX II"));
|
Mark Pizzolato | b01fa8f | 2012-11-09 12:18:15 -0800 | [diff] [blame] | 1073 | #endif
|
| 1074 | return SCPE_OK;
|
| 1075 | }
|
Mark Pizzolato | 923d541 | 2013-01-15 10:18:49 -0800 | [diff] [blame] | 1076 |
|
Mark Pizzolato | ef9d1ad | 2015-02-13 06:18:24 -0800 | [diff] [blame] | 1077 | t_stat cpu_model_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
Mark Pizzolato | 923d541 | 2013-01-15 10:18:49 -0800 | [diff] [blame] | 1078 | {
|
| 1079 | fprintf (st, "Initial memory size is 16MB.\n\n");
|
Mark Pizzolato | 51badc2 | 2013-03-19 01:52:31 -0700 | [diff] [blame] | 1080 | fprintf (st, "The CPU supports the BOOT command and is the only VAX device to do so. Note\n");
|
| 1081 | fprintf (st, "that the behavior of the bootstrap depends on the capabilities of the console\n");
|
| 1082 | fprintf (st, "terminal emulator. If the terminal window supports full VT100 emulation\n");
|
| 1083 | fprintf (st, "(including Multilanguage Character Set support), the bootstrap will ask the\n");
|
| 1084 | fprintf (st, "user to specify the language; otherwise, it will default to English.\n\n");
|
Mark Pizzolato | 923d541 | 2013-01-15 10:18:49 -0800 | [diff] [blame] | 1085 | fprintf (st, "The simulator is booted with the BOOT command:\n\n");
|
| 1086 | fprintf (st, " sim> BOOT\n\n");
|
| 1087 | return SCPE_OK;
|
| 1088 | }
|
Mark Pizzolato | 96dbeae | 2013-04-08 12:18:09 -0700 | [diff] [blame] | 1089 |
|
| 1090 | t_stat cpu_show_memory (FILE* st, UNIT* uptr, int32 val, void* desc)
|
| 1091 | {
|
| 1092 | uint32 memsize = (uint32)(MEMSIZE>>20);
|
| 1093 | uint32 baseaddr = 0;
|
| 1094 | struct {
|
| 1095 | uint32 capacity;
|
| 1096 | char *option;
|
| 1097 | } boards[] = {
|
| 1098 | { 16, "MS630-CA"},
|
| 1099 | { 4, "MS630-BB"},
|
| 1100 | { 2, "MS630-BA"},
|
| 1101 | { 1, "MS630-AA"},
|
| 1102 | { 0, NULL}};
|
| 1103 | int32 i;
|
| 1104 |
|
| 1105 | while (memsize > 1) {
|
| 1106 | for (i=0; boards[i].capacity > memsize; ++i)
|
| 1107 | ;
|
| 1108 | if (memsize == 2)
|
| 1109 | i = 3;
|
| 1110 | fprintf(st, "Memory (@0x%08x): %3d Mbytes (%s)\n", baseaddr, boards[i].capacity, boards[i].option);
|
| 1111 | memsize -= boards[i].capacity;
|
| 1112 | baseaddr += boards[i].capacity<<20;
|
| 1113 | }
|
| 1114 | if (memsize)
|
| 1115 | fprintf(st, "Memory (0x%08x): 1 Mbytes (On-Board)\n", baseaddr);
|
| 1116 | return SCPE_OK;
|
| 1117 | }
|