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