From 122a87e5448a3fff04caf391680705ac16ea88d2 Mon Sep 17 00:00:00 2001 From: Lars Brinkhoff Date: Tue, 4 Sep 2018 11:53:08 +0200 Subject: [PATCH] PDP11: ROM device. --- PDP11/pdp11_rom.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++ PDP11/pdp11_sys.c | 2 + makefile | 3 +- 3 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 PDP11/pdp11_rom.c diff --git a/PDP11/pdp11_rom.c b/PDP11/pdp11_rom.c new file mode 100644 index 00000000..d1f72bfc --- /dev/null +++ b/PDP11/pdp11_rom.c @@ -0,0 +1,221 @@ +/* pdp11_rom.c: Read-Only Memory. + + Copyright (c) 2018, Lars Brinkhoff + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + LARS BRINKHOFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "pdp11_defs.h" + +t_stat rom_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); +t_stat rom_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); +t_stat rom_rd (int32 *data, int32 PA, int32 access); +t_stat rom_reset (DEVICE *dptr); +t_stat rom_boot (int32 u, DEVICE *dptr); +t_stat rom_set_addr (UNIT *, int32, CONST char *, void *); +t_stat rom_show_addr (FILE *, UNIT *, int32, CONST void *); +t_stat rom_attach (UNIT *uptr, CONST char *cptr); +t_stat rom_detach (UNIT *uptr); +t_stat rom_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +t_stat rom_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *rom_description (DEVICE *dptr); + +/* ROM data structures + + rom_dev ROM device descriptor + rom_unit ROM unit list +*/ + +#define unit_base u3 +#define unit_end u4 + +#define ROM_UNITS 4 +#define ROM_UNIT_FLAGS UNIT_RO|UNIT_MUSTBUF|UNIT_BUFABLE|UNIT_ATTABLE + +DIB rom_dib[ROM_UNITS]; + +MTAB rom_mod[] = { + { MTAB_XTD|MTAB_VUN|MTAB_VALR, 010, "ADDRESS", "ADDRESS", + &rom_set_addr, &rom_show_addr, NULL, "Bus address" }, + { 0 } + }; + +UNIT rom_unit[ROM_UNITS]; + +DEVICE rom_dev = { + "ROM", rom_unit, NULL, rom_mod, + ROM_UNITS, 8, 9, 2, 8, 16, + rom_ex, rom_dep, rom_reset, + &rom_boot, &rom_attach, &rom_detach, + &rom_dib[0], DEV_DISABLE | DEV_UBUS | DEV_QBUS, + 0, NULL, NULL, NULL, + &rom_help, &rom_help_attach, /* help and attach_help routines */ + NULL, &rom_description /* description routine */ + }; + +t_stat rom_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ +int32 data; +t_stat r; + +r = rom_rd (&data, addr, 0); +if (r != SCPE_OK) + return r; +*vptr = (t_value)data; +return SCPE_OK; +} + +t_stat rom_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ +uint16 *image = (uint16 *)uptr->filebuf; + +image[(addr - uptr->unit_base) >> 1] = val; +return SCPE_OK; +} + +t_stat rom_rd (int32 *data, int32 PA, int32 access) +{ +int i; +for (i = 0; i < ROM_UNITS; i++) { + if (PA >= rom_unit[i].unit_base && PA < rom_unit[i].unit_end) { + uint16 *image = (uint16 *)rom_unit[i].filebuf; + *data = image[(PA - rom_unit[i].unit_base) >> 1]; + return SCPE_OK; + } +} +return SCPE_NXM; +} + +t_stat rom_reset (DEVICE *dptr) +{ +int i; +dptr->ctxt = &rom_dib[0]; +for (i = 0; i < ROM_UNITS; i++) { + rom_unit[i].flags |= ROM_UNIT_FLAGS; + rom_dib[i].next = &rom_dib[i + 1]; + } +rom_dib[ROM_UNITS - 1].next = NULL; +return SCPE_OK; +} + +t_stat rom_boot (int32 u, DEVICE *dptr) +{ +cpu_set_boot (rom_unit[u].unit_base); +return SCPE_OK; +} + +t_stat rom_set_addr (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ +int32 addr; +t_stat r; + +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; +if (cptr == NULL) + return SCPE_ARG; +addr = (int32) get_uint (cptr, 8, IOPAGEBASE+IOPAGEMASK, &r); +if (r != SCPE_OK) + return r; +if (addr < IOPAGEBASE) + return sim_messagef (SCPE_ARG, "ROM must be in I/O page, at or above 0%o\n", + IOPAGEBASE); +uptr->unit_base = uptr->unit_end = addr; +return SCPE_OK; +} + +t_stat rom_show_addr (FILE *f, UNIT *uptr, int32 val, CONST void *desc) +{ +if (uptr == NULL) + return SCPE_IERR; +if (uptr->unit_base != uptr->unit_end) + fprintf (f, "address=%o-%o", uptr->unit_base, uptr->unit_end - 1); +else + fprintf (f, "address=%o", uptr->unit_base); +return SCPE_OK; +} + +t_stat rom_make_dib (UNIT *uptr) +{ +DIB *dib = &rom_dib[uptr - rom_unit]; + +dib->ba = uptr->unit_base; +dib->lnt = uptr->capac; +dib->rd = &rom_rd; +return build_ubus_tab (&rom_dev, dib); +} + +t_stat rom_attach (UNIT *uptr, CONST char *cptr) +{ +t_stat r; + +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; +if (uptr->unit_base == 0) + return sim_messagef (SCPE_ARG, "Set address first.\n"); +sim_switches |= SWMASK ('Q'); +uptr->capac = sim_fsize_name (cptr); +if (uptr->capac == 0) + return SCPE_OPENERR; +r = attach_unit (uptr, cptr); +if (r != SCPE_OK) + return r; +r = rom_make_dib (uptr); +if (r != SCPE_OK) + return rom_detach (uptr); +uptr->unit_end = uptr->unit_base + uptr->capac; +return SCPE_OK; +} + +/* Detach */ + +t_stat rom_detach (UNIT *uptr) +{ +t_stat r; +DIB *dib = &rom_dib[uptr - rom_unit]; + +dib->rd = NULL; +r = build_ubus_tab (&rom_dev, dib); +if (r != SCPE_OK) + return r; +uptr->unit_end = uptr->unit_base; +dib->lnt = uptr->capac = 0; +return detach_unit (uptr); +} + +t_stat rom_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "ROM, Read-Only Memory\n\n"); +fprintf (st, "The ROM device can be used to add ROM modules to the I/O page.\n"); +fprintf (st, "First the ROM unit ADDRESS has to be set, and then the ATTACH command\n"); +fprintf (st, "can be used to fill the ROM with contents. The BOOT command is supported\n"); +fprintf (st, "for starting from the ROM.\n"); +return SCPE_OK; +} + +t_stat rom_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "The ATTACH command is used to specify the contents of a ROM unit.\n"); +fprintf (st, "Any file can be used. The file contents must be a flat binary image.\n"); +fprintf (st, "The unit ADDRESS must be set first.\n"); +return SCPE_OK; +} + +const char *rom_description (DEVICE *dptr) +{ +return "Read-Only Memory"; +} diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index 66c31b05..5bb036a9 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -116,6 +116,7 @@ extern DEVICE dup_dev; extern DEVICE dpv_dev; extern DEVICE kmc_dev; extern DEVICE uca_dev, ucb_dev; +extern DEVICE rom_dev; extern REG cpu_reg[]; extern int32 saved_PC; @@ -193,6 +194,7 @@ DEVICE *sim_devices[] = { &dpv_dev, &kmc_dev, &ke_dev, + &rom_dev, #else &clk_dev, &tti_dev, diff --git a/makefile b/makefile index a79f2b04..2104f1a1 100644 --- a/makefile +++ b/makefile @@ -1198,7 +1198,8 @@ PDP11 = ${PDP11D}/pdp11_fp.c ${PDP11D}/pdp11_cpu.c ${PDP11D}/pdp11_dz.c \ ${PDP11D}/pdp11_ta.c ${PDP11D}/pdp11_rc.c ${PDP11D}/pdp11_kg.c \ ${PDP11D}/pdp11_ke.c ${PDP11D}/pdp11_dc.c ${PDP11D}/pdp11_dmc.c \ ${PDP11D}/pdp11_kmc.c ${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_rs.c \ - ${PDP11D}/pdp11_vt.c ${PDP11D}/pdp11_td.c ${PDP11D}/pdp11_io_lib.c $(DISPLAYL) $(DISPLAYVT) + ${PDP11D}/pdp11_vt.c ${PDP11D}/pdp11_td.c ${PDP11D}/pdp11_io_lib.c \ + ${PDP11D}/pdp11_rom.c $(DISPLAYL) $(DISPLAYVT) PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} $(DISPLAY_OPT)