Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | #pragma once |
2 | |||
3 | const int Z80FQ = 3500000; // todo: #define as (conf.frame*conf.intfq) |
||
4 | const int FDD_RPS = 5; // rotation speed |
||
5 | |||
6 | const int MAX_TRACK_LEN = 6250; |
||
7 | const int MAX_CYLS = 86; // don't load images with so many tracks |
||
8 | const int MAX_PHYS_CYL = 86; // don't seek over it |
||
9 | const int MAX_SEC = 256; |
||
10 | |||
11 | struct SECHDR |
||
12 | { |
||
13 | unsigned char c,s,n,l; |
||
14 | unsigned short crc; // CRC заголовка сектора |
||
15 | |||
16 | // флаги crc зоны адреса и данных: |
||
17 | // При форматировании: |
||
18 | // 0 - генерируется правильное значение crc |
||
19 | // 1 - запись crc из crc(для адреса)/crcd(для данных) |
||
20 | // 2 - ошибочный crc (генерируется инверсией правильного crc)) |
||
21 | // При чтении (функция seek устанавливает поля c1 и c2): |
||
22 | // 0 - рассчитанное crc не совпадает с указанным в заголовке (возвращается crc error) |
||
23 | // 1 - рассчитанное crc совпадает с указанным в заголовке |
||
24 | unsigned char c1, c2; |
||
25 | u8 *data; // Указатель на данные сектора внутри трэка |
||
26 | u8 *id; // Указатель на заголовок сектора внутри трэка |
||
27 | u8 *wp; // Указатель на битовую карту сбойных байтов сектора внутри трэка (используется только при загрузке) |
||
28 | unsigned wp_start; // Номер первого бита в карте сбойных байтов (относительно начала трэка) для данного сектора |
||
29 | unsigned datlen; // Размер сектора в байтах |
||
30 | unsigned crcd; // used to load specific CRC from FDI-file |
||
31 | }; |
||
32 | |||
33 | enum SEEK_MODE { JUST_SEEK = 0, LOAD_SECTORS = 1 }; |
||
34 | |||
35 | static inline bool test_bit(const u8 *data, unsigned bit) |
||
36 | { |
||
37 | return (data[bit >> 3] & (1U << (bit & 7))) != 0; |
||
38 | } |
||
39 | |||
40 | static inline void set_bit(u8 *data, unsigned bit) |
||
41 | { |
||
42 | data[bit >> 3] |= (1U << (bit & 7)); |
||
43 | } |
||
44 | |||
45 | static inline void clr_bit(u8 *data, unsigned bit) |
||
46 | { |
||
47 | data[bit >> 3] &= ~(1U << (bit & 7)); |
||
48 | } |
||
49 | |||
50 | |||
51 | struct TRKCACHE |
||
52 | { |
||
53 | // cached track position |
||
54 | struct FDD *drive; |
||
55 | unsigned cyl, side; |
||
56 | |||
57 | // generic track data |
||
58 | unsigned trklen; |
||
59 | // pointer to data inside UDI |
||
60 | u8 *trkd; // данные |
||
61 | u8 *trki; // битовая карта синхроимпульсов |
||
62 | u8 *trkwp; // битовая карта сбойных байтов |
||
63 | unsigned ts_byte; // cpu.t per byte |
||
64 | SEEK_MODE sf; // flag: is sectors filled |
||
65 | unsigned s; // no. of sectors |
||
66 | |||
67 | // sectors on track |
||
68 | SECHDR hdr[MAX_SEC]; |
||
69 | |||
70 | void set_i(unsigned pos) { set_bit(trki, pos); } |
||
71 | void clr_i(unsigned pos) { clr_bit(trki, pos); } |
||
72 | bool test_i(unsigned pos) { return test_bit(trki, pos); } |
||
73 | |||
74 | void set_wp(unsigned pos) { set_bit(trkwp, pos); } |
||
75 | bool test_wp(unsigned pos) { return test_bit(trkwp, pos); } |
||
76 | |||
77 | void write(unsigned pos, unsigned char byte, char index) |
||
78 | { |
||
79 | if(!trkd) |
||
80 | return; |
||
81 | |||
82 | trkd[pos] = byte; |
||
83 | if (index) |
||
84 | set_i(pos); |
||
85 | else |
||
86 | clr_i(pos); |
||
87 | } |
||
88 | |||
89 | void seek(FDD *d, unsigned cyl, unsigned side, SEEK_MODE fs); |
||
90 | void format(); // before use, call seek(d,c,s,JUST_SEEK), set s and hdr[] |
||
91 | int write_sector(unsigned sec, unsigned char *data); // call seek(d,c,s,LOAD_SECTORS) |
||
92 | const SECHDR *get_sector(unsigned sec) const; // before use, call fill(d,c,s,LOAD_SECTORS) |
||
93 | |||
94 | void dump(); |
||
95 | void clear() |
||
96 | { |
||
97 | drive = 0; |
||
98 | trkd = 0; |
||
99 | ts_byte = Z80FQ/(MAX_TRACK_LEN * FDD_RPS); |
||
100 | } |
||
101 | TRKCACHE() { clear(); } |
||
102 | }; |
||
103 | |||
104 | |||
105 | struct FDD |
||
106 | { |
||
107 | u8 Id; |
||
108 | // drive data |
||
109 | |||
110 | __int64 motor; // 0 - not spinning, >0 - time when it'll stop |
||
111 | unsigned char track; // head position |
||
112 | |||
113 | // disk data |
||
114 | |||
115 | unsigned char *rawdata; // used in VirtualAlloc/VirtualFree |
||
116 | unsigned rawsize; |
||
117 | unsigned cyls, sides; |
||
118 | unsigned trklen[MAX_CYLS][2]; |
||
119 | u8 *trkd[MAX_CYLS][2]; // данные |
||
120 | u8 *trki[MAX_CYLS][2]; // битовые карты синхроимпульсов |
||
121 | u8 *trkwp[MAX_CYLS][2]; // битовые карты сбойных байтов |
||
122 | unsigned char optype; // bits: 0-not modified, 1-write sector, 2-format track |
||
123 | unsigned char snaptype; |
||
124 | |||
125 | TRKCACHE t; // used in read/write image |
||
126 | char name[0x200]; |
||
127 | char dsc[0x200]; |
||
128 | |||
129 | char test(); |
||
130 | void free(); |
||
131 | int index(); |
||
132 | |||
133 | void format_trd(unsigned CylCnt); // Используется только для wldr_trd |
||
134 | void emptydisk(unsigned FreeSecCnt); // Используется только для wldr_trd |
||
135 | int addfile(unsigned char *hdr, unsigned char *data); // Используется только для wldr_trd |
||
136 | void addboot(); // Используется только для wldr_trd |
||
137 | |||
138 | void newdisk(unsigned cyls, unsigned sides); |
||
139 | |||
140 | int read(unsigned char snType); |
||
141 | |||
142 | int read_scl(); |
||
143 | int read_hob(); |
||
144 | int read_trd(); |
||
145 | int write_trd(FILE *ff); |
||
146 | int read_fdi(); |
||
147 | int write_fdi(FILE *ff); |
||
148 | int read_td0(); |
||
149 | int write_td0(FILE *ff); |
||
150 | int read_udi(); |
||
151 | int write_udi(FILE *ff); |
||
152 | |||
153 | void format_isd(); |
||
154 | int read_isd(); |
||
155 | int write_isd(FILE *ff); |
||
156 | |||
157 | void format_pro(); |
||
158 | int read_pro(); |
||
159 | int write_pro(FILE *ff); |
||
160 | |||
161 | ~FDD() { free(); } |
||
162 | }; |
||
163 | |||
164 | |||
165 | struct WD1793 |
||
166 | { |
||
167 | enum WDSTATE |
||
168 | { |
||
169 | S_IDLE = 0, |
||
170 | S_WAIT, |
||
171 | |||
172 | S_DELAY_BEFORE_CMD, |
||
173 | S_CMD_RW, |
||
174 | S_FOUND_NEXT_ID, |
||
175 | S_RDSEC, |
||
176 | S_READ, |
||
177 | S_WRSEC, |
||
178 | S_WRITE, |
||
179 | S_WRTRACK, |
||
180 | S_WR_TRACK_DATA, |
||
181 | |||
182 | S_TYPE1_CMD, |
||
183 | S_STEP, |
||
184 | S_SEEKSTART, |
||
185 | S_RESTORE, |
||
186 | S_SEEK, |
||
187 | S_VERIFY, |
||
188 | S_VERIFY2, |
||
189 | |||
190 | S_WAIT_HLT, |
||
191 | S_WAIT_HLT_RW, |
||
192 | |||
193 | S_RESET |
||
194 | }; |
||
195 | |||
196 | __int64 next, time; |
||
197 | __int64 idx_tmo; |
||
198 | |||
199 | FDD *seldrive; |
||
200 | unsigned tshift; |
||
201 | |||
202 | WDSTATE state, state2; |
||
203 | |||
204 | unsigned char cmd; |
||
205 | unsigned char data, track, sector; |
||
206 | unsigned char rqs, status; |
||
207 | u8 sign_status; // Внешние сигналы (пока только HLD) |
||
208 | |||
209 | unsigned drive, side; // update this with changing 'system' |
||
210 | |||
211 | signed char stepdirection; |
||
212 | unsigned char system; // beta128 system register |
||
213 | |||
214 | unsigned idx_cnt; // idx counter |
||
215 | |||
216 | // read/write sector(s) data |
||
217 | __int64 end_waiting_am; |
||
218 | unsigned foundid; // index in trkcache.hdr for next encountered ID and bytes before this ID |
||
219 | unsigned rwptr, rwlen; |
||
220 | |||
221 | // format track data |
||
222 | unsigned start_crc; |
||
223 | |||
224 | enum CMDBITS |
||
225 | { |
||
226 | CMD_SEEK_RATE = 0x03, |
||
227 | CMD_SEEK_VERIFY = 0x04, |
||
228 | CMD_SEEK_HEADLOAD = 0x08, |
||
229 | CMD_SEEK_TRKUPD = 0x10, |
||
230 | CMD_SEEK_DIR = 0x20, |
||
231 | |||
232 | CMD_WRITE_DEL = 0x01, |
||
233 | CMD_SIDE_CMP_FLAG = 0x02, |
||
234 | CMD_DELAY = 0x04, |
||
235 | CMD_SIDE = 0x08, |
||
236 | CMD_SIDE_SHIFT = 3, |
||
237 | CMD_MULTIPLE = 0x10 |
||
238 | }; |
||
239 | |||
240 | enum BETA_STATUS |
||
241 | { |
||
242 | DRQ = 0x40, |
||
243 | INTRQ = 0x80 |
||
244 | }; |
||
245 | |||
246 | enum WD_STATUS |
||
247 | { |
||
248 | WDS_BUSY = 0x01, |
||
249 | WDS_INDEX = 0x02, |
||
250 | WDS_DRQ = 0x02, |
||
251 | WDS_TRK00 = 0x04, |
||
252 | WDS_LOST = 0x04, |
||
253 | WDS_CRCERR = 0x08, |
||
254 | WDS_NOTFOUND = 0x10, |
||
255 | WDS_SEEKERR = 0x10, |
||
256 | WDS_RECORDT = 0x20, |
||
257 | WDS_HEADL = 0x20, |
||
258 | WDS_WRFAULT = 0x20, |
||
259 | WDS_WRITEP = 0x40, |
||
260 | WDS_NOTRDY = 0x80 |
||
261 | }; |
||
262 | |||
263 | enum WD_SYS |
||
264 | { |
||
265 | SYS_HLT = 0x08 |
||
266 | }; |
||
267 | |||
268 | enum WD_SIG |
||
269 | { |
||
270 | SIG_HLD = 0x01 |
||
271 | }; |
||
272 | |||
273 | unsigned char in(unsigned char port); |
||
274 | void out(unsigned char port, unsigned char val); |
||
275 | u8 RdStatus(); |
||
276 | |||
277 | void process(); |
||
278 | void find_marker(); |
||
279 | char notready(); |
||
280 | void load(); |
||
281 | void getindex(); |
||
282 | void trdos_traps(); |
||
283 | |||
284 | // TRKCACHE trkcache; |
||
285 | FDD fdd[4]; |
||
286 | |||
287 | WD1793() |
||
288 | { |
||
289 | for(unsigned i = 0; i < 4; i++) // [vv] Для удобства отладки |
||
290 | fdd[i].Id = i; |
||
291 | seldrive = &fdd[0]; |
||
292 | idx_cnt = 0; |
||
293 | idx_tmo = LLONG_MAX; |
||
294 | sign_status = 0; |
||
295 | } |
||
296 | }; |