]> git.sesse.net Git - pistorm/blob - platforms/amiga/piscsi/piscsi.c
[WIP] PiSCSI boot ROM disabled for now
[pistorm] / platforms / amiga / piscsi / piscsi.c
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <endian.h>
8 #include "piscsi.h"
9 #include "piscsi-enums.h"
10 #include "../../../config_file/config_file.h"
11 #include "../../../gpio/gpio.h"
12
13 struct piscsi_dev devs[8];
14 uint8_t piscsi_cur_drive = 0;
15 uint32_t piscsi_u32[4];
16 uint32_t piscsi_rom_size = 0;
17 uint8_t *piscsi_rom_ptr;
18
19 extern unsigned char ac_piscsi_rom[];
20
21 static const char *op_type_names[4] = {
22     "BYTE",
23     "WORD",
24     "LONGWORD",
25     "MEM",
26 };
27
28 void piscsi_init() {
29     for (int i = 0; i < 8; i++) {
30         devs[i].fd = -1;
31         devs[i].c = devs[i].h = devs[i].s = 0;
32     }
33
34     FILE *in = fopen("./platforms/amiga/piscsi/piscsi.rom", "rb");
35     if (in == NULL) {
36         printf("[PISCSI] Could not open PISCSI Boot ROM file for reading.\n");
37         ac_piscsi_rom[20] = 0;
38         ac_piscsi_rom[21] = 0;
39         ac_piscsi_rom[22] = 0;
40         ac_piscsi_rom[23] = 0;
41         return;
42     }
43     fseek(in, 0, SEEK_END);
44     piscsi_rom_size = ftell(in);
45     fseek(in, 0, SEEK_SET);
46     piscsi_rom_ptr = malloc(piscsi_rom_size);
47     fread(piscsi_rom_ptr, piscsi_rom_size, 1, in);
48     fclose(in);
49     printf("[PISCSI] Loaded Boot ROM.\n");
50 }
51
52 void piscsi_map_drive(char *filename, uint8_t index) {
53     if (index > 7) {
54         printf("[PISCSI] Drive index %d out of range.\nUnable to map file %s to drive.\n", index, filename);
55         return;
56     }
57
58     int32_t tmp_fd = open(filename, O_RDWR);
59     if (tmp_fd == -1) {
60         printf("[PISCSI] Failed to open file %s, could not map drive %d.\n", filename, index);
61         return;
62     }
63
64     struct piscsi_dev *d = &devs[index];
65
66     uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
67     lseek(tmp_fd, 0, SEEK_SET);
68     printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
69     d->h = 64;
70     d->s = 63;
71     d->c = (file_size / 512) / (d->s * d->h);
72     printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
73     d->fs = file_size;
74     d->fd = tmp_fd;
75 }
76
77 void piscsi_unmap_drive(uint8_t index) {
78     if (devs[index].fd != -1) {
79         printf("[PISCSI] Unmapped drive %d.\n", index);
80         close (devs[index].fd);
81         devs[index].fd = -1;
82     }
83 }
84
85 extern struct emulator_config *cfg;
86 extern void stop_cpu_emulation(uint8_t disasm_cur);
87
88 void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
89     int32_t r;
90
91     struct piscsi_dev *d = &devs[piscsi_cur_drive];
92
93     switch (addr & 0xFFFF) {
94         case PISCSI_CMD_READ:
95             if (d->fd == -1) {
96                 printf ("[PISCSI] BUG: Attempted read from unmapped drive %d.\n", piscsi_cur_drive);
97                 break;
98             }
99             printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
100             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
101             if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
102                 printf("[PISCSI] \"DMA\" Read goes to mapped range %d.\n", r);
103                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
104                 read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
105             }
106             else {
107                 printf("[PISCSI] No mapped range found for read.\n");
108                 uint8_t c = 0;
109                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
110                 for (int i = 0; i < piscsi_u32[1]; i++) {
111                     read(d->fd, &c, 1);
112 #ifndef FAKESTORM
113                     write8(piscsi_u32[2] + i, (uint32_t)c);
114 #endif
115                 }
116             }
117             break;
118         case PISCSI_CMD_WRITE:
119             if (d->fd == -1) {
120                 printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", piscsi_cur_drive);
121                 break;
122             }
123             printf("[PISCSI] %d byte WRITE to block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
124             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
125             if (r != -1) {
126                 printf("[PISCSI] \"DMA\" Write comes from mapped range %d.\n", r);
127                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
128                 write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
129             }
130             else {
131                 printf("[PISCSI] No mapped range found for write.\n");
132                 uint8_t c = 0;
133                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
134                 for (int i = 0; i < piscsi_u32[1]; i++) {
135 #ifndef FAKESTORM
136                     c = read8(piscsi_u32[2] + i);
137 #endif
138                     write(d->fd, &c, 1);
139                 }
140             }
141             break;
142         case PISCSI_CMD_ADDR1:
143             piscsi_u32[0] = val;
144             printf("[PISCSI] Write to ADDR1: %.8x\n", piscsi_u32[0]);
145             break;
146         case PISCSI_CMD_ADDR2:
147             piscsi_u32[1] = val;
148             printf("[PISCSI] Write to ADDR2: %.8x\n", piscsi_u32[1]);
149             break;
150         case PISCSI_CMD_ADDR3:
151             piscsi_u32[2] = val;
152             printf("[PISCSI] Write to ADDR3: %.8x\n", piscsi_u32[2]);
153             break;
154         case PISCSI_CMD_ADDR4:
155             piscsi_u32[3] = val;
156             printf("[PISCSI] Write to ADDR4: %.8x\n", piscsi_u32[3]);
157             break;
158         case PISCSI_CMD_DRVNUM:
159             if (val != 0) {
160                 if (val < 10) // Kludge for GiggleDisk
161                     piscsi_cur_drive = val;
162                 else if (val >= 10 && val % 10 != 0)
163                     piscsi_cur_drive = 255;
164                 else
165                     piscsi_cur_drive = val / 10;
166             }
167             else
168                 piscsi_cur_drive = val;
169             printf("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
170             break;
171         case PISCSI_CMD_DEBUGME:
172             printf("[PISCSI] DebugMe triggered.\n");
173             stop_cpu_emulation(1);
174             break;
175         case PISCSI_CMD_DRIVER: {
176             printf("[PISCSI] Driver copy/patch called, destination address %.8X.\n", val);
177             int r = get_mapped_item_by_address(cfg, val);
178             if (r != -1) {
179                 uint32_t addr = val - cfg->map_offset[r];
180                 uint32_t rt_offs = 0;
181                 uint8_t *dst_data = cfg->map_data[r];
182                 memcpy(dst_data + addr, piscsi_rom_ptr + 0x400, 0x3C00);
183                 
184                 uint32_t base_offs = be32toh(*((uint32_t *)&dst_data[addr + 0x170])) + 2;
185                 rt_offs = val + 0x16E;
186                 printf ("Offset 1: %.8X -> %.8X\n", base_offs, rt_offs);
187                 *((uint32_t *)&dst_data[addr + 0x170]) = htobe32(rt_offs);
188
189                 uint32_t offs = be32toh(*((uint32_t *)&dst_data[addr + 0x174]));
190                 printf ("Offset 2: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
191                 *((uint32_t *)&dst_data[addr + 0x174]) = htobe32((offs - base_offs) + rt_offs);
192
193                 dst_data[addr + 0x178] |= 0x07;
194
195                 offs = be32toh(*((uint32_t *)&dst_data[addr + 0x17C]));
196                 printf ("Offset 3: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
197                 *((uint32_t *)&dst_data[addr + 0x17C]) = htobe32((offs - base_offs) + rt_offs);
198
199                 offs = be32toh(*((uint32_t *)&dst_data[addr + 0x180]));
200                 printf ("Offset 4: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
201                 *((uint32_t *)&dst_data[addr + 0x180]) = htobe32((offs - base_offs) + rt_offs);
202
203                 offs = be32toh(*((uint32_t *)&dst_data[addr + 0x184]));
204                 printf ("Offset 5: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
205                 *((uint32_t *)&dst_data[addr + 0x184]) = htobe32((offs - base_offs) + rt_offs);
206
207             }
208             else {
209                 for (int i = 0; i < 0x3C00; i++) {
210                     uint8_t src = piscsi_rom_ptr[0x400 + i];
211                     write8(addr + i, src);
212                 }
213             }
214             break;
215         }
216         default:
217             printf("[PISCSI] Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
218             break;
219     }
220 }
221
222 uint8_t piscsi_diag_area[] = {
223     0x90,
224     0x00,
225     0x00, 0x40,
226     0x2C, 0x00,
227     0x2C, 0x00,
228     0x00, 0x00,
229     0x00, 0x00,
230     0x00, 0x00,
231 };
232
233 uint8_t fastata_diag_area[] = {
234     0x90,
235     0x00,
236     0x00, 0x10,
237     0x9e, 0x08,
238     0x00, 0x00,
239     0x00, 0x00,
240     0x00, 0x02,
241     0x00, 0x00,
242 };
243
244 uint8_t piscsi_diag_read;
245
246 #define PIB 0x00
247
248 uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
249     if (type) {}
250     uint8_t *diag_area = piscsi_diag_area;
251
252     if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
253         uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
254         /*if (romoffs < 14 && !piscsi_diag_read) {
255             printf("[PISCSI] %s read from DiagArea @$%.4X: ", op_type_names[type], romoffs);
256             uint32_t v = 0;
257             switch (type) {
258                 case OP_TYPE_BYTE:
259                     v = diag_area[romoffs];
260                     printf("%.2X\n", v);
261                     break;
262                 case OP_TYPE_WORD:
263                     v = *((uint16_t *)&diag_area[romoffs]);
264                     printf("%.4X\n", v);
265                     break;
266                 case OP_TYPE_LONGWORD:
267                     v = (*((uint16_t *)&diag_area[romoffs]) << 16) | *((uint16_t *)&diag_area[romoffs + 2]);
268                     //v = *((uint32_t *)&diag_area[romoffs]);
269                     printf("%.8X\n", v);
270                     break;
271             }
272             if (romoffs == 0x0D)
273                 piscsi_diag_read = 1;
274             return v;   
275         }*/
276         if (romoffs < (piscsi_rom_size + PIB)) {
277             printf("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
278             uint32_t v = 0;
279             switch (type) {
280                 case OP_TYPE_BYTE:
281                     v = piscsi_rom_ptr[romoffs - PIB];
282                     printf("%.2X\n", v);
283                     break;
284                 case OP_TYPE_WORD:
285                     v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
286                     printf("%.4X\n", v);
287                     break;
288                 case OP_TYPE_LONGWORD:
289                     //v = (*((uint16_t *)&piscsi_rom_ptr[romoffs - 14]) << 16) | *((uint16_t *)&piscsi_rom_ptr[romoffs - 12]);
290                     v = be32toh(*((uint32_t *)&piscsi_rom_ptr[romoffs - PIB]));
291                     printf("%.8X\n", v);
292                     break;
293             }
294             return v;
295         }
296         return 0;
297     }
298     
299     switch (addr & 0xFFFF) {
300         case PISCSI_CMD_DRVTYPE:
301             if (devs[piscsi_cur_drive].fd == -1) {
302                 printf("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
303                 return 0;
304             }
305             printf("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
306             return 1;
307             break;
308         case PISCSI_CMD_DRVNUM:
309             return piscsi_cur_drive;
310             break;
311         case PISCSI_CMD_CYLS:
312             printf("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
313             return devs[piscsi_cur_drive].c;
314             break;
315         case PISCSI_CMD_HEADS:
316             printf("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
317             return devs[piscsi_cur_drive].h;
318             break;
319         case PISCSI_CMD_SECS:
320             printf("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
321             return devs[piscsi_cur_drive].s;
322             break;
323         case PISCSI_CMD_BLOCKS: {
324             uint32_t blox = devs[piscsi_cur_drive].fs / 512;
325             printf("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
326             printf("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
327             return blox;
328             break;
329         }
330         default:
331             printf("[PISCSI] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
332             break;
333     }
334
335     return 0;
336 }
337
338 void piscsi_block_op(uint8_t type, uint8_t num, uint32_t dest, uint32_t len) {
339     if (type || num || dest || len) {}
340 }