OSDN Git Service

67da95292944feda1f5df598a462a3bb49310ed5
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc9801 / sasi.cpp
1 /*
2         NEC PC-9801VX Emulator 'ePC-9801VX'
3         NEC PC-9801RA Emulator 'ePC-9801RA'
4         NEC PC-98XA Emulator 'ePC-98XA'
5         NEC PC-98XL Emulator 'ePC-98XL'
6         NEC PC-98RL Emulator 'ePC-98RL'
7
8         Author : Takeda.Toshiya
9         Date   : 2018.04.01-
10
11         [ sasi i/f ]
12 */
13
14 #include "sasi.h"
15 #include "../harddisk.h"
16 #include "../i8237.h"
17 #include "../i8259.h"
18 #include "../scsi_host.h"
19 #include "../scsi_hdd.h"
20
21 #define OCR_CHEN        0x80
22 #define OCR_NRDSW       0x40
23 #define OCR_SEL         0x20
24 #define OCR_RST         0x08
25 #define OCR_DMAE        0x02
26 #define OCR_INTE        0x01
27
28 #define ISR_REQ         0x80
29 #define ISR_ACK         0x40
30 #define ISR_BSY         0x20
31 #define ISR_MSG         0x10
32 #define ISR_CXD         0x08
33 #define ISR_IXO         0x04
34 #define ISR_INT         0x01
35
36 void SASI::reset()
37 {
38         ocr = 0;
39         irq_status = drq_status = false;
40 }
41
42 void SASI::write_io8(uint32_t addr, uint32_t data)
43 {
44         switch(addr) {
45         case 0x0080:
46                 #ifdef _SCSI_DEBUG_LOG
47                         this->out_debug_log(_T("[SASI] out %04X %02X\n"), addr, data);
48                 #endif
49 //              if(ocr & OCR_CHEN) {
50                         d_host->write_dma_io8(addr, data);
51 //              }
52                 break;
53                 
54         case 0x0082:
55                 #ifdef _SCSI_DEBUG_LOG
56                         this->out_debug_log(_T("[SASI] out %04X %02X\n"), addr, data);
57                 #endif
58                 d_host->write_signal(SIG_SCSI_RST, data, OCR_RST);
59                 d_host->write_signal(SIG_SCSI_SEL, data, OCR_SEL);
60                 ocr = data;
61                 break;
62         }
63 }
64
65 uint32_t SASI::read_io8(uint32_t addr)
66 {
67         uint32_t value = 0;
68         
69         switch(addr) {
70         case 0x0080:
71 //              if(ocr & OCR_CHEN) {
72                         value = d_host->read_dma_io8(addr);
73 //              }
74                 #ifdef _SCSI_DEBUG_LOG
75                         this->out_debug_log(_T("[SASI] in  %04X %02X\n"), addr, value);
76                 #endif
77                 return value;
78                 
79         case 0x0082:
80                 if(ocr & OCR_NRDSW) {
81                         value = (d_host->read_signal(SIG_SCSI_REQ) ? ISR_REQ : 0) |
82 //                              (d_host->read_signal(SIG_SCSI_ACK) ? ISR_ACK : 0) |
83                                 (d_host->read_signal(SIG_SCSI_BSY) ? ISR_BSY : 0) |
84                                 (d_host->read_signal(SIG_SCSI_MSG) ? ISR_MSG : 0) |
85                                 (d_host->read_signal(SIG_SCSI_CD ) ? ISR_CXD : 0) |
86                                 (d_host->read_signal(SIG_SCSI_IO ) ? ISR_IXO : 0) |
87                                 (irq_status                        ? ISR_INT : 0);
88 //                      irq_status = false;
89                         #ifdef _SCSI_DEBUG_LOG
90                                 this->out_debug_log(_T("[SASI] in  %04X %02X (REQ=%d,BSY=%d,MSG=%d,CxD=%d,IxO=%d,DH=%02X,DL=%02X)\n"), addr, value,
91                                         (value & ISR_REQ) ? 1 : 0,
92                                         (value & ISR_BSY) ? 1 : 0,
93                                         (value & ISR_MSG) ? 1 : 0,
94                                         (value & ISR_CXD) ? 1 : 0,
95                                         (value & ISR_IXO) ? 1 : 0,
96                                         vm->get_cpu(0)->read_debug_reg(_T("DH")), vm->get_cpu(0)->read_debug_reg(_T("DL")));
97                         #endif
98                 } else {
99                         value = 0;
100                         for(int i = 0; i < 2; i++) {
101                                 HARDDISK *unit = d_hdd->get_disk_handler(i);
102                                 uint32_t dt = 7, ct = 0;
103                                 
104                                 if(unit != NULL && unit->mounted()) {
105                                         double size = unit->sector_num * unit->sector_size;
106                                         int size_mb = (int)(size / 1024.0 / 1024.0 + 0.5);
107                                         
108                                         if(size_mb <= 6) {
109                                                 dt = 0;
110                                         } else if(size_mb <= 11) {
111                                                 dt = 1;
112                                         } else if(size_mb <= 16) {
113                                                 dt = 2;
114                                         } else if(size_mb <= 21) {
115                                                 if(unit->surfaces != 4) {
116                                                         dt = 3;
117                                                 } else {
118                                                         dt = 4;
119                                                 }
120                                         } else if(size_mb <= 31) {
121                                                 dt = 5;
122                                         } else {
123                                                 dt = 6;
124                                         }
125                                         if(unit->sector_size == 512) {
126                                                 ct = 1;
127                                         }
128                                 }
129                                 value |= dt << (i == 0 ? 3 : 0);
130                                 value |= ct << (i == 0 ? 7 : 6);
131                         }
132                         #ifdef _SCSI_DEBUG_LOG
133                                 this->out_debug_log(_T("[SASI] in  %04X %02X (NRDSW=0)\n"), addr, value);
134                         #endif
135                 }
136                 return value;
137         }
138         return 0xff;
139 }
140
141 /*
142 void SASI::write_dma_io8(uint32_t addr, uint32_t data)
143 {
144         write_io8(0x0080, data);
145 }
146
147 uint32_t SASI::read_dma_io8(uint32_t addr)
148 {
149         return read_io8(0x0080);
150 }
151 */
152
153 void SASI::write_signal(int id, uint32_t data, uint32_t mask)
154 {
155         switch(id) {
156         case SIG_SASI_IRQ:
157                 #ifdef _SCSI_DEBUG_LOG
158                         this->out_debug_log(_T("[SASI] IRQ=%d\n"), (data & mask) ? 1 : 0);
159                 #endif
160                 if(ocr & OCR_INTE) {
161                         d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR1, data, mask);
162                 }
163                 irq_status = ((data & mask) != 0);
164                 break;
165                 
166         case SIG_SASI_DRQ:
167                 #ifdef _SCSI_DEBUG_LOG
168                         this->out_debug_log(_T("[SASI] DRQ=%d\n"), (data & mask) ? 1 : 0);
169                 #endif
170                 if(ocr & OCR_DMAE) {
171                         #ifdef _PC98XA
172                                 d_dma->write_signal(SIG_I8237_CH3, data, mask);
173                         #else
174                                 d_dma->write_signal(SIG_I8237_CH0, data, mask);
175                         #endif
176                 } else {
177                         if(data & mask) {
178                                 #ifdef _SCSI_DEBUG_LOG
179                                         this->out_debug_log(_T("[SASI] DMAE=0, change IRQ\n"));
180                                 #endif
181                                 write_signal(SIG_SASI_IRQ, data, mask);
182                         }
183                 }
184                 drq_status = ((data & mask) != 0);
185                 break;
186                 
187         case SIG_SASI_TC:
188                 #ifdef _SCSI_DEBUG_LOG
189                         this->out_debug_log(_T("[SASI] TC=%d\n"), (data & mask) ? 1 : 0);
190                 #endif
191                 if(data & mask) {
192                         ocr &= ~OCR_DMAE;
193                 }
194                 break;
195         }
196 }
197
198 #define STATE_VERSION   2
199
200 bool SASI::process_state(FILEIO* state_fio, bool loading)
201 {
202         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
203                 return false;
204         }
205         if(!state_fio->StateCheckInt32(this_device_id)) {
206                 return false;
207         }
208         state_fio->StateUint8(ocr);
209         state_fio->StateBool(irq_status);
210         state_fio->StateBool(drq_status);
211         return true;
212 }
213