summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/pic8259.h
blob: 298ef1debea6aa2ca4d8b4bde25a9781510c00d6 (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
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/***************************************************************************

    Intel 8259A

    Programmable Interrupt Controller

                            _____   _____
                   _CS   1 |*    \_/     | 28  VCC
                   _WR   2 |             | 27  A0
                   _RD   3 |             | 26  _INTA
                    D7   4 |             | 25  IR7
                    D6   5 |             | 24  IR6
                    D5   6 |             | 23  IR5
                    D4   7 |    8259A    | 22  IR4
                    D3   8 |             | 21  IR3
                    D2   9 |             | 20  IR2
                    D1  10 |             | 19  IR1
                    D0  11 |             | 18  IR0
                  CAS0  12 |             | 17  INT
                  CAS1  13 |             | 16  _SP/_EN
                   GND  14 |_____________| 15  CAS2

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

#ifndef MAME_MACHINE_PIC8259_H
#define MAME_MACHINE_PIC8259_H


class pic8259_device : public device_t
{
public:
	pic8259_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);

	auto out_int_callback() { return m_out_int_func.bind(); } // Interrupt request output to CPU or master 8259 (active high)
	auto in_sp_callback() { return m_in_sp_func.bind(); } // Slave program select (VCC = master; GND = slave; pin becomes EN output in buffered mode)
	auto read_slave_ack_callback() { return m_read_slave_ack_func.bind(); } // Cascaded interrupt acknowledge request for slave 8259 to place vector on data bus

	uint8_t read(offs_t offset);
	void write(offs_t offset, uint8_t data);
	uint32_t acknowledge();

	DECLARE_WRITE_LINE_MEMBER( ir0_w ) { set_irq_line(0, state); }
	DECLARE_WRITE_LINE_MEMBER( ir1_w ) { set_irq_line(1, state); }
	DECLARE_WRITE_LINE_MEMBER( ir2_w ) { set_irq_line(2, state); }
	DECLARE_WRITE_LINE_MEMBER( ir3_w ) { set_irq_line(3, state); }
	DECLARE_WRITE_LINE_MEMBER( ir4_w ) { set_irq_line(4, state); }
	DECLARE_WRITE_LINE_MEMBER( ir5_w ) { set_irq_line(5, state); }
	DECLARE_WRITE_LINE_MEMBER( ir6_w ) { set_irq_line(6, state); }
	DECLARE_WRITE_LINE_MEMBER( ir7_w ) { set_irq_line(7, state); }

	IRQ_CALLBACK_MEMBER(inta_cb);

protected:
	pic8259_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	// device-level overrides
	virtual void device_resolve_objects() override;
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

	virtual bool is_x86() const { return m_is_x86; }

private:
	static constexpr device_timer_id TIMER_CHECK_IRQ = 0;

	inline void set_timer() { timer_set(attotime::zero, TIMER_CHECK_IRQ); }
	void set_irq_line(int irq, int state);


	enum class state_t : u8
	{
		ICW1,
		ICW2,
		ICW3,
		ICW4,
		READY
	};

	devcb_write_line m_out_int_func;
	devcb_read_line m_in_sp_func;
	devcb_read8 m_read_slave_ack_func;

	state_t m_state;

	uint8_t m_isr;
	uint8_t m_irr;
	uint8_t m_prio;
	uint8_t m_imr;
	uint8_t m_irq_lines;

	uint8_t m_input;
	uint8_t m_ocw3;

	uint8_t m_master;
	/* ICW1 state */
	uint8_t m_level_trig_mode;
	uint8_t m_vector_size;
	uint8_t m_cascade;
	uint8_t m_icw4_needed;
	uint32_t m_vector_addr_low;
	/* ICW2 state */
	uint8_t m_base;
	uint8_t m_vector_addr_high;

	/* ICW3 state */
	uint8_t m_slave;

	/* ICW4 state */
	uint8_t m_nested;
	uint8_t m_mode;
	uint8_t m_auto_eoi;
	uint8_t m_is_x86;
};

class v5x_icu_device : public pic8259_device
{
public:
	v5x_icu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);

protected:
	virtual bool is_x86() const override { return true; }
};

DECLARE_DEVICE_TYPE(PIC8259, pic8259_device)
DECLARE_DEVICE_TYPE(V5X_ICU, v5x_icu_device)

#endif // MAME_MACHINE_PIC8259_H