First Commit of my working state
[simh.git] / VAX / vax_sysdev.c
CommitLineData
196ba1fc
PH
1/* vax_sysdev.c: VAX 3900 system-specific logic\r
2\r
3 Copyright (c) 1998-2005, 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 This module contains the CVAX chip and VAX 3900 system-specific registers\r
27 and devices.\r
28\r
29 rom bootstrap ROM (no registers)\r
30 nvr non-volatile ROM (no registers)\r
31 csi console storage input\r
32 cso console storage output\r
33 sysd system devices (SSC miscellany)\r
34\r
35 25-Oct-05 RMS Automated CMCTL extended memory\r
36 16-Aug-05 RMS Fixed C++ declaration and cast problems\r
37 10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger)\r
38 30-Sep-04 RMS Moved CADR, MSER, CONPC, CONPSL, machine_check, cpu_boot,\r
39 con_halt here from vax_cpu.c\r
40 Moved model-specific IPR's here from vax_cpu1.c\r
41 09-Sep-04 RMS Integrated powerup into RESET (with -p)\r
42 Added model-specific registers and routines from CPU\r
43 23-Jan-04 MP Added extended physical memory support (Mark Pizzolato)\r
44 07-Jun-03 MP Added calibrated delay to ROM reads (Mark Pizzolato)\r
45 Fixed calibration problems interval timer (Mark Pizzolato)\r
46 12-May-03 RMS Fixed compilation warnings from VC.Net\r
47 23-Apr-03 RMS Revised for 32b/64b t_addr\r
48 19-Aug-02 RMS Removed unused variables (found by David Hittner)\r
49 Allowed NVR to be attached to file\r
50 30-May-02 RMS Widened POS to 32b\r
51 28-Feb-02 RMS Fixed bug, missing end of table (found by Lars Brinkhoff)\r
52*/\r
53\r
54#include "vax_defs.h"\r
55\r
56#define UNIT_V_NODELAY (UNIT_V_UF + 0) /* ROM access equal to RAM access */\r
57#define UNIT_NODELAY (1u << UNIT_V_NODELAY)\r
58\r
59/* Console storage control/status */\r
60\r
61#define CSICSR_IMP (CSR_DONE + CSR_IE) /* console input */\r
62#define CSICSR_RW (CSR_IE)\r
63#define CSOCSR_IMP (CSR_DONE + CSR_IE) /* console output */\r
64#define CSOCSR_RW (CSR_IE)\r
65\r
66/* CMCTL configuration registers */\r
67\r
68#define CMCNF_VLD 0x80000000 /* addr valid */\r
69#define CMCNF_BA 0x1FF00000 /* base addr */\r
70#define CMCNF_LOCK 0x00000040 /* lock NI */\r
71#define CMCNF_SRQ 0x00000020 /* sig req WO */\r
72#define CMCNF_SIG 0x0000001F /* signature */\r
73#define CMCNF_RW (CMCNF_VLD | CMCNF_BA) /* read/write */\r
74#define CMCNF_MASK (CMCNF_RW | CMCNF_SIG)\r
75#define MEM_BANK (1 << 22) /* bank size 4MB */\r
76#define MEM_SIG (0x17) /* ECC, 4 x 4MB */\r
77\r
78/* CMCTL error register */\r
79\r
80#define CMERR_RDS 0x80000000 /* uncorr err NI */\r
81#define CMERR_FRQ 0x40000000 /* 2nd RDS NI */\r
82#define CMERR_CRD 0x20000000 /* CRD err NI */\r
83#define CMERR_PAG 0x1FFFFC00 /* page addr NI */\r
84#define CMERR_DMA 0x00000100 /* DMA err NI */\r
85#define CMERR_BUS 0x00000080 /* bus err NI */\r
86#define CMERR_SYN 0x0000007F /* syndrome NI */\r
87#define CMERR_W1C (CMERR_RDS | CMERR_FRQ | CMERR_CRD | \\r
88 CMERR_DMA | CMERR_BUS)\r
89\r
90/* CMCTL control/status register */\r
91\r
92#define CMCSR_PMI 0x00002000 /* PMI speed NI */\r
93#define CMCSR_CRD 0x00001000 /* enb CRD int NI */\r
94#define CMCSR_FRF 0x00000800 /* force ref WONI */\r
95#define CMCSR_DET 0x00000400 /* dis err NI */\r
96#define CMCSR_FDT 0x00000200 /* fast diag NI */\r
97#define CMCSR_DCM 0x00000080 /* diag mode NI */\r
98#define CMCSR_SYN 0x0000007F /* syndrome NI */\r
99#define CMCSR_MASK (CMCSR_PMI | CMCSR_CRD | CMCSR_DET | \\r
100 CMCSR_FDT | CMCSR_DCM | CMCSR_SYN)\r
101\r
102/* KA655 boot/diagnostic register */\r
103\r
104#define BDR_BRKENB 0x00000080 /* break enable */\r
105\r
106/* KA655 cache control register */\r
107\r
108#define CACR_DRO 0x00FFFF00 /* diag bits RO */\r
109#define CACR_V_DPAR 24 /* data parity */\r
110#define CACR_FIXED 0x00000040 /* fixed bits */\r
111#define CACR_CPE 0x00000020 /* parity err W1C */\r
112#define CACR_CEN 0x00000010 /* enable */ \r
113#define CACR_DPE 0x00000004 /* disable par NI */\r
114#define CACR_WWP 0x00000002 /* write wrong par NI */\r
115#define CACR_DIAG 0x00000001 /* diag mode */\r
116#define CACR_W1C (CACR_CPE)\r
117#define CACR_RW (CACR_CEN | CACR_DPE | CACR_WWP | CACR_DIAG)\r
118\r
119/* SSC base register */\r
120\r
121#define SSCBASE_MBO 0x20000000 /* must be one */\r
122#define SSCBASE_RW 0x1FFFFC00 /* base address */\r
123\r
124/* SSC configuration register */\r
125\r
126#define SSCCNF_BLO 0x80000000 /* batt low W1C */\r
127#define SSCCNF_IVD 0x08000000 /* int dsbl NI */\r
128#define SSCCNF_IPL 0x03000000 /* int IPL NI */\r
129#define SSCCNF_ROM 0x00F70000 /* ROM param NI */\r
130#define SSCCNF_CTLP 0x00008000 /* ctrl P enb */\r
131#define SSCCNF_BAUD 0x00007700 /* baud rates NI */\r
132#define SSCCNF_ADS 0x00000077 /* addr strb NI */\r
133#define SSCCNF_W1C SSCCNF_BLO\r
134#define SSCCNF_RW 0x0BF7F777\r
135\r
136/* SSC timeout register */\r
137\r
138#define SSCBTO_BTO 0x80000000 /* timeout W1C */\r
139#define SSCBTO_RWT 0x40000000 /* read/write W1C */\r
140#define SSCBTO_INTV 0x00FFFFFF /* interval NI */\r
141#define SSCBTO_W1C (SSCBTO_BTO | SSCBTO_RWT)\r
142#define SSCBTO_RW SSCBTO_INTV\r
143\r
144/* SSC output port */\r
145\r
146#define SSCOTP_MASK 0x0000000F /* output port */\r
147\r
148/* SSC timer control/status */\r
149\r
150#define TMR_CSR_ERR 0x80000000 /* error W1C */\r
151#define TMR_CSR_DON 0x00000080 /* done W1C */\r
152#define TMR_CSR_IE 0x00000040 /* int enb */\r
153#define TMR_CSR_SGL 0x00000020 /* single WO */\r
154#define TMR_CSR_XFR 0x00000010 /* xfer WO */\r
155#define TMR_CSR_STP 0x00000004 /* stop */\r
156#define TMR_CSR_RUN 0x00000001 /* run */\r
157#define TMR_CSR_W1C (TMR_CSR_ERR | TMR_CSR_DON)\r
158#define TMR_CSR_RW (TMR_CSR_IE | TMR_CSR_STP | TMR_CSR_RUN)\r
159\r
160/* SSC timer intervals */\r
161\r
162#define TMR_INC 10000 /* usec/interval */\r
163\r
164/* SSC timer vector */\r
165\r
166#define TMR_VEC_MASK 0x000003FC /* vector */\r
167\r
168/* SSC address strobes */\r
169\r
170#define SSCADS_MASK 0x3FFFFFFC /* match or mask */\r
171\r
172extern int32 R[16];\r
173extern int32 STK[5];\r
174extern int32 PSL;\r
175extern int32 SISR;\r
176extern int32 mapen;\r
177extern int32 pcq[PCQ_SIZE];\r
178extern int32 pcq_p;\r
179extern int32 ibcnt, ppc;\r
180extern int32 in_ie;\r
181extern int32 mchk_va, mchk_ref;\r
182extern int32 fault_PC;\r
183extern int32 int_req[IPL_HLVL];\r
184extern UNIT cpu_unit;\r
185extern UNIT clk_unit;\r
186extern jmp_buf save_env;\r
187extern int32 p1;\r
188extern int32 sim_switches;\r
189extern int32 MSER;\r
190extern int32 tmr_poll;\r
191\r
192uint32 *rom = NULL; /* boot ROM */\r
193uint32 *nvr = NULL; /* non-volatile mem */\r
194int32 CADR = 0; /* cache disable reg */\r
195int32 MSER = 0; /* mem sys error reg */\r
196int32 conpc, conpsl; /* console reg */\r
197int32 csi_csr = 0; /* control/status */\r
198int32 cso_csr = 0; /* control/status */\r
199int32 cmctl_reg[CMCTLSIZE >> 2] = { 0 }; /* CMCTL reg */\r
200int32 ka_cacr = 0; /* KA655 cache ctl */\r
201int32 ka_bdr = BDR_BRKENB; /* KA655 boot diag */\r
202int32 ssc_base = SSCBASE; /* SSC base */\r
203int32 ssc_cnf = 0; /* SSC conf */\r
204int32 ssc_bto = 0; /* SSC timeout */\r
205int32 ssc_otp = 0; /* SSC output port */\r
206int32 tmr_csr[2] = { 0 }; /* SSC timers */\r
207uint32 tmr_tir[2] = { 0 }; /* curr interval */\r
208uint32 tmr_tnir[2] = { 0 }; /* next interval */\r
209int32 tmr_tivr[2] = { 0 }; /* vector */\r
210uint32 tmr_inc[2] = { 0 }; /* tir increment */\r
211uint32 tmr_sav[2] = { 0 }; /* saved inst cnt */\r
212int32 ssc_adsm[2] = { 0 }; /* addr strobes */\r
213int32 ssc_adsk[2] = { 0 };\r
214int32 cdg_dat[CDASIZE >> 2]; /* cache data */\r
215static uint32 rom_delay = 0;\r
216\r
217t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);\r
218t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);\r
219t_stat rom_reset (DEVICE *dptr);\r
220t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);\r
221t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);\r
222t_stat nvr_reset (DEVICE *dptr);\r
223t_stat nvr_attach (UNIT *uptr, char *cptr);\r
224t_stat nvr_detach (UNIT *uptr);\r
225t_stat csi_reset (DEVICE *dptr);\r
226t_stat cso_reset (DEVICE *dptr);\r
227t_stat cso_svc (UNIT *uptr);\r
228t_stat tmr_svc (UNIT *uptr);\r
229t_stat sysd_reset (DEVICE *dptr);\r
230\r
231int32 rom_rd (int32 pa);\r
232int32 nvr_rd (int32 pa);\r
233void nvr_wr (int32 pa, int32 val, int32 lnt);\r
234int32 csrs_rd (void);\r
235int32 csrd_rd (void);\r
236int32 csts_rd (void);\r
237void csrs_wr (int32 dat);\r
238void csts_wr (int32 dat);\r
239void cstd_wr (int32 dat);\r
240int32 cmctl_rd (int32 pa);\r
241void cmctl_wr (int32 pa, int32 val, int32 lnt);\r
242int32 ka_rd (int32 pa);\r
243void ka_wr (int32 pa, int32 val, int32 lnt);\r
244int32 cdg_rd (int32 pa);\r
245void cdg_wr (int32 pa, int32 val, int32 lnt);\r
246int32 ssc_rd (int32 pa);\r
247void ssc_wr (int32 pa, int32 val, int32 lnt);\r
248int32 tmr_tir_rd (int32 tmr, t_bool interp);\r
249void tmr_csr_wr (int32 tmr, int32 val);\r
250void tmr_sched (int32 tmr);\r
251void tmr_incr (int32 tmr, uint32 inc);\r
252int32 tmr0_inta (void);\r
253int32 tmr1_inta (void);\r
254int32 parity (int32 val, int32 odd);\r
255t_stat sysd_powerup (void);\r
256\r
257extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);\r
258extern int32 cqmap_rd (int32 pa);\r
259extern void cqmap_wr (int32 pa, int32 val, int32 lnt);\r
260extern int32 cqipc_rd (int32 pa);\r
261extern void cqipc_wr (int32 pa, int32 val, int32 lnt);\r
262extern int32 cqbic_rd (int32 pa);\r
263extern void cqbic_wr (int32 pa, int32 val, int32 lnt);\r
264extern int32 cqmem_rd (int32 pa);\r
265extern void cqmem_wr (int32 pa, int32 val, int32 lnt);\r
266extern int32 iccs_rd (void);\r
267extern int32 todr_rd (void);\r
268extern int32 rxcs_rd (void);\r
269extern int32 rxdb_rd (void);\r
270extern int32 txcs_rd (void);\r
271extern void iccs_wr (int32 dat);\r
272extern void todr_wr (int32 dat);\r
273extern void rxcs_wr (int32 dat);\r
274extern void txcs_wr (int32 dat);\r
275extern void txdb_wr (int32 dat);\r
276extern void ioreset_wr (int32 dat);\r
277extern uint32 sim_os_msec();\r
278\r
279/* ROM data structures\r
280\r
281 rom_dev ROM device descriptor\r
282 rom_unit ROM units\r
283 rom_reg ROM register list\r
284*/\r
285\r
286UNIT rom_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK, ROMSIZE) };\r
287\r
288REG rom_reg[] = {\r
289 { NULL }\r
290 };\r
291\r
292MTAB rom_mod[] = {\r
293 { UNIT_NODELAY, UNIT_NODELAY, "fast access", "NODELAY", NULL },\r
294 { UNIT_NODELAY, 0, "1usec calibrated access", "DELAY", NULL },\r
295 { 0 }\r
296 };\r
297\r
298DEVICE rom_dev = {\r
299 "ROM", &rom_unit, rom_reg, rom_mod,\r
300 1, 16, ROMAWIDTH, 4, 16, 32,\r
301 &rom_ex, &rom_dep, &rom_reset,\r
302 NULL, NULL, NULL,\r
303 NULL, 0\r
304 };\r
305\r
306/* NVR data structures\r
307\r
308 nvr_dev NVR device descriptor\r
309 nvr_unit NVR units\r
310 nvr_reg NVR register list\r
311*/\r
312\r
313UNIT nvr_unit =\r
314 { UDATA (NULL, UNIT_FIX+UNIT_BINK, NVRSIZE) };\r
315\r
316REG nvr_reg[] = {\r
317 { NULL }\r
318 };\r
319\r
320DEVICE nvr_dev = {\r
321 "NVR", &nvr_unit, nvr_reg, NULL,\r
322 1, 16, NVRAWIDTH, 4, 16, 32,\r
323 &nvr_ex, &nvr_dep, &nvr_reset,\r
324 NULL, &nvr_attach, &nvr_detach,\r
325 NULL, 0\r
326 };\r
327\r
328/* CSI data structures\r
329\r
330 csi_dev CSI device descriptor\r
331 csi_unit CSI unit descriptor\r
332 csi_reg CSI register list\r
333*/\r
334\r
335DIB csi_dib = { 0, 0, NULL, NULL, 1, IVCL (CSI), SCB_CSI, { NULL } };\r
336\r
337UNIT csi_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT };\r
338\r
339REG csi_reg[] = {\r
340 { ORDATA (BUF, csi_unit.buf, 8) },\r
341 { ORDATA (CSR, csi_csr, 16) },\r
342 { FLDATA (INT, int_req[IPL_CSI], INT_V_CSI) },\r
343 { FLDATA (DONE, csi_csr, CSR_V_DONE) },\r
344 { FLDATA (IE, csi_csr, CSR_V_IE) },\r
345 { DRDATA (POS, csi_unit.pos, 32), PV_LEFT },\r
346 { DRDATA (TIME, csi_unit.wait, 24), REG_NZ + PV_LEFT },\r
347 { NULL }\r
348 };\r
349\r
350MTAB csi_mod[] = {\r
351 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },\r
352 { 0 }\r
353 };\r
354\r
355DEVICE csi_dev = {\r
356 "CSI", &csi_unit, csi_reg, csi_mod,\r
357 1, 10, 31, 1, 8, 8,\r
358 NULL, NULL, &csi_reset,\r
359 NULL, NULL, NULL,\r
360 &csi_dib, 0\r
361 };\r
362\r
363/* CSO data structures\r
364\r
365 cso_dev CSO device descriptor\r
366 cso_unit CSO unit descriptor\r
367 cso_reg CSO register list\r
368*/\r
369\r
370DIB cso_dib = { 0, 0, NULL, NULL, 1, IVCL (CSO), SCB_CSO, { NULL } };\r
371\r
372UNIT cso_unit = { UDATA (&cso_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };\r
373\r
374REG cso_reg[] = {\r
375 { ORDATA (BUF, cso_unit.buf, 8) },\r
376 { ORDATA (CSR, cso_csr, 16) },\r
377 { FLDATA (INT, int_req[IPL_CSO], INT_V_CSO) },\r
378 { FLDATA (DONE, cso_csr, CSR_V_DONE) },\r
379 { FLDATA (IE, cso_csr, CSR_V_IE) },\r
380 { DRDATA (POS, cso_unit.pos, 32), PV_LEFT },\r
381 { DRDATA (TIME, cso_unit.wait, 24), PV_LEFT },\r
382 { NULL }\r
383 };\r
384\r
385MTAB cso_mod[] = {\r
386 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },\r
387 { 0 }\r
388 };\r
389\r
390DEVICE cso_dev = {\r
391 "CSO", &cso_unit, cso_reg, cso_mod,\r
392 1, 10, 31, 1, 8, 8,\r
393 NULL, NULL, &cso_reset,\r
394 NULL, NULL, NULL,\r
395 &cso_dib, 0\r
396 };\r
397\r
398/* SYSD data structures\r
399\r
400 sysd_dev SYSD device descriptor\r
401 sysd_unit SYSD units\r
402 sysd_reg SYSD register list\r
403*/\r
404\r
405DIB sysd_dib[] = {\r
406 0, 0, NULL, NULL,\r
407 2, IVCL (TMR0), 0, { &tmr0_inta, &tmr1_inta }\r
408 };\r
409\r
410UNIT sysd_unit[] = {\r
411 { UDATA (&tmr_svc, 0, 0) },\r
412 { UDATA (&tmr_svc, 0, 0) }\r
413 };\r
414\r
415REG sysd_reg[] = {\r
416 { HRDATA (CADR, CADR, 8) },\r
417 { HRDATA (MSER, MSER, 8) },\r
418 { HRDATA (CONPC, conpc, 32) },\r
419 { HRDATA (CONPSL, conpsl, 32) },\r
420 { BRDATA (CMCSR, cmctl_reg, 16, 32, CMCTLSIZE >> 2) },\r
421 { HRDATA (CACR, ka_cacr, 8) },\r
422 { HRDATA (BDR, ka_bdr, 8) },\r
423 { HRDATA (BASE, ssc_base, 29) },\r
424 { HRDATA (CNF, ssc_cnf, 32) },\r
425 { HRDATA (BTO, ssc_bto, 32) },\r
426 { HRDATA (OTP, ssc_otp, 4) },\r
427 { HRDATA (TCSR0, tmr_csr[0], 32) },\r
428 { HRDATA (TIR0, tmr_tir[0], 32) },\r
429 { HRDATA (TNIR0, tmr_tnir[0], 32) },\r
430 { HRDATA (TIVEC0, tmr_tivr[0], 9) },\r
431 { HRDATA (TINC0, tmr_inc[0], 32) },\r
432 { HRDATA (TSAV0, tmr_sav[0], 32) },\r
433 { HRDATA (TCSR1, tmr_csr[1], 32) },\r
434 { HRDATA (TIR1, tmr_tir[1], 32) },\r
435 { HRDATA (TNIR1, tmr_tnir[1], 32) },\r
436 { HRDATA (TIVEC1, tmr_tivr[1], 9) },\r
437 { HRDATA (TINC1, tmr_inc[1], 32) },\r
438 { HRDATA (TSAV1, tmr_sav[1], 32) },\r
439 { HRDATA (ADSM0, ssc_adsm[0], 32) },\r
440 { HRDATA (ADSK0, ssc_adsk[0], 32) },\r
441 { HRDATA (ADSM1, ssc_adsm[1], 32) },\r
442 { HRDATA (ADSK1, ssc_adsk[1], 32) },\r
443 { BRDATA (CDGDAT, cdg_dat, 16, 32, CDASIZE >> 2) },\r
444 { NULL }\r
445 };\r
446\r
447DEVICE sysd_dev = {\r
448 "SYSD", sysd_unit, sysd_reg, NULL,\r
449 2, 16, 16, 1, 16, 8,\r
450 NULL, NULL, &sysd_reset,\r
451 NULL, NULL, NULL,\r
452 &sysd_dib, 0\r
453 };\r
454\r
455/* ROM: read only memory - stored in a buffered file\r
456 Register space access routines see ROM twice\r
457\r
458 ROM access has been 'regulated' to about 1Mhz to avoid issues\r
459 with testing the interval timers in self-test. Specifically,\r
460 the VAX boot ROM (ka655.bin) contains code which presumes that\r
461 the VAX runs at a particular slower speed when code is running\r
462 from ROM (which is not cached). These assumptions are built\r
463 into instruction based timing loops. As the host platform gets\r
464 much faster than the original VAX, the assumptions embedded in\r
465 these code loops are no longer valid.\r
466 \r
467 Code has been added to the ROM implementation to limit CPU speed\r
468 to about 500K instructions per second. This heads off any future\r
469 issues with the embedded timing loops. \r
470*/\r
471\r
472int32 rom_swapb(int32 val)\r
473{\r
474return ((val << 24) & 0xff000000) | (( val << 8) & 0xff0000) |\r
475 ((val >> 8) & 0xff00) | ((val >> 24) & 0xff);\r
476}\r
477\r
478int32 rom_read_delay (int32 val)\r
479{\r
480uint32 i, l = rom_delay;\r
481int32 loopval = 0;\r
482\r
483if (rom_unit.flags & UNIT_NODELAY) return val;\r
484\r
485/* Calibrate the loop delay factor when first used.\r
486 Do this 4 times to and use the largest value computed. */\r
487\r
488if (rom_delay == 0) {\r
489 uint32 ts, te, c = 10000, samples = 0;\r
490 while (1) {\r
491 c = c * 2;\r
492 te = sim_os_msec();\r
493 while (te == (ts = sim_os_msec ())); /* align on ms tick */\r
494\r
495/* This is merely a busy wait with some "work" that won't get optimized\r
496 away by a good compiler. loopval always is zero. To avoid smart compilers,\r
497 the loopval variable is referenced in the function arguments so that the\r
498 function expression is not loop invariant. It also must be referenced\r
499 by subsequent code or to avoid the whole computation being eliminated. */\r
500\r
501 for (i = 0; i < c; i++)\r
502 loopval |= (loopval + ts) ^ rom_swapb (rom_swapb (loopval + ts));\r
503 te = sim_os_msec (); \r
504 if ((te - ts) < 50) continue; /* sample big enough? */\r
505 if (rom_delay < (loopval + (c / (te - ts) / 1000) + 1))\r
506 rom_delay = loopval + (c / (te - ts) / 1000) + 1;\r
507 if (++samples >= 4) break;\r
508 c = c / 2;\r
509 }\r
510 if (rom_delay < 5) rom_delay = 5;\r
511 }\r
512\r
513for (i = 0; i < l; i++)\r
514 loopval |= (loopval + val) ^ rom_swapb (rom_swapb (loopval + val));\r
515return val + loopval;\r
516}\r
517\r
518int32 rom_rd (int32 pa)\r
519{\r
520int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2;\r
521\r
522return rom_read_delay (rom[rg]);\r
523}\r
524\r
525void rom_wr_B (int32 pa, int32 val)\r
526{\r
527int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2;\r
528int32 sc = (pa & 3) << 3;\r
529\r
530rom[rg] = ((val & 0xFF) << sc) | (rom[rg] & ~(0xFF << sc));\r
531return;\r
532}\r
533\r
534/* ROM examine */\r
535\r
536t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)\r
537{\r
538uint32 addr = (uint32) exta;\r
539\r
540if ((vptr == NULL) || (addr & 03)) return SCPE_ARG;\r
541if (addr >= ROMSIZE) return SCPE_NXM;\r
542*vptr = rom[addr >> 2];\r
543return SCPE_OK;\r
544}\r
545\r
546/* ROM deposit */\r
547\r
548t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)\r
549{\r
550uint32 addr = (uint32) exta;\r
551\r
552if (addr & 03) return SCPE_ARG;\r
553if (addr >= ROMSIZE) return SCPE_NXM;\r
554rom[addr >> 2] = (uint32) val;\r
555return SCPE_OK;\r
556}\r
557\r
558/* ROM reset */\r
559\r
560t_stat rom_reset (DEVICE *dptr)\r
561{\r
562if (rom == NULL) rom = (uint32 *) calloc (ROMSIZE >> 2, sizeof (uint32));\r
563if (rom == NULL) return SCPE_MEM;\r
564return SCPE_OK;\r
565}\r
566\r
567/* NVR: non-volatile RAM - stored in a buffered file */\r
568\r
569int32 nvr_rd (int32 pa)\r
570{\r
571int32 rg = (pa - NVRBASE) >> 2;\r
572\r
573return nvr[rg];\r
574}\r
575\r
576void nvr_wr (int32 pa, int32 val, int32 lnt)\r
577{\r
578int32 rg = (pa - NVRBASE) >> 2;\r
579\r
580if (lnt < L_LONG) { /* byte or word? */\r
581 int32 sc = (pa & 3) << 3; /* merge */\r
582 int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF;\r
583 nvr[rg] = ((val & mask) << sc) | (nvr[rg] & ~(mask << sc));\r
584 }\r
585else nvr[rg] = val;\r
586return;\r
587}\r
588\r
589/* NVR examine */\r
590\r
591t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)\r
592{\r
593uint32 addr = (uint32) exta;\r
594\r
595if ((vptr == NULL) || (addr & 03)) return SCPE_ARG;\r
596if (addr >= NVRSIZE) return SCPE_NXM;\r
597*vptr = nvr[addr >> 2];\r
598return SCPE_OK;\r
599}\r
600\r
601/* NVR deposit */\r
602\r
603t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)\r
604{\r
605uint32 addr = (uint32) exta;\r
606\r
607if (addr & 03) return SCPE_ARG;\r
608if (addr >= NVRSIZE) return SCPE_NXM;\r
609nvr[addr >> 2] = (uint32) val;\r
610return SCPE_OK;\r
611}\r
612\r
613/* NVR reset */\r
614\r
615t_stat nvr_reset (DEVICE *dptr)\r
616{\r
617if (nvr == NULL) {\r
618 nvr = (uint32 *) calloc (NVRSIZE >> 2, sizeof (uint32));\r
619 nvr_unit.filebuf = nvr;\r
620 ssc_cnf = ssc_cnf | SSCCNF_BLO;\r
621 }\r
622if (nvr == NULL) return SCPE_MEM;\r
623return SCPE_OK;\r
624}\r
625\r
626/* NVR attach */\r
627\r
628t_stat nvr_attach (UNIT *uptr, char *cptr)\r
629{\r
630t_stat r;\r
631\r
632uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE);\r
633r = attach_unit (uptr, cptr);\r
634if (r != SCPE_OK)\r
635 uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);\r
636else {\r
637 uptr->hwmark = (uint32) uptr->capac;\r
638 ssc_cnf = ssc_cnf & ~SSCCNF_BLO;\r
639 }\r
640return r;\r
641}\r
642\r
643/* NVR detach */\r
644\r
645t_stat nvr_detach (UNIT *uptr)\r
646{\r
647t_stat r;\r
648\r
649r = detach_unit (uptr);\r
650if ((uptr->flags & UNIT_ATT) == 0)\r
651 uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);\r
652return r;\r
653}\r
654\r
655/* CSI: console storage input */\r
656\r
657int32 csrs_rd (void)\r
658{\r
659return (csi_csr & CSICSR_IMP);\r
660}\r
661\r
662int32 csrd_rd (void)\r
663{\r
664csi_csr = csi_csr & ~CSR_DONE;\r
665CLR_INT (CSI);\r
666return (csi_unit.buf & 0377);\r
667}\r
668\r
669void csrs_wr (int32 data)\r
670{\r
671if ((data & CSR_IE) == 0) CLR_INT (CSI);\r
672else if ((csi_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)\r
673 SET_INT (CSI);\r
674csi_csr = (csi_csr & ~CSICSR_RW) | (data & CSICSR_RW);\r
675return;\r
676}\r
677\r
678t_stat csi_reset (DEVICE *dptr)\r
679{\r
680csi_unit.buf = 0;\r
681csi_csr = 0;\r
682CLR_INT (CSI);\r
683return SCPE_OK;\r
684}\r
685\r
686/* CSO: console storage output */\r
687\r
688int32 csts_rd (void)\r
689{\r
690return (cso_csr & CSOCSR_IMP);\r
691}\r
692\r
693void csts_wr (int32 data)\r
694{\r
695if ((data & CSR_IE) == 0) CLR_INT (CSO);\r
696else if ((cso_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)\r
697 SET_INT (CSO);\r
698cso_csr = (cso_csr & ~CSOCSR_RW) | (data & CSOCSR_RW);\r
699return;\r
700}\r
701\r
702void cstd_wr (int32 data)\r
703{\r
704cso_unit.buf = data & 0377;\r
705cso_csr = cso_csr & ~CSR_DONE;\r
706CLR_INT (CSO);\r
707sim_activate (&cso_unit, cso_unit.wait);\r
708return;\r
709}\r
710\r
711t_stat cso_svc (UNIT *uptr)\r
712{\r
713cso_csr = cso_csr | CSR_DONE;\r
714if (cso_csr & CSR_IE) SET_INT (CSO);\r
715if ((cso_unit.flags & UNIT_ATT) == 0) return SCPE_OK;\r
716if (putc (cso_unit.buf, cso_unit.fileref) == EOF) {\r
717 perror ("CSO I/O error");\r
718 clearerr (cso_unit.fileref);\r
719 return SCPE_IOERR;\r
720 }\r
721cso_unit.pos = cso_unit.pos + 1;\r
722return SCPE_OK;\r
723}\r
724\r
725t_stat cso_reset (DEVICE *dptr)\r
726{\r
727cso_unit.buf = 0;\r
728cso_csr = CSR_DONE;\r
729CLR_INT (CSO);\r
730sim_cancel (&cso_unit); /* deactivate unit */\r
731return SCPE_OK;\r
732}\r
733\r
734/* SYSD: SSC access mechanisms and devices\r
735\r
736 - IPR space read/write routines\r
737 - register space read/write routines\r
738 - SSC local register read/write routines\r
739 - SSC console storage UART\r
740 - SSC timers\r
741 - CMCTL local register read/write routines\r
742*/\r
743\r
744/* Read/write IPR register space\r
745\r
746 These routines implement the SSC's response to IPR's which are\r
747 sent off the CPU chip for processing.\r
748*/\r
749\r
750int32 ReadIPR (int32 rg)\r
751{\r
752int32 val;\r
753\r
754switch (rg) {\r
755\r
756 case MT_ICCS: /* ICCS */\r
757 val = iccs_rd ();\r
758 break;\r
759\r
760 case MT_CSRS: /* CSRS */\r
761 val = csrs_rd ();\r
762 break;\r
763\r
764 case MT_CSRD: /* CSRD */\r
765 val = csrd_rd ();\r
766 break;\r
767\r
768 case MT_CSTS: /* CSTS */\r
769 val = csts_rd ();\r
770 break;\r
771\r
772 case MT_CSTD: /* CSTD */\r
773 val = 0;\r
774 break;\r
775\r
776 case MT_RXCS: /* RXCS */\r
777 val = rxcs_rd ();\r
778 break;\r
779\r
780 case MT_RXDB: /* RXDB */\r
781 val = rxdb_rd ();\r
782 break;\r
783\r
784 case MT_TXCS: /* TXCS */\r
785 val = txcs_rd ();\r
786 break;\r
787\r
788 case MT_TXDB: /* TXDB */\r
789 val = 0;\r
790 break;\r
791\r
792 case MT_TODR: /* TODR */\r
793 val = todr_rd ();\r
794 break;\r
795\r
796 case MT_CADR: /* CADR */\r
797 val = CADR & 0xFF;\r
798 break;\r
799\r
800 case MT_MSER: /* MSER */\r
801 val = MSER & 0xFF;\r
802 break;\r
803\r
804 case MT_CONPC: /* console PC */\r
805 val = conpc;\r
806 break;\r
807\r
808 case MT_CONPSL: /* console PSL */\r
809 val = conpsl;\r
810 break;\r
811\r
812 case MT_SID: /* SID */\r
813 val = CVAX_SID | CVAX_UREV;\r
814 break;\r
815\r
816 default:\r
817 ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */\r
818 val = 0;\r
819 break;\r
820 }\r
821\r
822return val;\r
823}\r
824\r
825void WriteIPR (int32 rg, int32 val)\r
826{\r
827switch (rg) {\r
828\r
829 case MT_ICCS: /* ICCS */\r
830 iccs_wr (val);\r
831 break;\r
832\r
833 case MT_TODR: /* TODR */\r
834 todr_wr (val);\r
835 break;\r
836\r
837 case MT_CSRS: /* CSRS */\r
838 csrs_wr (val);\r
839 break;\r
840\r
841 case MT_CSRD: /* CSRD */\r
842 break;\r
843\r
844 case MT_CSTS: /* CSTS */\r
845 csts_wr (val);\r
846 break;\r
847\r
848 case MT_CSTD: /* CSTD */\r
849 cstd_wr (val);\r
850 break;\r
851\r
852 case MT_RXCS: /* RXCS */\r
853 rxcs_wr (val);\r
854 break;\r
855\r
856 case MT_RXDB: /* RXDB */\r
857 break;\r
858\r
859 case MT_TXCS: /* TXCS */\r
860 txcs_wr (val);\r
861 break;\r
862\r
863 case MT_TXDB: /* TXDB */\r
864 txdb_wr (val);\r
865 break;\r
866\r
867 case MT_CADR: /* CADR */\r
868 CADR = (val & CADR_RW) | CADR_MBO;\r
869 break;\r
870\r
871 case MT_MSER: /* MSER */\r
872 MSER = MSER & MSER_HM;\r
873 break;\r
874\r
875 case MT_IORESET: /* IORESET */\r
876 ioreset_wr (val);\r
877 break;\r
878\r
879 case MT_SID:\r
880 case MT_CONPC:\r
881 case MT_CONPSL: /* halt reg */\r
882 RSVD_OPND_FAULT;\r
883\r
884 default:\r
885 ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */\r
886 break;\r
887 }\r
888\r
889return;\r
890}\r
891\r
892/* Read/write I/O register space\r
893\r
894 These routines are the 'catch all' for address space map. Any\r
895 address that doesn't explicitly belong to memory, I/O, or ROM\r
896 is given to these routines for processing.\r
897*/\r
898\r
899struct reglink { /* register linkage */\r
900 uint32 low; /* low addr */\r
901 uint32 high; /* high addr */\r
902 t_stat (*read)(int32 pa); /* read routine */\r
903 void (*write)(int32 pa, int32 val, int32 lnt); /* write routine */\r
904 };\r
905\r
906struct reglink regtable[] = {\r
907 { CQMAPBASE, CQMAPBASE+CQMAPSIZE, &cqmap_rd, &cqmap_wr },\r
908 { ROMBASE, ROMBASE+ROMSIZE+ROMSIZE, &rom_rd, NULL },\r
909 { NVRBASE, NVRBASE+NVRSIZE, &nvr_rd, &nvr_wr },\r
910 { CMCTLBASE, CMCTLBASE+CMCTLSIZE, &cmctl_rd, &cmctl_wr },\r
911 { SSCBASE, SSCBASE+SSCSIZE, &ssc_rd, &ssc_wr },\r
912 { KABASE, KABASE+KASIZE, &ka_rd, &ka_wr },\r
913 { CQBICBASE, CQBICBASE+CQBICSIZE, &cqbic_rd, &cqbic_wr },\r
914 { CQIPCBASE, CQIPCBASE+CQIPCSIZE, &cqipc_rd, &cqipc_wr },\r
915 { CQMBASE, CQMBASE+CQMSIZE, &cqmem_rd, &cqmem_wr },\r
916 { CDGBASE, CDGBASE+CDGSIZE, &cdg_rd, &cdg_wr },\r
917 { 0, 0, NULL, NULL }\r
918 };\r
919\r
920/* ReadReg - read register space\r
921\r
922 Inputs:\r
923 pa = physical address\r
924 lnt = length (BWLQ) - ignored\r
925 Output:\r
926 longword of data\r
927*/\r
928\r
929int32 ReadReg (uint32 pa, int32 lnt)\r
930{\r
931struct reglink *p;\r
932\r
933for (p = &regtable[0]; p->low != 0; p++) {\r
934 if ((pa >= p->low) && (pa < p->high) && p->read)\r
935 return p->read (pa);\r
936 }\r
937ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT;\r
938MACH_CHECK (MCHK_READ);\r
939return 0;\r
940}\r
941\r
942/* WriteReg - write register space\r
943\r
944 Inputs:\r
945 pa = physical address\r
946 val = data to write, right justified in 32b longword\r
947 lnt = length (BWLQ)\r
948 Outputs:\r
949 none\r
950*/\r
951\r
952void WriteReg (uint32 pa, int32 val, int32 lnt)\r
953{\r
954struct reglink *p;\r
955\r
956for (p = &regtable[0]; p->low != 0; p++) {\r
957 if ((pa >= p->low) && (pa < p->high) && p->write) {\r
958 p->write (pa, val, lnt); \r
959 return;\r
960 }\r
961 }\r
962ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT;\r
963MACH_CHECK (MCHK_WRITE);\r
964return;\r
965}\r
966\r
967/* CMCTL registers\r
968\r
969 CMCTL00 - 15 configure memory banks 00 - 15. Note that they are\r
970 here merely to entertain the firmware; the actual configuration\r
971 of memory is unaffected by the settings here.\r
972\r
973 CMCTL16 - error status register\r
974\r
975 CMCTL17 - control/diagnostic status register\r
976\r
977 The CMCTL registers are cleared at power up.\r
978*/\r
979\r
980int32 cmctl_rd (int32 pa)\r
981{\r
982int32 rg = (pa - CMCTLBASE) >> 2;\r
983\r
984switch (rg) {\r
985\r
986 default: /* config reg */\r
987 return cmctl_reg[rg] & CMCNF_MASK;\r
988\r
989 case 16: /* err status */\r
990 return cmctl_reg[rg];\r
991\r
992 case 17: /* csr */\r
993 return cmctl_reg[rg] & CMCSR_MASK;\r
994\r
995 case 18: /* KA655X ext mem */\r
996 if (MEMSIZE > MAXMEMSIZE) /* more than 128MB? */\r
997 return ((int32) MEMSIZE);\r
998 MACH_CHECK (MCHK_READ);\r
999 }\r
1000\r
1001return 0;\r
1002}\r
1003\r
1004void cmctl_wr (int32 pa, int32 val, int32 lnt)\r
1005{\r
1006int32 i, rg = (pa - CMCTLBASE) >> 2;\r
1007\r
1008if (lnt < L_LONG) { /* LW write only */\r
1009 int32 sc = (pa & 3) << 3; /* shift data to */\r
1010 val = val << sc; /* proper location */\r
1011 }\r
1012switch (rg) {\r
1013\r
1014 default: /* config reg */\r
1015 if (val & CMCNF_SRQ) { /* sig request? */\r
1016 int32 rg_g = rg & ~3; /* group of 4 */\r
1017 for (i = rg_g; i < (rg_g + 4); i++) {\r
1018 cmctl_reg[i] = cmctl_reg[i] & ~CMCNF_SIG;\r
1019 if (ADDR_IS_MEM (i * MEM_BANK))\r
1020 cmctl_reg[i] = cmctl_reg[i] | MEM_SIG;\r
1021 }\r
1022 }\r
1023 cmctl_reg[rg] = (cmctl_reg[rg] & ~CMCNF_RW) | (val & CMCNF_RW);\r
1024 break;\r
1025\r
1026 case 16: /* err status */\r
1027 cmctl_reg[rg] = cmctl_reg[rg] & ~(val & CMERR_W1C);\r
1028 break;\r
1029\r
1030 case 17: /* csr */\r
1031 cmctl_reg[rg] = val & CMCSR_MASK;\r
1032 break;\r
1033\r
1034 case 18:\r
1035 MACH_CHECK (MCHK_WRITE);\r
1036 }\r
1037\r
1038return;\r
1039}\r
1040\r
1041/* KA655 registers */\r
1042\r
1043int32 ka_rd (int32 pa)\r
1044{\r
1045int32 rg = (pa - KABASE) >> 2;\r
1046\r
1047switch (rg) {\r
1048\r
1049 case 0: /* CACR */\r
1050 return ka_cacr;\r
1051\r
1052 case 1: /* BDR */\r
1053 return ka_bdr;\r
1054 }\r
1055\r
1056return 0;\r
1057}\r
1058\r
1059void ka_wr (int32 pa, int32 val, int32 lnt)\r
1060{\r
1061int32 rg = (pa - KABASE) >> 2;\r
1062\r
1063if ((rg == 0) && ((pa & 3) == 0)) { /* lo byte only */\r
1064 ka_cacr = (ka_cacr & ~(val & CACR_W1C)) | CACR_FIXED;\r
1065 ka_cacr = (ka_cacr & ~CACR_RW) | (val & CACR_RW);\r
1066 }\r
1067return;\r
1068}\r
1069\r
1070int32 sysd_hlt_enb (void)\r
1071{\r
1072return ka_bdr & BDR_BRKENB;\r
1073}\r
1074\r
1075/* Cache diagnostic space */\r
1076\r
1077int32 cdg_rd (int32 pa)\r
1078{\r
1079int32 t, row = CDG_GETROW (pa);\r
1080\r
1081t = cdg_dat[row];\r
1082ka_cacr = ka_cacr & ~CACR_DRO; /* clear diag */\r
1083ka_cacr = ka_cacr |\r
1084 (parity ((t >> 24) & 0xFF, 1) << (CACR_V_DPAR + 3)) |\r
1085 (parity ((t >> 16) & 0xFF, 0) << (CACR_V_DPAR + 2)) |\r
1086 (parity ((t >> 8) & 0xFF, 1) << (CACR_V_DPAR + 1)) |\r
1087 (parity (t & 0xFF, 0) << CACR_V_DPAR);\r
1088return t;\r
1089}\r
1090\r
1091void cdg_wr (int32 pa, int32 val, int32 lnt)\r
1092{\r
1093int32 row = CDG_GETROW (pa);\r
1094\r
1095if (lnt < L_LONG) { /* byte or word? */\r
1096 int32 sc = (pa & 3) << 3; /* merge */\r
1097 int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF;\r
1098 int32 t = cdg_dat[row];\r
1099 val = ((val & mask) << sc) | (t & ~(mask << sc));\r
1100 }\r
1101cdg_dat[row] = val; /* store data */\r
1102return;\r
1103}\r
1104\r
1105int32 parity (int32 val, int32 odd)\r
1106{\r
1107for ( ; val != 0; val = val >> 1) {\r
1108 if (val & 1) odd = odd ^ 1;\r
1109 }\r
1110return odd;\r
1111}\r
1112\r
1113/* SSC registers - byte/word merges done in WriteReg */\r
1114\r
1115int32 ssc_rd (int32 pa)\r
1116{\r
1117int32 rg = (pa - SSCBASE) >> 2;\r
1118\r
1119switch (rg) {\r
1120\r
1121 case 0x00: /* base reg */\r
1122 return ssc_base;\r
1123\r
1124 case 0x04: /* conf reg */\r
1125 return ssc_cnf;\r
1126\r
1127 case 0x08: /* bus timeout */\r
1128 return ssc_bto;\r
1129\r
1130 case 0x0C: /* output port */\r
1131 return ssc_otp & SSCOTP_MASK;\r
1132\r
1133 case 0x1B: /* TODR */\r
1134 return todr_rd ();\r
1135\r
1136 case 0x1C: /* CSRS */\r
1137 return csrs_rd ();\r
1138\r
1139 case 0x1D: /* CSRD */\r
1140 return csrd_rd ();\r
1141\r
1142 case 0x1E: /* CSTS */\r
1143 return csts_rd ();\r
1144\r
1145 case 0x20: /* RXCS */\r
1146 return rxcs_rd ();\r
1147\r
1148 case 0x21: /* RXDB */\r
1149 return rxdb_rd ();\r
1150\r
1151 case 0x22: /* TXCS */\r
1152 return txcs_rd ();\r
1153\r
1154 case 0x40: /* T0CSR */\r
1155 return tmr_csr[0];\r
1156\r
1157 case 0x41: /* T0INT */\r
1158 return tmr_tir_rd (0, FALSE);\r
1159\r
1160 case 0x42: /* T0NI */\r
1161 return tmr_tnir[0];\r
1162\r
1163 case 0x43: /* T0VEC */\r
1164 return tmr_tivr[0];\r
1165\r
1166 case 0x44: /* T1CSR */\r
1167 return tmr_csr[1];\r
1168\r
1169 case 0x45: /* T1INT */\r
1170 return tmr_tir_rd (1, FALSE);\r
1171\r
1172 case 0x46: /* T1NI */\r
1173 return tmr_tnir[1];\r
1174\r
1175 case 0x47: /* T1VEC */\r
1176 return tmr_tivr[1];\r
1177\r
1178 case 0x4C: /* ADS0M */\r
1179 return ssc_adsm[0];\r
1180\r
1181 case 0x4D: /* ADS0K */\r
1182 return ssc_adsk[0];\r
1183\r
1184 case 0x50: /* ADS1M */\r
1185 return ssc_adsm[1];\r
1186\r
1187 case 0x51: /* ADS1K */\r
1188 return ssc_adsk[1];\r
1189 }\r
1190\r
1191return 0;\r
1192}\r
1193\r
1194void ssc_wr (int32 pa, int32 val, int32 lnt)\r
1195{\r
1196int32 rg = (pa - SSCBASE) >> 2;\r
1197\r
1198if (lnt < L_LONG) { /* byte or word? */\r
1199 int32 sc = (pa & 3) << 3; /* merge */\r
1200 int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF;\r
1201 int32 t = ssc_rd (pa);\r
1202 val = ((val & mask) << sc) | (t & ~(mask << sc));\r
1203 }\r
1204\r
1205switch (rg) {\r
1206\r
1207 case 0x00: /* base reg */\r
1208 ssc_base = (val & SSCBASE_RW) | SSCBASE_MBO;\r
1209 break;\r
1210\r
1211 case 0x04: /* conf reg */\r
1212 ssc_cnf = ssc_cnf & ~(val & SSCCNF_W1C);\r
1213 ssc_cnf = (ssc_cnf & ~SSCCNF_RW) | (val & SSCCNF_RW);\r
1214 break;\r
1215\r
1216 case 0x08: /* bus timeout */\r
1217 ssc_bto = ssc_bto & ~(val & SSCBTO_W1C);\r
1218 ssc_bto = (ssc_bto & ~SSCBTO_RW) | (val & SSCBTO_RW);\r
1219 break;\r
1220\r
1221 case 0x0C: /* output port */\r
1222 ssc_otp = val & SSCOTP_MASK;\r
1223 break;\r
1224\r
1225 case 0x1B: /* TODR */\r
1226 todr_wr (val);\r
1227 break;\r
1228\r
1229 case 0x1C: /* CSRS */\r
1230 csrs_wr (val);\r
1231 break;\r
1232\r
1233 case 0x1E: /* CSTS */\r
1234 csts_wr (val);\r
1235 break;\r
1236\r
1237 case 0x1F: /* CSTD */\r
1238 cstd_wr (val);\r
1239 break;\r
1240\r
1241 case 0x20: /* RXCS */\r
1242 rxcs_wr (val);\r
1243 break;\r
1244\r
1245 case 0x22: /* TXCS */\r
1246 txcs_wr (val);\r
1247 break;\r
1248\r
1249 case 0x23: /* TXDB */\r
1250 txdb_wr (val);\r
1251 break;\r
1252\r
1253 case 0x40: /* T0CSR */\r
1254 tmr_csr_wr (0, val);\r
1255 break;\r
1256\r
1257 case 0x42: /* T0NI */\r
1258 tmr_tnir[0] = val;\r
1259 break;\r
1260\r
1261 case 0x43: /* T0VEC */\r
1262 tmr_tivr[0] = val & TMR_VEC_MASK;\r
1263 break;\r
1264\r
1265 case 0x44: /* T1CSR */\r
1266 tmr_csr_wr (1, val);\r
1267 break;\r
1268\r
1269 case 0x46: /* T1NI */\r
1270 tmr_tnir[1] = val;\r
1271 break;\r
1272\r
1273 case 0x47: /* T1VEC */\r
1274 tmr_tivr[1] = val & TMR_VEC_MASK;\r
1275 break;\r
1276\r
1277 case 0x4C: /* ADS0M */\r
1278 ssc_adsm[0] = val & SSCADS_MASK;\r
1279 break;\r
1280\r
1281 case 0x4D: /* ADS0K */\r
1282 ssc_adsk[0] = val & SSCADS_MASK;\r
1283 break;\r
1284\r
1285 case 0x50: /* ADS1M */\r
1286 ssc_adsm[1] = val & SSCADS_MASK;\r
1287 break;\r
1288\r
1289 case 0x51: /* ADS1K */\r
1290 ssc_adsk[1] = val & SSCADS_MASK;\r
1291 break;\r
1292 }\r
1293\r
1294return;\r
1295}\r
1296\r
1297/* Programmable timers\r
1298\r
1299 The SSC timers, which increment at 1Mhz, cannot be accurately\r
1300 simulated due to the overhead that would be required for 1M\r
1301 clock events per second. Instead, a gross hack is used. When\r
1302 a timer is started, the clock interval is inspected.\r
1303\r
1304 if (int < 0 and small) then testing timer, count instructions.\r
1305 Small is determined by when the requested interval is less\r
1306 than the size of a 100hz system clock tick.\r
1307 if (int >= 0 or large) then counting a real interval, schedule\r
1308 clock events at 100Hz using calibrated line clock delay\r
1309 and when the remaining time value gets small enough, behave\r
1310 like the small case above.\r
1311\r
1312 If the interval register is read, then its value between events\r
1313 is interpolated using the current instruction count versus the\r
1314 count when the most recent event started, the result is scaled\r
1315 to the calibrated system clock, unless the interval being timed\r
1316 is less than a calibrated system clock tick (or the calibrated \r
1317 clock is running very slowly) at which time the result will be \r
1318 the elapsed instruction count.\r
1319\r
1320 The powerup TOY Test sometimes fails its tolerance test. This was\r
1321 due to varying system load causing varying calibration values to be\r
1322 used at different times while referencing the TIR. While timing long\r
1323 intervals, we now synchronize the stepping (and calibration) of the\r
1324 system tick with the opportunity to reference the value. This gives\r
1325 precise tolerance measurement values (when interval timers are used\r
1326 to measure the system clock), regardless of other load issues on the\r
1327 host system which might cause varying values of the system clock's\r
1328 calibration factor.\r
1329*/\r
1330\r
1331int32 tmr_tir_rd (int32 tmr, t_bool interp)\r
1332{\r
1333uint32 delta;\r
1334\r
1335if (interp || (tmr_csr[tmr] & TMR_CSR_RUN)) { /* interp, running? */\r
1336 delta = sim_grtime () - tmr_sav[tmr]; /* delta inst */\r
1337 if ((tmr_inc[tmr] == TMR_INC) && /* scale large int */\r
1338 (tmr_poll > TMR_INC))\r
1339 delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll);\r
1340 if (delta >= tmr_inc[tmr]) delta = tmr_inc[tmr] - 1;\r
1341 return tmr_tir[tmr] + delta;\r
1342 }\r
1343return tmr_tir[tmr];\r
1344}\r
1345\r
1346void tmr_csr_wr (int32 tmr, int32 val)\r
1347{\r
1348if ((tmr < 0) || (tmr > 1)) return;\r
1349if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */\r
1350 sim_cancel (&sysd_unit[tmr]); /* cancel timer */\r
1351 if (tmr_csr[tmr] & TMR_CSR_RUN) /* run 1 -> 0? */\r
1352 tmr_tir[tmr] = tmr_tir_rd (tmr, TRUE); /* update itr */\r
1353 }\r
1354tmr_csr[tmr] = tmr_csr[tmr] & ~(val & TMR_CSR_W1C); /* W1C csr */\r
1355tmr_csr[tmr] = (tmr_csr[tmr] & ~TMR_CSR_RW) | /* new r/w */\r
1356 (val & TMR_CSR_RW);\r
1357if (val & TMR_CSR_XFR) tmr_tir[tmr] = tmr_tnir[tmr]; /* xfr set? */\r
1358if (val & TMR_CSR_RUN) { /* run? */\r
1359 if (val & TMR_CSR_XFR) /* new tir? */\r
1360 sim_cancel (&sysd_unit[tmr]); /* stop prev */\r
1361 if (!sim_is_active (&sysd_unit[tmr])) /* not running? */\r
1362 tmr_sched (tmr); /* activate */\r
1363 }\r
1364else if (val & TMR_CSR_SGL) { /* single step? */\r
1365 tmr_incr (tmr, 1); /* incr tmr */\r
1366 if (tmr_tir[tmr] == 0) /* if ovflo, */\r
1367 tmr_tir[tmr] = tmr_tnir[tmr]; /* reload tir */\r
1368 }\r
1369if ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */\r
1370 (TMR_CSR_DON | TMR_CSR_IE)) {\r
1371 if (tmr) CLR_INT (TMR1);\r
1372 else CLR_INT (TMR0);\r
1373 }\r
1374return;\r
1375}\r
1376\r
1377/* Unit service */\r
1378\r
1379t_stat tmr_svc (UNIT *uptr)\r
1380{\r
1381int32 tmr = uptr - sysd_dev.units; /* get timer # */\r
1382\r
1383tmr_incr (tmr, tmr_inc[tmr]); /* incr timer */\r
1384return SCPE_OK;\r
1385}\r
1386\r
1387/* Timer increment */\r
1388\r
1389void tmr_incr (int32 tmr, uint32 inc)\r
1390{\r
1391uint32 new_tir = tmr_tir[tmr] + inc; /* add incr */\r
1392\r
1393if (new_tir < tmr_tir[tmr]) { /* ovflo? */\r
1394 tmr_tir[tmr] = 0; /* now 0 */\r
1395 if (tmr_csr[tmr] & TMR_CSR_DON) /* done? set err */\r
1396 tmr_csr[tmr] = tmr_csr[tmr] | TMR_CSR_ERR;\r
1397 else tmr_csr[tmr] = tmr_csr[tmr] | TMR_CSR_DON; /* set done */\r
1398 if (tmr_csr[tmr] & TMR_CSR_STP) /* stop? */\r
1399 tmr_csr[tmr] = tmr_csr[tmr] & ~TMR_CSR_RUN; /* clr run */\r
1400 if (tmr_csr[tmr] & TMR_CSR_RUN) { /* run? */\r
1401 tmr_tir[tmr] = tmr_tnir[tmr]; /* reload */\r
1402 tmr_sched (tmr); /* reactivate */\r
1403 }\r
1404 if (tmr_csr[tmr] & TMR_CSR_IE) { /* set int req */\r
1405 if (tmr) SET_INT (TMR1);\r
1406 else SET_INT (TMR0);\r
1407 }\r
1408 }\r
1409else {\r
1410 tmr_tir[tmr] = new_tir; /* no, upd tir */\r
1411 if (tmr_csr[tmr] & TMR_CSR_RUN) /* still running? */\r
1412 tmr_sched (tmr); /* reactivate */\r
1413 }\r
1414return;\r
1415}\r
1416\r
1417/* Timer scheduling */\r
1418\r
1419void tmr_sched (int32 tmr)\r
1420{\r
1421int32 clk_time = sim_is_active (&clk_unit) - 1;\r
1422int32 tmr_time;\r
1423\r
1424tmr_sav[tmr] = sim_grtime (); /* save intvl base */\r
1425if (tmr_tir[tmr] > (0xFFFFFFFFu - TMR_INC)) { /* short interval? */\r
1426 tmr_inc[tmr] = (~tmr_tir[tmr] + 1); /* inc = interval */\r
1427 tmr_time = tmr_inc[tmr];\r
1428 }\r
1429else {\r
1430 tmr_inc[tmr] = TMR_INC; /* usec/interval */\r
1431 tmr_time = tmr_poll;\r
1432 }\r
1433if (tmr_time == 0) tmr_time = 1;\r
1434if ((tmr_inc[tmr] == TMR_INC) && (tmr_time > clk_time)) {\r
1435\r
1436/* Align scheduled event to be identical to the event for the next clock\r
1437 tick. This lets us always see a consistent calibrated value, both for\r
1438 this scheduling, AND for any query of the current timer register that\r
1439 may happen in tmr_tir_rd (). This presumes that sim_activate will\r
1440 queue the interval timer behind the event for the clock tick. */\r
1441\r
1442 tmr_inc[tmr] = (uint32) (((double) clk_time * TMR_INC) / tmr_poll);\r
1443 tmr_time = clk_time;\r
1444 }\r
1445sim_activate (&sysd_unit[tmr], tmr_time);\r
1446return;\r
1447}\r
1448\r
1449int32 tmr0_inta (void)\r
1450{\r
1451return tmr_tivr[0];\r
1452}\r
1453\r
1454int32 tmr1_inta (void)\r
1455{\r
1456return tmr_tivr[1];\r
1457}\r
1458\r
1459/* Machine check */\r
1460\r
1461int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta)\r
1462{\r
1463int32 i, st1, st2, p2, hsir, acc;\r
1464\r
1465if (p1 & 0x80) p1 = p1 + mchk_ref; /* mref? set v/p */\r
1466p2 = mchk_va + 4; /* save vap */\r
1467for (i = hsir = 0; i < 16; i++) { /* find hsir */\r
1468 if ((SISR >> i) & 1) hsir = i;\r
1469 }\r
1470st1 = ((((uint32) opc) & 0xFF) << 24) |\r
1471 (hsir << 16) |\r
1472 ((CADR & 0xFF) << 8) |\r
1473 (MSER & 0xFF);\r
1474st2 = 0x00C07000 + (delta & 0xFF);\r
1475cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */\r
1476acc = ACC_MASK (KERN); /* in kernel mode */\r
1477in_ie = 1;\r
1478SP = SP - 20; /* push 5 words */\r
1479Write (SP, 16, L_LONG, WA); /* # bytes */\r
1480Write (SP + 4, p1, L_LONG, WA); /* mcheck type */\r
1481Write (SP + 8, p2, L_LONG, WA); /* address */\r
1482Write (SP + 12, st1, L_LONG, WA); /* state 1 */\r
1483Write (SP + 16, st2, L_LONG, WA); /* state 2 */\r
1484in_ie = 0;\r
1485return cc;\r
1486}\r
1487\r
1488/* Console entry */\r
1489\r
1490int32 con_halt (int32 code, int32 cc)\r
1491{\r
1492int32 temp;\r
1493\r
1494conpc = PC; /* save PC */\r
1495conpsl = ((PSL | cc) & 0xFFFF00FF) | CON_HLTINS; /* PSL, param */\r
1496temp = (PSL >> PSL_V_CUR) & 0x7; /* get is'cur */\r
1497if (temp > 4) conpsl = conpsl | CON_BADPSL; /* invalid? */\r
1498else STK[temp] = SP; /* save stack */\r
1499if (mapen) conpsl = conpsl | CON_MAPON; /* mapping on? */\r
1500mapen = 0; /* turn off map */\r
1501SP = IS; /* set SP from IS */\r
1502PSL = PSL_IS | PSL_IPL1F; /* PSL = 41F0000 */\r
1503JUMP (ROMBASE); /* PC = 20040000 */\r
1504return 0; /* new cc = 0 */\r
1505}\r
1506\r
1507/* Bootstrap */\r
1508\r
1509t_stat cpu_boot (int32 unitno, DEVICE *dptr)\r
1510{\r
1511extern t_stat load_cmd (int32 flag, char *cptr);\r
1512extern FILE *sim_log;\r
1513t_stat r;\r
1514\r
1515PC = ROMBASE;\r
1516PSL = PSL_IS | PSL_IPL1F;\r
1517conpc = 0;\r
1518conpsl = PSL_IS | PSL_IPL1F | CON_PWRUP;\r
1519if (rom == NULL) return SCPE_IERR;\r
1520if (*rom == 0) { /* no boot? */\r
1521 printf ("Loading boot code from ka655x.bin\n");\r
1522 if (sim_log) fprintf (sim_log, \r
1523 "Loading boot code from ka655x.bin\n");\r
1524 r = load_cmd (0, "-R ka655x.bin");\r
1525 if (r != SCPE_OK) return r;\r
1526 }\r
1527return SCPE_OK;\r
1528}\r
1529\r
1530/* SYSD reset */\r
1531\r
1532t_stat sysd_reset (DEVICE *dptr)\r
1533{\r
1534int32 i;\r
1535\r
1536if (sim_switches & SWMASK ('P')) sysd_powerup (); /* powerup? */\r
1537for (i = 0; i < 2; i++) {\r
1538 tmr_csr[i] = tmr_tnir[i] = tmr_tir[i] = 0;\r
1539 tmr_inc[i] = tmr_sav[i] = 0;\r
1540 sim_cancel (&sysd_unit[i]);\r
1541 }\r
1542csi_csr = 0;\r
1543csi_unit.buf = 0;\r
1544sim_cancel (&csi_unit);\r
1545CLR_INT (CSI);\r
1546cso_csr = CSR_DONE;\r
1547cso_unit.buf = 0;\r
1548sim_cancel (&cso_unit);\r
1549CLR_INT (CSO);\r
1550return SCPE_OK;\r
1551}\r
1552\r
1553/* SYSD powerup */\r
1554\r
1555t_stat sysd_powerup (void)\r
1556{\r
1557int32 i;\r
1558\r
1559for (i = 0; i < (CMCTLSIZE >> 2); i++) cmctl_reg[i] = 0;\r
1560for (i = 0; i < 2; i++) {\r
1561 tmr_tivr[i] = 0;\r
1562 ssc_adsm[i] = ssc_adsk[i] = 0;\r
1563 }\r
1564ka_cacr = 0;\r
1565ssc_base = SSCBASE;\r
1566ssc_cnf = ssc_cnf & SSCCNF_BLO;\r
1567ssc_bto = 0;\r
1568ssc_otp = 0;\r
1569return SCPE_OK;\r
1570}\r