This commit is contained in:
OBattler
2017-10-15 02:51:17 +02:00
381 changed files with 29855 additions and 23909 deletions

View File

@@ -8,13 +8,16 @@
*
* Main emulator include file.
*
* Version: @(#)86box.h 1.0.2 2017/06/04
* Version: @(#)86box.h 1.0.3 2017/10/09
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#ifndef BOX_H
# define BOX_H
#ifndef EMU_86BOX_H
# define EMU_86BOX_H
#if defined(ENABLE_BUSLOGIC_LOG) || \
@@ -38,5 +41,8 @@
#define CONFIG_FILE_W L"86box.cfg"
#define NVR_PATH L"nvr"
#define SCREENSHOT_PATH L"screenshots"
#endif /*BOX_H*/
#endif /*EMU_86BOX_H*/

View File

@@ -10,7 +10,7 @@
# settings, so we can avoid changing the main one for all of
# our local setups.
#
# Version: @(#)Makefile.local 1.0.2 2017/05/23
# Version: @(#)Makefile.local 1.0.4 2017/10/14
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
@@ -20,23 +20,23 @@
#########################################################################
DEBUG = y
OPTIM = n
COPTIM = -O1
DEBUG := y
OPTIM := n
COPTIM := -O1
# Name of the executable.
PROG = yourexe
PROG := yourexe
# Various compile-time options.
STUFF = #-DROM_TRACE=0xC800 -DIO_TRACE=0x70
EXTRAS = #-DYOURNAME
STUFF := #-DROM_TRACE=0xC800 -DIO_TRACE=0x70
EXTRAS := #-DYOURNAME
#########################################################################
# Include the master Makefile.MinGW for the rest. #
#########################################################################
include Makefile.mingw
include win/Makefile.mingw
# End of Makefile.local.

View File

@@ -1,987 +0,0 @@
#
# 86Box A hypervisor and IBM PC system emulator that specializes in
# running old operating systems and software designed for IBM
# PC systems and compatibles from 1981 through fairly recent
# system designs based on the PCI bus.
#
# This file is part of the 86Box distribution.
#
# Modified Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.45 2017/09/12
#
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
#
# Name of the executable.
ifndef PROG
PROG = 86Box
endif
# Various compile-time options.
# -DROM_TRACE=0xc800 traces ROM access from segment C800
# -DIO_TRACE=0x66 traces I/O on port 0x66
STUFF =
# Add feature selections here.
# -DANSI_CFG forces the config file to ANSI encoding.
# -DENABLE_VRAM_DUMP enables Video Ram dumping.
# -DENABLE_LOG_BREAKPOINT enables extra logging.
# -DENABLE_SCSI_BIOS_COMMAND_LOG=n enables extra logging.
# -DENABLE_AHA154X_LOG=n enables extra logging.
# -DENABLE_BUSLOGIC_LOG=n enables extra logging.
# -DENABLE_CDROM_LOG enables extra logging.
# -DENABLE_D86F_LOG enables extra logging.
# -DENABLE_FDC_LOG enables extra logging.
# -DENABLE_IDE_LOG enables extra logging.
# -DENABLE_SERIAL_LOG enables extra logging.
# -DENABLE_NIC_LOG enables extra logging.
ifndef EXTRAS
EXTRAS =
endif
# Defaults for several build options (possibly defined in a chained file.)
ifndef DEBUG
DEBUG = n
endif
ifndef OPTIM
OPTIM = n
endif
ifndef RELEASE
RELEASE = n
endif
ifndef USB
USB = n
endif
ifndef DEV_BRANCH
DEV_BRANCH = n
endif
ifndef CIRRUS
CIRRUS = n
endif
ifndef NV_RIVA
NV_RIVA = n
endif
ifndef FLUIDSYNTH
FLUIDSYNTH = y
endif
ifndef MUNT
MUNT = y
endif
ifndef PAS16
PAS16 = n
endif
ifndef NETWORK
NETWORK = y
endif
ifndef X64
X64 = n
endif
#########################################################################
# Nothing should need changing from here on.. #
#########################################################################
VPATH = $(EXPATH) . cpu \
cdrom floppy hdd machine \
sound \
sound/munt sound/munt/c_interface sound/munt/sha1 \
sound/munt/srchelper \
sound/resid-fp \
scsi video lzf network network/slirp win
PLAT = win/
ifeq ($(X64), y)
CPP = g++.exe -m64
CC = gcc.exe -m64
else
CPP = g++.exe -m32
CC = gcc.exe -m32
endif
WINDRES = windres.exe
OPTS = -DWIN32 -I$(PLAT) $(EXTRAS) $(STUFF)
ifdef EXFLAGS
OPTS += $(EXFLAGS)
endif
ifdef EXINC
OPTS += -I$(EXINC)
endif
ifeq ($(X64), y)
ifeq ($(OPTIM), y)
DFLAGS = -march=native
else
DFLAGS =
endif
else
ifeq ($(OPTIM), y)
DFLAGS = -march=native
else
DFLAGS = -march=i686
endif
endif
ifeq ($(DEBUG), y)
DFLAGS += -ggdb -DDEBUG
AOPTIM =
ifndef COPTIM
COPTIM = -Og
endif
else
ifeq ($(OPTIM), y)
AOPTIM = -mtune=native
ifndef COPTIM
COPTIM = -O6
endif
else
ifndef COPTIM
COPTIM = -O3
endif
endif
endif
AFLAGS = -msse -msse2 -mfpmath=sse
CFLAGS = $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) $(AFLAGS) \
-fomit-frame-pointer -mstackrealign -Wall
RFLAGS = --input-format=rc -O coff
ifeq ($(RELEASE), y)
CFLAGS += -DRELEASE_BUILD
RFLAGS += -DRELEASE_BUILD
endif
ifeq ($(VRAMDUMP), y)
CFLAGS += -DENABLE_VRAM_DUMP
RFLAGS += -DENABLE_VRAM_DUMP
endif
ifeq ($(FLUIDSYNTH), y)
CFLAGS += -DUSE_FLUIDSYNTH
FSYNTHOBJ = midi_fluidsynth.o
endif
ifeq ($(MUNT), y)
CFLAGS += -DUSE_MUNT
endif
ifeq ($(NETWORK), y)
CFLAGS += -DUSE_NETWORK
RFLAGS += -DUSE_NETWORK
endif
ifeq ($(X64), y)
PLATCG = codegen_x86-64.o
CGOPS = codegen_ops_x86-64.h
VCG = vid_voodoo_codegen_x86-64.h
else
PLATCG = codegen_x86.o
CGOPS = codegen_ops_x86.h
VCG = vid_voodoo_codegen_x86.h
endif
# Options for the DEV branch.
ifeq ($(DEV_BRANCH), y)
CFLAGS += -DDEV_BRANCH
ifeq ($(CIRRUS), y)
CFLAGS += -DUSE_CIRRUS
endif
ifeq ($(NV_RIVA), y)
CFLAGS += -DUSE_RIVA
endif
ifeq ($(PAS16), y)
CFLAGS += -DUSE_PAS16
endif
endif
# Options for works-in-progress.
ifndef SERIAL
SERIAL = serial.o
endif
ifndef EUROPC
EUROPC = machine_europc.o
endif
MAINOBJ = pc.o config.o random.o timer.o io.o dma.o nmi.o pic.o pit.o \
ppi.o pci.o mca.o mcr.o mem.o memregs.o rom.o \
device.o rtc.o nvr.o nvr_ps2.o \
intel.o intel_flash.o intel_sio.o
CPUOBJ = cpu.o 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o \
codegen.o \
codegen_ops.o \
codegen_timing_common.o codegen_timing_486.o \
codegen_timing_686.o codegen_timing_pentium.o \
codegen_timing_winchip.o $(PLATCG) \
x86seg.o x87.o
MACHINEOBJ = machine.o \
machine_common.o \
machine_amstrad.o $(EUROPC) \
machine_olivetti_m24.o \
machine_pcjr.o \
machine_tandy.o \
machine_xt.o machine_xt_laserxt.o \
machine_at.o \
machine_at_ali1429.o machine_at_commodore.o \
machine_at_neat.o machine_at_headland.o \
machine_at_opti495.o machine_at_scat.o \
machine_at_wd76c10.o \
machine_at_sis_85c471.o machine_at_sis_85c496.o \
machine_at_430lx_nx.o machine_at_430fx.o \
machine_at_430hx.o machine_at_430vx.o \
machine_at_440fx.o \
machine_ps1.o \
machine_ps2_isa.o machine_ps2_mca.o
DEVOBJ = bugger.o lpt.o $(SERIAL) \
tandy_eeprom.o tandy_rom.o \
sio_detect.o \
sio_fdc37c665.o sio_fdc37c669.o sio_fdc37c932fr.o \
sio_pc87306.o sio_w83877f.o sio_um8669f.o \
keyboard.o \
keyboard_xt.o keyboard_at.o keyboard_pcjr.o \
keyboard_amstrad.o keyboard_olim24.o \
gameport.o \
joystick_standard.o joystick_ch_flightstick_pro.o \
joystick_sw_pad.o joystick_tm_fcs.o \
mouse.o mouse_serial.o mouse_ps2.o mouse_bus.o
FDDOBJ = fdd.o fdc.o fdi2raw.o \
floppy.o floppy_common.o floppy_86f.o \
floppy_fdi.o floppy_imd.o floppy_img.o floppy_json.o floppy_td0.o
CDROMOBJ= cdrom.o \
cdrom_dosbox.o cdrom_image.o cdrom_ioctl.o cdrom_null.o
HDDOBJ = hdd.o hdd_image.o \
hdd_mfm_at.o hdd_mfm_xebec.o hdd_esdi_at.o hdd_esdi_mca.o \
hdd_ide_at.o hdd_ide_xt.o piix.o
ifeq ($(USB), y)
USBOBJ = usb.o
endif
ifeq ($(MUNT), y)
MUNTOBJ = midi_mt32.o \
Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \
LA32FloatWaveGenerator.o LA32WaveGenerator.o \
MidiStreamParser.o Part.o Partial.o PartialManager.o \
Poly.o ROMInfo.o SampleRateConverter_dummy.o Synth.o \
Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o
endif
ifeq ($(NETWORK), y)
NETOBJ = network.o \
net_pcap.o \
net_slirp.o \
bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o \
ip_input.o queue.o tcp_input.o debug.o ip_output.o \
sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o \
net_ne2000.o
endif
SCSIOBJ = scsi.o scsi_bios_command.o scsi_device.o scsi_disk.o \
scsi_buslogic.o scsi_aha154x.o
ifeq ($(DEV_BRANCH), y)
ifeq ($(PAS16), y)
PAS16OBJ = snd_pas16.o
endif
endif
SNDOBJ = sound.o \
openal.o \
dbopl.o nukedopl.o \
convolve.o convolve-sse.o envelope.o extfilt.o \
filter.o pot.o sid.o voice.o wave6581__ST.o \
wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \
wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \
wave8580_PST.o wave.o \
midi.o $(FSYNTHOBJ) $(MUNTOBJ) \
midi_system.o \
snd_speaker.o \
snd_ps1.o snd_pssj.o \
snd_lpt_dac.o snd_lpt_dss.o \
snd_adlib.o snd_adlibgold.o snd_ad1848.o \
snd_sb.o snd_sb_dsp.o snd_cms.o snd_dbopl.o \
snd_emu8k.o snd_gus.o snd_opl.o \
snd_mpu401.o $(PAS16OBJ) snd_resid.o \
snd_sn76489.o snd_ssi2001.o snd_wss.o \
snd_ym7128.o
VIDOBJ = video.o \
vid_cga.o vid_cga_comp.o vid_mda.o \
vid_ega.o vid_ega_render.o \
vid_vga.o vid_svga.o vid_svga_render.o \
vid_hercules.o vid_herculesplus.o vid_incolor.o \
vid_colorplus.o \
vid_genius.o \
vid_s3.o vid_s3_virge.o \
vid_et4000.o vid_et4000w32.o vid_icd2061.o \
vid_oti067.o \
vid_paradise.o \
vid_tvga.o vid_tgui9440.o vid_tkd8001_ramdac.o \
vid_ati_eeprom.o vid_ati18800.o vid_ati28800.o \
vid_ati68860_ramdac.o vid_ati_mach64.o \
vid_ics2595.o \
vid_sc1502x_ramdac.o \
vid_sdac_ramdac.o \
vid_stg_ramdac.o \
vid_wy700.o \
vid_voodoo.o \
vid_pcjr.o vid_ps1_svga.o \
vid_olivetti_m24.o \
vid_pc1512.o vid_pc1640.o vid_pc200.o \
vid_tandy.o vid_tandysl.o
WINOBJ = win.o \
win_ddraw.o win_ddraw_fs.o win_ddraw_screenshot.o \
win_d3d.o win_d3d_fs.o \
win_language.o win_status.o $(OPENDIR) win_dynld.o \
win_video.o $(WSERIAL) win_keyboard.o win_mouse.o \
win_iodev.o win_joystick.o win_midi.o \
win_settings.o win_deviceconfig.o win_joystickconfig.o \
86Box.res
ifeq ($(DEV_BRANCH), y)
ifeq ($(CIRRUS), y)
CIRRUSOBJ = vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o
endif
ifeq ($(NV_RIVA), y)
RIVAOBJ = vid_nv_riva128.o
endif
DEVBRANCHOBJ = $(CIRRUSOBJ) $(RIVAOBJ)
endif
OBJ = $(MAINOBJ) $(CPUOBJ) $(MACHINEOBJ) $(DEVOBJ) \
$(FDDOBJ) $(CDROMOBJ) $(HDDOBJ) \
$(USBOBJ) $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \
$(WINOBJ) $(DEVBRANCHOBJ)
ifdef EXOBJ
OBJ += $(EXOBJ)
endif
LZFOBJ = lzf_c.o lzf_d.o
LIBS = -mwindows \
-lopenal.dll \
-lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \
-lcomctl32 -lwinmm
ifeq ($(NETWORK), y)
LIBS += -lkernel32 -lwsock32 -liphlpapi -lpsapi
endif
LIBS += -static -lstdc++ -lgcc
LIBS += -Wl,--large-address-aware
# Build rules.
%.o: %.c
@echo $<
@$(CC) $(CFLAGS) $(WFLAGS) -c $<
%.o: %.cc
@echo $<
@$(CPP) $(CFLAGS) $(WFLAGS) -c $<
%.o: %.cpp
@echo $<
@$(CPP) $(CFLAGS) $(WFLAGS) -c $<
all: $(PROG).exe pcap_if.exe
$(PROG).exe: $(OBJ) $(LZFOBJ)
@echo Linking $(PROG).exe ..
@$(CC) -o $(PROG).exe $(OBJ) $(LZFOBJ) $(LIBS)
ifneq ($(DEBUG), y)
@strip $(PROG).exe
endif
pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res
@echo Linking pcap_if.exe ..
@$(CC) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res
ifneq ($(DEBUG), y)
@strip pcap_if.exe
endif
clean:
-rm *.o
-rm *.exe
-rm *.res
86Box.res: 86Box.rc
@echo Processing $<
@$(WINDRES) $(RFLAGS) $(EXTRAS) -i win/86Box.rc -o 86Box.res
pcap_if.res: pcap_if.rc
@echo Processing $<
@$(WINDRES) $(RFLAGS) -i win/pcap_if.rc -o pcap_if.res
# Module dependencies.
386.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87.h mem.h floppy.h fdc.h pic.h timer.h cpu/386_common.h
386_dynarec.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_ops.h cpu/x87.h mem.h cpu/codegen.h floppy.h fdc.h pic.h timer.h cpu/386_common.h \
cpu/x86_ops.h cpu/x86seg.h cpu/x86_ops_arith.h cpu/x86_ops_atomic.h cpu/x86_ops_bcd.h cpu/x86_ops_bit.h \
cpu/x86_ops_bitscan.h cpu/x86_ops_call.h cpu/x86_ops_flag.h cpu/x86_ops_fpu.h cpu/x86_ops_inc_dec.h cpu/x86_ops_int.h \
cpu/x86_ops_io.h cpu/x86_ops_jump.h cpu/x86_ops_misc.h \
cpu/x87_ops_arith.h cpu/x87_ops_misc.h cpu/x87_ops_loadstore.h \
cpu/x87_ops.h cpu/x86_ops_i686.h cpu/x86_ops_mmx.h \
cpu/x86_ops_mmx_arith.h cpu/x86_ops_mmx_cmp.h cpu/x86_ops_mmx_logic.h cpu/x86_ops_mmx_pack.h cpu/x86_ops_mmx_shift.h \
cpu/x86_ops_mov.h cpu/x86_ops_mov_ctrl.h cpu/x86_ops_mov_seg.h cpu/x86_ops_movx.h cpu/x86_ops_msr.h cpu/x86_ops_mul.h \
cpu/x86_ops_pmode.h cpu/x86_ops_prefix.h cpu/x86_ops_rep.h cpu/x86_ops_ret.h cpu/x86_ops_set.h cpu/x86_ops_shift.h \
cpu/x86_ops_stack.h cpu/x86_ops_string.h cpu/x86_ops_xchg.h \
cpu/386_ops.h
386_dynarec_ops.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_ops.h cpu/x87.h cpu/x86_flags.h mem.h cpu/codegen.h pic.h cpu/386_common.h \
cpu/x86_ops.h cpu/x86seg.h cpu/x86_ops_arith.h cpu/x86_ops_atomic.h cpu/x86_ops_bcd.h cpu/x86_ops_bit.h \
cpu/x86_ops_bitscan.h cpu/x86_ops_call.h cpu/x86_ops_flag.h cpu/x86_ops_fpu.h cpu/x86_ops_inc_dec.h cpu/x86_ops_int.h \
cpu/x86_ops_io.h cpu/x86_ops_jump.h cpu/x86_ops_misc.h \
cpu/x87_ops_arith.h cpu/x87_ops_misc.h cpu/x87_ops_loadstore.h \
cpu/x87_ops.h cpu/x86_ops_i686.h cpu/x86_ops_mmx.h \
cpu/x86_ops_mmx_arith.h cpu/x86_ops_mmx_cmp.h cpu/x86_ops_mmx_logic.h cpu/x86_ops_mmx_pack.h cpu/x86_ops_mmx_shift.h \
cpu/x86_ops_mov.h cpu/x86_ops_mov_ctrl.h cpu/x86_ops_mov_seg.h cpu/x86_ops_movx.h cpu/x86_ops_msr.h cpu/x86_ops_mul.h \
cpu/x86_ops_pmode.h cpu/x86_ops_prefix.h cpu/x86_ops_rep.h cpu/x86_ops_ret.h cpu/x86_ops_set.h cpu/x86_ops_shift.h \
cpu/x86_ops_stack.h cpu/x86_ops_string.h cpu/x86_ops_xchg.h \
cpu/386_ops.h
808x.o: ibm.h cpu/cpu.h cpu/x86.h keyboard.h mem.h nmi.h pic.h scsi/scsi.h timer.h
codegen.o: ibm.h cpu/x86_ops.h mem.h cpu/codegen.h
codegen_ops.o: ibm.h mem.h cpu/x86.h cpu/x86_ops.h cpu/x86_flags.h cpu/x87.h cpu/386_common.h cpu/cpu.h cpu/codegen.h cpu/codegen_ops.h \
cpu/$(CGOPS) cpu/codegen_ops_arith.h cpu/codegen_ops_fpu.h cpu/codegen_ops_jump.h cpu/codegen_ops_logic.h cpu/codegen_ops_misc.h \
cpu/codegen_ops_mmx.h cpu/codegen_ops_mov.h cpu/codegen_ops_shift.h cpu/codegen_ops_stack.h cpu/codegen_ops_xchg.h
codegen_timing_486.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h
codegen_timing_686.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_timing_common.h
codegen_timing_common.o: ibm.h cpu/codegen_timing_common.h
codegen_timing_pentium.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h
codegen_timing_winchip.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h
codegen_x86.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h mem.h cpu/386_common.h cpu/codegen.h cpu/codegen_ops.h \
cpu/codegen_ops_x86.h
codegen_x86-64.o: ibm.h mem.h cpu/cpu.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h cpu/386_common.h cpu/codegen.h cpu/codegen_ops.h \
cpu/codegen_ops_x86-64.h
cpu.o: ibm.h cpu/cpu.h device.h machine/machine.h io.h cpu/x86_ops.h mem.h pci.h cpu/codegen.h
x86seg.o: ibm.h mem.h nvr.h cpu/x86.h cpu/386.h cpu/386_common.h cpu/cpu.h
x87.o: ibm.h pic.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h cpu/386_common.h
bugger.o: ibm.h io.h bugger.h
cdrom.o: 86box.h cdrom.h ibm.h hdd/hdd_ide_at.h piix.h scsi/scsi.h timer.h \
win/plat_iodev.h
cdrom_dosbox.o: cdrom_dosbox.h
cdrom_image.o: config.h cdrom_dosbox.h cdrom.h cdrom_image.h cdrom_null.h
cdrom_ioctl.o: ibm.h cdrom.h cdrom_ioctl.h scsi/scsi.h
cdrom_null.o: ibm.h cdrom.h cdrom_ioctl.h
config.o: cdrom.h config.h device.h floppy/floppy.h floppy/fdc.h floppy/fdd.h ibm.h \
cpu/cpu.h gameport.h hdd/hdd_ide_at.h hdd/hdd.h machine/machine.h \
mouse.h network/network.h nvr.h scsi/scsi.h win/plat_joystick.h \
win/plat_midi.h sound/snd_dbopl.h sound/snd_mpu401.h \
sound/snd_opl.h sound/sound.h video/video.h win/win.h \
win/resource.h win/win_language.h
device.o: ibm.h cpu/cpu.h config.h device.h machine/machine.h sound/sound.h
dma.o: ibm.h cpu/x86.h mem.h io.h dma.h
floppy.o: ibm.h config.h floppy.h floppy_fdi.h fdc.h fdd.h timer.h \
floppy_img.h floppy_86f.h floppy_td0.h floppy_imd.h
floppy_common.o: ibm.h floppy.h floppy_common.h fdc.h fdd.h
floppy_86f.o: lzf/lzf.h config.h dma.h random.h floppy.h floppy_86f.h \
fdc.h fdd.h ibm.h
floppy_fdi.o: ibm.h floppy.h floppy_img.h floppy_fdi.h fdc.h fdd.h fdi2raw.h \
floppy.h floppy_imd.h fdc.h fdd.h config.h floppy_img.h
floppy_td0.o: ibm.h floppy.h floppy_td0.h fdc.h fdd.h
floppy_json.o: ibm.h floppy.h floppy_common.h floppy_json.h fdc.h fdd.h
fdc.o: ibm.h io.h dma.h pic.h timer.h floppy.h fdc.h fdd.h
fdd.o: ibm.h floppy.h fdc.h fdd.h
fdi2raw.o: fdi2raw.h ibm.h
gameport.o: ibm.h cpu/cpu.h device.h io.h timer.h gameport.h \
joystick_ch_flightstick_pro.h joystick_standard.h \
joystick_sw_pad.h joystick_tm_fcs.h plat_joystick.h
hdd.o: ibm.h cpu/cpu.h device.h hdd/hdd.h machine/machine.h \
hdd/hdd_esdi_at.h hdd/hdd_esdi_mca.h hdd/hdd_mfm_at.h \
hdd/hdd_mfm_xebec.h hdd/hdd_ide_xt.h
hdd_image.o: ibm.h hdd/hdd_ide_at.h hdd/hdd_image.h
hdd_esdi_at.o: ibm.h device.h hdd_image.h io.h mem.h pic.h rom.h timer.h \
hdd/hdd_esdi_at.h
hdd_esdi_mca.o: ibm.h device.h dma.h hdd/hdd_image.h io.h mca.h mem.h \
pic.h rom.h timer.h hdd/hdd_esdi_mca.h
hdd_ide_at.o: 86box.h cdrom.h hdd/hdd_image.h ibm.h io.h pic.h timer.h \
cdrom.h scsi/scsi.h hdd/hdd_ide_at.h
hdd_ide_xt.o: ibm.h io.h mem.h rom.h device.h hdd/hdd_ide_at.h hdd/hdd_ide_xt.h
hdd_mfm_at.o: ibm.h device.h hdd/hdd_image.h io.h pic.h timer.h hdd/hdd_mfm_at.h
hdd_mfm_xebec.o: ibm.h device.h dma.h hdd/hdd_image.h io.h mem.h pic.h rom.h \
timer.h hdd/hdd_mfm_xebec.h
intel.o: ibm.h cpu/cpu.h io.h mem.h pit.h timer.h intel.h
intel_flash.o: ibm.h cpu/cpu.h device.h mem.h machine/machine.h rom.h
intel_sio.o: ibm.h dma.h mem.h pci.h intel_sio.h
io.o: ibm.h io.h
joystick_ch_flightstick_pro.o: ibm.h device.h timer.h gameport.h \
joystick_standard.h plat_joystick.h
joystick_standard.o: ibm.h device.h timer.h gameport.h \
joystick_standard.h plat_joystick.h
joystick_sw_pad.o: ibm.h device.h timer.h gameport.h \
joystick_sw_pad.h plat_joystick.h
joystick_tm_fcs.o: ibm.h device.h timer.h gameport.h \
joystick_standard.h plat_joystick.h
keyboard.o: ibm.h plat_keyboard.h keyboard.h
keyboard_amstrad.o: ibm.h io.h mem.h pic.h pit.h timer.h sound/sound.h \
sound/snd_speaker.h keyboard.h keyboard_amstrad.h
keyboard_at.o: ibm.h io.h mem.h pic.h pit.h timer.h floppy.h fdc.h \
sound/sound.h sound/snd_speaker.h keyboard.h keyboard_at.h
keyboard_olim24.o: ibm.h io.h mem.h pic.h pit.h timer.h mouse.h \
sound/sound.h sound/snd_speaker.h keyboard.h keyboard_olim24.h
keyboard_pcjr.o: ibm.h io.h mem.h nmi.h pic.h pit.h timer.h \
device.h sound/sound.h sound/snd_speaker.h \
sound/snd_sn76489.h keyboard.h keyboard_pcjr.h
keyboard_xt.o: ibm.h io.h mem.h pic.h pit.h timer.h device.h tandy_eeprom.h \
sound/sound.h sound/snd_speaker.h keyboard.h keyboard_xt.h
lpt.o: ibm.h io.h lpt.h sound/snd_lpt_dac.h sound/snd_lpt_dss.h
machine.o: ibm.h cpu/cpu.h device.h floppy.h fdc.h fdd.h io.h \
machine/machine.h machine/machine_common.h machine/machine_amstrad.h \
machine/machine_europc.h machine/machine_olivetti_m24.h machine/machine_pcjr.h machine/machine_tandy.h \
machine/machine_xt.h machine/machine_xt_laserxt.h machine/machine_at.h machine/machine_at_ali1429.h \
machine/machine_at_commodore.h machine/machine_at_headland.h machine/machine_at_neat.h machine/machine_at_opti495.h \
machine/machine_at_scat.h machine/machine_at_wd76c10.h machine/machine_ps1.h machine/machine_ps2_isa.h \
machine/machine_ps2_mca.h machine/machine_at_sis_85c471.h machine/machine_at_sis_85c496.h \
machine/machine_at_430lx_nx.h machine/machine_at_430fx.h machine/machine_at_430hx.h machine/machine_at_430vx.h \
machine/machine_at_440fx.h video/vid_pcjr.h video/vid_tandy.h video/vid_tandysl.h
machine_amstrad.o: ibm.h cpu/cpu.h device.h floppy.h fdd.h fdc.h gameport.h io.h keyboard.h keyboard_amstrad.h lpt.h mem.h mouse.h \
nmi.h nvr.h machine/machine_common.h
machine_at.o: ibm.h bugger.h device.h dma.h gameport.h hdd/hdd_ide_at.h keyboard_at.h lpt.h mem.h nvr.h pic.h pit.h \
machine/machine_common.h machine/machine_at.h
machine_at_430fx.o: ibm.h cpu/cpu.h device.h sio.h intel_flash.h mem.h memregs.h pci.h piix.h \
machine/machine_at.h machine/machine_at_430fx.h
machine_at_430hx.o: ibm.h cpu/cpu.h device.h sio.h io.h intel_flash.h mem.h memregs.h pci.h \
piix.h sio.h machine/machine_at.h machine/machine_at_430hx.h
machine_at_430lx_nx.o: ibm.h cpu/cpu.h device.h sio.h intel.h intel_flash.h mem.h memregs.h pci.h intel_sio.h machine/machine_at.h \
machine/machine_at_430lx_nx.h
machine_at_430vx.o: ibm.h cpu/cpu.h device.h sio.h io.h mem.h memregs.h intel_flash.h pci.h piix.h \
machine/machine_at.h machine/machine_at_430vx.h
machine_at_440fx.o: ibm.h cpu/cpu.h device.h sio.h intel_flash.h io.h mem.h memregs.h pci.h piix.h machine/machine_at.h \
machine/machine_at_440fx.h
machine_at_ali1429.o: ibm.h cpu/cpu.h hdd/hdd_ide_at.h io.h mem.h machine/machine_at.h machine/machine_at_ali1429.h
machine_at_commodore.o: ibm.h io.h lpt.h serial.h machine/machine_at.h machine/machine_at_commodore.h
machine_at_compaq.o: ibm.h cpu/cpu.h mem.h machine/machine_at.h machine/machine_at_compaq.h
machine_at_headland.o: ibm.h cpu/cpu.h io.h mem.h machine/machine_at.h machine/machine_at_headland.h
machine_at_neat.o: ibm.h cpu/cpu.h io.h machine/machine_at.h machine/machine_at_neat.h
machine_at_opti495.o: ibm.h cpu/cpu.h io.h mem.h machine/machine_at.h machine/machine_at_opti495.h
machine_at_scat.o: ibm.h cpu/cpu.h io.h mem.h cpu/x86.h machine/machine_at.h machine/machine_at_scat.h
machine_at_sis_85c50x.o: ibm.h io.h mem.h pci.h machine/machine_at.h machine/machine_at_sis_5c50x.h
machine_at_sis_85c471.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h memregs.h serial.h machine/machine_at.h \
machine/machine_at_sis_85c471.h
machine_at_sis_85c496.o: ibm.h cpu/cpu.h sio.h io.h mem.h memregs.h pci.h machine/machine_at.h machine/machine_at_sis_85c496.h
machine_at_wd76c10.o: ibm.h floppy.h fdc.h io.h mem.h serial.h machine/machine_at.h machine/machine_at_wd76c10.h
machine_common.o: ibm.h dma.h floppy.h fdd.h fdc.h lpt.h pic.h pit.h serial.h machine/machine_common.h
machine_europc.o: ibm.h cpu/cpu.h io.h device.h gameport.h keyboard_xt.h lpt.h mem.h nmi.h rom.h machine/machine_common.h \
machine/machine_europc.h
europc_hdd.o: ibm.h io.h dma.h pic.h device.h timer.h hdd/hdd_image.h europc.h
machine_olivetti_m24.o: ibm.h cpu/cpu.h device.h gameport.h keyboard_olim24.h mem.h nmi.h nvr.h io.h machine/machine_common.h \
machine/machine_olivetti_m24.h
machine_pcjr.o: ibm.h device.h floppy.h fdc.h fdd.h keyboard_pcjr.h mem.h nmi.h pic.h pit.h serial.h sound/snd_sn76489.h \
machine/machine_pcjr.h
machine_ps1.o: ibm.h cpu/cpu.h device.h floppy.h dma.h gameport.h hdd/hdd_ide_at.h fdd.h fdc.h io.h keyboard_at.h lpt.h \
mem.h nvr.h pic.h pit.h rom.h serial.h sound/snd_ps1.h machine/machine_common.h machine/machine_ps1.h
machine_ps2_isa.o: ibm.h cpu/cpu.h device.h floppy.h dma.h fdd.h fdc.h io.h keyboard.h keyboard_at.h lpt.h mem.h nvr.h pic.h \
pit.h rom.h serial.h machine/machine_common.h machine/machine_ps2_isa.h
machine_ps2_mca.o: ibm.h cpu/cpu.h cpu/x86.h device.h dma.h io.h keyboard_at.h lpt.h mca.h mem.h mouse.h nvr.h pic.h \
pit.h rom.h nvr_ps2.h serial.h machine/machine_common.h machine/machine_ps2_mca.h
machine_tandy.o: ibm.h device.h gameport.h keyboard_xt.h mem.h nmi.h tandy_eeprom.h tandy_rom.h sound/snd_pssj.h \
sound/snd_sn76489.h
machine_xt.o: ibm.h bugger.h device.h gameport.h keyboard_xt.h mem.h nmi.h pit.h machine/machine_common.h \
machine/machine_xt.h
machine_xt_laserxt.o: ibm.h cpu/cpu.h io.h mem.h machine/machine_xt.h machine/machine_xt_laserxt.h
mca.o: ibm.h io.h mem.h mca.h
mcr.o: ibm.h
mem.o: ibm.h cpu/cpu.h cpu/x86_ops.h cpu/x86.h config.h \
io.h mem.h rom.h cpu/codegen.h video/video.h
memregs.o: ibm.h io.h memregs.h
mouse.o: ibm.h cpu/cpu.h device.h machine/machine.h mouse.h \
keyboard_olim24.h
mouse_bus.o: ibm.h io.h pic.h timer.h mouse.h
mouse_ps2.o: ibm.h keyboard_at.h mouse.h plat_mouse.h
mouse_serial.o: ibm.h timer.h serial.h mouse.h
nmi.o: ibm.h io.h nmi.h
network.o: ibm.h device.h network/network.h network/net_ne2000.h win/plat_ui.h
net_pcap.o: ibm.h config.h device.h network/network.h win/plat_dynld.h win/plat_thread.h
net_slirp.o: network/slirp/slirp.h network/slirp/queue.h ibm.h config.h device.h network/network.h win/plat_thread.h
net_ne2000.o: ibm.h io.h mem.h rom.h pci.h pic.h device.h config.h random.h network/network.h network/net_ne2000.h network/bswap.h
nvr.o: ibm.h cpu/cpu.h device.h io.h mem.h machine/machine.h \
machine/machine_europc.h nvr.h pic.h rom.h timer.h rtc.h
nvr_ps2.o: ibm.h device.h io.h mem.h rom.h nvr_ps2.h
pc.o: 86box.h config.h random.h ibm.h mem.h \
cpu/cpu.h cpu/x86_ops.h cpu/codegen.h \
dma.h nvr.h pic.h pit.h timer.h device.h machine/machine.h \
floppy.h floppy_86f.h floppy_fdi.h floppy_imd.h floppy_img.h floppy_td0.h \
random.h config.h fdc.h fdd.h gameport.h plat_joystick.h \
plat_midi.h hdd/hdd.h hdd/hdd_ide_at.h cdrom.h cdrom_ioctl.h \
cdrom_image.h cdrom_null.h scsi/scsi.h keyboard.h plat_keyboard.h \
keyboard_at.h mouse.h plat_mouse.h network/network.h serial.h \
sound/sound.h sound/snd_cms.h sound/snd_dbopl.h \
sound/snd_mpu401.h sound/snd_opl.h sound/snd_gus.h \
sound/snd_sb.h sound/snd_speaker.h sound/snd_ssi2001.h \
video/video.h video/vid_voodoo.h win/plat_ui.h
pci.o: ibm.h cdrom.h floppy.h fdc.h hdd/hdd_ide_at.h io.h keyboard_at.h mem.h pic.h pci.h
pic.o: ibm.h io.h pic.h pit.h
piix.o: ibm.h dma.h hdd/hdd_ide_at.h io.h mem.h pci.h piix.h
pit.o: ibm.h cpu/cpu.h dma.h io.h pic.h pit.h device.h timer.h \
machine/machine.h sound/snd_speaker.h video/video.h
ppi.o: ibm.h pit.h plat_keyboard.h plat_mouse.h
random.o: random.h
rom.o: config.h ibm.h mem.h rom.h
rtc.o: nvr.h rtc.h
scsi.o: 86box.h ibm.h timer.h device.h cdrom.h scsi/scsi.h \
scsi/scsi_aha154x.h scsi/scsi_buslogic.h
scsi_bios_command.o: ibm.h dma.h scsi/scsi.h scsi/scsi_bios_command.h scsi/scsi_device.h
scsi_device.o: ibm.h scsi/scsi.h scsi/scsi_disk.h cdrom.h
scsi_aha154x.o: ibm.h io.h mca.h mem.h mca.h rom.h dma.h pic.h timer.h \
device.h scsi/scsi.h scsi/scsi_bios_command.h scsi/scsi_aha154x.h \
scsi_buslogic.o: ibm.h io.h mem.h rom.h dma.h pic.h pci.h timer.h \
device.h scsi/scsi.h scsi/scsi_bios_command.h scsi/scsi_device.h \
scsi/scsi_buslogic.h
scsi_disk.o: 86box.h cdrom.h hdd/hdd_image.h ibm.h hdd/hdd_ide_at.h piix.h scsi/scsi.h \
scsi/scsi_disk.h timer.h win/plat_iodev.h
serial.o: ibm.h io.h pic.h timer.h serial.h plat_serial.h
sio_detect.o: ibm.h io.h floppy.h fdd.h fdc.h sio.h
sio_fdc37c665.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h serial.h \
sio.h floppy.h fdc.h fdd.h io.h hdd/hdd_ide_at.h lpt.h serial.h
sio_fdc37c932fr.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h \
serial.h sio.h
sio_pc87306.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h serial.h \
sio.h
sio_w83877f.o: ibm.h floppy.h fdc.h fdd.h io.h lpt.h serial.h sio.h
dbopl.o: sound/dbopl.h
midi.o: device.h sound/midi.h ibm.h win/plat_midi.h win/plat_ticks.h sound/midi_fluidsynth.h sound/midi_mt32.h sound/midi_system.h
midi_fluidsynth.o: config.h win/plat_dynld.h win/plat_thread.h win/plat_ui.h device.h sound/midi_fluidsynth.h sound/midi.h sound/sound.h
midi_mt32.o: sound/munt/c_interface/c_interface.h win/plat_thread.h ibm.h device.h mem.h rom.h sound/midi_mt32.h sound/midi.h \
sound/sound.h
midi_system.o: device.h win/plat_midi.h sound/midi_system.h sound/midi.h
nukedopl.o: sound/nukedopl.h
openal.o: ibm.h sound/sound.h
snd_ad1848.o: ibm.h dma.h pic.h timer.h sound/sound.h sound/snd_ad1848.h
snd_adlib.o: ibm.h io.h mca.h device.h sound/sound.h sound/snd_adlib.h sound/snd_opl.h
snd_adlibgold.o: ibm.h io.h dma.h pic.h pit.h mem.h rom.h timer.h device.h sound/sound.h sound/filters.h sound/snd_opl.h sound/snd_ym7128.h
snd_cms.o: ibm.h io.h device.h sound/sound.h sound/snd_cms.h
snd_dbopl.o: sound/dbopl.h sound/nukedopl.h sound/snd_dbopl.h
snd_emu8k.o: ibm.h io.h mem.h rom.h timer.h device.h sound/sound.h sound/snd_emu8k.h
snd_gus.o: ibm.h io.h pic.h dma.h timer.h device.h sound/sound.h sound/snd_gus.h
snd_lpt_dac.o: ibm.h cpu/cpu.h sound/filters.h lpt.h sound/snd_lpt_dac.h sound/sound.h timer.h
snd_lpt_dss.o: ibm.h cpu/cpu.h sound/filters.h lpt.h sound/snd_lpt_dss.h sound/sound.h timer.h
snd_mpu401.o: ibm.h device.h io.h pic.h timer.h sound/midi.h sound/sound.h sound/snd_mpu401.h
snd_opl.o: ibm.h io.h timer.h sound/sound.h sound/snd_opl.h sound/snd_dbopl.h
snd_pas16.o: ibm.h io.h pic.h pit.h dma.h timer.h device.h sound/sound.h sound/snd_opl.h sound/snd_pas16.h sound/snd_sb_dsp.h \
SOUND\filters.h
snd_ps1.o: ibm.h io.h pic.h timer.h device.h sound/sound.h sound/snd_ps1.h sound/snd_sn76489.h
snd_pssj.o: ibm.h io.h dma.h pic.h timer.h device.h sound/sound.h sound/snd_pssj.h sound/snd_sn76489.h
snd_resid.o: sound/resid-fp/sid.h sound/snd_resid.h
snd_sb.o: ibm.h io.h mca.h mem.h rom.h device.h sound/sound.h sound/snd_dbopl.h sound/snd_emu8k.h sound/snd_mpu401.h \
sound/snd_opl.h sound/snd_sb.h sound/snd_sb_dsp.h sound/filters.h
snd_sb_dsp.o: ibm.h io.h pic.h dma.h timer.h device.h sound/midi.h sound/sound.h sound/snd_mpu401.h sound/snd_sb_dsp.h
snd_sn76489.o: ibm.h io.h device.h sound/sound.h sound/snd_sn76489.h
snd_speaker.o: ibm.h sound/sound.h sound/snd_speaker.h
snd_ssi2001.o: ibm.h io.h device.h sound/sound.h sound/snd_resid.h sound/snd_ssi2001.h
snd_wss.o: ibm.h io.h pic.h dma.h device.h sound/sound.h sound/snd_ad1848.h sound/snd_opl.h sound/snd_wss.h
snd_ym7128.o: ibm.h sound/snd_ym7128.h
sound.o: ibm.h device.h timer.h cdrom.h win/plat_thread.h sound/midi.h sound/sound.h sound/snd_opl.h sound/snd_adlib.h \
sound/snd_pas16.h sound/snd_sb.h sound/snd_sb_dsp.h sound/snd_wss.h sound/filters.h
tandy_eeprom.o: ibm.h device.h mem.h io.h rom.h tandy_eeprom.h
tandy_rom.o: ibm.h device.h io.h mem.h rom.h tandy_rom.h
timer.o: ibm.h timer.h
usb.o: ibm.h io.h mem.h usb.h
vid_ati_eeprom.o: ibm.h mem.h rom.h video/vid_ati_eeprom.h
vid_ati_mach64.o: ibm.h device.h io.h mem.h pci.h rom.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_svga_render.h \
video/vid_ati68860_ramdac.h video/vid_ati_eeprom.h video/vid_ics2595.h
vid_ati18800.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_ati18800.h video/vid_ati_eeprom.h video/vid_svga.h
vid_ati28800.o: ibm.h io.h mem.h rom.h device.h timer.h video/video.h video/vid_ati28800.h video/vid_ati_eeprom.h video/vid_svga.h \
video/vid_svga_render.h
vid_ati68860_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_ati68860_ramdac.h video/vid_svga_render.h
vid_cga.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_cga_comp.h win/win_cgapal.h
vid_cga_comp.o: ibm.h device.h mem.h video/vid_cga.h video/vid_cga_comp.h
vid_cl_gd.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_cl_ramdac.h \
video/vid_cl_gd.h video/vid_cl_gd_blit.h
vid_cl_gd_blit.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_cl_ramdac.h \
video/vid_cl_gd.h video/vid_cl_gd_blit.h video/vid_cl_gd_vga_rop.h
vid_cl_gd_ramdac.o: ibm.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_cl_ramdac.h video/vid_cl_gd.h \
video/vid_cl_gd_blit.h
vid_colorplus.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_colorplus.h video/vid_cga_comp.h
vid_ega.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_ega.h video/vid_ega_render.h
vid_ega_render.o: ibm.h device.h mem.h rom.h video/video.h video/vid_ega.h video/vid_ega_render.h
vid_et4000.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_sc1502x_ramdac.h video/vid_et4000.h
vid_et4000w32.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_icd2061.h \
video/vid_stg_ramdac.h
vid_genius.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_genius.h
vid_hercules.o: ibm.h mem.h io.h timer.h device.h video/video.h video/vid_hercules.h win/win_cgapal.h
vid_herculesplus.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_herculesplus.h
vid_icd2061.o: ibm.h video/vid_icd2061.h
vid_ics2595.o: ibm.h video/vid_ics2595.h
vid_incolor.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_incolor.h
vid_mda.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_mda.h win/win_cgapal.h
vid_nv_riva128.o: ibm.h io.h mem.h pci.h pic.h rom.h timer.h device.h win/plat_thread.h video/video.h video/vid_svga.h \
video/vid_svga_render.h
vid_olivetti_m24.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_olivetti_m24.h
vid_oti067.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_oti067.h video/vid_svga.h
vid_paradise.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_paradise.h video/vid_svga.h video/vid_svga_render.h
vid_pc200.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_pc200.h
vid_pc1512.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_pc1512.h
vid_pc1640.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_cga.h video/vid_ega.h video/vid_pc1640.h
vid_pcjr.o: ibm.h io.h mem.h pic.h timer.h device.h video/video.h video/vid_cga_comp.h video/vid_pcjr.h
vid_ps1_svga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_vga.h
vid_s3.o: ibm.h device.h io.h mem.h pci.h rom.h win/plat_thread.h video/video.h video/vid_s3.h video/vid_svga.h \
video/vid_svga_render.h video/vid_sdac_ramdac.h
vid_s3_virge.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_s3_virge.h video/vid_svga.h \
video/vid_svga_render.h
vid_sc1502x_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_sc1502x_ramdac.h
vid_sdac_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_sdac_ramdac.h
vid_stg_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_stg_ramdac.h
vid_svga.o: ibm.h io.h mem.h rom.h timer.h video/video.h video/vid_svga.h video/vid_svga_render.h
vid_svga_render.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_svga_render.h
vid_tandy.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_tandy.h video/vid_cga_comp.h
vid_tandysl.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_tandysl.h
vid_tgui9440.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_svga_render.h \
video/vid_tkd8001_ramdac.h video/vid_tgui9440.h
vid_tkd8001_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_tkd8001_ramdac.h
vid_tvga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_tkd8001_ramdac.h \
video/vid_tvga.h
vid_vga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_vga.h
vid_voodoo.o: ibm.h cpu/cpu.h mem.h rom.h pci.h timer.h device.h win/plat_thread.h video/video.h video/vid_svga.h \
video/vid_voodoo.h video/vid_voodoo_dither.h video/$(VCG)
vid_wy700.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_wy700.h
video.o: ibm.h cpu/cpu.h io.h mem.h rom.h config.h device.h timer.h win/plat_thread.h video/video.h video/vid_svga.h \
win/resource.h win/win.h win/win_cgapal.h \
video/vid_ati18800.h video/vid_ati28800.h video/vid_ati_mach64.h video/vid_cga.h \
video/vid_cl_ramdac.h video/vid_cl_gd.h \
video/vid_ega.h video/vid_et4000.h video/vid_et4000w32.h video/vid_genius.h video/vid_hercules.h \
video/vid_herculesplus.h video/vid_incolor.h video/vid_colorplus.h video/vid_mda.h \
video/vid_nv_riva128.h \
video/vid_olivetti_m24.h video/vid_oti067.h video/vid_paradise.h video/vid_pc1512.h video/vid_pc1640.h \
video/vid_pc200.h video/vid_pcjr.h video/vid_ps1_svga.h video/vid_s3.h video/vid_s3_virge.h video/vid_tandy.h \
video/vid_tandysl.h video/vid_tgui9440.h video/vid_tvga.h video/vid_vga.h video/vid_wy700.h
win.o: 86box.h device.h floppy.h fdd.h hdd.h ibm.h cpu/cpu.h mem.h rom.h nvr.h config.h machine/machine.h hdd/hdd_ide_at.h cdrom.h cdrom_null.h \
cdrom_ioctl.h cdrom_image.h scsi/scsi.h scsi_disk.h video/video.h video/vid_ega.h mouse.h sound/sound.h sound/snd_dbopl.h \
win/plat_keyboard.h win/plat_iodev.h win/plat_mouse.h win/plat_midi.h win/plat_thread.h win/plat_ticks.h win/plat_ui.h \
win/resource.h win/win.h win/win_cgapal.h win/win_ddraw.h win/win_d3d.h win/win_language.h
win_d3d.o: video/video.h win/win.h win/resource.h win/win_d3d.h win/win_cgapal.h
win_d3d_fs.o: 86box.h video/video.h win/win.h win/resource.h win/win_d3d.h win/win_cgapal.h
win_ddraw.o: video/video.h win/resource.h win/win_ddraw.h win/win_cgapal.h
win_ddraw_fs.o: video/video.h win/resource.h win/win_ddraw.h win/win_cgapal.h
win_ddraw_screenshot.o: video/video.h win/resource.h win/win.h win/win_ddraw.h win/win_language.h
win_deviceconfig.o: win/plat_midi.h win/resource.h win/win.h win/win_language.h
win_dynld.o: win/plat_dynld.h win/resource.h ibm.h
win_iodev.o: ibm.h device.h cdrom.h cdrom_image.h cdrom_ioctl.h cdrom_null.h scsi/scsi_disk.h win/plat_iodev.h win/resource.h win/win.h
win_joystick.o: device.h gameport.h win/plat_joystick.h win/resource.h win/win.h
win_joystickconfig.o: ibm.h config.h device.h gameport.h win/plat_joystick.h win/resource.h win/win.h
win_keyboard.o: device.h win/plat_keyboard.h win/resource.h win/win.h
win_language.o: ibm.h device.h win/plat_ui.h win/resource.h win/win.h win/win_language.h
win_midi.o: ibm.h config.h sound/midi.h win/plat_midi.h win/resource.h
win_mouse.o: win/plat_mouse.h win/resource.h win/win.h
win_opendir.o: ibm.h win/plat_dir.h win/resource.h
win_serial.o: win/plat_thread.h win/plat_serial.h win/resource.h
win_settings.o: ibm.h mem.h cpu/cpu.h nvr.h device.h machine/machine.h cdrom.h floppy.h fdd.h hdd/hdd.h hdd/hdd_ide_at.h scsi/scsi.h network/network.h sound/midi.h \
sound/sound.h sound/snd_dbopl.h sound/snd_mpu401.h video/video.h video/vid_voodoo.h gameport.h mouse.h win/plat_midi.h \
win/resource.h win/win.h win/win_language.h
win_status.o: ibm.h mem.h cpu/x86_ops.h cpu/codegen.h device.h win/resource.h win/win.h
win_video.o: video/video.h win/resource.h win/win_cgapal.h
# End of Makefile.mingw.

View File

@@ -44,13 +44,18 @@
* configuration register (CTRL_SPCFG bit set) but have to
* remember that stuff first...
*
* Version: @(#)bugger.c 1.0.4 2017/05/09
* Version: @(#)bugger.c 1.0.7 2017/10/09
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 1989-2017 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "ui.h"
#include "bugger.h"
@@ -99,7 +104,7 @@ bug_setui(void)
(bug_ledr&0x02)?'R':'r', (bug_ledr&0x01)?'R':'r');
/* Send formatted string to the UI. */
status_settext(bug_str);
ui_sb_set_text(bug_str);
}

View File

@@ -9,24 +9,33 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)cdrom.c 1.0.4 2017/09/03
* Version: @(#)cdrom.c 1.0.17 2017/10/14
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016,2017 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#include "../86box.h"
#include "../config.h"
#include "../ibm.h"
#include "../timer.h"
#include "../device.h"
#include "../piix.h"
#include "../scsi/scsi.h"
#include "../timer.h"
#include "../hdd/hdd_ide_at.h"
#include "../win/plat_iodev.h"
#include "../nvr.h"
#include "../disk/hdc.h"
#include "../disk/hdc_ide.h"
#include "../plat.h"
#include "../ui.h"
#include "cdrom.h"
#include "cdrom_image.h"
#include "cdrom_null.h"
/* Bits of 'status' */
@@ -41,12 +50,6 @@
#define ABRT_ERR 0x04 /* Command aborted */
#define MCR_ERR 0x08 /* Media change request */
#define MODE_SELECT_PHASE_IDLE 0
#define MODE_SELECT_PHASE_HEADER 1
#define MODE_SELECT_PHASE_BLOCK_DESC 2
#define MODE_SELECT_PHASE_PAGE_HEADER 3
#define MODE_SELECT_PHASE_PAGE 4
cdrom_t cdrom[CDROM_NUM];
cdrom_drive_t cdrom_drives[CDROM_NUM];
uint8_t atapi_cdrom_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -67,12 +70,9 @@ uint8_t scsi_cdrom_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };
#ifdef __MSC__
# pragma pack(push,1)
#pragma pack(push,1)
static struct
#else
static struct __attribute__((__packed__))
#endif
{
uint8_t opcode;
uint8_t polled;
@@ -82,24 +82,17 @@ static struct __attribute__((__packed__))
uint16_t len;
uint8_t control;
} *gesn_cdb;
#ifdef __MSC__
# pragma pack(pop)
#endif
#pragma pack(pop)
#ifdef __MSC__
# pragma pack(push,1)
#pragma pack(push,1)
static struct
#else
static struct __attribute__((__packed__))
#endif
{
uint16_t len;
uint8_t notification_class;
uint8_t supported_events;
} *gesn_event_header;
#ifdef __MSC__
# pragma pack(pop)
#endif
#pragma pack(pop)
/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */
uint8_t cdrom_command_flags[0x100] =
@@ -986,16 +979,16 @@ void cdrom_mode_sense_load(uint8_t id)
switch(id)
{
case 0:
f = _wfopen(nvr_concat(L"cdrom_1_mode_sense.bin"), L"rb");
f = plat_fopen(nvr_path(L"cdrom_1_mode_sense.bin"), L"rb");
break;
case 1:
f = _wfopen(nvr_concat(L"cdrom_2_mode_sense.bin"), L"rb");
f = plat_fopen(nvr_path(L"cdrom_2_mode_sense.bin"), L"rb");
break;
case 2:
f = _wfopen(nvr_concat(L"cdrom_3_mode_sense.bin"), L"rb");
f = plat_fopen(nvr_path(L"cdrom_3_mode_sense.bin"), L"rb");
break;
case 3:
f = _wfopen(nvr_concat(L"cdrom_4_mode_sense.bin"), L"rb");
f = plat_fopen(nvr_path(L"cdrom_4_mode_sense.bin"), L"rb");
break;
default:
return;
@@ -1014,16 +1007,16 @@ void cdrom_mode_sense_save(uint8_t id)
switch(id)
{
case 0:
f = _wfopen(nvr_concat(L"cdrom_1_mode_sense.bin"), L"wb");
f = plat_fopen(nvr_path(L"cdrom_1_mode_sense.bin"), L"wb");
break;
case 1:
f = _wfopen(nvr_concat(L"cdrom_2_mode_sense.bin"), L"wb");
f = plat_fopen(nvr_path(L"cdrom_2_mode_sense.bin"), L"wb");
break;
case 2:
f = _wfopen(nvr_concat(L"cdrom_3_mode_sense.bin"), L"wb");
f = plat_fopen(nvr_path(L"cdrom_3_mode_sense.bin"), L"wb");
break;
case 3:
f = _wfopen(nvr_concat(L"cdrom_4_mode_sense.bin"), L"wb");
f = plat_fopen(nvr_path(L"cdrom_4_mode_sense.bin"), L"wb");
break;
default:
return;
@@ -1431,23 +1424,23 @@ static void cdrom_command_common(uint8_t id)
cdrom[id].pos = 0;
if (cdrom[id].packet_status == CDROM_PHASE_COMPLETE)
{
cdrom[id].callback = 20 * CDROM_TIME;
cdrom[id].callback = 20LL * CDROM_TIME;
}
else if (cdrom[id].packet_status == CDROM_PHASE_DATA_IN)
{
if (cdrom[id].current_cdb[0] == 0x42)
{
cdrom_log("CD-ROM %i: READ SUBCHANNEL\n");
cdrom[id].callback = 1000 * CDROM_TIME;
cdrom[id].callback = 1000LL * CDROM_TIME;
}
else
{
cdrom[id].callback = 60 * CDROM_TIME;
cdrom[id].callback = 60LL * CDROM_TIME;
}
}
else
{
cdrom[id].callback = 60 * CDROM_TIME;
cdrom[id].callback = 60LL * CDROM_TIME;
}
}
@@ -1505,11 +1498,7 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al
}
if (cdrom_request_length_is_zero(id) || (len == 0) || (cdrom_current_mode(id) == 0))
{
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = 0;
}
else
if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI)
{
cdrom[id].init_length = 0;
}
@@ -1521,11 +1510,7 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al
{
if (direction == 0)
{
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = alloc_len;
}
else
if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI)
{
cdrom[id].init_length = alloc_len;
}
@@ -1561,6 +1546,7 @@ static void cdrom_sense_clear(int id, int command)
static void cdrom_cmd_error(uint8_t id)
{
SCSIPhase = SCSI_PHASE_STATUS;
cdrom[id].error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR;
if (cdrom[id].unit_attention)
{
@@ -1569,12 +1555,13 @@ static void cdrom_cmd_error(uint8_t id)
cdrom[id].status = READY_STAT | ERR_STAT;
cdrom[id].phase = 3;
cdrom[id].packet_status = 0x80;
cdrom[id].callback = 50 * CDROM_TIME;
cdrom[id].callback = 50LL * CDROM_TIME;
cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", id, cdrom_sense_key, cdrom_asc, cdrom_ascq);
}
static void cdrom_unit_attention(uint8_t id)
{
SCSIPhase = SCSI_PHASE_STATUS;
cdrom[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR;
if (cdrom[id].unit_attention)
{
@@ -1583,7 +1570,7 @@ static void cdrom_unit_attention(uint8_t id)
cdrom[id].status = READY_STAT | ERR_STAT;
cdrom[id].phase = 3;
cdrom[id].packet_status = 0x80;
cdrom[id].callback = 50 * CDROM_TIME;
cdrom[id].callback = 50LL * CDROM_TIME;
cdrom_log("CD-ROM %i: UNIT ATTENTION\n", id);
}
@@ -1920,7 +1907,7 @@ static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packe
case 0x00: /* Physical format information */
total_sectors = (uint64_t) cdrom_drives[id].handler->size(id);
if (layer != 0)
if (layer != 0)
{
cdrom_invalid_field(id);
return 0;
@@ -2020,47 +2007,6 @@ static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packe
}
}
/*SCSI Get Event Status Notification*/
static uint32_t cdrom_get_event_status(uint8_t id, uint8_t *buffer)
{
uint8_t event_code, media_status = 0;
if (buffer[5])
{
media_status = MS_TRAY_OPEN;
if (cdrom_drives[id].handler->stop)
{
cdrom_drives[id].handler->stop(id);
}
}
else
{
media_status = MS_MEDIA_PRESENT;
}
event_code = MEC_NO_CHANGE;
if (media_status != MS_TRAY_OPEN)
{
if (!buffer[4])
{
event_code = MEC_NEW_MEDIA;
cdrom_drives[id].handler->load(id);
}
else if (buffer[4]==2)
{
event_code = MEC_EJECT_REQUESTED;
cdrom_drives[id].handler->eject(id);
}
}
buffer[4] = event_code;
buffer[5] = media_status;
buffer[6] = 0;
buffer[7] = 0;
return 8;
}
void cdrom_insert(uint8_t id)
{
cdrom[id].unit_attention = 1;
@@ -2164,6 +2110,15 @@ skip_ready_check:
}
/* Next it's time for NOT READY. */
if (!ready)
{
cdrom[id].media_status = MEC_MEDIA_REMOVAL;
}
else
{
cdrom[id].media_status = (cdrom[id].unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE;
}
if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready)
{
cdrom_log("CD-ROM %i: Not ready (%02X)\n", id, cdb[0]);
@@ -2182,7 +2137,7 @@ void cdrom_clear_callback(uint8_t channel)
if (id <= CDROM_NUM)
{
cdrom[id].callback = 0;
cdrom[id].callback = 0LL;
}
}
@@ -2210,7 +2165,7 @@ void cdrom_reset(uint8_t id)
{
cdrom_rezero(id);
cdrom[id].status = 0;
cdrom[id].callback = 0;
cdrom[id].callback = 0LL;
cdrom[id].packet_status = 0xff;
cdrom[id].unit_attention = 0;
}
@@ -2262,7 +2217,7 @@ void cdrom_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length)
}
}
/* cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", id, cdbufferb[2], cdbufferb[12], cdbufferb[13]); */
cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]);
if (buffer[2] == SENSE_UNIT_ATTENTION)
{
@@ -2321,16 +2276,20 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
int track = 0;
char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 };
char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 };
int32_t blen = 0;
int32_t *BufLen;
#if 0
#if 1
int CdbLength;
#endif
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength;
cdrom[id].status &= ~ERR_STAT;
}
else
{
BufLen = &blen;
cdrom[id].error = 0;
}
@@ -2355,10 +2314,10 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, ins, cdrom[id].unit_attention);
cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length);
#if 0
#if 1
for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++)
{
cdrom_log("CD-ROM %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]);
cdrom_log("CD-ROM %i: CDB[%d] = %d\n", id, CdbLength, cdb[CdbLength]);
}
#endif
}
@@ -2366,6 +2325,8 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
msf = cdb[1] & 2;
cdrom[id].sector_len = 0;
SCSIPhase = SCSI_PHASE_STATUS;
/* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */
if (cdrom_pre_execution_check(id, cdb) == 0)
{
@@ -2375,6 +2336,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
switch (cdb[0])
{
case GPCMD_TEST_UNIT_READY:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_command_complete(id);
break;
@@ -2385,16 +2347,22 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
}
cdrom[id].sector_pos = cdrom[id].sector_len = 0;
cdrom_seek(id, 0);
SCSIPhase = SCSI_PHASE_STATUS;
break;
case GPCMD_REQUEST_SENSE:
/* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE
should forget about the not ready, and report unit attention straight away. */
SCSIPhase = SCSI_PHASE_DATA_IN;
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
if (SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength < cdb[4])
if ((*BufLen == -1) || (cdb[4] < *BufLen))
{
cdb[4] = SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength;
*BufLen = cdb[4];
}
if (*BufLen < cdb[4])
{
cdb[4] = *BufLen;
}
}
cdrom_request_sense(id, cdbufferb, cdb[4]);
@@ -2403,12 +2371,20 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case GPCMD_SET_SPEED:
case GPCMD_SET_SPEED_ALT:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_command_complete(id);
break;
case GPCMD_MECHANISM_STATUS:
SCSIPhase = SCSI_PHASE_DATA_IN;
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
memset(cdbufferb, 0, 8);
cdbufferb[5] = 1;
@@ -2418,6 +2394,8 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case GPCMD_READ_TOC_PMA_ATIP:
cdrom[id].toctimes++;
SCSIPhase = SCSI_PHASE_DATA_IN;
max_len = cdb[7];
max_len <<= 8;
max_len |= cdb[8];
@@ -2431,6 +2409,13 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
cdrom_sense_key = cdrom_asc = cdrom_ascq = 0;
goto cdrom_readtoc_fallback;
}
else
{
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
}
alloc_length = cdbufferb[0];
alloc_length <<= 8;
alloc_length |= cdbufferb[1];
@@ -2476,6 +2461,11 @@ cdrom_readtoc_fallback:
cdbufferb[1] = (len - 2) & 0xff;
}
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, len, 0);
/* cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", id, toc_format, ide->cylinder, cdbufferb[1]); */
return;
@@ -2487,6 +2477,8 @@ cdrom_readtoc_fallback:
case GPCMD_READ_12:
case GPCMD_READ_CD:
case GPCMD_READ_CD_MSF:
SCSIPhase = SCSI_PHASE_DATA_IN;
switch(cdb[0])
{
case GPCMD_READ_6:
@@ -2526,9 +2518,10 @@ cdrom_readtoc_fallback:
if (!cdrom[id].sector_len)
{
SCSIPhase = SCSI_PHASE_STATUS;
/* cdrom_log("CD-ROM %i: All done - callback set\n", id); */
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].callback = 20 * CDROM_TIME;
cdrom[id].callback = 20LL * CDROM_TIME;
break;
}
@@ -2550,6 +2543,12 @@ cdrom_readtoc_fallback:
}
cdrom[id].packet_len = max_len * alloc_length;
if ((*BufLen == -1) || (cdrom[id].packet_len < *BufLen))
{
*BufLen = cdrom[id].packet_len;
}
if (cdrom[id].requested_blocks > 1)
{
cdrom_data_command_finish(id, alloc_length, alloc_length / cdrom[id].requested_blocks, alloc_length, 0);
@@ -2561,15 +2560,17 @@ cdrom_readtoc_fallback:
cdrom[id].all_blocks_total = cdrom[id].block_total;
if (cdrom[id].packet_status != CDROM_PHASE_COMPLETE)
{
update_status_bar_icon(SB_CDROM | id, 1);
ui_sb_update_icon(SB_CDROM | id, 1);
}
else
{
update_status_bar_icon(SB_CDROM | id, 0);
ui_sb_update_icon(SB_CDROM | id, 0);
}
return;
case GPCMD_READ_HEADER:
SCSIPhase = SCSI_PHASE_DATA_IN;
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
@@ -2577,6 +2578,13 @@ cdrom_readtoc_fallback:
{
return;
}
else
{
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
}
}
else
{
@@ -2600,11 +2608,18 @@ cdrom_readtoc_fallback:
len = 8;
}
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, len, 0);
return;
case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10:
SCSIPhase = SCSI_PHASE_DATA_IN;
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
@@ -2674,6 +2689,11 @@ cdrom_readtoc_fallback:
alloc_length = len;
}
if ((*BufLen == -1) || (alloc_length < *BufLen))
{
*BufLen = alloc_length;
}
cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", id, cdb[2]);
cdrom_data_command_finish(id, len, len, alloc_length, 0);
@@ -2681,6 +2701,8 @@ cdrom_readtoc_fallback:
case GPCMD_MODE_SELECT_6:
case GPCMD_MODE_SELECT_10:
SCSIPhase = SCSI_PHASE_DATA_OUT;
if (cdb[0] == GPCMD_MODE_SELECT_6)
{
len = cdb[4];
@@ -2690,12 +2712,19 @@ cdrom_readtoc_fallback:
len = (cdb[7] << 8) | cdb[8];
}
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
ret = cdrom_mode_select_init(id, cdb[0], len, cdb[1] & 1);
cdrom_data_command_finish(id, len, len, len, 1);
return;
case GPCMD_GET_CONFIGURATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
/* XXX: could result in alignment problems in some architectures */
len = (cdb[7] << 8) | cdb[8];
alloc_length = len;
@@ -2745,10 +2774,17 @@ cdrom_readtoc_fallback:
cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff;
cdbufferb[3] = (alloc_length - 4) & 0xff;
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, alloc_length, 0);
break;
case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
gesn_cdb = (void *) cdb;
gesn_event_header = (void *) cdbufferb;
@@ -2788,7 +2824,12 @@ cdrom_readtoc_fallback:
if (gesn_cdb->class & (1 << GESN_MEDIA))
{
gesn_event_header->notification_class |= GESN_MEDIA;
used_len = cdrom_get_event_status(id, cdbufferb);
cdbufferb[4] = cdrom[id].media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */
cdbufferb[5] = 1; /* Power Status (1 = Active) */
cdbufferb[6] = 0;
cdbufferb[7] = 0;
used_len = 8;
}
else
{
@@ -2797,10 +2838,19 @@ cdrom_readtoc_fallback:
}
gesn_event_header->len = used_len - sizeof(*gesn_event_header);
memcpy(cdbufferb, gesn_event_header, 4);
if ((*BufLen == -1) || (used_len < *BufLen))
{
*BufLen = used_len;
}
cdrom_data_command_finish(id, used_len, used_len, used_len, 0);
break;
case GPCMD_READ_DISC_INFORMATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
max_len = cdb[7];
max_len <<= 8;
max_len |= cdb[8];
@@ -2834,10 +2884,18 @@ cdrom_readtoc_fallback:
len=34;
}
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, max_len, 0);
SCSIPhase = BUS_IO;
break;
case GPCMD_READ_TRACK_INFORMATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
max_len = cdb[7];
max_len <<= 8;
max_len |= cdb[8];
@@ -2894,13 +2952,21 @@ cdrom_readtoc_fallback:
}
}
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, max_len, 0);
SCSIPhase = BUS_IO;
break;
case GPCMD_PLAY_AUDIO_10:
case GPCMD_PLAY_AUDIO_12:
case GPCMD_PLAY_AUDIO_MSF:
case GPCMD_PLAY_AUDIO_TRACK_INDEX:
SCSIPhase = SCSI_PHASE_STATUS;
switch(cdb[0])
{
case GPCMD_PLAY_AUDIO_10:
@@ -2947,6 +3013,8 @@ cdrom_readtoc_fallback:
break;
case GPCMD_READ_SUBCHANNEL:
SCSIPhase = SCSI_PHASE_DATA_IN;
max_len = cdb[7];
max_len <<= 8;
max_len |= cdb[8];
@@ -3053,10 +3121,17 @@ cdrom_readtoc_fallback:
}
}
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, max_len, 0);
break;
case GPCMD_READ_DVD_STRUCTURE:
SCSIPhase = SCSI_PHASE_DATA_IN;
if (cdrom_drives[id].handler->pass_through)
{
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
@@ -3064,6 +3139,13 @@ cdrom_readtoc_fallback:
{
return;
}
else
{
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
}
}
else
{
@@ -3109,6 +3191,11 @@ cdrom_readtoc_fallback:
{
ret = cdrom_read_dvd_structure(id, format, cdb, cdbufferb);
if ((*BufLen == -1) || (alloc_length < *BufLen))
{
*BufLen = alloc_length;
}
if (ret)
{
cdrom_data_command_finish(id, len, len, alloc_length, 0);
@@ -3132,6 +3219,8 @@ cdrom_readtoc_fallback:
break;
case GPCMD_START_STOP_UNIT:
SCSIPhase = SCSI_PHASE_STATUS;
switch(cdb[4] & 3)
{
case 0: /* Stop the disc. */
@@ -3159,6 +3248,8 @@ cdrom_readtoc_fallback:
break;
case GPCMD_INQUIRY:
SCSIPhase = SCSI_PHASE_DATA_IN;
max_len = cdb[3];
max_len <<= 8;
max_len |= cdb[4];
@@ -3237,15 +3328,23 @@ atapi_out:
cdbufferb[size_idx] = idx - preamble_len;
len=idx;
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, max_len, 0);
break;
case GPCMD_PREVENT_REMOVAL:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_command_complete(id);
break;
case GPCMD_PAUSE_RESUME_ALT:
case GPCMD_PAUSE_RESUME:
SCSIPhase = SCSI_PHASE_STATUS;
if (cdb[8] & 1)
{
if (cdrom_drives[id].handler->resume)
@@ -3275,6 +3374,8 @@ atapi_out:
case GPCMD_SEEK_6:
case GPCMD_SEEK_10:
SCSIPhase = SCSI_PHASE_STATUS;
switch(cdb[0])
{
case GPCMD_SEEK_6:
@@ -3289,15 +3390,24 @@ atapi_out:
break;
case GPCMD_READ_CDROM_CAPACITY:
SCSIPhase = SCSI_PHASE_DATA_IN;
if (cdrom_read_capacity(id, cdrom[id].current_cdb, cdbufferb, &len) == 0)
{
return;
}
if ((*BufLen == -1) || (len < *BufLen))
{
*BufLen = len;
}
cdrom_data_command_finish(id, len, len, len, 0);
break;
case GPCMD_STOP_PLAY_SCAN:
SCSIPhase = SCSI_PHASE_STATUS;
if (cdrom_drives[id].handler->stop)
{
cdrom_drives[id].handler->stop(id);
@@ -3482,6 +3592,7 @@ int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun)
uint8_t *cdbufferb;
uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun];
int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength;
cdbufferb = (uint8_t *) cdrom[id].buffer;
@@ -3490,14 +3601,15 @@ int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun)
return 0;
}
cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id][scsi_lun].InitLength);
memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, SCSIDevices[scsi_id][scsi_lun].InitLength);
cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen);
memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen);
return 1;
}
int cdrom_read_from_dma(uint8_t id)
{
uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer;
int32_t *BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength;
int i = 0;
int ret = 0;
@@ -3520,7 +3632,7 @@ int cdrom_read_from_dma(uint8_t id)
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
in_data_length = SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength;
in_data_length = *BufLen;
cdrom_log("CD-ROM %i: SCSI Input data length: %i\n", id, in_data_length);
}
else
@@ -3605,6 +3717,7 @@ int cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun)
uint8_t *cdbufferb;
uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun];
int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength;
if (id > CDROM_NUM)
{
@@ -3613,8 +3726,8 @@ int cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun)
cdbufferb = (uint8_t *) cdrom[id].buffer;
cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id][scsi_lun].InitLength);
memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, SCSIDevices[scsi_id][scsi_lun].InitLength);
cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen);
memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, *BufLen);
cdrom_log("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]);
cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]);
return 1;
@@ -3626,6 +3739,7 @@ int cdrom_write_to_dma(uint8_t id)
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
cdrom_log("Write to SCSI DMA: (%02X:%02X)\n", cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun);
ret = cdrom_write_to_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun);
}
else
@@ -3671,7 +3785,7 @@ void cdrom_phase_callback(uint8_t id)
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
cdrom[id].packet_status = 0xFF;
update_status_bar_icon(SB_CDROM | id, 0);
ui_sb_update_icon(SB_CDROM | id, 0);
cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_OUT:
@@ -3686,7 +3800,7 @@ void cdrom_phase_callback(uint8_t id)
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
update_status_bar_icon(SB_CDROM | id, 0);
ui_sb_update_icon(SB_CDROM | id, 0);
cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_IN:
@@ -3701,7 +3815,7 @@ void cdrom_phase_callback(uint8_t id)
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
update_status_bar_icon(SB_CDROM | id, 0);
ui_sb_update_icon(SB_CDROM | id, 0);
cdrom_irq_raise(id);
return;
case CDROM_PHASE_ERROR:
@@ -3854,3 +3968,79 @@ void cdrom_write(uint8_t channel, uint32_t val, int length)
return;
}
}
void cdrom_hard_reset(void)
{
int i = 0;
for (i=0; i<CDROM_NUM; i++) {
if (cdrom_drives[i].host_drive == 200) {
image_reset(i);
}
else if ((cdrom_drives[i].host_drive >= 'A') && (cdrom_drives[i].host_drive <= 'Z'))
{
ioctl_reset(i);
}
}
}
/* Peform a master init on the entire module. */
void
cdrom_global_init(void)
{
int c;
/* Clear the global data. */
memset(cdrom, 0x00, sizeof(cdrom));
memset(cdrom_drives, 0x00, sizeof(cdrom_drives));
/* Initialize the host devices, if any. */
cdrom_init_host_drives();
/* Set all drives to NULL mode. */
for (c=0; c<CDROM_NUM; c++)
cdrom_null_open(c, cdrom_drives[c].host_drive);
}
void
cdrom_global_reset(void)
{
int c;
for (c=0; c<CDROM_NUM; c++) {
if (cdrom_drives[c].bus_type) {
SCSIReset(cdrom_drives[c].scsi_device_id, cdrom_drives[c].scsi_device_lun);
}
pclog("CDROM global_reset drive=%d host=%02x\n", c, cdrom_drives[c].host_drive);
if (cdrom_drives[c].host_drive == 200) {
image_open(c, cdrom_image[c].image_path);
} else
if ((cdrom_drives[c].host_drive>='A') && (cdrom_drives[c].host_drive <= 'Z')) {
ioctl_open(c, cdrom_drives[c].host_drive);
} else {
cdrom_null_open(c, cdrom_drives[c].host_drive);
}
}
}
void
cdrom_close(uint8_t id)
{
switch (cdrom_drives[id].host_drive) {
case 0:
null_close(id);
break;
case 200:
image_close(id);
break;
default:
ioctl_close(id);
break;
}
}

View File

@@ -9,10 +9,11 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)cdrom.h 1.0.1 2017/06/03
* Version: @(#)cdrom.h 1.0.2 2017/10/12
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2017 Miran Grca.
*
* Copyright 2016,2017 Miran Grca.
*/
#ifndef EMU_CDROM_H
#define EMU_CDROM_H
@@ -33,14 +34,15 @@
#define CDROM_IMAGE 200
#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT))
#define CDROM_TIME (5 * 100 * (1 << TIMER_SHIFT))
#define IDE_TIME (5LL * 100LL * (1LL << TIMER_SHIFT))
#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT))
typedef struct {
int (*ready)(uint8_t id);
int (*medium_changed)(uint8_t id);
int (*media_type_id)(uint8_t id);
void (*audio_callback)(uint8_t id, int16_t *output, int len);
void (*audio_stop)(uint8_t id);
int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single);
@@ -61,10 +63,11 @@ typedef struct {
void (*exit)(uint8_t id);
} CDROM;
#pragma pack(push,1)
typedef struct {
uint8_t previous_command;
int toctimes;
int media_status;
int is_dma;
@@ -130,9 +133,7 @@ typedef struct {
int init_length;
} cdrom_t;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
int max_blocks_at_once;
@@ -153,7 +154,6 @@ typedef struct {
unsigned int sound_on;
unsigned int atapi_dma;
} cdrom_drive_t;
#pragma pack(pop)
typedef struct {
int image_is_iso;
@@ -227,14 +227,15 @@ int cdrom_lba_to_msf_accurate(int lba);
}
#endif
void cdrom_reset(uint8_t id);
void cdrom_set_signature(int id);
void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length);
void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks);
void cdrom_insert(uint8_t id);
extern void cdrom_close(uint8_t id);
extern void cdrom_reset(uint8_t id);
extern void cdrom_set_signature(int id);
extern void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length);
extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks);
extern void cdrom_insert(uint8_t id);
int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun);
int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
extern int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun);
extern int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
#define cdrom_sense_error cdrom[id].sense[0]
#define cdrom_sense_key cdrom[id].sense[2]
@@ -242,5 +243,9 @@ int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len
#define cdrom_ascq cdrom[id].sense[13]
#define cdrom_drive cdrom_drives[id].host_drive
extern void cdrom_global_init(void);
extern void cdrom_global_reset(void);
extern void cdrom_hard_reset(void);
#endif /*EMU_CDROM_H*/

View File

@@ -20,7 +20,10 @@
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#ifdef WIN32
//FIXME: should not be needed. */
# define _GNU_SOURCE
#endif
#include <stdio.h>
#include <cctype>

View File

@@ -6,9 +6,13 @@
#define __USE_LARGEFILE64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdarg.h>
#include "../config.h"
#include "../plat.h"
#include "cdrom_dosbox.h"
#include "cdrom.h"
#include "cdrom_image.h"
@@ -987,10 +991,10 @@ int image_open(uint8_t id, wchar_t *fn)
if (!cdrom_image[id].image_inited || cdrom_image[id].image_changed)
{
_swprintf(cdrom_image[id].image_path, L"%ws", fn);
swprintf(cdrom_image[id].image_path, sizeof(cdrom_image[id].image_path)/sizeof(wchar_t), L"%ls", fn);
}
if (!wcsicmp(get_extension_w(fn), L"ISO"))
if (! wcscasecmp(get_extension_w(fn), L"ISO"))
{
cdrom_image[id].image_is_iso = 1;
}

View File

@@ -1,35 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the CD-ROM host drive IOCTL interface for
* Windows using SCSI Passthrough Direct.
*
* This file lists the functions provided by various platform-
* specific cdrom-ioctl files.
*
* Version: @(#)cdrom_ioctl.h 1.0.3 2017/09/03
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2016 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#ifndef EMU_CDROM_IOCTL_H
#define EMU_CDROM_IOCTL_H
extern uint32_t cdrom_capacity;
extern int ioctl_open(uint8_t id, char d);
extern void ioctl_reset(uint8_t id);
extern void ioctl_close(uint8_t id);
#endif /*EMU_CDROM_IOCTL_H */

View File

@@ -9,139 +9,181 @@
* Implementation of the CD-ROM null interface for unmounted
* guest CD-ROM drives.
*
* Version: @(#)cdrom_null.c 1.0.2 2017/09/03
* Version: @(#)cdrom_null.c 1.0.4 2017/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2016 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "cdrom.h"
#include "cdrom_ioctl.h"
static CDROM null_cdrom;
static int null_ready(uint8_t id)
static int
null_ready(uint8_t id)
{
return 0;
return(0);
}
/* Always return 0, the contents of a null CD-ROM drive never change. */
static int null_medium_changed(uint8_t id)
static int
null_medium_changed(uint8_t id)
{
return 0;
return(0);
}
static uint8_t null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf)
static uint8_t
null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf)
{
return 0x13;
return(0x13);
}
static void null_eject(uint8_t id)
static void
null_eject(uint8_t id)
{
}
static void null_load(uint8_t id)
static void
null_load(uint8_t id)
{
}
static int null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len)
static int
null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len)
{
*len = 0;
return 0;
*len = 0;
return(0);
}
static int null_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
static int
null_readtoc(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single)
{
return 0;
return(0);
}
static int null_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen)
static int
null_readtoc_session(uint8_t id, uint8_t *b, int msf, int maxlen)
{
return 0;
return(0);
}
static int null_readtoc_raw(uint8_t id, unsigned char *b, int maxlen)
static int
null_readtoc_raw(uint8_t id, uint8_t *b, int maxlen)
{
return 0;
return(0);
}
static uint32_t null_size(uint8_t id)
static uint32_t
null_size(uint8_t id)
{
return 0;
return(0);
}
static int null_status(uint8_t id)
static int
null_status(uint8_t id)
{
return CD_STATUS_EMPTY;
return(CD_STATUS_EMPTY);
}
void cdrom_null_reset(uint8_t id)
void
cdrom_null_reset(uint8_t id)
{
}
void cdrom_set_null_handler(uint8_t id);
int cdrom_null_open(uint8_t id, char d)
int
cdrom_null_open(uint8_t id, char d)
{
cdrom_set_null_handler(id);
return 0;
cdrom_set_null_handler(id);
return(0);
}
void null_close(uint8_t id)
void
null_close(uint8_t id)
{
}
static void null_exit(uint8_t id)
static
void null_exit(uint8_t id)
{
}
static int null_is_track_audio(uint8_t id, uint32_t pos, int ismsf)
static int
null_is_track_audio(uint8_t id, uint32_t pos, int ismsf)
{
return 0;
return(0);
}
static int null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len)
static int
null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len)
{
return 0;
return(0);
}
static int null_media_type_id(uint8_t id)
static int
null_media_type_id(uint8_t id)
{
return 0x70;
return(0x70);
}
void cdrom_set_null_handler(uint8_t id)
void
cdrom_set_null_handler(uint8_t id)
{
cdrom_drives[id].handler = &null_cdrom;
cdrom_drives[id].host_drive = 0;
memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path));
cdrom_drives[id].handler = &null_cdrom;
cdrom_drives[id].host_drive = 0;
memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path));
}
static CDROM null_cdrom =
{
null_ready,
null_medium_changed,
null_media_type_id,
NULL,
NULL,
null_readtoc,
null_readtoc_session,
null_readtoc_raw,
null_getcurrentsubchannel,
null_pass_through,
null_readsector_raw,
NULL,
null_load,
null_eject,
NULL,
NULL,
null_size,
null_status,
null_is_track_audio,
NULL,
null_exit
static CDROM null_cdrom = {
null_ready,
null_medium_changed,
null_media_type_id,
NULL,
NULL,
null_readtoc,
null_readtoc_session,
null_readtoc_raw,
null_getcurrentsubchannel,
null_pass_through,
null_readsector_raw,
NULL,
null_load,
null_eject,
NULL,
NULL,
null_size,
null_status,
null_is_track_audio,
NULL,
null_exit
};

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,13 @@
*
* Configuration file handler header.
*
* Version: @(#)config.h 1.0.1 2017/08/23
* Version: @(#)config.h 1.0.3 2017/10/13
*
* Authors: Sarah Walker,
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Overdoze,
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
@@ -29,13 +30,18 @@ extern wchar_t config_file_default[256];
extern "C" {
#endif
extern void config_load(wchar_t *fn);
extern void config_save(void);
extern void config_write(wchar_t *fn);
extern void config_dump(void);
extern void config_delete_var(char *head, char *name);
extern int config_get_int(char *head, char *name, int def);
extern int config_get_hex16(char *head, char *name, int def);
extern int config_get_hex20(char *head, char *name, int def);
extern int config_get_mac(char *head, char *name, int def);
extern char *config_get_string(char *head, char *name, char *def);
extern wchar_t *config_get_wstring(char *head, char *name, wchar_t *def);
extern void config_delete_var(char *head, char *name);
extern void config_set_int(char *head, char *name, int val);
extern void config_set_hex16(char *head, char *name, int val);
extern void config_set_hex20(char *head, char *name, int val);
@@ -43,22 +49,11 @@ extern void config_set_mac(char *head, char *name, int val);
extern void config_set_string(char *head, char *name, char *val);
extern void config_set_wstring(char *head, char *name, wchar_t *val);
extern char *get_filename(char *s);
extern wchar_t *get_filename_w(wchar_t *s);
extern void append_filename(char *dest, char *s1, char *s2, int size);
extern void append_filename_w(wchar_t *dest, wchar_t *s1, wchar_t *s2, int size);
extern void put_backslash(char *s);
extern void put_backslash_w(wchar_t *s);
extern char *get_extension(char *s);
extern wchar_t *get_extension_w(wchar_t *s);
extern int config_load(wchar_t *fn);
extern void config_save(wchar_t *fn);
extern void config_dump(void);
extern void loadconfig(wchar_t *fn);
extern void saveconfig(void);
#ifdef __cplusplus
}

View File

@@ -1,10 +1,12 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "../ibm.h"
#include "cpu.h"
#include "x86.h"
@@ -39,21 +41,15 @@ x86seg _oldds;
extern int cpl_override;
int has_fpu;
extern int fpucount;
uint16_t rds;
uint16_t ea_rseg;
int is486;
int cgate32;
uint32_t cr2, cr3, cr4;
uint32_t dr[8];
uint8_t romext[32768];
uint8_t *ram,*rom;
uint32_t rmdat32;
#define rmdat rmdat32
#define fetchdat rmdat32

View File

@@ -1,21 +1,26 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "../ibm.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "../mem.h"
#include "../nmi.h"
#include "../pic.h"
#include "../timer.h"
#include "../floppy/floppy.h"
#include "../floppy/fdc.h"
#ifdef USE_DYNAREC
#include "codegen.h"
#endif
#include "386_common.h"
@@ -43,18 +48,12 @@ int trap;
int cpl_override=0;
int has_fpu;
int fpucount=0;
uint16_t rds;
uint16_t ea_rseg;
int is486;
int cgate32;
uint8_t romext[32768];
uint8_t *ram,*rom;
uint32_t rmdat32;
uint32_t backupregs[16];
int oddeven=0;
@@ -503,6 +502,7 @@ static int cpu_cycle_period(void)
}
}
#ifdef USE_DYNAREC
static int cycles_main = 0;
void exec386_dynarec(int cycs)
{
@@ -606,6 +606,9 @@ void exec386_dynarec(int cycs)
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
ins++;
insc++;
@@ -754,6 +757,9 @@ inrecomp=0;
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
@@ -822,6 +828,9 @@ inrecomp=0;
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
@@ -888,6 +897,19 @@ inrecomp=0;
loadcs(readmemw(0,addr+2));
}
}
else if (nmi && nmi_enable && nmi_mask)
{
cpu_state.oldpc = cpu_state.pc;
oldcs = CS;
pclog("NMI\n");
x86_int(2);
nmi_enable = 0;
if (nmi_auto_clear)
{
nmi_auto_clear = 0;
nmi = 0;
}
}
else if ((flags&I_FLAG) && pic_intpending)
{
temp=picinterrupt();
@@ -931,3 +953,4 @@ inrecomp=0;
cycles_main -= (cycles_start - cycles);
}
}
#endif

View File

@@ -1,3 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
# define INFINITY (__builtin_inff())
@@ -9,6 +13,7 @@
#include "x87.h"
#include "x86_flags.h"
#include "../mem.h"
#include "../nmi.h"
#include "codegen.h"
#include "../pic.h"

View File

@@ -1,4 +1,4 @@
/*
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
@@ -8,34 +8,41 @@
*
* 808x CPU emulation.
*
* Version: @(#)808x.c 1.0.0 2017/05/30
* SHR AX,1
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* 4 clocks - fetch opcode
* 4 clocks - fetch mod/rm
* 2 clocks - execute 2 clocks - fetch opcode 1
* 2 clocks - fetch opcode 2
* 4 clocks - fetch mod/rm
* 2 clocks - fetch opcode 1 2 clocks - execute
* 2 clocks - fetch opcode 2 etc
*
* Version: @(#)808x.c 1.0.4 2017/10/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
/*SHR AX,1
4 clocks - fetch opcode
4 clocks - fetch mod/rm
2 clocks - execute 2 clocks - fetch opcode 1
2 clocks - fetch opcode 2
4 clocks - fetch mod/rm
2 clocks - fetch opcode 1 2 clocks - execute
2 clocks - fetch opcode 2 etc*/
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "cpu.h"
#include "x86.h"
#include "../keyboard.h"
#include "../mem.h"
#include "../rom.h"
#include "../nmi.h"
#include "../pic.h"
#include "../timer.h"
#include "../scsi/scsi.h"
#include "../device.h" /* for scsi.h */
#include "../keyboard.h" /* its WRONG to have this in here!! --FvK */
#include "../scsi/scsi.h" /* its WRONG to have this in here!! --FvK */
#include "../plat.h"
int xt_cpu_multi;
int nmi = 0;
@@ -127,7 +134,10 @@ int noint=0;
int output=0;
#if 0
/* Also in mem.c */
int shadowbios=0;
#endif
int ins=0;
@@ -483,7 +493,10 @@ void makeznptable()
if (c&0x8000) znptable16[c]|=N_FLAG;
}
}
#if 1
/* Also in mem.c */
int timetolive=0;
#endif
extern uint32_t oldcs2;
extern uint32_t oldpc2;
@@ -503,7 +516,7 @@ void dumpregs(int force)
#ifndef RELEASE_BUILD
indump = 1;
output=0;
_wchdir(pcempath);
(void)plat_chdir(cfg_path);
nopageerrors=1;
f=fopen("ram.dmp","wb");
fwrite(ram,mem_size*1024,1,f);
@@ -600,7 +613,9 @@ void resetx86()
mmu_perm=4;
memset(inscounts, 0, sizeof(inscounts));
x86seg_reset();
#ifdef USE_DYNAREC
codegen_reset();
#endif
x86_was_reset = 1;
port_92_clear_reset();
scsi_card_reset();

View File

@@ -1,6 +1,10 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "x86_ops.h"
#include "../mem.h"
#include "x86_ops.h"
#include "codegen.h"
void (*codegen_timing_start)();

View File

@@ -1,3 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "x86.h"

View File

@@ -543,7 +543,7 @@ static x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, u
}
else
{
int base_reg, index_reg;
int base_reg = 0, index_reg = 0;
switch (rm)
{

View File

@@ -1,9 +1,13 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "../mem.h"
#include "codegen.h"
#include "codegen_ops.h"
#include "codegen_timing_common.h"

View File

@@ -8,13 +8,16 @@
- FPU queue
- Out of order execution (beyond most simplistic approximation)
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "../mem.h"
#include "codegen.h"
#include "codegen_timing_common.h"

View File

@@ -1,6 +1,11 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "codegen_timing_common.h"
uint64_t opcode_deps[256] =
{
/* ADD ADD ADD ADD*/

View File

@@ -9,19 +9,21 @@
- PMMX decode queue
- MMX latencies
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "../mem.h"
#include "codegen.h"
#include "codegen_ops.h"
#include "codegen_timing_common.h"
/*Instruction has different execution time for 16 and 32 bit data. Does not pair */
#define CYCLES_HAS_MULTI (1 << 28)

View File

@@ -1,3 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "cpu.h"
#include "x86.h"

View File

@@ -1,6 +1,10 @@
#ifdef __amd64__
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "cpu.h"
@@ -60,7 +64,9 @@ static int last_ssegs;
void codegen_init()
{
#if UNUSED
int c;
#endif
#ifdef __linux__
void *start;
size_t len;
@@ -234,7 +240,9 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
void codegen_block_init(uint32_t phys_addr)
{
codeblock_t *block;
#if UNUSED
int has_evicted = 0;
#endif
page_t *page = &pages[phys_addr >> 12];
if (!page->block[(phys_addr >> 10) & 3])
@@ -274,7 +282,9 @@ void codegen_block_init(uint32_t phys_addr)
void codegen_block_start_recompile(codeblock_t *block)
{
#if UNUSED
int has_evicted = 0;
#endif
page_t *page = &pages[block->phys >> 12];
if (!page->block[(block->phys >> 10) & 3])
@@ -590,7 +600,7 @@ static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat,
}
else
{
int base_reg, index_reg;
int base_reg = 0, index_reg = 0;
switch (cpu_rm)
{
@@ -1074,11 +1084,11 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
generate_call:
codegen_timing_opcode(opcode, fetchdat, op_32);
if ((op_table == x86_dynarec_opcodes &&
((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 ||
(opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 ||
(opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30))) ||
(op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))))
if (((op_table == x86_dynarec_opcodes) &&
(((opcode & 0xf0) == 0x70) || ((opcode & 0xfc) == 0xe0) || (opcode == 0xc2) ||
((opcode & 0xfe) == 0xca) || ((opcode & 0xfc) == 0xcc) || ((opcode & 0xfc) == 0xe8) ||
((opcode == 0xff) && (((fetchdat & 0x38) >= 0x10) && ((fetchdat & 0x38) < 0x30)))) ||
((op_table == x86_dynarec_opcodes_0f) && ((opcode & 0xf0) == 0x80))))
{
/*Opcode is likely to cause block to exit, update cycle count*/
if (codegen_block_cycles)

View File

@@ -1,13 +1,17 @@
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_flags.h"
#include "x86_ops.h"
#include "x87.h"
#include "../mem.h"
#include "386_common.h"

View File

@@ -8,15 +8,20 @@
*
* CPU type handler.
*
* Version: @(#)cpu.c 1.0.1 2017/06/03
* Version: @(#)cpu.c 1.0.4 2017/10/14
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 leilei.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "cpu.h"
#include "../device.h"
@@ -25,11 +30,14 @@
#include "x86_ops.h"
#include "../mem.h"
#include "../pci.h"
#ifdef USE_DYNAREC
#include "codegen.h"
#endif
int isa_cycles;
static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6;
#ifdef USE_DYNAREC
OpFn *x86_dynarec_opcodes;
OpFn *x86_dynarec_opcodes_0f;
OpFn *x86_dynarec_opcodes_d8_a16;
@@ -50,6 +58,7 @@ OpFn *x86_dynarec_opcodes_df_a16;
OpFn *x86_dynarec_opcodes_df_a32;
OpFn *x86_dynarec_opcodes_REPE;
OpFn *x86_dynarec_opcodes_REPNE;
#endif
OpFn *x86_opcodes;
OpFn *x86_opcodes_0f;
@@ -110,7 +119,7 @@ int cpu_waitstates;
int cpu_cache_int_enabled, cpu_cache_ext_enabled;
int cpu_pci_speed;
int is286, is386;
int is286, is386, is486;
int israpidcad, is_pentium;
uint64_t tsc = 0;
@@ -255,6 +264,13 @@ CPU cpus_ibmat[] =
{"", -1, 0, 0, 0, 0}
};
CPU cpus_ibmxt286[] =
{
/*286*/
{"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_ps1_m2011[] =
{
/*286*/
@@ -676,12 +692,19 @@ void cpu_set()
pclog("hasfpu - %i\n",hasfpu);
pclog("is486 - %i %i\n",is486,cpu_s->cpu_type);
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f);
#else
x86_setopcodes(ops_386, ops_386_0f);
#endif
x86_opcodes_REPE = ops_REPE;
x86_opcodes_REPNE = ops_REPNE;
#ifdef USE_DYNAREC
x86_dynarec_opcodes_REPE = dynarec_ops_REPE;
x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE;
#endif
#ifdef USE_DYNAREC
if (hasfpu)
{
x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16;
@@ -721,6 +744,7 @@ void cpu_set()
x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32;
}
codegen_timing_set(&codegen_timing_486);
#endif
if (hasfpu)
{
@@ -773,9 +797,14 @@ void cpu_set()
break;
case CPU_286:
#ifdef USE_DYNAREC
x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f);
#else
x86_setopcodes(ops_286, ops_286_0f);
#endif
if (enable_external_fpu)
{
#ifdef USE_DYNAREC
x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16;
x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32;
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16;
@@ -790,6 +819,7 @@ void cpu_set()
x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32;
#endif
x86_opcodes_d9_a16 = ops_fpu_287_d9_a16;
x86_opcodes_d9_a32 = ops_fpu_287_d9_a32;
x86_opcodes_da_a16 = ops_fpu_287_da_a16;
@@ -929,7 +959,11 @@ void cpu_set()
break;
case CPU_486SLC:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 3; /*register dest - memory src*/
timing_mr = 5; /*memory dest - register src*/
@@ -963,7 +997,11 @@ void cpu_set()
break;
case CPU_486DLC:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 3; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1002,7 +1040,11 @@ void cpu_set()
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME;
case CPU_i486SX:
case CPU_i486DX:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1037,7 +1079,11 @@ void cpu_set()
case CPU_Am486SX:
case CPU_Am486DX:
/*AMD timing identical to Intel*/
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1071,7 +1117,11 @@ void cpu_set()
case CPU_Cx486S:
case CPU_Cx486DX:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 3; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1104,7 +1154,11 @@ void cpu_set()
break;
case CPU_Cx5x86:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
@@ -1138,7 +1192,11 @@ void cpu_set()
break;
case CPU_WINCHIP:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_winchip_0f, dynarec_ops_386, dynarec_ops_winchip_0f);
#else
x86_setopcodes(ops_386, ops_winchip_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
@@ -1172,13 +1230,19 @@ void cpu_set()
timing_jmp_rm = 5;
timing_jmp_pm = 7;
timing_jmp_pm_gate = 17;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_winchip);
#endif
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
break;
case CPU_PENTIUM:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
#else
x86_setopcodes(ops_386, ops_pentium_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1215,11 +1279,17 @@ void cpu_set()
cpu_hasCR4 = 1;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_pentium);
#endif
break;
case CPU_PENTIUMMMX:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f);
#else
x86_setopcodes(ops_386, ops_pentiummmx_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1256,11 +1326,17 @@ void cpu_set()
cpu_hasCR4 = 1;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_pentium);
#endif
break;
case CPU_Cx6x86:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
#else
x86_setopcodes(ops_386, ops_pentium_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
@@ -1295,12 +1371,18 @@ void cpu_set()
cpu_hasMMX = 0;
cpu_hasMSR = 0;
cpu_hasCR4 = 0;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_686);
#endif
CPUID = 0; /*Disabled on powerup by default*/
break;
case CPU_Cx6x86L:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
#else
x86_setopcodes(ops_386, ops_pentium_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
@@ -1335,13 +1417,19 @@ void cpu_set()
cpu_hasMMX = 0;
cpu_hasMSR = 0;
cpu_hasCR4 = 0;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_686);
#endif
ccr4 = 0x80;
break;
case CPU_CxGX1:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
#else
x86_setopcodes(ops_386, ops_pentium_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
@@ -1359,11 +1447,14 @@ void cpu_set()
cpu_hasMSR = 1;
cpu_hasCR4 = 1;
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_686);
#endif
break;
case CPU_Cx6x86MX:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f);
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
@@ -1371,6 +1462,9 @@ void cpu_set()
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
#else
x86_setopcodes(ops_386, ops_c6x86mx_0f);
#endif
x86_opcodes_da_a16 = ops_fpu_686_da_a16;
x86_opcodes_da_a32 = ops_fpu_686_da_a32;
x86_opcodes_db_a16 = ops_fpu_686_db_a16;
@@ -1412,13 +1506,19 @@ void cpu_set()
cpu_hasMSR = 1;
cpu_hasCR4 = 1;
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_686);
#endif
ccr4 = 0x80;
break;
case CPU_K5:
case CPU_5K86:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f);
#else
x86_setopcodes(ops_386, ops_k6_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1438,7 +1538,11 @@ void cpu_set()
break;
case CPU_K6:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f);
#else
x86_setopcodes(ops_386, ops_k6_0f);
#endif
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@@ -1456,10 +1560,13 @@ void cpu_set()
cpu_hasCR4 = 1;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_pentium);
#endif
break;
case CPU_PENTIUMPRO:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f);
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
@@ -1467,6 +1574,9 @@ void cpu_set()
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
#else
x86_setopcodes(ops_386, ops_pentiumpro_0f);
#endif
x86_opcodes_da_a16 = ops_fpu_686_da_a16;
x86_opcodes_da_a32 = ops_fpu_686_da_a32;
x86_opcodes_db_a16 = ops_fpu_686_db_a16;
@@ -1490,11 +1600,14 @@ void cpu_set()
cpu_hasCR4 = 1;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_686);
#endif
break;
#if 0
case CPU_PENTIUM2:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f);
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
@@ -1502,6 +1615,9 @@ void cpu_set()
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
#else
x86_setopcodes(ops_386, ops_pentium2_0f);
#endif
x86_opcodes_da_a16 = ops_fpu_686_da_a16;
x86_opcodes_da_a32 = ops_fpu_686_da_a32;
x86_opcodes_db_a16 = ops_fpu_686_db_a16;
@@ -1525,11 +1641,14 @@ void cpu_set()
cpu_hasCR4 = 1;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_686);
#endif
break;
#endif
case CPU_PENTIUM2D:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentium2d_0f, dynarec_ops_386, dynarec_ops_pentium2d_0f);
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
@@ -1537,6 +1656,9 @@ void cpu_set()
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
#else
x86_setopcodes(ops_386, ops_pentium2d_0f);
#endif
x86_opcodes_da_a16 = ops_fpu_686_da_a16;
x86_opcodes_da_a32 = ops_fpu_686_da_a32;
x86_opcodes_db_a16 = ops_fpu_686_db_a16;
@@ -1560,7 +1682,9 @@ void cpu_set()
cpu_hasCR4 = 1;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE | CR4_OSFXSR;
#ifdef USE_DYNAREC
codegen_timing_set(&codegen_timing_686);
#endif
break;
default:
@@ -2452,6 +2576,7 @@ uint8_t cyrix_read(uint16_t addr, void *priv)
return 0xff;
}
#ifdef USE_DYNAREC
void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn *dynarec_opcodes_0f)
{
x86_opcodes = opcodes;
@@ -2459,6 +2584,13 @@ void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn
x86_dynarec_opcodes = dynarec_opcodes;
x86_dynarec_opcodes_0f = dynarec_opcodes_0f;
}
#else
void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f)
{
x86_opcodes = opcodes;
x86_opcodes_0f = opcodes_0f;
}
#endif
void cpu_update_waitstates()
{

View File

@@ -8,18 +8,18 @@
*
* CPU type handler.
*
* Version: @(#)cpu.h 1.0.0 2017/05/30
* Version: @(#)cpu.h 1.0.2 2017/10/14
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 leilei.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#ifndef _CPU_H_
#define _CPU_H_
#ifndef EMU_CPU_H
# define EMU_CPU_H
extern int cpu, cpu_manufacturer;
@@ -130,6 +130,7 @@ extern CPU cpus_pcjr[];
extern CPU cpus_europc[];
extern CPU cpus_pc1512[];
extern CPU cpus_ibmat[];
extern CPU cpus_ibmxt286[];
extern CPU cpus_ps1_m2011[];
extern CPU cpus_ps2_m30_286[];
extern CPU cpus_acer[];
@@ -197,4 +198,5 @@ typedef struct
extern msr_t msr;
#endif
#endif /*EMU_CPU_H*/

View File

@@ -17,7 +17,7 @@ uint8_t opcode;
int noint;
uint16_t lastcs,lastpc;
int timetolive,keyboardtimer;
extern int timetolive,keyboardtimer;
#define setznp168 setznp16

View File

@@ -4,8 +4,13 @@
#ifndef _X86_OPS_H
#define _X86_OPS_H
#define UNUSED(x) (void)(x)
typedef int (*OpFn)(uint32_t fetchdat);
#ifdef USE_DYNAREC
void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn *dynarec_opcodes_0f);
extern OpFn *x86_dynarec_opcodes;
@@ -91,6 +96,9 @@ extern OpFn dynarec_ops_fpu_686_df_a32[256];
extern OpFn dynarec_ops_REPE[1024];
extern OpFn dynarec_ops_REPNE[1024];
#else
void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f);
#endif
extern OpFn *x86_opcodes;
extern OpFn *x86_opcodes_0f;

View File

@@ -99,7 +99,9 @@ static int opSAHF(uint32_t fetchdat)
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
#if 0
codegen_flags_changed = 0;
#endif
return 0;
}
@@ -180,7 +182,9 @@ static int opPOPF_286(uint32_t fetchdat)
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
#if 0
codegen_flags_changed = 0;
#endif
return 0;
}
@@ -238,7 +242,9 @@ static int opPOPF(uint32_t fetchdat)
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
#if 0
codegen_flags_changed = 0;
#endif
return 0;
}
@@ -270,7 +276,9 @@ static int opPOPFD(uint32_t fetchdat)
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0);
#if 0
codegen_flags_changed = 0;
#endif
return 0;
}

View File

@@ -5,6 +5,8 @@ static int opIN_AL_imm(uint32_t fetchdat)
AL = inb(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
static int opIN_AX_imm(uint32_t fetchdat)
@@ -15,6 +17,8 @@ static int opIN_AX_imm(uint32_t fetchdat)
AX = inw(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
static int opIN_EAX_imm(uint32_t fetchdat)
@@ -27,6 +31,8 @@ static int opIN_EAX_imm(uint32_t fetchdat)
EAX = inl(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 0,1,0,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
@@ -39,6 +45,8 @@ static int opOUT_AL_imm(uint32_t fetchdat)
PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0);
if (port == 0x64)
return x86_was_reset;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
static int opOUT_AX_imm(uint32_t fetchdat)
@@ -49,6 +57,8 @@ static int opOUT_AX_imm(uint32_t fetchdat)
outw(port, AX);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
static int opOUT_EAX_imm(uint32_t fetchdat)
@@ -61,6 +71,8 @@ static int opOUT_EAX_imm(uint32_t fetchdat)
outl(port, EAX);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
@@ -70,6 +82,8 @@ static int opIN_AL_DX(uint32_t fetchdat)
AL = inb(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
static int opIN_AX_DX(uint32_t fetchdat)
@@ -79,6 +93,8 @@ static int opIN_AX_DX(uint32_t fetchdat)
AX = inw(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
static int opIN_EAX_DX(uint32_t fetchdat)
@@ -90,6 +106,8 @@ static int opIN_EAX_DX(uint32_t fetchdat)
EAX = inl(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
@@ -99,6 +117,8 @@ static int opOUT_AL_DX(uint32_t fetchdat)
outb(DX, AL);
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return x86_was_reset;
}
static int opOUT_AX_DX(uint32_t fetchdat)
@@ -108,6 +128,8 @@ static int opOUT_AX_DX(uint32_t fetchdat)
outw(DX, AX);
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}
static int opOUT_EAX_DX(uint32_t fetchdat)
@@ -118,5 +140,7 @@ static int opOUT_EAX_DX(uint32_t fetchdat)
check_io_perm(DX + 3);
outl(DX, EAX);
PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0);
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
}

View File

@@ -8,17 +8,20 @@
*
* x86 CPU segment emulation.
*
* Version: @(#)x86seg.c 1.0.0 2017/05/30
* Version: @(#)x86seg.c 1.0.3 2017/10/12
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "../nvr.h"
@@ -27,6 +30,7 @@
#include "386_common.h"
#include "cpu.h"
/*Controls whether the accessed bit in a descriptor is set when CS is loaded.*/
#define CS_ACCESSED
@@ -36,7 +40,6 @@
int stimes = 0;
int dtimes = 0;
int btimes = 0;
int is486=1;
uint32_t abrt_error;
int cgate16,cgate32;
@@ -61,7 +64,7 @@ void x86abort(const char *format, ...)
vprintf(format, ap);
va_end(ap);
fflush(stdout);
savenvr();
nvr_save();
dumpregs(1);
fflush(stdout);
exit(-1);
@@ -402,10 +405,12 @@ void loadseg(uint16_t seg, x86seg *s)
}
#endif
s->checked = 0;
#ifdef USE_DYNAREC
if (s == &_ds)
codegen_flat_ds = 0;
if (s == &_ss)
codegen_flat_ss = 0;
#endif
}
else
{
@@ -415,10 +420,12 @@ void loadseg(uint16_t seg, x86seg *s)
if (s == &_ss)
stack32 = 0;
s->checked = 1;
#ifdef USE_DYNAREC
if (s == &_ds)
codegen_flat_ds = 0;
if (s == &_ss)
codegen_flat_ss = 0;
#endif
}
if (s == &_ds)

View File

@@ -8,10 +8,11 @@
*
* x86 CPU segment emulation.
*
* Version: @(#)x86seg.h 1.0.0 2017/05/30
* Version: @(#)x86seg.h 1.0.1 2017/10/12
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2017 Miran Grca.
*/
void do_seg_load(x86seg *s, uint16_t *segdat);
extern void do_seg_load(x86seg *s, uint16_t *segdat);

View File

@@ -1,3 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define fplog 0
#include <math.h>
#include "../ibm.h"

View File

@@ -9,13 +9,17 @@
* Implementation of the generic device interface to handle
* all devices attached to the emulator.
*
* Version: @(#)device.c 1.0.3 2017/09/02
* Version: @(#)device.c 1.0.4 2017/10/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2016 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "cpu/cpu.h"
#include "config.h"
@@ -27,336 +31,387 @@
#define DEVICE_MAX 256 /* max # of devices */
static void *device_priv[DEVICE_MAX];
static device_t *devices[DEVICE_MAX];
static device_t *current_device;
static device_t *devices[DEVICE_MAX];
static void *device_priv[DEVICE_MAX];
static device_t *device_current;
void device_init(void)
void
device_init(void)
{
memset(devices, 0x00, sizeof(devices));
memset(devices, 0x00, sizeof(devices));
}
void device_add(device_t *d)
void
device_add(device_t *d)
{
int c = 0;
void *priv = NULL;
while (devices[c] != NULL && c < 256)
void *priv = NULL;
int c = 0;
while (devices[c] != NULL && c < 256)
c++;
if (c >= DEVICE_MAX)
fatal("device_add: too many devices\n");
if (c >= DEVICE_MAX)
fatal("device_add : too many devices\n");
current_device = d;
if (d->init != NULL)
{
priv = d->init();
if (priv == NULL)
fatal("device_add : device init failed\n");
}
devices[c] = d;
device_priv[c] = priv;
device_current = d;
if (d->init != NULL) {
priv = d->init(d);
if (priv == NULL)
fatal("device_add: device init failed\n");
}
devices[c] = d;
device_priv[c] = priv;
}
void device_close_all(void)
void
device_close_all(void)
{
int c;
int c;
for (c=0; c<DEVICE_MAX; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->close != NULL)
devices[c]->close(device_priv[c]);
devices[c] = device_priv[c] = NULL;
}
}
for (c=0; c<DEVICE_MAX; c++) {
if (devices[c] != NULL) {
if (devices[c]->close != NULL)
devices[c]->close(device_priv[c]);
devices[c] = device_priv[c] = NULL;
}
}
}
void *device_get_priv(device_t *d)
void
device_reset_all(void)
{
int c;
int c;
for (c=0; c<DEVICE_MAX; c++)
{
if (devices[c] != NULL)
{
if (devices[c] == d)
return device_priv[c];
}
}
return NULL;
for (c=0; c<DEVICE_MAX; c++) {
if (devices[c] != NULL) {
if (devices[c]->reset != NULL)
devices[c]->reset(device_priv[c]);
}
}
}
int device_available(device_t *d)
void *
device_get_priv(device_t *d)
{
int c;
for (c=0; c<DEVICE_MAX; c++) {
if (devices[c] != NULL) {
if (devices[c] == d)
return(device_priv[c]);
}
}
return(NULL);
}
int
device_available(device_t *d)
{
#ifdef RELEASE_BUILD
if (d->flags & DEVICE_NOT_WORKING)
return 0;
if (d->flags & DEVICE_NOT_WORKING) return(0);
#endif
if (d->available)
return d->available();
return 1;
if (d->available != NULL)
return(d->available());
return(1);
}
void device_speed_changed(void)
void
device_speed_changed(void)
{
int c;
for (c=0; c<DEVICE_MAX; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->speed_changed != NULL)
{
devices[c]->speed_changed(device_priv[c]);
}
}
}
sound_speed_changed();
int c;
for (c=0; c<DEVICE_MAX; c++) {
if (devices[c] != NULL) {
if (devices[c]->speed_changed != NULL)
devices[c]->speed_changed(device_priv[c]);
}
}
sound_speed_changed();
}
void device_force_redraw(void)
void
device_force_redraw(void)
{
int c;
for (c=0; c<DEVICE_MAX; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->force_redraw != NULL)
{
int c;
for (c=0; c<DEVICE_MAX; c++) {
if (devices[c] != NULL) {
if (devices[c]->force_redraw != NULL)
devices[c]->force_redraw(device_priv[c]);
}
}
}
}
}
}
char *device_add_status_info(char *s, int max_len)
void
device_add_status_info(char *s, int max_len)
{
int c;
for (c=0; c<DEVICE_MAX; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->add_status_info != NULL)
devices[c]->add_status_info(s, max_len, device_priv[c]);
}
}
int c;
return NULL;
for (c=0; c<DEVICE_MAX; c++) {
if (devices[c] != NULL) {
if (devices[c]->add_status_info != NULL)
devices[c]->add_status_info(s, max_len, device_priv[c]);
}
}
}
int device_get_config_int(char *s)
char *
device_get_config_string(char *s)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_int(current_device->name, s, config->default_int);
device_config_t *c = device_current->config;
config++;
}
return 0;
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_string(device_current->name, s, c->default_string));
c++;
}
return(NULL);
}
int device_get_config_int_ex(char *s, int default_int)
int
device_get_config_int(char *s)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_int(current_device->name, s, default_int);
device_config_t *c = device_current->config;
config++;
}
return default_int;
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_int(device_current->name, s, c->default_int));
c++;
}
return(0);
}
int device_get_config_hex16(char *s)
int
device_get_config_int_ex(char *s, int default_int)
{
device_config_t *config = current_device->config;
device_config_t *c = device_current->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_hex16(current_device->name, s, config->default_int);
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_int(device_current->name, s, default_int));
config++;
}
return 0;
c++;
}
return(default_int);
}
int device_get_config_hex20(char *s)
int
device_get_config_hex16(char *s)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_hex20(current_device->name, s, config->default_int);
device_config_t *c = device_current->config;
config++;
}
return 0;
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_hex16(device_current->name, s, c->default_int));
c++;
}
return(0);
}
int device_get_config_mac(char *s, int default_int)
int
device_get_config_hex20(char *s)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_mac(current_device->name, s, default_int);
device_config_t *c = device_current->config;
config++;
}
return default_int;
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_hex20(device_current->name, s, c->default_int));
c++;
}
return(0);
}
void device_set_config_int(char *s, int val)
int
device_get_config_mac(char *s, int default_int)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
{
config_set_int(current_device->name, s, val);
return;
}
device_config_t *c = device_current->config;
config++;
}
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_mac(device_current->name, s, default_int));
c++;
}
return(default_int);
}
void device_set_config_hex16(char *s, int val)
void
device_set_config_int(char *s, int val)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
{
config_set_hex16(current_device->name, s, val);
return;
}
device_config_t *c = device_current->config;
config++;
}
while (c && c->type != -1) {
if (! strcmp(s, c->name)) {
config_set_int(device_current->name, s, val);
break;
}
c++;
}
}
void device_set_config_hex20(char *s, int val)
void
device_set_config_hex16(char *s, int val)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
{
config_set_hex20(current_device->name, s, val);
return;
}
device_config_t *c = device_current->config;
config++;
}
while (c && c->type != -1) {
if (! strcmp(s, c->name)) {
config_set_hex16(device_current->name, s, val);
break;
}
c++;
}
}
void device_set_config_mac(char *s, int val)
void
device_set_config_hex20(char *s, int val)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
{
config_set_mac(current_device->name, s, val);
return;
}
device_config_t *c = device_current->config;
config++;
}
while (c && c->type != -1) {
if (! strcmp(s, c->name)) {
config_set_hex20(device_current->name, s, val);
break;
}
c++;
}
}
char *device_get_config_string(char *s)
void
device_set_config_mac(char *s, int val)
{
device_config_t *config = current_device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_string(current_device->name, s, config->default_string);
device_config_t *c = device_current->config;
config++;
}
return NULL;
while (c && c->type != -1) {
if (! strcmp(s, c->name)) {
config_set_mac(device_current->name, s, val);
break;
}
c++;
}
}
int machine_get_config_int(char *s)
int
device_is_valid(device_t *device, int machine_flags)
{
device_t *device = machine_getdevice(machine);
device_config_t *config;
if (!device)
{
return 1;
}
if (!device)
return 0;
if ((device->flags & DEVICE_AT) && !(machine_flags & MACHINE_AT)) {
return 0;
}
config = device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_int(device->name, s, config->default_int);
if ((device->flags & DEVICE_CBUS) && !(machine_flags & MACHINE_CBUS)) {
return 0;
}
config++;
}
return 0;
if ((device->flags & DEVICE_ISA) && !(machine_flags & MACHINE_ISA)) {
return 0;
}
if ((device->flags & DEVICE_MCA) && !(machine_flags & MACHINE_MCA)) {
return 0;
}
if ((device->flags & DEVICE_EISA) && !(machine_flags & MACHINE_EISA)) {
return 0;
}
if ((device->flags & DEVICE_VLB) && !(machine_flags & MACHINE_VLB)) {
return 0;
}
if ((device->flags & DEVICE_PCI) && !(machine_flags & MACHINE_PCI)) {
return 0;
}
if ((device->flags & DEVICE_PS2) && !(machine_flags & MACHINE_PS2_HDD)) {
return 0;
}
if ((device->flags & DEVICE_AGP) && !(machine_flags & MACHINE_AGP)) {
return 0;
}
return 1;
}
char *machine_get_config_string(char *s)
int
machine_get_config_int(char *s)
{
device_t *device = machine_getdevice(machine);
device_config_t *config;
if (!device)
return 0;
device_t *d = machine_getdevice(machine);
device_config_t *c;
config = device->config;
while (config && config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_string(device->name, s, config->default_string);
if (d == NULL) return(0);
config++;
}
return NULL;
c = d->config;
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_int(d->name, s, c->default_int));
c++;
}
return(0);
}
char *
machine_get_config_string(char *s)
{
device_t *d = machine_getdevice(machine);
device_config_t *c;
if (d == NULL) return(0);
c = d->config;
while (c && c->type != -1) {
if (! strcmp(s, c->name))
return(config_get_string(d->name, s, c->default_string));
c++;
}
return(NULL);
}

View File

@@ -9,12 +9,14 @@
* Implementation of the generic device interface to handle
* all devices attached to the emulator.
*
* Version: @(#)device.h 1.0.2 2017/08/23
* Version: @(#)device.h 1.0.3 2017/10/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2008-2016 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#ifndef EMU_DEVICE_H
# define EMU_DEVICE_H
@@ -32,69 +34,73 @@
#define CONFIG_MAC 9
enum
{
DEVICE_NOT_WORKING = 1, /*Device does not currently work correctly and will be disabled in a release build*/
DEVICE_AT = 2, /*Device requires an AT-compatible system*/
DEVICE_PS2 = 4, /*Device requires a PS/1 or PS/2 system*/
DEVICE_MCA = 0x20, /*Device requires the MCA bus*/
DEVICE_PCI = 0x40 /*Device requires the PCI bus*/
enum {
DEVICE_NOT_WORKING = 1, /* does not currently work correctly and will be disabled in a release build*/
DEVICE_AT = 2, /* requires an AT-compatible system */
DEVICE_PS2 = 4, /* requires a PS/1 or PS/2 system */
DEVICE_ISA = 8, /* requires the ISA bus */
DEVICE_CBUS = 0x10, /* requires the C-BUS bus */
DEVICE_MCA = 0x20, /* requires the MCA bus */
DEVICE_EISA = 0x40, /* requires the EISA bus */
DEVICE_VLB = 0x80, /* requires the PCI bus */
DEVICE_PCI = 0x100, /* requires the VLB bus */
DEVICE_AGP = 0x200 /* requires the AGP bus */
};
typedef struct device_config_selection_t
{
char description[256];
int value;
typedef struct {
char description[256];
int value;
} device_config_selection_t;
typedef struct device_config_file_filter_t
{
char description[256];
char extensions[25][25];
typedef struct {
char description[256];
char extensions[25][25];
} device_config_file_filter_t;
typedef struct device_config_spinner_t
{
int min;
int max;
int step;
typedef struct {
int min;
int max;
int step;
} device_config_spinner_t;
typedef struct device_config_t
{
char name[256];
char description[256];
int type;
char default_string[256];
int default_int;
device_config_selection_t selection[16];
device_config_file_filter_t file_filter[16];
device_config_spinner_t spinner;
typedef struct {
char name[256];
char description[256];
int type;
char default_string[256];
int default_int;
device_config_selection_t selection[16];
device_config_file_filter_t file_filter[16];
device_config_spinner_t spinner;
} device_config_t;
typedef struct device_t
{
char name[50];
uint32_t flags;
void *(*init)();
void (*close)(void *p);
int (*available)();
void (*speed_changed)(void *p);
void (*force_redraw)(void *p);
void (*add_status_info)(char *s, int max_len, void *p);
device_config_t *config;
typedef struct _device_ {
char name[50];
uint32_t flags; /* system flags */
uint32_t local; /* flags local to device */
void *(*init)(struct _device_ *);
void (*close)(void *p);
void (*reset)(void *p);
int (*available)(void);
void (*speed_changed)(void *p);
void (*force_redraw)(void *p);
void (*add_status_info)(char *s, int max_len, void *p);
device_config_t *config;
} device_t;
extern void device_init(void);
extern void device_add(device_t *d);
extern void device_close_all(void);
extern void device_reset_all(void);
extern void *device_get_priv(device_t *d);
extern int device_available(device_t *d);
extern void device_speed_changed(void);
extern void device_force_redraw(void);
extern char *device_add_status_info(char *s, int max_len);
extern void device_add_status_info(char *s, int max_len);
extern int device_get_config_int(char *name);
extern int device_get_config_int_ex(char *s, int default_int);
@@ -106,6 +112,7 @@ extern void device_set_config_hex16(char *s, int val);
extern void device_set_config_hex20(char *s, int val);
extern void device_set_config_mac(char *s, int val);
extern char *device_get_config_string(char *name);
extern int device_is_valid(device_t *device, int machine_flags);
extern int machine_get_config_int(char *s);
extern char *machine_get_config_string(char *s);

193
src/disk/hdc.c Normal file
View File

@@ -0,0 +1,193 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Common code to handle all sorts of disk controllers.
*
* Version: @(#)hdc.c 1.0.3 2017/10/04
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../cpu/cpu.h"
#include "../device.h"
#include "../machine/machine.h"
#include "hdc.h"
char hdc_name[16]; /* configured HDC name */
int hdc_current;
static void *
null_init(device_t *info)
{
return(NULL);
}
static void
null_close(void *priv)
{
}
static device_t null_device = {
"Null HDC", 0, 0,
null_init, null_close, NULL,
NULL, NULL, NULL, NULL, NULL
};
static void *
inthdc_init(device_t *info)
{
return(NULL);
}
static void
inthdc_close(void *priv)
{
}
static device_t inthdc_device = {
"Internal Controller", 0, 0,
inthdc_init, inthdc_close, NULL,
NULL, NULL, NULL, NULL, NULL
};
static struct {
char name[50];
char internal_name[16];
device_t *device;
int is_mfm;
} controllers[] = {
{ "None", "none",
&null_device, 0 },
{ "Internal Controller", "internal",
&inthdc_device, 0 },
{ "[ISA] [MFM] IBM PC Fixed Disk Adapter", "mfm_xebec",
&mfm_xt_xebec_device, 1 },
{ "[ISA] [MFM] DTC-5150X Fixed Disk Adapter", "mfm_dtc5150x",
&mfm_xt_dtc5150x_device, 1 },
{ "[ISA] [MFM] IBM PC/AT Fixed Disk Adapter", "mfm_at",
&mfm_at_wd1003_device, 1 },
{ "[ISA] [ESDI] PC/AT ESDI Fixed Disk Adapter", "esdi_wd1007vse1",
&esdi_at_wd1007vse1_device, 0 },
#if 0
{ "[ISA] [IDE] PC/AT IDE Adapter", "ide_isa",
&ide_isa_device, 0 },
{ "[PCI] [IDE] PCI IDE Adapter", "ide_pci",
&ide_pci_device, 0 },
#endif
{ "[ISA] [IDE] PC/XT XTIDE", "xtide",
&xtide_device , 0 },
{ "[ISA] [IDE] PC/AT XTIDE", "xtide_at",
&xtide_at_device, 0 },
{ "[ISA] [IDE] PS/2 XTIDE (Acculogic)", "xtide_ps2",
&xtide_ps2_device, 0 },
{ "[ISA] [IDE] PS/2 AT XTIDE (1.1.5)", "xtide_at_ps2",
&xtide_at_ps2_device, 0 },
{ "[MCA] [ESDI] IBM PS/2 ESDI Fixed Disk Adapter","esdi_mca",
&esdi_ps2_device, 1 },
{ "", "", NULL, 0 }
};
/* Initialize the 'hdc_current' value based on configured HDC name. */
void
hdc_init(char *name)
{
int c;
pclog("HDC: initializing..\n");
for (c=0; controllers[c].device; c++) {
if (! strcmp(name, controllers[c].internal_name)) {
hdc_current = c;
break;
}
}
}
/* Reset the HDC, whichever one that is. */
void
hdc_reset(void)
{
pclog("HDC: reset(current=%d, internal=%d)\n",
hdc_current, (machines[machine].flags & MACHINE_HAS_HDC)?1:0);
/* If we have a valid controller, add its device. */
if (hdc_current > 1)
device_add(controllers[hdc_current].device);
}
char *
hdc_get_name(int hdc)
{
return(controllers[hdc].name);
}
char *
hdc_get_internal_name(int hdc)
{
return(controllers[hdc].internal_name);
}
device_t *
hdc_get_device(int hdc)
{
return(controllers[hdc].device);
}
int
hdc_get_flags(int hdc)
{
return(controllers[hdc].device->flags);
}
int
hdc_available(int hdc)
{
return(device_available(controllers[hdc].device));
}
int
hdc_current_is_mfm(void)
{
return(controllers[hdc_current].is_mfm);
}

58
src/disk/hdc.h Normal file
View File

@@ -0,0 +1,58 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the common disk controller handler.
*
* Version: @(#)hdc.h 1.0.3 2017/10/01
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#ifndef EMU_HDC_H
# define EMU_HDC_H
#define MFM_NUM 2 /* 2 drives per controller supported */
#define ESDI_NUM 2 /* 2 drives per controller supported */
#define XTIDE_NUM 2 /* 2 drives per controller supported */
#define IDE_NUM 8
#define SCSI_NUM 16 /* theoretically the controller can have at
* least 7 devices, with each device being
* able to support 8 units, but hey... */
extern char hdc_name[16];
extern int hdc_current;
extern device_t mfm_xt_xebec_device; /* mfm_xt_xebec */
extern device_t mfm_xt_dtc5150x_device; /* mfm_xt_dtc */
extern device_t mfm_at_wd1003_device; /* mfm_at_wd1003 */
extern device_t esdi_at_wd1007vse1_device; /* esdi_at */
extern device_t esdi_ps2_device; /* esdi_mca */
extern device_t xtide_device; /* xtide_xt */
extern device_t xtide_at_device; /* xtide_at */
extern device_t xtide_ps2_device; /* xtide_ps2 */
extern device_t xtide_at_ps2_device; /* xtide_at_ps2 */
extern void hdc_init(char *name);
extern void hdc_reset(void);
extern char *hdc_get_name(int hdc);
extern char *hdc_get_internal_name(int hdc);
extern device_t *hdc_get_device(int hdc);
extern int hdc_get_flags(int hdc);
extern int hdc_available(int hdc);
extern int hdc_current_is_mfm(void);
#endif /*EMU_HDC_H*/

853
src/disk/hdc_esdi_at.c Normal file
View File

@@ -0,0 +1,853 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Driver for the ESDI controller (WD1007-vse1) for PC/AT.
*
* Version: @(#)hdc_esdi_at.c 1.0.4 2017/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "../ui.h"
#include "hdc.h"
#include "hdd.h"
#define HDC_TIME (TIMER_USEC*10LL)
#define BIOS_FILE L"roms/hdd/esdi_at/62-000279-061.bin"
#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 {
int cfg_spt;
int cfg_hpc;
int current_cylinder;
int real_spt;
int real_hpc;
int real_tracks;
int present;
int hdd_num;
} drive_t;
typedef struct {
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;
int64_t callback;
drive_t drives[2];
rom_t bios_rom;
} esdi_t;
static inline void
irq_raise(esdi_t *esdi)
{
if (! (esdi->fdisk&2))
picint(1<<14);
esdi->irqstat=1;
}
static inline void
irq_lower(esdi_t *esdi)
{
picintc(1<<14);
}
static void
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. */
static int
get_sector(esdi_t *esdi, off64_t *addr)
{
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->real_spt && drive->cfg_hpc==drive->real_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->real_spt - 1);
h = (*addr / (drive->real_spt - 1)) % drive->real_hpc;
c = (*addr / (drive->real_spt - 1)) / drive->real_hpc;
*addr = ((((off64_t)c * drive->real_hpc) + h) * drive->real_spt) + s;
}
return(0);
}
/* Move to the next sector using CHS addressing. */
static void
next_sector(esdi_t *esdi)
{
drive_t *drive = &esdi->drives[esdi->drive_sel];
esdi->sector++;
if (esdi->sector == (drive->cfg_spt + 1)) {
esdi->sector = 1;
if (++esdi->head == drive->cfg_hpc) {
esdi->head = 0;
esdi->cylinder++;
if (drive->current_cylinder < drive->real_tracks)
drive->current_cylinder++;
}
}
}
static void
esdi_writew(uint16_t port, uint16_t val, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
esdi->buffer[esdi->pos >> 1] = val;
esdi->pos += 2;
if (esdi->pos >= 512) {
esdi->pos = 0;
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 6LL*HDC_TIME;
timer_update_outstanding();
}
}
static void
esdi_write(uint16_t port, uint8_t val, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
switch (port) {
case 0x1F0: /* Data */
esdi_writew(port, val | (val << 8), priv);
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].present)
esdi->status = 0;
else
esdi->status = STAT_READY | STAT_DSC;
return;
case 0x1F7: /* Command register */
irq_lower(esdi);
esdi->command = val;
esdi->error = 0;
switch (val & 0xf0) {
case CMD_RESTORE:
esdi->command &= ~0x0f; /*Mask off step rate*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
case CMD_SEEK:
esdi->command &= ~0x0f; /*Mask off step rate*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
default:
switch (val) {
case CMD_NOP:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
case CMD_READ:
case CMD_READ+1:
case CMD_READ+2:
case CMD_READ+3:
esdi->command &= ~3;
if (val & 2)
fatal("Read with ECC\n");
case 0xa0:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
case CMD_WRITE:
case CMD_WRITE+1:
case CMD_WRITE+2:
case CMD_WRITE+3:
esdi->command &= ~3;
if (val & 2)
fatal("Write with ECC\n");
esdi->status = STAT_DRQ | STAT_DSC;
esdi->pos=0;
break;
case CMD_VERIFY:
case CMD_VERIFY+1:
esdi->command &= ~1;
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
case CMD_FORMAT:
esdi->status = STAT_DRQ;
esdi->pos=0;
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 30LL*HDC_TIME;
timer_update_outstanding();
break;
case CMD_DIAGNOSE: /* Execute Drive Diagnostics */
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
case 0xe0: /*???*/
case CMD_READ_PARAMETERS:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
default:
pclog("Bad esdi command %02X\n", val);
case 0xe8: /*???*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200LL*HDC_TIME;
timer_update_outstanding();
break;
}
}
break;
case 0x3F6: /* Device control */
if ((esdi->fdisk & 4) && !(val & 4)) {
timer_process();
esdi->callback = 500LL*HDC_TIME;
timer_update_outstanding();
esdi->reset = 1;
esdi->status = STAT_BUSY;
}
if (val & 4) {
/*Drive held in reset*/
timer_process();
esdi->callback = 0LL;
timer_update_outstanding();
esdi->status = STAT_BUSY;
}
esdi->fdisk = val;
irq_update(esdi);
}
}
static uint16_t
esdi_readw(uint16_t port, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
uint16_t temp;
temp = esdi->buffer[esdi->pos >> 1];
esdi->pos += 2;
if (esdi->pos >= 512) {
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) {
next_sector(esdi);
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 6LL*HDC_TIME;
timer_update_outstanding();
}
}
}
return(temp);
}
static uint8_t
esdi_read(uint16_t port, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
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 */
irq_lower(esdi);
temp = esdi->status;
break;
}
return(temp);
}
static void
esdi_callback(void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
drive_t *drive = &esdi->drives[esdi->drive_sel];
off64_t addr;
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;
return;
}
switch (esdi->command) {
case CMD_RESTORE:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
drive->current_cylinder = 0;
esdi->status = STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_SEEK:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
esdi->status = STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_READ:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_read_ex(drive->hdd_num, addr, 1,
(uint8_t *)esdi->buffer)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
irq_raise(esdi);
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
break;
case CMD_WRITE:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_write_ex(drive->hdd_num, addr, 1,
(uint8_t *)esdi->buffer)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
irq_raise(esdi);
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount) {
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
esdi->pos = 0;
next_sector(esdi);
} else {
esdi->status = STAT_READY | STAT_DSC;
}
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
break;
case CMD_VERIFY:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_read_ex(drive->hdd_num, addr, 1,
(uint8_t *)esdi->buffer)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
next_sector(esdi);
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount)
esdi->callback = 6LL*HDC_TIME;
else {
esdi->pos = 0;
esdi->status = STAT_READY | STAT_DSC;
irq_raise(esdi);
}
break;
case CMD_FORMAT:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_zero_ex(drive->hdd_num, addr, esdi->secount)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
esdi->status = STAT_READY | STAT_DSC;
irq_raise(esdi);
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
break;
case CMD_DIAGNOSE:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
esdi->error = 1; /*No error detected*/
esdi->status = STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
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;
irq_raise(esdi);
break;
case CMD_NOP:
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
case 0xe0:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
switch (esdi->cylinder >> 8) {
case 0x31:
esdi->cylinder = drive->real_tracks;
break;
case 0x33:
esdi->cylinder = drive->real_hpc;
break;
case 0x35:
esdi->cylinder = 0x200;
break;
case 0x36:
esdi->cylinder = drive->real_spt;
break;
default:
pclog("EDSI Bad read config %02x\n",
esdi->cylinder >> 8);
}
esdi->status = STAT_READY | STAT_DSC;
irq_raise(esdi);
break;
case 0xa0:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
memset(esdi->buffer, 0, 512);
memset(&esdi->buffer[3], 0xff, 512-6);
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_READ_PARAMETERS:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
memset(esdi->buffer, 0, 512);
esdi->buffer[0] = 0x44; /* general configuration */
esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */
esdi->buffer[2] = 0; /* number of removable cylinders */
esdi->buffer[3] = drive->real_hpc; /* number of heads */
esdi->buffer[4] = 600; /* number of unformatted bytes/track */
esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */
esdi->buffer[6] = drive->real_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 */
esdi->buffer[20] = 2; /* controller type */
esdi->buffer[21] = 1; /* sector buffer size, in sectors */
esdi->buffer[22] = 0; /* ecc bytes appended */
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;
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;
irq_raise(esdi);
break;
}
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
}
static void
esdi_rom_write(uint32_t addr, uint8_t val, void *priv)
{
rom_t *rom = (rom_t *)priv;
addr &= rom->mask;
if (addr >= 0x1f00 && addr < 0x2000)
rom->rom[addr] = val;
}
static void
loadhd(esdi_t *esdi, int hdd_num, int d, const wchar_t *fn)
{
drive_t *drive = &esdi->drives[d];
if (! hdd_image_load(hdd_num)) {
drive->present = 0;
return;
}
drive->cfg_spt = drive->real_spt = hdd[hdd_num].spt;
drive->cfg_hpc = drive->real_hpc = hdd[hdd_num].hpc;
drive->real_tracks = hdd[hdd_num].tracks;
drive->hdd_num = hdd_num;
drive->present = 1;
}
static void *
wd1007vse1_init(device_t *info)
{
int i, c = 0;
esdi_t *esdi = malloc(sizeof(esdi_t));
memset(esdi, 0x00, sizeof(esdi_t));
esdi->drives[0].present = esdi->drives[1].present = 0;
for (i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus==HDD_BUS_ESDI) && (hdd[i].esdi_channel<ESDI_NUM)) {
loadhd(esdi, i, hdd[i].esdi_channel, hdd[i].fn);
if (++c >= ESDI_NUM) break;
}
}
esdi->status = STAT_READY | STAT_DSC;
esdi->error = 1;
rom_init(&esdi->bios_rom,
BIOS_FILE, 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, 1,
esdi_read, esdi_readw, NULL,
esdi_write, esdi_writew, NULL, esdi);
io_sethandler(0x01f1, 7,
esdi_read, NULL, NULL,
esdi_write, NULL, NULL, esdi);
io_sethandler(0x03f6, 1, NULL, NULL, NULL,
esdi_write, NULL, NULL, esdi);
timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi);
return(esdi);
}
static void
wd1007vse1_close(void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
drive_t *drive;
int d;
esdi->drives[0].present = esdi->drives[1].present = 0;
for (d=0; d<2; d++) {
drive = &esdi->drives[d];
hdd_image_close(drive->hdd_num);
}
free(esdi);
}
static int
wd1007vse1_available(void)
{
return(rom_present(BIOS_FILE));
}
device_t esdi_at_wd1007vse1_device = {
"Western Digital WD1007V-SE1 (ESDI)",
DEVICE_ISA | DEVICE_AT,
0,
wd1007vse1_init,
wd1007vse1_close,
NULL,
wd1007vse1_available,
NULL, NULL, NULL, NULL
};

View File

@@ -52,25 +52,31 @@
* however, are auto-configured by the system software as
* shown above.
*
* Version: @(#)hdd_esdi_mca.c 1.0.2 2017/08/27
* Version: @(#)hdc_esdi_mca.c 1.0.6 2017/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2017 Fred N. van Kempen.
*/
#include <malloc.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../dma.h"
#include "hdd_image.h"
#include "../io.h"
#include "../mca.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdd_esdi_mca.h"
#include "../ui.h"
#include "hdc.h"
#include "hdd.h"
/* These are hardwired. */
@@ -78,8 +84,11 @@
#define ESDI_IOADDR_SEC 0x3518
#define ESDI_IRQCHAN 14
#define BIOS_FILE_L L"roms/hdd/esdi/90x8969.bin"
#define BIOS_FILE_H L"roms/hdd/esdi/90x8970.bin"
#define ESDI_TIME (2000 * TIMER_USEC)
#define ESDI_TIME (200LL*TIMER_USEC)
#define CMD_ADAPTER 0
@@ -88,8 +97,8 @@ typedef struct esdi_drive {
int tracks;
int sectors;
int present;
int hdc_num;
} esdi_drive_t;
int hdd_num;
} drive_t;
typedef struct esdi {
uint16_t base;
@@ -125,7 +134,7 @@ typedef struct esdi {
int cmd_state;
int in_reset;
int callback;
int64_t callback;
uint32_t rba;
@@ -133,7 +142,7 @@ typedef struct esdi {
int req_in_progress;
} cmds[3];
esdi_drive_t drives[2];
drive_t drives[2];
uint8_t pos_regs[8];
} esdi_t;
@@ -267,10 +276,10 @@ static void
esdi_callback(void *priv)
{
esdi_t *dev = (esdi_t *)priv;
esdi_drive_t *drive;
drive_t *drive;
int val;
dev->callback = 0;
dev->callback = 0LL;
/* If we are returning from a RESET, handle this first. */
if (dev->in_reset) {
@@ -317,8 +326,8 @@ esdi_callback(void *priv)
if (! dev->data_pos) {
if (dev->rba >= drive->sectors)
fatal("Read past end of drive\n");
hdd_image_read(drive->hdc_num, dev->rba, 1, (uint8_t *)dev->data);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
hdd_image_read(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data);
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
while (dev->data_pos < 256) {
@@ -396,14 +405,14 @@ esdi_callback(void *priv)
if (dev->rba >= drive->sectors)
fatal("Write past end of drive\n");
hdd_image_write(drive->hdc_num, dev->rba, 1, (uint8_t *)dev->data);
hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data);
dev->rba++;
dev->sector_pos++;
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
dev->data_pos = 0;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 0);
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
dev->status = STATUS_CMD_IN_PROGRESS;
dev->cmd_state = 2;
@@ -671,7 +680,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
case 2: /*Basic control register*/
if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) {
dev->in_reset = 1;
dev->callback = ESDI_TIME * 50;
dev->callback = ESDI_TIME * 50LL;
dev->status = STATUS_BUSY;
}
dev->basic_ctrl = val;
@@ -701,7 +710,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
case ATTN_RESET:
dev->in_reset = 1;
dev->callback = ESDI_TIME * 50;
dev->callback = ESDI_TIME * 50LL;
dev->status = STATUS_BUSY;
break;
@@ -963,9 +972,9 @@ esdi_mca_write(int port, uint8_t val, void *priv)
static void *
esdi_init(void)
esdi_init(device_t *info)
{
esdi_drive_t *drive;
drive_t *drive;
esdi_t *dev;
int c, i;
@@ -980,17 +989,16 @@ esdi_init(void)
dev->irq = ESDI_IRQCHAN;
rom_init_interleaved(&dev->bios_rom,
L"roms/hdd/esdi/90x8970.bin",
L"roms/hdd/esdi/90x8969.bin",
0x00000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
BIOS_FILE_L, BIOS_FILE_H,
0x00000, 16384, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
mem_mapping_disable(&dev->bios_rom.mapping);
dev->drives[0].present = dev->drives[1].present = 0;
for (c=0,i=0; i<HDC_NUM; i++) {
if ((hdc[i].bus == HDD_BUS_ESDI) && (hdc[i].esdi_channel < ESDI_NUM)) {
for (c=0,i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_ESDI) && (hdd[i].esdi_channel < ESDI_NUM)) {
/* This is an ESDI drive. */
drive = &dev->drives[hdc[i].esdi_channel];
drive = &dev->drives[hdd[i].esdi_channel];
/* Try to load an image for the drive. */
if (! hdd_image_load(i)) {
@@ -1000,11 +1008,11 @@ esdi_init(void)
}
/* OK, so fill in geometry info. */
drive->spt = hdc[i].spt;
drive->hpc = hdc[i].hpc;
drive->tracks = hdc[i].tracks;
drive->sectors = hdc[i].spt*hdc[i].hpc*hdc[i].tracks;
drive->hdc_num = i;
drive->spt = hdd[i].spt;
drive->hpc = hdd[i].hpc;
drive->tracks = hdd[i].tracks;
drive->sectors = hdd[i].spt*hdd[i].hpc*hdd[i].tracks;
drive->hdd_num = i;
/* Mark drive as present. */
drive->present = 1;
@@ -1022,7 +1030,7 @@ esdi_init(void)
/* Mark for a reset. */
dev->in_reset = 1;
dev->callback = ESDI_TIME * 50;
dev->callback = ESDI_TIME * 50LL;
dev->status = STATUS_BUSY;
/* Set the reply timer. */
@@ -1036,7 +1044,7 @@ static void
esdi_close(void *priv)
{
esdi_t *dev = (esdi_t *)priv;
esdi_drive_t *drive;
drive_t *drive;
int d;
dev->drives[0].present = dev->drives[1].present = 0;
@@ -1044,7 +1052,7 @@ esdi_close(void *priv)
for (d=0; d<2; d++) {
drive = &dev->drives[d];
hdd_image_close(drive->hdc_num);
hdd_image_close(drive->hdd_num);
}
free(dev);
@@ -1054,20 +1062,13 @@ esdi_close(void *priv)
static int
esdi_available(void)
{
return(rom_present(L"roms/hdd/esdi/90x8969.bin") &&
rom_present(L"roms/hdd/esdi/90x8970.bin"));
return(rom_present(BIOS_FILE_L) && rom_present(BIOS_FILE_H));
}
device_t hdd_esdi_device =
{
device_t esdi_ps2_device = {
"IBM ESDI Fixed Disk Adapter (MCA)",
DEVICE_MCA,
esdi_init,
esdi_close,
esdi_available,
NULL,
NULL,
NULL,
NULL
DEVICE_MCA, 0,
esdi_init, esdi_close, NULL,
esdi_available, NULL, NULL, NULL, NULL
};

View File

@@ -9,16 +9,20 @@
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
* Version: @(#)hdd_ide_at.c 1.0.6 2017/09/03
* Version: @(#)hdc_ide.c 1.0.12 2017/10/11
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#define __USE_LARGEFILE64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#include "../86box.h"
@@ -27,10 +31,13 @@
#include "../pic.h"
#include "../pci.h"
#include "../timer.h"
#include "../device.h"
#include "../cdrom/cdrom.h"
#include "../scsi/scsi.h"
#include "hdd_image.h"
#include "hdd_ide_at.h"
#include "../ui.h"
#include "hdc.h"
#include "hdc_ide.h"
#include "hdd.h"
/* Bits of 'atastat' */
@@ -83,38 +90,19 @@ enum
IDE_CDROM
};
uint64_t hdt[128][3] = { { 306, 4, 17 }, { 615, 2, 17 }, { 306, 4, 26 }, { 1024, 2, 17 }, { 697, 3, 17 }, { 306, 8, 17 }, { 614, 4, 17 }, { 615, 4, 17 }, /* 000-007 */
{ 670, 4, 17 }, { 697, 4, 17 }, { 987, 3, 17 }, { 820, 4, 17 }, { 670, 5, 17 }, { 697, 5, 17 }, { 733, 5, 17 }, { 615, 6, 17 }, /* 008-015 */
{ 462, 8, 17 }, { 306, 8, 26 }, { 615, 4, 26 }, { 1024, 4, 17 }, { 855, 5, 17 }, { 925, 5, 17 }, { 932, 5, 17 }, { 1024, 2, 40 }, /* 016-023 */
{ 809, 6, 17 }, { 976, 5, 17 }, { 977, 5, 17 }, { 698, 7, 17 }, { 699, 7, 17 }, { 981, 5, 17 }, { 615, 8, 17 }, { 989, 5, 17 }, /* 024-031 */
{ 820, 4, 26 }, { 1024, 5, 17 }, { 733, 7, 17 }, { 754, 7, 17 }, { 733, 5, 26 }, { 940, 6, 17 }, { 615, 6, 26 }, { 462, 8, 26 }, /* 032-039 */
{ 830, 7, 17 }, { 855, 7, 17 }, { 751, 8, 17 }, { 1024, 4, 26 }, { 918, 7, 17 }, { 925, 7, 17 }, { 855, 5, 26 }, { 977, 7, 17 }, /* 040-047 */
{ 987, 7, 17 }, { 1024, 7, 17 }, { 823, 4, 38 }, { 925, 8, 17 }, { 809, 6, 26 }, { 976, 5, 26 }, { 977, 5, 26 }, { 698, 7, 26 }, /* 048-055 */
{ 699, 7, 26 }, { 940, 8, 17 }, { 615, 8, 26 }, { 1024, 5, 26 }, { 733, 7, 26 }, { 1024, 8, 17 }, { 823, 10, 17 }, { 754, 11, 17 }, /* 056-063 */
{ 830, 10, 17 }, { 925, 9, 17 }, { 1224, 7, 17 }, { 940, 6, 26 }, { 855, 7, 26 }, { 751, 8, 26 }, { 1024, 9, 17 }, { 965, 10, 17 }, /* 064-071 */
{ 969, 5, 34 }, { 980, 10, 17 }, { 960, 5, 35 }, { 918, 11, 17 }, { 1024, 10, 17 }, { 977, 7, 26 }, { 1024, 7, 26 }, { 1024, 11, 17 }, /* 072-079 */
{ 940, 8, 26 }, { 776, 8, 33 }, { 755, 16, 17 }, { 1024, 12, 17 }, { 1024, 8, 26 }, { 823, 10, 26 }, { 830, 10, 26 }, { 925, 9, 26 }, /* 080-087 */
{ 960, 9, 26 }, { 1024, 13, 17 }, { 1224, 11, 17 }, { 900, 15, 17 }, { 969, 7, 34 }, { 917, 15, 17 }, { 918, 15, 17 }, { 1524, 4, 39 }, /* 088-095 */
{ 1024, 9, 26 }, { 1024, 14, 17 }, { 965, 10, 26 }, { 980, 10, 26 }, { 1020, 15, 17 }, { 1023, 15, 17 }, { 1024, 15, 17 }, { 1024, 16, 17 }, /* 096-103 */
{ 1224, 15, 17 }, { 755, 16, 26 }, { 903, 8, 46 }, { 984, 10, 34 }, { 900, 15, 26 }, { 917, 15, 26 }, { 1023, 15, 26 }, { 684, 16, 38 }, /* 104-111 */
{ 1930, 4, 62 }, { 967, 16, 31 }, { 1013, 10, 63 }, { 1218, 15, 36 }, { 654, 16, 63 }, { 659, 16, 63 }, { 702, 16, 63 }, { 1002, 13, 63 }, /* 112-119 */
{ 854, 16, 63 }, { 987, 16, 63 }, { 995, 16, 63 }, { 1024, 16, 63 }, { 1036, 16, 63 }, { 1120, 16, 59 }, { 1054, 16, 63 }, { 0, 0, 0 } }; /* 119-127 */
IDE ide_drives[IDE_NUM + XTIDE_NUM];
IDE *ext_ide;
int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length);
int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length);
void (*ide_bus_master_set_irq)(int channel);
int idecallback[5] = {0, 0, 0, 0, 0};
int64_t idecallback[5] = {0LL, 0LL, 0LL, 0LL, 0LL};
int cur_ide[5];
int ide_do_log = 0;
void ide_log(const char *format, ...)
static void ide_log(const char *format, ...)
{
#ifdef ENABLE_IDE_LOG
if (ide_do_log)
@@ -343,29 +331,29 @@ static void ide_identify(IDE *ide)
uint32_t c, h, s;
char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 };
#if 0
uint64_t full_size = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
#endif
device_identify[6] = (ide->hdc_num / 10) + 0x30;
device_identify[7] = (ide->hdc_num % 10) + 0x30;
device_identify[6] = (ide->hdd_num / 10) + 0x30;
device_identify[7] = (ide->hdd_num % 10) + 0x30;
ide_log("IDE Identify: %s\n", device_identify);
memset(ide->buffer, 0, 512);
c = hdc[ide->hdc_num].tracks; /* Cylinders */
h = hdc[ide->hdc_num].hpc; /* Heads */
s = hdc[ide->hdc_num].spt; /* Sectors */
c = hdd[ide->hdd_num].tracks; /* Cylinders */
h = hdd[ide->hdd_num].hpc; /* Heads */
s = hdd[ide->hdd_num].spt; /* Sectors */
if (hdc[ide->hdc_num].tracks <= 16383)
if (hdd[ide->hdd_num].tracks <= 16383)
{
ide->buffer[1] = hdc[ide->hdc_num].tracks; /* Cylinders */
ide->buffer[1] = hdd[ide->hdd_num].tracks; /* Cylinders */
}
else
{
ide->buffer[1] = 16383; /* Cylinders */
}
ide->buffer[3] = hdc[ide->hdc_num].hpc; /* Heads */
ide->buffer[6] = hdc[ide->hdc_num].spt; /* Sectors */
ide->buffer[3] = hdd[ide->hdd_num].hpc; /* Heads */
ide->buffer[6] = hdd[ide->hdd_num].spt; /* Sectors */
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */
@@ -373,7 +361,7 @@ static void ide_identify(IDE *ide)
ide->buffer[21] = 512; /*Buffer size*/
ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/
ide->buffer[48] = 1; /*Dword transfers supported*/
if (PCI && (ide->board < 2) && (hdc[ide->hdc_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
{
ide->buffer[49] = (1 << 8); /* LBA and DMA supported */
}
@@ -406,10 +394,10 @@ static void ide_identify(IDE *ide)
ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0;
if (ide->buffer[49] & (1 << 9))
{
ide->buffer[60] = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt) & 0xFFFF; /* Total addressable sectors (LBA) */
ide->buffer[61] = ((hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt) >> 16) & 0x0FFF;
ide->buffer[60] = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt) & 0xFFFF; /* Total addressable sectors (LBA) */
ide->buffer[61] = ((hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt) >> 16) & 0x0FFF;
}
if (PCI && (ide->board < 2) && (hdc[ide->hdc_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
{
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
@@ -499,21 +487,16 @@ static void ide_next_sector(IDE *ide)
static void loadhd(IDE *ide, int d, const wchar_t *fn)
{
int ret = 0;
ret = hdd_image_load(d);
if (!ret)
{
if (! hdd_image_load(d)) {
ide->type = IDE_NONE;
return;
}
ide->spt = hdc[d].spt;
ide->hpc = hdc[d].hpc;
ide->tracks = hdc[d].tracks;
ide->spt = hdd[d].spt;
ide->hpc = hdd[d].hpc;
ide->tracks = hdd[d].tracks;
ide->type = IDE_HDD;
ide->hdc_num = d;
ide->hdd_num = d;
ide->hdi = hdd_image_get_type(d);
}
@@ -590,7 +573,7 @@ static int ide_set_features(IDE *ide)
break;
case 0x04: /* Multiword DMA mode */
if (!PCI || (hdc[ide->hdc_num].bus != HDD_BUS_IDE_PIO_AND_DMA) || (ide->board >= 2) || (submode > 2))
if (!PCI || (hdd[ide->hdd_num].bus != HDD_BUS_IDE_PIO_AND_DMA) || (ide->board >= 2) || (submode > 2))
{
return 0;
}
@@ -619,30 +602,32 @@ void ide_set_sector(IDE *ide, int64_t sector_num)
}
else
{
cyl = sector_num / (hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
r = sector_num % (hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
ide->cylinder = cyl;
ide->head = ((r / hdc[ide->hdc_num].spt) & 0x0f);
ide->sector = (r % hdc[ide->hdc_num].spt) + 1;
ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f);
ide->sector = (r % hdd[ide->hdd_num].spt) + 1;
}
}
void ide_ter_disable_cond();
void ide_qua_disable_cond();
void resetide(void)
void ide_reset(void)
{
int c, d;
build_atapi_cdrom_map();
/* Close hard disk image files (if previously open) */
for (d = 0; d < (IDE_NUM + XTIDE_NUM); d++)
for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++)
{
ide_drives[d].channel = d;
ide_drives[d].type = IDE_NONE;
hdd_image_close(ide_drives[d].hdc_num);
if (ide_drive_is_cdrom(&ide_drives[d]))
if (ide_drives[d].hdd_num != -1)
hdd_image_close(ide_drives[d].hdd_num);
if ((d < 8) && ide_drive_is_cdrom(&ide_drives[d]))
{
cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT;
}
@@ -651,28 +636,28 @@ void resetide(void)
ide_drives[d].board = d >> 1;
}
idecallback[0]=idecallback[1]=0;
idecallback[2]=idecallback[3]=0;
idecallback[4]=0;
idecallback[0]=idecallback[1]=0LL;
idecallback[2]=idecallback[3]=0LL;
idecallback[4]=0LL;
pclog("IDE: loading disks...\n");
c = 0;
for (d = 0; d < HDC_NUM; d++)
for (d = 0; d < HDD_NUM; d++)
{
if (((hdc[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdc[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdc[d].ide_channel < IDE_NUM))
if (((hdd[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdd[d].ide_channel < IDE_NUM))
{
ide_log("Found IDE hard disk on channel %i\n", hdc[d].ide_channel);
loadhd(&ide_drives[hdc[d].ide_channel], d, hdc[d].fn);
c++;
if (c >= (IDE_NUM + XTIDE_NUM)) break;
ide_log("Found IDE hard disk on channel %i\n", hdd[d].ide_channel);
loadhd(&ide_drives[hdd[d].ide_channel], d, hdd[d].fn);
if (++c >= (IDE_NUM+XTIDE_NUM)) break;
}
if ((hdc[d].bus == HDD_BUS_XTIDE) && (hdc[d].xtide_channel < XTIDE_NUM))
if ((hdd[d].bus==HDD_BUS_XTIDE) && (hdd[d].xtide_channel < XTIDE_NUM))
{
ide_log("Found XT IDE hard disk on channel %i\n", hdc[d].xtide_channel);
loadhd(&ide_drives[hdc[d].xtide_channel | 8], d, hdc[d].fn);
c++;
if (c >= (IDE_NUM + XTIDE_NUM)) break;
ide_log("Found XT IDE hard disk on channel %i\n", hdd[d].xtide_channel);
loadhd(&ide_drives[hdd[d].xtide_channel | 8], d, hdd[d].fn);
if (++c >= (IDE_NUM+XTIDE_NUM)) break;
}
}
pclog("IDE: done, loaded %d disks.\n", c);
for (d = 0; d < IDE_NUM; d++)
{
@@ -770,7 +755,7 @@ void ide_write_data(int ide_board, uint32_t val, int length)
}
else
{
idecallback[ide_board]=6*IDE_TIME;
idecallback[ide_board]=6LL*IDE_TIME;
}
timer_update_outstanding();
}
@@ -900,7 +885,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
cdrom[atapi_cdrom_drives[ide->channel]].error = 1;
cdrom[atapi_cdrom_drives[ide->channel]].phase = 1;
cdrom[atapi_cdrom_drives[ide->channel]].request_length = 0xEB14;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 0;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL;
ide->cylinder = 0xEB14;
}
if (ide_drive_is_cdrom(ide_other))
@@ -909,11 +894,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
cdrom[atapi_cdrom_drives[ide_other->channel]].error = 1;
cdrom[atapi_cdrom_drives[ide_other->channel]].phase = 1;
cdrom[atapi_cdrom_drives[ide_other->channel]].request_length = 0xEB14;
cdrom[atapi_cdrom_drives[ide_other->channel]].callback = 0;
cdrom[atapi_cdrom_drives[ide_other->channel]].callback = 0LL;
ide->cylinder = 0xEB14;
}
idecallback[ide_board] = 0;
idecallback[ide_board] = 0LL;
timer_update_outstanding();
return;
}
@@ -959,9 +944,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 100*IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME;
}
idecallback[ide_board]=100*IDE_TIME;
idecallback[ide_board]=100LL*IDE_TIME;
timer_update_outstanding();
return;
@@ -978,9 +963,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 100*IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME;
}
idecallback[ide_board]=100*IDE_TIME;
idecallback[ide_board]=100LL*IDE_TIME;
timer_update_outstanding();
return;
@@ -1006,9 +991,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
}
idecallback[ide_board]=200*IDE_TIME;
idecallback[ide_board]=200LL*IDE_TIME;
timer_update_outstanding();
ide->do_initial_read = 1;
return;
@@ -1046,9 +1031,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
}
idecallback[ide_board]=200*IDE_TIME;
idecallback[ide_board]=200LL*IDE_TIME;
timer_update_outstanding();
return;
@@ -1065,9 +1050,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
}
idecallback[ide_board]=200*IDE_TIME;
idecallback[ide_board]=200LL*IDE_TIME;
timer_update_outstanding();
return;
@@ -1095,9 +1080,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 30*IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 30LL*IDE_TIME;
}
idecallback[ide_board]=30*IDE_TIME;
idecallback[ide_board]=30LL*IDE_TIME;
timer_update_outstanding();
return;
@@ -1126,9 +1111,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
/* callbackide(ide_board); */
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200 * IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL * IDE_TIME;
}
idecallback[ide_board] = 200 * IDE_TIME;
idecallback[ide_board] = 200LL * IDE_TIME;
timer_update_outstanding();
}
else
@@ -1144,9 +1129,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 30 * IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 30LL * IDE_TIME;
}
idecallback[ide_board] = 30 * IDE_TIME;
idecallback[ide_board] = 30LL * IDE_TIME;
timer_update_outstanding();
}
return;
@@ -1164,9 +1149,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
}
idecallback[ide_board]=200*IDE_TIME;
idecallback[ide_board]=200LL*IDE_TIME;
timer_update_outstanding();
return;
@@ -1183,7 +1168,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
{
ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=1;
idecallback[ide_board]=1LL;
timer_update_outstanding();
ide->pos=0;
}
@@ -1213,9 +1198,9 @@ ide_bad_command:
timer_process();
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[ide->channel]].callback = 0;
cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL;
}
idecallback[ide_board]=500*IDE_TIME;
idecallback[ide_board]=500LL*IDE_TIME;
timer_update_outstanding();
if (ide->type != IDE_NONE)
@@ -1236,7 +1221,7 @@ ide_bad_command:
{
/*Drive held in reset*/
timer_process();
idecallback[ide_board] = 0;
idecallback[ide_board] = 0LL;
timer_update_outstanding();
ide->atastat = ide_other->atastat = BUSY_STAT;
ide_irq_lower(ide);
@@ -1313,13 +1298,13 @@ uint32_t ide_read_data(int ide_board, int length)
}
else
{
idecallback[ide_board]=6*IDE_TIME;
idecallback[ide_board]=6LL*IDE_TIME;
}
timer_update_outstanding();
}
else
{
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
}
}
@@ -1513,13 +1498,13 @@ void callbackide(int ide_board)
ide_other = &ide_drives[cur_ide[ide_board] ^ 1];
if (ide->type == IDE_HDD)
{
full_size = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
}
ext_ide = ide;
if (ide_drive_is_cdrom(ide))
{
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback = 0;
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback = 0LL;
}
if (ide->command==0x30) times30++;
@@ -1650,11 +1635,11 @@ void callbackide(int ide_board)
ide->sector_pos = 0;
if (ide->secount)
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
}
else
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
}
}
@@ -1667,7 +1652,7 @@ void callbackide(int ide_board)
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
return;
case WIN_READ_DMA:
@@ -1686,11 +1671,11 @@ void callbackide(int ide_board)
ide->sector_pos = 0;
if (ide->secount)
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
}
else
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
}
}
@@ -1700,7 +1685,7 @@ void callbackide(int ide_board)
{
if (ide_bus_master_read(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512))
{
idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
idecallback[ide_board]=6LL*IDE_TIME; /*DMA not performed, try again later*/
}
else
{
@@ -1713,13 +1698,13 @@ void callbackide(int ide_board)
{
ide_next_sector(ide);
ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
idecallback[ide_board]=6LL*IDE_TIME;
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
}
}
@@ -1748,11 +1733,11 @@ void callbackide(int ide_board)
ide->sector_pos = 0;
if (ide->secount)
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
}
else
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
}
}
@@ -1772,7 +1757,7 @@ void callbackide(int ide_board)
ide->blockcount = 0;
}
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
return;
case WIN_WRITE:
@@ -1785,7 +1770,7 @@ void callbackide(int ide_board)
{
goto id_not_found;
}
hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
ide_irq_raise(ide);
ide->secount = (ide->secount - 1) & 0xff;
if (ide->secount)
@@ -1793,12 +1778,12 @@ void callbackide(int ide_board)
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
ide->pos=0;
ide_next_sector(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide->atastat = READY_STAT | DSC_STAT;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
return;
@@ -1817,12 +1802,12 @@ void callbackide(int ide_board)
{
if (ide_bus_master_write(ide_board, (uint8_t *)ide->buffer, 512))
{
idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
idecallback[ide_board]=6LL*IDE_TIME; /*DMA not performed, try again later*/
}
else
{
/*DMA successful*/
hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
@@ -1831,13 +1816,13 @@ void callbackide(int ide_board)
{
ide_next_sector(ide);
ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
idecallback[ide_board]=6LL*IDE_TIME;
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
}
}
@@ -1853,7 +1838,7 @@ void callbackide(int ide_board)
{
goto id_not_found;
}
hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
ide->blockcount++;
if (ide->blockcount >= ide->blocksize || ide->secount == 1)
{
@@ -1866,12 +1851,12 @@ void callbackide(int ide_board)
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
ide->pos=0;
ide_next_sector(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide->atastat = READY_STAT | DSC_STAT;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
return;
@@ -1888,7 +1873,7 @@ void callbackide(int ide_board)
ide->pos=0;
ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
return;
case WIN_FORMAT:
@@ -1900,12 +1885,12 @@ void callbackide(int ide_board)
{
goto id_not_found;
}
hdd_image_zero(ide->hdc_num, ide_get_sector(ide), ide->secount);
hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount);
ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide);
/* update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); */
/* ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */
return;
case WIN_DRIVE_DIAGNOSTICS:
@@ -1952,7 +1937,7 @@ void callbackide(int ide_board)
full_size /= (ide->head+1);
full_size /= ide->secount;
ide->specify_success = 1;
hdd_image_specify(ide->hdc_num, ide->head + 1, ide->secount);
hdd_image_specify(ide->hdd_num, ide->head + 1, ide->secount);
ide->spt=ide->secount;
ide->hpc=ide->head+1;
ide->atastat = READY_STAT | DSC_STAT;
@@ -2004,9 +1989,9 @@ void callbackide(int ide_board)
{
goto abort_cmd;
}
snum = hdc[ide->hdc_num].spt;
snum *= hdc[ide->hdc_num].hpc;
snum *= hdc[ide->hdc_num].tracks;
snum = hdd[ide->hdd_num].spt;
snum *= hdd[ide->hdd_num].hpc;
snum *= hdd[ide->hdd_num].tracks;
ide_set_sector(ide, snum - 1);
ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide);
@@ -2075,31 +2060,31 @@ id_not_found:
void ide_callback_pri()
{
idecallback[0] = 0;
idecallback[0] = 0LL;
callbackide(0);
}
void ide_callback_sec()
{
idecallback[1] = 0;
idecallback[1] = 0LL;
callbackide(1);
}
void ide_callback_ter()
{
idecallback[2] = 0;
idecallback[2] = 0LL;
callbackide(2);
}
void ide_callback_qua()
{
idecallback[3] = 0;
idecallback[3] = 0LL;
callbackide(3);
}
void ide_callback_xtide()
{
idecallback[4] = 0;
idecallback[4] = 0LL;
callbackide(4);
}
@@ -2206,7 +2191,8 @@ uint32_t ide_read_qua_l(uint16_t addr, void *priv)
static uint16_t ide_base_main[2] = { 0x1f0, 0x170 };
static uint16_t ide_side_main[2] = { 0x3f6, 0x376 };
void ide_pri_enable()
void ide_pri_enable(void)
{
io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
@@ -2214,7 +2200,7 @@ void ide_pri_enable()
ide_side_main[0] = 0x3f6;
}
void ide_pri_enable_ex()
void ide_pri_enable_ex(void)
{
if (ide_base_main[0] & 0x300)
{
@@ -2228,13 +2214,13 @@ void ide_pri_enable_ex()
}
}
void ide_pri_disable()
void ide_pri_disable(void)
{
io_removehandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
io_removehandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
}
void ide_sec_enable()
void ide_sec_enable(void)
{
io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
@@ -2242,7 +2228,7 @@ void ide_sec_enable()
ide_side_main[1] = 0x376;
}
void ide_sec_enable_ex()
void ide_sec_enable_ex(void)
{
if (ide_base_main[1] & 0x300)
{
@@ -2254,12 +2240,13 @@ void ide_sec_enable_ex()
}
}
void ide_sec_disable()
void ide_sec_disable(void)
{
io_removehandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
io_removehandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
}
void ide_set_base(int controller, uint16_t port)
{
ide_base_main[controller] = port;
@@ -2270,19 +2257,19 @@ void ide_set_side(int controller, uint16_t port)
ide_side_main[controller] = port;
}
void ide_ter_enable()
void ide_ter_enable(void)
{
io_sethandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL);
io_sethandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL);
}
void ide_ter_disable()
void ide_ter_disable(void)
{
io_removehandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL);
io_removehandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL);
}
void ide_ter_disable_cond()
void ide_ter_disable_cond(void)
{
if ((ide_drives[4].type == IDE_NONE) && (ide_drives[5].type == IDE_NONE))
{
@@ -2290,20 +2277,20 @@ void ide_ter_disable_cond()
}
}
void ide_ter_init()
void ide_ter_init(void)
{
ide_ter_enable();
timer_add(ide_callback_ter, &idecallback[2], &idecallback[2], NULL);
}
void ide_qua_enable()
void ide_qua_enable(void)
{
io_sethandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL);
io_sethandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL);
}
void ide_qua_disable_cond()
void ide_qua_disable_cond(void)
{
if ((ide_drives[6].type == IDE_NONE) && (ide_drives[7].type == IDE_NONE))
{
@@ -2311,20 +2298,39 @@ void ide_qua_disable_cond()
}
}
void ide_qua_disable()
void ide_qua_disable(void)
{
io_removehandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL);
io_removehandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL);
}
void ide_qua_init()
void ide_qua_init(void)
{
ide_qua_enable();
timer_add(ide_callback_qua, &idecallback[3], &idecallback[3], NULL);
}
void ide_init()
/*FIXME: this will go away after Kotori's rewrite. --FvK */
void ide_init_first(void)
{
int d;
memset(ide_drives, 0x00, sizeof(ide_drives));
for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++)
{
ide_drives[d].channel = d;
ide_drives[d].type = IDE_NONE;
ide_drives[d].hdd_num = -1;
ide_drives[d].atastat = READY_STAT | DSC_STAT;
ide_drives[d].service = 0;
ide_drives[d].board = d >> 1;
}
}
void ide_init(void)
{
ide_pri_enable();
ide_sec_enable();
@@ -2334,7 +2340,8 @@ void ide_init()
timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL);
}
void ide_xtide_init()
void ide_xtide_init(void)
{
ide_bus_master_read = ide_bus_master_write = NULL;

View File

@@ -9,11 +9,10 @@
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
* Version: @(#)hdd_ide_at.h 1.0.2 2017/08/24
* Version: @(#)hdd_ide.h 1.0.4 2017/09/30
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
@@ -21,7 +20,6 @@
# define EMU_IDE_H
#pragma pack(push,1)
typedef struct {
int type;
int board;
@@ -47,14 +45,13 @@ typedef struct {
int blocksize, blockcount;
uint16_t dma_identify_data[3];
int hdi,base;
int hdc_num;
int hdd_num;
uint8_t specify_success;
int mdma_mode;
uint8_t sector_buffer[256*512];
int do_initial_read;
int sector_pos;
} IDE;
#pragma pack(pop)
extern int ideboard;
@@ -63,43 +60,47 @@ extern int ide_enable[5];
extern int ide_irq[5];
extern IDE ide_drives[IDE_NUM + XTIDE_NUM];
extern int idecallback[5];
extern int64_t idecallback[5];
extern void ide_irq_raise(IDE *ide);
extern void ide_irq_lower(IDE *ide);
extern void writeide(int ide_board, uint16_t addr, uint8_t val);
extern void writeidew(int ide_board, uint16_t val);
extern uint8_t readide(int ide_board, uint16_t addr);
extern uint16_t readidew(int ide_board);
extern void callbackide(int ide_board);
extern void resetide(void);
extern void ide_init(void);
extern void ide_xtide_init(void);
extern void ide_ter_init(void);
extern void ide_qua_init(void);
extern void ide_pri_enable(void);
extern void ide_sec_enable(void);
extern void ide_ter_enable(void);
extern void ide_qua_enable(void);
extern void ide_pri_disable(void);
extern void ide_sec_disable(void);
extern void ide_ter_disable(void);
extern void ide_qua_disable(void);
extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel));
extern void ide_irq_raise(IDE *ide);
extern void ide_irq_lower(IDE *ide);
extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src);
extern void win_cdrom_eject(uint8_t id);
extern void win_cdrom_reload(uint8_t id);
extern void ide_pri_disable(void);
extern void ide_pri_enable_ex(void);
extern void ide_set_base(int controller, uint16_t port);
extern void ide_set_side(int controller, uint16_t port);
extern void ide_init_first(void);
extern void ide_init(void);
extern void ide_reset(void);
extern void ide_xtide_init(void);
extern void ide_pri_enable(void);
extern void ide_pri_enable_ex(void);
extern void ide_pri_disable(void);
extern void ide_sec_enable(void);
extern void ide_sec_disable(void);
extern void ide_ter_enable(void);
extern void ide_ter_disable(void);
extern void ide_ter_init(void);
extern void ide_qua_enable(void);
extern void ide_qua_disable(void);
extern void ide_qua_init(void);
extern void secondary_ide_check(void);
extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src);
#endif /*EMU_IDE_H*/

771
src/disk/hdc_mfm_at.c Normal file
View File

@@ -0,0 +1,771 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Driver for the IBM PC-AT MFM/RLL Fixed Disk controller.
*
* This controller was a 16bit ISA card, and it used a WD1003
* based design. Most cards were WD1003-WA2 or -WAH, where the
* -WA2 cards had a floppy controller as well (to save space.)
*
* Version: @(#)hdd_mfm_at.c 1.0.8 2017/10/14
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2017 Fred N. van Kempen.
*/
#define __USE_LARGEFILE64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../io.h"
#include "../pic.h"
#include "../timer.h"
#include "../ui.h"
#include "hdc.h"
#include "hdd.h"
#define MFM_TIME (TIMER_USEC*10LL)
#define MFM_DEBUG 0
#define STAT_ERR 0x01
#define STAT_INDEX 0x02
#define STAT_ECC 0x04
#define STAT_DRQ 0x08 /* data request */
#define STAT_DSC 0x10
#define STAT_WRFLT 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_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
typedef struct {
int8_t present, /* drive is present */
hdd_num, /* drive number in system */
steprate, /* current servo step rate */
spt, /* physical #sectors per track */
hpc, /* physical #heads per cylinder */
pad;
int16_t tracks; /* physical #tracks per cylinder */
int8_t cfg_spt, /* configured #sectors per track */
cfg_hpc; /* configured #heads per track */
int16_t curcyl; /* current track number */
} drive_t;
typedef struct {
uint8_t precomp, /* 1: precomp/error register */
error,
secount, /* 2: sector count register */
sector, /* 3: sector number */
head, /* 6: head number + drive select */
command, /* 7: command/status */
status,
fdisk; /* 8: control register */
uint16_t cylinder; /* 4/5: cylinder LOW and HIGH */
int8_t reset, /* controller in reset */
irqstat, /* current IRQ status */
drvsel, /* current selected drive */
pad;
int pos; /* offset within data buffer */
int64_t callback; /* callback delay timer */
uint16_t buffer[256]; /* data buffer (16b wide) */
drive_t drives[MFM_NUM]; /* attached drives */
} mfm_t;
static __inline void irq_raise(mfm_t *mfm)
{
/* If not already pending.. */
if (! mfm->irqstat) {
/* If enabled in the control register.. */
if (! (mfm->fdisk&0x02)) {
/* .. raise IRQ14. */
picint(1<<14);
}
/* Remember this. */
mfm->irqstat = 1;
}
}
static __inline void irq_lower(mfm_t *mfm)
{
/* If raised.. */
if (mfm->irqstat) {
/* If enabled in the control register.. */
if (! (mfm->fdisk&0x02)) {
/* .. drop IRQ14. */
picintc(1<<14);
}
/* Remember this. */
mfm->irqstat = 0;
}
}
/*
* Return the sector offset for the current register values.
*
* According to the WD1002/WD1003 technical reference manual,
* this is not done entirely correct. It specifies that the
* parameters set with the SET_DRIVE_PARAMETERS command are
* to be used only for multi-sector operations, and that any
* such operation can only be executed AFTER these parameters
* have been set. This would imply that for regular single
* transfers, the controller uses (or, can use) the actual
* geometry information...
*/
static int
get_sector(mfm_t *mfm, off64_t *addr)
{
drive_t *drive = &mfm->drives[mfm->drvsel];
if (drive->curcyl != mfm->cylinder) {
pclog("WD1003(%d) sector: wrong cylinder\n");
return(1);
}
if (mfm->head > drive->cfg_hpc) {
pclog("WD1003(%d) get_sector: past end of configured heads\n",
mfm->drvsel);
return(1);
}
if (mfm->sector >= drive->cfg_spt+1) {
pclog("WD1003(%d) get_sector: past end of configured sectors\n",
mfm->drvsel);
return(1);
}
#if 1
/* We should check this in the SET_DRIVE_PARAMETERS command! --FvK */
if (mfm->head > drive->hpc) {
pclog("WD1003(%d) get_sector: past end of heads\n", mfm->drvsel);
return(1);
}
if (mfm->sector >= drive->spt+1) {
pclog("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel);
return(1);
}
#endif
*addr = ((((off64_t) mfm->cylinder * drive->cfg_hpc) + mfm->head) *
drive->cfg_spt) + (mfm->sector - 1);
return(0);
}
/* Move to the next sector using CHS addressing. */
static void
next_sector(mfm_t *mfm)
{
drive_t *drive = &mfm->drives[mfm->drvsel];
if (++mfm->sector == (drive->cfg_spt+1)) {
mfm->sector = 1;
if (++mfm->head == drive->cfg_hpc) {
mfm->head = 0;
mfm->cylinder++;
if (drive->curcyl < drive->tracks)
drive->curcyl++;
}
}
}
static void
mfm_cmd(mfm_t *mfm, uint8_t val)
{
drive_t *drive = &mfm->drives[mfm->drvsel];
if (! drive->present) {
/* This happens if sofware polls all drives. */
pclog("WD1003(%d) command %02x on non-present drive\n",
mfm->drvsel, val);
mfm->command = 0xff;
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200LL*MFM_TIME;
timer_update_outstanding();
return;
}
irq_lower(mfm);
mfm->error = 0;
switch (val & 0xf0) {
case CMD_RESTORE:
drive->steprate = (val & 0x0f);
#if MFM_DEBUG
pclog("WD1003(%d) restore, step=%d\n",
mfm->drvsel, drive->steprate);
#endif
drive->curcyl = 0;
mfm->status = STAT_READY|STAT_DSC;
mfm->command = 0x00;
irq_raise(mfm);
break;
case CMD_SEEK:
drive->steprate = (val & 0x0f);
mfm->command = (val & 0xf0);
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200LL*MFM_TIME;
timer_update_outstanding();
break;
default:
switch (val) {
case CMD_READ:
case CMD_READ+1:
case CMD_READ+2:
case CMD_READ+3:
#if MFM_DEBUG
pclog("WD1003(%d) read, opt=%d\n",
mfm->drvsel, val&0x03);
#endif
mfm->command = (val & 0xf0);
if (val & 2)
fatal("WD1003: READ with ECC\n");
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200LL*MFM_TIME;
timer_update_outstanding();
break;
case CMD_WRITE:
case CMD_WRITE+1:
case CMD_WRITE+2:
case CMD_WRITE+3:
#if MFM_DEBUG
pclog("WD1003(%d) write, opt=%d\n",
mfm->drvsel, val & 0x03);
#endif
mfm->command = (val & 0xf0);
if (val & 2)
fatal("WD1003: WRITE with ECC\n");
mfm->status = STAT_DRQ|STAT_DSC;
mfm->pos = 0;
break;
case CMD_VERIFY:
case CMD_VERIFY+1:
mfm->command = (val & 0xfe);
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200LL*MFM_TIME;
timer_update_outstanding();
break;
case CMD_FORMAT:
mfm->command = val;
mfm->status = STAT_DRQ|STAT_BUSY;
mfm->pos = 0;
break;
case CMD_DIAGNOSE:
mfm->command = val;
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200LL*MFM_TIME;
timer_update_outstanding();
break;
case CMD_SET_PARAMETERS:
/*
* NOTE:
*
* We currently just set these parameters, and
* never bother to check if they "fit within"
* the actual parameters, as determined by the
* image loader.
*
* The difference in parameters is OK, and
* occurs when the BIOS or operating system
* decides to use a different translation
* scheme, but either way, it SHOULD always
* fit within the actual parameters!
*
* We SHOULD check that here!! --FvK
*/
if (drive->cfg_spt == 0) {
/* Only accept after RESET or DIAG. */
drive->cfg_spt = mfm->secount;
drive->cfg_hpc = mfm->head+1;
pclog("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n",
mfm->drvsel, drive->tracks,
drive->cfg_spt, drive->cfg_hpc);
} else {
pclog("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n",
mfm->drvsel, drive->tracks,
drive->cfg_spt, drive->cfg_hpc);
}
mfm->command = 0x00;
mfm->status = STAT_READY|STAT_DSC;
mfm->error = 1;
irq_raise(mfm);
break;
default:
pclog("WD1003: bad command %02X\n", val);
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200LL*MFM_TIME;
timer_update_outstanding();
break;
}
}
}
static void
mfm_writew(uint16_t port, uint16_t val, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
mfm->buffer[mfm->pos >> 1] = val;
mfm->pos += 2;
if (mfm->pos >= 512) {
mfm->pos = 0;
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 6LL*MFM_TIME;
timer_update_outstanding();
}
}
static void
mfm_write(uint16_t port, uint8_t val, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
#if MFM_DEBUG > 1
pclog("WD1003 write(%04x, %02x)\n", port, val);
#endif
switch (port) {
case 0x01f0: /* data */
mfm_writew(port, val | (val << 8), priv);
return;
case 0x01f1: /* write precompenstation */
mfm->precomp = val;
return;
case 0x01f2: /* sector count */
mfm->secount = val;
return;
case 0x01f3: /* sector */
mfm->sector = val;
return;
case 0x01f4: /* cylinder low */
mfm->cylinder = (mfm->cylinder & 0xff00) | val;
return;
case 0x01f5: /* cylinder high */
mfm->cylinder = (mfm->cylinder & 0xff) | (val << 8);
return;
case 0x01f6: /* drive/head */
mfm->head = val & 0xF;
mfm->drvsel = (val & 0x10) ? 1 : 0;
if (mfm->drives[mfm->drvsel].present)
mfm->status = STAT_READY|STAT_DSC;
else
mfm->status = 0;
return;
case 0x01f7: /* command register */
mfm_cmd(mfm, val);
break;
case 0x03f6: /* device control */
val &= 0x0f;
if ((mfm->fdisk & 0x04) && !(val & 0x04)) {
mfm->status = STAT_BUSY;
mfm->reset = 1;
timer_process();
mfm->callback = 500LL*MFM_TIME;
timer_update_outstanding();
}
if (val & 0x04) {
/* Drive held in reset. */
mfm->status = STAT_BUSY;
mfm->callback = 0LL;
timer_process();
timer_update_outstanding();
}
mfm->fdisk = val;
break;
}
}
static uint16_t
mfm_readw(uint16_t port, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
uint16_t ret;
ret = mfm->buffer[mfm->pos >> 1];
mfm->pos += 2;
if (mfm->pos >= 512) {
mfm->pos = 0;
mfm->status = STAT_READY|STAT_DSC;
if (mfm->command == CMD_READ) {
mfm->secount = (mfm->secount - 1) & 0xff;
if (mfm->secount) {
next_sector(mfm);
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 6LL*MFM_TIME;
timer_update_outstanding();
} else {
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
}
}
}
return(ret);
}
static uint8_t
mfm_read(uint16_t port, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
uint8_t ret = 0xff;
switch (port) {
case 0x01f0: /* data */
ret = mfm_readw(port, mfm) & 0xff;
break;
case 0x01f1: /* error */
ret = mfm->error;
break;
case 0x01f2: /* sector count */
ret = mfm->secount;
break;
case 0x01f3: /* sector */
ret = mfm->sector;
break;
case 0x01f4: /* CYlinder low */
ret = (uint8_t)(mfm->cylinder&0xff);
break;
case 0x01f5: /* Cylinder high */
ret = (uint8_t)(mfm->cylinder>>8);
break;
case 0x01f6: /* drive/head */
ret = (uint8_t)(0xa0 | mfm->head | (mfm->drvsel?0x10:0));
break;
case 0x01f7: /* Status */
irq_lower(mfm);
ret = mfm->status;
break;
default:
break;
}
#if MFM_DEBUG > 1
pclog("WD1003 read(%04x) = %02x\n", port, ret);
#endif
return(ret);
}
static void
do_seek(mfm_t *mfm)
{
drive_t *drive = &mfm->drives[mfm->drvsel];
#if MFM_DEBUG
pclog("WD1003(%d) seek(%d) max=%d\n",
mfm->drvsel,mfm->cylinder,drive->tracks);
#endif
if (mfm->cylinder < drive->tracks)
drive->curcyl = mfm->cylinder;
else
drive->curcyl = drive->tracks-1;
}
static void
do_callback(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
drive_t *drive = &mfm->drives[mfm->drvsel];
off64_t addr;
mfm->callback = 0LL;
if (mfm->reset) {
#if MFM_DEBUG
pclog("WD1003(%d) reset\n", mfm->drvsel);
#endif
mfm->status = STAT_READY|STAT_DSC;
mfm->error = 1;
mfm->secount = 1;
mfm->sector = 1;
mfm->head = 0;
mfm->cylinder = 0;
drive->steprate = 0x0f; /* default steprate */
drive->cfg_spt = 0; /* need new parameters */
mfm->reset = 0;
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
return;
}
switch (mfm->command) {
case CMD_SEEK:
#if MFM_DEBUG
pclog("WD1003(%d) seek, step=%d\n",
mfm->drvsel, drive->steprate);
#endif
do_seek(mfm);
mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
break;
case CMD_READ:
#if MFM_DEBUG
pclog("WD1003(%d) read(%d,%d,%d)\n",
mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector);
#endif
do_seek(mfm);
if (get_sector(mfm, &addr)) {
mfm->error = ERR_ID_NOT_FOUND;
mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
irq_raise(mfm);
break;
}
hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)mfm->buffer);
mfm->pos = 0;
mfm->status = STAT_DRQ|STAT_READY|STAT_DSC;
irq_raise(mfm);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
break;
case CMD_WRITE:
#if MFM_DEBUG
pclog("WD1003(%d) write(%d,%d,%d)\n",
mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector);
#endif
do_seek(mfm);
if (get_sector(mfm, &addr)) {
mfm->error = ERR_ID_NOT_FOUND;
mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
irq_raise(mfm);
break;
}
hdd_image_write(drive->hdd_num, addr, 1,(uint8_t *)mfm->buffer);
mfm->status = STAT_READY|STAT_DSC;
mfm->secount = (mfm->secount - 1) & 0xff;
if (mfm->secount) {
/* More sectors to do.. */
mfm->status |= STAT_DRQ;
mfm->pos = 0;
next_sector(mfm);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
} else {
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
}
irq_raise(mfm);
break;
case CMD_VERIFY:
#if MFM_DEBUG
pclog("WD1003(%d) verify(%d,%d,%d)\n",
mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector);
#endif
do_seek(mfm);
mfm->pos = 0;
mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
break;
case CMD_FORMAT:
#if MFM_DEBUG
pclog("WD1003(%d) format(%d,%d)\n",
mfm->drvsel, mfm->cylinder, mfm->head);
#endif
do_seek(mfm);
if (get_sector(mfm, &addr)) {
mfm->error = ERR_ID_NOT_FOUND;
mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
irq_raise(mfm);
break;
}
hdd_image_zero(drive->hdd_num, addr, mfm->secount);
mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
break;
case CMD_DIAGNOSE:
#if MFM_DEBUG
pclog("WD1003(%d) diag\n", mfm->drvsel);
#endif
drive->steprate = 0x0f;
mfm->error = 1;
mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
break;
default:
pclog("WD1003(%d) callback on unknown command %02x\n",
mfm->drvsel, mfm->command);
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
mfm->error = ERR_ABRT;
irq_raise(mfm);
break;
}
}
static void
loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
{
drive_t *drive = &mfm->drives[c];
if (! hdd_image_load(d)) {
drive->present = 0;
return;
}
drive->spt = hdd[d].spt;
drive->hpc = hdd[d].hpc;
drive->tracks = hdd[d].tracks;
drive->hdd_num = d;
drive->present = 1;
}
static void *
mfm_init(device_t *info)
{
mfm_t *mfm;
int c, d;
pclog("WD1003: ISA MFM/RLL Fixed Disk Adapter initializing ...\n");
mfm = malloc(sizeof(mfm_t));
memset(mfm, 0x00, sizeof(mfm_t));
c = 0;
for (d=0; d<HDD_NUM; d++) {
if ((hdd[d].bus == HDD_BUS_MFM) && (hdd[d].mfm_channel < MFM_NUM)) {
loadhd(mfm, hdd[d].mfm_channel, d, hdd[d].fn);
pclog("WD1003(%d): (%ls) geometry %d/%d/%d\n", c, hdd[d].fn,
(int)hdd[d].tracks, (int)hdd[d].hpc, (int)hdd[d].spt);
if (++c >= MFM_NUM) break;
}
}
mfm->status = STAT_READY|STAT_DSC; /* drive is ready */
mfm->error = 1; /* no errors */
io_sethandler(0x01f0, 1,
mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm);
io_sethandler(0x01f1, 7,
mfm_read, NULL, NULL, mfm_write, NULL, NULL, mfm);
io_sethandler(0x03f6, 1,
NULL, NULL, NULL, mfm_write, NULL, NULL, mfm);
timer_add(do_callback, &mfm->callback, &mfm->callback, mfm);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
return(mfm);
}
static void
mfm_close(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
int d;
for (d=0; d<2; d++) {
drive_t *drive = &mfm->drives[d];
hdd_image_close(drive->hdd_num);
}
free(mfm);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
}
device_t mfm_at_wd1003_device = {
"WD1003 AT MFM/RLL Controller",
DEVICE_ISA | DEVICE_AT,
0,
mfm_init, mfm_close, NULL,
NULL, NULL, NULL, NULL, NULL
};

921
src/disk/hdc_mfm_xt.c Normal file
View File

@@ -0,0 +1,921 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Driver for the IBM PC-XT Fixed Disk controller.
*
* The original controller shipped by IBM was made by Xebec, and
* several variations had been made:
*
* #1 Original, single drive (ST412), 10MB, 2 heads.
* #2 Update, single drive (ST412) but with option for a
* switch block that can be used to 'set' the actual
* drive type. Four switches are define, where switches
* 1 and 2 define drive0, and switches 3 and 4 drive1.
*
* 0 ON ON 306 2 0
* 1 ON OFF 375 8 0
* 2 OFF ON 306 6 256
* 3 OFF OFF 306 4 0
*
* The latter option is the default, in use on boards
* without the switch block option.
*
* #3 Another updated board, mostly to accomodate the new
* 20MB disk now being shipped. The controller can have
* up to 2 drives, the type of which is set using the
* switch block:
*
* SW1 SW2 CYLS HD SPT WPC
* 0 ON ON 306 4 17 0
* 1 ON OFF 612 4 17 0 (type 16)
* 2 OFF ON 615 4 17 300 (Seagate ST-225, 2)
* 3 OFF OFF 306 8 17 128 (IBM WD25, 13)
*
* Examples of #3 are IBM/Xebec, WD10004A-WX1 and ST11R.
*
* Since all controllers (including the ones made by DTC) use
* (mostly) the same API, we keep them all in this module.
*
* Version: @(#)hdd_mfm_xt.c 1.0.9 2017/10/11
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2017 Fred N. van Kempen.
*/
#define __USE_LARGEFILE64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../dma.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "../ui.h"
#include "hdc.h"
#include "hdd.h"
#define MFM_TIME (2000LL*TIMER_USEC)
#define XEBEC_BIOS_FILE L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin"
#define DTC_BIOS_FILE L"roms/hdd/mfm_xebec/dtc_cxd21a.bin"
enum {
STATE_IDLE,
STATE_RECEIVE_COMMAND,
STATE_START_COMMAND,
STATE_RECEIVE_DATA,
STATE_RECEIVED_DATA,
STATE_SEND_DATA,
STATE_SENT_DATA,
STATE_COMPLETION_BYTE,
STATE_DUNNO
};
typedef struct {
int spt, hpc;
int tracks;
int cfg_spt;
int cfg_hpc;
int cfg_cyl;
int current_cylinder;
int present;
int hdd_num;
} drive_t;
typedef struct {
rom_t bios_rom;
int64_t callback;
int state;
uint8_t status;
uint8_t command[6];
int command_pos;
uint8_t data[512];
int data_pos, data_len;
uint8_t sector_buf[512];
uint8_t irq_dma_mask;
uint8_t completion_byte;
uint8_t error;
int drive_sel;
drive_t drives[2];
int sector, head, cylinder;
int sector_count;
uint8_t switches;
} mfm_t;
#define STAT_IRQ 0x20
#define STAT_DRQ 0x10
#define STAT_BSY 0x08
#define STAT_CD 0x04
#define STAT_IO 0x02
#define STAT_REQ 0x01
#define IRQ_ENA 0x02
#define DMA_ENA 0x01
#define CMD_TEST_DRIVE_READY 0x00
#define CMD_RECALIBRATE 0x01
#define CMD_READ_STATUS 0x03
#define CMD_VERIFY_SECTORS 0x05
#define CMD_FORMAT_TRACK 0x06
#define CMD_READ_SECTORS 0x08
#define CMD_WRITE_SECTORS 0x0a
#define CMD_SEEK 0x0b
#define CMD_INIT_DRIVE_PARAMS 0x0c
#define CMD_WRITE_SECTOR_BUFFER 0x0f
#define CMD_BUFFER_DIAGNOSTIC 0xe0
#define CMD_CONTROLLER_DIAGNOSTIC 0xe4
#define CMD_DTC_GET_DRIVE_PARAMS 0xfb
#define CMD_DTC_SET_STEP_RATE 0xfc
#define CMD_DTC_SET_GEOMETRY 0xfe
#define CMD_DTC_GET_GEOMETRY 0xff
#define ERR_NOT_READY 0x04
#define ERR_SEEK_ERROR 0x15
#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21
static uint8_t
mfm_read(uint16_t port, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
uint8_t temp = 0xff;
switch (port) {
case 0x320: /*Read data*/
mfm->status &= ~STAT_IRQ;
switch (mfm->state) {
case STATE_COMPLETION_BYTE:
if ((mfm->status & 0xf) != (STAT_CD | STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", mfm->status);
temp = mfm->completion_byte;
mfm->status = 0;
mfm->state = STATE_IDLE;
break;
case STATE_SEND_DATA:
if ((mfm->status & 0xf) != (STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", mfm->status);
if (mfm->data_pos >= mfm->data_len)
fatal("Data write with full data!\n");
temp = mfm->data[mfm->data_pos++];
if (mfm->data_pos == mfm->data_len) {
mfm->status = STAT_BSY;
mfm->state = STATE_SENT_DATA;
mfm->callback = MFM_TIME;
}
break;
default:
fatal("Read data register - %i, %02x\n", mfm->state, mfm->status);
}
break;
case 0x321: /*Read status*/
temp = mfm->status;
break;
case 0x322: /*Read option jumpers*/
temp = mfm->switches;
break;
}
return(temp);
}
static void
mfm_write(uint16_t port, uint8_t val, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
switch (port) {
case 0x320: /*Write data*/
switch (mfm->state) {
case STATE_RECEIVE_COMMAND:
if ((mfm->status & 0xf) != (STAT_BSY | STAT_CD | STAT_REQ))
fatal("Bad write data state - STATE_START_COMMAND, status=%02x\n", mfm->status);
if (mfm->command_pos >= 6)
fatal("Command write with full command!\n");
/*Command data*/
mfm->command[mfm->command_pos++] = val;
if (mfm->command_pos == 6) {
mfm->status = STAT_BSY;
mfm->state = STATE_START_COMMAND;
mfm->callback = MFM_TIME;
}
break;
case STATE_RECEIVE_DATA:
if ((mfm->status & 0xf) != (STAT_BSY | STAT_REQ))
fatal("Bad write data state - STATE_RECEIVE_DATA, status=%02x\n", mfm->status);
if (mfm->data_pos >= mfm->data_len)
fatal("Data write with full data!\n");
/*Command data*/
mfm->data[mfm->data_pos++] = val;
if (mfm->data_pos == mfm->data_len) {
mfm->status = STAT_BSY;
mfm->state = STATE_RECEIVED_DATA;
mfm->callback = MFM_TIME;
}
break;
default:
fatal("Write data unknown state - %i %02x\n", mfm->state, mfm->status);
}
break;
case 0x321: /*Controller reset*/
mfm->status = 0;
break;
case 0x322: /*Generate controller-select-pulse*/
mfm->status = STAT_BSY | STAT_CD | STAT_REQ;
mfm->command_pos = 0;
mfm->state = STATE_RECEIVE_COMMAND;
break;
case 0x323: /*DMA/IRQ mask register*/
mfm->irq_dma_mask = val;
break;
}
}
static void mfm_complete(mfm_t *mfm)
{
mfm->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY;
mfm->state = STATE_COMPLETION_BYTE;
if (mfm->irq_dma_mask & IRQ_ENA) {
mfm->status |= STAT_IRQ;
picint(1 << 5);
}
}
static void
mfm_error(mfm_t *mfm, uint8_t error)
{
mfm->completion_byte |= 0x02;
mfm->error = error;
pclog("mfm_error - %02x\n", mfm->error);
}
static int
get_sector(mfm_t *mfm, off64_t *addr)
{
drive_t *drive = &mfm->drives[mfm->drive_sel];
int heads = drive->cfg_hpc;
if (drive->current_cylinder != mfm->cylinder) {
pclog("mfm_get_sector: wrong cylinder\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
if (mfm->head > heads) {
pclog("mfm_get_sector: past end of configured heads\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
if (mfm->head > drive->hpc) {
pclog("mfm_get_sector: past end of heads\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
if (mfm->sector >= 17) {
pclog("mfm_get_sector: past end of sectors\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
*addr = ((((off64_t) mfm->cylinder * heads) + mfm->head) *
17) + mfm->sector;
return(0);
}
static void
next_sector(mfm_t *mfm)
{
drive_t *drive = &mfm->drives[mfm->drive_sel];
mfm->sector++;
if (mfm->sector >= 17) {
mfm->sector = 0;
mfm->head++;
if (mfm->head >= drive->cfg_hpc) {
mfm->head = 0;
mfm->cylinder++;
drive->current_cylinder++;
if (drive->current_cylinder >= drive->cfg_cyl)
drive->current_cylinder = drive->cfg_cyl-1;
}
}
}
static void
mfm_callback(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
drive_t *drive;
off64_t addr;
mfm->callback = 0LL;
mfm->drive_sel = (mfm->command[1] & 0x20) ? 1 : 0;
mfm->completion_byte = mfm->drive_sel & 0x20;
drive = &mfm->drives[mfm->drive_sel];
switch (mfm->command[0]) {
case CMD_TEST_DRIVE_READY:
if (!drive->present)
mfm_error(mfm, ERR_NOT_READY);
mfm_complete(mfm);
break;
case CMD_RECALIBRATE:
if (!drive->present)
mfm_error(mfm, ERR_NOT_READY);
else {
mfm->cylinder = 0;
drive->current_cylinder = 0;
}
mfm_complete(mfm);
break;
case CMD_READ_STATUS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 4;
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
mfm->data[0] = mfm->error;
mfm->data[1] = mfm->drive_sel ? 0x20 : 0;
mfm->data[2] = mfm->data[3] = 0;
mfm->error = 0;
break;
case STATE_SENT_DATA:
mfm_complete(mfm);
break;
}
break;
case CMD_VERIFY_SECTORS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
mfm->sector = mfm->command[2] & 0x1f;
mfm->sector_count = mfm->command[4];
do {
if (get_sector(mfm, &addr)) {
pclog("get_sector failed\n");
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
next_sector(mfm);
mfm->sector_count = (mfm->sector_count-1) & 0xff;
} while (mfm->sector_count);
mfm_complete(mfm);
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1);
break;
default:
fatal("CMD_VERIFY_SECTORS: bad state %i\n", mfm->state);
}
break;
case CMD_FORMAT_TRACK:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
if (get_sector(mfm, &addr)) {
pclog("get_sector failed\n");
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_zero(drive->hdd_num, addr, 17);
mfm_complete(mfm);
break;
case CMD_READ_SECTORS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
mfm->sector = mfm->command[2] & 0x1f;
mfm->sector_count = mfm->command[4];
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 512;
if (get_sector(mfm, &addr)) {
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_read(drive->hdd_num, addr, 1,
(uint8_t *) mfm->sector_buf);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else {
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(mfm->data, mfm->sector_buf, 512);
}
break;
case STATE_SEND_DATA:
mfm->status = STAT_BSY;
if (mfm->irq_dma_mask & DMA_ENA) {
for (; mfm->data_pos < 512; mfm->data_pos++) {
int val = dma_channel_write(3, mfm->sector_buf[mfm->data_pos]);
if (val == DMA_NODATA) {
pclog("CMD_READ_SECTORS out of data!\n");
mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
mfm->callback = MFM_TIME;
return;
}
}
mfm->state = STATE_SENT_DATA;
mfm->callback = MFM_TIME;
} else
fatal("Read sectors no DMA! - shouldn't get here\n");
break;
case STATE_SENT_DATA:
next_sector(mfm);
mfm->data_pos = 0;
mfm->sector_count = (mfm->sector_count-1) & 0xff;
if (mfm->sector_count) {
if (get_sector(mfm, &addr)) {
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_read(drive->hdd_num, addr, 1,
(uint8_t *) mfm->sector_buf);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
mfm->state = STATE_SEND_DATA;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else {
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(mfm->data, mfm->sector_buf, 512);
}
} else {
mfm_complete(mfm);
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
}
break;
default:
fatal("CMD_READ_SECTORS: bad state %i\n", mfm->state);
}
break;
case CMD_WRITE_SECTORS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
mfm->sector = mfm->command[2] & 0x1f;
mfm->sector_count = mfm->command[4];
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 512;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
mfm->status = STAT_BSY;
if (mfm->irq_dma_mask & DMA_ENA) {
for (; mfm->data_pos < 512; mfm->data_pos++) {
int val = dma_channel_read(3);
if (val == DMA_NODATA) {
pclog("CMD_WRITE_SECTORS out of data!\n");
mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
mfm->callback = MFM_TIME;
return;
}
mfm->sector_buf[mfm->data_pos] = val & 0xff;
}
mfm->state = STATE_RECEIVED_DATA;
mfm->callback = MFM_TIME;
} else
fatal("Write sectors no DMA! - should never get here\n");
break;
case STATE_RECEIVED_DATA:
if (! (mfm->irq_dma_mask & DMA_ENA))
memcpy(mfm->sector_buf, mfm->data, 512);
if (get_sector(mfm, &addr))
{
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_write(drive->hdd_num, addr, 1,
(uint8_t *) mfm->sector_buf);
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
next_sector(mfm);
mfm->data_pos = 0;
mfm->sector_count = (mfm->sector_count-1) & 0xff;
if (mfm->sector_count) {
mfm->state = STATE_RECEIVE_DATA;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else
mfm->status = STAT_BSY | STAT_REQ;
} else
mfm_complete(mfm);
break;
default:
fatal("CMD_WRITE_SECTORS: bad state %i\n", mfm->state);
}
break;
case CMD_SEEK:
if (! drive->present)
mfm_error(mfm, ERR_NOT_READY);
else {
int cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : cylinder;
if (cylinder != drive->current_cylinder)
mfm_error(mfm, ERR_SEEK_ERROR);
}
mfm_complete(mfm);
break;
case CMD_INIT_DRIVE_PARAMS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 8;
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
drive->cfg_cyl = mfm->data[1] | (mfm->data[0] << 8);
drive->cfg_hpc = mfm->data[2];
pclog("Drive %i: cylinders=%i, heads=%i\n", mfm->drive_sel, drive->cfg_cyl, drive->cfg_hpc);
mfm_complete(mfm);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", mfm->state);
}
break;
case CMD_WRITE_SECTOR_BUFFER:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 512;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
if (mfm->irq_dma_mask & DMA_ENA) {
mfm->status = STAT_BSY;
for (; mfm->data_pos < 512; mfm->data_pos++) {
int val = dma_channel_read(3);
if (val == DMA_NODATA) {
pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n");
mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
mfm->callback = MFM_TIME;
return;
}
mfm->data[mfm->data_pos] = val & 0xff;
}
mfm->state = STATE_RECEIVED_DATA;
mfm->callback = MFM_TIME;
} else
fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n");
break;
case STATE_RECEIVED_DATA:
memcpy(mfm->sector_buf, mfm->data, 512);
mfm_complete(mfm);
break;
default:
fatal("CMD_WRITE_SECTOR_BUFFER bad state %i\n", mfm->state);
}
break;
case CMD_BUFFER_DIAGNOSTIC:
case CMD_CONTROLLER_DIAGNOSTIC:
mfm_complete(mfm);
break;
case 0xfa:
mfm_complete(mfm);
break;
case CMD_DTC_SET_STEP_RATE:
mfm_complete(mfm);
break;
case CMD_DTC_GET_DRIVE_PARAMS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 4;
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(mfm->data, 0, 4);
mfm->data[0] = drive->tracks & 0xff;
mfm->data[1] = 17 | ((drive->tracks >> 2) & 0xc0);
mfm->data[2] = drive->hpc-1;
pclog("Get drive params %02x %02x %02x %i\n", mfm->data[0], mfm->data[1], mfm->data[2], drive->tracks);
break;
case STATE_SENT_DATA:
mfm_complete(mfm);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", mfm->state);
}
break;
case CMD_DTC_GET_GEOMETRY:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 16;
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(mfm->data, 0, 16);
mfm->data[0x4] = drive->tracks & 0xff;
mfm->data[0x5] = (drive->tracks >> 8) & 0xff;
mfm->data[0xa] = drive->hpc;
break;
case STATE_SENT_DATA:
mfm_complete(mfm);
break;
}
break;
case CMD_DTC_SET_GEOMETRY:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 16;
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
/*Bit of a cheat here - we always report the actual geometry of the drive in use*/
mfm_complete(mfm);
break;
}
break;
default:
fatal("Unknown Xebec command - %02x %02x %02x %02x %02x %02x\n",
mfm->command[0], mfm->command[1],
mfm->command[2], mfm->command[3],
mfm->command[4], mfm->command[5]);
}
}
static void
loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
{
drive_t *drive = &mfm->drives[d];
if (! hdd_image_load(d)) {
drive->present = 0;
return;
}
drive->spt = hdd[c].spt;
drive->hpc = hdd[c].hpc;
drive->tracks = hdd[c].tracks;
drive->hdd_num = c;
drive->present = 1;
}
static struct {
int tracks, hpc;
} hd_types[4] = {
{ 306, 4 }, /* Type 0 */
{ 612, 4 }, /* Type 16 */
{ 615, 4 }, /* Type 2 */
{ 306, 8 } /* Type 13 */
};
static void
mfm_set_switches(mfm_t *mfm)
{
int c, d;
mfm->switches = 0;
for (d=0; d<2; d++) {
drive_t *drive = &mfm->drives[d];
if (! drive->present) continue;
for (c=0; c<4; c++) {
if (drive->spt == 17 &&
drive->hpc == hd_types[c].hpc &&
drive->tracks == hd_types[c].tracks) {
mfm->switches |= (c << (d ? 0 : 2));
break;
}
}
if (c == 4)
pclog("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C');
}
}
static void *
xebec_init(device_t *info)
{
int i, c = 0;
mfm_t *xebec = malloc(sizeof(mfm_t));
memset(xebec, 0x00, sizeof(mfm_t));
for (i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) {
loadhd(xebec, i, hdd[i].mfm_channel, hdd[i].fn);
if (++c > MFM_NUM) break;
}
}
mfm_set_switches(xebec);
rom_init(&xebec->bios_rom, XEBEC_BIOS_FILE,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 4,
mfm_read, NULL, NULL, mfm_write, NULL, NULL, xebec);
timer_add(mfm_callback, &xebec->callback, &xebec->callback, xebec);
return(xebec);
}
static void
mfm_close(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
int d;
for (d=0; d<2; d++) {
drive_t *drive = &mfm->drives[d];
hdd_image_close(drive->hdd_num);
}
free(mfm);
}
static int
xebec_available(void)
{
return(rom_present(XEBEC_BIOS_FILE));
}
device_t mfm_xt_xebec_device = {
"IBM PC Fixed Disk Adapter",
DEVICE_ISA,
0,
xebec_init, mfm_close, NULL,
xebec_available, NULL, NULL, NULL,
NULL
};
static void *
dtc5150x_init(device_t *info)
{
int i, c = 0;
mfm_t *dtc = malloc(sizeof(mfm_t));
memset(dtc, 0x00, sizeof(mfm_t));
for (i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) {
loadhd(dtc, i, hdd[i].mfm_channel, hdd[i].fn);
if (++c > MFM_NUM) break;
}
}
dtc->switches = 0xff;
dtc->drives[0].cfg_cyl = dtc->drives[0].tracks;
dtc->drives[0].cfg_hpc = dtc->drives[0].hpc;
dtc->drives[1].cfg_cyl = dtc->drives[1].tracks;
dtc->drives[1].cfg_hpc = dtc->drives[1].hpc;
rom_init(&dtc->bios_rom, DTC_BIOS_FILE,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 4,
mfm_read, NULL, NULL, mfm_write, NULL, NULL, dtc);
timer_add(mfm_callback, &dtc->callback, &dtc->callback, dtc);
return(dtc);
}
static int
dtc5150x_available(void)
{
return(rom_present(DTC_BIOS_FILE));
}
device_t mfm_xt_dtc5150x_device = {
"DTC 5150X",
DEVICE_ISA,
0,
dtc5150x_init, mfm_close, NULL,
dtc5150x_available, NULL, NULL, NULL,
NULL
};

272
src/disk/hdc_xtide.c Normal file
View File

@@ -0,0 +1,272 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* XT-IDE controller emulation.
*
* The XT-IDE project is intended to allow 8-bit ("XT") systems
* to use regular IDE drives. IDE is a standard based on the
* 16b PC/AT design, and so a special board (with its own BIOS)
* had to be created for this.
*
* XT-IDE is *NOT* the same as XTA, or X-IDE, which is an older
* standard where the actual MFM/RLL controller for the PC/XT
* was placed on the hard drive (hard drives where its drive
* type would end in "X" or "XT", such as the 8425XT.) This was
* more or less the original IDE, but since those systems were
* already on their way out, the newer IDE standard based on the
* PC/AT controller and 16b design became the IDE we now know.
*
* Version: @(#)hdc_xtide.c 1.0.8 2017/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../device.h"
#include "hdc.h"
#include "hdc_ide.h"
#define ROM_PATH_XT L"roms/hdd/xtide/ide_xt.bin"
#define ROM_PATH_AT L"roms/hdd/xtide/ide_at.bin"
#define ROM_PATH_PS2 L"roms/hdd/xtide/SIDE1V12.BIN"
#define ROM_PATH_PS2AT L"roms/hdd/xtide/ide_at_1_1_5.bin"
typedef struct {
uint8_t data_high;
rom_t bios_rom;
} xtide_t;
static void
xtide_write(uint16_t port, uint8_t val, void *priv)
{
xtide_t *xtide = (xtide_t *)priv;
switch (port & 0xf) {
case 0x0:
writeidew(4, val | (xtide->data_high << 8));
return;
case 0x1:
case 0x2:
case 0x3:
case 0x4:
case 0x5:
case 0x6:
case 0x7:
writeide(4, (port & 0xf) | 0x1f0, val);
return;
case 0x8:
xtide->data_high = val;
return;
case 0xe:
writeide(4, 0x3f6, val);
return;
}
}
static uint8_t
xtide_read(uint16_t port, void *priv)
{
xtide_t *xtide = (xtide_t *)priv;
uint16_t tempw = 0xffff;
switch (port & 0xf) {
case 0x0:
tempw = readidew(4);
xtide->data_high = tempw >> 8;
break;
case 0x1:
case 0x2:
case 0x3:
case 0x4:
case 0x5:
case 0x6:
case 0x7:
tempw = readide(4, (port & 0xf) | 0x1f0);
break;
case 0x8:
tempw = xtide->data_high;
break;
case 0xe:
tempw = readide(4, 0x3f6);
break;
default:
break;
}
return(tempw & 0xff);
}
static void *
xtide_init(device_t *info)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, ROM_PATH_XT,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0300, 16,
xtide_read, NULL, NULL,
xtide_write, NULL, NULL, xtide);
return(xtide);
}
static int
xtide_available(void)
{
return(rom_present(ROM_PATH_XT));
}
static void *
xtide_at_init(device_t *info)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, ROM_PATH_AT,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return(xtide);
}
static int
xtide_at_available(void)
{
return(rom_present(ROM_PATH_AT));
}
static void *
xtide_ps2_init(device_t *info)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, ROM_PATH_PS2,
0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0360, 16,
xtide_read, NULL, NULL,
xtide_write, NULL, NULL, xtide);
return(xtide);
}
static int
xtide_ps2_available(void)
{
return(rom_present(ROM_PATH_PS2));
}
static void *
xtide_at_ps2_init(device_t *info)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, ROM_PATH_PS2AT,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return(xtide);
}
static int
xtide_at_ps2_available(void)
{
return(rom_present(ROM_PATH_PS2AT));
}
static void
xtide_close(void *priv)
{
xtide_t *xtide = (xtide_t *)priv;
free(xtide);
}
device_t xtide_device = {
"XTIDE",
DEVICE_ISA,
0,
xtide_init, xtide_close, NULL,
xtide_available, NULL, NULL, NULL,
NULL
};
device_t xtide_at_device = {
"XTIDE (AT)",
DEVICE_ISA | DEVICE_AT,
0,
xtide_at_init, xtide_close, NULL,
xtide_at_available, NULL, NULL, NULL,
NULL
};
device_t xtide_ps2_device = {
"XTIDE (Acculogic)",
DEVICE_ISA,
0,
xtide_ps2_init, xtide_close, NULL,
xtide_ps2_available, NULL, NULL, NULL,
NULL
};
device_t xtide_at_ps2_device = {
"XTIDE (AT) (1.1.5)",
DEVICE_ISA | DEVICE_PS2,
0,
xtide_at_ps2_init, xtide_close, NULL,
xtide_at_ps2_available, NULL, NULL, NULL,
NULL
};

173
src/disk/hdd.c Normal file
View File

@@ -0,0 +1,173 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Common code to handle all sorts of hard disk images.
*
* Version: @(#)hdd.c 1.0.4 2017/10/09
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../ui.h"
#include "hdd.h"
hard_disk_t hdd[HDD_NUM];
int
hdd_init(void)
{
/* Clear all global data. */
memset(hdd, 0x00, sizeof(hdd));
return(0);
}
int
hdd_string_to_bus(char *str, int cdrom)
{
if (! strcmp(str, "none"))
return(HDD_BUS_DISABLED);
if (! strcmp(str, "mfm")) {
if (cdrom) {
no_cdrom:
ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4114);
return(0);
}
return(HDD_BUS_MFM);
}
/* FIXME: delete 'rll' in a year or so.. --FvK */
if (!strcmp(str, "esdi") || !strcmp(str, "rll")) {
if (cdrom) goto no_cdrom;
return(HDD_BUS_ESDI);
}
if (! strcmp(str, "ide_pio_only"))
return(HDD_BUS_IDE_PIO_ONLY);
if (! strcmp(str, "ide"))
return(HDD_BUS_IDE_PIO_ONLY);
if (! strcmp(str, "atapi_pio_only"))
return(HDD_BUS_IDE_PIO_ONLY);
if (! strcmp(str, "atapi"))
return(HDD_BUS_IDE_PIO_ONLY);
if (! strcmp(str, "eide"))
return(HDD_BUS_IDE_PIO_ONLY);
if (! strcmp(str, "xtide"))
return(HDD_BUS_XTIDE);
if (! strcmp(str, "atide"))
return(HDD_BUS_IDE_PIO_ONLY);
if (! strcmp(str, "ide_pio_and_dma"))
return(HDD_BUS_IDE_PIO_AND_DMA);
if (! strcmp(str, "atapi_pio_and_dma"))
return(HDD_BUS_IDE_PIO_AND_DMA);
if (! strcmp(str, "scsi"))
return(HDD_BUS_SCSI);
if (! strcmp(str, "removable")) {
if (cdrom) goto no_cdrom;
return(HDD_BUS_SCSI_REMOVABLE);
}
if (! strcmp(str, "scsi_removable")) {
if (cdrom) goto no_cdrom;
return(HDD_BUS_SCSI_REMOVABLE);
}
if (! strcmp(str, "removable_scsi")) {
if (cdrom) goto no_cdrom;
return(HDD_BUS_SCSI_REMOVABLE);
}
if (! strcmp(str, "usb"))
ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4110);
return(0);
}
char *
hdd_bus_to_string(int bus, int cdrom)
{
char *s = "none";
switch (bus) {
case HDD_BUS_DISABLED:
default:
break;
case HDD_BUS_MFM:
s = "mfm";
break;
case HDD_BUS_XTIDE:
s = "xtide";
break;
case HDD_BUS_ESDI:
s = "esdi";
break;
case HDD_BUS_IDE_PIO_ONLY:
s = cdrom ? "atapi_pio_only" : "ide_pio_only";
break;
case HDD_BUS_IDE_PIO_AND_DMA:
s = cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma";
break;
case HDD_BUS_SCSI:
s = "scsi";
break;
case HDD_BUS_SCSI_REMOVABLE:
s = "scsi_removable";
break;
}
return(s);
}
int
hdd_is_valid(int c)
{
if (hdd[c].bus == HDD_BUS_DISABLED) return(0);
if ((wcslen(hdd[c].fn) == 0) &&
(hdd[c].bus != HDD_BUS_SCSI_REMOVABLE)) return(0);
if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0)) return(0);
return(1);
}

96
src/disk/hdd.h Normal file
View File

@@ -0,0 +1,96 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the hard disk image handler.
*
* Version: @(#)hdd.h 1.0.3 2017/10/05
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#ifndef EMU_HDD_H
# define EMU_HDD_H
#define HDD_NUM 30 /* total of 30 images supported */
/* Hard Disk bus types. */
enum {
HDD_BUS_DISABLED = 0,
HDD_BUS_MFM,
HDD_BUS_XTIDE,
HDD_BUS_ESDI,
HDD_BUS_IDE_PIO_ONLY,
HDD_BUS_IDE_PIO_AND_DMA,
HDD_BUS_SCSI,
HDD_BUS_SCSI_REMOVABLE,
HDD_BUS_USB
};
/* Define the virtual Hard Disk. */
typedef struct {
int8_t is_hdi; /* image type (should rename) */
int8_t wp; /* disk has been mounted READ-ONLY */
uint8_t bus;
uint8_t mfm_channel; /* should rename and/or unionize */
uint8_t esdi_channel;
uint8_t xtide_channel;
uint8_t ide_channel;
uint8_t scsi_id;
uint8_t scsi_lun;
uint32_t base;
uint64_t spt,
hpc, /* physical geometry parameters */
tracks;
uint64_t at_spt, /* [Translation] parameters */
at_hpc;
FILE *f; /* current file handle to image */
wchar_t fn[260]; /* name of current image file */
wchar_t prev_fn[260]; /* name of previous image file */
} hard_disk_t;
extern hard_disk_t hdd[HDD_NUM];
extern uint64_t hdd_table[128][3];
extern int hdd_init(void);
extern int hdd_string_to_bus(char *str, int cdrom);
extern char *hdd_bus_to_string(int bus, int cdrom);
extern int hdd_is_valid(int c);
extern int hdd_image_load(int id);
extern void hdd_image_seek(uint8_t id, uint32_t sector);
extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count);
extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count);
extern uint32_t hdd_image_get_last_sector(uint8_t id);
extern uint8_t hdd_image_get_type(uint8_t id);
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
extern void hdd_image_unload(uint8_t id, int fn_preserve);
extern void hdd_image_close(uint8_t id);
extern int image_is_hdi(const wchar_t *s);
extern int image_is_hdx(const wchar_t *s, int check_signature);
#endif /*EMU_HDD_H*/

View File

@@ -1,15 +1,37 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Handling of hard disk image files.
*
* Version: @(#)hdd_image.c 1.0.5 2017/11/13
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#include <errno.h>
#include "../ibm.h"
#include "hdd_ide_at.h"
#include "hdd_image.h"
#include "../plat.h"
#include "hdd.h"
typedef struct
{
@@ -20,11 +42,13 @@ typedef struct
uint8_t loaded;
} hdd_image_t;
hdd_image_t hdd_images[HDC_NUM];
hdd_image_t hdd_images[HDD_NUM];
static char empty_sector[512];
static char *empty_sector_1mb;
int hdd_image_do_log = 0;
void hdd_image_log(const char *format, ...)
@@ -41,6 +65,7 @@ void hdd_image_log(const char *format, ...)
#endif
}
int image_is_hdi(const wchar_t *s)
{
int len;
@@ -52,7 +77,7 @@ int image_is_hdi(const wchar_t *s)
return 0;
}
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcsicmp(ext, L".HDI") == 0)
if (! wcscasecmp(ext, L".HDI"))
{
return 1;
}
@@ -62,7 +87,9 @@ int image_is_hdi(const wchar_t *s)
}
}
int image_is_hdx(const wchar_t *s, int check_signature)
int
image_is_hdx(const wchar_t *s, int check_signature)
{
int len;
FILE *f;
@@ -76,11 +103,11 @@ int image_is_hdx(const wchar_t *s, int check_signature)
return 0;
}
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcsicmp(ext, L".HDX") == 0)
if (wcscasecmp(ext, L".HDX") == 0)
{
if (check_signature)
{
f = _wfopen(s, L"rb");
f = plat_fopen((wchar_t *)s, L"rb");
if (!f)
{
return 0;
@@ -114,6 +141,7 @@ int image_is_hdx(const wchar_t *s, int check_signature)
}
}
int hdd_image_load(int id)
{
uint32_t sector_size = 512;
@@ -123,7 +151,7 @@ int hdd_image_load(int id)
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t i = 0, s = 0, t = 0;
wchar_t *fn = hdc[id].fn;
wchar_t *fn = hdd[id].fn;
int is_hdx[2] = { 0, 0 };
memset(empty_sector, 0, sizeof(empty_sector));
@@ -132,8 +160,11 @@ int hdd_image_load(int id)
if (hdd_images[id].loaded)
{
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
if (hdd_images[id].file)
{
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
hdd_images[id].loaded = 0;
}
@@ -144,10 +175,10 @@ int hdd_image_load(int id)
if (fn[0] == '.')
{
hdd_image_log("File name starts with .\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
hdd_images[id].file = _wfopen(fn, L"rb+");
hdd_images[id].file = plat_fopen(fn, L"rb+");
if (hdd_images[id].file == NULL)
{
/* Failed to open existing hard disk image */
@@ -155,34 +186,34 @@ int hdd_image_load(int id)
{
/* Failed because it does not exist,
so try to create new file */
if (hdc[id].wp)
if (hdd[id].wp)
{
hdd_image_log("A write-protected image must exist\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
hdd_images[id].file = _wfopen(fn, L"wb+");
hdd_images[id].file = plat_fopen(fn, L"wb+");
if (hdd_images[id].file == NULL)
{
hdd_image_log("Unable to open image\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
else
{
if (image_is_hdi(fn))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
hdd_images[id].base = 0x1000;
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
fwrite(&full_size, 1, 4, hdd_images[id].file);
fwrite(&sector_size, 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].tracks), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
for (c = 0; c < 0x3f8; c++)
{
fwrite(&zero, 1, 4, hdd_images[id].file);
@@ -191,14 +222,14 @@ int hdd_image_load(int id)
}
else if (is_hdx[0])
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
hdd_images[id].base = 0x28;
fwrite(&signature, 1, 8, hdd_images[id].file);
fwrite(&full_size, 1, 8, hdd_images[id].file);
fwrite(&sector_size, 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].tracks), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
hdd_images[id].type = 2;
@@ -210,7 +241,7 @@ int hdd_image_load(int id)
hdd_images[id].last_sector = 0;
}
s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
goto prepare_new_hard_disk;
}
@@ -218,7 +249,7 @@ int hdd_image_load(int id)
{
/* Failed for another reason */
hdd_image_log("Failed for another reason\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
@@ -239,26 +270,26 @@ int hdd_image_load(int id)
hdd_image_log("HDI: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
fread(&spt, 1, 4, hdd_images[id].file);
fread(&hpc, 1, 4, hdd_images[id].file);
fread(&tracks, 1, 4, hdd_images[id].file);
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks))
{
hdd_image_log("HDI: Geometry mismatch\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
hdd[id].spt = spt;
hdd[id].hpc = hpc;
hdd[id].tracks = tracks;
hdd_images[id].type = 1;
}
else if (is_hdx[1])
@@ -274,33 +305,33 @@ int hdd_image_load(int id)
hdd_image_log("HDX: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
fread(&spt, 1, 4, hdd_images[id].file);
fread(&hpc, 1, 4, hdd_images[id].file);
fread(&tracks, 1, 4, hdd_images[id].file);
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks))
{
hdd_image_log("HDX: Geometry mismatch\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
fread(&(hdc[id].at_spt), 1, 4, hdd_images[id].file);
fread(&(hdc[id].at_hpc), 1, 4, hdd_images[id].file);
hdd[id].spt = spt;
hdd[id].hpc = hpc;
hdd[id].tracks = tracks;
fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
hdd_images[id].type = 2;
}
else
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
hdd_images[id].type = 0;
}
}
@@ -339,8 +370,9 @@ prepare_new_hard_disk:
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
return 1;
hdd_images[id].loaded = 1;
return 1;
}
void hdd_image_seek(uint8_t id, uint32_t sector)
@@ -477,17 +509,17 @@ void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt)
{
if (hdd_images[id].type == 2)
{
hdc[id].at_hpc = hpc;
hdc[id].at_spt = spt;
hdd[id].at_hpc = hpc;
hdd[id].at_spt = spt;
fseeko64(hdd_images[id].file, 0x20, SEEK_SET);
fwrite(&(hdc[id].at_spt), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].at_hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
}
}
void hdd_image_unload(uint8_t id, int fn_preserve)
{
if (wcslen(hdc[id].fn) == 0)
if (wcslen(hdd[id].fn) == 0)
{
return;
}
@@ -499,17 +531,15 @@ void hdd_image_unload(uint8_t id, int fn_preserve)
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
hdd_images[id].loaded = 0;
}
hdd_images[id].last_sector = -1;
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
if (fn_preserve)
{
wcscpy(hdc[id].prev_fn, hdc[id].fn);
}
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
wcscpy(hdd[id].prev_fn, hdd[id].fn);
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
}
void hdd_image_close(uint8_t id)
@@ -519,4 +549,5 @@ void hdd_image_close(uint8_t id)
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
hdd_images[id].loaded = 0;
}

177
src/disk/hdd_table.c Normal file
View File

@@ -0,0 +1,177 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
* Version: @(#)hdd_table.c 1.0.3 2017/09/30
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#include "../86box.h"
#include "../ibm.h"
#include "../io.h"
#include "../pic.h"
#include "../pci.h"
#include "../timer.h"
#include "hdd.h"
uint64_t hdd_table[128][3] = {
{ 306, 4, 17 }, /* 0 - 7 */
{ 615, 2, 17 },
{ 306, 4, 26 },
{ 1024, 2, 17 },
{ 697, 3, 17 },
{ 306, 8, 17 },
{ 614, 4, 17 },
{ 615, 4, 17 },
{ 670, 4, 17 }, /* 8 - 15 */
{ 697, 4, 17 },
{ 987, 3, 17 },
{ 820, 4, 17 },
{ 670, 5, 17 },
{ 697, 5, 17 },
{ 733, 5, 17 },
{ 615, 6, 17 },
{ 462, 8, 17 }, /* 016-023 */
{ 306, 8, 26 },
{ 615, 4, 26 },
{ 1024, 4, 17 },
{ 855, 5, 17 },
{ 925, 5, 17 },
{ 932, 5, 17 },
{ 1024, 2, 40 },
{ 809, 6, 17 }, /* 024-031 */
{ 976, 5, 17 },
{ 977, 5, 17 },
{ 698, 7, 17 },
{ 699, 7, 17 },
{ 981, 5, 17 },
{ 615, 8, 17 },
{ 989, 5, 17 },
{ 820, 4, 26 }, /* 032-039 */
{ 1024, 5, 17 },
{ 733, 7, 17 },
{ 754, 7, 17 },
{ 733, 5, 26 },
{ 940, 6, 17 },
{ 615, 6, 26 },
{ 462, 8, 26 },
{ 830, 7, 17 }, /* 040-047 */
{ 855, 7, 17 },
{ 751, 8, 17 },
{ 1024, 4, 26 },
{ 918, 7, 17 },
{ 925, 7, 17 },
{ 855, 5, 26 },
{ 977, 7, 17 },
{ 987, 7, 17 }, /* 048-055 */
{ 1024, 7, 17 },
{ 823, 4, 38 },
{ 925, 8, 17 },
{ 809, 6, 26 },
{ 976, 5, 26 },
{ 977, 5, 26 },
{ 698, 7, 26 },
{ 699, 7, 26 }, /* 056-063 */
{ 940, 8, 17 },
{ 615, 8, 26 },
{ 1024, 5, 26 },
{ 733, 7, 26 },
{ 1024, 8, 17 },
{ 823, 10, 17 },
{ 754, 11, 17 },
{ 830, 10, 17 }, /* 064-071 */
{ 925, 9, 17 },
{ 1224, 7, 17 },
{ 940, 6, 26 },
{ 855, 7, 26 },
{ 751, 8, 26 },
{ 1024, 9, 17 },
{ 965, 10, 17 },
{ 969, 5, 34 }, /* 072-079 */
{ 980, 10, 17 },
{ 960, 5, 35 },
{ 918, 11, 17 },
{ 1024, 10, 17 },
{ 977, 7, 26 },
{ 1024, 7, 26 },
{ 1024, 11, 17 },
{ 940, 8, 26 }, /* 080-087 */
{ 776, 8, 33 },
{ 755, 16, 17 },
{ 1024, 12, 17 },
{ 1024, 8, 26 },
{ 823, 10, 26 },
{ 830, 10, 26 },
{ 925, 9, 26 },
{ 960, 9, 26 }, /* 088-095 */
{ 1024, 13, 17 },
{ 1224, 11, 17 },
{ 900, 15, 17 },
{ 969, 7, 34 },
{ 917, 15, 17 },
{ 918, 15, 17 },
{ 1524, 4, 39 },
{ 1024, 9, 26 }, /* 096-103 */
{ 1024, 14, 17 },
{ 965, 10, 26 },
{ 980, 10, 26 },
{ 1020, 15, 17 },
{ 1023, 15, 17 },
{ 1024, 15, 17 },
{ 1024, 16, 17 },
{ 1224, 15, 17 }, /* 104-111 */
{ 755, 16, 26 },
{ 903, 8, 46 },
{ 984, 10, 34 },
{ 900, 15, 26 },
{ 917, 15, 26 },
{ 1023, 15, 26 },
{ 684, 16, 38 },
{ 1930, 4, 62 }, /* 112-119 */
{ 967, 16, 31 },
{ 1013, 10, 63 },
{ 1218, 15, 36 },
{ 654, 16, 63 },
{ 659, 16, 63 },
{ 702, 16, 63 },
{ 1002, 13, 63 },
{ 854, 16, 63 }, /* 119-127 */
{ 987, 16, 63 },
{ 995, 16, 63 },
{ 1024, 16, 63 },
{ 1036, 16, 63 },
{ 1120, 16, 59 },
{ 1054, 16, 63 },
{ 0, 0, 0 }
};

View File

@@ -8,13 +8,17 @@
*
* Implementation of the Intel DMA controllers.
*
* Version: @(#)dma.c 1.0.2 2017/08/23
* Version: @(#)dma.c 1.0.3 2017/09/24
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "cpu/x86.h"
#include "mem.h"

View File

@@ -9,27 +9,32 @@
* Implementation of the NEC uPD-765 and compatible floppy disk
* controller.
*
* Version: @(#)fdc.c 1.0.2 2017/09/03
* Version: @(#)fdc.c 1.0.5 2017/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#include "../ibm.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../dma.h"
#include "../pic.h"
#include "../timer.h"
#include "../ui.h"
#include "floppy.h"
#include "fdc.h"
#include "fdd.h"
extern int motoron[FDD_NUM];
extern int64_t motoron[FDD_NUM];
int ui_writeprot[FDD_NUM] = {0, 0, 0, 0};
@@ -101,8 +106,8 @@ typedef struct FDC
int pcjr, ps1;
int watchdog_timer;
int watchdog_count;
int64_t watchdog_timer;
int64_t watchdog_count;
int data_ready;
int inread;
@@ -147,7 +152,7 @@ typedef struct FDC
uint16_t base_address;
} FDC;
int floppytime;
int64_t floppytime;
static FDC fdc;
@@ -388,10 +393,10 @@ static void fdc_watchdog_poll(void *p)
fdc->watchdog_count--;
if (fdc->watchdog_count)
fdc->watchdog_timer += 1000 * TIMER_USEC;
fdc->watchdog_timer += 1000LL * TIMER_USEC;
else
{
fdc->watchdog_timer = 0;
fdc->watchdog_timer = 0LL;
if (fdc->dor & 0x20)
picint(1 << 6);
}
@@ -663,17 +668,17 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
{
if ((fdc.dor & 0x40) && !(val & 0x40))
{
fdc.watchdog_timer = 1000 * TIMER_USEC;
fdc.watchdog_count = 1000;
fdc.watchdog_timer = 1000LL * TIMER_USEC;
fdc.watchdog_count = 1000LL;
picintc(1 << 6);
}
if ((val & 0x80) && !(fdc.dor & 0x80))
{
timer_process();
floppytime = 128 * (1 << TIMER_SHIFT);
floppytime = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
floppyint=-1;
update_status_bar_icon(SB_FLOPPY | 0, 0);
ui_sb_update_icon(SB_FLOPPY | 0, 0);
fdc_reset();
}
if (!fdd_get_flags(0))
@@ -703,14 +708,14 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
if ((val&4) && !(fdc.dor&4))
{
timer_process();
floppytime = 128 * (1 << TIMER_SHIFT);
floppytime = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
floppyint=-1;
fdc.perp &= 0xfc;
for (i = 0; i < FDD_NUM; i++)
{
update_status_bar_icon(SB_FLOPPY | i, 0);
ui_sb_update_icon(SB_FLOPPY | i, 0);
}
fdc_reset();
@@ -746,7 +751,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
if (val & 0x80)
{
timer_process();
floppytime = 128 * (1 << TIMER_SHIFT);
floppytime = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
floppyint=-1;
fdc.perp &= 0xfc;
@@ -927,7 +932,7 @@ bad_command:
fdc.stat |= 0x10;
floppyint=0xfc;
timer_process();
floppytime = 200 * (1 << TIMER_SHIFT);
floppytime = 200LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
}
@@ -953,7 +958,7 @@ bad_command:
fdc_log("Got all params %02X\n", fdc.command);
floppyint=fdc.command&0x1F;
timer_process();
floppytime = 1024 * (1 << TIMER_SHIFT);
floppytime = 1024LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc_reset_stat = 0;
switch (floppyint & 0x1F)
@@ -982,8 +987,8 @@ bad_command:
{
fdc.stat = 0x50;
}
floppytime = 0;
update_status_bar_icon(SB_FLOPPY | fdc.drive, 1);
floppytime = 0LL;
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1);
fdc.inread = 1;
break;
@@ -992,7 +997,7 @@ bad_command:
fdc.specify[0] = fdc.params[0];
fdc.specify[1] = fdc.params[1];
fdc.dma = (fdc.specify[1] & 1) ^ 1;
floppytime = 0;
floppytime = 0LL;
break;
case 0x12:
@@ -1006,7 +1011,7 @@ bad_command:
fdc.perp &= 0xfc;
fdc.perp |= (fdc.params[0] & 0x03);
}
floppytime = 0;
floppytime = 0LL;
return;
case 4:
@@ -1026,9 +1031,9 @@ bad_command:
fdc_implied_seek();
fdc.rw_track = fdc.params[1];
floppy_writesector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]);
floppytime = 0;
floppytime = 0LL;
fdc.written = 0;
update_status_bar_icon(SB_FLOPPY | fdc.drive, 1);
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1);
fdc.pos = 0;
if (fdc.pcjr)
fdc.stat = 0xb0;
@@ -1059,9 +1064,9 @@ bad_command:
fdc_implied_seek();
fdc.rw_track = fdc.params[1];
floppy_comparesector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]);
floppytime = 0;
floppytime = 0LL;
fdc.written = 0;
update_status_bar_icon(SB_FLOPPY | fdc.drive, 1);
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1);
fdc.pos = 0;
if (fdc.pcjr || !fdc.dma)
{
@@ -1104,15 +1109,15 @@ bad_command:
{
fdc.stat = 0x50;
}
floppytime = 0;
update_status_bar_icon(SB_FLOPPY | fdc.drive, 1);
floppytime = 0LL;
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1);
fdc.inread = 1;
break;
case 7: /*Recalibrate*/
seek_time_base = fdd_doublestep_40(real_drive(fdc.drive)) ? 10 : 5;
fdc.stat = (1 << real_drive(fdc.drive)) | 0x80;
floppytime = 0;
floppytime = 0LL;
drive_num = real_drive(fdc.drive);
@@ -1128,10 +1133,10 @@ bad_command:
fdc.st0 = 0x20 | (fdc.params[0] & 3);
}
fdc.pcn[fdc.params[0] & 3] = 0;
floppytime = 0;
floppytime = 0LL;
floppyint=-3;
timer_process();
floppytime = 2048 * (1 << TIMER_SHIFT);
floppytime = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
}
@@ -1140,7 +1145,7 @@ bad_command:
{
fdc_seek(fdc.drive, -fdc.max_track);
}
floppytime = fdc.max_track * seek_time_base * TIMER_USEC;
floppytime = ((int64_t) fdc.max_track) * ((int64_t) seek_time_base) * TIMER_USEC;
break;
case 0x0d: /*Format*/
@@ -1160,7 +1165,7 @@ bad_command:
fdc.stat = (1 << fdc.drive) | 0x80;
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
floppytime = 0;
floppytime = 0LL;
drive_num = real_drive(fdc.drive);
seek_time_base = fdd_doublestep_40(drive_num) ? 10 : 5;
@@ -1185,10 +1190,10 @@ bad_command:
{
fdc.pcn[fdc.params[0] & 3] = fdc.params[1];
}
floppytime = 0;
floppytime = 0LL;
floppyint=-3;
timer_process();
floppytime = 2048 * (1 << TIMER_SHIFT);
floppytime = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
}
@@ -1209,17 +1214,17 @@ bad_command:
fdc_seek(fdc.drive, -fdc.params[1]);
fdc.pcn[fdc.params[0] & 3] -= fdc.params[1];
}
floppytime = ((int) fdc.params[1]) * seek_time_base * TIMER_USEC;
floppytime = ((int64_t) fdc.params[1]) * ((int64_t) seek_time_base) * TIMER_USEC;
}
else
{
floppytime = seek_time_base * TIMER_USEC;
floppytime = ((int64_t) seek_time_base) * TIMER_USEC;
fdc.st0 = 0x20 | (fdc.params[0] & 7);
floppytime = 0;
floppytime = 0LL;
floppyint=-3;
timer_process();
floppytime = 2048 * (1 << TIMER_SHIFT);
floppytime = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
}
@@ -1232,10 +1237,10 @@ bad_command:
if ((fdc.params[1] - fdc.pcn[fdc.params[0] & 3]) == 0)
{
fdc.st0 = 0x20 | (fdc.params[0] & 7);
floppytime = 0;
floppytime = 0LL;
floppyint=-3;
timer_process();
floppytime = 2048 * (1 << TIMER_SHIFT);
floppytime = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
}
@@ -1243,13 +1248,13 @@ bad_command:
fdc_seek(fdc.drive, fdc.params[1] - fdc.pcn[fdc.params[0] & 3]);
fdc.pcn[fdc.params[0] & 3] = fdc.params[1];
if (seek_time < 0) seek_time = -seek_time;
floppytime = seek_time;
floppytime = ((int64_t) seek_time);
}
break;
case 10: /*Read sector ID*/
fdc_rate(fdc.drive);
floppytime = 0;
floppytime = 0LL;
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
if ((real_drive(fdc.drive) != 1) || fdc.drv2en)
@@ -1385,7 +1390,7 @@ uint8_t fdc_read(uint16_t addr, void *priv)
/* if (floppyint==0xA)
{
timer_process();
floppytime = 1024 * (1 << TIMER_SHIFT);
floppytime = 1024LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
} */
fdc.stat &= 0xf0;
@@ -1462,7 +1467,7 @@ void fdc_poll_common_finish(int compare, int st5)
fdc.res[9]=fdc.sector;
fdc.res[10]=fdc.params[4];
fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n" , fdc.res[4], fdc.res[5], fdc.res[6], fdc.res[7], fdc.res[8], fdc.res[9], fdc.res[10]);
update_status_bar_icon(SB_FLOPPY | fdc.drive, 0);
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0);
paramstogo=7;
}
@@ -1476,7 +1481,7 @@ void fdc_poll_readwrite_finish(int compare)
void fdc_no_dma_end(int compare)
{
floppytime = 0;
floppytime = 0LL;
fdc_poll_common_finish(compare, 0x80);
}
@@ -1486,7 +1491,7 @@ void fdc_callback(void *priv)
int compare = 0;
int drive_num = 0;
int old_sector = 0;
floppytime = 0;
floppytime = 0LL;
switch (floppyint)
{
case -3: /*End of command with interrupt*/
@@ -1508,7 +1513,7 @@ void fdc_callback(void *priv)
return;
case 2: /*Read track*/
update_status_bar_icon(SB_FLOPPY | fdc.drive, 1);
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1);
fdc.eot[fdc.drive]--;
fdc.read_track_sector.id.r++;
if (!fdc.eot[fdc.drive] || fdc.tc)
@@ -1544,7 +1549,7 @@ void fdc_callback(void *priv)
fdc.stat = (fdc.stat & 0xf) | 0xd0;
paramstogo = 1;
floppyint = 0;
floppytime = 0;
floppytime = 0LL;
return;
case 5: /*Write data*/
case 9: /*Write deleted data*/
@@ -1668,7 +1673,7 @@ void fdc_callback(void *priv)
{
fdc.sector++;
}
update_status_bar_icon(SB_FLOPPY | fdc.drive, 1);
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1);
switch (floppyint)
{
case 5:
@@ -1723,7 +1728,7 @@ void fdc_callback(void *priv)
}
floppyint=-3;
timer_process();
floppytime = 2048 * (1 << TIMER_SHIFT);
floppytime = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc.stat = 0x80 | (1 << fdc.drive);
return;
@@ -1761,7 +1766,7 @@ void fdc_callback(void *priv)
paramstogo = 2;
floppyint = 0;
floppytime = 0;
floppytime = 0LL;
return;
case 0x0d: /*Format track*/
@@ -1769,7 +1774,7 @@ void fdc_callback(void *priv)
{
fdc.format_state = 2;
timer_process();
floppytime = 128 * (1 << TIMER_SHIFT);
floppytime = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
}
else if (fdc.format_state == 2)
@@ -1800,7 +1805,7 @@ void fdc_callback(void *priv)
fdc.st0 = 0x20 | (fdc.params[0] & 7);
floppyint=-3;
timer_process();
floppytime = 2048 * (1 << TIMER_SHIFT);
floppytime = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc.stat = 0x80 | (1 << fdc.drive);
return;
@@ -1818,7 +1823,7 @@ void fdc_callback(void *priv)
fdc.res[10] = fdc.pretrk;
paramstogo = 10;
floppyint=0;
floppytime = 0;
floppytime = 0LL;
return;
case 0x10: /*Version*/
@@ -1826,7 +1831,7 @@ void fdc_callback(void *priv)
fdc.res[10] = 0x90;
paramstogo=1;
floppyint=0;
floppytime = 0;
floppytime = 0LL;
return;
case 0x13: /*Configure*/
@@ -1835,7 +1840,7 @@ void fdc_callback(void *priv)
fdc.fifo = (fdc.params[1] & 0x20) ? 0 : 1;
fdc.tfifo = (fdc.params[1] & 0xF);
fdc.stat = 0x80;
floppytime = 0;
floppytime = 0LL;
return;
case 0x14: /*Unlock*/
fdc.lock = 0;
@@ -1843,7 +1848,7 @@ void fdc_callback(void *priv)
fdc.res[10] = 0;
paramstogo=1;
floppyint=0;
floppytime = 0;
floppytime = 0LL;
return;
case 0x94: /*Lock*/
fdc.lock = 1;
@@ -1851,7 +1856,7 @@ void fdc_callback(void *priv)
fdc.res[10] = 0x10;
paramstogo=1;
floppyint=0;
floppytime = 0;
floppytime = 0LL;
return;
case 0x18: /*NSC*/
@@ -1859,7 +1864,7 @@ void fdc_callback(void *priv)
fdc.res[10] = 0x73;
paramstogo=1;
floppyint=0;
floppytime = 0;
floppytime = 0LL;
return;
case 0xfc: /*Invalid*/
@@ -1868,14 +1873,14 @@ void fdc_callback(void *priv)
fdc.res[10] = fdc.st0;
paramstogo=1;
floppyint=0;
floppytime = 0;
floppytime = 0LL;
return;
}
}
void fdc_error(int st5, int st6)
{
floppytime = 0;
floppytime = 0LL;
fdc_int();
fdc.fintr = 0;
@@ -1907,7 +1912,7 @@ void fdc_error(int st5, int st6)
fdc.res[10]=0;
break;
}
update_status_bar_icon(SB_FLOPPY | fdc.drive, 0);
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0);
paramstogo=7;
}
@@ -2138,7 +2143,7 @@ void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uin
fdc.res[8]=side;
fdc.res[9]=sector;
fdc.res[10]=size;
update_status_bar_icon(SB_FLOPPY | fdc.drive, 0);
ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0);
paramstogo=7;
}
@@ -2194,7 +2199,7 @@ void fdc_hard_reset()
for (i = 0; i < FDD_NUM; i++)
{
update_status_bar_icon(SB_FLOPPY | i, 0);
ui_sb_update_icon(SB_FLOPPY | i, 0);
}
}

View File

@@ -8,13 +8,17 @@
*
* Implementation of the floppy drive emulation.
*
* Version: @(#)fdd.c 1.0.2 2017/09/03
* Version: @(#)fdd.c 1.0.3 2017/09/24
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "floppy.h"
#include "fdc.h"

View File

@@ -19,9 +19,10 @@
#define STATIC_INLINE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
/* IF UAE */
/*#include "sysconfig.h"
@@ -37,7 +38,6 @@
#define VERBOSE
#undef VERBOSE
#include <assert.h>
#ifdef DEBUG
static char *datalog(uae_u8 *src, int len)
@@ -1608,7 +1608,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi
randval = rand();
if (randval < (RAND_MAX / 2)) {
if (randval > (RAND_MAX / 4)) {
if (randval <= (3 * RAND_MAX / 8))
if (randval <= (((3LL*RAND_MAX) / 8)))
randval = (2 * randval) - (RAND_MAX /4);
else
randval = (4 * randval) - RAND_MAX;
@@ -1617,7 +1617,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi
} else {
randval -= RAND_MAX / 2;
if (randval > (RAND_MAX / 4)) {
if (randval <= (3 * RAND_MAX / 8))
if (randval <= (((3LL*RAND_MAX) / 8)))
randval = (2 * randval) - (RAND_MAX /4);
else
randval = (4 * randval) - RAND_MAX;
@@ -1643,7 +1643,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi
randval = rand();
if (randval < (RAND_MAX / 2)) {
if (randval > (RAND_MAX / 4)) {
if (randval <= (3 * RAND_MAX / 8))
if (randval <= (((3LL*RAND_MAX) / 8)))
randval = (2 * randval) - (RAND_MAX /4);
else
randval = (4 * randval) - RAND_MAX;
@@ -1652,7 +1652,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi
} else {
randval -= RAND_MAX / 2;
if (randval > (RAND_MAX / 4)) {
if (randval <= (3 * RAND_MAX / 8))
if (randval <= (((3LL*RAND_MAX) / 8)))
randval = (2 * randval) - (RAND_MAX /4);
else
randval = (4 * randval) - RAND_MAX;

View File

@@ -9,18 +9,25 @@
* Generic floppy disk interface that communicates with the
* other handlers.
*
* Version: @(#)floppy.c 1.0.3 2017/09/12
* Version: @(#)floppy.c 1.0.8 2017/10/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../mem.h"
#include "../rom.h"
#include "../config.h"
#include "../timer.h"
#include "../plat.h"
#include "../ui.h"
#include "floppy.h"
#include "floppy_86f.h"
#include "floppy_fdi.h"
@@ -36,7 +43,7 @@ extern int driveempty[4];
wchar_t floppyfns[4][512];
int floppy_poll_time[FDD_NUM] = { 16, 16, 16, 16 };
int64_t floppy_poll_time[FDD_NUM] = { 16LL, 16LL, 16LL, 16LL };
int floppy_track[FDD_NUM];
int writeprot[FDD_NUM], fwriteprot[FDD_NUM];
@@ -60,7 +67,7 @@ int drive_empty[FDD_NUM] = {1, 1, 1, 1};
int floppy_changed[FDD_NUM];
int motorspin;
int motoron[FDD_NUM];
int64_t motoron[FDD_NUM];
int fdc_indexcount = 52;
@@ -130,14 +137,14 @@ void floppy_load(int drive, wchar_t *fn)
if (!fn) return;
p = get_extension_w(fn);
if (!p) return;
f = _wfopen(fn, L"rb");
f = plat_fopen(fn, L"rb");
if (!f) return;
fseek(f, -1, SEEK_END);
size = ftell(f) + 1;
fclose(f);
while (loaders[c].ext)
{
if (!_wcsicmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
if (!wcscasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
{
driveloaders[drive] = c;
memcpy(floppyfns[drive], fn, (wcslen(fn) << 1) + 2);
@@ -149,11 +156,11 @@ void floppy_load(int drive, wchar_t *fn)
}
c++;
}
pclog_w(L"Couldn't load %s %s\n",fn,p);
pclog("Couldn't load %ls %s\n",fn,p);
drive_empty[drive] = 1;
fdd_set_head(real_drive(drive), 0);
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
update_status_bar_icon_state(drive, 1);
ui_sb_update_icon_state(drive, 1);
}
void floppy_close(int drive)
@@ -172,7 +179,7 @@ void floppy_close(int drive)
drives[drive].format = NULL;
drives[drive].byteperiod = NULL;
drives[drive].stop = NULL;
update_status_bar_icon_state(drive, 1);
ui_sb_update_icon_state(drive, 1);
}
int floppy_notfound=0;
@@ -238,7 +245,7 @@ void floppy_poll(int drive)
fatal("Attempting to poll floppy drive %i that is not supposed to be there\n", drive);
}
floppy_poll_time[drive] += (int) floppy_real_period(drive);
floppy_poll_time[drive] += (int64_t) floppy_real_period(drive);
if (drives[drive].poll)
drives[drive].poll(drive);
@@ -404,3 +411,18 @@ void floppy_stop(int drive)
if (drives[drive].stop)
drives[drive].stop(drive);
}
void floppy_general_init(void)
{
floppy_init();
fdi_init();
img_init();
d86f_init();
td0_init();
imd_init();
floppy_load(0, floppyfns[0]);
floppy_load(1, floppyfns[1]);
floppy_load(2, floppyfns[2]);
floppy_load(3, floppyfns[3]);
}

View File

@@ -42,13 +42,14 @@ extern DRIVE drives[FDD_NUM];
extern int curdrive;
extern int floppy_time;
extern int floppy_poll_time[FDD_NUM];
extern int64_t floppy_poll_time[FDD_NUM];
extern void floppy_load(int drive, wchar_t *fn);
extern void floppy_new(int drive, char *fn);
extern void floppy_close(int drive);
extern void floppy_init(void);
extern void floppy_general_init(void);
extern void floppy_reset(void);
extern void floppy_poll(int drive);
extern void floppy_poll_0(void* priv);
@@ -87,7 +88,7 @@ extern int fdc_ready;
extern int fdc_indexcount;*/
extern int motorspin;
extern int motoron[FDD_NUM];
extern int64_t motoron[FDD_NUM];
extern int swwp;
extern int disable_write;

View File

@@ -10,23 +10,26 @@
* data in the form of FM/MFM-encoded transitions) which also
* forms the core of the emulator's floppy disk emulation.
*
* Version: @(#)floppy_86f.c 1.0.2 2017/09/03
* Version: @(#)floppy_86f.c 1.0.7 2017/10/12
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016,2017 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <wchar.h>
#include "../lzf/lzf.h"
#include "../ibm.h"
#include "../config.h"
#include "../dma.h"
#include "../nvr.h"
#include "../random.h"
#include "../plat.h"
#include "../ui.h"
#include "floppy.h"
#include "fdc.h"
#include "fdd.h"
@@ -3070,7 +3073,7 @@ void d86f_writeback(int drive)
/* The image is compressed. */
/* Open the original, compressed file. */
cf = _wfopen(d86f[drive].original_file_name, L"wb");
cf = plat_fopen(d86f[drive].original_file_name, L"wb");
/* Write the header to the original file. */
fwrite(header, 1, header_size, cf);
@@ -3362,10 +3365,10 @@ void d86f_load(int drive, wchar_t *fn)
d86f_unregister(drive);
writeprot[drive] = 0;
d86f[drive].f = _wfopen(fn, L"rb+");
d86f[drive].f = plat_fopen(fn, L"rb+");
if (!d86f[drive].f)
{
d86f[drive].f = _wfopen(fn, L"rb");
d86f[drive].f = plat_fopen(fn, L"rb");
if (!d86f[drive].f)
{
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
@@ -3423,7 +3426,7 @@ void d86f_load(int drive, wchar_t *fn)
}
fclose(d86f[drive].f);
d86f[drive].f = NULL;
update_status_bar_icon_state(drive, 1);
ui_sb_update_icon_state(drive, 1);
return;
}
else
@@ -3470,13 +3473,13 @@ void d86f_load(int drive, wchar_t *fn)
if (d86f[drive].is_compressed)
{
memcpy(temp_file_name, drive ? nvr_concat(L"TEMP$$$1.$$$") : nvr_concat(L"TEMP$$$0.$$$"), 256);
memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 256);
memcpy(d86f[drive].original_file_name, fn, (wcslen(fn) << 1) + 2);
fclose(d86f[drive].f);
d86f[drive].f = NULL;
d86f[drive].f = _wfopen(temp_file_name, L"wb");
d86f[drive].f = plat_fopen(temp_file_name, L"wb");
if (!d86f[drive].f)
{
d86f_log("86F: Unable to create temporary decompressed file\n");
@@ -3484,7 +3487,7 @@ void d86f_load(int drive, wchar_t *fn)
return;
}
tf = _wfopen(fn, L"rb");
tf = plat_fopen(fn, L"rb");
for (i = 0; i < 8; i++)
{
@@ -3510,12 +3513,12 @@ void d86f_load(int drive, wchar_t *fn)
if (!temp)
{
d86f_log("86F: Error decompressing file\n");
_wremove(temp_file_name);
plat_remove(temp_file_name);
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
return;
}
d86f[drive].f = _wfopen(temp_file_name, L"rb+");
d86f[drive].f = plat_fopen(temp_file_name, L"rb+");
}
if (d86f[drive].disk_flags & 0x100)
@@ -3526,7 +3529,7 @@ void d86f_load(int drive, wchar_t *fn)
d86f[drive].f = NULL;
if (d86f[drive].is_compressed)
{
_wremove(temp_file_name);
plat_remove(temp_file_name);
}
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
return;
@@ -3540,7 +3543,7 @@ void d86f_load(int drive, wchar_t *fn)
d86f[drive].f = NULL;
if (d86f[drive].is_compressed)
{
_wremove(temp_file_name);
plat_remove(temp_file_name);
}
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
return;
@@ -3559,11 +3562,11 @@ void d86f_load(int drive, wchar_t *fn)
if (d86f[drive].is_compressed)
{
d86f[drive].f = _wfopen(temp_file_name, L"rb");
d86f[drive].f = plat_fopen(temp_file_name, L"rb");
}
else
{
d86f[drive].f = _wfopen(fn, L"rb");
d86f[drive].f = plat_fopen(fn, L"rb");
}
}
@@ -3665,7 +3668,7 @@ void d86f_close(int drive)
{
wchar_t temp_file_name[2048];
memcpy(temp_file_name, drive ? nvr_concat(L"TEMP$$$1.$$$") : nvr_concat(L"TEMP$$$0.$$$"), 26);
memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 26);
if (d86f[drive].f)
{
@@ -3673,5 +3676,5 @@ void d86f_close(int drive)
d86f[drive].f = NULL;
}
if (d86f[drive].is_compressed)
_wremove(temp_file_name);
plat_remove(temp_file_name);
}

View File

@@ -8,12 +8,16 @@
*
* Shared code for all the floppy modules.
*
* Version: @(#)floppy_common.c 1.0.1 2017/09/10
* Version: @(#)floppy_common.c 1.0.2 2017/09/24
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2017 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../floppy/floppy.h"
#include "floppy_common.h"

View File

@@ -9,17 +9,20 @@
* Implementation of the FDI floppy stream image format
* interface to the FDI2RAW module.
*
* Version: @(#)floppy_fdi.c 1.0.1 2017/09/03
* Version: @(#)floppy_fdi.c 1.0.3 2017/10/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../plat.h"
#include "floppy.h"
#include "floppy_86f.h"
#include "floppy_img.h"
@@ -263,7 +266,7 @@ void fdi_load(int drive, wchar_t *fn)
char header[26];
writeprot[drive] = fwriteprot[drive] = 1;
fdi[drive].f = _wfopen(fn, L"rb");
fdi[drive].f = plat_fopen(fn, L"rb");
if (!fdi[drive].f)
{
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));

View File

@@ -8,14 +8,18 @@
*
* Implementation of the IMD floppy image format.
*
* Version: @(#)floppy_imd.c 1.0.1 2017/09/03
* Version: @(#)floppy_imd.c 1.0.3 2017/10/12
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#include <malloc.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../plat.h"
#include "floppy.h"
#include "floppy_imd.h"
#include "fdc.h"
@@ -86,10 +90,10 @@ void imd_load(int drive, wchar_t *fn)
d86f_unregister(drive);
writeprot[drive] = 0;
imd[drive].f = _wfopen(fn, L"rb+");
imd[drive].f = plat_fopen(fn, L"rb+");
if (!imd[drive].f)
{
imd[drive].f = _wfopen(fn, L"rb");
imd[drive].f = plat_fopen(fn, L"rb");
if (!imd[drive].f)
{
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));

View File

@@ -9,17 +9,22 @@
* Implementation of the raw sector-based floppy image format,
* as well as the Japanese FDI, CopyQM, and FDF formats.
*
* Version: @(#)floppy_img.c 1.0.1 2017/09/03
* Version: @(#)floppy_img.c 1.0.3 2017/10/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../config.h"
#include "../plat.h"
#include "floppy.h"
#include "floppy_img.h"
#include "fdc.h"
@@ -346,10 +351,10 @@ void img_load(int drive, wchar_t *fn)
d86f_unregister(drive);
writeprot[drive] = 0;
img[drive].f = _wfopen(fn, L"rb+");
img[drive].f = plat_fopen(fn, L"rb+");
if (!img[drive].f)
{
img[drive].f = _wfopen(fn, L"rb");
img[drive].f = plat_fopen(fn, L"rb");
if (!img[drive].f)
{
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
@@ -367,7 +372,7 @@ void img_load(int drive, wchar_t *fn)
img[drive].interleave = img[drive].skew = 0;
if (_wcsicmp(ext, L"FDI") == 0)
if (! wcscasecmp(ext, L"FDI"))
{
/* This is a Japanese FDI image, so let's read the header */
pclog("img_load(): File is a Japanese FDI image...\n");
@@ -412,7 +417,7 @@ void img_load(int drive, wchar_t *fn)
pclog("img_load(): File is a FDF image...\n");
fwriteprot[drive] = writeprot[drive] = 1;
fclose(img[drive].f);
img[drive].f = _wfopen(fn, L"rb");
img[drive].f = plat_fopen(fn, L"rb");
fdf = 1;
@@ -597,7 +602,7 @@ void img_load(int drive, wchar_t *fn)
pclog("img_load(): File is a CopyQM image...\n");
fwriteprot[drive] = writeprot[drive] = 1;
fclose(img[drive].f);
img[drive].f = _wfopen(fn, L"rb");
img[drive].f = plat_fopen(fn, L"rb");
fseek(img[drive].f, 0x03, SEEK_SET);
fread(&bpb_bps, 1, 2, img[drive].f);

View File

@@ -8,14 +8,19 @@
*
* Implementation of the PCjs JSON floppy image format.
*
* Version: @(#)floppy_json.c 1.0.1 2017/09/12
* Version: @(#)floppy_json.c 1.0.7 2017/10/14
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2017 Fred N. van Kempen.
*/
#include <wchar.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../plat.h"
#include "floppy.h"
#include "fdc.h"
#include "fdd.h"
@@ -25,7 +30,7 @@
#define NTRACKS 256
#define NSIDES 2
#define NSECTORS 128
#define NSECTORS 256
typedef struct {
@@ -122,10 +127,6 @@ handle(json_t *img, char *name, char *str)
l >>= 8;
*p++ = (l & 0x000000ff);
}
#if 1
pclog("JSON: added sector (%d,%d,%d/%d) size=%d pat=%08lx\n",
sec->track,sec->side,sec->sector,img->dmf,sec->size,pat);
#endif
} else if (! strcmp(name, "data")) {
if (sec->data == NULL)
sec->data = (uint8_t *)malloc(sec->size);
@@ -135,11 +136,6 @@ handle(json_t *img, char *name, char *str)
if (sp != NULL) *sp++ = '\0';
l = atol(str);
#if 1
if (p==sec->data)
pclog("JSON: added sector (%d,%d,%d/%d) size=%d data=%08lx\n",
sec->track,sec->side,sec->sector,img->dmf,sec->size,l);
#endif
*p++ = (l & 0x000000ff);
l >>= 8;
*p++ = (l & 0x000000ff);
@@ -482,7 +478,7 @@ json_load(int drive, wchar_t *fn)
memset(img, 0x00, sizeof(json_t));
/* Open the image file. */
img->f = _wfopen(fn, L"rb");
img->f = plat_fopen(fn, L"rb");
if (img->f == NULL) {
memset(fn, 0x00, sizeof(wchar_t));
return;
@@ -500,7 +496,7 @@ json_load(int drive, wchar_t *fn)
return;
}
pclog("JSON(%d): %S (%i tracks, %i sides, %i sectors)\n",
pclog("JSON(%d): %ls (%i tracks, %i sides, %i sectors)\n",
drive, fn, img->tracks, img->sides, img->spt[0][0]);
/*

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Teledisk floppy image format.
*
* Version: @(#)floppy_td0.c 1.0.2 2017/09/-3
* Version: @(#)floppy_td0.c 1.0.4 2017/10/12
*
* Authors: Milodrag Milanovic,
* Haruhiko OKUMURA,
@@ -37,9 +37,13 @@
* Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
* Edited and translated to English by Kenji RIKITAKE
*/
#include <wchar.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../plat.h"
#include "floppy.h"
#include "floppy_td0.h"
#include "fdc.h"
@@ -530,7 +534,7 @@ void td0_load(int drive, wchar_t *fn)
d86f_unregister(drive);
writeprot[drive] = 1;
td0[drive].f = _wfopen(fn, L"rb");
td0[drive].f = plat_fopen(fn, L"rb");
if (!td0[drive].f)
{
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));

View File

@@ -1,19 +1,22 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "ibm.h"
#include "cpu/cpu.h"
#include "device.h"
#include "io.h"
#include "timer.h"
#include <wchar.h>
#include "../ibm.h"
#include "../cpu/cpu.h"
#include "../device.h"
#include "../io.h"
#include "../timer.h"
#include "gameport.h"
#include "joystick_ch_flightstick_pro.h"
#include "joystick_standard.h"
#include "joystick_sw_pad.h"
#include "joystick_tm_fcs.h"
#include "plat_joystick.h"
#include "../plat_joystick.h"
int joystick_type;
@@ -46,52 +49,52 @@ static joystick_if_t *joystick_list[] =
NULL
};
char *joystick_get_name(int joystick)
char *joystick_get_name(int64_t joystick)
{
if (!joystick_list[joystick])
return NULL;
return joystick_list[joystick]->name;
}
int joystick_get_max_joysticks(int joystick)
int64_t joystick_get_max_joysticks(int64_t joystick)
{
return joystick_list[joystick]->max_joysticks;
}
int joystick_get_axis_count(int joystick)
int64_t joystick_get_axis_count(int64_t joystick)
{
return joystick_list[joystick]->axis_count;
}
int joystick_get_button_count(int joystick)
int64_t joystick_get_button_count(int64_t joystick)
{
return joystick_list[joystick]->button_count;
}
int joystick_get_pov_count(int joystick)
int64_t joystick_get_pov_count(int64_t joystick)
{
return joystick_list[joystick]->pov_count;
}
char *joystick_get_axis_name(int joystick, int id)
char *joystick_get_axis_name(int64_t joystick, int64_t id)
{
return joystick_list[joystick]->axis_names[id];
}
char *joystick_get_button_name(int joystick, int id)
char *joystick_get_button_name(int64_t joystick, int64_t id)
{
return joystick_list[joystick]->button_names[id];
}
char *joystick_get_pov_name(int joystick, int id)
char *joystick_get_pov_name(int64_t joystick, int64_t id)
{
return joystick_list[joystick]->pov_names[id];
}
typedef struct gameport_axis_t
{
int count;
int axis_nr;
int64_t count;
int64_t axis_nr;
struct gameport_t *gameport;
} gameport_axis_t;
@@ -107,7 +110,7 @@ typedef struct gameport_t
static gameport_t *gameport_global = NULL;
static int gameport_time(int axis)
static int64_t gameport_time(int64_t axis)
{
if (axis == AXIS_NOT_PRESENT)
return 0;
@@ -161,7 +164,7 @@ void gameport_timer_over(void *p)
gameport->joystick->a0_over(gameport->joystick_dat);
}
void *gameport_init_common()
void *gameport_init_common(void)
{
gameport_t *gameport = malloc(sizeof(gameport_t));
@@ -190,7 +193,7 @@ void *gameport_init_common()
return gameport;
}
void gameport_update_joystick_type()
void gameport_update_joystick_type(void)
{
gameport_t *gameport = gameport_global;
@@ -202,7 +205,7 @@ void gameport_update_joystick_type()
}
}
void *gameport_init()
void *gameport_init(device_t *info)
{
gameport_t *gameport = NULL;
@@ -219,7 +222,7 @@ void *gameport_init()
return gameport;
}
void *gameport_201_init()
void *gameport_201_init(device_t *info)
{
gameport_t *gameport;
@@ -255,23 +258,19 @@ void gameport_close(void *p)
device_t gameport_device =
{
"Game port",
0,
0, 0,
gameport_init,
gameport_close,
NULL,
NULL,
NULL,
NULL, NULL, NULL, NULL,
NULL
};
device_t gameport_201_device =
{
"Game port (port 201h only)",
0,
0, 0,
gameport_201_init,
gameport_close,
NULL,
NULL,
NULL,
NULL, NULL, NULL, NULL,
NULL
};

View File

@@ -30,14 +30,14 @@ extern device_t gameport_201_device;
extern int joystick_type;
extern char *joystick_get_name(int joystick);
extern int joystick_get_max_joysticks(int joystick);
extern int joystick_get_axis_count(int joystick);
extern int joystick_get_button_count(int joystick);
extern int joystick_get_pov_count(int joystick);
extern char *joystick_get_axis_name(int joystick, int id);
extern char *joystick_get_button_name(int joystick, int id);
extern char *joystick_get_pov_name(int joystick, int id);
extern char *joystick_get_name(int64_t joystick);
extern int64_t joystick_get_max_joysticks(int64_t joystick);
extern int64_t joystick_get_axis_count(int64_t joystick);
extern int64_t joystick_get_button_count(int64_t joystick);
extern int64_t joystick_get_pov_count(int64_t joystick);
extern char *joystick_get_axis_name(int64_t joystick, int64_t id);
extern char *joystick_get_button_name(int64_t joystick, int64_t id);
extern char *joystick_get_pov_name(int64_t joystick, int64_t id);
extern void gameport_update_joystick_type(void);

View File

@@ -1,10 +1,14 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "timer.h"
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../timer.h"
#include "../plat_joystick.h"
#include "gameport.h"
#include "joystick_standard.h"
#include "plat_joystick.h"
static void *ch_flightstick_pro_init()

View File

@@ -1,10 +1,14 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "timer.h"
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../timer.h"
#include "../plat_joystick.h"
#include "gameport.h"
#include "joystick_standard.h"
#include "plat_joystick.h"
static void *joystick_standard_init()

View File

@@ -19,26 +19,29 @@
- Some DOS stuff will write to 0x201 while a packet is being transferred.
This seems to be ignored.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "timer.h"
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../timer.h"
#include "../plat_joystick.h"
#include "gameport.h"
#include "joystick_sw_pad.h"
#include "plat_joystick.h"
typedef struct
{
int poll_time;
int poll_left;
int poll_clock;
int64_t poll_time;
int64_t poll_left;
int64_t poll_clock;
uint64_t poll_data;
int poll_mode;
int64_t poll_mode;
int trigger_time;
int data_mode;
int64_t trigger_time;
int64_t data_mode;
} sw_data;
static void sw_timer_over(void *p)
@@ -56,7 +59,7 @@ static void sw_timer_over(void *p)
}
if (sw->poll_left == 1 && !sw->poll_clock)
sw->poll_time += TIMER_USEC * 160;
sw->poll_time += TIMER_USEC * 160LL;
else if (sw->poll_left)
sw->poll_time += TIMER_USEC * 5;
else
@@ -222,7 +225,7 @@ static int sw_read_axis(void *p, int axis)
if (!JOYSTICK_PRESENT(0))
return AXIS_NOT_PRESENT;
return 0; /*No analogue support on Sidewinder game pad*/
return 0LL; /*No analogue support on Sidewinder game pad*/
}
static void sw_a0_over(void *p)

View File

@@ -1,10 +1,14 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "timer.h"
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../timer.h"
#include "../plat_joystick.h"
#include "gameport.h"
#include "joystick_standard.h"
#include "plat_joystick.h"
static void *tm_fcs_init(void)

View File

@@ -1,111 +0,0 @@
#include "../ibm.h"
#include "../cpu/cpu.h"
#include "../device.h"
#include "../machine/machine.h"
#include "hdd.h"
#include "hdd_esdi_at.h"
#include "hdd_esdi_mca.h"
#include "hdd_mfm_at.h"
#include "hdd_mfm_xebec.h"
#include "hdd_ide_xt.h"
char hdd_controller_name[16];
hard_disk_t hdc[HDC_NUM];
static device_t null_hdd_device;
static int hdd_controller_current;
static struct
{
char name[50];
char internal_name[16];
device_t *device;
int is_mfm;
} hdd_controllers[] =
{
{"None", "none", &null_hdd_device, 0},
{"[MFM] AT Fixed Disk Adapter", "mfm_at", &mfm_at_device, 1},
{"[MFM] DTC 5150X", "dtc5150x", &dtc_5150x_device, 1},
{"[MFM] Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1},
{"[ESDI] IBM ESDI Fixed Disk Adapter", "esdi_mca", &hdd_esdi_device, 1},
{"[ESDI] Western Digital WD1007V-SE1", "wd1007vse1", &wd1007vse1_device, 0},
{"[IDE] XTIDE", "xtide", &xtide_device, 0},
{"[IDE] XTIDE (Acculogic)", "xtide_ps2", &xtide_ps2_device, 0},
{"[IDE] XTIDE (AT)", "xtide_at", &xtide_at_device, 0},
{"[IDE] XTIDE (AT) (1.1.5)", "xtide_at_ps2", &xtide_at_ps2_device, 0},
{"", "", NULL, 0}
};
char *hdd_controller_get_name(int hdd)
{
return hdd_controllers[hdd].name;
}
char *hdd_controller_get_internal_name(int hdd)
{
return hdd_controllers[hdd].internal_name;
}
int hdd_controller_get_flags(int hdd)
{
return hdd_controllers[hdd].device->flags;
}
int hdd_controller_available(int hdd)
{
return device_available(hdd_controllers[hdd].device);
}
int hdd_controller_current_is_mfm()
{
return hdd_controllers[hdd_controller_current].is_mfm;
}
void hdd_controller_init(char *internal_name)
{
int c = 0;
if (machines[machine].flags & MACHINE_HAS_IDE)
{
return;
}
while (hdd_controllers[c].device)
{
if (!strcmp(internal_name, hdd_controllers[c].internal_name))
{
hdd_controller_current = c;
if (strcmp(internal_name, "none"))
device_add(hdd_controllers[c].device);
return;
}
c++;
}
}
static void *null_hdd_init()
{
return NULL;
}
static void null_hdd_close(void *p)
{
}
static device_t null_hdd_device =
{
"Null HDD controller",
0,
null_hdd_init,
null_hdd_close,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,16 +0,0 @@
#ifndef EMU_HDD_H
# define EMU_HDD_H
extern char hdd_controller_name[16];
extern char *hdd_controller_get_name(int hdd);
extern char *hdd_controller_get_internal_name(int hdd);
extern int hdd_controller_get_flags(int hdd);
extern int hdd_controller_available(int hdd);
extern int hdd_controller_current_is_mfm(void);
extern void hdd_controller_init(char *internal_name);
#endif /*EMU_HDD_H*/

View File

@@ -1,853 +0,0 @@
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include "../ibm.h"
#include "../device.h"
#include "hdd_image.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdd_esdi_at.h"
#define IDE_TIME (TIMER_USEC*10)
#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;
int real_spt;
int real_hpc;
int real_tracks;
int present;
int hdc_num;
} 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)
{
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->real_spt && drive->cfg_hpc == drive->real_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->real_spt - 1);
h = (*addr / (drive->real_spt - 1)) % drive->real_hpc;
c = (*addr / (drive->real_spt - 1)) / drive->real_hpc;
*addr = ((((off64_t) c * drive->real_hpc) + h) *
drive->real_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->real_tracks)
drive->current_cylinder++;
}
}
}
void esdi_write(uint16_t port, uint8_t val, void *p)
{
esdi_t *esdi = (esdi_t *)p;
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].present)
esdi->status = 0;
else
esdi->status = STAT_READY | STAT_DSC;
return;
case 0x1F7: /* Command register */
esdi_irq_lower(esdi);
esdi->command = val;
esdi->error = 0;
switch (val & 0xf0)
{
case CMD_RESTORE:
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:
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:
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:
esdi->command &= ~3;
if (val & 2)
fatal("Write with ECC\n");
esdi->status = STAT_DRQ | STAT_DSC;
esdi->pos=0;
break;
case CMD_VERIFY: case CMD_VERIFY+1:
esdi->command &= ~1;
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200 * IDE_TIME;
timer_update_outstanding();
break;
case CMD_FORMAT:
esdi->status = STAT_DRQ;
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;
}
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;
}
}
void esdi_writew(uint16_t port, uint16_t val, void *p)
{
esdi_t *esdi = (esdi_t *)p;
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;
}
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)
{
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();
}
}
}
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;
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;
return;
}
switch (esdi->command)
{
case CMD_RESTORE:
if (!drive->present)
{
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->present)
{
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->present)
{
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_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) 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;
esdi_irq_raise(esdi);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
break;
case CMD_WRITE:
if (!drive->present)
{
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_image_write_ex(drive->hdc_num, addr, 1, (uint8_t *) 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;
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
break;
case CMD_VERIFY:
if (!drive->present)
{
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_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
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;
esdi_irq_raise(esdi);
}
}
break;
case CMD_FORMAT:
if (!drive->present)
{
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_image_zero_ex(drive->hdc_num, 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);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
break;
case CMD_DIAGNOSE:
if (!drive->present)
{
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->present)
{
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->present)
{
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->real_tracks;
break;
case 0x33:
esdi->cylinder = drive->real_hpc;
break;
case 0x35:
esdi->cylinder = 0x200;
break;
case 0x36:
esdi->cylinder = drive->real_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->present)
{
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;
esdi_irq_raise(esdi);
}
break;
case CMD_READ_PARAMETERS:
if (!drive->present)
{
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->real_tracks; /* number of non-removable cylinders */
esdi->buffer[2] = 0; /* number of removable cylinders */
esdi->buffer[3] = drive->real_hpc; /* number of heads */
esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */
esdi->buffer[4] = 600; /* number of unformatted bytes/track */
esdi->buffer[6] = drive->real_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 */
esdi->buffer[20] = 2; /* controller type */
esdi->buffer[21] = 1; /* sector buffer size, in sectors */
esdi->buffer[22] = 0; /* ecc bytes appended */
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;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 0);
}
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;
}
static void loadhd(esdi_t *esdi, int hdc_num, int d, const wchar_t *fn)
{
esdi_drive_t *drive = &esdi->drives[d];
int ret = 0;
ret = hdd_image_load(hdc_num);
if (!ret)
{
drive->present = 0;
return;
}
drive->cfg_spt = drive->real_spt = hdc[hdc_num].spt;
drive->cfg_hpc = drive->real_hpc = hdc[hdc_num].hpc;
drive->real_tracks = hdc[hdc_num].tracks;
drive->hdc_num = hdc_num;
drive->present = 1;
}
void *wd1007vse1_init()
{
int i = 0;
int c = 0;
esdi_t *esdi = malloc(sizeof(esdi_t));
memset(esdi, 0, sizeof(esdi_t));
esdi->drives[0].present = esdi->drives[1].present = 0;
for (i = 0; i < HDC_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_ESDI) && (hdc[i].esdi_channel < ESDI_NUM))
{
loadhd(esdi, i, hdc[i].esdi_channel, hdc[i].fn);
c++;
if (c >= ESDI_NUM) break;
}
}
esdi->status = STAT_READY | STAT_DSC;
esdi->error = 1; /*No errors*/
rom_init(&esdi->bios_rom, L"roms/hdd/esdi_at/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;
esdi_drive_t *drive;
int d;
esdi->drives[0].present = esdi->drives[1].present = 0;
for (d = 0; d < 2; d++)
{
drive = &esdi->drives[d];
hdd_image_close(drive->hdc_num);
}
free(esdi);
}
static int wd1007vse1_available()
{
return rom_present(L"roms/hdd/esdi_at/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
};

View File

@@ -1 +0,0 @@
extern device_t wd1007vse1_device;

View File

@@ -1 +0,0 @@
extern device_t hdd_esdi_device;

View File

@@ -1,224 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* XT IDE controller emulation.
*
* Version: @(#)xtide.c 1.0.3 2017/08/24
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <malloc.h>
#include "../ibm.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../device.h"
#include "hdd_ide_at.h"
#include "hdd_ide_xt.h"
#define XTIDE_ROM_PATH L"roms/hdd/xtide/ide_xt.bin"
#define ATIDE_ROM_PATH L"roms/hdd/xtide/ide_at.bin"
typedef struct xtide_t
{
uint8_t data_high;
rom_t bios_rom;
} xtide_t;
static void xtide_write(uint16_t port, uint8_t val, void *p)
{
xtide_t *xtide = (xtide_t *)p;
switch (port & 0xf)
{
case 0x0:
writeidew(4, val | (xtide->data_high << 8));
return;
case 0x1: case 0x2: case 0x3:
case 0x4: case 0x5: case 0x6: case 0x7:
writeide(4, (port & 0xf) | 0x1f0, val);
return;
case 0x8:
xtide->data_high = val;
return;
case 0xe:
writeide(4, 0x3f6, val);
return;
}
}
static uint8_t xtide_read(uint16_t port, void *p)
{
xtide_t *xtide = (xtide_t *)p;
uint16_t tempw;
switch (port & 0xf)
{
case 0x0:
tempw = readidew(4);
xtide->data_high = tempw >> 8;
return tempw & 0xff;
case 0x1: case 0x2: case 0x3:
case 0x4: case 0x5: case 0x6: case 0x7:
return readide(4, (port & 0xf) | 0x1f0);
case 0x8:
return xtide->data_high;
case 0xe:
return readide(4, 0x3f6);
default:
return 0xff;
}
}
static void *xtide_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, XTIDE_ROM_PATH, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide);
return xtide;
}
static void *xtide_at_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, ATIDE_ROM_PATH, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return xtide;
}
static void *xtide_ps2_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, L"roms/hdd/xtide/SIDE1V12.BIN", 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0360, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide);
return xtide;
}
static void *xtide_at_ps2_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, L"roms/hdd/xtide/ide_at_1_1_5.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return xtide;
}
static void xtide_close(void *p)
{
xtide_t *xtide = (xtide_t *)p;
free(xtide);
}
static int xtide_available(void)
{
return rom_present(L"roms/hdd/xtide/ide_xt.bin");
}
static int xtide_at_available(void)
{
return rom_present(L"roms/hdd/xtide/ide_at.bin");
}
static int xtide_ps2_available(void)
{
return rom_present(L"roms/hdd/xtide/SIDE1V12.BIN");
}
static int xtide_at_ps2_available(void)
{
return rom_present(L"roms/hdd/xtide/ide_at_1_1_5.bin");
}
device_t xtide_device =
{
"XTIDE",
0,
xtide_init,
xtide_close,
xtide_available,
NULL,
NULL,
NULL,
NULL
};
device_t xtide_at_device =
{
"XTIDE (AT)",
DEVICE_AT,
xtide_at_init,
xtide_close,
xtide_at_available,
NULL,
NULL,
NULL,
NULL
};
device_t xtide_ps2_device =
{
"XTIDE (Acculogic)",
0,
xtide_ps2_init,
xtide_close,
xtide_ps2_available,
NULL,
NULL,
NULL,
NULL
};
device_t xtide_at_ps2_device =
{
"XTIDE (AT) (1.1.5)",
DEVICE_PS2,
xtide_at_ps2_init,
xtide_close,
xtide_at_ps2_available,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,28 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* XT IDE controller emulation.
*
* Version: @(#)xtide.h 1.0.2 2017/08/23
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#ifndef EMU_XTIDE_H
# define EMU_XTIDE_H
extern device_t xtide_device;
extern device_t xtide_at_device;
extern device_t xtide_ps2_device;
extern device_t xtide_at_ps2_device;
#endif /*EMU_XTIDE_H*/

View File

@@ -1,20 +0,0 @@
#ifndef EMU_HDD_IMAGE_H
# define EMU_HDD_IMAGE_H
extern int hdd_image_load(int id);
extern void hdd_image_seek(uint8_t id, uint32_t sector);
extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count);
extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count);
extern uint32_t hdd_image_get_last_sector(uint8_t id);
extern uint8_t hdd_image_get_type(uint8_t id);
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
extern void hdd_image_unload(uint8_t id, int fn_preserve);
extern void hdd_image_close(uint8_t id);
#endif /*EMU_HDD_IMAGE_H*/

View File

@@ -1,610 +0,0 @@
#include <malloc.h>
#include "../ibm.h"
#include "hdd_image.h"
#include "../device.h"
#include "../io.h"
#include "../pic.h"
#include "../timer.h"
#include "hdd_mfm_at.h"
#define IDE_TIME (TIMER_USEC*10)
#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_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
typedef struct mfm_drive_t
{
int spt, hpc;
int tracks;
int cfg_spt;
int cfg_hpc;
int current_cylinder;
int present;
int hdc_num;
} mfm_drive_t;
typedef struct mfm_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;
mfm_drive_t drives[2];
} mfm_t;
uint16_t mfm_readw(uint16_t port, void *p);
void mfm_writew(uint16_t port, uint16_t val, void *p);
static __inline void mfm_irq_raise(mfm_t *mfm)
{
if (!(mfm->fdisk&2))
picint(1 << 14);
mfm->irqstat=1;
}
static __inline void mfm_irq_lower(mfm_t *mfm)
{
picintc(1 << 14);
}
void mfm_irq_update(mfm_t *mfm)
{
if (mfm->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(mfm->fdisk & 2))
picint(1 << 14);
}
/*
* Return the sector offset for the current register values
*/
static int mfm_get_sector(mfm_t *mfm, off64_t *addr)
{
mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
int heads = drive->cfg_hpc;
int sectors = drive->cfg_spt;
if (drive->current_cylinder != mfm->cylinder)
{
pclog("mfm_get_sector: wrong cylinder\n");
return 1;
}
if (mfm->head > heads)
{
pclog("mfm_get_sector: past end of configured heads\n");
return 1;
}
if (mfm->sector >= sectors+1)
{
pclog("mfm_get_sector: past end of configured sectors\n");
return 1;
}
if (mfm->head > drive->hpc)
{
pclog("mfm_get_sector: past end of heads\n");
return 1;
}
if (mfm->sector >= drive->spt+1)
{
pclog("mfm_get_sector: past end of sectors\n");
return 1;
}
*addr = ((((off64_t) mfm->cylinder * heads) + mfm->head) *
sectors) + (mfm->sector - 1);
return 0;
}
/**
* Move to the next sector using CHS addressing
*/
static void mfm_next_sector(mfm_t *mfm)
{
mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
mfm->sector++;
if (mfm->sector == (drive->cfg_spt + 1))
{
mfm->sector = 1;
mfm->head++;
if (mfm->head == drive->cfg_hpc)
{
mfm->head = 0;
mfm->cylinder++;
if (drive->current_cylinder < drive->tracks)
drive->current_cylinder++;
}
}
}
static void loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
{
mfm_drive_t *drive = &mfm->drives[c];
int ret = 0;
ret = hdd_image_load(d);
if (!ret)
{
drive->present = 0;
return;
}
drive->spt = hdc[d].spt;
drive->hpc = hdc[d].hpc;
drive->tracks = hdc[d].tracks;
drive->hdc_num = d;
drive->present = 1;
}
void mfm_write(uint16_t port, uint8_t val, void *p)
{
mfm_t *mfm = (mfm_t *)p;
switch (port)
{
case 0x1F0: /* Data */
mfm_writew(port, val | (val << 8), p);
return;
case 0x1F1: /* Write precompenstation */
mfm->cylprecomp = val;
return;
case 0x1F2: /* Sector count */
mfm->secount = val;
return;
case 0x1F3: /* Sector */
mfm->sector = val;
return;
case 0x1F4: /* Cylinder low */
mfm->cylinder = (mfm->cylinder & 0xFF00) | val;
return;
case 0x1F5: /* Cylinder high */
mfm->cylinder = (mfm->cylinder & 0xFF) | (val << 8);
return;
case 0x1F6: /* Drive/Head */
mfm->head = val & 0xF;
mfm->drive_sel = (val & 0x10) ? 1 : 0;
if (mfm->drives[mfm->drive_sel].present)
mfm->status = STAT_READY | STAT_DSC;
else
mfm->status = 0;
return;
case 0x1F7: /* Command register */
if (!mfm->drives[mfm->drive_sel].present)
fatal("Command on non-present drive\n");
mfm_irq_lower(mfm);
mfm->command = val;
mfm->error = 0;
switch (val & 0xf0)
{
case CMD_RESTORE:
mfm->command &= ~0x0f; /*Mask off step rate*/
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
case CMD_SEEK:
mfm->command &= ~0x0f; /*Mask off step rate*/
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
default:
switch (val)
{
case CMD_READ: case CMD_READ+1:
case CMD_READ+2: case CMD_READ+3:
mfm->command &= ~3;
if (val & 2)
fatal("Read with ECC\n");
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
case CMD_WRITE: case CMD_WRITE+1:
case CMD_WRITE+2: case CMD_WRITE+3:
mfm->command &= ~3;
if (val & 2)
fatal("Write with ECC\n");
mfm->status = STAT_DRQ | STAT_DSC;
mfm->pos=0;
break;
case CMD_VERIFY: case CMD_VERIFY+1:
mfm->command &= ~1;
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200 * IDE_TIME;
timer_update_outstanding();
break;
case CMD_FORMAT:
mfm->status = STAT_DRQ | STAT_BUSY;
mfm->pos=0;
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 30*IDE_TIME;
timer_update_outstanding();
break;
case CMD_DIAGNOSE: /* Execute Drive Diagnostics */
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
default:
pclog("Bad MFM command %02X\n", val);
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
}
}
break;
case 0x3F6: /* Device control */
if ((mfm->fdisk & 4) && !(val & 4))
{
timer_process();
mfm->callback = 500*IDE_TIME;
timer_update_outstanding();
mfm->reset = 1;
mfm->status = STAT_BUSY;
}
if (val & 4)
{
/*Drive held in reset*/
timer_process();
mfm->callback = 0;
timer_update_outstanding();
mfm->status = STAT_BUSY;
}
mfm->fdisk = val;
mfm_irq_update(mfm);
return;
}
}
void mfm_writew(uint16_t port, uint16_t val, void *p)
{
mfm_t *mfm = (mfm_t *)p;
mfm->buffer[mfm->pos >> 1] = val;
mfm->pos += 2;
if (mfm->pos >= 512)
{
mfm->pos = 0;
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 6*IDE_TIME;
timer_update_outstanding();
}
}
uint8_t mfm_read(uint16_t port, void *p)
{
mfm_t *mfm = (mfm_t *)p;
uint8_t temp;
switch (port)
{
case 0x1F0: /* Data */
temp = mfm_readw(port, mfm) & 0xff;
break;
case 0x1F1: /* Error */
temp = mfm->error;
break;
case 0x1F2: /* Sector count */
temp = (uint8_t)mfm->secount;
break;
case 0x1F3: /* Sector */
temp = (uint8_t)mfm->sector;
break;
case 0x1F4: /* Cylinder low */
temp = (uint8_t)(mfm->cylinder&0xFF);
break;
case 0x1F5: /* Cylinder high */
temp = (uint8_t)(mfm->cylinder>>8);
break;
case 0x1F6: /* Drive/Head */
temp = (uint8_t)(mfm->head | (mfm->drive_sel ? 0x10 : 0) | 0xa0);
break;
case 0x1F7: /* Status */
mfm_irq_lower(mfm);
temp = mfm->status;
break;
default:
temp = 0xff;
break;
}
return temp;
}
uint16_t mfm_readw(uint16_t port, void *p)
{
mfm_t *mfm = (mfm_t *)p;
uint16_t temp;
temp = mfm->buffer[mfm->pos >> 1];
mfm->pos += 2;
if (mfm->pos >= 512)
{
mfm->pos=0;
mfm->status = STAT_READY | STAT_DSC;
if (mfm->command == CMD_READ)
{
mfm->secount = (mfm->secount - 1) & 0xff;
if (mfm->secount)
{
mfm_next_sector(mfm);
mfm->status = STAT_BUSY;
timer_process();
mfm->callback = 6*IDE_TIME;
timer_update_outstanding();
}
else
{
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0);
}
}
}
return temp;
}
static void do_seek(mfm_t *mfm)
{
mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
if (mfm->cylinder < drive->tracks)
drive->current_cylinder = mfm->cylinder;
else
drive->current_cylinder = drive->tracks-1;
}
void mfm_callback(void *p)
{
mfm_t *mfm = (mfm_t *)p;
mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
off64_t addr;
mfm->callback = 0;
if (mfm->reset)
{
mfm->status = STAT_READY | STAT_DSC;
mfm->error = 1;
mfm->secount = 1;
mfm->sector = 1;
mfm->head = 0;
mfm->cylinder = 0;
mfm->reset = 0;
return;
}
switch (mfm->command)
{
case CMD_RESTORE:
drive->current_cylinder = 0;
mfm->status = STAT_READY | STAT_DSC;
mfm_irq_raise(mfm);
break;
case CMD_SEEK:
do_seek(mfm);
mfm->status = STAT_READY | STAT_DSC;
mfm_irq_raise(mfm);
break;
case CMD_READ:
do_seek(mfm);
if (mfm_get_sector(mfm, &addr))
{
mfm->error = ERR_ID_NOT_FOUND;
mfm->status = STAT_READY | STAT_DSC | STAT_ERR;
mfm_irq_raise(mfm);
break;
}
hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) mfm->buffer);
mfm->pos = 0;
mfm->status = STAT_DRQ | STAT_READY | STAT_DSC;
mfm_irq_raise(mfm);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
break;
case CMD_WRITE:
do_seek(mfm);
if (mfm_get_sector(mfm, &addr))
{
mfm->error = ERR_ID_NOT_FOUND;
mfm->status = STAT_READY | STAT_DSC | STAT_ERR;
mfm_irq_raise(mfm);
break;
}
hdd_image_write(drive->hdc_num, addr, 1, (uint8_t *) mfm->buffer);
mfm_irq_raise(mfm);
mfm->secount = (mfm->secount - 1) & 0xff;
if (mfm->secount)
{
mfm->status = STAT_DRQ | STAT_READY | STAT_DSC;
mfm->pos = 0;
mfm_next_sector(mfm);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
}
else
{
mfm->status = STAT_READY | STAT_DSC;
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0);
}
break;
case CMD_VERIFY:
do_seek(mfm);
mfm->pos = 0;
mfm->status = STAT_READY | STAT_DSC;
mfm_irq_raise(mfm);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
break;
case CMD_FORMAT:
do_seek(mfm);
if (mfm_get_sector(mfm, &addr))
{
mfm->error = ERR_ID_NOT_FOUND;
mfm->status = STAT_READY | STAT_DSC | STAT_ERR;
mfm_irq_raise(mfm);
break;
}
hdd_image_zero(drive->hdc_num, addr, mfm->secount);
mfm->status = STAT_READY | STAT_DSC;
mfm_irq_raise(mfm);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
break;
case CMD_DIAGNOSE:
mfm->error = 1; /*No error detected*/
mfm->status = STAT_READY | STAT_DSC;
mfm_irq_raise(mfm);
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
drive->cfg_spt = mfm->secount;
drive->cfg_hpc = mfm->head+1;
pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc);
mfm->status = STAT_READY | STAT_DSC;
mfm_irq_raise(mfm);
break;
default:
pclog("Callback on unknown command %02x\n", mfm->command);
mfm->status = STAT_READY | STAT_ERR | STAT_DSC;
mfm->error = ERR_ABRT;
mfm_irq_raise(mfm);
break;
}
}
void *mfm_init()
{
int c, d;
mfm_t *mfm = malloc(sizeof(mfm_t));
memset(mfm, 0, sizeof(mfm_t));
c = 0;
for (d = 0; d < HDC_NUM; d++)
{
if ((hdc[d].bus == HDD_BUS_MFM) && (hdc[d].mfm_channel < MFM_NUM))
{
loadhd(mfm, hdc[d].mfm_channel, d, hdc[d].fn);
c++;
if (c >= MFM_NUM) break;
}
}
mfm->status = STAT_READY | STAT_DSC;
mfm->error = 1; /*No errors*/
io_sethandler(0x01f0, 0x0001, mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm);
io_sethandler(0x01f1, 0x0007, mfm_read, NULL, NULL, mfm_write, NULL, NULL, mfm);
io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, mfm_write, NULL, NULL, mfm);
timer_add(mfm_callback, &mfm->callback, &mfm->callback, mfm);
return mfm;
}
void mfm_close(void *p)
{
mfm_t *mfm = (mfm_t *)p;
int d;
for (d = 0; d < 2; d++)
{
mfm_drive_t *drive = &mfm->drives[d];
hdd_image_close(drive->hdc_num);
}
free(mfm);
}
device_t mfm_at_device =
{
"IBM PC AT Fixed Disk Adapter",
DEVICE_AT,
mfm_init,
mfm_close,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1 +0,0 @@
extern device_t mfm_at_device;

View File

@@ -1,918 +0,0 @@
#include <malloc.h>
#include <sys/types.h>
#include "../ibm.h"
#include "../device.h"
#include "../dma.h"
#include "hdd_image.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdd_mfm_xebec.h"
#define XEBEC_TIME (2000 * TIMER_USEC)
enum
{
STATE_IDLE,
STATE_RECEIVE_COMMAND,
STATE_START_COMMAND,
STATE_RECEIVE_DATA,
STATE_RECEIVED_DATA,
STATE_SEND_DATA,
STATE_SENT_DATA,
STATE_COMPLETION_BYTE,
STATE_DUNNO
};
typedef struct mfm_drive_t
{
int spt, hpc;
int tracks;
int cfg_spt;
int cfg_hpc;
int cfg_cyl;
int current_cylinder;
int present;
int hdc_num;
} mfm_drive_t;
typedef struct xebec_t
{
rom_t bios_rom;
int callback;
int state;
uint8_t status;
uint8_t command[6];
int command_pos;
uint8_t data[512];
int data_pos, data_len;
uint8_t sector_buf[512];
uint8_t irq_dma_mask;
uint8_t completion_byte;
uint8_t error;
int drive_sel;
mfm_drive_t drives[2];
int sector, head, cylinder;
int sector_count;
uint8_t switches;
} xebec_t;
#define STAT_IRQ 0x20
#define STAT_DRQ 0x10
#define STAT_BSY 0x08
#define STAT_CD 0x04
#define STAT_IO 0x02
#define STAT_REQ 0x01
#define IRQ_ENA 0x02
#define DMA_ENA 0x01
#define CMD_TEST_DRIVE_READY 0x00
#define CMD_RECALIBRATE 0x01
#define CMD_READ_STATUS 0x03
#define CMD_VERIFY_SECTORS 0x05
#define CMD_FORMAT_TRACK 0x06
#define CMD_READ_SECTORS 0x08
#define CMD_WRITE_SECTORS 0x0a
#define CMD_SEEK 0x0b
#define CMD_INIT_DRIVE_PARAMS 0x0c
#define CMD_WRITE_SECTOR_BUFFER 0x0f
#define CMD_BUFFER_DIAGNOSTIC 0xe0
#define CMD_CONTROLLER_DIAGNOSTIC 0xe4
#define CMD_DTC_GET_DRIVE_PARAMS 0xfb
#define CMD_DTC_SET_STEP_RATE 0xfc
#define CMD_DTC_SET_GEOMETRY 0xfe
#define CMD_DTC_GET_GEOMETRY 0xff
#define ERR_NOT_READY 0x04
#define ERR_SEEK_ERROR 0x15
#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21
static uint8_t xebec_read(uint16_t port, void *p)
{
xebec_t *xebec = (xebec_t *)p;
uint8_t temp = 0xff;
switch (port)
{
case 0x320: /*Read data*/
xebec->status &= ~STAT_IRQ;
switch (xebec->state)
{
case STATE_COMPLETION_BYTE:
if ((xebec->status & 0xf) != (STAT_CD | STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", xebec->status);
temp = xebec->completion_byte;
xebec->status = 0;
xebec->state = STATE_IDLE;
break;
case STATE_SEND_DATA:
if ((xebec->status & 0xf) != (STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", xebec->status);
if (xebec->data_pos >= xebec->data_len)
fatal("Data write with full data!\n");
temp = xebec->data[xebec->data_pos++];
if (xebec->data_pos == xebec->data_len)
{
xebec->status = STAT_BSY;
xebec->state = STATE_SENT_DATA;
xebec->callback = XEBEC_TIME;
}
break;
default:
fatal("Read data register - %i, %02x\n", xebec->state, xebec->status);
}
break;
case 0x321: /*Read status*/
temp = xebec->status;
break;
case 0x322: /*Read option jumpers*/
temp = xebec->switches;
break;
}
return temp;
}
static void xebec_write(uint16_t port, uint8_t val, void *p)
{
xebec_t *xebec = (xebec_t *)p;
switch (port)
{
case 0x320: /*Write data*/
switch (xebec->state)
{
case STATE_RECEIVE_COMMAND:
if ((xebec->status & 0xf) != (STAT_BSY | STAT_CD | STAT_REQ))
fatal("Bad write data state - STATE_START_COMMAND, status=%02x\n", xebec->status);
if (xebec->command_pos >= 6)
fatal("Command write with full command!\n");
/*Command data*/
xebec->command[xebec->command_pos++] = val;
if (xebec->command_pos == 6)
{
xebec->status = STAT_BSY;
xebec->state = STATE_START_COMMAND;
xebec->callback = XEBEC_TIME;
}
break;
case STATE_RECEIVE_DATA:
if ((xebec->status & 0xf) != (STAT_BSY | STAT_REQ))
fatal("Bad write data state - STATE_RECEIVE_DATA, status=%02x\n", xebec->status);
if (xebec->data_pos >= xebec->data_len)
fatal("Data write with full data!\n");
/*Command data*/
xebec->data[xebec->data_pos++] = val;
if (xebec->data_pos == xebec->data_len)
{
xebec->status = STAT_BSY;
xebec->state = STATE_RECEIVED_DATA;
xebec->callback = XEBEC_TIME;
}
break;
default:
fatal("Write data unknown state - %i %02x\n", xebec->state, xebec->status);
}
break;
case 0x321: /*Controller reset*/
xebec->status = 0;
break;
case 0x322: /*Generate controller-select-pulse*/
xebec->status = STAT_BSY | STAT_CD | STAT_REQ;
xebec->command_pos = 0;
xebec->state = STATE_RECEIVE_COMMAND;
break;
case 0x323: /*DMA/IRQ mask register*/
xebec->irq_dma_mask = val;
break;
}
}
static void xebec_complete(xebec_t *xebec)
{
xebec->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY;
xebec->state = STATE_COMPLETION_BYTE;
if (xebec->irq_dma_mask & IRQ_ENA)
{
xebec->status |= STAT_IRQ;
picint(1 << 5);
}
}
static void xebec_error(xebec_t *xebec, uint8_t error)
{
xebec->completion_byte |= 0x02;
xebec->error = error;
pclog("xebec_error - %02x\n", xebec->error);
}
static int xebec_get_sector(xebec_t *xebec, off64_t *addr)
{
mfm_drive_t *drive = &xebec->drives[xebec->drive_sel];
int heads = drive->cfg_hpc;
if (drive->current_cylinder != xebec->cylinder)
{
pclog("mfm_get_sector: wrong cylinder\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
if (xebec->head > heads)
{
pclog("mfm_get_sector: past end of configured heads\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
if (xebec->head > drive->hpc)
{
pclog("mfm_get_sector: past end of heads\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
if (xebec->sector >= 17)
{
pclog("mfm_get_sector: past end of sectors\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
*addr = ((((off64_t) xebec->cylinder * heads) + xebec->head) *
17) + xebec->sector;
return 0;
}
static void xebec_next_sector(xebec_t *xebec)
{
mfm_drive_t *drive = &xebec->drives[xebec->drive_sel];
xebec->sector++;
if (xebec->sector >= 17)
{
xebec->sector = 0;
xebec->head++;
if (xebec->head >= drive->cfg_hpc)
{
xebec->head = 0;
xebec->cylinder++;
drive->current_cylinder++;
if (drive->current_cylinder >= drive->cfg_cyl)
drive->current_cylinder = drive->cfg_cyl-1;
}
}
}
static void xebec_callback(void *p)
{
off64_t addr;
xebec_t *xebec = (xebec_t *)p;
mfm_drive_t *drive;
xebec->callback = 0;
xebec->drive_sel = (xebec->command[1] & 0x20) ? 1 : 0;
xebec->completion_byte = xebec->drive_sel & 0x20;
drive = &xebec->drives[xebec->drive_sel];
switch (xebec->command[0])
{
case CMD_TEST_DRIVE_READY:
if (!drive->present)
xebec_error(xebec, ERR_NOT_READY);
xebec_complete(xebec);
break;
case CMD_RECALIBRATE:
if (!drive->present)
xebec_error(xebec, ERR_NOT_READY);
else
{
xebec->cylinder = 0;
drive->current_cylinder = 0;
}
xebec_complete(xebec);
break;
case CMD_READ_STATUS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 4;
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
xebec->data[0] = xebec->error;
xebec->data[1] = xebec->drive_sel ? 0x20 : 0;
xebec->data[2] = xebec->data[3] = 0;
xebec->error = 0;
break;
case STATE_SENT_DATA:
xebec_complete(xebec);
break;
}
break;
case CMD_VERIFY_SECTORS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
xebec->sector = xebec->command[2] & 0x1f;
xebec->sector_count = xebec->command[4];
do
{
if (xebec_get_sector(xebec, &addr))
{
pclog("xebec_get_sector failed\n");
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
xebec_next_sector(xebec);
xebec->sector_count = (xebec->sector_count-1) & 0xff;
} while (xebec->sector_count);
xebec_complete(xebec);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
break;
default:
fatal("CMD_VERIFY_SECTORS: bad state %i\n", xebec->state);
}
break;
case CMD_FORMAT_TRACK:
{
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
if (xebec_get_sector(xebec, &addr))
{
pclog("xebec_get_sector failed\n");
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_zero(drive->hdc_num, addr, 17);
xebec_complete(xebec);
}
break;
case CMD_READ_SECTORS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
xebec->sector = xebec->command[2] & 0x1f;
xebec->sector_count = xebec->command[4];
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 512;
{
if (xebec_get_sector(xebec, &addr))
{
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
}
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
{
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(xebec->data, xebec->sector_buf, 512);
}
break;
case STATE_SEND_DATA:
xebec->status = STAT_BSY;
if (xebec->irq_dma_mask & DMA_ENA)
{
for (; xebec->data_pos < 512; xebec->data_pos++)
{
int val = dma_channel_write(3, xebec->sector_buf[xebec->data_pos]);
if (val == DMA_NODATA)
{
pclog("CMD_READ_SECTORS out of data!\n");
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
xebec->callback = XEBEC_TIME;
return;
}
}
xebec->state = STATE_SENT_DATA;
xebec->callback = XEBEC_TIME;
}
else
fatal("Read sectors no DMA! - shouldn't get here\n");
break;
case STATE_SENT_DATA:
xebec_next_sector(xebec);
xebec->data_pos = 0;
xebec->sector_count = (xebec->sector_count-1) & 0xff;
if (xebec->sector_count)
{
if (xebec_get_sector(xebec, &addr))
{
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
xebec->state = STATE_SEND_DATA;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
{
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(xebec->data, xebec->sector_buf, 512);
}
}
else
{
xebec_complete(xebec);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0);
}
break;
default:
fatal("CMD_READ_SECTORS: bad state %i\n", xebec->state);
}
break;
case CMD_WRITE_SECTORS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
xebec->sector = xebec->command[2] & 0x1f;
xebec->sector_count = xebec->command[4];
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 512;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
xebec->status = STAT_BSY;
if (xebec->irq_dma_mask & DMA_ENA)
{
for (; xebec->data_pos < 512; xebec->data_pos++)
{
int val = dma_channel_read(3);
if (val == DMA_NODATA)
{
pclog("CMD_WRITE_SECTORS out of data!\n");
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
xebec->callback = XEBEC_TIME;
return;
}
xebec->sector_buf[xebec->data_pos] = val & 0xff;
}
xebec->state = STATE_RECEIVED_DATA;
xebec->callback = XEBEC_TIME;
}
else
fatal("Write sectors no DMA! - should never get here\n");
break;
case STATE_RECEIVED_DATA:
if (!(xebec->irq_dma_mask & DMA_ENA))
memcpy(xebec->sector_buf, xebec->data, 512);
{
if (xebec_get_sector(xebec, &addr))
{
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_write(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
}
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
xebec_next_sector(xebec);
xebec->data_pos = 0;
xebec->sector_count = (xebec->sector_count-1) & 0xff;
if (xebec->sector_count)
{
xebec->state = STATE_RECEIVE_DATA;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
xebec->status = STAT_BSY | STAT_REQ;
}
else
xebec_complete(xebec);
break;
default:
fatal("CMD_WRITE_SECTORS: bad state %i\n", xebec->state);
}
break;
case CMD_SEEK:
if (!drive->present)
xebec_error(xebec, ERR_NOT_READY);
else
{
int cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : cylinder;
if (cylinder != drive->current_cylinder)
xebec_error(xebec, ERR_SEEK_ERROR);
}
xebec_complete(xebec);
break;
case CMD_INIT_DRIVE_PARAMS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 8;
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
drive->cfg_cyl = xebec->data[1] | (xebec->data[0] << 8);
drive->cfg_hpc = xebec->data[2];
pclog("Drive %i: cylinders=%i, heads=%i\n", xebec->drive_sel, drive->cfg_cyl, drive->cfg_hpc);
xebec_complete(xebec);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", xebec->state);
}
break;
case CMD_WRITE_SECTOR_BUFFER:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 512;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
if (xebec->irq_dma_mask & DMA_ENA)
{
xebec->status = STAT_BSY;
for (; xebec->data_pos < 512; xebec->data_pos++)
{
int val = dma_channel_read(3);
if (val == DMA_NODATA)
{
pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n");
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
xebec->callback = XEBEC_TIME;
return;
}
xebec->data[xebec->data_pos] = val & 0xff;
}
xebec->state = STATE_RECEIVED_DATA;
xebec->callback = XEBEC_TIME;
}
else
fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n");
break;
case STATE_RECEIVED_DATA:
memcpy(xebec->sector_buf, xebec->data, 512);
xebec_complete(xebec);
break;
default:
fatal("CMD_WRITE_SECTOR_BUFFER bad state %i\n", xebec->state);
}
break;
case CMD_BUFFER_DIAGNOSTIC:
case CMD_CONTROLLER_DIAGNOSTIC:
xebec_complete(xebec);
break;
case 0xfa:
xebec_complete(xebec);
break;
case CMD_DTC_SET_STEP_RATE:
xebec_complete(xebec);
break;
case CMD_DTC_GET_DRIVE_PARAMS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 4;
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(xebec->data, 0, 4);
xebec->data[0] = drive->tracks & 0xff;
xebec->data[1] = 17 | ((drive->tracks >> 2) & 0xc0);
xebec->data[2] = drive->hpc-1;
pclog("Get drive params %02x %02x %02x %i\n", xebec->data[0], xebec->data[1], xebec->data[2], drive->tracks);
break;
case STATE_SENT_DATA:
xebec_complete(xebec);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", xebec->state);
}
break;
case CMD_DTC_GET_GEOMETRY:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 16;
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(xebec->data, 0, 16);
xebec->data[0x4] = drive->tracks & 0xff;
xebec->data[0x5] = (drive->tracks >> 8) & 0xff;
xebec->data[0xa] = drive->hpc;
break;
case STATE_SENT_DATA:
xebec_complete(xebec);
break;
}
break;
case CMD_DTC_SET_GEOMETRY:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 16;
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
/*Bit of a cheat here - we always report the actual geometry of the drive in use*/
xebec_complete(xebec);
break;
}
break;
default:
fatal("Unknown Xebec command - %02x %02x %02x %02x %02x %02x\n",
xebec->command[0], xebec->command[1],
xebec->command[2], xebec->command[3],
xebec->command[4], xebec->command[5]);
}
}
static void loadhd(xebec_t *xebec, int c, int d, const wchar_t *fn)
{
mfm_drive_t *drive = &xebec->drives[d];
int ret = 0;
ret = hdd_image_load(d);
if (!ret)
{
drive->present = 0;
return;
}
drive->spt = hdc[c].spt;
drive->hpc = hdc[c].hpc;
drive->tracks = hdc[c].tracks;
drive->hdc_num = c;
drive->present = 1;
}
static struct
{
int tracks, hpc;
} xebec_hd_types[4] =
{
{306, 4}, /*Type 0*/
{612, 4}, /*Type 16*/
{615, 4}, /*Type 2*/
{306, 8} /*Type 13*/
};
static void xebec_set_switches(xebec_t *xebec)
{
int c, d;
xebec->switches = 0;
for (d = 0; d < 2; d++)
{
mfm_drive_t *drive = &xebec->drives[d];
if (!drive->present)
continue;
for (c = 0; c < 4; c++)
{
if (drive->spt == 17 &&
drive->hpc == xebec_hd_types[c].hpc &&
drive->tracks == xebec_hd_types[c].tracks)
{
xebec->switches |= (c << (d ? 0 : 2));
break;
}
}
if (c == 4)
pclog("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C');
}
}
static void *xebec_init()
{
int i = 0;
int c = 0;
xebec_t *xebec = malloc(sizeof(xebec_t));
memset(xebec, 0, sizeof(xebec_t));
for (i = 0; i < HDC_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_MFM) && (hdc[i].mfm_channel < MFM_NUM))
{
loadhd(xebec, i, hdc[i].mfm_channel, hdc[i].fn);
c++;
if (c > MFM_NUM) break;
}
}
xebec_set_switches(xebec);
rom_init(&xebec->bios_rom, L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec);
timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec);
return xebec;
}
static void xebec_close(void *p)
{
xebec_t *xebec = (xebec_t *)p;
int d;
for (d = 0; d < 2; d++)
{
mfm_drive_t *drive = &xebec->drives[d];
hdd_image_close(drive->hdc_num);
}
free(xebec);
}
static int xebec_available()
{
return rom_present(L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin");
}
device_t mfm_xebec_device =
{
"IBM PC Fixed Disk Adapter",
0,
xebec_init,
xebec_close,
xebec_available,
NULL,
NULL,
NULL,
NULL
};
static void *dtc_5150x_init()
{
int i = 0;
int c = 0;
xebec_t *xebec = malloc(sizeof(xebec_t));
memset(xebec, 0, sizeof(xebec_t));
for (i = 0; i < HDC_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_MFM) && (hdc[i].mfm_channel < MFM_NUM))
{
loadhd(xebec, i, hdc[i].mfm_channel, hdc[i].fn);
c++;
if (c > MFM_NUM) break;
}
}
xebec->switches = 0xff;
xebec->drives[0].cfg_cyl = xebec->drives[0].tracks;
xebec->drives[0].cfg_hpc = xebec->drives[0].hpc;
xebec->drives[1].cfg_cyl = xebec->drives[1].tracks;
xebec->drives[1].cfg_hpc = xebec->drives[1].hpc;
rom_init(&xebec->bios_rom, L"roms/hdd/mfm_xebec/dtc_cxd21a.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec);
timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec);
return xebec;
}
static int dtc_5150x_available()
{
return rom_present(L"roms/hdd/mfm_xebec/dtc_cxd21a.bin");
}
device_t dtc_5150x_device =
{
"DTC 5150X",
0,
dtc_5150x_init,
xebec_close,
dtc_5150x_available,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,2 +0,0 @@
extern device_t mfm_xebec_device;
extern device_t dtc_5150x_device;

View File

@@ -1,6 +1,9 @@
/* Intel 82335 SX emulation, used by the Phoenix 386 clone. */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "mem.h"

372
src/ibm.h
View File

@@ -8,18 +8,20 @@
*
* General include file.
*
* Version: @(#)ibm.h 1.0.3 2017/09/03
* !!!NOTE!!! The goal is to GET RID of this file. Do NOT add stuff !!
*
* Version: @(#)ibm.h 1.0.8 2017/10/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define printf pclog
#ifndef EMU_IBM_H
# define EMU_IBM_H
#define printf pclog
/*Memory*/
@@ -286,38 +288,38 @@ extern int cpl_override;
/*Timer*/
typedef struct PIT_nr
{
int nr;
int64_t nr;
struct PIT *pit;
} PIT_nr;
typedef struct PIT
{
uint32_t l[3];
int c[3];
int64_t c[3];
uint8_t m[3];
uint8_t ctrl,ctrls[3];
int wp,rm[3],wm[3];
int64_t wp,rm[3],wm[3];
uint16_t rl[3];
int thit[3];
int delay[3];
int rereadlatch[3];
int gate[3];
int out[3];
int running[3];
int enabled[3];
int newcount[3];
int count[3];
int using_timer[3];
int initial[3];
int latched[3];
int disabled[3];
int64_t thit[3];
int64_t delay[3];
int64_t rereadlatch[3];
int64_t gate[3];
int64_t out[3];
int64_t running[3];
int64_t enabled[3];
int64_t newcount[3];
int64_t count[3];
int64_t using_timer[3];
int64_t initial[3];
int64_t latched[3];
int64_t disabled[3];
uint8_t read_status[3];
int do_read_status[3];
int64_t do_read_status[3];
PIT_nr pit_nr[3];
void (*set_out_funcs[3])(int new_out, int old_out);
void (*set_out_funcs[3])(int64_t new_out, int64_t old_out);
} PIT;
PIT pit, pit2;
@@ -373,176 +375,80 @@ extern PIC pic, pic2;
extern int pic_intpending;
extern int floppytime;
extern int64_t floppytime;
extern wchar_t floppyfns[4][512];
extern int driveempty[4];
#define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_HERCULESPLUS || gfxcard==GFX_INCOLOR || gfxcard==GFX_GENIUS) && (romset<ROM_TANDY || romset>=ROM_IBMAT))
#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_WY700 && gfxcard!=GFX_GENIUS && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && gfxcard!=GFX_HERCULESPLUS && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200)
#define PCJR (romset == ROM_IBMPCJR)
#define AMIBIOS (romset==ROM_AMI386SX || romset==ROM_AMI486 || romset == ROM_WIN486)
#define VGA ((gfxcard>=GFX_TVGA) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_WY700 && gfxcard!=GFX_GENIUS && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && gfxcard!=GFX_HERCULESPLUS && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200)
int GAMEBLASTER, GUS, SSI2001, voodoo_enabled, buslogic_enabled;
extern int AMSTRAD, AT, is286, is386, PCI, TANDY;
enum
{
ROM_IBMPC = 0, /*301 keyboard error, 131 cassette (!!!) error*/
ROM_IBMXT, /*301 keyboard error*/
ROM_IBMPCJR,
ROM_GENXT, /*'Generic XT BIOS'*/
ROM_DTKXT,
ROM_EUROPC,
ROM_OLIM24,
ROM_TANDY,
ROM_PC1512,
ROM_PC200,
ROM_PC1640,
ROM_PC2086,
ROM_PC3086,
ROM_AMIXT, /*XT Clone with AMI BIOS*/
ROM_LTXT,
ROM_LXT3,
ROM_PX386,
ROM_DTK386,
ROM_PXXT,
ROM_JUKOPC,
ROM_TANDY1000HX,
ROM_TANDY1000SL2,
ROM_IBMAT,
ROM_CMDPC30,
ROM_AMI286,
ROM_AWARD286,
ROM_DELL200,
ROM_MISC286,
ROM_IBMAT386,
ROM_ACER386,
ROM_MEGAPC,
ROM_AMI386SX,
ROM_AMI486,
ROM_WIN486,
ROM_PCI486,
ROM_SIS496,
ROM_430VX,
ROM_ENDEAVOR,
ROM_REVENGE,
ROM_IBMPS1_2011,
ROM_DESKPRO_386,
ROM_PORTABLE,
#if 0
ROM_PORTABLEII,
ROM_PORTABLEIII,
ROM_PORTABLEIII386, /* The original Compaq Portable III shipped with an Intel 80286 CPU, but later switched to a 386DX. */
#endif
ROM_IBMPS1_2121,
ROM_AMI386DX_OPTI495,
ROM_MR386DX_OPTI495,
ROM_IBMPS2_M30_286,
ROM_IBMPS2_M50,
ROM_IBMPS2_M55SX,
ROM_IBMPS2_M80,
ROM_DTK486, /*DTK PKM-0038S E-2 / SiS 471 / Award BIOS / SiS 85C471*/
ROM_VLI486SV2G, /*ASUS VL/I-486SV2G / SiS 471 / Award BIOS / SiS 85C471*/
ROM_R418, /*Rise Computer R418 / SiS 496/497 / Award BIOS / SMC FDC37C665*/
ROM_586MC1, /*Micro Star 586MC1 MS-5103 / 430LX / Award BIOS*/
ROM_PLATO, /*Intel Premiere/PCI II / 430NX / AMI BIOS / SMC FDC37C665*/
ROM_MB500N, /*PC Partner MB500N / 430FX / Award BIOS / SMC FDC37C665*/
ROM_P54TP4XE, /*ASUS P/I-P55TP4XE / 430FX / Award BIOS / SMC FDC37C665*/
ROM_AP53, /*AOpen AP53 / 430HX / AMI BIOS / SMC FDC37C665/669*/
ROM_P55T2S, /*ASUS P/I-P55T2S / 430HX / AMI BIOS / National Semiconductors PC87306*/
ROM_ACERM3A, /*Acer M3A / 430HX / Acer BIOS / SMC FDC37C932FR*/
ROM_ACERV35N, /*Acer V35N / 430HX / Acer BIOS / SMC FDC37C932FR*/
ROM_P55T2P4, /*ASUS P/I-P55T2P4 / 430HX / Award BIOS / Winbond W8387F*/
ROM_P55TVP4, /*ASUS P/I-P55TVP4 / 430HX / Award BIOS / Winbond W8387F*/
ROM_P55VA, /*Epox P55-VA / 430VX / Award BIOS / SMC FDC37C932FR*/
ROM_440FX, /*Tyan Titan-Pro AT / 440FX / Award BIOS / SMC FDC37C665*/
ROM_MARL, /*Intel Advanced/ML / 430HX / AMI BIOS / National Semiconductors PC87306*/
ROM_THOR, /*Intel Advanced/ATX / 430FX / AMI BIOS / National Semiconductors PC87306*/
ROM_MRTHOR, /*Intel Advanced/ATX / 430FX / MR.BIOS / National Semiconductors PC87306*/
ROM_POWERMATE_V,/*NEC PowerMate V / 430FX / Phoenix BIOS / SMC FDC37C665*/
ROM_IBMPS1_2121_ISA,/*IBM PS/1 Model 2121 with ISA expansion bus*/
ROM_SPC4200P, /*Samsung SPC-4200P / SCAT / Phoenix BIOS*/
ROM_SUPER286TR, /*Hyundai Super-286TR / SCAT / Award BIOS*/
ROM_AWARD386SX_OPTI495,
ROM_AWARD386DX_OPTI495,
ROM_AWARD486_OPTI495,
ROM_MEGAPCDX, /*386DX mdoel of the Mega PC - Note by Tohka: The documentation (that I have in German) clearly says such a model exists.*/
ROM_ZAPPA, /*Intel Advanced/ZP / 430FX / AMI BIOS / National Semiconductors PC87306*/
ROM_CMDPC60,
ROM_S1668, /*Tyan Titan-Pro ATX / 440FX / AMI BIOS / SMC FDC37C669*/
ROM_IBMPS1_2133,
ROM_PRESIDENT, /*President Award 430FX PCI / 430FX / Award BIOS / Unknown Super I/O chip*/
ROM_IBMPS2_M80_486,
ROM_MAX
};
extern int romspresent[ROM_MAX];
extern int hasfpu;
extern int romset;
enum
{
GFX_CGA = 0,
GFX_MDA,
GFX_HERCULES,
GFX_EGA, /*Using IBM EGA BIOS*/
GFX_TVGA, /*Using Trident TVGA8900D BIOS*/
GFX_ET4000, /*Tseng ET4000*/
GFX_ET4000W32, /*Tseng ET4000/W32p (Diamond Stealth 32)*/
GFX_BAHAMAS64, /*S3 Vision864 (Paradise Bahamas 64)*/
GFX_N9_9FX, /*S3 764/Trio64 (Number Nine 9FX)*/
GFX_VIRGE, /*S3 Virge*/
GFX_TGUI9440, /*Trident TGUI9440*/
GFX_VGA, /*IBM VGA*/
GFX_VGAEDGE16, /*ATI VGA Edge-16 (18800-1)*/
GFX_VGACHARGER, /*ATI VGA Charger (28800-5)*/
GFX_OTI067, /*Oak OTI-067*/
GFX_MACH64GX, /*ATI Graphics Pro Turbo (Mach64)*/
GFX_CL_GD5429, /*Cirrus Logic CL-GD5429*/
GFX_VIRGEDX, /*S3 Virge/DX*/
GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/
GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/
GFX_INCOLOR, /* Hercules InColor */
GFX_COLORPLUS, /* Plantronics ColorPlus */
GFX_WY700, /* Wyse 700 */
GFX_GENIUS, /* MDSI Genius */
GFX_MACH64VT2, /*ATI Mach64 VT2*/
GFX_EGA, /*Using IBM EGA BIOS*/
GFX_TVGA, /*Using Trident TVGA8900D BIOS*/
GFX_ET4000, /*Tseng ET4000*/
GFX_ET4000W32_VLB, /*Tseng ET4000/W32p (Diamond Stealth 32) VLB*/
GFX_ET4000W32_PCI, /*Tseng ET4000/W32p (Diamond Stealth 32) PCI*/
GFX_BAHAMAS64_VLB, /*S3 Vision864 (Paradise Bahamas 64) VLB*/
GFX_BAHAMAS64_PCI, /*S3 Vision864 (Paradise Bahamas 64) PCI*/
GFX_N9_9FX_VLB, /*S3 764/Trio64 (Number Nine 9FX) VLB*/
GFX_N9_9FX_PCI, /*S3 764/Trio64 (Number Nine 9FX) PCI*/
GFX_VIRGE_VLB, /*S3 Virge VLB*/
GFX_VIRGE_PCI, /*S3 Virge PCI*/
GFX_TGUI9440_VLB, /*Trident TGUI9440 VLB*/
GFX_TGUI9440_PCI, /*Trident TGUI9440 PCI*/
GFX_VGA, /*IBM VGA*/
GFX_VGAEDGE16, /*ATI VGA Edge-16 (18800-1)*/
GFX_VGACHARGER, /*ATI VGA Charger (28800-5)*/
GFX_OTI067, /*Oak OTI-067*/
GFX_MACH64GX_VLB, /*ATI Graphics Pro Turbo (Mach64) VLB*/
GFX_MACH64GX_PCI, /*ATI Graphics Pro Turbo (Mach64) PCI*/
GFX_CL_GD5429, /*Cirrus Logic CL-GD5429*/
GFX_VIRGEDX_VLB, /*S3 Virge/DX VLB*/
GFX_VIRGEDX_PCI, /*S3 Virge/DX PCI*/
GFX_PHOENIX_TRIO32_VLB, /*S3 732/Trio32 (Phoenix) VLB*/
GFX_PHOENIX_TRIO32_PCI, /*S3 732/Trio32 (Phoenix) PCI*/
GFX_PHOENIX_TRIO64_VLB, /*S3 764/Trio64 (Phoenix) VLB*/
GFX_PHOENIX_TRIO64_PCI, /*S3 764/Trio64 (Phoenix) PCI*/
GFX_INCOLOR, /*Hercules InColor*/
GFX_COLORPLUS, /*Plantronics ColorPlus*/
GFX_WY700, /*Wyse 700*/
GFX_GENIUS, /*MDSI Genius*/
GFX_MACH64VT2, /*ATI Mach64 VT2*/
GFX_COMPAQ_EGA, /*Compaq EGA*/
GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/
GFX_COMPAQ_VGA, /*Compaq/Paradise VGA*/
GFX_MIRO_VISION964, /*S3 Vision964 (Miro Crystal)*/
GFX_CL_GD5446, /*Cirrus Logic CL-GD5446*/
GFX_VGAWONDERXL, /*Compaq ATI VGA Wonder XL (28800-5)*/
GFX_WD90C11, /*Paradise WD90C11 Standalone*/
GFX_OTI077, /*Oak OTI-077*/
GFX_VGAWONDERXL24, /*Compaq ATI VGA Wonder XL24 (28800-6)*/
GFX_STEALTH64, /*S3 Vision864 (Diamond Stealth 64)*/
GFX_PHOENIX_VISION864, /*S3 Vision864 (Phoenix)*/
GFX_RIVATNT,
GFX_RIVA128,
GFX_COMPAQ_EGA, /*Compaq EGA*/
GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/
GFX_COMPAQ_VGA, /*Compaq/Paradise VGA*/
GFX_CL_GD5446, /*Cirrus Logic CL-GD5446*/
GFX_VGAWONDERXL, /*Compaq ATI VGA Wonder XL (28800-5)*/
GFX_WD90C11, /*Paradise WD90C11 Standalone*/
GFX_OTI077, /*Oak OTI-077*/
GFX_VGAWONDERXL24, /*Compaq ATI VGA Wonder XL24 (28800-6)*/
GFX_STEALTH64_VLB, /*S3 Vision864 (Diamond Stealth 64) VLB*/
GFX_STEALTH64_PCI, /*S3 Vision864 (Diamond Stealth 64) PCI*/
GFX_PHOENIX_VISION864_VLB, /*S3 Vision864 (Phoenix) VLB*/
GFX_PHOENIX_VISION864_PCI, /*S3 Vision864 (Phoenix) PCI*/
GFX_RIVATNT, /*nVidia Riva TNT*/
GFX_RIVATNT2, /*nVidia Riva TNT2*/
GFX_RIVA128, /*nVidia Riva 128*/
GFX_HERCULESPLUS,
GFX_RIVATNT2,
GFX_VIRGEVX_VLB, /*S3 Virge/VX VLB*/
GFX_VIRGEVX_PCI, /*S3 Virge/VX PCI*/
GFX_VIRGEDX4_VLB, /*S3 Virge/DX (VBE 2.0) VLB*/
GFX_VIRGEDX4_PCI, /*S3 Virge/DX (VBE 2.0) PCI*/
GFX_TRIGEM_UNK,
GFX_OTI037, /*Oak OTI-037*/
GFX_OTI037, /*Oak OTI-037*/
GFX_VIRGEVX, /*S3 Virge/VX*/
GFX_VIRGEDX4, /*S3 Virge/DX (VBE 2.0)*/
GFX_TRIGEM_UNK, /*Unknown TriGem graphics card with Hangeul ROM*/
GFX_MIRO_VISION964, /*S3 Vision964 (Miro Crystal)*/
GFX_MAX
};
@@ -585,62 +491,12 @@ extern int gated,speakval,speakon;
#define SND_WSS 9 /*Windows Sound System*/
#define SND_PAS16 10 /*Pro Audio Spectrum 16*/
extern wchar_t pcempath[512];
extern wchar_t exe_path[1024];
extern wchar_t cfg_path[1024];
/*Hard disk*/
enum
{
HDD_BUS_DISABLED = 0,
HDD_BUS_MFM,
HDD_BUS_XTIDE,
HDD_BUS_ESDI,
HDD_BUS_IDE_PIO_ONLY,
HDD_BUS_IDE_PIO_AND_DMA,
HDD_BUS_SCSI,
HDD_BUS_SCSI_REMOVABLE,
HDD_BUS_USB
};
#define HDC_NUM 30
#define MFM_NUM 2
#define ESDI_NUM 2
#define XTIDE_NUM 2
#define IDE_NUM 8
#define SCSI_NUM 16 /* Theoretically the controller can have at least 64 devices, or even 128 in case of a wide bus, but
let's not exaggerate with them - 16 ought to be enough for everyone. */
#pragma pack(push,1)
typedef struct {
FILE *f;
uint64_t spt,hpc; /*Sectors per track, heads per cylinder*/
uint64_t tracks;
int is_hdi;
int wp;
uint32_t base;
uint64_t at_spt,at_hpc; /*[Translation] Sectors per track, heads per cylinder*/
unsigned int bus;
unsigned int mfm_channel;
unsigned int esdi_channel;
unsigned int xtide_channel;
unsigned int ide_channel;
unsigned int scsi_id;
unsigned int scsi_lun;
wchar_t fn[260];
wchar_t prev_fn[260];
} hard_disk_t;
#pragma pack(pop)
extern hard_disk_t hdc[HDC_NUM];
uint64_t hdt[128][3];
uint64_t hdt_mfm[128][3];
int image_is_hdi(const wchar_t *s);
int image_is_hdx(const wchar_t *s, int check_signature);
/*Keyboard*/
extern int keybsenddelay;
extern int64_t keybsenddelay;
/*CD-ROM*/
@@ -653,7 +509,7 @@ enum
CDROM_BUS_USB = 8
};
extern int idecallback[5];
extern int64_t idecallback[5];
#define CD_STATUS_EMPTY 0
#define CD_STATUS_DATA_ONLY 1
@@ -682,10 +538,6 @@ extern uint64_t timer_freq;
extern int infocus;
extern void onesec(void);
extern void resetpc_cad(void);
extern void ctrl_alt_esc(void);
extern int dump_on_exit;
extern int start_in_fullscreen;
@@ -704,10 +556,6 @@ extern uint64_t star;
#define FPU_CW_Reserved_Bits (0xe0c0)
extern wchar_t nvr_path[1024];
extern int path_len;
wchar_t *nvr_concat(wchar_t *to_concat);
extern int mem_a20_state;
@@ -735,11 +583,11 @@ extern PCI_RESET pci_reset_handler;
extern void trc_init(void);
extern int enable_xtide;
extern int enable_external_fpu;
extern int serial_enabled[2];
extern int lpt_enabled, bugger_enabled;
extern int romset;
extern int invert_display;
@@ -749,8 +597,24 @@ extern int scale;
/* Function prototypes. */
extern void pclog(const char *format, ...);
extern void fatal(const char *format, ...);
extern wchar_t *pc_concat(wchar_t *str);
extern int pc_init_modules(void);
extern int pc_init(int argc, wchar_t *argv[]);
extern void pc_close(void);
extern void pc_reset_hard_close(void);
extern void pc_reset_hard_init(void);
extern void pc_reset_hard(void);
extern void pc_full_speed(void);
extern void pc_speed_changed(void);
extern void pc_send_cad(void);
extern void pc_send_cae(void);
extern void pc_run(void);
extern void onesec(void);
extern int checkio(int port);
extern void closepc(void);
extern void codegen_block_end(void);
extern void codegen_reset(void);
extern void cpu_set_edx(void);
@@ -762,12 +626,9 @@ extern void execx86(int cycs);
extern void flushmmucache(void);
extern void flushmmucache_cr3(void);
extern int idivl(int32_t val);
extern void initmodules(void);
extern void initpc(int argc, wchar_t *argv[]);
extern void loadcscall(uint16_t seg);
extern void loadcsjmp(uint16_t seg, uint32_t oxpc);
extern void mmu_invalidate(uint32_t addr);
extern void pclog(const char *format, ...);
extern void pmodeint(int num, int soft);
extern void pmoderetf(int is32, uint16_t off);
extern void pmodeiret(int is32);
@@ -775,15 +636,9 @@ extern void port_92_clear_reset(void);
extern uint8_t readdacfifo(void);
extern void refreshread(void);
extern void resetmcr(void);
extern void resetpchard_close(void);
extern void resetpchard_init(void);
extern void resetpchard(void);
extern void resetreadlookup(void);
extern void resetx86(void);
extern void runpc(void);
extern void saveconfig(void);
extern void softresetx86(void);
extern void speedchanged(void);
extern void x86_int_sw(int num);
extern int x86_int_sw_rm(int num);
extern void x86gpf(char *s, uint16_t error);
@@ -793,25 +648,10 @@ extern void x86ts(char *s, uint16_t error);
extern void x87_dumpregs(void);
extern void x87_reset(void);
/* Platform functions. */
extern void pclog(const char *format, ...);
extern void pclog_w(const wchar_t *format, ...);
extern void fatal(const char *format, ...);
extern void update_status_bar_icon(int tag, int active);
extern void update_status_bar_icon_state(int tag, int state);
extern void status_settextw(wchar_t *wstr);
extern void status_settext(char *str);
#define SB_FLOPPY 0x00
#define SB_CDROM 0x10
#define SB_RDISK 0x20
#define SB_HDD 0x40
#define SB_NETWORK 0x50
#define SB_TEXT 0x60
#define UNUSED(x) (void)x
/* Configuration values. */
#define SERIAL_MAX 2
#define PARALLEL_MAX 1
#endif /*EMU_IBM_H*/

View File

@@ -1,6 +1,10 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "cpu/cpu.h"
#include "io.h"
@@ -23,7 +27,7 @@ uint8_t batman_brdconfig(uint16_t port, void *p)
}
static uint16_t batman_timer_latch;
static int batman_timer = 0;
static int64_t batman_timer = 0;
static void batman_timer_over(void *p)
{
batman_timer = 0;

View File

@@ -8,21 +8,27 @@
*
* Implementation of the Intel 2 Mbit 8-bit flash devices.
*
* Version: @(#)intel_flash.c 1.0.1 2017/08/23
* Version: @(#)intel_flash.c 1.0.8 2017/10/14
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "ibm.h"
#include "cpu/cpu.h"
#include "device.h"
#include "mem.h"
#include "machine/machine.h"
#include "rom.h"
#include "nvr.h"
#include "plat.h"
#define FLASH_IS_BXB 2
#define FLASH_INVERT 1
@@ -175,7 +181,7 @@ static void intel_flash_add_mappings_inverted(flash_t *flash)
void *intel_flash_init(uint8_t type)
{
FILE *f;
int i;
int i, l;
flash_t *flash;
wchar_t *machine_name;
wchar_t *flash_name;
@@ -183,14 +189,16 @@ void *intel_flash_init(uint8_t type)
flash = malloc(sizeof(flash_t));
memset(flash, 0, sizeof(flash_t));
machine_name = (wchar_t *) malloc((strlen(machine_get_internal_name_ex(machine)) << 1) + 2);
mbstowcs(machine_name, machine_get_internal_name_ex(machine), strlen(machine_get_internal_name_ex(machine)) + 1);
flash_name = (wchar_t *) malloc((wcslen(machine_name) << 1) + 2 + 8);
_swprintf(flash_name, L"%s.bin", machine_name);
l = strlen(machine_get_internal_name_ex(machine)) + 1;
machine_name = (wchar_t *) malloc(l << 1);
mbstowcs(machine_name, machine_get_internal_name_ex(machine), l);
l = wcslen(machine_name) + 5;
flash_name = (wchar_t *) malloc(l << 1);
swprintf(flash_name, l, L"%s.bin", machine_name);
wcscpy(flash_path, flash_name);
pclog_w(L"Flash path: %s\n", flash_name);
pclog("Flash path: %ls\n", flash_name);
flash->flash_id = (type & FLASH_IS_BXB) ? 0x95 : 0x94;
flash->invert_high_pin = (type & FLASH_INVERT);
@@ -252,7 +260,7 @@ void *intel_flash_init(uint8_t type)
flash->command = CMD_READ_ARRAY;
flash->status = 0;
f = nvrfopen(flash_path, L"rb");
f = nvr_fopen(flash_path, L"rb");
if (f)
{
fread(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
@@ -295,7 +303,7 @@ void intel_flash_close(void *p)
FILE *f;
flash_t *flash = (flash_t *)p;
f = nvrfopen(flash_path, L"wb");
f = nvr_fopen(flash_path, L"wb");
fwrite(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
fwrite(&(flash->array[flash->block_start[BLOCK_DATA1]]), flash->block_len[BLOCK_DATA1], 1, f);
fwrite(&(flash->array[flash->block_start[BLOCK_DATA2]]), flash->block_len[BLOCK_DATA2], 1, f);
@@ -304,54 +312,43 @@ void intel_flash_close(void *p)
free(flash);
}
device_t intel_flash_bxt_ami_device =
{
"Intel 28F001BXT Flash BIOS",
0,
0, 0,
intel_flash_bxt_ami_init,
intel_flash_close,
NULL,
NULL,
NULL,
NULL,
NULL
NULL,
NULL, NULL, NULL, NULL, NULL
};
device_t intel_flash_bxb_ami_device =
{
"Intel 28F001BXB Flash BIOS",
0,
0, 0,
intel_flash_bxb_ami_init,
intel_flash_close,
NULL,
NULL,
NULL,
NULL,
NULL
NULL,
NULL, NULL, NULL, NULL, NULL
};
device_t intel_flash_bxt_device =
{
"Intel 28F001BXT Flash BIOS",
0,
0, 0,
intel_flash_bxt_init,
intel_flash_close,
NULL,
NULL,
NULL,
NULL,
NULL
NULL,
NULL, NULL, NULL, NULL, NULL
};
device_t intel_flash_bxb_device =
{
"Intel 28F001BXB Flash BIOS",
0,
0, 0,
intel_flash_bxb_init,
intel_flash_close,
NULL,
NULL,
NULL,
NULL,
NULL
NULL,
NULL, NULL, NULL, NULL, NULL
};

View File

@@ -6,14 +6,17 @@
*
* Emulation of Intel System I/O PCI chip.
*
* Version: @(#)intel_sio.c 1.0.5 2017/09/03
* Version: @(#)intel_sio.c 1.0.6 2017/09/24
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "dma.h"

View File

@@ -1,6 +1,10 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
@@ -69,6 +73,44 @@ void io_sethandler(uint16_t base, int size,
}
}
void io_sethandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
int c;
size <<= 2;
for (c = 0; c < size; c += 2)
{
if (!port_inb[ base + c][0] && !port_inw[ base + c][0] && !port_inl[ base + c][0] &&
!port_outb[base + c][0] && !port_outw[base + c][0] && !port_outl[base + c][0])
{
port_inb[ base + c][0] = inb;
port_inw[ base + c][0] = inw;
port_inl[ base + c][0] = inl;
port_outb[base + c][0] = outb;
port_outw[base + c][0] = outw;
port_outl[base + c][0] = outl;
port_priv[base + c][0] = priv;
}
else if (!port_inb[ base + c][1] && !port_inw[ base + c][1] && !port_inl[ base + c][1] &&
!port_outb[base + c][1] && !port_outw[base + c][1] && !port_outl[base + c][1])
{
port_inb[ base + c][1] = inb;
port_inw[ base + c][1] = inw;
port_inl[ base + c][1] = inl;
port_outb[base + c][1] = outb;
port_outw[base + c][1] = outw;
port_outl[base + c][1] = outl;
port_priv[base + c][1] = priv;
}
}
}
void io_removehandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
@@ -116,11 +158,61 @@ void io_removehandler(uint16_t base, int size,
}
}
void io_removehandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
int c;
size <<= 2;
for (c = 0; c < size; c += 2)
{
if (port_priv[base + c][0] == priv)
{
if (port_inb[ base + c][0] == inb)
port_inb[ base + c][0] = NULL;
if (port_inw[ base + c][0] == inw)
port_inw[ base + c][0] = NULL;
if (port_inl[ base + c][0] == inl)
port_inl[ base + c][0] = NULL;
if (port_outb[ base + c][0] == outb)
port_outb[ base + c][0] = NULL;
if (port_outw[ base + c][0] == outw)
port_outw[ base + c][0] = NULL;
if (port_outl[ base + c][0] == outl)
port_outl[ base + c][0] = NULL;
port_priv[base + c][0] = NULL;
}
if (port_priv[base + c][1] == priv)
{
if (port_inb[ base + c][1] == inb)
port_inb[ base + c][1] = NULL;
if (port_inw[ base + c][1] == inw)
port_inw[ base + c][1] = NULL;
if (port_inl[ base + c][1] == inl)
port_inl[ base + c][1] = NULL;
if (port_outb[ base + c][1] == outb)
port_outb[ base + c][1] = NULL;
if (port_outw[ base + c][1] == outw)
port_outw[ base + c][1] = NULL;
if (port_outl[ base + c][1] == outl)
port_outl[ base + c][1] = NULL;
port_priv[base + c][1] = NULL;
}
}
}
#if 0
uint8_t cgamode,cgastat=0,cgacol;
int hsync;
uint8_t lpt2dat;
int sw9;
int t237=0;
#endif
uint8_t inb(uint16_t port)
{
uint8_t temp = 0xff;

View File

@@ -11,7 +11,16 @@ extern void io_sethandler(uint16_t base, int size,
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);
extern void io_sethandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);
extern void io_removehandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
@@ -20,3 +29,12 @@ extern void io_removehandler(uint16_t base, int size,
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);
extern void io_removehandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);

View File

@@ -8,20 +8,26 @@
*
* Host to guest keyboard interface and keyboard scan code sets.
*
* Version: @(#)keyboard.c 1.0.1 2017/08/23
* Version: @(#)keyboard.c 1.0.4 2017/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "plat_keyboard.h"
#include "keyboard.h"
int keybsendcallback = 0;
int keybsenddelay;
int64_t keybsenddelay;
typedef struct
{

View File

@@ -1,7 +1,10 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "mem.h"
@@ -45,12 +48,16 @@ void keyboard_amstrad_poll(void)
keyboard_amstrad.wantirq = 0;
keyboard_amstrad.pa = keyboard_amstrad.key_waiting;
picint(2);
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_amstrad : take IRQ\n");
#endif
}
if (key_queue_start != key_queue_end && !keyboard_amstrad.pa)
{
keyboard_amstrad.key_waiting = key_queue[key_queue_start];
#if ENABLE_KEYBOARD_LOG
pclog("Reading %02X from the key queue at %i\n", keyboard_amstrad.key_waiting, key_queue_start);
#endif
key_queue_start = (key_queue_start + 1) & 0xf;
keyboard_amstrad.wantirq = 1;
}
@@ -59,22 +66,30 @@ void keyboard_amstrad_poll(void)
void keyboard_amstrad_adddata(uint8_t val)
{
key_queue[key_queue_end] = val;
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_amstrad : %02X added to key queue at %i\n", val, key_queue_end);
#endif
key_queue_end = (key_queue_end + 1) & 0xf;
return;
}
void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv)
{
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, keyboard_amstrad.pb);
#endif
switch (port)
{
case 0x61:
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_amstrad : pb write %02X %02X %i %02X %i\n", val, keyboard_amstrad.pb, !(keyboard_amstrad.pb & 0x40), keyboard_amstrad.pb & 0x40, (val & 0x40));
#endif
if (!(keyboard_amstrad.pb & 0x40) && (val & 0x40)) /*Reset keyboard*/
{
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_amstrad : reset keyboard\n");
#endif
keyboard_amstrad_adddata(0xaa);
}
keyboard_amstrad.pb = val;
@@ -165,7 +180,9 @@ void keyboard_amstrad_reset(void)
void keyboard_amstrad_init(void)
{
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_amstrad_init\n");
#endif
io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL, NULL);
keyboard_amstrad_reset();
keyboard_send = keyboard_amstrad_adddata;

View File

@@ -8,19 +8,23 @@
*
* Intel 8042 (AT keyboard controller) emulation.
*
* Version: @(#)keyboard_at.c 1.0.2 2017/09/03
* Version: @(#)keyboard_at.c 1.0.3 2017/09/24
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "pic.h"
#include "pit.h"
#include "mem.h"
#include "rom.h"
#include "timer.h"
#include "floppy/floppy.h"
#include "floppy/fdc.h"
@@ -43,7 +47,7 @@
#define STAT_IFULL 0x02
#define STAT_OFULL 0x01
#define PS2_REFRESH_TIME (16 * TIMER_USEC)
#define PS2_REFRESH_TIME (16LL * TIMER_USEC)
#define CCB_UNUSED 0x80
#define CCB_TRANSLATE 0x40
@@ -84,7 +88,7 @@ struct
void (*mouse_write)(uint8_t val, void *p);
void *mouse_p;
int refresh_time;
int64_t refresh_time;
int refresh;
int is_ps2;
@@ -141,7 +145,7 @@ void keyboard_at_log(const char *format, ...)
static void keyboard_at_poll(void)
{
keybsenddelay += (1000 * TIMER_USEC);
keybsenddelay += (1000LL * TIMER_USEC);
if ((keyboard_at.out_new != -1) && !keyboard_at.last_irq)
{

View File

@@ -1,4 +1,8 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "mem.h"
@@ -45,16 +49,20 @@ static uint8_t mouse_scancodes[7];
static void keyboard_olim24_poll(void)
{
keybsenddelay += (1000 * TIMER_USEC);
keybsenddelay += (1000LL * TIMER_USEC);
if (keyboard_olim24.wantirq)
{
keyboard_olim24.wantirq = 0;
picint(2);
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_olim24 : take IRQ\n");
#endif
}
if (!(keyboard_olim24.status & STAT_OFULL) && key_queue_start != key_queue_end)
{
#if ENABLE_KEYBOARD_LOG
pclog("Reading %02X from the key queue at %i\n", keyboard_olim24.out, key_queue_start);
#endif
keyboard_olim24.out = key_queue[key_queue_start];
key_queue_start = (key_queue_start + 1) & 0xf;
keyboard_olim24.status |= STAT_OFULL;
@@ -68,14 +76,18 @@ void keyboard_olim24_adddata(uint8_t val)
{
key_queue[key_queue_end] = val;
key_queue_end = (key_queue_end + 1) & 0xf;
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_olim24 : %02X added to key queue %02X\n", val, keyboard_olim24.status);
#endif
return;
}
static void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv)
{
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_olim24 : write %04X %02X\n", port, val);
#endif
/* if (ram[8] == 0xc3)
{
output = 3;

View File

@@ -1,7 +1,10 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "mem.h"
@@ -43,7 +46,7 @@ static int key_queue_start = 0, key_queue_end = 0;
void keyboard_pcjr_poll()
{
keybsenddelay += (220 * TIMER_USEC);
keybsenddelay += (220LL * TIMER_USEC);
if (key_queue_start != key_queue_end && !keyboard_pcjr.serial_pos && !keyboard_pcjr.latched)

View File

@@ -1,10 +1,14 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "ibm.h"
#include "io.h"
#include "mem.h"
#include "rom.h"
#include "pic.h"
#include "pit.h"
#include "timer.h"
@@ -42,12 +46,14 @@ static int key_queue_start = 0, key_queue_end = 0;
static void keyboard_xt_poll(void)
{
keybsenddelay += (1000 * TIMER_USEC);
keybsenddelay += (1000LL * TIMER_USEC);
if (key_queue_start != key_queue_end && !keyboard_xt.blocked)
{
keyboard_xt.pa = key_queue[key_queue_start];
picint(2);
#if ENABLE_KEYBOARD_LOG
pclog("Reading %02X from the key queue at %i\n", keyboard_xt.pa, key_queue_start);
#endif
key_queue_start = (key_queue_start + 1) & 0xf;
keyboard_xt.blocked = 1;
}
@@ -56,7 +62,9 @@ static void keyboard_xt_poll(void)
void keyboard_xt_adddata(uint8_t val)
{
key_queue[key_queue_end] = val;
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_xt : %02X added to key queue at %i\n", val, key_queue_end);
#endif
key_queue_end = (key_queue_end + 1) & 0xf;
return;
}
@@ -68,7 +76,9 @@ static void keyboard_xt_write(uint16_t port, uint8_t val, void *priv)
case 0x61:
if (!(keyboard_xt.pb & 0x40) && (val & 0x40)) /*Reset keyboard*/
{
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_xt : reset keyboard\n");
#endif
key_queue_end = key_queue_start;
keyboard_xt_adddata(0xaa);
}

View File

@@ -1,725 +0,0 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*Linux CD-ROM support via IOCTL*/
#include <linux/cdrom.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include "ibm.h"
#include "ide.h"
#include "cdrom_ioctl.h"
static ATAPI ioctl_atapi;
static uint32_t last_block = 0;
static uint32_t cdrom_capacity = 0;
static int ioctl_inited = 0;
static char ioctl_path[8];
static int tocvalid = 0;
static struct cdrom_tocentry toc[100];
static int first_track, last_track;
int old_cdrom_drive;
#define MSFtoLBA(m,s,f) (((((m*60)+s)*75)+f)-150)
enum
{
CD_STOPPED = 0,
CD_PLAYING,
CD_PAUSED
};
static int ioctl_cd_state = CD_STOPPED;
static uint32_t ioctl_cd_pos = 0, ioctl_cd_end = 0;
#define BUF_SIZE 32768
static int16_t cd_buffer[BUF_SIZE];
static int cd_buflen = 0;
void ioctl_audio_callback(int16_t *output, int len)
{
int fd;
struct cdrom_read_audio read_audio;
// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount());
if (ioctl_cd_state != CD_PLAYING)
{
memset(output, 0, len * 2);
return;
}
fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
{
memset(output, 0, len * 2);
return;
}
while (cd_buflen < len)
{
if (ioctl_cd_pos < ioctl_cd_end)
{
read_audio.addr.lba = ioctl_cd_pos - 150;
read_audio.addr_format = CDROM_LBA;
read_audio.nframes = 1;
read_audio.buf = (__u8 *)&cd_buffer[cd_buflen];
if (ioctl(fd, CDROMREADAUDIO, &read_audio) < 0)
{
// pclog("DeviceIoControl returned false\n");
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
ioctl_cd_state = CD_STOPPED;
cd_buflen = len;
}
else
{
// pclog("DeviceIoControl returned true\n");
ioctl_cd_pos++;
cd_buflen += (2352 / 2);
}
}
else
{
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
ioctl_cd_state = CD_STOPPED;
cd_buflen = len;
}
}
close(fd);
memcpy(output, cd_buffer, len * 2);
// for (c = 0; c < BUF_SIZE - len; c++)
// cd_buffer[c] = cd_buffer[c + cd_buflen];
memcpy(&cd_buffer[0], &cd_buffer[len], (BUF_SIZE - len) * 2);
cd_buflen -= len;
// pclog("Done %i\n", GetTickCount());
}
void ioctl_audio_stop()
{
ioctl_cd_state = CD_STOPPED;
}
static int get_track_nr(uint32_t pos)
{
int c;
int track = 0;
if (!tocvalid)
return 0;
for (c = first_track; c < last_track; c++)
{
uint32_t track_address = toc[c].cdte_addr.msf.frame +
(toc[c].cdte_addr.msf.second * 75) +
(toc[c].cdte_addr.msf.minute * 75 * 60);
//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address);
if (track_address <= pos)
track = c;
}
return track;
}
static int is_track_audio(uint32_t pos)
{
int c;
int control = 0;
if (!tocvalid)
return 0;
for (c = first_track; c < last_track; c++)
{
uint32_t track_address = toc[c].cdte_addr.msf.frame +
(toc[c].cdte_addr.msf.second * 75) +
(toc[c].cdte_addr.msf.minute * 75 * 60);
//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address);
if (track_address <= pos)
control = toc[c].cdte_ctrl;
}
return (control & 4) ? 0 : 1;
}
static int ioctl_is_track_audio(uint32_t pos, int ismsf)
{
if (ismsf)
{
int m = (pos >> 16) & 0xff;
int s = (pos >> 8) & 0xff;
int f = pos & 0xff;
pos = MSFtoLBA(m, s, f);
}
return is_track_audio(pos);
}
static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
// pclog("Play audio - %08X %08X %i\n", pos, len, ismsf);
if (ismsf)
{
pos = (pos & 0xff) + (((pos >> 8) & 0xff) * 75) + (((pos >> 16) & 0xff) * 75 * 60);
len = (len & 0xff) + (((len >> 8) & 0xff) * 75) + (((len >> 16) & 0xff) * 75 * 60);
// pclog("MSF - pos = %08X len = %08X\n", pos, len);
}
else
len += pos;
ioctl_cd_pos = pos;// + 150;
ioctl_cd_end = pos+len;// + 150;
ioctl_cd_state = CD_PLAYING;
if (ioctl_cd_pos < 150)
ioctl_cd_pos = 150;
// pclog("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, 0, len);
}
static void ioctl_pause(void)
{
if (ioctl_cd_state == CD_PLAYING)
ioctl_cd_state = CD_PAUSED;
}
static void ioctl_resume(void)
{
if (ioctl_cd_state == CD_PAUSED)
ioctl_cd_state = CD_PLAYING;
}
static void ioctl_stop(void)
{
ioctl_cd_state = CD_STOPPED;
}
static void ioctl_seek(uint32_t pos)
{
// pclog("Seek %08X\n", pos);
ioctl_cd_pos = pos;
ioctl_cd_state = CD_STOPPED;
}
static int read_toc(int fd, struct cdrom_tocentry *btoc)
{
struct cdrom_tochdr toc_hdr;
int track, err;
//pclog("read_toc\n");
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
pclog("read_toc: CDROMREADTOCHDR failed\n");
return 0;
}
first_track = toc_hdr.cdth_trk0;
last_track = toc_hdr.cdth_trk1;
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
memset(btoc, 0, sizeof(cdrom_tocentry));
for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++)
{
btoc[track].cdte_track = track;
btoc[track].cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &btoc[track]);
if (err == -1)
{
// pclog("read_toc: CDROMREADTOCENTRY failed on track %i\n", track);
return 0;
}
// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame);
}
return 1;
}
static int ioctl_ready(void)
{
long size;
int temp;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc_entry;
int err;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
close(fd);
return 0;
}
// pclog("CDROMREADTOCHDR: start track=%i end track=%i\n", toc_hdr.cdth_trk0, toc_hdr.cdth_trk1);
toc_entry.cdte_track = toc_hdr.cdth_trk1;
toc_entry.cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc_entry);
if (err == -1)
{
close(fd);
return 0;
}
// pclog("CDROMREADTOCENTRY: addr=%02i:%02i:%02i\n", toc_entry.cdte_addr.msf.minute, toc_entry.cdte_addr.msf.second, toc_entry.cdte_addr.msf.frame);
if ((toc_entry.cdte_addr.msf.minute != toc[toc_hdr.cdth_trk1].cdte_addr.msf.minute) ||
(toc_entry.cdte_addr.msf.second != toc[toc_hdr.cdth_trk1].cdte_addr.msf.second) ||
(toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ) ||
!tocvalid)
{
int track;
ioctl_cd_state = CD_STOPPED;
tocvalid = read_toc(fd, toc);
close(fd);
return 1;
}
close(fd);
return 1;
}
static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, int single)
{
int c;
int lb = 0;
int tv = 0;
struct cdrom_tocentry lbtoc[100];
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
ioctl_cd_state = CD_STOPPED;
tv = read_toc(fd, lbtoc);
close(fd);
if (!tv)
return 0;
last_block = 0;
for (c = 0; c <= last_track; c++)
{
uint32_t address;
address = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
if (address > last_block)
lb = address;
}
return lb;
}
static int ioctl_medium_changed(void)
{
long size;
int temp;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc_entry;
int err;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
close(fd);
return 0;
}
toc_entry.cdte_track = toc_hdr.cdth_trk1;
toc_entry.cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc_entry);
if (err == -1)
{
close(fd);
return 0;
}
// pclog("CDROMREADTOCENTRY: addr=%02i:%02i:%02i\n", toc_entry.cdte_addr.msf.minute, toc_entry.cdte_addr.msf.second, toc_entry.cdte_addr.msf.frame);
if ((toc_entry.cdte_addr.msf.minute != toc[toc_hdr.cdth_trk1].cdte_addr.msf.minute) ||
(toc_entry.cdte_addr.msf.second != toc[toc_hdr.cdth_trk1].cdte_addr.msf.second) ||
(toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ))
{
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
return 1;
}
return 0;
}
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
{
struct cdrom_subchnl sub;
uint32_t cdpos = ioctl_cd_pos;
int track = get_track_nr(cdpos);
uint32_t track_address = toc[track].cdte_addr.msf.frame +
(toc[track].cdte_addr.msf.second * 75) +
(toc[track].cdte_addr.msf.minute * 75 * 60);
long size;
int pos=0;
int err;
uint8_t ret;
//pclog("ioctl_getsubchannel: cdpos=%x track_address=%x track=%i\n", cdpos, track_address, track);
if (ioctl_cd_state == CD_PLAYING)
ret = 0x11;
else if (ioctl_cd_state == CD_PAUSED)
ret = 0x12;
else
ret = 0x13;
b[pos++] = (toc[track].cdte_adr << 4) | toc[track].cdte_ctrl;
b[pos++] = track;
b[pos++] = 0;
if (msf)
{
uint32_t dat = cdpos;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
dat = cdpos - track_address;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
}
else
{
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
cdpos -= track_address;
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
}
return ret;
}
static void ioctl_eject(void)
{
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return;
ioctl(fd, CDROMEJECT);
close(fd);
}
static void ioctl_load(void)
{
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return;
ioctl(fd, CDROMEJECT);
close(fd);
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
}
union
{
struct cdrom_msf *msf;
char b[CD_FRAMESIZE_RAW];
} raw_read_params;
static int lba_to_msf(int lba)
{
return (((lba / 75) / 60) << 16) + (((lba / 75) % 60) << 8) + (lba % 75);
}
static int ioctl_sector_data_type(int sector, int ismsf)
{
return 2; /* Always Mode 1 */
}
static void ioctl_readsector_raw(uint8_t *b, int sector)
{
int err;
int imsf = lba_to_msf(sector);
int cdrom = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (cdrom <= 0)
return;
raw_read_params.msf = malloc(sizeof(struct cdrom_msf));
raw_read_params.msf->cdmsf_frame0 = imsf & 0xff;
raw_read_params.msf->cdmsf_sec0 = (imsf >> 8) & 0xff;
raw_read_params.msf->cdmsf_min0 = (imsf >> 16) & 0xff;
/* This will read the actual raw sectors from the disc. */
err = ioctl(cdrom, CDROMREADRAW, (void *) &raw_read_params);
if (err == -1)
{
pclog("read_toc: CDROMREADTOCHDR failed\n");
return;
}
memcpy(b, raw_read_params.b, 2352);
close(cdrom);
free(raw_read_params.msf);
}
static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
{
int len=4;
long size;
int c,d;
uint32_t temp;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
ioctl_cd_state = CD_STOPPED;
tocvalid = read_toc(fd, toc);
close(fd);
if (!tocvalid)
return 4;
// pclog("Read TOC done! %i\n",single);
b[2] = first_track;
b[3] = last_track;
d = 0;
//pclog("Read TOC starttrack=%i\n", starttrack);
for (c = 1; c <= last_track; c++)
{
if (toc[c].cdte_track >= starttrack)
{
d = c;
break;
}
}
b[2] = toc[c].cdte_track;
last_block = 0;
for (c = d; c <= last_track; c++)
{
uint32_t address;
if ((len + 8) > maxlen)
break;
// pclog("Len %i max %i Track %02X - %02X %02X %02i:%02i:%02i %08X\n",len,maxlen,toc[c].cdte_track,toc[c].cdte_adr,toc[c].cdte_ctrl,toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame,MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame));
b[len++] = 0; /*Reserved*/
b[len++] = (toc[c].cdte_adr << 4) | toc[c].cdte_ctrl;
b[len++] = toc[c].cdte_track;
b[len++] = 0; /*Reserved*/
address = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
if (address > last_block)
last_block = address;
if (msf)
{
b[len++] = 0;
b[len++] = toc[c].cdte_addr.msf.minute;
b[len++] = toc[c].cdte_addr.msf.second;
b[len++] = toc[c].cdte_addr.msf.frame;
}
else
{
temp = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
b[len++] = temp >> 24;
b[len++] = temp >> 16;
b[len++] = temp >> 8;
b[len++] = temp;
}
if (single)
break;
}
b[0] = (uint8_t)(((len-2) >> 8) & 0xff);
b[1] = (uint8_t)((len-2) & 0xff);
/* pclog("Table of Contents (%i bytes) : \n", size);
pclog("First track - %02X\n", first_track);
pclog("Last track - %02X\n", last_track);
for (c = 0; c <= last_track; c++)
pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, 0, toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
for (c = 0;c <= last_track; c++)
pclog("Track %02X - number %02X control %02X adr %02X address %06X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame));*/
return len;
}
static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
{
struct cdrom_multisession session;
int len = 4;
int err;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
session.addr_format = CDROM_MSF;
err = ioctl(fd, CDROMMULTISESSION, &session);
if (err == -1)
{
close(fd);
return 0;
}
b[2] = 0;
b[3] = 0;
b[len++] = 0; /*Reserved*/
b[len++] = (toc[0].cdte_adr << 4) | toc[0].cdte_ctrl;
b[len++] = toc[0].cdte_track;
b[len++] = 0; /*Reserved*/
if (msf)
{
b[len++] = 0;
b[len++] = session.addr.msf.minute;
b[len++] = session.addr.msf.second;
b[len++] = session.addr.msf.frame;
}
else
{
uint32_t temp = MSFtoLBA(session.addr.msf.minute, session.addr.msf.second, session.addr.msf.frame);
b[len++] = temp >> 24;
b[len++] = temp >> 16;
b[len++] = temp >> 8;
b[len++] = temp;
}
return len;
}
static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
{
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc2[100];
int track, err;
int len = 4;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
//pclog("read_toc\n");
if (fd <= 0)
return 0;
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
pclog("read_toc: CDROMREADTOCHDR failed\n");
return 0;
}
b[2] = toc_hdr.cdth_trk0;
b[3] = toc_hdr.cdth_trk1;
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
memset(toc, 0, sizeof(toc));
for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++)
{
if ((len + 11) > maxlen)
{
pclog("ioctl_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n");
close(fd);
return len;
}
toc2[track].cdte_track = track;
toc2[track].cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc2[track]);
if (err == -1)
{
// pclog("read_toc: CDROMREADTOCENTRY failed on track %i\n", track);
close(fd);
return 0;
}
// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame);
b[len++] = toc2[track].cdte_track;
b[len++]= (toc2[track].cdte_adr << 4) | toc[track].cdte_ctrl;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++] = toc2[track].cdte_addr.msf.minute;
b[len++] = toc2[track].cdte_addr.msf.second;
b[len++] = toc2[track].cdte_addr.msf.frame;
}
close(fd);
return len;
}
static uint32_t ioctl_size()
{
return cdrom_capacity;
}
static int ioctl_status()
{
if (!(ioctl_ready) && (cdrom_drive <= 0)) return CD_STATUS_EMPTY;
switch(ioctl_cd_state)
{
case CD_PLAYING:
return CD_STATUS_PLAYING;
case CD_PAUSED:
return CD_STATUS_PAUSED;
case CD_STOPPED:
return CD_STATUS_STOPPED;
}
}
void ioctl_reset()
{
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
//pclog("ioctl_reset: fd=%i\n", fd);
tocvalid = 0;
if (fd <= 0)
return;
tocvalid = read_toc(fd, toc);
close(fd);
}
int ioctl_open(char d)
{
atapi=&ioctl_atapi;
return 0;
}
void ioctl_close(void)
{
}
static void ioctl_exit(void)
{
ioctl_stop();
ioctl_inited = 0;
tocvalid=0;
}
static ATAPI ioctl_atapi=
{
ioctl_ready,
ioctl_medium_changed,
ioctl_readtoc,
ioctl_readtoc_session,
ioctl_readtoc_raw,
ioctl_getcurrentsubchannel,
NULL,
NULL,
NULL,
ioctl_sector_data_type,
ioctl_readsector_raw,
ioctl_playaudio,
ioctl_seek,
ioctl_load,
ioctl_eject,
ioctl_pause,
ioctl_resume,
ioctl_size,
ioctl_status,
ioctl_is_track_audio,
ioctl_stop,
ioctl_exit
};

View File

@@ -1,108 +0,0 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include "plat_thread.h"
typedef struct {
pthread_cond_t cond;
pthread_mutex_t mutex;
} event_pthread_t;
thread_t *thread_create(void (*thread_rout)(void *param), void *param)
{
pthread_t *thread = malloc(sizeof(pthread_t));
if (thread != NULL)
pthread_create(thread, NULL, thread_rout, param);
return(thread);
}
void thread_kill(thread_t *handle)
{
pthread_t *thread = (pthread_t *)handle;
if (thread != NULL) {
pthread_cancel(*thread);
pthread_join(*thread, NULL);
free(thread);
}
}
event_t *thread_create_event(void)
{
event_pthread_t *event = malloc(sizeof(event_pthread_t));
if (event != NULL) {
pthread_cond_init(&event->cond, NULL);
pthread_mutex_init(&event->mutex, NULL);
}
return((event_t *)event);
}
void thread_set_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
if (event != NULL) {
pthread_mutex_lock(&event->mutex);
pthread_cond_broadcast(&event->cond);
pthread_mutex_unlock(&event->mutex);
}
}
void thread_reset_event(event_t *handle)
{
}
int thread_wait_event(event_t *handle, int timeout)
{
event_pthread_t *event = (event_pthread_t *)handle;
struct timespec abstime;
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_nsec += (timeout % 1000) * 1000000;
abstime.tv_sec += (timeout / 1000);
if (abstime.tv_nsec > 1000000000) {
abstime.tv_nsec -= 1000000000;
abstime.tv_sec++;
}
pthread_mutex_lock(&event->mutex);
pthread_cond_timedwait(&event->cond, &event->mutex, &abstime);
pthread_mutex_unlock(&event->mutex);
return(0);
}
void thread_destroy_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
if (event != NULL) {
pthread_cond_destroy(&event->cond);
pthread_mutex_destroy(&event->mutex);
free(event);
}
}
void thread_sleep(int t)
{
usleep(t * 1000);
}

Some files were not shown because too many files have changed in this diff Show More