277 lines
8.8 KiB
C
277 lines
8.8 KiB
C
/* kx10_cp.c: PDP10 Card Punch
|
||
|
||
Copyright (c) 2016-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"),
|
||
to deal in the Software without restriction, including without limitation
|
||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
and/or sell copies of the Software, and to permit persons to whom the
|
||
Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
This is the standard card punch.
|
||
|
||
These units each buffer one record in local memory and signal
|
||
ready when the buffer is full or empty. The channel must be
|
||
ready to recieve/transmit data when they are activated since
|
||
they will transfer their block during chan_cmd. All data is
|
||
transmitted as BCD characters.
|
||
|
||
*/
|
||
|
||
#include "kx10_defs.h"
|
||
#include "sim_card.h"
|
||
#include "sim_defs.h"
|
||
#if (NUM_DEVS_CP > 0)
|
||
|
||
#define UNIT_CDP UNIT_ATTABLE | UNIT_DISABLE | UNIT_SEQ | MODE_DEC29
|
||
|
||
#define CP_DEVNUM 0110
|
||
|
||
#if KL
|
||
#define CP_DIS DEV_DIS
|
||
#endif
|
||
|
||
#ifndef CP_DIS
|
||
#define CP_DIS 0
|
||
#endif
|
||
|
||
|
||
/* std devices. data structures
|
||
|
||
cp_dev Card Punch device descriptor
|
||
cp_unit Card Punch unit descriptor
|
||
cp_reg Card Punch register list
|
||
cp_mod Card Punch modifiers list
|
||
*/
|
||
|
||
/* CONO Bits */
|
||
#define SET_DATA_REQ 0000010
|
||
#define CLR_DATA_REQ 0000020
|
||
#define SET_PUNCH_ON 0000040
|
||
#define CLR_END_CARD 0000100
|
||
#define EN_END_CARD 0000200
|
||
#define DIS_END_CARD 0000400
|
||
#define CLR_ERROR 0001000
|
||
#define EN_TROUBLE 0002000
|
||
#define DIS_TROUBLE 0004000
|
||
#define EJECT 0010000 /* Finish punch and eject */
|
||
#define OFFSET_CARD 0040000 /* Offset card stack */
|
||
#define CLR_PUNCH 0100000 /* Clear Trouble, Error, End */
|
||
|
||
/* CONI Bits */
|
||
#define PIA 0000007
|
||
#define DATA_REQ 0000010
|
||
#define PUNCH_ON 0000040
|
||
#define END_CARD 0000100 /* Eject or column 80 */
|
||
#define END_CARD_EN 0000200
|
||
#define CARD_IN_PUNCH 0000400 /* Card ready to punch */
|
||
#define ERROR 0001000 /* Punch error */
|
||
#define TROUBLE_EN 0002000
|
||
#define TROUBLE 0004000 /* Bit 18,22,23, or 21 */
|
||
#define EJECT_FAIL 0010000 /* Could not eject card 23 */
|
||
#define PICK_FAIL 0020000 /* Could not pick up card 22 */
|
||
#define NEED_OPR 0040000 /* Hopper empty, chip full 21 */
|
||
#define HOPPER_LOW 0100000 /* less 200 cards 20 */
|
||
#define TEST 0400000 /* In test mode 18 */
|
||
|
||
#define STATUS u3
|
||
#define COL u4
|
||
|
||
t_stat cp_devio(uint32 dev, uint64 *data);
|
||
t_stat cp_srv(UNIT *);
|
||
t_stat cp_reset(DEVICE *);
|
||
t_stat cp_attach(UNIT *, CONST char *);
|
||
t_stat cp_detach(UNIT *);
|
||
t_stat cp_help(FILE *, DEVICE *, UNIT *, int32, const char *);
|
||
const char *cp_description(DEVICE *dptr);
|
||
uint16 cp_buffer[80];
|
||
|
||
|
||
DIB cp_dib = { CP_DEVNUM, 1, cp_devio, NULL};
|
||
|
||
UNIT cp_unit = {UDATA(cp_srv, UNIT_CDP, 0), 2000 };
|
||
|
||
MTAB cp_mod[] = {
|
||
{ MODE_CHAR, MODE_026, "IBM026", "IBM026", NULL, NULL, NULL,
|
||
"IBM 026 punch encoding"},
|
||
{ MODE_CHAR, MODE_029, "IBM029", "IBM029", NULL, NULL, NULL,
|
||
"IBM 029 punch encoding"},
|
||
{ MODE_CHAR, MODE_DEC29, "DEC029", "DEC029", NULL, NULL, NULL,
|
||
"DEC 029 punch encoding"},
|
||
{MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||
&sim_card_set_fmt, &sim_card_show_fmt, NULL},
|
||
{0}
|
||
};
|
||
|
||
REG cp_reg[] = {
|
||
{BRDATA(BUFF, cp_buffer, 16, 16, sizeof(cp_buffer)/sizeof(uint16)), REG_HRO},
|
||
{0}
|
||
};
|
||
|
||
DEVICE cp_dev = {
|
||
"CP", &cp_unit, cp_reg, cp_mod,
|
||
NUM_DEVS_CP, 8, 15, 1, 8, 8,
|
||
NULL, NULL, NULL, NULL, &cp_attach, &cp_detach,
|
||
&cp_dib, DEV_DISABLE | DEV_DEBUG | DEV_CARD | CP_DIS, 0, crd_debug,
|
||
NULL, NULL, &cp_help, NULL, NULL, &cp_description
|
||
};
|
||
|
||
|
||
|
||
|
||
/* Card punch routine
|
||
*/
|
||
|
||
t_stat cp_devio(uint32 dev, uint64 *data) {
|
||
UNIT *uptr = &cp_unit;
|
||
uint16 col;
|
||
|
||
switch(dev & 3) {
|
||
case CONI:
|
||
*data = uptr->STATUS;
|
||
sim_debug(DEBUG_CONI, &cp_dev, "CP: CONI %012llo\n", *data);
|
||
break;
|
||
case CONO:
|
||
clr_interrupt(dev);
|
||
sim_debug(DEBUG_CONO, &cp_dev, "CP: CONO %012llo\n", *data);
|
||
uptr->STATUS &= ~PIA;
|
||
uptr->STATUS |= *data & PIA;
|
||
if (*data & CLR_PUNCH) {
|
||
uptr->STATUS &= ~(TROUBLE|ERROR|END_CARD|END_CARD_EN|TROUBLE_EN);
|
||
break;
|
||
}
|
||
if (*data & SET_DATA_REQ) {
|
||
uptr->STATUS |= DATA_REQ;
|
||
set_interrupt(dev, uptr->STATUS);
|
||
}
|
||
if (*data & CLR_DATA_REQ)
|
||
uptr->STATUS &= ~DATA_REQ;
|
||
if (*data & CLR_END_CARD)
|
||
uptr->STATUS &= ~END_CARD;
|
||
if (*data & EN_END_CARD)
|
||
uptr->STATUS |= END_CARD_EN;
|
||
if (*data & DIS_END_CARD)
|
||
uptr->STATUS &= ~END_CARD_EN;
|
||
if (*data & EN_TROUBLE)
|
||
uptr->STATUS |= TROUBLE_EN;
|
||
if (*data & DIS_TROUBLE)
|
||
uptr->STATUS &= ~TROUBLE_EN;
|
||
if (*data & EJECT && uptr->STATUS & CARD_IN_PUNCH) {
|
||
uptr->COL = 80;
|
||
uptr->STATUS &= ~DATA_REQ;
|
||
sim_activate(uptr, uptr->wait);
|
||
}
|
||
if ((uptr->STATUS & (TROUBLE|TROUBLE_EN)) == (TROUBLE|TROUBLE_EN))
|
||
set_interrupt(CP_DEVNUM, uptr->STATUS);
|
||
if ((uptr->STATUS & (END_CARD|END_CARD_EN)) == (END_CARD|END_CARD_EN))
|
||
set_interrupt(CP_DEVNUM, uptr->STATUS);
|
||
if (*data & PUNCH_ON) {
|
||
uptr->STATUS |= PUNCH_ON;
|
||
sim_activate(uptr, uptr->wait);
|
||
}
|
||
break;
|
||
case DATAI:
|
||
*data = 0;
|
||
break;
|
||
case DATAO:
|
||
col = *data & 0xfff;
|
||
cp_buffer[uptr->COL++] = col;
|
||
uptr->STATUS &= ~DATA_REQ;
|
||
clr_interrupt(dev);
|
||
sim_debug(DEBUG_DATAIO, &cp_dev, "CP: DATAO %012llo %d\n", *data,
|
||
uptr->COL);
|
||
sim_activate(uptr, uptr->wait);
|
||
break;
|
||
}
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* Handle transfer of data for card punch */
|
||
t_stat
|
||
cp_srv(UNIT *uptr) {
|
||
|
||
if (uptr->STATUS & PUNCH_ON) {
|
||
|
||
uptr->STATUS |= CARD_IN_PUNCH;
|
||
if (uptr->STATUS & DATA_REQ) {
|
||
sim_activate(uptr, uptr->wait);
|
||
return SCPE_OK;
|
||
}
|
||
if (uptr->COL < 80) {
|
||
if ((uptr->STATUS & DATA_REQ) == 0) {
|
||
uptr->STATUS |= DATA_REQ;
|
||
set_interrupt(CP_DEVNUM, uptr->STATUS);
|
||
}
|
||
sim_activate(uptr, uptr->wait);
|
||
return SCPE_OK;
|
||
}
|
||
uptr->COL = 0;
|
||
uptr->STATUS &= ~(PUNCH_ON|CARD_IN_PUNCH);
|
||
uptr->STATUS |= END_CARD;
|
||
switch(sim_punch_card(uptr, cp_buffer)) {
|
||
case CDSE_EOF:
|
||
case CDSE_EMPTY:
|
||
uptr->STATUS |= PICK_FAIL|TROUBLE;
|
||
break;
|
||
/* If we get here, something is wrong */
|
||
case CDSE_ERROR:
|
||
uptr->STATUS |= EJECT_FAIL|TROUBLE;
|
||
break;
|
||
case CDSE_OK:
|
||
break;
|
||
}
|
||
if ((uptr->STATUS & (TROUBLE|TROUBLE_EN)) == (TROUBLE|TROUBLE_EN))
|
||
set_interrupt(CP_DEVNUM, uptr->STATUS);
|
||
if (uptr->STATUS & END_CARD_EN)
|
||
set_interrupt(CP_DEVNUM, uptr->STATUS);
|
||
}
|
||
|
||
return SCPE_OK;
|
||
}
|
||
|
||
|
||
t_stat
|
||
cp_attach(UNIT * uptr, CONST char *file)
|
||
{
|
||
sim_switches |= SWMASK ('A'); /* Position to EOF */
|
||
return sim_card_attach(uptr, file);
|
||
}
|
||
|
||
t_stat
|
||
cp_detach(UNIT * uptr)
|
||
{
|
||
|
||
if (uptr->STATUS & CARD_IN_PUNCH)
|
||
sim_punch_card(uptr, cp_buffer);
|
||
return sim_card_detach(uptr);
|
||
}
|
||
|
||
t_stat
|
||
cp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||
{
|
||
fprintf (st, "Card Punch\n\n");
|
||
sim_card_attach_help(st, dptr, uptr, flag, cptr);
|
||
fprint_set_help(st, dptr);
|
||
fprint_show_help(st, dptr);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
const char *
|
||
cp_description(DEVICE *dptr)
|
||
{
|
||
return "Card Punch";
|
||
}
|
||
|
||
#endif
|
||
|