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

« back to all changes in this revision

Viewing changes to SDS/sds_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
/* sds_drm.c: SDS 940 Project Genie drum simulator
 
2
 
 
3
   Copyright (c) 2002-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
   drm          drum
 
27
 
 
28
   The drum is buffered in memory.
 
29
 
 
30
   Note: the Project Genie documentation and the actual monitor sources disagree
 
31
   on the I/O instruction definitions for the drum.  The simulator follows the
 
32
   monitor sources, as follows:
 
33
 
 
34
   DCC    OP      00230404B       RESET DRUM CHANNEL
 
35
   DSC    OP      00230204B       START DRUM CHANNEL (NO CHAIN)
 
36
   DRA    OP      00230504B       READ DRUM TIMING COUNTER INTO 21B
 
37
   DSR    OP      04030204B       SKIP IF DRUM NOT BUSY
 
38
   DSE    OP      04037404B       SKIP IF NO DRUM ERROR
 
39
*/
 
40
 
 
41
#include "sds_defs.h"
 
42
#include <math.h>
 
43
 
 
44
/* Constants */
 
45
 
 
46
#define DRM_N_WD        11                              /* word addr width */
 
47
#define DRM_V_WD        0                               /* position */
 
48
#define DRM_M_WD        ((1 << DRM_N_WD) - 1)           /* word mask */
 
49
#define DRM_NUMWD       (1 << DRM_N_WD)                 /* words/sector */
 
50
#define DRM_NUMGP       236                             /* gap/sector */
 
51
#define DRM_PHYWD       (DRM_NUMWD + DRM_NUMGP)         /* phys wds/sector */
 
52
#define DRM_N_SC        3                               /* sect addr width */
 
53
#define DRM_V_SC        (DRM_N_WD)                      /* position */
 
54
#define DRM_M_SC        ((1 << DRM_N_SC) - 1)           /* sector mask */
 
55
#define DRM_NUMSC       (1 << DRM_N_SC)                 /* sectors/track */
 
56
#define DRM_N_TR        7                               /* track addr width */
 
57
#define DRM_V_TR        (DRM_N_WD+DRM_N_SC)             /* position */
 
58
#define DRM_M_TR        ((1 << DRM_N_TR) - 1)           /* track mask */
 
59
#define DRM_NUMTR       84                              /* tracks/drum */
 
60
#define DRM_N_ADDR      (DRM_N_WD+DRM_N_SC+DRM_N_TR)    /* drum addr width */
 
61
#define DRM_SWMASK      ((1 << (DRM_N_WD+DRM_N_SC)) - 1)/* sector+word mask */
 
62
#define DRM_DAMASK      ((1 << DRM_N_ADDR) - 1)         /* drum addr mask */
 
63
#define DRM_SIZE        (DRM_NUMTR*DRM_NUMSC*DRM_NUMWD) /* words/disk */
 
64
#define DRM_WCMASK      037777                          /* wc mask */
 
65
#define DRM_GETSC(x)    (((x) >> DRM_V_SC) & DRM_M_SC)
 
66
 
 
67
#define DRM_PC          020
 
68
#define DRM_AD          021
 
69
#define DRM_ADAT        (1 << (DRM_N_WD + DRM_N_SC))    /* data flag */
 
70
 
 
71
#define DRM_SFET        0                               /* fetch state */
 
72
#define DRM_SFCA        1                               /* fetch CA */
 
73
#define DRM_SFDA        2                               /* fetch DA */
 
74
#define DRM_SXFR        3                               /* xfer */
 
75
 
 
76
#define DRM_V_OP        21                              /* drum op */
 
77
#define DRM_M_OP        07
 
78
#define DRM_V_RW        20
 
79
#define DRM_GETOP(x)    (((x) >> DRM_V_OP) & DRM_M_OP)
 
80
#define DRM_GETRW(x)    (((x) >> DRM_V_RW) & 1)
 
81
#define  DRM_OXF        0                               /* xfer */
 
82
#define  DRM_OCX        1                               /* cond xfer */
 
83
#define  DRM_OBR        2                               /* branch */
 
84
#define  DRM_ORS        3                               /* reset error */
 
85
#define  DRM_END        4                               /* end prog */
 
86
#define  DRM_EIE        5                               /* end int if err */
 
87
#define  DRM_EIU        7                               /* end int uncond */
 
88
 
 
89
#define GET_TWORD(x)    ((int32) fmod (sim_gtime() / ((double) (x)), \
 
90
                        ((double) (DRM_NUMSC * DRM_PHYWD))))
 
91
 
 
92
extern uint32 M[];                                      /* memory */
 
93
extern uint32 alert, int_req;
 
94
extern int32 stop_invins, stop_invdev, stop_inviop;
 
95
uint32 drm_da = 0;                                      /* disk address */
 
96
uint32 drm_ca = 0;                                      /* core address */
 
97
uint32 drm_wc = 0;                                      /* word count */
 
98
int32 drm_par = 0;                                      /* cumulative par */
 
