[WIP] PiSCSI, Pi-NET and some other things

This commit is contained in:
beeanyew
2021-01-27 22:13:54 +01:00
parent 40343f9a09
commit 142e2eea1b
23 changed files with 2065 additions and 13 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
*.img
*.hdf
*.rom
!/platforms/amiga/piscsi/*.rom
/m68kmake
/m68kmake.exe
/m68kops.c

View File

@@ -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

View File

@@ -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;

View File

@@ -6,6 +6,10 @@
#include "amiga-autoconf.h"
#include "amiga-registers.h"
#include "../shared/rtc.h"
#include "piscsi/piscsi.h"
#include "piscsi/piscsi-enums.h"
#include "net/pi-net.h"
#include "net/pi-net-enums.h"
#include "rtg/rtg.h"
int handle_register_read_amiga(unsigned int addr, unsigned char type, unsigned int *val);
@@ -36,7 +40,7 @@ extern unsigned char cdtv_sram[32 * SIZE_KILO];
#define min(a, b) (a < b) ? a : b
#define max(a, b) (a > b) ? a : b
static uint8_t rtg_enabled;
static uint8_t rtg_enabled = 0, piscsi_enabled = 0, pinet_enabled = 0;
inline int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type) {
if (!ac_z2_done && addr >= AC_Z2_BASE && addr < AC_Z2_BASE + AC_SIZE) {
@@ -148,6 +152,20 @@ void adjust_ranges_amiga(struct emulator_config *cfg) {
cfg->custom_low = min(cfg->custom_low, PIGFX_RTG_BASE);
cfg->custom_high = max(cfg->custom_high, PIGFX_UPPER);
}
if (piscsi_enabled) {
if (cfg->custom_low == 0)
cfg->custom_low = PISCSI_OFFSET;
else
cfg->custom_low = min(cfg->custom_low, PISCSI_OFFSET);
cfg->custom_high = max(cfg->custom_high, PISCSI_UPPER);
}
if (pinet_enabled) {
if (cfg->custom_low == 0)
cfg->custom_low = PINET_OFFSET;
else
cfg->custom_low = min(cfg->custom_low, PINET_OFFSET);
cfg->custom_high = max(cfg->custom_high, PINET_UPPER);
}
printf("Platform custom range: %.8X-%.8X\n", cfg->custom_low, cfg->custom_high);
printf("Platform mapped range: %.8X-%.8X\n", cfg->mapped_low, cfg->mapped_high);
@@ -295,6 +313,47 @@ void setvar_amiga(struct emulator_config *cfg, char *var, char *val) {
else
printf("[AMIGA} Failed to enable RTG.\n");
}
// PiSCSI stuff
if (strcmp(var, "piscsi") == 0) {
printf("[AMIGA] PISCSI Interface Enabled.\n");
piscsi_enabled = 1;
piscsi_init();
adjust_ranges_amiga(cfg);
}
if (piscsi_enabled) {
if (strcmp(var, "piscsi0") == 0) {
piscsi_map_drive(val, 0);
}
if (strcmp(var, "piscsi1") == 0) {
piscsi_map_drive(val, 1);
}
if (strcmp(var, "piscsi2") == 0) {
piscsi_map_drive(val, 2);
}
if (strcmp(var, "piscsi3") == 0) {
piscsi_map_drive(val, 3);
}
if (strcmp(var, "piscsi4") == 0) {
piscsi_map_drive(val, 4);
}
if (strcmp(var, "piscsi5") == 0) {
piscsi_map_drive(val, 5);
}
if (strcmp(var, "piscsi6") == 0) {
piscsi_map_drive(val, 6);
}
}
// Pi-Net stuff
if (strcmp(var, "pi-net") == 0) {
printf("[AMIGA] PI-NET Interface Enabled.\n");
pinet_enabled = 1;
pinet_init(val);
adjust_ranges_amiga(cfg);
}
// RTC stuff
if (strcmp(var, "rtc_type") == 0) {
if (val && strlen(val) != 0) {
if (strcmp(val, "msm") == 0) {

View File

@@ -0,0 +1 @@
m68k-amigaos-gcc -m68020 -O2 -o pi-net.device -ramiga-dev -noixemul -fbaserel pi-net-amiga.c -ldebug -lamiga

View File

@@ -0,0 +1,460 @@
#include <exec/resident.h>
#include <exec/memory.h>
#include <exec/alerts.h>
#include <exec/io.h>
#include <exec/execbase.h>
#include <libraries/expansion.h>
#include <dos/filehandler.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/dos.h>
#include <proto/expansion.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <exec/lists.h>
#include <exec/errors.h>
#include <exec/interrupts.h>
#include <exec/tasks.h>
#include <hardware/intbits.h>
#include <string.h>
#include "sana2.h"
#include "../pi-net-enums.h"
#include <clib/debug_protos.h>
#include <stdint.h>
#include <stdlib.h>
#define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PINET_OFFSET + cmd)) = val;
#define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PINET_OFFSET + cmd)) = val;
#define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PINET_OFFSET + cmd)) = val;
#define READBYTE(cmd, var) var = *(volatile unsigned char *)(PINET_OFFSET + cmd);
#define READSHORT(cmd, var) var = *(volatile unsigned short *)(PINET_OFFSET + cmd);
#define READLONG(cmd, var) var = *(volatile unsigned long *)(PINET_OFFSET + cmd);
//typedef BOOL (*BMFunc)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
typedef struct BufferManagement
{
struct MinNode bm_Node;
BOOL (*bm_CopyFromBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
BOOL (*bm_CopyToBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
} BufferManagement;
#pragma pack(4)
struct pinet_base {
struct Device* pi_dev;
struct Unit unit;
uint8_t MAC[6];
uint8_t IP[4];
struct List read_list;
struct SignalSemaphore read_list_sem;
};
struct ExecBase* SysBase = NULL;
const char DevName[] = "pi-net.device";
const char DevIdString[] = "Pi-NET 0.1";
const UWORD DevVersion = 1;
const UWORD DevRevision = 0;
#include "stabs.h"
struct pinet_base *dev_base = NULL;
struct WBStartup *_WBenchMsg = NULL;
//#define exit(...)
//#define debug(...)
//#define KPrintF(...)
uint32_t __UserDevInit(struct Device* dev) {
uint8_t *p;
uint32_t i;
int32_t ok;
SysBase = *(struct ExecBase **)4L;
KPrintF("Initializing net device.\n");
dev_base = AllocMem(sizeof(struct pinet_base), MEMF_PUBLIC | MEMF_CLEAR);
dev_base->pi_dev = dev;
KPrintF("Grabbing MAC.\n");
for (int i = 0; i < 6; i++) {
READBYTE((PINET_CMD_MAC + i), dev_base->MAC[i]);
}
KPrintF("Grabbing IP.\n");
for (int i = 0; i < 4; i++) {
READBYTE((PINET_CMD_IP + i), dev_base->IP[i]);
}
return (uint32_t)dev;
}
uint32_t __UserDevCleanup(void) {
KPrintF("Cleaning up.\n");
FreeMem(dev_base, sizeof(struct pinet_base));
return 0;
}
uint32_t __UserDevOpen(struct IORequest *io, uint32_t num, uint32_t flags) {
struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
uint32_t ok = 0, ret = IOERR_OPENFAIL;
struct BufferManagement *bm;
KPrintF("Opening net device %ld.\n", num);
dev_base->unit.unit_OpenCnt++;
if (num == 0 && dev_base->unit.unit_OpenCnt == 1) {
//KPrintF("Trying to alloc buffer management.\n");
//if ((bm = (struct BufferManagement*)AllocVec(sizeof(struct BufferManagement), MEMF_CLEAR | MEMF_PUBLIC))) {
//KPrintF("Setting up buffer copy funcs (1).\n");
//bm->bm_CopyToBuffer = (BOOL *)GetTagData(S2_CopyToBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
//KPrintF("Setting up buffer copy funcs (2).\n");
//bm->bm_CopyFromBuffer = (BOOL *)GetTagData(S2_CopyFromBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
KPrintF("Doing more things.\n");
ioreq->ios2_BufferManagement = NULL;//(VOID *)bm;
ioreq->ios2_Req.io_Error = 0;
ioreq->ios2_Req.io_Unit = (struct Unit *)&dev_base->unit;
ioreq->ios2_Req.io_Device = (struct Device *)dev_base->pi_dev;
KPrintF("New list.\n");
NewList(&dev_base->read_list);
InitSemaphore(&dev_base->read_list_sem);
ret = 0;
ok = 1;
//}
}
if (ret == IOERR_OPENFAIL) {
KPrintF("Failed to open device. Already open?\n");
}
else {
KPrintF("Device opened, yay.\n");
}
ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
KPrintF("Opened device, return code: %ld\n", ret);
return ret;
}
uint32_t __UserDevClose(struct IORequest *io) {
return 0;
}
uint32_t pinet_read_frame(struct IOSana2Req *ioreq) {
uint32_t datasize;
uint8_t *frame_ptr;
uint8_t broadcast;
uint32_t err = 0;
struct BufferManagement *bm;
/*uint8_t* frm = (uint8_t *)(PINET_OFFSET + PINET_CMD_FRAME);
uint32_t sz = ((uint32_t)frm[0] << 8) | ((uint32_t)frm[1]);
uint32_t ser = ((uint32_t)frm[2] << 8) | ((uint32_t)frm[3]);
uint16_t tp = ((uint16_t)frm[16] << 8) | ((uint16_t)frm[17]);
if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
frame_ptr = frm + 4;
datasize = sz;
req->ios2_Req.io_Flags = SANA2IOF_RAW;
}
else {
frame_ptr = frm + 4 + ETH_HDR_SIZE;
datasize = sz - ETH_HDR_SIZE;
req->ios2_Req.io_Flags = 0;
}
req->ios2_DataLength = datasize;
//D(("datasize: %lx\n",datasize));
//D(("frame_ptr: %lx\n",frame_ptr));
//D(("ios2_Data: %lx\n",req->ios2_Data));
//D(("bufmgmt: %lx\n",req->ios2_BufferManagement));
// copy frame to device user (probably tcp/ip system)
bm = (struct BufferManagement *)req->ios2_BufferManagement;
if (!(*bm->bm_CopyToBuffer)(req->ios2_Data, frame_ptr, datasize)) {
//D(("rx copybuf error\n"));
req->ios2_Req.io_Error = S2ERR_SOFTWARE;
req->ios2_WireError = S2WERR_BUFF_ERROR;
err = 1;
}
else {
req->ios2_Req.io_Error = req->ios2_WireError = 0;
err = 0;
}
memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
//D(("RXSZ %ld\n",(LONG)sz));
//D(("RXPT %ld\n",(LONG)tp));
//D(("RXSER %ld\n",(LONG)ser));
//D(("RXDST %lx...\n",*((ULONG*)(req->ios2_DstAddr))));
//D(("RXSRC %lx\n",*((ULONG*)(req->ios2_SrcAddr))));
//D(("RXSRC %lx\n",*((ULONG*)(frame_ptr))));
broadcast = TRUE;
for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
if (frame[i+4] != 0xff) {
broadcast = FALSE;
break;
}
}
if (broadcast) {
req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
}
req->ios2_PacketType = tp;*/
return err;
}
void pinet_write_frame(struct IOSana2Req *ioreq) {
}
void exit(int status) { }
ADDTABL_1(__BeginIO,a1);
void __BeginIO(struct IORequest *io) {
struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
ULONG unit = (ULONG)ioreq->ios2_Req.io_Unit;
int mtu;
ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
ioreq->ios2_Req.io_Error = S2ERR_NO_ERROR;
ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
//D(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));
switch( ioreq->ios2_Req.io_Command ) {
case CMD_READ:
KPrintF("Read\n");
if (pinet_read_frame(ioreq) != 0) {
ioreq->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
}
ioreq = NULL;
break;
case S2_BROADCAST:
KPrintF("Broadcast\n");
if (ioreq->ios2_DstAddr) {
for (int i = 0; i < ADDRFIELDSIZE; i++) {
ioreq->ios2_DstAddr[i] = 0xFF;
}
} else {
KPrintF("Invalid ios2_DstAddr\n");
}
/* Fallthrough */
case CMD_WRITE: {
KPrintF("Write\n");
pinet_write_frame(ioreq);
break;
}
case S2_READORPHAN:
ioreq->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
ioreq = NULL;
break;
case S2_ONLINE:
case S2_OFFLINE:
case S2_CONFIGINTERFACE: /* forward request */
break;
case S2_GETSTATIONADDRESS:
for (int i = 0; i < ADDRFIELDSIZE; i++) {
ioreq->ios2_SrcAddr[i] = dev_base->MAC[i];
ioreq->ios2_DstAddr[i] = dev_base->MAC[i];
}
break;
case S2_DEVICEQUERY: {
struct Sana2DeviceQuery *devquery;
devquery = ioreq->ios2_StatData;
devquery->DevQueryFormat = 0;
devquery->DeviceLevel = 0;
if (devquery->SizeAvailable >= 18)
devquery->AddrFieldSize = ADDRFIELDSIZE * 8;
if (devquery->SizeAvailable >= 22)
devquery->MTU = 1500;
if (devquery->SizeAvailable >= 26)
devquery->BPS = 1000 * 1000 * 100;
if (devquery->SizeAvailable >= 30)
devquery->HardwareType = S2WireType_Ethernet;
devquery->SizeSupplied = (devquery->SizeAvailable < 30) ? devquery->SizeAvailable : 30;
break;
}
case S2_GETSPECIALSTATS: {
struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ioreq->ios2_StatData;
s2ssh->RecordCountSupplied = 0;
break;
}
default: {
uint8_t cmd = ioreq->ios2_Req.io_Command;
KPrintF("Unknown/unhandled IO command %lx\n", cmd);
ioreq->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
break;
}
}
if (ioreq) {
if (!(ioreq->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
ReplyMsg((struct Message *)ioreq);
} else {
ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
}
}
}
ADDTABL_1(__AbortIO,a1);
void __AbortIO(struct IORequest* ioreq) {
struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
if (!ioreq) return;
ioreq->io_Error = IOERR_ABORTED;
ios2->ios2_WireError = 0;
}
ADDTABL_1(__TermIO,a1);
void __TermIO(struct IORequest *ioreq) {
struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
if (!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
ReplyMsg((struct Message *)ioreq);
} else {
ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
}
}
/*ULONG get_frame_serial(UBYTE* frame) {
UBYTE* frm = (UBYTE*)frame;
ULONG ser = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
return ser;
}
ULONG read_frame(struct IOSana2Req *req, volatile UBYTE *frame)
{
ULONG datasize;
BYTE *frame_ptr;
BOOL broadcast;
ULONG err = 0;
struct BufferManagement *bm;
UBYTE* frm = (UBYTE*)frame;
ULONG sz = ((ULONG)frm[0]<<8)|((ULONG)frm[1]);
ULONG ser = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
USHORT tp = ((USHORT)frm[16]<<8)|((USHORT)frm[17]);
if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
frame_ptr = frm+4;
datasize = sz;
req->ios2_Req.io_Flags = SANA2IOF_RAW;
}
else {
frame_ptr = frm+4+HW_ETH_HDR_SIZE;
datasize = sz-HW_ETH_HDR_SIZE;
req->ios2_Req.io_Flags = 0;
}
req->ios2_DataLength = datasize;
//D(("datasize: %lx\n",datasize));
//D(("frame_ptr: %lx\n",frame_ptr));
//D(("ios2_Data: %lx\n",req->ios2_Data));
//D(("bufmgmt: %lx\n",req->ios2_BufferManagement));
// copy frame to device user (probably tcp/ip system)
bm = (struct BufferManagement *)req->ios2_BufferManagement;
if (!(*bm->bm_CopyToBuffer)(req->ios2_Data, frame_ptr, datasize)) {
//D(("rx copybuf error\n"));
req->ios2_Req.io_Error = S2ERR_SOFTWARE;
req->ios2_WireError = S2WERR_BUFF_ERROR;
err = 1;
}
else {
req->ios2_Req.io_Error = req->ios2_WireError = 0;
err = 0;
}
memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
//D(("RXSZ %ld\n",(LONG)sz));
//D(("RXPT %ld\n",(LONG)tp));
//D(("RXSER %ld\n",(LONG)ser));
//D(("RXDST %lx...\n",*((ULONG*)(req->ios2_DstAddr))));
//D(("RXSRC %lx\n",*((ULONG*)(req->ios2_SrcAddr))));
//D(("RXSRC %lx\n",*((ULONG*)(frame_ptr))));
broadcast = TRUE;
for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
if (frame[i+4] != 0xff) {
broadcast = FALSE;
break;
}
}
if (broadcast) {
req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
}
req->ios2_PacketType = tp;
return err;
}
ULONG write_frame(struct IOSana2Req *req, UBYTE *frame)
{
ULONG rc=0;
struct BufferManagement *bm;
USHORT sz=0;
if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
sz = req->ios2_DataLength;
} else {
sz = req->ios2_DataLength + HW_ETH_HDR_SIZE;
*((USHORT*)(frame+6+6)) = (USHORT)req->ios2_PacketType;
memcpy(frame, req->ios2_DstAddr, HW_ADDRFIELDSIZE);
memcpy(frame+6, HW_MAC, HW_ADDRFIELDSIZE);
frame+=HW_ETH_HDR_SIZE;
}
if (sz>0) {
bm = (struct BufferManagement *)req->ios2_BufferManagement;
if (!(*bm->bm_CopyFromBuffer)(frame, req->ios2_Data, req->ios2_DataLength)) {
rc = 1; // FIXME error code
//D(("tx copybuf err\n"));
}
else {
// buffer was copied to zz9000, send it
volatile USHORT* reg = (volatile USHORT*)(ZZ9K_REGS+0x80); // FIXME send_frame reg
*reg = sz;
// get feedback
rc = *reg;
if (rc!=0) {
D(("tx err: %d\n",rc));
}
}
}
return rc;
}*/
ADDTABL_END();

Binary file not shown.

View File

@@ -0,0 +1,261 @@
#ifndef SANA2_SANA2DEVICE_H
#define SANA2_SANA2DEVICE_H 1
/*
** $Filename: devices/sana2.h $
** $Revision: 4.1 $
** $Date: 1994/10/03 20:55:10 $
**
** Structure definitions for SANA-II devices.
**
** (C) Copyright 1991 Commodore-Amiga Inc.
** All Rights Reserved
*/
#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif
#ifndef EXEC_IO_H
#include <exec/io.h>
#endif
#ifndef EXEC_ERRORS_H
#include <exec/errors.h>
#endif
#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif
#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif
#define SANA2_MAX_ADDR_BITS (128)
#define SANA2_MAX_ADDR_BYTES ((SANA2_MAX_ADDR_BITS+7)/8)
struct IOSana2Req
{
struct IORequest ios2_Req;
ULONG ios2_WireError; /* wire type specific error */
ULONG ios2_PacketType; /* packet type */
UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES]; /* source addr */
UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES]; /* dest address */
ULONG ios2_DataLength; /* length of packet data */
VOID *ios2_Data; /* packet data */
VOID *ios2_StatData; /* statistics data pointer */
VOID *ios2_BufferManagement; /* see SANA-II OpenDevice adoc */
};
/*
** defines for the io_Flags field
*/
#define SANA2IOB_RAW (7) /* raw packet IO requested */
#define SANA2IOF_RAW (1<<SANA2IOB_RAW)
#define SANA2IOB_BCAST (6) /* broadcast packet (received) */
#define SANA2IOF_BCAST (1<<SANA2IOB_BCAST)
#define SANA2IOB_MCAST (5) /* multicast packet (received) */
#define SANA2IOF_MCAST (1<<SANA2IOB_MCAST)
#define SANA2IOB_QUICK (IOB_QUICK) /* quick IO requested (0) */
#define SANA2IOF_QUICK (IOF_QUICK)
/*
** defines for OpenDevice() flags
*/
#define SANA2OPB_MINE (0) /* exclusive access requested */
#define SANA2OPF_MINE (1<<SANA2OPB_MINE)
#define SANA2OPB_PROM (1) /* promiscuous mode requested */
#define SANA2OPF_PROM (1<<SANA2OPB_PROM)
/*
** defines for OpenDevice() tags
*/
#define S2_Dummy (TAG_USER + 0xB0000)
#define S2_CopyToBuff (S2_Dummy + 1)
#define S2_CopyFromBuff (S2_Dummy + 2)
#define S2_PacketFilter (S2_Dummy + 3)
struct Sana2DeviceQuery
{
/*
** Standard information
*/
ULONG SizeAvailable; /* bytes available */
ULONG SizeSupplied; /* bytes supplied */
ULONG DevQueryFormat; /* this is type 0 */
ULONG DeviceLevel; /* this document is level 0 */
/*
** Common information
*/
UWORD AddrFieldSize; /* address size in bits */
ULONG MTU; /* maximum packet data size */
ULONG BPS; /* line rate (bits/sec) */
ULONG HardwareType; /* what the wire is */
/*
** Format specific information
*/
};
/*
** defined Hardware types
**
** If your hardware type isn't listed below contact CATS to get a new
** type number added for your hardware.
*/
#define S2WireType_Ethernet 1
#define S2WireType_IEEE802 6
#define S2WireType_Arcnet 7
#define S2WireType_LocalTalk 11
#define S2WireType_DyLAN 12
#define S2WireType_AmokNet 200 /* Amiga Floppy Port hardware */
#define S2WireType_Liana 202 /* Villate Tronic parallel port hw */
#define S2WireType_PPP 253
#define S2WireType_SLIP 254
#define S2WireType_CSLIP 255 /* Compressed SLIP */
#define S2WireType_PLIP 420 /* SLIP over a parallel port */
struct Sana2PacketTypeStats
{
ULONG PacketsSent; /* transmitted count */
ULONG PacketsReceived; /* received count */
ULONG BytesSent; /* bytes transmitted count */
ULONG BytesReceived; /* bytes received count */
ULONG PacketsDropped; /* packets dropped count */
};
struct Sana2SpecialStatRecord
{
ULONG Type; /* statistic identifier */
ULONG Count; /* the statistic */
char *String; /* statistic name */
};
struct Sana2SpecialStatHeader
{
ULONG RecordCountMax; /* room available */
ULONG RecordCountSupplied; /* number supplied */
/* struct Sana2SpecialStatRecord[RecordCountMax]; */
};
struct Sana2DeviceStats
{
ULONG PacketsReceived; /* received count */
ULONG PacketsSent; /* transmitted count */
ULONG BadData; /* bad packets received */
ULONG Overruns; /* hardware miss count */
ULONG Unused; /* Unused field */
ULONG UnknownTypesReceived; /* orphan count */
ULONG Reconfigurations; /* network reconfigurations */
struct timeval LastStart; /* time of last online */
};
/*
** Device Commands
*/
#define S2_START (CMD_NONSTD)
#define S2_DEVICEQUERY (S2_START+ 0)
#define S2_GETSTATIONADDRESS (S2_START+ 1)
#define S2_CONFIGINTERFACE (S2_START+ 2)
#define S2_ADDMULTICASTADDRESS (S2_START+ 5)
#define S2_DELMULTICASTADDRESS (S2_START+ 6)
#define S2_MULTICAST (S2_START+ 7)
#define S2_BROADCAST (S2_START+ 8)
#define S2_TRACKTYPE (S2_START+ 9)
#define S2_UNTRACKTYPE (S2_START+10)
#define S2_GETTYPESTATS (S2_START+11)
#define S2_GETSPECIALSTATS (S2_START+12)
#define S2_GETGLOBALSTATS (S2_START+13)
#define S2_ONEVENT (S2_START+14)
#define S2_READORPHAN (S2_START+15)
#define S2_ONLINE (S2_START+16)
#define S2_OFFLINE (S2_START+17)
#define S2_END (S2_START+18)
/*
** defined errors for io_Error (see also <exec/errors.h>)
*/
#define S2ERR_NO_ERROR 0 /* peachy-keen */
#define S2ERR_NO_RESOURCES 1 /* resource allocation failure */
#define S2ERR_BAD_ARGUMENT 3 /* garbage somewhere */
#define S2ERR_BAD_STATE 4 /* inappropriate state */
#define S2ERR_BAD_ADDRESS 5 /* who? */
#define S2ERR_MTU_EXCEEDED 6 /* too much to chew */
#define S2ERR_NOT_SUPPORTED 8 /* hardware can't support cmd */
#define S2ERR_SOFTWARE 9 /* software error detected */
#define S2ERR_OUTOFSERVICE 10 /* driver is OFFLINE */
#define S2ERR_TX_FAILURE 11 /* Transmission attempt failed */
/*
** From <exec/errors.h>
**
** IOERR_OPENFAIL (-1) * device/unit failed to open *
** IOERR_ABORTED (-2) * request terminated early [after AbortIO()] *
** IOERR_NOCMD (-3) * command not supported by device *
** IOERR_BADLENGTH (-4) * not a valid length (usually IO_LENGTH) *
** IOERR_BADADDRESS (-5) * invalid address (misaligned or bad range) *
** IOERR_UNITBUSY (-6) * device opens ok, but requested unit is busy *
** IOERR_SELFTEST (-7) * hardware failed self-test *
*/
/*
** defined errors for ios2_WireError
*/
#define S2WERR_GENERIC_ERROR 0 /* no specific info available */
#define S2WERR_NOT_CONFIGURED 1 /* unit not configured */
#define S2WERR_UNIT_ONLINE 2 /* unit is currently online */
#define S2WERR_UNIT_OFFLINE 3 /* unit is currently offline */
#define S2WERR_ALREADY_TRACKED 4 /* protocol already tracked */
#define S2WERR_NOT_TRACKED 5 /* protocol not tracked */
#define S2WERR_BUFF_ERROR 6 /* buff mgt func returned error */
#define S2WERR_SRC_ADDRESS 7 /* source address problem */
#define S2WERR_DST_ADDRESS 8 /* destination address problem */
#define S2WERR_BAD_BROADCAST 9 /* broadcast address problem */
#define S2WERR_BAD_MULTICAST 10 /* multicast address problem */
#define S2WERR_MULTICAST_FULL 11 /* multicast address list full */
#define S2WERR_BAD_EVENT 12 /* unsupported event class */
#define S2WERR_BAD_STATDATA 13 /* statdata failed sanity check */
#define S2WERR_IS_CONFIGURED 15 /* attempt to config twice */
#define S2WERR_NULL_POINTER 16 /* null pointer detected */
#define S2WERR_TOO_MANY_RETIRES 17 /* tx failed - too many retries */
#define S2WERR_RCVREL_HDW_ERR 18 /* Driver fixable HW error */
/*
** defined events
*/
#define S2EVENT_ERROR (1L<<0) /* error catch all */
#define S2EVENT_TX (1L<<1) /* transmitter error catch all */
#define S2EVENT_RX (1L<<2) /* receiver error catch all */
#define S2EVENT_ONLINE (1L<<3) /* unit is in service */
#define S2EVENT_OFFLINE (1L<<4) /* unit is not in service */
#define S2EVENT_BUFF (1L<<5) /* buff mgt function error */
#define S2EVENT_HARDWARE (1L<<6) /* hardware error catch all */
#define S2EVENT_SOFTWARE (1L<<7) /* software error catch all */
#endif /* SANA2_SANA2DEVICE_H */

