home *** CD-ROM | disk | FTP | other *** search
- /* pdp18b_stddev.c: 18b PDP's standard devices
-
- Copyright (c) 1994, Robert M Supnik, Digital Equipment Corporation
- All rights reserved
-
- ptr paper tape reader
- ptp paper tape punch
- tti keyboard
- tto teleprinter
- clk clock
- */
-
- #include "pdp18b_defs.h"
-
- extern int int_req, saved_PC;
- extern unsigned int M[];
- int clk_state = 0;
- int ptr_err = 0, ptr_stopioe = 0, ptr_state = 0;
- int ptp_err = 0, ptp_stopioe = 0;
- int tti_state = 0;
- int tto_state = 0;
- int clk_svc (UNIT *uptr);
- int ptr_svc (UNIT *uptr);
- int ptp_svc (UNIT *uptr);
- int tti_svc (UNIT *uptr);
- int tto_svc (UNIT *uptr);
- int clk_reset (DEVICE *dptr);
- int ptr_reset (DEVICE *dptr);
- int ptp_reset (DEVICE *dptr);
- int tti_reset (DEVICE *dptr);
- int tto_reset (DEVICE *dptr);
- int ptr_attach (UNIT *uptr, char *cptr);
- int ptp_attach (UNIT *uptr, char *cptr);
- int ptr_detach (UNIT *uptr);
- int ptp_detach (UNIT *uptr);
- int ptr_boot (int unitno);
- extern int sim_activate (UNIT *uptr, int interval);
- extern int sim_cancel (UNIT *uptr);
- extern int sim_poll_kbd (void);
- extern int sim_type_tty (char out);
- extern int attach_unit (UNIT *uptr, char *cptr);
- extern int detach_unit (UNIT *uptr);
-
- /* CLK data structures
-
- clk_dev CLK device descriptor
- clk_unit CLK unit
- clk_reg CLK register list
- */
-
- UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 5000 };
-
- REG clk_reg[] = {
- { FLDATA (INT, int_req, INT_V_CLK) },
- { FLDATA (DONE, int_req, INT_V_CLK) },
- { FLDATA (ENABLE, clk_state, 0) },
- { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
- { NULL } };
-
- DEVICE clk_dev = {
- "CLK", &clk_unit, clk_reg, NULL,
- 1, 0, 0, 0, 0, 0,
- NULL, NULL, &clk_reset,
- NULL, NULL, NULL };
-
- /* PTR data structures
-
- ptr_dev PTR device descriptor
- ptr_unit PTR unit
- ptr_reg PTR register list
- */
-
- UNIT ptr_unit = {
- UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
-
- REG ptr_reg[] = {
- { ORDATA (BUF, ptr_unit.buf, 18) },
- { FLDATA (INT, int_req, INT_V_PTR) },
- { FLDATA (DONE, int_req, INT_V_PTR) },
- #if defined (IOS_PTRERR)
- { FLDATA (ERR, ptr_err, 0) },
- #endif
- { ORDATA (BCNT, ptr_state, 5), REG_HRO },
- { DRDATA (POS, ptr_unit.pos, 32), PV_LEFT },
- { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
- { FLDATA (STOP_IOE, ptr_stopioe, 0) },
- { NULL } };
-
- DEVICE ptr_dev = {
- "PTR", &ptr_unit, ptr_reg, NULL,
- 1, 10, 32, 1, 8, 8,
- NULL, NULL, &ptr_reset,
- &ptr_boot, &ptr_attach, &ptr_detach };
-
- /* PTP data structures
-
- ptp_dev PTP device descriptor
- ptp_unit PTP unit
- ptp_reg PTP register list
- */
-
- UNIT ptp_unit = {
- UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
-
- REG ptp_reg[] = {
- { ORDATA (BUF, ptp_unit.buf, 8) },
- { FLDATA (INT, int_req, INT_V_PTP) },
- { FLDATA (DONE, int_req, INT_V_PTP) },
- #if defined (IOS_PTPERR)
- { FLDATA (ERR, ptp_err, 0) },
- #endif
- { DRDATA (POS, ptp_unit.pos, 32), PV_LEFT },
- { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
- { FLDATA (STOP_IOE, ptp_stopioe, 0) },
- { NULL } };
-
- DEVICE ptp_dev = {
- "PTP", &ptp_unit, ptp_reg, NULL,
- 1, 10, 32, 1, 8, 8,
- NULL, NULL, &ptp_reset,
- NULL, &ptp_attach, &ptp_detach };
-
- /* TTI data structures
-
- tti_dev TTI device descriptor
- tti_unit TTI unit
- tti_reg TTI register list
- tti_trans ASCII to Baudot table
- */
-
- #if defined (KSR28)
- #define TTI_WIDTH 5
- #define TTI_FIGURES (1 << TTI_WIDTH)
- #define TTI_2ND (1 << (TTI_WIDTH + 1))
- #define TTI_BOTH (1 << (TTI_WIDTH + 2))
- #define BAUDOT_LETTERS 033
- #define BAUDOT_FIGURES 037
- #define BEL 064
-
- static const int tti_trans[128] = {
- BEL,BEL,BEL,BEL,BEL,BEL,BEL,BEL,
- BEL,BEL,0210,BEL,BEL,0202,BEL,BEL, /* lf, cr */
- BEL,BEL,BEL,BEL,BEL,BEL,BEL,BEL,
- BEL,BEL,BEL,BEL,BEL,BEL,BEL,BEL,
- 0204,066,061,045,062,BEL,053,072, /* space - ' */
- 076,051,BEL,BEL,046,070,047,067, /* ( - / */
- 055,075,071,060,052,041,065,074, /* 0 - 7 */
- 054,043,056,057,BEL,BEL,BEL,063, /* 8 - ? */
- BEL,030,023,016,022,020,026,013, /* @ - G */
- 005,014,032,036,011,007,006,003, /* H - O */
- 015,035,012,024,001,034,017,031, /* P - W */
- 027,025,021,BEL,BEL,BEL,BEL,BEL, /* X - _ */
- BEL,030,023,016,022,020,026,013, /* ` - g */
- 005,014,032,036,011,007,006,003, /* h - o */
- 015,035,012,024,001,034,017,031, /* p - w */
- 027,025,021,BEL,BEL,BEL,BEL,BEL }; /* x - DEL */
- #else
-
- #define TTI_WIDTH 8
- #endif
-
- #define TTI_MASK ((1 << TTI_WIDTH) - 1)
-
- UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
-
- REG tti_reg[] = {
- { ORDATA (BUF, tti_unit.buf, TTI_WIDTH) },
- { FLDATA (INT, int_req, INT_V_TTI) },
- { FLDATA (DONE, int_req, INT_V_TTI) },
- #if defined (KSR28)
- { ORDATA (TTI2ND, tti_state, (TTI_WIDTH + 3)), REG_HRO },
- #endif
- { DRDATA (POS, tti_unit.pos, 32), PV_LEFT },
- { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
- { NULL } };
-
- DEVICE tti_dev = {
- "TTI", &tti_unit, tti_reg, NULL,
- 1, 10, 32, 1, 8, 8,
- NULL, NULL, &tti_reset,
- NULL, NULL, NULL };
-
- /* TTO data structures
-
- tto_dev TTO device descriptor
- tto_unit TTO unit
- tto_reg TTO register list
- tto_trans Baudot to ASCII table
- */
-
- #if defined (KSR28)
- #define TTO_WIDTH 5
- #define TTO_FIGURES (1 << TTO_WIDTH)
-
- static const char tto_trans[64] = {
- 0 ,'T',015,'O',' ','H','N','M',
- 012,'L','R','G','I','P','C','V',
- 'E','Z','D','B','S','Y','F','X',
- 'A','W','J', 0 ,'U','Q','K', 0,
- 0 ,'5',015,'9',' ','#',',','.',
- 012,')','4','&','8','0',':',';',
- '3','"','$','?','\a','6','!','/',
- '-','2','\'',0 ,'7','1','(', 0 };
- #else
-
- #define TTO_WIDTH 8
- #endif
-
- #define TTO_MASK ((1 << TTO_WIDTH) - 1)
-
- UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
-
- REG tto_reg[] = {
- { ORDATA (BUF, tto_unit.buf, TTO_WIDTH) },
- { FLDATA (INT, int_req, INT_V_TTO) },
- { FLDATA (DONE, int_req, INT_V_TTO) },
- #if defined (KSR28)
- { FLDATA (TTO2ND, tto_state, 0), REG_HRO },
- #endif
- { DRDATA (POS, tto_unit.pos, 32), PV_LEFT },
- { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
- { NULL } };
-
- DEVICE tto_dev = {
- "TTO", &tto_unit, tto_reg, NULL,
- 1, 10, 32, 1, 8, 8,
- NULL, NULL, &tto_reset,
- NULL, NULL, NULL };
-
- /* Clock: IOT routine */
-
- int clk (int pulse, int AC)
- {
- if (pulse == 001) return (int_req & INT_CLK)? IOT_SKP + AC: AC; /* CLSF */
- if (pulse == 004) clk_reset (&clk_dev); /* CLOF */
- else if (pulse == 044) { /* CLON */
- int_req = int_req & ~INT_CLK; /* clear flag */
- clk_state = 1; /* clock on */
- sim_activate (&clk_unit, clk_unit.wait); } /* start clock */
- return AC;
- }
-
- /* Unit service */
-
- int clk_svc (UNIT *uptr)
- {
- if (clk_state) { /* clock on? */
- M[7] = (M[7] + 1) & 0777777; /* incr counter */
- if (M[7] == 0) int_req = int_req | INT_CLK; /* ovrflo? set flag */
- sim_activate (&clk_unit, clk_unit.wait); } /* reactivate unit */
- return SCPE_OK;
- }
-
- /* Reset routine */
-
- int clk_reset (DEVICE *dptr)
- {
- int_req = int_req & ~INT_CLK; /* clear flag */
- clk_state = 0; /* clock off */
- sim_cancel (&clk_unit); /* stop clock */
- return SCPE_OK;
- }
-
- /* IORS service for all standard devices */
-
- int std_iors (void)
- {
- return ((int_req & INT_CLK)? IOS_CLK: 0) |
- ((int_req & INT_PTR)? IOS_PTR: 0) |
- ((int_req & INT_PTP)? IOS_PTP: 0) |
- ((int_req & INT_TTI)? IOS_TTI: 0) |
- ((int_req & INT_TTO)? IOS_TTO: 0) |
- #if defined (IOS_PTRERR)
- (ptr_err? IOS_PTRERR: 0) |
- #endif
- #if defined (IOS_PTPERR)
- (ptp_err? IOS_PTPERR: 0) |
- #endif
- (clk_state? IOS_CLKON: 0);
- }
-
- /* Paper tape reader: IOT routine */
-
- int ptr (int pulse, int AC)
- {
- if (pulse == 001) return (int_req & INT_PTR)? IOT_SKP + AC: AC; /* RSF */
- if (pulse & 002) { /* RRB, RCF */
- int_req = int_req & ~INT_PTR; /* clear done */
- AC = ptr_unit.buf; } /* return buffer */
- if (pulse & 004) { /* RSA, RSB */
- ptr_state = (pulse & 040)? 18: 0; /* set mode */
- int_req = int_req & ~INT_PTR; /* clear done */
- ptr_state = 0; /* alpha mode */
- ptr_unit.buf = 0; /* clear buffer */
- sim_activate (&ptr_unit, ptr_unit.wait); }
- return AC;
- }
-
- /* Unit service */
-
- int ptr_svc (UNIT *uptr)
- {
- int temp;
-
- if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */
- #if defined (IOS_PTRERR)
- int_req = int_req | INT_PTR; /* if err, set int */
- ptr_err = 1;
- #endif
- return IORETURN (ptr_stopioe, SCPE_UNATT); }
- if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
- #if defined (IOS_PTRERR)
- int_req = int_req | INT_PTR; /* if err, set done */
- ptr_err = 1;
- #endif
- if (feof (ptr_unit.fileref)) {
- if (ptr_stopioe) printf ("PTR end of file\n");
- else return SCPE_OK; }
- else perror ("PTR I/O error");
- clearerr (ptr_unit.fileref);
- return SCPE_IOERR; }
- if (ptr_state == 0) ptr_unit.buf = temp & 0377; /* alpha */
- else if (temp & 0200) { /* binary */
- ptr_state = ptr_state - 6;
- ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); }
- if (ptr_state == 0) int_req = int_req | INT_PTR; /* set flag */
- ptr_unit.pos = ptr_unit.pos + 1;
- return SCPE_OK;
- }
-
- /* Reset routine */
-
- int ptr_reset (DEVICE *dptr)
- {
- ptr_state = 0; /* clear state */
- ptr_unit.buf = 0;
- int_req = int_req & ~INT_PTR; /* clear flag */
- ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1;
- sim_cancel (&ptr_unit); /* deactivate unit */
- return SCPE_OK;
- }
-
- /* Attach routine */
-
- int ptr_attach (UNIT *uptr, char *cptr)
- {
- int reason;
-
- reason = attach_unit (uptr, cptr);
- ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1;
- return reason;
- }
-
- /* Detach routine */
-
- int ptr_detach (UNIT *uptr)
- {
- ptr_err = 1;
- return detach_unit (uptr);
- }
-
- /* Bootstrap routine */
-
- #define BOOT_START 017762
- #define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
-
- static const int boot_rom[] = {
- 0000000, /* r, 0 */
- 0700101, /* rsf */
- 0617763, /* jmp .-1 */
- 0700112, /* rrb */
- 0700144, /* rsb */
- 0637762, /* jmp i r */
- 0700144, /* go, rsb */
- 0117762, /* g, jms r */
- 0057775, /* dac out */
- 0417775, /* xct out */
- 0117762, /* jms r */
- 0000000, /* out, 0 */
- 0617771 /* jmp g */
- };
-
- int ptr_boot (int unitno)
- {
- int i;
-
- for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
- saved_PC = BOOT_START;
- return SCPE_OK;
- }
-
- /* Paper tape punch: IOT routine */
-
- int ptp (int pulse, int AC)
- {
- if (pulse == 001) return (int_req & INT_PTP)? IOT_SKP + AC: AC; /* PSF */
- if (pulse & 002) int_req = int_req & ~INT_PTP; /* PCF */
- if (pulse & 004) { /* PSA, PSB, PLS */
- int_req = int_req & ~INT_PTP; /* clear flag */
- ptp_unit.buf = (pulse & 040)? /* load punch buf */
- (AC & 077) | 0200: AC & 0377; /* bin or alpha */
- sim_activate (&ptp_unit, ptp_unit.wait); } /* activate unit */
- return AC;
- }
-
- /* Unit service */
-
- int ptp_svc (UNIT *uptr)
- {
- int_req = int_req | INT_PTP; /* set done flag */
- if ((ptp_unit.flags & UNIT_ATT) == 0) { /* not attached? */
- ptp_err = 1; /* set error */
- return IORETURN (ptp_stopioe, SCPE_UNATT); }
- if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */
- ptp_err = 1; /* set error */
- perror ("PTP I/O error");
- clearerr (ptp_unit.fileref);
- return SCPE_IOERR; }
- ptp_unit.pos = ptp_unit.pos + 1;
- return SCPE_OK;
- }
-
- /* Reset routine */
-
- int ptp_reset (DEVICE *dptr)
- {
- ptp_unit.buf = 0;
- int_req = int_req & ~INT_PTP; /* clear flag */
- ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1;
- sim_cancel (&ptp_unit); /* deactivate unit */
- return SCPE_OK;
- }
-
- /* Attach routine */
-
- int ptp_attach (UNIT *uptr, char *cptr)
- {
- int reason;
-
- reason = attach_unit (uptr, cptr);
- ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1;
- return reason;
- }
-
- /* Detach routine */
-
- int ptp_detach (UNIT *uptr)
- {
- ptp_err = 1;
- return detach_unit (uptr);
- }
-
- /* Terminal input: IOT routine */
-
- int tti (int pulse, int AC)
- {
- if (pulse == 001) return (int_req & INT_TTI)? IOT_SKP + AC: AC; /* KSF */
- if (pulse == 002) { /* KRB */
- int_req = int_req & ~INT_TTI; /* clear flag */
- return tti_unit.buf & TTI_WIDTH; } /* return buffer */
- return AC;
- }
-
- /* Unit service */
-
- int tti_svc (UNIT *uptr)
- {
- int temp;
-
- sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
-
- #if defined (KSR28) /* Baudot... */
- if (tti_state & TTI_2ND) { /* char waiting? */
- tti_unit.buf = tti_state & TTI_WIDTH; /* return char */
- tti_state = tti_state & ~TTI_2ND; } /* not waiting */
- else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
- temp = tti_trans[temp & 0177]; /* translate char */
- if (temp & TTI_BOTH) tti_unit.buf = temp & TTI_WIDTH;
- else if ((temp & TTI_FIGURES) == (tti_state & TTI_FIGURES)) {
- tti_unit.buf = temp & TTI_WIDTH;
- tti_state = temp; } /* change state */
- else { tti_unit.buf = (temp & TTI_FIGURES)?
- BAUDOT_FIGURES: BAUDOT_LETTERS;
- tti_state = temp | TTI_2ND; } } /* set 2nd waiting */
-
- #else /* ASCII... */
- if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
- tti_unit.buf = (temp & 0377) | 0200; /* got char */
- #endif
- int_req = int_req | INT_TTI; /* set flag */
- tti_unit.pos = tti_unit.pos + 1;
- return SCPE_OK;
- }
-
- /* Reset routine */
-
- int tti_reset (DEVICE *dptr)
- {
- tti_unit.buf = 0; /* clear buffer */
- tti_state = 0; /* clear state */
- int_req = int_req & ~INT_TTI; /* clear flag */
- sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
- return SCPE_OK;
- }
-
- /* Terminal output: IOT routine */
-
- int tto (int pulse, int AC)
- {
- if (pulse == 001) return (int_req & INT_TTO)? IOT_SKP + AC: AC; /* TSF */
- if (pulse & 002) int_req = int_req & ~INT_TTO; /* clear flag */
- if (pulse & 004) { /* load buffer */
- sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
- tto_unit.buf = AC & TTO_MASK; } /* load buffer */
- return AC;
- }
-
- /* Unit service */
-
- int tto_svc (UNIT *uptr)
- {
- int out, temp;
-
- #if defined (KSR28) /* Baudot... */
- if (tto_unit.buf == BAUDOT_FIGURES) { /* set figures? */
- tto_state = TTO_FIGURES;
- return SCPE_OK; }
- if (tto_unit.buf == BAUDOT_LETTERS) { /* set letters? */
- tto_state = 0;
- return SCPE_OK; }
- out = tto_trans[tto_unit.buf + tto_state]; /* translate */
- #else
- out = tto_unit.buf & 0177; /* ASCII... */
- #endif
- int_req = int_req | INT_TTO; /* set flag */
- if ((temp = sim_type_tty (out)) != SCPE_OK) return temp;
- tto_unit.pos = tto_unit.pos + 1;
- return SCPE_OK;
- }
-
- /* Reset routine */
-
- int tto_reset (DEVICE *dptr)
- {
- tto_unit.buf = 0; /* clear buffer */
- tto_state = 0; /* clear state */
- int_req = int_req & ~INT_TTO; /* clear flag */
- sim_cancel (&tto_unit); /* deactivate unit */
- return SCPE_OK;
- }
-