From: beeanyew Date: Wed, 27 Jan 2021 21:13:54 +0000 (+0100) Subject: [WIP] PiSCSI, Pi-NET and some other things X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=142e2eea1be320255b44fb2902eb3297a6def5ae;p=pistorm [WIP] PiSCSI, Pi-NET and some other things --- diff --git a/.gitignore b/.gitignore index 32ea919..aaf0ccc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.img *.hdf *.rom +!/platforms/amiga/piscsi/*.rom /m68kmake /m68kmake.exe /m68kops.c diff --git a/Makefile b/Makefile index b738fa3..21c4427 100644 --- 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 diff --git a/emulator.c b/emulator.c index 75338a4..845a80c 100644 --- a/emulator.c +++ b/emulator.c @@ -23,6 +23,10 @@ #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; diff --git a/platforms/amiga/amiga-platform.c b/platforms/amiga/amiga-platform.c index 264b1d9..c4bcf00 100644 --- a/platforms/amiga/amiga-platform.c +++ b/platforms/amiga/amiga-platform.c @@ -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 index 0000000..302ffc5 --- /dev/null +++ b/platforms/amiga/net/net_driver_amiga/build.sh @@ -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 index 0000000..68923f5 --- /dev/null +++ b/platforms/amiga/net/net_driver_amiga/pi-net-amiga.c @@ -0,0 +1,460 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sana2.h" +#include "../pi-net-enums.h" + +#include +#include +#include + +#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; iios2_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; iios2_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 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 index 0000000..4265a2d --- /dev/null +++ b/platforms/amiga/net/net_driver_amiga/sana2.h @@ -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 +#endif + +#ifndef EXEC_PORTS_H +#include +#endif + +#ifndef EXEC_IO_H +#include +#endif + +#ifndef EXEC_ERRORS_H +#include +#endif + +#ifndef DEVICES_TIMER_H +#include +#endif + +#ifndef UTILITY_TAGITEM_H +#include +#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<) +*/ +#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 +** +** 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 index 0000000..c7ba857 --- /dev/null +++ b/platforms/amiga/net/pi-net-enums.h @@ -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 index 0000000..b206438 --- /dev/null +++ b/platforms/amiga/net/pi-net.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#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 index 0000000..6b101a9 --- /dev/null +++ b/platforms/amiga/net/pi-net.h @@ -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 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 index 0000000..50c70c1 --- /dev/null +++ b/platforms/amiga/piscsi/device_driver_amiga/bootrom.s @@ -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 index 0000000..7e20377 --- /dev/null +++ b/platforms/amiga/piscsi/device_driver_amiga/build.bat @@ -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 index 0000000..9fd02f7 --- /dev/null +++ b/platforms/amiga/piscsi/device_driver_amiga/build.sh @@ -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 index 0000000..4bf7e1e --- /dev/null +++ b/platforms/amiga/piscsi/device_driver_amiga/makerom.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +#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 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 index 0000000..757078a --- /dev/null +++ b/platforms/amiga/piscsi/device_driver_amiga/piscsi-amiga.c @@ -0,0 +1,578 @@ +/* + * Based on: + * Amiga ZZ9000 USB Storage Driver (ZZ9000USBStorage.device) + * Copyright (C) 2016-2020, Lukas F. Hartmann + * Based on code Copyright (C) 2016, Jason S. McMullan + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#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 index 0000000..b56d39c --- /dev/null +++ b/platforms/amiga/piscsi/piscsi-enums.h @@ -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 index 0000000..52d1fdb --- /dev/null +++ b/platforms/amiga/piscsi/piscsi.c @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#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 index 0000000..b0148e2 --- /dev/null +++ b/platforms/amiga/piscsi/piscsi.h @@ -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 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 index 94250eb..0000000 --- a/run.sh +++ /dev/null @@ -1 +0,0 @@ -taskset 0x8 sudo ./emulator