summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/wd1010.h
blob: b6a637c99e9868103dbf0b41653c53f0894ad44a (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
// license:BSD-3-Clause
// copyright-holders:Dirk Best
/***************************************************************************

    Western Digital WD1010-05 Winchester Disk Controller

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

#ifndef MAME_MACHINE_WD1010_H
#define MAME_MACHINE_WD1010_H

#pragma once

#include "imagedev/harddriv.h"


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

// ======================> wd1010_device

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

	auto out_intrq_callback() { return m_out_intrq_cb.bind(); }
	auto out_bcr_callback() { return m_out_bcr_cb.bind(); }
	auto in_data_callback() { return m_in_data_cb.bind(); }
	auto out_data_callback() { return m_out_data_cb.bind(); }

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

	void drdy_w(int state);
	void brdy_w(int state);

protected:
	// device-level overrides
	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;

private:
	enum
	{
		STATUS_ERR = 0x01, // error
		STATUS_CIP = 0x02, // command in progress
		STATUS_RSV = 0x04, // reserved
		STATUS_DRQ = 0x08, // data request
		STATUS_SC  = 0x10, // seek complete
		STATUS_WF  = 0x20, // write fault
		STATUS_RDY = 0x40, // drive ready
		STATUS_BSY = 0x80  // controller busy
	};

	enum
	{
		ERR_DM   = 0x01, // data address mark not found
		ERR_TK   = 0x02, // track zero error
		ERR_AC   = 0x04, // aborted command
		ERR_RSV1 = 0x08, // reserved, forced to 0
		ERR_ID   = 0x10, // id not found
		ERR_RSV2 = 0x20, // reserved, forced to 0
		ERR_CRC  = 0x40, // crc error
		ERR_BB   = 0x80  // bad block
	};

	enum
	{
		CMD_RESTORE = 1,
		CMD_READ_SECTOR = 2,
		CMD_WRITE_SECTOR = 3,
		CMD_SCAN_ID = 4,
		CMD_WRITE_FORMAT = 5,
		CMD_SEEK = 7
	};

	enum
	{
		TIMER_SEEK,
		TIMER_DATA
	};

	void set_error(int error);
	void set_intrq(int state);
	attotime get_stepping_rate();
	void start_command();
	void end_command();
	int get_lbasector();

	// extract values from sdh
	int head() { return (m_sdh >> 0) & 0x07; }
	int drive() { return (m_sdh >> 3) & 0x03; }
	int sector_size()
	{
		const int S[4] = { 256, 512, 1024, 128 };
		return S[(m_sdh >> 5) & 0x03];
	}

	void cmd_restore();
	void cmd_read_sector();
	void cmd_write_sector();
	void cmd_scan_id();
	void cmd_seek();

	devcb_write_line m_out_intrq_cb;
	devcb_write_line m_out_bcr_cb;
	devcb_read8 m_in_data_cb;
	devcb_write8 m_out_data_cb;

	struct
	{
		harddisk_image_device *drive;
		uint8_t head;
		uint16_t cylinder;
		uint8_t sector;
	} m_drives[4];

	emu_timer *m_seek_timer;
	emu_timer *m_data_timer;

	int m_intrq;
	int m_brdy;
	uint8_t m_stepping_rate;
	uint8_t  m_command;

	// task file registers
	uint8_t m_error;
	uint8_t m_precomp;
	uint8_t m_sector_count;
	uint8_t m_sector_number;
	uint16_t m_cylinder;
	uint8_t m_sdh;
	uint8_t m_status;
};

// device type definition
DECLARE_DEVICE_TYPE(WD1010, wd1010_device)

#endif // MAME_MACHINE_WD1010_H