summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/i8089/i8089.h
blob: df72f847b856cb2910073314621adb7511832084 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// license:GPL-2.0+
// copyright-holders:Dirk Best,Carl
/***************************************************************************

    Intel 8089 I/O Processor

***************************************************************************/

#ifndef MAME_CPU_I8089_I8089_H
#define MAME_CPU_I8089_I8089_H

#pragma once

#ifdef _MSC_VER
// MSVC seems to want to actually instantiate templates when it gets an extern template declaration, effectively defeating the purpose of extern template declatations altogether
// In this case it causes a problem because the required_device template can't be instantiated for the incomplete i8089_channel_device type
#include "i8089_channel.h"
#endif


//**************************************************************************
//  INTERFACE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_I8089_DATA_WIDTH(_data_width) \
	downcast<i8089_device &>(*device).set_data_width(_data_width);

#define MCFG_I8089_SINTR1(_sintr1) \
	devcb = &downcast<i8089_device *>(device)->set_sintr1_callback(DEVCB_##_sintr1);

#define MCFG_I8089_SINTR2(_sintr2) \
	devcb = &downcast<i8089_device *>(device)->set_sintr2_callback(DEVCB_##_sintr2);


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// forward declaration
class i8089_channel_device;

// ======================> i8089_device

class i8089_device : public cpu_device
{
	friend class i8089_channel_device;

public:
	// construction/destruction
	i8089_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// callbacks
	template <class Object> devcb_base &set_sintr1_callback(Object &&sintr1) { return m_write_sintr1.set_callback(std::forward<Object>(sintr1)); }
	template <class Object> devcb_base &set_sintr2_callback(Object &&sintr2) { return m_write_sintr2.set_callback(std::forward<Object>(sintr2)); }

	// configuration helpers
	void set_data_width(uint8_t data_width) { m_data_width = data_width; }

	// input lines
	DECLARE_WRITE_LINE_MEMBER( ca_w );
	DECLARE_WRITE_LINE_MEMBER( sel_w ) { m_sel = state; }
	DECLARE_WRITE_LINE_MEMBER( drq1_w );
	DECLARE_WRITE_LINE_MEMBER( drq2_w );
	DECLARE_WRITE_LINE_MEMBER( ext1_w );
	DECLARE_WRITE_LINE_MEMBER( ext2_w );

protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_config_complete() override;
	virtual void device_reset() override;

	// device_execute_interface overrides
	virtual void execute_run() override;

	int m_icount;

	// device_memory_interface overrides
	virtual space_config_vector memory_space_config() const override;

	address_space_config m_program_config;
	address_space_config m_io_config;

	// device_disasm_interface overrides
	virtual util::disasm_interface *create_disassembler() override;

	// device_state_interface overrides
	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;

	// optional information overrides
	virtual void device_add_mconfig(machine_config &config) override;

private:
	bool sysbus_width() const { return BIT(m_sysbus, 0); }
	bool remotebus_width() const { return BIT(m_soc, 0); }
	bool request_grant() const { return BIT(m_soc, 1); }

	// internal communication
	DECLARE_WRITE_LINE_MEMBER( ch1_sintr_w ) { m_write_sintr1(state); }
	DECLARE_WRITE_LINE_MEMBER( ch2_sintr_w ) { m_write_sintr2(state); }

	uint8_t read_byte(bool space, offs_t address);
	uint16_t read_word(bool space, offs_t address);
	void write_byte(bool space, offs_t address, uint8_t data);
	void write_word(bool space, offs_t address, uint16_t data);

	required_device<i8089_channel_device> m_ch1;
	required_device<i8089_channel_device> m_ch2;

	devcb_write_line m_write_sintr1;
	devcb_write_line m_write_sintr2;

	void initialize();

	uint8_t m_data_width;
	address_space *m_mem;
	address_space *m_io;

	// register indexes for the debugger state
	enum
	{
		SYSBUS,
		SCB,
		SOC,
		DIVIDER1,
		CH1_GA, CH1_GB, CH1_GC,
		CH1_TP, CH1_BC, CH1_IX,
		CH1_CC, CH1_MC, CH1_CP,
		CH1_PP, CH1_PSW,
		DIVIDER2,
		CH2_GA, CH2_GB, CH2_GC,
		CH2_TP, CH2_BC, CH2_IX,
		CH2_CC, CH2_MC, CH2_CP,
		CH2_PP, CH2_PSW
	};

	// system configuration
	uint8_t m_sysbus;
	offs_t m_scb;
	uint8_t m_soc;

	bool m_initialized;
	bool m_master;

	// task pointer for the currently executing channel
	offs_t m_current_tp;

	// state of input pins
	int m_ca;
	int m_sel;
	bool m_last_chan;
};


// device type definition
DECLARE_DEVICE_TYPE(I8089, i8089_device)

#endif // MAME_CPU_I8089_I8089_H