1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /**********************************************************************
4 
5     SGI IOC2 I/O Controller emulation
6 
7 **********************************************************************/
8 
9 #ifndef MAME_MACHINE_IOC2_H
10 #define MAME_MACHINE_IOC2_H
11 
12 #pragma once
13 
14 #include "machine/at_keybc.h"
15 #include "bus/pc_kbd/pc_kbdc.h"
16 #include "bus/pc_kbd/keyboards.h"
17 #include "machine/pc_lpt.h"
18 #include "machine/pckeybrd.h"
19 #include "machine/pit8253.h"
20 #include "machine/z80scc.h"
21 
22 class ioc2_device : public device_t
23 {
24 public:
set_cpu_tag(T && tag)25 	template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
26 
27 	DECLARE_INPUT_CHANGED_MEMBER( power_button );
28 	DECLARE_INPUT_CHANGED_MEMBER( volume_down );
29 	DECLARE_INPUT_CHANGED_MEMBER( volume_up );
30 
31 	DECLARE_WRITE_LINE_MEMBER(gio_int0_w);
32 	DECLARE_WRITE_LINE_MEMBER(gio_int1_w);
33 	DECLARE_WRITE_LINE_MEMBER(gio_int2_w);
34 	DECLARE_WRITE_LINE_MEMBER(hpc_dma_done_w);
35 	DECLARE_WRITE_LINE_MEMBER(mc_dma_done_w);
36 	DECLARE_WRITE_LINE_MEMBER(scsi0_int_w);
37 	DECLARE_WRITE_LINE_MEMBER(scsi1_int_w);
38 	DECLARE_WRITE_LINE_MEMBER(enet_int_w);
39 	DECLARE_WRITE_LINE_MEMBER(video_int_w);
40 
41 	void raise_local_irq(int channel, uint8_t mask);
42 	void lower_local_irq(int channel, uint8_t mask);
43 
44 	enum : uint8_t
45 	{
46 		INT3_LOCAL0_FIFO      = 0x01,
47 		INT3_LOCAL0_SCSI0     = 0x02,
48 		INT3_LOCAL0_SCSI1     = 0x04,
49 		INT3_LOCAL0_ETHERNET  = 0x08,
50 		INT3_LOCAL0_MC_DMA    = 0x10,
51 		INT3_LOCAL0_PARALLEL  = 0x20,
52 		INT3_LOCAL0_GRAPHICS  = 0x40,
53 		INT3_LOCAL0_MAPPABLE0 = 0x80,
54 	};
55 
56 	enum : uint8_t
57 	{
58 		INT3_LOCAL1_GP0       = 0x01,
59 		INT3_LOCAL1_PANEL     = 0x02,
60 		INT3_LOCAL1_GP2       = 0x04,
61 		INT3_LOCAL1_MAPPABLE1 = 0x08,
62 		INT3_LOCAL1_HPC_DMA   = 0x10,
63 		INT3_LOCAL1_AC_FAIL   = 0x20,
64 		INT3_LOCAL1_VIDEO     = 0x40,
65 		INT3_LOCAL1_RETRACE   = 0x80,
66 	};
67 
68 	void set_local_int_mask(int channel, const uint8_t mask);
69 	void set_map_int_mask(int channel, const uint8_t mask);
70 	void set_timer_int_clear(const uint8_t data);
71 	void set_mappable_int(uint8_t mask, bool state);
72 
73 protected:
74 	ioc2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
75 
76 	virtual void device_start() override;
77 	virtual void device_reset() override;
78 	virtual void device_add_mconfig(machine_config &config) override;
79 	virtual ioport_constructor device_input_ports() const override;
80 
81 	DECLARE_WRITE_LINE_MEMBER(timer0_int);
82 	DECLARE_WRITE_LINE_MEMBER(timer1_int);
83 	DECLARE_WRITE_LINE_MEMBER(pit_clock2_out);
84 	DECLARE_WRITE_LINE_MEMBER(kbdc_int_w);
85 	DECLARE_WRITE_LINE_MEMBER(duart_int_w);
86 
87 	void check_mappable_interrupt(int channel);
88 
89 	u8 pi1_dma_ctrl_r();
90 	void pi1_dma_ctrl_w(u8 data);
91 	u8 pi1_int_status_r();
92 	void pi1_int_status_w(u8 data);
93 	u8 pi1_int_mask_r();
94 	void pi1_int_mask_w(u8 data);
95 	u8 pi1_timer1_r();
96 	u8 pi1_timer2_r();
97 	u8 pi1_timer3_r();
98 	u8 pi1_timer4_r();
99 	void pi1_timer1_w(u8 data);
100 	void pi1_timer2_w(u8 data);
101 	void pi1_timer3_w(u8 data);
102 	void pi1_timer4_w(u8 data);
103 	u8 gc_select_r();
104 	void gc_select_w(u8 data);
105 	u8 gen_cntl_r();
106 	void gen_cntl_w(u8 data);
107 	u8 front_panel_r();
108 	void front_panel_w(u8 data);
109 	u8 system_id_r();
110 	u8 read_r();
111 	u8 dma_sel_r();
112 	void dma_sel_w(u8 data);
113 	u8 reset_r();
114 	void reset_w(u8 data);
115 	u8 write_r();
116 	void write_w(u8 data);
117 	template <int N> u8 local_status_r();
118 	template <int N> u8 local_mask_r();
119 	template <int N> void local_mask_w(u8 data);
120 	u8 map_status_r();
121 	template <int N> u8 map_mask_r();
122 	template <int N> void map_mask_w(u8 data);
123 	u8 map_pol_r();
124 	void map_pol_w(u8 data);
125 	void timer_int_clear_w(u8 data);
126 	u8 error_status_r();
127 
128 	void base_map(address_map &map);
129 
130 	enum
131 	{
132 		FRONT_PANEL_POWER_STATE      = 0x01,
133 		FRONT_PANEL_POWER_BUTTON_INT = 0x02,
134 		FRONT_PANEL_VOL_DOWN_INT     = 0x10,
135 		FRONT_PANEL_VOL_DOWN_HOLD    = 0x20,
136 		FRONT_PANEL_VOL_UP_INT       = 0x40,
137 		FRONT_PANEL_VOL_UP_HOLD      = 0x80,
138 
139 		FRONT_PANEL_INT_MASK         = FRONT_PANEL_POWER_BUTTON_INT |
140 									   FRONT_PANEL_VOL_DOWN_INT |
141 									   FRONT_PANEL_VOL_UP_INT
142 	};
143 
144 	enum
145 	{
146 		DMA_SEL_CLOCK_SEL_MASK    = 0x30,
147 		DMA_SEL_CLOCK_SEL_10MHz   = 0x00,
148 		DMA_SEL_CLOCK_SEL_6_67MHz = 0x10,
149 		DMA_SEL_CLOCK_SEL_EXT     = 0x20,
150 	};
151 
152 	required_device<cpu_device> m_maincpu;
153 	required_device<scc85230_device> m_scc;
154 	required_device<pc_lpt_device> m_pi1;   // we assume standard parallel port (SPP) mode
155 											// TODO: SGI parallel port (SGIPP), HP BOISE high speed parallel port (HPBPP), and Ricoh scanner mode
156 	required_device<ps2_keyboard_controller_device> m_kbdc;
157 	required_device<pit8254_device> m_pit;
158 
159 	virtual void handle_reset_reg_write(uint8_t data);
160 	virtual uint8_t get_system_id() = 0;
161 
162 	uint8_t m_gen_ctrl_select_reg;
163 	uint8_t m_gen_ctrl_reg;
164 	uint8_t m_front_panel_reg;
165 
166 	uint8_t m_read_reg;
167 	uint8_t m_dma_sel;
168 	uint8_t m_reset_reg;
169 	uint8_t m_write_reg;
170 
171 	uint8_t m_int3_local_status_reg[2];
172 	uint8_t m_int3_local_mask_reg[2];
173 	uint8_t m_int3_map_status_reg;
174 	uint8_t m_int3_map_mask_reg[2];
175 	uint8_t m_int3_map_pol_reg;
176 	uint8_t m_int3_err_status_reg;
177 
178 	uint32_t    m_par_read_cnt;
179 	uint32_t    m_par_cntl;
180 	uint8_t m_system_id;
181 
182 	static char const *const SCC_TAG;
183 	static char const *const PI1_TAG;
184 	static char const *const KBDC_TAG;
185 	static char const *const PIT_TAG;
186 	static char const *const RS232A_TAG;
187 	static char const *const RS232B_TAG;
188 
189 	static const XTAL SCC_PCLK;
190 	static const XTAL SCC_RXA_CLK;
191 	static const XTAL SCC_TXA_CLK;
192 	static const XTAL SCC_RXB_CLK;
193 	static const XTAL SCC_TXB_CLK;
194 };
195 
196 class ioc2_guinness_device : public ioc2_device
197 {
198 public:
199 	template <typename T>
ioc2_guinness_device(const machine_config & mconfig,const char * tag,device_t * owner,T && cpu_tag)200 	ioc2_guinness_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu_tag)
201 		: ioc2_guinness_device(mconfig, tag, owner, (uint32_t)0)
202 	{
203 		set_cpu_tag(std::forward<T>(cpu_tag));
204 	}
205 
206 	void map(address_map &map);
207 	ioc2_guinness_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
208 
209 protected:
get_system_id()210 	uint8_t get_system_id() override { return 0x26; }
211 };
212 
213 class ioc2_full_house_device : public ioc2_device
214 {
215 public:
216 	template <typename T>
ioc2_full_house_device(const machine_config & mconfig,const char * tag,device_t * owner,T && cpu_tag)217 	ioc2_full_house_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu_tag)
218 		: ioc2_full_house_device(mconfig, tag, owner, (uint32_t)0)
219 	{
220 		set_cpu_tag(std::forward<T>(cpu_tag));
221 	}
222 
223 	ioc2_full_house_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
224 
225 	void map(address_map &map);
226 	void int2_map(address_map &map);
227 
228 protected:
get_system_id()229 	uint8_t get_system_id() override { return 0x11; }
230 };
231 
232 DECLARE_DEVICE_TYPE(SGI_IOC2_GUINNESS,   ioc2_guinness_device)
233 DECLARE_DEVICE_TYPE(SGI_IOC2_FULL_HOUSE, ioc2_full_house_device)
234 
235 #endif // MAME_MACHINE_IOC2_H
236