summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/wd33c9x.h
blob: d5f3b5a5da426f2e61fc3416086a0751438835b6 (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
// license:BSD-3-Clause
// copyright-holders:Tyson Smith
/*
 * wd33c9x.h
 */

#ifndef MAME_MACHINE_WD33C9X_H
#define MAME_MACHINE_WD33C9X_H

#pragma once

#include "machine/nscsi_bus.h"

class wd33c9x_base_device : public nscsi_device
{
public:
	auto irq_cb() { return m_irq_cb.bind(); }
	auto drq_cb() { return m_drq_cb.bind(); }

	// Direct Addressing Interface
	DECLARE_READ8_MEMBER(dir_r);
	DECLARE_WRITE8_MEMBER(dir_w);

	// Indirect Addressing Interface
	DECLARE_READ8_MEMBER(indir_r);
	DECLARE_WRITE8_MEMBER(indir_w);

	// Alternative Indirect Addressing Interface
	DECLARE_READ8_MEMBER(indir_addr_r);
	DECLARE_WRITE8_MEMBER(indir_addr_w);
	DECLARE_READ8_MEMBER(indir_reg_r);
	DECLARE_WRITE8_MEMBER(indir_reg_w);

	// Master Reset (MR) Interface
	DECLARE_WRITE_LINE_MEMBER(reset_w);

	// DMA Interface (for use with DRQ)
	uint8_t dma_r();
	void dma_w(const uint8_t data);

protected:
	wd33c9x_base_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;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

	virtual void scsi_ctrl_changed() override;

private:
	static constexpr uint8_t NUM_REGS = 0x20;
	static constexpr uint8_t REGS_MASK = NUM_REGS - 1;
	uint8_t m_addr;
	uint8_t m_regs[NUM_REGS];
	uint8_t m_command_length;

	void start_command();

	void step(bool timeout);
	void set_scsi_state(uint16_t state);
	void set_scsi_state_sub(uint8_t sub);
	uint16_t m_scsi_state;
	uint8_t m_mode;
	uint8_t m_xfr_phase;
	uint8_t m_step_count;

	void load_transfer_count();
	bool decrement_transfer_count();
	uint32_t m_transfer_count;

	uint8_t data_fifo_pop();
	void data_fifo_push(const uint8_t data);
	bool data_fifo_empty() const;
	bool data_fifo_full() const;
	void data_fifo_reset();
	static constexpr uint8_t DATA_FIFO_SIZE = 12;
	uint8_t m_data_fifo[DATA_FIFO_SIZE];
	uint8_t m_data_fifo_pos;
	uint8_t m_data_fifo_size;

	uint32_t send_byte(const uint32_t value = 0, const uint32_t mask = 0);

	uint8_t irq_fifo_pop();
	void irq_fifo_push(const uint8_t status);
	bool irq_fifo_empty() const;
	bool irq_fifo_full() const;
	void irq_fifo_reset();
	static constexpr uint8_t IRQ_FIFO_SIZE = 8;
	uint8_t m_irq_fifo[IRQ_FIFO_SIZE];
	uint8_t m_irq_fifo_pos;
	uint8_t m_irq_fifo_size;

	void update_irq();
	devcb_write_line m_irq_cb;

	void set_drq();
	void clear_drq();
	devcb_write_line m_drq_cb;
	bool m_drq_state;

	void delay(uint32_t cycles);
	void delay_cycles(uint32_t cycles);
	emu_timer *m_timer;

	bool set_command_length(const uint8_t cc);
	uint8_t get_msg_out() const;
};

class wd33c92_device : public wd33c9x_base_device
{
public:
	wd33c92_device(const machine_config &mconfig, const char *tag, device_t *owner)
		: wd33c92_device(mconfig, tag, owner, 0)
	{
	}

	wd33c92_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class wd33c93n_device : public wd33c9x_base_device
{
public:
	wd33c93n_device(const machine_config &mconfig, const char *tag, device_t *owner)
		: wd33c93n_device(mconfig, tag, owner, 0)
	{
	}

	wd33c93n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class wd33c93a_device : public wd33c9x_base_device
{
public:
	wd33c93a_device(const machine_config &mconfig, const char *tag, device_t *owner)
		: wd33c93a_device(mconfig, tag, owner, 0)
	{
	}

	wd33c93a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class wd33c93b_device : public wd33c9x_base_device
{
public:
	wd33c93b_device(const machine_config &mconfig, const char *tag, device_t *owner)
		: wd33c93b_device(mconfig, tag, owner, 0)
	{
	}

	wd33c93b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};


DECLARE_DEVICE_TYPE(WD33C92, wd33c92_device)
DECLARE_DEVICE_TYPE(WD33C93N, wd33c93n_device)
DECLARE_DEVICE_TYPE(WD33C93A, wd33c93a_device)
DECLARE_DEVICE_TYPE(WD33C93B, wd33c93b_device)

#endif // MAME_MACHINE_WD33C9X_H