mirror of
https://github.com/simh/simh.git
synced 2026-01-13 15:27:14 +00:00
RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially debugged. Do NOT enable these features for normal operations. 1. New Features in 3.1-0 1.1 SCP and libraries - Added simulated Ethernet support for VMS, FreeBSD, Mac OS/X. - Added status return to tmxr_putc_ln. - Added sim_putchar_s to handle possible output stalls. 1.2 All DECtapes - Added "DECtape off reel" error stop. 1.3 All Asynchronous Consoles - Added support for output congestion stall if using a Telnet connection. 1.4 PDP-1 - Added Type 23 parallel drum support. 1.5 PDP-8 - Added instruction history. - Added TSC8-75 option support for ETOS. - Added TD8E DECtape support. 1.6 PDP-18b - Added instruction history. - Changed PDP-9, PDP-15 API default to enabled. 1.7 PDP-11 - Added support for 18b only Qbus devices. - Formalized bus and addressing definitions. - Added control to enable/disable autoconfiguration. - Added stub support for second Unibus Ethernet controller. 1.7 Interdata 32b - Added instruction history. 1.8 Eclipse - Added floating point support. - Added programmable interval timer support. 1.9 H316 - Added DMA/DMC support. - Added fixed head disk support. - Added moving head disk support. - Added magtape support. 1.10 IBM 1130 (Brian Knittel) - Added support for physical card reader, using the Cardread interface (www.ibm1130.org/sim/downloads). - Added support for physical printer (flushes output buffer after each line). 2. Bugs Fixed in 3.1-0 2.1 SCP and libraries - Fixed numerous bugs in Ethernet library. 2.2 All DECtapes - Fixed reverse checksum value in 'read all' mode. - Simplified (and sped up) timing. 2.3 PDP-8 - Fixed bug in RX28 read status (found by Charles Dickman). - Fixed RX28 double density write. 2.4 PDP-18b - Fixed autoincrement bug in PDP-4, PDP-7, PDP-9. 2.5 PDP-11/VAX - Revised RQ MB->LBN conversion for greater accuracy. - Fixed bug in IO configuration (found by David Hittner). - Fixed bug with multiple RQ RAUSER drives. - Fixed bug in second Qbus Ethernet controller interrupts. 2.6 Nova/Eclipse - Fixed bugs in DKP flag clear, map setup, map usage (Charles Owen). - Fixed bug in MT, reset completes despite I/O reset (Charles Owen). - Fixed bug in MT, space operations return word count (Charles Owen). 2.7 IBM 1130 (Brian Knittel) - Fixed bug in setting carry bit in subtract and subtract double. - Fixed timing problem in console printer simulation. 2.8 1620 - Fixed bug in branch digit (found by Dave Babcock). 3. New Features in 3.0 vs prior releases 3.1 SCP and Libraries - Added ASSIGN/DEASSIGN (logical name) commands. - Changed RESTORE to unconditionally detach files. - Added E11 and TPC format support to magtape library. - Fixed bug in SHOW CONNECTIONS. - Added USE_ADDR64 support. 3.2 All magtapes - Magtapes support SIMH format, E11 format, and TPC format (read only). - SET <tape_unit> FORMAT=format sets the specified tape unit's format. - SHOW <tape_unit> FORMAT displays the specified tape unit's format. - Tape format can also be set as part of the ATTACH command, using the -F switch. 3.3 VAX - VAX can be compiled without USE_INT64. - If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support files > 2GB. - VAX ROM has speed control (SET ROM DELAY/NODELAY). 3.4 PDP-1 - Added block loader format support to LOAD. - Changed BOOT PTR to allow loading of all of the first bank of memory. - The LOAD command takes an optional argument specifying the memory field to be loaded. - The PTR BOOT command takes its starting memory field from the TA (address switch) register. 3.5 PDP-18b Family - Added PDP-4 EAE support. - Added PDP-15 FP15 support. - Added PDP-15 XVM support. - Added PDP-15 "re-entrancy ECO". - Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. 4. Bugs Fixed in 3.0 vs prior releases 4.1 SCP and Libraries - Fixed end of file problem in dep, idep. - Fixed handling of trailing spaces in dep, idep. 4.2 VAX - Fixed CVTfi bug: integer overflow not set if exponent out of range - Fixed EMODx bugs: o First and second operands reversed o Separated fraction received wrong exponent o Overflow calculation on separated integer incorrect o Fraction not set to zero if exponent out of range - Fixed interval timer and ROM access to pass power-up self-test even on very fast host processors (fixes from Mark Pizzolato). - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.3 1401 - Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. - Fixed MCE bug, BS off by 1 if zero suppress. - Fixed chaining bug, D lost if return to SCP. - Fixed H branch, branch occurs after continue. - Added check for invalid 8 character MCW, LCA. - Fixed magtape load-mode end of record response. - Revised fetch to model hardware more closely. - Fixed tape read end-of-record handling based on real 1401. - Added diagnostic read (space forward). 4.4 Nova - Fixed DSK variable size interaction with restore. - Fixed bug in DSK set size routine. 4.5 PDP-1 - Fixed DT variable size interaction with restore. - Updated CPU, line printer, standard devices to detect indefinite I/O wait. - Fixed incorrect logical, missing activate, break in drum simulator. - Fixed bugs in instruction decoding, overprinting for line printer. - Fixed system hang if continue after PTR error. - Fixed PTR to start/stop on successive rpa instructions. 4.6 PDP-11 - Fixed DT variable size interaction with restore. - Fixed bug in MMR1 update (found by Tim Stark). - Added XQ features and fixed bugs: o Corrected XQ interrupts on IE state transition (code by Tom Evans). o Added XQ interrupt clear on soft reset. o Removed XQ interrupt when setting XL or RL (multiple people). o Added SET/SHOW XQ STATS. o Added SHOW XQ FILTERS. o Added ability to split received packet into multiple buffers. o Added explicit runt and giant packet processing. - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.7 PDP-18B - Fixed DT, RF variable size interaction with restore. - Fixed MT bug in MTTR. - Fixed bug in PDP-4 line printer overprinting. - Fixed bug in PDP-15 memory protect/skip interaction. - Fixed bug in RF set size routine. - Increased PTP TIME for PDP-15 operating systems. - Fixed priorities in PDP-15 API (differs from PDP-9). - Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9). - Fixed bug in CAF, clears API subsystem. 4.8 PDP-8 - Fixed DT, DF, RF, RX variable size interaction with restore. - Fixed MT bug in SKTR. - Fixed bug in DF, RF set size routine. 4.9 HP2100 - Fixed bug in DP (13210A controller only), DQ read status. - Fixed bug in DP, DQ seek complete. - Fixed DR drum sizes. - Fixed DR variable capacity interaction with SAVE/RESTORE. 4.10 GRI - Fixed bug in SC queue pointer management. 4.11 PDP-10 - Fixed bug in RP read header. 4.12 Ibm1130 - Fixed bugs found by APL 1130. 4.13 Altairz80 - Fixed bug in real-time clock on Windows host. 4.14 1620 - Fixed bug in immediate index add (found by Michael Short).
301 lines
10 KiB
C
301 lines
10 KiB
C
/* h316_lp.c: Honeywell 316/516 line printer
|
||
|
||
Copyright (c) 1999-2003, Robert M. Supnik
|
||
|
||
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
|
||
ROBERT M SUPNIK 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.
|
||
|
||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||
in this Software without prior written authorization from Robert M Supnik.
|
||
|
||
lpt line printer
|
||
|
||
24-Oct-03 RMS Added DMA/DMC support
|
||
25-Apr-03 RMS Revised for extended file support
|
||
30-May-02 RMS Widened POS to 32b
|
||
|
||
The Series 16 line printer is an unbuffered Analex shuttle printer.
|
||
Because it was unbuffered, the CPU had to scan out an entire line's
|
||
worth of characters (60 words) for every character on the print drum
|
||
(64 characters). Because it was a shuttle printer, the entire
|
||
process must be repeated first for the odd columns and then for the
|
||
even columns. After scanning the odd columns, the printer carriage
|
||
shuttled right by one column; after scanning the even columns, the
|
||
carriage shuttled left. This halved the number of hammers required,
|
||
reducing cost but increasing mechanical complexity.
|
||
|
||
The real printer is very timing dependent. If the CPU misses a
|
||
scan, then the wrong characters are printed. If the printer protocol
|
||
is violated, then results are unpredictable. The simulated printer
|
||
is much more forgiving. Rather than simulating the fixed drum and
|
||
hammer timing of the real printer, the simulator is driven by the
|
||
program's OTA instructions. If the program misses a time slot, the
|
||
simulator will still print the "correct" result. A timing based
|
||
simulation would be very hard to do in the absense of accurate
|
||
instruction timing.
|
||
|
||
Printer state is maintained in a set of position and state variables:
|
||
|
||
lpt_wdpos word count within a line scan (0-59)
|
||
lpt_drpos drum position (0-63)
|
||
lpt_crpos carriage position (0-1)
|
||
lpt_svcst service state (shuttle, paper advance)
|
||
lpt_svcch channel for paper advance (0 = no adv)
|
||
lpt_rdy transfer ready flag
|
||
lpt_prdn printing done flag
|
||
lpt_dma use DMA/DMC
|
||
lpt_eor DMA/DMC end of range
|
||
*/
|
||
|
||
#include "h316_defs.h"
|
||
|
||
#define LPT_WIDTH 120 /* width */
|
||
#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */
|
||
#define LPT_DRUM 64 /* drum rows */
|
||
#define LPT_SVCSH 01 /* shuttle */
|
||
#define LPT_SVCPA 02 /* paper advance */
|
||
|
||
extern int32 dev_int, dev_enb;
|
||
extern int32 stop_inst;
|
||
extern uint32 chan_req;
|
||
|
||
int32 lpt_wdpos = 0; /* word position */
|
||
int32 lpt_drpos = 0; /* drum position */
|
||
int32 lpt_crpos = 0; /* carriage position */
|
||
int32 lpt_svcst = 0; /* service state */
|
||
int32 lpt_svcch = 0; /* service channel */
|
||
int32 lpt_rdy = 0; /* transfer flag */
|
||
int32 lpt_prdn = 1; /* printing done */
|
||
int32 lpt_dma = 0; /* use DMA/DMC */
|
||
int32 lpt_eor = 0; /* DMA/DMC end range */
|
||
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
|
||
int32 lpt_xtime = 5; /* transfer time */
|
||
int32 lpt_etime = 50; /* end of scan time */
|
||
int32 lpt_ptime = 5000; /* paper adv time */
|
||
int32 lpt_stopioe = 0; /* stop on error */
|
||
|
||
int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||
t_stat lpt_svc (UNIT *uptr);
|
||
t_stat lpt_reset (DEVICE *dptr);
|
||
|
||
/* LPT data structures
|
||
|
||
lpt_dev LPT device descriptor
|
||
lpt_unit LPT unit descriptor
|
||
lpt_mod LPT modifiers
|
||
lpt_reg LPT register list
|
||
*/
|
||
|
||
DIB lpt_dib = { LPT, IOBUS, 1, &lptio };
|
||
|
||
UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
||
|
||
REG lpt_reg[] = {
|
||
{ DRDATA (WDPOS, lpt_wdpos, 6) },
|
||
{ DRDATA (DRPOS, lpt_drpos, 6) },
|
||
{ FLDATA (CRPOS, lpt_crpos, 0) },
|
||
{ FLDATA (RDY, lpt_rdy, 0) },
|
||
{ FLDATA (EOR, lpt_eor, 0) },
|
||
{ FLDATA (DMA, lpt_dma, 0) },
|
||
{ FLDATA (PRDN, lpt_prdn, 0) },
|
||
{ FLDATA (INTREQ, dev_int, INT_V_LPT) },
|
||
{ FLDATA (ENABLE, dev_enb, INT_V_LPT) },
|
||
{ ORDATA (SVCST, lpt_svcst, 2) },
|
||
{ ORDATA (SVCCH, lpt_svcch, 2) },
|
||
{ BRDATA (BUF, lpt_buf, 8, 8, 120) },
|
||
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
|
||
{ DRDATA (XTIME, lpt_xtime, 24), PV_LEFT },
|
||
{ DRDATA (ETIME, lpt_etime, 24), PV_LEFT },
|
||
{ DRDATA (PTIME, lpt_ptime, 24), PV_LEFT },
|
||
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
|
||
{ NULL } };
|
||
|
||
DEVICE lpt_dev = {
|
||
"LPT", &lpt_unit, lpt_reg, NULL,
|
||
1, 10, 31, 1, 8, 8,
|
||
NULL, NULL, &lpt_reset,
|
||
NULL, NULL, NULL,
|
||
&lpt_dib, DEV_DISABLE };
|
||
|
||
/* IO routine */
|
||
|
||
int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||
{
|
||
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
|
||
int32 chr;
|
||
|
||
switch (inst) { /* case on opcode */
|
||
case ioOCP: /* OCP */
|
||
switch (fnc) { /* case on fnc */
|
||
case 000: case 002: case 004: /* paper adv */
|
||
lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */
|
||
lpt_svcch = fnc >> 1; /* save channel */
|
||
sim_activate (&lpt_unit, lpt_ptime);
|
||
CLR_INT (INT_LPT); /* clear int */
|
||
break;
|
||
case 003: /* init scan DMA/DMC */
|
||
lpt_prdn = 0; /* clear pr done */
|
||
lpt_wdpos = 0; /* init scan pos */
|
||
lpt_eor = 0;
|
||
if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */
|
||
lpt_dma = 0;
|
||
if (!sim_is_active (&lpt_unit)) {
|
||
lpt_rdy = 1;
|
||
if (lpt_dma) SET_CH_REQ (ch); }
|
||
CLR_INT (INT_LPT); /* clear int */
|
||
break;
|
||
case 007: /* init scan IO bus*/
|
||
lpt_prdn = 0; /* clear pr done */
|
||
lpt_wdpos = 0; /* init scan pos */
|
||
lpt_eor = 0;
|
||
lpt_dma = 0; /* IO bus */
|
||
if (!sim_is_active (&lpt_unit)) lpt_rdy = 1;
|
||
CLR_INT (INT_LPT); /* clear int */
|
||
break;
|
||
default:
|
||
return IOBADFNC (dat); }
|
||
break;
|
||
|
||
case ioSKS: /* SKS */
|
||
switch (fnc) { /* case on fnc */
|
||
case 000: /* if xfer rdy */
|
||
if (lpt_rdy) return IOSKIP (dat);
|
||
break;
|
||
case 002: /* if !alarm */
|
||
if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat);
|
||
break;
|
||
case 003: /* if odd col */
|
||
if (lpt_crpos) return IOSKIP (dat);
|
||
break;
|
||
case 004: /* if !interrupt */
|
||
if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat);
|
||
break;
|
||
case 011: /* if line printed */
|
||
if (lpt_prdn) return IOSKIP (dat);
|
||
break;
|
||
case 012: /* if !shuttling */
|
||
if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat);
|
||
break;
|
||
case 013:
|
||
if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat);
|
||
break;
|
||
case 014: /* if !advancing */
|
||
if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat);
|
||
break;
|
||
case 015:
|
||
if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat);
|
||
break;
|
||
case 016:
|
||
if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat);
|
||
break;
|
||
case 017:
|
||
if (lpt_prdn && !(lpt_svcst & (LPT_SVCSH | LPT_SVCPA)))
|
||
return IOSKIP (dat);
|
||
break;
|
||
default:
|
||
return IOBADFNC (dat); }
|
||
break;
|
||
|
||
case ioOTA: /* OTA */
|
||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||
if (lpt_rdy) { /* xfer ready? */
|
||
lpt_rdy = 0; /* clear xfer */
|
||
chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */
|
||
if (chr == lpt_drpos) { /* match drum pos? */
|
||
if (chr < 040) chr = chr | 0100;
|
||
lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr; }
|
||
lpt_wdpos++; /* adv scan pos */
|
||
if (lpt_wdpos >= LPT_SCAN) { /* end of scan? */
|
||
lpt_wdpos = 0; /* reset scan pos */
|
||
lpt_drpos++; /* adv drum pos */
|
||
if (lpt_drpos >= LPT_DRUM) { /* end of drum? */
|
||
lpt_drpos = 0; /* reset drum pos */
|
||
lpt_crpos = lpt_crpos ^ 1; /* shuttle */
|
||
lpt_svcst = lpt_svcst | LPT_SVCSH;
|
||
sim_activate (&lpt_unit, lpt_ptime);
|
||
} /* end if shuttle */
|
||
else sim_activate (&lpt_unit, lpt_etime);
|
||
} /* end if endscan */
|
||
else sim_activate (&lpt_unit, lpt_xtime);
|
||
return IOSKIP (dat); } /* skip return */
|
||
break;
|
||
|
||
case ioEND: /* end DMA/DMC */
|
||
lpt_eor = 1; /* set end range */
|
||
break; } /* end case op */
|
||
return dat;
|
||
}
|
||
|
||
/* Unit service */
|
||
|
||
t_stat lpt_svc (UNIT *uptr)
|
||
{
|
||
int32 i;
|
||
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
|
||
static const char *lpt_cc[] = {
|
||
"\r",
|
||
"\n",
|
||
"\n\f",
|
||
"\n" };
|
||
|
||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||
if (lpt_dma) { /* DMA/DMC? */
|
||
if (lpt_eor) SET_INT (INT_LPT); /* end range? intr */
|
||
else {
|
||
lpt_rdy = 1; /* set ready */
|
||
SET_CH_REQ (ch); } } /* get more data */
|
||
else lpt_rdy = 1; /* IO, continue scan */
|
||
if (lpt_dma && lpt_eor) SET_INT (INT_LPT); /* end of range? */
|
||
if (lpt_svcst & LPT_SVCSH) { /* shuttling */
|
||
SET_INT (INT_LPT); /* interrupt */
|
||
if (lpt_crpos == 0) lpt_prdn = 1; }
|
||
if (lpt_svcst & LPT_SVCPA) { /* paper advance */
|
||
SET_INT (INT_LPT); /* interrupt */
|
||
for (i = LPT_WIDTH - 1; i >= 0; i++) {
|
||
if (lpt_buf[i] != ' ') break; }
|
||
lpt_buf[i + 1] = 0;
|
||
fputs (lpt_buf, uptr->fileref); /* output buf */
|
||
fputs (lpt_cc[lpt_svcch & 03], uptr->fileref); /* output eol */
|
||
uptr->pos = ftell (uptr->fileref); /* update pos */
|
||
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buf */
|
||
}
|
||
lpt_svcst = 0;
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* Reset routine */
|
||
|
||
t_stat lpt_reset (DEVICE *dptr)
|
||
{
|
||
int32 i;
|
||
|
||
lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */
|
||
lpt_svcst = lpt_svcch = 0; /* idle state */
|
||
lpt_rdy = 0; /* not rdy to xfer */
|
||
lpt_prdn = 1; /* printing done */
|
||
lpt_eor = 0;
|
||
lpt_dma = 0;
|
||
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */
|
||
lpt_buf[LPT_WIDTH] = 0;
|
||
CLR_INT (INT_LPT); /* clear int, enb */
|
||
CLR_ENB (INT_LPT);
|
||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||
return SCPE_OK;
|
||
}
|