View File

@@ -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,
};

View File

@@ -0,0 +1,77 @@
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <endian.h>
#include "pi-net.h"
#include "pi-net-enums.h"
#include "../../../config_file/config_file.h"
#include "../../../gpio/gpio.h"
uint32_t pinet_u32[4];
static const char *op_type_names[4] = {
"BYTE",
"WORD",
"LONGWORD",
"MEM",
};
void pinet_init(char *dev) {
// Initialize them nets.
}
uint8_t PI_MAC[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t PI_IP[4] = { 192, 168, 1, 9 };
void handle_pinet_write(uint32_t addr, uint32_t val, uint8_t type) {
int32_t r;
switch (addr & 0xFFFF) {
case PINET_CMD_READ:
printf("[PI-NET] Read.\n");
break;
case PINET_CMD_WRITE:
printf("[PI-NET] Write.\n");
break;
case PINET_CMD_ADDR1:
pinet_u32[0] = val;
printf("[PI-NET] Write to ADDR1: %.8x\n", pinet_u32[0]);
break;
case PINET_CMD_ADDR2:
pinet_u32[1] = val;
printf("[PI-NET] Write to ADDR2: %.8x\n", pinet_u32[1]);
break;
case PINET_CMD_ADDR3:
pinet_u32[2] = val;
printf("[PI-NET] Write to ADDR3: %.8x\n", pinet_u32[2]);
break;
case PINET_CMD_ADDR4:
pinet_u32[3] = val;
printf("[PI-NET] Write to ADDR4: %.8x\n", pinet_u32[3]);
break;
default:
printf("[PI-NET] Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
break;
}
}
uint32_t handle_pinet_read(uint32_t addr_, uint8_t type) {
uint32_t addr = addr_ & 0xFFFF;
if (addr >= PINET_CMD_MAC && addr < PINET_CMD_IP) {
printf("[PI-NET] Read from MAC: %.2X. (%.8X)\n", PI_MAC[addr - PINET_CMD_MAC], addr_);
return PI_MAC[addr - PINET_CMD_MAC];
}
if (addr >= PINET_CMD_IP && addr < PINET_CMD_BEEF) {
printf("[PI-NET] Read from IP: %.2X. (%.8X)\n", PI_IP[addr - PINET_CMD_IP], addr_);
return PI_IP[addr - PINET_CMD_IP];
}
switch (addr & 0xFFFF) {
default:
printf("[PI-NET] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
break;
}
return 0;
}

View File

@@ -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);

Binary file not shown.

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,62 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#define BOOTLDR_SIZE 0x400
char *rombuf, *zerobuf, *devicebuf;
int main(int argc, char *argv[]) {
FILE *rom = fopen("bootrom", "rb");
if (!rom) {
printf("Could not open file bootrom for reading.\n");
return 1;
}
FILE *out = fopen("../piscsi.rom", "wb+");
if (!out) {
printf("Could not open file piscsi.rom for writing.\n");
fclose(rom);
return 1;
}
FILE *device = fopen("pi-scsi.device", "rb");
if (!device) {
printf("Could not open file pi-scsi.device for reading.\n");
fclose(rom);
fclose(out);
return 1;
}
fseek(device, 0, SEEK_END);
fseek(rom, 0, SEEK_END);
uint32_t rom_size = ftell(rom);
uint32_t device_size = ftell(device);
fseek(rom, 0, SEEK_SET);
fseek(device, 0, SEEK_SET);
uint32_t pad_size = BOOTLDR_SIZE - rom_size;
rombuf = malloc(rom_size);
devicebuf = malloc(device_size);
zerobuf = malloc(pad_size);
memset(zerobuf, 0x00, pad_size);
fread(rombuf, rom_size, 1, rom);
fread(devicebuf, device_size, 1, device);
fwrite(rombuf, rom_size, 1, out);
fwrite(zerobuf, pad_size, 1, out);
fwrite(devicebuf, device_size, 1, out);
printf("piscsi.rom successfully created.\n");
free(rombuf);
free(zerobuf);
free(devicebuf);
fclose(out);
fclose(device);
fclose(rom);
return 0;
}

View File

@@ -0,0 +1,578 @@
/*
* Based on:
* Amiga ZZ9000 USB Storage Driver (ZZ9000USBStorage.device)
* Copyright (C) 2016-2020, Lukas F. Hartmann <lukas@mntre.com>
* Based on code Copyright (C) 2016, Jason S. McMullan <jason.mcmullan@gmail.com>
* All rights reserved.
*
* Licensed under the MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <exec/resident.h>
#include <exec/errors.h>
#include <exec/memory.h>
#include <exec/lists.h>
#include <exec/alerts.h>
#include <exec/tasks.h>
#include <exec/io.h>
#include <exec/execbase.h>
#include <libraries/expansion.h>
#include <devices/trackdisk.h>
#include <devices/timer.h>
#include <devices/scsidisk.h>
#include <dos/filehandler.h>
#include <proto/exec.h>
#include <proto/disk.h>
#include <proto/expansion.h>
#include <clib/debug_protos.h>
#include <stdint.h>
#include <stdlib.h>
#include "../piscsi-enums.h"
#define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
#define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
#define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
#define READSHORT(cmd, var) var = *(volatile unsigned short *)(PISCSI_OFFSET + cmd);
#define READLONG(cmd, var) var = *(volatile unsigned long *)(PISCSI_OFFSET + cmd);
#pragma pack(4)
struct piscsi_base {
struct Device* pi_dev;
struct piscsi_unit {
struct Unit unit;
uint32_t regs_ptr;
uint8_t enabled;
uint8_t present;
uint8_t valid;
uint8_t read_only;
uint8_t motor;
uint8_t unit_num;
uint16_t h, s;
uint32_t c;
uint32_t change_num;
} units[NUM_UNITS];
};
struct ExecBase* SysBase = NULL;
const char DevName[] = "pi-scsi.device";
const char DevIdString[] = "Pi-SCSI 0.1";
const UWORD DevVersion = 1;
const UWORD DevRevision = 0;
#include "stabs.h"
struct piscsi_base *dev_base = NULL;
struct WBStartup *_WBenchMsg = NULL;
//#define exit(...)
//#define debug(...)
#define KPrintF(...)
//#define bug(x,args...) KPrintF(x ,##args);
//#define debug(x,args...) bug("%s:%ld " x "\n", __func__, (unsigned long)__LINE__ ,##args)
uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io);
uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write);
uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io);
extern void* DOSBase[2];
uint32_t __UserDevInit(struct Device* dev) {
//uint8_t* registers = NULL;
SysBase = *(struct ExecBase **)4L;
KPrintF("Initializing devices.\n");
dev_base = AllocMem(sizeof(struct piscsi_base), MEMF_PUBLIC | MEMF_CLEAR);
dev_base->pi_dev = dev;
for (int i = 0; i < NUM_UNITS; i++) {
uint16_t r = 0;
WRITESHORT(PISCSI_CMD_DRVNUM, i);
dev_base->units[i].regs_ptr = PISCSI_OFFSET;
READSHORT(PISCSI_CMD_DRVTYPE, r);
dev_base->units[i].enabled = r;
dev_base->units[i].present = r;
dev_base->units[i].valid = r;
dev_base->units[i].unit_num = i;
if (dev_base->units[i].present) {
READLONG(PISCSI_CMD_CYLS, dev_base->units[i].c);
READSHORT(PISCSI_CMD_HEADS, dev_base->units[i].h);
READSHORT(PISCSI_CMD_SECS, dev_base->units[i].s);
KPrintF("C/H/S: %ld / %ld / %ld\n", dev_base->units[i].c, dev_base->units[i].h, dev_base->units[i].s);
}
dev_base->units[i].change_num++;
// Send any reset signal to the "SCSI" device here.
}
return 1;
}
uint32_t __UserDevCleanup(void) {
KPrintF("Cleaning up.\n");
FreeMem(dev_base, sizeof(struct piscsi_base));
return 0;
}
uint32_t __UserDevOpen(struct IOExtTD *iotd, uint32_t num, uint32_t flags) {
struct Node* node = (struct Node*)iotd;
int io_err = IOERR_OPENFAIL;
int unit_num = 0;
WRITELONG(PISCSI_CMD_DRVNUM, num);
READLONG(PISCSI_CMD_DRVNUM, unit_num);
KPrintF("Opening device %ld Flags: %ld (%lx)\n", unit_num, flags, flags);
if (iotd && unit_num < NUM_UNITS) {
if (dev_base->units[unit_num].enabled && dev_base->units[unit_num].present) {
io_err = 0;
iotd->iotd_Req.io_Unit = (struct Unit*)&dev_base->units[unit_num].unit;
iotd->iotd_Req.io_Unit->unit_flags = UNITF_ACTIVE;
iotd->iotd_Req.io_Unit->unit_OpenCnt = 1;
}
}
skip:;
iotd->iotd_Req.io_Error = io_err;
return io_err;
}
uint32_t __UserDevClose(struct IOExtTD *iotd) {
return 0;
}
void exit(int status) { }
int main() {
return 0;
}
ADDTABL_1(__BeginIO,a1);
void __BeginIO(struct IORequest *io) {
if (dev_base == NULL || io == NULL)
return;
struct piscsi_unit *u;
struct Node* node = (struct Node*)io;
u = (struct piscsi_unit *)io->io_Unit;
if (node == NULL || u == NULL)
return;
KPrintF("io_Command = %ld, io_Flags = 0x%lx quick = %lx\n", io->io_Command, io->io_Flags, (io->io_Flags & IOF_QUICK));
io->io_Error = piscsi_perform_io(u, io);
if (!(io->io_Flags & IOF_QUICK)) {
ReplyMsg(&io->io_Message);
}
}
ADDTABL_1(__AbortIO,a1);
void __AbortIO(struct IORequest* io) {
KPrintF("AbortIO!\n");
if (!io) return;
io->io_Error = IOERR_ABORTED;
}
uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write) {
struct IOStdReq *iostd = (struct IOStdReq *)io;
struct IOExtTD *iotd = (struct IOExtTD *)io;
uint8_t* data;
uint32_t len, num_blocks;
uint32_t block, max_addr;
uint8_t sderr;
data = iotd->iotd_Req.io_Data;
len = iotd->iotd_Req.io_Length;
//uint32_t offset2 = iostd->io_Offset;
max_addr = 0xffffffff;
// well... if we had 64 bits this would make sense
if ((offset > max_addr) || (offset+len > max_addr))
return IOERR_BADADDRESS;
if (data == 0)
return IOERR_BADADDRESS;
if (len < PISCSI_BLOCK_SIZE) {
iostd->io_Actual = 0;
return IOERR_BADLENGTH;
}
//block = offset;// >> SD_SECTOR_SHIFT;
//num_blocks = len;// >> SD_SECTOR_SHIFT;
sderr = 0;
if (write) {
//uint32_t retries = 10;
//KPrintF("Write %lx -> %lx %lx\n", (uint32_t)data, offset, len);
WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
WRITELONG(PISCSI_CMD_ADDR2, len);
WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
WRITESHORT(PISCSI_CMD_WRITE, 1);
} else {
//KPrintF("read %lx %lx -> %lx\n", offset, len, (uint32_t)data);
WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
WRITELONG(PISCSI_CMD_ADDR2, len);
WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
WRITESHORT(PISCSI_CMD_READ, 1);
}
if (sderr) {
iostd->io_Actual = 0;
if (sderr & SCSIERR_TIMEOUT)
return TDERR_DiskChanged;
if (sderr & SCSIERR_PARAM)
return TDERR_SeekError;
if (sderr & SCSIERR_ADDRESS)
return TDERR_SeekError;
if (sderr & (SCSIERR_ERASESEQ | SCSIERR_ERASERES))
return TDERR_BadSecPreamble;
if (sderr & SCSIERR_CRC)
return TDERR_BadSecSum;
if (sderr & SCSIERR_ILLEGAL)
return TDERR_TooFewSecs;
if (sderr & SCSIERR_IDLE)
return TDERR_PostReset;
return TDERR_SeekError;
} else {
iostd->io_Actual = len;
}
return 0;
}
#define PISCSI_ID_STRING "PISTORM Fake SCSI Disk 0.1 1111111111111111"
uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
{
struct IOStdReq *iostd = (struct IOStdReq *)io;
struct SCSICmd *scsi = iostd->io_Data;
//uint8_t* registers = sdu->sdu_Registers;
uint8_t *data = (uint8_t *)scsi->scsi_Data;
uint32_t i, block, blocks, maxblocks;
uint8_t err = 0;
KPrintF("SCSI len=%ld, cmd = %02lx %02lx %02lx ... (%ld)\n",
iostd->io_Length, scsi->scsi_Command[0],
scsi->scsi_Command[1], scsi->scsi_Command[2],
scsi->scsi_CmdLength);
//maxblocks = u->s * u->c * u->h;
if (scsi->scsi_CmdLength < 6) {
//KPrintF("SCSICMD BADLENGTH2");
return IOERR_BADLENGTH;
}
if (scsi->scsi_Command == NULL) {
//KPrintF("SCSICMD IOERR_BADADDRESS1");
return IOERR_BADADDRESS;
}
scsi->scsi_Actual = 0;
//iostd->io_Actual = sizeof(*scsi);
switch (scsi->scsi_Command[0]) {
case 0x00: // TEST_UNIT_READY
KPrintF("SCSI command: Test Unit Ready.\n");
err = 0;
break;
case 0x12: // INQUIRY
KPrintF("SCSI command: Inquiry.\n");
for (i = 0; i < scsi->scsi_Length; i++) {
uint8_t val = 0;
switch (i) {
case 0: // SCSI device type: direct-access device
val = (0 << 5) | 0;
break;
case 1: // RMB = 1
val = (1 << 7);
break;
case 2: // VERSION = 0
val = 0;
break;
case 3: // NORMACA=0, HISUP = 0, RESPONSE_DATA_FORMAT = 2
val = (0 << 5) | (0 << 4) | 2;
break;
case 4: // ADDITIONAL_LENGTH = 44 - 4
val = 44 - 4;
break;
default:
if (i >= 8 && i < 44)
val = PISCSI_ID_STRING[i - 8];
else
val = 0;
break;
}
data[i] = val;
}
scsi->scsi_Actual = i;
err = 0;
break;
case 0x08: // READ (6)
case 0x0a: // WRITE (6)
block = scsi->scsi_Command[1] & 0x1f;
block = (block << 8) | scsi->scsi_Command[2];
block = (block << 8) | scsi->scsi_Command[3];
blocks = scsi->scsi_Command[4];
READLONG(PISCSI_CMD_BLOCKS, maxblocks);
if (block + blocks > maxblocks) {
err = IOERR_BADADDRESS;
break;
}
/*if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
err = IOERR_BADLENGTH;
break;
}*/
if (data == NULL) {
err = IOERR_BADADDRESS;
break;
}
if (scsi->scsi_Command[0] == 0x08) {
//KPrintF("scsi_read %lx %lx\n",block,blocks);
KPrintF("SCSI read %lx %lx -> %lx\n", block, blocks, (uint32_t)data);
WRITELONG(PISCSI_CMD_ADDR2, block);
WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
WRITESHORT(PISCSI_CMD_READ, 1);
}
else {
//KPrintF("scsi_write %lx %lx\n",block,blocks);
KPrintF("SCSI write %lx -> %lx %lx\n", (uint32_t)data, block, blocks);
WRITELONG(PISCSI_CMD_ADDR2, block);
WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
WRITESHORT(PISCSI_CMD_WRITE, 1);
}
scsi->scsi_Actual = scsi->scsi_Length;
err = 0;
break;
case 0x25: // READ CAPACITY (10)
KPrintF("SCSI command: Read Capacity.\n");
if (scsi->scsi_CmdLength < 10) {
err = HFERR_BadStatus;
break;
}
block = *((uint32_t*)&scsi->scsi_Command[2]);
/*if ((scsi->scsi_Command[8] & 1) || block != 0) {
// PMI Not supported
KPrintF("PMI not supported.\n");
err = HFERR_BadStatus;
break;
}*/
if (scsi->scsi_Length < 8) {
err = IOERR_BADLENGTH;
break;
}
READLONG(PISCSI_CMD_BLOCKS, blocks);
((uint32_t*)data)[0] = blocks - 1;
((uint32_t*)data)[1] = PISCSI_BLOCK_SIZE;
scsi->scsi_Actual = 8;
err = 0;
break;
case 0x1a: // MODE SENSE (6)
KPrintF("SCSI command: Mode Sense.\n");
data[0] = 3 + 8 + 0x16;
data[1] = 0; // MEDIUM TYPE
data[2] = 0;
data[3] = 8;
READLONG(PISCSI_CMD_BLOCKS, maxblocks);
(blocks = (maxblocks - 1) & 0xFFFFFF);
*((uint32_t *)&data[4]) = blocks;
*((uint32_t *)&data[8]) = PISCSI_BLOCK_SIZE;
switch (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]) {
case 0x0300: { // Format Device Mode
KPrintF("Grabbing SCSI format device mode data.\n");
uint8_t *datext = data + 12;
datext[0] = 0x03;
datext[1] = 0x16;
datext[2] = 0x00;
datext[3] = 0x01;
*((uint32_t *)&datext[4]) = 0;
*((uint32_t *)&datext[8]) = 0;
*((uint16_t *)&datext[10]) = u->s;
*((uint16_t *)&datext[12]) = PISCSI_BLOCK_SIZE;
datext[14] = 0x00;
datext[15] = 0x01;
*((uint32_t *)&datext[16]) = 0;
datext[20] = 0x80;
scsi->scsi_Actual = data[0] + 1;
err = 0;
break;
}
case 0x0400: // Rigid Drive Geometry
KPrintF("Grabbing SCSI rigid drive geometry.\n");
uint8_t *datext = data + 12;
datext[0] = 0x04;
*((uint32_t *)&datext[1]) = u->c;
datext[1] = 0x16;
datext[5] = u->h;
datext[6] = 0x00;
*((uint32_t *)&datext[6]) = 0;
*((uint32_t *)&datext[10]) = 0;
*((uint32_t *)&datext[13]) = u->c;
datext[17] = 0;
*((uint32_t *)&datext[18]) = 0;
*((uint16_t *)&datext[20]) = 5400;
scsi->scsi_Actual = data[0] + 1;
err = 0;
break;
default:
KPrintF("[WARN] Unhandled mode sense thing: %lx\n", ((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]);
err = HFERR_BadStatus;
break;
}
break;
case 0x37: // READ DEFECT DATA (10)
break;
default:
KPrintF("Unknown/unhandled SCSI command %lx.\n", scsi->scsi_Command[0]);
err = HFERR_BadStatus;
break;
}
if (err != 0) {
KPrintF("Some SCSI error occured: %ld\n", err);
scsi->scsi_Actual = 0;
}
return err;
}
#define DUMMYCMD iostd->io_Actual = 0; break;
uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io) {
struct IOStdReq *iostd = (struct IOStdReq *)io;
struct IOExtTD *iotd = (struct IOExtTD *)io;
uint8_t *data;
uint32_t len;
uint32_t offset;
//struct DriveGeometry *geom;
uint8_t err = 0;
if (!u->enabled) {
return IOERR_OPENFAIL;
}
data = iotd->iotd_Req.io_Data;
len = iotd->iotd_Req.io_Length;
if (io->io_Error == IOERR_ABORTED) {
return io->io_Error;
}
//KPrintF("cmd: %s\n",cmd_name(io->io_Command));
//KPrintF("IO %lx Start, io_Flags = %ld, io_Command = %ld\n", io, io->io_Flags, io->io_Command);
switch (io->io_Command) {
case CMD_CLEAR:
/* Invalidate read buffer */
DUMMYCMD;
case CMD_UPDATE:
/* Flush write buffer */
DUMMYCMD;
case TD_PROTSTATUS:
DUMMYCMD;
case TD_CHANGENUM:
iostd->io_Actual = u->change_num;
break;
case TD_REMOVE:
DUMMYCMD;
case TD_CHANGESTATE:
DUMMYCMD;
case TD_GETDRIVETYPE:
iostd->io_Actual = DG_DIRECT_ACCESS;
break;
case TD_MOTOR:
iostd->io_Actual = u->motor;
u->motor = iostd->io_Length ? 1 : 0;
break;
case TD_FORMAT:
offset = iotd->iotd_Req.io_Offset;
//err = 0;
err = piscsi_rw(u, io, offset, 1);
break;
case CMD_WRITE:
offset = iotd->iotd_Req.io_Offset;
//err = 0;
err = piscsi_rw(u, io, offset, 1);
break;
case CMD_READ:
offset = iotd->iotd_Req.io_Offset;
//err = 0;
err = piscsi_rw(u, io, offset, 0);
break;
case HD_SCSICMD:
//err = 0;
err = piscsi_scsi(u, io);
break;
default: {
int cmd = io->io_Command;
KPrintF("Unknown IO command: %ld\n", cmd);
err = IOERR_NOCMD;
break;
}
}
return err;
}
#undef DUMMYCMD
ADDTABL_END();

