OSDN Git Service

4d3b1af047ca213bdeb337c25e482f9a3acdf0aa
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmr50 / 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 "../upd71071.h"
15
16 // control register
17 #define CTRL_WEN        0x80
18 #define CTRL_IMSK       0x40
19 #define CTRL_ATN        0x10
20 #define CTRL_SEL        0x04
21 #define CTRL_DMAE       0x02
22 #define CTRL_RST        0x01
23
24 #define STATUS_REQ      0x80
25 #define STATUS_IO       0x40
26 #define STATUS_MSG      0x20
27 #define STATUS_CD       0x10
28 #define STATUS_BSY      0x08
29 #define STATUS_INT      0x02
30 #define STATUS_PERR     0x01
31
32 void SCSI::reset()
33 {
34         ctrl_reg = CTRL_IMSK;
35         irq_status = false;
36 }
37
38 void SCSI::write_io8(uint32_t addr, uint32_t data)
39 {
40         switch(addr & 0xffff) {
41         case 0xc30:
42                 // data register
43                 #ifdef _SCSI_DEBUG_LOG
44                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
45                 #endif
46                 if(ctrl_reg & CTRL_WEN) {
47                         d_host->write_dma_io8(addr, data);
48                 }
49                 break;
50                 
51         case 0xc32:
52                 // control register
53                 #ifdef _SCSI_DEBUG_LOG
54                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
55                 #endif
56                 ctrl_reg = data;
57                 if(ctrl_reg  & CTRL_WEN) {
58                         d_host->write_signal(SIG_SCSI_RST, data, CTRL_RST);
59                         d_host->write_signal(SIG_SCSI_SEL, data, CTRL_SEL);
60                         d_host->write_signal(SIG_SCSI_ATN, data, CTRL_ATN);
61                 }
62                 break;
63         }
64 }
65
66 uint32_t SCSI::read_io8(uint32_t addr)
67 {
68         uint32_t value = 0;
69         
70         switch(addr & 0xffff) {
71         case 0xc30:
72                 // data register
73                 if(ctrl_reg & CTRL_WEN) {
74                         value = d_host->read_dma_io8(addr);
75                 }
76                 #ifdef _SCSI_DEBUG_LOG
77                         this->out_debug_log(_T("[SCSI] in  %04X %02X\n"), addr, value);
78                 #endif
79                 return value;
80                 
81         case 0xc32:
82                 // status register
83                 value = (d_host->read_signal(SIG_SCSI_REQ) ? STATUS_REQ : 0) |
84                         (d_host->read_signal(SIG_SCSI_IO ) ? STATUS_IO  : 0) |
85                         (d_host->read_signal(SIG_SCSI_MSG) ? STATUS_MSG : 0) |
86                         (d_host->read_signal(SIG_SCSI_CD ) ? STATUS_CD  : 0) |
87                         (d_host->read_signal(SIG_SCSI_BSY) ? STATUS_BSY : 0) |
88                         (irq_status                        ? STATUS_INT : 0);
89                 #ifdef _SCSI_DEBUG_LOG
90                         this->out_debug_log(_T("[SCSI] in  %04X %02X\n"), addr, value);
91                 #endif
92                 return value;
93         }
94         return 0xff;
95 }
96
97 void SCSI::write_signal(int id, uint32_t data, uint32_t mask)
98 {
99         switch(id) {
100         case SIG_SCSI_IRQ:
101                 if(ctrl_reg & CTRL_IMSK) {
102                         d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR0, data, mask);
103                 }
104                 irq_status = ((data & mask) != 0);
105                 break;
106                 
107         case SIG_SCSI_DRQ:
108                 if(ctrl_reg & CTRL_DMAE) {
109                         d_dma->write_signal(SIG_UPD71071_CH1, data, mask);
110                 }
111                 break;
112         }
113 }
114
115 #define STATE_VERSION   1
116
117 #include "../../statesub.h"
118
119 void SCSI::decl_state()
120 {
121         enter_decl_state(STATE_VERSION);
122
123         DECL_STATE_ENTRY_UINT8(ctrl_reg);
124         DECL_STATE_ENTRY_BOOL(irq_status);
125         
126         leave_decl_state();
127 }
128
129 void SCSI::save_state(FILEIO* state_fio)
130 {
131         if(state_entry != NULL) {
132                 state_entry->save_state(state_fio);
133         }
134
135 //      state_fio->FputUint32(STATE_VERSION);
136 //      state_fio->FputInt32(this_device_id);
137         
138 //      state_fio->FputUint8(ctrl_reg);
139 //      state_fio->FputBool(irq_status);
140 }
141
142 bool SCSI::load_state(FILEIO* state_fio)
143 {
144         bool mb = false;
145         if(state_entry != NULL) {
146                 mb = state_entry->load_state(state_fio);
147         }
148         if(!mb) {
149                 return false;
150         }
151
152 //      if(state_fio->FgetUint32() != STATE_VERSION) {
153 //              return false;
154 //      }
155 //      if(state_fio->FgetInt32() != this_device_id) {
156 //              return false;
157 //      }
158 //      ctrl_reg = state_fio->FgetUint8();
159 //      irq_status = state_fio->FgetBool();
160         return true;
161 }
162
163 bool SCSI::process_state(FILEIO* state_fio, bool loading)
164 {
165         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
166                 return false;
167         }
168         if(!state_fio->StateCheckInt32(this_device_id)) {
169                 return false;
170         }
171         state_fio->StateUint8(ctrl_reg);
172         state_fio->StateBool(irq_status);
173         return true;
174 }