/* * 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, NULL); 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; }