]> git.sesse.net Git - pistorm/blob - platforms/amiga/piscsi/piscsi.c
497b6ede71dc5dd613b2ab99cf629e738328515d
[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 "../hunk-reloc.h"
11 #include "../../../config_file/config_file.h"
12 #include "../../../gpio/ps_protocol.h"
13
14 #define BE(val) be32toh(val)
15
16 // Comment these lines to restore debug output:
17 #define printf(...)
18 #define stop_cpu_emulation(...)
19
20 #ifdef FAKESTORM
21 #define lseek64 lseek
22 #endif
23
24 extern struct emulator_config *cfg;
25 extern void stop_cpu_emulation(uint8_t disasm_cur);
26
27 struct piscsi_dev devs[8];
28 uint8_t piscsi_cur_drive = 0;
29 uint32_t piscsi_u32[4];
30 uint32_t piscsi_dbg[8];
31 uint32_t piscsi_rom_size = 0;
32 uint8_t *piscsi_rom_ptr;
33
34 uint32_t rom_partitions[128];
35 uint32_t rom_partition_prio[128];
36 uint32_t rom_cur_partition = 0;
37
38 extern unsigned char ac_piscsi_rom[];
39
40 static const char *op_type_names[4] = {
41     "BYTE",
42     "WORD",
43     "LONGWORD",
44     "MEM",
45 };
46
47 //static const char *partition_marker = "PART";
48
49 struct hunk_info piscsi_hinfo;
50 struct hunk_reloc piscsi_hreloc[256];
51
52 void piscsi_init() {
53     for (int i = 0; i < 8; i++) {
54         devs[i].fd = -1;
55         devs[i].lba = 0;
56         devs[i].c = devs[i].h = devs[i].s = 0;
57     }
58
59     FILE *in = fopen("./platforms/amiga/piscsi/piscsi.rom", "rb");
60     if (in == NULL) {
61         printf("[PISCSI] Could not open PISCSI Boot ROM file for reading.\n");
62         // Zero out the boot ROM offset from the autoconfig ROM.
63         ac_piscsi_rom[20] = 0;
64         ac_piscsi_rom[21] = 0;
65         ac_piscsi_rom[22] = 0;
66         ac_piscsi_rom[23] = 0;
67         return;
68     }
69     fseek(in, 0, SEEK_END);
70     piscsi_rom_size = ftell(in);
71     fseek(in, 0, SEEK_SET);
72     piscsi_rom_ptr = malloc(piscsi_rom_size);
73     fread(piscsi_rom_ptr, piscsi_rom_size, 1, in);
74     fclose(in);
75
76     // Parse the hunks in the device driver to find relocation offsets
77     in = fopen("./platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device", "rb");
78     fseek(in, 0x0, SEEK_SET);
79     process_hunks(in, &piscsi_hinfo, piscsi_hreloc);
80
81     fclose(in);
82     printf("[PISCSI] Loaded Boot ROM.\n");
83 }
84
85 void piscsi_find_partitions(struct piscsi_dev *d) {
86     int fd = d->fd;
87     int cur_partition = 0;
88     uint8_t tmp;
89
90     for (int i = 0; i < 16; i++) {
91         if (d->pb[i]) {
92             free(d->pb[i]);
93             d->pb[i] = NULL;
94         }
95     }
96
97     if (!d->rdb || d->rdb->rdb_PartitionList == 0) {
98         printf("[PISCSI] No partitions on disk.\n");
99         return;
100     }
101
102     char *block = malloc(512);
103
104     lseek(fd, be32toh(d->rdb->rdb_PartitionList) * 512, SEEK_SET);
105 next_partition:;
106     read(fd, block, 512);
107
108     struct PartitionBlock *pb = (struct PartitionBlock *)block;
109     tmp = pb->pb_DriveName[0];
110     pb->pb_DriveName[tmp + 1] = 0x00;
111     printf("[PISCSI] Partition %d: %s\n", cur_partition, pb->pb_DriveName + 1);
112     printf("Checksum: %.8X HostID: %d\n", BE(pb->pb_ChkSum), BE(pb->pb_HostID));
113     printf("Flags: %d (%.8X) Devflags: %d (%.8X)\n", BE(pb->pb_Flags), BE(pb->pb_Flags), BE(pb->pb_DevFlags), BE(pb->pb_DevFlags));
114     d->pb[cur_partition] = pb;
115
116     if (d->pb[cur_partition]->pb_Next != 0xFFFFFFFF) {
117         uint64_t next = be32toh(pb->pb_Next);
118         block = malloc(512);
119         lseek64(fd, next * 512, SEEK_SET);
120         cur_partition++;
121         printf("[PISCSI] Next partition at block %d.\n", be32toh(pb->pb_Next));
122         goto next_partition;
123     }
124     printf("[PISCSI] No more partitions on disk.\n");
125     d->num_partitions = cur_partition + 1;
126
127     return;
128 }
129
130 int piscsi_parse_rdb(struct piscsi_dev *d) {
131     int fd = d->fd;
132     int i = 0;
133     uint8_t *block = malloc(512);
134
135     lseek(fd, 0, SEEK_SET);
136     for (i = 0; i < RDB_BLOCK_LIMIT; i++) {
137         read(fd, block, 512);
138         uint32_t first = be32toh(*((uint32_t *)&block[0]));
139         if (first == RDB_IDENTIFIER)
140             goto rdb_found;
141     }
142     goto no_rdb_found;
143 rdb_found:;
144     struct RigidDiskBlock *rdb = (struct RigidDiskBlock *)block;
145     printf("[PISCSI] RDB found at block %d.\n", i);
146     d->c = be32toh(rdb->rdb_Cylinders);
147     d->h = be32toh(rdb->rdb_Heads);
148     d->s = be32toh(rdb->rdb_Sectors);
149     printf("[PISCSI] RDB - first partition at block %d.\n", be32toh(rdb->rdb_PartitionList));
150     d->rdb = rdb;
151     sprintf(d->rdb->rdb_DriveInitName, "pi-scsi.device");
152     return 0;
153
154 no_rdb_found:;
155     if (block)
156         free(block);
157
158     return -1;
159 }
160
161 void piscsi_map_drive(char *filename, uint8_t index) {
162     if (index > 7) {
163         printf("[PISCSI] Drive index %d out of range.\nUnable to map file %s to drive.\n", index, filename);
164         return;
165     }
166
167     int32_t tmp_fd = open(filename, O_RDWR);
168     if (tmp_fd == -1) {
169         printf("[PISCSI] Failed to open file %s, could not map drive %d.\n", filename, index);
170         return;
171     }
172
173     struct piscsi_dev *d = &devs[index];
174
175     uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
176     d->fs = file_size;
177     d->fd = tmp_fd;
178     lseek(tmp_fd, 0, SEEK_SET);
179     printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
180
181     if (piscsi_parse_rdb(d) == -1) {
182         printf("[PISCSI] No RDB found on disk, making up some CHS values.\n");
183         d->h = 64;
184         d->s = 63;
185         d->c = (file_size / 512) / (d->s * d->h);
186     }
187     printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
188
189     piscsi_find_partitions(d);
190     //stop_cpu_emulation(1);
191 }
192
193 void piscsi_unmap_drive(uint8_t index) {
194     if (devs[index].fd != -1) {
195         printf("[PISCSI] Unmapped drive %d.\n", index);
196         close (devs[index].fd);
197         devs[index].fd = -1;
198     }
199 }
200
201 char *io_cmd_name(int index) {
202     switch (index) {
203         case CMD_INVALID: return "INVALID";
204         case CMD_RESET: return "RESET";
205         case CMD_READ: return "READ";
206         case CMD_WRITE: return "WRITE";
207         case CMD_UPDATE: return "UPDATE";
208         case CMD_CLEAR: return "CLEAR";
209         case CMD_STOP: return "STOP";
210         case CMD_START: return "START";
211         case CMD_FLUSH: return "FLUSH";
212         case TD_MOTOR: return "TD_MOTOR";
213         case TD_SEEK: return "SEEK";
214         case TD_FORMAT: return "FORMAT";
215         case TD_REMOVE: return "REMOVE";
216         case TD_CHANGENUM: return "CHANGENUM";
217         case TD_CHANGESTATE: return "CHANGESTATE";
218         case TD_PROTSTATUS: return "PROTSTATUS";
219         case TD_RAWREAD: return "RAWREAD";
220         case TD_RAWWRITE: return "RAWWRITE";
221         case TD_GETDRIVETYPE: return "GETDRIVETYPE";
222         case TD_GETNUMTRACKS: return "GETNUMTRACKS";
223         case TD_ADDCHANGEINT: return "ADDCHANGEINT";
224         case TD_REMCHANGEINT: return "REMCHANGEINT";
225         case TD_GETGEOMETRY: return "GETGEOMETRY";
226         case TD_EJECT: return "EJECT";
227         case TD_LASTCOMM: return "LASTCOMM/READ64";
228         case TD_WRITE64: return "WRITE64";
229         case HD_SCSICMD: return "HD_SCSICMD";
230         case NSCMD_DEVICEQUERY: return "NSCMD_DEVICEQUERY";
231         case NSCMD_TD_READ64: return "NSCMD_TD_READ64";
232         case NSCMD_TD_WRITE64: return "NSCMD_TD_WRITE64";
233         case NSCMD_TD_FORMAT64: return "NSCMD_TD_FORMAT64";
234
235         default:
236             return "!!!Unhandled IO command";
237     }
238 }
239
240 char *scsi_cmd_name(int index) {
241     switch(index) {
242         case 0x00: return "TEST UNIT READY";
243         case 0x12: return "INQUIRY";
244         case 0x08: return "READ (6)";
245         case 0x0A: return "WRITE (6)";
246         case 0x28: return "READ (10)";
247         case 0x2A: return "WRITE (10)";
248         case 0x25: return "READ CAPACITY";
249         case 0x1A: return "MODE SENSE";
250         case 0x37: return "READ DEFECT DATA";
251         default:
252             return "!!!Unhandled SCSI command";
253     }
254 }
255
256 void print_piscsi_debug_message(int index) {
257     switch (index) {
258         case DBG_INIT:
259             printf("[PISCSI] Initializing devices.\n");
260             break;
261         case DBG_OPENDEV:
262             printf("[PISCSI] Opening device %d (%d). Flags: %d (%.2X)\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[2]);
263             break;
264         case DBG_CLEANUP:
265             printf("[PISCSI] Cleaning up.\n");
266             break;
267         case DBG_CHS:
268             printf("[PISCSI] C/H/S: %d / %d / %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
269             break;
270         case DBG_BEGINIO:
271             printf("[PISCSI] BeginIO: io_Command: %d - io_Flags = %d - quick: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
272             break;
273         case DBG_ABORTIO:
274             printf("[PISCSI] AbortIO!\n");
275             break;
276         case DBG_SCSICMD:
277             printf("[PISCSI] SCSI Command %d (%s)\n", piscsi_dbg[1], scsi_cmd_name(piscsi_dbg[1]));
278             printf("Len: %d - %.2X %.2X %.2X - Command Length: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[3], piscsi_dbg[4]);
279             break;
280         case DBG_SCSI_UNKNOWN_MODESENSE:
281             printf("SCSI: Unknown modesense %.4X\n", piscsi_dbg[0]);
282             break;
283         case DBG_SCSI_UNKNOWN_COMMAND:
284             printf("SCSI: Unknown command %.4X\n", piscsi_dbg[0]);
285             break;
286         case DBG_SCSIERR:
287             printf("SCSI: An error occured: %.4X\n", piscsi_dbg[0]);
288             break;
289         case DBG_IOCMD:
290             printf("[PISCSI] IO Command %d (%s)\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
291             break;
292         case DBG_IOCMD_UNHANDLED:
293             printf("[PISCSI] WARN: IO command %.4X (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
294             break;
295     }
296 }
297
298 void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
299     int32_t r;
300
301     struct piscsi_dev *d = &devs[piscsi_cur_drive];
302
303     uint16_t cmd = (addr & 0xFFFF);
304
305     switch (cmd) {
306         case PISCSI_CMD_READ64:
307         case PISCSI_CMD_READ:
308             d = &devs[val];
309             if (d->fd == -1) {
310                 printf ("[PISCSI] BUG: Attempted read from unmapped drive %d.\n", val);
311                 break;
312             }
313
314             if (cmd == PISCSI_CMD_READ) {
315                 printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
316                 d->lba = piscsi_u32[0];
317                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
318             }
319             else {
320                 uint64_t src = piscsi_u32[3];
321                 src = (src << 32) | piscsi_u32[0];
322                 printf("[PISCSI] %d byte READ64 from block %lld to address %.8X\n", piscsi_u32[1], (src / 512), piscsi_u32[2]);
323                 d->lba = (src / 512);
324                 lseek64(d->fd, src, SEEK_SET);
325             }
326
327             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
328             if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
329                 printf("[PISCSI] \"DMA\" Read goes to mapped range %d.\n", r);
330                 read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
331             }
332             else {
333                 printf("[PISCSI] No mapped range found for read.\n");
334                 uint8_t c = 0;
335                 for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
336                     read(d->fd, &c, 1);
337                     write8(piscsi_u32[2] + i, (uint32_t)c);
338                 }
339             }
340             break;
341         case PISCSI_CMD_WRITE64:
342         case PISCSI_CMD_WRITE:
343             d = &devs[val];
344             if (d->fd == -1) {
345                 printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", val);
346                 break;
347             }
348
349             if (cmd == PISCSI_CMD_WRITE) {
350                 printf("[PISCSI] %d byte WRITE to block %d from address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
351                 d->lba = piscsi_u32[0];
352                 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
353             }
354             else {
355                 uint64_t src = piscsi_u32[3];
356                 src = (src << 32) | piscsi_u32[0];
357                 printf("[PISCSI] %d byte WRITE64 to block %lld from address %.8X\n", piscsi_u32[1], (src / 512), piscsi_u32[2]);
358                 d->lba = (src / 512);
359                 lseek64(d->fd, src, SEEK_SET);
360             }
361
362             r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
363             if (r != -1) {
364                 printf("[PISCSI] \"DMA\" Write comes from mapped range %d.\n", r);
365                 write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
366             }
367             else {
368                 printf("[PISCSI] No mapped range found for write.\n");
369                 uint8_t c = 0;
370                 for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
371                     c = read8(piscsi_u32[2] + i);
372                     write(d->fd, &c, 1);
373                 }
374             }
375             break;
376         case PISCSI_CMD_ADDR1: case PISCSI_CMD_ADDR2: case PISCSI_CMD_ADDR3: case PISCSI_CMD_ADDR4: {
377             int i = ((addr & 0xFFFF) - PISCSI_CMD_ADDR1) / 4;
378             piscsi_u32[i] = val;
379             break;
380         }
381         case PISCSI_CMD_DRVNUM:
382             if (val % 10 != 0)
383                 piscsi_cur_drive = 255;
384             else
385                 piscsi_cur_drive = val / 10;
386             printf("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
387             break;
388         case PISCSI_CMD_DEBUGME:
389             printf("[PISCSI] DebugMe triggered (%d).\n", val);
390             stop_cpu_emulation(1);
391             break;
392         case PISCSI_CMD_DRIVER: {
393             printf("[PISCSI] Driver copy/patch called, destination address %.8X.\n", val);
394             int r = get_mapped_item_by_address(cfg, val);
395             if (r != -1) {
396                 uint32_t addr = val - cfg->map_offset[r];
397                 uint8_t *dst_data = cfg->map_data[r];
398                 uint8_t cur_partition = 0;
399                 memcpy(dst_data + addr, piscsi_rom_ptr + 0x400, 0x3C00);
400
401                 piscsi_hinfo.base_offset = val;
402                 
403                 reloc_hunks(piscsi_hreloc, dst_data + addr, &piscsi_hinfo);
404                 stop_cpu_emulation(1);
405
406                 #define PUTNODELONG(val) *(uint32_t *)&dst_data[p_offs] = htobe32(val); p_offs += 4;
407                 #define PUTNODELONGBE(val) *(uint32_t *)&dst_data[p_offs] = val; p_offs += 4;
408
409                 for (int i = 0; i < 128; i++) {
410                     rom_partitions[i] = 0;
411                     rom_partition_prio[i] = 0;
412                 }
413                 rom_cur_partition = 0;
414
415                 uint32_t data_addr = addr + 0x3F00;
416                 sprintf((char *)dst_data + data_addr, "pi-scsi.device");
417                 uint32_t addr2 = addr + 0x4000;
418                 for (int i = 0; i < NUM_UNITS; i++) {
419                     piscsi_find_partitions(&devs[i]);
420                     if (devs[i].num_partitions) {
421                         uint32_t p_offs = addr2;
422                         printf("[PISCSI] Adding %d partitions for unit %d\n", devs[i].num_partitions, i);
423                         for (uint32_t j = 0; j < devs[i].num_partitions; j++) {
424                             printf("Partition %d: %s\n", j, devs[i].pb[j]->pb_DriveName + 1);
425                             sprintf((char *)dst_data + p_offs, "%s", devs[i].pb[j]->pb_DriveName + 1);
426                             p_offs += 0x20;
427                             PUTNODELONG(addr2 + cfg->map_offset[r]);
428                             PUTNODELONG(data_addr + cfg->map_offset[r]);
429                             PUTNODELONG((i * 10));
430                             PUTNODELONG(0);
431                             uint32_t nodesize = (be32toh(devs[i].pb[j]->pb_Environment[0]) + 1) * 4;
432                             memcpy(dst_data + p_offs, devs[i].pb[j]->pb_Environment, nodesize);
433
434                             struct pihd_dosnode_data *dat = (struct pihd_dosnode_data *)(&dst_data[addr2+0x20]);
435
436                             if (BE(devs[i].pb[j]->pb_Flags) & 0x01) {
437                                 printf("Partition is bootable.\n");
438                                 rom_partition_prio[cur_partition] = 0;
439                                 dat->priority = 0;
440                             }
441                             else {
442                                 printf("Partition is not bootable.\n");
443                                 rom_partition_prio[cur_partition] = -128;
444                                 dat->priority = htobe32(-128);
445                             }
446
447                             printf("DOSNode Data:\n");
448                             printf("Name: %s Device: %s\n", dst_data + addr2, dst_data + data_addr);
449                             printf("Unit: %d Flags: %d Pad1: %d\n", BE(dat->unit), BE(dat->flags), BE(dat->pad1));
450                             printf("Node len: %d Block len: %d\n", BE(dat->node_len) * 4, BE(dat->block_len) * 4);
451                             printf("H: %d SPB: %d BPS: %d\n", BE(dat->surf), BE(dat->secs_per_block), BE(dat->blocks_per_track));
452                             printf("Reserved: %d Prealloc: %d\n", BE(dat->reserved_blocks), BE(dat->pad2));
453                             printf("Interleaved: %d Buffers: %d Memtype: %d\n", BE(dat->interleave), BE(dat->buffers), BE(dat->mem_type));
454                             printf("Lowcyl: %d Highcyl: %d Prio: %d\n", BE(dat->lowcyl), BE(dat->highcyl), BE(dat->priority));
455                             printf("Maxtransfer: %.8X Mask: %.8X\n", BE(dat->maxtransfer), BE(dat->transfer_mask));
456                             printf("DOSType: %.8X\n", BE(dat->dostype));
457
458                             rom_partitions[cur_partition] = addr2 + 0x20 + cfg->map_offset[r];
459                             cur_partition++;
460                             addr2 += 0x100;
461                             p_offs = addr2;
462                         }
463                     }
464                 }
465             }
466            
467             break;
468         }
469         case PISCSI_CMD_NEXTPART:
470             printf("[PISCSI] Switch partition %d -> %d\n", rom_cur_partition, rom_cur_partition + 1);
471             rom_cur_partition++;
472             break;
473         case PISCSI_DBG_VAL1: case PISCSI_DBG_VAL2: case PISCSI_DBG_VAL3: case PISCSI_DBG_VAL4:
474         case PISCSI_DBG_VAL5: case PISCSI_DBG_VAL6: case PISCSI_DBG_VAL7: case PISCSI_DBG_VAL8: {
475             int i = ((addr & 0xFFFF) - PISCSI_DBG_VAL1) / 4;
476             piscsi_dbg[i] = val;
477             break;
478         }
479         case PISCSI_DBG_MSG:
480             print_piscsi_debug_message(val);
481             break;
482         default:
483             printf("[PISCSI] WARN: Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
484             break;
485     }
486 }
487
488 #define PIB 0x00
489
490 uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
491     if (type) {}
492
493     if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
494         uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
495         if (romoffs < (piscsi_rom_size + PIB)) {
496             //printf("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
497             uint32_t v = 0;
498             switch (type) {
499                 case OP_TYPE_BYTE:
500                     v = piscsi_rom_ptr[romoffs - PIB];
501                     //printf("%.2X\n", v);
502                     break;
503                 case OP_TYPE_WORD:
504                     v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
505                     //printf("%.4X\n", v);
506                     break;
507                 case OP_TYPE_LONGWORD:
508                     v = be32toh(*((uint32_t *)&piscsi_rom_ptr[romoffs - PIB]));
509                     //printf("%.8X\n", v);
510                     break;
511             }
512             return v;
513         }
514         return 0;
515     }
516     
517     switch (addr & 0xFFFF) {
518         case PISCSI_CMD_ADDR1: case PISCSI_CMD_ADDR2: case PISCSI_CMD_ADDR3: case PISCSI_CMD_ADDR4: {
519             int i = ((addr & 0xFFFF) - PISCSI_CMD_ADDR1) / 4;
520             return piscsi_u32[i];
521             break;
522         }
523         case PISCSI_CMD_DRVTYPE:
524             if (devs[piscsi_cur_drive].fd == -1) {
525                 printf("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
526                 return 0;
527             }
528             printf("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
529             return 1;
530             break;
531         case PISCSI_CMD_DRVNUM:
532             return piscsi_cur_drive;
533             break;
534         case PISCSI_CMD_CYLS:
535             printf("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
536             return devs[piscsi_cur_drive].c;
537             break;
538         case PISCSI_CMD_HEADS:
539             printf("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
540             return devs[piscsi_cur_drive].h;
541             break;
542         case PISCSI_CMD_SECS:
543             printf("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
544             return devs[piscsi_cur_drive].s;
545             break;
546         case PISCSI_CMD_BLOCKS: {
547             uint32_t blox = devs[piscsi_cur_drive].fs / 512;
548             printf("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
549             printf("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
550             return blox;
551             break;
552         }
553         case PISCSI_CMD_GETPART: {
554             printf("[PISCSI] Get ROM partition %d offset: %.8X\n", rom_cur_partition, rom_partitions[rom_cur_partition]);
555             return rom_partitions[rom_cur_partition];
556             break;
557         }
558         case PISCSI_CMD_GETPRIO:
559             printf("[PISCSI] Get partition %d boot priority: %d\n", rom_cur_partition, rom_partition_prio[rom_cur_partition]);
560             return rom_partition_prio[rom_cur_partition];
561             break;
562         default:
563             printf("[PISCSI] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
564             break;
565     }
566
567     return 0;
568 }