]> git.sesse.net Git - pistorm/blob - platforms/amiga/Gayle.c
IDE updates, fix mouse hook hotkey
[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
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         printf("[HDD%d] HDD Image %s failed open\n", i, hdd_image_file[i]);
89       } else {
90         printf("[HDD%d] Attaching HDD image %s.\n", i, hdd_image_file[i]);
91         if (strcmp(hdd_image_file[i] + (strlen(hdd_image_file[i]) - 3), "img") != 0) {
92           printf("No header present on HDD image %s.\n", hdd_image_file[i]);
93           ide_attach_hdf(ide0, i, fd);
94         }
95         else {
96           printf("Attaching HDD image with header.\n");
97           ide_attach(ide0, i, fd);
98         }
99         printf("[HDD%d] HDD Image %s attached\n", i, hdd_image_file[i]);
100       }
101     }
102   }
103   ide_reset_begin(ide0);
104 }
105
106 uint8_t CheckIrq(void) {
107   uint8_t irq;
108
109   if (gayle_int & (1 << 7)) {
110     irq = ide0->drive[0].intrq || ide0->drive[1].intrq;
111     //  if (irq==0)
112     //  printf("IDE IRQ: %x\n",irq);
113     return irq;
114   };
115   return 0;
116 }
117
118 static uint8_t ide_action = 0;
119
120 void writeGayleB(unsigned int address, unsigned int value) {
121   if (address >= gayle_ide_base) {
122     switch ((address - gayle_ide_base) - gayle_ide_adj) {
123       case GFEAT_OFFSET:
124         printf("Write to GFEAT: %.2X.\n", value);
125         ide_action = ide_feature_w;
126         goto idewrite8;
127       case GCMD_OFFSET:
128         //printf("Write to GCMD: %.2X.\n", value);
129         ide_action = ide_command_w;
130         goto idewrite8;
131       case GSECTCOUNT_OFFSET:
132         ide_action = ide_sec_count;
133         goto idewrite8;
134       case GSECTNUM_OFFSET:
135         ide_action = ide_sec_num;
136         goto idewrite8;
137       case GCYLLOW_OFFSET:
138         ide_action = ide_cyl_low;
139         goto idewrite8;
140       case GCYLHIGH_OFFSET:
141         ide_action = ide_cyl_hi;
142         goto idewrite8;
143       case GDEVHEAD_OFFSET:
144         printf("Write to GDEVHEAD: %.2X.\n", value);
145         ide_action = ide_dev_head;
146         goto idewrite8;
147       case GCTRL_OFFSET:
148         printf("Write to GCTRL: %.2X.\n", value);
149         ide_action = ide_devctrl_w;
150         goto idewrite8;
151       case GIRQ_4000_OFFSET:
152         gayle_a4k_irq = value;
153       case GIRQ_OFFSET:
154         gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
155         return;
156     }
157     goto skip_idewrite8;
158 idewrite8:;
159     ide_write8(ide0, ide_action, value);
160     return;
161 skip_idewrite8:;
162   }
163
164   switch (address) {
165     /*case 0xDD203A:
166       printf("Write bye to A4000 Gayle: %.2X\n", value);
167       gayle_a4k = value;
168       return;*/
169     case GIDENT:
170       printf("Write to GIDENT: %d\n", value);
171       counter = 0;
172       return;
173     case GCONF:
174       printf("Write to GCONF: %d\n", gayle_cfg);
175       gayle_cfg = value;
176       return;
177     case RAMSEY_REG:
178       ramsey_cfg = value & 0x0F;
179       return;
180     case GINT:
181       gayle_int = value;
182       return;
183     case GCS:
184       gayle_cs_mask = value & ~3;
185       gayle_cs &= ~3;
186       gayle_cs |= value & 3;
187       printf("Write to GCS: %d\n", gayle_cs);
188       //ide0->selected = gayle_cs;
189       return;
190   }
191
192   if ((address & GAYLEMASK) == CLOCKBASE) {
193     if ((address & CLOCKMASK) >= 0x8000) {
194       if (cdtv_mode) {
195         //printf("[CDTV] BYTE write to SRAM @%.8X (%.8X): %.2X\n", (address & CLOCKMASK) - 0x8000, address, value);
196         cdtv_sram[(address & CLOCKMASK) - 0x8000] = value;
197       }
198       return;
199     }
200     //printf("Byte write to RTC.\n");
201     put_rtc_byte(address, value, rtc_type);
202     return;
203   }
204
205   printf("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value);
206 }
207
208 void writeGayle(unsigned int address, unsigned int value) {
209   if (address - gayle_ide_base == GDATA_OFFSET) {
210     ide_write16(ide0, ide_data, value);
211     return;
212   }
213
214   if (address == GIRQ_A4000) {
215     gayle_a4k_irq = value;
216     return;
217   }
218
219   if ((address & GAYLEMASK) == CLOCKBASE) {
220     if ((address & CLOCKMASK) >= 0x8000) {
221       if (cdtv_mode) {
222         //printf("[CDTV] WORD write to SRAM @%.8X (%.8X): %.4X\n", (address & CLOCKMASK) - 0x8000, address, htobe16(value));
223         ((short *) ((size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000)))[0] = htobe16(value);
224       }
225       return;
226     }
227     //printf("Word write to RTC.\n");
228     put_rtc_byte(address + 1, (value & 0xFF), rtc_type);
229     put_rtc_byte(address, (value >> 8), rtc_type);
230     return;
231   }
232
233   printf("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value);
234 }
235
236 void writeGayleL(unsigned int address, unsigned int value) {
237   if ((address & GAYLEMASK) == CLOCKBASE) {
238     if ((address & CLOCKMASK) >= 0x8000) {
239       if (cdtv_mode) {
240         //printf("[CDTV] LONGWORD write to SRAM @%.8X (%.8X): %.8X\n", (address & CLOCKMASK) - 0x8000, address, htobe32(value));
241         ((int *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0] = htobe32(value);
242       }
243       return;
244     }
245     //printf("Longword write to RTC.\n");
246     put_rtc_byte(address + 3, (value & 0xFF), rtc_type);
247     put_rtc_byte(address + 2, ((value & 0x0000FF00) >> 8), rtc_type);
248     put_rtc_byte(address + 1, ((value & 0x00FF0000) >> 16), rtc_type);
249     put_rtc_byte(address, (value >> 24), rtc_type);
250     return;
251   }
252
253   printf("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value);
254 }
255
256 uint8_t readGayleB(unsigned int address) {
257   uint8_t ide_action = 0, ide_val = 0;
258
259   if (address >= gayle_ide_base) {
260     switch ((address - gayle_ide_base) - gayle_ide_adj) {
261       case GERROR_OFFSET:
262         ide_action = ide_error_r;
263         goto ideread8;
264       case GSTATUS_OFFSET:
265         ide_action = ide_status_r;
266         goto ideread8;
267       case GSECTCOUNT_OFFSET:
268         ide_action = ide_sec_count;
269         goto ideread8;
270       case GSECTNUM_OFFSET:
271         ide_action = ide_sec_num;
272         goto ideread8;
273       case GCYLLOW_OFFSET:
274         ide_action = ide_cyl_low;
275         goto ideread8;
276       case GCYLHIGH_OFFSET:
277         ide_action = ide_cyl_hi;
278         goto ideread8;
279       case GDEVHEAD_OFFSET:
280         ide_action = ide_dev_head;
281         goto ideread8;
282       case GCTRL_OFFSET:
283         ide_action = ide_altst_r;
284         goto ideread8;
285       case GIRQ_4000_OFFSET:
286       case GIRQ_OFFSET:
287         return 0x80;
288         //gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
289     }
290     goto skip_ideread8;
291 ideread8:;
292     ide_val = ide_read8(ide0, ide_action);
293     if (((address - gayle_ide_base) - gayle_ide_adj) == GDEVHEAD_OFFSET)
294       printf("Read from GDEVHEAD: %.2X\n", ide_val);
295     return ide_read8(ide0, ide_action);
296 skip_ideread8:;
297   }
298
299   switch (address) {
300     case GIDENT: {
301       uint8_t val;
302       if (counter == 0 || counter == 1 || counter == 3) {
303         val = 0x80;  // 80; to enable gayle
304       } else {
305         val = 0x00;
306       }
307       counter++;
308       printf("Read from GIDENT: %.2X.\n", val);
309       return val;
310     }
311     case GINT:
312       return gayle_int;
313     case GCONF:
314       printf("Read from GCONF: %d\n", gayle_cfg & 0x0F);
315       return gayle_cfg & 0x0f;
316     case GCS: {
317       uint8_t v;
318       v = gayle_cs_mask | gayle_cs;
319       printf("Read from GCS: %d\n", v);
320       return v;
321     }
322     // This seems incorrect, GARY_REG3 is the same as GIDENT, and the A4000
323     // service manual says that Gary is accessible in the address range $DFC000 to $DFFFFF.
324     case GARY_REG0:
325     case GARY_REG1:
326     case GARY_REG2:
327       return gary_cfg[address - GARY_REG0];
328       break;
329     //case GARY_REG3:
330     case GARY_REG4:
331     //case GARY_REG5:
332       return gary_cfg[address - GARY_REG4];
333     case RAMSEY_ID:
334       return ramsey_id;
335     case RAMSEY_REG:
336       return ramsey_cfg;
337     case GARY_REG5: { // This makes no sense.
338       uint8_t val;
339       if (counter == 0 || counter == 1 || counter == 3) {
340         val = 0x80;  // 80; to enable GARY
341       } else {
342         val = 0x00;
343       }
344       counter++;
345       return val;
346     }
347     //case 0xDD203A:
348       // This can't be correct, as this is the same address as GDEVHEAD on the A4000 Gayle.
349       //printf("Read Byte from Gayle A4k: %.2X\n", gayle_a4k);
350       //return gayle_a4k;
351   }
352
353   if ((address & GAYLEMASK) == CLOCKBASE) {
354     if ((address & CLOCKMASK) >= 0x8000) {
355       if (cdtv_mode) {
356         //printf("[CDTV] BYTE read from SRAM @%.8X (%.8X): %.2X\n", (address & CLOCKMASK) - 0x8000, address, cdtv_sram[(address & CLOCKMASK) - 0x8000]);
357         return cdtv_sram[(address & CLOCKMASK) - 0x8000];
358       }
359       return 0;
360     }
361     //printf("Byte read from RTC.\n");
362     return get_rtc_byte(address, rtc_type);
363   }
364
365   printf("Read Byte From Gayle Space 0x%06x\n", address);
366   return 0xFF;
367 }
368
369 uint16_t readGayle(unsigned int address) {
370   if (address - gayle_ide_base == GDATA_OFFSET) {
371     uint16_t value;
372     value = ide_read16(ide0, ide_data);
373     //  value = (value << 8) | (value >> 8);
374     return value;
375   }
376
377   if (address == GIRQ_A4000) {
378     gayle_a4k_irq = 0x8000;
379     return 0x8000;
380   }
381
382   if ((address & GAYLEMASK) == CLOCKBASE) {
383     if ((address & CLOCKMASK) >= 0x8000) {
384       if (cdtv_mode) {
385         //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]));
386         return be16toh( (( unsigned short *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]);
387       }
388       return 0;
389     }
390     //printf("Word read from RTC.\n");
391     return ((get_rtc_byte(address, rtc_type) << 8) | (get_rtc_byte(address + 1, rtc_type)));
392   }
393
394   printf("Read Word From Gayle Space 0x%06x\n", address);
395   return 0x8000;
396 }
397
398 uint32_t readGayleL(unsigned int address) {
399   if ((address & GAYLEMASK) == CLOCKBASE) {
400     if ((address & CLOCKMASK) >= 0x8000) {
401       if (cdtv_mode) {
402         //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]));
403         return be32toh( (( unsigned int *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]);
404       }
405       return 0;
406     }
407     //printf("Longword read from RTC.\n");
408     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)));
409   }
410
411   printf("Read Long From Gayle Space 0x%06x\n", address);
412   return 0x8000;
413 }