5 // Created by Matt Parsons on 06/03/2019.
6 // Copyright © 2019 Matt Parsons. All rights reserved.
9 // Write Byte to Gayle Space 0xda9000 (0x0000c3)
10 // Read Byte From Gayle Space 0xda9000
11 // Read Byte From Gayle Space 0xdaa000
22 #include "platforms/shared/rtc.h"
23 #include "config_file/config_file.h"
25 #include "gayle-ide/ide.h"
26 #include "amiga-registers.h"
29 //#define DEBUG printf
33 uint8_t ramsey_cfg = 0x08;
34 static uint8_t ramsey_id = RAMSEY_REV7;
37 static uint8_t gayle_irq, gayle_cs, gayle_cs_mask, gayle_cfg;
38 static struct ide_controller *ide0 = NULL;
41 uint8_t rtc_type = RTC_TYPE_RICOH;
43 char *hdd_image_file[GAYLE_MAX_HARDFILES];
45 uint8_t cdtv_mode = 0;
46 unsigned char cdtv_sram[32 * SIZE_KILO];
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;
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;
59 struct ide_controller *get_ide(int index) {
64 void adjust_gayle_4000() {
65 gayle_ide_base = GAYLE_IDE_BASE_A4000;
70 void adjust_gayle_1200() {
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);
81 void InitGayle(void) {
82 uint8_t num_ide_drives = 0;
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);
89 ide0 = ide_allocate("cf");
93 printf("[HDD%d] HDD Image %s failed open\n", i, hdd_image_file[i]);
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);
102 printf("Attaching HDD image with header.\n");
103 ide_attach(ide0, i, fd);
106 printf("[HDD%d] HDD Image %s attached\n", i, hdd_image_file[i]);
111 ide_reset_begin(ide0);
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;
120 uint8_t CheckIrq(void) {
123 if (gayle_int & (1 << 7)) {
124 irq = ide0->drive[0].intrq || ide0->drive[1].intrq;
126 // printf("IDE IRQ: %x\n",irq);
132 static uint8_t ide_action = 0;
134 void writeGayleB(unsigned int address, unsigned int value) {
136 if (address >= gayle_ide_base) {
137 switch ((address - gayle_ide_base) - gayle_ide_adj) {
139 //printf("Write to GFEAT: %.2X.\n", value);
140 ide_action = ide_feature_w;
143 //printf("Write to GCMD: %.2X.\n", value);
144 ide_action = ide_command_w;
146 case GSECTCOUNT_OFFSET:
147 ide_action = ide_sec_count;
149 case GSECTNUM_OFFSET:
150 ide_action = ide_sec_num;
153 ide_action = ide_cyl_low;
155 case GCYLHIGH_OFFSET:
156 ide_action = ide_cyl_hi;
158 case GDEVHEAD_OFFSET:
159 //printf("Write to GDEVHEAD: %.2X.\n", value);
160 ide_action = ide_dev_head;
163 //printf("Write to GCTRL: %.2X.\n", value);
164 ide_action = ide_devctrl_w;
166 case GIRQ_4000_OFFSET:
167 gayle_a4k_irq = value;
169 gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
174 ide_write8(ide0, ide_action, value);
182 printf("Write bye to A4000 Gayle: %.2X\n", value);
186 //printf("Write to GIDENT: %d\n", value);
190 //printf("Write to GCONF: %d\n", gayle_cfg);
194 ramsey_cfg = value & 0x0F;
200 gayle_cs_mask = value & ~3;
202 gayle_cs |= value & 3;
203 printf("Write to GCS: %d\n", gayle_cs);
204 //ide0->selected = gayle_cs;
208 if ((address & GAYLEMASK) == CLOCKBASE) {
209 if ((address & CLOCKMASK) >= 0x8000) {
211 //printf("[CDTV] BYTE write to SRAM @%.8X (%.8X): %.2X\n", (address & CLOCKMASK) - 0x8000, address, value);
212 cdtv_sram[(address & CLOCKMASK) - 0x8000] = value;
216 //printf("Byte write to RTC.\n");
217 put_rtc_byte(address, value, rtc_type);
221 DEBUG("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value);
224 void writeGayle(unsigned int address, unsigned int value) {
226 if (address - gayle_ide_base == GDATA_OFFSET) {
227 ide_write16(ide0, ide_data, value);
231 if (address == GIRQ_A4000) {
232 gayle_a4k_irq = value;
237 if ((address & GAYLEMASK) == CLOCKBASE) {
238 if ((address & CLOCKMASK) >= 0x8000) {
240 //printf("[CDTV] WORD write to SRAM @%.8X (%.8X): %.4X\n", (address & CLOCKMASK) - 0x8000, address, htobe16(value));
241 ((short *) ((size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000)))[0] = htobe16(value);
245 //printf("Word write to RTC.\n");
246 put_rtc_byte(address + 1, (value & 0xFF), rtc_type);
247 put_rtc_byte(address, (value >> 8), rtc_type);
251 DEBUG("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value);
254 void writeGayleL(unsigned int address, unsigned int value) {
255 if ((address & GAYLEMASK) == CLOCKBASE) {
256 if ((address & CLOCKMASK) >= 0x8000) {
258 //printf("[CDTV] LONGWORD write to SRAM @%.8X (%.8X): %.8X\n", (address & CLOCKMASK) - 0x8000, address, htobe32(value));
259 ((int *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0] = htobe32(value);
263 //printf("Longword write to RTC.\n");
264 put_rtc_byte(address + 3, (value & 0xFF), rtc_type);
265 put_rtc_byte(address + 2, ((value & 0x0000FF00) >> 8), rtc_type);
266 put_rtc_byte(address + 1, ((value & 0x00FF0000) >> 16), rtc_type);
267 put_rtc_byte(address, (value >> 24), rtc_type);
271 DEBUG("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value);
274 uint8_t readGayleB(unsigned int address) {
276 uint8_t ide_action = 0, ide_val = 0;
278 if (address >= gayle_ide_base) {
279 switch ((address - gayle_ide_base) - gayle_ide_adj) {
281 ide_action = ide_error_r;
284 ide_action = ide_status_r;
286 case GSECTCOUNT_OFFSET:
287 ide_action = ide_sec_count;
289 case GSECTNUM_OFFSET:
290 ide_action = ide_sec_num;
293 ide_action = ide_cyl_low;
295 case GCYLHIGH_OFFSET:
296 ide_action = ide_cyl_hi;
298 case GDEVHEAD_OFFSET:
299 ide_action = ide_dev_head;
302 ide_action = ide_altst_r;
304 case GIRQ_4000_OFFSET:
307 //gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
311 ide_val = ide_read8(ide0, ide_action);
319 if (counter == 0 || counter == 1 || counter == 3) {
320 val = 0x80; // 80; to enable gayle
325 //printf("Read from GIDENT: %.2X.\n", val);
331 //printf("Read from GCONF: %d\n", gayle_cfg & 0x0F);
332 return gayle_cfg & 0x0f;
335 v = gayle_cs_mask | gayle_cs;
336 printf("Read from GCS: %d\n", v);
339 // This seems incorrect, GARY_REG3 is the same as GIDENT, and the A4000
340 // service manual says that Gary is accessible in the address range $DFC000 to $DFFFFF.
344 return gary_cfg[address - GARY_REG0];
349 return gary_cfg[address - GARY_REG4];
354 case GARY_REG5: { // This makes no sense.
356 if (counter == 0 || counter == 1 || counter == 3) {
357 val = 0x80; // 80; to enable GARY
365 // This can't be correct, as this is the same address as GDEVHEAD on the A4000 Gayle.
366 //printf("Read Byte from Gayle A4k: %.2X\n", gayle_a4k);
371 if ((address & GAYLEMASK) == CLOCKBASE) {
372 if ((address & CLOCKMASK) >= 0x8000) {
374 //printf("[CDTV] BYTE read from SRAM @%.8X (%.8X): %.2X\n", (address & CLOCKMASK) - 0x8000, address, cdtv_sram[(address & CLOCKMASK) - 0x8000]);
375 return cdtv_sram[(address & CLOCKMASK) - 0x8000];
379 //printf("Byte read from RTC.\n");
380 return get_rtc_byte(address, rtc_type);
383 DEBUG("Read Byte From Gayle Space 0x%06x\n", address);
387 uint16_t readGayle(unsigned int address) {
389 if (address - gayle_ide_base == GDATA_OFFSET) {
391 value = ide_read16(ide0, ide_data);
392 // value = (value << 8) | (value >> 8);
396 if (address == GIRQ_A4000) {
397 gayle_a4k_irq = 0x8000;
402 if ((address & GAYLEMASK) == CLOCKBASE) {
403 if ((address & CLOCKMASK) >= 0x8000) {
405 //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]));
406 return be16toh( (( unsigned short *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]);
410 //printf("Word read from RTC.\n");
411 return ((get_rtc_byte(address, rtc_type) << 8) | (get_rtc_byte(address + 1, rtc_type)));
414 DEBUG("Read Word From Gayle Space 0x%06x\n", address);
418 uint32_t readGayleL(unsigned int address) {
419 if ((address & GAYLEMASK) == CLOCKBASE) {
420 if ((address & CLOCKMASK) >= 0x8000) {
422 //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]));
423 return be32toh( (( unsigned int *) (size_t)(cdtv_sram + (address & CLOCKMASK) - 0x8000))[0]);
427 //printf("Longword read from RTC.\n");
428 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)));
431 DEBUG("Read Long From Gayle Space 0x%06x\n", address);