1 /*  bootrom.c: Boot ROM simulator for Motorola processors
2 
3     Copyright (c) 2010-2011, William A. Beech
4 
5     Permission is hereby granted, free of charge, to any person obtaining a
6     copy of this software and associated documentation files (the "Software"),
7     to deal in the Software without restriction, including without limitation
8     the rights to use, copy, modify, merge, publish, distribute, sublicense,
9     and/or sell copies of the Software, and to permit persons to whom the
10     Software is furnished to do so, subject to the following conditions:
11 
12     The above copyright notice and this permission notice shall be included in
13     all copies or substantial portions of the Software.
14 
15     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18     WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19     IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22     Except as contained in this notice, the name of William A. Beech shall not be
23     used in advertising or otherwise to promote the sale, use or other dealings
24     in this Software without prior written authorization from William A. Beech.
25 
26     These functions support a single simulated 2704 to 2764 EPROM device on
27     an 8-bit computer system..  This device allows the the device buffer to
28     be loaded from a binary file containing the emulated EPROM code.
29 
30     These functions support a simulated 2704, 2708, 2716, 2732 or 2764 EPROM
31     device on a CPU board.  The byte get and put routines use an offset into
32     the boot EPROM image to locate the proper byte.  This allows another device
33     to set the base address for the boot EPROM.  The device type is stored as
34     a binary number in the first three unit flag bits.
35 
36     This device uses a dynamically allocated buffer to hold the EPROM image.
37     A call to BOOTROM_config will free the current buffer.  A call to
38     BOOTROM_reset will allocate a new buffer of BOOTROM_unit.capac bytes.  A
39     call to BOOTROM_attach will load the buffer with the EPROM image.
40 */
41 
42 #include <stdio.h>
43 #include "swtp_defs.h"
44 
45 #define UNIT_V_MSIZE    (UNIT_V_UF)     /* ROM Size */
46 #define UNIT_MSIZE      (0x7 << UNIT_V_MSIZE)
47 #define UNIT_NONE       (0 << UNIT_V_MSIZE) /* No EPROM */
48 #define UNIT_2704       (1 << UNIT_V_MSIZE) /* 2704 mode */
49 #define UNIT_2708       (2 << UNIT_V_MSIZE) /* 2708 mode */
50 #define UNIT_2716       (3 << UNIT_V_MSIZE) /* 2716 mode */
51 #define UNIT_2732       (4 << UNIT_V_MSIZE) /* 2732 mode */
52 #define UNIT_2764       (5 << UNIT_V_MSIZE) /* 2764 mode */
53 
54 /* function prototypes */
55 
56 t_stat BOOTROM_svc (UNIT *uptr);
57 t_stat BOOTROM_config (UNIT *uptr, int32 val, char *cptr, void *desc);
58 t_stat BOOTROM_attach (UNIT *uptr, char *cptr);
59 t_stat BOOTROM_reset (DEVICE *dptr);
60 int32 BOOTROM_get_mbyte(int32 offset);
61 
62 /* SIMH Standard I/O Data Structures */
63 
64 UNIT BOOTROM_unit = { UDATA (NULL,
65                            UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),
66                     KBD_POLL_WAIT };
67 
68 MTAB BOOTROM_mod[] = {
69     { UNIT_MSIZE, UNIT_NONE, "None", "NONE", &BOOTROM_config },
70     { UNIT_MSIZE, UNIT_2704, "2704", "2704", &BOOTROM_config },
71     { UNIT_MSIZE, UNIT_2708, "2708", "2708", &BOOTROM_config },
72     { UNIT_MSIZE, UNIT_2716, "2716", "2716", &BOOTROM_config },
73     { UNIT_MSIZE, UNIT_2732, "2732", "2732", &BOOTROM_config },
74     { UNIT_MSIZE, UNIT_2764, "2764", "2764", &BOOTROM_config },
75     { 0 }
76 };
77 
78 DEBTAB BOOTROM_debug[] = {
79     { "ALL", DEBUG_all },
80     { "FLOW", DEBUG_flow },
81     { "READ", DEBUG_read },
82     { "WRITE", DEBUG_write },
83     { "LEV1", DEBUG_level1 },
84     { "LEV2", DEBUG_level2 },
85     { NULL }
86 };
87 
88 DEVICE BOOTROM_dev = {
89     "BOOTROM",                      /* name */
90     &BOOTROM_unit,                  /* units */
91     NULL,                           /* registers */
92     BOOTROM_mod,                    /* modifiers */
93     1,                              /* numunits */
94     16,                             /* aradix */
95     32,                             /* awidth */
96     1,                              /* aincr */
97     16,                             /* dradix */
98     8,                              /* dwidth */
99     NULL,                           /* examine */
100     NULL,                           /* deposit */
101     &BOOTROM_reset,                 /* reset */
102     NULL,                           /* boot */
103     &BOOTROM_attach,                /* attach */
104     NULL,                           /* detach */
105     NULL,                           /* ctxt */
106     DEV_DEBUG,                      /* flags */
107     0,                              /* dctrl */
108     BOOTROM_debug,                  /* debflags */
109     NULL,                           /* msize */
110     NULL                            /* lname */
111 };
112 
113 /* global variables */
114 
115 /* BOOTROM_attach - attach file to EPROM unit */
116 
BOOTROM_attach(UNIT * uptr,char * cptr)117 t_stat BOOTROM_attach (UNIT *uptr, char *cptr)
118 {
119     t_stat r;
120 
121     if (BOOTROM_dev.dctrl & DEBUG_flow)
122         printf("BOOTROM_attach: cptr=%s\n", cptr);
123     if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
124         if (BOOTROM_dev.dctrl & DEBUG_flow)
125             printf("BOOTROM_attach: Error\n");
126         return r;
127     }
128     if (BOOTROM_dev.dctrl & DEBUG_flow)
129         printf("BOOTROM_attach: Done\n");
130     return (BOOTROM_reset (NULL));
131 }
132 
133 /* BOOTROM_config = None, 2704, 2708, 2716, 2732 or 2764 */
134 
BOOTROM_config(UNIT * uptr,int32 val,char * cptr,void * desc)135 t_stat BOOTROM_config (UNIT *uptr, int32 val, char *cptr, void *desc)
136 {
137     if (BOOTROM_dev.dctrl & DEBUG_flow) /* entry message */
138         printf("BOOTROM_config: val=%d\n", val);
139     if ((val < UNIT_NONE) || (val > UNIT_2764)) { /* valid param? */
140         if (BOOTROM_dev.dctrl & DEBUG_flow) /* No */
141             printf("BOOTROM_config: Parameter error\n");
142         return SCPE_ARG;
143     }
144     if (val == UNIT_NONE)
145         BOOTROM_unit.capac = 0;         /* set EPROM size */
146     else
147         BOOTROM_unit.capac = 0x200 << ((val >> UNIT_V_MSIZE) - 1); /* set EPROM size */
148     if (BOOTROM_unit.filebuf) {         /* free buffer */
149         free (BOOTROM_unit.filebuf);
150         BOOTROM_unit.filebuf = NULL;
151     }
152     if (BOOTROM_dev.dctrl & DEBUG_flow) /* status message */
153         printf("BOOTROM_config: BOOTROM_unit.capac=%d\n",
154             BOOTROM_unit.capac);
155     if (BOOTROM_dev.dctrl & DEBUG_flow) /* exit message */
156         printf("BOOTROM_config: Done\n");
157     return SCPE_OK;
158 }
159 
160 /* EPROM reset */
161 
BOOTROM_reset(DEVICE * dptr)162 t_stat BOOTROM_reset (DEVICE *dptr)
163 {
164     int j, c;
165     FILE *fp;
166     t_stat r;
167 
168     if (BOOTROM_dev.dctrl & DEBUG_flow)
169         printf("BOOTROM_reset: \n");
170     if ((BOOTROM_unit.flags & UNIT_MSIZE) == 0) { /* if none selected */
171 //        printf("   EPROM: Defaulted to None\n");
172 //        printf("      \"set eprom NONE | 2704 | 2708 | 2716 | 2732 | 2764\"\n");
173 //        printf("      \"att eprom <filename>\"\n");
174         BOOTROM_unit.capac = 0;         /* set EPROM size to 0 */
175         if (BOOTROM_dev.dctrl & DEBUG_flow)
176             printf("BOOTROM_reset: Done1\n");
177         return SCPE_OK;
178         }                               /* if attached */
179 //    printf("   EPROM: Initializing [%04X-%04XH]\n",
180 //        0xE000, 0xE000 + BOOTROM_unit.capac - 1);
181     if (BOOTROM_unit.filebuf == NULL) { /* no buffer allocated */
182         BOOTROM_unit.filebuf = malloc(BOOTROM_unit.capac); /* allocate EPROM buffer */
183         if (BOOTROM_unit.filebuf == NULL) {
184             if (BOOTROM_dev.dctrl & DEBUG_flow)
185                 printf("BOOTROM_reset: Malloc error\n");
186             return SCPE_MEM;
187         }
188     }
189     fp = fopen(BOOTROM_unit.filename, "rb"); /* open EPROM file */
190     if (fp == NULL) {
191         printf("\tUnable to open ROM file %s\n",BOOTROM_unit.filename);
192         printf("\tNo ROM image loaded!!!\n");
193         return SCPE_OK;
194     }
195     j = 0;                              /* load EPROM file */
196     c = fgetc(fp);
197     while (c != EOF) {
198         *(uint8 *)(BOOTROM_unit.filebuf + j++) = c & 0xFF;
199         c = fgetc(fp);
200         if (j > BOOTROM_unit.capac) {
201             printf("\tImage is too large - Load truncated!!!\n");
202             break;
203         }
204     }
205     fclose(fp);
206 //    printf("\t%d bytes of ROM image %s loaded\n", j, BOOTROM_unit.filename);
207     if (BOOTROM_dev.dctrl & DEBUG_flow)
208         printf("BOOTROM_reset: Done2\n");
209     return SCPE_OK;
210 }
211 
212 /*  get a byte from memory - byte offset of image */
213 
BOOTROM_get_mbyte(int32 offset)214 int32 BOOTROM_get_mbyte(int32 offset)
215 {
216     int32 val;
217 
218     if (BOOTROM_unit.filebuf == NULL) {
219         if (BOOTROM_dev.dctrl & DEBUG_read)
220             printf("BOOTROM_get_mbyte: EPROM not configured\n");
221         return 0xFF;
222     }
223     if (BOOTROM_dev.dctrl & DEBUG_read)
224         printf("BOOTROM_get_mbyte: offset=%04X\n", offset);
225     val = *(uint8 *)(BOOTROM_unit.filebuf + offset) & 0xFF;
226     if (BOOTROM_dev.dctrl & DEBUG_read)
227         printf("BOOTROM_get_mbyte: Normal val=%02X\n", val);
228     return val;
229 }
230 
231 /* end of bootrom.c */
232