From 5d6c3fb9ea587fa05f84f8c00be355496957d9f8 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 5 Jul 2017 21:00:50 +0100 Subject: [PATCH] Added WD1007V-SE1 ESDI emulation. --- src/Makefile.am | 2 +- src/Makefile.linux32 | 2 +- src/Makefile.linux32-wx-sdl2 | 2 +- src/Makefile.linux64 | 2 +- src/Makefile.linux64-wx-sdl2 | 2 +- src/Makefile.mingw | 2 +- src/Makefile.mingw-wx-sdl2 | 2 +- src/Makefile.mingw64 | 2 +- src/Makefile.osx64-wx-sdl2 | 2 +- src/esdi_at.c | 834 +++++++++++++++++++++++++++++++++++ src/esdi_at.h | 1 + src/hdd.c | 16 +- src/hdd_file.c | 39 +- src/hdd_file.h | 6 +- src/rom.c | 2 +- src/rom.h | 4 + 16 files changed, 891 insertions(+), 29 deletions(-) create mode 100644 src/esdi_at.c create mode 100644 src/esdi_at.h diff --git a/src/Makefile.am b/src/Makefile.am index b8ae928..2ab6bbc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ amrefresh: pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acer386sx.c ali1429.c amstrad.c cdrom-ioctl-linux.c cdrom-image.cc cdrom-null.c \ codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ -dac.c dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ +dac.c dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ laserxt.c lpt.c mca.c mcr.c mem.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c olivetti_m24.c \ diff --git a/src/Makefile.linux32 b/src/Makefile.linux32 index ea65156..40a175b 100644 --- a/src/Makefile.linux32 +++ b/src/Makefile.linux32 @@ -7,7 +7,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o allegro allegro-gui-configure.o allegro-gui-config-sel.o allegro-gui-deviceconfig.o allegro-gui-hdconf.o allegro-joystick.o allegro-keyboard.o allegro-main.o \ allegro-midi.o allegro-mouse.o allegro-video.o amstrad.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.c compaq.o config.o cpu.o \ -dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ +dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \ laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ diff --git a/src/Makefile.linux32-wx-sdl2 b/src/Makefile.linux32-wx-sdl2 index 2735900..c0cb649 100644 --- a/src/Makefile.linux32-wx-sdl2 +++ b/src/Makefile.linux32-wx-sdl2 @@ -5,7 +5,7 @@ WXRC = wxrc CFLAGS = -O3 -fomit-frame-pointer -msse2 -m32 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags) OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.c compaq.o config.o cpu.o \ -dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ +dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \ laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ diff --git a/src/Makefile.linux64 b/src/Makefile.linux64 index 7715e58..1234299 100644 --- a/src/Makefile.linux64 +++ b/src/Makefile.linux64 @@ -6,7 +6,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o allegro allegro-gui-configure.o allegro-gui-config-sel.o allegro-gui-deviceconfig.o allegro-gui-hdconf.o allegro-joystick.o allegro-keyboard.o allegro-main.o \ allegro-midi.o allegro-mouse.o allegro-video.o amstrad.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \ -dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ +dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \ laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ diff --git a/src/Makefile.linux64-wx-sdl2 b/src/Makefile.linux64-wx-sdl2 index 15c2f3e..d4f5305 100644 --- a/src/Makefile.linux64-wx-sdl2 +++ b/src/Makefile.linux64-wx-sdl2 @@ -5,7 +5,7 @@ WXRC = wxrc CFLAGS = -Doff64_t=__off64_t -O3 -fomit-frame-pointer -msse2 -m64 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags) OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \ -dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ +dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \ laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 7e1f51a..9e34408 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -5,7 +5,7 @@ WINDRES = windres.exe CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Wall -Werror -fno-strict-aliasing OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-image.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \ - dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \ + dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \ i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o \ mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index 741ad5f..bd47f6a 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -5,7 +5,7 @@ WXRC = wxrc CFLAGS = -DRELEASE_BUILD -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-image.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \ - device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \ + device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \ i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o \ mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o \ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index 812b4ce..1e108c4 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -5,7 +5,7 @@ WINDRES = windres.exe CFLAGS = -O3 -fomit-frame-pointer -msse2 -Wall -Werror -fno-strict-aliasing OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-image.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \ - dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \ + dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \ i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o \ mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o \ diff --git a/src/Makefile.osx64-wx-sdl2 b/src/Makefile.osx64-wx-sdl2 index 953f665..a93c541 100644 --- a/src/Makefile.osx64-wx-sdl2 +++ b/src/Makefile.osx64-wx-sdl2 @@ -5,7 +5,7 @@ WXRC = wxrc CFLAGS = -D__unix=1 -DPCEM_RENDER_WITH_TIMER -DPCEM_RENDER_TIMER_LOOP -Dfopen64=fopen -Dfseeko64=fseeko -Dftello64=ftello -Doff64_t=off_t -O3 -fomit-frame-pointer -msse2 -m64 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags) -I/usr/local/opt/openal-soft/include -I/usr/local/include OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl-osx.o cdrom-image.o cdrom-null.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \ -dac.o device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ +dac.o device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \ laserxt.o lpt.o mca.o mcr.o mem.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ diff --git a/src/esdi_at.c b/src/esdi_at.c new file mode 100644 index 0000000..88646ee --- /dev/null +++ b/src/esdi_at.c @@ -0,0 +1,834 @@ +#include +#include +#include +#include + +#include + +#include "ibm.h" +#include "device.h" +#include "hdd_file.h" +#include "io.h" +#include "mem.h" +#include "pic.h" +#include "rom.h" +#include "timer.h" + +#include "esdi_at.h" + + +#define IDE_TIME (TIMER_USEC*10)//(5 * 100 * (1 << TIMER_SHIFT)) + +#define STAT_ERR 0x01 +#define STAT_INDEX 0x02 +#define STAT_CORRECTED_DATA 0x04 +#define STAT_DRQ 0x08 /* Data request */ +#define STAT_DSC 0x10 +#define STAT_SEEK_COMPLETE 0x20 +#define STAT_READY 0x40 +#define STAT_BUSY 0x80 + +#define ERR_DAM_NOT_FOUND 0x01 /*Data Address Mark not found*/ +#define ERR_TR000 0x02 /*Track 0 not found*/ +#define ERR_ABRT 0x04 /*Command aborted*/ +#define ERR_ID_NOT_FOUND 0x10 /*ID not found*/ +#define ERR_DATA_CRC 0x40 /*Data CRC error*/ +#define ERR_BAD_BLOCK 0x80 /*Bad Block detected*/ + +#define CMD_NOP 0x00 +#define CMD_RESTORE 0x10 +#define CMD_READ 0x20 +#define CMD_WRITE 0x30 +#define CMD_VERIFY 0x40 +#define CMD_FORMAT 0x50 +#define CMD_SEEK 0x70 +#define CMD_DIAGNOSE 0x90 +#define CMD_SET_PARAMETERS 0x91 +#define CMD_READ_PARAMETERS 0xec + +extern char ide_fn[4][512]; + +typedef struct esdi_drive_t +{ + int cfg_spt; + int cfg_hpc; + int current_cylinder; + hdd_file_t hdd_file; +} esdi_drive_t; + +typedef struct esdi_t +{ + uint8_t status; + uint8_t error; + int secount,sector,cylinder,head,cylprecomp; + uint8_t command; + uint8_t fdisk; + int pos; + + int drive_sel; + int reset; + uint16_t buffer[256]; + int irqstat; + + int callback; + + esdi_drive_t drives[2]; + + rom_t bios_rom; +} esdi_t; + +uint16_t esdi_readw(uint16_t port, void *p); +void esdi_writew(uint16_t port, uint16_t val, void *p); + +static inline void esdi_irq_raise(esdi_t *esdi) +{ +// pclog("IDE_IRQ_RAISE\n"); + if (!(esdi->fdisk&2)) + picint(1 << 14); + + esdi->irqstat=1; +} + +static inline void esdi_irq_lower(esdi_t *esdi) +{ + picintc(1 << 14); +} + +void esdi_irq_update(esdi_t *esdi) +{ + if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2)) + picint(1 << 14); +} + +/* + * Return the sector offset for the current register values + */ +int esdi_get_sector(esdi_t *esdi, off64_t *addr) +{ + esdi_drive_t *drive = &esdi->drives[esdi->drive_sel]; + int heads = drive->cfg_hpc; + int sectors = drive->cfg_spt; + + if (esdi->head > heads) + { + pclog("esdi_get_sector: past end of configured heads\n"); + return 1; + } + if (esdi->sector >= sectors+1) + { + pclog("esdi_get_sector: past end of configured sectors\n"); + return 1; + } + + if (drive->cfg_spt == drive->hdd_file.spt && drive->cfg_hpc == drive->hdd_file.hpc) + { + *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * + sectors) + (esdi->sector - 1); + } + else + { + /*When performing translation, the firmware seems to leave 1 + sector per track inaccessible (spare sector)*/ + int c, h, s; + *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * + sectors) + (esdi->sector - 1); + + s = *addr % (drive->hdd_file.spt - 1); + h = (*addr / (drive->hdd_file.spt - 1)) % drive->hdd_file.hpc; + c = (*addr / (drive->hdd_file.spt - 1)) / drive->hdd_file.hpc; + + *addr = ((((off64_t) c * drive->hdd_file.hpc) + h) * + drive->hdd_file.spt) + s; + } + + return 0; +} + +/** + * Move to the next sector using CHS addressing + */ +void esdi_next_sector(esdi_t *esdi) +{ + esdi_drive_t *drive = &esdi->drives[esdi->drive_sel]; + + esdi->sector++; + if (esdi->sector == (drive->cfg_spt + 1)) + { + esdi->sector = 1; + esdi->head++; + if (esdi->head == drive->cfg_hpc) + { + esdi->head = 0; + esdi->cylinder++; + if (drive->current_cylinder < drive->hdd_file.tracks) + drive->current_cylinder++; + } + } +} + +void esdi_write(uint16_t port, uint8_t val, void *p) +{ + esdi_t *esdi = (esdi_t *)p; + +// pclog("esdi_write: addr=%04x val=%02x\n", port, val); + switch (port) + { + case 0x1F0: /* Data */ + esdi_writew(port, val | (val << 8), p); + return; + + case 0x1F1: /* Write precompenstation */ + esdi->cylprecomp = val; + return; + + case 0x1F2: /* Sector count */ + esdi->secount = val; + return; + + case 0x1F3: /* Sector */ + esdi->sector = val; + return; + + case 0x1F4: /* Cylinder low */ + esdi->cylinder = (esdi->cylinder & 0xFF00) | val; + return; + + case 0x1F5: /* Cylinder high */ + esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8); + return; + + case 0x1F6: /* Drive/Head */ + esdi->head = val & 0xF; + esdi->drive_sel = (val & 0x10) ? 1 : 0; + if (esdi->drives[esdi->drive_sel].hdd_file.f == NULL) + esdi->status = 0; + else + esdi->status = STAT_READY | STAT_DSC; + return; + + case 0x1F7: /* Command register */ +// if (esdi->drives[esdi->drive_sel].hdd_file.f == NULL && val != CMD_SET_PARAMETERS && val != CMD_NOP && val != 0xe0 && (val & ~3) != 0x20 && (val & ~3) != 0x30 && (val & ~3) != 0x40 && val != 0x90 && val != CMD_READ_PARAMETERS) +// fatal("Command %02x on non-present drive\n", val); + + esdi_irq_lower(esdi); + esdi->command = val; + esdi->error = 0; + + switch (val & 0xf0) + { + case CMD_RESTORE: +// pclog("Restore\n"); + esdi->command &= ~0x0f; /*Mask off step rate*/ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200*IDE_TIME; + timer_update_outstanding(); + break; + + case CMD_SEEK: +// pclog("Seek to cylinder %i\n", esdi->cylinder); + esdi->command &= ~0x0f; /*Mask off step rate*/ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200*IDE_TIME; + timer_update_outstanding(); + break; + + default: + switch (val) + { + case CMD_NOP: + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200*IDE_TIME; + timer_update_outstanding(); + break; + + case CMD_READ: case CMD_READ+1: + case CMD_READ+2: case CMD_READ+3: +// pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",esdi->secount,esdi->sector,esdi->cylinder,esdi->head,ins); + esdi->command &= ~3; + if (val & 2) + fatal("Read with ECC\n"); + case 0xa0: + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200*IDE_TIME; + timer_update_outstanding(); + break; + + case CMD_WRITE: case CMD_WRITE+1: + case CMD_WRITE+2: case CMD_WRITE+3: +// pclog("Write %i sectors to sector %i cylinder %i head %i\n",esdi->secount,esdi->sector,esdi->cylinder,esdi->head); + esdi->command &= ~3; + if (val & 2) + fatal("Write with ECC\n"); + esdi->status = STAT_DRQ | STAT_DSC;// | STAT_BUSY; + esdi->pos=0; + break; + + case CMD_VERIFY: case CMD_VERIFY+1: +// pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",esdi->secount,esdi->sector,esdi->cylinder,esdi->head); + esdi->command &= ~1; + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200 * IDE_TIME; + timer_update_outstanding(); + break; + + case CMD_FORMAT: +// pclog("Format track %i head %i\n", esdi->cylinder, esdi->head); + esdi->status = STAT_DRQ;// | STAT_BUSY; + esdi->pos=0; + break; + + case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 30*IDE_TIME; + timer_update_outstanding(); + break; + + case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200*IDE_TIME; + timer_update_outstanding(); + break; + + case 0xe0: /*???*/ + case CMD_READ_PARAMETERS: + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200*IDE_TIME; + timer_update_outstanding(); + break; + + default: + pclog("Bad esdi command %02X\n", val); + case 0xe8: /*???*/ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200*IDE_TIME; + timer_update_outstanding(); + break; + } + } + break; + + case 0x3F6: /* Device control */ + if ((esdi->fdisk & 4) && !(val & 4)) + { + timer_process(); + esdi->callback = 500*IDE_TIME; + timer_update_outstanding(); + esdi->reset = 1; + esdi->status = STAT_BUSY; +// pclog("esdi Reset\n"); + } + if (val & 4) + { + /*Drive held in reset*/ + timer_process(); + esdi->callback = 0; + timer_update_outstanding(); + esdi->status = STAT_BUSY; + } + esdi->fdisk = val; + esdi_irq_update(esdi); + return; + } +// fatal("Bad ESDI write %04X %02X\n", port, val); +} + +void esdi_writew(uint16_t port, uint16_t val, void *p) +{ + esdi_t *esdi = (esdi_t *)p; + +// pclog("Write ESDIw %04X\n",val); + esdi->buffer[esdi->pos >> 1] = val; + esdi->pos += 2; + + if (esdi->pos >= 512) + { + esdi->pos = 0; + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 6*IDE_TIME; + timer_update_outstanding(); + } +} + +uint8_t esdi_read(uint16_t port, void *p) +{ + esdi_t *esdi = (esdi_t *)p; + uint8_t temp = 0xff; + + switch (port) + { + case 0x1F0: /* Data */ + temp = esdi_readw(port, esdi) & 0xff; + break; + + case 0x1F1: /* Error */ + temp = esdi->error; + break; + + case 0x1F2: /* Sector count */ + temp = (uint8_t)esdi->secount; + break; + + case 0x1F3: /* Sector */ + temp = (uint8_t)esdi->sector; + break; + + case 0x1F4: /* Cylinder low */ + temp = (uint8_t)(esdi->cylinder&0xFF); + break; + + case 0x1F5: /* Cylinder high */ + temp = (uint8_t)(esdi->cylinder>>8); + break; + + case 0x1F6: /* Drive/Head */ + temp = (uint8_t)(esdi->head | (esdi->drive_sel ? 0x10 : 0) | 0xa0); + break; + + case 0x1F7: /* Status */ + esdi_irq_lower(esdi); + temp = esdi->status; + break; + } + +// if (port != 0x1f7) pclog("esdi_read: addr=%04x val=%02x %04X:%04x\n", port, temp, CS, cpu_state.pc); + return temp; +} + +uint16_t esdi_readw(uint16_t port, void *p) +{ + esdi_t *esdi = (esdi_t *)p; + uint16_t temp; + + temp = esdi->buffer[esdi->pos >> 1]; + esdi->pos += 2; + + if (esdi->pos >= 512) + { +// pclog("Over! packlen %i %i\n",ide->packlen,ide->pos); + esdi->pos=0; + esdi->status = STAT_READY | STAT_DSC; + if (esdi->command == CMD_READ || esdi->command == 0xa0) + { + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) + { + esdi_next_sector(esdi); + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 6*IDE_TIME; + timer_update_outstanding(); + } + } + } + +// pclog("esdi_readw: temp=%04x %i\n", temp, esdi->pos); + return temp; +} + +void esdi_callback(void *p) +{ + esdi_t *esdi = (esdi_t *)p; + esdi_drive_t *drive = &esdi->drives[esdi->drive_sel]; + off64_t addr; + +// pclog("esdi_callback: command=%02x reset=%i\n", esdi->command, esdi->reset); + esdi->callback = 0; + if (esdi->reset) + { + esdi->status = STAT_READY | STAT_DSC; + esdi->error = 1; + esdi->secount = 1; + esdi->sector = 1; + esdi->head = 0; + esdi->cylinder = 0; + esdi->reset = 0; +// pclog("Reset callback\n"); + return; + } + switch (esdi->command) + { + case CMD_RESTORE: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + drive->current_cylinder = 0; + esdi->status = STAT_READY | STAT_DSC; + esdi_irq_raise(esdi); + } + break; + + case CMD_SEEK: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + esdi->status = STAT_READY | STAT_DSC; + esdi_irq_raise(esdi); + } + break; + + case CMD_READ: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + if (esdi_get_sector(esdi, &addr)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + if (hdd_read_sectors(&drive->hdd_file, addr, 1, esdi->buffer)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; +// pclog("Read sector callback %i %i %i offset %08X %i left %i %02X\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt,ide.atastat[ide.board]); +// if (addr) output=3; + esdi_irq_raise(esdi); + readflash_set(READFLASH_HDC, esdi->drive_sel); + } + break; + + case CMD_WRITE: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + if (esdi_get_sector(esdi, &addr)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + if (hdd_write_sectors(&drive->hdd_file, addr, 1, esdi->buffer)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + esdi_irq_raise(esdi); + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) + { + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + esdi->pos = 0; + esdi_next_sector(esdi); + } + else + esdi->status = STAT_READY | STAT_DSC; + readflash_set(READFLASH_HDC, esdi->drive_sel); + } + break; + + case CMD_VERIFY: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + if (esdi_get_sector(esdi, &addr)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + if (hdd_read_sectors(&drive->hdd_file, addr, 1, esdi->buffer)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + readflash_set(READFLASH_HDC, esdi->drive_sel); + esdi_next_sector(esdi); + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) + esdi->callback = 6*IDE_TIME; + else + { + esdi->pos = 0; + esdi->status = STAT_READY | STAT_DSC; +// pclog("Read verify callback %i %i %i offset %08X %i left\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount); + esdi_irq_raise(esdi); + } + } + break; + + case CMD_FORMAT: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + if (esdi_get_sector(esdi, &addr)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + if (hdd_format_sectors(&drive->hdd_file, addr, esdi->secount)) + { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + esdi_irq_raise(esdi); + break; + } + esdi->status = STAT_READY | STAT_DSC; + esdi_irq_raise(esdi); + readflash_set(READFLASH_HDC, esdi->drive_sel); + } + break; + + case CMD_DIAGNOSE: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + esdi->error = 1; /*No error detected*/ + esdi->status = STAT_READY | STAT_DSC; + esdi_irq_raise(esdi); + } + break; + + case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + drive->cfg_spt = esdi->secount; + drive->cfg_hpc = esdi->head+1; + pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); + if (!esdi->secount) + fatal("secount=0\n"); + esdi->status = STAT_READY | STAT_DSC; + esdi_irq_raise(esdi); + } + break; + + case CMD_NOP: + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + break; + + case 0xe0: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + switch (esdi->cylinder >> 8) + { + case 0x31: + esdi->cylinder = drive->hdd_file.tracks; + break; + case 0x33: + esdi->cylinder = drive->hdd_file.hpc; + break; + case 0x35: + esdi->cylinder = 0x200; + break; + case 0x36: + esdi->cylinder = drive->hdd_file.spt; + break; + default: + pclog("EDSI Bad read config %02x\n", esdi->cylinder >> 8); + } + esdi->status = STAT_READY | STAT_DSC; + esdi_irq_raise(esdi); + } + break; + + case 0xa0: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + memset(esdi->buffer, 0, 512); + memset(&esdi->buffer[3], 0xff, 512-6); + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; +// pclog("Read sector callback %i %i %i offset %08X %i left %i %02X\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt,ide.atastat[ide.board]); +// if (addr) output=3; + esdi_irq_raise(esdi); + } + break; + + case CMD_READ_PARAMETERS: + if (!drive->hdd_file.f) + { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + } + else + { + memset(esdi->buffer, 0, 512); + + esdi->buffer[0] = 0x44; /* general configuration */ + esdi->buffer[1] = drive->hdd_file.tracks; /* number of non-removable cylinders */ + esdi->buffer[2] = 0; /* number of removable cylinders */ + esdi->buffer[3] = drive->hdd_file.hpc; /* number of heads */ + esdi->buffer[5] = esdi->buffer[4] * drive->hdd_file.spt; /* number of unformatted bytes/sector */ + esdi->buffer[4] = 600; /* number of unformatted bytes/track */ + esdi->buffer[6] = drive->hdd_file.spt; /* number of sectors */ + esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/ + esdi->buffer[8] = 0; /* minimum bytes in postamble */ + esdi->buffer[9] = 0; /* number of words of vendor status */ + /* controller info */ +// char wdp_cnsn[20]; /* controller serial number */ + esdi->buffer[20] = 2; /* controller type */ + esdi->buffer[21] = 1; /* sector buffer size, in sectors */ + esdi->buffer[22] = 0; /* ecc bytes appended */ +// char wdp_rev[8]; /* firmware revision */ + //27 + esdi->buffer[27] = 'W' | ('D' << 8); + esdi->buffer[28] = '1' | ('0' << 8); + esdi->buffer[29] = '0' | ('7' << 8); + esdi->buffer[30] = 'V' | ('-' << 8); + esdi->buffer[31] = 'S' | ('E' << 8); + esdi->buffer[32] = '1'; + esdi->buffer[47] = 0; /* sectors per interrupt */ + esdi->buffer[48] = 0;/* can use double word read/write? */ + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + esdi_irq_raise(esdi); + } + break; + + default: + pclog("ESDI Callback on unknown command %02x\n", esdi->command); + case 0xe8: + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + esdi_irq_raise(esdi); + break; + } +} + +static void esdi_rom_write(uint32_t addr, uint8_t val, void *p) +{ + rom_t *rom = (rom_t *)p; + + addr &= rom->mask; + + if (addr >= 0x1f00 && addr < 0x2000) + rom->rom[addr] = val; +} + +void *wd1007vse1_init() +{ + esdi_t *esdi = malloc(sizeof(esdi_t)); + memset(esdi, 0, sizeof(esdi_t)); + + hdd_load(&esdi->drives[0].hdd_file, 0, ide_fn[0]); + hdd_load(&esdi->drives[1].hdd_file, 1, ide_fn[1]); + + esdi->drives[0].cfg_spt = esdi->drives[0].hdd_file.spt; + esdi->drives[0].cfg_hpc = esdi->drives[0].hdd_file.hpc; + esdi->drives[1].cfg_spt = esdi->drives[1].hdd_file.spt; + esdi->drives[1].cfg_hpc = esdi->drives[1].hdd_file.hpc; + + esdi->status = STAT_READY | STAT_DSC; + esdi->error = 1; /*No errors*/ + + rom_init(&esdi->bios_rom, "roms/62-000279-061.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_set_handler(&esdi->bios_rom.mapping, + rom_read, rom_readw, rom_readl, + esdi_rom_write, NULL, NULL); + + io_sethandler(0x01f0, 0x0001, esdi_read, esdi_readw, NULL, esdi_write, esdi_writew, NULL, esdi); + io_sethandler(0x01f1, 0x0007, esdi_read, NULL, NULL, esdi_write, NULL, NULL, esdi); + io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, esdi_write, NULL, NULL, esdi); + + timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi); + + return esdi; +} + +void wd1007vse1_close(void *p) +{ + esdi_t *esdi = (esdi_t *)p; + + hdd_close(&esdi->drives[0].hdd_file); + hdd_close(&esdi->drives[1].hdd_file); + + free(esdi); +} + +static int wd1007vse1_available() +{ + return rom_present("roms/62-000279-061.bin"); +} + +device_t wd1007vse1_device = +{ + "Western Digital WD1007V-SE1 (ESDI)", + DEVICE_AT, + wd1007vse1_init, + wd1007vse1_close, + wd1007vse1_available, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/esdi_at.h b/src/esdi_at.h new file mode 100644 index 0000000..75efd32 --- /dev/null +++ b/src/esdi_at.h @@ -0,0 +1 @@ +extern device_t wd1007vse1_device; diff --git a/src/hdd.c b/src/hdd.c index 41e5a1d..aaaaa20 100644 --- a/src/hdd.c +++ b/src/hdd.c @@ -2,6 +2,7 @@ #include "device.h" #include "hdd.h" +#include "esdi_at.h" #include "hdd_esdi.h" #include "mfm_at.h" #include "mfm_xebec.h" @@ -21,13 +22,14 @@ static struct int is_mfm; } hdd_controllers[] = { - {"None", "none", &null_hdd_device, 0}, - {"AT Fixed Disk Adapter", "mfm_at", &mfm_at_device, 1}, - {"DTC 5150X", "dtc5150x", &dtc_5150x_device, 1}, - {"Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1}, - {"IBM ESDI Fixed Disk Adapter (MCA)", "esdi_mca", &hdd_esdi_device, 1}, - {"XTIDE", "xtide", &xtide_device, 0}, - {"XTIDE (AT)", "xtide_at", &xtide_at_device, 0}, + {"None", "none", &null_hdd_device, 0}, + {"AT Fixed Disk Adapter", "mfm_at", &mfm_at_device, 1}, + {"DTC 5150X", "dtc5150x", &dtc_5150x_device, 1}, + {"Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1}, + {"IBM ESDI Fixed Disk Adapter (MCA)", "esdi_mca", &hdd_esdi_device, 1}, + {"Western Digital WD1007V-SE1 (ESDI)","wd1007vse1", &wd1007vse1_device, 0}, + {"XTIDE", "xtide", &xtide_device, 0}, + {"XTIDE (AT)", "xtide_at", &xtide_at_device, 0}, {"", "", NULL, 0} }; diff --git a/src/hdd_file.c b/src/hdd_file.c index 01e5007..fdfd77e 100644 --- a/src/hdd_file.c +++ b/src/hdd_file.c @@ -52,34 +52,55 @@ void hdd_close(hdd_file_t *hdd) } } -void hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer) +int hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer) { off64_t addr; - + int transfer_sectors = nr_sectors; + + if ((hdd->sectors - offset) < transfer_sectors) + transfer_sectors = hdd->sectors - offset; addr = offset * 512; fseeko64(hdd->f, addr, SEEK_SET); - fread(buffer, nr_sectors*512, 1, hdd->f); + fread(buffer, transfer_sectors*512, 1, hdd->f); + + if (nr_sectors != transfer_sectors) + return 1; + return 0; } -void hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer) +int hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer) { off64_t addr; - + int transfer_sectors = nr_sectors; + + if ((hdd->sectors - offset) < transfer_sectors) + transfer_sectors = hdd->sectors - offset; addr = offset * 512; fseeko64(hdd->f, addr, SEEK_SET); - fwrite(buffer, nr_sectors*512, 1, hdd->f); + fwrite(buffer, transfer_sectors*512, 1, hdd->f); + + if (nr_sectors != transfer_sectors) + return 1; + return 0; } -void hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors) +int hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors) { off64_t addr; int c; uint8_t zero_buffer[512]; - + int transfer_sectors = nr_sectors; + memset(zero_buffer, 0, 512); + if ((hdd->sectors - offset) < transfer_sectors) + transfer_sectors = hdd->sectors - offset; addr = offset * 512; fseeko64(hdd->f, addr, SEEK_SET); - for (c = 0; c < nr_sectors; c++) + for (c = 0; c < transfer_sectors; c++) fwrite(zero_buffer, 512, 1, hdd->f); + + if (nr_sectors != transfer_sectors) + return 1; + return 0; } diff --git a/src/hdd_file.h b/src/hdd_file.h index 83ef438..cd2997c 100644 --- a/src/hdd_file.h +++ b/src/hdd_file.h @@ -9,6 +9,6 @@ typedef struct hdd_file_t void hdd_load(hdd_file_t *hdd, int d, const char *fn); void hdd_close(hdd_file_t *hdd); -void hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer); -void hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer); -void hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors); +int hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer); +int hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer); +int hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors); diff --git a/src/rom.c b/src/rom.c index abbca06..b83b098 100644 --- a/src/rom.c +++ b/src/rom.c @@ -31,7 +31,7 @@ int rom_present(char *fn) return 0; } -static uint8_t rom_read(uint32_t addr, void *p) +uint8_t rom_read(uint32_t addr, void *p) { rom_t *rom = (rom_t *)p; // pclog("rom_read : %08x %08x %02x\n", addr, rom->mask, rom->rom[addr & rom->mask]); diff --git a/src/rom.h b/src/rom.h index 06ace63..0e32d57 100644 --- a/src/rom.h +++ b/src/rom.h @@ -10,3 +10,7 @@ typedef struct rom_t int rom_init(rom_t *rom, char *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags); int rom_init_interleaved(rom_t *rom, char *fn_low, char *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags); + +uint8_t rom_read(uint32_t addr, void *p); +uint16_t rom_readw(uint32_t addr, void *p); +uint32_t rom_readl(uint32_t addr, void *p);