1 // license:BSD-3-Clause
2 // copyright-holders:Miodrag Milanovic, R.Belmont
3 /***************************************************************************
4 
5         HP DIO and DIO-II bus devices
6 
7         DIO is 16-bit, essentially the MC68000 bus
8         DIO-II extends to 32-bit for 68020/030/040 machines
9 
10         16-bit DIO cards fit and work in either 16 or 32 bit systems, much like 8-bit ISA.
11         32-bit DIO-II cards only work in 32 bit DIO-II systems.
12 
13 ***************************************************************************/
14 
15 #ifndef MAME_BUS_HPDIO_HPDIO_H
16 #define MAME_BUS_HPDIO_HPDIO_H
17 
18 #pragma once
19 
20 namespace bus { namespace hp_dio {
21 
22 //**************************************************************************
23 //  TYPE DEFINITIONS
24 //**************************************************************************
25 
26 class device_dio16_card_interface;
27 class dio16_device;
28 
29 class dio16_slot_device : public device_t, public device_slot_interface
30 {
31 public:
32 	// construction/destruction
33 	template <typename T, typename U>
dio16_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,T && dio_tag,U && opts,const char * dflt,bool fixed)34 	dio16_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&dio_tag, U &&opts, const char *dflt, bool fixed) :
35 		dio16_slot_device(mconfig, tag, owner, clock)
36 	{
37 		set_dio(std::forward<T>(dio_tag));
38 		option_reset();
39 		opts(*this);
40 		set_default_option(dflt);
41 		set_fixed(fixed);
42 	}
43 	dio16_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
44 
45 	// inline configuration
set_dio(T && dio_tag)46 	template <typename T> void set_dio(T &&dio_tag) { m_dio.set_tag(std::forward<T>(dio_tag)); }
47 
48 protected:
49 	dio16_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
50 
51 	// device-level overrides
52 	virtual void device_resolve_objects() override;
53 	virtual void device_validity_check(validity_checker &valid) const override;
54 	virtual void device_start() override;
55 
56 	// configuration
57 	required_device<dio16_device> m_dio;
58 };
59 
60 // ======================> dio16_device
61 class dio16_device : public device_t
62 {
63 public:
64 	// construction/destruction
65 	dio16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
66 	// inline configuration
set_program_space(T && tag,int spacenum)67 	template <typename T> void set_program_space(T &&tag, int spacenum) { m_prgspace.set_tag(std::forward<T>(tag), spacenum); }
68 
69 	// callback configuration
dmar0_out_cb()70 	auto dmar0_out_cb() { return m_dmar0_out_cb.bind(); }
dmar1_out_cb()71 	auto dmar1_out_cb() { return m_dmar1_out_cb.bind(); }
irq1_out_cb()72 	auto irq1_out_cb() { return m_irq1_out_cb.bind(); }
irq2_out_cb()73 	auto irq2_out_cb() { return m_irq2_out_cb.bind(); }
irq3_out_cb()74 	auto irq3_out_cb() { return m_irq3_out_cb.bind(); }
irq4_out_cb()75 	auto irq4_out_cb() { return m_irq4_out_cb.bind(); }
irq5_out_cb()76 	auto irq5_out_cb() { return m_irq5_out_cb.bind(); }
irq6_out_cb()77 	auto irq6_out_cb() { return m_irq6_out_cb.bind(); }
irq7_out_cb()78 	auto irq7_out_cb() { return m_irq7_out_cb.bind(); }
79 
80 	template<typename R, typename W> void install_memory(offs_t start, offs_t end, R rhandler, W whandler);
81 
82 	// DANGER: these will currently produce different results for a DIO-I card on DIO-I and DIO-II systems
83 	//         due to the varying bus widths.  Using all install_memory() shields you from this problem.
84 	//         Either know what you're doing (m_prgwidth is available to cards for this purpose) or
85 	//         only use these for 32-bit DIO-II cards.
86 	void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
87 	void install_rom(offs_t start, offs_t end, const char *tag, uint8_t *data);
88 
89 	void unmap_bank(offs_t start, offs_t end);
90 	void unmap_rom(offs_t start, offs_t end);
program_space()91 	address_space &program_space() { return *m_prgspace; }
92 
93 	// IRQs 1, 2, and 7 are reserved for non-bus usage.
94 
95 	// input lines
DECLARE_WRITE_LINE_MEMBER(dmar0_in)96 	DECLARE_WRITE_LINE_MEMBER(dmar0_in) { set_dmar(m_bus_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(dmar1_in)97 	DECLARE_WRITE_LINE_MEMBER(dmar1_in) { set_dmar(m_bus_index, 1, state); }
DECLARE_WRITE_LINE_MEMBER(irq1_in)98 	DECLARE_WRITE_LINE_MEMBER(irq1_in) { set_irq(m_bus_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(irq2_in)99 	DECLARE_WRITE_LINE_MEMBER(irq2_in) { set_irq(m_bus_index, 1, state); }
DECLARE_WRITE_LINE_MEMBER(irq3_in)100 	DECLARE_WRITE_LINE_MEMBER(irq3_in) { set_irq(m_bus_index, 2, state); }
DECLARE_WRITE_LINE_MEMBER(irq4_in)101 	DECLARE_WRITE_LINE_MEMBER(irq4_in) { set_irq(m_bus_index, 3, state); }
DECLARE_WRITE_LINE_MEMBER(irq5_in)102 	DECLARE_WRITE_LINE_MEMBER(irq5_in) { set_irq(m_bus_index, 4, state); }
DECLARE_WRITE_LINE_MEMBER(irq6_in)103 	DECLARE_WRITE_LINE_MEMBER(irq6_in) { set_irq(m_bus_index, 5, state); }
DECLARE_WRITE_LINE_MEMBER(irq7_in)104 	DECLARE_WRITE_LINE_MEMBER(irq7_in) { set_irq(m_bus_index, 6, state); }
105 	DECLARE_WRITE_LINE_MEMBER(reset_in);
106 
107 	// output lines
DECLARE_READ_LINE_MEMBER(irq1_out)108 	DECLARE_READ_LINE_MEMBER(irq1_out) const { return (m_irq[0] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq2_out)109 	DECLARE_READ_LINE_MEMBER(irq2_out) const { return (m_irq[1] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq3_out)110 	DECLARE_READ_LINE_MEMBER(irq3_out) const { return (m_irq[2] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq4_out)111 	DECLARE_READ_LINE_MEMBER(irq4_out) const { return (m_irq[3] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq5_out)112 	DECLARE_READ_LINE_MEMBER(irq5_out) const { return (m_irq[4] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq6_out)113 	DECLARE_READ_LINE_MEMBER(irq6_out) const { return (m_irq[5] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq7_out)114 	DECLARE_READ_LINE_MEMBER(irq7_out) const { return (m_irq[6] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(dmar0_out)115 	DECLARE_READ_LINE_MEMBER(dmar0_out) const { return dmar0_r(); }
DECLARE_READ_LINE_MEMBER(dmar1_out)116 	DECLARE_READ_LINE_MEMBER(dmar1_out) const { return dmar1_r(); }
117 
dmar0_r()118 	bool dmar0_r() const { return (m_dmar[0] & ~m_bus_index) ? 1 : 0; }
dmar1_r()119 	bool dmar1_r() const { return (m_dmar[1] & ~m_bus_index) ? 1 : 0; }
120 
121 	uint8_t dmack_r_out(int index, int channel);
122 	void dmack_w_out(int index, int channel, uint8_t data);
123 
124 	int m_prgwidth;
125 
126 	unsigned add_card(device_dio16_card_interface & card);
127 	void set_irq(unsigned int index, unsigned int num, int state);
128 	void set_dmar(unsigned int index, unsigned int num, int state);
129 
130 protected:
131 	dio16_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
132 	void install_space(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
133 
134 	// device-level overrides
135 	virtual void device_start() override;
136 	virtual void device_reset() override;
137 
138 	// internal state
139 	std::list<device_dio16_card_interface *> m_cards;
140 
141 	// address spaces
142 	required_address_space m_prgspace;
143 	int m_bus_index;
144 
145 	// packed line states
146 	u16 m_irq[7];
147 	u16 m_dmar[2];
148 
149 	devcb_write_line m_irq1_out_cb;
150 	devcb_write_line m_irq2_out_cb;
151 	devcb_write_line m_irq3_out_cb;
152 	devcb_write_line m_irq4_out_cb;
153 	devcb_write_line m_irq5_out_cb;
154 	devcb_write_line m_irq6_out_cb;
155 	devcb_write_line m_irq7_out_cb;
156 
157 	devcb_write_line m_dmar0_out_cb;
158 	devcb_write_line m_dmar1_out_cb;
159 };
160 
161 // ======================> device_dio16_card_interface
162 
163 // class representing interface-specific live dio16 card
164 class device_dio16_card_interface : public device_interface
165 {
166 	friend class dio16_device;
167 	template <class ElementType> friend class simple_list;
168 public:
169 	// construction/destruction
170 	virtual ~device_dio16_card_interface();
171 
next()172 	device_dio16_card_interface *next() const { return m_next; }
173 	// inline configuration
set_diobus(dio16_device & dio_device)174 	void set_diobus(dio16_device &dio_device) {
175 		m_dio_dev = &dio_device;
176 		m_index = m_dio_dev->add_card(*this);
177 	}
178 protected:
179 	device_dio16_card_interface(const machine_config &mconfig, device_t &device);
dio()180 	dio16_device &dio() {
181 		assert(m_dio_dev);
182 		return *m_dio_dev;
183 	}
184 
185 	virtual void interface_pre_start() override;
186 
get_index()187 	int get_index() { return m_index; };
program_space()188 	address_space &program_space() { return m_dio_dev->program_space(); }
189 
DECLARE_WRITE_LINE_MEMBER(irq1_out)190 	DECLARE_WRITE_LINE_MEMBER(irq1_out) { m_dio_dev->set_irq(m_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(irq2_out)191 	DECLARE_WRITE_LINE_MEMBER(irq2_out) { m_dio_dev->set_irq(m_index, 1, state); }
DECLARE_WRITE_LINE_MEMBER(irq3_out)192 	DECLARE_WRITE_LINE_MEMBER(irq3_out) { m_dio_dev->set_irq(m_index, 2, state); }
DECLARE_WRITE_LINE_MEMBER(irq4_out)193 	DECLARE_WRITE_LINE_MEMBER(irq4_out) { m_dio_dev->set_irq(m_index, 3, state); }
DECLARE_WRITE_LINE_MEMBER(irq5_out)194 	DECLARE_WRITE_LINE_MEMBER(irq5_out) { m_dio_dev->set_irq(m_index, 4, state); }
DECLARE_WRITE_LINE_MEMBER(irq6_out)195 	DECLARE_WRITE_LINE_MEMBER(irq6_out) { m_dio_dev->set_irq(m_index, 5, state); }
DECLARE_WRITE_LINE_MEMBER(irq7_out)196 	DECLARE_WRITE_LINE_MEMBER(irq7_out) { m_dio_dev->set_irq(m_index, 6, state); }
DECLARE_WRITE_LINE_MEMBER(dmar0_out)197 	DECLARE_WRITE_LINE_MEMBER(dmar0_out) { m_dio_dev->set_dmar(m_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(dmar1_out)198 	DECLARE_WRITE_LINE_MEMBER(dmar1_out) { m_dio_dev->set_dmar(m_index, 1, state); }
199 
DECLARE_WRITE_LINE_MEMBER(irq1_in)200 	virtual DECLARE_WRITE_LINE_MEMBER(irq1_in) {}
DECLARE_WRITE_LINE_MEMBER(irq2_in)201 	virtual DECLARE_WRITE_LINE_MEMBER(irq2_in) {}
DECLARE_WRITE_LINE_MEMBER(irq3_in)202 	virtual DECLARE_WRITE_LINE_MEMBER(irq3_in) {}
DECLARE_WRITE_LINE_MEMBER(irq4_in)203 	virtual DECLARE_WRITE_LINE_MEMBER(irq4_in) {}
DECLARE_WRITE_LINE_MEMBER(irq5_in)204 	virtual DECLARE_WRITE_LINE_MEMBER(irq5_in) {}
DECLARE_WRITE_LINE_MEMBER(irq6_in)205 	virtual DECLARE_WRITE_LINE_MEMBER(irq6_in) {}
DECLARE_WRITE_LINE_MEMBER(irq7_in)206 	virtual DECLARE_WRITE_LINE_MEMBER(irq7_in) {}
DECLARE_WRITE_LINE_MEMBER(dmar0_in)207 	virtual DECLARE_WRITE_LINE_MEMBER(dmar0_in) {}
DECLARE_WRITE_LINE_MEMBER(dmar1_in)208 	virtual DECLARE_WRITE_LINE_MEMBER(dmar1_in) {}
209 
dmack_r_out(int channel)210 	virtual uint8_t dmack_r_out(int channel) { return m_dio_dev->dmack_r_out(m_index, channel); }
dmack_w_out(int channel,uint8_t data)211 	virtual void dmack_w_out(int channel, uint8_t data) { m_dio_dev->dmack_w_out(m_index, channel, data); }
dmack_r_in(int channel)212 	virtual uint8_t dmack_r_in(int channel) { return 0xff; }
dmack_w_in(int channel,uint8_t data)213 	virtual void dmack_w_in(int channel, uint8_t data) {}
214 
DECLARE_WRITE_LINE_MEMBER(reset_in)215 	virtual DECLARE_WRITE_LINE_MEMBER(reset_in) {}
216 
dmar0_r()217 	bool dmar0_r() const { return m_dio_dev->dmar0_r(); }
dmar1_r()218 	bool dmar1_r() const { return m_dio_dev->dmar1_r(); }
219 
220 	dio16_device *m_dio_dev;
221 
222 private:
223 	void set_bus(dio16_device & bus);
224 	device_dio16_card_interface *m_next;
225 	unsigned int m_index;
226 };
227 
228 class dio32_device;
229 
230 class dio32_slot_device : public dio16_slot_device
231 {
232 public:
233 	// construction/destruction
234 	template <typename T, typename U>
dio32_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,T && dio_tag,U && opts,const char * dflt,bool fixed)235 	dio32_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&dio_tag, U &&opts, const char *dflt, bool fixed) :
236 		dio32_slot_device(mconfig, tag, owner, clock)
237 	{
238 		set_dio(std::forward<T>(dio_tag));
239 		option_reset();
240 		opts(*this);
241 		set_default_option(dflt);
242 		set_fixed(fixed);
243 	}
244 	dio32_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
245 
246 protected:
247 	// device-level overrides
248 	virtual void device_start() override;
249 };
250 
251 // ======================> dio32_device
252 class dio32_device : public dio16_device
253 {
254 public:
255 	// construction/destruction
256 	dio32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
257 
258 	void install16_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler);
259 
260 protected:
261 	// device-level overrides
262 	virtual void device_start() override;
263 };
264 
265 // ======================> device_dio32_card_interface
266 
267 // class representing interface-specific live dio32 card
268 class device_dio32_card_interface : public device_dio16_card_interface
269 {
270 	friend class dio32_device;
271 public:
272 	// construction/destruction
273 	virtual ~device_dio32_card_interface();
274 
275 protected:
276 	device_dio32_card_interface(const machine_config &mconfig, device_t &device);
277 
278 	virtual void interface_pre_start() override;
279 
dio()280 	dio32_device &dio() { assert(m_dio_dev); return downcast<dio32_device &>(*m_dio_dev); }
281 };
282 
283 } } // namespace bus::hp_dio
284 
285 // device type definition
286 DECLARE_DEVICE_TYPE_NS(DIO16_SLOT, bus::hp_dio, dio16_slot_device)
287 DECLARE_DEVICE_TYPE_NS(DIO32, bus::hp_dio, dio32_device)
288 DECLARE_DEVICE_TYPE_NS(DIO32_SLOT, bus::hp_dio, dio32_slot_device)
289 DECLARE_DEVICE_TYPE_NS(DIO16, bus::hp_dio, dio16_device)
290 
291 void dio16_cards(device_slot_interface &device);
292 void dio32_cards(device_slot_interface &device);
293 
294 #endif // MAME_BUS_HPDIO_HPDIO_H
295