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

« back to all changes in this revision

Viewing changes to H316/h316_mt.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
/* h316_mt.c: H316/516 magnetic tape simulator
 
2
 
 
3
   Copyright (c) 2003-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
   mt           516-4100 seven track magnetic tape
 
27
 
 
28
   Magnetic tapes are represented as a series of variable records
 
29
   of the form:
 
30
 
 
31
        32b byte count
 
32
        byte 0
 
33
        byte 1
 
34
        :
 
35
        byte n-2
 
36
        byte n-1
 
37
        32b byte count
 
38
 
 
39
   If the byte count is odd, the record is padded with an extra byte
 
40
   of junk.  File marks are represented by a byte count of 0.
 
41
*/
 
42
 
 
43
#include "h316_defs.h"
 
44
#include "sim_tape.h"
 
45
 
 
46
#define MT_NUMDR        4                               /* number of drives */
 
47
#define DB_N_SIZE       16                              /* max data buf */
 
48
#define DBSIZE          (1 << DB_N_SIZE)                /* max data cmd */
 
49
#define FNC             u3                              /* function */
 
50
#define UST             u4                              /* unit status */
 
51
#define UNIT_WPRT       (MTUF_WLK | UNIT_RO)            /* write prot */
 
52
 
 
53
/* Function codes */
 
54
 
 
55
#define FNC_RBCD2       000
 
56
#define FNC_RBIN2       001
 
57
#define FNC_RBIN3       002
 
58
#define FNC_DMANM       003
 
59
#define FNC_WBCD2       004
 
60
#define FNC_WBIN2       005
 
61
#define FNC_WEOF        006
 
62
#define FNC_IOBUS       007
 
63
#define FNC_WBIN3       010
 
64
#define FNC_FSR         011
 
65
#define FNC_FSF         012
 
66
#define FNC_DMAAU       013
 
67
#define FNC_REW         014
 
68
#define FNC_BSR         015
 
69
#define FNC_BSF         016
 
70
#define FNC_STOPW       017
 
71
#define FNC_2ND         020                             /* second state */
 
72
#define FNC_NOP         (FNC_STOPW|FNC_2ND)
 
73
#define FNC_EOM         040                             /* end of motion */
 
74
 
 
75
/* Status - unit.UST */
 
76
 
 
77
#define STA_BOT         0000002                         /* beg of tape */
 
78
#define STA_EOT         0000001                         /* end of tape */
 
79
 
 
80
extern int32 dev_int, dev_enb, chan_req;
 
81
extern int32 stop_inst;
 
82
 
 
83
uint32 mt_buf = 0;                                      /* data buffer */
 
84
uint32 mt_usel = 0;                                     /* unit select */
 
85
uint32 mt_busy = 0;                                     /* ctlr busy */
 
86
uint32 mt_mdirq = 0;                                    /* motion done int req */
 
87
uint32 mt_rdy = 0;                                      /* transfer ready (int) */
 
88
uint32 mt_err = 0;                                      /* error */
 
89
uint32 mt_eof = 0;                                      /* end of file */
 
90
uint32 mt_eor = 0;                                      /* transfer done */
 
91
uint32 mt_dma = 0;                                      /* DMA/DMC */
 
92
uint32 mt_xtime = 16;                                   /* transfer time */
 
93
uint32 mt_ctime = 3000;                                 /* start/stop time */
 
94
uint32 mt_stopioe = 1;                                  /* stop on I/O error */
 
95
uint8 mtxb[DBSIZE] = { 0 };                             /* data buffer */
 
96
t_mtrlnt mt_ptr = 0, mt_max = 0;                        /* buffer ptrs */
 
97
 
 
98
int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev);
 
99
void mt_updint (uint32 rdy, uint32 mdone);
 
100
t_stat mt_svc (UNIT *uptr);
 
101
t_stat mt_reset (DEVICE *dptr);
 
102
t_stat mt_attach (UNIT *uptr, char *cptr);
 
103
t_stat mt_detach (UNIT *uptr);
 
104
t_stat mt_map_err (UNIT *uptr, t_stat st);
 
105
void mt_wrwd (UNIT *uptr, uint32 dat);
 
106
 
 
107
/* MT data structures
 
108
 
 
109
   mt_dev       MT device descriptor
 
110
   mt_unit      MT unit list
 
111
   mt_reg       MT register list
 
112
   mt_mod       MT modifier list
 
113
*/
 
