mirror of
https://github.com/simh/simh.git
synced 2026-04-24 19:33:40 +00:00
S3: Restore original S3 code to branch
This commit is contained in:
committed by
Mark Pizzolato
parent
adf023bf86
commit
d29c6f43e3
792
S3/s3_disk.c
Normal file
792
S3/s3_disk.c
Normal file
@@ -0,0 +1,792 @@
|
||||
/* s3_disk.c: IBM 5444 Disk Drives
|
||||
|
||||
Copyright (c) 2001-2005, Charles E. Owen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
r1 Removeable disk 1
|
||||
f1 Fixed disk 1
|
||||
r2 Removeable disk 2
|
||||
f2 Fixed disk 2
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
08-Oct-02 RMS Added impossible function catcher
|
||||
*/
|
||||
|
||||
#include "s3_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
extern uint8 M[];
|
||||
extern int32 IAR[], level;
|
||||
extern FILE *trace;
|
||||
extern int32 debug_reg;
|
||||
char dbuf[DSK_SECTSIZE]; /* Disk buffer */
|
||||
int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data);
|
||||
int32 read_sector(UNIT *uptr, char *dbuf, int32 sect);
|
||||
int32 write_sector(UNIT *uptr, char *dbuf, int32 sect);
|
||||
t_stat r1_svc (UNIT *uptr);
|
||||
t_stat r1_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat r1_attach (UNIT *uptr, char *cptr);
|
||||
t_stat r1_reset (DEVICE *dptr);
|
||||
t_stat f1_svc (UNIT *uptr);
|
||||
t_stat f1_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat f1_attach (UNIT *uptr, char *cptr);
|
||||
t_stat f1_reset (DEVICE *dptr);
|
||||
t_stat r2_svc (UNIT *uptr);
|
||||
t_stat r2_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat r2_attach (UNIT *uptr, char *cptr);
|
||||
t_stat r2_reset (DEVICE *dptr);
|
||||
t_stat f2_svc (UNIT *uptr);
|
||||
t_stat f2_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat f2_attach (UNIT *uptr, char *cptr);
|
||||
t_stat f2_reset (DEVICE *dptr);
|
||||
extern int32 GetMem(int32 addr);
|
||||
extern int32 PutMem(int32 addr, int32 data);
|
||||
|
||||
char opstr[5][5] = { "SIO", "LIO", "TIO", "SNS", "APL" };
|
||||
|
||||
int32 DDAR[2]; /* Data address register */
|
||||
int32 DCAR[2]; /* Disk Control Address Register */
|
||||
int32 diskerr[2] = { 0, 0 }; /* Error status */
|
||||
int32 notrdy[2] = { 0, 0 }; /* Not ready error */
|
||||
int32 seekbusy[2] = { 0, 0 }; /* Drive busy flags */
|
||||
int32 seekhead[2] = { 0, 0 }; /* Disk head 0,1 */
|
||||
int32 found[2] = { 0, 0 }; /* Scan found bit */
|
||||
int32 RIDsect[2] = { 0, 0 }; /* for Read ID */
|
||||
|
||||
/* Disk data structures
|
||||
|
||||
xy_dev CDR descriptor
|
||||
xy_unit CDR unit descriptor
|
||||
xy_reg CDR register list
|
||||
|
||||
x = F or R
|
||||
y = 1 or 2
|
||||
*/
|
||||
|
||||
UNIT r1_unit = { UDATA (&r1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG r1_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[0], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[0], 0) },
|
||||
{ HRDATA (DAR, DDAR[0], 16) },
|
||||
{ HRDATA (CAR, DCAR[0], 16) },
|
||||
{ HRDATA (ERR, diskerr[0], 16) },
|
||||
{ DRDATA (CYL, r1_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[0], 8) },
|
||||
{ DRDATA (POS, r1_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, r1_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE r1_dev = {
|
||||
"R1", &r1_unit, r1_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &r1_reset,
|
||||
&r1_boot, &r1_attach, NULL
|
||||
};
|
||||
|
||||
UNIT f1_unit = { UDATA (&f1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG f1_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[0], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[0], 0) },
|
||||
{ HRDATA (DAR, DDAR[0], 16) },
|
||||
{ HRDATA (CAR, DCAR[0], 16) },
|
||||
{ HRDATA (ERR, diskerr[0], 16) },
|
||||
{ DRDATA (CYL, f1_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[0], 8) },
|
||||
{ DRDATA (POS, f1_unit.pos, 32), PV_LEFT },
|
||||
{ DRDATA (TIME, f1_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE f1_dev = {
|
||||
"F1", &f1_unit, f1_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &f1_reset,
|
||||
&f1_boot, &f1_attach, NULL
|
||||
};
|
||||
|
||||
UNIT r2_unit = { UDATA (&r2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG r2_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[1], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[1], 0) },
|
||||
{ HRDATA (DAR, DDAR[1], 16) },
|
||||
{ HRDATA (CAR, DCAR[1], 16) },
|
||||
{ HRDATA (ERR, diskerr[1], 16) },
|
||||
{ DRDATA (CYL, r2_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[1], 8) },
|
||||
{ DRDATA (POS, r2_unit.pos, 32), PV_LEFT },
|
||||
{ DRDATA (TIME, r2_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE r2_dev = {
|
||||
"R2", &r2_unit, r2_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &r2_reset,
|
||||
&r2_boot, &r2_attach, NULL
|
||||
};
|
||||
|
||||
UNIT f2_unit = { UDATA (&f2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 };
|
||||
|
||||
REG f2_reg[] = {
|
||||
{ FLDATA (NOTRDY, notrdy[1], 0) },
|
||||
{ FLDATA (SEEK, seekbusy[1], 0) },
|
||||
{ HRDATA (DAR, DDAR[1], 16) },
|
||||
{ HRDATA (CAR, DCAR[1], 16) },
|
||||
{ HRDATA (ERR, diskerr[1], 16) },
|
||||
{ DRDATA (CYL, f2_unit.u3, 8) },
|
||||
{ DRDATA (HEAD, seekhead[1], 8) },
|
||||
{ DRDATA (POS, f2_unit.pos, 32), PV_LEFT },
|
||||
{ DRDATA (TIME, f2_unit.wait, 24), PV_LEFT },
|
||||
{ BRDATA (BUF, dbuf, 8, 8, 256) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE f2_dev = {
|
||||
"F2", &f2_unit, f2_reg, NULL,
|
||||
1, 10, 31, 1, 8, 7,
|
||||
NULL, NULL, &f2_reset,
|
||||
&f2_boot, &f2_attach, NULL
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* 5444: master routines */
|
||||
|
||||
int32 dsk1 (int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
r = dsk(0, op, m, n, data);
|
||||
return (r);
|
||||
}
|
||||
|
||||
int32 dsk2 (int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
r = dsk(1, op, m, n, data);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/* 5444: operational routine */
|
||||
|
||||
int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data)
|
||||
{
|
||||
int32 iodata, i, j, u, sect, nsects, addr, r, c, res;
|
||||
int32 F, C, S, N, usave;
|
||||
UNIT *uptr;
|
||||
|
||||
u = m;
|
||||
if (disk == 1) u += 2;
|
||||
F = GetMem(DCAR[disk]+0); /* Flag bits */
|
||||
C = GetMem(DCAR[disk]+1); /* Cylinder */
|
||||
S = GetMem(DCAR[disk]+2); /* Sector */
|
||||
N = GetMem(DCAR[disk]+3); /* Number of sectors */
|
||||
switch (u) {
|
||||
case 0:
|
||||
uptr = r1_dev.units;
|
||||
break;
|
||||
case 1:
|
||||
uptr = f1_dev.units;
|
||||
break;
|
||||
case 2:
|
||||
uptr = r2_dev.units;
|
||||
break;
|
||||
case 3:
|
||||
uptr = f2_dev.units;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (debug_reg & 0x02)
|
||||
fprintf(trace, "==> %04X %s %01X,%d,%04X DAR=%04X CAR=%04X C=%02X, S=%02X, N=%02X\n",
|
||||
IAR[level],
|
||||
opstr[op],
|
||||
m, n, data,
|
||||
DDAR[disk],
|
||||
DCAR[disk],
|
||||
C, S, N);
|
||||
|
||||
switch (op) {
|
||||
|
||||
/* SIO 5444 */
|
||||
case 0:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT;
|
||||
diskerr[disk] = 0; /* SIO resets errors */
|
||||
found[disk] = 0; /* ... and found bit */
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Seek */
|
||||
if (S & 0x80)
|
||||
seekhead[disk] = 1;
|
||||
else
|
||||
seekhead[disk] = 0;
|
||||
if (S & 1) {
|
||||
uptr -> u3 += N;
|
||||
} else {
|
||||
uptr -> u3 -= N;
|
||||
}
|
||||
if (uptr -> u3 < 0)
|
||||
uptr -> u3 = 0;
|
||||
if (uptr -> u3 > 203) {
|
||||
uptr -> u3 = 0;
|
||||
diskerr[disk] |= 0x0100;
|
||||
if (debug_reg & 0x02)
|
||||
fprintf(trace, "==> Seek Past End of Disk\n");
|
||||
}
|
||||
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
|
||||
/* Seek arms are the same for both disks on a drive:
|
||||
update the other arm */
|
||||
|
||||
usave = uptr -> u3;
|
||||
if (u == 0) uptr = f1_dev.units;
|
||||
if (u == 1) uptr = r1_dev.units;
|
||||
if (u == 2) uptr = f2_dev.units;
|
||||
if (u == 3) uptr = r2_dev.units;
|
||||
uptr -> u3 = usave;
|
||||
|
||||
seekbusy[disk] = 1;
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
|
||||
case 0x01: /* Read */
|
||||
switch (data) {
|
||||
case 0: /* Read data */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
|
||||
for (i = 0; i < nsects; i++) {
|
||||
r = read_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0800;
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
PutMem(addr, dbuf[j]);
|
||||
addr++;
|
||||
}
|
||||
|
||||
if (sect == 55) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF; /* HJS mod */
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF; /* HJS mod */
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
case 1: /* Read ID */
|
||||
if (uptr -> u3 > 0 && uptr -> u3 < 4)
|
||||
PutMem(DCAR[disk], 1);
|
||||
else
|
||||
PutMem(DCAR[disk], 0);
|
||||
PutMem(DCAR[disk]+1, uptr -> u3);
|
||||
PutMem(DCAR[disk]+2, RIDsect[disk]);
|
||||
RIDsect[disk]++;
|
||||
if (RIDsect[disk] > 23)
|
||||
RIDsect[disk] = 32;
|
||||
if (RIDsect[disk] > 55)
|
||||
RIDsect[disk] = 0;
|
||||
break;
|
||||
case 2: /* Read Diagnostic */
|
||||
iodata = STOP_INVDEV;
|
||||
break;
|
||||
case 3: /* Verify */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
r = read_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0800;
|
||||
break;
|
||||
}
|
||||
if (sect == 55) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
break;
|
||||
case 0x02: /* Write */
|
||||
switch (data) {
|
||||
case 0: /* Write Data */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
dbuf[j] = GetMem(addr);
|
||||
addr++;
|
||||
}
|
||||
r = write_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0400;
|
||||
break;
|
||||
}
|
||||
if (sect == 55) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF; /* HJS mod */
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
case 1: /* Write identifier */
|
||||
if (seekhead[disk] == 0)
|
||||
S = 0;
|
||||
else
|
||||
S = 0x80;
|
||||
N = 23;
|
||||
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
dbuf[j] = GetMem(addr);
|
||||
}
|
||||
r = write_sector(uptr, dbuf, sect);
|
||||
if (r != 1) {
|
||||
diskerr[disk] |= 0x0400;
|
||||
break;
|
||||
}
|
||||
if (sect == 55) {
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > 0) diskerr[disk] |= 0x0020;
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
break;
|
||||
case 0x03: /* Scan */
|
||||
sect = (S >> 2) & 0x3F;
|
||||
nsects = N + 1;
|
||||
addr = DDAR[disk];
|
||||
for (i = 0; i < nsects; i++) {
|
||||
r = read_sector(uptr, dbuf, sect);
|
||||
if (r != 1 || uptr->u3 != C) {
|
||||
diskerr[disk] |= 0x0800;
|
||||
break;
|
||||
}
|
||||
res = 0;
|
||||
for (j = 0; j < DSK_SECTSIZE; j++) {
|
||||
c = GetMem(addr);
|
||||
if (j != 0xff) {
|
||||
if (dbuf[i] < c)
|
||||
res = 1;
|
||||
if (dbuf[i] > c)
|
||||
res = 3;
|
||||
}
|
||||
addr++;
|
||||
}
|
||||
if (res == 0)
|
||||
found[disk] = 1;
|
||||
if (res == data)
|
||||
break;
|
||||
if (sect == 55) { /* HJS MODS */
|
||||
S = sect;
|
||||
N = nsects - i - 2;
|
||||
if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */
|
||||
DDAR[disk] = addr & 0xFFFF;
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
sim_activate(uptr, 1);
|
||||
iodata = SCPE_OK;
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
S = sect - 1;
|
||||
N = nsects - i - 2;
|
||||
if (sect == 24)
|
||||
sect = 32;
|
||||
}
|
||||
PutMem(DCAR[disk]+2, S << 2);
|
||||
PutMem(DCAR[disk]+3, N);
|
||||
/*sim_activate(uptr, uptr -> wait);*/
|
||||
sim_activate(uptr, 1);
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return iodata;
|
||||
|
||||
/* LIO 5444 */
|
||||
case 1:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT;
|
||||
switch (n) {
|
||||
case 0x04: /* Data Addr */
|
||||
DDAR[disk] = data;
|
||||
break;
|
||||
case 0x06: /* Control Addr */
|
||||
DCAR[disk] = data;
|
||||
break;
|
||||
default:
|
||||
return STOP_INVDEV;
|
||||
}
|
||||
return SCPE_OK;
|
||||
/* TIO 5444 */
|
||||
case 2:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT << 16;
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Error */
|
||||
if (diskerr[disk] || notrdy[disk])
|
||||
iodata = 1;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0)
|
||||
iodata = 1;
|
||||
break;
|
||||
case 0x02: /* Busy */
|
||||
if (sim_is_active (uptr))
|
||||
iodata = 1;
|
||||
break;
|
||||
case 0x04:
|
||||
if (found[disk])
|
||||
iodata = 1;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
|
||||
/* SNS 5444 */
|
||||
case 3:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT << 16;
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x01:
|
||||
break;
|
||||
case 0x02:
|
||||
iodata = diskerr[disk];
|
||||
if (notrdy[disk])
|
||||
iodata |= 0x4000;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0)
|
||||
iodata |= 0x4000;
|
||||
if (seekbusy[disk])
|
||||
iodata |= 0x0010;
|
||||
if (uptr -> u3 == 0)
|
||||
iodata |= 0x0040;
|
||||
break;
|
||||
case 0x03:
|
||||
iodata = 0;
|
||||
break;
|
||||
case 0x04:
|
||||
iodata = DDAR[disk];
|
||||
break;
|
||||
case 0x06:
|
||||
iodata = DCAR[disk];
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
iodata |= ((SCPE_OK << 16) & 0xffff0000);
|
||||
return (iodata);
|
||||
|
||||
/* APL 5444 */
|
||||
case 4:
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT << 16;
|
||||
iodata = 0;
|
||||
switch (n) {
|
||||
case 0x00: /* Error */
|
||||
if (diskerr[disk] || notrdy[disk])
|
||||
iodata = 1;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0)
|
||||
iodata = 1;
|
||||
break;
|
||||
case 0x02: /* Busy */
|
||||
if (sim_is_active (uptr))
|
||||
iodata = 1;
|
||||
break;
|
||||
default:
|
||||
return (STOP_INVDEV << 16);
|
||||
}
|
||||
return ((SCPE_OK << 16) | iodata);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sim_printf (">>DSK%d non-existent function %d\n", disk, op);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Disk unit service. If a stacker select is active, copy to the
|
||||
selected stacker. Otherwise, copy to the normal stacker. If the
|
||||
unit is unattached, simply exit.
|
||||
*/
|
||||
|
||||
t_stat r1_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[0] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f1_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[0] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat r2_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[1] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f2_svc (UNIT *uptr)
|
||||
{
|
||||
seekbusy[1] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Disk reset */
|
||||
|
||||
t_stat r1_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */
|
||||
found[0] = 0;
|
||||
sim_cancel (&r1_unit); /* clear event */
|
||||
r1_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f1_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */
|
||||
found[0] = 0;
|
||||
sim_cancel (&f1_unit); /* clear event */
|
||||
f1_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat r2_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */
|
||||
found[1] = 0;
|
||||
sim_cancel (&r2_unit); /* clear event */
|
||||
r2_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f2_reset (DEVICE *dptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */
|
||||
found[1] = 0;
|
||||
sim_cancel (&f2_unit); /* clear event */
|
||||
f2_unit.u3 = 0; /* cylinder 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Disk unit attach */
|
||||
|
||||
t_stat r1_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */
|
||||
found[0] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
t_stat f1_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */
|
||||
found[0] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
t_stat r2_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */
|
||||
found[1] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
t_stat f2_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */
|
||||
found[1] = 0;
|
||||
uptr -> u3 = 0; /* cylinder 0 */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
t_stat r1_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
r1_unit.u3 = 0;
|
||||
read_sector(r1_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f1_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
f1_unit.u3 = 0;
|
||||
read_sector(f1_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat r2_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
r2_unit.u3 = 0;
|
||||
read_sector(r2_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat f2_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
f2_unit.u3 = 0;
|
||||
read_sector(f2_dev.units, dbuf, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
M[i] = dbuf[i];
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Raw Disk Data In/Out */
|
||||
|
||||
int32 read_sector(UNIT *uptr, char *dbuf, int32 sect)
|
||||
{
|
||||
static int32 rtn, realsect;
|
||||
static long pos;
|
||||
|
||||
/* calculate real sector no */
|
||||
if (sect > 23)
|
||||
realsect = sect - 8;
|
||||
else
|
||||
realsect = sect;
|
||||
/* physically read the sector */
|
||||
pos = DSK_CYLSIZE * uptr -> u3;
|
||||
pos += DSK_SECTSIZE * realsect;
|
||||
rtn = fseek(uptr -> fileref, pos, 0);
|
||||
rtn = fread(dbuf, DSK_SECTSIZE, 1, uptr -> fileref);
|
||||
return (rtn);
|
||||
}
|
||||
|
||||
int32 write_sector(UNIT *uptr, char *dbuf, int32 sect)
|
||||
{
|
||||
static int32 rtn, realsect;
|
||||
static long pos;
|
||||
|
||||
/* calculate real sector no */
|
||||
if (sect > 23)
|
||||
realsect = sect - 8;
|
||||
else
|
||||
realsect = sect;
|
||||
if (uptr -> u3 == 0 && realsect == 32)
|
||||
rtn = 0;
|
||||
/* physically write the sector */
|
||||
pos = DSK_CYLSIZE * uptr -> u3;
|
||||
pos += DSK_SECTSIZE * realsect;
|
||||
rtn = fseek(uptr -> fileref, pos, 0);
|
||||
rtn = fwrite(dbuf, DSK_SECTSIZE, 1, uptr -> fileref);
|
||||
return (rtn);
|
||||
}
|
||||
Reference in New Issue
Block a user