OSDN Git Service

[VM] TRY:Use namespace {VMNAME} to separate around VMs. This feature still apply...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / floppy.cpp
1 /*
2  * FM-7 Main I/O -> FDC [floppy.cpp]
3  *
4  * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
5  * License: GPLv2
6  * History:
7  *   Mar 19, 2015 : Initial, split from fm7_mainio.cpp .
8  *
9  */
10
11 #include "fm7_mainio.h"
12
13 #include "../mc6809.h"
14 #include "../z80.h"
15
16 #include "../mb8877.h"
17 #include "../disk.h"
18 #if defined(HAS_DMA)
19 #include "hd6844.h"
20 #endif
21
22 namespace FM7 {
23         
24 #define FDC_CMD_TYPE1           1
25 #define FDC_CMD_RD_SEC          2
26 #define FDC_CMD_RD_MSEC         3
27 #define FDC_CMD_WR_SEC          4
28 #define FDC_CMD_WR_MSEC         5
29 #define FDC_CMD_RD_ADDR         6
30 #define FDC_CMD_RD_TRK          7
31 #define FDC_CMD_WR_TRK          8
32 #define FDC_CMD_TYPE4           0x80
33
34 void FM7_MAINIO::reset_fdc(void)
35 {
36         if(connect_fdc) {
37                 fdc_cmdreg = 0;
38                 fdc_statreg = fdc->read_io8(0);
39                 fdc_trackreg = fdc->read_io8(1);
40                 fdc_sectreg = fdc->read_io8(2);
41                 fdc_datareg = fdc->read_io8(3);
42                 fdc_headreg = 0xfe | fdc->read_signal(SIG_MB8877_SIDEREG);
43                 fdc_drvsel = 0x7c | fdc->read_signal(SIG_MB8877_DRIVEREG);
44                 irqreg_fdc = 0x00; //0b00000000;
45         }
46         //fdc_motor = (fdc->read_signal(SIG_MB8877_MOTOR) != 0);
47         fdc_motor = false;
48         
49 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
50         defined(_FM77AV20) || defined(_FM77AV20EX)
51         if(connect_fdc) {
52                 fdc_reg_fd1e = 0x80;
53                 for(int i = 0; i < 4; i++) {
54                         fdc_drive_table[i] = (uint8_t)i;
55                         fdc->set_drive_type(i, DRIVE_TYPE_2D);
56                 }
57         }
58 #else
59         if(connect_fdc) {
60                 for(int i = 0; i < 4; i++) {
61                         fdc->set_drive_type(i, DRIVE_TYPE_2D);
62                 }
63         }
64 #endif  
65         if(event_fdc_motor >= 0) cancel_event(this, event_fdc_motor);
66         event_fdc_motor = -1;
67         irqstat_fdc = false;
68         irqmask_mfd = true;
69         if(connect_fdc) {
70                 set_fdc_motor(fdc_motor);
71         }
72 }
73         
74
75 /* FDD */
76
77 void FM7_MAINIO::set_fdc_cmd(uint8_t val)
78 {
79         if(!connect_fdc) return;
80         //irqreg_fdc = 0x00;
81         fdc_cmdreg = val;
82 #if defined(HAS_DMA)
83         if(((fdc_cmdreg >= 0x80) && (fdc_cmdreg < 0xd0)) || (fdc_cmdreg >= 0xe0)) {
84                 uint32_t words = dmac->read_signal(HD6844_WORDS_REG_0);
85                 if((words != 0) && (words < 0xffff) && (dmac->read_signal(HD6844_IS_TRANSFER_0) == 0)) {
86                         dmac->write_signal(HD6844_SRC_FIXED_ADDR_CH0, 3, 0xffffffff);
87                         dmac->write_signal(HD6844_TRANSFER_START, 0, 0xffffffff);
88                         //this->out_debug_log(_T("FDC: Start DMA CMDREG=%02x CHRN=%02x %02x %02x * DRVSEL=%08x\n"),
89                         //                                       fdc_cmdreg, fdc_trackreg, fdc_headreg & 0x01, fdc_sectreg, fdc_drvsel);
90                 }
91         }
92 #endif  
93         fdc->write_io8(0, val & 0x00ff);
94 //#ifdef _FM7_FDC_DEBUG 
95         if(config.special_debug_fdc) out_debug_log(_T("FDC: CMD: $%02x"), fdc_cmdreg);
96 //#endif        
97 }
98
99 uint8_t FM7_MAINIO::get_fdc_stat(void)
100 {
101         //uint32_t stat_backup = fdc_statreg;
102         if(!connect_fdc) return 0xff;
103         fdc_statreg =  fdc->read_io8(0);
104 #ifdef _FM7_FDC_DEBUG   
105         if(stat_backup != fdc_statreg) this->out_debug_log(_T("FDC: \nGet Stat(not busy): $%02x"), fdc_statreg);
106 #endif  
107         return fdc_statreg;
108 }
109
110 void FM7_MAINIO::set_fdc_track(uint8_t val)
111 {
112         if(!connect_fdc) return;
113         // if mode is 2DD and type-of-image = 2D then val >>= 1;
114         
115         fdc_trackreg = val;
116 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
117         defined(_FM77AV20) || defined(_FM77AV20EX)
118         uint32_t d;
119         if((fdc_drvsel & 0x40) == 0) {
120                 d = fdc_drive_table[fdc_drvsel & 0x03] & 0x03;
121         } else {
122                 d = fdc_drvsel & 0x03;
123         }
124 #if 1
125         DISK *disk = fdc->get_disk_handler(d);
126         if(disk->media_type != MEDIA_TYPE_2D){
127                 if(config.special_debug_fdc)  out_debug_log(_T("NOTE: MEDIA TYPE IS 2DD"));
128                 //if(disk->drive_type == DRIVE_TYPE_2D) val <<= 1;
129         } else { 
130                 if(config.special_debug_fdc)  out_debug_log(_T("NOTE: MEDIA TYPE IS 2D"));
131                 //if(disk->drive_type != DRIVE_TYPE_2D) val >>= 1;
132         }
133 #endif
134 #endif  
135         fdc->write_io8(1, val);
136 //#ifdef _FM7_FDC_DEBUG 
137         if(config.special_debug_fdc)  out_debug_log(_T("FDC : Set Track: %d"), val);
138 //#endif        
139 }
140
141 uint8_t FM7_MAINIO::get_fdc_track(void)
142 {
143         if(!connect_fdc) return 0xff;
144         fdc_trackreg = fdc->read_io8(1);
145         return fdc_trackreg;
146 }
147
148 void FM7_MAINIO::set_fdc_sector(uint8_t val)
149 {
150         if(!connect_fdc) return;
151         fdc_sectreg = val;
152         fdc->write_io8(2, val);
153 //#ifdef _FM7_FDC_DEBUG 
154         if(config.special_debug_fdc)  out_debug_log(_T("FDC: Set Sector: $%02x"), val);
155 //#endif        
156 }
157
158 uint8_t FM7_MAINIO::get_fdc_sector(void)
159 {
160         if(!connect_fdc) return 0xff;
161         fdc_sectreg = fdc->read_io8(2);
162         return fdc_sectreg;
163 }
164   
165 void FM7_MAINIO::set_fdc_data(uint8_t val)
166 {
167         if(!connect_fdc) return;
168         fdc_datareg = val;
169         fdc->write_io8(3, val & 0x00ff);
170 }
171
172 uint8_t FM7_MAINIO::get_fdc_data(void)
173 {
174         if(!connect_fdc) return 0xff;
175         fdc_datareg = fdc->read_io8(3);
176         
177         return fdc_datareg;
178 }
179
180 uint8_t FM7_MAINIO::get_fdc_motor(void)
181 {
182         uint8_t val = 0x3c; //0b01111100;
183         uint8_t drv;
184         bool bv;
185         
186         if(!connect_fdc) return 0xff;
187         fdc_motor = (fdc->read_signal(SIG_MB8877_MOTOR) != 0) ? true : false;
188         //fdc_drvsel = fdc->read_signal(SIG_MB8877_READ_DRIVE_REG);
189         drv = fdc_drvsel & 0x03;
190         val = val | (fdc_drvsel & 0x03);
191 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
192         defined(_FM77AV20) || defined(_FM77AV20EX)
193         val = val | (fdc_drvsel & 0x40);
194         if((fdc_drvsel & 0x40) != 0) {
195                 drv = fdc_drive_table[drv & 0x03];
196         }
197 #endif  
198         fdc_motor = fdc_motor & (fdc->get_drive_type(drv) != DRIVE_TYPE_UNK);
199         if(fdc_motor) val |= 0x80;
200 //#ifdef _FM7_FDC_DEBUG 
201         if(config.special_debug_fdc)  out_debug_log(_T("FDC: Get motor/Drive: $%02x"), val);
202 //#endif        
203         return val;
204 }
205   
206 void FM7_MAINIO::set_fdc_fd1c(uint8_t val)
207 {
208         if(!connect_fdc) return;
209         fdc_headreg = (val & 0x01) | 0xfe;
210         fdc->write_signal(SIG_MB8877_SIDEREG, val, 0x01);
211 //#ifdef _FM7_FDC_DEBUG 
212         if(config.special_debug_fdc)  out_debug_log(_T("FDC: Set side/head: $%02x"), val);
213 //#endif        
214 }
215
216 uint8_t FM7_MAINIO::get_fdc_fd1c(void)
217 {
218         if(!connect_fdc) return 0xff;
219         //fdc_headreg = fdc->read_signal(SIG_MB8877_SIDEREG);
220         return fdc_headreg;
221 }
222
223 void FM7_MAINIO::set_fdc_fd1d(uint8_t val)
224 {
225         bool backup_motor = fdc_motor;
226         bool f;
227         if(!connect_fdc) return;
228         if((val & 0x80) != 0) {
229                 f = true;
230         } else {
231                 f = false;
232         }
233
234 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
235         defined(_FM77AV20) || defined(_FM77AV20EX)
236         if((val & 0x40) == 0) {
237                 fdc->write_signal(SIG_MB8877_DRIVEREG, fdc_drive_table[val & 0x03], 0x03);
238         } else {
239                 fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x03);
240         }
241         fdc_drvsel = val;
242 #else
243         fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x03);
244         fdc_drvsel = val;
245 #endif  
246
247         if(f != backup_motor) {
248                 if(event_fdc_motor >= 0) cancel_event(this, event_fdc_motor);
249                 if(f) {
250                         register_event(this, EVENT_FD_MOTOR_ON, 1000.0 * 300.0, false, &event_fdc_motor); // Motor ON After 0.3Sec.
251                 } else {
252                         register_event(this, EVENT_FD_MOTOR_OFF, 1000.0 * 50.0, false, &event_fdc_motor); // Motor OFF After 0.05Sec.
253                 }
254         }
255 //#ifdef _FM7_FDC_DEBUG 
256         if(config.special_debug_fdc)  out_debug_log(_T("FDC: Set Drive Select: $%02x"), val);
257 //#endif        
258 }
259
260 uint8_t FM7_MAINIO::get_fdc_fd1e(void)
261 {
262 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
263         defined(_FM77AV20) || defined(_FM77AV20EX)
264         uint8_t val = 0xa0;
265         val |= (fdc_reg_fd1e & 0x5f);
266         if(config.special_debug_fdc) out_debug_log(_T("FDC: GET $FD1E value=$%02x"), val);
267         return val;
268 #else
269         //if(config.special_debug_fdc) out_debug_log(_T("FDC: GET $FD1E value=$%02x"), val);
270         return 0xff;
271 #endif
272 }       
273
274 void FM7_MAINIO::set_fdc_fd1e(uint8_t val)
275 {
276 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
277         defined(_FM77AV20) || defined(_FM77AV20EX)
278         uint8_t drive;
279         if(!connect_fdc) return;
280         
281         fdc_reg_fd1e = val;
282         
283         if((val & 0x10) != 0) {
284                 fdc_drive_table[(val & 0x0c) >> 2] = val & 0x03;
285                 if(((val & 0x0c) >> 2) == (fdc_drvsel & 0x03)) {
286                         fdc->write_signal(SIG_MB8877_DRIVEREG, fdc_drive_table[(val & 0x0c) >> 2], 0x03);
287                 }
288         }
289         if((val & 0x40) != 0) {
290                 for(drive = 0; drive < MAX_DRIVE; drive++) fdc->set_drive_type(drive, DRIVE_TYPE_2D);
291                 if(config.special_debug_fdc) out_debug_log(_T("SET DRIVE to 2D"));
292         } else {
293                 for(drive = 0; drive < MAX_DRIVE; drive++) fdc->set_drive_type(drive, DRIVE_TYPE_2DD);
294                 if(config.special_debug_fdc) out_debug_log(_T("SET DRIVE to 2DD"));
295         }
296         if(config.special_debug_fdc) out_debug_log(_T("FDC: SET $FD1E value=$%02x"), val);
297 #endif  
298 }
299
300 void FM7_MAINIO::set_irq_mfd(bool flag)
301 {
302         bool backup = irqstat_fdc;
303         if(!connect_fdc) return;
304         if(flag) {
305                 irqreg_fdc |= 0x40; //0b01000000;
306         } else {
307                 irqreg_fdc &= 0xbf; //0b10111111;
308         }
309 #if defined(_FM77_VARIANTS)
310         flag = flag & !(intmode_fdc);
311 #endif
312 //#if !defined(_FM8) // With FM8, $FD1F is alive and not do_irq(), Thanks to Anna_Wu.
313         irqstat_fdc = flag & !irqmask_mfd;
314         if(backup != irqstat_fdc) do_irq();
315 //#endif
316         return;
317 }
318
319 void FM7_MAINIO::set_drq_mfd(bool flag)
320 {
321         if(!connect_fdc) return;
322         if(flag) {
323                 irqreg_fdc |= 0x80;//0b10000000;
324         } else {
325                 irqreg_fdc &= 0x7f; //0b01111111;
326         }
327 #if defined(HAS_DMA)
328         if((dmac->read_signal(HD6844_IS_TRANSFER_0) != 0) && (flag)) {
329                 dmac->write_signal(HD6844_DO_TRANSFER, 0x0, 0xffffffff);
330         }
331 #endif  
332         return;
333 }
334
335 uint8_t FM7_MAINIO::fdc_getdrqirq(void)
336 {
337         uint8_t val = irqreg_fdc | 0x3f;
338         if(!connect_fdc) return 0xff;
339         return val;
340 }
341
342 void FM7_MAINIO::set_fdc_motor(bool flag)
343 {
344         if(!connect_fdc) return;
345         uint8_t val;
346         fdc->write_signal(SIG_MB8877_MOTOR, flag ? 0x01 : 0x00, 0x01);
347         val = fdc_drvsel & 0x03;
348 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
349         defined(_FM77AV20) || defined(_FM77AV20EX)
350         if((fdc_drvsel & 0x40) == 0) {
351                 val = fdc_drive_table[val & 0x03];
352         }
353 #endif
354         fdc_motor = (fdc->read_signal(SIG_MB8877_MOTOR) != 0);
355         fdc_motor = fdc_motor & (fdc->get_drive_type(val) != DRIVE_TYPE_UNK);
356         if(config.special_debug_fdc) out_debug_log(_T("FDC: MOTOR=%d VAL=$%02x"), flag, val);
357 }
358
359 }