Still not quite working, only FFS working for now.
*.img
*.hdf
*.rom
+*.dll
+*.bin
+*.exe
+*.stackdump
!/platforms/amiga/piscsi/*.rom
/m68kmake
/m68kmake.exe
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
#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"
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;
int mem_fd, mouse_fd = -1, keyboard_fd = -1;
int mem_fd_gpclk;
-int gayle_emulation_enabled = 1;
int irq;
int gayleirq;
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;
do_disasm = 0;
}
-//unsigned char g_kick[524288];
-//unsigned char g_ram[FASTSIZE + 1]; /* RAM */
int ovl;
static volatile unsigned char maprom;
// 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 {
#include "gayle-ide/ide.h"
#include "amiga-registers.h"
+//#define DEBUG(...)
+#define DEBUG printf
+
uint8_t gary_cfg[8];
uint8_t ramsey_cfg = 0x08;
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;
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;
}
}
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 {
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) {
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) {
}
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) {
}
uint8_t readGayleB(unsigned int address) {
- 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 (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;
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) {
}
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) {
#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"
ac_z2_current_pic = 0;
ac_z3_current_pic = 0;
+ if (piscsi_enabled)
+ piscsi_refresh_drives();
+
adjust_ranges_amiga(cfg);
}
#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) {
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;
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++) {
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;
*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;
+}
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;
};
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);
FindResident EQU -96
OpenLibrary EQU -552
CloseLibrary EQU -414
+OpenResource EQU -$1F2
+AddResource EQU -$1E6
; Expansion stuff
MakeDosNode EQU -144
; 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 ***************************************************
**********************************************************************
;
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
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
#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
#include <string.h>
#include <stdlib.h>
-#define BOOTLDR_SIZE 0x400
+#define BOOTLDR_SIZE 0x1000
#define DIAG_TOTAL_SIZE 0x4000
char *rombuf, *zerobuf, *devicebuf;
uint8_t read_only;
uint8_t motor;
uint8_t unit_num;
+ uint16_t scsi_num;
uint16_t h, s;
uint32_t c;
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);
//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;
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];
-
- blocks = scsi->scsi_Command[7];
- blocks = (blocks << 8) | scsi->scsi_Command[8];
- break;
- }
-
- WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
+ 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 = *(uint16_t *)(&scsi->scsi_Command[7]);
+ /*blocks = scsi->scsi_Command[7];
+ blocks = (blocks << 8) | scsi->scsi_Command[8];*/
+
+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;
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;
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);
}
break;
- case 0x37: // READ DEFECT DATA (10)
+ case SCSICMD_READ_DEFECT_DATA_10:
break;
- case 0x40: // CHANGE DEFINITION
+ case SCSICMD_CHANGE_DEFINITION:
break;
default:
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,
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
#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
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];
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[];
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;
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");
}
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) {
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;
}
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;
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);
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;
}
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);
+ }
}
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);
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);
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;
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;
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]);
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;
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;
}
}
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;
}
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;
}
#define NSCMD_TD_FORMAT64 0xC003
#define RDB_BLOCK_LIMIT 16
-#define RDB_IDENTIFIER 0x5244534B
-
-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);
+// RDSK
+#define RDB_IDENTIFIER 0x5244534B
+// PART
+#define PART_IDENTIFIER 0x50415254
+// FSHD
+#define FS_IDENTIFIER 0x46534844
-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;
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 */
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;
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();
# 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`.
* (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
-
-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.
+# If you for instance want to mount a FAT32 disk with fat95, these old instructions may be of some use:
-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
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) {
#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; \
}
#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; \
}
#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"
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;