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
43 volAtomic uint cells [N_CELL_INTERRUPTS];
44
45 uint lower_store_size; // In K words, power of 2; 32 - 4096
46 uint cyclic; // 7 bits
47 uint nea; // 8 bits
48 uint onl; // 4 bits
49 uint interlace; // 1 bit
50 uint lwr; // 1 bit
51
52 // Note that SCUs had no switches to designate SCU 'A' or 'B', etc.
53 // Instead, SCU "A" is the one with base address switches set for 01400,
54 // SCU "B" is the SCU with base address switches set to 02000, etc.
55 // uint mem_base; // zero on boot scu
56 // mode reg: mostly not stored here; returned by scu_get_mode_register()
57 // int mode; // program/manual; if 1, sscr instruction can set some fields
58
59 // CPU/IOM connectivity; designated 0..7
60 // [CAC] really CPU/SCU and SCU/IOM connectivity
61 struct ports
62 {
63 //bool is_enabled;
64 enum active_dev type; // type of connected device
65 int dev_idx; // index of connected dev (cpu_unit_udx, iom_unit_idx
66 bool is_exp;
67 // which port on the connected device?
68 // if is_exp is false, then only [0] is used.
69 // if true, one connection for each sub-port; -1 if not connected
70 volAtomic int dev_port [N_SCU_SUBPORTS];
71 volAtomic bool subport_enables [N_SCU_SUBPORTS];
72 volAtomic bool xipmask [N_SCU_SUBPORTS];
73 volAtomic int xipmaskval;
74 } ports [N_SCU_PORTS];
75
76 // system controller mode register
77 word4 id;
78 word18 mode_reg;
79
80 uint elapsed_days;
81 uint steady_clock; // If non-zero the clock is tied to the cycle counter
82 uint bullet_time;
83 int64 clock_delta;
84 int64 user_correction;
85 uint64 last_time;
86 } scu_t;
87
88 extern scu_t scu [N_SCU_UNITS_MAX];
89
90 extern DEVICE scu_dev;
91
92 int scu_set_interrupt(uint scu_unit_idx, uint inum);
93 void scu_init (void);
94 t_stat scu_sscr (cpu_state_t * cpup, uint scu_unit_idx, UNUSED uint cpu_unit_idx, uint cpu_port_num, word18 addr,
95 word36 rega, word36 regq);
96 t_stat scu_smic (cpu_state_t * cpup, uint scu_unit_idx, uint UNUSED cpu_unit_idx, uint cpu_port_num, word36 rega);
97 t_stat scu_rscr (cpu_state_t * cpup, uint scu_unit_idx, uint cpu_unit_idx, word18 addr, word36 * rega, word36 * regq);
98 int scu_cioc (uint cpu_unit_idx, uint scu_unit_idx, uint scu_port_num, uint expander_command, uint sub_mask);
99 t_stat scu_rmcm (uint scu_unit_idx, uint cpu_unit_idx, word36 * rega, word36 * regq);
100 t_stat scu_smcm (uint scu_unit_idx, uint cpu_unit_idx, word36 rega, word36 regq);
101 void scu_clear_interrupt (uint scu_unit_idx, uint inum);
102 uint scu_get_highest_intr (uint scu_unit_idx);
103 t_stat scu_reset (DEVICE *dptr);
104 t_stat scu_reset_unit (UNIT * uptr, int32 value, const char * cptr,
105 void * desc);
106 void scu_unit_reset (int scu_unit_idx);