#include <endian.h>
#include "piscsi.h"
#include "piscsi-enums.h"
+#include "../hunk-reloc.h"
#include "../../../config_file/config_file.h"
-#include "../../../gpio/gpio.h"
+#include "../../../gpio/ps_protocol.h"
// Comment this line to restore debug output:
-#define printf(...)
+//#define printf(...)
+
+#ifdef FAKESTORM
+#define lseek64 lseek
+#endif
+
+extern struct emulator_config *cfg;
+extern void stop_cpu_emulation(uint8_t disasm_cur);
struct piscsi_dev devs[8];
uint8_t piscsi_cur_drive = 0;
"MEM",
};
+//static const char *partition_marker = "PART";
+
+struct hunk_info piscsi_hinfo;
+struct hunk_reloc piscsi_hreloc[256];
+
void piscsi_init() {
for (int i = 0; i < 8; i++) {
devs[i].fd = -1;
FILE *in = fopen("./platforms/amiga/piscsi/piscsi.rom", "rb");
if (in == NULL) {
printf("[PISCSI] Could not open PISCSI Boot ROM file for reading.\n");
+ // Zero out the boot ROM offset from the autoconfig ROM.
ac_piscsi_rom[20] = 0;
ac_piscsi_rom[21] = 0;
ac_piscsi_rom[22] = 0;
fseek(in, 0, SEEK_SET);
piscsi_rom_ptr = malloc(piscsi_rom_size);
fread(piscsi_rom_ptr, piscsi_rom_size, 1, in);
+ fclose(in);
+
+ // Parse the hunks in the device driver to find relocation offsets
+ in = fopen("./platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device", "rb");
+ fseek(in, 0x0, SEEK_SET);
+ process_hunks(in, &piscsi_hinfo, piscsi_hreloc);
+
fclose(in);
printf("[PISCSI] Loaded Boot ROM.\n");
}
+void piscsi_find_partitions(struct piscsi_dev *d) {
+ int fd = d->fd;
+ char *block = malloc(512);
+ int cur_partition = 0;
+ uint8_t tmp;
+
+ if (!d->rdb || d->rdb->rdb_PartitionList == 0) {
+ printf("[PISCSI] No partitions on disk.\n");
+ return;
+ }
+
+ lseek(fd, be32toh(d->rdb->rdb_PartitionList) * 512, SEEK_SET);
+next_partition:;
+ read(fd, block, 512);
+
+ struct PartitionBlock *pb = (struct PartitionBlock *)block;
+ tmp = pb->pb_DriveName[0];
+ pb->pb_DriveName[tmp + 1] = 0x00;
+ printf("Partition %d: %s\n", cur_partition, pb->pb_DriveName + 1);
+ d->pb[cur_partition] = pb;
+
+ if (d->pb[cur_partition]->pb_Next != 0xFFFFFFFF) {
+ uint64_t next = be32toh(pb->pb_Next);
+ block = malloc(512);
+ lseek64(fd, next * 512, SEEK_SET);
+ cur_partition++;
+ printf("Next partition at block %d.\n", be32toh(pb->pb_Next));
+ goto next_partition;
+ }
+ printf("No more partitions on disk.\n");
+
+ return;
+}
+
+int piscsi_parse_rdb(struct piscsi_dev *d) {
+ int fd = d->fd;
+ int i = 0;
+ uint8_t *block = malloc(512);
+
+ lseek(fd, 0, SEEK_SET);
+ for (i = 0; i < RDB_BLOCK_LIMIT; i++) {
+ read(fd, block, 512);
+ uint32_t first = be32toh(*((uint32_t *)&block[0]));
+ if (first == RDB_IDENTIFIER)
+ goto rdb_found;
+ else {
+ printf("Block %d is not RDB, looking for %.8X, found %.8X\n", i, RDB_IDENTIFIER, first);
+ }
+ }
+ goto no_rdb_found;
+rdb_found:;
+ struct RigidDiskBlock *rdb = (struct RigidDiskBlock *)block;
+ printf("[PISCSI] RDB found at block %d.\n", i);
+ d->c = be32toh(rdb->rdb_Cylinders);
+ d->h = be32toh(rdb->rdb_Heads);
+ d->s = be32toh(rdb->rdb_Sectors);
+ printf("[PISCSI] RDB - first partition at block %d.\n", be32toh(rdb->rdb_PartitionList));
+ d->rdb = rdb;
+ sprintf(d->rdb->rdb_DriveInitName, "pi-scsi.device");
+ return 0;
+
+no_rdb_found:;
+ if (block)
+ free(block);
+
+ return -1;
+}
+
void piscsi_map_drive(char *filename, uint8_t index) {
if (index > 7) {
printf("[PISCSI] Drive index %d out of range.\nUnable to map file %s to drive.\n", index, filename);
struct piscsi_dev *d = &devs[index];
uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
+ d->fs = file_size;
+ d->fd = tmp_fd;
lseek(tmp_fd, 0, SEEK_SET);
printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
- d->h = 64;
- d->s = 63;
- d->c = (file_size / 512) / (d->s * d->h);
+
+ if (piscsi_parse_rdb(d) == -1) {
+ printf("[PISCSI] No RDB found on disk, making up some CHS values.\n");
+ d->h = 64;
+ d->s = 63;
+ d->c = (file_size / 512) / (d->s * d->h);
+ }
printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
- d->fs = file_size;
- d->fd = tmp_fd;
+
+ piscsi_find_partitions(d);
+ //stop_cpu_emulation(1);
}
void piscsi_unmap_drive(uint8_t index) {
}
}
-#define TDF_EXTCOM (1<<15)
-
-#define CMD_INVALID 0
-#define CMD_RESET 1
-#define CMD_READ 2
-#define CMD_WRITE 3
-#define CMD_UPDATE 4
-#define CMD_CLEAR 5
-#define CMD_STOP 6
-#define CMD_START 7
-#define CMD_FLUSH 8
-#define CMD_NONSTD 9
-
-#define TD_MOTOR (CMD_NONSTD+0)
-#define TD_SEEK (CMD_NONSTD+1)
-#define TD_FORMAT (CMD_NONSTD+2)
-#define TD_REMOVE (CMD_NONSTD+3)
-#define TD_CHANGENUM (CMD_NONSTD+4)
-#define TD_CHANGESTATE (CMD_NONSTD+5)
-#define TD_PROTSTATUS (CMD_NONSTD+6)
-#define TD_RAWREAD (CMD_NONSTD+7)
-#define TD_RAWWRITE (CMD_NONSTD+8)
-#define TD_GETDRIVETYPE (CMD_NONSTD+9)
-#define TD_GETNUMTRACKS (CMD_NONSTD+10)
-#define TD_ADDCHANGEINT (CMD_NONSTD+11)
-#define TD_REMCHANGEINT (CMD_NONSTD+12)
-#define TD_GETGEOMETRY (CMD_NONSTD+13)
-#define TD_EJECT (CMD_NONSTD+14)
-#define TD_LASTCOMM (CMD_NONSTD+15)
-
-#define ETD_WRITE (CMD_WRITE|TDF_EXTCOM)
-#define ETD_READ (CMD_READ|TDF_EXTCOM)
-#define ETD_MOTOR (TD_MOTOR|TDF_EXTCOM)
-#define ETD_SEEK (TD_SEEK|TDF_EXTCOM)
-#define ETD_FORMAT (TD_FORMAT|TDF_EXTCOM)
-#define ETD_UPDATE (CMD_UPDATE|TDF_EXTCOM)
-#define ETD_CLEAR (CMD_CLEAR|TDF_EXTCOM)
-#define ETD_RAWREAD (TD_RAWREAD|TDF_EXTCOM)
-#define ETD_RAWWRITE (TD_RAWWRITE|TDF_EXTCOM)
-
-#define HD_SCSICMD 28
-
char *io_cmd_name(int index) {
switch (index) {
case CMD_INVALID: return "INVALID";
case TD_REMCHANGEINT: return "REMCHANGEINT";
case TD_GETGEOMETRY: return "GETGEOMETRY";
case TD_EJECT: return "EJECT";
- case TD_LASTCOMM: return "LASTCOMM";
+ case TD_LASTCOMM: return "LASTCOMM/READ64";
+ case TD_WRITE64: return "WRITE64";
case HD_SCSICMD: return "HD_SCSICMD";
+ case NSCMD_DEVICEQUERY: return "NSCMD_DEVICEQUERY";
+ case NSCMD_TD_READ64: return "NSCMD_TD_READ64";
+ case NSCMD_TD_WRITE64: return "NSCMD_TD_WRITE64";
+ case NSCMD_TD_FORMAT64: return "NSCMD_TD_FORMAT64";
+
default:
return "!!!Unhandled IO command";
}
switch(index) {
case 0x00: return "TEST UNIT READY";
case 0x12: return "INQUIRY";
- case 0x08: return "READ";
- case 0x0A: return "WRITE";
+ case 0x08: return "READ (6)";
+ case 0x0A: return "WRITE (6)";
+ case 0x28: return "READ (10)";
+ case 0x2A: return "WRITE (10)";
case 0x25: return "READ CAPACITY";
case 0x1A: return "MODE SENSE";
case 0x37: return "READ DEFECT DATA";
printf("[PISCSI] IO Command %d (%s)\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
break;
case DBG_IOCMD_UNHANDLED:
- printf("[PISCSI] WARN: IO command %d (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
+ printf("[PISCSI] WARN: IO command %.4X (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
}
}
-extern struct emulator_config *cfg;
-extern void stop_cpu_emulation(uint8_t disasm_cur);
-
void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
int32_t r;
struct piscsi_dev *d = &devs[piscsi_cur_drive];
- switch (addr & 0xFFFF) {
+ uint16_t cmd = (addr & 0xFFFF);
+
+ switch (cmd) {
+ case PISCSI_CMD_READ64:
case PISCSI_CMD_READ:
d = &devs[val];
if (d->fd == -1) {
printf ("[PISCSI] BUG: Attempted read from unmapped drive %d.\n", piscsi_cur_drive);
break;
}
- printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
- d->lba = piscsi_u32[0];
+
+ if (cmd == PISCSI_CMD_READ) {
+ printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
+ d->lba = piscsi_u32[0];
+ lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
+ }
+ else {
+ uint64_t src = piscsi_u32[3];
+ src = (src << 32) | piscsi_u32[0];
+ printf("[PISCSI] %d byte READ64 from block %lld to address %.8X\n", piscsi_u32[1], (src / 512), piscsi_u32[2]);
+ d->lba = (src / 512);
+ lseek64(d->fd, src, SEEK_SET);
+ }
+
r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
printf("[PISCSI] \"DMA\" Read goes to mapped range %d.\n", r);
- lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
}
else {
printf("[PISCSI] No mapped range found for read.\n");
uint8_t c = 0;
- lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
- for (int i = 0; i < piscsi_u32[1]; i++) {
+ for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
read(d->fd, &c, 1);
-#ifndef FAKESTORM
write8(piscsi_u32[2] + i, (uint32_t)c);
-#endif
}
}
break;
+ case PISCSI_CMD_WRITE64:
case PISCSI_CMD_WRITE:
d = &devs[val];
if (d->fd == -1) {
printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", piscsi_cur_drive);
break;
}
- d->lba = piscsi_u32[0];
- printf("[PISCSI] %d byte WRITE to block %d from address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
+
+ if (cmd == PISCSI_CMD_WRITE) {
+ printf("[PISCSI] %d byte WRITE to block %d from address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
+ d->lba = piscsi_u32[0];
+ lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
+ }
+ else {
+ uint64_t src = piscsi_u32[3];
+ src = (src << 32) | piscsi_u32[0];
+ printf("[PISCSI] %d byte WRITE64 to block %lld from address %.8X\n", piscsi_u32[1], (src / 512), piscsi_u32[2]);
+ d->lba = (src / 512);
+ lseek64(d->fd, src, SEEK_SET);
+ }
+
r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
if (r != -1) {
printf("[PISCSI] \"DMA\" Write comes from mapped range %d.\n", r);
- lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
}
else {
printf("[PISCSI] No mapped range found for write.\n");
uint8_t c = 0;
- lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
- for (int i = 0; i < piscsi_u32[1]; i++) {
-#ifndef FAKESTORM
+ for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
c = read8(piscsi_u32[2] + i);
-#endif
write(d->fd, &c, 1);
}
}
int r = get_mapped_item_by_address(cfg, val);
if (r != -1) {
uint32_t addr = val - cfg->map_offset[r];
- uint32_t rt_offs = 0;
uint8_t *dst_data = cfg->map_data[r];
memcpy(dst_data + addr, piscsi_rom_ptr + 0x400, 0x3C00);
-
- uint32_t base_offs = be32toh(*((uint32_t *)&dst_data[addr + 0x170])) + 2;
- rt_offs = val + 0x16E;
- printf ("Offset 1: %.8X -> %.8X\n", base_offs, rt_offs);
- *((uint32_t *)&dst_data[addr + 0x170]) = htobe32(rt_offs);
-
- uint32_t offs = be32toh(*((uint32_t *)&dst_data[addr + 0x174]));
- printf ("Offset 2: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
- *((uint32_t *)&dst_data[addr + 0x174]) = htobe32((offs - base_offs) + rt_offs);
-
- dst_data[addr + 0x178] |= 0x07;
-
- offs = be32toh(*((uint32_t *)&dst_data[addr + 0x17C]));
- printf ("Offset 3: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
- *((uint32_t *)&dst_data[addr + 0x17C]) = htobe32((offs - base_offs) + rt_offs);
-
- offs = be32toh(*((uint32_t *)&dst_data[addr + 0x180]));
- printf ("Offset 4: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
- *((uint32_t *)&dst_data[addr + 0x180]) = htobe32((offs - base_offs) + rt_offs);
-
- offs = be32toh(*((uint32_t *)&dst_data[addr + 0x184]));
- printf ("Offset 5: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
- *((uint32_t *)&dst_data[addr + 0x184]) = htobe32((offs - base_offs) + rt_offs);
+ piscsi_hinfo.base_offset = val;
+
+ reloc_hunks(piscsi_hreloc, dst_data + addr, &piscsi_hinfo);
+ stop_cpu_emulation(1);
}
else {
for (int i = 0; i < 0x3C00; i++) {
if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
if (romoffs < (piscsi_rom_size + PIB)) {
- printf("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
+ //printf("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
uint32_t v = 0;
switch (type) {
case OP_TYPE_BYTE:
v = piscsi_rom_ptr[romoffs - PIB];
- printf("%.2X\n", v);
+ //printf("%.2X\n", v);
break;
case OP_TYPE_WORD:
v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
- printf("%.4X\n", v);
+ //printf("%.4X\n", v);
break;
case OP_TYPE_LONGWORD:
v = be32toh(*((uint32_t *)&piscsi_rom_ptr[romoffs - PIB]));
- printf("%.8X\n", v);
+ //printf("%.8X\n", v);
break;
}
return v;