1 /* mp-8m.c: SWTP 8K Byte Memory Card emulator
2
3 Copyright (c) 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 6 simulated MP-8M memory cards on an SS-50 system.
27
28 Each unit uses a dynamically allocated 8192 byte buffer to hold the data.
29 Each unit contains the base address in mp_8m_unit.u3. The unit capacity is
30 held in mp_8m_unit.capac. Each unit can be enabled or disabled to reconfigure
31 the RAM for the system.
32 */
33
34 #include <stdio.h>
35 #include "swtp_defs.h"
36
37 #define MP_8M_NUM 6 /* number of MP-*m boards */
38
39 /* prototypes */
40
41 t_stat mp_8m_reset (DEVICE *dptr);
42 int32 mp_8m_get_mbyte(int32 addr);
43 int32 mp_8m_get_mword(int32 addr);
44 void mp_8m_put_mbyte(int32 addr, int32 val);
45 void mp_8m_put_mword(int32 addr, int32 val);
46
47 /* isbc064 Standard I/O Data Structures */
48
49 UNIT mp_8m_unit[] = {
50 { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
51 { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
52 { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
53 { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
54 { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
55 { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 }
56 };
57
58 MTAB mp_8m_mod[] = {
59 { 0 }
60 };
61
62 DEBTAB mp_8m_debug[] = {
63 { "ALL", DEBUG_all },
64 { "FLOW", DEBUG_flow },
65 { "READ", DEBUG_read },
66 { "WRITE", DEBUG_write },
67 { "LEV1", DEBUG_level1 },
68 { "LEV2", DEBUG_level2 },
69 { NULL }
70 };
71
72 DEVICE mp_8m_dev = {
73 "MP-8M", //name
74 mp_8m_unit, //units
75 NULL, //registers
76 mp_8m_mod, //modifiers
77 MP_8M_NUM, //numunits
78 16, //aradix
79 8, //awidth
80 1, //aincr
81 16, //dradix
82 8, //dwidth
83 NULL, //examine
84 NULL, //deposite
85 &mp_8m_reset, //reset
86 NULL, //boot
87 NULL, //attach
88 NULL, //detach
89 NULL, //ctxt
90 DEV_DEBUG, //flags
91 0, //dctrl
92 mp_8m_debug, //debflags
93 NULL, //msize
94 NULL //lname
95 };
96
97 /* Reset routine */
98
mp_8m_reset(DEVICE * dptr)99 t_stat mp_8m_reset (DEVICE *dptr)
100 {
101 int32 i, j, val;
102 UNIT *uptr;
103
104 if (mp_8m_dev.dctrl & DEBUG_flow)
105 printf("mp_8m_reset: \n");
106 for (i = 0; i < MP_8M_NUM; i++) { /* init all units */
107 uptr = mp_8m_dev.units + i;
108 if (mp_8m_dev.dctrl & DEBUG_flow)
109 printf("MP-8M %d unit.flags=%08X\n", i, uptr->flags);
110 uptr->capac = 0x2000;
111 if (i < 4)
112 uptr->u3 = 0x2000 * i;
113 else
114 uptr->u3 = 0x2000 * (i + 1);
115 if (uptr->filebuf == NULL) {
116 uptr->filebuf = malloc(0x2000);
117 if (uptr->filebuf == NULL) {
118 printf("mp_8m_reset: Malloc error\n");
119 return SCPE_MEM;
120 }
121 for (j=0; j<8192; j++) { /* fill pattern for testing */
122 val = (0xA0 | i);
123 *(uint8 *)(uptr->filebuf + j) = val & 0xFF;
124 }
125 }
126 if (mp_8m_dev.dctrl & DEBUG_flow)
127 printf("MP-8M %d initialized at [%04X-%04XH]\n", i, uptr->u3,
128 uptr->u3 + uptr->capac - 1);
129 }
130 if (mp_8m_dev.dctrl & DEBUG_flow)
131 printf("mp_8m_reset: Done\n");
132 return SCPE_OK;
133 }
134
135 /* I/O instruction handlers, called from the mp-b2 module when an
136 external memory read or write is issued.
137 */
138
139 /* get a byte from memory */
140
mp_8m_get_mbyte(int32 addr)141 int32 mp_8m_get_mbyte(int32 addr)
142 {
143 int32 val, org, len;
144 int32 i;
145 UNIT *uptr;
146
147 if (mp_8m_dev.dctrl & DEBUG_read)
148 printf("mp_8m_get_mbyte: addr=%04X", addr);
149 for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */
150 uptr = mp_8m_dev.units + i;
151 org = uptr->u3;
152 len = uptr->capac - 1;
153 if ((addr >= org) && (addr <= org + len)) {
154 val = *(uint8 *)(uptr->filebuf + (addr - org));
155 if (mp_8m_dev.dctrl & DEBUG_read)
156 printf(" val=%04X\n", val);
157 return (val & 0xFF);
158 }
159 }
160 if (mp_8m_dev.dctrl & DEBUG_read)
161 printf("mp_8m_get_mbyte: Out of range\n");
162 return 0xFF; /* multibus has active high pullups */
163 }
164
165 /* get a word from memory */
166
mp_8m_get_mword(int32 addr)167 int32 mp_8m_get_mword(int32 addr)
168 {
169 int32 val;
170
171 val = (mp_8m_get_mbyte(addr) << 8);
172 val |= mp_8m_get_mbyte(addr+1);
173 return val;
174 }
175
176 /* put a byte into memory */
177
mp_8m_put_mbyte(int32 addr,int32 val)178 void mp_8m_put_mbyte(int32 addr, int32 val)
179 {
180 int32 org, len, type;
181 int32 i;
182 UNIT *uptr;
183
184 if (mp_8m_dev.dctrl & DEBUG_write)
185 printf("mp_8m_put_mbyte: addr=%04X, val=%02X", addr, val);
186 for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */
187 uptr = mp_8m_dev.units + i;
188 org = uptr->u3;
189 len = uptr->capac - 1;
190 if ((addr >= org) && (addr < org + len)) {
191 *(uint8 *)(uptr->filebuf + (addr - org)) = val & 0xFF;
192 if (mp_8m_dev.dctrl & DEBUG_write)
193 printf("\n");
194 return;
195 }
196 }
197 if (mp_8m_dev.dctrl & DEBUG_write)
198 printf("mp_8m_put_mbyte: Out of range\n");
199 }
200
201 /* put a word into memory */
202
mp_8m_put_mword(int32 addr,int32 val)203 void mp_8m_put_mword(int32 addr, int32 val)
204 {
205 mp_8m_put_mbyte(addr, val >> 8);
206 mp_8m_put_mbyte(addr+1, val);
207 }
208
209 /* end of mp-8m.c */
210