~ubuntu-branches/ubuntu/utopic/simh/utopic

« back to all changes in this revision

Viewing changes to PDP1/pdp1_drm.c

  • Committer: Bazaar Package Importer
  • Author(s): Vince Mulhollon
  • Date: 2004-04-20 20:01:26 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040420200126-ehsuleda8xcgi51h
Tags: 3.2.0-1
New upstream 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pdp1_drm.c: PDP-1 drum simulator
 
2
 
 
3
   Copyright (c) 1993-2004, Robert M Supnik
 
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
   ROBERT M SUPNIK 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 Robert M Supnik shall not
 
23
   be used in advertising or otherwise to promote the sale, use or other dealings
 
24
   in this Software without prior written authorization from Robert M Supnik.
 
25
 
 
26
   drp          Type 23 parallel drum
 
27
   drm          Type 24 serial drum
 
28
 
 
29
   08-Dec-03    RMS     Added parallel drum support
 
30
                        Fixed bug in DBL/DCN decoding
 
31
   26-Oct-03    RMS     Cleaned up buffer copy code
 
32
   23-Jul-03    RMS     Fixed incorrect logical, missing activate
 
33
   05-Dec-02    RMS     Cloned from pdp18b_drm.c
 
34
*/
 
35
 
 
36
#include "pdp1_defs.h"
 
37
#include <math.h>
 
38
 
 
39
/* Serial drum constants */
 
40
 
 
41
#define DRM_NUMWDS      256                             /* words/sector */
 
42
#define DRM_NUMSC       2                               /* sectors/track */
 
43
#define DRM_NUMTR       256                             /* tracks/drum */
 
44
#define DRM_NUMWDT      (DRM_NUMWDS * DRM_NUMSC)        /* words/track */
 
45
#define DRM_SIZE        (DRM_NUMTR * DRM_NUMWDT)        /* words/drum */
 
46
#define DRM_SMASK       ((DRM_NUMTR * DRM_NUMSC) - 1)   /* sector mask */
 
47
 
 
48
/* Parallel drum constants */
 
49
 
 
50
#define DRP_NUMWDT      4096                            /* words/track */
 
51
#define DRP_NUMTK       32                              /* tracks/drum */
 
52
#define DRP_SIZE        (DRP_NUMWDT * DRP_NUMTK)        /* words/drum */
 
53
#define DRP_V_RWE       17                              /* read/write enable */
 
54
#define DRP_V_FLD       12                              /* drum field */
 
55
#define DRP_M_FLD       037
 
56
#define DRP_TAMASK      07777                           /* track address */
 
57
#define DRP_WCMASK      07777                           /* word count */
 
58
#define DRP_MAINCM      07777                           /* mem addr incr */
 
59
#define DRP_GETRWE(x)   (((x) >> DRP_V_RWE) & 1)
 
60
#define DRP_GETRWF(x)   (((x) >> DRP_V_FLD) & DRP_M_FLD)
 
61
 
 
62
/* Parameters in the unit descriptor */
 
63
 
 
64
#define FUNC            u4                              /* function */
 
65
#define DRM_READ        000                             /* read */
 
66
#define DRM_WRITE       010                             /* write */
 
67
#define DRP_RW          000                             /* read/write */
 
68
#define DRP_BRK         001                             /* break on address */
 
69
 
 
70
#define GET_POS(x)      ((int) fmod (sim_gtime() / ((double) (x)), \
 
71
                        ((double) DRM_NUMWDT)))
 
72
 
 
73
extern int32 M[];
 
74
extern int32 iosta, sbs;
 
75
extern int32 stop_inst;
 
76
extern UNIT cpu_unit;
 
77
 
 
78
/* Serial drum variables */
 
79
 
 
80
uint32 drm_da = 0;                                      /* track address */
 
81
uint32 drm_ma = 0;                                      /* memory address */
 
82
uint32 drm_err = 0;                                     /* error flag */
 
83
uint32 drm_wlk = 0;                                     /* write lock */
 
84
int32 drm_time = 4;                                     /* inter-word time */
 
85
int32 drm_stopioe = 1;                                  /* stop on error */
 
86
 
 
87
/* Parallel drum variables */
 
88
 
 
89
uint32 drp_rde = 0;                                     /* read enable */
 
90
uint32 drp_wre = 0;                                     /* write enable */
 