View File

@@ -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,
};

View File

@@ -0,0 +1,197 @@
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <endian.h>
#include "piscsi.h"
#include "piscsi-enums.h"
#include "../../../config_file/config_file.h"
#include "../../../gpio/gpio.h"
struct piscsi_dev devs[8];
uint8_t piscsi_cur_drive = 0;
uint32_t piscsi_u32[4];
static const char *op_type_names[4] = {
"BYTE",
"WORD",
"LONGWORD",
"MEM",
};
void piscsi_init() {
for (int i = 0; i < 8; i++) {
devs[i].fd = -1;
devs[i].c = devs[i].h = devs[i].s = 0;
}
}
void piscsi_map_drive(char *filename, uint8_t index) {
if (index > 7) {
printf("[PISCSI] Drive index %d out of range.\nUnable to map file %s to drive.\n", index, filename);
return;
}
int32_t tmp_fd = open(filename, O_RDWR);
if (tmp_fd == -1) {
printf("[PISCSI] Failed to open file %s, could not map drive %d.\n", filename, index);
return;
}
struct piscsi_dev *d = &devs[index];
uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
lseek(tmp_fd, 0, SEEK_SET);
printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
d->h = 64;
d->s = 63;
d->c = (file_size / 512) / (d->s * d->h);
printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
d->fs = file_size;
d->fd = tmp_fd;
}
void piscsi_unmap_drive(uint8_t index) {
if (devs[index].fd != -1) {
printf("[PISCSI] Unmapped drive %d.\n", index);
close (devs[index].fd);
devs[index].fd = -1;
}
}
extern struct emulator_config *cfg;
void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
int32_t r;
struct piscsi_dev *d = &devs[piscsi_cur_drive];
switch (addr & 0xFFFF) {
case PISCSI_CMD_READ:
if (d->fd == -1) {
printf ("[PISCSI] BUG: Attempted read from unmapped drive %d.\n", piscsi_cur_drive);
break;
}
printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
printf("[PISCSI] \"DMA\" Read goes to mapped range %d.\n", r);
lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
}
else {
printf("[PISCSI] No mapped range found for read.\n");
uint8_t c = 0;
lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
for (int i = 0; i < piscsi_u32[1]; i++) {
read(d->fd, &c, 1);
#ifndef FAKESTORM
write8(piscsi_u32[2] + i, (uint32_t)c);
#endif
}
}
break;
case PISCSI_CMD_WRITE:
if (d->fd == -1) {
printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", piscsi_cur_drive);
break;
}
printf("[PISCSI] %d byte WRITE to block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
if (r != -1) {
printf("[PISCSI] \"DMA\" Write comes from mapped range %d.\n", r);
lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
}
else {
printf("[PISCSI] No mapped range found for write.\n");
uint8_t c = 0;
lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
for (int i = 0; i < piscsi_u32[1]; i++) {
#ifndef FAKESTORM
c = read8(piscsi_u32[2] + i);
#endif
write(d->fd, &c, 1);
}
}
break;
case PISCSI_CMD_ADDR1:
piscsi_u32[0] = val;
printf("[PISCSI] Write to ADDR1: %.8x\n", piscsi_u32[0]);
break;
case PISCSI_CMD_ADDR2:
piscsi_u32[1] = val;
printf("[PISCSI] Write to ADDR2: %.8x\n", piscsi_u32[1]);
break;
case PISCSI_CMD_ADDR3:
piscsi_u32[2] = val;
printf("[PISCSI] Write to ADDR3: %.8x\n", piscsi_u32[2]);
break;
case PISCSI_CMD_ADDR4:
piscsi_u32[3] = val;
printf("[PISCSI] Write to ADDR4: %.8x\n", piscsi_u32[3]);
break;
case PISCSI_CMD_DRVNUM:
if (val != 0) {
if (val < 10) // Kludge for GiggleDisk
piscsi_cur_drive = val;
else if (val >= 10 && val % 10 != 0)
piscsi_cur_drive = 255;
else
piscsi_cur_drive = val / 10;
}
else
piscsi_cur_drive = val;
printf("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
break;
default:
printf("[PISCSI] Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
break;
}
}
uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
if (type) {}
switch (addr & 0xFFFF) {
case PISCSI_CMD_DRVTYPE:
if (devs[piscsi_cur_drive].fd == -1) {
printf("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
return 0;
}
printf("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
return 1;
break;
case PISCSI_CMD_DRVNUM:
return piscsi_cur_drive;
break;
case PISCSI_CMD_CYLS:
printf("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
return devs[piscsi_cur_drive].c;
break;
case PISCSI_CMD_HEADS:
printf("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
return devs[piscsi_cur_drive].h;
break;
case PISCSI_CMD_SECS:
printf("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
return devs[piscsi_cur_drive].s;
break;
case PISCSI_CMD_BLOCKS: {
uint32_t blox = devs[piscsi_cur_drive].fs / 512;
printf("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
printf("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
return blox;
break;
}
default:
printf("[PISCSI] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
break;
}
return 0;
}
void piscsi_block_op(uint8_t type, uint8_t num, uint32_t dest, uint32_t len) {
if (type || num || dest || len) {}
}

View File

@@ -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;
};

Binary file not shown.

1
run.sh
View File

@@ -1 +0,0 @@
taskset 0x8 sudo ./emulator