1
0
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:
Richard Cornwell
2017-10-29 12:31:33 -04:00
parent f37bfd74e4
commit 9165f0bcd9
8 changed files with 775 additions and 404 deletions

View File

@@ -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.

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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

View File

@@ -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 *);

View File

@@ -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;

View File

@@ -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);
}