1 /*
2 * vim: filetype=c:tabstop=4:ai:expandtab
3 * SPDX-License-Identifier: ICU
4 * scspell-id: dab0da0d-f62e-11ec-8f5d-80ee73e9b8e7
5 *
6 * ---------------------------------------------------------------------------
7 *
8 * Copyright (c) 2007-2013 Michael Mondy
9 * Copyright (c) 2012-2016 Harry Reed
10 * Copyright (c) 2013-2022 Charles Anthony
11 * Copyright (c) 2021-2025 The DPS8M Development Team
12 *
13 * This software is made available under the terms of the ICU License.
14 * See the LICENSE.md file at the top-level directory of this distribution.
15 *
16 * ---------------------------------------------------------------------------
17 */
18
19 // Devices connected to a SCU
20 enum active_dev { ADEV_NONE, ADEV_CPU, ADEV_IOM };
21
22 typedef struct
23 {
24 volAtomic uint port_enable [N_SCU_PORTS]; // enable/disable
25
26 // Mask registers A and B, each with 32 interrupt bits.
27 volAtomic word32 exec_intr_mask [N_ASSIGNMENTS];
28
29 // Mask assignment.
30 // 2 mask registers, A and B, each 32 bits wide.
31 // A CPU will be attached to port N.
32 // Mask assignment assigns a mask register (A or B) to a CPU
33 // on port N.
34 // That is, when interrupt I is set:
35 // For reg = A, B
36 //
37 // Mask A, B is set to Off or 0-7.
38 // mask_enable [A|B] says that mask A or B is not off
39 // if (mask_enable) then mask_assignment is a port number
40 volAtomic uint mask_enable [N_ASSIGNMENTS]; // enable/disable
41 volAtomic uint mask_assignment [N_ASSIGNMENTS]; // assigned port number
42 // The 9-bit mask assignment field as last set (ports 0-7, bit 8 = off);
43 // rscr returns it as written, e.g. several ports, or none (SM781 10A).
44 // mask_enable/mask_assignment are derived from it.
45 uint mask_field [N_ASSIGNMENTS];
46
47 volAtomic uint cells [N_CELL_INTERRUPTS];
48
49 uint lower_store_size; // In K words, power of 2; 32 - 4096
50 uint cyclic; // 7 bits
51 uint nea; // 8 bits
52 uint onl; // 4 bits
53 uint interlace; // 1 bit
54 uint lwr; // 1 bit
55
56 // Note that SCUs had no switches to designate SCU 'A' or 'B', etc.
57 // Instead, SCU "A" is the one with base address switches set for 01400,
58 // SCU "B" is the SCU with base address switches set to 02000, etc.
59 // uint mem_base; // zero on boot scu
60 // mode reg: mostly not stored here; returned by scu_get_mode_register()
61 // int mode; // program/manual; if 1, sscr instruction can set some fields
62
63 // CPU/IOM connectivity; designated 0..7
64 // [CAC] really CPU/SCU and SCU/IOM connectivity
65 struct ports
66 {
67 //bool is_enabled;
68 enum active_dev type; // type of connected device
69 int dev_idx; // index of connected dev (cpu_unit_udx, iom_unit_idx
70 bool is_exp;
71 // which port on the connected device?
72 // if is_exp is false, then only [0] is used.
73 // if true, one connection for each sub-port; -1 if not connected
74 volAtomic int dev_port [N_SCU_SUBPORTS];
75 volAtomic bool subport_enables [N_SCU_SUBPORTS];
76 volAtomic bool xipmask [N_SCU_SUBPORTS];
77 volAtomic int xipmaskval;
78 } ports [N_SCU_PORTS];
79
80 // system controller mode register
81 word4 id;
82 word18 mode_reg;
83
84 uint elapsed_days;
85 uint steady_clock; // If non-zero the clock is tied to the cycle counter
86 uint bullet_time;
87 int64 clock_delta;
88 int64 user_correction;
89 uint64 last_time;
90 } scu_t;
91
92 extern scu_t scu [N_SCU_UNITS_MAX];
93
94 extern DEVICE scu_dev;
95
96 int scu_set_interrupt(uint scu_unit_idx, uint inum);
97 void scu_init (void);
98 t_stat scu_sscr (cpu_state_t * cpup, uint scu_unit_idx, UNUSED uint cpu_unit_idx, uint cpu_port_num, word18 addr,
99 word36 rega, word36 regq);
100 t_stat scu_smic (cpu_state_t * cpup, uint scu_unit_idx, uint UNUSED cpu_unit_idx, uint cpu_port_num, word36 rega);
101 t_stat scu_rscr (cpu_state_t * cpup, uint scu_unit_idx, uint cpu_unit_idx, word18 addr, word36 * rega, word36 * regq);
102 int scu_cioc (uint cpu_unit_idx, uint scu_unit_idx, uint scu_port_num, uint expander_command, uint sub_mask);
103 t_stat scu_rmcm (uint scu_unit_idx, uint cpu_unit_idx, word36 * rega, word36 * regq);
104 t_stat scu_smcm (uint scu_unit_idx, uint cpu_unit_idx, word36 rega, word36 regq);
105 void scu_clear_interrupt (uint scu_unit_idx, uint inum);
106 uint scu_get_highest_intr (uint scu_unit_idx);
107 t_stat scu_reset (DEVICE *dptr);
108 t_stat scu_reset_unit (UNIT * uptr, int32 value, const char * cptr,
109 void * desc);
110 void scu_unit_reset (int scu_unit_idx);