]> git.sesse.net Git - pistorm/commitdiff
[WIP] PiSCSI, Pi-NET and some other things
authorbeeanyew <beeanyew@gmail.com>
Wed, 27 Jan 2021 21:13:54 +0000 (22:13 +0100)
committerbeeanyew <beeanyew@gmail.com>
Wed, 27 Jan 2021 21:13:54 +0000 (22:13 +0100)
23 files changed:
.gitignore
Makefile
emulator.c
platforms/amiga/amiga-platform.c
platforms/amiga/net/net_driver_amiga/build.sh [new file with mode: 0644]
platforms/amiga/net/net_driver_amiga/pi-net-amiga.c [new file with mode: 0644]
platforms/amiga/net/net_driver_amiga/pi-net.device [new file with mode: 0644]
platforms/amiga/net/net_driver_amiga/sana2.h [new file with mode: 0644]
platforms/amiga/net/pi-net-enums.h [new file with mode: 0644]
platforms/amiga/net/pi-net.c [new file with mode: 0644]
platforms/amiga/net/pi-net.h [new file with mode: 0644]
platforms/amiga/piscsi/device_driver_amiga/bootrom [new file with mode: 0644]
platforms/amiga/piscsi/device_driver_amiga/bootrom.s [new file with mode: 0644]
platforms/amiga/piscsi/device_driver_amiga/build.bat [new file with mode: 0644]
platforms/amiga/piscsi/device_driver_amiga/build.sh [new file with mode: 0644]
platforms/amiga/piscsi/device_driver_amiga/makerom.c [new file with mode: 0644]
platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device [new file with mode: 0644]
platforms/amiga/piscsi/device_driver_amiga/piscsi-amiga.c [new file with mode: 0644]
platforms/amiga/piscsi/piscsi-enums.h [new file with mode: 0644]
platforms/amiga/piscsi/piscsi.c [new file with mode: 0644]
platforms/amiga/piscsi/piscsi.h [new file with mode: 0644]
platforms/amiga/piscsi/piscsi.rom [new file with mode: 0644]
run.sh [deleted file]

index 32ea9199c7d9681e7f1f9b71b3a8aece746c8cf9..aaf0cccdd4eba0a0ea22277793b55aeea8f8b6c8 100644 (file)
@@ -2,6 +2,7 @@
 *.img
 *.hdf
 *.rom
+!/platforms/amiga/piscsi/*.rom
 /m68kmake
 /m68kmake.exe
 /m68kops.c
index b738fa3bda6d9ec57a8e8a57b31323a210a4bca1..21c44271e102d1dace88f44893dbd58e7f403c02 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,6 +17,8 @@ MAINFILES        = emulator.c \
        platforms/amiga/rtg/rtg.c \
        platforms/amiga/rtg/rtg-output.c \
        platforms/amiga/rtg/rtg-gfx.c \
+       platforms/amiga/piscsi/piscsi.c \
+       platforms/amiga/net/pi-net.c \
        platforms/shared/rtc.c
 
 MUSASHIFILES     = m68kcpu.c m68kdasm.c softfloat/softfloat.c
index 75338a41393dee557b636f123e6319c8782b030a..845a80c8766d74015774716c4c0161d6ef5f8fc6 100644 (file)
 #include "platforms/amiga/gayle-ide/ide.h"
 #include "platforms/amiga/amiga-registers.h"
 #include "platforms/amiga/rtg/rtg.h"
+#include "platforms/amiga/piscsi/piscsi.h"
+#include "platforms/amiga/piscsi/piscsi-enums.h"
+#include "platforms/amiga/net/pi-net.h"
+#include "platforms/amiga/net/pi-net-enums.h"
 #include "gpio/gpio.h"
 
 unsigned char read_ranges;
@@ -242,6 +246,10 @@ disasm_run:;
     if (realtime_disassembly) {
       m68k_execute(1);
       m68k_disassemble(disasm_buf, m68k_get_reg(NULL, M68K_REG_PC), cpu_type);
+      /*printf("REGA: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1), m68k_get_reg(NULL, M68K_REG_A2), m68k_get_reg(NULL, M68K_REG_A3), \
+              m68k_get_reg(NULL, M68K_REG_A4), m68k_get_reg(NULL, M68K_REG_A5), m68k_get_reg(NULL, M68K_REG_A6), m68k_get_reg(NULL, M68K_REG_A7));
+      printf("REGD: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2), m68k_get_reg(NULL, M68K_REG_D3), \
+              m68k_get_reg(NULL, M68K_REG_D4), m68k_get_reg(NULL, M68K_REG_D5), m68k_get_reg(NULL, M68K_REG_D6), m68k_get_reg(NULL, M68K_REG_D7));*/
       printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf);
     }
     
