1 // SPDX-License-Identifier: MIT
11 #include "config_file/config_file.h"
12 #include "gpio/ps_protocol.h"
13 #include "piscsi-enums.h"
15 #include "platforms/amiga/hunk-reloc.h"
17 #define BE(val) be32toh(val)
18 #define BE16(val) be16toh(val)
20 // Uncomment the line below to enable debug output
21 //#define PISCSI_DEBUG
25 //#define DEBUG_TRIVIAL printf
26 #define DEBUG_TRVIAL(...)
28 extern void stop_cpu_emulation(uint8_t disasm_cur);
30 static const char *op_type_names[4] = {
38 #define DEBUG_TRIVIAL(...)
39 #define stop_cpu_emulation(...)
46 extern struct emulator_config *cfg;
48 struct piscsi_dev devs[8];
49 struct piscsi_fs filesystems[NUM_FILESYSTEMS];
51 uint8_t piscsi_num_fs = 0;
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;
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;
64 extern unsigned char ac_piscsi_rom[];
66 //static const char *partition_marker = "PART";
68 struct hunk_info piscsi_hinfo;
69 struct hunk_reloc piscsi_hreloc[256];
72 for (int i = 0; i < 8; i++) {
75 devs[i].c = devs[i].h = devs[i].s = 0;
78 if (piscsi_rom_ptr == NULL) {
79 FILE *in = fopen("./platforms/amiga/piscsi/piscsi.rom", "rb");
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;
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);
95 fseek(in, PISCSI_DRIVER_OFFSET, SEEK_SET);
96 process_hunks(in, &piscsi_hinfo, piscsi_hreloc, PISCSI_DRIVER_OFFSET);
100 printf("[PISCSI] Loaded Boot ROM.\n");
102 printf("[PISCSI] Boot ROM already loaded.\n");
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) {
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;
121 if (filesystems[i].fhb) {
122 free(filesystems[i].fhb);
123 filesystems[i].fhb = NULL;
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;
132 void piscsi_find_partitions(struct piscsi_dev *d) {
134 int cur_partition = 0;
137 for (int i = 0; i < 16; i++) {
144 if (!d->rdb || d->rdb->rdb_PartitionList == 0) {
145 DEBUG("[PISCSI] No partitions on disk.\n");
149 char *block = malloc(512);
151 lseek(fd, BE(d->rdb->rdb_PartitionList) * 512, SEEK_SET);
153 read(fd, block, 512);
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));
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;
169 if (d->pb[cur_partition]->pb_Next != 0xFFFFFFFF) {
170 uint64_t next = be32toh(pb->pb_Next);
172 lseek64(fd, next * 512, SEEK_SET);
174 DEBUG("[PISCSI] Next partition at block %d.\n", be32toh(pb->pb_Next));
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);
184 int piscsi_parse_rdb(struct piscsi_dev *d) {
187 uint8_t *block = malloc(512);
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)
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));
208 sprintf(d->rdb->rdb_DriveInitName, "pi-scsi.device");
218 void piscsi_refresh_drives() {
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;
226 if (filesystems[i].fhb) {
227 free(filesystems[i].fhb);
228 filesystems[i].fhb = NULL;
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;
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]);
247 void piscsi_find_filesystems(struct piscsi_dev *d) {
248 if (!d->num_partitions)
251 uint8_t fs_found = 0;
253 uint8_t *fhb_block = malloc(512);
255 lseek64(d->fd, d->fshd_offs, SEEK_SET);
257 struct FileSysHeaderBlock *fhb = (struct FileSysHeaderBlock *)fhb_block;
258 read(d->fd, fhb_block, 512);
260 while (BE(fhb->fhb_ID) == FS_IDENTIFIER) {
261 char *dosID = (char *)&fhb->fhb_DosType;
263 uint16_t *fsVer = (uint16_t *)&fhb->fhb_Version;
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);
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)
283 goto skip_fs_load_lseg;
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]);
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);
303 DEBUG("[!!!FSHD] No file systems found on hard drive!\n");
311 struct piscsi_dev *piscsi_get_dev(uint8_t index) {
315 void piscsi_map_drive(char *filename, uint8_t index) {
317 printf("[PISCSI] Drive index %d out of range.\nUnable to map file %s to drive.\n", index, filename);
321 int32_t tmp_fd = open(filename, O_RDWR);
323 printf("[PISCSI] Failed to open file %s, could not map drive %d.\n", filename, index);
327 struct piscsi_dev *d = &devs[index];
329 uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
332 lseek(tmp_fd, 0, SEEK_SET);
333 printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
335 if (piscsi_parse_rdb(d) == -1) {
336 DEBUG("[PISCSI] No RDB found on disk, making up some CHS values.\n");
339 d->c = (file_size / 512) / (d->s * d->h);
341 printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
343 printf ("Finding partitions.\n");
344 piscsi_find_partitions(d);
345 printf ("Finding file systems.\n");
346 piscsi_find_filesystems(d);
350 void piscsi_unmap_drive(uint8_t index) {
351 if (devs[index].fd != -1) {
352 DEBUG("[PISCSI] Unmapped drive %d.\n", index);
353 close (devs[index].fd);
358 char *io_cmd_name(int index) {
360 case CMD_INVALID: return "INVALID";
361 case CMD_RESET: return "RESET";
362 case CMD_READ: return "READ";
363 case CMD_WRITE: return "WRITE";
364 case CMD_UPDATE: return "UPDATE";
365 case CMD_CLEAR: return "CLEAR";
366 case CMD_STOP: return "STOP";
367 case CMD_START: return "START";
368 case CMD_FLUSH: return "FLUSH";
369 case TD_MOTOR: return "TD_MOTOR";
370 case TD_SEEK: return "SEEK";
371 case TD_FORMAT: return "FORMAT";
372 case TD_REMOVE: return "REMOVE";
373 case TD_CHANGENUM: return "CHANGENUM";
374 case TD_CHANGESTATE: return "CHANGESTATE";
375 case TD_PROTSTATUS: return "PROTSTATUS";
376 case TD_RAWREAD: return "RAWREAD";
377 case TD_RAWWRITE: return "RAWWRITE";
378 case TD_GETDRIVETYPE: return "GETDRIVETYPE";
379 case TD_GETNUMTRACKS: return "GETNUMTRACKS";
380 case TD_ADDCHANGEINT: return "ADDCHANGEINT";
381 case TD_REMCHANGEINT: return "REMCHANGEINT";
382 case TD_GETGEOMETRY: return "GETGEOMETRY";
383 case TD_EJECT: return "EJECT";
384 case TD_LASTCOMM: return "LASTCOMM/READ64";
385 case TD_WRITE64: return "WRITE64";
386 case HD_SCSICMD: return "HD_SCSICMD";
387 case NSCMD_DEVICEQUERY: return "NSCMD_DEVICEQUERY";
388 case NSCMD_TD_READ64: return "NSCMD_TD_READ64";
389 case NSCMD_TD_WRITE64: return "NSCMD_TD_WRITE64";
390 case NSCMD_TD_FORMAT64: return "NSCMD_TD_FORMAT64";
393 return "[!!!PISCSI] Unhandled IO command";
397 #define GETSCSINAME(a) case a: return ""#a"";
398 #define SCSIUNHANDLED(a) return "[!!!PISCSI] Unhandled SCSI command "#a"";
400 char *scsi_cmd_name(int index) {
402 GETSCSINAME(SCSICMD_TEST_UNIT_READY);
403 GETSCSINAME(SCSICMD_INQUIRY);
404 GETSCSINAME(SCSICMD_READ_6);
405 GETSCSINAME(SCSICMD_WRITE_6);
406 GETSCSINAME(SCSICMD_READ_10);
407 GETSCSINAME(SCSICMD_WRITE_10);
408 GETSCSINAME(SCSICMD_READ_CAPACITY_10);
409 GETSCSINAME(SCSICMD_MODE_SENSE_6);
410 GETSCSINAME(SCSICMD_READ_DEFECT_DATA_10);
412 return "[!!!PISCSI] Unhandled SCSI command";
416 void print_piscsi_debug_message(int index) {
421 DEBUG("[PISCSI] Initializing devices.\n");
424 if (piscsi_dbg[0] != 255) {
425 DEBUG("[PISCSI] Opening device %d (%d). Flags: %d (%.2X)\n", piscsi_dbg[0], piscsi_dbg[2], piscsi_dbg[1], piscsi_dbg[1]);
429 DEBUG("[PISCSI] Cleaning up.\n");
432 DEBUG("[PISCSI] C/H/S: %d / %d / %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
435 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]);
438 DEBUG("[PISCSI] AbortIO!\n");
441 DEBUG("[PISCSI] SCSI Command %d (%s)\n", piscsi_dbg[1], scsi_cmd_name(piscsi_dbg[1]));
442 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]);
444 case DBG_SCSI_UNKNOWN_MODESENSE:
445 DEBUG("[!!!PISCSI] SCSI: Unknown modesense %.4X\n", piscsi_dbg[0]);
447 case DBG_SCSI_UNKNOWN_COMMAND:
448 DEBUG("[!!!PISCSI] SCSI: Unknown command %.4X\n", piscsi_dbg[0]);
451 DEBUG("[!!!PISCSI] SCSI: An error occured: %.4X\n", piscsi_dbg[0]);
454 DEBUG_TRIVIAL("[PISCSI] IO Command %d (%s)\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
456 case DBG_IOCMD_UNHANDLED:
457 DEBUG("[!!!PISCSI] WARN: IO command %.4X (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
459 case DBG_SCSI_FORMATDEVICE:
460 DEBUG("[PISCSI] Get SCSI FormatDevice MODE SENSE.\n");
463 DEBUG("[PISCSI] Get SCSI RDG MODE SENSE.\n");
465 case DBG_SCSICMD_RW10:
467 r = get_mapped_item_by_address(cfg, piscsi_dbg[0]);
468 struct SCSICmd_RW10 *rwdat = NULL;
471 uint32_t addr = piscsi_dbg[0] - cfg->map_offset[r];
472 rwdat = (struct SCSICmd_RW10 *)(&cfg->map_data[r][addr]);
475 DEBUG_TRIVIAL("[RW10] scsiData: %.8X\n", piscsi_dbg[0]);
476 for (int i = 0; i < 10; i++) {
477 data[i] = read8(piscsi_dbg[0] + i);
482 DEBUG_TRIVIAL("[RW10] CMD: %.2X\n", rwdat->opcode);
483 DEBUG_TRIVIAL("[RW10] RDP: %.2X\n", rwdat->rdprotect_flags);
484 DEBUG_TRIVIAL("[RW10] Block: %d (%d)\n", rwdat->block, BE(rwdat->block));
485 DEBUG_TRIVIAL("[RW10] Res_Group: %.2X\n", rwdat->res_groupnum);
486 DEBUG_TRIVIAL("[RW10] Len: %d (%d)\n", rwdat->len, BE16(rwdat->len));
490 case DBG_SCSI_DEBUG_MODESENSE_6:
491 DEBUG_TRIVIAL("[PISCSI] SCSI ModeSense debug. Data: %.8X\n", piscsi_dbg[0]);
492 r = get_mapped_item_by_address(cfg, piscsi_dbg[0]);
495 uint32_t addr = piscsi_dbg[0] - cfg->map_offset[r];
496 struct SCSICmd_ModeSense6 *sense = (struct SCSICmd_ModeSense6 *)(&cfg->map_data[r][addr]);
497 DEBUG_TRIVIAL("[SenseData] CMD: %.2X\n", sense->opcode);
498 DEBUG_TRIVIAL("[SenseData] DBD: %d\n", sense->reserved_dbd & 0x04);
499 DEBUG_TRIVIAL("[SenseData] PC: %d\n", (sense->pc_pagecode & 0xC0 >> 6));
500 DEBUG_TRIVIAL("[SenseData] PageCodes: %.2X %.2X\n", (sense->pc_pagecode & 0x3F), sense->subpage_code);
501 DEBUG_TRIVIAL("[SenseData] AllocLen: %d\n", sense->alloc_len);
502 DEBUG_TRIVIAL("[SenseData] Control: %.2X (%d)\n", sense->control, sense->control);
506 DEBUG("[!!!PISCSI] ModeSense data not immediately available.\n");
510 DEBUG("[!!!PISCSI] No debug message available for index %d.\n", index);
515 #define DEBUGME_SIMPLE(i, s) case i: DEBUG(s); break;
517 void piscsi_debugme(uint32_t index) {
519 DEBUGME_SIMPLE(1, "[PISCSI-DEBUGME] Arrived at DiagEntry.\n");
520 DEBUGME_SIMPLE(3, "[PISCSI-DEBUGME] Init: Interrupt disable.\n");
521 DEBUGME_SIMPLE(4, "[PISCSI-DEBUGME] Init: Copy/reloc driver.\n");
522 DEBUGME_SIMPLE(5, "[PISCSI-DEBUGME] Init: InitResident.\n");
523 DEBUGME_SIMPLE(7, "[PISCSI-DEBUGME] Init: Begin partition loop.\n");
524 DEBUGME_SIMPLE(8, "[PISCSI-DEBUGME] Init: Partition loop done. Cleaning up and returning to Exec.\n");
525 DEBUGME_SIMPLE(9, "[PISCSI-DEBUGME] Init: Load file systems.\n");
526 DEBUGME_SIMPLE(10, "[PISCSI-DEBUGME] Init: AllocMem for resident.\n");
527 DEBUGME_SIMPLE(11, "[PISCSI-DEBUGME] Init: Checking if resident is loaded.\n");
528 DEBUGME_SIMPLE(22, "[PISCSI-DEBUGME] Arrived at BootEntry.\n");
529 DEBUGME_SIMPLE(30, "[PISCSI-DEBUGME] LoadFileSystems: Opening FileSystem.resource.\n");
530 DEBUGME_SIMPLE(33, "[PISCSI-DEBUGME] FileSystem.resource not available, creating.\n");
532 DEBUG("[PISCSI-DEBUGME] OpenResource result: %d\n", piscsi_u32[0]);
538 DEBUG("[!!!PISCSI-DEBUGME] No debugme message for index %d!\n", index);
543 stop_cpu_emulation(1);
547 void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
553 struct piscsi_dev *d = &devs[piscsi_cur_drive];
555 uint16_t cmd = (addr & 0xFFFF);
558 case PISCSI_CMD_READ64:
559 case PISCSI_CMD_READ:
562 DEBUG("[!!!PISCSI] BUG: Attempted read from unmapped drive %d.\n", val);
566 if (cmd == PISCSI_CMD_READ) {
567 DEBUG("[PISCSI-%d] %d byte READ from block %d to address %.8X\n", val, piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
568 d->lba = piscsi_u32[0];
569 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
572 uint64_t src = piscsi_u32[3];
573 src = (src << 32) | piscsi_u32[0];
574 DEBUG("[PISCSI-%d] %d byte READ64 from block %lld to address %.8X\n", val, piscsi_u32[1], (src / 512), piscsi_u32[2]);
575 d->lba = (src / 512);
576 lseek64(d->fd, src, SEEK_SET);
579 r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
580 if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
581 DEBUG_TRIVIAL("[PISCSI-%d] \"DMA\" Read goes to mapped range %d.\n", val, r);
582 read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
585 DEBUG_TRIVIAL("[PISCSI-%d] No mapped range found for read.\n", val);
587 for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
589 write8(piscsi_u32[2] + i, (uint32_t)c);
593 case PISCSI_CMD_WRITE64:
594 case PISCSI_CMD_WRITE:
597 DEBUG ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", val);
601 if (cmd == PISCSI_CMD_WRITE) {
602 DEBUG("[PISCSI-%d] %d byte WRITE to block %d from address %.8X\n", val, piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
603 d->lba = piscsi_u32[0];
604 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
607 uint64_t src = piscsi_u32[3];
608 src = (src << 32) | piscsi_u32[0];
609 DEBUG("[PISCSI-%d] %d byte WRITE64 to block %lld from address %.8X\n", val, piscsi_u32[1], (src / 512), piscsi_u32[2]);
610 d->lba = (src / 512);
611 lseek64(d->fd, src, SEEK_SET);
614 r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
616 DEBUG_TRIVIAL("[PISCSI-%d] \"DMA\" Write comes from mapped range %d.\n", val, r);
617 write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
620 DEBUG_TRIVIAL("[PISCSI-%d] No mapped range found for write.\n", val);
622 for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
623 c = read8(piscsi_u32[2] + i);
628 case PISCSI_CMD_ADDR1: case PISCSI_CMD_ADDR2: case PISCSI_CMD_ADDR3: case PISCSI_CMD_ADDR4: {
629 int i = ((addr & 0xFFFF) - PISCSI_CMD_ADDR1) / 4;
633 case PISCSI_CMD_DRVNUM:
634 //printf("%d ", val);
636 piscsi_cur_drive = 255;
638 piscsi_cur_drive = val / 10;
639 if (piscsi_cur_drive > NUM_UNITS)
640 piscsi_cur_drive = 255;
642 if (piscsi_cur_drive != 255) {
643 DEBUG("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
646 case PISCSI_CMD_DEBUGME:
649 case PISCSI_CMD_DRIVER: {
650 DEBUG("[PISCSI] Driver copy/patch called, destination address %.8X.\n", val);
651 int r = get_mapped_item_by_address(cfg, val);
653 uint32_t addr = val - cfg->map_offset[r];
654 uint8_t *dst_data = cfg->map_data[r];
655 uint8_t cur_partition = 0;
656 memcpy(dst_data + addr, piscsi_rom_ptr + PISCSI_DRIVER_OFFSET, 0x4000 - PISCSI_DRIVER_OFFSET);
658 piscsi_hinfo.base_offset = val;
660 reloc_hunks(piscsi_hreloc, dst_data + addr, &piscsi_hinfo);
662 #define PUTNODELONG(val) *(uint32_t *)&dst_data[p_offs] = htobe32(val); p_offs += 4;
663 #define PUTNODELONGBE(val) *(uint32_t *)&dst_data[p_offs] = val; p_offs += 4;
665 for (int i = 0; i < 128; i++) {
666 rom_partitions[i] = 0;
667 rom_partition_prio[i] = 0;
668 rom_partition_dostype[i] = 0;
670 rom_cur_partition = 0;
672 uint32_t data_addr = addr + 0x3F00;
673 sprintf((char *)dst_data + data_addr, "pi-scsi.device");
674 uint32_t addr2 = addr + 0x4000;
675 for (int i = 0; i < NUM_UNITS; i++) {
676 if (devs[i].fd != -1)
677 piscsi_find_partitions(&devs[i]);
681 if (devs[i].num_partitions) {
682 uint32_t p_offs = addr2;
683 DEBUG("[PISCSI] Adding %d partitions for unit %d\n", devs[i].num_partitions, i);
684 for (uint32_t j = 0; j < devs[i].num_partitions; j++) {
685 DEBUG("Partition %d: %s\n", j, devs[i].pb[j]->pb_DriveName + 1);
686 sprintf((char *)dst_data + p_offs, "%s", devs[i].pb[j]->pb_DriveName + 1);
688 PUTNODELONG(addr2 + cfg->map_offset[r]);
689 PUTNODELONG(data_addr + cfg->map_offset[r]);
690 PUTNODELONG((i * 10));
692 uint32_t nodesize = (be32toh(devs[i].pb[j]->pb_Environment[0]) + 1) * 4;
693 memcpy(dst_data + p_offs, devs[i].pb[j]->pb_Environment, nodesize);
695 struct pihd_dosnode_data *dat = (struct pihd_dosnode_data *)(&dst_data[addr2+0x20]);
697 if (BE(devs[i].pb[j]->pb_Flags) & 0x01) {
698 DEBUG("Partition is bootable.\n");
699 rom_partition_prio[cur_partition] = 0;
703 DEBUG("Partition is not bootable.\n");
704 rom_partition_prio[cur_partition] = -128;
705 dat->priority = htobe32(-128);
708 DEBUG("DOSNode Data:\n");
709 DEBUG("Name: %s Device: %s\n", dst_data + addr2, dst_data + data_addr);
710 DEBUG("Unit: %d Flags: %d Pad1: %d\n", BE(dat->unit), BE(dat->flags), BE(dat->pad1));
711 DEBUG("Node len: %d Block len: %d\n", BE(dat->node_len) * 4, BE(dat->block_len) * 4);
712 DEBUG("H: %d SPB: %d BPS: %d\n", BE(dat->surf), BE(dat->secs_per_block), BE(dat->blocks_per_track));
713 DEBUG("Reserved: %d Prealloc: %d\n", BE(dat->reserved_blocks), BE(dat->pad2));
714 DEBUG("Interleaved: %d Buffers: %d Memtype: %d\n", BE(dat->interleave), BE(dat->buffers), BE(dat->mem_type));
715 DEBUG("Lowcyl: %d Highcyl: %d Prio: %d\n", BE(dat->lowcyl), BE(dat->highcyl), BE(dat->priority));
716 DEBUG("Maxtransfer: %.8X Mask: %.8X\n", BE(dat->maxtransfer), BE(dat->transfer_mask));
717 DEBUG("DOSType: %.8X\n", BE(dat->dostype));
719 rom_partitions[cur_partition] = addr2 + 0x20 + cfg->map_offset[r];
720 rom_partition_dostype[cur_partition] = dat->dostype;
732 case PISCSI_CMD_NEXTPART:
733 DEBUG("[PISCSI] Switch partition %d -> %d\n", rom_cur_partition, rom_cur_partition + 1);
736 case PISCSI_CMD_NEXTFS:
737 DEBUG("[PISCSI] Switch file file system %d -> %d\n", rom_cur_fs, rom_cur_fs + 1);
740 case PISCSI_CMD_COPYFS:
741 DEBUG("[PISCSI] Copy file system %d to %.8X and reloc.\n", rom_cur_fs, piscsi_u32[2]);
742 r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
744 uint32_t addr = piscsi_u32[2] - cfg->map_offset[r];
745 memset(cfg->map_data[r] + addr, 0x00, filesystems[rom_cur_fs].h_info.alloc_size);
746 memcpy(cfg->map_data[r] + addr, filesystems[rom_cur_fs].binary_data, filesystems[rom_cur_fs].h_info.byte_size);
747 filesystems[rom_cur_fs].h_info.base_offset = piscsi_u32[2];
748 reloc_hunks(filesystems[rom_cur_fs].relocs, cfg->map_data[r] + addr, &filesystems[rom_cur_fs].h_info);
749 filesystems[rom_cur_fs].handler = piscsi_u32[2];
752 case PISCSI_CMD_SETFSH: {
754 DEBUG("[PISCSI] Set handler for partition %d (DeviceNode: %.8X)\n", rom_cur_partition, val);
755 r = get_mapped_item_by_address(cfg, val);
757 uint32_t addr = val - cfg->map_offset[r];
758 struct DeviceNode *node = (struct DeviceNode *)(cfg->map_data[r] + addr);
760 char *dosID = (char *)&rom_partition_dostype[rom_cur_partition];
762 DEBUG("[PISCSI] Partition DOSType is %c%c%c/%d\n", dosID[0], dosID[1], dosID[2], dosID[3]);
763 for (i = 0; i < piscsi_num_fs; i++) {
764 if (rom_partition_dostype[rom_cur_partition] == filesystems[i].FS_ID) {
765 node->dn_SegList = htobe32((filesystems[i].handler >> 2));
766 node->dn_GlobalVec = 0xFFFFFFFF;
770 DEBUG("[!!!PISCSI] Found no handler for file system!\n");
772 DEBUG("[FS-HANDLER] Next: %d Type: %.8X\n", BE(node->dn_Next), BE(node->dn_Type));
773 DEBUG("[FS-HANDLER] Task: %d Lock: %d\n", BE(node->dn_Task), BE(node->dn_Lock));
774 DEBUG("[FS-HANDLER] Handler: %d Stacksize: %d\n", BE((uint32_t)node->dn_Handler), BE(node->dn_StackSize));
775 DEBUG("[FS-HANDLER] Priority: %d Startup: %d\n", BE((uint32_t)node->dn_Priority), BE(node->dn_Startup));
776 DEBUG("[FS-HANDLER] SegList: %.8X GlobalVec: %d\n", BE((uint32_t)node->dn_SegList), BE(node->dn_GlobalVec));
777 DEBUG("[PISCSI] Handler for partition %.8X set to %.8X (%.8X).\n", BE((uint32_t)node->dn_Name), filesystems[i].FS_ID, filesystems[i].handler);
781 case PISCSI_DBG_VAL1: case PISCSI_DBG_VAL2: case PISCSI_DBG_VAL3: case PISCSI_DBG_VAL4:
782 case PISCSI_DBG_VAL5: case PISCSI_DBG_VAL6: case PISCSI_DBG_VAL7: case PISCSI_DBG_VAL8: {
783 int i = ((addr & 0xFFFF) - PISCSI_DBG_VAL1) / 4;
788 print_piscsi_debug_message(val);
791 DEBUG("[!!!PISCSI] WARN: Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
798 uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
801 if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
802 uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
803 if (romoffs < (piscsi_rom_size + PIB)) {
804 //DEBUG("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
808 v = piscsi_rom_ptr[romoffs - PIB];
809 //DEBUG("%.2X\n", v);
812 v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
813 //DEBUG("%.4X\n", v);
815 case OP_TYPE_LONGWORD:
816 v = be32toh(*((uint32_t *)&piscsi_rom_ptr[romoffs - PIB]));
817 //DEBUG("%.8X\n", v);
825 switch (addr & 0xFFFF) {
826 case PISCSI_CMD_ADDR1: case PISCSI_CMD_ADDR2: case PISCSI_CMD_ADDR3: case PISCSI_CMD_ADDR4: {
827 int i = ((addr & 0xFFFF) - PISCSI_CMD_ADDR1) / 4;
828 return piscsi_u32[i];
831 case PISCSI_CMD_DRVTYPE:
832 if (devs[piscsi_cur_drive].fd == -1) {
833 DEBUG("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
836 DEBUG("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
839 case PISCSI_CMD_DRVNUM:
840 return piscsi_cur_drive;
842 case PISCSI_CMD_CYLS:
843 DEBUG("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
844 return devs[piscsi_cur_drive].c;
846 case PISCSI_CMD_HEADS:
847 DEBUG("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
848 return devs[piscsi_cur_drive].h;
850 case PISCSI_CMD_SECS:
851 DEBUG("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
852 return devs[piscsi_cur_drive].s;
854 case PISCSI_CMD_BLOCKS: {
855 uint32_t blox = devs[piscsi_cur_drive].fs / 512;
856 DEBUG("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
857 DEBUG("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
861 case PISCSI_CMD_GETPART: {
862 DEBUG("[PISCSI] Get ROM partition %d offset: %.8X\n", rom_cur_partition, rom_partitions[rom_cur_partition]);
863 return rom_partitions[rom_cur_partition];
866 case PISCSI_CMD_GETPRIO:
867 DEBUG("[PISCSI] Get partition %d boot priority: %d\n", rom_cur_partition, rom_partition_prio[rom_cur_partition]);
868 return rom_partition_prio[rom_cur_partition];
870 case PISCSI_CMD_CHECKFS:
871 DEBUG("[PISCSI] Get current loaded file system: %.8X\n", filesystems[rom_cur_fs].FS_ID);
872 return filesystems[rom_cur_fs].FS_ID;
873 case PISCSI_CMD_FSSIZE:
874 DEBUG("[PISCSI] Get alloc size of loaded file system: %d\n", filesystems[rom_cur_fs].h_info.alloc_size);
875 return filesystems[rom_cur_fs].h_info.alloc_size;
877 DEBUG("[!!!PISCSI] WARN: Unhandled %s register read from %.8X\n", op_type_names[type], addr);