[WIP] PiSCSI custom file system experiments

Still not quite working, only FFS working for now.
This commit is contained in:
beeanyew 2021-02-16 08:03:46 +01:00
parent 1baedcea07
commit 24d09251d5
23 changed files with 1026 additions and 336 deletions

4
.gitignore vendored
View File

@ -2,6 +2,10 @@
*.img
*.hdf
*.rom
*.dll
*.bin
*.exe
*.stackdump
!/platforms/amiga/piscsi/*.rom
/m68kmake
/m68kmake.exe

View File

@ -26,14 +26,14 @@ loopcycles 300
platform amiga
# Uncomment to let reads/writes through from/to the RTC memory range
#setvar enable_rtc_emulation 0
# Uncomment to set a custom HD image file for ide0 drive 0/1
# Uncomment to set a HD image file for ide0 drive 0/1
#setvar hdd0 snakes.img
#setvar hdd1 snakes2.img
# Uncomment to enable RTG
#setvar rtg
# Uncomment to enable CDTV mode (not working, requires Kickstart 1.3+CDTV extended ROM)
#setvar cdtv
# Uncomment this line to enabled the PiSCSI interface
# Uncomment this line to enable the PiSCSI interface
#setvar piscsi
# Use setvar piscsi0 through piscsi6 to add up to seven mapped drives to the interface.
#setvar piscsi0 PI0.hdf

View File

@ -23,6 +23,7 @@
#include "platforms/amiga/gayle-ide/ide.h"
#include "platforms/amiga/amiga-registers.h"
#include "platforms/amiga/rtg/rtg.h"
#include "platforms/amiga/hunk-reloc.h"
#include "platforms/amiga/piscsi/piscsi.h"
#include "platforms/amiga/piscsi/piscsi-enums.h"
#include "platforms/amiga/net/pi-net.h"
@ -46,6 +47,8 @@ char mouse_dx = 0, mouse_dy = 0;
char mouse_buttons = 0;
extern uint8_t gayle_int;
extern uint8_t gayle_ide_enabled;
extern uint8_t gayle_emulation_enabled;
extern uint8_t gayle_a4k_int;
extern volatile unsigned int *gpio;
extern volatile uint16_t srdata;
@ -60,7 +63,6 @@ char disasm_buf[4096];
int mem_fd, mouse_fd = -1, keyboard_fd = -1;
int mem_fd_gpclk;
int gayle_emulation_enabled = 1;
int irq;
int gayleirq;
@ -81,7 +83,7 @@ void *iplThread(void *args) {
else
irq = 0;
if (gayle_emulation_enabled) {
if (gayle_ide_enabled) {
if (((gayle_int & 0x80) || gayle_a4k_int) && (get_ide(0)->drive[0].intrq || get_ide(0)->drive[1].intrq)) {
//get_ide(0)->drive[0].intrq = 0;
gayleirq = 1;
@ -111,8 +113,6 @@ void stop_cpu_emulation(uint8_t disasm_cur) {
do_disasm = 0;
}
//unsigned char g_kick[524288];
//unsigned char g_ram[FASTSIZE + 1]; /* RAM */
int ovl;
static volatile unsigned char maprom;
@ -140,10 +140,7 @@ int main(int argc, char *argv[]) {
// Some command line switch stuffles
for (g = 1; g < argc; g++) {
if (strcmp(argv[g], "--disable-gayle") == 0) {
gayle_emulation_enabled = 0;
}
else if (strcmp(argv[g], "--cpu_type") == 0 || strcmp(argv[g], "--cpu") == 0) {
if (strcmp(argv[g], "--cpu_type") == 0 || strcmp(argv[g], "--cpu") == 0) {
if (g + 1 >= argc) {
printf("%s switch found, but no CPU type specified.\n", argv[g]);
} else {

View File

@ -25,6 +25,9 @@
#include "gayle-ide/ide.h"
#include "amiga-registers.h"
//#define DEBUG(...)
#define DEBUG printf
uint8_t gary_cfg[8];
uint8_t ramsey_cfg = 0x08;
@ -32,7 +35,7 @@ static uint8_t ramsey_id = RAMSEY_REV7;
int counter;
static uint8_t gayle_irq, gayle_cs, gayle_cs_mask, gayle_cfg;
static struct ide_controller *ide0;
static struct ide_controller *ide0 = NULL;
int fd;
uint8_t rtc_type = RTC_TYPE_RICOH;
@ -49,10 +52,12 @@ uint8_t gayle_int = 0;
uint32_t gayle_ide_mask = ~GDATA;
uint32_t gayle_ide_base = GDATA;
uint8_t gayle_ide_enabled = 1;
uint8_t gayle_emulation_enabled = 1;
uint8_t gayle_ide_adj = 0;
struct ide_controller *get_ide(int index) {
//if (index) {}
if (index) {}
return ide0;
}
@ -74,16 +79,16 @@ void set_hard_drive_image_file_amiga(uint8_t index, char *filename) {
}
void InitGayle(void) {
if (!hdd_image_file[0]) {
hdd_image_file[0] = calloc(1, 64);
sprintf(hdd_image_file[0], "hd0.img");
}
ide0 = ide_allocate("cf");
uint8_t num_ide_drives = 0;
for (int i = 0; i < GAYLE_MAX_HARDFILES; i++) {
if (hdd_image_file[i]) {
fd = open(hdd_image_file[i], O_RDWR);
if (fd != -1) {
if (!ide0)
ide0 = ide_allocate("cf");
}
if (fd == -1) {
printf("[HDD%d] HDD Image %s failed open\n", i, hdd_image_file[i]);
} else {
@ -91,16 +96,25 @@ void InitGayle(void) {
if (strcmp(hdd_image_file[i] + (strlen(hdd_image_file[i]) - 3), "img") != 0) {
printf("No header present on HDD image %s.\n", hdd_image_file[i]);
ide_attach_hdf(ide0, i, fd);
num_ide_drives++;
}
else {
printf("Attaching HDD image with header.\n");
ide_attach(ide0, i, fd);
num_ide_drives++;
}
printf("[HDD%d] HDD Image %s attached\n", i, hdd_image_file[i]);
}
}
}
ide_reset_begin(ide0);
if (ide0)
ide_reset_begin(ide0);
if (num_ide_drives == 0) {
// No IDE drives mounted, disable IDE component of Gayle
printf("No IDE drives mounted, disabling Gayle IDE component.\n");
gayle_ide_enabled = 0;
}
}
uint8_t CheckIrq(void) {
@ -118,47 +132,49 @@ uint8_t CheckIrq(void) {
static uint8_t ide_action = 0;
void writeGayleB(unsigned int address, unsigned int value) {
if (address >= gayle_ide_base) {
switch ((address - gayle_ide_base) - gayle_ide_adj) {
case GFEAT_OFFSET:
//printf("Write to GFEAT: %.2X.\n", value);
ide_action = ide_feature_w;
goto idewrite8;
case GCMD_OFFSET:
//printf("Write to GCMD: %.2X.\n", value);
ide_action = ide_command_w;
goto idewrite8;
case GSECTCOUNT_OFFSET:
ide_action = ide_sec_count;
goto idewrite8;
case GSECTNUM_OFFSET:
ide_action = ide_sec_num;
goto idewrite8;
case GCYLLOW_OFFSET:
ide_action = ide_cyl_low;
goto idewrite8;
case GCYLHIGH_OFFSET:
ide_action = ide_cyl_hi;
goto idewrite8;
case GDEVHEAD_OFFSET:
//printf("Write to GDEVHEAD: %.2X.\n", value);
ide_action = ide_dev_head;
goto idewrite8;
case GCTRL_OFFSET:
//printf("Write to GCTRL: %.2X.\n", value);
ide_action = ide_devctrl_w;
goto idewrite8;
case GIRQ_4000_OFFSET:
gayle_a4k_irq = value;
case GIRQ_OFFSET:
gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
return;
}
goto skip_idewrite8;
if (ide0) {
if (address >= gayle_ide_base) {
switch ((address - gayle_ide_base) - gayle_ide_adj) {
case GFEAT_OFFSET:
//printf("Write to GFEAT: %.2X.\n", value);
ide_action = ide_feature_w;
goto idewrite8;
case GCMD_OFFSET:
//printf("Write to GCMD: %.2X.\n", value);
ide_action = ide_command_w;
goto idewrite8;
case GSECTCOUNT_OFFSET:
ide_action = ide_sec_count;
goto idewrite8;
case GSECTNUM_OFFSET:
ide_action = ide_sec_num;
goto idewrite8;
case GCYLLOW_OFFSET:
ide_action = ide_cyl_low;
goto idewrite8;
case GCYLHIGH_OFFSET:
ide_action = ide_cyl_hi;
goto idewrite8;
case GDEVHEAD_OFFSET:
//printf("Write to GDEVHEAD: %.2X.\n", value);
ide_action = ide_dev_head;
goto idewrite8;
case GCTRL_OFFSET:
//printf("Write to GCTRL: %.2X.\n", value);
ide_action = ide_devctrl_w;
goto idewrite8;
case GIRQ_4000_OFFSET:
gayle_a4k_irq = value;
case GIRQ_OFFSET:
gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
return;
}
goto skip_idewrite8;
idewrite8:;
ide_write8(ide0, ide_action, value);
return;
ide_write8(ide0, ide_action, value);
return;
skip_idewrite8:;
}
}
switch (address) {
@ -206,14 +222,16 @@ skip_idewrite8:;
}
void writeGayle(unsigned int address, unsigned int value) {
if (address - gayle_ide_base == GDATA_OFFSET) {
ide_write16(ide0, ide_data, value);
return;
}
if (ide0) {
if (address - gayle_ide_base == GDATA_OFFSET) {
ide_write16(ide0, ide_data, value);
return;
}
if (address == GIRQ_A4000) {
gayle_a4k_irq = value;
return;
if (address == GIRQ_A4000) {
gayle_a4k_irq = value;
return;
}
}
if ((address & GAYLEMASK) == CLOCKBASE) {
@ -254,100 +272,100 @@ void writeGayleL(unsigned int address, unsigned int value) {
}
uint8_t readGayleB(unsigned int address) {
uint8_t ide_action = 0, ide_val = 0;
if (ide0) {
uint8_t ide_action = 0, ide_val = 0;
if (address >= gayle_ide_base) {
switch ((address - gayle_ide_base) - gayle_ide_adj) {
case GERROR_OFFSET:
ide_action = ide_error_r;
goto ideread8;
case GSTATUS_OFFSET:
ide_action = ide_status_r;
goto ideread8;
case GSECTCOUNT_OFFSET:
ide_action = ide_sec_count;
goto ideread8;
case GSECTNUM_OFFSET:
ide_action = ide_sec_num;
goto ideread8;
case GCYLLOW_OFFSET:
ide_action = ide_cyl_low;
goto ideread8;
case GCYLHIGH_OFFSET:
ide_action = ide_cyl_hi;
goto ideread8;
case GDEVHEAD_OFFSET:
ide_action = ide_dev_head;
goto ideread8;
case GCTRL_OFFSET:
ide_action = ide_altst_r;
goto ideread8;
case GIRQ_4000_OFFSET:
case GIRQ_OFFSET:
return 0x80;
//gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
}
goto skip_ideread8;
if (address >= gayle_ide_base) {
switch ((address - gayle_ide_base) - gayle_ide_adj) {
case GERROR_OFFSET:
ide_action = ide_error_r;
goto ideread8;
case GSTATUS_OFFSET:
ide_action = ide_status_r;
goto ideread8;
case GSECTCOUNT_OFFSET:
ide_action = ide_sec_count;
goto ideread8;
case GSECTNUM_OFFSET:
ide_action = ide_sec_num;
goto ideread8;
case GCYLLOW_OFFSET:
ide_action = ide_cyl_low;
goto ideread8;
case GCYLHIGH_OFFSET:
ide_action = ide_cyl_hi;
goto ideread8;
case GDEVHEAD_OFFSET:
ide_action = ide_dev_head;
goto ideread8;
case GCTRL_OFFSET:
ide_action = ide_altst_r;
goto ideread8;
case GIRQ_4000_OFFSET:
case GIRQ_OFFSET:
return 0x80;
//gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
}
goto skip_ideread8;
ideread8:;
ide_val = ide_read8(ide0, ide_action);
//if (((address - gayle_ide_base) - gayle_ide_adj) == GDEVHEAD_OFFSET)
//printf("Read from GDEVHEAD: %.2X\n", ide_val);
return ide_read8(ide0, ide_action);
ide_val = ide_read8(ide0, ide_action);
return ide_val;
skip_ideread8:;
}
}
switch (address) {
case GIDENT: {
uint8_t val;
if (counter == 0 || counter == 1 || counter == 3) {
val = 0x80; // 80; to enable gayle
} else {
val = 0x00;
switch (address) {
case GIDENT: {
uint8_t val;
if (counter == 0 || counter == 1 || counter == 3) {
val = 0x80; // 80; to enable gayle
} else {
val = 0x00;
}
counter++;
//printf("Read from GIDENT: %.2X.\n", val);
return val;
}
counter++;
//printf("Read from GIDENT: %.2X.\n", val);
return val;
}
case GINT:
return gayle_int;
case GCONF:
//printf("Read from GCONF: %d\n", gayle_cfg & 0x0F);
return gayle_cfg & 0x0f;
case GCS: {
uint8_t v;
v = gayle_cs_mask | gayle_cs;
printf("Read from GCS: %d\n", v);
return v;
}
// This seems incorrect, GARY_REG3 is the same as GIDENT, and the A4000
// service manual says that Gary is accessible in the address range $DFC000 to $DFFFFF.
case GARY_REG0:
case GARY_REG1:
case GARY_REG2:
return gary_cfg[address - GARY_REG0];
break;
//case GARY_REG3:
case GARY_REG4:
//case GARY_REG5:
return gary_cfg[address - GARY_REG4];
case RAMSEY_ID:
return ramsey_id;
case RAMSEY_REG:
return ramsey_cfg;
case GARY_REG5: { // This makes no sense.
uint8_t val;
if (counter == 0 || counter == 1 || counter == 3) {
val = 0x80; // 80; to enable GARY
} else {
val = 0x00;
case GINT:
return gayle_int;
case GCONF:
//printf("Read from GCONF: %d\n", gayle_cfg & 0x0F);
return gayle_cfg & 0x0f;
case GCS: {
uint8_t v;
v = gayle_cs_mask | gayle_cs;
printf("Read from GCS: %d\n", v);
return v;
}
counter++;
return val;
// This seems incorrect, GARY_REG3 is the same as GIDENT, and the A4000
// service manual says that Gary is accessible in the address range $DFC000 to $DFFFFF.
case GARY_REG0:
case GARY_REG1:
case GARY_REG2:
return gary_cfg[address - GARY_REG0];
break;
//case GARY_REG3:
case GARY_REG4:
//case GARY_REG5:
return gary_cfg[address - GARY_REG4];
case RAMSEY_ID:
return ramsey_id;
case RAMSEY_REG:
return ramsey_cfg;
case GARY_REG5: { // This makes no sense.
uint8_t val;
if (counter == 0 || counter == 1 || counter == 3) {
val = 0x80; // 80; to enable GARY
} else {
val = 0x00;
}
counter++;
return val;
}
//case 0xDD203A:
// This can't be correct, as this is the same address as GDEVHEAD on the A4000 Gayle.
//printf("Read Byte from Gayle A4k: %.2X\n", gayle_a4k);
//return gayle_a4k;
}
//case 0xDD203A:
// This can't be correct, as this is the same address as GDEVHEAD on the A4000 Gayle.
//printf("Read Byte from Gayle A4k: %.2X\n", gayle_a4k);
//return gayle_a4k;
}
if ((address & GAYLEMASK) == CLOCKBASE) {
@ -367,16 +385,18 @@ skip_ideread8:;
}
uint16_t readGayle(unsigned int address) {
if (address - gayle_ide_base == GDATA_OFFSET) {
uint16_t value;
value = ide_read16(ide0, ide_data);
// value = (value << 8) | (value >> 8);
return value;
}
if (ide0) {
if (address - gayle_ide_base == GDATA_OFFSET) {
uint16_t value;
value = ide_read16(ide0, ide_data);
// value = (value << 8) | (value >> 8);
return value;
}
if (address == GIRQ_A4000) {
gayle_a4k_irq = 0x8000;
return 0x8000;
if (address == GIRQ_A4000) {
gayle_a4k_irq = 0x8000;
return 0x8000;
}
}
if ((address & GAYLEMASK) == CLOCKBASE) {

View File

@ -6,6 +6,7 @@
#include "amiga-autoconf.h"
#include "amiga-registers.h"
#include "../shared/rtc.h"
#include "hunk-reloc.h"
#include "piscsi/piscsi.h"
#include "piscsi/piscsi-enums.h"
#include "net/pi-net.h"
@ -398,6 +399,9 @@ void handle_reset_amiga(struct emulator_config *cfg) {
ac_z2_current_pic = 0;
ac_z3_current_pic = 0;
if (piscsi_enabled)
piscsi_refresh_drives();
adjust_ranges_amiga(cfg);
}

View File

@ -6,13 +6,21 @@
#include <endian.h>
#include "hunk-reloc.h"
#ifdef FAKESTORM
#define lseek64 lseek
#endif
#define DEBUG(...)
//#define DEBUG printf
#define BE(val) be32toh(val)
#define BE16(val) be16toh(val)
#define READLW(a, b) fread(&a, 4, 1, b); a = be32toh(a);
#define READW(a, b) fread(&a, 2, 1, b); a = be16toh(a);
uint32_t lw;
uint32_t lw = 0;
static uint32_t file_offset = 0, add_size = 0;
char *hunk_id_name(uint32_t index) {
switch (index) {
@ -70,7 +78,7 @@ int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_re
case HUNKTYPE_CODE:
DEBUG("Hunk %d: CODE.\n", info->current_hunk);
READLW(discard, f);
info->hunk_offsets[info->current_hunk] = ftell(f);
info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
DEBUG("Code hunk size: %d (%.8X)\n", discard * 4, discard * 4);
fseek(f, discard * 4, SEEK_CUR);
return 0;
@ -80,7 +88,7 @@ int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_re
DEBUG("Processing Reloc32 hunk.\n");
do {
READLW(discard, f);
if (discard) {
if (discard && discard != 0xFFFFFFFF) {
READLW(cur_hunk, f);
DEBUG("Relocating %d offsets pointing to hunk %d.\n", discard, cur_hunk);
for(uint32_t i = 0; i < discard; i++) {
@ -114,13 +122,14 @@ int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_re
case HUNKTYPE_BSS:
DEBUG("Hunk %d: BSS.\n", info->current_hunk);
READLW(discard, f);
info->hunk_offsets[info->current_hunk] = ftell(f);
info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
DEBUG("Skipping BSS hunk. Size: %d\n", discard * 4);
add_size += (discard * 4);
return 0;
case HUNKTYPE_DATA:
DEBUG("Hunk %d: DATA.\n", info->current_hunk);
READLW(discard, f);
info->hunk_offsets[info->current_hunk] = ftell(f);
info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
DEBUG("Skipping data hunk. Size: %d.\n", discard * 4);
fseek(f, discard * 4, SEEK_CUR);
return 0;
@ -148,24 +157,87 @@ void reloc_hunk(struct hunk_reloc *h, uint8_t *buf, struct hunk_info *i) {
*src_ptr = htobe32(dst);
}
void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r) {
void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r, uint32_t offset) {
READLW(lw, in);
DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
while(!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
file_offset = offset;
add_size = 0;
while (!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
READLW(lw, in);
if (feof(in)) goto end_parse;
DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
DEBUG("File pos: %.8lX\n", ftell(in));
DEBUG("File pos: %.8lX\n", ftell(in) - file_offset);
}
end_parse:;
DEBUG("Done processing hunks.\n");
}
void reloc_hunks(struct hunk_reloc *r, uint8_t *buf, struct hunk_info *h_info) {
for(uint32_t i = 0; i < h_info->reloc_hunks; i++) {
reloc_hunk(&r[i], buf, h_info);
DEBUG("Relocating %d offsets.\n", h_info->reloc_hunks);
for (uint32_t i = 0; i < h_info->reloc_hunks; i++) {
DEBUG("Relocating offset %d.\n", i);
reloc_hunk(&r[i], buf, h_info);
}
DEBUG("Done relocating offsets.\n");
}
struct LoadSegBlock {
uint32_t lsb_ID;
uint32_t lsb_SummedLongs;
int32_t lsb_ChkSum;
uint32_t lsb_HostID;
uint32_t lsb_Next;
uint32_t lsb_LoadData[123]; // Assumes 512 byte blocks
};
#define LOADSEG_IDENTIFIER 0x4C534547
int load_lseg(int fd, uint8_t **buf_p, struct hunk_info *i, struct hunk_reloc *relocs) {
if (fd == -1)
return -1;
uint8_t *block = malloc(512);
uint32_t next_blk = 0;
struct LoadSegBlock *lsb = (struct LoadSegBlock *)block;
read(fd, block, 512);
if (BE(lsb->lsb_ID) != LOADSEG_IDENTIFIER) {
DEBUG("[LOAD_LSEG] Attempted to load a non LSEG-block: %.8X", BE(lsb->lsb_ID));
goto fail;
}
char *filename = "data/lsegout.bin";
FILE *out = fopen(filename, "wb+");
DEBUG("[LOAD_LSEG] LSEG data:\n");
DEBUG("[LOAD_LSEG] Longs: %d HostID: %d\n", BE(lsb->lsb_SummedLongs), BE(lsb->lsb_HostID));
DEBUG("[LOAD_LSEG] Next: %d LoadData: %p\n", BE(lsb->lsb_Next), (void *)lsb->lsb_LoadData);
next_blk = BE(lsb->lsb_Next);
do {
next_blk = BE(lsb->lsb_Next);
fwrite(lsb->lsb_LoadData, 4, 123, out);
lseek64(fd, next_blk * 512, SEEK_SET);
read(fd, block, 512);
} while (next_blk != 0xFFFFFFFF);
uint32_t file_size = ftell(out);
fseek(out, 0, SEEK_SET);
uint8_t *buf = malloc(file_size + 1024);
fread(buf, file_size, 1, out);
fseek(out, 0, SEEK_SET);
process_hunks(out, i, relocs, 0x0);
fclose(out);
*buf_p = buf;
i->byte_size = file_size;
i->alloc_size = file_size + add_size;
return 0;
fail:;
if (block)
free(block);
return -1;
}

View File

@ -8,7 +8,7 @@ struct hunk_info {
uint16_t current_hunk;
uint16_t num_libs;
uint8_t *libnames[256];
uint32_t table_size;
uint32_t table_size, byte_size, alloc_size;
uint32_t base_offset;
uint32_t first_hunk, last_hunk, num_hunks;
uint32_t reloc_hunks;
@ -27,6 +27,8 @@ enum hunk_types {
};
int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_reloc *r);
int load_lseg(int fd, uint8_t **buf_p, struct hunk_info *i, struct hunk_reloc *relocs);
void reloc_hunk(struct hunk_reloc *h, uint8_t *buf, struct hunk_info *i);
void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r);
void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r, uint32_t offset);
void reloc_hunks(struct hunk_reloc *r, uint8_t *buf, struct hunk_info *h_info);

View File

@ -62,6 +62,8 @@ InitResident EQU -102
FindResident EQU -96
OpenLibrary EQU -552
CloseLibrary EQU -414
OpenResource EQU -$1F2
AddResource EQU -$1E6
; Expansion stuff
MakeDosNode EQU -144
@ -70,11 +72,28 @@ AddBootNode EQU -36
; PiSCSI stuff
PiSCSIAddr1 EQU $80000010
PiSCSIAddr2 EQU $80000014
PiSCSIAddr3 EQU $80000018
PiSCSIAddr4 EQU $8000001C
PiSCSIDebugMe EQU $80000020
PiSCSIDriver EQU $80000040
PiSCSINextPart EQU $80000044
PiSCSIGetPart EQU $80000048
PiSCSIGetPrio EQU $8000004C
PiSCSIGetFS EQU $80000060
PiSCSINextFS EQU $80000064
PiSCSICopyFS EQU $80000068
PiSCSIFSSize EQU $8000006C
PiSCSISetFSH EQU $80000070
PiSCSIDbg1 EQU $80001010
PiSCSIDbg2 EQU $80001014
PiSCSIDbg3 EQU $80001018
PiSCSIDbg4 EQU $8000101C
PiSCSIDbg5 EQU $80001020
PiSCSIDbg6 EQU $80001024
PiSCSIDbg7 EQU $80001028
PiSCSIDbg8 EQU $8000102C
PiSCSIDbgMsg EQU $80001000
******* RomStart ***************************************************
**********************************************************************
@ -238,7 +257,7 @@ Init: ; After Diag patching, our romtag will point to this
;
align 2
move.l a6,-(a7) ; Push A6 to stack
;move.w #$00B8,$dff09a ; Disable interrupts during init
move.w #$00B8,$dff09a ; Disable interrupts during init
move.l #3,PiSCSIDebugMe
move.l #11,PiSCSIDebugMe
@ -265,37 +284,138 @@ Init: ; After Diag patching, our romtag will point to this
jsr InitResident(a6) ; Initialize the PiSCSI driver
SkipDriverLoad:
move.l #9,PiSCSIDebugMe
bra.w LoadFileSystems
FSLoadExit:
lea ExpansionName(pc),a1
moveq #0,d0
jsr OpenLibrary(a6) ; Open expansion.library to make this work, somehow
move.l d0,a6
move.l #7,PiSCSIDebugMe
PartitionLoop:
move.l #9,PiSCSIDebugMe
move.l PiSCSIGetPart,d0 ; Get the available partition in the current slot
beq.s EndPartitions ; If the next partition returns 0, there's no additional partitions
move.l d0,a0
jsr MakeDosNode(a6)
move.l #7,PiSCSIDebugMe
move.l d0,PiSCSISetFSH
move.l d0,a0
move.l PiSCSIGetPrio,d0
move.l #0,d1
move.l PiSCSIAddr1,a1
jsr AddBootNode(a6)
move.l #8,PiSCSIDebugMe
move.l #1,PiSCSINextPart ; Switch to the next partition
bra.w PartitionLoop
EndPartitions:
move.l #8,PiSCSIDebugMe
move.l a6,a1
move.l #800,PiSCSIDebugMe
movea.l 4,a6
move.l #801,PiSCSIDebugMe
jsr CloseLibrary(a6)
move.l #6,PiSCSIDebugMe
move.l #802,PiSCSIDebugMe
move.l (a7)+,a6 ; Pop A6 from stack
move.l #803,PiSCSIDebugMe
;move.w #$80B8,$dff09a ; Re-enable interrupts
move.w #$80B8,$dff09a ; Re-enable interrupts
move.l #804,PiSCSIDebugMe
moveq.l #1,d0 ; indicate "success"
move.l #805,PiSCSIDebugMe
rts
END
align 4
FileSysName dc.b 'FileSystem.resource',0
FileSysCreator dc.b 'PiStorm',0
CurFS: dc.l $0
FSResource: dc.l $0
align 2
LoadFileSystems:
movem.l d0-d7/a0-a6,-(sp) ; Push registers to stack
move.l #30,PiSCSIDebugMe
lea FileSysName(pc),a1
jsr OpenResource(a6)
tst.l d0
bne FSRExists
move.l #33,PiSCSIDebugMe ; FileSystem.resource isn't open, create it
lea FSRes(pc),a1
move.l a1,-(a7)
jsr AddResource(a6)
move.l (a7)+,a0
move.l a0,d0
FSRExists:
move.l d0,PiSCSIAddr2 ; PiSCSIAddr2 is now FileSystem.resource
move.l #31,PiSCSIDebugMe
move.l PiSCSIAddr2,a0
move.l PiSCSIGetFS,d0
cmp.l #0,d0
beq.w FSDone
move.l d0,d7
FSNext:
move.l #45,PiSCSIDebugMe
lea fsr_FileSysEntries(a0),a0
move.l a0,d2
move.l LH_HEAD(a0),d0
beq.w NoEntries
FSLoop:
move.l #34,PiSCSIDebugMe
move.l d0,a1
move.l #35,PiSCSIDebugMe
cmp.l fse_DosType(a1),d7
move.l #36,PiSCSIDebugMe
beq.w AlreadyLoaded
move.l #37,PiSCSIDebugMe
move.l LN_SUCC(a1),d0
bne.w FSLoop
move.l #390,PiSCSIDebugMe
bra.w NoEntries
align 2
NoEntries:
move.l #39,PiSCSIDebugMe
move.l PiSCSIFSSize,d0
move.l #40,PiSCSIDebugMe
move.l #0,d1
move.l #41,PiSCSIDebugMe
jsr AllocMem(a6)
move.l d0,PiSCSIAddr3
move.l #1,PiSCSICopyFS
AlreadyLoaded:
move.l #480,PiSCSIDebugMe
move.l PiSCSIAddr2,a0
move.l #1,PiSCSINextFS
move.l PiSCSIGetFS,d0
move.l d0,d7
cmp.l #0,d0
bne.w FSNext
FSDone: move.l #37,PiSCSIDebugMe
move.l #32,PiSCSIDebugMe ; Couldn't open FileSystem.resource, Kick 1.2/1.3?
movem.l (sp)+,d0-d7/a0-a6 ; Pop registers from stack
bra.w FSLoadExit
FileSysRes
dc.l 0
dc.l 0
dc.b NT_RESOURCE
dc.b 0
dc.l FileSysName
dc.l FileSysCreator
.Head
dc.l .Tail
.Tail
dc.l 0
dc.l .Head
dc.b NT_RESOURCE
dc.b 0

View File

@ -2,7 +2,7 @@
#m68k-amigaos-gcc -m68020 -O2 -o pi-scsi.device -ramiga-dev -noixemul -fbaserel piscsi-amiga.c -ldebug -lamiga
#m68k-amigaos-gcc -m68020 -O2 -o scsi.device -ramiga-dev -noixemul -fbaserel piscsi-amiga.c -ldebug -lamiga -D_FSCSIDEV
#m68k-amigaos-gcc -m68020 -O2 -o 2nd.scsi.device -ramiga-dev -noixemul -fbaserel piscsi-amiga.c -ldebug -lamiga -D_FSCSI2ND
vasmm68k_mot.exe -m68020 -Fhunk -I$VBCC/NDK39/include/include_i bootrom.s -o a.out
vasmm68k_mot.exe -m68000 -Fhunk -I$VBCC/NDK39/include/include_i bootrom.s -o bootrom
#m68k-amigaos-as -m68020 bootrom.s &&
m68k-amigaos-objcopy --strip-all ./a.out ./bootrom
rm ./a.out
#m68k-amigaos-objcopy --strip-all ./a.out ./bootrom
#rm ./a.out

View File

@ -3,7 +3,7 @@
#include <string.h>
#include <stdlib.h>
#define BOOTLDR_SIZE 0x400
#define BOOTLDR_SIZE 0x1000
#define DIAG_TOTAL_SIZE 0x4000
char *rombuf, *zerobuf, *devicebuf;

View File

@ -47,6 +47,7 @@ struct piscsi_base {
uint8_t read_only;
uint8_t motor;
uint8_t unit_num;
uint16_t scsi_num;
uint16_t h, s;
uint32_t c;
@ -115,6 +116,7 @@ static struct Library __attribute__((used)) *init_device(uint8_t *seg_list asm("
dev_base->units[i].present = r;
dev_base->units[i].valid = r;
dev_base->units[i].unit_num = i;
dev_base->units[i].scsi_num = i * 10;
if (dev_base->units[i].present) {
READLONG(PISCSI_CMD_CYLS, dev_base->units[i].c);
READSHORT(PISCSI_CMD_HEADS, dev_base->units[i].h);
@ -320,11 +322,11 @@ uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
//iostd->io_Actual = sizeof(*scsi);
switch (scsi->scsi_Command[0]) {
case 0x00: // TEST_UNIT_READY
case SCSICMD_TEST_UNIT_READY:
err = 0;
break;
case 0x12: // INQUIRY
case SCSICMD_INQUIRY:
for (i = 0; i < scsi->scsi_Length; i++) {
uint8_t val = 0;
@ -357,42 +359,35 @@ uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
err = 0;
break;
case 0x08: // READ (6)
case 0x0a: // WRITE (6)
case 0x28: // READ (10)
case 0x2A: // WRITE (10)
switch (scsi->scsi_Command[0]) {
case 0x0A:
write = 1;
case 0x08:
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];
break;
case 0x2A:
write = 1;
case 0x28:
block = scsi->scsi_Command[2];
block = (block << 8) | scsi->scsi_Command[3];
block = (block << 8) | scsi->scsi_Command[4];
block = (block << 8) | scsi->scsi_Command[5];
case SCSICMD_WRITE_6:
write = 1;
case SCSICMD_READ_6:
block = *(uint32_t *)(&scsi->scsi_Command[0]) & 0x001FFFFF;
/*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];
goto scsireadwrite;
case SCSICMD_WRITE_10:
write = 1;
case SCSICMD_READ_10:
block = *(uint32_t *)(&scsi->scsi_Command[2]);
/*block = scsi->scsi_Command[2];
block = (block << 8) | scsi->scsi_Command[3];
block = (block << 8) | scsi->scsi_Command[4];
block = (block << 8) | scsi->scsi_Command[5];*/
blocks = scsi->scsi_Command[7];
blocks = (blocks << 8) | scsi->scsi_Command[8];
break;
}
blocks = *(uint16_t *)(&scsi->scsi_Command[7]);
/*blocks = scsi->scsi_Command[7];
blocks = (blocks << 8) | scsi->scsi_Command[8];*/
WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
scsireadwrite:;
WRITESHORT(PISCSI_CMD_DRVNUM, (u->scsi_num));
READLONG(PISCSI_CMD_BLOCKS, maxblocks);
if (block + blocks > maxblocks || blocks == 0) {
err = IOERR_BADADDRESS;
break;
}
/*if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
err = IOERR_BADLENGTH;
break;
}*/
if (data == NULL) {
err = IOERR_BADADDRESS;
break;
@ -415,20 +410,18 @@ uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
err = 0;
break;
case 0x25: // READ CAPACITY (10)
case SCSICMD_READ_CAPACITY_10:
if (scsi->scsi_CmdLength < 10) {
err = HFERR_BadStatus;
break;
}
block = *((uint32_t*)&scsi->scsi_Command[2]);
if (scsi->scsi_Length < 8) {
err = IOERR_BADLENGTH;
break;
}
WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
WRITESHORT(PISCSI_CMD_DRVNUM, (u->scsi_num));
READLONG(PISCSI_CMD_BLOCKS, blocks);
((uint32_t*)data)[0] = blocks - 1;
((uint32_t*)data)[1] = PISCSI_BLOCK_SIZE;
@ -437,13 +430,16 @@ uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
err = 0;
break;
case 0x1a: // MODE SENSE (6)
case SCSICMD_MODE_SENSE_6:
data[0] = 3 + 8 + 0x16;
data[1] = 0; // MEDIUM TYPE
data[2] = 0;
data[3] = 8;
WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
debugval(PISCSI_DBG_VAL1, ((uint32_t)scsi->scsi_Command));
debug(PISCSI_DBG_MSG, DBG_SCSI_DEBUG_MODESENSE_6);
WRITESHORT(PISCSI_CMD_DRVNUM, (u->scsi_num));
READLONG(PISCSI_CMD_BLOCKS, maxblocks);
(blocks = (maxblocks - 1) & 0xFFFFFF);
@ -498,9 +494,9 @@ uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
}
break;
case 0x37: // READ DEFECT DATA (10)
case SCSICMD_READ_DEFECT_DATA_10:
break;
case 0x40: // CHANGE DEFINITION
case SCSICMD_CHANGE_DEFINITION:
break;
default:

View File

@ -37,6 +37,11 @@ enum piscsi_cmds {
PISCSI_CMD_GETPRIO = 0x4C,
PISCSI_CMD_WRITE64 = 0x50,
PISCSI_CMD_READ64 = 0x52,
PISCSI_CMD_CHECKFS = 0x60,
PISCSI_CMD_NEXTFS = 0x64,
PISCSI_CMD_COPYFS = 0x68,
PISCSI_CMD_FSSIZE = 0x6C,
PISCSI_CMD_SETFSH = 0x70,
PISCSI_DBG_MSG = 0x1000,
PISCSI_DBG_VAL1 = 0x1010,
PISCSI_DBG_VAL2 = 0x1014,
@ -65,6 +70,155 @@ enum piscsi_dbg_msgs {
DBG_SCSI_UNKNOWN_COMMAND,
DBG_SCSIERR,
DBG_IOCMD_UNHANDLED,
DBG_SCSI_DEBUG_MODESENSE_6,
DBG_SCSI_DEBUG_MODESENSE_10,
};
enum scsi_commands {
SCSICMD_TEST_UNIT_READY = 0x00,
SCSICMD_REWIND = 0x01,
SCSICMD_REQUEST_SENSE = 0x03,
SCSICMD_FORMAT = 0x04,
SCSICMD_READ_BLOCK_LIMITS = 0x05,
SCSICMD_REASSIGN_BLOCKS = 0x07,
SCSICMD_INITIALIZE_ELEMENT_STATUS = 0x07,
SCSICMD_READ_6 = 0x08,
SCSICMD_WRITE_6 = 0x0A,
SCSICMD_SEEK_6 = 0x0B,
SCSICMD_READ_REVERSE_6 = 0x0F,
SCSICMD_WRITE_FILEMARKS_6 = 0x10,
SCSICMD_SPACE_6 = 0x11,
SCSICMD_INQUIRY = 0x12,
SCSICMD_VERIFY_6 = 0x13,
SCSICMD_RECOVER_BUFFERED_DATA = 0x14,
SCSICMD_MODE_SELECT_6 = 0x15,
SCSICMD_RESERVE_6 = 0x16,
SCSICMD_RELEASE_6 = 0x17,
SCSICMD_COPY = 0x18,
SCSICMD_ERASE_6 = 0x19,
SCSICMD_MODE_SENSE_6 = 0x1A,
SCSICMD_START_STOP_UNIT = 0x1B,
SCSICMD_LOAD_UNLOAD = 0x1B,
SCSICMD_RECEIVE_DIAGNOSTIC_RESULTS = 0x1C,
SCSICMD_SEND_DIAGNOSTIC = 0x1D,
SCSICMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E,
SCSICMD_READ_FORMAT_CAPACITIES = 0x23,
SCSICMD_READ_CAPACITY_10 = 0x25,
SCSICMD_READ_10 = 0x28,
SCSICMD_READ_GENERATION = 0x29,
SCSICMD_WRITE_10 = 0x2A,
SCSICMD_SEEK_10 = 0x2B,
SCSICMD_LOCATE_10 = 0x2B,
SCSICMD_ERASE_10 = 0x2C,
SCSICMD_READ_UPDATED_BLOCK = 0x2D,
SCSICMD_WRITE_AND_VERIFY_10 = 0x2E,
SCSICMD_VERIFY_10 = 0x2F,
SCSICMD_SET_LIMITS_10 = 0x33,
SCSICMD_PREFETCH_10 = 0x34,
SCSICMD_READ_POSITION = 0x34,
SCSICMD_SYNCHRONIZE_CACHE_10 = 0x35,
SCSICMD_LOCK_UNLOCK_CACHE_10 = 0x36,
SCSICMD_READ_DEFECT_DATA_10 = 0x37,
SCSICMD_INITIALIZE_ELEMENT_STATUS_WITH_RANGE = 0x37,
SCSICMD_MEDIUM_SCAN = 0x38,
SCSICMD_COMPARE = 0x39,
SCSICMD_COPY_AND_VERIFY = 0x3A,
SCSICMD_WRITE_BUFFER = 0x3B,
SCSICMD_READ_BUFFER = 0x3C,
SCSICMD_UPDATE_BLOCK = 0x3D,
SCSICMD_READ_LONG_10 = 0x3E,
SCSICMD_WRITE_LONG_10 = 0x3F,
SCSICMD_CHANGE_DEFINITION = 0x40,
SCSICMD_WRITE_SAME_10 = 0x41,
SCSICMD_UNMAP = 0x42,
SCSICMD_READ_TOC_PMA_ATIP = 0x43,
SCSICMD_REPORT_DENSITY_SUPPORT = 0x44,
SCSICMD_PLAY_AUDIO_10 = 0x45,
SCSICMD_GET_CONFIGURATION = 0x46,
SCSICMD_PLAY_AUDIO_MSF = 0x47,
SCSICMD_SANITIZE = 0x48,
SCSICMD_GET_EVENT_STATUS_NOTIFICATION = 0x4A,
SCSICMD_PAUSE_RESUME = 0x4B,
SCSICMD_LOG_SELECT = 0x4C,
SCSICMD_LOG_SENSE = 0x4D,
SCSICMD_XDWRITE_10 = 0x50,
SCSICMD_XPWRITE_10 = 0x51,
SCSICMD_READ_DISC_INFORMATION = 0x51,
SCSICMD_XDREAD_10 = 0x52,
SCSICMD_XDWRITEREAD_10 = 0x53,
SCSICMD_SEND_OPC_INFORMATION = 0x54,
SCSICMD_MODE_SELECT_10 = 0x55,
SCSICMD_RESERVE_10 = 0x56,
SCSICMD_RELEASE_10 = 0x57,
SCSICMD_REPAIR_TRACK = 0x58,
SCSICMD_MODE_SENSE_10 = 0x5A,
SCSICMD_CLOSE_TRACK_SESSION = 0x5B,
SCSICMD_READ_BUFFER_CAPACITY = 0x5C,
SCSICMD_SEND_CUE_SHEET = 0x5D,
SCSICMD_PERSISTENT_RESERVE_IN = 0x5E,
SCSICMD_PERSISTENT_RESERVE_OUT = 0x5F,
SCSICMD_EXTENDED_CDB = 0x7E,
SCSICMD_VARIABLELENGTH_CDB = 0x7F,
SCSICMD_XDWRITE_EXTENDED_16 = 0x80,
SCSICMD_WRITE_FILEMARKS_16 = 0x80,
SCSICMD_READ_REVERSE_16 = 0x81,
SCSICMD_3RDPARTY_COPY_OUT_CMDS = 0x83,
SCSICMD_3RDPARTY_COPY_IN_CMDS = 0x84,
SCSICMD_ATA_PASSTHROUGH_16 = 0x85,
SCSICMD_ACCESS_CONTROL_IN = 0x86,
SCSICMD_ACCESS_CONTROL_OUT = 0x87,
SCSICMD_READ_16 = 0x88,
SCSICMD_COMPARE_AND_WRITE = 0x89,
SCSICMD_WRITE_16 = 0x8A,
SCSICMD_ORWRITE = 0x8B,
SCSICMD_READ_ATTRIBUTE = 0x8C,
SCSICMD_WRITE_ATTRIBUTE = 0x8D,
SCSICMD_WRITE_AND_VERIFY_16 = 0x8E,
SCSICMD_VERIFY_16 = 0x8F,
SCSICMD_PREFETCH_16 = 0x90,
SCSICMD_SYNCHRONIZE_CACHE_16 = 0x91,
SCSICMD_SPACE_16 = 0x91,
SCSICMD_LOCK_UNLOCK_CACHE_16 = 0x92,
SCSICMD_LOCATE_16 = 0x92,
SCSICMD_WRITE_SAME_16 = 0x93,
SCSICMD_ERASE_16 = 0x93,
SCSICMD_SERVICE_ACTION_BIDIRECTIONAL = 0x9D,
SCSICMD_SERVICE_ACTION_IN_16 = 0x9E,
SCSICMD_SERVICE_ACTION_OUT_16 = 0x9F,
SCSICMD_REPORT_LUNS = 0xA0,
SCSICMD_ATA_PASSTHROUGH_12 = 0xA1,
SCSICMD_SECURITY_PROTOCOL_IN = 0xA2,
SCSICMD_MAINTENANCE_IN = 0xA3,
SCSICMD_MAINTENANCE_OUT = 0xA4,
SCSICMD_REPORT_KEY = 0xA4,
SCSICMD_MOVE_MEDIUM = 0xA5,
SCSICMD_PLAY_AUDIO_12 = 0xA5,
SCSICMD_EXCHANGE_MEDIUM = 0xA6,
SCSICMD_MOVE_MEDIUM_ATTACHED = 0xA7,
SCSICMD_READ_12 = 0xA8,
SCSICMD_SERVICE_ACTION_OUT_12 = 0xA9,
SCSICMD_WRITE_12 = 0xAA,
SCSICMD_SERVICE_ACTION_IN_12 = 0xAB,
SCSICMD_ERASE_12 = 0xAC,
SCSICMD_READ_DVD_STRUCTURE = 0xAD,
SCSICMD_WRITE_AND_VERIFY_12 = 0xAE,
SCSICMD_VERIFY_12 = 0xAF,
SCSICMD_SEARCH_DATA_HIGH_12 = 0xB0,
SCSICMD_SEARCH_DATA_EQUAL_12 = 0xB1,
SCSICMD_SEARCH_DATA_LOW_12 = 0xB2,
SCSICMD_SET_LIMITS_12 = 0xB3,
SCSICMD_READ_ELEMENT_STATUS_ATTACHED = 0xB4,
SCSICMD_SECURITY_PROTOCOL_OUT = 0xB5,
SCSICMD_SEND_VOLUME_TAG = 0xB6,
SCSICMD_READ_DEFECT_DATA_12 = 0xB7,
SCSICMD_READ_ELEMENT_STATUS = 0xB8,
SCSICMD_READ_CD_MSF = 0xB9,
SCSICMD_REDUNDANCY_GROUP_IN = 0xBA,
SCSICMD_REDUNDANCY_GROUP_OUT = 0xBB,
SCSICMD_SPARE_IN = 0xBC,
SCSICMD_SPARE_OUT = 0xBD,
SCSICMD_VOLUME_SET_IN = 0xBE,
SCSICMD_VOLUME_SET_OUT = 0xBF,
};
#define TD_READ64 24

View File

@ -5,16 +5,20 @@
#include <fcntl.h>
#include <unistd.h>
#include <endian.h>
#include "../hunk-reloc.h"
#include "piscsi.h"
#include "piscsi-enums.h"
#include "../hunk-reloc.h"
#include "../../../config_file/config_file.h"
#include "../../../gpio/ps_protocol.h"
#define BE(val) be32toh(val)
#define BE16(val) be16toh(val)
// Comment these lines to restore debug output:
#define printf(...)
#define DEBUG(...)
//#define DEBUG printf
#define DEBUG_TRIVIAL(...)
//#define DEBUG_TRIVIAL printf
#define stop_cpu_emulation(...)
#ifdef FAKESTORM
@ -25,6 +29,10 @@ extern struct emulator_config *cfg;
extern void stop_cpu_emulation(uint8_t disasm_cur);
struct piscsi_dev devs[8];
struct piscsi_fs filesystems[NUM_FILESYSTEMS];
uint8_t piscsi_num_fs = 0;
uint8_t piscsi_cur_drive = 0;
uint32_t piscsi_u32[4];
uint32_t piscsi_dbg[8];
@ -33,7 +41,10 @@ uint8_t *piscsi_rom_ptr;
uint32_t rom_partitions[128];
uint32_t rom_partition_prio[128];
uint32_t rom_cur_partition = 0;
uint32_t rom_partition_dostype[128];
uint32_t rom_cur_partition = 0, rom_cur_fs = 0;
extern unsigned char ac_piscsi_rom[];
@ -58,7 +69,7 @@ void piscsi_init() {
FILE *in = fopen("./platforms/amiga/piscsi/piscsi.rom", "rb");
if (in == NULL) {
printf("[PISCSI] Could not open PISCSI Boot ROM file for reading.\n");
printf("[PISCSI] Could not open PISCSI Boot ROM file for reading!\n");
// Zero out the boot ROM offset from the autoconfig ROM.
ac_piscsi_rom[20] = 0;
ac_piscsi_rom[21] = 0;
@ -71,12 +82,9 @@ void piscsi_init() {
fseek(in, 0, SEEK_SET);
piscsi_rom_ptr = malloc(piscsi_rom_size);
fread(piscsi_rom_ptr, piscsi_rom_size, 1, in);
fclose(in);
// Parse the hunks in the device driver to find relocation offsets
in = fopen("./platforms/amiga/piscsi/device_driver_amiga/pi-scsi.device", "rb");
fseek(in, 0x0, SEEK_SET);
process_hunks(in, &piscsi_hinfo, piscsi_hreloc);
fseek(in, PISCSI_DRIVER_OFFSET, SEEK_SET);
process_hunks(in, &piscsi_hinfo, piscsi_hreloc, PISCSI_DRIVER_OFFSET);
fclose(in);
printf("[PISCSI] Loaded Boot ROM.\n");
@ -95,22 +103,28 @@ void piscsi_find_partitions(struct piscsi_dev *d) {
}
if (!d->rdb || d->rdb->rdb_PartitionList == 0) {
printf("[PISCSI] No partitions on disk.\n");
DEBUG("[PISCSI] No partitions on disk.\n");
return;
}
char *block = malloc(512);
lseek(fd, be32toh(d->rdb->rdb_PartitionList) * 512, SEEK_SET);
lseek(fd, BE(d->rdb->rdb_PartitionList) * 512, SEEK_SET);
next_partition:;
read(fd, block, 512);
uint32_t first = be32toh(*((uint32_t *)&block[0]));
if (first != PART_IDENTIFIER) {
DEBUG("Entry at block %d is not a valid partition. Aborting.\n", BE(d->rdb->rdb_PartitionList));
return;
}
struct PartitionBlock *pb = (struct PartitionBlock *)block;
tmp = pb->pb_DriveName[0];
pb->pb_DriveName[tmp + 1] = 0x00;
printf("[PISCSI] Partition %d: %s\n", cur_partition, pb->pb_DriveName + 1);
printf("Checksum: %.8X HostID: %d\n", BE(pb->pb_ChkSum), BE(pb->pb_HostID));
printf("Flags: %d (%.8X) Devflags: %d (%.8X)\n", BE(pb->pb_Flags), BE(pb->pb_Flags), BE(pb->pb_DevFlags), BE(pb->pb_DevFlags));
DEBUG("[PISCSI] Partition %d: %s\n", cur_partition, pb->pb_DriveName + 1);
DEBUG("Checksum: %.8X HostID: %d\n", BE(pb->pb_ChkSum), BE(pb->pb_HostID));
DEBUG("Flags: %d (%.8X) Devflags: %d (%.8X)\n", BE(pb->pb_Flags), BE(pb->pb_Flags), BE(pb->pb_DevFlags), BE(pb->pb_DevFlags));
d->pb[cur_partition] = pb;
if (d->pb[cur_partition]->pb_Next != 0xFFFFFFFF) {
@ -118,11 +132,12 @@ next_partition:;
block = malloc(512);
lseek64(fd, next * 512, SEEK_SET);
cur_partition++;
printf("[PISCSI] Next partition at block %d.\n", be32toh(pb->pb_Next));
DEBUG("[PISCSI] Next partition at block %d.\n", be32toh(pb->pb_Next));
goto next_partition;
}
printf("[PISCSI] No more partitions on disk.\n");
DEBUG("[PISCSI] No more partitions on disk.\n");
d->num_partitions = cur_partition + 1;
d->fshd_offs = lseek64(fd, 0, SEEK_CUR);
return;
}
@ -142,11 +157,14 @@ int piscsi_parse_rdb(struct piscsi_dev *d) {
goto no_rdb_found;
rdb_found:;
struct RigidDiskBlock *rdb = (struct RigidDiskBlock *)block;
printf("[PISCSI] RDB found at block %d.\n", i);
DEBUG("[PISCSI] RDB found at block %d.\n", i);
d->c = be32toh(rdb->rdb_Cylinders);
d->h = be32toh(rdb->rdb_Heads);
d->s = be32toh(rdb->rdb_Sectors);
printf("[PISCSI] RDB - first partition at block %d.\n", be32toh(rdb->rdb_PartitionList));
d->num_partitions = 0;
DEBUG("[PISCSI] RDB - first partition at block %d.\n", be32toh(rdb->rdb_PartitionList));
if (d->rdb)
free(d->rdb);
d->rdb = rdb;
sprintf(d->rdb->rdb_DriveInitName, "pi-scsi.device");
return 0;
@ -158,6 +176,96 @@ no_rdb_found:;
return -1;
}
void piscsi_refresh_drives() {
piscsi_num_fs = 0;
for (int i = 0; i < NUM_FILESYSTEMS; i++) {
if (filesystems[i].binary_data) {
free(filesystems[i].binary_data);
filesystems[i].binary_data = NULL;
}
if (filesystems[i].fhb) {
free(filesystems[i].fhb);
filesystems[i].fhb = NULL;
}
filesystems[i].h_info.current_hunk = 0;
filesystems[i].h_info.reloc_hunks = 0;
filesystems[i].FS_ID = 0;
filesystems[i].handler = 0;
}
rom_cur_fs = 0;
for (int i = 0; i < NUM_UNITS; i++) {
if (devs[i].fd != -1) {
piscsi_parse_rdb(&devs[i]);
piscsi_find_partitions(&devs[i]);
piscsi_find_filesystems(&devs[i]);
}
}
}
void piscsi_find_filesystems(struct piscsi_dev *d) {
if (!d->num_partitions)
return;
uint8_t fs_found = 0;
uint8_t *fhb_block = malloc(512);
lseek64(d->fd, d->fshd_offs, SEEK_SET);
struct FileSysHeaderBlock *fhb = (struct FileSysHeaderBlock *)fhb_block;
read(d->fd, fhb_block, 512);
while (BE(fhb->fhb_ID) == FS_IDENTIFIER) {
char *dosID = (char *)&fhb->fhb_DosType;
uint16_t *fsVer = (uint16_t *)&fhb->fhb_Version;
DEBUG("[FSHD] FSHD Block found.\n");
DEBUG("[FSHD] HostID: %d Next: %d Size: %d\n", BE(fhb->fhb_HostID), BE(fhb->fhb_Next), BE(fhb->fhb_SummedLongs));
DEBUG("[FSHD] Flags: %.8X DOSType: %c%c%c/%d\n", BE(fhb->fhb_Flags), dosID[0], dosID[1], dosID[2], dosID[3]);
DEBUG("[FSHD] Version: %d.%d\n", BE16(fsVer[0]), BE16(fsVer[1]));
DEBUG("[FSHD] Patchflags: %d Type: %d\n", BE(fhb->fhb_PatchFlags), BE(fhb->fhb_Type));
DEBUG("[FSHD] Task: %d Lock: %d\n", BE(fhb->fhb_Task), BE(fhb->fhb_Lock));
DEBUG("[FSHD] Handler: %d StackSize: %d\n", BE(fhb->fhb_Handler), BE(fhb->fhb_StackSize));
DEBUG("[FSHD] Prio: %d Startup: %d\n", BE(fhb->fhb_Priority), BE(fhb->fhb_Startup));
DEBUG("[FSHD] SegListBlocks: %d GlobalVec: %d\n", BE(fhb->fhb_Priority), BE(fhb->fhb_Startup));
DEBUG("[FSHD] FileSysName: %s\n", fhb->fhb_FileSysName + 1);
for (int i = 0; i < NUM_FILESYSTEMS; i++) {
if (filesystems[i].FS_ID == fhb->fhb_DosType) {
DEBUG("[FSHD] File system %c%c%c/%d already loaded. Skipping.\n", dosID[0], dosID[1], dosID[2], dosID[3]);
if (BE(fhb->fhb_Next) == 0xFFFFFFFF)
goto fs_done;
goto skip_fs_load_lseg;
}
}
if (load_lseg(d->fd, &filesystems[piscsi_num_fs].binary_data, &filesystems[piscsi_num_fs].h_info, filesystems[piscsi_num_fs].relocs) != -1) {
filesystems[piscsi_num_fs].FS_ID = fhb->fhb_DosType;
filesystems[piscsi_num_fs].fhb = fhb;
printf("[FSHD] Loaded and set up file system %d: %c%c%c/%d\n", piscsi_num_fs + 1, dosID[0], dosID[1], dosID[2], dosID[3]);
piscsi_num_fs++;
}
skip_fs_load_lseg:;
fs_found++;
lseek64(d->fd, BE(fhb->fhb_Next) * 512, SEEK_SET);
fhb_block = malloc(512);
fhb = (struct FileSysHeaderBlock *)fhb_block;
read(d->fd, fhb_block, 512);
}
if (!fs_found)
DEBUG("[!!!FSHD] No file systems found on hard drive!\n");
fs_done:;
if (fhb_block)
free(fhb_block);
}
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);
@ -179,20 +287,20 @@ void piscsi_map_drive(char *filename, uint8_t index) {
printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
if (piscsi_parse_rdb(d) == -1) {
printf("[PISCSI] No RDB found on disk, making up some CHS values.\n");
d->h = 64;
DEBUG("[PISCSI] No RDB found on disk, making up some CHS values.\n");
d->h = 16;
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);
piscsi_find_partitions(d);
//stop_cpu_emulation(1);
piscsi_find_filesystems(d);
}
void piscsi_unmap_drive(uint8_t index) {
if (devs[index].fd != -1) {
printf("[PISCSI] Unmapped drive %d.\n", index);
DEBUG("[PISCSI] Unmapped drive %d.\n", index);
close (devs[index].fd);
devs[index].fd = -1;
}
@ -233,65 +341,129 @@ char *io_cmd_name(int index) {
case NSCMD_TD_FORMAT64: return "NSCMD_TD_FORMAT64";
default:
return "!!!Unhandled IO command";
return "[!!!PISCSI] Unhandled IO command";
}
}
#define GETSCSINAME(a) case a: return ""#a"";
#define SCSIUNHANDLED(a) return "[!!!PISCSI] Unhandled SCSI command "#a"";
char *scsi_cmd_name(int index) {
switch(index) {
case 0x00: return "TEST UNIT READY";
case 0x12: return "INQUIRY";
case 0x08: return "READ (6)";
case 0x0A: return "WRITE (6)";
case 0x28: return "READ (10)";
case 0x2A: return "WRITE (10)";
case 0x25: return "READ CAPACITY";
case 0x1A: return "MODE SENSE";
case 0x37: return "READ DEFECT DATA";
GETSCSINAME(SCSICMD_TEST_UNIT_READY);
GETSCSINAME(SCSICMD_INQUIRY);
GETSCSINAME(SCSICMD_READ_6);
GETSCSINAME(SCSICMD_WRITE_6);
GETSCSINAME(SCSICMD_READ_10);
GETSCSINAME(SCSICMD_WRITE_10);
GETSCSINAME(SCSICMD_READ_CAPACITY_10);
GETSCSINAME(SCSICMD_MODE_SENSE_6);
GETSCSINAME(SCSICMD_READ_DEFECT_DATA_10);
default:
return "!!!Unhandled SCSI command";
return "[!!!PISCSI] Unhandled SCSI command";
}
}
void print_piscsi_debug_message(int index) {
int32_t r = 0;
switch (index) {
case DBG_INIT:
printf("[PISCSI] Initializing devices.\n");
DEBUG("[PISCSI] Initializing devices.\n");
break;
case DBG_OPENDEV:
printf("[PISCSI] Opening device %d (%d). Flags: %d (%.2X)\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[2]);
if (piscsi_dbg[0] != 255)
DEBUG("[PISCSI] Opening device %d (%d). Flags: %d (%.2X)\n", piscsi_dbg[0], piscsi_dbg[2], piscsi_dbg[1], piscsi_dbg[1]);
break;
case DBG_CLEANUP:
printf("[PISCSI] Cleaning up.\n");
DEBUG("[PISCSI] Cleaning up.\n");
break;
case DBG_CHS:
printf("[PISCSI] C/H/S: %d / %d / %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
DEBUG("[PISCSI] C/H/S: %d / %d / %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
break;
case DBG_BEGINIO:
printf("[PISCSI] BeginIO: io_Command: %d - io_Flags = %d - quick: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
DEBUG("[PISCSI] BeginIO: io_Command: %d (%s) - io_Flags = %d - quick: %d\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]), piscsi_dbg[1], piscsi_dbg[2]);
break;
case DBG_ABORTIO:
printf("[PISCSI] AbortIO!\n");
DEBUG("[PISCSI] AbortIO!\n");
break;
case DBG_SCSICMD:
printf("[PISCSI] SCSI Command %d (%s)\n", piscsi_dbg[1], scsi_cmd_name(piscsi_dbg[1]));
printf("Len: %d - %.2X %.2X %.2X - Command Length: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[3], piscsi_dbg[4]);
DEBUG("[PISCSI] SCSI Command %d (%s)\n", piscsi_dbg[1], scsi_cmd_name(piscsi_dbg[1]));
DEBUG("Len: %d - %.2X %.2X %.2X - Command Length: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[3], piscsi_dbg[4]);
break;
case DBG_SCSI_UNKNOWN_MODESENSE:
printf("SCSI: Unknown modesense %.4X\n", piscsi_dbg[0]);
DEBUG("[!!!PISCSI] SCSI: Unknown modesense %.4X\n", piscsi_dbg[0]);
break;
case DBG_SCSI_UNKNOWN_COMMAND:
printf("SCSI: Unknown command %.4X\n", piscsi_dbg[0]);
DEBUG("[!!!PISCSI] SCSI: Unknown command %.4X\n", piscsi_dbg[0]);
break;
case DBG_SCSIERR:
printf("SCSI: An error occured: %.4X\n", piscsi_dbg[0]);
DEBUG("[!!!PISCSI] SCSI: An error occured: %.4X\n", piscsi_dbg[0]);
break;
case DBG_IOCMD:
printf("[PISCSI] IO Command %d (%s)\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
DEBUG_TRIVIAL("[PISCSI] IO Command %d (%s)\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
break;
case DBG_IOCMD_UNHANDLED:
printf("[PISCSI] WARN: IO command %.4X (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
DEBUG("[!!!PISCSI] WARN: IO command %.4X (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
break;
case DBG_SCSI_FORMATDEVICE:
DEBUG("[PISCSI] Get SCSI FormatDevice MODE SENSE.\n");
break;
case DBG_SCSI_RDG:
DEBUG("[PISCSI] Get SCSI RDG MODE SENSE.\n");
break;
case DBG_SCSI_DEBUG_MODESENSE_6:
DEBUG_TRIVIAL("[PISCSI] SCSI ModeSense debug. Data: %.8X\n", piscsi_dbg[0]);
r = get_mapped_item_by_address(cfg, piscsi_dbg[0]);
if (r != -1) {
uint32_t addr = piscsi_dbg[0] - cfg->map_offset[r];
struct SCSICmd_ModeSense6 *sense = (struct SCSICmd_ModeSense6 *)(&cfg->map_data[r][addr]);
DEBUG_TRIVIAL("[SenseData] CMD: %.2X\n", sense->opcode);
DEBUG_TRIVIAL("[SenseData] DBD: %d\n", sense->reserved_dbd & 0x04);
DEBUG_TRIVIAL("[SenseData] PC: %d\n", (sense->pc_pagecode & 0xC0 >> 6));
DEBUG_TRIVIAL("[SenseData] PageCodes: %.2X %.2X\n", (sense->pc_pagecode & 0x3F), sense->subpage_code);
DEBUG_TRIVIAL("[SenseData] AllocLen: %d\n", sense->alloc_len);
DEBUG_TRIVIAL("[SenseData] Control: %.2X (%d)\n", sense->control, sense->control);
}
else {
DEBUG("[!!!PISCSI] ModeSense data not immediately available.\n");
}
break;
default:
DEBUG("[!!!PISCSI] No debug message available for index %d.\n", index);
break;
}
}
#define DEBUGME_SIMPLE(i, s) case i: DEBUG(s); break;
void piscsi_debugme(uint32_t index) {
switch (index) {
DEBUGME_SIMPLE(1, "[PISCSI-DEBUGME] Arrived at DiagEntry.\n");
DEBUGME_SIMPLE(3, "[PISCSI-DEBUGME] Init: Interrupt disable.\n");
DEBUGME_SIMPLE(4, "[PISCSI-DEBUGME] Init: Copy/reloc driver.\n");
DEBUGME_SIMPLE(5, "[PISCSI-DEBUGME] Init: InitResident.\n");
DEBUGME_SIMPLE(7, "[PISCSI-DEBUGME] Init: Begin partition loop.\n");
DEBUGME_SIMPLE(8, "[PISCSI-DEBUGME] Init: Partition loop done. Cleaning up and returning to Exec.\n");
DEBUGME_SIMPLE(9, "[PISCSI-DEBUGME] Init: Load file systems.\n");
DEBUGME_SIMPLE(10, "[PISCSI-DEBUGME] Init: AllocMem for resident.\n");
DEBUGME_SIMPLE(11, "[PISCSI-DEBUGME] Init: Checking if resident is loaded.\n");
DEBUGME_SIMPLE(22, "[PISCSI-DEBUGME] Arrived at BootEntry.\n");
DEBUGME_SIMPLE(30, "[PISCSI-DEBUGME] LoadFileSystems: Opening FileSystem.resource.\n");
DEBUGME_SIMPLE(33, "[PISCSI-DEBUGME] FileSystem.resource not available, creating.\n");
case 31:
DEBUG("[PISCSI-DEBUGME] OpenResource result: %d\n", piscsi_u32[0]);
break;
case 32:
DEBUG("AAAAHH!\n");
break;
default:
DEBUG("[!!!PISCSI-DEBUGME] No debugme message for index %d!\n", index);
break;
}
if (index == 8) {
stop_cpu_emulation(1);
}
}
@ -307,30 +479,30 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
case PISCSI_CMD_READ:
d = &devs[val];
if (d->fd == -1) {
printf ("[PISCSI] BUG: Attempted read from unmapped drive %d.\n", val);
DEBUG("[!!!PISCSI] BUG: Attempted read from unmapped drive %d.\n", val);
break;
}
if (cmd == PISCSI_CMD_READ) {
printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
DEBUG("[PISCSI-%d] %d byte READ from block %d to address %.8X\n", val, piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
d->lba = piscsi_u32[0];
lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
}
else {
uint64_t src = piscsi_u32[3];
src = (src << 32) | piscsi_u32[0];
printf("[PISCSI] %d byte READ64 from block %lld to address %.8X\n", piscsi_u32[1], (src / 512), piscsi_u32[2]);
DEBUG("[PISCSI-%d] %d byte READ64 from block %lld to address %.8X\n", val, piscsi_u32[1], (src / 512), piscsi_u32[2]);
d->lba = (src / 512);
lseek64(d->fd, src, SEEK_SET);
}
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);
DEBUG_TRIVIAL("[PISCSI-%d] \"DMA\" Read goes to mapped range %d.\n", val, r);
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");
DEBUG_TRIVIAL("[PISCSI-%d] No mapped range found for read.\n", val);
uint8_t c = 0;
for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
read(d->fd, &c, 1);
@ -342,30 +514,30 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
case PISCSI_CMD_WRITE:
d = &devs[val];
if (d->fd == -1) {
printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", val);
DEBUG ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", val);
break;
}
if (cmd == PISCSI_CMD_WRITE) {
printf("[PISCSI] %d byte WRITE to block %d from address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
DEBUG("[PISCSI-%d] %d byte WRITE to block %d from address %.8X\n", val, piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
d->lba = piscsi_u32[0];
lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
}
else {
uint64_t src = piscsi_u32[3];
src = (src << 32) | piscsi_u32[0];
printf("[PISCSI] %d byte WRITE64 to block %lld from address %.8X\n", piscsi_u32[1], (src / 512), piscsi_u32[2]);
DEBUG("[PISCSI-%d] %d byte WRITE64 to block %lld from address %.8X\n", val, piscsi_u32[1], (src / 512), piscsi_u32[2]);
d->lba = (src / 512);
lseek64(d->fd, src, SEEK_SET);
}
r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
if (r != -1) {
printf("[PISCSI] \"DMA\" Write comes from mapped range %d.\n", r);
DEBUG_TRIVIAL("[PISCSI-%d] \"DMA\" Write comes from mapped range %d.\n", val, r);
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");
DEBUG_TRIVIAL("[PISCSI-%d] No mapped range found for write.\n", val);
uint8_t c = 0;
for (uint32_t i = 0; i < piscsi_u32[1]; i++) {
c = read8(piscsi_u32[2] + i);
@ -379,29 +551,32 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
break;
}
case PISCSI_CMD_DRVNUM:
//printf("%d ", val);
if (val % 10 != 0)
piscsi_cur_drive = 255;
else
piscsi_cur_drive = val / 10;
printf("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
if (piscsi_cur_drive > NUM_UNITS)
piscsi_cur_drive = 255;
if (piscsi_cur_drive != 255)
DEBUG("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
break;
case PISCSI_CMD_DEBUGME:
printf("[PISCSI] DebugMe triggered (%d).\n", val);
stop_cpu_emulation(1);
piscsi_debugme(val);
break;
case PISCSI_CMD_DRIVER: {
printf("[PISCSI] Driver copy/patch called, destination address %.8X.\n", val);
DEBUG("[PISCSI] Driver copy/patch called, destination address %.8X.\n", val);
int r = get_mapped_item_by_address(cfg, val);
if (r != -1) {
uint32_t addr = val - cfg->map_offset[r];
uint8_t *dst_data = cfg->map_data[r];
uint8_t cur_partition = 0;
memcpy(dst_data + addr, piscsi_rom_ptr + 0x400, 0x3C00);
memcpy(dst_data + addr, piscsi_rom_ptr + PISCSI_DRIVER_OFFSET, 0x4000 - PISCSI_DRIVER_OFFSET);
piscsi_hinfo.base_offset = val;
reloc_hunks(piscsi_hreloc, dst_data + addr, &piscsi_hinfo);
stop_cpu_emulation(1);
#define PUTNODELONG(val) *(uint32_t *)&dst_data[p_offs] = htobe32(val); p_offs += 4;
#define PUTNODELONGBE(val) *(uint32_t *)&dst_data[p_offs] = val; p_offs += 4;
@ -409,6 +584,7 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
for (int i = 0; i < 128; i++) {
rom_partitions[i] = 0;
rom_partition_prio[i] = 0;
rom_partition_dostype[i] = 0;
}
rom_cur_partition = 0;
@ -416,12 +592,16 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
sprintf((char *)dst_data + data_addr, "pi-scsi.device");
uint32_t addr2 = addr + 0x4000;
for (int i = 0; i < NUM_UNITS; i++) {
piscsi_find_partitions(&devs[i]);
if (devs[i].fd != -1)
piscsi_find_partitions(&devs[i]);
else
goto skip_disk;
if (devs[i].num_partitions) {
uint32_t p_offs = addr2;
printf("[PISCSI] Adding %d partitions for unit %d\n", devs[i].num_partitions, i);
DEBUG("[PISCSI] Adding %d partitions for unit %d\n", devs[i].num_partitions, i);
for (uint32_t j = 0; j < devs[i].num_partitions; j++) {
printf("Partition %d: %s\n", j, devs[i].pb[j]->pb_DriveName + 1);
DEBUG("Partition %d: %s\n", j, devs[i].pb[j]->pb_DriveName + 1);
sprintf((char *)dst_data + p_offs, "%s", devs[i].pb[j]->pb_DriveName + 1);
p_offs += 0x20;
PUTNODELONG(addr2 + cfg->map_offset[r]);
@ -434,42 +614,86 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
struct pihd_dosnode_data *dat = (struct pihd_dosnode_data *)(&dst_data[addr2+0x20]);
if (BE(devs[i].pb[j]->pb_Flags) & 0x01) {
printf("Partition is bootable.\n");
DEBUG("Partition is bootable.\n");
rom_partition_prio[cur_partition] = 0;
dat->priority = 0;
}
else {
printf("Partition is not bootable.\n");
DEBUG("Partition is not bootable.\n");
rom_partition_prio[cur_partition] = -128;
dat->priority = htobe32(-128);
}
printf("DOSNode Data:\n");
printf("Name: %s Device: %s\n", dst_data + addr2, dst_data + data_addr);
printf("Unit: %d Flags: %d Pad1: %d\n", BE(dat->unit), BE(dat->flags), BE(dat->pad1));
printf("Node len: %d Block len: %d\n", BE(dat->node_len) * 4, BE(dat->block_len) * 4);
printf("H: %d SPB: %d BPS: %d\n", BE(dat->surf), BE(dat->secs_per_block), BE(dat->blocks_per_track));
printf("Reserved: %d Prealloc: %d\n", BE(dat->reserved_blocks), BE(dat->pad2));
printf("Interleaved: %d Buffers: %d Memtype: %d\n", BE(dat->interleave), BE(dat->buffers), BE(dat->mem_type));
printf("Lowcyl: %d Highcyl: %d Prio: %d\n", BE(dat->lowcyl), BE(dat->highcyl), BE(dat->priority));
printf("Maxtransfer: %.8X Mask: %.8X\n", BE(dat->maxtransfer), BE(dat->transfer_mask));
printf("DOSType: %.8X\n", BE(dat->dostype));
DEBUG("DOSNode Data:\n");
DEBUG("Name: %s Device: %s\n", dst_data + addr2, dst_data + data_addr);
DEBUG("Unit: %d Flags: %d Pad1: %d\n", BE(dat->unit), BE(dat->flags), BE(dat->pad1));
DEBUG("Node len: %d Block len: %d\n", BE(dat->node_len) * 4, BE(dat->block_len) * 4);
DEBUG("H: %d SPB: %d BPS: %d\n", BE(dat->surf), BE(dat->secs_per_block), BE(dat->blocks_per_track));
DEBUG("Reserved: %d Prealloc: %d\n", BE(dat->reserved_blocks), BE(dat->pad2));
DEBUG("Interleaved: %d Buffers: %d Memtype: %d\n", BE(dat->interleave), BE(dat->buffers), BE(dat->mem_type));
DEBUG("Lowcyl: %d Highcyl: %d Prio: %d\n", BE(dat->lowcyl), BE(dat->highcyl), BE(dat->priority));
DEBUG("Maxtransfer: %.8X Mask: %.8X\n", BE(dat->maxtransfer), BE(dat->transfer_mask));
DEBUG("DOSType: %.8X\n", BE(dat->dostype));
rom_partitions[cur_partition] = addr2 + 0x20 + cfg->map_offset[r];
rom_partition_dostype[cur_partition] = dat->dostype;
cur_partition++;
addr2 += 0x100;
p_offs = addr2;
}
}
skip_disk:;
}
}
break;
}
case PISCSI_CMD_NEXTPART:
printf("[PISCSI] Switch partition %d -> %d\n", rom_cur_partition, rom_cur_partition + 1);
DEBUG("[PISCSI] Switch partition %d -> %d\n", rom_cur_partition, rom_cur_partition + 1);
rom_cur_partition++;
break;
case PISCSI_CMD_NEXTFS:
DEBUG("[PISCSI] Switch file file system %d -> %d\n", rom_cur_fs, rom_cur_fs + 1);
rom_cur_fs++;
break;
case PISCSI_CMD_COPYFS:
DEBUG("[PISCSI] Copy file system %d to %.8X and reloc.\n", rom_cur_fs, piscsi_u32[2]);
r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
if (r != -1) {
uint32_t addr = piscsi_u32[2] - cfg->map_offset[r];
memset(cfg->map_data[r] + addr, 0x00, filesystems[rom_cur_fs].h_info.alloc_size);
memcpy(cfg->map_data[r] + addr, filesystems[rom_cur_fs].binary_data, filesystems[rom_cur_fs].h_info.byte_size);
filesystems[rom_cur_fs].h_info.base_offset = piscsi_u32[2];
reloc_hunks(filesystems[rom_cur_fs].relocs, cfg->map_data[r] + addr, &filesystems[rom_cur_fs].h_info);
filesystems[rom_cur_fs].handler = piscsi_u32[2];
}
break;
case PISCSI_CMD_SETFSH: {
int i = 0;
DEBUG("[PISCSI] Set handler for partition %d (DeviceNode: %.8X)\n", rom_cur_partition, val);
r = get_mapped_item_by_address(cfg, val);
if (r != -1) {
uint32_t addr = val - cfg->map_offset[r];
struct DeviceNode *node = (struct DeviceNode *)(cfg->map_data[r] + addr);
char *dosID = (char *)&rom_partition_dostype[rom_cur_partition];
DEBUG("[PISCSI] Partition DOSType is %c%c%c/%d\n", dosID[0], dosID[1], dosID[2], dosID[3]);
for (i = 0; i < piscsi_num_fs; i++) {
if (rom_partition_dostype[rom_cur_partition] == filesystems[i].FS_ID) {
node->dn_SegList = htobe32(filesystems[i].handler);
goto fs_found;
}
}
DEBUG("[!!!PISCSI] Found no handler for file system!\n");
fs_found:;
DEBUG("[FS-HANDLER] Next: %d Type: %d\n", BE(node->dn_Next), BE(node->dn_Type));
DEBUG("[FS-HANDLER] Task: %d Lock: %d\n", BE(node->dn_Task), BE(node->dn_Lock));
DEBUG("[FS-HANDLER] Handler: %d Stacksize: %d\n", BE((uint32_t)node->dn_Handler), BE(node->dn_StackSize));
DEBUG("[FS-HANDLER] Priority: %d Startup: %d\n", BE((uint32_t)node->dn_Priority), BE(node->dn_Startup));
DEBUG("[FS-HANDLER] SegList: %d GlobalVec: %d\n", BE((uint32_t)node->dn_SegList), BE(node->dn_GlobalVec));
DEBUG("[PISCSI] Handler for partition %.8X set to %.8X (%.8X).\n", BE((uint32_t)node->dn_Name), filesystems[i].FS_ID, filesystems[i].handler);
}
break;
}
case PISCSI_DBG_VAL1: case PISCSI_DBG_VAL2: case PISCSI_DBG_VAL3: case PISCSI_DBG_VAL4:
case PISCSI_DBG_VAL5: case PISCSI_DBG_VAL6: case PISCSI_DBG_VAL7: case PISCSI_DBG_VAL8: {
int i = ((addr & 0xFFFF) - PISCSI_DBG_VAL1) / 4;
@ -480,7 +704,7 @@ void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
print_piscsi_debug_message(val);
break;
default:
printf("[PISCSI] WARN: Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
DEBUG("[!!!PISCSI] WARN: Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
break;
}
}
@ -493,20 +717,20 @@ uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
if (romoffs < (piscsi_rom_size + PIB)) {
//printf("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
//DEBUG("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
uint32_t v = 0;
switch (type) {
case OP_TYPE_BYTE:
v = piscsi_rom_ptr[romoffs - PIB];
//printf("%.2X\n", v);
//DEBUG("%.2X\n", v);
break;
case OP_TYPE_WORD:
v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
//printf("%.4X\n", v);
//DEBUG("%.4X\n", v);
break;
case OP_TYPE_LONGWORD:
v = be32toh(*((uint32_t *)&piscsi_rom_ptr[romoffs - PIB]));
//printf("%.8X\n", v);
//DEBUG("%.8X\n", v);
break;
}
return v;
@ -522,45 +746,51 @@ uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
}
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);
DEBUG("[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);
DEBUG("[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);
DEBUG("[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);
DEBUG("[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);
DEBUG("[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);
DEBUG("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
DEBUG("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
return blox;
break;
}
case PISCSI_CMD_GETPART: {
printf("[PISCSI] Get ROM partition %d offset: %.8X\n", rom_cur_partition, rom_partitions[rom_cur_partition]);
DEBUG("[PISCSI] Get ROM partition %d offset: %.8X\n", rom_cur_partition, rom_partitions[rom_cur_partition]);
return rom_partitions[rom_cur_partition];
break;
}
case PISCSI_CMD_GETPRIO:
printf("[PISCSI] Get partition %d boot priority: %d\n", rom_cur_partition, rom_partition_prio[rom_cur_partition]);
DEBUG("[PISCSI] Get partition %d boot priority: %d\n", rom_cur_partition, rom_partition_prio[rom_cur_partition]);
return rom_partition_prio[rom_cur_partition];
break;
case PISCSI_CMD_CHECKFS:
DEBUG("[PISCSI] Get current loaded file system: %.8X\n", filesystems[rom_cur_fs].FS_ID);
return filesystems[rom_cur_fs].FS_ID;
case PISCSI_CMD_FSSIZE:
DEBUG("[PISCSI] Get alloc size of loaded file system: %d\n", filesystems[rom_cur_fs].h_info.alloc_size);
return filesystems[rom_cur_fs].h_info.alloc_size;
default:
printf("[PISCSI] Unhandled %s register read from %.8X\n", op_type_names[type], addr);
DEBUG("[!!!PISCSI] WARN: Unhandled %s register read from %.8X\n", op_type_names[type], addr);
break;
}

View File

@ -47,15 +47,16 @@
#define NSCMD_TD_FORMAT64 0xC003
#define RDB_BLOCK_LIMIT 16
// RDSK
#define RDB_IDENTIFIER 0x5244534B
// PART
#define PART_IDENTIFIER 0x50415254
// FSHD
#define FS_IDENTIFIER 0x46534844
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);
#define PISCSI_DRIVER_OFFSET 0x1000
#define NUM_FILESYSTEMS 32
struct piscsi_dev {
uint32_t c;
@ -64,11 +65,21 @@ struct piscsi_dev {
int32_t fd;
uint32_t lba;
uint32_t num_partitions;
uint32_t fshd_offs;
// Will parse max eight partitions per disk
struct PartitionBlock *pb[16];
struct RigidDiskBlock *rdb;
};
struct piscsi_fs {
struct FileSysHeaderBlock * fhb;
uint32_t FS_ID;
uint32_t handler;
struct hunk_reloc relocs[512];
struct hunk_info h_info;
uint8_t *binary_data;
};
// .long 0 /* dos disk name */
// .long 0 /* device file name */
// .long 0 /* unit */
@ -166,6 +177,20 @@ struct RigidDiskBlock {
char rdb_DriveInitName[40];
};
struct DeviceNode {
uint32_t dn_Next;
uint32_t dn_Type;
uint32_t dn_Task;
uint32_t dn_Lock;
uint8_t *dn_Handler;
uint32_t dn_StackSize;
int32_t dn_Priority;
uint32_t dn_Startup;
uint32_t dn_SegList;
uint32_t dn_GlobalVec;
uint8_t *dn_Name;
};
struct PartitionBlock {
uint32_t pb_ID;
uint32_t pb_SummedLongs;
@ -180,3 +205,45 @@ struct PartitionBlock {
uint32_t pb_Environment[20];
uint32_t pb_EReserved[12];
};
struct SCSICmd_ModeSense6 {
uint8_t opcode;
uint8_t reserved_dbd;
uint8_t pc_pagecode;
uint8_t subpage_code;
uint8_t alloc_len;
uint8_t control;
};
struct FileSysHeaderBlock {
uint32_t fhb_ID;
uint32_t fhb_SummedLongs;
int32_t fhb_ChkSum;
uint32_t fhb_HostID;
uint32_t fhb_Next;
uint32_t fhb_Flags;
uint32_t fhb_Reserved1[2];
uint32_t fhb_DosType;
uint32_t fhb_Version;
uint32_t fhb_PatchFlags;
uint32_t fhb_Type;
uint32_t fhb_Task;
uint32_t fhb_Lock;
uint32_t fhb_Handler;
uint32_t fhb_StackSize;
int32_t fhb_Priority;
int32_t fhb_Startup;
int32_t fhb_SegListBlocks;
int32_t fhb_GlobalVec;
uint32_t fhb_Reserved2[23];
uint8_t fhb_FileSysName[84];
};
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_find_filesystems(struct piscsi_dev *d);
void piscsi_refresh_drives();

Binary file not shown.

View File

@ -1,15 +1,23 @@
# PiSCSI Interface/Device driver for Amiga
Intended to be used as a high performance replacement for scsi.device, can currently be used for mounting raw RDB disk images (RDSK) for use in Workbench.
A high performance replacement for scsi.device, allowing automatic booting and mounting of raw hard disk (RDB/RDSK) images.
This driver and interface is work in progress, do not use it in conjunction with any critical data that you need to survive.
# Instructions
To use the PiSCSI interface, simply enable it by uncommenting the `setvar piscsi` line in default.cfg, or add it to the config file you're currently using.
Add disk images to the PiSCSI interface by uncommenting the `piscsi0` and `piscsi1` lines and editing them to point at the disk image(s) you want to use.
Physical drives can also be mounted using their mount point files on Linux, such as `/dev/sda` for a USB stick, but keep in mind that this is dangerous as it can destroy the contents of the disk.
You can mount up to 7 disk images using setvar `piscsi0` through `piscsi6`.
# Making changes to the driver
If you make changes to the driver, you can always test these on the Amiga as a regular file in `DEVS:`, but the Z2 device has to be disabled for this to work properly.
If you use the boot ROM, the separate `pi-scsi.device` driver file currently has to match the one in `piscsi.rom`. This is due to an oversight, and will probably be addressed at some point...
Steps to create an updated boot ROM, all of these are done in the `device_driver_amiga` directory:
* (Optional) If you've made changes to bootrom.s, first run `./build.sh`.
@ -18,17 +26,8 @@ Steps to create an updated boot ROM, all of these are done in the `device_driver
* (Optional) If you haven't previously compiled the `makerom` binary, or the code for it has been updated since last time, simply run `gcc makerom.c -o makerom`
* Run `./makerom` to assemble the boot ROM file, it's automatically in the correct place for the emulator to find it.
# Instructions
# If you for instance want to mount a FAT32 disk with fat95, these old instructions may be of some use:
In a perfect world, the PiSCSI boot ROM would automatically detect drives/partitions and add them as boot nodes to be available during early startup, but this is not yet possible.
To enable the PiSCSI interface, uncomment the `setvar piscsi` line in default.cfg, or add it to the config file you're currently using.
Add disk images to the PiSCSI interface by uncommenting the `piscsi0` and `piscsi1` lines and editing them to point at the disk image(s) you want to use. `piscsi0` through `piscsi6` are available for a total of seven mapped drives.
To get a hard drive image mounted when WB starts, you need a few things:
* Copy pi-scsi.device from the `device_driver_amiga` folder to `SYS:Devs` on your Amiga.
If you're super savvy, the driver is also available in "RAM" at the address `$80004400` because that's where the PiSCSI interface keeps the boot ROM, so you can technically just write it to a file on the Amiga from there.
* Download giggledisk from http://www.geit.de/eng_giggledisk.html or https://aminet.net/package/disk/misc/giggledisk to make MountLists for attached devices.
Place the giggledisk binary in `C:` or something so that it's available in the search path.
* It might be a good idea to have fat95 installed on your Amiga, in case you want to use FAT32 images or other file systems that fat95 can handle: https://aminet.net/package/disk/misc/fat95

View File

@ -62,6 +62,9 @@ void rtg_update_screen();
unsigned int rtg_read(uint32_t address, uint8_t mode) {
//printf("%s read from RTG: %.8X\n", op_type_names[mode], address);
if (address == RTG_COMMAND) {
return 0xFFCF;
}
if (address >= PIGFX_REG_SIZE) {
if (rtg_mem && (address - PIGFX_REG_SIZE) < PIGFX_UPPER) {
switch (mode) {

View File

@ -255,12 +255,19 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t
#define DECODE_PLANAR_PIXEL(a) \
switch (planes) { \
case 8: if (layer_mask & 0x80 && bmp_data[(plane_size * 7) + cur_byte] & cur_bit) a |= 0x80; \
/* Fallthrough */ \
case 7: if (layer_mask & 0x40 && bmp_data[(plane_size * 6) + cur_byte] & cur_bit) a |= 0x40; \
/* Fallthrough */ \
case 6: if (layer_mask & 0x20 && bmp_data[(plane_size * 5) + cur_byte] & cur_bit) a |= 0x20; \
/* Fallthrough */ \
case 5: if (layer_mask & 0x10 && bmp_data[(plane_size * 4) + cur_byte] & cur_bit) a |= 0x10; \
/* Fallthrough */ \
case 4: if (layer_mask & 0x08 && bmp_data[(plane_size * 3) + cur_byte] & cur_bit) a |= 0x08; \
/* Fallthrough */ \
case 3: if (layer_mask & 0x04 && bmp_data[(plane_size * 2) + cur_byte] & cur_bit) a |= 0x04; \
/* Fallthrough */ \
case 2: if (layer_mask & 0x02 && bmp_data[plane_size + cur_byte] & cur_bit) a |= 0x02; \
/* Fallthrough */ \
case 1: if (layer_mask & 0x01 && bmp_data[cur_byte] & cur_bit) a |= 0x01; \
break; \
}
@ -268,12 +275,19 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t
#define DECODE_INVERTED_PLANAR_PIXEL(a) \
switch (planes) { \
case 8: if (layer_mask & 0x80 && (bmp_data[(plane_size * 7) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x80; \
/* Fallthrough */ \
case 7: if (layer_mask & 0x40 && (bmp_data[(plane_size * 6) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x40; \
/* Fallthrough */ \
case 6: if (layer_mask & 0x20 && (bmp_data[(plane_size * 5) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x20; \
/* Fallthrough */ \
case 5: if (layer_mask & 0x10 && (bmp_data[(plane_size * 4) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x10; \
/* Fallthrough */ \
case 4: if (layer_mask & 0x08 && (bmp_data[(plane_size * 3) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x08; \
/* Fallthrough */ \
case 3: if (layer_mask & 0x04 && (bmp_data[(plane_size * 2) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x04; \
/* Fallthrough */ \
case 2: if (layer_mask & 0x02 && (bmp_data[plane_size + cur_byte] ^ 0xFF) & cur_bit) a |= 0x02; \
/* Fallthrough */ \
case 1: if (layer_mask & 0x01 && (bmp_data[cur_byte] ^ 0xFF) & cur_bit) a |= 0x01; \
break; \
}

View File

@ -21,6 +21,8 @@
#define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(b->RegisterBase)+cmd) = val;
#define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(b->RegisterBase)+cmd) = val;
#define CHECKRTG *((unsigned short *)(CARD_OFFSET))
#define CARD_OFFSET 0x70000000
#define CARD_REGSIZE 0x00010000
#define CARD_MEMSIZE 0x02000000 // 32MB "VRAM"
@ -225,6 +227,12 @@ static BYTE card_initialized;
int FindCard(__REGA0(struct BoardInfo* b)) {
//if (card_already_found)
// return 1;
uint16_t card_check = CHECKRTG;
if (card_check != 0xFFCF) {
// RTG not enabled
return 0;
}
struct ConfigDev* cd = NULL;
struct ExpansionBase *ExpansionBase = NULL;
struct DOSBase *DOSBase = NULL;