]> git.sesse.net Git - pistorm/blob - platforms/amiga/Gayle.c
Silence some compile warnings
[pistorm] / platforms / amiga / Gayle.c
1 //
2 //  Gayle.c
3 //  Omega
4 //
5 //  Created by Matt Parsons on 06/03/2019.
6 //  Copyright © 2019 Matt Parsons. All rights reserved.
7 //
8
9 // Write Byte to Gayle Space 0xda9000 (0x0000c3)
10 // Read Byte From Gayle Space 0xda9000
11 // Read Byte From Gayle Space 0xdaa000
12
13 #include "Gayle.h"
14 #include <fcntl.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <time.h>
20 #include <endian.h>
21
22 #include "platforms/shared/rtc.h"
23 #include "config_file/config_file.h"
24
25 #include "gayle-ide/ide.h"
26 #include "amiga-registers.h"
27
28 #define DEBUG(...)
29 //#define DEBUG printf
30
31 uint8_t gary_cfg[8];
32
33 uint8_t ramsey_cfg = 0x08;
34 static uint8_t ramsey_id = RAMSEY_REV7;
35
36 int counter;
37 static uint8_t gayle_irq, gayle_cs, gayle_cs_mask, gayle_cfg;
38 static struct ide_controller *ide0 = NULL;
39 int fd;
40
41 uint8_t rtc_type = RTC_TYPE_RICOH;
42
43 char *hdd_image_file[GAYLE_MAX_HARDFILES];
44
45 uint8_t cdtv_mode = 0;
46 unsigned char cdtv_sram[32 * SIZE_KILO];
47
48 uint8_t gayle_a4k = 0xA0;
49 uint16_t gayle_a4k_irq = 0;
50 uint8_t gayle_a4k_int = 0;
51 uint8_t gayle_int = 0;
52
53 uint32_t gayle_ide_mask = ~GDATA;
54 uint32_t gayle_ide_base = GDATA;
55 uint8_t gayle_ide_enabled = 1;
56 uint8_t gayle_emulation_enabled = 1;
57 uint8_t gayle_ide_adj = 0;
58
59 struct ide_controller *get_ide(int index) {
60   if (index) {}
61   return ide0;
62 }
63
64 void adjust_gayle_4000() {
65   gayle_ide_base = GAYLE_IDE_BASE_A4000;
66   gayle_ide_adj = 2;
67   gayle_a4k_int = 1;
68 }
69
70 void adjust_gayle_1200() {
71
72 }
73
74 void set_hard_drive_image_file_amiga(uint8_t index, char *filename) {
75   if (hdd_image_file[index] != NULL)
76     free(hdd_image_file[index]);
77   hdd_image_file[index] = calloc(1, strlen(filename) + 1);
78   strcpy(hdd_image_file[index], filename);
79 }
80
81 void InitGayle(void) {
82   uint8_t num_ide_drives = 0;
83
84   for (int i = 0; i < GAYLE_MAX_HARDFILES; i++) {
85     if (hdd_image_file[i]) {
86       fd = open(hdd_image_file[i], O_RDWR);
87       if (fd != -1) {
88         if (!ide0)
89             ide0 = ide_allocate("cf");
90       }
91
92       if (fd == -1) {
93         printf("[HDD%d] HDD Image %s failed open\n", i, hdd_image_file[i]);
94       } else {
95         printf("[HDD%d] Attaching HDD image %s.\n", i, hdd_image_file[i]);
96         if (strcmp(hdd_image_file[i] + (strlen(hdd_image_file[i]) - 3), "img") != 0) {
97           printf("No header present on HDD image %s.\n", hdd_image_file[i]);
98           ide_attach_hdf(ide0, i, fd);
99           num_ide_drives++;
100         }
101         else {
102           printf("Attaching HDD image with header.\n");
103           ide_attach(ide0, i, fd);
104           num_ide_drives++;
105         }
106         printf("[HDD%d] HDD Image %s attached\n", i, hdd_image_file[i]);
107       }
108     }
109   }
110   if (ide0)
111     ide_reset_begin(ide0);
112
113   if (num_ide_drives == 0) {
114     // No IDE drives mounted, disable IDE component of Gayle
115     printf("No IDE drives mounted, disabling Gayle IDE component.\n");
116     gayle_ide_enabled = 0;
117   }
118 }
119
120 uint8_t CheckIrq(void) {
121   uint8_t irq;
122
123   if (gayle_int & (1 << 7)) {
124     irq = ide0->drive[0].intrq || ide0->drive[1].intrq;
125     //  if (irq==0)
126     //  printf("IDE IRQ: %x\n",irq);
127     return irq;
128   };
129   return 0;
130 }
131
132 static uint8_t ide_action = 0;
133
134 void writeGayleB(unsigned int address, unsigned int value) {
135   if (ide0) {
136     if (address >= gayle_ide_base) {
137       switch ((address - gayle_ide_base) - gayle_ide_adj) {
138         case GFEAT_OFFSET:
139           //printf("Write to GFEAT: %.2X.\n", value);
140           ide_action = ide_feature_w;
141           goto idewrite8;
142         case GCMD_OFFSET:
143           //printf("Write to GCMD: %.2X.\n", value);
144           ide_action = ide_command_w;
145           goto idewrite8;
146         case GSECTCOUNT_OFFSET:
147           ide_action = ide_sec_count;
148           goto idewrite8;
149         case GSECTNUM_OFFSET:
150           ide_action = ide_sec_num;
151           goto idewrite8;
152         case GCYLLOW_OFFSET:
153           ide_action = ide_cyl_low;
154           goto idewrite8;
155         case GCYLHIGH_OFFSET:
156           ide_action = ide_cyl_hi;
157           goto idewrite8;
158         case GDEVHEAD_OFFSET:
159           //printf("Write to GDEVHEAD: %.2X.\n", value);
160           ide_action = ide_dev_head;
161           goto idewrite8;
162         case GCTRL_OFFSET:
163           //printf("Write to GCTRL: %.2X.\n", value);
164           ide_action = ide_devctrl_w;
165           goto idewrite8;
166         case GIRQ_4000_OFFSET:
167           gayle_a4k_irq = value;
168         /* Fallthrough */
169         case GIRQ_OFFSET:
170           gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
171           return;
172       }
173       goto skip_idewrite8;
174 idewrite8:;
175       ide_write8(ide0, ide_action, value);
176       return;
177 skip_idewrite8:;
178     }
179   }
180
181   switch (address) {
182     /*case 0xDD203A:
183       printf("Write bye to A4000 Gayle: %.2X\n", value);
184       gayle_a4k = value;
185       return;*/
186     case GIDENT:
187       //printf("Write to GIDENT: %d\n", value);
188       counter = 0;
189       return;
190     case GCONF:
191       //printf("Write to GCONF: %d\n", gayle_cfg);
192       gayle_cfg = value;
193       return;
194     case RAMSEY_REG:
195       ramsey_cfg = value & 0x0F;
196       return;
197     case GINT:
198       gayle_int = value;
199       return;
200     case GCS:
201       gayle_cs_mask = value & ~3;
202       gayle_cs &= ~3;
203       gayle_cs |= value & 3;
204       printf("Write to GCS: %d\n", gayle_cs);
205       //ide0->selected = gayle_cs;
206       return;
207   }
208
209   if ((address & GAYLEMASK) == CLOCKBASE) {
210     if ((address & CLOCKMASK) >= 0x8000) {
211       if (cdtv_mode) {
212         //printf("[CDTV] BYTE write to SRAM @%.8X (%.8X): %.2X\n", (address & CLOCKMASK) - 0x8000, address, value);
213         cdtv_sram[(address & CLOCKMASK) - 0x8000] = value;
214       }
215       return;
216     }
217     //printf("Byte write to RTC.\n");
218     put_rtc_byte(address, value, rtc_type);
219     return;
220   }
221
222   DEBUG("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value);
223 }
224
225 void writeGayle(unsigned int address, unsigned int value) {
226   if (ide0) {
227     if (address - gayle_ide_base == GDATA_OFFSET) {
228       ide_write16(ide0, ide_data, value);
229       return;
230     }
231
232     if (address == GIRQ_A4000) {
233       gayle_a4k_irq = value;
234       return;
235     }
236   }
237
238   if ((address & GAYLEMASK) == CLOCKBASE) {
239     if ((address & CLOCKMASK) >= 0x8000) {
240       if (cdtv_mode) {
241         //printf("[CDTV] WORD write to SRAM @%.8X (%.8X): %.4X\n", (address & CLOCKMASK) - 0x8000, address, htobe16(value));
242         ((short *) ((size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000)))[0] = htobe16(value);
243       }
244       return;
245     }
246     //printf("Word write to RTC.\n");
247     put_rtc_byte(address + 1, (value & 0xFF), rtc_type);
248     put_rtc_byte(address, (value >> 8), rtc_type);
249     return;
250   }
251
252   DEBUG("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value);
253 }
254
255 void writeGayleL(unsigned int address, unsigned int value) {
256   if ((address & GAYLEMASK) == CLOCKBASE) {
257     if ((address & CLOCKMASK) >= 0x8000) {
258       if (cdtv_mode) {
259         //printf("[CDTV] LONGWORD write to SRAM @%.8X (%.8X): %.8X\n", (address & CLOCKMASK) - 0x8000, address, htobe32(value));
260         ((int *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0] = htobe32(value);
261       }
262       return;
263     }
264     //printf("Longword write to RTC.\n");
265     put_rtc_byte(address + 3, (value & 0xFF), rtc_type);
266     put_rtc_byte(address + 2, ((value & 0x0000FF00) >> 8), rtc_type);
267     put_rtc_byte(address + 1, ((value & 0x00FF0000) >> 16), rtc_type);
268     put_rtc_byte(address, (value >> 24), rtc_type);
269     return;
270   }
271
272   DEBUG("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value);
273 }
274
275 uint8_t readGayleB(unsigned int address) {
276   if (ide0) {
277     uint8_t ide_action = 0, ide_val = 0;
278
279     if (address >= gayle_ide_base) {
280       switch ((address - gayle_ide_base) - gayle_ide_adj) {
281         case GERROR_OFFSET:
282           ide_action = ide_error_r;
283           goto ideread8;
284         case GSTATUS_OFFSET:
285           ide_action = ide_status_r;
286           goto ideread8;
287         case GSECTCOUNT_OFFSET:
288           ide_action = ide_sec_count;
289           goto ideread8;
290         case GSECTNUM_OFFSET:
291           ide_action = ide_sec_num;
292           goto ideread8;
293         case GCYLLOW_OFFSET:
294           ide_action = ide_cyl_low;
295           goto ideread8;
296         case GCYLHIGH_OFFSET:
297           ide_action = ide_cyl_hi;
298           goto ideread8;
299         case GDEVHEAD_OFFSET:
300           ide_action = ide_dev_head;
301           goto ideread8;
302         case GCTRL_OFFSET:
303           ide_action = ide_altst_r;
304           goto ideread8;
305         case GIRQ_4000_OFFSET:
306         case GIRQ_OFFSET:
307           return 0x80;
308           //gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
309       }
310       goto skip_ideread8;
311 ideread8:;
312       ide_val = ide_read8(ide0, ide_action);
313       return ide_val;
314 skip_ideread8:;
315     }
316
317     switch (address) {
318       case GIDENT: {
319         uint8_t val;
320         if (counter == 0 || counter == 1 || counter == 3) {
321           val = 0x80;  // 80; to enable gayle
322         } else {
323           val = 0x00;
324         }
325         counter++;
326         //printf("Read from GIDENT: %.2X.\n", val);
327         return val;
328       }
329       case GINT:
330         return gayle_int;
331       case GCONF:
332         //printf("Read from GCONF: %d\n", gayle_cfg & 0x0F);
333         return gayle_cfg & 0x0f;
334       case GCS: {
335         uint8_t v;
336         v = gayle_cs_mask | gayle_cs;
337         printf("Read from GCS: %d\n", v);
338         return v;
339       }
340       // This seems incorrect, GARY_REG3 is the same as GIDENT, and the A4000
341       // service manual says that Gary is accessible in the address range $DFC000 to $DFFFFF.
342       case GARY_REG0:
343       case GARY_REG1:
344       case GARY_REG2:
345         return gary_cfg[address - GARY_REG0];
346         break;
347       //case GARY_REG3:
348       case GARY_REG4:
349       //case GARY_REG5:
350         return gary_cfg[address - GARY_REG4];
351       case RAMSEY_ID:
352         return ramsey_id;
353       case RAMSEY_REG:
354         return ramsey_cfg;
355       case GARY_REG5: { // This makes no sense.
356         uint8_t val;
357         if (counter == 0 || counter == 1 || counter == 3) {
358           val = 0x80;  // 80; to enable GARY
359         } else {
360           val = 0x00;
361         }
362         counter++;
363         return val;
364       }
365       //case 0xDD203A:
366         // This can't be correct, as this is the same address as GDEVHEAD on the A4000 Gayle.
367         //printf("Read Byte from Gayle A4k: %.2X\n", gayle_a4k);
368         //return gayle_a4k;
369     }
370   }
371
372   if ((address & GAYLEMASK) == CLOCKBASE) {
373     if ((address & CLOCKMASK) >= 0x8000) {
374       if (cdtv_mode) {
375         //printf("[CDTV] BYTE read from SRAM @%.8X (%.8X): %.2X\n", (address & CLOCKMASK) - 0x8000, address, cdtv_sram[(address & CLOCKMASK) - 0x8000]);
376         return cdtv_sram[(address & CLOCKMASK) - 0x8000];
377       }
378       return 0;
379     }
380     //printf("Byte read from RTC.\n");
381     return get_rtc_byte(address, rtc_type);
382   }
383
384   DEBUG("Read Byte From Gayle Space 0x%06x\n", address);
385   return 0xFF;
386 }
387
388 uint16_t readGayle(unsigned int address) {
389   if (ide0) {
390     if (address - gayle_ide_base == GDATA_OFFSET) {
391       uint16_t value;
392       value = ide_read16(ide0, ide_data);
393       //        value = (value << 8) | (value >> 8);
394       return value;
395     }
396
397     if (address == GIRQ_A4000) {
398       gayle_a4k_irq = 0x8000;
399       return 0x8000;
400     }
401   }
402
403   if ((address & GAYLEMASK) == CLOCKBASE) {
404     if ((address & CLOCKMASK) >= 0x8000) {
405       if (cdtv_mode) {
406         //printf("[CDTV] WORD read from SRAM @%.8X (%.8X): %.4X\n", (address & CLOCKMASK) - 0x8000, address, be16toh( (( unsigned short *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]));
407         return be16toh( (( unsigned short *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]);
408       }
409       return 0;
410     }
411     //printf("Word read from RTC.\n");
412     return ((get_rtc_byte(address, rtc_type) << 8) | (get_rtc_byte(address + 1, rtc_type)));
413   }
414
415   DEBUG("Read Word From Gayle Space 0x%06x\n", address);
416   return 0x8000;
417 }
418
419 uint32_t readGayleL(unsigned int address) {
420   if ((address & GAYLEMASK) == CLOCKBASE) {
421     if ((address & CLOCKMASK) >= 0x8000) {
422       if (cdtv_mode) {
423         //printf("[CDTV] LONGWORD read from SRAM @%.8X (%.8X): %.8X\n", (address & CLOCKMASK) - 0x8000, address, be32toh( (( unsigned short *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]));
424         return be32toh( (( unsigned int *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]);
425       }
426       return 0;
427     }
428     //printf("Longword read from RTC.\n");
429     return ((get_rtc_byte(address, rtc_type) << 24) | (get_rtc_byte(address + 1, rtc_type) << 16) | (get_rtc_byte(address + 2, rtc_type) << 8) | (get_rtc_byte(address + 3, rtc_type)));
430   }
431
432   DEBUG("Read Long From Gayle Space 0x%06x\n", address);
433   return 0x8000;
434 }