]> git.sesse.net Git - pistorm/blobdiff - platforms/amiga/piscsi/piscsi.c
[WIP] Pile of stuff
[pistorm] / platforms / amiga / piscsi / piscsi.c
index 9f9500b2bf88f798ea11c2d3e5ac010dcc34872b..bfc8186e3f0091630fd80104db83708a0328b49e 100644 (file)
@@ -7,11 +7,19 @@
 #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;
@@ -29,6 +37,11 @@ static const char *op_type_names[4] = {
     "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;
@@ -39,6 +52,7 @@ void piscsi_init() {
     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;
@@ -50,10 +64,85 @@ void piscsi_init() {
     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);
@@ -69,14 +158,21 @@ void piscsi_map_drive(char *filename, uint8_t index) {
     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) {
@@ -87,48 +183,6 @@ 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";
@@ -155,8 +209,14 @@ char *io_cmd_name(int index) {
         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";
     }
@@ -166,8 +226,10 @@ char *scsi_cmd_name(int index) {
     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";
@@ -213,67 +275,84 @@ void print_piscsi_debug_message(int index) {
             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);
                 }
             }
@@ -305,33 +384,13 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
             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++) {
@@ -364,20 +423,20 @@ uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
     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;