1 /*This is the chipset used in the Award 286 clone model*/
2 #include "ibm.h"
3 #include "cpu.h"
4 #include "io.h"
5 #include "mem.h"
6 #include "scat.h"
7 #include "x86.h"
8 #include "nmi.h"
9 
10 static uint8_t scat_regs[256];
11 static int scat_index;
12 static uint8_t scat_port_92 = 0;
13 static uint8_t scat_ems_reg_2xA = 0;
14 static mem_mapping_t scat_low_mapping[32];
15 static mem_mapping_t scat_ems_mapping[32];
16 static mem_mapping_t scat_high_mapping[16];
17 static scat_t scat_stat[32];
18 static uint32_t scat_xms_bound;
19 static mem_mapping_t scat_remap_mapping[6];
20 static mem_mapping_t scat_4000_EFFF_mapping[44];
21 static mem_mapping_t scat_low_ROMCS_mapping[8];
22 
23 static int scat_max_map[32] = { 0, 1,  1,  1,  2,  3,  4,  8,
24                                 4, 8, 12, 16, 20, 24, 28, 32,
25                                 0, 5,  9, 13,  6, 10,  0,  0,
26                                 0, 0,  0,  0,  0,  0,  0,  0 };
27 static int scatsx_max_map[32] = {  0,  1,  2,  1,  3,  4,  6, 10,
28                                    5,  9, 13,  4,  8, 12, 16, 14,
29                                   18, 22, 26, 20, 24, 28, 32, 18,
30                                   20, 32,  0,  0,  0,  0,  0,  0 };
31 
32 static int external_is_RAS = 0;
33 
34 static int scatsx_external_is_RAS[33] = { 0, 0, 0, 0, 0, 0, 0, 0,
35                                           0, 0, 0, 1, 0, 0, 1, 1,
36                                           0, 0, 0, 0, 0, 0, 1, 1,
37                                           1, 1, 1, 1, 1, 1, 1, 1,
38                                           0 };
39 
40 uint8_t scat_read(uint16_t port, void *priv);
41 void scat_write(uint16_t port, uint8_t val, void *priv);
42 
scat_romcs_state_update(uint8_t val)43 void scat_romcs_state_update(uint8_t val)
44 {
45         int i;
46         for(i = 0; i < 4; i++)
47         {
48                 if (val & 1)
49                 {
50                         mem_mapping_enable(&scat_low_ROMCS_mapping[i << 1]);
51                         mem_mapping_enable(&scat_low_ROMCS_mapping[(i << 1) + 1]);
52                 }
53                 else
54                 {
55                         mem_mapping_disable(&scat_low_ROMCS_mapping[i << 1]);
56                         mem_mapping_disable(&scat_low_ROMCS_mapping[(i << 1) + 1]);
57                 }
58                 val >>= 1;
59         }
60 
61         for(i = 0; i < 4; i++)
62         {
63                 if (val & 1)
64                 {
65                         mem_mapping_enable(&bios_mapping[i << 1]);
66                         mem_mapping_enable(&bios_mapping[(i << 1) + 1]);
67                 }
68                 else
69                 {
70                         mem_mapping_disable(&bios_mapping[i << 1]);
71                         mem_mapping_disable(&bios_mapping[(i << 1) + 1]);
72                 }
73                 val >>= 1;
74         }
75 }
76 
scat_shadow_state_update()77 void scat_shadow_state_update()
78 {
79         int i, val;
80 
81         for (i = 0; i < 24; i++)
82         {
83                 val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL | MEM_WRITE_INTERNAL : MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
84                 mem_set_mem_state((i + 40) << 14, 0x4000, val);
85         }
86 
87         flushmmucache();
88 }
89 
scat_set_xms_bound(uint8_t val)90 void scat_set_xms_bound(uint8_t val)
91 {
92         uint32_t max_xms_size = ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0xFE0000 : 0xFC0000;
93 
94         switch (val & 0x0F)
95         {
96                 case 1:
97                 scat_xms_bound = 0x100000;
98                 break;
99                 case 2:
100                 scat_xms_bound = 0x140000;
101                 break;
102                 case 3:
103                 scat_xms_bound = 0x180000;
104                 break;
105                 case 4:
106                 scat_xms_bound = 0x200000;
107                 break;
108                 case 5:
109                 scat_xms_bound = 0x300000;
110                 break;
111                 case 6:
112                 scat_xms_bound = 0x400000;
113                 break;
114                 case 7:
115                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000;
116                 break;
117                 case 8:
118                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000;
119                 break;
120                 case 9:
121                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000;
122                 break;
123                 case 10:
124                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000;
125                 break;
126                 case 11:
127                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000;
128                 break;
129                 case 12:
130                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000;
131                 break;
132                 case 13:
133                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000;
134                 break;
135                 case 14:
136                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000;
137                 break;
138                 case 15:
139                 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000;
140                 break;
141                 default:
142                 scat_xms_bound = max_xms_size;
143                 break;
144         }
145 
146         if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3))
147         {
148                 if((val & 0x0F) == 0 || scat_xms_bound > 0x160000)
149                         scat_xms_bound = 0x160000;
150 //                pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, (0x160000 - scat_xms_bound) >> 10);
151                 if (scat_xms_bound > 0x100000)
152                         mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
153                 if (scat_xms_bound < 0x160000)
154                         mem_set_mem_state(scat_xms_bound, 0x160000 - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
155         }
156         else
157         {
158                 if (scat_xms_bound > max_xms_size)
159                         scat_xms_bound = max_xms_size;
160 //                pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, ((mem_size << 10) - scat_xms_bound) >> 10);
161                 if (scat_xms_bound > 0x100000)
162                         mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
163                 if (scat_xms_bound < (mem_size << 10))
164                         mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
165         }
166 
167         mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000);
168         if(scat_regs[SCAT_VERSION] & 0xF0)
169         {
170                 int i;
171                 for(i=0;i<8;i++)
172                 {
173                         if(val & 0x10)
174                                 mem_mapping_disable(&scat_high_mapping[i]);
175                         else
176                                 mem_mapping_enable(&scat_high_mapping[i]);
177                 }
178         }
179 }
180 
get_scat_addr(uint32_t addr,scat_t * p)181 uint32_t get_scat_addr(uint32_t addr, scat_t *p)
182 {
183         int nbank;
184 
185         if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80))
186                 addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14;
187 
188         if ((scat_regs[SCAT_VERSION] & 0xF0) == 0)
189         {
190                 switch((scat_regs[SCAT_EXTENDED_BOUNDARY] & ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 0x40 : 0)) | (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F))
191                 {
192                         case 0x41:
193                         nbank = addr >> 19;
194                         if(nbank < 4)
195                                 nbank = 1;
196                         else if(nbank == 4)
197                                 nbank = 0;
198                         else
199                                 nbank -= 3;
200                         break;
201                         case 0x42:
202                         nbank = addr >> 19;
203                         if(nbank < 8)
204                                 nbank = 1 + (nbank >> 2);
205                         else if(nbank == 8)
206                                 nbank = 0;
207                         else
208                                 nbank -= 6;
209                         break;
210                         case 0x43:
211                         nbank = addr >> 19;
212                         if(nbank < 12)
213                                 nbank = 1 + (nbank >> 2);
214                         else if(nbank == 12)
215                                 nbank = 0;
216                         else
217                                 nbank -= 9;
218                         break;
219                         case 0x44:
220                         nbank = addr >> 19;
221                         if(nbank < 4)
222                                 nbank = 2;
223                         else if(nbank < 6)
224                                 nbank -= 4;
225                         else
226                                 nbank -= 3;
227                         break;
228                         case 0x45:
229                         nbank = addr >> 19;
230                         if(nbank < 8)
231                                 nbank = 2 + (nbank >> 2);
232                         else if(nbank < 10)
233                                 nbank -= 8;
234                         else
235                                 nbank -= 6;
236                         break;
237                         default:
238                         nbank = addr >> (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21);
239                         break;
240                 }
241                 nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3;
242                 if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && nbank == 2 && (addr & 0x7FFFF) < 0x60000 && mem_size > 640)
243                 {
244                         nbank = 1;
245                         addr ^= 0x70000;
246                 }
247 
248                 if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0)
249                 {
250                         if(nbank == 3)
251                                 nbank = 7;
252                         else
253                                 return 0xFFFFFFFF;
254                 }
255                 else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80)
256                 {
257                         switch(nbank)
258                         {
259                                 case 7:
260                                 nbank = 3;
261                                 break;
262                                 // Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed.
263                                 case 5:
264                                 case 1:
265                                 nbank = 1;
266                                 break;
267                                 case 3:
268                                 nbank = 2;
269                                 break;
270                                 default:
271                                 nbank = 0;
272                                 break;
273                         }
274                 }
275 
276                 if((scat_regs[SCAT_VERSION] & 0x0F) > 3 && (mem_size > 2048) && (mem_size & 1536))
277                 {
278                         if((mem_size & 1536) == 512)
279                         {
280                                 if(nbank == 0)
281                                         addr &= 0x7FFFF;
282                                 else
283                                         addr = 0x80000 + ((addr & 0x1FFFFF) | ((nbank - 1) << 21));
284                         }
285                         else
286                         {
287                                 if(nbank < 2)
288                                         addr = (addr & 0x7FFFF) | (nbank << 19);
289                                 else
290                                         addr = 0x100000 + ((addr & 0x1FFFFF) | ((nbank - 2) << 21));
291                         }
292                 }
293                 else
294                 {
295                         int nbanks_2048k, nbanks_512k;
296                         if (mem_size <= ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 2048 : 4096) && (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8) || external_is_RAS))
297                         {
298                                 nbanks_2048k = 0;
299                                 nbanks_512k = mem_size >> 9;
300                         }
301                         else
302                         {
303                                 nbanks_2048k = mem_size >> 11;
304                                 nbanks_512k = (mem_size & 1536) >> 9;
305                         }
306                         if(nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)))
307                         {
308                                   addr &= 0x1FFFFF;
309                                   addr |= (nbank << 21);
310                         }
311                         else if(nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))
312                         {
313                                   addr &= 0x7FFFF;
314                                   addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19);
315                         }
316                         else
317                         {
318                                   addr &= 0x1FFFF;
319                                   addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17);
320                         }
321                 }
322         }
323         else
324         {
325                 uint32_t addr2;
326                 switch(scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F)
327                 {
328                         case 2:
329                         case 4:
330                         nbank = addr >> 19;
331                         if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
332                         {
333                                 nbank = (addr >> 10) & 1;
334                                 addr2 = addr >> 11;
335                         }
336                         else
337                                 addr2 = addr >> 10;
338                         break;
339                         case 3:
340                         nbank = addr >> 19;
341                         if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
342                         {
343                                 nbank = (addr >> 10) & 1;
344                                 addr2 = addr >> 11;
345                         }
346                         else if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7FFFF) < 0x60000)
347                         {
348                                 addr ^= 0x1F0000;
349                                 nbank = (addr >> 10) & 1;
350                                 addr2 = addr >> 11;
351                         }
352                         else
353                                 addr2 = addr >> 10;
354                         break;
355                         case 5:
356                         nbank = addr >> 19;
357                         if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4)
358                         {
359                                 nbank = (addr >> 10) & 3;
360                                 addr2 = addr >> 12;
361                         }
362                         else
363                                 addr2 = addr >> 10;
364                         break;
365                         case 6:
366                         nbank = addr >> 19;
367                         if(nbank < 2)
368                         {
369                                 nbank = (addr >> 10) & 1;
370                                 addr2 = addr >> 11;
371                         }
372                         else
373                         {
374                                 nbank = 2 + ((addr - 0x100000) >> 21);
375                                 addr2 = (addr - 0x100000) >> 11;
376                         }
377                         break;
378                         case 7:
379                         case 0x0F:
380                         nbank = addr >> 19;
381                         if(nbank < 2)
382                         {
383                                 nbank = (addr >> 10) & 1;
384                                 addr2 = addr >> 11;
385                         }
386                         else if(nbank < 10)
387                         {
388                                 nbank = 2 + (((addr - 0x100000) >> 11) & 1);
389                                 addr2 = (addr - 0x100000) >> 12;
390                         }
391                         else
392                         {
393                                 nbank = 4 + ((addr - 0x500000) >> 21);
394                                 addr2 = (addr - 0x500000) >> 11;
395                         }
396                         break;
397                         case 8:
398                         nbank = addr >> 19;
399                         if(nbank < 4)
400                         {
401                                 nbank = 1;
402                                 addr2 = addr >> 11;
403                         }
404                         else if(nbank == 4)
405                         {
406                                 nbank = 0;
407                                 addr2 = addr >> 10;
408                         }
409                         else
410                         {
411                                 nbank -= 3;
412                                 addr2 = addr >> 10;
413                         }
414                         break;
415                         case 9:
416                         nbank = addr >> 19;
417                         if(nbank < 8)
418                         {
419                                 nbank = 1 + ((addr >> 11) & 1);
420                                 addr2 = addr >> 12;
421                         }
422                         else if(nbank == 8)
423                         {
424                                 nbank = 0;
425                                 addr2 = addr >> 10;
426                         }
427                         else
428                         {
429                                 nbank -= 6;
430                                 addr2 = addr >> 10;
431                         }
432                         break;
433                         case 0x0A:
434                         nbank = addr >> 19;
435                         if(nbank < 8)
436                         {
437                                 nbank = 1 + ((addr >> 11) & 1);
438                                 addr2 = addr >> 12;
439                         }
440                         else if(nbank < 12)
441                         {
442                                 nbank = 3;
443                                 addr2 = addr >> 11;
444                         }
445                         else if(nbank == 12)
446                         {
447                                 nbank = 0;
448                                 addr2 = addr >> 10;
449                         }
450                         else
451                         {
452                                 nbank -= 9;
453                                 addr2 = addr >> 10;
454                         }
455                         break;
456                         case 0x0B:
457                         nbank = addr >> 21;
458                         addr2 = addr >> 11;
459                         break;
460                         case 0x0C:
461                         case 0x0D:
462                         nbank = addr >> 21;
463                         if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
464                         {
465                                 nbank = (addr >> 11) & 1;
466                                 addr2 = addr >> 12;
467                         }
468                         else
469                                 addr2 = addr >> 11;
470                         break;
471                         case 0x0E:
472                         case 0x13:
473                         nbank = addr >> 21;
474                         if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4)
475                         {
476                                 nbank = (addr >> 11) & 3;
477                                 addr2 = addr >> 13;
478                         }
479                         else
480                                 addr2 = addr >> 11;
481                         break;
482                         case 0x10:
483                         case 0x11:
484                         nbank = addr >> 19;
485                         if(nbank < 2)
486                         {
487                                 nbank = (addr >> 10) & 1;
488                                 addr2 = addr >> 11;
489                         }
490                         else if(nbank < 10)
491                         {
492                                 nbank = 2 + (((addr - 0x100000) >> 11) & 1);
493                                 addr2 = (addr - 0x100000) >> 12;
494                         }
495                         else if(nbank < 18)
496                         {
497                                 nbank = 4 + (((addr - 0x500000) >> 11) & 1);
498                                 addr2 = (addr - 0x500000) >> 12;
499                         }
500                         else
501                         {
502                                 nbank = 6 + ((addr - 0x900000) >> 21);
503                                 addr2 = (addr - 0x900000) >> 11;
504                         }
505                         break;
506                         case 0x12:
507                         nbank = addr >> 19;
508                         if(nbank < 2)
509                         {
510                                 nbank = (addr >> 10) & 1;
511                                 addr2 = addr >> 11;
512                         }
513                         else if(nbank < 10)
514                         {
515                                 nbank = 2 + (((addr - 0x100000) >> 11) & 1);
516                                 addr2 = (addr - 0x100000) >> 12;
517                         }
518                         else
519                         {
520                                 nbank = 4 + (((addr - 0x500000) >> 11) & 3);
521                                 addr2 = (addr - 0x500000) >> 13;
522                         }
523                         break;
524                         case 0x14:
525                         case 0x15:
526                         nbank = addr >> 21;
527                         if((nbank & 7) < 4)
528                         {
529                                 nbank = (addr >> 11) & 3;
530                                 addr2 = addr >> 13;
531                         }
532                         else if((nbank & 7) < 6)
533                         {
534                                 nbank = 4 + (((addr - 0x800000) >> 11) & 1);
535                                 addr2 = (addr - 0x800000) >> 12;
536                         }
537                         else
538                         {
539                                 nbank = 6 + (((addr - 0xC00000) >> 11) & 3);
540                                 addr2 = (addr - 0xC00000) >> 13;
541                         }
542                         break;
543                         case 0x16:
544                         nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3);
545                         addr2 = addr >> 13;
546                         break;
547                         case 0x17:
548                         if(external_is_RAS && (addr & 0x800) == 0)
549                                 return 0xFFFFFFFF;
550                         nbank = addr >> 19;
551                         if(nbank < 2)
552                         {
553                                 nbank = (addr >> 10) & 1;
554                                 addr2 = addr >> 11;
555                         }
556                         else
557                         {
558                                 nbank = 2 + ((addr - 0x100000) >> 23);
559                                 addr2 = (addr - 0x100000) >> 12;
560                         }
561                         break;
562                         case 0x18:
563                         if(external_is_RAS && (addr & 0x800) == 0)
564                                 return 0xFFFFFFFF;
565                         nbank = addr >> 21;
566                         if(nbank < 4)
567                         {
568                                 nbank = 1;
569                                 addr2 = addr >> 12;
570                         }
571                         else if(nbank == 4)
572                         {
573                                 nbank = 0;
574                                 addr2 = addr >> 11;
575                         }
576                         else
577                         {
578                                 nbank -= 3;
579                                 addr2 = addr >> 11;
580                         }
581                         break;
582                         case 0x19:
583                         if(external_is_RAS && (addr & 0x800) == 0)
584                                 return 0xFFFFFFFF;
585                         nbank = addr >> 23;
586                         if((nbank & 3) < 2)
587                         {
588                                 nbank = (addr >> 12) & 1;
589                                 addr2 = addr >> 13;
590                         }
591                         else
592                                 addr2 = addr >> 12;
593                         break;
594                         default:
595                         if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6)
596                         {
597                                 nbank = addr >> 19;
598                                 addr2 = (addr >> 10) & 0x1FF;
599                         }
600                         else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17)
601                         {
602                                 nbank = addr >> 21;
603                                 addr2 = (addr >> 11) & 0x3FF;
604                         }
605                         else
606                         {
607                                 nbank = addr >> 23;
608                                 addr2 = (addr >> 12) & 0x7FF;
609                         }
610                         break;
611                 }
612 
613                 nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3;
614                 if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 0x16 && nbank == 3)
615                         return 0xFFFFFFFF;
616 
617                 if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0)
618                 {
619                         if(nbank == 3)
620                                 nbank = 7;
621                         else
622                                 return 0xFFFFFFFF;
623                 }
624                 else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80)
625                 {
626                         switch(nbank)
627                         {
628                                 case 7:
629                                 nbank = 3;
630                                 break;
631                                 // Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed.
632                                 case 5:
633                                 case 1:
634                                 nbank = 1;
635                                 break;
636                                 case 3:
637                                 nbank = 2;
638                                 break;
639                                 default:
640                                 nbank = 0;
641                                 break;
642                         }
643                 }
644 
645                 switch(mem_size & ~511)
646                 {
647                         case 1024:
648                         case 1536:
649                         addr &= 0x3FF;
650                         if(nbank < 2)
651                                 addr |= (nbank << 10) | ((addr2 & 0x1FF) << 11);
652                         else
653                                 addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19);
654                         break;
655                         case 2048:
656                         if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 5)
657                         {
658                                 addr &= 0x3FF;
659                                 if(nbank < 4)
660                                         addr |= (nbank << 10) | ((addr2 & 0x1FF) << 12);
661                                 else
662                                         addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19);
663                         }
664                         else
665                         {
666                                 addr &= 0x7FF;
667                                 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
668                         }
669                         break;
670                         case 2560:
671                         if(nbank == 0)
672                                 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
673                         else
674                         {
675                                 addr &= 0x7FF;
676                                 addr2 &= 0x3FF;
677                                 addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21));
678                         }
679                         break;
680                         case 3072:
681                         if(nbank < 2)
682                                 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
683                         else
684                                 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
685                         break;
686                         case 4096:
687                         case 6144:
688                         addr &= 0x7FF;
689                         if(nbank < 2)
690                                 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 12);
691                         else
692                                 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
693                         break;
694                         case 4608:
695                         if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18))
696                         {
697                                 if(nbank == 0)
698                                         addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
699                                 else if(nbank < 3)
700                                         addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12));
701                                 else
702                                         addr = 0x480000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 3) << 19));
703                         }
704                         else if(nbank == 0)
705                                 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
706                         else
707                         {
708                                 addr &= 0x7FF;
709                                 addr2 &= 0x3FF;
710                                 addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21));
711                         }
712                         break;
713                         case 5120:
714                         case 7168:
715                         if(nbank < 2)
716                                 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
717                         else if(nbank < 4)
718                                 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
719                         else
720                                 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
721                         break;
722                         case 6656:
723                         if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18))
724                         {
725                                 if(nbank == 0)
726                                         addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
727                                 else if(nbank < 3)
728                                         addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12));
729                                 else if(nbank == 3)
730                                         addr = 0x480000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11));
731                                 else
732                                         addr = 0x680000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 4) << 19));
733                         }
734                         else if(nbank == 0)
735                                 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
736                         else if(nbank == 1)
737                         {
738                                 addr &= 0x7FF;
739                                 addr2 &= 0x3FF;
740                                 addr = addr + 0x80000 + (addr2 << 11);
741                         }
742                         else
743                         {
744                                 addr &= 0x7FF;
745                                 addr2 &= 0x3FF;
746                                 addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21));
747                         }
748                         break;
749                         case 8192:
750                         addr &= 0x7FF;
751                         if(nbank < 4)
752                                 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
753                         else
754                                 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
755                         break;
756                         case 9216:
757                         if(nbank < 2)
758                                 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
759                         else if(external_is_RAS)
760                         {
761                                 if(nbank < 6)
762                                         addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
763                                 else
764                                         addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
765                         }
766                         else
767                                 addr = 0x100000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23));
768                         break;
769                         case 10240:
770                         if(external_is_RAS)
771                         {
772                                 addr &= 0x7FF;
773                                 if(nbank < 4)
774                                         addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
775                                 else
776                                         addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
777                         }
778                         else if(nbank == 0)
779                                 addr = (addr & 0x7FF) | ((addr2 & 0x3FF) << 11);
780                         else
781                         {
782                                 addr &= 0xFFF;
783                                 addr2 &= 0x7FF;
784                                 addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23));
785                         }
786                         break;
787                         case 11264:
788                         if(nbank < 2)
789                                 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
790                         else if(nbank < 6)
791                                 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
792                         else
793                                 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
794                         break;
795                         case 12288:
796                         if(external_is_RAS)
797                         {
798                                 addr &= 0x7FF;
799                                 if(nbank < 4)
800                                         addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
801                                 else if(nbank < 6)
802                                         addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21);
803                                 else
804                                         addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
805                         }
806                         else
807                         {
808                                 if(nbank < 2)
809                                         addr = (addr & 0x7FF) | (nbank << 11) | ((addr2 & 0x3FF) << 12);
810                                 else
811                                         addr = 0x400000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23));
812                         }
813                         break;
814                         case 13312:
815                         if(nbank < 2)
816                                 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
817                         else if(nbank < 4)
818                                 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
819                         else
820                                 addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11));
821                         break;
822                         case 14336:
823                         addr &= 0x7FF;
824                         if(nbank < 4)
825                                 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
826                         else if(nbank < 6)
827                                 addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21);
828                         else
829                                 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
830                         break;
831                         case 16384:
832                         if(external_is_RAS)
833                         {
834                                 addr &= 0x7FF;
835                                 addr2 &= 0x3FF;
836                                 addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21);
837                         }
838                         else
839                         {
840                                 addr &= 0xFFF;
841                                 addr2 &= 0x7FF;
842                                 if(nbank < 2)
843                                         addr |= (addr2 << 13) | (nbank << 12);
844                                 else
845                                         addr |= (addr2 << 12) | (nbank << 23);
846                         }
847                         break;
848                         default:
849                         if(mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6))
850                         {
851                                 addr &= 0x3FF;
852                                 addr2 &= 0x1FF;
853                                 addr |= (addr2 << 10) | (nbank << 19);
854                         }
855                         else if(mem_size < 8192 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17)
856                         {
857                                 addr &= 0x7FF;
858                                 addr2 &= 0x3FF;
859                                 addr |= (addr2 << 11) | (nbank << 21);
860                         }
861                         else
862                         {
863                                 addr &= 0xFFF;
864                                 addr2 &= 0x7FF;
865                                 addr |= (addr2 << 12) | (nbank << 23);
866                         }
867                         break;
868                 }
869         }
870         return addr;
871 }
872 
scat_set_global_EMS_state(int state)873 void scat_set_global_EMS_state(int state)
874 {
875         int i;
876         uint32_t base_addr, virt_addr;
877 
878         for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++)
879         {
880                 base_addr = (i + 16) << 14;
881                 if(i >= 24)
882                         base_addr += 0x30000;
883                 if(state && (scat_stat[i].regs_2x9 & 0x80))
884                 {
885                         virt_addr = get_scat_addr(base_addr, &scat_stat[i]);
886                         if(i < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
887                         else mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]);
888                         mem_mapping_enable(&scat_ems_mapping[i]);
889                         if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[i], ram + virt_addr);
890                         else mem_mapping_set_exec(&scat_ems_mapping[i], NULL);
891                 }
892                 else
893                 {
894                         mem_mapping_set_exec(&scat_ems_mapping[i], ram + base_addr);
895                         mem_mapping_disable(&scat_ems_mapping[i]);
896 
897                         int conf = (scat_regs[SCAT_VERSION] & 0xF0) ? (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) : (scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2);
898                         if(i < 24)
899                         {
900                                 if(conf > 1 || (conf == 1 && i < 16))
901                                         mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
902                                 else
903                                         mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
904                         }
905                         else if(conf > 3 || ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && conf == 2))
906                                 mem_mapping_enable(&scat_4000_EFFF_mapping[i + 12]);
907                         else
908                                 mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]);
909                 }
910         }
911         flushmmucache();
912 }
913 
scat_memmap_state_update()914 void scat_memmap_state_update()
915 {
916         int i;
917         uint32_t addr;
918 
919         for(i=(((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 16);i<44;i++)
920         {
921                 addr = get_scat_addr(0x40000 + (i << 14), NULL);
922                 mem_mapping_set_exec(&scat_4000_EFFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
923 //                pclog("scat_memmap_state_update : Address %06X to %06X\n", 0x40000 + (i << 14), addr);
924         }
925         addr = get_scat_addr(0, NULL);
926 //        pclog("scat_memmap_state_update : Address 000000 to %06X\n", addr);
927         mem_mapping_set_exec(&scat_low_mapping[0], addr < (mem_size << 10) ? ram + addr : NULL);
928         addr = get_scat_addr(0xF0000, NULL);
929 //        pclog("scat_memmap_state_update : Address 0F0000 to %06X\n", addr);
930         mem_mapping_set_exec(&scat_low_mapping[1], addr < (mem_size << 10) ? ram + addr : NULL);
931         for(i=2;i<32;i++)
932         {
933                 addr = get_scat_addr(i << 19, NULL);
934                 mem_mapping_set_exec(&scat_low_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
935 //                pclog("scat_memmap_state_update : Address %06X to %06X\n", i << 19, addr);
936         }
937 
938         if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
939         {
940                 for(i=0;i < scat_max_map[(scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)];i++)
941                         mem_mapping_enable(&scat_low_mapping[i]);
942                 for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]);
943 
944                 for(i=24;i<36;i++)
945                 {
946                         if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4)
947                                 mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
948                         else
949                                 mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
950                 }
951         }
952         else
953         {
954                 for(i=0;i < scatsx_max_map[scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F];i++)
955                         mem_mapping_enable(&scat_low_mapping[i]);
956                 for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]);
957 
958                 for(i=24;i<36;i++)
959                 {
960                         if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 2 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)
961                                 mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
962                         else
963                                 mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
964                 }
965         }
966 
967         if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0))
968         {
969                 if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3))
970                 {
971                         mem_mapping_disable(&scat_low_mapping[2]);
972                         for(i=0;i<6;i++)
973                         {
974                                 addr = get_scat_addr(0x100000 + (i << 16), NULL);
975                                 mem_mapping_set_exec(&scat_remap_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
976                                 mem_mapping_enable(&scat_remap_mapping[i]);
977 //                                pclog("scat_memmap_state_update : Address %06X to %06X\n", 0x100000 + (i << 16), addr);
978                         }
979                 }
980                 else
981                 {
982                         for(i=0;i<6;i++)
983                                 mem_mapping_disable(&scat_remap_mapping[i]);
984                         if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 4) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 3))
985                                 mem_mapping_enable(&scat_low_mapping[2]);
986                 }
987         }
988         else
989         {
990                 for(i=0;i<6;i++)
991                         mem_mapping_disable(&scat_remap_mapping[i]);
992                 mem_mapping_enable(&scat_low_mapping[2]);
993         }
994 
995         scat_set_global_EMS_state(scat_regs[SCAT_EMS_CONTROL] & 0x80);
996 }
997 
scat_write(uint16_t port,uint8_t val,void * priv)998 void scat_write(uint16_t port, uint8_t val, void *priv)
999 {
1000         uint8_t scat_reg_valid = 0, scat_shadow_update = 0, scat_map_update = 0, index;
1001         uint32_t base_addr, virt_addr;
1002 
1003         switch (port)
1004         {
1005                 case 0x22:
1006                 scat_index = val;
1007                 break;
1008 
1009                 case 0x23:
1010                 switch (scat_index)
1011                 {
1012                         case SCAT_DMA_WAIT_STATE_CONTROL:
1013                         case SCAT_CLOCK_CONTROL:
1014                         case SCAT_PERIPHERAL_CONTROL:
1015                         scat_reg_valid = 1;
1016                         break;
1017                         case SCAT_EMS_CONTROL:
1018                         if(val & 0x40)
1019                         {
1020                                 if(val & 1)
1021                                 {
1022                                         io_sethandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1023                                         io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1024                                 }
1025                                 else
1026                                 {
1027                                         io_sethandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1028                                         io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1029                                 }
1030                         }
1031                         else
1032                         {
1033                                 io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1034                                 io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1035                         }
1036                         scat_set_global_EMS_state(val & 0x80);
1037                         scat_reg_valid = 1;
1038                         break;
1039                         case SCAT_POWER_MANAGEMENT:
1040                         // TODO - Only use AUX parity disable bit for this version. Other bits should be implemented later.
1041                         val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60;
1042                         scat_reg_valid = 1;
1043                         break;
1044                         case SCAT_DRAM_CONFIGURATION:
1045                         scat_map_update = 1;
1046 
1047                         if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
1048                         {
1049                                 cpu_waitstates = (val & 0x70) == 0 ? 1 : 2;
1050                                 cpu_update_waitstates();
1051                         }
1052 
1053                         scat_reg_valid = 1;
1054                         break;
1055                         case SCAT_EXTENDED_BOUNDARY:
1056                         if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
1057                         {
1058                                 if(scat_regs[SCAT_VERSION] < 4)
1059                                 {
1060                                         val &= 0xBF;
1061                                         scat_set_xms_bound(val & 0x0f);
1062                                 }
1063                                 else
1064                                 {
1065                                         val = (val & 0x7F) | 0x80;
1066                                         scat_set_xms_bound(val & 0x4f);
1067                                 }
1068                         }
1069                         else
1070                                 scat_set_xms_bound(val & 0x1f);
1071                         mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1072                         if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0xC0) scat_map_update = 1;
1073                         scat_reg_valid = 1;
1074                         break;
1075                         case SCAT_ROM_ENABLE:
1076                         scat_reg_valid = 1;
1077                         scat_romcs_state_update(val);
1078                         break;
1079                         case SCAT_RAM_WRITE_PROTECT:
1080                         scat_reg_valid = 1;
1081                         flushmmucache_cr3();
1082                         break;
1083                         case SCAT_SHADOW_RAM_ENABLE_1:
1084                         case SCAT_SHADOW_RAM_ENABLE_2:
1085                         case SCAT_SHADOW_RAM_ENABLE_3:
1086                         scat_reg_valid = 1;
1087                         scat_shadow_update = 1;
1088                         break;
1089                         case SCATSX_LAPTOP_FEATURES:
1090                         if((scat_regs[SCAT_VERSION] & 0xF0) != 0)
1091                         {
1092                                 val = (val & ~8) | (scat_regs[SCATSX_LAPTOP_FEATURES] & 8);
1093                                 scat_reg_valid = 1;
1094                         }
1095                         break;
1096                         case SCATSX_FAST_VIDEO_CONTROL:
1097                         case SCATSX_FAST_VIDEORAM_ENABLE:
1098                         case SCATSX_HIGH_PERFORMANCE_REFRESH:
1099                         case SCATSX_CAS_TIMING_FOR_DMA:
1100                         if((scat_regs[SCAT_VERSION] & 0xF0) != 0) scat_reg_valid = 1;
1101                         break;
1102                         default:
1103                         break;
1104                 }
1105                 if (scat_reg_valid)
1106                         scat_regs[scat_index] = val;
1107                 else pclog("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.oldpc);
1108                 if (scat_shadow_update)
1109                         scat_shadow_state_update();
1110                 if (scat_map_update)
1111                         scat_memmap_state_update();
1112 //                pclog("Write SCAT Register %02X to %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc);
1113                 break;
1114 
1115                 case 0x92:
1116                 if ((mem_a20_alt ^ val) & 2)
1117                 {
1118                          mem_a20_alt = val & 2;
1119                          mem_a20_recalc();
1120                 }
1121                 if ((~scat_port_92 & val) & 1)
1122                 {
1123                          softresetx86();
1124                         cpu_set_edx();
1125                 }
1126                 scat_port_92 = val;
1127                 break;
1128 
1129                 case 0x208:
1130                 case 0x218:
1131                 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1132                 {
1133 //                        pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc);
1134                         if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1135                         else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1136                         scat_stat[index].regs_2x8 = val;
1137                         base_addr = (index + 16) << 14;
1138                         if(index >= 24)
1139                                 base_addr += 0x30000;
1140 
1141                         if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80))
1142                         {
1143                                 virt_addr = get_scat_addr(base_addr, &scat_stat[index]);
1144                                 if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr);
1145                                 else mem_mapping_set_exec(&scat_ems_mapping[index], NULL);
1146                                 flushmmucache();
1147                         }
1148                 }
1149                 break;
1150                 case 0x209:
1151                 case 0x219:
1152                 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1153                 {
1154 //                        pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc);
1155                         if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1156                         else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1157                         scat_stat[index].regs_2x9 = val;
1158                         base_addr = (index + 16) << 14;
1159                         if(index >= 24)
1160                                 base_addr += 0x30000;
1161 
1162                         if (scat_regs[SCAT_EMS_CONTROL] & 0x80)
1163                         {
1164                                 if (val & 0x80)
1165                                 {
1166                                         virt_addr = get_scat_addr(base_addr, &scat_stat[index]);
1167                                         if(index < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[index]);
1168                                         else mem_mapping_disable(&scat_4000_EFFF_mapping[index + 12]);
1169                                         if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr);
1170                                         else mem_mapping_set_exec(&scat_ems_mapping[index], NULL);
1171                                         mem_mapping_enable(&scat_ems_mapping[index]);
1172 //                                        pclog("Map page %d(address %05X) to address %06X\n", index, base_addr, virt_addr);
1173                                 }
1174                                 else
1175                                 {
1176                                         mem_mapping_set_exec(&scat_ems_mapping[index], ram + base_addr);
1177                                         mem_mapping_disable(&scat_ems_mapping[index]);
1178                                         if(index < 24) mem_mapping_enable(&scat_4000_EFFF_mapping[index]);
1179                                         else mem_mapping_enable(&scat_4000_EFFF_mapping[index + 12]);
1180 //                                        pclog("Unmap page %d(address %06X)\n", index, base_addr);
1181                                 }
1182                                 flushmmucache();
1183                         }
1184 
1185                         if (scat_ems_reg_2xA & 0x80)
1186                         {
1187                                 scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0x1f : 3));
1188                         }
1189                 }
1190                 break;
1191                 case 0x20A:
1192                 case 0x21A:
1193                 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1194                 {
1195 //                        pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc);
1196                         scat_ems_reg_2xA = ((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? val : val & 0xc3;
1197                 }
1198                 break;
1199         }
1200 }
1201 
scat_read(uint16_t port,void * priv)1202 uint8_t scat_read(uint16_t port, void *priv)
1203 {
1204         uint8_t val = 0xff, index;
1205         switch (port)
1206         {
1207                 case 0x23:
1208                 switch (scat_index)
1209                 {
1210                         case SCAT_MISCELLANEOUS_STATUS:
1211                         val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5);
1212                         break;
1213                         case SCAT_DRAM_CONFIGURATION:
1214                         if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10);
1215                         else val = scat_regs[scat_index];
1216                         break;
1217                         case SCAT_EXTENDED_BOUNDARY:
1218                         val = scat_regs[scat_index];
1219                         if ((scat_regs[SCAT_VERSION] & 0xF0) == 0)
1220                         {
1221                                 if((scat_regs[SCAT_VERSION] & 0x0F) >= 4)
1222                                         val |= 0x80;
1223                                 else
1224                                         val &= 0xAF;
1225                         }
1226                         break;
1227                         default:
1228                         val = scat_regs[scat_index];
1229                         break;
1230                 }
1231 //                pclog("Read SCAT Register %02X at %04X:%04X\n", scat_index, CS, cpu_state.pc);
1232                 break;
1233 
1234                 case 0x92:
1235                 val = scat_port_92;
1236                 break;
1237 
1238                 case 0x208:
1239                 case 0x218:
1240                 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1241                 {
1242 //                        pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc);
1243                         if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1244                         else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1245                         val = scat_stat[index].regs_2x8;
1246                 }
1247                 break;
1248                 case 0x209:
1249                 case 0x219:
1250                 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1251                 {
1252 //                        pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc);
1253                         if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1254                         else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1255                         val = scat_stat[index].regs_2x9;
1256                 }
1257                 break;
1258                 case 0x20A:
1259                 case 0x21A:
1260                 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1261                 {
1262 //                        pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc);
1263                         val = scat_ems_reg_2xA;
1264                 }
1265                 break;
1266         }
1267         return val;
1268 }
1269 
mem_read_scatb(uint32_t addr,void * priv)1270 uint8_t mem_read_scatb(uint32_t addr, void *priv)
1271 {
1272         uint8_t val = 0xff;
1273         scat_t *stat = (scat_t *)priv;
1274 
1275         addr = get_scat_addr(addr, stat);
1276         if (addr < (mem_size << 10))
1277                 val = ram[addr];
1278 
1279         return val;
1280 }
1281 
mem_write_scatb(uint32_t addr,uint8_t val,void * priv)1282 void mem_write_scatb(uint32_t addr, uint8_t val, void *priv)
1283 {
1284         scat_t *stat = (scat_t *)priv;
1285         uint32_t oldaddr = addr, chkaddr;
1286 
1287         addr = get_scat_addr(addr, stat);
1288         chkaddr = stat ? addr : oldaddr;
1289         if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
1290         {
1291                 if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
1292         }
1293         if (addr < (mem_size << 10))
1294                   ram[addr] = val;
1295 }
1296 
mem_read_scatw(uint32_t addr,void * priv)1297 uint16_t mem_read_scatw(uint32_t addr, void *priv)
1298 {
1299         uint16_t val = 0xffff;
1300         scat_t *stat = (scat_t *)priv;
1301 
1302         if((addr & 0x3FFF) == 0x3FFF) pclog("mem_read_scatw(%08X, %p) called.\n", addr, priv);
1303         addr = get_scat_addr(addr, stat);
1304         if (addr < (mem_size << 10))
1305                 val = *(uint16_t *)&ram[addr];
1306 
1307         return val;
1308 }
1309 
mem_write_scatw(uint32_t addr,uint16_t val,void * priv)1310 void mem_write_scatw(uint32_t addr, uint16_t val, void *priv)
1311 {
1312         scat_t *stat = (scat_t *)priv;
1313         uint32_t oldaddr = addr, chkaddr;
1314 
1315         if((addr & 0x3FFF) == 0x3FFF) pclog("mem_write_scatw(%08X, %04X, %p) called.\n", addr, val, priv);
1316         addr = get_scat_addr(addr, stat);
1317         chkaddr = stat ? addr : oldaddr;
1318         if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
1319         {
1320                 if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
1321         }
1322         if (addr < (mem_size << 10))
1323                   *(uint16_t *)&ram[addr] = val;
1324 }
1325 
mem_read_scatl(uint32_t addr,void * priv)1326 uint32_t mem_read_scatl(uint32_t addr, void *priv)
1327 {
1328         uint32_t val = 0xffffffff;
1329         scat_t *stat = (scat_t *)priv;
1330 
1331         if((addr & 0x3FFF) > 0x3FFC) pclog("mem_read_scatl(%08X, %p) called.\n", addr, priv);
1332         addr = get_scat_addr(addr, stat);
1333         if (addr < (mem_size << 10))
1334                 val = *(uint32_t *)&ram[addr];
1335 
1336         return val;
1337 }
1338 
mem_write_scatl(uint32_t addr,uint32_t val,void * priv)1339 void mem_write_scatl(uint32_t addr, uint32_t val, void *priv)
1340 {
1341         scat_t *stat = (scat_t *)priv;
1342         uint32_t oldaddr = addr, chkaddr;
1343 
1344         if((addr & 0x3FFF) > 0x3FFC) pclog("mem_write_scatl(%08X, %08X, %p) called.\n", addr, val, priv);
1345         addr = get_scat_addr(addr, stat);
1346         chkaddr = stat ? addr : oldaddr;
1347         if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
1348         {
1349                 if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
1350         }
1351         if (addr < (mem_size << 10))
1352                   *(uint32_t *)&ram[addr] = val;
1353 }
1354 
scat_init()1355 void scat_init()
1356 {
1357         int i;
1358 
1359         io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1360         io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1361 
1362         for (i = 0; i < 256; i++)
1363         {
1364                 scat_regs[i] = 0xff;
1365         }
1366 
1367         scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0;
1368         switch(romset)
1369         {
1370                 case ROM_GW286CT:
1371                 case ROM_SPC4216P:
1372                 scat_regs[SCAT_VERSION] = 4;
1373                 break;
1374                 default:
1375                 scat_regs[SCAT_VERSION] = 1;
1376                 break;
1377         }
1378         scat_regs[SCAT_CLOCK_CONTROL] = 2;
1379         scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80;
1380         scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37;
1381         scat_regs[SCAT_POWER_MANAGEMENT] = 0;
1382         scat_regs[SCAT_ROM_ENABLE] = 0xC0;
1383         scat_regs[SCAT_RAM_WRITE_PROTECT] = 0;
1384         scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0;
1385         scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0;
1386         scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0;
1387         scat_regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12;
1388         scat_regs[SCAT_EXTENDED_BOUNDARY] = 0;
1389         scat_regs[SCAT_EMS_CONTROL] = 0;
1390         scat_port_92 = 0;
1391 
1392         mem_mapping_disable(&ram_low_mapping);
1393         mem_mapping_disable(&ram_mid_mapping);
1394         mem_mapping_disable(&ram_high_mapping);
1395         for (i = 0; i < 4; i++)
1396                 mem_mapping_disable(&bios_mapping[i]);
1397         mem_mapping_add(&scat_low_mapping[0], 0, 0x40000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL);
1398         mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL);
1399         for(i=2;i<32;i++)
1400         {
1401                 mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL);
1402         }
1403         mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, scat_regs[SCAT_VERSION] < 4 ? 0x40000 : 0x60000);
1404 
1405         for (i = 0; i < 44; i++)
1406                 mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
1407         for (i = 0; i < 8; i++)
1408         {
1409                 mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL);
1410                 mem_mapping_disable(&scat_low_ROMCS_mapping[i]);
1411         }
1412 
1413         for (i = 0; i < 32; i++)
1414         {
1415                 scat_stat[i].regs_2x8 = 0xff;
1416                 scat_stat[i].regs_2x9 = 0x03;
1417                 mem_mapping_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]);
1418         }
1419 
1420         for(i=4;i<10;i++) isram[i] = 0;
1421 
1422         for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++)
1423         {
1424                 mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL);
1425                 mem_mapping_enable(&scat_high_mapping[i]);
1426         }
1427 
1428         for(i=0;i<6;i++)
1429                 mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
1430 
1431         external_is_RAS = (scat_regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4;
1432 
1433         scat_set_xms_bound(0);
1434         scat_memmap_state_update();
1435         scat_shadow_state_update();
1436 }
1437 
scatsx_init()1438 void scatsx_init()
1439 {
1440         int i;
1441 
1442         io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1443         io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL,  NULL);
1444 
1445         for (i = 0; i < 256; i++)
1446         {
1447                 scat_regs[i] = 0xff;
1448         }
1449 
1450         scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0;
1451         scat_regs[SCAT_VERSION] = 0x13;
1452         scat_regs[SCAT_CLOCK_CONTROL] = 6;
1453         scat_regs[SCAT_PERIPHERAL_CONTROL] = 0;
1454         scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37;
1455         scat_regs[SCAT_POWER_MANAGEMENT] = 0;
1456         scat_regs[SCAT_ROM_ENABLE] = 0xC0;
1457         scat_regs[SCAT_RAM_WRITE_PROTECT] = 0;
1458         scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0;
1459         scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0;
1460         scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0;
1461         scat_regs[SCAT_DRAM_CONFIGURATION] = 1;
1462         scat_regs[SCAT_EXTENDED_BOUNDARY] = 0;
1463         scat_regs[SCAT_EMS_CONTROL] = 0;
1464         scat_regs[SCATSX_LAPTOP_FEATURES] = 0;
1465         scat_regs[SCATSX_FAST_VIDEO_CONTROL] = 0;
1466         scat_regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0;
1467         scat_regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8;
1468         scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3;
1469         scat_port_92 = 0;
1470 
1471         mem_mapping_disable(&ram_low_mapping);
1472         mem_mapping_disable(&ram_mid_mapping);
1473         mem_mapping_disable(&ram_high_mapping);
1474         for (i = 0; i < 4; i++)
1475                 mem_mapping_disable(&bios_mapping[i]);
1476         mem_mapping_add(&scat_low_mapping[0], 0, 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL);
1477         mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL);
1478         for(i=2;i<32;i++)
1479         {
1480                 mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL);
1481         }
1482         mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, 0x40000);
1483 
1484         for (i = 16; i < 44; i++)
1485         {
1486                 mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
1487                 mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
1488         }
1489         for (i = 0; i < 8; i++)
1490         {
1491                 mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL);
1492                 mem_mapping_disable(&scat_low_ROMCS_mapping[i]);
1493         }
1494 
1495         for (i = 24; i < 32; i++)
1496         {
1497                 scat_stat[i].regs_2x8 = 0xff;
1498                 scat_stat[i].regs_2x9 = 0x03;
1499                 mem_mapping_add(&scat_ems_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + 28) << 14), 0, &scat_stat[i]);
1500                 mem_mapping_disable(&scat_ems_mapping[i]);
1501         }
1502 
1503         for (i = 0; i < 16; i++)
1504         {
1505                 mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL);
1506                 mem_mapping_enable(&scat_high_mapping[i]);
1507         }
1508 
1509         for(i=0;i<6;i++)
1510                 mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
1511 
1512         external_is_RAS = scatsx_external_is_RAS[mem_size >> 9];
1513 
1514         scat_set_xms_bound(0);
1515         scat_memmap_state_update();
1516         scat_shadow_state_update();
1517 }
1518