99
int32 drm_err = 0;                                      /* error */
 
100
int32 drm_rw = 0;                                       /* read/write */
 
101
int32 drm_sta = 0;                                      /* drum state */
 
102
int32 drm_ftime = 3;                                    /* time to fetch */
 
103
int32 drm_xtime = 1;                                    /* time to xfr */
 
104
int32 drm_stopioe = 1;                                  /* stop on error */
 
105
 
 
106
DEVICE drm_dev;
 
107
t_stat drm (uint32 fnc, uint32 inst, uint32 *dat);
 
108
t_stat drm_svc (UNIT *uptr);
 
109
t_stat drm_reset (DEVICE *dptr);
 
110
 
 
111
/* DRM data structures
 
112
 
 
113
   drm_dev      device descriptor
 
114
   drm_unit     unit descriptor
 
115
   drm_reg      register list
 
116
*/
 
117
 
 
118
DIB drm_dib = { -1, DEV3_GDRM, 0, NULL, &drm };
 
119
 
 
120
UNIT drm_unit =
 
121
        { UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
 
122
                DRM_SIZE) };
 
123
 
 
124
REG drm_reg[] = {
 
125
        { ORDATA (DA, drm_da, DRM_N_ADDR) },
 
126
        { ORDATA (CA, drm_ca, 16) },
 
127
        { ORDATA (WC, drm_wc, 14) },
 
128
        { ORDATA (PAR, drm_par, 12) },
 
129
        { FLDATA (RW, drm_rw, 0) },
 
130
        { FLDATA (ERR, drm_err, 0) },
 
131
        { ORDATA (STA, drm_sta, 2) },
 
132
        { DRDATA (FTIME, drm_ftime, 24), REG_NZ + PV_LEFT },
 
133
        { DRDATA (XTIME, drm_xtime, 24), REG_NZ + PV_LEFT },
 
134
        { FLDATA (STOP_IOE, drm_stopioe, 0) },
 
135
        { NULL }  };
 
136
 
 
137
DEVICE drm_dev = {
 
138
        "DRM", &drm_unit, drm_reg, NULL,
 
139
        1, 8, DRM_N_ADDR, 1, 8, 24,
 
140
        NULL, NULL, &drm_reset,
 
141
        NULL, NULL, NULL,
 
142
        &drm_dib, DEV_DISABLE | DEV_DIS };
 
143
 
 
144
/* Drum routine -  EOM/SKS 3xx04 */
 
145
 
 
146
t_stat drm (uint32 fnc, uint32 inst, uint32 *dat)
 
147
{
 
148
int32 t, op = inst & 07700;
 
149
 
 
150
switch (fnc) {
 
151
case IO_CONN:                                           /* connect */
 
152
    if (op == 00400) return drm_reset (&drm_dev);       /* EOM 404 = reset */
 
153
    if (op == 00500) {                                  /* EOM 504 = read DA */
 
154
        if (sim_is_active (&drm_unit)) return SCPE_OK;  /* must be idle */
 
155
        t = GET_TWORD (drm_xtime);                      /* get position */
 
156
        if (t < DRM_NUMGP) M[DRM_AD] = DRM_NUMWD - t;   /* in gap? */
 
157
        else M[DRM_AD] = (t - DRM_NUMGP) | DRM_ADAT;  } /* in data */
 
158
    else if (op == 00200) {                             /* EOM 204 = start */
 
159
        if (sim_is_active (&drm_unit)) return SCPE_OK;  /* must be idle */
 
160
        drm_sta = DRM_SFET;                             /* state = fetch */
 
161
        sim_activate (&drm_unit, drm_ftime);  }         /* activate */
 
162
    else CRETINS;
 
163
    break;
 
164
 
 
165
case IO_SKS:                                            /* SKS */
 
166
    if (((op == 07400) && !drm_err) ||                  /* 37404: no err */
 
167
        ((op == 00200) && !sim_is_active (&drm_unit)))  /* 30204: idle */
 
168
        *dat = 1;
 
169
    break;
 
170
 
 
171
default:
 
172
    return SCPE_IERR;  }                                /* can't get here */
 
173
return SCPE_OK;
 
174
}
 
175
 
 
176
/* Unit service */
 
177
 
 
178
t_stat drm_svc (UNIT *uptr)
 
