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