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