]> git.sesse.net Git - pistorm/blob - platforms/amiga/piscsi/piscsi.c
[WIP] PiSCSI boot ROM experiments
[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
87 void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
88     int32_t r;
89
90     struct piscsi_dev *d = &devs[piscsi_cur_drive];
91
92     switch (addr & 0xFFFF) {
93         case PISCSI_CMD_READ:
94             if (d->fd == -1) {
95                 printf ("[PISCSI] BUG: Attempted read from unmapped drive %d.\n", piscsi_cur_drive);
96                 break;
97             }
98             printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
99             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
100             if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
101                 printf("[PISCSI] \"DMA\" Read goes to mapped range %d.\n", r);
102                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
103                 read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
104             }
105             else {
106                 printf("[PISCSI] No mapped range found for read.\n");
107                 uint8_t c = 0;
108                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
109                 for (int i = 0; i < piscsi_u32[1]; i++) {
110                     read(d->fd, &c, 1);
111 #ifndef FAKESTORM
112                     write8(piscsi_u32[2] + i, (uint32_t)c);
113 #endif
114                 }
115             }
116             break;
117         case PISCSI_CMD_WRITE:
118             if (d->fd == -1) {
119                 printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", piscsi_cur_drive);
120                 break;
121             }
122             printf("[PISCSI] %d byte WRITE to block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
123             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
124             if (r != -1) {
125                 printf("[PISCSI] \"DMA\" Write comes from mapped range %d.\n", r);
126                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
127                 write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
128             }
129             else {
130                 printf("[PISCSI] No mapped range found for write.\n");
131                 uint8_t c = 0;
132                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
133                 for (int i = 0; i < piscsi_u32[1]; i++) {
134 #ifndef FAKESTORM
135                     c = read8(piscsi_u32[2] + i);
136 #endif
137                     write(d->fd, &c, 1);
138                 }
139             }
140             break;
141         case PISCSI_CMD_ADDR1:
142             piscsi_u32[0] = val;
143             printf("[PISCSI] Write to ADDR1: %.8x\n", piscsi_u32[0]);
144             break;
145         case PISCSI_CMD_ADDR2:
146             piscsi_u32[1] = val;
147             printf("[PISCSI] Write to ADDR2: %.8x\n", piscsi_u32[1]);
148             break;
149         case PISCSI_CMD_ADDR3:
150             piscsi_u32[2] = val;
151             printf("[PISCSI] Write to ADDR3: %.8x\n", piscsi_u32[2]);
152             break;
153         case PISCSI_CMD_ADDR4:
154             piscsi_u32[3] = val;
155             printf("[PISCSI] Write to ADDR4: %.8x\n", piscsi_u32[3]);
156             break;
157         case PISCSI_CMD_DRVNUM:
158             if (val != 0) {
159                 if (val < 10) // Kludge for GiggleDisk
160                     piscsi_cur_drive = val;
161                 else if (val >= 10 && val % 10 != 0)
162                     piscsi_cur_drive = 255;
163                 else
164                     piscsi_cur_drive = val / 10;
165             }
166             else
167                 piscsi_cur_drive = val;
168             printf("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
169             break;
170         default:
171             printf("[PISCSI] Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
172             break;
173     }
174 }
175
176 uint8_t piscsi_diag_area[] = {
177     0x90,
178     0x00,
179     0x00, 0x40,
180     0x2C, 0x00,
181     0x2C, 0x00,
182     0x00, 0x00,
183     0x00, 0x00,
184     0x00, 0x00,
185 };
186
187 uint8_t fastata_diag_area[] = {
188     0x90,
189     0x00,
190     0x00, 0x10,
191     0x9e, 0x08,
192     0x00, 0x00,
193     0x00, 0x00,
194     0x00, 0x02,
195     0x00, 0x00,
196 };
197
198 uint8_t piscsi_diag_read;
199
200 #define PIB 0x00
201
202 uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
203     if (type) {}
204     uint8_t *diag_area = piscsi_diag_area;
205
206     if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
207         uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
208         if (romoffs < 14 && !piscsi_diag_read) {
209             printf("[PISCSI] %s read from DiagArea @$%.4X: ", op_type_names[type], romoffs);
210             uint32_t v = 0;
211             switch (type) {
212                 case OP_TYPE_BYTE:
213                     v = diag_area[romoffs];
214                     printf("%.2X\n", v);
215                     break;
216                 case OP_TYPE_WORD:
217                     v = *((uint16_t *)&diag_area[romoffs]);
218                     printf("%.4X\n", v);
219                     break;
220                 case OP_TYPE_LONGWORD:
221                     v = (*((uint16_t *)&diag_area[romoffs]) << 16) | *((uint16_t *)&diag_area[romoffs + 2]);
222                     //v = *((uint32_t *)&diag_area[romoffs]);
223                     printf("%.8X\n", v);
224                     break;
225             }
226             if (romoffs == 0x0D)
227                 piscsi_diag_read = 1;
228             return v;   
229         }
230         if (romoffs < (piscsi_rom_size + PIB)) {
231             printf("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
232             uint32_t v = 0;
233             switch (type) {
234                 case OP_TYPE_BYTE:
235                     v = piscsi_rom_ptr[romoffs - PIB];
236                     printf("%.2X\n", v);
237                     break;
238                 case OP_TYPE_WORD:
239                     v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
240                     printf("%.4X\n", v);
241                     break;
242                 case OP_TYPE_LONGWORD:
243                     //v = (*((uint16_t *)&diag_area[romoffs - 14]) << 16) | *((uint16_t *)&diag_area[romoffs - 12]);
244                     v = be32toh(*((uint32_t *)&diag_area[romoffs - PIB]));
245                     printf("%.8X\n", v);
246                     break;
247             }
248             return v;
249         }
250         return 0;
251     }
252     
253     switch (addr & 0xFFFF) {
254         case PISCSI_CMD_DRVTYPE:
255             if (devs[piscsi_cur_drive].fd == -1) {
256                 printf("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
257                 return 0;
258             }
259             printf("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
260             return 1;
261             break;
262         case PISCSI_CMD_DRVNUM:
263             return piscsi_cur_drive;
264             break;
265         case PISCSI_CMD_CYLS:
266             printf("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
267             return devs[piscsi_cur_drive].c;
268             break;
269         case PISCSI_CMD_HEADS:
270             printf("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
271             return devs[piscsi_cur_drive].h;
272             break;
273         case PISCSI_CMD_SECS:
274             printf("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
275             return devs[piscsi_cur_drive].s;
276             break;
277         case PISCSI_CMD_BLOCKS: {
278             uint32_t blox = devs[piscsi_cur_drive].fs / 512;
279             printf("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
280             printf("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
281             return blox;
282             break;
283         }
284         default:
285             printf("[PISCSI] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
286             break;
287     }
288
289     return 0;
290 }
291
292 void piscsi_block_op(uint8_t type, uint8_t num, uint32_t dest, uint32_t len) {
293     if (type || num || dest || len) {}
294 }