WinUAE/idecontrollers.cpp
2022-09-21 15:25:11 +03:00

3176 lines
81 KiB
C++

/*
* UAE - The Un*x Amiga Emulator
*
* Other IDE controllers
*
* (c) 2015 Toni Wilen
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
#include "memory.h"
#include "newcpu.h"
#include "uae.h"
#include "gui.h"
#include "filesys.h"
#include "threaddep/thread.h"
#include "debug.h"
#include "ide.h"
#include "idecontrollers.h"
#include "zfile.h"
#include "custom.h"
#include "rommgr.h"
#include "cpuboard.h"
#include "scsi.h"
#include "ncr9x_scsi.h"
#include "autoconf.h"
#include "devices.h"
#define DEBUG_IDE 0
#define DEBUG_IDE_GVP 0
#define DEBUG_IDE_ALF 0
#define DEBUG_IDE_APOLLO 0
#define DEBUG_IDE_MASOBOSHI 0
#define GVP_IDE 0 // GVP A3001
#define ALF_IDE 1
#define ARRIBA_IDE 2
#define APOLLO_IDE (ARRIBA_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define MASOBOSHI_IDE (APOLLO_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define ADIDE_IDE (MASOBOSHI_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define MTEC_IDE (ADIDE_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define PROTAR_IDE (MTEC_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define ROCHARD_IDE (PROTAR_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define x86_AT_IDE (ROCHARD_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
#define GOLEMFAST_IDE (x86_AT_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
#define BUDDHA_IDE (GOLEMFAST_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
#define DATAFLYERPLUS_IDE (BUDDHA_IDE + 3 * MAX_DUPLICATE_EXPANSION_BOARDS)
#define ATEAM_IDE (DATAFLYERPLUS_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define FASTATA4K_IDE (ATEAM_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define ELSATHD_IDE (FASTATA4K_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
#define ACCESSX_IDE (ELSATHD_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define IVST500AT_IDE (ACCESSX_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
#define TRIFECTA_IDE (IVST500AT_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define TANDEM_IDE (TRIFECTA_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define DOTTO_IDE (TANDEM_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define DEV_IDE (DOTTO_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define TOTAL_IDE (DEV_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define ALF_ROM_OFFSET 0x0100
#define GVP_IDE_ROM_OFFSET 0x8000
#define APOLLO_ROM_OFFSET 0x8000
#define ADIDE_ROM_OFFSET 0x8000
#define MASOBOSHI_ROM_OFFSET 0x0080
#define MASOBOSHI_ROM_OFFSET_END 0xf000
#define MASOBOSHI_SCSI_OFFSET 0xf800
#define MASOBOSHI_SCSI_OFFSET_END 0xfc00
#define TRIFECTA_SCSI_OFFSET 0x0000
#define TRIFECTA_SCSI_OFFSET_END 0x0100
/* masoboshi:
IDE
- FFCC = base address, data (0)
- FF81 = -004B
- FF41 = -008B
- FF01 = -01CB
- FEC1 = -010B
- FE81 = -014B
- FE41 = -018B select (6)
- FE01 = -01CB status (7)
- FE03 = command (7)
- FA00 = ESP, 2 byte register spacing
- F9CC = data
- F047 = -0F85 (-0FB9) interrupt request? (bit 3)
- F040 = -0F8C interrupt request? (bit 1) Write anything = clear irq?
- F000 = some status register
- F04C = DMA address (long)
- F04A = number of words
- F044 = ???
- F047 = bit 7 = start dma
*/
#define MAX_IDE_UNITS 10
static struct ide_board *gvp_ide_rom_board, *gvp_ide_controller_board;
static struct ide_board *alf_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *apollo_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *masoboshi_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *adide_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *mtec_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *protar_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *rochard_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *x86_at_ide_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *golemfast_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *buddha_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *dataflyerplus_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *ateam_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *arriba_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *fastata4k_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *elsathd_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *accessx_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *ivst500at_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *trifecta_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *tandem_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board* dotto_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board* dev_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_hdf *idecontroller_drive[TOTAL_IDE * 2];
static struct ide_thread_state idecontroller_its;
static struct ide_board *ide_boards[MAX_IDE_UNITS + 1];
static int dev_hd_io_base, dev_hd_io_total;
static int dev_hd_io_size;
static int dev_hd_data_base;
static int dev_hd_io_secondary;
static void freencrunit(struct ide_board *ide)
{
if (!ide)
return;
for (int i = 0; i < MAX_IDE_UNITS; i++) {
if (ide_boards[i] == ide) {
ide_boards[i] = NULL;
}
}
for(int i = 0; i < MAX_IDE_PORTS_BOARD; i++) {
remove_ide_unit(&ide->ide[i], 0);
}
if (ide->self_ptr)
*ide->self_ptr = NULL;
xfree(ide->rom);
xfree(ide);
}
static struct ide_board *allocide(struct ide_board **idep, struct romconfig *rc, int ch)
{
struct ide_board *ide;
if (ch < 0) {
if (*idep) {
freencrunit(*idep);
*idep = NULL;
}
ide = xcalloc(struct ide_board, 1);
for (int i = 0; i < MAX_IDE_UNITS; i++) {
if (ide_boards[i] == NULL) {
ide_boards[i] = ide;
rc->unitdata = ide;
ide->rc = rc;
ide->self_ptr = idep;
if (idep)
*idep = ide;
return ide;
}
}
}
return *idep;
}
static struct ide_board *getideboard(uaecptr addr)
{
for (int i = 0; ide_boards[i]; i++) {
if (!ide_boards[i]->baseaddress && !ide_boards[i]->configured)
return ide_boards[i];
if ((addr & ~ide_boards[i]->mask) == ide_boards[i]->baseaddress)
return ide_boards[i];
}
return NULL;
}
static void init_ide(struct ide_board *board, int ide_num, int maxunit, bool byteswap, bool adide)
{
for (int i = 0; i < maxunit / 2; i++) {
struct ide_hdf **idetable = &idecontroller_drive[(ide_num + i) * 2];
alloc_ide_mem (idetable, 2, &idecontroller_its);
board->ide[i] = idetable[0];
idetable[0]->board = board;
idetable[1]->board = board;
idetable[0]->byteswap = byteswap;
idetable[1]->byteswap = byteswap;
idetable[0]->adide = adide;
idetable[1]->adide = adide;
ide_initialize(idecontroller_drive, ide_num + i);
}
idecontroller_its.idetable = idecontroller_drive;
idecontroller_its.idetotal = TOTAL_IDE * 2;
start_ide_thread(&idecontroller_its);
}
static void add_ide_standard_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc, struct ide_board **ideboard, int idetype, bool byteswap, bool adide, int maxunit)
{
struct ide_hdf *ide;
struct ide_board *ideb;
if (ch >= maxunit)
return;
ideb = allocide(&ideboard[ci->controller_type_unit], rc, ch);
if (!ideb)
return;
ideb->keepautoconfig = true;
ideb->type = idetype;
ide = add_ide_unit (&idecontroller_drive[(idetype + ci->controller_type_unit) * 2], 2, ch, ci, rc);
init_ide(ideb, idetype + ci->controller_type_unit, maxunit, byteswap, adide);
}
static bool ide_interrupt_check(struct ide_board *board, bool edge_triggered)
{
if (!board->configured)
return false;
bool irq = false;
for (int i = 0; i < MAX_IDE_PORTS_BOARD; i++) {
if (board->ide[i] && !irq) {
irq = ide_irq_check(board->ide[i], edge_triggered);
}
}
#if 0
if (board->irq != irq)
write_log(_T("IDE irq %d -> %d\n"), board->irq, irq);
#endif
board->irq = irq;
return irq;
}
static bool ide_rethink(struct ide_board *board, bool edge_triggered)
{
bool irq = false;
if (board->configured) {
if (board->intena && ide_interrupt_check(board, edge_triggered)) {
irq = true;
}
}
return irq;
}
void x86_doirq(uint8_t irqnum);
static void idecontroller_rethink(void)
{
bool irq = false;
for (int i = 0; ide_boards[i]; i++) {
if (ide_boards[i] == x86_at_ide_board[0] || ide_boards[i] == x86_at_ide_board[1]) {
bool x86irq = ide_rethink(ide_boards[i], true);
if (x86irq && ide_boards[i] == x86_at_ide_board[0]) {
x86_doirq(14);
}
} else {
if (ide_rethink(ide_boards[i], false))
safe_interrupt_set(IRQ_SOURCE_IDE, i, ide_boards[i]->intlev6);
}
}
}
static void idecontroller_hsync(void)
{
for (int i = 0; ide_boards[i]; i++) {
struct ide_board *board = ide_boards[i];
if (board->hsync_cnt > 0) {
board->hsync_cnt--;
if (!board->hsync_cnt && board->hsync_code)
board->hsync_code(board);
}
if (board->configured) {
for (int j = 0; j < MAX_IDE_PORTS_BOARD; j++) {
if (board->ide[j]) {
ide_interrupt_hsync(board->ide[j]);
}
}
if (ide_interrupt_check(board, false)) {
devices_rethink_all(idecontroller_rethink);
}
}
}
}
static void reset_ide(struct ide_board *board)
{
board->configured = 0;
board->intena = false;
board->enabled = false;
}
static void idecontroller_reset(int hardreset)
{
for (int i = 0; ide_boards[i]; i++) {
reset_ide(ide_boards[i]);
}
}
static void idecontroller_free(void)
{
stop_ide_thread(&idecontroller_its);
for (int i = 0; i < MAX_IDE_UNITS; i++) {
freencrunit(ide_boards[i]);
}
}
static bool is_gvp2_intreq(uaecptr addr)
{
if (ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SII) && (addr & 0x440) == 0x440)
return true;
return false;
}
static bool is_gvp1_intreq(uaecptr addr)
{
if (ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SI) && (addr & 0x440) == 0x40)
return true;
return false;
}
static bool get_ide_is_8bit(struct ide_board *board)
{
struct ide_hdf *ide = board->ide[0];
if (!ide)
return false;
if (ide->ide_drv)
ide = ide->pair;
return ide->mode_8bit;
}
static uae_u32 get_ide_reg_multi(struct ide_board *board, int reg, int portnum, int dataportsize)
{
struct ide_hdf *ide = board->ide[portnum];
if (!ide)
return 0;
if (ide->ide_drv)
ide = ide->pair;
if (reg == 0) {
if (dataportsize)
return ide_get_data(ide);
else
return ide_get_data_8bit(ide);
} else {
return ide_read_reg(ide, reg);
}
}
static void put_ide_reg_multi(struct ide_board *board, int reg, uae_u32 v, int portnum, int dataportsize)
{
struct ide_hdf *ide = board->ide[portnum];
if (!ide)
return;
if (ide->ide_drv)
ide = ide->pair;
if (reg == 0) {
if (dataportsize)
ide_put_data(ide, v);
else
ide_put_data_8bit(ide, v);
} else {
ide_write_reg(ide, reg, v);
}
}
static uae_u32 get_ide_reg(struct ide_board *board, int reg)
{
return get_ide_reg_multi(board, reg, 0, reg == 0 ? 1 : 0);
}
static void put_ide_reg(struct ide_board *board, int reg, uae_u32 v)
{
put_ide_reg_multi(board, reg, v, 0, reg == 0 ? 1 : 0);
}
static uae_u32 get_ide_reg_8bitdata(struct ide_board *board, int reg)
{
return get_ide_reg_multi(board, reg, 0, 0);
}
static void put_ide_reg_8bitdata(struct ide_board *board, int reg, uae_u32 v)
{
put_ide_reg_multi(board, reg, v, 0, 0);
}
static int get_gvp_reg(uaecptr addr, struct ide_board *board)
{
int reg = -1;
if (addr & 0x1000) {
reg = IDE_SECONDARY + ((addr >> 8) & 7);
} else if (addr & 0x0800) {
reg = (addr >> 8) & 7;
}
if (!(addr & 0x400) && (addr & 0x20)) {
if (reg < 0)
reg = 0;
int extra = (addr >> 1) & 15;
if (extra >= 8)
reg |= IDE_SECONDARY;
reg |= extra;
}
if (reg >= 0)
reg &= IDE_SECONDARY | 7;
return reg;
}
static int get_apollo_reg(uaecptr addr, struct ide_board *board)
{
if (addr & 0x4000)
return -1;
int reg = addr & 0x1fff;
reg >>= 10;
if (addr & 0x2000)
reg |= IDE_SECONDARY;
if (reg != 0 && !(addr & 1))
reg = -1;
return reg;
}
static int get_alf_reg(uaecptr addr, struct ide_board *board)
{
if (addr & 0x8000)
return -1;
if (addr & 0x4000) {
;
} else if (addr & 0x1000) {
addr &= 0xfff;
addr >>= 9;
} else if (addr & 0x2000) {
addr &= 0xfff;
addr >>= 9;
addr |= IDE_SECONDARY;
}
return addr;
}
static int get_masoboshi_reg(uaecptr addr, struct ide_board *board)
{
int reg;
if (addr < 0xfc00)
return -1;
reg = 7 - ((addr >> 6) & 7);
if (addr < 0xfe00)
reg |= IDE_SECONDARY;
return reg;
}
static void masoboshi_ide_dma(struct ide_board *board)
{
board->state2[0] |= 0x80;
}
static int get_trifecta_reg(uaecptr addr, struct ide_board *board)
{
int reg;
if (!(addr & 0x800))
return -1;
reg = (addr >> 6) & 7;
if (addr & 0x200)
reg |= IDE_SECONDARY;
return reg;
}
static int get_adide_reg(uaecptr addr, struct ide_board *board)
{
int reg;
if (addr & 0x8000)
return -1;
reg = (addr >> 1) & 7;
if (addr & 0x10)
reg |= IDE_SECONDARY;
return reg;
}
static int get_buddha_reg(uaecptr addr, struct ide_board *board, int *portnum)
{
int reg = -1;
if (addr < 0x800 || addr >= 0xe00)
return reg;
*portnum = (addr - 0x800) / 0x200;
reg = (addr >> 2) & 15;
if (addr & 0x100)
reg |= IDE_SECONDARY;
return reg;
}
static int get_rochard_reg(uaecptr addr, struct ide_board *board, int *portnum)
{
int reg = -1;
if ((addr & 0x8001) != 0x8001)
return -1;
*portnum = (addr & 0x4000) ? 1 : 0;
reg = (addr >> 5) & 7;
if (addr & 0x2000)
reg |= IDE_SECONDARY;
return reg;
}
static int get_dataflyerplus_reg(uaecptr addr, struct ide_board *board)
{
int reg = -1;
if (!(addr & 0x8000))
return -1;
reg = (addr / 0x40) & 7;
return reg;
}
static int get_golemfast_reg(uaecptr addr, struct ide_board *board)
{
int reg = -1;
if ((addr & 0x8001) != 0x8000)
return -1;
reg = (addr >> 2) & 7;
if (addr & 0x2000)
reg |= IDE_SECONDARY;
return reg;
}
static int get_ateam_reg(uaecptr addr, struct ide_board *board)
{
if (!(addr & 1))
return -1;
if ((addr & 0xf000) != 0xf000)
return -1;
addr >>= 7;
addr &= 15;
if (addr >= 8) {
addr &= 7;
addr |= IDE_SECONDARY;
}
return addr;
}
static int get_arriba_reg(uaecptr addr, struct ide_board *board)
{
if (!(addr & 0x8000))
return -1;
if (addr & 1)
return -1;
int reg = ((addr & 0x0fff) >> 9) & 7;
return reg;
}
static int get_elsathd_reg(uaecptr addr, struct ide_board *board)
{
if (!(addr & 0x8000))
return -1;
if (!(addr & 1))
return -1;
int reg = ((addr & 0x0fff) >> 9) & 7;
return reg;
}
static int get_fastata4k_reg(uaecptr addr, struct ide_board *board, int *portnum)
{
*portnum = 0;
if (addr & 1)
return -1;
if (!(addr & 0x8000))
return -1;
if ((addr & 0xf500) == 0x8500)
return -2;
if (addr & 0x0100)
return -1;
*portnum = (addr & 0x1000) ? 1 : 0;
addr &= 0xe00;
addr >>= 9;
return addr;
}
static int get_accessx_reg(uaecptr addr, struct ide_board *board, int *portnum)
{
*portnum = 0;
if (!(addr & 0x8000))
return -1;
if ((addr & 1))
return -1;
if (addr & 0x400)
*portnum = 1;
int reg = (addr >> 6) & 7;
if (addr & 0x200)
reg |= IDE_SECONDARY;
return reg;
}
static int get_ivst500at_reg(uaecptr addr, struct ide_board *board, int *portnum)
{
*portnum = 0;
if (addr & (0x4000 | 0x8000))
return -1;
if (!(addr & 1))
return -1;
int reg = (addr >> 2) & 7;
if (addr & 0x2000)
reg |= IDE_SECONDARY;
return reg;
}
static int get_dev_hd_reg(uaecptr addr, struct ide_board* board)
{
int reg = -1;
if (addr & 0x8000) {
return -1;
}
if (addr >= dev_hd_io_base && addr < dev_hd_io_base + dev_hd_io_total) {
reg = (addr - dev_hd_io_base) / dev_hd_io_size;
reg &= 7;
if (reg == 0) {
write_log("invalid %08x\n", addr);
}
} else if (addr >= dev_hd_data_base && addr < dev_hd_data_base + 0x100) {
reg = 0;
} else {
write_log("out of range %08x\n", addr);
}
return reg;
}
static int getidenum(struct ide_board *board, struct ide_board **arr)
{
for (int i = 0; i < MAX_DUPLICATE_EXPANSION_BOARDS; i++) {
if (board == arr[i])
return i;
}
return 0;
}
static uae_u32 ide_read_byte(struct ide_board *board, uaecptr addr)
{
uaecptr oaddr = addr;
uae_u8 v = 0xff;
addr &= board->mask;
#if DEBUG_IDE
if (0 || !(addr & 0x8000))
write_log(_T("IDE IO BYTE READ %08x %08x\n"), addr, M68K_GETPC);
#endif
if (addr < 0x40 && (!board->configured || board->keepautoconfig))
return board->acmemory[addr];
if (board->type == BUDDHA_IDE) {
int portnum;
int regnum = get_buddha_reg(addr, board, &portnum);
if (regnum >= 0) {
if (board->ide[portnum])
v = get_ide_reg_multi(board, regnum, portnum, 1);
} else if (addr >= 0xf00 && addr < 0x1000) {
if ((addr & ~3) == 0xf00)
v = ide_irq_check(board->ide[0], false) ? 0x80 : 0x00;
else if ((addr & ~3) == 0xf40)
v = ide_irq_check(board->ide[1], false) ? 0x80 : 0x00;
else if ((addr & ~3) == 0xf80)
v = ide_irq_check(board->ide[2], false) ? 0x80 : 0x00;
else
v = 0;
} else if (addr >= 0x7fc && addr <= 0x7ff) {
v = board->userdata;
} else {
v = board->rom[addr & board->rom_mask];
}
} else if (board->type == ALF_IDE || board->type == TANDEM_IDE) {
if (addr < 0x1100 || (addr & 1)) {
if (board->rom)
v = board->rom[addr & board->rom_mask];
return v;
}
int regnum = get_alf_reg(addr, board);
if (regnum >= 0) {
v = get_ide_reg(board, regnum);
}
#if DEBUG_IDE_ALF
write_log(_T("ALF GET %08x %02x %d %08x\n"), addr, v, regnum, M68K_GETPC);
#endif
} else if (board->type == GOLEMFAST_IDE) {
if (!(addr & 0x8000)) {
if (board->rom) {
v = board->rom[addr & board->rom_mask];
}
} else if ((addr & 0x8700) == 0x8400 || (addr & 0x8700) == 0x8000) {
v = golemfast_ncr9x_scsi_get(oaddr, getidenum(board, golemfast_board));
} else if ((addr & 0x8700) == 0x8100) {
int regnum = get_golemfast_reg(addr, board);
if (regnum >= 0) {
v = get_ide_reg(board, regnum);
}
} else if ((addr & 0x8700) == 0x8300) {
v = board->original_rc->device_id ^ 7;
if (!board->original_rc->autoboot_disabled)
v |= 0x20;
if (!(board->original_rc->device_settings & 1))
v |= 0x08;
if (ide_irq_check(board->ide[0], false) || ide_drq_check(board->ide[0]))
v |= 0x80; // IDE IRQ | DRQ
//write_log(_T("READ JUMPER %08x %02x %08x\n"), addr, v, M68K_GETPC);
}
} else if (board->type == MASOBOSHI_IDE) {
int regnum = -1;
bool rom = false;
if (addr >= MASOBOSHI_ROM_OFFSET && addr < MASOBOSHI_ROM_OFFSET_END) {
if (board->rom) {
v = board->rom[addr & board->rom_mask];
rom = true;
}
} else if ((addr >= 0xf000 && addr <= 0xf00f) || (addr >= 0xf100 && addr <= 0xf10f)) {
// scsi dma controller
if (board->subtype)
v = masoboshi_ncr9x_scsi_get(oaddr, getidenum(board, masoboshi_board));
} else if (addr == 0xf040) {
v = 1;
if (ide_irq_check(board->ide[0], false)) {
v |= 2;
board->irq = true;
}
if (board->irq) {
v &= ~1;
}
v |= board->state2[0] & 0x80;
} else if (addr == 0xf047) {
v = board->state;
} else {
regnum = get_masoboshi_reg(addr, board);
if (regnum >= 0) {
v = get_ide_reg(board, regnum);
} else if (addr >= MASOBOSHI_SCSI_OFFSET && addr < MASOBOSHI_SCSI_OFFSET_END) {
if (board->subtype)
v = masoboshi_ncr9x_scsi_get(oaddr, getidenum(board, masoboshi_board));
else
v = 0xff;
}
}
#if DEBUG_IDE_MASOBOSHI
if (!rom)
write_log(_T("MASOBOSHI BYTE GET %08x %02x %d %08x\n"), addr, v, regnum, M68K_GETPC);
#endif
} else if (board->type == TRIFECTA_IDE) {
if (addr & 1) {
int regnum = get_trifecta_reg(addr, board);
if (regnum >= 0) {
v = get_ide_reg(board, regnum);
}
}
if (addr >= TRIFECTA_SCSI_OFFSET && addr < TRIFECTA_SCSI_OFFSET_END) {
if (board->subtype)
v = trifecta_ncr9x_scsi_get(oaddr, getidenum(board, trifecta_board));
else
v = 0xff;
}
if (addr == 0x401) {
if (board->subtype) {
// LX (SCSI+IDE)
v = (board->aci->rc->device_id ^ 7) & 7; // inverted SCSI ID
} else {
// EC (IDE)
v = 0;
}
v |= (board->aci->rc->device_settings ^ 0xfc) << 3;
} else if (addr >= 0x1000) {
if (board->rom)
v = board->rom[addr & board->rom_mask];
}
//write_log(_T("trifecta get %08x %08x\n"), addr, M68K_GETPC);
} else if (board->type == APOLLO_IDE) {
if (addr >= APOLLO_ROM_OFFSET) {
if (board->rom)
v = board->rom[(addr - APOLLO_ROM_OFFSET) & board->rom_mask];
} else if (board->configured) {
if ((addr & 0xc000) == 0x4000) {
v = apollo_scsi_bget(oaddr, board->userdata);
} else if (addr < 0x4000) {
int regnum = get_apollo_reg(addr, board);
if (regnum >= 0) {
v = get_ide_reg(board, regnum);
} else {
v = 0;
}
}
}
} else if (board->type == GVP_IDE) {
if (addr >= GVP_IDE_ROM_OFFSET) {
if (board->rom) {
if (addr & 1)
v = 0xe8; // board id
else
v = board->rom[((addr - GVP_IDE_ROM_OFFSET) / 2) & board->rom_mask];
return v;
}
v = 0xe8;
#if DEBUG_IDE_GVP
write_log(_T("GVP BOOT GET %08x %02x %08x\n"), addr, v, M68K_GETPC);
#endif
return v;
}
if (board->configured) {
if (board == gvp_ide_rom_board && ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SII)) {
if (addr == 0x42) {
v = 0xff;
}
#if DEBUG_IDE_GVP
write_log(_T("GVP BOOT GET %08x %02x %08x\n"), addr, v, M68K_GETPC);
#endif
} else {
int regnum = get_gvp_reg(addr, board);
#if DEBUG_IDE_GVP
write_log(_T("GVP IDE GET %08x %02x %d %08x\n"), addr, v, regnum, M68K_GETPC);
#endif
if (regnum >= 0) {
v = get_ide_reg(board, regnum);
} else if (is_gvp2_intreq(addr)) {
v = board->irq ? 0x40 : 0x00;
#if DEBUG_IDE_GVP
write_log(_T("GVP IRQ %02x\n"), v);
#endif
ide_interrupt_check(board, false);
} else if (is_gvp1_intreq(addr)) {
v = board->irq ? 0x80 : 0x00;
#if DEBUG_IDE_GVP
write_log(_T("GVP IRQ %02x\n"), v);
#endif
ide_interrupt_check(board, false);
}
}
} else {
v = 0xff;
}
} else if (board->type == ADIDE_IDE) {
if (addr & ADIDE_ROM_OFFSET) {
v = board->rom[addr & board->rom_mask];
} else if (board->configured) {
int regnum = get_adide_reg(addr, board);
v = get_ide_reg(board, regnum);
v = (uae_u8)adide_decode_word(v);
}
} else if (board->type == MTEC_IDE) {
if (!(addr & 0x8000)) {
v = board->rom[addr & board->rom_mask];
} else if (board->configured) {
v = get_ide_reg(board, (addr >> 8) & 7);
}
} else if (board->type == PROTAR_IDE) {
v = board->rom[addr & board->rom_mask];
} else if (board->type == DATAFLYERPLUS_IDE) {
v = board->rom[addr & board->rom_mask];
if (board->configured) {
if (addr == 0x10) {
if (board->subtype & 2) {
v = ide_irq_check(board->ide[0], false) ? 0x08 : 0x00;
}
} else if (addr < 0x80) {
if (board->subtype & 1) {
v = idescsi_scsi_get(oaddr);
} else {
v = 0xff;
}
}
}
if ((addr & 0x8000) && (board->subtype & 2)) {
int regnum = get_dataflyerplus_reg(addr, board);
if (regnum >= 0)
v = get_ide_reg(board, regnum);
}
} else if (board->type == ROCHARD_IDE) {
if (addr & 0x8000) {
int portnum;
int regnum = get_rochard_reg(addr, board, &portnum);
if (regnum >= 0 && board->ide[portnum])
v = get_ide_reg_multi(board, regnum, portnum, 1);
} else if ((addr & 0x7c00) == 0x7000) {
if (board->subtype)
v = idescsi_scsi_get(oaddr);
else
v = 0;
} else {
v = board->rom[addr & board->rom_mask];
}
} else if (board->type == ATEAM_IDE) {
if (addr == 1) {
v = ide_irq_check(board->ide[0], false) ? 0x00 : 0x80;
} else {
int reg = get_ateam_reg(addr, board);
if (reg >= 0) {
v = get_ide_reg(board, reg);
} else {
v = board->rom[addr & board->rom_mask];
}
}
} else if (board->type == ARRIBA_IDE) {
int reg = get_arriba_reg(addr, board);
if (reg >= 0) {
v = get_ide_reg(board, reg);
} else if (board->rom && !(addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[offset];
}
} else if (board->type == ELSATHD_IDE) {
int reg = get_elsathd_reg(addr, board);
if (reg >= 0) {
v = get_ide_reg(board, reg);
} else if (board->rom && !(addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[offset];
}
} else if (board->type == FASTATA4K_IDE) {
int portnum;
int reg = get_fastata4k_reg(addr, board, &portnum);
if (reg >= 0) {
if (board->ide[portnum])
v = get_ide_reg_multi(board, reg, portnum, 1);
} else if (reg == -2) {
v = ide_irq_check(board->ide[0], false) ? 1 << 6 : 0;
if (board->ide[1])
v |= ide_irq_check(board->ide[1], false) ? 1 << 5 : 0;
if (v)
v |= 1 << 7;
} else {
if (board->rom && addr >= 0x0200) {
int offset = addr - 0x200;
offset &= board->rom_mask;
v = board->rom[(offset + 0) & board->rom_mask];
}
}
} else if (board->type == ACCESSX_IDE) {
int portnum;
int reg = get_accessx_reg(addr, board, &portnum);
if (reg >= 0) {
if (board->ide[portnum])
v = get_ide_reg_multi(board, reg, portnum, 1);
} else if (board->rom && !(addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[offset];
}
} else if (board->type == IVST500AT_IDE) {
int portnum;
int reg = get_ivst500at_reg(addr, board, &portnum);
if (reg >= 0) {
if (board->ide[portnum])
v = get_ide_reg_multi(board, reg, portnum, 1);
} else if (board->rom && (addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[offset];
} else if ((addr & 0x4000) && (addr & 1)) {
v = ide_irq_check(board->ide[0], false) ? 1 : 0;
}
} else if (board->type == DOTTO_IDE) {
int offset = addr;
v = board->rom[offset];
if (board->configured) {
int regnum = get_adide_reg(addr, board);
if (regnum >= 0) {
v = get_ide_reg(board, regnum);
v = (uae_u8)adide_decode_word(v);
}
}
} else if (board->type == DEV_IDE) {
if (addr == 0x88) {
v = 0xff;
} else if (addr == 0x86 || addr == 0x90 || addr == 0x92 || addr == 0x94 || addr == 0x96) {
if (addr == 0x86) {
board->dma_ptr = 0x80;
board->dma_cnt = 1;
}
v = board->rom[board->dma_ptr * 2 + 0x8000];
board->dma_ptr++;
if (board->dma_cnt == 1) {
uae_u8 v2 = board->rom[board->dma_ptr * 2 + 0x8000];
board->dma_ptr++;
if (v != (v2 ^ 0xff)) {
write_log("error!\n");
}
board->dma_cnt = 0;
}
} else {
int reg = get_dev_hd_reg(addr, board);
if (reg >= 0) {
v = get_ide_reg(board, reg);
} else {
v = board->rom[addr];
}
}
}
return v;
}
static uae_u32 ide_read_word(struct ide_board *board, uaecptr addr)
{
uae_u32 v = 0xffff;
addr &= board->mask;
if (addr < 0x40 && (!board->configured || board->keepautoconfig)) {
v = board->acmemory[addr] << 8;
v |= board->acmemory[addr + 1];
return v;
}
if (board->type == APOLLO_IDE) {
if (addr >= APOLLO_ROM_OFFSET) {
if (board->rom) {
v = board->rom[(addr + 0 - APOLLO_ROM_OFFSET) & board->rom_mask];
v <<= 8;
v |= board->rom[(addr + 1 - APOLLO_ROM_OFFSET) & board->rom_mask];
}
}
} else if (board->type == DATAFLYERPLUS_IDE) {
if (!(addr & 0x8000) && (board->subtype & 2)) {
if (board->rom) {
v = board->rom[(addr + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(addr + 1) & board->rom_mask];
}
}
} else if (board->type == ROCHARD_IDE) {
if (addr < 8192) {
if (board->rom) {
v = board->rom[(addr + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(addr + 1) & board->rom_mask];
}
}
}
if (board->configured) {
if (board->type == BUDDHA_IDE) {
int portnum;
int regnum = get_buddha_reg(addr, board, &portnum);
if (regnum == IDE_DATA) {
if (board->ide[portnum])
v = get_ide_reg_multi(board, IDE_DATA, portnum, 1);
} else {
v = ide_read_byte(board, addr) << 8;
v |= ide_read_byte(board, addr + 1);
}
} else if (board->type == ALF_IDE || board->type == TANDEM_IDE) {
int regnum = get_alf_reg(addr, board);
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
} else {
v = 0;
if (addr == 0x4000 && board->intena)
v = board->irq ? 0x8000 : 0x0000;
#if DEBUG_IDE_ALF
write_log(_T("ALF IO WORD READ %08x %08x\n"), addr, M68K_GETPC);
#endif
}
} else if (board->type == GOLEMFAST_IDE) {
if ((addr & 0x8700) == 0x8100) {
int regnum = get_golemfast_reg(addr, board);
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
} else {
v = ide_read_byte(board, addr) << 8;
v |= ide_read_byte(board, addr + 1);
}
} else {
v = ide_read_byte(board, addr) << 8;
v |= ide_read_byte(board, addr + 1);
}
} else if (board->type == MASOBOSHI_IDE) {
if (addr >= MASOBOSHI_ROM_OFFSET && addr < MASOBOSHI_ROM_OFFSET_END) {
if (board->rom) {
v = board->rom[addr & board->rom_mask] << 8;
v |= board->rom[(addr + 1) & board->rom_mask];
}
} else if (addr == 0xf04c || addr == 0xf14c) {
v = board->dma_ptr >> 16;
} else if (addr == 0xf04e || addr == 0xf14e) {
v = board->dma_ptr;
write_log(_T("MASOBOSHI IDE DMA PTR READ = %08x %08x\n"), board->dma_ptr, M68K_GETPC);
} else if (addr == 0xf04a || addr == 0xf14a) {
v = board->dma_cnt;
write_log(_T("MASOBOSHI IDE DMA LEN READ = %04x %08x\n"), board->dma_cnt, v, M68K_GETPC);
} else {
int regnum = get_masoboshi_reg(addr, board);
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
} else {
v = ide_read_byte(board, addr) << 8;
v |= ide_read_byte(board, addr + 1);
}
}
} else if (board->type == TRIFECTA_IDE) {
if (addr >= 0x1000) {
if (board->rom) {
v = board->rom[addr & board->rom_mask] << 8;
v |= board->rom[(addr + 1) & board->rom_mask];
}
} else {
int regnum = get_trifecta_reg(addr, board);
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
} else {
v = ide_read_byte(board, addr) << 8;
v |= ide_read_byte(board, addr + 1);
}
}
} else if (board->type == APOLLO_IDE) {
if ((addr & 0xc000) == 0x4000) {
v = apollo_scsi_bget(addr, board->userdata);
v <<= 8;
v |= apollo_scsi_bget(addr + 1, board->userdata);
} else if (addr < 0x4000) {
int regnum = get_apollo_reg(addr, board);
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
} else {
v = 0;
}
}
} else if (board->type == GVP_IDE) {
if (board == gvp_ide_controller_board || ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SI)) {
if (addr < 0x60) {
if (is_gvp1_intreq(addr))
v = gvp_ide_controller_board->irq ? 0x8000 : 0x0000;
else if (addr == 0x40) {
if (ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SII))
v = board->intena ? 8 : 0;
}
#if DEBUG_IDE_GVP
write_log(_T("GVP IO WORD READ %08x %08x\n"), addr, M68K_GETPC);
#endif
} else {
int regnum = get_gvp_reg(addr, board);
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
#if DEBUG_IDE_GVP > 2
write_log(_T("IDE WORD READ %04x\n"), v);
#endif
} else {
v = ide_read_byte(board, addr) << 8;
v |= ide_read_byte(board, addr + 1);
}
}
}
} else if (board->type == ADIDE_IDE) {
int regnum = get_adide_reg(addr, board);
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
} else {
v = get_ide_reg(board, regnum) << 8;
v = adide_decode_word(v);
}
} else if (board->type == MTEC_IDE) {
if (addr & 0x8000) {
int regnum = (addr >> 8) & 7;
if (regnum == IDE_DATA)
v = get_ide_reg(board, regnum);
else
v = ide_read_byte(board, addr) << 8;
}
} else if (board->type == DATAFLYERPLUS_IDE) {
if (board->subtype & 2) {
int reg = get_dataflyerplus_reg(addr, board);
if (reg >= 0)
v = get_ide_reg_multi(board, reg, 0, 1);
} else {
v = 0xff;
}
} else if (board->type == ROCHARD_IDE) {
if ((addr & 0x8020) == 0x8000) {
v = get_ide_reg_multi(board, IDE_DATA, (addr & 0x4000) ? 1 : 0, 1);
}
} else if (board->type == ATEAM_IDE) {
if ((addr & 0xf800) == 0xf800) {
v = get_ide_reg_multi(board, IDE_DATA, 0, 1);
}
} else if (board->type == ARRIBA_IDE) {
int reg = get_arriba_reg(addr, board);
if (reg == 0) {
v = get_ide_reg_multi(board, IDE_DATA, 0, 1);
} else if (board->rom && !(addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[(offset + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(offset + 1) & board->rom_mask];
}
} else if (board->type == ELSATHD_IDE) {
int reg = get_elsathd_reg(addr | 1, board);
if (reg == 0) {
v = get_ide_reg_multi(board, IDE_DATA, 0, 1);
} else if (reg > 0) {
v = get_ide_reg(board, reg);
} else if (board->rom && !(addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[(offset + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(offset + 1) & board->rom_mask];
}
} else if (board->type == FASTATA4K_IDE) {
int portnum;
int reg = get_fastata4k_reg(addr, board, &portnum);
if (reg == 0) {
v = get_ide_reg_multi(board, IDE_DATA, portnum, 1);
} else if (board->rom && addr >= 0x0200) {
int offset = addr - 0x200;
offset &= board->rom_mask;
v = board->rom[(offset + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(offset + 1) & board->rom_mask];
}
} else if (board->type == ACCESSX_IDE) {
int portnum;
int reg = get_accessx_reg(addr, board, &portnum);
if (reg == 0) {
v = get_ide_reg_multi(board, IDE_DATA, portnum, 1);
} else if (board->rom && !(addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[(offset + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(offset + 1) & board->rom_mask];
}
} else if (board->type == IVST500AT_IDE) {
int portnum;
int reg = get_ivst500at_reg(addr, board, &portnum);
if (reg == 0 || addr == 0 || addr == 2) {
v = get_ide_reg_multi(board, IDE_DATA, portnum, 1);
} else if (board->rom && (addr & 0x8000)) {
int offset = addr & 0x7fff;
v = board->rom[(offset + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(offset + 1) & board->rom_mask];
}
} else if (board->type == DOTTO_IDE) {
int offset = addr;
v = board->rom[(offset + 0) & board->rom_mask];
v <<= 8;
v |= board->rom[(offset + 1) & board->rom_mask];
if (board->configured) {
int regnum = get_adide_reg(addr, board);
if (regnum >= 0) {
if (regnum == IDE_DATA) {
v = get_ide_reg(board, IDE_DATA);
} else {
v = get_ide_reg(board, regnum) << 8;
v = adide_decode_word(v);
}
}
}
} else if (board->type == DEV_IDE) {
int reg = get_dev_hd_reg(addr, board);
if (reg == IDE_DATA) {
v = get_ide_reg(board, reg);
}
}
}
#if DEBUG_IDE
if (0 || !(addr & 0x8000))
write_log(_T("IDE IO WORD READ %08x %04x %08x\n"), addr, v, M68K_GETPC);
#endif
return v;
}
static void ide_write_byte(struct ide_board *board, uaecptr addr, uae_u8 v)
{
uaecptr oaddr = addr;
addr &= board->mask;
#if DEBUG_IDE
if (0 || !(addr & 0x8000))
write_log(_T("IDE IO BYTE WRITE %08x=%02x %08x\n"), addr, v, M68K_GETPC);
#endif
if (!board->configured) {
addrbank *ab = board->bank;
if (addr == 0x48) {
if (board->aci->zorro == 2) {
map_banks_z2(ab, v, (board->mask + 1) >> 16);
board->baseaddress = v << 16;
board->configured = 1;
if (board->type == ROCHARD_IDE) {
rochard_scsi_init(board->original_rc, board->baseaddress);
} else if (board->type == MASOBOSHI_IDE) {
ncr_masoboshi_autoconfig_init(board->original_rc, board->baseaddress);
} else if (board->type == GOLEMFAST_IDE) {
ncr_golemfast_autoconfig_init(board->original_rc, board->baseaddress);
} else if (board->type == DATAFLYERPLUS_IDE) {
dataflyerplus_scsi_init(board->original_rc, board->baseaddress);
} else if (board->type == TRIFECTA_IDE) {
ncr_trifecta_autoconfig_init(board->original_rc, board->baseaddress);
}
expamem_next(ab, NULL);
}
return;
}
if (addr == 0x4c) {
board->configured = 1;
expamem_shutup(ab);
return;
}
}
if (board->configured) {
if (board->type == BUDDHA_IDE) {
int portnum;
int regnum = get_buddha_reg(addr, board, &portnum);
if (regnum >= 0) {
if (board->ide[portnum]) {
put_ide_reg_multi(board, regnum, v, portnum, 1);
}
} else if (addr >= 0xfc0 && addr < 0xfc4) {
board->intena = true;
} else if (addr >= 0x7fc && addr <= 0x7ff) {
board->userdata = v;
}
} else if (board->type == ALF_IDE || board->type == TANDEM_IDE) {
int regnum = get_alf_reg(addr, board);
if (regnum >= 0)
put_ide_reg(board, regnum, v);
#if DEBUG_IDE_ALF
write_log(_T("ALF PUT %08x %02x %d %08x\n"), addr, v, regnum, M68K_GETPC);
#endif
} else if (board->type == GOLEMFAST_IDE) {
if ((addr & 0x8700) == 0x8400 || (addr & 0x8700) == 0x8000) {
golemfast_ncr9x_scsi_put(oaddr, v, getidenum(board, golemfast_board));
} else if ((addr & 0x8700) == 0x8100) {
int regnum = get_golemfast_reg(addr, board);
if (regnum >= 0)
put_ide_reg(board, regnum, v);
}
} else if (board->type == MASOBOSHI_IDE) {
#if DEBUG_IDE_MASOBOSHI
write_log(_T("MASOBOSHI IO BYTE PUT %08x %02x %08x\n"), addr, v, M68K_GETPC);
#endif
int regnum = get_masoboshi_reg(addr, board);
if (regnum >= 0) {
put_ide_reg(board, regnum, v);
} else if (addr >= MASOBOSHI_SCSI_OFFSET && addr < MASOBOSHI_SCSI_OFFSET_END) {
if (board->subtype)
masoboshi_ncr9x_scsi_put(oaddr, v, getidenum(board, masoboshi_board));
} else if ((addr >= 0xf000 && addr <= 0xf007)) {
if (board->subtype)
masoboshi_ncr9x_scsi_put(oaddr, v, getidenum(board, masoboshi_board));
} else if (addr >= 0xf00a && addr <= 0xf00f) {
// scsi dma controller
masoboshi_ncr9x_scsi_put(oaddr, v, getidenum(board, masoboshi_board));
} else if (addr >= 0xf040 && addr <= 0xf04f) {
// ide dma controller
if (addr >= 0xf04c && addr < 0xf050) {
int shift = (3 - (addr - 0xf04c)) * 8;
uae_u32 mask = 0xff << shift;
board->dma_ptr &= ~mask;
board->dma_ptr |= v << shift;
board->dma_ptr &= 0xffffff;
} else if (addr >= 0xf04a && addr < 0xf04c) {
if (addr == 0xf04a) {
board->dma_cnt &= 0x00ff;
board->dma_cnt |= v << 8;
} else {
board->dma_cnt &= 0xff00;
board->dma_cnt |= v;
}
} else if (addr >= 0xf040 && addr < 0xf048) {
board->state2[addr - 0xf040] = v;
board->state2[0] &= ~0x80;
if (addr == 0xf047) {
board->state = v;
board->intena = (v & 8) != 0;
// masoboshi ide dma
if (v & 0x80) {
board->hsync_code = masoboshi_ide_dma;
board->hsync_cnt = (board->dma_cnt / maxhpos) * 2 + 1;
write_log(_T("MASOBOSHI IDE DMA %s start %08x, %d\n"), (board->state2[5] & 0x80) ? _T("READ") : _T("WRITE"), board->dma_ptr, board->dma_cnt);
if (ide_drq_check(board->ide[0])) {
if (!(board->state2[5] & 0x80)) {
for (int i = 0; i < board->dma_cnt; i++) {
put_ide_reg(board, IDE_DATA, get_word(board->dma_ptr & ~1));
board->dma_ptr += 2;
}
} else {
for (int i = 0; i < board->dma_cnt; i++) {
put_word(board->dma_ptr & ~1, get_ide_reg(board, IDE_DATA));
board->dma_ptr += 2;
}
}
board->dma_cnt = 0;
}
}
}
if (addr == 0xf040) {
board->state2[0] &= ~0x80;
board->irq = false;
}
}
}
} else if (board->type == TRIFECTA_IDE) {
if (addr & 1) {
int regnum = get_trifecta_reg(addr, board);
if (regnum >= 0) {
put_ide_reg(board, regnum, v);
}
}
if (addr >= TRIFECTA_SCSI_OFFSET && addr < TRIFECTA_SCSI_OFFSET_END) {
if (board->subtype)
trifecta_ncr9x_scsi_put(oaddr, v, getidenum(board, trifecta_board));
}
if (addr >= 0x400 && addr <= 0x407) {
trifecta_ncr9x_scsi_put(oaddr, v, getidenum(board, trifecta_board));
}
} else if (board->type == APOLLO_IDE) {
if ((addr & 0xc000) == 0x4000) {
apollo_scsi_bput(oaddr, v, board->userdata);
} else if (addr < 0x4000) {
int regnum = get_apollo_reg(addr, board);
if (regnum >= 0) {
put_ide_reg(board, regnum, v);
}
}
} else if (board->type == GVP_IDE) {
if (board == gvp_ide_rom_board && ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SII)) {
#if DEBUG_IDE_GVP
write_log(_T("GVP BOOT PUT %08x %02x %08x\n"), addr, v, M68K_GETPC);
#endif
} else {
int regnum = get_gvp_reg(addr, board);
#if DEBUG_IDE_GVP
write_log(_T("GVP IDE PUT %08x %02x %d %08x\n"), addr, v, regnum, M68K_GETPC);
#endif
if (regnum >= 0)
put_ide_reg(board, regnum, v);
}
} else if (board->type == ADIDE_IDE) {
if (board->configured) {
int regnum = get_adide_reg(addr, board);
v = (uae_u8)adide_encode_word(v);
put_ide_reg(board, regnum, v);
}
} else if (board->type == MTEC_IDE) {
if (board->configured && (addr & 0x8000)) {
put_ide_reg(board, (addr >> 8) & 7, v);
}
} else if (board->type == DATAFLYERPLUS_IDE) {
if (board->configured) {
if (addr & 0x8000) {
if (board->subtype & 2) {
int regnum = get_dataflyerplus_reg(addr, board);
if (regnum >= 0)
put_ide_reg(board, regnum, v);
}
} else if (addr < 0x80) {
if (board->subtype & 1) {
idescsi_scsi_put(oaddr, v);
}
}
}
} else if (board->type == ROCHARD_IDE) {
if (board->configured) {
if (addr & 0x8000) {
int portnum;
int regnum = get_rochard_reg(addr, board, &portnum);
if (regnum >= 0 && board->ide[portnum])
put_ide_reg_multi(board, regnum, v, portnum, 1);
} else if ((addr & 0x7c00) == 0x7000) {
if (board->subtype)
idescsi_scsi_put(oaddr, v);
}
}
} else if (board->type == ATEAM_IDE) {
if ((addr & 0xff01) == 0x0101) {
// disable interrupt strobe address
board->intena = false;
} else if ((addr & 0xff01) == 0x0201) {
// enable interrupt strobe address
board->intena = true;
} else {
int reg = get_ateam_reg(addr, board);
if (reg >= 0) {
put_ide_reg(board, reg, v);
}
}
} else if (board->type == ARRIBA_IDE) {
int reg = get_arriba_reg(addr, board);
if (reg >= 0) {
put_ide_reg(board, reg, v);
}
} else if (board->type == ELSATHD_IDE) {
int reg = get_elsathd_reg(addr, board);
if (reg >= 0) {
put_ide_reg(board, reg, v);
}
} else if (board->type == FASTATA4K_IDE) {
int portnum;
int reg = get_fastata4k_reg(addr, board, &portnum);
if (board->ide[portnum]) {
put_ide_reg_multi(board, reg, v, portnum, 1);
}
} else if (board->type == ACCESSX_IDE) {
int portnum;
int reg = get_accessx_reg(addr, board, &portnum);
if (board->ide[portnum]) {
put_ide_reg_multi(board, reg, v, portnum, 1);
}
} else if (board->type == IVST500AT_IDE) {
int portnum;
int reg = get_ivst500at_reg(addr, board, &portnum);
if (board->ide[portnum]) {
put_ide_reg_multi(board, reg, v, portnum, 1);
}
} else if (board->type == DOTTO_IDE) {
if (board->configured) {
int regnum = get_adide_reg(addr, board);
v = (uae_u8)adide_encode_word(v);
put_ide_reg(board, regnum, v);
}
} else if (board->type == DEV_IDE) {
if (addr == 0x86) {
board->dma_ptr = 0;
board->dma_cnt = 0;
} else if (addr == 0x90 || addr == 0x92 || addr == 0x94 || addr == 0x96) {
board->dma_ptr <<= 8;
board->dma_ptr |= v;
board->dma_ptr &= 0xffffff;
} else {
int reg = get_dev_hd_reg(addr, board);
if (reg >= 0) {
put_ide_reg(board, reg, v);
}
}
}
}
}
static void ide_write_word(struct ide_board *board, uaecptr addr, uae_u16 v)
{
addr &= board->mask;
#if DEBUG_IDE
if (0 || !(addr & 0x8000))
write_log(_T("IDE IO WORD WRITE %08x=%04x %08x\n"), addr, v, M68K_GETPC);
#endif
if (board->configured) {
if (board->type == BUDDHA_IDE) {
int portnum;
int regnum = get_buddha_reg(addr, board, &portnum);
if (regnum == IDE_DATA) {
if (board->ide[portnum])
put_ide_reg_multi(board, IDE_DATA, v, portnum, 1);
} else {
ide_write_byte(board, addr, v >> 8);
ide_write_byte(board, addr + 1, (uae_u8)v);
}
} else if (board->type == ALF_IDE || board->type == TANDEM_IDE) {
int regnum = get_alf_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
} else {
#if DEBUG_IDE_ALF
write_log(_T("ALF IO WORD WRITE %08x %04x %08x\n"), addr, v, M68K_GETPC);
#endif
}
} else if (board->type == GOLEMFAST_IDE) {
if ((addr & 0x8700) == 0x8100) {
int regnum = get_golemfast_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
} else {
ide_write_byte(board, addr, v >> 8);
ide_write_byte(board, addr + 1, (uae_u8)v);
}
} else {
ide_write_byte(board, addr, v >> 8);
ide_write_byte(board, addr + 1, (uae_u8)v);
}
} else if (board->type == MASOBOSHI_IDE) {
int regnum = get_masoboshi_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
} else {
ide_write_byte(board, addr, v >> 8);
ide_write_byte(board, addr + 1, (uae_u8)v);
}
#if DEBUG_IDE_MASOBOSHI
write_log(_T("MASOBOSHI IO WORD WRITE %08x %04x %08x\n"), addr, v, M68K_GETPC);
#endif
} else if (board->type == TRIFECTA_IDE) {
int regnum = get_trifecta_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
} else {
ide_write_byte(board, addr, v >> 8);
ide_write_byte(board, addr + 1, (uae_u8)v);
}
} else if (board->type == APOLLO_IDE) {
if ((addr & 0xc000) == 0x4000) {
apollo_scsi_bput(addr, v >> 8, board->userdata);
apollo_scsi_bput(addr + 1, (uae_u8)v, board->userdata);
} else if (addr < 0x4000) {
int regnum = get_apollo_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
}
}
} else if (board->type == GVP_IDE) {
if (board == gvp_ide_controller_board || ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SI)) {
if (addr < 0x60) {
#if DEBUG_IDE_GVP
write_log(_T("GVP IO WORD WRITE %08x %04x %08x\n"), addr, v, M68K_GETPC);
#endif
if (addr == 0x40 && ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SII))
board->intena = (v & 8) != 0;
} else {
int regnum = get_gvp_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
#if DEBUG_IDE_GVP > 2
write_log(_T("IDE WORD WRITE %04x\n"), v);
#endif
} else {
ide_write_byte(board, addr, v >> 8);
ide_write_byte(board, addr + 1, v & 0xff);
}
}
}
} else if (board->type == ADIDE_IDE) {
int regnum = get_adide_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
} else {
v = adide_encode_word(v);
put_ide_reg(board, regnum, v >> 8);
}
} else if (board->type == MTEC_IDE) {
if (board->configured && (addr & 0x8000)) {
int regnum = (addr >> 8) & 7;
if (regnum == IDE_DATA)
put_ide_reg(board, regnum, v);
else
ide_write_byte(board, addr, v >> 8);
}
} else if (board->type == DATAFLYERPLUS_IDE) {
if (board->configured) {
if (board->subtype & 2) {
int reg = get_dataflyerplus_reg(addr, board);
if (reg >= 0)
put_ide_reg_multi(board, reg, v, 0, 1);
}
}
} else if (board->type == ROCHARD_IDE) {
if (board->configured && (addr & 0x8020) == 0x8000) {
put_ide_reg_multi(board, IDE_DATA, v, (addr & 0x4000) ? 1 : 0, 1);
}
} else if (board->type == ATEAM_IDE) {
if (board->configured && (addr & 0xf800) == 0xf800) {
put_ide_reg_multi(board, IDE_DATA, v, 0, 1);
}
} else if (board->type == ARRIBA_IDE) {
int reg = get_arriba_reg(addr, board);
if (!reg) {
put_ide_reg_multi(board, IDE_DATA, v, 0, 1);
}
} else if (board->type == ELSATHD_IDE) {
int reg = get_elsathd_reg(addr | 1, board);
if (!reg) {
put_ide_reg_multi(board, IDE_DATA, v, 0, 1);
} else if (reg > 0) {
put_ide_reg(board, reg, v & 0xff);
}
} else if (board->type == FASTATA4K_IDE) {
int portnum;
int reg = get_fastata4k_reg(addr, board, &portnum);
if (reg == 0) {
put_ide_reg_multi(board, IDE_DATA, v, portnum, 1);
}
} else if (board->type == ACCESSX_IDE) {
int portnum;
int reg = get_accessx_reg(addr, board, &portnum);
if (!reg) {
put_ide_reg_multi(board, IDE_DATA, v, portnum, 1);
}
} else if (board->type == IVST500AT_IDE) {
int portnum;
int reg = get_ivst500at_reg(addr, board, &portnum);
if (!reg || addr == 0 || addr == 2) {
put_ide_reg_multi(board, IDE_DATA, v, portnum, 1);
}
} else if (board->type == DOTTO_IDE) {
int regnum = get_adide_reg(addr, board);
if (regnum == IDE_DATA) {
put_ide_reg(board, IDE_DATA, v);
} else {
v = adide_encode_word(v);
put_ide_reg(board, regnum, v >> 8);
}
} else if (board->type == DEV_IDE) {
int reg = get_dev_hd_reg(addr, board);
if (reg == IDE_DATA) {
put_ide_reg(board, reg, v);
}
}
}
}
static uae_u32 ide_read_wordi(struct ide_board *board, uaecptr addr)
{
return ide_read_word(board, addr);
}
IDE_MEMORY_FUNCTIONS(ide_controller_gvp, ide, gvp_ide_controller_board);
addrbank gvp_ide_controller_bank = {
ide_controller_gvp_lget, ide_controller_gvp_wget, ide_controller_gvp_bget,
ide_controller_gvp_lput, ide_controller_gvp_wput, ide_controller_gvp_bput,
default_xlate, default_check, NULL, NULL, _T("GVP IDE"),
dummy_lgeti, dummy_wgeti,
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
};
IDE_MEMORY_FUNCTIONS(ide_rom_gvp, ide, gvp_ide_rom_board);
addrbank gvp_ide_rom_bank = {
ide_rom_gvp_lget, ide_rom_gvp_wget, ide_rom_gvp_bget,
ide_rom_gvp_lput, ide_rom_gvp_wput, ide_rom_gvp_bput,
default_xlate, default_check, NULL, NULL, _T("GVP BOOT"),
dummy_lgeti, dummy_wgeti,
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
};
static void REGPARAM2 ide_generic_bput (uaecptr addr, uae_u32 b)
{
struct ide_board *ide = getideboard(addr);
if (ide)
ide_write_byte(ide, addr, b);
}
static void REGPARAM2 ide_generic_wput (uaecptr addr, uae_u32 b)
{
struct ide_board *ide = getideboard(addr);
if (ide)
ide_write_word(ide, addr, b);
}
static void REGPARAM2 ide_generic_lput (uaecptr addr, uae_u32 b)
{
struct ide_board *ide = getideboard(addr);
if (ide) {
ide_write_word(ide, addr, b >> 16);
ide_write_word(ide, addr + 2, b);
}
}
static uae_u32 REGPARAM2 ide_generic_bget (uaecptr addr)
{
struct ide_board *ide = getideboard(addr);
if (ide)
return ide_read_byte(ide, addr);
return 0;
}
static uae_u32 REGPARAM2 ide_generic_wget (uaecptr addr)
{
struct ide_board *ide = getideboard(addr);
if (ide)
return ide_read_word(ide, addr);
return 0;
}
static uae_u32 REGPARAM2 ide_generic_lget (uaecptr addr)
{
struct ide_board *ide = getideboard(addr);
if (ide) {
uae_u32 v = ide_read_word(ide, addr) << 16;
v |= ide_read_word(ide, addr + 2);
return v;
}
return 0;
}
static uae_u32 REGPARAM2 ide_generic_wgeti(uaecptr addr)
{
struct ide_board *ide = getideboard(addr);
if (ide)
return ide_read_wordi(ide, addr);
return 0;
}
static uae_u32 REGPARAM2 ide_generic_lgeti(uaecptr addr)
{
struct ide_board *ide = getideboard(addr);
if (ide) {
uae_u32 v = ide_read_wordi(ide, addr) << 16;
v |= ide_read_wordi(ide, addr + 2);
return v;
}
return 0;
}
static uae_u8 *REGPARAM2 ide_generic_xlate(uaecptr addr)
{
struct ide_board *ide = getideboard(addr);
if (!ide)
return NULL;
addr &= ide->rom_mask;
return ide->rom + addr;
}
static int REGPARAM2 ide_generic_check(uaecptr a, uae_u32 b)
{
struct ide_board *ide = getideboard(a);
if (!ide)
return 0;
a &= ide->rom_mask;
if (a >= ide->rom_start && a + b < ide->rom_size)
return 1;
return 0;
}
static addrbank ide_bank_generic = {
ide_generic_lget, ide_generic_wget, ide_generic_bget,
ide_generic_lput, ide_generic_wput, ide_generic_bput,
ide_generic_xlate, ide_generic_check, NULL, NULL, _T("IDE"),
ide_generic_lgeti, ide_generic_wgeti,
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
};
static struct ide_board *getide(struct autoconfig_info *aci)
{
device_add_rethink(idecontroller_rethink);
device_add_hsync(idecontroller_hsync);
device_add_exit(idecontroller_free);
for (int i = 0; i < MAX_IDE_UNITS; i++) {
if (ide_boards[i]) {
struct ide_board *ide = ide_boards[i];
if (ide->rc == aci->rc) {
ide->original_rc = aci->rc;
ide->rc = NULL;
ide->aci = aci;
return ide;
}
}
}
return NULL;
}
static void ide_add_reset(void)
{
device_add_reset(idecontroller_reset);
}
static void ew(struct ide_board *ide, int addr, uae_u32 value)
{
addr &= 0xffff;
if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
ide->acmemory[addr] = (value & 0xf0);
ide->acmemory[addr + 2] = (value & 0x0f) << 4;
} else {
ide->acmemory[addr] = ~(value & 0xf0);
ide->acmemory[addr + 2] = ~((value & 0x0f) << 4);
}
}
static const uae_u8 gvp_ide2_rom_autoconfig[16] = { 0xd1, 0x0d, 0x00, 0x00, 0x07, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
static const uae_u8 gvp_ide2_controller_autoconfig[16] = { 0xc1, 0x0b, 0x00, 0x00, 0x07, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const uae_u8 gvp_ide1_controller_autoconfig[16] = { 0xd1, 0x08, 0x00, 0x00, 0x07, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
bool gvp_ide_rom_autoconfig_init(struct autoconfig_info *aci)
{
const uae_u8 *autoconfig;
if (ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SI)) {
autoconfig = gvp_ide1_controller_autoconfig;
} else {
autoconfig = gvp_ide2_rom_autoconfig;
}
ide_add_reset();
aci->autoconfigp = autoconfig;
if (!aci->doinit)
return true;
struct ide_board *ide = getide(aci);
if (ISCPUBOARD(BOARD_GVP, BOARD_GVP_SUB_A3001SI)) {
ide->bank = &gvp_ide_rom_bank;
init_ide(ide, GVP_IDE, 2, true, false);
ide->rom_size = 8192;
gvp_ide_controller_board->intena = true;
ide->intena = true;
gvp_ide_controller_board->configured = -1;
} else {
ide->bank = &gvp_ide_rom_bank;
ide->rom_size = 16384;
}
ide->mask = 65536 - 1;
ide->type = GVP_IDE;
ide->configured = 0;
memset(ide->acmemory, 0xff, sizeof ide->acmemory);
ide->rom = xcalloc(uae_u8, ide->rom_size);
memset(ide->rom, 0xff, ide->rom_size);
ide->rom_mask = ide->rom_size - 1;
load_rom_rc(aci->rc, ROMTYPE_CB_A3001S1, ide->rom_size, 0, ide->rom, ide->rom_size, LOADROM_FILL);
for (int i = 0; i < 16; i++) {
uae_u8 b = autoconfig[i];
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
bool gvp_ide_controller_autoconfig_init(struct autoconfig_info *aci)
{
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = gvp_ide2_controller_autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
init_ide(ide, GVP_IDE, 2, true, false);
ide->configured = 0;
ide->bank = &gvp_ide_controller_bank;
memset(ide->acmemory, 0xff, sizeof ide->acmemory);
for (int i = 0; i < 16; i++) {
uae_u8 b = gvp_ide2_controller_autoconfig[i];
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
void gvp_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
struct ide_hdf *ide;
if (!allocide(&gvp_ide_rom_board, rc, ch))
return;
if (!allocide(&gvp_ide_controller_board, rc, ch))
return;
ide = add_ide_unit (&idecontroller_drive[(GVP_IDE + ci->controller_type_unit) * 2], 2, ch, ci, rc);
}
static const uae_u8 alf_autoconfig[16] = { 0xd1, 6, 0x00, 0x00, 0x08, 0x2c, 0x00, 0x00, 0x00, 0x00, ALF_ROM_OFFSET >> 8, ALF_ROM_OFFSET & 0xff };
static const uae_u8 alfplus_autoconfig[16] = { 0xd1, 38, 0x00, 0x00, 0x08, 0x2c, 0x00, 0x00, 0x00, 0x00, ALF_ROM_OFFSET >> 8, ALF_ROM_OFFSET & 0xff };
bool alf_init(struct autoconfig_info *aci)
{
bool alfplus = is_board_enabled(&currprefs, ROMTYPE_ALFAPLUS, 0);
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = alfplus ? alfplus_autoconfig : alf_autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
if (!ide)
return false;
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->type = ALF_IDE;
ide->rom_size = 32768 * 6;
ide->userdata = alfplus;
ide->intena = alfplus;
ide->mask = 65536 - 1;
memset(ide->acmemory, 0xff, sizeof ide->acmemory);
ide->rom = xcalloc(uae_u8, ide->rom_size);
memset(ide->rom, 0xff, ide->rom_size);
ide->rom_mask = ide->rom_size - 1;
for (int i = 0; i < 16; i++) {
uae_u8 b = alfplus ? alfplus_autoconfig[i] : alf_autoconfig[i];
ew(ide, i * 4, b);
}
if (!aci->rc->autoboot_disabled) {
struct zfile *z = read_device_from_romconfig(aci->rc, alfplus ? ROMTYPE_ALFAPLUS : ROMTYPE_ALFA);
if (z) {
for (int i = 0; i < 0x1000 / 2; i++) {
uae_u8 b;
zfile_fread(&b, 1, 1, z);
ide->rom[ALF_ROM_OFFSET + i * 4 + 0] = b;
zfile_fread(&b, 1, 1, z);
ide->rom[ALF_ROM_OFFSET + i * 4 + 2] = b;
}
for (int i = 0; i < 32768 - 0x1000; i++) {
uae_u8 b;
zfile_fread(&b, 1, 1, z);
ide->rom[0x2000 + i * 4 + 1] = b;
zfile_fread(&b, 1, 1, z);
ide->rom[0x2000 + i * 4 + 3] = b;
}
zfile_fclose(z);
}
}
aci->addrbank = ide->bank;
return true;
}
void alf_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, alf_board, ALF_IDE, false, false, 2);
}
// prod 0x22 = IDE + SCSI
// prod 0x23 = SCSI only
// prod 0x33 = IDE only
const uae_u8 apollo_autoconfig[16] = { 0xd1, 0x22, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, APOLLO_ROM_OFFSET >> 8, APOLLO_ROM_OFFSET & 0xff };
const uae_u8 apollo_autoconfig_cpuboard[16] = { 0xd2, 0x23, 0x40, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, APOLLO_ROM_OFFSET >> 8, APOLLO_ROM_OFFSET & 0xff };
const uae_u8 apollo_autoconfig_cpuboard_060[16] = { 0xd2, 0x23, 0x40, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x02, APOLLO_ROM_OFFSET >> 8, APOLLO_ROM_OFFSET & 0xff };
static bool apollo_init(struct autoconfig_info *aci, bool cpuboard)
{
const uae_u8 *autoconfig = apollo_autoconfig;
if (cpuboard) {
if (currprefs.cpu_model == 68060)
autoconfig = apollo_autoconfig_cpuboard_060;
else
autoconfig = apollo_autoconfig_cpuboard;
}
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
if (!ide)
return false;
if (cpuboard) {
// bit 0: scsi enable
// bit 1: memory disable
ide->userdata = currprefs.cpuboard_settings & 1;
} else {
ide->userdata = aci->rc->autoboot_disabled ? 2 : 0;
}
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->rom_size = 32768;
ide->type = APOLLO_IDE;
memset(ide->acmemory, 0xff, sizeof ide->acmemory);
ide->rom = xcalloc(uae_u8, ide->rom_size);
memset(ide->rom, 0xff, ide->rom_size);
ide->rom_mask = ide->rom_size - 1;
ide->keepautoconfig = false;
for (int i = 0; i < 16; i++) {
uae_u8 b = autoconfig[i];
if (cpuboard && i == 9 && (currprefs.cpuboard_settings & 2))
b |= 1; // memory disable (serial bit 0)
ew(ide, i * 4, b);
}
if (cpuboard) {
ide->mask = 131072 - 1;
struct zfile *z = read_device_from_romconfig(aci->rc, ROMTYPE_APOLLO);
if (z) {
int len = zfile_size32(z);
// skip 68060 $f0 ROM block
if (len >= 65536)
zfile_fseek(z, 32768, SEEK_SET);
for (int i = 0; i < 32768; i++) {
uae_u8 b;
zfile_fread(&b, 1, 1, z);
ide->rom[i] = b;
}
zfile_fclose(z);
}
} else {
ide->mask = 65536 - 1;
load_rom_rc(aci->rc, ROMTYPE_APOLLO, 16384, 0, ide->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
}
aci->addrbank = ide->bank;
return true;
}
bool apollo_init_hd(struct autoconfig_info *aci)
{
return apollo_init(aci, false);
}
bool apollo_init_cpu(struct autoconfig_info *aci)
{
return apollo_init(aci, true);
}
void apollo_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, apollo_board, APOLLO_IDE, true, false, 2);
}
bool masoboshi_init(struct autoconfig_info *aci)
{
int rom_size = 65536;
uae_u8 *rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ROMTYPE_MASOBOSHI, 32768, 0, rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
ide_add_reset();
if (!aci->doinit) {
if (aci->rc && aci->rc->autoboot_disabled)
memcpy(aci->autoconfig_raw, rom + 0x100, sizeof aci->autoconfig_raw);
else
memcpy(aci->autoconfig_raw, rom + 0x000, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
if (!ide)
return false;
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->type = MASOBOSHI_IDE;
ide->rom_size = rom_size;
ide->rom_mask = ide->mask = rom_size - 1;
ide->rom = rom;
ide->subtype = aci->rc->subtype;
if (aci->rc && aci->rc->autoboot_disabled)
memcpy(ide->acmemory, ide->rom + 0x100, sizeof ide->acmemory);
else
memcpy(ide->acmemory, ide->rom + 0x000, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
static void masoboshi_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, masoboshi_board, MASOBOSHI_IDE, true, false, 2);
}
void masoboshi_add_idescsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
if (ch < 0) {
masoboshi_add_ide_unit(ch, ci, rc);
masoboshi_add_scsi_unit(ch, ci, rc);
} else {
if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST)
masoboshi_add_ide_unit(ch, ci, rc);
else
masoboshi_add_scsi_unit(ch, ci, rc);
}
}
bool trifecta_init(struct autoconfig_info *aci)
{
int rom_size = 65536;
uae_u8 *rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = aci->ert->autoconfig;
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
if (!ide)
return false;
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->type = TRIFECTA_IDE;
ide->rom_size = rom_size;
ide->rom_mask = ide->mask = rom_size - 1;
ide->rom = rom;
ide->subtype = aci->rc->subtype;
ide->keepautoconfig = false;
ide->intena = true;
if (!aci->rc->autoboot_disabled)
load_rom_rc(aci->rc, ROMTYPE_TRIFECTA, 32768, 0, rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
for (int i = 0; i < 16; i++) {
uae_u8 b = aci->ert->autoconfig[i];
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
static void trifecta_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, trifecta_board, TRIFECTA_IDE, true, false, 2);
}
void trifecta_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
if (ch < 0) {
trifecta_add_ide_unit(ch, ci, rc);
trifecta_add_scsi_unit(ch, ci, rc);
} else {
if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST)
trifecta_add_ide_unit(ch, ci, rc);
else
trifecta_add_scsi_unit(ch, ci, rc);
}
}
static const uae_u8 adide_autoconfig[16] = { 0xd1, 0x02, 0x00, 0x00, 0x08, 0x17, 0x00, 0x00, 0x00, 0x00, ADIDE_ROM_OFFSET >> 8, ADIDE_ROM_OFFSET & 0xff };
bool adide_init(struct autoconfig_info *aci)
{
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = adide_autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->keepautoconfig = false;
ide->bank = &ide_bank_generic;
ide->rom_size = 32768;
ide->mask = 65536 - 1;
memset(ide->acmemory, 0xff, sizeof ide->acmemory);
ide->rom = xcalloc(uae_u8, ide->rom_size);
memset(ide->rom, 0xff, ide->rom_size);
ide->rom_mask = ide->rom_size - 1;
if (!aci->rc->autoboot_disabled) {
load_rom_rc(aci->rc, ROMTYPE_ADIDE, 16384, 0, ide->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
}
for (int i = 0; i < 16; i++) {
uae_u8 b = adide_autoconfig[i];
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
void adide_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, adide_board, ADIDE_IDE, false, true, 2);
}
bool mtec_init(struct autoconfig_info *aci)
{
uae_u8 *rom;
int rom_size = 32768;
rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ROMTYPE_MTEC, 16384, !aci->rc->autoboot_disabled ? 16384 : 0, rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
ide_add_reset();
if (!aci->doinit) {
memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom = rom;
ide->rom_size = rom_size;
ide->rom_mask = rom_size - 1;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
void mtec_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, mtec_board, MTEC_IDE, false, false, 2);
}
bool rochard_init(struct autoconfig_info *aci)
{
ide_add_reset();
if (!aci->doinit) {
load_rom_rc(aci->rc, ROMTYPE_ROCHARD, 8192, !aci->rc->autoboot_disabled ? 8192 : 0, aci->autoconfig_raw, sizeof aci->autoconfig_raw, 0);
return true;
}
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->rom_size = 32768;
ide->mask = 65536 - 1;
ide->subtype = aci->rc->subtype;
ide->rom = xcalloc(uae_u8, ide->rom_size);
memset(ide->rom, 0xff, ide->rom_size);
ide->rom_mask = ide->rom_size - 1;
load_rom_rc(aci->rc, ROMTYPE_ROCHARD, 8192, !aci->rc->autoboot_disabled ? 8192 : 0, ide->rom, 16384, 0);
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
static void rochard_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, rochard_board, ROCHARD_IDE, true, false, 4);
}
bool buddha_init(struct autoconfig_info *aci)
{
const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_BUDDHA);
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = ert->autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->rom_size = 65536;
ide->mask = 65536 - 1;
ide->rom = xcalloc(uae_u8, ide->rom_size);
memset(ide->rom, 0xff, ide->rom_size);
ide->rom_mask = ide->rom_size - 1;
load_rom_rc(aci->rc, ROMTYPE_BUDDHA, 32768, 0, ide->rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
for (int i = 0; i < 16; i++) {
uae_u8 b = ert->autoconfig[i];
if (i == 1 && (aci->rc->device_settings & 1))
b = 42;
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
void buddha_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, buddha_board, BUDDHA_IDE, false, false, 6);
}
void rochard_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
if (ch < 0) {
rochard_add_ide_unit(ch, ci, rc);
rochard_add_scsi_unit(ch, ci, rc);
} else {
if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST)
rochard_add_ide_unit(ch, ci, rc);
else
rochard_add_scsi_unit(ch, ci, rc);
}
}
bool golemfast_init(struct autoconfig_info *aci)
{
int rom_size = 32768;
uae_u8 *rom;
rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ROMTYPE_GOLEMFAST, 16384, 0, rom, 32768, 0);
ide_add_reset();
if (!aci->doinit) {
memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
ide->rom = rom;
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->rom_size = rom_size;
ide->mask = 65536 - 1;
ide->rom_mask = ide->rom_size - 1;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
static void golemfast_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, golemfast_board, GOLEMFAST_IDE, false, false, 2);
}
void golemfast_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
if (ch < 0) {
golemfast_add_ide_unit(ch, ci, rc);
golemfast_add_scsi_unit(ch, ci, rc);
} else {
if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST)
golemfast_add_ide_unit(ch, ci, rc);
else
golemfast_add_scsi_unit(ch, ci, rc);
}
}
bool dataflyerplus_init(struct autoconfig_info *aci)
{
int rom_size = 16384;
uae_u8 *rom;
rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ROMTYPE_DATAFLYER, 32768, aci->rc->autoboot_disabled ? 8192 : 0, rom, 16384, LOADROM_EVENONLY_ODDONE);
ide_add_reset();
if (!aci->doinit) {
memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
ide->rom = rom;
ide->configured = 0;
ide->bank = &ide_bank_generic;
ide->rom_size = rom_size;
ide->mask = 65536 - 1;
ide->keepautoconfig = false;
ide->subtype = ((aci->rc->device_settings & 3) <= 1) ? 1 : 0; // scsi
ide->subtype |= ((aci->rc->device_settings & 3) != 1) ? 2 : 0; // ide
ide->rom_mask = ide->rom_size - 1;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
static void dataflyerplus_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, dataflyerplus_board, DATAFLYERPLUS_IDE, true, false, 2);
}
void dataflyerplus_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
if (ch < 0) {
dataflyerplus_add_ide_unit(ch, ci, rc);
dataflyerplus_add_scsi_unit(ch, ci, rc);
} else {
if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST)
dataflyerplus_add_ide_unit(ch, ci, rc);
else
dataflyerplus_add_scsi_unit(ch, ci, rc);
}
}
bool ateam_init(struct autoconfig_info *aci)
{
uae_u8 *rom;
int rom_size = 32768;
rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ROMTYPE_ATEAM, 16384, !aci->rc->autoboot_disabled ? 0xc000 : 0x8000, rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
ide_add_reset();
if (!aci->doinit) {
memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->keepautoconfig = false;
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom = rom;
ide->rom_size = rom_size;
ide->rom_mask = rom_size - 1;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
void ateam_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, ateam_board, ATEAM_IDE, true, false, 2);
}
bool fastata4k_init(struct autoconfig_info *aci)
{
uae_u8 *rom;
int rom_size = 65536;
if (aci->postinit) {
struct ide_board *ide = getideboard(expamem_board_pointer);
ide->baseaddress = expamem_board_pointer;
ide->configured = 1;
return true;
}
ide_add_reset();
if (!aci->doinit) {
memcpy(aci->autoconfig_bytes, aci->ert->autoconfig, sizeof aci->ert->autoconfig);
int type = aci->rc->device_settings & 3;
if (type == 0)
aci->autoconfig_bytes[1] = 25;
else if (type == 1)
aci->autoconfig_bytes[1] = 29;
aci->autoconfigp = aci->autoconfig_bytes;
return true;
}
rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ROMTYPE_FASTATA4K, 65536, 0, rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->keepautoconfig = false;
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom = rom;
ide->rom_size = rom_size;
ide->rom_mask = rom_size - 1;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
aci->autoconfig_automatic = true;
return true;
}
void fastata4k_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, fastata4k_board, FASTATA4K_IDE, false, false, 2);
}
bool arriba_init(struct autoconfig_info *aci)
{
const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_ARRIBA);
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = ert->autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom_size = 32768;
ide->rom_mask = 32768 - 1;
ide->rom = xcalloc(uae_u8, 32768);
load_rom_rc(aci->rc, ROMTYPE_ARRIBA, 32768, 0, ide->rom, 32768, LOADROM_FILL);
for (int i = 0; i < 16; i++) {
uae_u8 b = ert->autoconfig[i];
if (i == 0 && aci->rc->autoboot_disabled)
b &= ~0x10;
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
void arriba_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, arriba_board, ARRIBA_IDE, false, false, 2);
}
bool elsathd_init(struct autoconfig_info *aci)
{
uae_u8 *rom;
int rom_size = 16384;
rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ELSATHD_IDE, 16384, 0, rom, 16384, LOADROM_FILL);
if (aci->rc->autoboot_disabled)
rom[0] &= ~0x10;
ide_add_reset();
if (!aci->doinit) {
memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->keepautoconfig = false;
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom = rom;
ide->rom_size = rom_size;
ide->rom_mask = rom_size - 1;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
void elsathd_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, elsathd_board, ELSATHD_IDE, true, false, 2);
}
bool accessx_init(struct autoconfig_info *aci)
{
uae_u8 *rom;
int rom_size = 32768;
rom = xcalloc(uae_u8, rom_size);
memset(rom, 0xff, rom_size);
load_rom_rc(aci->rc, ROMTYPE_ACCESSX, 32768, 0, rom, 32768, LOADROM_FILL);
uae_u8 rom2[32768];
memcpy(rom2, rom, 32768);
if ((rom[0] != 0xd0 && rom[1] != 0x10) && (rom[0] != 0xc0 && rom[1] != 0x10)) {
// descramble
if (aci->rc->subtype == 1) {
// 2000 variant
for (int i = 0; i < 32768; i += 2) {
int addr = 0;
addr |= ((i >> 7) & 1) << 0;
addr |= ((i >> 10) & 1) << 1;
addr |= ((i >> 9) & 1) << 2;
addr |= ((i >> 8) & 1) << 3;
addr |= ((i >> 1) & 1) << 4;
addr |= ((i >> 2) & 1) << 5;
addr |= ((i >> 3) & 1) << 6;
addr |= ((i >> 4) & 1) << 7;
addr |= ((i >> 13) & 1) << 8;
addr |= ((i >> 14) & 1) << 9;
if (!aci->rc->autoboot_disabled)
addr |= 1 << 10;
addr |= ((i >> 11) & 1) << 11;
addr |= ((i >> 6) & 1) << 12;
addr |= ((i >> 12) & 1) << 13;
addr |= ((i >> 5) & 1) << 14;
uae_u8 b = rom2[addr];
uae_u8 v = 0;
v |= ((b >> 4) & 1) << 1;
v |= ((b >> 5) & 1) << 2;
v |= ((b >> 6) & 1) << 0;
v |= ((b >> 7) & 1) << 3;
rom[i + 0] = v << 4;
rom[i + 1] = 0xff;
}
} else {
// 500 variant
for (int i = 0; i < 16384; i++) {
int addr = 0;
addr |= ((i >> 5) & 1) << 0;
addr |= ((i >> 4) & 1) << 1;
addr |= ((i >> 3) & 1) << 2;
addr |= ((i >> 6) & 1) << 3;
addr |= ((i >> 1) & 1) << 4;
addr |= ((i >> 0) & 1) << 5;
addr |= ((i >> 9) & 1) << 6;
addr |= ((i >> 11) & 1) << 7;
addr |= ((i >> 10) & 1) << 8;
addr |= ((i >> 8) & 1) << 9;
addr |= ((i >> 2) & 1) << 10;
addr |= ((i >> 7) & 1) << 11;
addr |= ((i >> 13) & 1) << 12;
addr |= ((i >> 12) & 1) << 13;
if (aci->rc->autoboot_disabled)
addr |= 1 << 14;
uae_u8 b = rom2[addr];
uae_u8 v = 0;
v |= ((b >> 0) & 1) << 1;
v |= ((b >> 1) & 1) << 2;
v |= ((b >> 2) & 1) << 3;
v |= ((b >> 3) & 1) << 0;
rom[i * 2 + 0] = v << 4;
rom[i * 2 + 1] = 0xff;
}
}
} else {
int offset = aci->rc->autoboot_disabled ? 16384 : 0;
for (int i = 0; i < 16384; i++) {
rom[i * 2 + 0] = rom2[i + offset];
rom[i * 2 + 1] = 0xff;
}
}
ide_add_reset();
if (!aci->doinit) {
memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
ide->configured = 0;
ide->intena = true;
ide->intlev6 = true;
ide->keepautoconfig = false;
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom = rom;
ide->rom_size = rom_size;
ide->rom_mask = rom_size - 1;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
void accessx_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, accessx_board, ACCESSX_IDE, false, false, 4);
}
bool trumpcard500at_init(struct autoconfig_info *aci)
{
const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_IVST500AT);
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = ert->autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom_size = 32768;
ide->rom_mask = 32768 - 1;
ide->keepautoconfig = false;
ide->intena = true;
ide->rom = xcalloc(uae_u8, 32768);
load_rom_rc(aci->rc, ROMTYPE_IVST500AT, 16384, 0, ide->rom, 32768, LOADROM_EVENONLY_ODDONE);
for (int i = 0; i < 16; i++) {
uae_u8 b = ert->autoconfig[i];
if (i == 0 && aci->rc->autoboot_disabled)
b &= ~0x10;
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
void trumpcard500at_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, ivst500at_board, IVST500AT_IDE, true, false, 2);
}
bool tandem_init(struct autoconfig_info *aci)
{
const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_TANDEM);
ide_add_reset();
if (!aci->doinit) {
aci->autoconfigp = ert->autoconfig;
return true;
}
struct ide_board *ide = getide(aci);
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
for (int i = 0; i < 16; i++) {
uae_u8 b = ert->autoconfig[i];
ew(ide, i * 4, b);
}
aci->addrbank = ide->bank;
return true;
}
void tandem_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, tandem_board, TANDEM_IDE, false, false, 2);
}
bool dotto_init(struct autoconfig_info *aci)
{
const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_DOTTO);
ide_add_reset();
uae_u8 *rom = xcalloc(uae_u8, 65536);
load_rom_rc(aci->rc, ROMTYPE_DOTTO, 32768, 0, rom, 65536, LOADROM_EVENONLY_ODDONE);
if (!aci->doinit) {
memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->rom_size = 65536;
ide->rom_mask = 65536 - 1;
ide->keepautoconfig = false;
ide->rom = rom;
memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
aci->addrbank = ide->bank;
return true;
}
void dotto_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, dotto_board, DOTTO_IDE, false, true, 2);
}
static const uae_u8 dev_autoconfig[16] = { 0xd1, 1, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
bool dev_hd_init(struct autoconfig_info *aci)
{
bool ac = true;
const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_DEVHD);
ide_add_reset();
uae_u8 *rom = xcalloc(uae_u8, 262144);
load_rom_rc(aci->rc, ROMTYPE_DEVHD, 131072, 0, rom, 262144, LOADROM_EVENONLY_ODDONE);
memmove(rom + 0x8000, rom, 262144 - 0x8000);
if (!ac) {
// fake
aci->start = 0xe90000;
aci->size = 0x10000;
}
dev_hd_io_base = 0x4000;
dev_hd_io_size = 4;
dev_hd_data_base = 0x4800;
dev_hd_io_secondary = 0x1000;
dev_hd_io_total = 8 * 4;
if (!aci->doinit) {
if (ac) {
aci->autoconfigp = dev_autoconfig;
}
xfree(rom);
return true;
}
struct ide_board *ide = getide(aci);
if (ac) {
for (int i = 0; i < 16; i++) {
uae_u8 b = dev_autoconfig[i];
ew(ide, i * 4, b);
}
}
ide->bank = &ide_bank_generic;
ide->mask = 65536 - 1;
ide->keepautoconfig = true;
ide->rom = rom;
memcpy(ide->rom, ide->acmemory, 128);
if (!ac) {
ide->baseaddress = aci->start;
ide->configured = 1;
map_banks(ide->bank, aci->start >> 16, aci->size >> 16, 0);
}
aci->addrbank = ide->bank;
return true;
}
void dev_hd_add_ide_unit(int ch, struct uaedev_config_info* ci, struct romconfig* rc)
{
add_ide_standard_unit(ch, ci, rc, dev_board, DEV_IDE, false, true, 2);
}
extern void x86_xt_ide_bios(struct zfile*, struct romconfig*);
static bool x86_at_hd_init(struct autoconfig_info *aci, int type)
{
static const int parent[] = { ROMTYPE_A1060, ROMTYPE_A2088, ROMTYPE_A2088T, ROMTYPE_A2286, ROMTYPE_A2386, 0 };
aci->parent_romtype = parent;
ide_add_reset();
if (!aci->doinit)
return true;
struct ide_board *ide = getide(aci);
if (!ide)
return false;
ide->intena = type == 0;
ide->configured = 1;
ide->bank = &ide_bank_generic;
struct zfile *f = read_device_from_romconfig(aci->rc, 0);
if (f) {
x86_xt_ide_bios(f, aci->rc);
zfile_fclose(f);
}
return true;
}
bool x86_at_hd_init_1(struct autoconfig_info *aci)
{
return x86_at_hd_init(aci, 0);
}
bool x86_at_hd_init_xt(struct autoconfig_info *aci)
{
return x86_at_hd_init(aci, 1);
}
void x86_add_at_hd_unit_1(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, &x86_at_ide_board[0], x86_AT_IDE + 0, false, false, 2);
}
void x86_add_at_hd_unit_xt(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
add_ide_standard_unit(ch, ci, rc, &x86_at_ide_board[1], x86_AT_IDE + 1, false, false, 2);
}
static int x86_ide_reg(int portnum, int *unit)
{
if (portnum >= 0x1f0 && portnum < 0x1f8) {
*unit = 0;
return portnum & 7;
}
if (portnum == 0x3f6) {
*unit = 0;
return 6 | IDE_SECONDARY;
}
if (portnum >= 0x300 && portnum < 0x310) {
*unit = 1;
if (portnum < 0x308)
return portnum & 7;
if (portnum == 0x308)
return 8;
if (portnum >= 0x308+6)
return (portnum & 7) | IDE_SECONDARY;
}
return -1;
}
void x86_ide_hd_put(int portnum, uae_u16 v, int size)
{
if (portnum < 0) {
for (int i = 0; i < MAX_DUPLICATE_EXPANSION_BOARDS; i++) {
struct ide_board *board = x86_at_ide_board[i];
if (board)
ide_reset_device(board->ide[0]);
}
return;
}
int unit;
int regnum = x86_ide_reg(portnum, &unit);
if (regnum >= 0) {
struct ide_board *board = x86_at_ide_board[unit];
if (board) {
if (size == 0) {
if (get_ide_is_8bit(board)) {
v = get_ide_reg_8bitdata(board, regnum);
} else {
if (regnum == 8) {
board->data_latch = v;
} else if (regnum == 0) {
v <<= 8;
v |= board->data_latch;
put_ide_reg(board, regnum, v);
} else {
put_ide_reg_8bitdata(board, regnum, v);
}
}
} else {
put_ide_reg(board, regnum, (v >> 8) | (v << 8));
}
}
}
}
uae_u16 x86_ide_hd_get(int portnum, int size)
{
uae_u16 v = 0;
int unit;
int regnum = x86_ide_reg(portnum, &unit);
if (regnum >= 0) {
struct ide_board *board = x86_at_ide_board[unit];
if (board) {
if (size == 0) {
if (get_ide_is_8bit(board)) {
v = get_ide_reg_8bitdata(board, regnum);
} else {
if (regnum == 0) {
board->data_latch = get_ide_reg(board, regnum);
v = board->data_latch >> 8;
} else if (regnum == 8) {
v = board->data_latch;
} else {
v = get_ide_reg_8bitdata(board, regnum & 7);
}
}
} else {
v = get_ide_reg(board, regnum);
v = (v >> 8) | (v << 8);
}
}
}
return v;
}