*.img
*.hdf
*.rom
+!/platforms/amiga/piscsi/*.rom
/m68kmake
/m68kmake.exe
/m68kops.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
#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;
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);
}
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); \
} \
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) {
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) {
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;
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; \
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))) {
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)
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;
#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);
#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) {
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);
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) {
--- /dev/null
+m68k-amigaos-gcc -m68020 -O2 -o pi-net.device -ramiga-dev -noixemul -fbaserel pi-net-amiga.c -ldebug -lamiga
--- /dev/null
+#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();
--- /dev/null
+#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 */
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+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);
--- /dev/null
+/* 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 */
--- /dev/null
+vc +aos68k -nostdlib -I$VBCC/targets/m68k-amigaos/include2 -c99 -O2 -o pi-scsi.device piscsi-amiga.c -ldebug -lamiga -cpu=68020
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+/*
+ * 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();
--- /dev/null
+#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
--- /dev/null
+#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) {}
+}
--- /dev/null
+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;
+};
+++ /dev/null
-taskset 0x8 sudo ./emulator