mirror of
https://github.com/rcornwell/sims.git
synced 2026-02-26 00:34:10 +00:00
IBM360: Many patches. DASD now appears to work.
This commit is contained in:
@@ -1,18 +1,21 @@
|
||||
Current status:
|
||||
|
||||
Operating Systems:
|
||||
TOS/360: Will IPL, and read IPL deck. Will not run any test jobs.
|
||||
TOS/360: Will IPL, and read IPL deck. Will run some jobs.
|
||||
|
||||
DOS/360: Will IPL disk init job.
|
||||
DOS/360: Will initialize disk.
|
||||
Will not restore disk.
|
||||
Will run 2314 distribution.
|
||||
|
||||
OS/360: Will IPL disk init job.
|
||||
OS/360: Will initialize disk.
|
||||
Will not restore disk.
|
||||
Will start to IPL OS/360
|
||||
|
||||
ibm360_cpu.c:
|
||||
Need to complete floating point and decimal instructions.
|
||||
|
||||
ibm360_chan.c
|
||||
Need to move fprintf's to sim_debug functions.
|
||||
Add number of Channels and subchannels as option.
|
||||
More debugging required.
|
||||
|
||||
ibm360_cdp.c:
|
||||
Add support for binary mode.
|
||||
@@ -27,13 +30,13 @@ ibm360_con.c:
|
||||
Appears to be working.
|
||||
|
||||
ibm360_dasd.c:
|
||||
Need to complete.
|
||||
Possibly working.
|
||||
|
||||
ibm360_lpr.c:
|
||||
Need to add in support for line skip and skip control.
|
||||
|
||||
ibm360_mt.c:
|
||||
Appears to be working.
|
||||
Possibly working.
|
||||
|
||||
ibm360_sys.c:
|
||||
Need to add in deposit function.
|
||||
|
||||
@@ -77,9 +77,9 @@
|
||||
#define PMASK 0xf0000000 /* Storage protection mask */
|
||||
extern uint32 *M;
|
||||
extern uint8 key[MAXMEMSIZE / 2048];
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
#define MAX_DEV (MAX_CHAN * 256)
|
||||
int channels = MAX_CHAN;
|
||||
int subchannels = SUB_CHANS; /* Number of subchannels */
|
||||
int irq_pend = 0;
|
||||
uint32 caw[256]; /* Channel command address word */
|
||||
@@ -132,7 +132,7 @@ find_subchan(uint16 device) {
|
||||
return -1;
|
||||
if (device > 0xff) {
|
||||
chan = (device >> 8) & 0x7;
|
||||
if (chan > MAX_CHAN)
|
||||
if (chan > channels)
|
||||
return -1;
|
||||
return subchannels + chan;
|
||||
}
|
||||
@@ -178,24 +178,15 @@ int writefull(int chan, uint32 addr, uint32 *word) {
|
||||
chan_status[chan] |= STATUS_PROT;
|
||||
return 1;
|
||||
}
|
||||
k = key[(addr & 0xfffc00) >> 10];
|
||||
k = key[(addr & 0xfffc00) >> 10];
|
||||
if ((k & 0x8) != 0 && (k & 0xf0) != sk) {
|
||||
chan_status[chan] |= STATUS_PROT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Channel write %02x %06x %08x %08x '", chan, addr, *word, ccw_count[chan]);
|
||||
addr &= AMASK;
|
||||
addr >>= 2;
|
||||
M[addr] = *word;
|
||||
for(k = 24; k >= 0; k -= 8) {
|
||||
char ch = ebcdic_to_ascii[(*word >> k) & 0xFF];
|
||||
if (ch < 0x20 || ch == 0xff)
|
||||
ch = '.';
|
||||
fprintf(stderr, "%c", ch);
|
||||
}
|
||||
|
||||
fprintf(stderr, "'\n\r");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -206,18 +197,25 @@ load_ccw(uint16 chan, int tic_ok) {
|
||||
UNIT *uptr;
|
||||
|
||||
loop:
|
||||
/* Abort if channel not on double boundry */
|
||||
if ((caw[chan] & 0x7) != 0) {
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
return 1;
|
||||
}
|
||||
/* Abort if we have any errors */
|
||||
if (chan_status[chan] & 0x7f)
|
||||
return 1;
|
||||
/* Check if we have status modifier set */
|
||||
if (chan_status[chan] & STATUS_MOD) {
|
||||
caw[chan]+=8;
|
||||
caw[chan] &= PMASK|AMASK; /* Mask overflow bits */
|
||||
chan_status[chan] &= ~STATUS_MOD;
|
||||
}
|
||||
/* Read in next CCW */
|
||||
readfull(chan, caw[chan], &word);
|
||||
fprintf(stderr, "Channel read ccw %02x %06x %08x\n\r", chan, caw[chan], word);
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw %02x %06x %08x\n",
|
||||
chan, caw[chan], word);
|
||||
/* TIC can't follow TIC nor be first in chain */
|
||||
if (((word >> 24) & 0xf) == CMD_TIC) {
|
||||
if (tic_ok) {
|
||||
caw[chan] = (caw[chan] & PMASK) | (word & AMASK);
|
||||
@@ -230,15 +228,17 @@ fprintf(stderr, "Channel read ccw %02x %06x %08x\n\r", chan, caw[chan], word);
|
||||
}
|
||||
caw[chan] += 4;
|
||||
caw[chan] &= PMASK|AMASK; /* Mask overflow bits */
|
||||
/* Check if fetch ok */
|
||||
/* Check if not chaining data */
|
||||
if ((ccw_flags[chan] & FLAG_CD) == 0) {
|
||||
ccw_cmd[chan] = (word >> 24) & 0xff;
|
||||
cmd = 1;
|
||||
}
|
||||
/* Set up for this command */
|
||||
ccw_addr[chan] = word & AMASK;
|
||||
ccw_addr[chan] |= caw[chan] & PMASK; /* Copy key */
|
||||
readfull(chan, caw[chan], &word);
|
||||
fprintf(stderr, "Channel read ccw2 %02x %06x %08x\n\r", chan, caw[chan], word);
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw2 %02x %06x %08x\n",
|
||||
chan, caw[chan], word);
|
||||
caw[chan]+=4;
|
||||
caw[chan] &= PMASK|AMASK; /* Mask overflow bits */
|
||||
ccw_count[chan] = word & 0xffff;
|
||||
@@ -292,26 +292,41 @@ chan_read_byte(uint16 addr, uint8 *data) {
|
||||
int byte;
|
||||
int k;
|
||||
|
||||
/* Abort if we have any errors */
|
||||
if (chan_status[chan] & 0x7f)
|
||||
return 1;
|
||||
if ((ccw_cmd[chan] & 0x1) == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (chan_byte[chan] == BUFF_CHNEND)
|
||||
return 1;
|
||||
if (ccw_count[chan] == 0) {
|
||||
if ((ccw_flags[chan] & FLAG_CD) == 0) {
|
||||
chan_status[chan] |= STATUS_CEND;
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_read_end\n");
|
||||
return 1;
|
||||
} else {
|
||||
if (load_ccw(chan, 1))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (chan_byte[chan] == BUFF_EMPTY) {
|
||||
if (readfull(chan, ccw_addr[chan], &chan_buf[chan])) {
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "Channel read %02x %06x %08x %08x '", chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]);
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "Channel write %02x %06x %08x %08x '",
|
||||
chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]);
|
||||
for(k = 24; k >= 0; k -= 8) {
|
||||
char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF];
|
||||
if (ch < 0x20 || ch == 0xff)
|
||||
ch = '.';
|
||||
fprintf(stderr, "%c", ch);
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch);
|
||||
}
|
||||
|
||||
fprintf(stderr, "'\n\r");
|
||||
sim_debug(DEBUG_DATA, & cpu_dev, "'\n");
|
||||
chan_byte[chan] = ccw_addr[chan] & 0x3;
|
||||
ccw_addr[chan] += 4 - chan_byte[chan];
|
||||
}
|
||||
@@ -319,16 +334,6 @@ fprintf(stderr, "Channel read %02x %06x %08x %08x '", chan, ccw_addr[chan], chan
|
||||
byte = (chan_buf[chan] >> (8 * (3 - (chan_byte[chan] & 0x3)))) & 0xff;
|
||||
chan_byte[chan]++;
|
||||
*data = byte;
|
||||
if (ccw_count[chan] == 0) {
|
||||
if (ccw_flags[chan] & FLAG_CD)
|
||||
return load_ccw(chan, 1);
|
||||
else {
|
||||
chan_status[chan] |= STATUS_CEND;
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
}
|
||||
fprintf(stderr, "chan_read_end\n\r");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -338,11 +343,34 @@ chan_write_byte(uint16 addr, uint8 *data) {
|
||||
int chan = find_subchan(addr);
|
||||
int byte;
|
||||
int offset;
|
||||
int k;
|
||||
uint32 mask;
|
||||
|
||||
/* Abort if we have any errors */
|
||||
if (chan_status[chan] & 0x7f)
|
||||
return 1;
|
||||
if ((ccw_cmd[chan] & 0x1) != 0) {
|
||||
return 1;
|
||||
}
|
||||
if (ccw_count[chan] == 0) {
|
||||
if (chan_byte[chan] != BUFF_CHNEND) {
|
||||
if (writefull(chan, ccw_addr[chan], &chan_buf[chan])) {
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((ccw_flags[chan] & FLAG_CD) == 0) {
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
if ((ccw_flags[chan] & FLAG_SLI) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_ length\n");
|
||||
chan_status[chan] |= STATUS_LENGTH;
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_end\n");
|
||||
return 1;
|
||||
}
|
||||
if (load_ccw(chan, 1))
|
||||
return 1;
|
||||
}
|
||||
if (chan_byte[chan] == BUFF_CHNEND) {
|
||||
if ((ccw_flags[chan] & FLAG_SLI) == 0) {
|
||||
chan_status[chan] |= STATUS_LENGTH;
|
||||
@@ -355,13 +383,13 @@ chan_write_byte(uint16 addr, uint8 *data) {
|
||||
ccw_addr[chan]--;
|
||||
else
|
||||
ccw_addr[chan]++;
|
||||
if (ccw_count[chan] == 0) {
|
||||
if (ccw_flags[chan] & FLAG_CD)
|
||||
return load_ccw(chan, 1);
|
||||
else
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
return 1;
|
||||
}
|
||||
// if (ccw_count[chan] == 0) {
|
||||
// if (ccw_flags[chan] & FLAG_CD)
|
||||
// return load_ccw(chan, 1);
|
||||
// else
|
||||
// chan_byte[chan] = BUFF_CHNEND;
|
||||
// return 1;
|
||||
// }
|
||||
return 0;
|
||||
}
|
||||
if (chan_byte[chan] == (BUFF_EMPTY|BUFF_DIRTY)) {
|
||||
@@ -370,6 +398,15 @@ chan_write_byte(uint16 addr, uint8 *data) {
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "Channel read %02x %06x %08x %08x '",
|
||||
chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]);
|
||||
for(k = 24; k >= 0; k -= 8) {
|
||||
char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF];
|
||||
if (ch < 0x20 || ch == 0xff)
|
||||
ch = '.';
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch);
|
||||
}
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "'\n");
|
||||
if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD)
|
||||
ccw_addr[chan] -= 1 + (ccw_addr[chan] & 0x3);
|
||||
else
|
||||
@@ -397,17 +434,6 @@ chan_write_byte(uint16 addr, uint8 *data) {
|
||||
} else
|
||||
chan_byte[chan]++;
|
||||
chan_byte[chan] |= BUFF_DIRTY;
|
||||
if (ccw_count[chan] == 0) {
|
||||
if (writefull(chan, ccw_addr[chan], &chan_buf[chan])) {
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
return 1;
|
||||
}
|
||||
if (ccw_flags[chan] & FLAG_CD)
|
||||
return load_ccw(chan, 1);
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
fprintf(stderr, "chan_write_end\n\r");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -420,7 +446,8 @@ set_devattn(uint16 addr, uint8 flags) {
|
||||
chan_status[chan] |= ((uint16)flags) << 8;
|
||||
} else
|
||||
dev_status[addr] = flags;
|
||||
fprintf(stderr, "set_devattn(%x, %x) %x\n\r", addr, flags, chan_dev[chan]);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn(%x, %x) %x\n",
|
||||
addr, flags, chan_dev[chan]);
|
||||
irq_pend = 1;
|
||||
}
|
||||
|
||||
@@ -428,15 +455,26 @@ void
|
||||
chan_end(uint16 addr, uint8 flags) {
|
||||
int chan = find_subchan(addr);
|
||||
|
||||
fprintf(stderr, "chan_end(%x, %x)\n\r", addr, flags);
|
||||
if (chan_byte[chan] & BUFF_DIRTY) {
|
||||
int k;
|
||||
writefull(chan, ccw_addr[chan], &chan_buf[chan]);
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "Channel read %02x %06x %08x %08x '",
|
||||
chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]);
|
||||
for(k = 24; k >= 0; k -= 8) {
|
||||
char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF];
|
||||
if (ch < 0x20 || ch == 0xff)
|
||||
ch = '.';
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch);
|
||||
}
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "'\n");
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x, %x) %x\n", addr, flags, ccw_count[chan]);
|
||||
chan_status[chan] |= STATUS_CEND;
|
||||
chan_status[chan] |= ((uint16)flags) << 8;
|
||||
ccw_cmd[chan] = 0;
|
||||
if (ccw_count[chan] != 0 && (ccw_flags[chan] & FLAG_SLI) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end length\n");
|
||||
chan_status[chan] |= STATUS_LENGTH;
|
||||
ccw_flags[chan] = 0;
|
||||
}
|
||||
@@ -455,7 +493,10 @@ int
|
||||
store_csw(uint16 chan) {
|
||||
M[0x40 >> 2] = caw[chan];
|
||||
M[0x44 >> 2] = (((uint32)ccw_count[chan])) | ((uint32)chan_status[chan]<<16);
|
||||
fprintf(stderr, "Channel store csw %02x %06x %08x\n\r", chan, M[0x40>>2], M[0x44 >> 2]);
|
||||
chan_status[chan] = 0;
|
||||
chan_dev[chan] = 0;
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %06x %08x\n",
|
||||
chan, M[0x40>>2], M[0x44 >> 2]);
|
||||
return chan_dev[chan];
|
||||
}
|
||||
|
||||
@@ -466,12 +507,15 @@ int startio(uint16 addr) {
|
||||
UNIT *uptr;
|
||||
uint8 status;
|
||||
|
||||
fprintf(stderr, "SIO %x %x %x %x\n\r", addr, chan, ccw_cmd[chan], ccw_flags[chan]);
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x %x %x\n", addr, chan,
|
||||
ccw_cmd[chan], ccw_flags[chan]);
|
||||
if (chan < 0 || dibp == 0)
|
||||
return 3;
|
||||
uptr = find_chan_dev(addr);
|
||||
if (uptr == 0)
|
||||
return 3;
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return 3;
|
||||
if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0)
|
||||
return 2;
|
||||
chan_status[chan] = 0;
|
||||
@@ -482,18 +526,31 @@ fprintf(stderr, "SIO %x %x %x %x\n\r", addr, chan, ccw_cmd[chan], ccw_flags[chan
|
||||
chan_status[chan] = dibp->start_io(uptr, chan) << 8;
|
||||
if (chan_status[chan] != 0) {
|
||||
M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | M[0x44 >> 2] & 0xffff;
|
||||
fprintf(stderr, "Channel store csw %02x %08x\n\r", chan, M[0x44 >> 2]);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n",
|
||||
chan, M[0x44 >> 2]);
|
||||
chan_status[chan] = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (load_ccw(chan, 0) || (chan_status[chan] & (STATUS_PCI))) {
|
||||
M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | M[0x44 >> 2] & 0xffff;
|
||||
fprintf(stderr, "Channel store csw %02x %08x\n\r", chan, M[0x44 >> 2]);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n",
|
||||
chan, M[0x44 >> 2]);
|
||||
chan_status[chan] &= ~STATUS_PCI;
|
||||
dev_status[addr] = 0;
|
||||
return 1;
|
||||
}
|
||||
if (chan_status[chan] & STATUS_BUSY) {
|
||||
M[0x40 >> 2] = 0;
|
||||
M[0x44 >> 2] = ((uint32)chan_status[chan]<<16);// | M[0x44 >> 2] & 0xffff;
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n",
|
||||
chan, M[0x44 >> 2]);
|
||||
chan_status[chan] = 0;
|
||||
dev_status[addr] = 0;
|
||||
chan_dev[chan] = 0;
|
||||
ccw_cmd[chan] = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -508,23 +565,23 @@ int testio(uint16 addr) {
|
||||
uptr = find_chan_dev(addr);
|
||||
if (uptr == 0)
|
||||
return 3;
|
||||
if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0)
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return 3;
|
||||
if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0)
|
||||
return 2;
|
||||
if (chan_dev[chan] != addr)
|
||||
if (chan_dev[chan] != 0 && chan_dev[chan] != addr)
|
||||
return 2;
|
||||
if (ccw_cmd[chan] == 0 && chan_status[chan] != 0) {
|
||||
store_csw(chan);
|
||||
chan_status[chan] = 0;
|
||||
dev_status[addr] = 0;
|
||||
return 1;
|
||||
}
|
||||
if (dev_status[addr] & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) {
|
||||
if (dev_status[addr] != 0) {
|
||||
M[0x40 >> 2] = 0;
|
||||
M[0x44 >> 2] = ((uint32)dev_status[addr]) << 24;
|
||||
dev_status[addr] = 0;
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "Testio %x %x\n\r", addr, chan_status[chan]);
|
||||
chan_status[chan] = dibp->start_cmd(uptr, chan, 0) << 8;
|
||||
if (chan_status[chan] & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) {
|
||||
M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | M[0x44 >> 2] & 0xffff;
|
||||
@@ -565,6 +622,8 @@ int testchan(uint16 channel) {
|
||||
channel >>= 8;
|
||||
if (channel = 0)
|
||||
return 0;
|
||||
if (channel > channels)
|
||||
return 3;
|
||||
st = chan_status[subchannels + channel];
|
||||
if (st & STATUS_BUSY)
|
||||
return 2;
|
||||
@@ -598,6 +657,7 @@ t_stat chan_boot(uint16 addr, DEVICE *dptyr) {
|
||||
chan_dev[chan] = addr;
|
||||
ccw_count[chan] = 24;
|
||||
ccw_flags[chan] = FLAG_CC|FLAG_SLI;
|
||||
ccw_addr[chan] = 0;
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
ccw_cmd[chan] = 0x2;
|
||||
chan_status[chan] &= 0xff;
|
||||
@@ -621,20 +681,20 @@ uint16 scan_chan(uint8 mask) {
|
||||
if (irq_pend == 0)
|
||||
return 0;
|
||||
irq_pend = 0;
|
||||
for (i = 0; i < subchannels + MAX_CHAN; i++) {
|
||||
for (i = 0; i < subchannels + channels; i++) {
|
||||
if (i >= subchannels)
|
||||
imask = imask / 2;
|
||||
|
||||
/* If channel end, check if we should continue */
|
||||
if (chan_status[i] & STATUS_CEND) {
|
||||
if (ccw_flags[i] & FLAG_CC) {
|
||||
//fprintf(stderr, "Scan(%x %x) CC\n\r", i, chan_status[i]);
|
||||
if (chan_status[i] & STATUS_DEND)
|
||||
(void)load_ccw(i, 1);
|
||||
else
|
||||
irq_pend = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Scan(%x %x %x %x) end\n\r", i, chan_status[i], imask, mask);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x) end\n", i,
|
||||
chan_status[i], imask, mask);
|
||||
if ((imask & mask) != 0 || loading != 0) {
|
||||
pend = chan_dev[i];
|
||||
break;
|
||||
@@ -645,10 +705,9 @@ fprintf(stderr, "Scan(%x %x %x %x) end\n\r", i, chan_status[i], imask, mask);
|
||||
if (pend) {
|
||||
irq_pend = 1;
|
||||
i = find_subchan(pend);
|
||||
fprintf(stderr, "Scan end (%x %x)\n\r", chan_dev[i], pend);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Scan end (%x %x)\n", chan_dev[i],
|
||||
pend);
|
||||
store_csw(i);
|
||||
chan_status[i] = 0;
|
||||
chan_dev[i] = 0;
|
||||
dev_status[pend] = 0;
|
||||
} else {
|
||||
for (i = 0; i < MAX_DEV; i++) {
|
||||
@@ -656,10 +715,11 @@ fprintf(stderr, "Scan end (%x %x)\n\r", chan_dev[i], pend);
|
||||
pend = find_subchan(i);
|
||||
if (ccw_cmd[pend] == 0 && mask & (0x80 >> (i >> 8))) {
|
||||
irq_pend = 1;
|
||||
fprintf(stderr, "Set atten %03x %02x\n\r", i, dev_status[i]);
|
||||
// M[0x40 >> 2] = 0;
|
||||
M[0x44 >> 2] = (((uint32)dev_status[i]) << 24) |
|
||||
(M[0x44>>2] & 0xffff);
|
||||
M[0x44 >> 2] = (((uint32)dev_status[i]) << 24);
|
||||
M[0x40>>2] = 0;
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"Set atten %03x %02x [%08x] %08x\n",
|
||||
i, dev_status[i], M[0x40 >> 2], M[0x44 >> 2]);
|
||||
dev_status[i] = 0;
|
||||
return i;
|
||||
}
|
||||
@@ -667,6 +727,9 @@ fprintf(stderr, "Set atten %03x %02x\n\r", i, dev_status[i]);
|
||||
}
|
||||
pend = 0;
|
||||
}
|
||||
/* Only return loading unit on loading */
|
||||
if (loading != 0 && loading != pend)
|
||||
return 0;
|
||||
return pend;
|
||||
}
|
||||
|
||||
@@ -737,10 +800,14 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc)
|
||||
if (r != SCPE_OK)
|
||||
return r;
|
||||
|
||||
devaddr = GET_UADDR(uptr->u3);
|
||||
if ((newdev >> 8) > channels)
|
||||
return SCPE_ARG;
|
||||
|
||||
if (newdev > MAX_DEV)
|
||||
return SCPE_ARG;
|
||||
|
||||
devaddr = GET_UADDR(uptr->u3);
|
||||
|
||||
/* Clear out existing entry */
|
||||
if (dptr->flags & DEV_UADDR) {
|
||||
dev_unit[devaddr] = NULL;
|
||||
@@ -769,11 +836,16 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc)
|
||||
/* Update device entry */
|
||||
if (dptr->flags & DEV_UADDR) {
|
||||
dev_unit[devaddr] = dibp;
|
||||
fprintf(stderr, "Set dev %x\n\r", devaddr);
|
||||
uptr->u3 &= ~UNIT_ADDR(0x7ff);
|
||||
uptr->u3 |= UNIT_ADDR(devaddr);
|
||||
fprintf(stderr, "Set dev %x\n\r", GET_UADDR(uptr->u3));
|
||||
} else {
|
||||
for (i = 0; i < dibp->numunits; i++) {
|
||||
dev_unit[devaddr + i] = dibp;
|
||||
fprintf(stderr, "Set dev %x\n\r", devaddr + i);
|
||||
uptr = &((dibp->units)[i]);
|
||||
uptr->u3 &= ~UNIT_ADDR(0x7ff);
|
||||
uptr->u3 |= UNIT_ADDR(devaddr + i);
|
||||
fprintf(stderr, "Set dev %x\n\r", GET_UADDR(uptr->u3));
|
||||
}
|
||||
}
|
||||
return r;
|
||||
|
||||
@@ -85,13 +85,19 @@ t_stat con_detach(UNIT *);
|
||||
|
||||
|
||||
UNIT con_unit[] = {
|
||||
{UDATA(con_srv, 0, 0), 0, UNIT_ADDR(0x1F)}, /* A */
|
||||
{UDATA(con_srv, UNIT_ATT, 0), 0, UNIT_ADDR(0x1F)}, /* A */
|
||||
};
|
||||
|
||||
MTAB con_mod[] = {
|
||||
{MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr,
|
||||
&show_dev_addr, NULL},
|
||||
{0}
|
||||
};
|
||||
|
||||
struct dib con_dib = { 0xFF, 1, NULL, con_startcmd, NULL, con_unit, con_ini};
|
||||
|
||||
DEVICE con_dev = {
|
||||
"INQ", con_unit, NULL, NULL,
|
||||
"INQ", con_unit, NULL, con_mod,
|
||||
NUM_DEVS_CON, 8, 15, 1, 8, 8,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&con_dib, DEV_UADDR | DEV_DISABLE | DEV_DEBUG, 0, dev_debug
|
||||
@@ -258,7 +264,7 @@ con_srv(UNIT *uptr) {
|
||||
switch (ch) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
sim_debug(DEBUG_CMD, &con_dev, "%d: ent\n", u);
|
||||
sim_debug(DEBUG_DATA, &con_dev, "%d: ent\n", u);
|
||||
// if (con_data[u].inptr != 0)
|
||||
uptr->u3 |= CON_INPUT;
|
||||
uptr->u3 |= CON_CR;
|
||||
@@ -295,7 +301,7 @@ con_srv(UNIT *uptr) {
|
||||
break;
|
||||
|
||||
default:
|
||||
sim_debug(DEBUG_CMD, &con_dev, "%d: key '%c'\n", u, ch);
|
||||
sim_debug(DEBUG_DATA, &con_dev, "%d: key '%c'\n", u, ch);
|
||||
if (con_data[u].inptr < sizeof(con_data[u].ibuff)) {
|
||||
ch = ascii_to_ebcdic[ch];
|
||||
if (ch == 0xff) {
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
#define UNIT_MSIZE (0xff << UNIT_V_MSIZE)
|
||||
#define MEMAMOUNT(x) (x << UNIT_V_MSIZE)
|
||||
|
||||
#define HIST_MAX 50000
|
||||
#define TMR_RTC 0
|
||||
|
||||
#define HIST_MAX 5000000
|
||||
#define HIST_MIN 64
|
||||
#define HIST_PC 0x1000000
|
||||
#define HIST_SPW 0x2000000
|
||||
@@ -56,6 +58,8 @@ uint16 irqcode; /* Interupt code */
|
||||
uint8 flags; /* Misc flags */
|
||||
uint16 irqaddr; /* Address of IRQ vector */
|
||||
uint16 loading; /* Doing IPL */
|
||||
uint8 interval_irq = 0; /* Interval timer IRQ */
|
||||
|
||||
|
||||
#define ASCII 0x08 /* ASCII/EBCDIC mode */
|
||||
#define MCHECK 0x04 /* Machine check flag */
|
||||
@@ -143,6 +147,12 @@ const char *cpu_description (DEVICE *dptr);
|
||||
|
||||
t_bool build_dev_tab (void);
|
||||
|
||||
/* Interval timer option */
|
||||
t_stat rtc_srv(UNIT * uptr);
|
||||
t_stat rtc_reset(DEVICE * dptr);
|
||||
int32 rtc_tps = 120;
|
||||
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
cpu_dev CPU device descriptor
|
||||
@@ -151,7 +161,7 @@ t_bool build_dev_tab (void);
|
||||
cpu_mod CPU modifier list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (/*&rtc_srv*/NULL, UNIT_BINK, MAXMEMSIZE) };
|
||||
UNIT cpu_unit = { UDATA (&rtc_srv, UNIT_BINK, MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{ HRDATA (PC, PC, 24) },
|
||||
@@ -206,9 +216,9 @@ MTAB cpu_mod[] = {
|
||||
DEVICE cpu_dev = {
|
||||
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
||||
1, 16, 24, 1, 16, 8,
|
||||
&cpu_ex, &cpu_dep, &cpu_reset,
|
||||
NULL, NULL, NULL, NULL, 0, 0, NULL,
|
||||
NULL, NULL, &cpu_help, NULL, NULL, &cpu_description
|
||||
&cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL,
|
||||
NULL, DEV_DEBUG, 0, dev_debug,
|
||||
// NULL, NULL, &cpu_help, NULL, NULL, &cpu_description
|
||||
};
|
||||
|
||||
#if 0 /* 370 Operators */
|
||||
@@ -337,9 +347,10 @@ int WriteFull(uint32 addr, uint32 data) {
|
||||
storepsw(OPPSW, IRC_ADDR);
|
||||
return 1;
|
||||
}
|
||||
// if ((addr& 0xffff00) == 0x1800) {
|
||||
// fprintf(stderr, "Write %x %x\n\r", addr, data);
|
||||
// }
|
||||
|
||||
if ((addr & 0xfffff0) == 0xc90 && data == 0x40404040) {
|
||||
fprintf(stderr, "Error word\n\r");
|
||||
}
|
||||
|
||||
offset = addr & 0x3;
|
||||
addr >>= 2;
|
||||
@@ -406,9 +417,9 @@ int WriteByte(uint32 addr, uint32 data) {
|
||||
storepsw(OPPSW, IRC_ADDR);
|
||||
return 1;
|
||||
}
|
||||
// if ((addr& 0xffff00) == 0x1800) {
|
||||
// fprintf(stderr, "Write Byte %x %x\n\r", addr, data);
|
||||
// }
|
||||
if ((addr & 0xfffff0) == 0xc90 && data == 0x40) {
|
||||
fprintf(stderr, "Error byte\n\r");
|
||||
}
|
||||
|
||||
offset = 8 * (3 - (addr & 0x3));
|
||||
addr >>= 2;
|
||||
@@ -447,10 +458,10 @@ int WriteHalf(uint32 addr, uint32 data) {
|
||||
storepsw(OPPSW, IRC_ADDR);
|
||||
return 1;
|
||||
}
|
||||
// if ((addr& 0xffff00) == 0x1800) {
|
||||
// fprintf(stderr, "Write Half %x %x\n\r", addr, data);
|
||||
// }
|
||||
|
||||
if ((addr & 0xfffff0) == 0xc90 && data == 0x4040) {
|
||||
fprintf(stderr, "Error half\n\r");
|
||||
}
|
||||
offset = addr & 0x3;
|
||||
addr >>= 2;
|
||||
|
||||
@@ -523,6 +534,12 @@ sim_instr(void)
|
||||
t_uint64 t64a;
|
||||
|
||||
reason = SCPE_OK;
|
||||
/* Enable timer if option set */
|
||||
if (cpu_unit.flags & FEAT_TIMER) {
|
||||
sim_activate(&cpu_unit, 10000);
|
||||
}
|
||||
interval_irq = 0;
|
||||
|
||||
while (reason == SCPE_OK) {
|
||||
|
||||
wait_loop:
|
||||
@@ -549,8 +566,16 @@ wait_loop:
|
||||
goto supress;
|
||||
}
|
||||
|
||||
if (interval_irq && (sysmsk & 01)) {
|
||||
interval_irq = 0;
|
||||
storepsw(OEPSW, 0x40);
|
||||
goto supress;
|
||||
}
|
||||
|
||||
if (loading || flags & WAIT) {
|
||||
/* CPU IDLE */
|
||||
if (flags & WAIT && sysmsk == 0)
|
||||
return STOP_HALT;
|
||||
sim_interval = -1;
|
||||
goto wait_loop;
|
||||
}
|
||||
@@ -780,9 +805,19 @@ opr:
|
||||
} else if ((addr1 & 0x7) != 0) {
|
||||
storepsw(OPPSW, IRC_SPEC);
|
||||
} else {
|
||||
irqaddr = addr1;
|
||||
irqcode = 0;
|
||||
goto supress;
|
||||
if (ReadFull(addr1, &src1))
|
||||
goto supress;
|
||||
if (ReadFull(addr1+4, &src2))
|
||||
goto supress;
|
||||
if (hst_lnt) {
|
||||
hst_p = hst_p + 1;
|
||||
if (hst_p >= hst_lnt)
|
||||
hst_p = 0;
|
||||
hst[hst_p].pc = irqaddr | HIST_LPW;
|
||||
hst[hst_p].src1 = src1;
|
||||
hst[hst_p].src2 = src2;
|
||||
}
|
||||
goto lpsw;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -798,6 +833,8 @@ opr:
|
||||
storepsw(OPPSW, IRC_PRIV);
|
||||
else
|
||||
cc = testio(addr1);
|
||||
// if (cc != 0 && hst_lnt && hst_p > 2)
|
||||
// hst_p -= 2;
|
||||
break;
|
||||
|
||||
case OP_HIO:
|
||||
@@ -879,10 +916,8 @@ set_cc:
|
||||
set_cc3:
|
||||
regs[reg1] = dest;
|
||||
cc = 3;
|
||||
if (pmsk & FIXOVR) {
|
||||
if (pmsk & FIXOVR)
|
||||
storepsw(OPPSW, IRC_FIXOVR);
|
||||
reason =1;
|
||||
}
|
||||
}
|
||||
goto set_cc;
|
||||
|
||||
@@ -895,9 +930,9 @@ set_cc3:
|
||||
case OP_ALR:
|
||||
dest = src1 + src2;
|
||||
cc = 0;
|
||||
if ((uint32)src1 > (uint32)src2)
|
||||
if ((uint32)dest < (uint32)src1)
|
||||
cc |= 2;
|
||||
if (dest == 0)
|
||||
if (dest != 0)
|
||||
cc |= 1;
|
||||
regs[reg1] = dest;
|
||||
break;
|
||||
@@ -1035,10 +1070,9 @@ fprintf(stderr, " %d %08x %08x\n\r", src1, dest, src1);
|
||||
src1 = -src1;
|
||||
if (fill & 2)
|
||||
src2 = -src2;
|
||||
regs[reg1|1] = src2;
|
||||
regs[reg1] = src1;
|
||||
regs[reg1] = src2;
|
||||
regs[reg1|1] = src1;
|
||||
fprintf(stderr, " %08x %08x\n\r", src1, src2);
|
||||
// reason =1;
|
||||
break;
|
||||
|
||||
case OP_NR:
|
||||
@@ -1147,23 +1181,31 @@ char_save:
|
||||
|
||||
case OP_SRL:
|
||||
dest = regs[reg1];
|
||||
if (hst_lnt)
|
||||
hst[hst_p].src1 = dest;
|
||||
dest = ((uint32)dest) >> (addr1 & 0x3f);
|
||||
regs[reg1] = dest;
|
||||
break;
|
||||
|
||||
case OP_SLL:
|
||||
dest = regs[reg1];
|
||||
if (hst_lnt)
|
||||
hst[hst_p].src1 = dest;
|
||||
dest = ((uint32)dest) << (addr1 & 0x3f);
|
||||
regs[reg1] = dest;
|
||||
break;
|
||||
|
||||
case OP_SRA:
|
||||
dest = regs[reg1];
|
||||
if (hst_lnt)
|
||||
hst[hst_p].src1 = dest;
|
||||
dest = (int32)dest >> (addr1 & 0x3f);
|
||||
goto set_cc;
|
||||
|
||||
case OP_SLA:
|
||||
dest = regs[reg1];
|
||||
if (hst_lnt)
|
||||
hst[hst_p].src1 = dest;
|
||||
src2 = dest & MSIGN;
|
||||
addr1 &= 0x3f;
|
||||
cc = 0;
|
||||
@@ -1752,12 +1794,12 @@ save_dbl:
|
||||
|
||||
/* Floating Store register */
|
||||
case OP_STD:
|
||||
if (WriteFull(addr2 + 4, src1h))
|
||||
if (WriteFull(addr1 + 4, src1h))
|
||||
break;
|
||||
/* Fall through */
|
||||
|
||||
case OP_STE:
|
||||
WriteFull(addr2, src1);
|
||||
WriteFull(addr1, src1);
|
||||
break;
|
||||
|
||||
/* Floating Compare */
|
||||
@@ -1913,8 +1955,8 @@ save_dbl:
|
||||
/* Compute sign of result */
|
||||
case OP_MP:
|
||||
case OP_DP:
|
||||
// storepsw(OPPSW, IRC_OPR);
|
||||
// goto supress;
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
break;
|
||||
|
||||
/* Extended precision load round */
|
||||
@@ -1926,7 +1968,7 @@ save_dbl:
|
||||
case OP_MXDR:
|
||||
case OP_MXD:
|
||||
default:
|
||||
reason=1;
|
||||
// reason=1;
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
}
|
||||
@@ -1951,6 +1993,7 @@ supress:
|
||||
if (hst_lnt) {
|
||||
hst[hst_p].src2 = src2;
|
||||
}
|
||||
lpsw:
|
||||
sysmsk = (src1 >> 24) & 0xff;
|
||||
st_key = (src1 >> 16) & 0xf0;
|
||||
flags = (src1 >> 16) & 0xf;
|
||||
@@ -1980,6 +2023,26 @@ t_stat cpu_reset (DEVICE *dptr)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Interval timer routines */
|
||||
t_stat
|
||||
rtc_srv(UNIT * uptr)
|
||||
{
|
||||
if (cpu_unit.flags & FEAT_TIMER) {
|
||||
int32 t;
|
||||
t = sim_rtcn_calb (rtc_tps, TMR_RTC);
|
||||
sim_activate_after(uptr, 1000000/rtc_tps);
|
||||
t = M[0x50>>2];
|
||||
M[0x50>>2]--;
|
||||
if (((t ^ M[0x50>>2]) & MSIGN) != 0 && (t & MSIGN) == 0) {
|
||||
fprintf(stderr, "Timer %08x\n\r", M[0x50>>2]);
|
||||
interval_irq = 1;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Memory examine */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -347,6 +347,7 @@ const char ebcdic_to_ascii[256];
|
||||
extern DEBTAB dev_debug[];
|
||||
extern DEBTAB crd_debug[];
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE cdp_dev;
|
||||
extern DEVICE cdr_dev;
|
||||
extern DEVICE lpr_dev;
|
||||
@@ -356,6 +357,7 @@ extern DEVICE mtb_dev;
|
||||
extern DEVICE dda_dev;
|
||||
extern DEVICE ddb_dev;
|
||||
extern DEVICE com_dev;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
#define NUM_DEVS_CDP 1
|
||||
#define NUM_DEVS_CDR 1
|
||||
@@ -368,5 +370,4 @@ extern DEVICE com_dev;
|
||||
#define NUM_DEVS_COM 1
|
||||
#define NUM_UNITS_COM 16
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern void fprint_inst(FILE *, uint16 *);
|
||||
|
||||
@@ -175,7 +175,7 @@ print_line(UNIT * uptr)
|
||||
|
||||
/* Print out buffer */
|
||||
sim_fwrite(&out, 1, i, uptr->fileref);
|
||||
fprintf(stderr, "%s", out);
|
||||
sim_debug(DEBUG_DETAIL, &lpr_dev, "%s", out);
|
||||
uptr->u4++;
|
||||
if (uptr->u4 > uptr->capac) {
|
||||
uptr->u4 = 1;
|
||||
@@ -190,14 +190,15 @@ uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd)
|
||||
uint8 ch;
|
||||
|
||||
if ((uptr->u3 & LPR_CMDMSK) != 0) {
|
||||
if ((uptr->flags & UNIT_ATT) != 0)
|
||||
if ((uptr->flags & UNIT_ATT) != 0)
|
||||
return SNS_BSY;
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_CMD, &lpr_dev, "Cmd %02x\n", cmd);
|
||||
|
||||
switch (cmd & 0x7) {
|
||||
case 1: /* Write command */
|
||||
case 3:
|
||||
uptr->u3 &= ~(LPR_CMDMSK);
|
||||
uptr->u3 |= (cmd & LPR_CMDMSK);
|
||||
sim_activate(uptr, 10); /* Start unit off */
|
||||
@@ -205,6 +206,14 @@ uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd)
|
||||
uptr->u6 = 0;
|
||||
return 0;
|
||||
|
||||
case 3: /* Carrage control */
|
||||
uptr->u3 &= ~(LPR_CMDMSK);
|
||||
uptr->u3 |= (cmd & LPR_CMDMSK);
|
||||
sim_activate(uptr, 10); /* Start unit off */
|
||||
uptr->u5 = 0;
|
||||
uptr->u6 = 0;
|
||||
return SNS_CHNEND;
|
||||
|
||||
case 0: /* Status */
|
||||
break;
|
||||
|
||||
@@ -228,33 +237,37 @@ t_stat
|
||||
lpr_srv(UNIT *uptr) {
|
||||
int addr = GET_UADDR(uptr->u3);
|
||||
int u = (uptr - lpr_unit);
|
||||
int cmd = (uptr->u3 & 0x7);
|
||||
|
||||
if ((uptr->u3 & 0xFF) == 4) {
|
||||
if (cmd == 4) {
|
||||
uint8 ch = uptr->u5;
|
||||
uptr->u3 &= ~(LPR_CMDMSK);
|
||||
chan_write_byte(GET_UADDR(uptr->u3), &ch);
|
||||
chan_end(addr, SNS_DEVEND|SNS_CHNEND);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if ((uptr->u3 & LPR_FULL) || (uptr->u3 & 0x7) == 0x3) {
|
||||
if ((uptr->u3 & LPR_FULL) || cmd == 0x3) {
|
||||
print_line(uptr);
|
||||
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
|
||||
uptr->u6 = 0;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
// set_devattn(addr, SNS_DEVEND);
|
||||
// chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
set_devattn(addr, SNS_DEVEND);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Copy next column over */
|
||||
if ((uptr->u3 & 0x7) == 1 && uptr->u6 < 144) {
|
||||
if(chan_read_byte(addr, &lpr_data[u].lbuff[uptr->u6++])) {
|
||||
if (cmd == 1 && (uptr->u3 & LPR_FULL) == 0) {
|
||||
if(chan_read_byte(addr, &lpr_data[u].lbuff[uptr->u6])) {
|
||||
uptr->u3 |= LPR_FULL;
|
||||
} else {
|
||||
sim_activate(uptr, 10);
|
||||
sim_activate(uptr, 20);
|
||||
uptr->u6++;
|
||||
}
|
||||
if (uptr->u3 & LPR_FULL || uptr->u6 >= 144) {
|
||||
if (uptr->u3 & LPR_FULL || uptr->u6 >= 132) {
|
||||
uptr->u3 |= LPR_FULL;
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
sim_activate(uptr, 1000);
|
||||
chan_end(addr, SNS_CHNEND);
|
||||
sim_activate(uptr, 3000);
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
|
||||
@@ -85,8 +85,6 @@
|
||||
#define MT_TRANS 0x2000 /* Translation turned on ignored 9 track */
|
||||
#define MT_CONV 0x4000 /* Data converter on ignored 9 track */
|
||||
#define MT_BUSY 0x8000 /* Flag to send a CUE */
|
||||
#define MT_CHAN_MSK 0xff0000 /* Channel mask */
|
||||
#define MT_CHAN_V 16 /* Channel shift */
|
||||
|
||||
/* in u4 is current buffer position */
|
||||
|
||||
@@ -171,7 +169,7 @@ UNIT mta_unit[] = {
|
||||
{UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x187)}, /* 7 */
|
||||
};
|
||||
|
||||
struct dib mta_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mta_unit, NULL};
|
||||
struct dib mta_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mta_unit, mt_ini};
|
||||
|
||||
DEVICE mta_dev = {
|
||||
"MTA", mta_unit, NULL, mt_mod,
|
||||
@@ -192,7 +190,7 @@ UNIT mtb_unit[] = {
|
||||
{UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x287)}, /* 7 */
|
||||
};
|
||||
|
||||
struct dib mtb_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mtb_unit, NULL};
|
||||
struct dib mtb_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mtb_unit, mt_ini};
|
||||
|
||||
DEVICE mtb_dev = {
|
||||
"MTB", mtb_unit, NULL, mt_mod,
|
||||
@@ -264,36 +262,52 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
uptr->u4 = 0;
|
||||
uptr->u6 = 0;
|
||||
mt_busy[GET_DEV_BUF(dptr->flags)] = 1;
|
||||
if ((cmd & 0x7) == 0x7) /* Quick end channel on control */
|
||||
if ((cmd & 0x7) == 0x7) { /* Quick end channel on control */
|
||||
// if ((cmd & 0x30) == 0) {
|
||||
// mt_busy[GET_DEV_BUF(dptr->flags)] = 0;
|
||||
// }
|
||||
return SNS_CHNEND;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0x3: /* Control */
|
||||
case 0xb: /* Control */
|
||||
if ((uptr->flags & MTUF_9TR) == 0) {
|
||||
uptr->u5 |= (SNS_7TRACK << 8);
|
||||
if ((cmd & 0x30) == 0)
|
||||
return SNS_DEVEND;
|
||||
if ((cmd & 0x38) == 0x18)
|
||||
return SNS_DEVEND;
|
||||
if ((cmd & 0xc0) != 0xc0) {
|
||||
if ((cmd & 0xc0) == 0xc0) {
|
||||
uptr->u5 |= SNS_CMDREJ;
|
||||
} else {
|
||||
uptr->u3 &= ~MT_MDEN_MSK;
|
||||
uptr->u3 |= (cmd & MT_MDEN_MSK);
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
|
||||
}
|
||||
switch((cmd >> 3) & 07) {
|
||||
case 0: /* NOP */
|
||||
case 1: /* Diagnostics */
|
||||
case 3:
|
||||
return SNS_CHNEND|SNS_DEVEND ;
|
||||
case 2: /* Reset condition */
|
||||
uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
|
||||
uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_ODD | MT_CONV;
|
||||
break;
|
||||
case 4:
|
||||
uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
|
||||
uptr->u3 |= (cmd & MT_MDEN_MSK);
|
||||
break;
|
||||
case 5:
|
||||
uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
|
||||
uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_TRANS;
|
||||
break;
|
||||
case 6:
|
||||
uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
|
||||
uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_ODD;
|
||||
break;
|
||||
case 7:
|
||||
uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
|
||||
uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_ODD | MT_TRANS;
|
||||
break;
|
||||
}
|
||||
uptr->u3 &= ~(MT_ODD|MT_TRANS);
|
||||
uptr->u3 |= MT_CONV;
|
||||
if (cmd & 0x10)
|
||||
uptr->u3 |= MT_ODD;
|
||||
if (cmd & 0x20)
|
||||
uptr->u3 &= ~MT_CONV;
|
||||
if (cmd & 0x08)
|
||||
uptr->u3 |= MT_TRANS;
|
||||
} else {
|
||||
if ((cmd & 0xf0) != 0xc0) {
|
||||
uptr->u5 |= SNS_CMDREJ;
|
||||
}
|
||||
// if ((cmd & 0xf0) != 0xc0) {
|
||||
// uptr->u5 |= SNS_CMDREJ;
|
||||
// }
|
||||
uptr->u3 &= ~MT_MDEN_MSK;
|
||||
if (cmd & 0x8)
|
||||
uptr->u3 |= MT_MDEN_800;
|
||||
@@ -420,7 +434,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||
ch = mt_buffer[bufnum][uptr->u4++];
|
||||
/* if we are a 7track tape, handle conversion */
|
||||
if ((uptr->flags & MTUF_9TR) == 0) {
|
||||
mode = (uptr->u3 & MT_ODD) ? 0100 : 0;
|
||||
mode = (uptr->u3 & MT_ODD) ? 0 : 0100;
|
||||
if ((parity_table[ch & 077] ^ (ch & 0100) ^ mode) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "Parity error unit=%d %d %03o\n",
|
||||
unit, uptr->u4-1, ch);
|
||||
@@ -504,7 +518,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||
}
|
||||
} else {
|
||||
if ((uptr->flags & MTUF_9TR) == 0) {
|
||||
mode = (uptr->u3 & MT_ODD) ? 0100 : 0;
|
||||
mode = (uptr->u3 & MT_ODD) ? 0 : 0100;
|
||||
if (uptr->u3 & MT_TRANS)
|
||||
ch = (ch & 0xf) | ((ch & 0x30) ^ 0x30);
|
||||
if (uptr->u3 & MT_CONV) {
|
||||
@@ -564,7 +578,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||
|
||||
ch = mt_buffer[bufnum][--uptr->u4];
|
||||
if ((uptr->flags & MTUF_9TR) == 0) {
|
||||
mode = (uptr->u3 & MT_ODD) ? 0100 : 0;
|
||||
mode = (uptr->u3 & MT_ODD) ? 0 : 0100;
|
||||
ch &= 077;
|
||||
if ((parity_table[ch & 077] ^ (ch & 0100) ^ mode) == 0) {
|
||||
uptr->u5 |= (SNS_VRC << 16) | SNS_DATCHK;
|
||||
@@ -621,10 +635,12 @@ t_stat mt_srv(UNIT * uptr)
|
||||
uptr->u3 &= ~MT_CMDMSK;
|
||||
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
|
||||
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
uptr->u4 ++;
|
||||
sim_activate(uptr, 500);
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
} else {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit);
|
||||
uptr->u3 &= ~(MT_CMDMSK);
|
||||
@@ -641,10 +657,12 @@ t_stat mt_srv(UNIT * uptr)
|
||||
uptr->u3 &= ~MT_CMDMSK;
|
||||
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
|
||||
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
uptr->u4 ++;
|
||||
sim_activate(uptr, 500);
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
break;
|
||||
case 1:
|
||||
uptr->u4++;
|
||||
@@ -680,8 +698,10 @@ t_stat mt_srv(UNIT * uptr)
|
||||
uptr->u3 &= ~MT_CMDMSK;
|
||||
mt_busy[bufnum] &= ~1;
|
||||
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
uptr->u4 ++;
|
||||
sim_activate(uptr, 500);
|
||||
break;
|
||||
@@ -717,6 +737,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||
case 0:
|
||||
uptr->u4 ++;
|
||||
sim_activate(uptr, 500);
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
break;
|
||||
case 1:
|
||||
uptr->u4++;
|
||||
@@ -757,6 +778,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||
case 0:
|
||||
uptr->u4 ++;
|
||||
sim_activate(uptr, 500);
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
break;
|
||||
case 1:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit);
|
||||
@@ -795,10 +817,12 @@ t_stat mt_srv(UNIT * uptr)
|
||||
uptr->u5 |= SNS_CMDREJ;
|
||||
uptr->u3 &= ~MT_CMDMSK;
|
||||
mt_busy[bufnum] &= ~1;
|
||||
// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
} else {
|
||||
uptr->u4 ++;
|
||||
sim_activate(uptr, 500);
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@@ -818,24 +842,26 @@ t_stat mt_srv(UNIT * uptr)
|
||||
if (uptr->u4 == 0) {
|
||||
uptr->u4 ++;
|
||||
sim_activate(uptr, 30000);
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
mt_busy[bufnum] &= ~1;
|
||||
} else {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit);
|
||||
uptr->u3 &= ~(MT_CMDMSK);
|
||||
r = sim_tape_rewind(uptr);
|
||||
set_devattn(addr, SNS_DEVEND);
|
||||
mt_busy[bufnum] &= ~1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MT_RUN:
|
||||
if (uptr->u4 == 0) {
|
||||
uptr->u4 ++;
|
||||
mt_busy[bufnum] &= ~1;
|
||||
sim_activate(uptr, 30000);
|
||||
// chan_end(addr, SNS_CHNEND);
|
||||
} else {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit);
|
||||
uptr->u3 &= ~(MT_CMDMSK);
|
||||
r = sim_tape_detach(uptr);
|
||||
mt_busy[bufnum] &= ~1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -847,7 +873,9 @@ mt_ini(UNIT * uptr, t_bool f)
|
||||
{
|
||||
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||
|
||||
uptr->u3 = MT_ODD|MT_DENS_800;
|
||||
uptr->u3 &= ~0xffff;
|
||||
if ((uptr->flags & MTUF_9TR) == 0)
|
||||
uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800;
|
||||
mt_busy[GET_DEV_BUF(dptr->flags)] = 0;
|
||||
}
|
||||
|
||||
@@ -884,7 +912,10 @@ mt_boot(int32 unit_num, DEVICE * dptr)
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT; /* attached? */
|
||||
uptr->u3 |= MT_CONV;
|
||||
if ((uptr->flags & MTUF_9TR) == 0) {
|
||||
uptr->u3 &= ~0xffff;
|
||||
uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800;
|
||||
}
|
||||
return chan_boot(GET_UADDR(uptr->u3), dptr);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user