OSDN Git Service

[VM][FMTOWNS][DMAC][CDROM][SCSI] FM-Towns's DMAC don't push CPU wait.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / scsi.cpp
1 /*
2         FUJITSU FMR-50 Emulator 'eFMR-50'
3         FUJITSU FMR-60 Emulator 'eFMR-60'
4
5         Author : Takeda.Toshiya
6         Date   : 2016.03.03-
7
8         [ scsi ]
9 */
10
11 #include "scsi.h"
12 #include "../i8259.h"
13 #include "../scsi_host.h"
14 #include "./dmac.h"
15
16 #undef _SCSI_DEBUG_LOG
17 // control register
18 #define CTRL_WEN        0x80
19 #define CTRL_IMSK       0x40
20 #define CTRL_ATN        0x10
21 #define CTRL_SEL        0x04
22 #define CTRL_DMAE       0x02
23 #define CTRL_RST        0x01
24
25 #define STATUS_REQ      0x80
26 #define STATUS_IO       0x40
27 #define STATUS_MSG      0x20
28 #define STATUS_CD       0x10
29 #define STATUS_BSY      0x08
30 #define STATUS_INT      0x02
31 #define STATUS_PERR     0x01
32
33 namespace FMTOWNS {
34
35 void SCSI::reset()
36 {
37         ctrl_reg = CTRL_IMSK;
38         irq_status = false;
39         irq_status_bak = false;
40         exirq_status = false;
41         ex_int_enable = false;
42         dma_enabled = true;
43 }
44
45 void SCSI::write_io8w(uint32_t addr, uint32_t data, int *wait)
46 {
47 //      out_debug_log(_T("Write I/O %04X %02X"), addr, data);
48         *wait = 6; // temporally.
49         switch(addr & 0xffff) {
50         case 0x0c30:
51                 // data register
52                 #ifdef _SCSI_DEBUG_LOG
53                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
54                 #endif
55 //                      d_host->write_signal(SIG_SCSI_REQ, 0, 0);
56                 if(ctrl_reg & CTRL_WEN) {
57 //              if((ctrl_reg & CTRL_WEN) && !(ctrl_reg & CTRL_DMAE)) {
58                         d_host->write_dma_io8(addr, data);
59                 }
60                 break;
61
62         case 0x0c32:
63                 // control register
64                 #ifdef _SCSI_DEBUG_LOG
65                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
66                 #endif
67                 if((machine_id >= 0x0300) & ((machine_id & 0xff00) != 0x0400)) { // After UX
68                         ex_int_enable = ((data & 0x20) != 0) ? true : false;
69                         // Set host to 16bit bus width. BIT3 ,= '1'.
70                 }
71                 if(ctrl_reg  & CTRL_WEN) {
72                         d_host->write_signal(SIG_SCSI_RST, data, CTRL_RST);
73                         d_host->write_signal(SIG_SCSI_ATN, data, CTRL_ATN);
74                         d_host->write_signal(SIG_SCSI_SEL, data, CTRL_SEL);
75                         d_host->write_signal(SIG_SCSI_HOST_DMAE, data, CTRL_DMAE);
76                 }
77                 ctrl_reg = data;
78                 if((data & CTRL_DMAE) != 0) dma_enabled = true;
79                 break;
80         }
81 }
82
83
84 uint32_t SCSI::read_io8w(uint32_t addr, int* wait)
85 {
86         uint32_t value = 0;
87         *wait = 6; // Temporally
88         switch(addr & 0xffff) {
89         case 0x0034:
90 //              if(machine_id >= 0x0600) { // After UG
91 //                      value = 0x7f; // Ready to transfer 16bit width DMA, excepts CX/UX.
92 //              } else {
93                         value = 0xff;
94 //              }
95                 break;
96         case 0x0c30:
97                 // data register
98 //              d_host->write_signal(SIG_SCSI_REQ, 0, 0);
99 //              if((ctrl_reg & CTRL_WEN) && !(ctrl_reg & CTRL_DMAE)) {
100                 if(ctrl_reg & CTRL_WEN) {
101                         value = d_host->read_dma_io8(addr);
102                 }
103                 #ifdef _SCSI_DEBUG_LOG
104                         this->out_debug_log(_T("[SCSI] in  %04X %02X\n"), addr, value);
105                 #endif
106 //              return value;
107                 break;
108         case 0x0c32:
109                 // status register
110                 value = (d_host->read_signal(SIG_SCSI_REQ) ? STATUS_REQ : 0) |
111                         (d_host->read_signal(SIG_SCSI_IO ) ? STATUS_IO  : 0) |
112                         (d_host->read_signal(SIG_SCSI_MSG) ? STATUS_MSG : 0) |
113                             (d_host->read_signal(SIG_SCSI_CD ) ? STATUS_CD  : 0) |
114                                 (d_host->read_signal(SIG_SCSI_BSY) ? STATUS_BSY : 0) |
115                         (irq_status                        ? STATUS_INT : 0);
116                 if((machine_id >= 0x0300) & ((machine_id & 0xff00) != 0x0400)) { // After UX
117                         value = value | 0x00;
118                 } else {
119                         value = value | 0x04; // Disable EX-Int.
120                 }
121                 #ifdef _SCSI_DEBUG_LOG
122                         this->out_debug_log(_T("[SCSI] in  %04X %02X\n"), addr, value);
123                 #endif
124 //                      irq_status = false;
125 //              return value;
126                         break;
127         case 0xc34:
128                 // From MAME 0.216
129                 // Linux uses this port to detect the ability to do word transfers.  We'll tell it that it doesn't for now.
130                 value = 0x80;
131                 break;
132         }
133 //      out_debug_log(_T("[SCSI] READ I/O %04X %02X\n"), addr, value);
134         return value;
135 }
136 #if 0
137 void SCSI::write_io16w(uint32_t addr, uint32_t data, int *wait)
138 {
139         write_io8w(addr & 0xfffe, data, wait);
140 }
141 uint32_t SCSI::read_io16w(uint32_t addr, int *wait)
142 {
143         return read_io8w(addr & 0xfffe, wait);
144 }
145 #endif
146 void SCSI::write_signal(int id, uint32_t data, uint32_t mask)
147 {
148         switch(id) {
149         case SIG_SCSI_16BIT_BUS:
150                 //transfer_16bit = ((data & mask) != 0) ? true : false;
151                 break;
152         case SIG_SCSI_IRQ:
153                 if((ctrl_reg & CTRL_IMSK)) {
154 //                      if(irq_status_bak != ((data & mask) != 0)) {
155                                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR0, data, mask);
156                                 //out_debug_log(_T("[SCSI] IRQ  %04X %02X\n"), data, mask);
157 //                      }
158                         irq_status_bak = ((data & mask) != 0);
159                 }
160                 if((machine_id >= 0x0300) & ((machine_id & 0xff00) != 0x0400)) { // After UX
161                         if(!(exirq_status)) {
162                                 irq_status = ((data & mask) != 0);
163                         } else {
164                                 irq_status = true;
165                         }
166                 } else {
167                         irq_status = ((data & mask) != 0);
168                 }
169                 break;
170
171         case SIG_SCSI_DRQ:
172                 if(((ctrl_reg & CTRL_DMAE) != 0) /*&& (dma_enabled)*/) {
173                         d_dma->write_signal(SIG_UPD71071_CH1, data, mask);
174                 }
175 /*              if((machine_id >= 0x0300) & ((machine_id & 0xff00) != 0x0400)) { // After UX
176                         if(ex_int_enable) {
177                                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR0, data, mask);
178                                 exirq_status = ((data & mask) != 0);
179                                 if(exirq_status) {
180                                         irq_status = true;
181                                 } else if(!(irq_status_bak)) {
182                                         irq_status = false;
183                                 }
184                         }
185                 }*/
186                 break;
187         case SIG_SCSI_EOT:
188                 dma_enabled = ((data & mask) == 0) ? true : false;
189                 break;
190         }
191 }
192
193 #define STATE_VERSION   4
194
195 bool SCSI::process_state(FILEIO* state_fio, bool loading)
196 {
197         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
198                 return false;
199         }
200         if(!state_fio->StateCheckInt32(this_device_id)) {
201                 return false;
202         }
203         state_fio->StateValue(machine_id);
204         state_fio->StateValue(cpu_id);
205
206         state_fio->StateValue(ctrl_reg);
207         state_fio->StateValue(irq_status);
208         state_fio->StateValue(irq_status_bak);
209         state_fio->StateValue(dma_enabled);
210
211         if((machine_id >= 0x0300) & ((machine_id & 0xff00) != 0x0400)) { // After UX
212                 state_fio->StateValue(ex_int_enable);
213                 state_fio->StateValue(exirq_status);
214         }
215         return true;
216 }
217 }