]> git.sesse.net Git - pistorm/blob - platforms/amiga/piscsi/piscsi.c
07df2bef12cd29c3e1133d543d395385d3bbbfd4
[pistorm] / platforms / amiga / piscsi / piscsi.c
1 // SPDX-License-Identifier: MIT
2
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <endian.h>
10
11 #include "config_file/config_file.h"
12 #include "gpio/ps_protocol.h"
13 #include "piscsi-enums.h"
14 #include "piscsi.h"
15 #include "platforms/amiga/hunk-reloc.h"
16
17 #define BE(val) be32toh(val)
18 #define BE16(val) be16toh(val)
19
20 // Uncomment the line below to enable debug output
21 //#define PISCSI_DEBUG
22
23 #ifdef PISCSI_DEBUG
24 #define DEBUG printf
25 //#define DEBUG_TRIVIAL printf
26 #define DEBUG_TRVIAL(...)
27
28 extern void stop_cpu_emulation(uint8_t disasm_cur);
29
30 static const char *op_type_names[4] = {
31     "BYTE",
32     "WORD",
33     "LONGWORD",
34     "MEM",
35 };
36 #else
37 #define DEBUG(...)
38 #define DEBUG_TRIVIAL(...)
39 #define stop_cpu_emulation(...)
40 #endif
41
42 #ifdef FAKESTORM
43 #define lseek64 lseek
44 #endif
45
46 extern struct emulator_config *cfg;
47
48 struct piscsi_dev devs[8];
49 struct piscsi_fs filesystems[NUM_FILESYSTEMS];
50
51 uint8_t piscsi_num_fs = 0;
52
53 uint8_t piscsi_cur_drive = 0;
54 uint32_t piscsi_u32[4];
55 uint32_t piscsi_dbg[8];
56 uint32_t piscsi_rom_size = 0;
57 uint8_t *piscsi_rom_ptr;
58
59 uint32_t rom_partitions[128];
60 uint32_t rom_partition_prio[128];
61 uint32_t rom_partition_dostype[128];
62 uint32_t rom_cur_partition = 0, rom_cur_fs = 0;
63
64 extern unsigned char ac_piscsi_rom[];
65
66 //static const char *partition_marker = "PART";
67
68 struct hunk_info piscsi_hinfo;
69 struct hunk_reloc piscsi_hreloc[256];
70
71 void piscsi_init() {
72     for (int i = 0; i < 8; i++) {
73         devs[i].fd = -1;
74         devs[i].lba = 0;
75         devs[i].c = devs[i].h = devs[i].s = 0;
76     }
77
78     if (piscsi_rom_ptr == NULL) {
79         FILE *in = fopen("./platforms/amiga/piscsi/piscsi.rom", "rb");
80         if (in == NULL) {
81             printf("[PISCSI] Could not open PISCSI Boot ROM file for reading!\n");
82             // Zero out the boot ROM offset from the autoconfig ROM.
83             ac_piscsi_rom[20] = 0;
84             ac_piscsi_rom[21] = 0;
85             ac_piscsi_rom[22] = 0;
86             ac_piscsi_rom[23] = 0;
87             return;
88         }
89         fseek(in, 0, SEEK_END);
90         piscsi_rom_size = ftell(in);
91         fseek(in, 0, SEEK_SET);
92         piscsi_rom_ptr = malloc(piscsi_rom_size);
93         fread(piscsi_rom_ptr, piscsi_rom_size, 1, in);
94
95         fseek(in, PISCSI_DRIVER_OFFSET, SEEK_SET);
96         process_hunks(in, &piscsi_hinfo, piscsi_hreloc, PISCSI_DRIVER_OFFSET);
97
98         fclose(in);
99
100         printf("[PISCSI] Loaded Boot ROM.\n");
101     } else {
102         printf("[PISCSI] Boot ROM already loaded.\n");
103     }
104     fflush(stdout);
105 }
106
107 void piscsi_shutdown() {
108     printf("[PISCSI] Shutting down PiSCSI.\n");
109     for (int i = 0; i < 8; i++) {
110         if (devs[i].fd != -1) {
111             close(devs[i].fd);
112             devs[i].fd = -1;
113         }
114     }
115
116     for (int i = 0; i < NUM_FILESYSTEMS; i++) {
117         if (filesystems[i].binary_data) {
118             free(filesystems[i].binary_data);
119             filesystems[i].binary_data = NULL;
120         }
121         if (filesystems[i].fhb) {
122             free(filesystems[i].fhb);
123             filesystems[i].fhb = NULL;
124         }
125         filesystems[i].h_info.current_hunk = 0;
126         filesystems[i].h_info.reloc_hunks = 0;
127         filesystems[i].FS_ID = 0;
128         filesystems[i].handler = 0;
129     }
130 }
131
132 void piscsi_find_partitions(struct piscsi_dev *d) {
133     int fd = d->fd;
134     int cur_partition = 0;
135     uint8_t tmp;
136
137     for (int i = 0; i < 16; i++) {
138         if (d->pb[i]) {
139             free(d->pb[i]);
140             d->pb[i] = NULL;
141         }
142     }
143
144     if (!d->rdb || d->rdb->rdb_PartitionList == 0) {
145         DEBUG("[PISCSI] No partitions on disk.\n");
146         return;
147     }
148
149     char *block = malloc(512);
150
151     lseek(fd, BE(d->rdb->rdb_PartitionList) * 512, SEEK_SET);
152 next_partition:;
153     read(fd, block, 512);
154
155     uint32_t first = be32toh(*((uint32_t *)&block[0]));
156     if (first != PART_IDENTIFIER) {
157         DEBUG("Entry at block %d is not a valid partition. Aborting.\n", BE(d->rdb->rdb_PartitionList));
158         return;
159     }
160
161     struct PartitionBlock *pb = (struct PartitionBlock *)block;
162     tmp = pb->pb_DriveName[0];
163     pb->pb_DriveName[tmp + 1] = 0x00;
164     DEBUG("[PISCSI] Partition %d: %s\n", cur_partition, pb->pb_DriveName + 1);
165     DEBUG("Checksum: %.8X HostID: %d\n", BE(pb->pb_ChkSum), BE(pb->pb_HostID));
166     DEBUG("Flags: %d (%.8X) Devflags: %d (%.8X)\n", BE(pb->pb_Flags), BE(pb->pb_Flags), BE(pb->pb_DevFlags), BE(pb->pb_DevFlags));
167     d->pb[cur_partition] = pb;
168
169     if (d->pb[cur_partition]->pb_Next != 0xFFFFFFFF) {
170         uint64_t next = be32toh(pb->pb_Next);
171         block = malloc(512);
172         lseek64(fd, next * 512, SEEK_SET);
173         cur_partition++;
174         DEBUG("[PISCSI] Next partition at block %d.\n", be32toh(pb->pb_Next));
175         goto next_partition;
176     }
177     DEBUG("[PISCSI] No more partitions on disk.\n");
178     d->num_partitions = cur_partition + 1;
179     d->fshd_offs = lseek64(fd, 0, SEEK_CUR);
180
181     return;
182 }
183
184 int piscsi_parse_rdb(struct piscsi_dev *d) {
185     int fd = d->fd;
186     int i = 0;
187     uint8_t *block = malloc(512);
188
189     lseek(fd, 0, SEEK_SET);
190     for (i = 0; i < RDB_BLOCK_LIMIT; i++) {
191         read(fd, block, 512);
192         uint32_t first = be32toh(*((uint32_t *)&block[0]));
193         if (first == RDB_IDENTIFIER)
194             goto rdb_found;
195     }
196     goto no_rdb_found;
197 rdb_found:;
198     struct RigidDiskBlock *rdb = (struct RigidDiskBlock *)block;
199     DEBUG("[PISCSI] RDB found at block %d.\n", i);
200     d->c = be32toh(rdb->rdb_Cylinders);
201     d->h = be32toh(rdb->rdb_Heads);
202     d->s = be32toh(rdb->rdb_Sectors);
203     d->num_partitions = 0;
204     DEBUG("[PISCSI] RDB - first partition at block %d.\n", be32toh(rdb->rdb_PartitionList));
205     if (d->rdb)
206         free(d->rdb);
207     d->rdb = rdb;
208     sprintf(d->rdb->rdb_DriveInitName, "pi-scsi.device");
209     return 0;
210
211 no_rdb_found:;
212     if (block)
213         free(block);
214
215     return -1;
216 }
217
218 void piscsi_refresh_drives() {
219     piscsi_num_fs = 0;
220
221     for (int i = 0; i < NUM_FILESYSTEMS; i++) {
222         if (filesystems[i].binary_data) {
223             free(filesystems[i].binary_data);
224             filesystems[i].binary_data = NULL;
225         }
226         if (filesystems[i].fhb) {
227             free(filesystems[i].fhb);
228             filesystems[i].fhb = NULL;
229         }
230         filesystems[i].h_info.current_hunk = 0;
231         filesystems[i].h_info.reloc_hunks = 0;
232         filesystems[i].FS_ID = 0;
233         filesystems[i].handler = 0;
234     }
235
236     rom_cur_fs = 0;
237
238     for (int i = 0; i < NUM_UNITS; i++) {
239         if (devs[i].fd != -1) {
240             piscsi_parse_rdb(&devs[i]);
241             piscsi_find_partitions(&devs[i]);
242             piscsi_find_filesystems(&devs[i]);
243         }
244     }
245 }
246
247 void piscsi_find_filesystems(struct piscsi_dev *d) {
248     if (!d->num_partitions)
249         return;
250
251     uint8_t fs_found = 0;
252
253     uint8_t *fhb_block = malloc(512);
254
255     lseek64(d->fd, d->fshd_offs, SEEK_SET);
256
257     struct FileSysHeaderBlock *fhb = (struct FileSysHeaderBlock *)fhb_block;
258     read(d->fd, fhb_block, 512);
259
260     while (BE(fhb->fhb_ID) == FS_IDENTIFIER) {
261         char *dosID = (char *)&fhb->fhb_DosType;
262 #ifdef PISCSI_DEBUG
263         uint16_t *fsVer = (uint16_t *)&fhb->fhb_Version;
264
265         DEBUG("[FSHD] FSHD Block found.\n");
266         DEBUG("[FSHD] HostID: %d Next: %d Size: %d\n", BE(fhb->fhb_HostID), BE(fhb->fhb_Next), BE(fhb->fhb_SummedLongs));
267         DEBUG("[FSHD] Flags: %.8X DOSType: %c%c%c/%d\n", BE(fhb->fhb_Flags), dosID[0], dosID[1], dosID[2], dosID[3]);
268         DEBUG("[FSHD] Version: %d.%d\n", BE16(fsVer[0]), BE16(fsVer[1]));
269         DEBUG("[FSHD] Patchflags: %d Type: %d\n", BE(fhb->fhb_PatchFlags), BE(fhb->fhb_Type));
270         DEBUG("[FSHD] Task: %d Lock: %d\n", BE(fhb->fhb_Task), BE(fhb->fhb_Lock));
271         DEBUG("[FSHD] Handler: %d StackSize: %d\n", BE(fhb->fhb_Handler), BE(fhb->fhb_StackSize));
272         DEBUG("[FSHD] Prio: %d Startup: %d\n", BE(fhb->fhb_Priority), BE(fhb->fhb_Startup));
273         DEBUG("[FSHD] SegListBlocks: %d GlobalVec: %d\n", BE(fhb->fhb_Priority), BE(fhb->fhb_Startup));
274         DEBUG("[FSHD] FileSysName: %s\n", fhb->fhb_FileSysName + 1);
275 #endif
276
277         for (int i = 0; i < NUM_FILESYSTEMS; i++) {
278             if (filesystems[i].FS_ID == fhb->fhb_DosType) {
279                 DEBUG("[FSHD] File system %c%c%c/%d already loaded. Skipping.\n", dosID[0], dosID[1], dosID[2], dosID[3]);
280                 if (BE(fhb->fhb_Next) == 0xFFFFFFFF)
281                     goto fs_done;
282
283                 goto skip_fs_load_lseg;
284             }
285         }
286
287         if (load_lseg(d->fd, &filesystems[piscsi_num_fs].binary_data, &filesystems[piscsi_num_fs].h_info, filesystems[piscsi_num_fs].relocs) != -1) {
288             filesystems[piscsi_num_fs].FS_ID = fhb->fhb_DosType;
289             filesystems[piscsi_num_fs].fhb = fhb;
290             printf("[FSHD] Loaded and set up file system %d: %c%c%c/%d\n", piscsi_num_fs + 1, dosID[0], dosID[1], dosID[2], dosID[3]);
291             piscsi_num_fs++;
292         }
293
294 skip_fs_load_lseg:;
295         fs_found++;
296         lseek64(d->fd, BE(fhb->fhb_Next) * 512, SEEK_SET);
297         fhb_block = malloc(512);
298         fhb = (struct FileSysHeaderBlock *)fhb_block;
299         read(d->fd, fhb_block, 512);
300     }
301
302     if (!fs_found) {
303         DEBUG("[!!!FSHD] No file systems found on hard drive!\n");
304     }
305
306 fs_done:;
307     if (fhb_block)
308         free(fhb_block);
309 }
310
311 void piscsi_map_drive(char *filename, uint8_t index) {
312     if (index > 7) {
313         printf("[PISCSI] Drive index %d out of range.\nUnable to map file %s to drive.\n", index, filename);
314         return;
315     }
316
317     int32_t tmp_fd = open(filename, O_RDWR);
318     if (tmp_fd == -1) {
319         printf("[PISCSI] Failed to open file %s, could not map drive %d.\n", filename, index);
320         return;
321     }
322
323     struct piscsi_dev *d = &devs[index];
324
325     uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
326     d->fs = file_size;
327     d->fd = tmp_fd;
328     lseek(tmp_fd, 0, SEEK_SET);
329     printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
330
331     if (piscsi_parse_rdb(d) == -1) {
332         DEBUG("[PISCSI] No RDB found on disk, making up some CHS values.\n");
333         d->h = 16;
334         d->s = 63;
335         d->c = (file_size / 512) / (d->s * d->h);
336     }
337     printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
338
339     printf ("Finding partitions.\n");
340     piscsi_find_partitions(d);
341     printf ("Finding file systems.\n");
342     piscsi_find_filesystems(d);
343     printf ("Done.\n");
344 }
345
346 void piscsi_unmap_drive(uint8_t index) {
347     if (devs[index].fd != -1) {
348         DEBUG("[PISCSI] Unmapped drive %d.\n", index);
349         close (devs[index].fd);
350         devs[index].fd = -1;
351     }
352 }
353
354 char *io_cmd_name(int index) {
355     switch (index) {
356         case CMD_INVALID: return "INVALID";
357         case CMD_RESET: return "RESET";
358         case CMD_READ: return "READ";
359         case CMD_WRITE: return "WRITE";
360         case CMD_UPDATE: return "UPDATE";
361         case CMD_CLEAR: return "CLEAR";
362         case CMD_STOP: return "STOP";
363         case CMD_START: return "START";
364         case CMD_FLUSH: return "FLUSH";
365         case TD_MOTOR: return "TD_MOTOR";
366         case TD_SEEK: return "SEEK";
367         case TD_FORMAT: return "FORMAT";
368         case TD_REMOVE: return "REMOVE";
369         case TD_CHANGENUM: return "CHANGENUM";
370         case TD_CHANGESTATE: return "CHANGESTATE";
371         case TD_PROTSTATUS: return "PROTSTATUS";
372         case TD_RAWREAD: return "RAWREAD";
373         case TD_RAWWRITE: return "RAWWRITE";
374         case TD_GETDRIVETYPE: return "GETDRIVETYPE";
375         case TD_GETNUMTRACKS: return "GETNUMTRACKS";
376         case TD_ADDCHANGEINT: return "ADDCHANGEINT";
377         case TD_REMCHANGEINT: return "REMCHANGEINT";
378         case TD_GETGEOMETRY: return "GETGEOMETRY";
379         case TD_EJECT: return "EJECT";
380         case TD_LASTCOMM: return "LASTCOMM/READ64";
381         case TD_WRITE64: return "WRITE64";
382         case HD_SCSICMD: return "HD_SCSICMD";
383         case NSCMD_DEVICEQUERY: return "NSCMD_DEVICEQUERY";
384         case NSCMD_TD_READ64: return "NSCMD_TD_READ64";
385         case NSCMD_TD_WRITE64: return "NSCMD_TD_WRITE64";
386         case NSCMD_TD_FORMAT64: return "NSCMD_TD_FORMAT64";
387
388         default:
389             return "[!!!PISCSI] Unhandled IO command";
390     }
391 }
392
393 #define GETSCSINAME(a) case a: return ""#a"";
394 #define SCSIUNHANDLED(a) return "[!!!PISCSI] Unhandled SCSI command "#a"";
395
396 char *scsi_cmd_name(int index) {
397     switch(index) {
398         GETSCSINAME(SCSICMD_TEST_UNIT_READY);
399         GETSCSINAME(SCSICMD_INQUIRY);
400         GETSCSINAME(SCSICMD_READ_6);
401         GETSCSINAME(SCSICMD_WRITE_6);
402         GETSCSINAME(SCSICMD_READ_10);
403         GETSCSINAME(SCSICMD_WRITE_10);
404         GETSCSINAME(SCSICMD_READ_CAPACITY_10);
405         GETSCSINAME(SCSICMD_MODE_SENSE_6);
406         GETSCSINAME(SCSICMD_READ_DEFECT_DATA_10);
407         default:
408             return "[!!!PISCSI] Unhandled SCSI command";
409     }
410 }
411
412 void print_piscsi_debug_message(int index) {
413     int32_t r = 0;
414
415     switch (index) {
416         case DBG_INIT:
417             DEBUG("[PISCSI] Initializing devices.\n");
418             break;
419         case DBG_OPENDEV:
420             if (piscsi_dbg[0] != 255) {
421                 DEBUG("[PISCSI] Opening device %d (%d). Flags: %d (%.2X)\n", piscsi_dbg[0], piscsi_dbg[2], piscsi_dbg[1], piscsi_dbg[1]);
422             }
423             break;
424         case DBG_CLEANUP:
425             DEBUG("[PISCSI] Cleaning up.\n");
426             break;
427         case DBG_CHS:
428             DEBUG("[PISCSI] C/H/S: %d / %d / %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
429             break;
430         case DBG_BEGINIO:
431             DEBUG("[PISCSI] BeginIO: io_Command: %d (%s) - io_Flags = %d - quick: %d\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]), piscsi_dbg[1], piscsi_dbg[2]);
432             break;
433         case DBG_ABORTIO:
434             DEBUG("[PISCSI] AbortIO!\n");
435             break;
436         case DBG_SCSICMD:
437             DEBUG("[PISCSI] SCSI Command %d (%s)\n", piscsi_dbg[1], scsi_cmd_name(piscsi_dbg[1]));
438             DEBUG("Len: %d - %.2X %.2X %.2X - Command Length: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[3], piscsi_dbg[4]);
439             break;
440         case DBG_SCSI_UNKNOWN_MODESENSE:
441             DEBUG("[!!!PISCSI] SCSI: Unknown modesense %.4X\n", piscsi_dbg[0]);
442             break;
443         case DBG_SCSI_UNKNOWN_COMMAND:
444             DEBUG("[!!!PISCSI] SCSI: Unknown command %.4X\n", piscsi_dbg[0]);
445             break;
446         case DBG_SCSIERR:
447             DEBUG("[!!!PISCSI] SCSI: An error occured: %.4X\n", piscsi_dbg[0]);
448             break;
449         case DBG_IOCMD:
450             DEBUG_TRIVIAL("[PISCSI] IO Command %d (%s)\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
451             break;
452         case DBG_IOCMD_UNHANDLED:
453             DEBUG("[!!!PISCSI] WARN: IO command %.4X (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
454             break;
455         case DBG_SCSI_FORMATDEVICE:
456             DEBUG("[PISCSI] Get SCSI FormatDevice MODE SENSE.\n");
457             break;
458         case DBG_SCSI_RDG:
459             DEBUG("[PISCSI] Get SCSI RDG MODE SENSE.\n");
460             break;
461         case DBG_SCSICMD_RW10:
462 #ifdef PISCSI_DEBUG
463             r = get_mapped_item_by_address(cfg, piscsi_dbg[0]);
464             struct SCSICmd_RW10 *rwdat = NULL;
465             char data[10];
466             if (r != -1) {
467                 uint32_t addr = piscsi_dbg[0] - cfg->map_offset[r];
468                 rwdat = (struct SCSICmd_RW10 *)(&cfg->map_data[r][addr]);
469             }
470             else {
471                 DEBUG_TRIVIAL("[RW10] scsiData: %.8X\n", piscsi_dbg[0]);
472                 for (int i = 0; i < 10; i++) {
473                     data[i] = read8(piscsi_dbg[0] + i);
474                 }
475                 rwdat = data;
476             }
477             if (rwdat) {
478                 DEBUG_TRIVIAL("[RW10] CMD: %.2X\n", rwdat->opcode);
479                 DEBUG_TRIVIAL("[RW10] RDP: %.2X\n", rwdat->rdprotect_flags);
480                 DEBUG_TRIVIAL("[RW10] Block: %d (%d)\n", rwdat->block, BE(rwdat->block));
481                 DEBUG_TRIVIAL("[RW10] Res_Group: %.2X\n", rwdat->res_groupnum);
482                 DEBUG_TRIVIAL("[RW10] Len: %d (%d)\n", rwdat->len, BE16(rwdat->len));
483             }
484 #endif
485             break;
486         case DBG_SCSI_DEBUG_MODESENSE_6:
487             DEBUG_TRIVIAL("[PISCSI] SCSI ModeSense debug. Data: %.8X\n", piscsi_dbg[0]);
488             r = get_mapped_item_by_address(cfg, piscsi_dbg[0]);
489             if (r != -1) {
490 #ifdef PISCSI_DEBUG
491                 uint32_t addr = piscsi_dbg[0] - cfg->map_offset[r];
492                 struct SCSICmd_ModeSense6 *sense = (struct SCSICmd_ModeSense6 *)(&cfg->map_data[r][addr]);
493                 DEBUG_TRIVIAL("[SenseData] CMD: %.2X\n", sense->opcode);
494                 DEBUG_TRIVIAL("[SenseData] DBD: %d\n", sense->reserved_dbd & 0x04);
495                 DEBUG_TRIVIAL("[SenseData] PC: %d\n", (sense->pc_pagecode & 0xC0 >> 6));
496                 DEBUG_TRIVIAL("[SenseData] PageCodes: %.2X %.2X\n", (sense->pc_pagecode & 0x3F), sense->subpage_code);
497                 DEBUG_TRIVIAL("[SenseData] AllocLen: %d\n", sense->alloc_len);
498                 DEBUG_TRIVIAL("[SenseData] Control: %.2X (%d)\n", sense->control, sense->control);
499 #endif
500             }
501             else {
502                 DEBUG("[!!!PISCSI] ModeSense data not immediately available.\n");
503             }
504             break;
505         default:
506             DEBUG("[!!!PISCSI] No debug message available for index %d.\n", index);
507             break;
508     }
509 }
510
511 #define DEBUGME_SIMPLE(i, s) case i: DEBUG(s); break;
512
513 void piscsi_debugme(uint32_t index) {
514     switch (index) {
515         DEBUGME_SIMPLE(1, "[PISCSI-DEBUGME] Arrived at DiagEntry.\n");
516         DEBUGME_SIMPLE(3, "[PISCSI-DEBUGME] Init: Interrupt disable.\n");
517         DEBUGME_SIMPLE(4, "[PISCSI-DEBUGME] Init: Copy/reloc driver.\n");
518         DEBUGME_SIMPLE(5, "[PISCSI-DEBUGME] Init: InitResident.\n");
519         DEBUGME_SIMPLE(7, "[PISCSI-DEBUGME] Init: Begin partition loop.\n");
520         DEBUGME_SIMPLE(8, "[PISCSI-DEBUGME] Init: Partition loop done. Cleaning up and returning to Exec.\n");
521         DEBUGME_SIMPLE(9, "[PISCSI-DEBUGME] Init: Load file systems.\n");
522         DEBUGME_SIMPLE(10, "[PISCSI-DEBUGME] Init: AllocMem for resident.\n");
523         DEBUGME_SIMPLE(11, "[PISCSI-DEBUGME] Init: Checking if resident is loaded.\n");
524         DEBUGME_SIMPLE(22, "[PISCSI-DEBUGME] Arrived at BootEntry.\n");
525         DEBUGME_SIMPLE(30, "[PISCSI-DEBUGME] LoadFileSystems: Opening FileSystem.resource.\n");
526         DEBUGME_SIMPLE(33, "[PISCSI-DEBUGME] FileSystem.resource not available, creating.\n");
527         case 31:
528             DEBUG("[PISCSI-DEBUGME] OpenResource result: %d\n", piscsi_u32[0]);
529             break;
530         case 32:
531             DEBUG("AAAAHH!\n");
532             break;
533         default:
534             DEBUG("[!!!PISCSI-DEBUGME] No debugme message for index %d!\n", index);
535             break;
536     }
537
538     if (index == 8) {
539         stop_cpu_emulation(1);
540     }
541 }
542
543 void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
544     int32_t r;
545 #ifndef PISCSI_DEBUG
546     if (type) {}
547 #endif
548
549     struct piscsi_dev *d = &devs[piscsi_cur_drive];
550
551     uint16_t cmd = (addr & 0xFFFF);
552
553     switch (cmd) {
554         case PISCSI_CMD_READ64:
555         case PISCSI_CMD_READ:
556             d = &devs[val];
557             if (d->fd == -1) {
558                 DEBUG("[!!!PISCSI] BUG: Attempted read from unmapped drive %d.\n", val);
559                 break;
560             }
561
562             if (cmd == PISCSI_CMD_READ) {
563                 DEBUG("[PISCSI-%d] %d byte READ from block %d to address %.8X\n", val, piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
564                 d->lba = piscsi_u32[0];
565                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
566             }
567             else {
568                 uint64_t src = piscsi_u32[3];
569                 src = (src << 32) | piscsi_u32[0];
570                 DEBUG("[PISCSI-%d] %d byte READ64 from block %lld to address %.8X\n", val, piscsi_u32[1], (src / 512), piscsi_u32[2]);
571                 d->lba = (src / 512);
572                 lseek64(d->fd, src, SEEK_SET);
573             }
574
575             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
576             if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
577                 DEBUG_TRIVIAL("[PISCSI-%d] \"DMA\" Read goes to mapped range %d.\n", val, r);
578                 read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
579             }
580             else {
581                 DEBUG_TRIVIAL("[PISCSI-%d] No mapped range found for read.\n", val);
582                 uint8_t c = 0;
583                 for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
584                     read(d->fd, &c, 1);
585                     write8(piscsi_u32[2] + i, (uint32_t)c);
586                 }
587             }
588             break;
589         case PISCSI_CMD_WRITE64:
590         case PISCSI_CMD_WRITE:
591             d = &devs[val];
592             if (d->fd == -1) {
593                 DEBUG ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", val);
594                 break;
595             }
596
597             if (cmd == PISCSI_CMD_WRITE) {
598                 DEBUG("[PISCSI-%d] %d byte WRITE to block %d from address %.8X\n", val, piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
599                 d->lba = piscsi_u32[0];
600                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
601             }
602             else {
603                 uint64_t src = piscsi_u32[3];
604                 src = (src << 32) | piscsi_u32[0];
605                 DEBUG("[PISCSI-%d] %d byte WRITE64 to block %lld from address %.8X\n", val, piscsi_u32[1], (src / 512), piscsi_u32[2]);
606                 d->lba = (src / 512);
607                 lseek64(d->fd, src, SEEK_SET);
608             }
609
610             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
611             if (r != -1) {
612                 DEBUG_TRIVIAL("[PISCSI-%d] \"DMA\" Write comes from mapped range %d.\n", val, r);
613                 write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
614             }
615             else {
616                 DEBUG_TRIVIAL("[PISCSI-%d] No mapped range found for write.\n", val);
617                 uint8_t c = 0;
618                 for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
619                     c = read8(piscsi_u32[2] + i);
620                     write(d->fd, &c, 1);
621                 }
622             }
623             break;
624         case PISCSI_CMD_ADDR1: case PISCSI_CMD_ADDR2: case PISCSI_CMD_ADDR3: case PISCSI_CMD_ADDR4: {
625             int i = ((addr & 0xFFFF) - PISCSI_CMD_ADDR1) / 4;
626             piscsi_u32[i] = val;
627             break;
628         }
629         case PISCSI_CMD_DRVNUM:
630             //printf("%d ", val);
631             if (val % 10 != 0)
632                 piscsi_cur_drive = 255;
633             else
634                 piscsi_cur_drive = val / 10;
635             if (piscsi_cur_drive > NUM_UNITS)
636                 piscsi_cur_drive = 255;
637
638             if (piscsi_cur_drive != 255) {
639                 DEBUG("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
640             }
641             break;
642         case PISCSI_CMD_DEBUGME:
643             piscsi_debugme(val);
644             break;
645         case PISCSI_CMD_DRIVER: {
646             DEBUG("[PISCSI] Driver copy/patch called, destination address %.8X.\n", val);
647             int r = get_mapped_item_by_address(cfg, val);
648             if (r != -1) {
649                 uint32_t addr = val - cfg->map_offset[r];
650                 uint8_t *dst_data = cfg->map_data[r];
651                 uint8_t cur_partition = 0;
652                 memcpy(dst_data + addr, piscsi_rom_ptr + PISCSI_DRIVER_OFFSET, 0x4000 - PISCSI_DRIVER_OFFSET);
653
654                 piscsi_hinfo.base_offset = val;
655
656                 reloc_hunks(piscsi_hreloc, dst_data + addr, &piscsi_hinfo);
657
658                 #define PUTNODELONG(val) *(uint32_t *)&dst_data[p_offs] = htobe32(val); p_offs += 4;
659                 #define PUTNODELONGBE(val) *(uint32_t *)&dst_data[p_offs] = val; p_offs += 4;
660
661                 for (int i = 0; i < 128; i++) {
662                     rom_partitions[i] = 0;
663                     rom_partition_prio[i] = 0;
664                     rom_partition_dostype[i] = 0;
665                 }
666                 rom_cur_partition = 0;
667
668                 uint32_t data_addr = addr + 0x3F00;
669                 sprintf((char *)dst_data + data_addr, "pi-scsi.device");
670                 uint32_t addr2 = addr + 0x4000;
671                 for (int i = 0; i < NUM_UNITS; i++) {
672                     if (devs[i].fd != -1)
673                         piscsi_find_partitions(&devs[i]);
674                     else
675                         goto skip_disk;
676
677                     if (devs[i].num_partitions) {
678                         uint32_t p_offs = addr2;
679                         DEBUG("[PISCSI] Adding %d partitions for unit %d\n", devs[i].num_partitions, i);
680                         for (uint32_t j = 0; j < devs[i].num_partitions; j++) {
681                             DEBUG("Partition %d: %s\n", j, devs[i].pb[j]->pb_DriveName + 1);
682                             sprintf((char *)dst_data + p_offs, "%s", devs[i].pb[j]->pb_DriveName + 1);
683                             p_offs += 0x20;
684                             PUTNODELONG(addr2 + cfg->map_offset[r]);
685                             PUTNODELONG(data_addr + cfg->map_offset[r]);
686                             PUTNODELONG((i * 10));
687                             PUTNODELONG(0);
688                             uint32_t nodesize = (be32toh(devs[i].pb[j]->pb_Environment[0]) + 1) * 4;
689                             memcpy(dst_data + p_offs, devs[i].pb[j]->pb_Environment, nodesize);
690
691                             struct pihd_dosnode_data *dat = (struct pihd_dosnode_data *)(&dst_data[addr2+0x20]);
692
693                             if (BE(devs[i].pb[j]->pb_Flags) & 0x01) {
694                                 DEBUG("Partition is bootable.\n");
695                                 rom_partition_prio[cur_partition] = 0;
696                                 dat->priority = 0;
697                             }
698                             else {
699                                 DEBUG("Partition is not bootable.\n");
700                                 rom_partition_prio[cur_partition] = -128;
701                                 dat->priority = htobe32(-128);
702                             }
703
704                             DEBUG("DOSNode Data:\n");
705                             DEBUG("Name: %s Device: %s\n", dst_data + addr2, dst_data + data_addr);
706                             DEBUG("Unit: %d Flags: %d Pad1: %d\n", BE(dat->unit), BE(dat->flags), BE(dat->pad1));
707                             DEBUG("Node len: %d Block len: %d\n", BE(dat->node_len) * 4, BE(dat->block_len) * 4);
708                             DEBUG("H: %d SPB: %d BPS: %d\n", BE(dat->surf), BE(dat->secs_per_block), BE(dat->blocks_per_track));
709                             DEBUG("Reserved: %d Prealloc: %d\n", BE(dat->reserved_blocks), BE(dat->pad2));
710                             DEBUG("Interleaved: %d Buffers: %d Memtype: %d\n", BE(dat->interleave), BE(dat->buffers), BE(dat->mem_type));
711                             DEBUG("Lowcyl: %d Highcyl: %d Prio: %d\n", BE(dat->lowcyl), BE(dat->highcyl), BE(dat->priority));
712                             DEBUG("Maxtransfer: %.8X Mask: %.8X\n", BE(dat->maxtransfer), BE(dat->transfer_mask));
713                             DEBUG("DOSType: %.8X\n", BE(dat->dostype));
714
715                             rom_partitions[cur_partition] = addr2 + 0x20 + cfg->map_offset[r];
716                             rom_partition_dostype[cur_partition] = dat->dostype;
717                             cur_partition++;
718                             addr2 += 0x100;
719                             p_offs = addr2;
720                         }
721                     }
722 skip_disk:;
723                 }
724             }
725
726             break;
727         }
728         case PISCSI_CMD_NEXTPART:
729             DEBUG("[PISCSI] Switch partition %d -> %d\n", rom_cur_partition, rom_cur_partition + 1);
730             rom_cur_partition++;
731             break;
732         case PISCSI_CMD_NEXTFS:
733             DEBUG("[PISCSI] Switch file file system %d -> %d\n", rom_cur_fs, rom_cur_fs + 1);
734             rom_cur_fs++;
735             break;
736         case PISCSI_CMD_COPYFS:
737             DEBUG("[PISCSI] Copy file system %d to %.8X and reloc.\n", rom_cur_fs, piscsi_u32[2]);
738             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
739             if (r != -1) {
740                 uint32_t addr = piscsi_u32[2] - cfg->map_offset[r];
741                 memset(cfg->map_data[r] + addr, 0x00, filesystems[rom_cur_fs].h_info.alloc_size);
742                 memcpy(cfg->map_data[r] + addr, filesystems[rom_cur_fs].binary_data, filesystems[rom_cur_fs].h_info.byte_size);
743                 filesystems[rom_cur_fs].h_info.base_offset = piscsi_u32[2];
744                 reloc_hunks(filesystems[rom_cur_fs].relocs, cfg->map_data[r] + addr, &filesystems[rom_cur_fs].h_info);
745                 filesystems[rom_cur_fs].handler = piscsi_u32[2];
746             }
747             break;
748         case PISCSI_CMD_SETFSH: {
749             int i = 0;
750             DEBUG("[PISCSI] Set handler for partition %d (DeviceNode: %.8X)\n", rom_cur_partition, val);
751             r = get_mapped_item_by_address(cfg, val);
752             if (r != -1) {
753                 uint32_t addr = val - cfg->map_offset[r];
754                 struct DeviceNode *node = (struct DeviceNode *)(cfg->map_data[r] + addr);
755 #ifdef PISCSI_DEBUG
756                 char *dosID = (char *)&rom_partition_dostype[rom_cur_partition];
757 #endif
758                 DEBUG("[PISCSI] Partition DOSType is %c%c%c/%d\n", dosID[0], dosID[1], dosID[2], dosID[3]);
759                 for (i = 0; i < piscsi_num_fs; i++) {
760                     if (rom_partition_dostype[rom_cur_partition] == filesystems[i].FS_ID) {
761                         node->dn_SegList = htobe32((filesystems[i].handler >> 2));
762                         node->dn_GlobalVec = 0xFFFFFFFF;
763                         goto fs_found;
764                     }
765                 }
766                 DEBUG("[!!!PISCSI] Found no handler for file system!\n");
767 fs_found:;
768                 DEBUG("[FS-HANDLER] Next: %d Type: %.8X\n", BE(node->dn_Next), BE(node->dn_Type));
769                 DEBUG("[FS-HANDLER] Task: %d Lock: %d\n", BE(node->dn_Task), BE(node->dn_Lock));
770                 DEBUG("[FS-HANDLER] Handler: %d Stacksize: %d\n", BE((uint32_t)node->dn_Handler), BE(node->dn_StackSize));
771                 DEBUG("[FS-HANDLER] Priority: %d Startup: %d\n", BE((uint32_t)node->dn_Priority), BE(node->dn_Startup));
772                 DEBUG("[FS-HANDLER] SegList: %.8X GlobalVec: %d\n", BE((uint32_t)node->dn_SegList), BE(node->dn_GlobalVec));
773                 DEBUG("[PISCSI] Handler for partition %.8X set to %.8X (%.8X).\n", BE((uint32_t)node->dn_Name), filesystems[i].FS_ID, filesystems[i].handler);
774             }
775             break;
776         }
777         case PISCSI_DBG_VAL1: case PISCSI_DBG_VAL2: case PISCSI_DBG_VAL3: case PISCSI_DBG_VAL4:
778         case PISCSI_DBG_VAL5: case PISCSI_DBG_VAL6: case PISCSI_DBG_VAL7: case PISCSI_DBG_VAL8: {
779             int i = ((addr & 0xFFFF) - PISCSI_DBG_VAL1) / 4;
780             piscsi_dbg[i] = val;
781             break;
782         }
783         case PISCSI_DBG_MSG:
784             print_piscsi_debug_message(val);
785             break;
786         default:
787             DEBUG("[!!!PISCSI] WARN: Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
788             break;
789     }
790 }
791
792 #define PIB 0x00
793
794 uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
795     if (type) {}
796
797     if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
798         uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
799         if (romoffs < (piscsi_rom_size + PIB)) {
800             //DEBUG("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
801             uint32_t v = 0;
802             switch (type) {
803                 case OP_TYPE_BYTE:
804                     v = piscsi_rom_ptr[romoffs - PIB];
805                     //DEBUG("%.2X\n", v);
806                     break;
807                 case OP_TYPE_WORD:
808                     v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
809                     //DEBUG("%.4X\n", v);
810                     break;
811                 case OP_TYPE_LONGWORD:
812                     v = be32toh(*((uint32_t *)&piscsi_rom_ptr[romoffs - PIB]));
813                     //DEBUG("%.8X\n", v);
814                     break;
815             }
816             return v;
817         }
818         return 0;
819     }
820
821     switch (addr & 0xFFFF) {
822         case PISCSI_CMD_ADDR1: case PISCSI_CMD_ADDR2: case PISCSI_CMD_ADDR3: case PISCSI_CMD_ADDR4: {
823             int i = ((addr & 0xFFFF) - PISCSI_CMD_ADDR1) / 4;
824             return piscsi_u32[i];
825             break;
826         }
827         case PISCSI_CMD_DRVTYPE:
828             if (devs[piscsi_cur_drive].fd == -1) {
829                 DEBUG("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
830                 return 0;
831             }
832             DEBUG("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
833             return 1;
834             break;
835         case PISCSI_CMD_DRVNUM:
836             return piscsi_cur_drive;
837             break;
838         case PISCSI_CMD_CYLS:
839             DEBUG("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
840             return devs[piscsi_cur_drive].c;
841             break;
842         case PISCSI_CMD_HEADS:
843             DEBUG("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
844             return devs[piscsi_cur_drive].h;
845             break;
846         case PISCSI_CMD_SECS:
847             DEBUG("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
848             return devs[piscsi_cur_drive].s;
849             break;
850         case PISCSI_CMD_BLOCKS: {
851             uint32_t blox = devs[piscsi_cur_drive].fs / 512;
852             DEBUG("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
853             DEBUG("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
854             return blox;
855             break;
856         }
857         case PISCSI_CMD_GETPART: {
858             DEBUG("[PISCSI] Get ROM partition %d offset: %.8X\n", rom_cur_partition, rom_partitions[rom_cur_partition]);
859             return rom_partitions[rom_cur_partition];
860             break;
861         }
862         case PISCSI_CMD_GETPRIO:
863             DEBUG("[PISCSI] Get partition %d boot priority: %d\n", rom_cur_partition, rom_partition_prio[rom_cur_partition]);
864             return rom_partition_prio[rom_cur_partition];
865             break;
866         case PISCSI_CMD_CHECKFS:
867             DEBUG("[PISCSI] Get current loaded file system: %.8X\n", filesystems[rom_cur_fs].FS_ID);
868             return filesystems[rom_cur_fs].FS_ID;
869         case PISCSI_CMD_FSSIZE:
870             DEBUG("[PISCSI] Get alloc size of loaded file system: %d\n", filesystems[rom_cur_fs].h_info.alloc_size);
871             return filesystems[rom_cur_fs].h_info.alloc_size;
872         default:
873             DEBUG("[!!!PISCSI] WARN: Unhandled %s register read from %.8X\n", op_type_names[type], addr);
874             break;
875     }
876
877     return 0;
878 }