diff options
author | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2019-04-09 02:40:05 +0100 |
---|---|---|
committer | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2019-04-09 02:40:05 +0100 |
commit | b72dc79eec3d369a38202522165f5ef4cfa5b98b (patch) | |
tree | 82e9754139370a77b76549aa32a40855bce987cb | |
parent | 9ae59a93a74424e26045b749141cb238ec049a96 (diff) | |
download | mdk-b72dc79eec3d369a38202522165f5ef4cfa5b98b.tar.gz mdk-b72dc79eec3d369a38202522165f5ef4cfa5b98b.tar.bz2 |
Support IOC commands for disk/drum devices
Thanks to Kevin Brunelle
There is a minor fix included with regards to tape devices. The test
was failing if M == 0, when it should fail when M != 0.
NOTICE: This patch changes the behavior of the VM and changes the
function parameters for the ioc_ function. Documentation changes are
included.
Permits the following:
LDX BLKNUM
IOC 0(8)
OUT ADDR(8) Write block from ADDR into disk[BLKNUM]
IOC 0(8)
IN ADDR(8) Read block from disk[BLKNUM] into ADDR
...
BLKNUM CON 45000 Example possible block on disk
I was having an issue writing a block to a drive and then reading back
the same block. Because it is impossible to move the SEEK_CUR pointer
backwards on a disk device, there was no way for a program to read
back a block that it wrote to a disk without restarting or fiddling
with ~/.mdk/disk?.dev files and symbolic links.
I have added a function parameter to the ioc_ function and used it to
pass the value of rX to ioc_. This permits us to use IOC commands to
move the read/write head on a disk/drum device. I believe that this
conforms to the potential meaning of Knuth's description of IOC for
disk/drum devices.
I have put in tests to verify that rX is positive and M = 0.
I have updated the documentation to reflect this new behavior.
This makes disks much more usable.
Note: I won't be offended if this patch is rejected because it changed
the behavior of the VM. I think it fits the spirit and enhances the
functionality in a way that some might find useful. I wanted it for
something I was working on, and I felt others might want the same. The
thing with the paper-tape should be fixed, though.
-rw-r--r-- | doc/mdk_tut.texi | 19 | ||||
-rw-r--r-- | mixgtk/mixgtk_device.c | 4 | ||||
-rw-r--r-- | mixlib/mix_device.c | 4 | ||||
-rw-r--r-- | mixlib/mix_device.h | 2 | ||||
-rw-r--r-- | mixlib/xmix_device.c | 15 | ||||
-rw-r--r-- | mixlib/xmix_device.h | 2 | ||||
-rw-r--r-- | mixlib/xmix_vm.c | 4 |
7 files changed, 31 insertions, 19 deletions
diff --git a/doc/mdk_tut.texi b/doc/mdk_tut.texi index e2d3a15..9ff6f86 100644 --- a/doc/mdk_tut.texi +++ b/doc/mdk_tut.texi @@ -684,14 +684,17 @@ OPCODE = 34, MOD = I/O unit. @noindent In all the above instructions, the @samp{MOD} subfile must be in the range 0-20, since it denotes the operation's target device. The -@samp{IOC} instruction only makes sense for tape devices (@samp{MOD} = -0-7 or 20): it shifts the read/write pointer by the number of words -given by @samp{M} (if it equals zero, the tape is rewound)@footnote{In -Knuth's original definition, there are other control operations -available, but they do not make sense when implementing the block -devices as disk files (as we do in @sc{mdk} simulator). For the same -reason, @sc{mdk} devices are always ready, since all input-output -operations are performed using synchronous system calls.}. +@samp{IOC} instruction makes sense for magnetic tape devices (@samp{MOD} = +0-7): it shifts the read/write pointer by the number of blocks +given by @samp{M} (if it equals zero, the tape is rewound), paper tape +devices (@samp{MOD} = 20): @samp{M} should be 0, the tape is rewound, +and disk/drum devices (@samp{MOD} = 8-15): it moves the read/write +pointer to the block specified in rX and @samp{M} should be 0@footnote{In +Knuth's original definition, there are other control operations available, +but they do not make sense when implementing the devices as disk files (as +we do in @sc{mdk} simulator). For the same reason, @sc{mdk} devices are +always ready, since all input-output operations are performed using +synchronous system calls.}. @node Conversion operators, Shift operators, Input-output operators, MIX instruction set diff --git a/mixgtk/mixgtk_device.c b/mixgtk/mixgtk_device.c index d3ce934..0cae037 100644 --- a/mixgtk/mixgtk_device.c +++ b/mixgtk/mixgtk_device.c @@ -272,9 +272,9 @@ read_ (mix_device_t *dev, mix_word_t *block) } static gboolean -ioc_ (mix_device_t *dev, mix_short_t cmd) +ioc_ (mix_device_t *dev, mix_short_t cmd, mix_word_t val) { - return (DEF_DEV_VTABLE_->ioc)(dev, cmd); + return (DEF_DEV_VTABLE_->ioc)(dev, cmd, val); } static gboolean diff --git a/mixlib/mix_device.c b/mixlib/mix_device.c index 5d3927c..e63119b 100644 --- a/mixlib/mix_device.c +++ b/mixlib/mix_device.c @@ -148,11 +148,11 @@ mix_device_read (mix_device_t *dev, mix_word_t *block) } gboolean -mix_device_ioc (mix_device_t *dev, mix_short_t arg) +mix_device_ioc (mix_device_t *dev, mix_short_t arg, mix_word_t val) { g_return_val_if_fail (dev != NULL, FALSE); g_assert (dev->vtable != NULL); - return (dev->vtable->ioc) (dev, arg); + return (dev->vtable->ioc) (dev, arg, val); } gboolean diff --git a/mixlib/mix_device.h b/mixlib/mix_device.h index 1273f18..c0e03ab 100644 --- a/mixlib/mix_device.h +++ b/mixlib/mix_device.h @@ -148,7 +148,7 @@ mix_device_read (mix_device_t *dev, mix_word_t *block); >0 - skip forward the given number of blocks */ extern gboolean -mix_device_ioc (mix_device_t *dev, mix_short_t arg); +mix_device_ioc (mix_device_t *dev, mix_short_t arg, mix_word_t val); /* Check if a device is busy diff --git a/mixlib/xmix_device.c b/mixlib/xmix_device.c index 8d4084c..6fb085f 100644 --- a/mixlib/xmix_device.c +++ b/mixlib/xmix_device.c @@ -143,14 +143,20 @@ read_ (mix_device_t *dev, mix_word_t *block) } static gboolean -ioc_ (mix_device_t *dev, mix_short_t arg) +ioc_ (mix_device_t *dev, mix_short_t arg, mix_word_t val) { int m; FILE *file; + long diskblock; m = mix_short_magnitude(arg); if (mix_short_is_negative(arg)) m = -m; m *= sizeof (mix_word_t) * SIZES_[dev->type]; + + diskblock = mix_word_magnitude(val); + if (mix_word_is_negative(val)) diskblock = -diskblock; + diskblock *= sizeof (mix_word_t) * SIZES_[dev->type]; + file = mix_io_to_FILE (GET_CHANNEL_(dev)); if (dev->type >= mix_dev_TAPE_0 && dev->type <= mix_dev_TAPE_7) @@ -160,12 +166,13 @@ ioc_ (mix_device_t *dev, mix_short_t arg) } if (dev->type >= mix_dev_DISK_0 && dev->type <= mix_dev_DISK_7) { - if (m == 0) return FALSE; - // position disk + // move read/write head to block + if (m != 0 || diskblock < 0) return FALSE; + else fseek (file, diskblock, SEEK_SET); } if (dev->type == mix_dev_PAPER_TAPE) { - if (m == 0) return FALSE; + if (m != 0) return FALSE; rewind (file); } return TRUE; diff --git a/mixlib/xmix_device.h b/mixlib/xmix_device.h index 13950c9..4de321d 100644 --- a/mixlib/xmix_device.h +++ b/mixlib/xmix_device.h @@ -32,7 +32,7 @@ extern gchar *DEV_DIR_; /* table of overridable device operations */ typedef gboolean (*mix_dev_write_func_t) (mix_device_t *, const mix_word_t *); typedef gboolean (*mix_dev_read_func_t) (mix_device_t *, mix_word_t *); -typedef gboolean (*mix_dev_ioc_func_t) (mix_device_t *, mix_short_t); +typedef gboolean (*mix_dev_ioc_func_t) (mix_device_t *, mix_short_t, mix_word_t); typedef gboolean (*mix_dev_busy_func_t) (const mix_device_t *); typedef void (*mix_dev_destroy_t) (mix_device_t *); diff --git a/mixlib/xmix_vm.c b/mixlib/xmix_vm.c index 68a8106..1b8d80a 100644 --- a/mixlib/xmix_vm.c +++ b/mixlib/xmix_vm.c @@ -303,6 +303,7 @@ ioc_handler_ (mix_vm_t *vm, const mix_ins_t *ins) { mix_address_t addr; mix_device_t *dev; + mix_word_t val; g_assert (ins->opcode == mix_opIOC); @@ -312,7 +313,8 @@ ioc_handler_ (mix_vm_t *vm, const mix_ins_t *ins) dev = get_dev_ (vm, ins->fspec); fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO); - fail_if_not_ (vm, mix_device_ioc (dev, addr), MIX_VM_ERROR_DEV_CTL); + val = get_rX_ (vm); + fail_if_not_ (vm, mix_device_ioc (dev, addr, val), MIX_VM_ERROR_DEV_CTL); inc_loc_ (vm); return TRUE; |