| /* i2716.c: Intel 2716 EPROM simulator for 8-bit processors | |
| Copyright (c) 2011, William A. Beech | |
| 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 | |
| WILLIAM A. BEECH 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. | |
| Except as contained in this notice, the name of William A. Beech shall not be | |
| used in advertising or otherwise to promote the sale, use or other dealings | |
| in this Software without prior written authorization from William A. Beech. | |
| These functions support a simulated 2704 to 2764 EPROMs device on an 8-bit | |
| computer system. This device allows the attachment of the device to a binary file | |
| containing the EPROM code. | |
| These functions support emulation of 0 to 4 2716 EPROM devices on a CPU board. | |
| The byte get and put routines use an offset into the boot EPROM image to locate | |
| the proper byte. This allows another device to set the base address for each | |
| EPROM. | |
| This device uses a dynamically allocated buffer to hold each EPROM image. | |
| A call to BOOTROM_config will free the current buffer. A call to | |
| i2716_reset will allocate a new buffer of 2048 bytes. A | |
| call to BOOTROM_attach will load the buffer with the EPROM image. | |
| */ | |
| #include <stdio.h> | |
| #include "swtp_defs.h" | |
| #define I2716_NUM 4 /* number of 2716 EPROMS */ | |
| extern int32 get_base(void); | |
| /* function prototypes */ | |
| t_stat i2716_attach (UNIT *uptr, char *cptr); | |
| t_stat i2716_reset (DEVICE *dptr); | |
| int32 i2716_get_mbyte(int32 offset); | |
| /* SIMH EPROM Standard I/O Data Structures */ | |
| UNIT i2716_unit[] = { | |
| { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 }, | |
| { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 }, | |
| { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 }, | |
| { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 } | |
| }; | |
| MTAB i2716_mod[] = { | |
| { 0 } | |
| }; | |
| DEBTAB i2716_debug[] = { | |
| { "ALL", DEBUG_all }, | |
| { "FLOW", DEBUG_flow }, | |
| { "READ", DEBUG_read }, | |
| { "WRITE", DEBUG_write }, | |
| { "LEV1", DEBUG_level1 }, | |
| { "LEV2", DEBUG_level2 }, | |
| { NULL } | |
| }; | |
| DEVICE i2716_dev = { | |
| "I2716", /* name */ | |
| i2716_unit, /* units */ | |
| NULL, /* registers */ | |
| i2716_mod, /* modifiers */ | |
| I2716_NUM, /* numunits */ | |
| 16, /* aradix */ | |
| 32, /* awidth */ | |
| 1, /* aincr */ | |
| 16, /* dradix */ | |
| 8, /* dwidth */ | |
| NULL, /* examine */ | |
| NULL, /* deposit */ | |
| &i2716_reset, /* reset */ | |
| NULL, /* boot */ | |
| &i2716_attach, /* attach */ | |
| NULL, /* detach */ | |
| NULL, /* ctxt */ | |
| DEV_DEBUG, /* flags */ | |
| 0, /* dctrl */ | |
| i2716_debug, /* debflags */ | |
| NULL, /* msize */ | |
| NULL /* lname */ | |
| }; | |
| /* global variables */ | |
| /* i2716_attach - attach file to EPROM unit | |
| force EPROM reset at completion */ | |
| t_stat i2716_attach (UNIT *uptr, char *cptr) | |
| { | |
| int32 j, c; | |
| t_stat r; | |
| FILE *fp; | |
| if (i2716_dev.dctrl & DEBUG_flow) | |
| printf("i2716_attach: cptr=%s\n", cptr); | |
| if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { | |
| if (i2716_dev.dctrl & DEBUG_flow) | |
| printf("i2716_attach: Error\n"); | |
| return r; | |
| } | |
| if (i2716_dev.dctrl & DEBUG_read) | |
| printf("\tOpen file\n"); | |
| fp = fopen(uptr->filename, "rb"); /* open EPROM file */ | |
| if (fp == NULL) { | |
| printf("i2716%d: Unable to open ROM file %s\n", (int)(uptr - i2716_dev.units), uptr->filename); | |
| printf("\tNo ROM image loaded!!!\n"); | |
| return SCPE_OK; | |
| } | |
| if (i2716_dev.dctrl & DEBUG_read) | |
| printf("\tRead file\n"); | |
| j = 0; /* load EPROM file */ | |
| c = fgetc(fp); | |
| while (c != EOF) { | |
| *((uint8 *)(uptr->filebuf) + j++) = c & 0xFF; | |
| c = fgetc(fp); | |
| if (j > 2048) { | |
| printf("\tImage is too large - Load truncated!!!\n"); | |
| break; | |
| } | |
| } | |
| if (i2716_dev.dctrl & DEBUG_read) | |
| printf("\tClose file\n"); | |
| fclose(fp); | |
| // printf("i2716%d: %d bytes of ROM image %s loaded\n",uptr - i2716_dev.units, j, uptr->filename); | |
| if (i2716_dev.dctrl & DEBUG_flow) | |
| printf("i2716_attach: Done\n"); | |
| return SCPE_OK; | |
| } | |
| /* EPROM reset */ | |
| t_stat i2716_reset (DEVICE *dptr) | |
| { | |
| int32 i, base; | |
| UNIT *uptr; | |
| if (i2716_dev.dctrl & DEBUG_flow) | |
| printf("i2716_reset: \n"); | |
| for (i = 0; i < I2716_NUM; i++) { /* init all units */ | |
| uptr = i2716_dev.units + i; | |
| if (i2716_dev.dctrl & DEBUG_flow) | |
| printf("i2716 %d unit.flags=%08X\n", i, uptr->flags); | |
| uptr->capac = 2048; | |
| uptr->u3 = 2048 * i; | |
| base = get_base(); | |
| if (uptr->filebuf == NULL) { /* no buffer allocated */ | |
| uptr->filebuf = malloc(2048); /* allocate EPROM buffer */ | |
| if (uptr->filebuf == NULL) { | |
| if (i2716_dev.dctrl & DEBUG_flow) | |
| printf("i2716_reset: Malloc error\n"); | |
| return SCPE_MEM; | |
| } | |
| } | |
| if (base == 0) { | |
| // printf("i2716%d: Not enabled on MP-A2\n", i); | |
| continue; | |
| } | |
| // printf("i2716%d: Initializing [%04X-%04XH]\n", | |
| // i, base+uptr->u3, base+uptr->u3 + uptr->capac); | |
| // if ((uptr->flags & UNIT_ATT) == 0) { | |
| // printf("i2716%d: No file attached\n", i); | |
| // } | |
| } | |
| if (i2716_dev.dctrl & DEBUG_flow) | |
| printf("i2716_reset: Done\n"); | |
| return SCPE_OK; | |
| } | |
| /* I/O instruction handlers, called from the CPU module when an | |
| EPROM memory read or write is issued. | |
| */ | |
| /* get a byte from memory */ | |
| int32 i2716_get_mbyte(int32 offset) | |
| { | |
| int32 i, val, org, len; | |
| UNIT *uptr; | |
| for (i = 0; i < I2716_NUM; i++) { /* find addressed unit */ | |
| uptr = i2716_dev.units + i; | |
| org = uptr->u3; | |
| len = uptr->capac - 1; | |
| if ((offset >= org) && (offset < (org + len))) { | |
| if (uptr->filebuf == NULL) { | |
| if (i2716_dev.dctrl & DEBUG_read) | |
| printf("i2716_get_mbyte: EPROM not configured\n"); | |
| return 0xFF; | |
| } else { | |
| val = *((uint8 *)(uptr->filebuf) + (offset - org)); | |
| if (i2716_dev.dctrl & DEBUG_read) | |
| printf(" val=%04X\n", val); | |
| return (val & 0xFF); | |
| } | |
| } | |
| } | |
| if (i2716_dev.dctrl & DEBUG_read) | |
| printf("i2716_get_mbyte: Out of range\n"); | |
| return 0xFF; | |
| } | |
| /* end of i2716.c */ |