summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/mb87030.h
blob: dc07f0edb9b15a6915d06fffb79453ac4be9b7e7 (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
#ifndef MAME_MACHINE_MB87030_H
#define MAME_MACHINE_MB87030_H

#pragma once

#include "machine/nscsi_bus.h"
#include <queue>

class mb87030_device : public nscsi_device, public nscsi_slot_card_interface
{
public:
	mb87030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	virtual void map(address_map &map);

	auto out_irq_callback() { return m_irq_handler.bind(); }
	auto out_dreq_callback() { return m_dreq_handler.bind(); }

	DECLARE_READ8_MEMBER(bdid_r);
	DECLARE_READ8_MEMBER(sctl_r);
	DECLARE_READ8_MEMBER(scmd_r);
	DECLARE_READ8_MEMBER(tmod_r);
	DECLARE_READ8_MEMBER(ints_r);
	DECLARE_READ8_MEMBER(psns_r);
	DECLARE_READ8_MEMBER(ssts_r);
	DECLARE_READ8_MEMBER(serr_r);
	DECLARE_READ8_MEMBER(pctl_r);
	DECLARE_READ8_MEMBER(mbc_r);
	DECLARE_READ8_MEMBER(dreg_r);
	DECLARE_READ8_MEMBER(temp_r);
	DECLARE_READ8_MEMBER(tch_r);
	DECLARE_READ8_MEMBER(tcm_r);
	DECLARE_READ8_MEMBER(tcl_r);
	DECLARE_READ8_MEMBER(exbf_r);

	DECLARE_WRITE8_MEMBER(bdid_w);
	DECLARE_WRITE8_MEMBER(sctl_w);
	DECLARE_WRITE8_MEMBER(scmd_w);
	DECLARE_WRITE8_MEMBER(tmod_w);
	DECLARE_WRITE8_MEMBER(ints_w);
	DECLARE_WRITE8_MEMBER(sdgc_w);
	DECLARE_WRITE8_MEMBER(pctl_w);
	DECLARE_WRITE8_MEMBER(dreg_w);
	DECLARE_WRITE8_MEMBER(temp_w);
	DECLARE_WRITE8_MEMBER(tch_w);
	DECLARE_WRITE8_MEMBER(tcm_w);
	DECLARE_WRITE8_MEMBER(tcl_w);
	DECLARE_WRITE8_MEMBER(exbf_w);

	DECLARE_WRITE_LINE_MEMBER(reset_w);
	virtual void scsi_ctrl_changed() override;

	uint8_t dma_r();
	void dma_w(uint8_t val);

	void ctrl_write(uint32_t value, uint32_t mask) { scsi_bus->ctrl_w(scsi_refid, value, mask); scsi_ctrl_changed(); }
	uint32_t data_read() { return scsi_bus->data_r(); };
protected:
	mb87030_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	virtual void device_start() override;
	virtual void device_reset() override;
private:

	constexpr static uint8_t SCTL_INT_ENABLE = 0x01;
	constexpr static uint8_t SCTL_RESELECT_ENABLE = 0x02;
	constexpr static uint8_t SCTL_SELECT_ENABLE = 0x04;
	constexpr static uint8_t SCTL_PARITY_ENABLE = 0x08;
	constexpr static uint8_t SCTL_ARBITRATION_ENABLE = 0x10;
	constexpr static uint8_t SCTL_DIAG_MODE = 0x20;
	constexpr static uint8_t SCTL_CONTROL_RESET = 0x40;
	constexpr static uint8_t SCTL_RESET_AND_DISABLE = 0x80;

	constexpr static uint8_t SCMD_TERM_MODE = 0x01;
	constexpr static uint8_t SCMD_PRG_XFER = 0x02;
	constexpr static uint8_t SCMD_INTERCEPT_XFER = 0x04;
	constexpr static uint8_t SCMD_RST_OUT = 0x08;
	constexpr static uint8_t SCMD_CMD_BUS_RELEASE = 0x00;
	constexpr static uint8_t SCMD_CMD_SELECT = 0x20;
	constexpr static uint8_t SCMD_CMD_RESET_ATN = 0x40;
	constexpr static uint8_t SCMD_CMD_SET_ATN = 0x60;
	constexpr static uint8_t SCMD_CMD_TRANSFER = 0x80;
	constexpr static uint8_t SCMD_CMD_TRANSFER_PAUSE = 0xa0;
	constexpr static uint8_t SCMD_CMD_RESET_ACK_REQ = 0xc0;
	constexpr static uint8_t SCMD_CMD_SET_ACK_REQ = 0xe0;
	constexpr static uint8_t SCMD_CMD_MASK = 0xe0;

	constexpr static uint8_t TMOD_MIN_TRANSFER_PERIOD_SHIFT = 0x02;
	constexpr static uint8_t TMOD_MIN_TRANSFER_PERIOD_MASK = 0x0c;
	constexpr static uint8_t TMOD_MAX_TRANSFER_OFFSET_SHIFT = 0x04;
	constexpr static uint8_t TMOD_MIN_TRANSFER_OFFSET_MASK = 0x70;
	constexpr static uint8_t TMOD_SYNC_XFER = 0x80;

	constexpr static uint8_t PCTL_PHASE_SHIFT = 0x00;
	constexpr static uint8_t PCTL_PHASE_MASK = 0x07;
	constexpr static uint8_t PCTL_BUS_FREE_IE = 0x80;

	constexpr static uint8_t PSNS_IO = 0x01;
	constexpr static uint8_t PSNS_CD = 0x02;
	constexpr static uint8_t PSNS_MSG = 0x04;
	constexpr static uint8_t PSNS_BSY = 0x08;
	constexpr static uint8_t PSNS_SEL = 0x10;
	constexpr static uint8_t PSNS_ATN = 0x20;
	constexpr static uint8_t PSNS_ACK = 0x40;
	constexpr static uint8_t PSNS_REQ = 0x80;

	constexpr static uint8_t INTS_RESET_CONDITION = 0x01;
	constexpr static uint8_t INTS_SPC_HARD_ERR = 0x02;
	constexpr static uint8_t INTS_SPC_TIMEOUT = 0x04;
	constexpr static uint8_t INTS_SERVICE_REQUIRED = 0x08;
	constexpr static uint8_t INTS_COMMAND_COMPLETE = 0x10;
	constexpr static uint8_t INTS_DISCONNECTED = 0x20;
	constexpr static uint8_t INTS_RESELECTED = 0x40;
	constexpr static uint8_t INTS_SELECTED = 0x80;

	constexpr static uint8_t SSTS_DREQ_EMPTY = 0x01;
	constexpr static uint8_t SSTS_DREQ_FULL = 0x02;
	constexpr static uint8_t SSTS_TC_ZERO = 0x04;
	constexpr static uint8_t SSTS_SCSI_RST = 0x08;
	constexpr static uint8_t SSTS_XFER_IN_PROGRESS = 0x10;
	constexpr static uint8_t SSTS_SPC_BUSY = 0x20;
	constexpr static uint8_t SSTS_TARG_CONNECTED = 0x40;
	constexpr static uint8_t SSTS_INIT_CONNECTED = 0x80;

	constexpr static uint8_t SERR_OFFSET_ERROR = 0x01;
	constexpr static uint8_t SERR_SHORT_PERIOD = 0x02;
	constexpr static uint8_t SERR_PHASE_ERROR = 0x04;
	constexpr static uint8_t SERR_TC_P_ERROR = 0x08;
	constexpr static uint8_t SERR_DATA_ERROR_SPC = 0x40;
	constexpr static uint8_t SERR_DATA_ERROR_SCSI = 0x80;

	constexpr static uint8_t SDGC_DIAG_IO = 0x01;
	constexpr static uint8_t SDGC_DIAG_CD = 0x02;
	constexpr static uint8_t SDGC_DIAG_MSG = 0x04;
	constexpr static uint8_t SDGC_DIAG_BSY = 0x08;
	constexpr static uint8_t SDGC_DIAG_ACK = 0x40;
	constexpr static uint8_t SDGC_DIAG_REQ = 0x80;

	emu_timer *m_timer;
	emu_timer *m_delay_timer;

	enum TimerId {
		Delay,
		Timeout,
	};
	enum class State: uint8_t {
		Idle,
		ArbitrationWaitBusFree,
		ArbitrationAssertBSY,
		ArbitrationWait,
		ArbitrationAssertSEL,
		ArbitrationDeAssertBSY,
		SelectionWaitBusFree,
		SelectionAssertSEL,
		SelectionWaitBSY,
		Selection,
		TransferWaitReq,
		TransferSendData,
		TransferSendDataDMAReq,
		TransferSendDataDMAResp,
		TransferRecvData,
		TransferRecvDataDMAReq,
		TransferRecvDataDMAResp,
		TransferSendAck,
		TransferWaitDeassertREQ,
		TransferDeassertACK
		//TransferCommand,
	} m_state;

	void update_ssts(void);
	void update_ints(void);

	void scsi_disconnect_timeout(void);
	void scsi_command_complete(void);
	void scsi_disconnect(void);
	void update_state(mb87030_device::State new_state, int delay = 0, int timeout = 0);
	auto get_state_name(State state) const;
	void scsi_set_ctrl(uint32_t val, uint32_t mask);
	uint32_t scsi_get_ctrl();
	void step(bool timeout);

	devcb_write_line m_irq_handler;
	devcb_write_line m_dreq_handler;

	TIMER_CALLBACK_MEMBER(delay_timeout);
	TIMER_CALLBACK_MEMBER(timeout);

	// registers
	uint8_t m_bdid;
	uint8_t m_sctl;
	uint8_t m_scmd;
	uint8_t m_tmod;
	uint8_t m_ints;
	uint8_t m_sdgc;
	uint8_t m_ssts;
	uint8_t m_serr;
	uint8_t m_pctl;
	uint8_t m_mbc;
	uint8_t m_dreg;
	uint8_t m_temp;
	uint8_t m_tch;
	uint8_t m_tcm;
	uint32_t m_tc;
	uint8_t m_exbf;

	uint8_t m_bus_data;
	uint8_t m_hdb;
	bool m_hdb_loaded;
	bool m_send_atn_during_selection;
	util::fifo <uint8_t, 8> m_fifo;

	uint8_t m_scsi_phase;
	uint32_t m_scsi_ctrl;

	bool m_dma_transfer;
};


DECLARE_DEVICE_TYPE(MB87030, mb87030_device)

#endif // MAME_MACHINE_MB87030_H