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
|
/**********************************************************
* DIABLO31 and DIABLO44 hard drive support
*
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
*
* Licenses: MAME, GPLv2
**********************************************************/
#if !defined(_DIABLO_HD_DEVICE_)
#define _DIABLO_HD_DEVICE_
#include "emu.h"
#include "imagedev/diablo.h"
#ifndef DIABLO_DEBUG
#define DIABLO_DEBUG 1 //!< set to 1 to enable debug log output
#endif
#define DIABLO_HD_0 "diablo0"
#define DIABLO_HD_1 "diablo1"
extern const device_type DIABLO_HD;
class diablo_hd_device : public device_t
{
public:
diablo_hd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~diablo_hd_device();
static const int DIABLO_UNIT_MAX = 2; //!< max number of drive units
static const int DIABLO_CYLINDERS = 203; //!< number of cylinders per drive
static const int DIABLO_CYLINDER_MASK = 0777; //!< bit maks for cylinder number (9 bits)
static const int DIABLO_SPT = 12; //!< number of sectors per track
static const int DIABLO_SECTOR_MASK = 017; //!< bit maks for sector number (4 bits)
static const int DIABLO_HEADS = 2; //!< number of heads per drive
static const int DIABLO_HEAD_MASK = 1; //!< bit maks for head number (1 bit)
static const int DIABLO_PAGES = 203*2*12; //!< number of pages per drive
//! convert a cylinder/head/sector to a logical block address (page)
static inline int DIABLO_PAGE(int c, int h, int s) { return (c * DIABLO_HEADS + h) * DIABLO_SPT + s; }
void set_sector_callback(void* cookie, void(*callback)(void*, int));
int bits_per_sector() const;
const char* description() const;
int unit() const;
attotime rotation_time() const;
attotime sector_time() const;
attotime bit_time() const;
int get_seek_read_write_0() const;
int get_ready_0() const;
int get_sector_mark_0() const;
int get_addx_acknowledge_0() const;
int get_log_addx_interlock_0() const;
int get_seek_incomplete_0() const;
int get_cylinder() const;
int get_head() const;
int get_sector() const;
int get_page() const;
void select(int unit);
void set_head(int head);
void set_cylinder(int cylinder);
void set_restore(int restore);
void set_strobe(int strobe);
void set_egate(int gate);
void set_wrgate(int gate);
void set_rdgate(int gate);
void wr_data(int index, int wrdata);
int rd_data(int index);
int rd_clock(int index);
protected:
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
virtual machine_config_constructor device_mconfig_additions() const;
private:
#if DIABLO_DEBUG
int m_log_level;
void logprintf(int level, const char* format, ...);
# define LOG_DRIVE(x) logprintf x
#else
# define LOG_DRIVE(x)
#endif
bool m_diablo31; //!< true, if this is a DIABLO31 drive
int m_unit; //!< drive unit number (0 or 1)
char m_description[32]; //!< description of the drive(s)
int m_packs; //!< number of packs in drive (1 or 2)
attotime m_rotation_time; //!< rotation time in atto seconds
attotime m_sector_time; //!< sector time in atto seconds
attotime m_sector_mark_0_time; //!< sector mark going 0 before sector pulse time
attotime m_sector_mark_1_time; //!< sector mark going 1 after sector pulse time
attotime m_bit_time; //!< bit time in atto seconds
int m_s_r_w_0; //!< drive seek/read/write signal (active 0)
int m_ready_0; //!< drive ready signal (active 0)
int m_sector_mark_0; //!< sector mark (0 if new sector)
int m_addx_acknowledge_0; //!< address acknowledge, i.e. seek successful (active 0)
int m_log_addx_interlock_0; //!< log address interlock, i.e. seek in progress (active 0)
int m_seek_incomplete_0; //!< seek incomplete, i.e. seek in progress (active 0)
int m_egate_0; //!< erase gate
int m_wrgate_0; //!< write gate
int m_rdgate_0; //!< read gate
int m_cylinders; //!< total number of cylinders
int m_pages; //!< total number of pages
int m_seekto; //!< seek to cylinder number
int m_restore; //!< restore to cylinder 0 flag
int m_cylinder; //!< current cylinder number
int m_head; //!< current head (track) number on cylinder
int m_sector; //!< current sector number in track
int m_page; //!< current page (derived from cylinder, head and sector)
UINT8** m_cache; //!< pages raw bytes
UINT32** m_bits; //!< pages expanded to bits
int m_rdfirst; //!< set to first bit of a sector that is read from
int m_rdlast; //!< set to last bit of a sector that was read from
int m_wrfirst; //!< set to non-zero if a sector is written to
int m_wrlast; //!< set to last bit of a sector that was written to
void *m_sector_callback_cookie; //!< cookie to pass to callback
void (*m_sector_callback)(void*,int); //!< callback to call at the start of each sector
emu_timer* m_timer; //!< sector timer
diablo_image_device* m_image; //!< diablo_image_device interfacing the CHD
chd_file* m_handle; //!< underlying CHD handle
hard_disk_file* m_disk; //!< underlying hard disk file
//! translate C/H/S to a page and read the sector
void read_sector();
//! compute the checksum of a record
int cksum(UINT8 *src, size_t size, int start);
//! expand a series of clock bits and 0 data bits
size_t expand_zeroes(UINT32 *bits, size_t dst, size_t size);
//! expand a series of 0 words and write a final sync bit
size_t expand_sync(UINT32 *bits, size_t dst, size_t size);
//! expand a record of words into a array of bits at dst
size_t expand_record(UINT32 *bits, size_t dst, UINT8 *field, size_t size);
//! expand a record's checksum word to 32 bits
size_t expand_cksum(UINT32 *bits, size_t dst, UINT8 *field, size_t size);
//! expand a sector into an array of clock and data bits
UINT32* expand_sector();
#if DIABLO_DEBUG
//! dump a number of words as ASCII characters
void dump_ascii(UINT8 *src, size_t size);
//! dump a record's contents
size_t dump_record(UINT8 *src, size_t addr, size_t size, const char *name, int cr);
#endif
//! find a sync bit in an array of clock and data bits
size_t squeeze_sync(UINT32 *bits, size_t src, size_t size);
//! find a 16 x 0 bits sequence in an array of clock and data bits
size_t squeeze_unsync(UINT32 *bits, size_t src, size_t size);
//! squeeze an array of clock and data bits into a sector's record
size_t squeeze_record(UINT32 *bits, size_t src, UINT8 *field, size_t size);
//! squeeze an array of 32 clock and data bits into a checksum word
size_t squeeze_cksum(UINT32 *bits, size_t src, int *cksum);
//! squeeze a array of clock and data bits into a sector's data
void squeeze_sector();
//! deassert the sector mark
void sector_mark_1();
//! assert the sector mark and read the next sector
void sector_mark_0();
};
#define MCFG_DIABLO_DRIVES_ADD() \
MCFG_DEVICE_ADD(DIABLO_HD_0, DIABLO_HD, ATTOSECONDS_TO_HZ(attotime::from_nsec(300).as_double())) \
MCFG_DEVICE_ADD(DIABLO_HD_1, DIABLO_HD, ATTOSECONDS_TO_HZ(attotime::from_nsec(300).as_double()))
#endif // !defined(_DIABLO_HD_DEVICE_)
|