179
{
 
180
int32 t, rda;
 
181
uint32 dpc, dwd;
 
182
uint32 *fbuf = uptr->filebuf;
 
183
 
 
184
if (drm_sta != DRM_SXFR) {                              /* fetch drum prog? */
 
185
    dpc = M[DRM_PC];                                    /* get drum PC */
 
186
    dwd = M[dpc & PAMASK];                              /* get drum inst */
 
187
    M[DRM_PC] = (dpc + 1) & PAMASK;                     /* update drum PC */
 
188
    if (drm_sta == DRM_SFCA) {                          /* fetch core addr? */
 
189
        drm_rw = DRM_GETRW (dwd);                       /* set op */
 
190
        drm_ca = dwd & PAMASK;                          /* set core addr */
 
191
        drm_sta = DRM_SFDA;  }                          /* next is disk addr */
 
192
    else if (drm_sta == DRM_SFDA) {                     /* fetch disk addr? */
 
193
        drm_da = dwd & DRM_DAMASK;                      /* set disk addr */
 
194
        drm_sta = DRM_SXFR;                             /* next is xfer */
 
195
        drm_par = 0;                                    /* init parity */
 
196
        rda = (drm_da & DRM_SWMASK) + (DRM_GETSC (drm_da) * DRM_NUMGP);
 
197
        t = rda - GET_TWORD (drm_xtime);                /* difference */
 
198
        if (t <= 0) t = t + (DRM_NUMSC * DRM_PHYWD);    /* add trk lnt */
 
199
        sim_activate (&drm_unit, t * drm_xtime);  }     /* activate */
 
200
    else {
 
201
        switch (DRM_GETOP (dwd)) {
 
202
        case DRM_OCX:                                   /* cond xfr */
 
203
            if (drm_err) {                              /* error? */
 
204
                int_req = int_req | INT_DRM;            /* req int */
 
205
                return SCPE_OK;  }                      /* done */
 
206
        case DRM_OXF:                                   /* transfer */
 
207
            drm_wc = dwd & DRM_WCMASK;                  /* save wc */
 
208
            drm_sta = DRM_SFCA;                         /* next state */
 
209
            break;
 
210
        case DRM_OBR:                                   /* branch */
 
211
            M[DRM_PC] = dwd & PAMASK;                   /* new drum PC */
 
212
            break;
 
213
        case DRM_END:                                   /* end */
 
214
            return SCPE_OK;
 
215
        case DRM_EIE:                                   /* end, int if err */
 
216
            if (!drm_err) return SCPE_OK;
 
217
        case DRM_EIU:                                   /* end, int uncond */
 
218
            int_req = int_req | INT_DRM;
 
219
            return SCPE_OK;  }                          /* end switch */
 
220
        }                                               /* end else sta */
 
221
    sim_activate (uptr, drm_ftime);                     /* fetch next word */
 
222
    }                                                   /* end if !xfr */
 
223
else {                                                  /* transfer word */
 
224
    if ((uptr->flags & UNIT_BUF) == 0) {                /* not buffered? */
 
225
        drm_err = 1;                                    /* error */
 
226
        CRETIOE (drm_stopioe, SCPE_UNATT);  }
 
227
    if (drm_rw) {                                       /* write? */
 
228
        dwd = M[drm_ca];                                /* get mem word */
 
229
        fbuf[drm_da] = dwd;                             /* write to drum */
 
230
        if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1;  }
 
231
    else {                                              /* read */
 
232
        dwd = fbuf[drm_da];                             /* get drum word */
 
233
        M[drm_ca] = dwd;  }                             /* write to mem */
 
234
    drm_da = drm_da + 1;                                /* inc drum addr */
 
235
    if (drm_da >= DRM_SIZE) drm_da = 0;                 /* wrap */
 
236
    drm_ca = (drm_ca + 1) & PAMASK;                     /* inc core addr */
 
237
    drm_wc = (drm_wc - 1) & DRM_WCMASK;                 /* dec word cnt */
 
238
    drm_par = drm_par ^ (dwd >> 12);                    /* parity */
 
239
    drm_par = ((drm_par << 1) | (drm_par >> 11)) & 07777;
 
240
    drm_par = drm_par ^ (dwd & 07777);
 
241
    if (drm_wc) {                                       /* more to do */
 
242
        if (drm_da & DRM_M_WD) sim_activate (uptr, drm_xtime);
 
243
        else sim_activate (uptr, drm_xtime * DRM_NUMGP);  }
 
244
    else {                                              /* end xfr */
 
245
#if defined (DRM_PAR)
 
246
        if ((drm_da & DRM_M_WD) && drm_rw) {            /* wr end mid sector? */
 
247
            M[drm_da] = drm_par << 12;                  /* clobber data */
 
248
            if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1;  }
 
249
#endif
 
250
        drm_sta = DRM_SFET;                             /* back to fetch */
 
251
        sim_activate (uptr, drm_ftime);                 /* schedule */
 
252
        }                                               /* end else end xfr */
 
253
    }                                                   /* end else xfr */
 
254
return SCPE_OK;
 
255
}
 
256
 
 
257
/* Reset routine */
 
258
 
 
259
t_stat drm_reset (DEVICE *dptr)
 
260
{
 
261
drm_da = 0;                                             /* clear state */
 
262
drm_ca = 0;
 
263
drm_wc = 0;
 
264
drm_par = 0;
 
265
drm_sta = 0;
 
266
drm_err = 0;
 
267
drm_rw = 0;
 
268
int_req = int_req & ~INT_DRM;                           /* clear intr */
 
269
sim_cancel (&drm_unit);                                 /* deactivate */
 
270
return SCPE_OK;
 
271
}