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