2 Skelton for retropc emulator
5 Author : Takeda.Toshiya
16 I8237::I8237(VM_TEMPLATE* parent_vm, EMU* parent_emu) : I8237_BASE(parent_vm, parent_emu)
18 for(int i = 0; i < 4; i++) {
19 dma[i].dev = vm->dummy;
21 #ifdef SINGLE_MODE_DMA
30 void I8237::write_io8(uint32_t addr, uint32_t data)
32 int ch = (addr >> 1) & 3;
33 uint8_t bit = 1 << (data & 3);
36 case 0x00: case 0x02: case 0x04: case 0x06:
38 dma[ch].bareg = (dma[ch].bareg & 0xff) | (data << 8);
40 dma[ch].bareg = (dma[ch].bareg & 0xff00) | data;
42 dma[ch].areg = dma[ch].bareg;
45 case 0x01: case 0x03: case 0x05: case 0x07:
47 dma[ch].bcreg = (dma[ch].bcreg & 0xff) | (data << 8);
49 dma[ch].bcreg = (dma[ch].bcreg & 0xff00) | data;
51 dma[ch].creg = dma[ch].bcreg;
63 #ifndef SINGLE_MODE_DMA
72 // single mask register
81 dma[data & 3].mode = data;
91 // clear mask register
101 void I8237::write_signal(int id, uint32_t data, uint32_t mask)
103 if(SIG_I8237_CH0 <= id && id <= SIG_I8237_CH3) {
104 int ch = id - SIG_I8237_CH0;
105 uint8_t bit = 1 << ch;
108 write_signals(&dma[ch].outputs_tc, 0);
110 #ifndef SINGLE_MODE_DMA
117 } else if(SIG_I8237_BANK0 <= id && id <= SIG_I8237_BANK3) {
118 // external bank registers
119 int ch = id - SIG_I8237_BANK0;
120 dma[ch].bankreg &= ~mask;
121 dma[ch].bankreg |= data & mask;
122 } else if(SIG_I8237_MASK0 <= id && id <= SIG_I8237_MASK3) {
123 // external bank registers
124 int ch = id - SIG_I8237_MASK0;
125 dma[ch].incmask &= ~mask;
126 dma[ch].incmask |= data & mask;
130 uint32_t I8237::read_signal(int id)
132 if(SIG_I8237_BANK0 <= id && id <= SIG_I8237_BANK3) {
133 // external bank registers
134 int ch = id - SIG_I8237_BANK0;
135 return dma[ch].bankreg;
136 } else if(SIG_I8237_MASK0 <= id && id <= SIG_I8237_MASK3) {
137 // external bank registers
138 int ch = id - SIG_I8237_MASK0;
139 return dma[ch].incmask;
144 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
148 for(int ch = 0; ch < 4; ch++) {
149 uint8_t bit = 1 << ch;
150 if((req & bit) && !(mask & bit)) {
153 switch(dma[ch].mode & 0x0c) {
161 write_mem(dma[ch].areg | (dma[ch].bankreg << 16), tmp);
165 tmp = read_mem(dma[ch].areg | (dma[ch].bankreg << 16));
169 if(dma[ch].mode & 0x20) {
171 if(dma[ch].areg == 0xffff) {
172 dma[ch].bankreg = (dma[ch].bankreg & ~dma[ch].incmask) | ((dma[ch].bankreg - 1) & dma[ch].incmask);
176 if(dma[ch].areg == 0) {
177 dma[ch].bankreg = (dma[ch].bankreg & ~dma[ch].incmask) | ((dma[ch].bankreg + 1) & dma[ch].incmask);
181 // check dma condition
182 if(dma[ch].creg-- == 0) {
184 if(dma[ch].mode & 0x10) {
186 dma[ch].areg = dma[ch].bareg;
187 dma[ch].creg = dma[ch].bcreg;
193 write_signals(&dma[ch].outputs_tc, 0xffffffff);
194 #ifdef SINGLE_MODE_DMA
195 } else if((dma[ch].mode & 0xc0) == 0x40) {
203 #ifdef SINGLE_MODE_DMA
210 #define STATE_VERSION 2
212 bool I8237::process_state(FILEIO* state_fio, bool loading)
214 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
217 if(!state_fio->StateCheckInt32(this_device_id)) {
220 for(int i = 0; i < 4; i++) {
221 state_fio->StateUint16(dma[i].areg);
222 state_fio->StateUint16(dma[i].creg);
223 state_fio->StateUint16(dma[i].bareg);
224 state_fio->StateUint16(dma[i].bcreg);
225 state_fio->StateUint8(dma[i].mode);
226 state_fio->StateUint16(dma[i].bankreg);
227 state_fio->StateUint16(dma[i].incmask);
229 state_fio->StateBool(low_high);
230 state_fio->StateUint8(cmd);
231 state_fio->StateUint8(req);
232 state_fio->StateUint8(mask);
233 state_fio->StateUint8(tc);
234 state_fio->StateUint32(tmp);
235 state_fio->StateBool(mode_word);
236 state_fio->StateUint32(addr_mask);