mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
3176 lines
81 KiB
C++
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;
|
|
}
|