114
 
 
115
DIB mt_dib = { MT, IOBUS, MT_NUMDR, &mtio };
 
116
 
 
117
UNIT mt_unit[] = {
 
118
        { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
 
119
        { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
 
120
        { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
 
121
        { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }  };
 
122
 
 
123
REG mt_reg[] = {
 
124
        { ORDATA (BUF, mt_buf, 16) },
 
125
        { ORDATA (USEL, mt_usel, 2) },
 
126
        { FLDATA (BUSY, mt_busy, 0) },
 
127
        { FLDATA (RDY, mt_rdy, 0) },
 
128
        { FLDATA (ERR, mt_err, 0) },
 
129
        { FLDATA (EOF, mt_eof, 0) },
 
130
        { FLDATA (EOR, mt_eor, 0) },
 
131
        { FLDATA (MDIRQ, mt_mdirq, 0) },
 
132
        { FLDATA (DMA, mt_dma, 0) },
 
133
        { FLDATA (INTREQ, dev_int, INT_V_MT) },
 
134
        { FLDATA (ENABLE, dev_enb, INT_V_MT) },
 
135
        { BRDATA (DBUF, mtxb, 8, 8, DBSIZE) },
 
136
        { DRDATA (BPTR, mt_ptr, DB_N_SIZE + 1) },
 
137
        { DRDATA (BMAX, mt_max, DB_N_SIZE + 1) },
 
138
        { DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
 
139
        { DRDATA (XTIME, mt_xtime, 24), REG_NZ + PV_LEFT },
 
140
        { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT) },
 
141
        { URDATA (FNC, mt_unit[0].FNC, 8, 8, 0, MT_NUMDR, REG_HRO) },
 
142
        { URDATA (UST, mt_unit[0].UST, 8, 2, 0, MT_NUMDR, REG_HRO) },
 
143
        { ORDATA (CHAN, mt_dib.chan, 5), REG_HRO },
 
144
        { FLDATA (STOP_IOE, mt_stopioe, 0) },
 
145
        { NULL }  };
 
146
 
 
147
MTAB mt_mod[] = {
 
148
        { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
 
149
        { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, 
 
150
        { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
 
151
                &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
 
152
        { MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS",
 
153
                &io_set_iobus, NULL, NULL },
 
154
        { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
 
155
                &io_set_dmc, NULL, NULL },
 
156
        { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
 
157
                &io_set_dma, NULL, NULL },
 
158
        { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
 
159
                NULL, &io_show_chan, NULL },
 
160
        { 0 }  };
 
161
 
 
162
DEVICE mt_dev = {
 
163
        "MT", mt_unit, mt_reg, mt_mod,
 
164
        MT_NUMDR, 10, 31, 1, 8, 8,
 
165
        NULL, NULL, &mt_reset,
 
166
        NULL, &mt_attach, &mt_detach,
 
167
        &mt_dib, DEV_DISABLE };
 
168
 
 
169
/* IO routine */
 
170
 
 
171
int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev)
 
172
{
 
173
uint32 u = dev & 03;
 
174
UNIT *uptr = mt_dev.units + u;
 
175
static uint8 wrt_fnc[16] = {                            /* >0 = wr, 1 = chan op */
 
176
 0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
 
177
 
 
178
switch (inst) {                                         /* case on opcode */
 
179
case ioOCP:
 
180
        mt_updint (mt_rdy, 0);                          /* clear motion intr */
 
181
        mt_eof = 0;                                     /* clear eof */
 
182
        switch (fnc) {                                  /* case on function */
 
183
        case FNC_DMANM:                                 /* set DMA/DMC */
 
184
        case FNC_DMAAU:
 
185
            mt_usel = u;                                /* save unit select */
 
186
            if (mt_dib.chan) mt_dma = 1;                /* if configured */
 
187
            break;
 
188
        case FNC_IOBUS:                                 /* set IOBUS */
 
189
            mt_usel = u;                                /* save unit select */
 
190
            mt_dma = 0;
 
191
            break;
 
192
        case FNC_STOPW:                                 /* stop write */
 
193
            mt_usel = u;                                /* save unit select */
 
194
            mt_updint (0, mt_mdirq);                    /* clear ready */
 
195
            if (wrt_fnc[uptr->FNC & 017] == 1)          /* writing? */
 
196
                mt_eor = 1;                             /* set transfer done */
 
197
            break;          
 
198
        default:                                        /* motion command */
 
199
            if (mt_busy) return dat;                    /* nop if ctlr busy */
 
200
            mt_eor = 0;                                 /* clr transfer done */
 
201
            mt_err = 0;                                 /* clr error */
 
202
            mt_usel = u;                                /* save unit select */
 
203
            if (((uptr->flags & UNIT_ATT) == 0) ||      /* nop if not att */
 
204
                sim_is_active (uptr))                   /* or busy */
 
205
                (IORETURN (mt_stopioe, SCPE_UNATT) | dat);
 
206
            if (wrt_fnc[fnc] && (uptr->flags & UNIT_WPRT))
 
207
                return (STOP_MTWRP << IOT_V_REASON);
 
208
            uptr->FNC = fnc;
 
209
            uptr->UST = 0;
 
210
            mt_busy = 1;
 
211
            sim_activate (uptr, mt_ctime);              /* schedule */
 
212
            break;  }
 
213
        break;
 
214
case ioINA:                                             /* INA */
 
215
        if (fnc) return IOBADFNC (dat);                 /* fnc 0 only */
 
216
        if (mt_rdy) {                                   /* ready? */
 
217
            mt_rdy = 0;                                 /* clear ready */
 
218
            return IOSKIP (dat | mt_buf);  }            /* ret buf, skip */
 
219
        break;
 
220
case ioOTA:                                             /* OTA */
 
221
        if (fnc) return IOBADFNC (dat);                 /* fnc 0 only */
 
222
        if (mt_rdy) {                                   /* ready? */
 
223
            mt_rdy = 0;                                 /* clear ready */
 
224
            mt_buf = dat;                               /* store buf */
 
225
            return IOSKIP (dat);  }                     /* skip */
 
226
        break;
 
227
case ioSKS:
 
228
        uptr = mt_dev.units + mt_usel;                  /* use saved unit sel */
 
229
        switch (fnc) {
 
230
        case 000:                                       /* ready */
 
231
            if (mt_rdy) return IOSKIP (dat);
 
232
            break;
 
233
        case 001:                                       /* !busy */
 
234
            if (!mt_busy) return IOSKIP (dat);
 
235
            break;
 
236
        case 002:                                       /* !error */
 
237
            if (!mt_err) return IOSKIP (dat);
 
238
            break;
 
239
        case 003:                                       /* !BOT */
 
240
            if (!(uptr->UST & STA_BOT)) return IOSKIP (dat);
 
241
            break;
 
242
        case 004:                                       /* !interrupting */
 
243
            if (!TST_INTREQ (INT_MT)) return IOSKIP (dat);
 
244
            break;
 
245
        case 005:                                       /* !EOT */
 
246
            if (!(uptr->UST & STA_EOT)) return IOSKIP (dat);
 
247
            break;
 
248
        case 006:                                       /* !EOF */
 
249
            if (!mt_eof) return IOSKIP (dat);
 
250
            break;
 
251
        case 007:                                       /* !write prot */
 
252
            if (!(uptr->flags & UNIT_WPRT)) return IOSKIP (dat);
 
253
            break;
 
254
        case 011:                                       /* operational */
 
255
            if ((uptr->flags & UNIT_ATT) &&
 
256
                ((uptr->FNC & 017) != FNC_REW)) return IOSKIP (dat);
 
257
            break;
 
258
        case 012:                                       /* skip if !chan 2 */
 
259
            return IOSKIP (dat);
 
260
        case 013:                                       /* skip if !auto */
 
261
            return IOSKIP (dat);
 
262
        case 014:                                       /* !rewinding */
 
263
            uptr = mt_dev.units + (dev & 03);           /* use specified unit */
 
264
            if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat);
 
265
            break;  }
 
266
        break;
 
267
case ioEND:                                             /* end of range */
 
268
        mt_eor = 1;                                     /* transfer done */
 
269
        break;  }
 
270
return dat;
 
271
}
 
272
 
 
273
/* Unit service
 
274
 
 
275
   If rewind done, reposition to start of tape, set status
 
276
   else, do operation, set done, interrupt
 
277
 
 
278
   Can't be write locked, can only write lock detached unit
 
279
*/
 
280
 
 
281
t_stat mt_svc (UNIT *uptr)
 
282
{
 
283
int32 ch = mt_dib.chan - 1;                             /* DMA/DMC ch */
 
284
uint32 i, c1, c2, c3;
 
285
t_mtrlnt tbc;
 
286
t_stat st, r = SCPE_OK;
 
287
 
 
288
if ((uptr->flags & UNIT_ATT) == 0) {                    /* offline? */
 
289
        mt_err = 1;
 
290
        mt_busy = 0;
 
291
        mt_updint (0, 1);                               /* cmd done */
 
292
        return IORETURN (mt_stopioe, SCPE_UNATT);  }
 
293
 
 
294
switch (uptr->FNC) {                                    /* case on function */
 
295
case FNC_REW:                                           /* rewind (initial) */
 
296
        mt_busy = 0;                                    /* ctlr not busy */
 
297
        uptr->FNC = uptr->FNC | FNC_2ND;
 
298
        sim_activate (uptr, mt_ctime);
 
299
        return SCPE_OK;                                 /* continue */
 
300
 
 
301
case FNC_REW | FNC_2ND:                                 /* rewind done */
 
302
        uptr->pos = 0;                                  /* reposition file */
 
303
        uptr->UST = STA_BOT;                            /* set BOT */
 
304
        uptr->FNC = FNC_NOP;                            /* nop function */
 
305
        for (i = 0; i < MT_NUMDR; i++) {                /* last rewind? */
 
306
            if ((mt_unit[i].FNC & 017) == FNC_REW) return SCPE_OK;  }
 
307
        mt_updint (mt_rdy, 1);                          /* yes, motion done */
 
308
        return SCPE_OK;
 
309
 
 
310
case FNC_WEOF:                                          /* write file mark */
 
311
        if (st = sim_tape_wrtmk (uptr))                 /* write tmk, err? */
 
312
            r = mt_map_err (uptr, st);                  /* map error */
 
313
        break;                                          /* sched end motion */
 
314
 
 
315
case FNC_FSR:                                           /* space fwd rec */
 
316
        if (st = sim_tape_sprecf (uptr, &tbc))          /* space fwd, err? */
 
317
            r = mt_map_err (uptr, st);                  /* map error */
 
318
        break;                                          /* sched end motion */
 
319
 
 
320
case FNC_BSR:                                           /* space rev rec */
 
321
        if (st = sim_tape_sprecr (uptr, &tbc))          /* space rev, err? */
 
322
            r = mt_map_err (uptr, st);                  /* map error */
 
323
        break;                                          /* sched end motion */
 
324
 
 
325
case FNC_FSF:                                           /* space fwd file */
 
326
        while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
 
327
        r = mt_map_err (uptr, st);                      /* map error */
 
328
        break;                                          /* sched end motion */
 
329
 
 
330
case FNC_BSF:                                           /* space rev file */
 
331
        while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
 
332
        r = mt_map_err (uptr, st);                      /* map error */
 
333
        break;                                          /* sched end motion */
 
334
 
 
335
case FNC_EOM:                                           /* end of motion */
 
336
        uptr->FNC = FNC_NOP;                            /* nop function */
 
337
        mt_busy = 0;                                    /* not busy */
 
338
        mt_updint (mt_rdy, 1);                          /* end of motion */
 
339
        return SCPE_OK;                                 /* done! */
 
340
 
 
341
/* Unit service, continued */
 
342
 
 
343
case FNC_RBCD2: case FNC_RBIN2: case FNC_RBIN3:         /* read first */
 
344
        mt_ptr = 0;                                     /* clr buf ptr */
 
345
        st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE);     /* read rec */
 
346
        if (st != MTSE_OK) {                            /* error? */
 
347
            r = mt_map_err (uptr, st);                  /* map error */
 
348
            break;  }                                   /* sched end motion */
 
349
        uptr->FNC = uptr->FNC | FNC_2ND;                /* next state */
 
350
        sim_activate (uptr, mt_xtime);                  /* sched xfer */
 
351
        return SCPE_OK;
 
352
 
 
353
case FNC_RBCD2 | FNC_2ND:                               /* read, word */
 
354
case FNC_RBIN2 | FNC_2ND:
 
355
case FNC_RBIN3 | FNC_2ND:
 
356
        if (mt_ptr >= mt_max) break;                    /* record done? */
 
357
        c1 = mtxb[mt_ptr++] & 077;                      /* get 2 chars */
 
358
        c2 = mtxb[mt_ptr++] & 077;
 
359
        if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) {       /* BCD? */
 
360
            if (c1 == 012) c1 = 0;                      /* change 12 to 0 */
 
361
            if (c2 == 012) c2 = 0;  }
 
362
        if (uptr->FNC == (FNC_RBIN3 | FNC_2ND)) {       /* read 3? */
 
363
            if (mt_ptr >= mt_max) break;                /* lose wd if not enuf */
 
364
            c3 = mtxb[mt_ptr++] & 017;  }               /* get 3rd char */
 
365
        else c3 = 0;
 
366
        sim_activate (uptr, mt_xtime);                  /* no, sched word */
 
367
        if (mt_eor) return SCPE_OK;                     /* xfer done? */
 
368
        mt_buf = (c1 << 10) | (c2 << 4) | c3;           /* pack chars */
 
369
        if (mt_rdy) mt_err = 1;                         /* buf full? err */
 
370
        mt_updint (1, mt_mdirq);                        /* set ready */
 
371
        if (mt_dma) SET_CH_REQ (ch);                    /* DMC/DMA? req chan */
 
372
        return SCPE_OK;                                 /* continue */
 
373
        
 
374
case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3:         /* write first */
 
375
        mt_ptr = 0;                                     /* clear buf ptr */
 
376
        mt_updint (1, mt_mdirq);                        /* set ready */
 
377
        if (mt_dma) SET_CH_REQ (ch);                    /* DMC/DMA? req chan */
 
378
        uptr->FNC = uptr->FNC | FNC_2ND;                /* next state */
 
379
        sim_activate (uptr, mt_xtime);                  /* sched xfer */
 
380
        return SCPE_OK;                                 /* continue */
 
381
 
 
382
case FNC_WBCD2 | FNC_2ND:                               /* write, word */
 
383
case FNC_WBIN2 | FNC_2ND:
 
384
case FNC_WBIN3 | FNC_2ND:
 
385
        if (mt_eor || mt_rdy) {                 /* done or no data? */
 
386
            if (!mt_rdy) mt_wrwd (uptr, mt_buf);        /* write last word */
 
387
            if (mt_ptr) {                               /* any data? */
 
388
                if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr))  /* write, err? */
 
389
                    r = mt_map_err (uptr, st);  }       /* map error */
 
390
            break;  }                                   /* sched end motion */
 
391
        mt_wrwd (uptr, mt_buf);                         /* write word */
 
392
        sim_activate (uptr, mt_xtime);                  /* no, sched word */
 
393
        mt_updint (1, mt_mdirq);                        /* set ready */
 
394
        if (mt_dma) SET_CH_REQ (ch);                    /* DMC/DMA? req chan */
 
395
        return SCPE_OK;                                 /* continue */
 
396
 
 
397
default:                                                /* unknown */
 
398
        break;  }
 
399
 
 
400
/* End of command, process error or schedule end of motion */
 
401
 
 
402
if (r != SCPE_OK) {
 
403
        uptr->FNC = FNC_NOP;                            /* nop function */
 
404
        mt_busy = 0;                                    /* not busy */
 
405
        mt_updint (mt_rdy, 1);                          /* end of motion */
 
406
        return r;  }
 
407
uptr->FNC = FNC_EOM;                                    /* sched end motion */
 
408
sim_activate (uptr, mt_ctime);
 
409
return SCPE_OK;
 
410
}
 
411
 
 
412
/* Write word to buffer */
 
413
 
 
414
void mt_wrwd (UNIT *uptr, uint32 dat)
 
415
{
 
416
uint32 c1, c2;
 
417
 
 
418
c1 = (dat >> 10) & 077;                                 /* get 2 chars */
 
419
c2 = (dat >> 4) & 077;
 
420
if (uptr->FNC == (FNC_WBCD2 | FNC_2ND)) {               /* BCD? */
 
421
        if (c1 == 0) c1 = 012;                          /* change 0 to 12 */
 
422
        if (c2 == 0) c2 = 012;  }
 
423
if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c1;               /* store 2 char */
 
424
if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c2;
 
425
if ((uptr->FNC == (FNC_WBIN3 | FNC_2ND)) &&             /* write 3? */
 
426
        (mt_ptr < DBSIZE)) mtxb[mt_ptr++] = mt_buf & 017;
 
427
return;
 
428
}
 
429
 
 
430
/* Map tape error status */
 
431
 
 
432
t_stat mt_map_err (UNIT *uptr, t_stat st)
 
433
{
 
434
switch (st) {
 
435
case MTSE_FMT:                                          /* illegal fmt */
 
436
case MTSE_UNATT:                                        /* unattached */
 
437
        mt_err = 1;                                     /* reject */
 
438
case MTSE_OK:                                           /* no error */
 
439
        return SCPE_IERR;                               /* never get here! */
 
440
case MTSE_TMK:                                          /* end of file */
 
441
        mt_eof = 1;                                     /* eof */
 
442
        break;
 
443
case MTSE_INVRL:                                        /* invalid rec lnt */
 
444
        mt_err = 1;
 
445
        return SCPE_MTRLNT;
 
446
case MTSE_IOERR:                                        /* IO error */
 
447
        mt_err = 1;                                     /* error */
 
448
        if (mt_stopioe) return SCPE_IOERR;
 
449
        break;
 
450
case MTSE_RECE:                                         /* record in error */
 
451
case MTSE_EOM:                                          /* end of medium */
 
452
        mt_err = 1;                                     /* error */
 
453
        break;
 
454
case MTSE_BOT:                                          /* reverse into BOT */
 
455
        uptr->UST = STA_BOT;                            /* set status */
 
456
        break;
 
457
case MTSE_WRP:                                          /* write protect */
 
458
        mt_err = 1;                                     /* error */
 
459
        return STOP_MTWRP;  }
 
460
return SCPE_OK;
 
461
}
 
462
 
 
463
/* Update interrupts */
 
464
 
 
465
void mt_updint (uint32 rdy, uint32 mdirq)
 
466
{
 
467
mt_rdy = rdy;                                           /* store new ready */
 
468
mt_mdirq = mdirq;                                       /* store new motion irq */
 
469
if ((mt_rdy && !mt_dma) || mt_mdirq) SET_INT (INT_MT);  /* update int request */
 
470
else CLR_INT (INT_MT);
 
471
return;
 
472
}
 
473
 
 
474
/* Reset routine */
 
475
 
 
476
t_stat mt_reset (DEVICE *dptr)
 
477
{
 
478
int32 i;
 
479
UNIT *uptr;
 
480
 
 
481
mt_buf = 0;                                             /* clear state */
 
482
mt_usel = 0;
 
483
mt_mdirq = 0;
 
484
mt_eor = 0;
 
485
mt_busy = 0;
 
486
mt_rdy = 0;
 
487
mt_eof = 0;
 
488
mt_err = 0;
 
489
mt_dma = 0;
 
490
CLR_INT (INT_MT);                                       /* clear int, enb */
 
491
CLR_ENB (INT_MT);
 
492
for (i = 0; i < MT_NUMDR; i++) {                        /* loop thru units */
 
493
        uptr = mt_dev.units + i;
 
494
        sim_tape_reset (uptr);                          /* reset tape */
 
495
        sim_cancel (uptr);                              /* cancel op */
 
496
        uptr->UST = uptr->pos? 0: STA_BOT;              /* update status */
 
497
        uptr->FNC = FNC_NOP;  }
 
498
return SCPE_OK;
 
499
}
 
500
 
 
501
/* Attach routine */
 
502
 
 
503
t_stat mt_attach (UNIT *uptr, char *cptr)
 
504
{
 
505
t_stat r;
 
506
 
 
507
r = sim_tape_attach (uptr, cptr);                       /* attach unit */
 
508
if (r != SCPE_OK) return r;                             /* update status */
 
509
uptr->UST = STA_BOT;
 
510
return r;
 
511
}
 
512
 
 
513
/* Detach routine */
 
514
 
 
515
t_stat mt_detach (UNIT* uptr)
 
516
{
 
517
uptr->UST = 0;                                          /* update status */
 
518
uptr->FNC = FNC_NOP;                                    /* nop function */
 
519
return sim_tape_detach (uptr);                          /* detach unit */
 
520
}