91
uint32 drp_rdf = 0;                                     /* read field */
 
92
uint32 drp_wrf = 0;                                     /* write field */
 
93
uint32 drp_ta = 0;                                      /* track address */
 
94
uint32 drp_wc = 0;                                      /* word count */
 
95
uint32 drp_ma = 0;                                      /* memory address */
 
96
uint32 drp_err = 0;                                     /* error */
 
97
int32 drp_time = 2;                                     /* inter-word time */
 
98
int32 drp_stopioe = 1;                                  /* stop on error */
 
99
 
 
100
/* Forward declarations */
 
101
 
 
102
t_stat drm_svc (UNIT *uptr);
 
103
t_stat drm_reset (DEVICE *dptr);
 
104
t_stat drp_svc (UNIT *uptr);
 
105
t_stat drp_reset (DEVICE *dptr);
 
106
 
 
107
/* DRM data structures
 
108
 
 
109
   drm_dev      DRM device descriptor
 
110
   drm_unit     DRM unit descriptor
 
111
   drm_reg      DRM register list
 
112
*/
 
113
 
 
114
UNIT drm_unit =
 
115
        { UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
 
116
                DRM_SIZE) };
 
117
 
 
118
REG drm_reg[] = {
 
119
        { ORDATA (DA, drm_da, 9) },
 
120
        { ORDATA (MA, drm_ma, 16) },
 
121
        { FLDATA (DONE, iosta, IOS_V_DRM) },
 
122
        { FLDATA (ERR, drm_err, 0) },
 
123
        { ORDATA (WLK, drm_wlk, 32) },
 
124
        { DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
 
125
        { FLDATA (STOP_IOE, drm_stopioe, 0) },
 
126
        { NULL }  };
 
127
 
 
128
DEVICE drm_dev = {
 
129
        "DRM", &drm_unit, drm_reg, NULL,
 
130
        1, 8, 20, 1, 8, 18,
 
131
        NULL, NULL, &drm_reset,
 
132
        NULL, NULL, NULL,
 
133
        NULL, DEV_DISABLE };
 
134
 
 
135
/* DRP data structures
 
136
 
 
137
   drp_dev      DRP device descriptor
 
138
   drp_unit     DRP unit descriptor
 
139
   drp_reg      DRP register list
 
140
*/
 
141
 
 
142
UNIT drp_unit =
 
143
        { UDATA (&drp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
 
144
                DRM_SIZE) };
 
145
 
 
146
REG drp_reg[] = {
 
147
        { ORDATA (TA, drp_ta, 12) },
 
148
        { ORDATA (RDF, drp_rdf, 5) },
 
149
        { FLDATA (RDE, drp_rde, 0) },
 
150
        { FLDATA (WRF, drp_wrf, 5) },
 
151
        { FLDATA (WRE, drp_wre, 0) },
 
152
        { ORDATA (MA, drp_ma, 16) },
 
153
        { ORDATA (WC, drp_wc, 12) },
 
154
        { FLDATA (BUSY, iosta, IOS_V_DRP) },
 
155
        { FLDATA (ERR, drp_err, 0) },
 
156
        { DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT },
 
157
        { FLDATA (STOP_IOE, drp_stopioe, 0) },
 
158
        { NULL }  };
 
159
 
 
160
DEVICE drp_dev = {
 
161
        "DRP", &drp_unit, drp_reg, NULL,
 
162
        1, 8, 20, 1, 8, 18,
 
163
        NULL, NULL, &drp_reset,
 
164
        NULL, NULL, NULL,
 
165
        NULL, DEV_DISABLE | DEV_DIS };
 
166
 
 
167
/* IOT routines */
 
168
 
 
169
int32 drm (int32 IR, int32 dev, int32 dat)
 
170
{
 
171
int32 t;
 
172
int32 pulse = (IR >> 6) & 037;
 
173
 
 
174
if ((drm_dev.flags & DEV_DIS) == 0) {                   /* serial enabled? */
 
175
        if ((pulse != 001) && (pulse != 011))           /* invalid pulse? */
 
176
            return (stop_inst << IOT_V_REASON) | dat;   /* stop if requested */
 
177
        switch (dev) {                                  /* switch on device */
 
178
        case 061:                                       /* DWR, DRD */
 
179
            drm_ma = dat & AMASK;                       /* load mem addr */
 
180
            drm_unit.FUNC = pulse & DRM_WRITE;          /* save function */
 
181
            break;
 
182
        case 062:                                       /* DBL, DCN */
 
183
            if ((pulse & 010) == 0)                     /* DBL? */
 
184
                drm_da = dat & DRM_SMASK;               /* load sector # */
 
185
            iosta = iosta & ~IOS_DRM;                   /* clear flags */
 
186
            drm_err = 0;
 
187
            t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
 
188
            if (t <= 0) t = t + DRM_NUMWDT;             /* wrap around? */
 
189
            sim_activate (&drm_unit, t);                /* start operation */
 
190
            break;
 
191
        case 063:                                       /* DTD */
 
192
            if (pulse == 011) return (stop_inst << IOT_V_REASON) | dat;
 
193
            if (iosta & IOS_DRM) return (dat | IOT_SKP); /* skip if done */
 
194
            break;
 
195
        case 064:                                       /* DSE, DSP */
 
196
            if ((drm_err == 0) || (pulse & 010))        /* no error, par test? */
 
197
                return (dat | IOT_SKP);
 
198
            }                                           /* end case */
 
199
        return dat;  }                                  /* end if serial */
 
200
 
 
201
if ((drp_dev.flags & DEV_DIS) == 0) {                   /* parallel enabled? */
 
202
        switch (dev) {                                  /* switch on device */
 
203
        case 061:                                       /* DIA, DBA */
 
204
            drp_err = 0;                                /* clear error */
 
205
            iosta = iosta & ~IOS_DRP;                   /* not busy */
 
206
            drp_rde = DRP_GETRWE (dat);                 /* set read enable */
 
207
            drp_rdf = DRP_GETRWF (dat);                 /* set read field */
 
208
            drp_ta = dat & DRP_TAMASK;                  /* set track addr */
 
209
            if (IR & 02000) {                           /* DBA? */
 
210
                t = drp_ta - GET_POS (drp_time);        /* delta words */
 
211
                if (t <= 0) t = t + DRP_NUMWDT;         /* wrap around? */
 
212
                sim_activate (&drp_unit, t);            /* start operation */
 
213
                drp_unit.FUNC = DRP_BRK;  }             /* mark as break */
 
214
            else drp_unit.FUNC = DRP_RW;                /* no, read/write */
 
215
            break;
 
216
        case 062:                                       /* DWC, DRA */
 
217
            if (IR & 02000) dat = GET_POS (drp_time) |  /* DRA, get position */
 
218
                (drp_err? 0400000: 0);
 
219
            else {                                      /* DWC */
 
220
                drp_wre = DRP_GETRWE (dat);             /* set write enable */
 
221
                drp_wrf = DRP_GETRWF (dat);             /* set write field */
 
222
                drp_wc = dat & DRP_WCMASK;  }           /* set word count */
 
223
            break;
 
224
        case 063:                                       /* DCL */
 
225
            drp_ma = dat & AMASK;                       /* set mem address */
 
226
            t = drp_ta - GET_POS (drp_time);            /* delta words */
 
227
            if (t <= 0) t = t + DRP_NUMWDT;             /* wrap around? */
 
228
            sim_activate (&drp_unit, t);                /* start operation */
 
229
            iosta = iosta | IOS_DRP;                    /* set busy */
 
230
            break;
 
231
        case 064:                                       /* not assigned */
 
232
            return (stop_inst << IOT_V_REASON) | dat;   /* stop if requested */
 
233
            }                                           /* end case */
 
234
        return dat;  }                                  /* end if parallel */
 
235
 
 
236
return (stop_inst << IOT_V_REASON) | dat;               /* stop if requested */
 
237
}
 
238
 
 
239
/* Serial unit service - this code assumes the entire drum is buffered */
 
240
 
 
241
t_stat drm_svc (UNIT *uptr)
 
242
{
 
243
uint32 i, da;
 
244
uint32 *fbuf = uptr->filebuf;
 
245
 
 
246
if ((uptr->flags & UNIT_BUF) == 0) {                    /* not buf? abort */
 
247
        drm_err = 1;                                    /* set error */
 
248
        iosta = iosta | IOS_DRM;                        /* set done */
 
249
        sbs = sbs | SB_RQ;                              /* req intr */
 
250
        return IORETURN (drm_stopioe, SCPE_UNATT);  }
 
251
 
 
252
da = drm_da * DRM_NUMWDS;                               /* compute dev addr */
 
253
for (i = 0; i < DRM_NUMWDS; i++, da++) {                /* do transfer */
 
254
        if (uptr->FUNC == DRM_READ) {                   /* read? */
 
255
            if (MEM_ADDR_OK (drm_ma))                   /* if !nxm */
 
256
                M[drm_ma] = fbuf[da];  }                /* read word */
 
257
        else {                                          /* write */
 
258
            if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
 
259
            else {                                      /* not locked */
 
260
                fbuf[da] = M[drm_ma];                   /* write word */
 
261
                if (da >= uptr->hwmark) uptr->hwmark = da + 1;  }  }
 
262
        drm_ma = (drm_ma + 1) & AMASK;  }               /* incr mem addr */
 
263
drm_da = (drm_da + 1) & DRM_SMASK;                      /* incr dev addr */
 
264
iosta = iosta | IOS_DRM;                                /* set done */
 
265
sbs = sbs | SB_RQ;                                      /* req intr */
 
266
return SCPE_OK;
 
267
}
 
268
 
 
269
/* Reset routine */
 
270
 
 
271
t_stat drm_reset (DEVICE *dptr)
 
272
{
 
273
if ((drm_dev.flags & DEV_DIS) == 0)
 
274
        drp_dev.flags = drp_dev.flags | DEV_DIS;
 
275
drm_da = drm_ma = drm_err = 0;
 
276
iosta = iosta & ~IOS_DRM;
 
277
sim_cancel (&drm_unit);
 
278
drm_unit.FUNC = 0;
 
279
return SCPE_OK;
 
280
}
 
281
 
 
282
/* Parallel unit service - this code assumes the entire drum is buffered */
 
283
 
 
284
t_stat drp_svc (UNIT *uptr)
 
285
{
 
286
uint32 i, lim;
 
287
uint32 *fbuf = uptr->filebuf;
 
288
 
 
289
if ((uptr->flags & UNIT_BUF) == 0) {                    /* not buf? abort */
 
290
        drp_err = 1;                                    /* set error */
 
291
        iosta = iosta & ~IOS_DRP;                       /* clear busy */
 
292
        if (uptr->FUNC) sbs = sbs | SB_RQ;              /* req intr */
 
293
        return IORETURN (drp_stopioe, SCPE_UNATT);  }
 
294
 
 
295
if (uptr->FUNC == DRP_RW) {                             /* read/write? */
 
296
        lim = drp_wc? drp_wc: DRP_TAMASK + 1;           /* eff word count */
 
297
        for (i = 0; i < lim; i++) {                     /* do transfer */
 
298
            if (drp_wre)                                /* write enabled? */
 
299
                fbuf[(drp_wrf << DRP_V_FLD) | drp_ta] = M[drp_ma];
 
300
            if (drp_rde && MEM_ADDR_OK (drp_ma))        /* read enabled? */
 
301
                M[drp_ma] = fbuf[(drp_rdf << DRP_V_FLD) | drp_ta];
 
302
            drp_ta = (drp_ta + 1) & DRP_TAMASK;         /* incr track addr */
 
303
            drp_ma = ((drp_ma & ~DRP_MAINCM) | ((drp_ma + 1) & DRP_MAINCM));
 
304
            }                                           /* end for */
 
305
        }                                               /* end if */
 
306
iosta = iosta & ~IOS_DRP;                               /* clear busy */
 
307
if (uptr->FUNC) sbs = sbs | SB_RQ;                      /* req intr */
 
308
return SCPE_OK;
 
309
}
 
310
 
 
311
/* Reset routine */
 
312
 
 
313
t_stat drp_reset (DEVICE *dptr)
 
314
{
 
315
if ((drp_dev.flags & DEV_DIS) == 0)
 
316
        drm_dev.flags = drm_dev.flags | DEV_DIS;
 
317
drp_ta = 0;
 
318
drp_rde = drp_rdf = drp_wre = drp_wrf = 0;
 
319
drp_err = 0;
 
320
drp_ma = 0;
 
321
drp_wc = 0;
 
322
iosta = iosta & ~IOS_DRP;
 
323
sim_cancel (&drp_unit);
 
324
drp_unit.FUNC = 0;
 
325
return SCPE_OK;
 
326
}