1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-23 02:47:57 +00:00

IBM360: Code cleanup.

This commit is contained in:
Richard Cornwell 2020-06-07 08:42:25 -04:00
parent b5837f5b49
commit ea936a5c89
11 changed files with 778 additions and 742 deletions

View File

@ -1,6 +1,6 @@
/* ibm360_cdp.c: IBM 360 Card Punch
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -48,6 +48,9 @@
#define CDP_WR 0x01 /* Punch command */
#define CDP_CARD 0x100 /* Unit has card in buffer */
/* Upper 11 bits of u3 hold the device address */
/* u4 holds current column, */
/* in u5 packs sense byte 0,1 and 3 */
/* Sense byte 0 */
@ -60,6 +63,10 @@
#define SNS_SEQUENCE 0x02 /* Unusual sequence */
#define SNS_CHN9 0x01 /* Channel 9 on printer */
#define CMD u3
#define COL u4
#define SNS u5
/* std devices. data structures
@ -122,7 +129,7 @@ uint8 cdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
DEVICE *dptr = find_dev_from_unit(uptr);
int unit = (uptr - dptr->units);
if ((uptr->u3 & (CDP_CARD|CDP_CMDMSK)) != 0) {
if ((uptr->CMD & (CDP_CARD|CDP_CMDMSK)) != 0) {
if ((uptr->flags & UNIT_ATT) != 0)
return SNS_BSY;
return SNS_DEVEND|SNS_UNITCHK;
@ -131,16 +138,16 @@ uint8 cdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %x\n", unit, cmd);
switch (cmd & 0x7) {
case 1: /* Write command */
uptr->u3 &= ~(CDP_CMDMSK);
uptr->u3 |= (cmd & CDP_CMDMSK);
uptr->CMD &= ~(CDP_CMDMSK);
uptr->CMD |= (cmd & CDP_CMDMSK);
sim_activate(uptr, 10); /* Start unit off */
uptr->u4 = 0;
uptr->u5 = 0;
uptr->COL = 0;
uptr->SNS = 0;
return 0;
case 3:
if (cmd != 0x3) {
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
}
return SNS_CHNEND|SNS_DEVEND;
@ -149,16 +156,16 @@ uint8 cdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
break;
case 4: /* Sense */
uptr->u3 &= ~(CDP_CMDMSK);
uptr->u3 |= (cmd & CDP_CMDMSK);
uptr->CMD &= ~(CDP_CMDMSK);
uptr->CMD |= (cmd & CDP_CMDMSK);
sim_activate(uptr, 10);
return 0;
default: /* invalid command */
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
break;
}
if (uptr->u5 & 0xff)
if (uptr->SNS & 0xff)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
}
@ -169,19 +176,19 @@ t_stat
cdp_srv(UNIT *uptr) {
int u = uptr-cdp_unit;
uint16 *image = (uint16 *)(uptr->up7);
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
/* Handle sense */
if ((uptr->u3 & CDP_CMDMSK) == 0x4) {
uint8 ch = uptr->u5;
if ((uptr->CMD & CDP_CMDMSK) == 0x4) {
uint8 ch = uptr->SNS;
chan_write_byte(addr, &ch);
chan_end(addr, SNS_DEVEND|SNS_CHNEND);
return SCPE_OK;
}
if (uptr->u3 & CDP_CARD) {
if (uptr->CMD & CDP_CARD) {
/* Done waiting, punch card */
uptr->u3 &= ~CDP_CARD;
uptr->CMD &= ~CDP_CARD;
sim_debug(DEBUG_DETAIL, &cdp_dev, "unit=%d:punch\n", u);
switch(sim_punch_card(uptr, image)) {
/* If we get here, something is wrong */
@ -197,20 +204,20 @@ cdp_srv(UNIT *uptr) {
}
/* Copy next column over */
if (uptr->u4 < 80) {
if (uptr->COL < 80) {
uint8 ch = 0;
if (chan_read_byte(addr, &ch)) {
uptr->u3 |= CDP_CARD;
uptr->CMD |= CDP_CARD;
} else {
sim_debug(DEBUG_DATA, &cdp_dev, "%d: Char < %02o\n", u, ch);
image[uptr->u4++] = sim_ebcdic_to_hol(ch);
if (uptr->u4 == 80) {
uptr->u3 |= CDP_CARD;
image[uptr->COL++] = sim_ebcdic_to_hol(ch);
if (uptr->COL == 80) {
uptr->CMD |= CDP_CARD;
}
}
if (uptr->u3 & CDP_CARD) {
uptr->u3 &= ~(CDP_CMDMSK);
if (uptr->CMD & CDP_CARD) {
uptr->CMD &= ~(CDP_CMDMSK);
chan_end(addr, SNS_CHNEND);
sim_activate(uptr, 10000);
} else
@ -229,7 +236,7 @@ cdp_attach(UNIT * uptr, CONST char *file)
return r;
if (uptr->up7 == 0) {
uptr->up7 = calloc(80, sizeof(uint16));
uptr->u5 = 0;
uptr->SNS = 0;
}
return SCPE_OK;
}
@ -239,7 +246,7 @@ cdp_detach(UNIT * uptr)
{
uint16 *image = (uint16 *)(uptr->up7);
if (uptr->u5 & CDP_CARD)
if (uptr->SNS & CDP_CARD)
sim_punch_card(uptr, image);
if (uptr->up7 != 0)
free(uptr->up7);

View File

@ -1,6 +1,6 @@
/* ibm360_cdr.c: IBM 360 Card Reader.
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -48,6 +48,9 @@
#define CDP_WR 0x09 /* Punch command */
#define CDR_CARD 0x100 /* Unit has card in buffer */
/* Upper 11 bits of u3 hold the device address */
/* u4 holds current column, */
/* in u5 packs sense byte 0,1 and 3 */
/* Sense byte 0 */
@ -60,6 +63,9 @@
#define SNS_SEQUENCE 0x02 /* Unusual sequence */
#define SNS_CHN9 0x01 /* Channel 9 on printer */
#define CMD u3
#define COL u4
#define SNS u5
/* std devices. data structures
@ -71,8 +77,6 @@
*/
uint8 cdr_startcmd(UNIT *, uint16, uint8);
t_stat cdr_boot(int32, DEVICE *);
t_stat cdr_srv(UNIT *);
@ -117,7 +121,7 @@ uint8 cdr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
DEVICE *dptr = find_dev_from_unit(uptr);
int unit = (uptr - dptr->units);
if ((uptr->u3 & CDR_CMDMSK) != 0) {
if ((uptr->CMD & CDR_CMDMSK) != 0) {
if ((uptr->flags & UNIT_ATT) != 0)
return SNS_BSY;
return SNS_DEVEND;
@ -126,36 +130,36 @@ uint8 cdr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %x\n", unit, cmd);
if (cmd != 4 && sim_card_eof(uptr) == 1) {
uint16 *image = (uint16 *)(uptr->up7);
uptr->u5 = SNS_INTVENT;
uptr->SNS = SNS_INTVENT;
sim_read_card(uptr, image); /* Read in the EOF */
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
}
if (cmd != 4 && (uptr->flags & UNIT_ATT) == 0) {
uptr->u5 = SNS_INTVENT;
uptr->SNS = SNS_INTVENT;
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
}
switch (cmd & 0x7) {
case 2: /* Read command */
if ((cmd & 0xc0) != 0xc0)
uptr->u3 &= ~CDR_CARD;
uptr->u3 &= ~(CDR_CMDMSK);
uptr->u3 |= (cmd & CDR_CMDMSK);
uptr->CMD &= ~CDR_CARD;
uptr->CMD &= ~(CDR_CMDMSK);
uptr->CMD |= (cmd & CDR_CMDMSK);
sim_activate(uptr, 1000); /* Start unit off */
uptr->u4 = 0;
uptr->u5 = 0;
uptr->COL = 0;
uptr->SNS = 0;
return 0;
case 3: /* Control */
uptr->u5 = 0;
uptr->u3 &= ~(CDR_CMDMSK|CDR_CARD);
uptr->SNS = 0;
uptr->CMD &= ~(CDR_CMDMSK|CDR_CARD);
if (cmd == 0x3)
return SNS_CHNEND|SNS_DEVEND;
if ((cmd & 0x30) != 0x20 || (cmd & 0xc0) == 0xc0) {
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
}
uptr->u3 |= (cmd & CDR_CMDMSK);
uptr->u4 = 0;
uptr->CMD |= (cmd & CDR_CMDMSK);
uptr->COL = 0;
sim_activate(uptr, 1000); /* Start unit off */
return 0;
@ -163,17 +167,17 @@ uint8 cdr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
break;
case 4: /* Sense */
uptr->u3 &= ~(CDR_CMDMSK);
uptr->u3 |= (cmd & CDR_CMDMSK);
uptr->CMD &= ~(CDR_CMDMSK);
uptr->CMD |= (cmd & CDR_CMDMSK);
sim_activate(uptr, 10);
return 0;
default: /* invalid command */
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
break;
}
if (uptr->u5)
if (uptr->SNS)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
}
@ -181,38 +185,38 @@ uint8 cdr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
/* Handle transfer of data for card reader */
t_stat
cdr_srv(UNIT *uptr) {
int addr = GET_UADDR(uptr->u3);
int addr = GET_UADDR(uptr->CMD);
uint16 *image = (uint16 *)(uptr->up7);
if ((uptr->u3 & CDR_CMDMSK) == CHN_SNS) {
uint8 ch = uptr->u5;
if ((uptr->CMD & CDR_CMDMSK) == CHN_SNS) {
uint8 ch = uptr->SNS;
if (ch == 0 && (uptr->flags & UNIT_ATT) == 0)
ch = SNS_INTVENT;
chan_write_byte(addr, &ch);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
uptr->u3 &= ~(CDR_CMDMSK);
uptr->CMD &= ~(CDR_CMDMSK);
return SCPE_OK;
}
/* Check if new card requested. */
if ((uptr->u3 & CDR_CARD) == 0) {
if ((uptr->CMD & CDR_CARD) == 0) {
switch(sim_read_card(uptr, image)) {
case CDSE_EMPTY:
uptr->u5 = SNS_INTVENT;
uptr->SNS = SNS_INTVENT;
case CDSE_EOF:
uptr->u3 &= ~CDR_CMDMSK;
uptr->CMD &= ~CDR_CMDMSK;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
return SCPE_OK;
case CDSE_ERROR:
uptr->u5 = SNS_INTVENT;
uptr->u3 &= ~CDR_CMDMSK;
uptr->SNS = SNS_INTVENT;
uptr->CMD &= ~CDR_CMDMSK;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
case CDSE_OK:
uptr->u3 |= CDR_CARD;
if ((uptr->u3 & CDR_CMDMSK) == CDR_FEED) {
uptr->CMD |= CDR_CARD;
if ((uptr->CMD & CDR_CMDMSK) == CDR_FEED) {
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
uptr->u3 &= ~(CDR_CMDMSK);
uptr->CMD &= ~(CDR_CMDMSK);
return SCPE_OK;
}
break;
@ -220,29 +224,29 @@ cdr_srv(UNIT *uptr) {
}
/* Copy next column over */
if ((uptr->u3 & CDR_CMDMSK) == CDR_RD) {
if ((uptr->CMD & CDR_CMDMSK) == CDR_RD) {
int u = uptr-cdr_unit;
uint16 xlat;
uint8 ch = 0;
xlat = sim_hol_to_ebcdic(image[uptr->u4]);
xlat = sim_hol_to_ebcdic(image[uptr->COL]);
if (xlat == 0x100) {
uptr->u5 |= SNS_DATCHK;
uptr->SNS |= SNS_DATCHK;
ch = 0x00;
} else
ch = (uint8)(xlat&0xff);
if (chan_write_byte(addr, &ch)) {
uptr->u3 &= ~(CDR_CMDMSK);
chan_end(addr, SNS_CHNEND|SNS_DEVEND|(uptr->u5 ? SNS_UNITCHK:0));
uptr->CMD &= ~(CDR_CMDMSK);
chan_end(addr, SNS_CHNEND|SNS_DEVEND|(uptr->SNS ? SNS_UNITCHK:0));
return SCPE_OK;
} else {
uptr->u4++;
uptr->COL++;
sim_debug(DEBUG_DATA, &cdr_dev, "%d: Char > %02o\n", u, ch);
}
if (uptr->u4 == 80) {
uptr->u3 &= ~(CDR_CMDMSK);
chan_end(addr, SNS_CHNEND|SNS_DEVEND|(uptr->u5 ? SNS_UNITCHK:0));
if (uptr->COL == 80) {
uptr->CMD &= ~(CDR_CMDMSK);
chan_end(addr, SNS_CHNEND|SNS_DEVEND|(uptr->SNS ? SNS_UNITCHK:0));
}
sim_activate(uptr, 10);
}
@ -257,13 +261,13 @@ cdr_boot(int32 unit_num, DEVICE * dptr)
if ((uptr->flags & UNIT_ATT) == 0)
return SCPE_UNATT; /* attached? */
return chan_boot(GET_UADDR(uptr->u3), dptr);
return chan_boot(GET_UADDR(uptr->CMD), dptr);
}
t_stat
cdr_attach(UNIT * uptr, CONST char *file)
{
int addr = GET_UADDR(uptr->u3);
int addr = GET_UADDR(uptr->CMD);
t_stat r;
if ((r = sim_card_attach(uptr, file)) != SCPE_OK)
@ -271,8 +275,8 @@ cdr_attach(UNIT * uptr, CONST char *file)
if (uptr->up7 == 0)
uptr->up7 = malloc(sizeof(uint16)*80);
set_devattn(addr, SNS_DEVEND);
uptr->u3 &= ~(CDR_CARD);
uptr->u4 = 0;
uptr->CMD &= ~(CDR_CARD);
uptr->COL = 0;
uptr->u6 = 0;
return SCPE_OK;
}
@ -283,7 +287,7 @@ cdr_detach(UNIT * uptr)
if (uptr->up7 != 0)
free(uptr->up7);
uptr->up7 = 0;
uptr->u5 = 0;
uptr->SNS = 0;
return sim_card_detach(uptr);
}

View File

@ -1,6 +1,6 @@
/* ibm360_chan.c: IBM 360 Channel functions.
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View File

@ -1,6 +1,6 @@
/* ibm360_com.c: IBM 360 2703 communications controller
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -54,7 +54,12 @@
#define BYPASS 0x10000 /* Don't echo output */
#define BREAK 0x20000 /* Return unit exception */
/* Upper 11 bits of u3 hold the device address */
/* u4 */
/* Where we are reading from */
/* u5 */
/* Sense byte 0 */
#define SNS_CMDREJ 0x80 /* Command reject */
#define SNS_INTVENT 0x40 /* Unit intervention required */
@ -65,12 +70,12 @@
#define SNS_RECV 0x02 /* Receiving */
#define SNS_TIMEOUT 0x01 /* Timeout */
/* u5 */
/* Where we are reading from */
#define IPTR u5
/* u6 */
/* Pointer into buffer */
#define CMD u3
#define IPTR u4
#define SNS u5
#define BPTR u6
uint8 coml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ;
@ -248,12 +253,12 @@ static const uint8 com_2741_out[256] = {
};
uint8 coml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
DEVICE *dptr = find_dev_from_unit(uptr);
int unit = (uptr - dptr->units);
sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %x\n", unit, cmd);
if ((uptr->u3 & 0xff) != 0) {
if ((uptr->CMD & 0xff) != 0) {
return SNS_BSY;
}
@ -264,29 +269,29 @@ uint8 coml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
return SNS_CHNEND|SNS_DEVEND;
case 0x2: /* Read command */
case 0x1: /* Write command */
uptr->u3 |= cmd;
uptr->u4 = 0;
uptr->CMD |= cmd;
uptr->SNS = 0;
sim_activate(uptr, 200);
return 0;
case 0x0: /* Status */
if (cmd == 0x4) { /* Sense */
uptr->u3 |= cmd;
uptr->CMD |= cmd;
sim_activate(uptr, 200);
return 0;
}
break;
}
if (uptr->u4 & 0xff)
if (uptr->SNS & 0xff)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
}
uint8 coml_haltio(UNIT *uptr) {
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
DEVICE *dptr = find_dev_from_unit(uptr);
int unit = (uptr - dptr->units);
int cmd = uptr->u3 & 0xff;
int cmd = uptr->CMD & 0xff;
sim_debug(DEBUG_CMD, dptr, "HLTIO unit=%d %x\n", unit, cmd);
if ((com_unit[0].flags & UNIT_ATT) == 0) /* attached? */
@ -306,14 +311,14 @@ uint8 coml_haltio(UNIT *uptr) {
case CMD_BRK: /* Send break signal */
case CMD_PREP: /* Wait for incoming data */
case CMD_SRCH: /* Wait for EOT character */
uptr->u3 &= ~(ADDR9|ADDR|0xff);
uptr->CMD &= ~(ADDR9|ADDR|0xff);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
case CMD_ENB: /* Enable line */
/* Terminate the operation */
(void)tmxr_set_get_modem_bits(&com_ldsc[unit], 0, TMXR_MDM_DTR, NULL);
(void)tmxr_reset_ln(&com_ldsc[unit]);
uptr->u3 &= ~0xffff;
uptr->CMD &= ~0xffff;
break;
}
return 1;
@ -322,10 +327,10 @@ uint8 coml_haltio(UNIT *uptr) {
/* Handle per unit commands */
t_stat coml_srv(UNIT * uptr)
{
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
DEVICE *dptr = find_dev_from_unit(uptr);
int unit = (uptr - dptr->units);
int cmd = uptr->u3 & 0xff;
int cmd = uptr->CMD & 0xff;
uint8 ch;
@ -334,55 +339,55 @@ t_stat coml_srv(UNIT * uptr)
break;
case 0x4:
ch = uptr->u4 & 0xff;
ch = uptr->SNS & 0xff;
sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 1 %x\n", unit, ch);
chan_write_byte(addr, &ch) ;
uptr->u3 &= ~0xff;
uptr->CMD &= ~0xff;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
case CMD_DIAL: /* Dial call */
uptr->u4 = SNS_CMDREJ;
uptr->SNS = SNS_CMDREJ;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
break;
case CMD_INH: /* Read data without timeout */
case CMD_RD: /* Read in data from com line */
uptr->u4 = 0;
if (uptr->u3 & ENAB) {
uptr->SNS = 0;
if (uptr->CMD & ENAB) {
if (com_ldsc[unit].conn == 0) {
uptr->u3 &= ~(0xff|BREAK|INPUT|ENAB|POLL);
uptr->u4 = SNS_INTVENT;
uptr->CMD &= ~(0xff|BREAK|INPUT|ENAB|POLL);
uptr->SNS = SNS_INTVENT;
uptr->BPTR = 0;
uptr->IPTR = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
return SCPE_OK;
}
if (uptr->u3 & ADDR) {
if (uptr->CMD & ADDR) {
ch = 0x16;
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d addr %02x\n", unit, ch);
uptr->u3 &= ~ADDR;
uptr->CMD &= ~ADDR;
if (chan_write_byte( addr, &ch)) {
uptr->u3 &= ~(ADDR9|0xff);
uptr->CMD &= ~(ADDR9|0xff);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
return SCPE_OK;
}
if (uptr->u3 & ADDR9) {
uptr->u3 &= ~(ADDR9|0xff);
if (uptr->CMD & ADDR9) {
uptr->CMD &= ~(ADDR9|0xff);
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d addr9 %02x\n", unit, ch);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
return SCPE_OK;
}
} else if (uptr->u3 & BREAK) {
uptr->u3 &= ~(0xff|BREAK|INPUT);
uptr->u4 = SNS_INTVENT;
} else if (uptr->CMD & BREAK) {
uptr->CMD &= ~(0xff|BREAK|INPUT);
uptr->SNS = SNS_INTVENT;
uptr->BPTR = 0;
uptr->IPTR = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
return SCPE_OK;
} else if (uptr->u3 & INPUT) {
} else if (uptr->CMD & INPUT) {
if (uptr->BPTR == uptr->IPTR) {
uptr->u3 &= ~(0xff|INPUT);
uptr->CMD &= ~(0xff|INPUT);
uptr->BPTR = 0;
uptr->IPTR = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
@ -390,7 +395,7 @@ t_stat coml_srv(UNIT * uptr)
}
ch = com_buf[unit][uptr->IPTR++];
if (chan_write_byte( addr, &ch)) {
uptr->u3 &= ~(0xff|INPUT);
uptr->CMD &= ~(0xff|INPUT);
uptr->IPTR = 0;
uptr->BPTR = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
@ -402,11 +407,11 @@ t_stat coml_srv(UNIT * uptr)
break;
case CMD_WR: /* Write data to com line */
uptr->u4 = 0;
if (uptr->u3 & ENAB) {
uptr->SNS = 0;
if (uptr->CMD & ENAB) {
if (com_ldsc[unit].conn == 0) {
uptr->u3 &= ~(0xff|BREAK|INPUT|ENAB|POLL);
uptr->u4 = SNS_INTVENT;
uptr->CMD &= ~(0xff|BREAK|INPUT|ENAB|POLL);
uptr->SNS = SNS_INTVENT;
uptr->BPTR = 0;
uptr->IPTR = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
@ -414,7 +419,7 @@ t_stat coml_srv(UNIT * uptr)
}
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d write\n", unit);
if (chan_read_byte (addr, &ch)) {
uptr->u3 &= ~0xff;
uptr->CMD &= ~0xff;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
} else {
int32 data;
@ -422,16 +427,16 @@ t_stat coml_srv(UNIT * uptr)
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d send %02x %02x '%c'\n",
unit, ch, data, isprint(data)? data: '^');
if (ch == 0x1f) { /* Check for address character */
uptr->u3 |= ADDR;
uptr->CMD |= ADDR;
} else if (ch == 0x16) {
uptr->u3 &= ~ADDR;
uptr->CMD &= ~ADDR;
} else if (ch == 0xb8) { /* Bypass */
uptr->u3 |= BYPASS;
uptr->CMD |= BYPASS;
} else if (ch == 0x58) { /* Restore */
uptr->u3 &= ~(BYPASS|ADDR|ADDR9);
} else if ((uptr->u3 & ADDR) != 0 && ch == 0x13) {
uptr->u3 |= ADDR9;
} else if ((uptr->u3 & ADDR) == 0 && data != 0xff) {
uptr->CMD &= ~(BYPASS|ADDR|ADDR9);
} else if ((uptr->CMD & ADDR) != 0 && ch == 0x13) {
uptr->CMD |= ADDR9;
} else if ((uptr->CMD & ADDR) == 0 && data != 0xff) {
data = sim_tt_outcvt(data, TT_GET_MODE(uptr->flags) |
TTUF_KSR);
tmxr_putc_ln( &com_ldsc[unit], data);
@ -442,81 +447,81 @@ t_stat coml_srv(UNIT * uptr)
}
} else {
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d write error\n", unit);
uptr->u3 &= ~0xff;
uptr->CMD &= ~0xff;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
}
break;
case CMD_BRK: /* Send break signal */
uptr->u3 &= ~0xff;
uptr->u4 = 0;
uptr->CMD &= ~0xff;
uptr->SNS = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
case CMD_PREP: /* Wait for incoming data */
uptr->u4 = 0;
if (uptr->u3 & ENAB) {
uptr->SNS = 0;
if (uptr->CMD & ENAB) {
if (com_ldsc[unit].conn == 0) {
uptr->u3 &= ~(0xff|BREAK|INPUT|ENAB|POLL);
uptr->u4 = SNS_INTVENT;
uptr->CMD &= ~(0xff|BREAK|INPUT|ENAB|POLL);
uptr->SNS = SNS_INTVENT;
uptr->BPTR = 0;
uptr->IPTR = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
return SCPE_OK;
}
uptr->u3 &= ~(ADDR|ADDR9);
if (uptr->u3 & (INPUT|BREAK)) {
uptr->u3 &= ~0xff;
uptr->CMD &= ~(ADDR|ADDR9);
if (uptr->CMD & (INPUT|BREAK)) {
uptr->CMD &= ~0xff;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
} else {
sim_activate(uptr, 200);
}
} else {
uptr->u3 &= ~0xff;
uptr->CMD &= ~0xff;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
}
break;
case CMD_SRCH: /* Wait for EOT character */
uptr->u3 &= ~0xff;
uptr->u4 = 0;
uptr->CMD &= ~0xff;
uptr->SNS = 0;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
case CMD_ENB: /* Enable line */
uptr->u4 = 0;
if ((uptr->u3 & (POLL|ENAB)) == ENAB) {
uptr->u3 &= ~0xff;
uptr->SNS = 0;
if ((uptr->CMD & (POLL|ENAB)) == ENAB) {
uptr->CMD &= ~0xff;
uptr->BPTR = 0;
uptr->IPTR = 0;
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d enable connect\n", unit);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
} else if ((uptr->u3 & POLL) == 0) {
} else if ((uptr->CMD & POLL) == 0) {
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d enable\n", unit);
(void)tmxr_set_get_modem_bits(&com_ldsc[unit], TMXR_MDM_DTR,
0, NULL);
uptr->u3 |= POLL;
uptr->CMD |= POLL;
}
break;
case CMD_DIS: /* Disable line */
uptr->u4 = 0;
uptr->SNS = 0;
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d disable\n", unit);
(void)tmxr_set_get_modem_bits(&com_ldsc[unit], 0, TMXR_MDM_DTR, NULL);
(void)tmxr_reset_ln(&com_ldsc[unit]);
uptr->u3 &= ~(0xff|POLL|ENAB) ;
uptr->CMD &= ~(0xff|POLL|ENAB) ;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
}
if (uptr->u3 & ENAB) {
if (uptr->CMD & ENAB) {
if (cmd == CMD_RD || cmd == CMD_PREP) {
if (tmxr_rqln(&com_ldsc[unit]) > 0) {
int32 data = tmxr_getc_ln (&com_ldsc[unit]);
ch = com_2741_in[data & 0x7f];
sim_debug(DEBUG_DATA, dptr, "COML: unit=%d read '%c' %02x\n", unit, data, ch);
if (data & SCPE_BREAK) {
uptr->u3 |= BREAK;
uptr->CMD |= BREAK;
return SCPE_OK;
}
/* Handle end of buffer */
@ -525,7 +530,7 @@ t_stat coml_srv(UNIT * uptr)
case '\n':
com_buf[unit][uptr->BPTR++] = 0x5b;
com_buf[unit][uptr->BPTR++] = 0x1f;
uptr->u3 |= INPUT;
uptr->CMD |= INPUT;
uptr->IPTR = 0;
tmxr_putc_ln( &com_ldsc[unit], '\r');
tmxr_putc_ln( &com_ldsc[unit], '\n');
@ -551,7 +556,7 @@ t_stat coml_srv(UNIT * uptr)
break;
case 03: /* ^C */
uptr->u3 |= BREAK;
uptr->CMD |= BREAK;
break;
default:
@ -560,13 +565,13 @@ t_stat coml_srv(UNIT * uptr)
sim_putchar('\007');
} else {
com_buf[unit][uptr->BPTR++] = ch;
if ((uptr->u3 & BYPASS) == 0)
if ((uptr->CMD & BYPASS) == 0)
tmxr_putc_ln( &com_ldsc[unit], data);
}
} else {
com_buf[unit][uptr->BPTR++] = 0x5b;
com_buf[unit][uptr->BPTR++] = 0x1f;
uptr->u3 |= INPUT;
uptr->CMD |= INPUT;
uptr->BPTR &= 0xff;
}
}
@ -590,16 +595,16 @@ t_stat com_scan(UNIT * uptr)
if (ln >= 0) { /* got one? rcv enb*/
line = &coml_unit[ln];
sim_debug(DEBUG_DETAIL, &com_dev, "COM line connect %d\n", ln);
if (line->u3 & ENAB) /* Already connected */
if (line->CMD & ENAB) /* Already connected */
return SCPE_OK;
if ((line->u3 & POLL) == 0) { /* Check if not polling */
if ((line->CMD & POLL) == 0) { /* Check if not polling */
(void)tmxr_set_get_modem_bits(&com_ldsc[ln], 0,
TMXR_MDM_DTR, NULL);
(void)tmxr_reset_ln(&com_ldsc[ln]);
} else {
com_ldsc[ln].rcve = 1; /* Mark as ok */
line->u3 &= ~POLL;
line->u3 |= ENAB;
line->CMD &= ~POLL;
line->CMD |= ENAB;
sim_debug(DEBUG_DETAIL, &com_dev, "COM line connect %d\n", ln);
sim_activate(line, 200);
}
@ -634,7 +639,7 @@ com_attach(UNIT * uptr, CONST char *cptr)
// (void)tmxr_set_line_modem_control(&com_ldsc[i], TRUE);
// (void)tmxr_set_get_modem_bits(&com_ldsc[i], 0, TMXR_MDM_DTR, NULL);
// (void)tmxr_reset_ln(&com_ldsc[i]);
coml_unit[i].u3 &= ~0xffff;
coml_unit[i].CMD &= ~0xffff;
}
sim_activate(uptr, tmxr_poll);
return SCPE_OK;
@ -649,7 +654,7 @@ com_detach(UNIT * uptr)
for (i = 0; i< com_desc.lines; i++) {
(void)tmxr_set_get_modem_bits(&com_ldsc[i], 0, TMXR_MDM_DTR, NULL);
(void)tmxr_reset_ln(&com_ldsc[i]);
coml_unit[i].u3 &= ~0xffff;
coml_unit[i].CMD &= ~0xffff;
}
sim_cancel(uptr);
r = tmxr_detach(&com_desc, uptr);

View File

@ -1,6 +1,6 @@
/* ibm360_con.c: IBM 360 Inquiry console.
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -49,6 +49,8 @@
#define CON_REQ 0x400 /* Request key pressed */
#define CON_OUTPUT 0x800 /* Output characters since R */
/* Upper 11 bits of u3 hold the device address */
/* Input buffer pointer held in u4 */
/* in u5 packs sense byte 0,1 and 3 */
@ -56,7 +58,9 @@
#define SNS_CMDREJ 0x80 /* Command reject */
#define SNS_INTVENT 0x40 /* Unit intervention required */
#define CMD u3
#define IPTR u4
#define SNS u5
/* std devices. data structures
@ -110,81 +114,81 @@ void
con_ini(UNIT *uptr, t_bool f) {
int u = (uptr - con_unit);
con_data[u].inptr = 0;
uptr->u3 &= ~CON_MSK;
uptr->u5 = 0;
uptr->CMD &= ~CON_MSK;
uptr->SNS = 0;
sim_activate(uptr, 1000);
}
uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
int u = (uptr - con_unit);
if ((uptr->u3 & CON_MSK) != 0)
if ((uptr->CMD & CON_MSK) != 0)
return SNS_BSY;
if ((cmd & 0xf0) != 0) {
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
}
switch (cmd & 0x7) {
case 2: /* Read command */
sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd RD\n", u);
if (uptr->u3 & CON_REQ) {
if (uptr->CMD & CON_REQ) {
return SNS_ATTN|SNS_BSY;
}
if ((uptr->u3 & CON_INPUT) == 0 &&
(con_data[u].inptr == 0 || uptr->u3 & CON_CR)) {
if ((uptr->CMD & CON_INPUT) == 0 &&
(con_data[u].inptr == 0 || uptr->CMD & CON_CR)) {
/* Activate input so we can get response */
if ((uptr->u3 & CON_OUTPUT) != 0) {
if ((uptr->CMD & CON_OUTPUT) != 0) {
sim_putchar('\r');
sim_putchar('\n');
uptr->u3 &= ~CON_OUTPUT;
uptr->CMD &= ~CON_OUTPUT;
}
sim_putchar('I');
sim_putchar(' ');
}
uptr->u4 = 0;
uptr->u3 |= cmd & CON_MSK;
uptr->u5 = 0;
uptr->IPTR = 0;
uptr->CMD |= cmd & CON_MSK;
uptr->SNS = 0;
return 0;
case 1: /* Write command */
sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd WR\n", u);
if (uptr->u3 & CON_REQ) {
if (uptr->CMD & CON_REQ) {
return SNS_ATTN|SNS_BSY;
}
uptr->u3 |= cmd & CON_MSK;
uptr->u5 = 0;
if (uptr->u3 & CON_CR) {
uptr->CMD |= cmd & CON_MSK;
uptr->SNS = 0;
if (uptr->CMD & CON_CR) {
sim_putchar('R');
sim_putchar(' ');
uptr->u3 &= ~CON_CR;
uptr->u3 |= CON_OUTPUT;
uptr->CMD &= ~CON_CR;
uptr->CMD |= CON_OUTPUT;
}
return 0;
case 3: /* Control */
sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd NOP\n", u);
if (uptr->u3 & CON_REQ) {
if (uptr->CMD & CON_REQ) {
return SNS_ATTN|SNS_BSY;
}
uptr->u5 = 0;
uptr->SNS = 0;
return SNS_CHNEND|SNS_DEVEND;
case 0: /* Status */
break;
case 4: /* Sense */
uptr->u3 |= cmd & CON_MSK;
uptr->CMD |= cmd & CON_MSK;
return 0;
default: /* invalid command */
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
break;
}
if (uptr->u5)
if (uptr->SNS)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
}
@ -192,9 +196,9 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
/* Handle transfer of data for printer */
t_stat
con_srv(UNIT *uptr) {
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
int u = (uptr - con_unit);
int cmd = uptr->u3 & CON_MSK;
int cmd = uptr->CMD & CON_MSK;
t_stat r = SCPE_ARG; /* Force error if not set */
uint8 ch;
int i;
@ -203,12 +207,12 @@ con_srv(UNIT *uptr) {
switch (cmd) {
case 4: /* Sense */
sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd SNS %02x\n", u, uptr->u5);
sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd SNS %02x\n", u, uptr->SNS);
/* Check if request pending */
ch = uptr->u5;
ch = uptr->SNS;
chan_write_byte(addr, &ch);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
uptr->u3 &= ~(CON_MSK);
uptr->CMD &= ~(CON_MSK);
break;
case CON_WR:
@ -217,58 +221,58 @@ con_srv(UNIT *uptr) {
if (cmd == CON_ACR) {
sim_putchar('\r');
sim_putchar('\n');
uptr->u3 |= CON_CR;
uptr->u3 &= ~CON_OUTPUT;
uptr->CMD |= CON_CR;
uptr->CMD &= ~CON_OUTPUT;
}
uptr->u3 &= ~CON_MSK;
uptr->CMD &= ~CON_MSK;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
delay = 40000;
} else {
if (ch == 0x15) {
sim_putchar('\r');
sim_putchar('\n');
uptr->u3 |= CON_CR;
uptr->u3 &= ~CON_OUTPUT;
uptr->CMD |= CON_CR;
uptr->CMD &= ~CON_OUTPUT;
} else {
ch = ebcdic_to_ascii[ch];
if (ch != 0) {
if (!isprint(ch))
ch = '_';
sim_putchar(ch);
uptr->u3 &= ~CON_OUTPUT;
uptr->CMD &= ~CON_OUTPUT;
}
}
}
break;
case CON_RD:
if (uptr->u3 & CON_INPUT) {
uptr->u3 &= ~CON_REQ;
if (uptr->CMD & CON_INPUT) {
uptr->CMD &= ~CON_REQ;
if (con_data[u].inptr == 0) {
uptr->u3 &= ~CON_INPUT;
uptr->CMD &= ~CON_INPUT;
con_data[u].inptr = 0;
cmd = 0;
uptr->u3 &= ~(CON_MSK);
uptr->CMD &= ~(CON_MSK);
sim_debug(DEBUG_CMD, &con_dev, "%d: devend\n", u);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
}
ch = con_data[u].ibuff[uptr->u4++];
ch = con_data[u].ibuff[uptr->IPTR++];
sim_debug(DEBUG_CMD, &con_dev, "%d: rd %02x\n", u, ch);
if (chan_write_byte(addr, &ch)) {
uptr->u3 &= ~CON_INPUT;
uptr->CMD &= ~CON_INPUT;
con_data[u].inptr = 0;
cmd = 0;
uptr->u3 &= ~(CON_MSK);
uptr->CMD &= ~(CON_MSK);
sim_debug(DEBUG_CMD, &con_dev, "%d: devend input\n", u);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
} else {
if (uptr->u4 == con_data[u].inptr) {
uptr->u3 &= ~CON_INPUT;
if (uptr->IPTR == con_data[u].inptr) {
uptr->CMD &= ~CON_INPUT;
con_data[u].inptr = 0;
cmd = 0;
uptr->u3 &= ~(CON_MSK);
uptr->CMD &= ~(CON_MSK);
sim_debug(DEBUG_CMD, &con_dev, "%d: devend\n", u);
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
}
@ -280,22 +284,22 @@ con_srv(UNIT *uptr) {
r = sim_poll_kbd();
if (r & SCPE_KFLAG) {
ch = r & 0377;
if ((uptr->u3 & CON_INPUT) == 0) {
if ((uptr->CMD & CON_INPUT) == 0) {
/* Handle end of buffer */
switch (ch) {
case '\r':
case '\n':
sim_debug(DEBUG_DATA, &con_dev, "%d: ent\n", u);
uptr->u3 |= CON_INPUT;
uptr->u3 |= CON_CR;
uptr->u3 &= ~CON_OUTPUT;
uptr->CMD |= CON_INPUT;
uptr->CMD |= CON_CR;
uptr->CMD &= ~CON_OUTPUT;
sim_putchar('\r');
sim_putchar('\n');
/* Fall through */
case 033: /* request key */
if (cmd != CON_RD) {
uptr->u3 |= CON_REQ;
uptr->CMD |= CON_REQ;
}
break;
case 0177:
@ -337,7 +341,7 @@ con_srv(UNIT *uptr) {
} else {
if (cmd == CON_RD && ch == 03) { /* Cancel */
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
uptr->u3 &= ~CON_INPUT;
uptr->CMD &= ~CON_INPUT;
con_data[u].inptr = 0;
cmd = 0;
} else {
@ -346,10 +350,10 @@ con_srv(UNIT *uptr) {
}
}
if (cmd == 0 && uptr->u3 & CON_REQ) {
if (cmd == 0 && uptr->CMD & CON_REQ) {
sim_debug(DEBUG_CMD, &con_dev, "%d: setattn %x\n", u, addr);
set_devattn(addr, SNS_ATTN);
uptr->u3 &= ~CON_REQ;
uptr->CMD &= ~CON_REQ;
}
sim_activate(uptr, delay);
return SCPE_OK;

View File

@ -1,6 +1,6 @@
/* ibm360_cpu.c: ibm 360 cpu simulator.
Copyright (c) 2019, Richard Cornwell
Copyright (c) 2019-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* ibm360_defs.h: IBM 360 simulator definitions
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -86,12 +86,8 @@ typedef struct dib {
} DIB;
#define DEV_V_ADDR DEV_V_UF /* Pointer to device address */
#define DEV_ADDR_MASK (0x7ff << DEV_V_ADDR)
#define DEV_V_UADDR (DEV_V_UF + 10) /* Device address in Unit */
#define DEV_UADDR (1 << DEV_V_UADDR)
#define GET_DADDR(x) (0x7ff & ((x) >> DEV_V_ADDR))
#define DEV_ADDR(x) ((x) << DEV_V_ADDR)
#define UNIT_V_ADDR 20
#define UNIT_ADDR_MASK (0x7ff << UNIT_V_ADDR)

View File

@ -1,6 +1,6 @@
/* ibm360_lpr.c: IBM 360 Line Printer
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -48,6 +48,8 @@
#define LPR_CMDMSK 0xff /* Mask command part. */
#define LPR_FULL 0x100 /* Buffer full */
/* Upper 11 bits of u3 hold the device address */
/* u4 holds current line */
/* in u5 packs sense byte 0,1 and 3 */
/* Sense byte 0 */
@ -61,6 +63,11 @@
#define SNS_CHN9 0x01 /* Channel 9 on printer */
/* u6 hold buffer position */
#define CMD u3
#define LINE u4
#define SNS u5
#define POS u6
/* std devices. data structures
@ -138,7 +145,7 @@ lpr_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
if (i < 20 || i > 100)
return SCPE_ARG;
uptr->capac = i;
uptr->u4 = 0;
uptr->LINE = 0;
return SCPE_OK;
}
@ -163,7 +170,7 @@ print_line(UNIT * uptr)
memset(out, ' ', sizeof(out));
/* Scan each column */
for (i = 0; i < uptr->u6; i++) {
for (i = 0; i < uptr->POS; i++) {
int ch = lpr_data[u].lbuff[i];
ch = ebcdic_to_ascii[ch];
@ -182,9 +189,9 @@ print_line(UNIT * uptr)
sim_fwrite(&out, 1, i, uptr->fileref);
uptr->pos += i;
sim_debug(DEBUG_DETAIL, &lpr_dev, "%s", out);
uptr->u4++;
if ((t_addr)uptr->u4 > uptr->capac) {
uptr->u4 = 1;
uptr->LINE++;
if ((t_addr)uptr->LINE > uptr->capac) {
uptr->LINE = 1;
}
memset(&lpr_data[u].lbuff[0], 0, 144);
@ -193,7 +200,7 @@ print_line(UNIT * uptr)
uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd)
{
if ((uptr->u3 & LPR_CMDMSK) != 0) {
if ((uptr->CMD & LPR_CMDMSK) != 0) {
if ((uptr->flags & UNIT_ATT) != 0)
return SNS_BSY;
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
@ -203,35 +210,35 @@ uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd)
switch (cmd & 0x3) {
case 1: /* Write command */
uptr->u3 &= ~(LPR_CMDMSK);
uptr->u3 |= (cmd & LPR_CMDMSK);
uptr->CMD &= ~(LPR_CMDMSK);
uptr->CMD |= (cmd & LPR_CMDMSK);
sim_activate(uptr, 10); /* Start unit off */
uptr->u5 = 0;
uptr->u6 = 0;
uptr->SNS = 0;
uptr->POS = 0;
return 0;
case 3: /* Carrage control */
uptr->u3 &= ~(LPR_CMDMSK);
uptr->u3 |= (cmd & LPR_CMDMSK);
uptr->CMD &= ~(LPR_CMDMSK);
uptr->CMD |= (cmd & LPR_CMDMSK);
sim_activate(uptr, 10); /* Start unit off */
uptr->u5 = 0;
uptr->u6 = 0;
uptr->SNS = 0;
uptr->POS = 0;
return SNS_CHNEND;
case 0: /* Status */
if (cmd == 0x4) { /* Sense */
uptr->u3 &= ~(LPR_CMDMSK);
uptr->u3 |= (cmd & LPR_CMDMSK);
uptr->CMD &= ~(LPR_CMDMSK);
uptr->CMD |= (cmd & LPR_CMDMSK);
sim_activate(uptr, 10); /* Start unit off */
return 0;
}
break;
default: /* invalid command */
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
break;
}
if (uptr->u5 & 0xff)
if (uptr->SNS & 0xff)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
}
@ -239,43 +246,43 @@ uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd)
/* Handle transfer of data for printer */
t_stat
lpr_srv(UNIT *uptr) {
int addr = GET_UADDR(uptr->u3);
int addr = GET_UADDR(uptr->CMD);
int u = (uptr - lpr_unit);
int cmd = (uptr->u3 & 0x7);
int cmd = (uptr->CMD & 0x7);
if (cmd == 4) {
uint8 ch = uptr->u5;
uptr->u3 &= ~(LPR_CMDMSK);
uint8 ch = uptr->SNS;
uptr->CMD &= ~(LPR_CMDMSK);
chan_write_byte(addr, &ch);
chan_end(addr, SNS_DEVEND|SNS_CHNEND);
return SCPE_OK;
}
if (cmd == 7) {
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u6 = 0;
uptr->CMD &= ~(LPR_FULL|LPR_CMDMSK);
uptr->POS = 0;
chan_end(addr, SNS_DEVEND|SNS_CHNEND);
return SCPE_OK;
}
if ((uptr->u3 & LPR_FULL) || cmd == 0x3) {
if ((uptr->CMD & LPR_FULL) || cmd == 0x3) {
print_line(uptr);
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u6 = 0;
uptr->CMD &= ~(LPR_FULL|LPR_CMDMSK);
uptr->POS = 0;
set_devattn(addr, SNS_DEVEND);
return SCPE_OK;
}
/* Copy next column over */
if (cmd == 1 && (uptr->u3 & LPR_FULL) == 0) {
if(chan_read_byte(addr, &lpr_data[u].lbuff[uptr->u6])) {
uptr->u3 |= LPR_FULL;
if (cmd == 1 && (uptr->CMD & LPR_FULL) == 0) {
if(chan_read_byte(addr, &lpr_data[u].lbuff[uptr->POS])) {
uptr->CMD |= LPR_FULL;
} else {
sim_activate(uptr, 20);
uptr->u6++;
uptr->POS++;
}
if (uptr->u3 & LPR_FULL || uptr->u6 > 132) {
uptr->u3 |= LPR_FULL;
if (uptr->CMD & LPR_FULL || uptr->POS > 132) {
uptr->CMD |= LPR_FULL;
chan_end(addr, SNS_CHNEND);
sim_activate(uptr, 5000);
}
@ -285,9 +292,9 @@ lpr_srv(UNIT *uptr) {
void
lpr_ini(UNIT *uptr, t_bool f) {
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u4 = 0;
uptr->u5 = 0;
uptr->CMD &= ~(LPR_FULL|LPR_CMDMSK);
uptr->LINE = 0;
uptr->SNS = 0;
}
t_stat
@ -298,17 +305,17 @@ lpr_attach(UNIT * uptr, CONST char *file)
sim_switches |= SWMASK ('A'); /* Position to EOF */
if ((r = attach_unit(uptr, file)) != SCPE_OK)
return r;
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u4 = 0;
uptr->u5 = 0;
set_devattn(GET_UADDR(uptr->u3), SNS_DEVEND);
uptr->CMD &= ~(LPR_FULL|LPR_CMDMSK);
uptr->LINE = 0;
uptr->SNS = 0;
set_devattn(GET_UADDR(uptr->CMD), SNS_DEVEND);
return SCPE_OK;
}
t_stat
lpr_detach(UNIT * uptr)
{
if (uptr->u3 & LPR_FULL)
if (uptr->CMD & LPR_FULL)
print_line(uptr);
return detach_unit(uptr);
}

View File

@ -1,6 +1,6 @@
/* ibm360_mt.c: IBM 360 2400 Magnetic tape controller
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -87,6 +87,8 @@
#define MT_CONV 0x4000 /* Data converter on ignored 9 track */
#define MT_BUSY 0x8000 /* Flag to send a CUE */
/* Upper 11 bits of u3 hold the device address */
/* in u4 is current buffer position */
/* in u5 packs sense byte 0,1 and 3 */
@ -133,6 +135,11 @@
#define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF)
#define CLR_BUF(u) u->hwmark = 0xFFFFFFFF
#define CMD u3
#define POS u4
#define SNS u5
#define CPOS u6
uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ;
t_stat mt_srv(UNIT *);
t_stat mt_boot(int32, DEVICE *);
@ -225,11 +232,11 @@ uint8 bcd_to_ebcdic[64] = {
uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
DEVICE *dptr = find_dev_from_unit(uptr);
int unit = (uptr - dptr->units);
if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0 || (uptr->u3 & MT_CMDMSK) != 0) {
if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0 || (uptr->CMD & MT_CMDMSK) != 0) {
sim_debug(DEBUG_CMD, dptr, "CMD busy unit=%d %x\n", unit, cmd);
uptr->flags |= MT_BUSY; /* Flag we need to send CUE */
return SNS_BSY;
@ -243,23 +250,23 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
case 0x1: /* Write command */
case 0x2: /* Read command */
case 0xc: /* Read backward */
uptr->u5 = 0;
uptr->u5 |= SNS_TUASTA << 8;
uptr->SNS = 0;
uptr->SNS |= SNS_TUASTA << 8;
if ((uptr->flags & MTUF_9TR) == 0)
uptr->u5 |= (SNS_7TRACK << 8);
uptr->SNS |= (SNS_7TRACK << 8);
if (sim_tape_wrp(uptr))
uptr->u5 |= (SNS_WRP << 8);
uptr->SNS |= (SNS_WRP << 8);
if (sim_tape_bot(uptr))
uptr->u5 |= (SNS_LOAD << 8);
uptr->SNS |= (SNS_LOAD << 8);
/* Fall through */
case 0x4: /* Sense */
uptr->u3 &= ~(MT_CMDMSK);
uptr->u3 |= cmd & MT_CMDMSK;
uptr->CMD &= ~(MT_CMDMSK);
uptr->CMD |= cmd & MT_CMDMSK;
sim_activate(uptr, 1000); /* Start unit off */
CLR_BUF(uptr);
uptr->u4 = 0;
uptr->u6 = 0;
uptr->POS = 0;
uptr->CPOS = 0;
mt_busy[GET_DEV_BUF(dptr->flags)] = 1;
if ((cmd & 0x7) == 0x7) /* Quick end channel on control */
return SNS_CHNEND;
@ -268,13 +275,13 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
case 0x3: /* Control */
case 0xb: /* Control */
if ((uptr->flags & UNIT_ATT) == 0) {
uptr->u5 |= SNS_INTVENT;
uptr->SNS |= SNS_INTVENT;
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
}
if ((uptr->flags & MTUF_9TR) == 0) {
uptr->u5 |= (SNS_7TRACK << 8);
uptr->SNS |= (SNS_7TRACK << 8);
if ((cmd & 0xc0) == 0xc0) {
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
}
switch((cmd >> 3) & 07) {
@ -283,44 +290,44 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
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;
uptr->CMD &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
uptr->CMD |= (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);
uptr->CMD &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
uptr->CMD |= (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;
uptr->CMD &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
uptr->CMD |= (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;
uptr->CMD &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
uptr->CMD |= (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;
uptr->CMD &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK);
uptr->CMD |= (cmd & MT_MDEN_MSK) | MT_ODD | MT_TRANS;
break;
}
} else {
uptr->u3 &= ~MT_MDEN_MSK;
uptr->CMD &= ~MT_MDEN_MSK;
if (cmd & 0x8)
uptr->u3 |= MT_MDEN_800;
uptr->CMD |= MT_MDEN_800;
else
uptr->u3 |= MT_MDEN_1600;
uptr->CMD |= MT_MDEN_1600;
}
uptr->u5 = 0;
uptr->SNS = 0;
break;
case 0x0: /* Status */
break;
default: /* invalid command */
uptr->u5 |= SNS_CMDREJ;
uptr->SNS |= SNS_CMDREJ;
break;
}
if (uptr->u5 & 0xff)
if (uptr->SNS & 0xff)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
}
@ -355,7 +362,7 @@ t_stat mt_error(UNIT * uptr, uint16 addr, t_stat r, DEVICE * dptr)
break;
case MTSE_EOM: /* end of medium */
sim_debug(DEBUG_EXP, dptr, "EOT ");
uptr->u5 = SNS_EQUCHK;
uptr->SNS = SNS_EQUCHK;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
return SCPE_OK;
}
@ -366,10 +373,10 @@ t_stat mt_error(UNIT * uptr, uint16 addr, t_stat r, DEVICE * dptr)
/* Handle processing of tape requests. */
t_stat mt_srv(UNIT * uptr)
{
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
DEVICE *dptr = find_dev_from_unit(uptr);
int unit = (uptr - dptr->units);
int cmd = uptr->u3 & MT_CMDMSK;
int cmd = uptr->CMD & MT_CMDMSK;
int bufnum = GET_DEV_BUF(dptr->flags);
t_mtrlnt reclen;
t_stat r = SCPE_ARG; /* Force error if not set */
@ -377,9 +384,9 @@ t_stat mt_srv(UNIT * uptr)
int mode = 0;
if ((uptr->flags & UNIT_ATT) == 0) {
uptr->u5 |= SNS_INTVENT;
uptr->SNS |= SNS_INTVENT;
if (cmd != MT_SENSE) {
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
@ -392,30 +399,30 @@ t_stat mt_srv(UNIT * uptr)
break;
case MT_SENSE:
ch = uptr->u5 & 0xff;
ch = uptr->SNS & 0xff;
sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 1 %x\n", unit, ch);
chan_write_byte(addr, &ch) ;
ch = (uptr->u5 >> 8) & 0xff;
ch = (uptr->SNS >> 8) & 0xff;
sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 2 %x\n", unit, ch);
chan_write_byte(addr, &ch) ;
ch = 0xc0;
sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 3 %x\n", unit, ch);
chan_write_byte(addr, &ch) ;
ch = (uptr->u5 >> 16) & 0xff;
ch = (uptr->SNS >> 16) & 0xff;
sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 4 %x\n", unit, ch);
chan_write_byte(addr, &ch) ;
ch = 0;
chan_write_byte(addr, &ch) ;
chan_write_byte(addr, &ch);
uptr->u3 &= ~MT_CMDMSK;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
case MT_READ:
if (uptr->u3 & MT_READDONE) {
uptr->u3 &= ~(MT_CMDMSK|MT_READDONE);
if (uptr->CMD & MT_READDONE) {
uptr->CMD &= ~(MT_CMDMSK|MT_READDONE);
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
break;
@ -427,44 +434,44 @@ t_stat mt_srv(UNIT * uptr)
if ((r = sim_tape_rdrecf(uptr, &mt_buffer[bufnum][0], &reclen,
BUFFSIZE)) != MTSE_OK) {
sim_debug(DEBUG_DETAIL, dptr, " error %d\n", r);
uptr->u3 &= ~(MT_CMDMSK|MT_READDONE);
uptr->CMD &= ~(MT_CMDMSK|MT_READDONE);
return mt_error(uptr, addr, r, dptr);
}
uptr->u4 = 0;
uptr->POS = 0;
uptr->hwmark = reclen;
sim_debug(DEBUG_DETAIL, dptr, "Block %d chars\n", reclen);
}
ch = mt_buffer[bufnum][uptr->u4++];
ch = mt_buffer[bufnum][uptr->POS++];
/* if we are a 7track tape, handle conversion */
if ((uptr->flags & MTUF_9TR) == 0) {
mode = (uptr->u3 & MT_ODD) ? 0 : 0100;
mode = (uptr->CMD & 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);
uptr->u5 |= (SNS_VRC << 16) | SNS_DATCHK;
unit, uptr->POS-1, ch);
uptr->SNS |= (SNS_VRC << 16) | SNS_DATCHK;
}
ch &= 077;
if (uptr->u3 & MT_TRANS)
if (uptr->CMD & MT_TRANS)
ch = bcd_to_ebcdic[ch];
if (uptr->u3 & MT_CONV) {
if (uptr->CMD & MT_CONV) {
sim_debug(DEBUG_DATA, dptr, "Read raw data unit=%d %d %02x %02x\n",
unit, uptr->u4, ch, uptr->u6);
if (uptr->u6 == 0 && (t_addr)uptr->u4 < uptr->hwmark) {
uptr->u6 = MT_CONV1 | ch;
unit, uptr->POS, ch, uptr->CPOS);
if (uptr->CPOS == 0 && (t_addr)uptr->POS < uptr->hwmark) {
uptr->CPOS = MT_CONV1 | ch;
sim_activate(uptr, 20);
return SCPE_OK;
} else if ((uptr->u6 & 0xc0) == MT_CONV1) {
int t = uptr->u6 & 0x3F;
uptr->u6 = MT_CONV2 | ch;
} else if ((uptr->CPOS & 0xc0) == MT_CONV1) {
int t = uptr->CPOS & 0x3F;
uptr->CPOS = MT_CONV2 | ch;
ch = (t << 2) | ((ch >> 4) & 03);
} else if ((uptr->u6 & 0xc0) == MT_CONV2) {
int t = uptr->u6 & 0xf;
uptr->u6 = MT_CONV3 | ch;
} else if ((uptr->CPOS & 0xc0) == MT_CONV2) {
int t = uptr->CPOS & 0xf;
uptr->CPOS = MT_CONV3 | ch;
ch = (t << 4) | ((ch >> 2) & 0xf);
} else if ((uptr->u6 & 0xc0) == MT_CONV3) {
ch |= ((uptr->u6 & 0x3) << 6);
uptr->u6 = 0;
} else if ((uptr->CPOS & 0xc0) == MT_CONV3) {
ch |= ((uptr->CPOS & 0x3) << 6);
uptr->CPOS = 0;
}
}
}
@ -473,22 +480,22 @@ t_stat mt_srv(UNIT * uptr)
if (chan_write_byte(addr, &ch)) {
sim_debug(DEBUG_DATA, dptr, "Read unit=%d EOR\n\r", unit);
/* If not read whole record, skip till end */
if ((t_addr)uptr->u4 < uptr->hwmark) {
if ((t_addr)uptr->POS < uptr->hwmark) {
/* Send dummy character to force SLI */
chan_write_byte(addr, &ch);
sim_activate(uptr, (uptr->hwmark-uptr->u4) * 20);
uptr->u3 |= MT_READDONE;
sim_activate(uptr, (uptr->hwmark-uptr->POS) * 20);
uptr->CMD |= MT_READDONE;
break;
}
uptr->u3 &= ~MT_CMDMSK;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_DEVEND);
} else {
sim_debug(DEBUG_DATA, dptr, "Read data unit=%d %d %02x\n\r",
unit, uptr->u4, ch);
if ((t_addr)uptr->u4 >= uptr->hwmark) { /* In IRG */
unit, uptr->POS, ch);
if ((t_addr)uptr->POS >= uptr->hwmark) { /* In IRG */
/* Handle end of record */
uptr->u3 &= ~MT_CMDMSK;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
} else
@ -500,8 +507,8 @@ t_stat mt_srv(UNIT * uptr)
case MT_WRITE:
/* Check if write protected */
if (sim_tape_wrp(uptr)) {
uptr->u5 |= SNS_CMDREJ;
uptr->u3 &= ~MT_CMDMSK;
uptr->SNS |= SNS_CMDREJ;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
break;
@ -509,52 +516,52 @@ t_stat mt_srv(UNIT * uptr)
/* Grab data until channel has no more */
if (chan_read_byte(addr, &ch)) {
if (uptr->u4 > 0) { /* Only if data in record */
if (uptr->POS > 0) { /* Only if data in record */
reclen = uptr->hwmark;
sim_debug(DEBUG_DETAIL, dptr, "Write unit=%d Block %d chars\n",
unit, reclen);
r = sim_tape_wrrecf(uptr, &mt_buffer[bufnum][0], reclen);
uptr->u4 = 0;
uptr->u3 &= ~MT_CMDMSK;
uptr->POS = 0;
uptr->CMD &= ~MT_CMDMSK;
mt_error(uptr, addr, r, dptr); /* Record errors */
} else {
uptr->u5 |= SNS_WCZERO; /* Write with no data */
uptr->SNS |= SNS_WCZERO; /* Write with no data */
}
} else {
if ((uptr->flags & MTUF_9TR) == 0) {
mode = (uptr->u3 & MT_ODD) ? 0 : 0100;
if (uptr->u3 & MT_TRANS)
mode = (uptr->CMD & MT_ODD) ? 0 : 0100;
if (uptr->CMD & MT_TRANS)
ch = (ch & 0xf) | ((ch & 0x30) ^ 0x30);
if (uptr->u3 & MT_CONV) {
if (uptr->u6 == 0) {
uptr->u6 = MT_CONV1 | (ch & 0x3);
if (uptr->CMD & MT_CONV) {
if (uptr->CPOS == 0) {
uptr->CPOS = MT_CONV1 | (ch & 0x3);
ch >>= 2;
} else if ((uptr->u6 & 0xc0) == MT_CONV1) {
int t = uptr->u6 & 0x3;
uptr->u6 = MT_CONV2 | (ch & 0xf);
} else if ((uptr->CPOS & 0xc0) == MT_CONV1) {
int t = uptr->CPOS & 0x3;
uptr->CPOS = MT_CONV2 | (ch & 0xf);
ch = (t << 4) | ((ch >> 4) & 0xf);
} else if ((uptr->u6 & 0xc0) == MT_CONV2) {
int t = uptr->u6 & 0xf;
} else if ((uptr->CPOS & 0xc0) == MT_CONV2) {
int t = uptr->CPOS & 0xf;
ch = (t << 2) | ((ch >> 6) & 0x3);
ch ^= parity_table[ch & 077] ^ mode;
mt_buffer[bufnum][uptr->u4++] = ch;
uptr->u6 = 0;
mt_buffer[bufnum][uptr->POS++] = ch;
uptr->CPOS = 0;
}
}
ch &= 077;
ch |= parity_table[ch] ^ mode;
}
mt_buffer[bufnum][uptr->u4++] = ch;
mt_buffer[bufnum][uptr->POS++] = ch;
sim_debug(DEBUG_DATA, dptr, "Write data unit=%d %d %02o\n\r",
unit, uptr->u4, ch);
uptr->hwmark = uptr->u4;
unit, uptr->POS, ch);
uptr->hwmark = uptr->POS;
}
sim_activate(uptr, 20);
break;
case MT_RDBK:
if (uptr->u3 & MT_READDONE) {
uptr->u3 &= ~(MT_CMDMSK|MT_READDONE);
if (uptr->CMD & MT_READDONE) {
uptr->CMD &= ~(MT_CMDMSK|MT_READDONE);
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
return SCPE_OK;
@ -563,7 +570,7 @@ t_stat mt_srv(UNIT * uptr)
/* If at end of record, fill buffer */
if (BUF_EMPTY(uptr)) {
if (sim_tape_bot(uptr)) {
uptr->u3 &= ~MT_CMDMSK;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
@ -571,39 +578,39 @@ t_stat mt_srv(UNIT * uptr)
sim_debug(DEBUG_DETAIL, dptr, "Read backward unit=%d ", unit);
if ((r = sim_tape_rdrecr(uptr, &mt_buffer[bufnum][0], &reclen,
BUFFSIZE)) != MTSE_OK) {
uptr->u3 &= ~(MT_CMDMSK|MT_READDONE);
uptr->CMD &= ~(MT_CMDMSK|MT_READDONE);
return mt_error(uptr, addr, r, dptr);
}
uptr->u4 = reclen;
uptr->POS = reclen;
uptr->hwmark = reclen;
sim_debug(DEBUG_DETAIL, dptr, "Binary Block %d chars\n", reclen);
}
ch = mt_buffer[bufnum][--uptr->u4];
ch = mt_buffer[bufnum][--uptr->POS];
if ((uptr->flags & MTUF_9TR) == 0) {
mode = (uptr->u3 & MT_ODD) ? 0 : 0100;
mode = (uptr->CMD & MT_ODD) ? 0 : 0100;
ch &= 077;
if ((parity_table[ch & 077] ^ (ch & 0100) ^ mode) == 0) {
uptr->u5 |= (SNS_VRC << 16) | SNS_DATCHK;
uptr->SNS |= (SNS_VRC << 16) | SNS_DATCHK;
}
if (uptr->u3 & MT_TRANS)
if (uptr->CMD & MT_TRANS)
ch = bcd_to_ebcdic[ch];
if (uptr->u3 & MT_CONV) {
if (uptr->u6 == 0 && (t_addr)uptr->u4 < uptr->hwmark) {
uptr->u6 = MT_CONV1 | ch;
if (uptr->CMD & MT_CONV) {
if (uptr->CPOS == 0 && (t_addr)uptr->POS < uptr->hwmark) {
uptr->CPOS = MT_CONV1 | ch;
sim_activate(uptr, 20);
return SCPE_OK;
} else if ((uptr->u6 & 0xc0) == MT_CONV1) {
int t = uptr->u6 & 0x3F;
uptr->u6 = MT_CONV2 | ch;
} else if ((uptr->CPOS & 0xc0) == MT_CONV1) {
int t = uptr->CPOS & 0x3F;
uptr->CPOS = MT_CONV2 | ch;
ch = t | ((ch << 6) & 0xc0);
} else if ((uptr->u6 & 0xc0) == MT_CONV2) {
int t = uptr->u6 & 0x3C;
uptr->u6 = MT_CONV3 | ch;
} else if ((uptr->CPOS & 0xc0) == MT_CONV2) {
int t = uptr->CPOS & 0x3C;
uptr->CPOS = MT_CONV3 | ch;
ch = (t >> 2) | ((ch << 4) & 0xf0);
} else if ((uptr->u6 & 0xc0) == MT_CONV3) {
ch |= ((uptr->u6 & 0x30) >> 4);
uptr->u6 = 0;
} else if ((uptr->CPOS & 0xc0) == MT_CONV3) {
ch |= ((uptr->CPOS & 0x30) >> 4);
uptr->CPOS = 0;
}
}
}
@ -611,19 +618,19 @@ t_stat mt_srv(UNIT * uptr)
if (chan_write_byte(addr, &ch)) {
sim_debug(DEBUG_DATA, dptr, "Read unit=%d EOR\n\r", unit);
/* If not read whole record, skip till end */
if (uptr->u4 >= 0) {
sim_activate(uptr, (uptr->u4) * 20);
uptr->u3 |= MT_READDONE;
if (uptr->POS >= 0) {
sim_activate(uptr, (uptr->POS) * 20);
uptr->CMD |= MT_READDONE;
return SCPE_OK;
}
uptr->u3 &= ~MT_CMDMSK;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
} else {
sim_debug(DEBUG_DATA, dptr, "Read data unit=%d %d %02o\n\r",
unit, uptr->u4, ch);
if (uptr->u4 == 0) { /* In IRG */
uptr->u3 &= ~MT_CMDMSK;
unit, uptr->POS, ch);
if (uptr->POS == 0) { /* In IRG */
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
} else
@ -634,19 +641,19 @@ t_stat mt_srv(UNIT * uptr)
case 0xf:
switch (cmd) {
case MT_WTM:
if (uptr->u4 == 0) {
if (uptr->POS == 0) {
if (sim_tape_wrp(uptr)) {
uptr->u5 |= SNS_CMDREJ;
uptr->u3 &= ~MT_CMDMSK;
uptr->SNS |= SNS_CMDREJ;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
}
uptr->u4 ++;
uptr->POS ++;
sim_activate(uptr, 500);
} else {
sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
r = sim_tape_wrtmk(uptr);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
@ -654,24 +661,24 @@ t_stat mt_srv(UNIT * uptr)
break;
case MT_BSR:
switch (uptr->u4 ) {
switch (uptr->POS ) {
case 0:
if (sim_tape_bot(uptr)) {
uptr->u3 &= ~MT_CMDMSK;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
}
uptr->u4 ++;
uptr->POS ++;
sim_activate(uptr, 500);
break;
case 1:
uptr->u4++;
uptr->POS++;
sim_debug(DEBUG_DETAIL, dptr, "Backspace rec unit=%d ", unit);
r = sim_tape_sprecr(uptr, &reclen);
/* We don't set EOF on BSR */
if (r == MTSE_TMK) {
uptr->u4++;
uptr->POS++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else {
@ -680,12 +687,12 @@ t_stat mt_srv(UNIT * uptr)
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
@ -693,38 +700,38 @@ t_stat mt_srv(UNIT * uptr)
break;
case MT_BSF:
switch(uptr->u4) {
switch(uptr->POS) {
case 0:
if (sim_tape_bot(uptr)) {
uptr->u3 &= ~MT_CMDMSK;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
break;
}
uptr->u4 ++;
uptr->POS ++;
sim_activate(uptr, 500);
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Backspace file unit=%d\n", unit);
r = sim_tape_sprecr(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4++;
uptr->POS++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_BOT) {
uptr->u4+= 2;
uptr->POS+= 2;
sim_activate(uptr, 50);
} else {
sim_activate(uptr, 10 + (10 * reclen));
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
@ -732,21 +739,21 @@ t_stat mt_srv(UNIT * uptr)
break;
case MT_FSR:
switch(uptr->u4) {
switch(uptr->POS) {
case 0:
uptr->u4 ++;
uptr->POS ++;
sim_activate(uptr, 500);
break;
case 1:
uptr->u4++;
uptr->POS++;
sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit);
r = sim_tape_sprecf(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4 = 3;
uptr->POS = 3;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_EOM) {
uptr->u4 = 4;
uptr->POS = 4;
sim_activate(uptr, 50);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen);
@ -754,17 +761,17 @@ t_stat mt_srv(UNIT * uptr)
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
case 4:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
@ -772,20 +779,20 @@ t_stat mt_srv(UNIT * uptr)
break;
case MT_FSF:
switch(uptr->u4) {
switch(uptr->POS) {
case 0:
uptr->u4 ++;
uptr->POS ++;
sim_activate(uptr, 500);
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit);
r = sim_tape_sprecf(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4++;
uptr->POS++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_EOM) {
uptr->u4+= 2;
uptr->POS+= 2;
sim_activate(uptr, 50);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen);
@ -793,13 +800,13 @@ t_stat mt_srv(UNIT * uptr)
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
sim_debug(DEBUG_DETAIL, dptr, "Skip done unit=%d\n", unit);
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
@ -807,15 +814,15 @@ t_stat mt_srv(UNIT * uptr)
break;
case MT_ERG:
switch (uptr->u4) {
switch (uptr->POS) {
case 0:
if (sim_tape_wrp(uptr)) {
uptr->u5 |= SNS_CMDREJ;
uptr->u3 &= ~MT_CMDMSK;
uptr->SNS |= SNS_CMDREJ;
uptr->CMD &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
} else {
uptr->u4 ++;
uptr->POS ++;
sim_activate(uptr, 500);
}
break;
@ -823,36 +830,36 @@ t_stat mt_srv(UNIT * uptr)
sim_debug(DEBUG_DETAIL, dptr, "Erase unit=%d\n", unit);
r = sim_tape_wrgap(uptr, 35);
sim_activate(uptr, 5000);
uptr->u4++;
uptr->POS++;
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
}
break;
case MT_REW:
if (uptr->u4 == 0) {
uptr->u4 ++;
if (uptr->POS == 0) {
uptr->POS ++;
sim_activate(uptr, 30000);
mt_busy[bufnum] &= ~1;
} else {
sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
r = sim_tape_rewind(uptr);
set_devattn(addr, SNS_DEVEND);
}
break;
case MT_RUN:
if (uptr->u4 == 0) {
uptr->u4 ++;
if (uptr->POS == 0) {
uptr->POS ++;
mt_busy[bufnum] &= ~1;
sim_activate(uptr, 30000);
} else {
sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
uptr->CMD &= ~(MT_CMDMSK);
r = sim_tape_detach(uptr);
set_devattn(addr, SNS_DEVEND);
}
@ -867,9 +874,9 @@ mt_ini(UNIT * uptr, t_bool f)
{
DEVICE *dptr = find_dev_from_unit(uptr);
uptr->u3 &= UNIT_ADDR_MASK;
uptr->CMD &= UNIT_ADDR_MASK;
if ((uptr->flags & MTUF_9TR) == 0)
uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800;
uptr->CMD |= MT_ODD|MT_CONV|MT_MDEN_800;
mt_busy[GET_DEV_BUF(dptr->flags)] = 0;
}
@ -882,24 +889,24 @@ mt_reset(DEVICE * dptr)
t_stat
mt_attach(UNIT * uptr, CONST char *file)
{
uint16 addr = GET_UADDR(uptr->u3);
uint16 addr = GET_UADDR(uptr->CMD);
t_stat r;
if ((r = sim_tape_attach_ex(uptr, file, 0, 0)) != SCPE_OK)
return r;
set_devattn(addr, SNS_DEVEND);
uptr->u3 &= UNIT_ADDR_MASK;
uptr->u4 = 0;
uptr->u5 = 0;
uptr->CMD &= UNIT_ADDR_MASK;
uptr->POS = 0;
uptr->SNS = 0;
return SCPE_OK;
}
t_stat
mt_detach(UNIT * uptr)
{
uptr->u3 &= UNIT_ADDR_MASK;
uptr->u4 = 0;
uptr->u5 = 0;
uptr->CMD &= UNIT_ADDR_MASK;
uptr->POS = 0;
uptr->SNS = 0;
return sim_tape_detach(uptr);
}
@ -911,10 +918,10 @@ mt_boot(int32 unit_num, DEVICE * dptr)
if ((uptr->flags & UNIT_ATT) == 0)
return SCPE_UNATT; /* attached? */
if ((uptr->flags & MTUF_9TR) == 0) {
uptr->u3 &= UNIT_ADDR_MASK;
uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800;
uptr->CMD &= UNIT_ADDR_MASK;
uptr->CMD |= MT_ODD|MT_CONV|MT_MDEN_800;
}
return chan_boot(GET_UADDR(uptr->u3), dptr);
return chan_boot(GET_UADDR(uptr->CMD), dptr);
}
#endif

View File

@ -1,6 +1,6 @@
/* ibm360_sys.c: IBM 360 Simulator system interface.
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),