1 /* pdp11_io_lib.c: Unibus/Qbus common support routines
2 
3    Copyright (c) 1993-2008, 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 be
23    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 
27 #if defined (VM_PDP10)                                  /* PDP10 version */
28 #include "pdp10_defs.h"
29 
30 #elif defined (VM_VAX)                                  /* VAX version */
31 #include "vax_defs.h"
32 
33 #else                                                   /* PDP-11 version */
34 #include "pdp11_defs.h"
35 #endif
36 #include "sim_sock.h"
37 #include "sim_tmxr.h"
38 
39 extern FILE *sim_log;
40 extern DEVICE *sim_devices[];
41 extern int32 autcon_enb;
42 extern int32 int_vec[IPL_HLVL][32];
43 extern int32 (*int_ack[IPL_HLVL][32])(void);
44 extern t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
45 extern t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md);
46 
47 extern t_stat build_dib_tab (void);
48 
49 static DIB *iodibp[IOPAGESIZE >> 1];
50 
51 /* Enable/disable autoconfiguration */
52 
set_autocon(UNIT * uptr,int32 val,char * cptr,void * desc)53 t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc)
54 {
55 if (cptr != NULL)
56     return SCPE_ARG;
57 autcon_enb = val;
58 return auto_config (NULL, 0);
59 }
60 
61 /* Show autoconfiguration status */
62 
show_autocon(FILE * st,UNIT * uptr,int32 val,void * desc)63 t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc)
64 {
65 fprintf (st, "autoconfiguration ");
66 fprintf (st, autcon_enb? "enabled": "disabled");
67 return SCPE_OK;
68 }
69 
70 /* Change device address */
71 
set_addr(UNIT * uptr,int32 val,char * cptr,void * desc)72 t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc)
73 {
74 DEVICE *dptr;
75 DIB *dibp;
76 uint32 newba;
77 t_stat r;
78 
79 if (cptr == NULL)
80     return SCPE_ARG;
81 if ((val == 0) || (uptr == NULL))
82     return SCPE_IERR;
83 dptr = find_dev_from_unit (uptr);
84 if (dptr == NULL)
85     return SCPE_IERR;
86 dibp = (DIB *) dptr->ctxt;
87 if (dibp == NULL)
88     return SCPE_IERR;
89 newba = (uint32) get_uint (cptr, DEV_RDX, IOPAGEBASE+IOPAGEMASK, &r); /* get new */
90 if (r != SCPE_OK)
91     return r;
92 if ((newba <= IOPAGEBASE) ||                            /* > IO page base? */
93     (newba % ((uint32) val)))                           /* check modulus */
94     return SCPE_ARG;
95 dibp->ba = newba;                                       /* store */
96 dptr->flags = dptr->flags & ~DEV_FLTA;                  /* not floating */
97 autcon_enb = 0;                                         /* autoconfig off */
98 return SCPE_OK;
99 }
100 
101 /* Show device address */
102 
show_addr(FILE * st,UNIT * uptr,int32 val,void * desc)103 t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc)
104 {
105 DEVICE *dptr;
106 DIB *dibp;
107 
108 if (uptr == NULL)
109     return SCPE_IERR;
110 dptr = find_dev_from_unit (uptr);
111 if (dptr == NULL)
112     return SCPE_IERR;
113 dibp = (DIB *) dptr->ctxt;
114 if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE))
115     return SCPE_IERR;
116 fprintf (st, "address=");
117 fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
118 if (dibp->lnt > 1) {
119     fprintf (st, "-");
120     fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT);
121     }
122 if (dptr->flags & DEV_FLTA)
123     fprintf (st, "*");
124 return SCPE_OK;
125 }
126 
127 /* Set address floating */
128 
set_addr_flt(UNIT * uptr,int32 val,char * cptr,void * desc)129 t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc)
130 {
131 DEVICE *dptr;
132 
133 if (cptr != NULL)
134     return SCPE_ARG;
135 if (uptr == NULL)
136     return SCPE_IERR;
137 dptr = find_dev_from_unit (uptr);
138 if (dptr == NULL)
139     return SCPE_IERR;
140 dptr->flags = dptr->flags | DEV_FLTA;                   /* floating */
141 return auto_config (NULL, 0);                           /* autoconfigure */
142 }
143 
144 /* Change device vector */
145 
set_vec(UNIT * uptr,int32 arg,char * cptr,void * desc)146 t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc)
147 {
148 DEVICE *dptr;
149 DIB *dibp;
150 uint32 newvec;
151 t_stat r;
152 
153 if (cptr == NULL)
154     return SCPE_ARG;
155 if (uptr == NULL)
156     return SCPE_IERR;
157 dptr = find_dev_from_unit (uptr);
158 if (dptr == NULL)
159     return SCPE_IERR;
160 dibp = (DIB *) dptr->ctxt;
161 if (dibp == NULL)
162     return SCPE_IERR;
163 newvec = (uint32) get_uint (cptr, DEV_RDX, VEC_Q + 01000, &r);
164 if ((r != SCPE_OK) || (newvec == VEC_Q) ||
165     ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) ||
166     (newvec & ((dibp->vnum > 1)? 07: 03)))
167     return SCPE_ARG;
168 dibp->vec = newvec;
169 dptr->flags = dptr->flags & ~DEV_FLTA;                  /* not floating */
170 autcon_enb = 0;                                         /* autoconfig off */
171 return SCPE_OK;
172 }
173 
174 /* Show device vector */
175 
show_vec(FILE * st,UNIT * uptr,int32 arg,void * desc)176 t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc)
177 {
178 DEVICE *dptr;
179 DIB *dibp;
180 uint32 vec, numvec;
181 
182 if (uptr == NULL)
183     return SCPE_IERR;
184 dptr = find_dev_from_unit (uptr);
185 if (dptr == NULL)
186     return SCPE_IERR;
187 dibp = (DIB *) dptr->ctxt;
188 if (dibp == NULL)
189     return SCPE_IERR;
190 vec = dibp->vec;
191 if (arg)
192     numvec = arg;
193 else numvec = dibp->vnum;
194 if (vec == 0)
195     fprintf (st, "no vector");
196 else {
197     fprintf (st, "vector=");
198     fprint_val (st, (t_value) vec, DEV_RDX, 16, PV_LEFT);
199     if (numvec > 1) {
200         fprintf (st, "-");
201         fprint_val (st, (t_value) vec + (4 * (numvec - 1)), DEV_RDX, 16, PV_LEFT);
202         }
203     }
204 return SCPE_OK;
205 }
206 
207 /* Show vector for terminal multiplexor */
208 
show_vec_mux(FILE * st,UNIT * uptr,int32 arg,void * desc)209 t_stat show_vec_mux (FILE *st, UNIT *uptr, int32 arg, void *desc)
210 {
211 TMXR *mp = (TMXR *) desc;
212 
213 if ((mp == NULL) || (arg == 0))
214     return SCPE_IERR;
215 return show_vec (st, uptr, ((mp->lines * 2) / arg), desc);
216 }
217 
218 /* Init Unibus tables */
219 
init_ubus_tab(void)220 void init_ubus_tab (void)
221 {
222 int32 i, j;
223 
224 for (i = 0; i < IPL_HLVL; i++) {                        /* clear intr tab */
225     for (j = 0; j < 32; j++) {
226         int_vec[i][j] = 0;
227         int_ack[i][j] = NULL;
228         }
229     }
230 for (i = 0; i < (IOPAGESIZE >> 1); i++) {               /* clear dispatch tab */
231     iodispR[i] = NULL;
232     iodispW[i] = NULL;
233     iodibp[i] = NULL;
234     }
235 return;
236 }
237 
238 /* Build Unibus tables */
239 
build_ubus_tab(DEVICE * dptr,DIB * dibp)240 t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp)
241 {
242 int32 i, idx, vec, ilvl, ibit;
243 
244 if ((dptr == NULL) || (dibp == NULL))                   /* validate args */
245     return SCPE_IERR;
246 if (dibp->vnum > VEC_DEVMAX)
247     return SCPE_IERR;
248 for (i = 0; i < dibp->vnum; i++) {                      /* loop thru vec */
249     idx = dibp->vloc + i;                               /* vector index */
250     vec = dibp->vec? (dibp->vec + (i * 4)): 0;          /* vector addr */
251     ilvl = idx / 32;
252     ibit = idx % 32;
253     if ((int_ack[ilvl][ibit] && dibp->ack[i] &&         /* conflict? */
254         (int_ack[ilvl][ibit] != dibp->ack[i])) ||
255         (int_vec[ilvl][ibit] && vec &&
256         (int_vec[ilvl][ibit] != vec))) {
257         printf ("Device %s interrupt slot conflict at %d\n",
258                 sim_dname (dptr), idx);
259         if (sim_log)
260             fprintf (sim_log, "Device %s interrupt slot conflict at %d\n",
261                      sim_dname (dptr), idx);
262         return SCPE_STOP;
263         }
264     if (dibp->ack[i])
265         int_ack[ilvl][ibit] = dibp->ack[i];
266     else if (vec)
267         int_vec[ilvl][ibit] = vec;
268     }
269 for (i = 0; i < (int32) dibp->lnt; i = i + 2) {         /* create entries */
270     idx = ((dibp->ba + i) & IOPAGEMASK) >> 1;           /* index into disp */
271     if ((iodispR[idx] && dibp->rd &&                    /* conflict? */
272         (iodispR[idx] != dibp->rd)) ||
273         (iodispW[idx] && dibp->wr &&
274         (iodispW[idx] != dibp->wr))) {
275         printf ("Device %s address conflict at \n", sim_dname (dptr));
276         fprint_val (stdout, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
277         if (sim_log) {
278             fprintf (sim_log, "Device %s address conflict at \n", sim_dname (dptr));
279             fprint_val (sim_log, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
280             }
281         return SCPE_STOP;
282         }
283     if (dibp->rd)                                       /* set rd dispatch */
284         iodispR[idx] = dibp->rd;
285     if (dibp->wr)                                       /* set wr dispatch */
286         iodispW[idx] = dibp->wr;
287     iodibp[idx] = dibp;                                 /* remember DIB */
288     }
289 return SCPE_OK;
290 }
291 
292 /* Show IO space */
293 
show_iospace(FILE * st,UNIT * uptr,int32 val,void * desc)294 t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc)
295 {
296 uint32 i, j;
297 DEVICE *dptr;
298 DIB *dibp;
299 
300 if (build_dib_tab ())                                   /* build IO page */
301     return SCPE_OK;
302 for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) {  /* loop thru entries */
303     if (iodibp[i] && (iodibp[i] != dibp)) {             /* new block? */
304         dibp = iodibp[i];                               /* DIB for block */
305         for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) {
306             if (((DIB*) sim_devices[j]->ctxt) == dibp) {
307                 dptr = sim_devices[j];                  /* locate device */
308                 break;
309                 }                                       /* end if */
310             }                                           /* end for j */
311         fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
312         fprintf (st, " - ");
313         fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT);
314         fprintf (st, "%c\t%s\n",                        /* print block entry */
315             (dptr && (dptr->flags & DEV_FLTA))? '*': ' ',
316             dptr? sim_dname (dptr): "CPU");
317         }                                               /* end if */
318     }                                                   /* end for i */
319 return SCPE_OK;
320 }
321 
322 /* Autoconfiguration
323 
324    The table reflects the MicroVAX 3900 microcode, with one addition - the
325    number of controllers field handles devices where multiple instances
326    are simulated through a single DEVICE structure (e.g., DZ, VH).
327 
328    A minus number of vectors indicates a field that should be calculated
329    but not placed in the DIB (RQ, TQ dynamic vectors) */
330 
331 #define AUTO_MAXC       4
332 #define AUTO_CSRBASE    0010
333 #define AUTO_VECBASE    0300
334 
335 typedef struct {
336     char        *dnam[AUTO_MAXC];
337     int32       numc;
338     int32       numv;
339     uint32      amod;
340     uint32      vmod;
341     uint32      fixa[AUTO_MAXC];
342     uint32      fixv[AUTO_MAXC];
343     } AUTO_CON;
344 
345 AUTO_CON auto_tab[] = {
346     { { "DCI" }, DCX_LINES, 2, 0, 8, { 0 } },           /* DC11 - fx CSRs */
347     { { "DLI" }, DLX_LINES, 2, 0, 8, { 0 } },           /* KL11/DL11/DLV11 - fx CSRs */
348     { { NULL }, 1, 2, 0, 8, { 0 } },                    /* DLV11J - fx CSRs */
349     { { NULL }, 1, 2, 8, 8 },                           /* DJ11 */
350     { { NULL }, 1, 2, 16, 8 },                          /* DH11 */
351     { { NULL }, 1, 2, 8, 8 },                           /* DQ11 */
352     { { NULL }, 1, 2, 8, 8 },                           /* DU11 */
353     { { NULL }, 1, 2, 8, 8 },                           /* DUP11 */
354     { { NULL }, 10, 2, 8, 8 },                          /* LK11A */
355     { { NULL }, 1, 2, 8, 8 },                           /* DMC11 */
356     { { "DZ" }, DZ_MUXES, 2, 8, 8 },                    /* DZ11 */
357     { { NULL }, 1, 2, 8, 8 },                           /* KMC11 */
358     { { NULL }, 1, 2, 8, 8 },                           /* LPP11 */
359     { { NULL }, 1, 2, 8, 8 },                           /* VMV21 */
360     { { NULL }, 1, 2, 16, 8 },                          /* VMV31 */
361     { { NULL }, 1, 2, 8, 8 },                           /* DWR70 */
362     { { "RL", "RLB" }, 1, 1, 8, 4, {IOBA_RL}, {VEC_RL} }, /* RL11 */
363     { { "TS", "TSB", "TSC", "TSD" }, 1, 1, 0, 4,        /* TS11 */
364         {IOBA_TS, IOBA_TS + 4, IOBA_TS + 8, IOBA_TS + 12},
365         {VEC_TS} },
366     { { NULL }, 1, 2, 16, 8 },                          /* LPA11K */
367     { { NULL }, 1, 2, 8, 8 },                           /* KW11C */
368     { { NULL }, 1, 1, 8, 8 },                           /* reserved */
369     { { "RX", "RY" }, 1, 1, 8, 4, {IOBA_RX} , {VEC_RX} }, /* RX11/RX211 */
370     { { NULL }, 1, 1, 8, 4 },                           /* DR11W */
371     { { NULL }, 1, 1, 8, 4, { 0, 0 }, { 0 } },          /* DR11B - fx CSRs,vec */
372     { { NULL }, 1, 2, 8, 8 },                           /* DMP11 */
373     { { NULL }, 1, 2, 8, 8 },                           /* DPV11 */
374     { { NULL }, 1, 2, 8, 8 },                           /* ISB11 */
375     { { NULL }, 1, 2, 16, 8 },                          /* DMV11 */
376     { { "XU", "XUB" }, 1, 1, 8, 4, {IOBA_XU}, {VEC_XU} },   /* DEUNA */
377     { { "XQ", "XQB" }, 1, 1, 0, 4,                      /* DEQNA */
378         {IOBA_XQ,IOBA_XQB}, {VEC_XQ} },
379     { { "RQ", "RQB", "RQC", "RQD" }, 1, -1, 4, 4,       /* RQDX3 */
380         {IOBA_RQ}, {VEC_RQ} },
381     { { NULL }, 1, 8, 32, 4 },                          /* DMF32 */
382     { { NULL }, 1, 2, 16, 8 },                          /* KMS11 */
383     { { NULL }, 1, 1, 16, 4 },                          /* VS100 */
384     { { "TQ", "TQB" }, 1, -1, 4, 4, {IOBA_TQ}, {VEC_TQ} }, /* TQK50 */
385     { { NULL }, 1, 2, 16, 8 },                          /* KMV11 */
386     { { "VH" }, VH_MUXES, 2, 16, 8 },                   /* DHU11/DHQ11 */
387     { { NULL }, 1, 6, 32, 4 },                          /* DMZ32 */
388     { { NULL }, 1, 6, 32, 4 },                          /* CP132 */
389     { { NULL }, 1, 2, 64, 8, { 0 } },                   /* QVSS - fx CSR */
390     { { NULL }, 1, 1, 8, 4 },                           /* VS31 */
391     { { NULL }, 1, 1, 0, 4, { 0 } },                    /* LNV11 - fx CSR */
392     { { NULL }, 1, 1, 16, 4 },                          /* LNV21/QPSS */
393     { { NULL }, 1, 1, 8, 4, { 0 } },                    /* QTA - fx CSR */
394     { { NULL }, 1, 1, 8, 4 },                           /* DSV11 */
395     { { NULL }, 1, 2, 8, 8 },                           /* CSAM */
396     { { NULL }, 1, 2, 8, 8 },                           /* ADV11C */
397     { { NULL }, 1, 0, 8, 0 },                           /* AAV11C */
398     { { NULL }, 1, 2, 8, 8, { 0 }, { 0 } },             /* AXV11C - fx CSR,vec */
399     { { NULL }, 1, 2, 4, 8, { 0 } },                    /* KWV11C - fx CSR */
400     { { NULL }, 1, 2, 8, 8, { 0 } },                    /* ADV11D - fx CSR */
401     { { NULL }, 1, 2, 8, 8, { 0 } },                    /* AAV11D - fx CSR */
402     { { "QDSS" }, 1, 3, 0, 16, {IOBA_QDSS} },           /* QDSS - fx CSR */
403     { { NULL }, -1 }                                    /* end table */
404 };
405 
auto_config(char * name,int32 nctrl)406 t_stat auto_config (char *name, int32 nctrl)
407 {
408 uint32 csr = IOPAGEBASE + AUTO_CSRBASE;
409 uint32 vec = VEC_Q + AUTO_VECBASE;
410 AUTO_CON *autp;
411 DEVICE *dptr;
412 DIB *dibp;
413 uint32 j, k, vmask, amask;
414 
415 if (autcon_enb == 0)                                    /* enabled? */
416     return SCPE_OK;
417 if (name) {                                             /* updating? */
418     if (nctrl < 0)
419         return SCPE_ARG;
420     for (autp = auto_tab; autp->numc >= 0; autp++) {
421         for (j = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) {
422             if (strcmp (name, autp->dnam[j]) == 0)
423                 autp->numc = nctrl;
424             }
425         }
426     }
427 for (autp = auto_tab; autp->numc >= 0; autp++) {        /* loop thru table */
428     if (autp->amod) {                                   /* floating csr? */
429         amask = autp->amod - 1;
430         csr = (csr + amask) & ~amask;                   /* align csr */
431         }
432     for (j = k = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) {
433         if (autp->dnam[j] == NULL)                      /* no device? */
434             continue;
435         dptr = find_dev (autp->dnam[j]);                /* find ctrl */
436         if ((dptr == NULL) ||                           /* enabled, floating? */
437             (dptr->flags & DEV_DIS) ||
438             !(dptr->flags & DEV_FLTA))
439             continue;
440         dibp = (DIB *) dptr->ctxt;                      /* get DIB */
441         if (dibp == NULL)                               /* not there??? */
442             return SCPE_IERR;
443         if (autp->amod) {                               /* dyn csr needed? */
444             if (autp->fixa[k])                          /* fixed csr avail? */
445                 dibp->ba = autp->fixa[k];               /* use it */
446             else {                                      /* no fixed left */
447                 dibp->ba = csr;                         /* set CSR */
448                 csr += (autp->numc * autp->amod);       /* next CSR */
449                 }                                       /* end else */
450             }                                           /* end if dyn csr */
451         if (autp->numv && autp->vmod) {                 /* dyn vec needed? */
452             uint32 numv = abs (autp->numv);             /* get num vec */
453             if (autp->fixv[k]) {                        /* fixed vec avail? */
454                 if (autp->numv > 0)
455                     dibp->vec = autp->fixv[k];          /* use it */
456                 }
457             else {                                      /* no fixed left */
458                 vmask = autp->vmod - 1;
459                 vec = (vec + vmask) & ~vmask;           /* align vector */
460                 if (autp->numv > 0)
461                     dibp->vec = vec;                    /* set vector */
462                 vec += (autp->numc * numv * 4);
463                 }                                       /* end else */
464             }                                           /* end if dyn vec */
465         k++;                                            /* next instance */
466         }                                               /* end for j */
467     if (autp->amod)                                     /* flt CSR? gap */
468         csr = csr + 2;
469     }                                                   /* end for i */
470 return SCPE_OK;
471 }
472 
473 /* Factory bad block table creation routine
474 
475    This routine writes a DEC standard 044 compliant bad block table on the
476    last track of the specified unit.  The bad block table consists of 10
477    repetitions of the same table, formatted as follows:
478 
479         words 0-1       pack id number
480         words 2-3       cylinder/sector/surface specifications
481          :
482         words n-n+1     end of table (-1,-1)
483 
484    Inputs:
485         uptr    =       pointer to unit
486         sec     =       number of sectors per surface
487         wds     =       number of words per sector
488    Outputs:
489         sta     =       status code
490 */
491 
pdp11_bad_block(UNIT * uptr,int32 sec,int32 wds)492 t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds)
493 {
494 int32 i;
495 t_addr da;
496 uint16 *buf;
497 
498 if ((sec < 2) || (wds < 16))
499     return SCPE_ARG;
500 if ((uptr->flags & UNIT_ATT) == 0)
501     return SCPE_UNATT;
502 if (uptr->flags & UNIT_RO)
503     return SCPE_RO;
504 if (!get_yn ("Overwrite last track? [N]", FALSE))
505     return SCPE_OK;
506 da = (uptr->capac - (sec * wds)) * sizeof (uint16);
507 if (sim_fseek (uptr->fileref, da, SEEK_SET))
508     return SCPE_IOERR;
509 if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL)
510     return SCPE_MEM;
511 buf[0] = buf[1] = 012345u;
512 buf[2] = buf[3] = 0;
513 for (i = 4; i < wds; i++)
514     buf[i] = 0177777u;
515 for (i = 0; (i < sec) && (i < 10); i++)
516     sim_fwrite (buf, sizeof (uint16), wds, uptr->fileref);
517 free (buf);
518 if (ferror (uptr->fileref))
519     return SCPE_IOERR;
520 return SCPE_OK;
521 }
522