mirror of
https://github.com/captain-amygdala/pistorm.git
synced 2026-01-28 20:41:08 +00:00
[WIP] PiSCSI, Pi-NET and some other things
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
||||
*.img
|
||||
*.hdf
|
||||
*.rom
|
||||
!/platforms/amiga/piscsi/*.rom
|
||||
/m68kmake
|
||||
/m68kmake.exe
|
||||
/m68kops.c
|
||||
|
||||
2
Makefile
2
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
|
||||
|
||||
47
emulator.c
47
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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
1
platforms/amiga/net/net_driver_amiga/build.sh
Normal file
1
platforms/amiga/net/net_driver_amiga/build.sh
Normal file
@@ -0,0 +1 @@
|
||||
m68k-amigaos-gcc -m68020 -O2 -o pi-net.device -ramiga-dev -noixemul -fbaserel pi-net-amiga.c -ldebug -lamiga
|
||||
460
platforms/amiga/net/net_driver_amiga/pi-net-amiga.c
Normal file
460
platforms/amiga/net/net_driver_amiga/pi-net-amiga.c
Normal 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();
|
||||
BIN
platforms/amiga/net/net_driver_amiga/pi-net.device
Normal file
BIN
platforms/amiga/net/net_driver_amiga/pi-net.device
Normal file
Binary file not shown.
261
platforms/amiga/net/net_driver_amiga/sana2.h
Normal file
261
platforms/amiga/net/net_driver_amiga/sana2.h
Normal 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 */
|
||||
24
platforms/amiga/net/pi-net-enums.h
Normal file
24
platforms/amiga/net/pi-net-enums.h
Normal 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,
|
||||
};
|
||||
77
platforms/amiga/net/pi-net.c
Normal file
77
platforms/amiga/net/pi-net.c
Normal 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;
|
||||
}
|
||||
3
platforms/amiga/net/pi-net.h
Normal file
3
platforms/amiga/net/pi-net.h
Normal 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);
|
||||
BIN
platforms/amiga/piscsi/device_driver_amiga/bootrom
Normal file
BIN
platforms/amiga/piscsi/device_driver_amiga/bootrom
Normal file
Binary file not shown.
251
platforms/amiga/piscsi/device_driver_amiga/bootrom.s
Normal file
251
platforms/amiga/piscsi/device_driver_amiga/bootrom.s
Normal 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 */
|
||||
1
platforms/amiga/piscsi/device_driver_amiga/build.bat
Normal file
1
platforms/amiga/piscsi/device_driver_amiga/build.bat
Normal 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
|
||||
4
platforms/amiga/piscsi/device_driver_amiga/build.sh
Normal file
4
platforms/amiga/piscsi/device_driver_amiga/build.sh
Normal 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
|
||||
62
platforms/amiga/piscsi/device_driver_amiga/makerom.c
Normal file
62
platforms/amiga/piscsi/device_driver_amiga/makerom.c
Normal 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;
|
||||
}
|
||||
BIN
platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device
Normal file
BIN
platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device
Normal file
Binary file not shown.
578
platforms/amiga/piscsi/device_driver_amiga/piscsi-amiga.c
Normal file
578
platforms/amiga/piscsi/device_driver_amiga/piscsi-amiga.c
Normal 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();
|
||||
33
platforms/amiga/piscsi/piscsi-enums.h
Normal file
33
platforms/amiga/piscsi/piscsi-enums.h
Normal 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,
|
||||
};
|
||||
197
platforms/amiga/piscsi/piscsi.c
Normal file
197
platforms/amiga/piscsi/piscsi.c
Normal 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) {}
|
||||
}
|
||||
14
platforms/amiga/piscsi/piscsi.h
Normal file
14
platforms/amiga/piscsi/piscsi.h
Normal 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;
|
||||
};
|
||||
BIN
platforms/amiga/piscsi/piscsi.rom
Normal file
BIN
platforms/amiga/piscsi/piscsi.rom
Normal file
Binary file not shown.
Reference in New Issue
Block a user