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