@@ -369,6 +377,12 @@ void cdtv_dmac_write(uint32_t address, uint32_t value, uint8_t type);
     unsigned int target = 0; \
     switch(cfg->platform->id) { \
       case PLATFORM_AMIGA: { \
+        if (address >= PISCSI_OFFSET && address < PISCSI_UPPER) { \
+          return handle_piscsi_read(address, a); \
+        } \
+        if (address >= PINET_OFFSET && address < PINET_UPPER) { \
+          return handle_pinet_read(address, a); \
+        } \
         if (address >= PIGFX_RTG_BASE && address < PIGFX_UPPER) { \
           return rtg_read((address & 0x0FFFFFFF), a); \
         } \
@@ -389,14 +403,14 @@ void cdtv_dmac_write(uint32_t address, uint32_t value, uint8_t type);
 unsigned int m68k_read_memory_8(unsigned int address) {
   PLATFORM_CHECK_READ(OP_TYPE_BYTE);
 
-  if (address >= 0xE90000 && address < 0xF00000) {
+  /*if (address >= 0xE90000 && address < 0xF00000) {
     printf("BYTE read from DMAC @%.8X:", address);
     uint32_t v = cdtv_dmac_read(address & 0xFFFF, OP_TYPE_BYTE);
     printf("%.2X\n", v);
     m68k_end_timeslice();
     cpu_emulation_running = 0;
     return v;
-  }
+  }*/
 
   if (mouse_hook_enabled) {
     if (address == CIAAPRA) {
@@ -444,14 +458,14 @@ unsigned int m68k_read_memory_8(unsigned int address) {
 unsigned int m68k_read_memory_16(unsigned int address) {
   PLATFORM_CHECK_READ(OP_TYPE_WORD);
 
-  if (address >= 0xE90000 && address < 0xF00000) {
+  /*if (address >= 0xE90000 && address < 0xF00000) {
     printf("WORD read from DMAC @%.8X:", address);
     uint32_t v = cdtv_dmac_read(address & 0xFFFF, OP_TYPE_WORD);
     printf("%.2X\n", v);
     m68k_end_timeslice();
     cpu_emulation_running = 0;
     return v;
-  }
+  }*/
 
   if (mouse_hook_enabled) {
     if (address == JOY0DAT) {
@@ -489,14 +503,14 @@ unsigned int m68k_read_memory_16(unsigned int address) {
 unsigned int m68k_read_memory_32(unsigned int address) {
   PLATFORM_CHECK_READ(OP_TYPE_LONGWORD);
 
-  if (address >= 0xE90000 && address < 0xF00000) {
+  /*if (address >= 0xE90000 && address < 0xF00000) {
     printf("LONGWORD read from DMAC @%.8X:", address);
     uint32_t v = cdtv_dmac_read(address & 0xFFFF, OP_TYPE_LONGWORD);
     printf("%.2X\n", v);
     m68k_end_timeslice();
     cpu_emulation_running = 0;
     return v;
-  }
+  }*/
 
   if (address & 0xFF000000)
     return 0;
@@ -516,6 +530,12 @@ unsigned int m68k_read_memory_32(unsigned int address) {
   if (address >= cfg->custom_low && address < cfg->custom_high) { \
     switch(cfg->platform->id) { \
       case PLATFORM_AMIGA: { \
+        if (address >= PISCSI_OFFSET && address < PISCSI_UPPER) { \
+          handle_piscsi_write(address, value, a); \
+        } \
+        if (address >= PINET_OFFSET && address < PINET_UPPER) { \
+          handle_pinet_write(address, value, a); \
+        } \
         if (address >= PIGFX_RTG_BASE && address < PIGFX_UPPER) { \
           rtg_write((address & 0x0FFFFFFF), value, a); \
           return; \
@@ -537,13 +557,13 @@ unsigned int m68k_read_memory_32(unsigned int address) {
 void m68k_write_memory_8(unsigned int address, unsigned int value) {
   PLATFORM_CHECK_WRITE(OP_TYPE_BYTE);
 
-  if (address >= 0xE90000 && address < 0xF00000) {
+  /*if (address >= 0xE90000 && address < 0xF00000) {
     printf("BYTE write to DMAC @%.8X: %.2X\n", address, value);
     cdtv_dmac_write(address & 0xFFFF, value, OP_TYPE_BYTE);
     m68k_end_timeslice();
     cpu_emulation_running = 0;
     return;
-  }
+  }*/
 
   if (address == 0xbfe001) {
     if (ovl != (value & (1 << 0))) {
@@ -562,12 +582,17 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) {
 void m68k_write_memory_16(unsigned int address, unsigned int value) {
   PLATFORM_CHECK_WRITE(OP_TYPE_WORD);
 
-  if (address >= 0xE90000 && address < 0xF00000) {
+  /*if (address >= 0xE90000 && address < 0xF00000) {
     printf("WORD write to DMAC @%.8X: %.4X\n", address, value);
     cdtv_dmac_write(address & 0xFFFF, value, OP_TYPE_WORD);
     m68k_end_timeslice();
     cpu_emulation_running = 0;
     return;
+  }*/
+
+  if (address == 0xDFF030) {
+    char *beb = (char *)&value;
+    printf("%c%c", beb[1], beb[0]);
   }
 
   if (address & 0xFF000000)
@@ -583,13 +608,13 @@ void m68k_write_memory_16(unsigned int address, unsigned int value) {
 void m68k_write_memory_32(unsigned int address, unsigned int value) {
   PLATFORM_CHECK_WRITE(OP_TYPE_LONGWORD);
 
-  if (address >= 0xE90000 && address < 0xF00000) {
+  /*if (address >= 0xE90000 && address < 0xF00000) {
     printf("LONGWORD write to DMAC @%.8X: %.8X\n", address, value);
     cdtv_dmac_write(address & 0xFFFF, value, OP_TYPE_LONGWORD);
     m68k_end_timeslice();
     cpu_emulation_running = 0;
     return;
-  }
+  }*/
 
   if (address & 0xFF000000)
     return;
index 264b1d96565941d9e3aecfeb149b679ee164281b..c4bcf0041f2a37e28e0eeef21885d15d6e8ec191 100644 (file)
@@ -6,6 +6,10 @@
 #include "amiga-autoconf.h"
 #include "amiga-registers.h"
 #include "../shared/rtc.h"
+#include "piscsi/piscsi.h"
+#include "piscsi/piscsi-enums.h"
+#include "net/pi-net.h"
+#include "net/pi-net-enums.h"
 #include "rtg/rtg.h"
 
 int handle_register_read_amiga(unsigned int addr, unsigned char type, unsigned int *val);
@@ -36,7 +40,7 @@ extern unsigned char cdtv_sram[32 * SIZE_KILO];
 #define min(a, b) (a < b) ? a : b
 #define max(a, b) (a > b) ? a : b
 
-static uint8_t rtg_enabled;
+static uint8_t rtg_enabled = 0, piscsi_enabled = 0, pinet_enabled = 0;
 
 inline int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type) {
     if (!ac_z2_done && addr >= AC_Z2_BASE && addr < AC_Z2_BASE + AC_SIZE) {
@@ -148,6 +152,20 @@ void adjust_ranges_amiga(struct emulator_config *cfg) {
             cfg->custom_low = min(cfg->custom_low, PIGFX_RTG_BASE);
         cfg->custom_high = max(cfg->custom_high, PIGFX_UPPER);
     }
+    if (piscsi_enabled) {
+        if (cfg->custom_low == 0)
+            cfg->custom_low = PISCSI_OFFSET;
+        else
+            cfg->custom_low = min(cfg->custom_low, PISCSI_OFFSET);
+        cfg->custom_high = max(cfg->custom_high, PISCSI_UPPER);
+    }
+    if (pinet_enabled) {
+        if (cfg->custom_low == 0)
+            cfg->custom_low = PINET_OFFSET;
+        else
+            cfg->custom_low = min(cfg->custom_low, PINET_OFFSET);
+        cfg->custom_high = max(cfg->custom_high, PINET_UPPER);
+    }
 
     printf("Platform custom range: %.8X-%.8X\n", cfg->custom_low, cfg->custom_high);
     printf("Platform mapped range: %.8X-%.8X\n", cfg->mapped_low, cfg->mapped_high);
@@ -295,6 +313,47 @@ void setvar_amiga(struct emulator_config *cfg, char *var, char *val) {
         else
             printf("[AMIGA} Failed to enable RTG.\n");
     }
+
+    // PiSCSI stuff
+    if (strcmp(var, "piscsi") == 0) {
+        printf("[AMIGA] PISCSI Interface Enabled.\n");
+        piscsi_enabled = 1;
+        piscsi_init();
+        adjust_ranges_amiga(cfg);
+    }
+    if (piscsi_enabled) {
+        if (strcmp(var, "piscsi0") == 0) {
+            piscsi_map_drive(val, 0);
+        }
+        if (strcmp(var, "piscsi1") == 0) {
+            piscsi_map_drive(val, 1);
+        }
+        if (strcmp(var, "piscsi2") == 0) {
+            piscsi_map_drive(val, 2);
+        }
+        if (strcmp(var, "piscsi3") == 0) {
+            piscsi_map_drive(val, 3);
+        }
+        if (strcmp(var, "piscsi4") == 0) {
+            piscsi_map_drive(val, 4);
+        }
+        if (strcmp(var, "piscsi5") == 0) {
+            piscsi_map_drive(val, 5);
+        }
+        if (strcmp(var, "piscsi6") == 0) {
+            piscsi_map_drive(val, 6);
+        }
+    }
+
+    // Pi-Net stuff
+    if (strcmp(var, "pi-net") == 0) {
+        printf("[AMIGA] PI-NET Interface Enabled.\n");
+        pinet_enabled = 1;
+        pinet_init(val);
+        adjust_ranges_amiga(cfg);
+    }
+
+    // RTC stuff
     if (strcmp(var, "rtc_type") == 0) {
         if (val && strlen(val) != 0) {
             if (strcmp(val, "msm") == 0) {
diff --git a/platforms/amiga/net/net_driver_amiga/build.sh b/platforms/amiga/net/net_driver_amiga/build.sh
new file mode 100644 (file)
index 0000000..302ffc5
--- /dev/null
@@ -0,0 +1 @@
+m68k-amigaos-gcc -m68020 -O2 -o pi-net.device -ramiga-dev -noixemul -fbaserel pi-net-amiga.c -ldebug -lamiga
diff --git a/platforms/amiga/net/net_driver_amiga/pi-net-amiga.c b/platforms/amiga/net/net_driver_amiga/pi-net-amiga.c
new file mode 100644 (file)
index 0000000..68923f5
--- /dev/null
@@ -0,0 +1,460 @@
+#include <exec/resident.h>
+#include <exec/memory.h>
+#include <exec/alerts.h>
+#include <exec/io.h>
+#include <exec/execbase.h>
+#include <libraries/expansion.h>
+#include <dos/filehandler.h>
+#include <proto/exec.h>
+#include <proto/utility.h>
+#include <proto/dos.h>
+#include <proto/expansion.h>
+#include <clib/exec_protos.h>
+#include <clib/alib_protos.h>
+#include <dos/dostags.h>
+#include <utility/tagitem.h>
+#include <exec/lists.h>
+#include <exec/errors.h>
+#include <exec/interrupts.h>
+#include <exec/tasks.h>
+#include <hardware/intbits.h>
+#include <string.h>
+#include "sana2.h"
+#include "../pi-net-enums.h"
+
+#include <clib/debug_protos.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PINET_OFFSET + cmd)) = val;
+#define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PINET_OFFSET + cmd)) = val;
+#define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PINET_OFFSET + cmd)) = val;
+
+#define READBYTE(cmd, var) var = *(volatile unsigned char *)(PINET_OFFSET + cmd);
+#define READSHORT(cmd, var) var = *(volatile unsigned short *)(PINET_OFFSET + cmd);
+#define READLONG(cmd, var) var = *(volatile unsigned long *)(PINET_OFFSET + cmd);
+
+//typedef BOOL (*BMFunc)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
+
+typedef struct BufferManagement
+{
+  struct MinNode   bm_Node;
+  BOOL           (*bm_CopyFromBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
+  BOOL           (*bm_CopyToBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
+} BufferManagement;
+
+#pragma pack(4)
+struct pinet_base {
+    struct Device* pi_dev;
+    struct Unit unit;
+    uint8_t MAC[6];
+    uint8_t IP[4];
+
+       struct List read_list;
+       struct SignalSemaphore read_list_sem;
+};
+
+struct ExecBase* SysBase = NULL;
+
+const char DevName[] = "pi-net.device";
+const char DevIdString[] = "Pi-NET 0.1";
+
+const UWORD DevVersion = 1;
+const UWORD DevRevision = 0;
+
+#include "stabs.h"
+
+struct pinet_base *dev_base = NULL;
+
+struct WBStartup *_WBenchMsg = NULL;
+
+//#define exit(...)
+//#define debug(...)
+//#define KPrintF(...)
+
+uint32_t __UserDevInit(struct Device* dev) {
+       uint8_t *p;
+       uint32_t i;
+       int32_t  ok;
+
+    SysBase = *(struct ExecBase **)4L;
+
+    KPrintF("Initializing net device.\n");
+
+    dev_base = AllocMem(sizeof(struct pinet_base), MEMF_PUBLIC | MEMF_CLEAR);
+    dev_base->pi_dev = dev;
+
+    KPrintF("Grabbing MAC.\n");
+    for (int i = 0; i < 6; i++) {
+        READBYTE((PINET_CMD_MAC + i), dev_base->MAC[i]);
+    }
+    KPrintF("Grabbing IP.\n");
+    for (int i = 0; i < 4; i++) {
+        READBYTE((PINET_CMD_IP + i), dev_base->IP[i]);
+    }
+
+       return (uint32_t)dev;
+}
+
+uint32_t __UserDevCleanup(void) {
+    KPrintF("Cleaning up.\n");
+    FreeMem(dev_base, sizeof(struct pinet_base));
+    return 0;
+}
+
+uint32_t __UserDevOpen(struct IORequest *io, uint32_t num, uint32_t flags) {
+    struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
+       uint32_t ok = 0, ret = IOERR_OPENFAIL;
+    struct BufferManagement *bm;
+
+    KPrintF("Opening net device %ld.\n", num);
+    dev_base->unit.unit_OpenCnt++;
+
+    if (num == 0 && dev_base->unit.unit_OpenCnt == 1) {
+        //KPrintF("Trying to alloc buffer management.\n");
+        //if ((bm = (struct BufferManagement*)AllocVec(sizeof(struct BufferManagement), MEMF_CLEAR | MEMF_PUBLIC))) {
+            //KPrintF("Setting up buffer copy funcs (1).\n");
+            //bm->bm_CopyToBuffer = (BOOL *)GetTagData(S2_CopyToBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
+            //KPrintF("Setting up buffer copy funcs (2).\n");
+            //bm->bm_CopyFromBuffer = (BOOL *)GetTagData(S2_CopyFromBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
+
+            KPrintF("Doing more things.\n");
+            ioreq->ios2_BufferManagement = NULL;//(VOID *)bm;
+            ioreq->ios2_Req.io_Error = 0;
+            ioreq->ios2_Req.io_Unit = (struct Unit *)&dev_base->unit;
+            ioreq->ios2_Req.io_Device = (struct Device *)dev_base->pi_dev;
+
+            KPrintF("New list.\n");
+
+            NewList(&dev_base->read_list);
+            InitSemaphore(&dev_base->read_list_sem);
+            
+            ret = 0;
+            ok = 1;
+        //}
+    }
+
+    if (ret == IOERR_OPENFAIL) {
+        KPrintF("Failed to open device. Already open?\n");
+    }
+    else {
+        KPrintF("Device opened, yay.\n");
+    }
+    ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
+
+    KPrintF("Opened device, return code: %ld\n", ret);
+
+    return ret;
+}
+
+uint32_t __UserDevClose(struct IORequest *io) {
+  return 0;
+}
+
+uint32_t pinet_read_frame(struct IOSana2Req *ioreq) {
+    uint32_t datasize;
+    uint8_t *frame_ptr;
+    uint8_t broadcast;
+    uint32_t err = 0;
+    struct BufferManagement *bm;
+
+    /*uint8_t* frm = (uint8_t *)(PINET_OFFSET + PINET_CMD_FRAME);
+    uint32_t sz   = ((uint32_t)frm[0] << 8) | ((uint32_t)frm[1]);
+    uint32_t ser  = ((uint32_t)frm[2] << 8) | ((uint32_t)frm[3]);
+    uint16_t tp   = ((uint16_t)frm[16] << 8) | ((uint16_t)frm[17]);
+    
+    if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
+        frame_ptr = frm + 4;
+        datasize = sz;
+        req->ios2_Req.io_Flags = SANA2IOF_RAW;
+    }
+    else {
+        frame_ptr = frm + 4 + ETH_HDR_SIZE;
+        datasize = sz - ETH_HDR_SIZE;
+        req->ios2_Req.io_Flags = 0;
+    }
+
+    req->ios2_DataLength = datasize;
+
+    //D(("datasize: %lx\n",datasize));
+    //D(("frame_ptr: %lx\n",frame_ptr));
+    //D(("ios2_Data: %lx\n",req->ios2_Data));
+    //D(("bufmgmt: %lx\n",req->ios2_BufferManagement));
+
+    // copy frame to device user (probably tcp/ip system)
+    bm = (struct BufferManagement *)req->ios2_BufferManagement;
+    if (!(*bm->bm_CopyToBuffer)(req->ios2_Data, frame_ptr, datasize)) {
+        //D(("rx copybuf error\n"));
+        req->ios2_Req.io_Error = S2ERR_SOFTWARE;
+        req->ios2_WireError = S2WERR_BUFF_ERROR;
+        err = 1;
+    }
+    else {
+        req->ios2_Req.io_Error = req->ios2_WireError = 0;
+        err = 0;
+    }
+    
+    memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
+    memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
+    
+    //D(("RXSZ %ld\n",(LONG)sz));
+    //D(("RXPT %ld\n",(LONG)tp));
+
+    //D(("RXSER %ld\n",(LONG)ser));
+    //D(("RXDST %lx...\n",*((ULONG*)(req->ios2_DstAddr))));
+    //D(("RXSRC %lx\n",*((ULONG*)(req->ios2_SrcAddr))));
+    //D(("RXSRC %lx\n",*((ULONG*)(frame_ptr))));
+
+    broadcast = TRUE;
+    for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
+        if (frame[i+4] != 0xff) {
+        broadcast = FALSE;
+        break;
+        }
+    }
+    if (broadcast) {
+        req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
+    }
+    
+    req->ios2_PacketType = tp;*/
+
+    return err;
+}
+
+void pinet_write_frame(struct IOSana2Req *ioreq) {
+    
+}
+
+void exit(int status) { }
+
+ADDTABL_1(__BeginIO,a1);
+void __BeginIO(struct IORequest *io) {
+    struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
+    ULONG unit = (ULONG)ioreq->ios2_Req.io_Unit;
+    int mtu;
+
+    ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
+    ioreq->ios2_Req.io_Error = S2ERR_NO_ERROR;
+    ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
+
+    //D(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));
+
+    switch( ioreq->ios2_Req.io_Command ) {
+        case CMD_READ:
+            KPrintF("Read\n");
+            if (pinet_read_frame(ioreq) != 0) {
+                ioreq->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
+                ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
+            }
+            ioreq = NULL;
+            break;
+        case S2_BROADCAST:
+            KPrintF("Broadcast\n");
+            if (ioreq->ios2_DstAddr) {
+                for (int i = 0; i < ADDRFIELDSIZE; i++) {
+                    ioreq->ios2_DstAddr[i] = 0xFF;
+                }
+            } else {
+                KPrintF("Invalid ios2_DstAddr\n");
+            }
+            /* Fallthrough */
+        case CMD_WRITE: {
+            KPrintF("Write\n");
+            pinet_write_frame(ioreq);
+            break;
+        }
+
+        case S2_READORPHAN:
+            ioreq->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
+            ioreq = NULL;
+            break;
+        case S2_ONLINE:
+        case S2_OFFLINE:
+        case S2_CONFIGINTERFACE:   /* forward request */
+            break;
+
+        case S2_GETSTATIONADDRESS:
+            for (int i = 0; i < ADDRFIELDSIZE; i++) {
+                ioreq->ios2_SrcAddr[i] = dev_base->MAC[i];
+                ioreq->ios2_DstAddr[i] = dev_base->MAC[i];
+            }
+            break;
+        case S2_DEVICEQUERY: {
+            struct Sana2DeviceQuery *devquery;
+
+            devquery = ioreq->ios2_StatData;
+            devquery->DevQueryFormat = 0;
+            devquery->DeviceLevel = 0;
+
+            if (devquery->SizeAvailable >= 18)
+                devquery->AddrFieldSize = ADDRFIELDSIZE * 8;
+            if (devquery->SizeAvailable >= 22)
+                devquery->MTU           = 1500;
+            if (devquery->SizeAvailable >= 26)
+                devquery->BPS           =  1000 * 1000 * 100;
+            if (devquery->SizeAvailable >= 30)
+                devquery->HardwareType  = S2WireType_Ethernet;
+
+            devquery->SizeSupplied = (devquery->SizeAvailable < 30) ? devquery->SizeAvailable : 30;
+            break;
+        }
+        case S2_GETSPECIALSTATS: {
+            struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ioreq->ios2_StatData;
+            s2ssh->RecordCountSupplied = 0;
+            break;
+        }
+        default: {
+            uint8_t cmd = ioreq->ios2_Req.io_Command;
+            KPrintF("Unknown/unhandled IO command %lx\n", cmd);
+            ioreq->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
+            ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
+            break;
+        }
+    }
+
+    if (ioreq) {
+        if (!(ioreq->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
+            ReplyMsg((struct Message *)ioreq);
+        } else {
+            ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
+        }
+    }
+}
+
+ADDTABL_1(__AbortIO,a1);
+void __AbortIO(struct IORequest* ioreq) {
+    struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
+
+    if (!ioreq) return;
+       ioreq->io_Error = IOERR_ABORTED;
+    ios2->ios2_WireError = 0;
+}
+
+ADDTABL_1(__TermIO,a1);
+void __TermIO(struct IORequest *ioreq) {
+    struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
+    
+    if (!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
+        ReplyMsg((struct Message *)ioreq);
+    } else {
+        ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
+    }
+}
+
+/*ULONG get_frame_serial(UBYTE* frame) {
+  UBYTE* frm = (UBYTE*)frame;
+  ULONG ser  = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
+  return ser;
+}
+
+ULONG read_frame(struct IOSana2Req *req, volatile UBYTE *frame)
+{
+  ULONG datasize;
+  BYTE *frame_ptr;
+  BOOL broadcast;
+  ULONG err = 0;
+  struct BufferManagement *bm;
+
+  UBYTE* frm = (UBYTE*)frame;
+  ULONG sz   = ((ULONG)frm[0]<<8)|((ULONG)frm[1]);
+  ULONG ser  = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
+  USHORT tp  = ((USHORT)frm[16]<<8)|((USHORT)frm[17]);
+  
+  if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
+    frame_ptr = frm+4;
+    datasize = sz;
+    req->ios2_Req.io_Flags = SANA2IOF_RAW;
+  }
+  else {
+    frame_ptr = frm+4+HW_ETH_HDR_SIZE;
+    datasize = sz-HW_ETH_HDR_SIZE;
+    req->ios2_Req.io_Flags = 0;
+  }
+
+  req->ios2_DataLength = datasize;
+
+  //D(("datasize: %lx\n",datasize));
+  //D(("frame_ptr: %lx\n",frame_ptr));
+  //D(("ios2_Data: %lx\n",req->ios2_Data));
+  //D(("bufmgmt: %lx\n",req->ios2_BufferManagement));
+
+  // copy frame to device user (probably tcp/ip system)
+  bm = (struct BufferManagement *)req->ios2_BufferManagement;
+  if (!(*bm->bm_CopyToBuffer)(req->ios2_Data, frame_ptr, datasize)) {
+    //D(("rx copybuf error\n"));
+    req->ios2_Req.io_Error = S2ERR_SOFTWARE;
+    req->ios2_WireError = S2WERR_BUFF_ERROR;
+    err = 1;
+  }
+  else {
+    req->ios2_Req.io_Error = req->ios2_WireError = 0;
+    err = 0;
+  }
+  
+  memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
+  memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
+  
+  //D(("RXSZ %ld\n",(LONG)sz));
+  //D(("RXPT %ld\n",(LONG)tp));
+
+  //D(("RXSER %ld\n",(LONG)ser));
+  //D(("RXDST %lx...\n",*((ULONG*)(req->ios2_DstAddr))));
+  //D(("RXSRC %lx\n",*((ULONG*)(req->ios2_SrcAddr))));
+  //D(("RXSRC %lx\n",*((ULONG*)(frame_ptr))));
+
+  broadcast = TRUE;
+  for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
+    if (frame[i+4] != 0xff) {
+      broadcast = FALSE;
+      break;
+    }
+  }
+  if (broadcast) {
+    req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
+  }
+  
+  req->ios2_PacketType = tp;
+
+  return err;
+}
+
+ULONG write_frame(struct IOSana2Req *req, UBYTE *frame)
+{
+   ULONG rc=0;
+   struct BufferManagement *bm;
+   USHORT sz=0;
+   
+   if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
+      sz = req->ios2_DataLength;
+   } else {
+      sz = req->ios2_DataLength + HW_ETH_HDR_SIZE;
+      *((USHORT*)(frame+6+6)) = (USHORT)req->ios2_PacketType;
+      memcpy(frame, req->ios2_DstAddr, HW_ADDRFIELDSIZE);
+      memcpy(frame+6, HW_MAC, HW_ADDRFIELDSIZE);
+      frame+=HW_ETH_HDR_SIZE;
+   }
+
+   if (sz>0) {
+     bm = (struct BufferManagement *)req->ios2_BufferManagement;
+
+     if (!(*bm->bm_CopyFromBuffer)(frame, req->ios2_Data, req->ios2_DataLength)) {
+       rc = 1; // FIXME error code
+       //D(("tx copybuf err\n"));
+     }
+     else {
+       // buffer was copied to zz9000, send it
+       volatile USHORT* reg = (volatile USHORT*)(ZZ9K_REGS+0x80); // FIXME send_frame reg
+       *reg = sz;
+
+       // get feedback
+       rc = *reg;
+       if (rc!=0) {
+         D(("tx err: %d\n",rc));
+       }
+     }
+   }
+
+   return rc;
+}*/
+
+ADDTABL_END();
diff --git a/platforms/amiga/net/net_driver_amiga/pi-net.device b/platforms/amiga/net/net_driver_amiga/pi-net.device
new file mode 100644 (file)
index 0000000..96f8b30
Binary files /dev/null and b/platforms/amiga/net/net_driver_amiga/pi-net.device differ
diff --git a/platforms/amiga/net/net_driver_amiga/sana2.h b/platforms/amiga/net/net_driver_amiga/sana2.h
new file mode 100644 (file)
index 0000000..4265a2d
--- /dev/null
@@ -0,0 +1,261 @@
+#ifndef SANA2_SANA2DEVICE_H
+#define SANA2_SANA2DEVICE_H 1
+/*
+**      $Filename: devices/sana2.h $
+**      $Revision: 4.1 $
+**      $Date: 1994/10/03 20:55:10 $
+**
+**      Structure definitions for SANA-II devices.
+**
+**      (C) Copyright 1991 Commodore-Amiga Inc.
+**              All Rights Reserved
+*/
+
+
+#ifndef EXEC_TYPES_H
+#include <exec/types.h>
+#endif
+
+#ifndef EXEC_PORTS_H
+#include <exec/ports.h>
+#endif
+
+#ifndef EXEC_IO_H
+#include <exec/io.h>
+#endif
+
+#ifndef EXEC_ERRORS_H
+#include <exec/errors.h>
+#endif
+
+#ifndef DEVICES_TIMER_H
+#include <devices/timer.h>
+#endif
+
+#ifndef UTILITY_TAGITEM_H
+#include <utility/tagitem.h>
+#endif
+
+
+#define SANA2_MAX_ADDR_BITS     (128)
+#define SANA2_MAX_ADDR_BYTES    ((SANA2_MAX_ADDR_BITS+7)/8)
+
+struct IOSana2Req
+{
+        struct IORequest ios2_Req;
+        ULONG ios2_WireError;           /* wire type specific error     */
+        ULONG ios2_PacketType;          /* packet type                  */
+        UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES];       /* source addr  */
+        UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES];       /* dest address */
+        ULONG ios2_DataLength;          /* length of packet data        */
+        VOID *ios2_Data;                /* packet data                  */
+        VOID *ios2_StatData;            /* statistics data pointer      */
+        VOID *ios2_BufferManagement;    /* see SANA-II OpenDevice adoc  */
+};
+
+
+/*
+** defines for the io_Flags field
+*/
+#define SANA2IOB_RAW    (7)             /* raw packet IO requested      */
+#define SANA2IOF_RAW    (1<<SANA2IOB_RAW)
+
+#define SANA2IOB_BCAST  (6)             /* broadcast packet (received)  */
+#define SANA2IOF_BCAST  (1<<SANA2IOB_BCAST)
+
+#define SANA2IOB_MCAST  (5)             /* multicast packet (received)  */
+#define SANA2IOF_MCAST  (1<<SANA2IOB_MCAST)
+
+#define SANA2IOB_QUICK  (IOB_QUICK)     /* quick IO requested (0)       */
+#define SANA2IOF_QUICK  (IOF_QUICK)
+
+
+/*
+** defines for OpenDevice() flags
+*/
+#define SANA2OPB_MINE   (0)             /* exclusive access requested   */
+#define SANA2OPF_MINE   (1<<SANA2OPB_MINE)
+
+#define SANA2OPB_PROM   (1)             /* promiscuous mode requested   */
+#define SANA2OPF_PROM   (1<<SANA2OPB_PROM)
+
+
+/*
+** defines for OpenDevice() tags
+*/
+#define S2_Dummy        (TAG_USER + 0xB0000)
+
+#define S2_CopyToBuff   (S2_Dummy + 1)
+#define S2_CopyFromBuff (S2_Dummy + 2)
+#define S2_PacketFilter (S2_Dummy + 3)
+
+struct Sana2DeviceQuery
+{
+/*
+** Standard information
+*/
+        ULONG   SizeAvailable;          /* bytes available              */
+        ULONG   SizeSupplied;           /* bytes supplied               */
+        ULONG   DevQueryFormat;         /* this is type 0               */
+        ULONG   DeviceLevel;            /* this document is level 0     */
+/*
+** Common information
+*/
+        UWORD   AddrFieldSize;          /* address size in bits         */
+        ULONG   MTU;                    /* maximum packet data size     */
+        ULONG   BPS;                    /* line rate (bits/sec)         */
+        ULONG   HardwareType;           /* what the wire is             */
+/*
+** Format specific information
+*/
+};
+
+
+/*
+** defined Hardware types
+**
+**  If your hardware type isn't listed below contact CATS to get a new
+**  type number added for your hardware.
+*/
+#define S2WireType_Ethernet             1
+#define S2WireType_IEEE802              6
+#define S2WireType_Arcnet               7
+#define S2WireType_LocalTalk            11
+#define S2WireType_DyLAN                12
+
+#define S2WireType_AmokNet              200    /* Amiga Floppy Port hardware */
+
+#define S2WireType_Liana               202     /* Villate Tronic parallel port hw */
+
+#define S2WireType_PPP                  253
+#define S2WireType_SLIP                 254
+#define S2WireType_CSLIP                255    /* Compressed SLIP */
+
+#define S2WireType_PLIP                        420     /* SLIP over a parallel port */
+
+struct Sana2PacketTypeStats
+{
+        ULONG PacketsSent;              /* transmitted count            */
+        ULONG PacketsReceived;          /* received count               */
+        ULONG BytesSent;                /* bytes transmitted count      */
+        ULONG BytesReceived;            /* bytes received count         */
+        ULONG PacketsDropped;           /* packets dropped count        */
+};
+
+
+struct Sana2SpecialStatRecord
+{
+        ULONG Type;                     /* statistic identifier         */
+        ULONG Count;                    /* the statistic                */
+        char *String;                   /* statistic name               */
+};
+
+
+struct Sana2SpecialStatHeader
+{
+        ULONG RecordCountMax;           /* room available               */
+        ULONG RecordCountSupplied;      /* number supplied              */
+        /* struct Sana2SpecialStatRecord[RecordCountMax]; */
+};
+
+
+struct Sana2DeviceStats
+{
+        ULONG PacketsReceived;          /* received count               */
+        ULONG PacketsSent;              /* transmitted count            */
+        ULONG BadData;                  /* bad packets received         */
+        ULONG Overruns;                 /* hardware miss count          */
+        ULONG Unused;                   /* Unused field                 */
+        ULONG UnknownTypesReceived;     /* orphan count                 */
+        ULONG Reconfigurations;         /* network reconfigurations     */
+        struct timeval LastStart;       /* time of last online          */
+};
+
+
+/*
+** Device Commands
+*/
+#define S2_START                (CMD_NONSTD)
+
+#define S2_DEVICEQUERY          (S2_START+ 0)
+#define S2_GETSTATIONADDRESS    (S2_START+ 1)
+#define S2_CONFIGINTERFACE      (S2_START+ 2)
+#define S2_ADDMULTICASTADDRESS  (S2_START+ 5)
+#define S2_DELMULTICASTADDRESS  (S2_START+ 6)
+#define S2_MULTICAST            (S2_START+ 7)
+#define S2_BROADCAST            (S2_START+ 8)
+#define S2_TRACKTYPE            (S2_START+ 9)
+#define S2_UNTRACKTYPE          (S2_START+10)
+#define S2_GETTYPESTATS         (S2_START+11)
+#define S2_GETSPECIALSTATS      (S2_START+12)
+#define S2_GETGLOBALSTATS       (S2_START+13)
+#define S2_ONEVENT              (S2_START+14)
+#define S2_READORPHAN           (S2_START+15)
+#define S2_ONLINE               (S2_START+16)
+#define S2_OFFLINE              (S2_START+17)
+
+#define S2_END                  (S2_START+18)
+
+
+/*
+** defined errors for io_Error  (see also <exec/errors.h>)
+*/
+#define S2ERR_NO_ERROR          0       /* peachy-keen                  */
+#define S2ERR_NO_RESOURCES      1       /* resource allocation failure  */
+#define S2ERR_BAD_ARGUMENT      3       /* garbage somewhere            */
+#define S2ERR_BAD_STATE         4       /* inappropriate state          */
+#define S2ERR_BAD_ADDRESS       5       /* who?                         */
+#define S2ERR_MTU_EXCEEDED      6       /* too much to chew             */
+#define S2ERR_NOT_SUPPORTED     8       /* hardware can't support cmd   */
+#define S2ERR_SOFTWARE          9       /* software error detected      */
+#define S2ERR_OUTOFSERVICE      10      /* driver is OFFLINE            */
+#define S2ERR_TX_FAILURE        11      /* Transmission attempt failed  */
+/*
+** From <exec/errors.h>
+**
+**      IOERR_OPENFAIL   (-1) * device/unit failed to open *
+**      IOERR_ABORTED    (-2) * request terminated early [after AbortIO()] *
+**      IOERR_NOCMD      (-3) * command not supported by device *
+**      IOERR_BADLENGTH  (-4) * not a valid length (usually IO_LENGTH) *
+**      IOERR_BADADDRESS (-5) * invalid address (misaligned or bad range) *
+**      IOERR_UNITBUSY   (-6) * device opens ok, but requested unit is busy *
+**      IOERR_SELFTEST   (-7) * hardware failed self-test *
+*/
+
+/*
+** defined errors for ios2_WireError
+*/
+#define S2WERR_GENERIC_ERROR    0       /* no specific info available   */
+#define S2WERR_NOT_CONFIGURED   1       /* unit not configured          */
+#define S2WERR_UNIT_ONLINE      2       /* unit is currently online     */
+#define S2WERR_UNIT_OFFLINE     3       /* unit is currently offline    */
+#define S2WERR_ALREADY_TRACKED  4       /* protocol already tracked     */
+#define S2WERR_NOT_TRACKED      5       /* protocol not tracked         */
+#define S2WERR_BUFF_ERROR       6       /* buff mgt func returned error */
+#define S2WERR_SRC_ADDRESS      7       /* source address problem       */
+#define S2WERR_DST_ADDRESS      8       /* destination address problem  */
+#define S2WERR_BAD_BROADCAST    9       /* broadcast address problem    */
+#define S2WERR_BAD_MULTICAST    10      /* multicast address problem    */
+#define S2WERR_MULTICAST_FULL   11      /* multicast address list full  */
+#define S2WERR_BAD_EVENT        12      /* unsupported event class      */
+#define S2WERR_BAD_STATDATA     13      /* statdata failed sanity check */
+#define S2WERR_IS_CONFIGURED    15      /* attempt to config twice      */
+#define S2WERR_NULL_POINTER     16      /* null pointer detected        */
+#define S2WERR_TOO_MANY_RETIRES 17      /* tx failed - too many retries */
+#define S2WERR_RCVREL_HDW_ERR   18      /* Driver fixable HW error      */
+
+
+/*
+** defined events
+*/
+#define S2EVENT_ERROR           (1L<<0) /* error catch all              */
+#define S2EVENT_TX              (1L<<1) /* transmitter error catch all  */
+#define S2EVENT_RX              (1L<<2) /* receiver error catch all     */
+#define S2EVENT_ONLINE          (1L<<3) /* unit is in service           */
+#define S2EVENT_OFFLINE         (1L<<4) /* unit is not in service       */
+#define S2EVENT_BUFF            (1L<<5) /* buff mgt function error      */
+#define S2EVENT_HARDWARE        (1L<<6) /* hardware error catch all     */
+#define S2EVENT_SOFTWARE        (1L<<7) /* software error catch all     */
+
+
+#endif  /* SANA2_SANA2DEVICE_H */
diff --git a/platforms/amiga/net/pi-net-enums.h b/platforms/amiga/net/pi-net-enums.h
new file mode 100644 (file)
index 0000000..c7ba857
--- /dev/null
@@ -0,0 +1,24 @@
+#define PINET_OFFSET  0x80010000
+#define PINET_REGSIZE 0x00010000
+#define PINET_UPPER   0x80020000
+
+/*enum piscsi_stuff {
+    PISCSI_BLOCK_SIZE = 512,
+    PISCSI_TRACK_SECTORS = 2048,
+};*/
+
+#define ADDRFIELDSIZE 6
+#define ETH_HDR_SIZE  14
+
+enum pinet_cmds {
+    PINET_CMD_WRITE     = 0x00,
+    PINET_CMD_READ      = 0x02,
+    PINET_CMD_MAC       = 0x04,
+    PINET_CMD_IP        = 0x0A,
+    PINET_CMD_BEEF      = 0x0E,
+    PINET_CMD_ADDR1     = 0x10,
+    PINET_CMD_ADDR2     = 0x14,
+    PINET_CMD_ADDR3     = 0x18,
+    PINET_CMD_ADDR4     = 0x1C,
+    PINET_CMD_FRAME     = 0x1000,
+};
\ No newline at end of file
diff --git a/platforms/amiga/net/pi-net.c b/platforms/amiga/net/pi-net.c
new file mode 100644 (file)
index 0000000..b206438
--- /dev/null
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <endian.h>
+#include "pi-net.h"
+#include "pi-net-enums.h"
+#include "../../../config_file/config_file.h"
+#include "../../../gpio/gpio.h"
+
+uint32_t pinet_u32[4];
+static const char *op_type_names[4] = {
+    "BYTE",
+    "WORD",
+    "LONGWORD",
+    "MEM",
+};
+
+void pinet_init(char *dev) {
+    // Initialize them nets.
+}
+
+uint8_t PI_MAC[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+uint8_t PI_IP[4] = { 192, 168, 1, 9 };
+
+void handle_pinet_write(uint32_t addr, uint32_t val, uint8_t type) {
+    int32_t r;
+
+    switch (addr & 0xFFFF) {
+        case PINET_CMD_READ:
+            printf("[PI-NET] Read.\n");
+            break;
+        case PINET_CMD_WRITE:
+            printf("[PI-NET] Write.\n");
+            break;
+        case PINET_CMD_ADDR1:
+            pinet_u32[0] = val;
+            printf("[PI-NET] Write to ADDR1: %.8x\n", pinet_u32[0]);
+            break;
+        case PINET_CMD_ADDR2:
+            pinet_u32[1] = val;
+            printf("[PI-NET] Write to ADDR2: %.8x\n", pinet_u32[1]);
+            break;
+        case PINET_CMD_ADDR3:
+            pinet_u32[2] = val;
+            printf("[PI-NET] Write to ADDR3: %.8x\n", pinet_u32[2]);
+            break;
+        case PINET_CMD_ADDR4:
+            pinet_u32[3] = val;
+            printf("[PI-NET] Write to ADDR4: %.8x\n", pinet_u32[3]);
+            break;
+        default:
+            printf("[PI-NET] Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
+            break;
+    }
+}
+
+uint32_t handle_pinet_read(uint32_t addr_, uint8_t type) {
+    uint32_t addr = addr_ & 0xFFFF;
+
+    if (addr >= PINET_CMD_MAC && addr < PINET_CMD_IP) {
+        printf("[PI-NET] Read from MAC: %.2X. (%.8X)\n", PI_MAC[addr - PINET_CMD_MAC], addr_);
+        return PI_MAC[addr - PINET_CMD_MAC];
+    }
+    if (addr >= PINET_CMD_IP && addr < PINET_CMD_BEEF) {
+        printf("[PI-NET] Read from IP: %.2X. (%.8X)\n", PI_IP[addr - PINET_CMD_IP], addr_);
+        return PI_IP[addr - PINET_CMD_IP];
+    }
+
+    switch (addr & 0xFFFF) {
+        default:
+            printf("[PI-NET] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
+            break;
+    }
+
+    return 0;
+}
diff --git a/platforms/amiga/net/pi-net.h b/platforms/amiga/net/pi-net.h
new file mode 100644 (file)
index 0000000..6b101a9
--- /dev/null
@@ -0,0 +1,3 @@
+void pinet_init(char *dev);
+void handle_pinet_write(uint32_t addr, uint32_t val, uint8_t type);
+uint32_t handle_pinet_read(uint32_t addr, uint8_t type);
diff --git a/platforms/amiga/piscsi/device_driver_amiga/bootrom b/platforms/amiga/piscsi/device_driver_amiga/bootrom
new file mode 100644 (file)
index 0000000..1e806e7
Binary files /dev/null and b/platforms/amiga/piscsi/device_driver_amiga/bootrom differ
diff --git a/platforms/amiga/piscsi/device_driver_amiga/bootrom.s b/platforms/amiga/piscsi/device_driver_amiga/bootrom.s
new file mode 100644 (file)
index 0000000..50c70c1
--- /dev/null
@@ -0,0 +1,251 @@
+/* ConfigDev passed in a3 */
+/*
+struct ConfigDev {
+    struct Node   cd_Node; // 0  2ptr,2byte,1ptr = 14byte
+    UBYTE   cd_Flags; // 14
+    UBYTE   cd_Pad; // 15
+    struct ExpansionRom cd_Rom; // 16   16bytes
+    APTR    cd_BoardAddr; // 32
+    ...
+*/
+.set SysBase,4
+.set OpenLibrary,-552
+.set CloseLibrary,-414
+.set PutStr,-948
+.set VPrintf,-954
+.set AllocMem,-198
+.set FindResident,-96
+
+start:
+    jmp realstart(pc)
+    handover:
+    jmp trampoline(pc)
+
+.align 4
+realstart:
+    movea.l SysBase,a6 /* allocate RAM for loading ourselves to */
+    move.l #0x40000,d0
+    moveq #0,d1 /* MEMF_ANY */
+    jsr AllocMem(a6)
+    tst.l d0
+    beq allocfail
+
+    move.l d0, a4 /* load addr */
+
+    move.l (a7)+,a3 /* restore configdev address from stack */
+    jmp 0x24(a4) /* jmp to handover at new memory location (0x20+0x04) */
+
+.align 4
+allocfail:  
+    move.l d1,0xdff180
+    add.l #1,d1
+    bra allocfail
+
+/* we will arrive here in our copy in amiga RAM */
+/* a0 contains board addr, a3 contains configdev addr */
+.align 4
+trampoline:
+    lea configdev(pc),a1
+    move.l a3,(a1) /* store configdev pointer */
+
+    move.l a4, a0 /* board addr not needed anymore, keep loadaddr in a0 */
+
+    /* add resident ---------------------- */
+
+    /* mntsd.device is at loadaddr + 0x400 (skip 2 blocks) */
+    move.l  a0,-(a7)
+    add.l   #0x400, a0
+    /* relocate the binary (hunk) */
+    jsr     relocstart(pc)
+    move.l  (a7)+, a0 /* address of loaded mntsd.device */
+    move.l  a0, a4
+    move.l  a4, a1 /* restore board addr */
+
+    add.l   #0x400+0x180, a1 /* start of mntsd.device + $180 = romtag FIXME */
+    move.l  #0, d1 /* no seglist */
+    move.l  4,a6
+    jsr     -102(a6) /* InitResident */
+    /* object = InitResident(resident, segList) */
+    /* D0                    A1        D1 */
+
+    /* make dos node --------------------- */
+
+    jmp initdos(pc)
+
+.align 4
+configdev:
+    .long 0
+
+segtprs:
+    .long 0
+    .long 0
+
+    .align 4
+    relocstart:
+    lea.l  segptrs(pc), a1
+
+    move.l 8(a0), d4 /* number of hunks */
+    move.l #0, d5
+
+    /*
+        a0: executable base addr
+        a1: segptrs
+        a2: addr of hunk0
+
+        d4: numhunks
+        d5: pass#
+        d6: current hunk addr
+    */
+
+    /* hunk 0 address in memory */
+    move.l a0, d6
+    add.l  #0x24, d6
+    move.l d6, a2 /* addr of first hunk */
+    move.l d6, (a1) /* store pointer to this hunk in segptrs[1] */
+
+relocpass:
+    move.l a2, a3
+    move.l 0x14(a0), d0 /* ptr to first hunk size */
+
+    lsl.l  #2, d0 /* firsthunk + first size */
+    add.l  d0, a3 /* end of first hunk, start of reloc table */
+
+    jsr  reloctables(pc)
+
+    add.l  #4, a3 /* skip hunk_end */
+    add.l  #4, a3 /* skip hunk_data */
+    move.l (a3)+, d0 /* size of data hunk */
+    lsl.l  #2, d0
+
+    move.l a3, 4(a1) /* store pointer to this hunk in segptrs[1] */
+    move.l a3, d6 /* save current hunk ptr for patching CHECKME */
+    add.l  d0, a3 /* arrive at reloc tables of data hunk */
+
+    jsr   reloctables(pc)
+
+    cmp #1, d5
+    bge rcomplete
+
+    /* start pass 1 */
+    move.l #1, d5
+    move.l a2, d6 /* addr of first hunk */
+    bra relocpass
+
+rcomplete:
+    rts
+
+.align 4
+reloctables:
+    move.l (a3)+, d2 /* skip 0000 03ec marker */
+    reloctable:
+    move.l (a3)+, d2 /* number of relocs to process */
+
+    tst.w  d2
+    beq    relocdone /* done if zero */
+
+    move.l (a3)+, d1  /* segment number to point to */
+
+    lsl.l #2, d1
+    move.l (a1,d1), d1 /* offset to add to target slots */
+
+    bra rloop
+relocloop:
+    move.l (a3)+, a4
+
+    tst.w d5 /* pass = 0? */
+    beq rloop
+
+    /* pass = 1, so patch */
+    add.l  d6, a4 /* add current hunk address */
+    add.l  d1, (a4) /* the actual patching */
+
+    move.l d1, 0xdff180
+    rloop:
+    dbra   d2, relocloop
+    jmp reloctable(pc)
+    relocdone:
+    rts
+
+.align 4
+initdos:  
+    move.l  4,a6
+    lea     expansionname(pc),a1
+
+    moveq   #37, d0
+    jsr     OpenLibrary(a6) /* open expansion.library */
+    tst.l   d0
+    beq.s   nodos
+    move.l  d0,a6
+
+        /*movem.l a0-a6/d0-d6,-(a7)
+        move.l #0xbeef,d2
+        lea.l fmtdebug(pc),a1
+        jsr printf(pc)
+        movem.l (a7)+,a0-a6/d0-d6*/
+
+    lea     dosnode(pc),a0
+    lea     diskname(pc),a1
+    move.l  a1,(a0) /* store in parmpkt */
+    lea     devicename(pc),a1
+    move.l  a1,4(a0) /* store in parmpkt */
+
+    jsr     -144(a6) /* MakeDosNode */
+    move.l  d0, a0 /* fresh device node */
+
+    /* add boot node --------------------- */
+
+    move.l  #0, d0
+    move.l  #0, d1
+    move.l configdev(pc),a1
+    /*move.l  #0, a1*/ /* later put ConfigDev here (a3) */
+    jsr     -36(a6) /* AddBootNode */
+
+    move.l  a6,a1 /* close expansion library */
+    move.l  4,a6
+    jsr     CloseLibrary(a6)
+    moveq   #1,d0
+    move.l  (a7)+,a6
+    rts
+
+nodos:
+    move.l d1,0xdff180
+    add.l #1,d1
+    bra nodos
+
+    moveq   #1,d0
+    move.l  (a7)+,a6
+    rts
+
+.align 4
+diskname:
+    .asciz "PDH0"
+    .align 4
+devicename:
+    .asciz "pi-scsi.device"
+    .align 4
+expansionname:
+    .asciz "expansion.library"
+    .align 4
+dosnode:
+    .long 0 /* dos disk name */
+    .long 0 /* device file name */
+    .long 0 /* unit */
+    .long 0 /* flags */
+    .long 16 /* length of node? */
+    .long 128 /* longs in a block */
+    .long 0
+    .long 4 /* surfaces */
+    .long 1 /* sectors per block */
+    .long 256 /* blocks per track */
+    .long 2 /* reserved bootblocks 256 = 128KB */
+    .long 0
+    .long 0
+    .long 2  /* lowcyl FIXME */
+    /*.long 2047*/ /* hicyl */
+    .long 1023
+    .long 10 /* buffers */
+    .long 0 /* MEMF_ANY */
+    .long 0x0001fe00 /* MAXTRANS */
+    .long 0x7ffffffe /* Mask */
+    .long -1 /* boot prio */
+    .long 0x444f5303 /* dostype: DOS3 */
diff --git a/platforms/amiga/piscsi/device_driver_amiga/build.bat b/platforms/amiga/piscsi/device_driver_amiga/build.bat
new file mode 100644 (file)
index 0000000..7e20377
--- /dev/null
@@ -0,0 +1 @@
+vc +aos68k -nostdlib -I$VBCC/targets/m68k-amigaos/include2 -c99 -O2 -o pi-scsi.device piscsi-amiga.c -ldebug -lamiga -cpu=68020
diff --git a/platforms/amiga/piscsi/device_driver_amiga/build.sh b/platforms/amiga/piscsi/device_driver_amiga/build.sh
new file mode 100644 (file)
index 0000000..9fd02f7
--- /dev/null
@@ -0,0 +1,4 @@
+#m68k-amigaos-gcc piscsi-amiga.c -ramiga-dev -noixemul -fbaserel -O2 -o pi-scsi.device -ldebug -lamiga -m68020
+m68k-amigaos-gcc -m68020 -O2 -o pi-scsi.device -ramiga-dev -noixemul -fbaserel piscsi-amiga.c -ldebug -lamiga
+m68k-amigaos-as -m68000 bootrom.s && m68k-amigaos-objcopy --strip-all ./a.out ./bootrom
+rm ./a.out
diff --git a/platforms/amiga/piscsi/device_driver_amiga/makerom.c b/platforms/amiga/piscsi/device_driver_amiga/makerom.c
new file mode 100644 (file)
index 0000000..4bf7e1e
--- /dev/null
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define BOOTLDR_SIZE 0x400
+
+char *rombuf, *zerobuf, *devicebuf;
+
+int main(int argc, char *argv[]) {
+    FILE *rom = fopen("bootrom", "rb");
+    if (!rom) {
+        printf("Could not open file bootrom for reading.\n");
+        return 1;
+    }
+    FILE *out = fopen("../piscsi.rom", "wb+");
+    if (!out) {
+        printf("Could not open file piscsi.rom for writing.\n");
+        fclose(rom);
+        return 1;
+    }
+    FILE *device = fopen("pi-scsi.device", "rb");
+    if (!device) {
+        printf("Could not open file pi-scsi.device for reading.\n");
+        fclose(rom);
+        fclose(out);
+        return 1;
+    }
+
+    fseek(device, 0, SEEK_END);
+    fseek(rom, 0, SEEK_END);
+    uint32_t rom_size = ftell(rom);
+    uint32_t device_size = ftell(device);
+    fseek(rom, 0, SEEK_SET);
+    fseek(device, 0, SEEK_SET);
+
+    uint32_t pad_size = BOOTLDR_SIZE - rom_size;
+
+    rombuf = malloc(rom_size);
+    devicebuf = malloc(device_size);
+    zerobuf = malloc(pad_size);
+    memset(zerobuf, 0x00, pad_size);
+
+    fread(rombuf, rom_size, 1, rom);
+    fread(devicebuf, device_size, 1, device);
+
+    fwrite(rombuf, rom_size, 1, out);
+    fwrite(zerobuf, pad_size, 1, out);
+    fwrite(devicebuf, device_size, 1, out);
+
+    printf("piscsi.rom successfully created.\n");
+
+    free(rombuf);
+    free(zerobuf);
+    free(devicebuf);
+    
+    fclose(out);
+    fclose(device);
+    fclose(rom);
+
+    return 0;
+}
diff --git a/platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device b/platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device
new file mode 100644 (file)
index 0000000..cdb4635
Binary files /dev/null and b/platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device differ
diff --git a/platforms/amiga/piscsi/device_driver_amiga/piscsi-amiga.c b/platforms/amiga/piscsi/device_driver_amiga/piscsi-amiga.c
new file mode 100644 (file)
index 0000000..757078a
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * Based on:
+ * Amiga ZZ9000 USB Storage Driver (ZZ9000USBStorage.device)
+ * Copyright (C) 2016-2020, Lukas F. Hartmann <lukas@mntre.com>
+ * Based on code Copyright (C) 2016, Jason S. McMullan <jason.mcmullan@gmail.com>
+ * All rights reserved.
+ *
+ * Licensed under the MIT License:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <exec/resident.h>
+#include <exec/errors.h>
+#include <exec/memory.h>
+#include <exec/lists.h>
+#include <exec/alerts.h>
+#include <exec/tasks.h>
+#include <exec/io.h>
+#include <exec/execbase.h>
+
+#include <libraries/expansion.h>
+
+#include <devices/trackdisk.h>
+#include <devices/timer.h>
+#include <devices/scsidisk.h>
+
+#include <dos/filehandler.h>
+
+#include <proto/exec.h>
+#include <proto/disk.h>
+#include <proto/expansion.h>
+
+#include <clib/debug_protos.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "../piscsi-enums.h"
+
+#define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
+#define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
+#define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
+
+#define READSHORT(cmd, var) var = *(volatile unsigned short *)(PISCSI_OFFSET + cmd);
+#define READLONG(cmd, var) var = *(volatile unsigned long *)(PISCSI_OFFSET + cmd);
+
+#pragma pack(4)
+struct piscsi_base {
+    struct Device* pi_dev;
+    struct piscsi_unit {
+        struct Unit unit;
+        uint32_t regs_ptr;
+
+        uint8_t enabled;
+        uint8_t present;
+        uint8_t valid;
+        uint8_t read_only;
+        uint8_t motor;
+        uint8_t unit_num;
+        uint16_t h, s;
+        uint32_t c;
+
+        uint32_t change_num;
+    } units[NUM_UNITS];
+};
+
+struct ExecBase* SysBase = NULL;
+
+const char DevName[] = "pi-scsi.device";
+const char DevIdString[] = "Pi-SCSI 0.1";
+
+const UWORD DevVersion = 1;
+const UWORD DevRevision = 0;
+
+#include "stabs.h"
+
+struct piscsi_base *dev_base = NULL;
+
+struct WBStartup *_WBenchMsg = NULL;
+
+//#define exit(...)
+//#define debug(...)
+#define KPrintF(...)
+
+//#define bug(x,args...) KPrintF(x ,##args);
+//#define debug(x,args...) bug("%s:%ld " x "\n", __func__, (unsigned long)__LINE__ ,##args)
+
+uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io);
+uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write);
+uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io);
+
+extern void* DOSBase[2];
+
+uint32_t __UserDevInit(struct Device* dev) {
+    //uint8_t* registers = NULL;
+    SysBase = *(struct ExecBase **)4L;
+
+    KPrintF("Initializing devices.\n");
+
+    dev_base = AllocMem(sizeof(struct piscsi_base), MEMF_PUBLIC | MEMF_CLEAR);
+    dev_base->pi_dev = dev;
+
+    for (int i = 0; i < NUM_UNITS; i++) {
+        uint16_t r = 0;
+        WRITESHORT(PISCSI_CMD_DRVNUM, i);
+        dev_base->units[i].regs_ptr = PISCSI_OFFSET;
+        READSHORT(PISCSI_CMD_DRVTYPE, r);
+        dev_base->units[i].enabled = r;
+        dev_base->units[i].present = r;
+        dev_base->units[i].valid = r;
+        dev_base->units[i].unit_num = i;
+        if (dev_base->units[i].present) {
+            READLONG(PISCSI_CMD_CYLS, dev_base->units[i].c);
+            READSHORT(PISCSI_CMD_HEADS, dev_base->units[i].h);
+            READSHORT(PISCSI_CMD_SECS, dev_base->units[i].s);
+            KPrintF("C/H/S: %ld / %ld / %ld\n", dev_base->units[i].c, dev_base->units[i].h, dev_base->units[i].s);
+        }
+        dev_base->units[i].change_num++;
+        // Send any reset signal to the "SCSI" device here.
+    }
+
+    return 1;
+}
+
+uint32_t __UserDevCleanup(void) {
+    KPrintF("Cleaning up.\n");
+    FreeMem(dev_base, sizeof(struct piscsi_base));
+    return 0;
+}
+
+uint32_t __UserDevOpen(struct IOExtTD *iotd, uint32_t num, uint32_t flags) {
+    struct Node* node = (struct Node*)iotd;
+    int io_err = IOERR_OPENFAIL;
+
+    int unit_num = 0;
+    WRITELONG(PISCSI_CMD_DRVNUM, num);
+    READLONG(PISCSI_CMD_DRVNUM, unit_num);
+
+    KPrintF("Opening device %ld Flags: %ld (%lx)\n", unit_num, flags, flags);
+
+    if (iotd && unit_num < NUM_UNITS) {
+        if (dev_base->units[unit_num].enabled && dev_base->units[unit_num].present) {
+            io_err = 0;
+            iotd->iotd_Req.io_Unit = (struct Unit*)&dev_base->units[unit_num].unit;
+            iotd->iotd_Req.io_Unit->unit_flags = UNITF_ACTIVE;
+            iotd->iotd_Req.io_Unit->unit_OpenCnt = 1;
+        }
+    }
+
+skip:;
+    iotd->iotd_Req.io_Error = io_err;
+
+    return io_err;
+}
+
+uint32_t __UserDevClose(struct IOExtTD *iotd) {
+  return 0;
+}
+
+void exit(int status) { }
+
+int main() {
+    return 0;
+}
+
+ADDTABL_1(__BeginIO,a1);
+void __BeginIO(struct IORequest *io) {
+    if (dev_base == NULL || io == NULL)
+        return;
+    
+    struct piscsi_unit *u;
+    struct Node* node = (struct Node*)io;
+    u = (struct piscsi_unit *)io->io_Unit;
+
+    if (node == NULL || u == NULL)
+        return;
+
+    KPrintF("io_Command = %ld, io_Flags = 0x%lx quick = %lx\n", io->io_Command, io->io_Flags, (io->io_Flags & IOF_QUICK));
+    io->io_Error = piscsi_perform_io(u, io);
+
+    if (!(io->io_Flags & IOF_QUICK)) {
+        ReplyMsg(&io->io_Message);
+    }
+}
+
+ADDTABL_1(__AbortIO,a1);
+void __AbortIO(struct IORequest* io) {
+    KPrintF("AbortIO!\n");
+    if (!io) return;
+    io->io_Error = IOERR_ABORTED;
+}
+
+uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write) {
+    struct IOStdReq *iostd = (struct IOStdReq *)io;
+    struct IOExtTD *iotd = (struct IOExtTD *)io;
+
+    uint8_t* data;
+    uint32_t len, num_blocks;
+    uint32_t block, max_addr;
+    uint8_t sderr;
+
+    data = iotd->iotd_Req.io_Data;
+    len = iotd->iotd_Req.io_Length;
+    //uint32_t offset2 = iostd->io_Offset;
+
+    max_addr = 0xffffffff;
+
+    // well... if we had 64 bits this would make sense
+    if ((offset > max_addr) || (offset+len > max_addr))
+        return IOERR_BADADDRESS;
+    if (data == 0)
+        return IOERR_BADADDRESS;
+    if (len < PISCSI_BLOCK_SIZE) {
+        iostd->io_Actual = 0;
+        return IOERR_BADLENGTH;
+    }
+
+    //block = offset;// >> SD_SECTOR_SHIFT;
+    //num_blocks = len;// >> SD_SECTOR_SHIFT;
+    sderr = 0;
+
+    if (write) {
+        //uint32_t retries = 10;
+        //KPrintF("Write %lx -> %lx %lx\n", (uint32_t)data, offset, len);
+        WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
+        WRITELONG(PISCSI_CMD_ADDR2, len);
+        WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
+        WRITESHORT(PISCSI_CMD_WRITE, 1);
+    } else {
+        //KPrintF("read %lx %lx -> %lx\n", offset, len, (uint32_t)data);
+        WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
+        WRITELONG(PISCSI_CMD_ADDR2, len);
+        WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
+        WRITESHORT(PISCSI_CMD_READ, 1);
+    }
+
+    if (sderr) {
+        iostd->io_Actual = 0;
+
+        if (sderr & SCSIERR_TIMEOUT)
+            return TDERR_DiskChanged;
+        if (sderr & SCSIERR_PARAM)
+            return TDERR_SeekError;
+        if (sderr & SCSIERR_ADDRESS)
+            return TDERR_SeekError;
+        if (sderr & (SCSIERR_ERASESEQ | SCSIERR_ERASERES))
+            return TDERR_BadSecPreamble;
+        if (sderr & SCSIERR_CRC)
+            return TDERR_BadSecSum;
+        if (sderr & SCSIERR_ILLEGAL)
+            return TDERR_TooFewSecs;
+        if (sderr & SCSIERR_IDLE)
+            return TDERR_PostReset;
+
+        return TDERR_SeekError;
+    } else {
+        iostd->io_Actual = len;
+    }
+
+    return 0;
+}
+
+#define PISCSI_ID_STRING "PISTORM Fake SCSI Disk  0.1 1111111111111111"
+
+uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
+{
+    struct IOStdReq *iostd = (struct IOStdReq *)io;
+    struct SCSICmd *scsi = iostd->io_Data;
+    //uint8_t* registers = sdu->sdu_Registers;
+    uint8_t *data = (uint8_t *)scsi->scsi_Data;
+    uint32_t i, block, blocks, maxblocks;
+    uint8_t err = 0;
+
+    KPrintF("SCSI len=%ld, cmd = %02lx %02lx %02lx ... (%ld)\n",
+        iostd->io_Length, scsi->scsi_Command[0],
+        scsi->scsi_Command[1], scsi->scsi_Command[2],
+        scsi->scsi_CmdLength);
+
+    //maxblocks = u->s * u->c * u->h;
+
+    if (scsi->scsi_CmdLength < 6) {
+        //KPrintF("SCSICMD BADLENGTH2");
+        return IOERR_BADLENGTH;
+    }
+
+    if (scsi->scsi_Command == NULL) {
+        //KPrintF("SCSICMD IOERR_BADADDRESS1");
+        return IOERR_BADADDRESS;
+    }
+
+    scsi->scsi_Actual = 0;
+    //iostd->io_Actual = sizeof(*scsi);
+
+    switch (scsi->scsi_Command[0]) {
+        case 0x00:      // TEST_UNIT_READY
+            KPrintF("SCSI command: Test Unit Ready.\n");
+            err = 0;
+            break;
+        
+        case 0x12:      // INQUIRY
+            KPrintF("SCSI command: Inquiry.\n");
+            for (i = 0; i < scsi->scsi_Length; i++) {
+                uint8_t val = 0;
+
+                switch (i) {
+                    case 0: // SCSI device type: direct-access device
+                        val = (0 << 5) | 0;
+                        break;
+                    case 1: // RMB = 1
+                        val = (1 << 7);
+                        break;
+                    case 2: // VERSION = 0
+                        val = 0;
+                        break;
+                    case 3: // NORMACA=0, HISUP = 0, RESPONSE_DATA_FORMAT = 2
+                        val = (0 << 5) | (0 << 4) | 2;
+                        break;
+                    case 4: // ADDITIONAL_LENGTH = 44 - 4
+                        val = 44 - 4;
+                        break;
+                    default:
+                        if (i >= 8 && i < 44)
+                            val = PISCSI_ID_STRING[i - 8];
+                        else
+                            val = 0;
+                        break;
+                }
+                data[i] = val;
+            }
+            scsi->scsi_Actual = i;
+            err = 0;
+            break;
+        
+        case 0x08: // READ (6)
+        case 0x0a: // WRITE (6)
+            block = scsi->scsi_Command[1] & 0x1f;
+            block = (block << 8) | scsi->scsi_Command[2];
+            block = (block << 8) | scsi->scsi_Command[3];
+            blocks = scsi->scsi_Command[4];
+
+            READLONG(PISCSI_CMD_BLOCKS, maxblocks);
+            if (block + blocks > maxblocks) {
+                err = IOERR_BADADDRESS;
+                break;
+            }
+            /*if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
+                err = IOERR_BADLENGTH;
+                break;
+            }*/
+            if (data == NULL) {
+                err = IOERR_BADADDRESS;
+                break;
+            }
+
+            if (scsi->scsi_Command[0] == 0x08) {
+                //KPrintF("scsi_read %lx %lx\n",block,blocks);
+                KPrintF("SCSI read %lx %lx -> %lx\n", block, blocks, (uint32_t)data);
+                WRITELONG(PISCSI_CMD_ADDR2, block);
+                WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
+                WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
+                WRITESHORT(PISCSI_CMD_READ, 1);
+            }
+            else {
+                //KPrintF("scsi_write %lx %lx\n",block,blocks);
+                KPrintF("SCSI write %lx -> %lx %lx\n", (uint32_t)data, block, blocks);
+                WRITELONG(PISCSI_CMD_ADDR2, block);
+                WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
+                WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
+                WRITESHORT(PISCSI_CMD_WRITE, 1);
+            }
+
+            scsi->scsi_Actual = scsi->scsi_Length;
+            err = 0;
+            break;
+        
+        case 0x25: // READ CAPACITY (10)
+            KPrintF("SCSI command: Read Capacity.\n");
+            if (scsi->scsi_CmdLength < 10) {
+                err = HFERR_BadStatus;
+                break;
+            }
+
+            block = *((uint32_t*)&scsi->scsi_Command[2]);
+
+            /*if ((scsi->scsi_Command[8] & 1) || block != 0) {
+                // PMI Not supported
+                KPrintF("PMI not supported.\n");
+                err = HFERR_BadStatus;
+                break;
+            }*/
+
+            if (scsi->scsi_Length < 8) {
+                err = IOERR_BADLENGTH;
+                break;
+            }
+
+            READLONG(PISCSI_CMD_BLOCKS, blocks);
+            ((uint32_t*)data)[0] = blocks - 1;
+            ((uint32_t*)data)[1] = PISCSI_BLOCK_SIZE;
+
+            scsi->scsi_Actual = 8;
+            err = 0;
+
+            break;
+        case 0x1a: // MODE SENSE (6)    
+            KPrintF("SCSI command: Mode Sense.\n");
+            data[0] = 3 + 8 + 0x16;
+            data[1] = 0; // MEDIUM TYPE
+            data[2] = 0;
+            data[3] = 8;
+
+            READLONG(PISCSI_CMD_BLOCKS, maxblocks);
+            (blocks = (maxblocks - 1) & 0xFFFFFF);
+
+            *((uint32_t *)&data[4]) = blocks;
+            *((uint32_t *)&data[8]) = PISCSI_BLOCK_SIZE;
+
+            switch (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]) {
+                case 0x0300: { // Format Device Mode
+                    KPrintF("Grabbing SCSI format device mode data.\n");
+                    uint8_t *datext = data + 12;
+                    datext[0] = 0x03;
+                    datext[1] = 0x16;
+                    datext[2] = 0x00;
+                    datext[3] = 0x01;
+                    *((uint32_t *)&datext[4]) = 0;
+                    *((uint32_t *)&datext[8]) = 0;
+                    *((uint16_t *)&datext[10]) = u->s;
+                    *((uint16_t *)&datext[12]) = PISCSI_BLOCK_SIZE;
+                    datext[14] = 0x00;
+                    datext[15] = 0x01;
+                    *((uint32_t *)&datext[16]) = 0;
+                    datext[20] = 0x80;
+
+                    scsi->scsi_Actual = data[0] + 1;
+                    err = 0;
+                    break;
+                }
+                case 0x0400: // Rigid Drive Geometry
+                    KPrintF("Grabbing SCSI rigid drive geometry.\n");
+                    uint8_t *datext = data + 12;
+                    datext[0] = 0x04;
+                    *((uint32_t *)&datext[1]) = u->c;
+                    datext[1] = 0x16;
+                    datext[5] = u->h;
+                    datext[6] = 0x00;
+                    *((uint32_t *)&datext[6]) = 0;
+                    *((uint32_t *)&datext[10]) = 0;
+                    *((uint32_t *)&datext[13]) = u->c;
+                    datext[17] = 0;
+                    *((uint32_t *)&datext[18]) = 0;
+                    *((uint16_t *)&datext[20]) = 5400;
+
+                    scsi->scsi_Actual = data[0] + 1;
+                    err = 0;
+                    break;
+                
+                default:
+                    KPrintF("[WARN] Unhandled mode sense thing: %lx\n", ((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]);
+                    err = HFERR_BadStatus;
+                    break;
+            }
+            break;
+        
+        case 0x37: // READ DEFECT DATA (10)
+            
+            break;
+
+        default:
+            KPrintF("Unknown/unhandled SCSI command %lx.\n", scsi->scsi_Command[0]);
+            err = HFERR_BadStatus;
+            break;
+    }
+
+    if (err != 0) {
+        KPrintF("Some SCSI error occured: %ld\n", err);
+        scsi->scsi_Actual = 0;
+    }
+
+    return err;
+}
+
+#define DUMMYCMD iostd->io_Actual = 0; break;
+uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io) {
+    struct IOStdReq *iostd = (struct IOStdReq *)io;
+    struct IOExtTD *iotd = (struct IOExtTD *)io;
+
+    uint8_t *data;
+    uint32_t len;
+    uint32_t offset;
+    //struct DriveGeometry *geom;
+    uint8_t err = 0;
+
+    if (!u->enabled) {
+        return IOERR_OPENFAIL;
+    }
+
+    data = iotd->iotd_Req.io_Data;
+    len = iotd->iotd_Req.io_Length;
+
+    if (io->io_Error == IOERR_ABORTED) {
+        return io->io_Error;
+    }
+
+    //KPrintF("cmd: %s\n",cmd_name(io->io_Command));
+    //KPrintF("IO %lx Start, io_Flags = %ld, io_Command = %ld\n", io, io->io_Flags, io->io_Command);
+
+    switch (io->io_Command) {
+        case CMD_CLEAR:
+            /* Invalidate read buffer */
+            DUMMYCMD;
+        case CMD_UPDATE:
+            /* Flush write buffer */
+            DUMMYCMD;
+        case TD_PROTSTATUS:
+            DUMMYCMD;
+        case TD_CHANGENUM:
+            iostd->io_Actual = u->change_num;
+            break;
+        case TD_REMOVE:
+            DUMMYCMD;
+        case TD_CHANGESTATE:
+            DUMMYCMD;
+        case TD_GETDRIVETYPE:
+            iostd->io_Actual = DG_DIRECT_ACCESS;
+            break;
+        case TD_MOTOR:
+            iostd->io_Actual = u->motor;
+            u->motor = iostd->io_Length ? 1 : 0;
+            break;
+
+        case TD_FORMAT:
+            offset = iotd->iotd_Req.io_Offset;
+            //err = 0;
+            err = piscsi_rw(u, io, offset, 1);
+            break;
+        case CMD_WRITE:
+            offset = iotd->iotd_Req.io_Offset;
+            //err = 0;
+            err = piscsi_rw(u, io, offset, 1);
+            break;
+        case CMD_READ:
+            offset = iotd->iotd_Req.io_Offset;
+            //err = 0;
+            err = piscsi_rw(u, io, offset, 0);
+            break;
+        case HD_SCSICMD:
+            //err = 0;
+            err = piscsi_scsi(u, io);
+            break;
+        default: {
+            int cmd = io->io_Command;
+            KPrintF("Unknown IO command: %ld\n", cmd);
+            err = IOERR_NOCMD;
+            break;
+        }
+    }
+
+    return err;
+}
+#undef DUMMYCMD
+
+ADDTABL_END();
diff --git a/platforms/amiga/piscsi/piscsi-enums.h b/platforms/amiga/piscsi/piscsi-enums.h
new file mode 100644 (file)
index 0000000..b56d39c
--- /dev/null
@@ -0,0 +1,33 @@
+#define NUM_UNITS 7
+#define PISCSI_OFFSET  0x80000000
+#define PISCSI_REGSIZE 0x00010000
+#define PISCSI_UPPER   0x80010000
+
+#define SCSIERR_TIMEOUT  (1 << 7)
+#define SCSIERR_PARAM    (1 << 6)
+#define SCSIERR_ADDRESS  (1 << 5)
+#define SCSIERR_ERASESEQ (1 << 4)
+#define SCSIERR_CRC      (1 << 3)
+#define SCSIERR_ILLEGAL  (1 << 2)
+#define SCSIERR_ERASERES (1 << 1)
+#define SCSIERR_IDLE     (1 << 0)
+
+enum piscsi_stuff {
+    PISCSI_BLOCK_SIZE = 512,
+    PISCSI_TRACK_SECTORS = 2048,
+};
+
+enum piscsi_cmds {
+    PISCSI_CMD_WRITE    = 0x00,
+    PISCSI_CMD_READ     = 0x02,
+    PISCSI_CMD_DRVNUM   = 0x04,
+    PISCSI_CMD_DRVTYPE  = 0x06,
+    PISCSI_CMD_BLOCKS   = 0x08,
+    PISCSI_CMD_CYLS     = 0x0A,
+    PISCSI_CMD_HEADS    = 0x0C,
+    PISCSI_CMD_SECS     = 0x0E,
+    PISCSI_CMD_ADDR1    = 0x10,
+    PISCSI_CMD_ADDR2    = 0x14,
+    PISCSI_CMD_ADDR3    = 0x18,
+    PISCSI_CMD_ADDR4    = 0x1C,
+};
\ No newline at end of file
diff --git a/platforms/amiga/piscsi/piscsi.c b/platforms/amiga/piscsi/piscsi.c
new file mode 100644 (file)
index 0000000..52d1fdb
--- /dev/null
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <endian.h>
+#include "piscsi.h"
+#include "piscsi-enums.h"
+#include "../../../config_file/config_file.h"
+#include "../../../gpio/gpio.h"
+
+struct piscsi_dev devs[8];
+uint8_t piscsi_cur_drive = 0;
+uint32_t piscsi_u32[4];
+
+static const char *op_type_names[4] = {
+    "BYTE",
+    "WORD",
+    "LONGWORD",
+    "MEM",
+};
+
+void piscsi_init() {
+    for (int i = 0; i < 8; i++) {
+        devs[i].fd = -1;
+        devs[i].c = devs[i].h = devs[i].s = 0;
+    }
+}
+
+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);
+        return;
+    }
+
+    int32_t tmp_fd = open(filename, O_RDWR);
+    if (tmp_fd == -1) {
+        printf("[PISCSI] Failed to open file %s, could not map drive %d.\n", filename, index);
+        return;
+    }
+
+    struct piscsi_dev *d = &devs[index];
+
+    uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
+    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);
+    printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
+    d->fs = file_size;
+    d->fd = tmp_fd;
+}
+
+void piscsi_unmap_drive(uint8_t index) {
+    if (devs[index].fd != -1) {
+        printf("[PISCSI] Unmapped drive %d.\n", index);
+        close (devs[index].fd);
+        devs[index].fd = -1;
+    }
+}
+
+extern struct emulator_config *cfg;
+
+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) {
+        case PISCSI_CMD_READ:
+            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]);
+            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++) {
+                    read(d->fd, &c, 1);
+#ifndef FAKESTORM
+                    write8(piscsi_u32[2] + i, (uint32_t)c);
+#endif
+                }
+            }
+            break;
+        case PISCSI_CMD_WRITE:
+            if (d->fd == -1) {
+                printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", piscsi_cur_drive);
+                break;
+            }
+            printf("[PISCSI] %d byte WRITE to block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
+            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
+                    c = read8(piscsi_u32[2] + i);
+#endif
+                    write(d->fd, &c, 1);
+                }
+            }
+            break;
+        case PISCSI_CMD_ADDR1:
+            piscsi_u32[0] = val;
+            printf("[PISCSI] Write to ADDR1: %.8x\n", piscsi_u32[0]);
+            break;
+        case PISCSI_CMD_ADDR2:
+            piscsi_u32[1] = val;
+            printf("[PISCSI] Write to ADDR2: %.8x\n", piscsi_u32[1]);
+            break;
+        case PISCSI_CMD_ADDR3:
+            piscsi_u32[2] = val;
+            printf("[PISCSI] Write to ADDR3: %.8x\n", piscsi_u32[2]);
+            break;
+        case PISCSI_CMD_ADDR4:
+            piscsi_u32[3] = val;
+            printf("[PISCSI] Write to ADDR4: %.8x\n", piscsi_u32[3]);
+            break;
+        case PISCSI_CMD_DRVNUM:
+            if (val != 0) {
+                if (val < 10) // Kludge for GiggleDisk
+                    piscsi_cur_drive = val;
+                else if (val >= 10 && val % 10 != 0)
+                    piscsi_cur_drive = 255;
+                else
+                    piscsi_cur_drive = val / 10;
+            }
+            else
+                piscsi_cur_drive = val;
+            printf("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
+            break;
+        default:
+            printf("[PISCSI] Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
+            break;
+    }
+}
+
+uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
+    if (type) {}
+    
+    switch (addr & 0xFFFF) {
+        case PISCSI_CMD_DRVTYPE:
+            if (devs[piscsi_cur_drive].fd == -1) {
+                printf("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
+                return 0;
+            }
+            printf("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
+            return 1;
+            break;
+        case PISCSI_CMD_DRVNUM:
+            return piscsi_cur_drive;
+            break;
+        case PISCSI_CMD_CYLS:
+            printf("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
+            return devs[piscsi_cur_drive].c;
+            break;
+        case PISCSI_CMD_HEADS:
+            printf("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
+            return devs[piscsi_cur_drive].h;
+            break;
+        case PISCSI_CMD_SECS:
+            printf("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
+            return devs[piscsi_cur_drive].s;
+            break;
+        case PISCSI_CMD_BLOCKS: {
+            uint32_t blox = devs[piscsi_cur_drive].fs / 512;
+            printf("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
+            printf("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
+            return blox;
+            break;
+        }
+        default:
+            printf("[PISCSI] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
+            break;
+    }
+
+    return 0;
+}
+
+void piscsi_block_op(uint8_t type, uint8_t num, uint32_t dest, uint32_t len) {
+    if (type || num || dest || len) {}
+}
diff --git a/platforms/amiga/piscsi/piscsi.h b/platforms/amiga/piscsi/piscsi.h
new file mode 100644 (file)
index 0000000..b0148e2
--- /dev/null
@@ -0,0 +1,14 @@
+void piscsi_init();
+void piscsi_map_drive(char *filename, uint8_t index);
+
+void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type);
+uint32_t handle_piscsi_read(uint32_t addr, uint8_t type);
+
+void piscsi_block_op(uint8_t type, uint8_t num, uint32_t dest, uint32_t len);
+
+struct piscsi_dev {
+    uint32_t c;
+    uint16_t h, s;
+    uint64_t fs;
+    int32_t fd;
+};
diff --git a/platforms/amiga/piscsi/piscsi.rom b/platforms/amiga/piscsi/piscsi.rom
new file mode 100644 (file)
index 0000000..8473c03
Binary files /dev/null and b/platforms/amiga/piscsi/piscsi.rom differ
diff --git a/run.sh b/run.sh
deleted file mode 100755 (executable)
index 94250eb..0000000
--- a/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-taskset 0x8 sudo ./emulator