summaryrefslogtreecommitdiffstats
path: root/private/mvdm/softpc.new/base/comms/printer.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/softpc.new/base/comms/printer.c')
-rw-r--r--private/mvdm/softpc.new/base/comms/printer.c836
1 files changed, 836 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/base/comms/printer.c b/private/mvdm/softpc.new/base/comms/printer.c
new file mode 100644
index 000000000..0ef68ce1d
--- /dev/null
+++ b/private/mvdm/softpc.new/base/comms/printer.c
@@ -0,0 +1,836 @@
+#include "insignia.h"
+#include "host_def.h"
+#ifdef PRINTER
+
+/*
+ * VPC-XT Revision 1.0
+ *
+ * Title: Parallel Printer Port Emulation
+ *
+ * Description: Emulates the IBM || Printer card as used in the original
+ * IBM XT, which is itself a H/W emulation of an Intel 8255.
+ *
+ * Author: Henry Nash
+ *
+ * Notes: None
+ *
+ * Mods:
+ * <chrisP 11Sep91>
+ * Allow transition to NOTBUSY in the OUTA state as well as the READY
+ * state. i.e. at the leading edge of the ACK pulse after just one
+ * INB (STATUS) rather than two. Our printer port emulation relies on
+ * these INB's to toggle the ACK line and set NOTBUSY true again. So
+ * the port could be left in the BUSY condition at the end of an app's
+ * print job (which can confuse the next print request). NOTE we could
+ * still have a problem if the PC app bypasses the BIOS and is too lazy
+ * to do even one INB(STATUS) after the last print byte.
+ */
+
+
+
+/* for NTVDM port -- williamh
+ * There are such things called Dongles which many software companies have
+ * used for copy protection. Each software comes with its dedicated Dongle
+ * that records necessary indentification inforamtion. It is required
+ * to plug the device onto the parallel port in order to run the software
+ * correctly. The device has an outlet which can be connectted to parallel
+ * port printer so the the user doesn't sacrifice his parallel port when
+ * the device in plugged on the original connector.
+ * There are several Dongle vendors and each one of them provides their
+ * propietary library or driver for the applications to link to. These
+ * drivers know how to read/WRITE the Dongle to verify a legitmate copy.
+ * Since it has to maintain compatiblility with standard PC parallel port,
+ * the devices are designed in a way that it can be programmed without
+ * disturbing ordinary parallel port operation. To do this, it usually does
+ * this:
+ * (1) Turn off strobe.
+ * (2) output data pattern to data port
+ * (3) delay a little bit(looping in instructions) and then go to (2)
+ * until the chunk of data has been sent. NOTE THAT THE STROBE LINE
+ * IS NEVER "strobe"
+ * (4). Read status port and by interpreting the line differently,
+ * the driver decodes any id information it is looking for.
+ *
+ * In order to support these devices, we have to do these:
+ * (1). We can not fake printer status. We have to get the real
+ * status line states.
+ * (2). we have to output data to the printer without waiting the data
+ * to be qualified(strobing).
+ * (3). We must be smart enough to detect the application is done with
+ * its Dongle things and wants everything goes back to normal.
+ * We must adjust ourselves under this circumestances.
+ * (4). Down level printer driver must provide function that we can call
+ * to control the port directly.
+ * (5). Printer h/w interrupt is not allowed to be enabled under this
+ * circumstance --and how can we make sure of that?????
+ *
+ */
+
+#ifdef SCCSID
+static char SccsID[] = "@(#)printer.c 1.19 11/14/94 Copyright Insignia Solutions Ltd.";
+#endif
+
+#ifdef SEGMENTATION
+/*
+ * The following #include specifies the code segment into which this
+ * module will by placed by the MPW C compiler on the Mac II running
+ * MultiFinder.
+ */
+#include "SOFTPC_PRINTER.seg"
+#endif
+
+
+/*
+ * O/S include files.
+ */
+#include <stdio.h>
+#include TypesH
+#include TimeH
+#ifdef SYSTEMV
+#ifdef STINGER
+#include <sys/termio.h>
+#endif
+#endif
+
+/*
+ * SoftPC include files
+ */
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "ios.h"
+#include "bios.h"
+#include "printer.h"
+#include "error.h"
+#include "config.h"
+#include "host_lpt.h"
+#include "ica.h"
+#include "quick_ev.h"
+
+#include "debug.h"
+#ifndef PROD
+#include "trace.h"
+#endif
+
+
+/*
+ * ============================================================================
+ * Global data
+ * ============================================================================
+ */
+
+
+/*
+ * ============================================================================
+ * Static data and defines
+ * ============================================================================
+ */
+
+#define PRINTER_BIT_MASK 0x3 /* bits decoded from address bus */
+#define CONTROL_REG_MASK 0xE0; /* unused bits drift to HIGH */
+#define STATUS_REG_MASK 0x07; /* unused bits drift to HIGH */
+
+#define DATA_OFFSET 0 /* ouput register */
+#define STATUS_OFFSET 1 /* status register */
+#define CONTROL_OFFSET 2 /* control register */
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
+static half_word output_reg[NUM_PARALLEL_PORTS];
+static half_word control_reg[NUM_PARALLEL_PORTS];
+#define NOTBUSY 0x80
+#define ACK 0x40
+#define PEND 0x20
+#define SELECT 0x10
+#define ERROR 0x08
+
+static half_word status_reg[NUM_PARALLEL_PORTS];
+#define IRQ 0x10
+#define SELECT_IN 0x08
+#define INIT_P 0x04
+#define AUTO_FEED 0x02
+#define STROBE 0x01
+
+LOCAL IU8 retryErrorCount = 0; /* num status inb before clearing ERROR */
+
+static int state[NUM_PARALLEL_PORTS]; /* state control variable */
+/*
+ * set up arrays of all port addresses
+ */
+static io_addr port_start[] = {LPT1_PORT_START,LPT2_PORT_START,LPT3_PORT_START};
+static io_addr port_end[] = {LPT1_PORT_END, LPT2_PORT_END, LPT3_PORT_END};
+static int port_no[] = {LPT1_PORT_START & LPT_MASK, LPT2_PORT_START & LPT_MASK,
+ LPT3_PORT_START & LPT_MASK };
+static half_word lpt_adapter[] = {LPT1_ADAPTER, LPT2_ADAPTER, LPT3_ADAPTER};
+static sys_addr port_address[] = {LPT1_PORT_ADDRESS, LPT2_PORT_ADDRESS, LPT3_PORT_ADDRESS};
+static sys_addr timeout_address[] = {LPT1_TIMEOUT_ADDRESS, LPT2_TIMEOUT_ADDRESS, LPT3_TIMEOUT_ADDRESS};
+static q_ev_handle handle_for_out_event[NUM_PARALLEL_PORTS];
+static q_ev_handle handle_for_outa_event[NUM_PARALLEL_PORTS];
+
+#if defined(NTVDM) && defined(MONITOR)
+/* sudeepb 24-Jan-1993 for printing performance for x86 */
+sys_addr lp16BitPrtBuf;
+sys_addr lp16BitPrtId;
+sys_addr lp16BitPrtCount;
+sys_addr lp16BitPrtBusy;
+#endif
+
+#define STATE_READY 0
+#define STATE_OUT 1
+#define STATE_OUTA 2
+#if defined(NTVDM)
+#define STATE_DATA 3
+#define STATE_DONGLE 4
+#endif
+
+/*
+ * State transitions:
+ *
+ * +-> STATE_READY
+ * | |
+ * | | ........ write char to output_reg, print on low-high strobe
+ * | V set NOTBUSY to false
+ * | STATE_OUT
+ * | |
+ * | | ........ (read status) set ACK low
+ * | V
+ * | STATE_OUTA
+ * | |
+ * | | ........ (read status) set ACK high
+ * +-----+
+ *
+ * Caveat: if the control register interrupt request bit is set,
+ * we assume that the application isn't interested in getting the
+ * ACKs and just wants to know when the printer state changes back
+ * to NOTBUSY. I'm not sure to want extent you can get away with
+ * this: however, applications using the BIOS printer services
+ * should be OK.
+ */
+
+#ifdef PS_FLUSHING
+LOCAL IBOOL psFlushEnabled[NUM_PARALLEL_PORTS]; /* TRUE if PostScript flushing
+ is enabled */
+#endif /* PS_FLUSHING */
+
+
+/*
+ * ============================================================================
+ * Internal functions & macros
+ * ============================================================================
+ */
+
+#define set_low(val, bit) val &= ~bit
+#define set_high(val, bit) val |= bit
+#define low_high(val1, val2, bit) (!(val1 & bit) && (val2 & bit))
+#define high_low(val1, val2, bit) ((val1 & bit) && !(val2 & bit))
+#define toggled(val1, val2, bit) ((val1 & bit) != (val2 & bit))
+#define negate(val, bit) val ^= bit
+
+/*
+ * Defines and variables to handle tables stored in 16-bit code for NT
+ * monitors.
+ */
+#if defined(NTVDM) && defined(MONITOR)
+
+static BOOL intel_setup = FALSE;
+
+static sys_addr status_addr;
+static sys_addr control_addr;
+static sys_addr state_addr;
+
+#define get_status(adap) (sas_hw_at_no_check(status_addr+(adap)))
+#define set_status(adap,val) (sas_store_no_check(status_addr+(adap),(val)))
+
+#define get_control(adap) (sas_hw_at_no_check(control_addr+(adap)))
+#define set_control(adap,val) (sas_store_no_check(control_addr+(adap),(val)))
+
+#define get_state(adap) (sas_hw_at_no_check(state_addr+(adap)))
+#define set_state(adap,val) (sas_store_no_check(state_addr+(adap),(val)))
+
+#else /* NTVDM && MONITOR */
+
+#define get_status(adap) (status_reg[adapter])
+#define set_status(adap,val) (status_reg[adapter] = (val))
+
+#define get_control(adap) (control_reg[adapter])
+#define set_control(adap,val) (control_reg[adapter] = (val))
+
+#define get_state(adap) (state[adapter])
+#define set_state(adap,val) (state[adapter] = (val))
+
+#endif /* NTVDM && MONITOR */
+
+static void printer_inb IPT2(io_addr, port, half_word *, value);
+static void printer_outb IPT2(io_addr, port, half_word, value);
+static void notbusy_check IPT1(int,adapter);
+
+
+/*
+ * ============================================================================
+ * External functions
+ * ============================================================================
+ */
+
+void printer_post IFN1(int,adapter)
+{
+ /*
+ * Set up BIOS data area.
+ */
+ sas_storew(port_address[adapter],(word)port_start[adapter]);
+ sas_store(timeout_address[adapter], (half_word)0x14 ); /* timeout */
+}
+
+#if defined(NTVDM) && defined(MONITOR)
+static void lpr_state_outa_event IFN1(long,adapter)
+{
+ set_status(adapter, get_status(adapter) | ACK);
+ set_state(adapter, STATE_READY);
+}
+
+static void lpr_state_out_event IFN1(long,adapter)
+{
+ set_status(adapter, get_status(adapter) & ~ACK);
+ set_state(adapter, STATE_OUTA);
+ handle_for_outa_event[adapter]=add_q_event_t(lpr_state_outa_event,HOST_PRINTER_DELAY,adapter);
+}
+
+#else /* NTVDM && MONITOR */
+
+static void lpr_state_outa_event IFN1(long,adapter)
+{
+ set_high(status_reg[adapter],ACK);
+ state[adapter]=STATE_READY;
+}
+
+static void lpr_state_out_event IFN1(long,adapter)
+{
+ set_low(status_reg[adapter], ACK);
+ state[adapter]=STATE_OUTA;
+ handle_for_outa_event[adapter]=add_q_event_t(lpr_state_outa_event,HOST_PRINTER_DELAY,adapter);
+}
+#endif /* NTVDM && MONITOR */
+
+static void printer_inb IFN2(io_addr,port, half_word *,value)
+{
+ int adapter, i;
+
+ note_trace1(PRINTER_VERBOSE,"inb from printer port %#x ",port);
+ /*
+ ** Scan the ports to find out which one is used. NB the
+ ** port must be valid one because we only used io_define_inb()
+ ** for the valid ports
+ */
+ for(i=0; i < NUM_PARALLEL_PORTS; i++)
+ if((port & LPT_MASK) == port_no[i])
+ break;
+ adapter = i % NUM_PARALLEL_PORTS;
+
+ port = port & PRINTER_BIT_MASK; /* clear unused bits */
+
+ switch(port)
+ {
+ case DATA_OFFSET:
+ *value = output_reg[adapter];
+ break;
+
+ case STATUS_OFFSET:
+ switch(get_state(adapter))
+ {
+#if defined(NTVDM)
+ case STATE_DONGLE:
+ /* read directly from the port for Dongle */
+ *value = host_read_printer_status_port(adapter);
+ set_status(adapter, *value);
+ break;
+ case STATE_DATA:
+
+#endif
+
+ case STATE_READY:
+ notbusy_check(adapter);
+ *value = get_status(adapter) | STATUS_REG_MASK;
+
+
+ /* Clear ERROR as it will be set if we fail on the print. */
+ /* Clear after two inbs as DOS seems to require this. */
+ if (retryErrorCount > 0)
+ retryErrorCount--;
+ else
+ set_status(adapter, get_status(adapter) | ERROR);
+ break;
+ case STATE_OUT:
+ *value = get_status(adapter) | STATUS_REG_MASK;
+#ifndef DELAYED_INTS
+ delete_q_event(handle_for_out_event[adapter]);
+ lpr_state_out_event(adapter);
+#else
+ set_low(status_reg[adapter], ACK);
+ state[adapter] = STATE_OUTA;
+#endif /* DELAYED INTS */
+ break;
+ case STATE_OUTA:
+ notbusy_check(adapter); /* <chrisP 11Sep91> */
+ *value = get_status(adapter) | STATUS_REG_MASK;
+#ifndef DELAYED_INTS
+ delete_q_event(handle_for_outa_event[adapter]);
+ lpr_state_outa_event(adapter);
+#else
+ set_high(status_reg[adapter], ACK);
+ state[adapter] = STATE_READY;
+#endif
+ break;
+ default:
+ note_trace1(PRINTER_VERBOSE,
+ "<pinb() - unknown state %x>",
+ get_state(adapter));
+ break;
+ }
+ break;
+ case CONTROL_OFFSET:
+ *value = get_control(adapter) | CONTROL_REG_MASK;
+ negate(*value, STROBE);
+ negate(*value, AUTO_FEED);
+ negate(*value, SELECT_IN);
+ break;
+ }
+ note_trace3(PRINTER_VERBOSE, "<pinb() %x, ret %x, state %x>",
+ port, *value, get_state(adapter));
+
+
+}
+
+static void printer_outb IFN2(io_addr,port, half_word,value)
+{
+ int adapter, i;
+ half_word old_control;
+#ifdef PC_CONFIG
+ char variable_text[MAXPATHLEN];
+ int softpcerr;
+ int severity;
+
+ softpcerr = 0;
+ severity = 0;
+#endif
+
+
+ note_trace2(PRINTER_VERBOSE,"outb to printer port %#x with value %#x",
+ port, value);
+
+ /*
+ ** Scan the ports to find out which one is used. NB the
+ ** port must be valid one because we only used io_define_inb()
+ ** for the valid ports
+ */
+ for(i=0; i < NUM_PARALLEL_PORTS; i++)
+ if((port & LPT_MASK) == port_no[i])
+ break;
+ adapter = i % NUM_PARALLEL_PORTS;
+
+ note_trace3(PRINTER_VERBOSE, "<poutb() %x, val %x, state %x>",
+ port, value, get_state(adapter));
+
+ port = port & PRINTER_BIT_MASK; /* clear unused bits */
+
+ switch(get_state(adapter))
+ {
+#if defined(NTVDM)
+ case STATE_DONGLE:
+ if (port == DATA_OFFSET) {
+ output_reg[adapter] = value;
+ host_print_byte(adapter, value);
+ break;
+ }
+ // fall through
+ case STATE_DATA:
+ if (port == DATA_OFFSET) {
+ if (host_set_lpt_direct_access(adapter, TRUE)) {
+ host_print_byte(adapter, output_reg[adapter]);
+ host_print_byte(adapter, value);
+ set_state(adapter, STATE_DONGLE);
+ /* Write char to internal buffer */
+ output_reg[adapter] = value;
+ }
+ else {
+ /* unable to open the lpt for direct access,
+ mark the device busy */
+
+#if !defined(MONITOR)
+ set_low(status_reg[adapter], NOTBUSY);
+#else /* NTVDM && !MONITOR */
+ set_status(adapter, 0x7F);
+#endif
+
+
+ }
+ break;
+ }
+
+ // fall through
+#endif
+ case STATE_OUT:
+ case STATE_OUTA:
+ case STATE_READY:
+ switch(port)
+ {
+ case DATA_OFFSET:
+#if defined(NTVDM)
+ set_state(adapter, STATE_DATA);
+#endif
+ /* Write char to internal buffer */
+ output_reg[adapter] = value;
+ break;
+ case STATUS_OFFSET:
+ /* Not possible */
+ break;
+
+ case CONTROL_OFFSET:
+ /* Write control bits */
+ old_control = get_control(adapter); /* Save old value to see what's changed */
+ set_control(adapter, value);
+ if (low_high(old_control, value, INIT_P))
+#ifdef PC_CONFIG
+ /* this was a call to host_print_doc - <chrisP 28Aug91> */
+ host_reset_print(&softpcerr, &severity);
+ if (softpcerr != 0)
+ host_error(softpcerr, severity, variable_text);
+#else
+ /* this was a call to host_print_doc - <chrisP 28Aug91> */
+ host_reset_print(adapter);
+#endif
+
+ if (toggled(old_control, value, AUTO_FEED))
+ host_print_auto_feed(adapter,
+ ((value & AUTO_FEED) != 0));
+
+ if (low_high(old_control, value, STROBE))
+ {
+#if defined(NTVDM)
+ if (get_state(adapter) == STATE_DONGLE) {
+ host_set_lpt_direct_access(adapter, FALSE);
+ /* pass through to print out the last byte
+ * which we have sent it out the data port
+ * while we are in DONGLE state.
+ */
+
+ set_state(adapter, STATE_READY);
+ }
+#endif
+
+#ifdef PS_FLUSHING
+ /*
+ * If PostScript flushing is enabled for this
+ * port then we flush on a Ctrl-D
+ */
+ if ( psFlushEnabled[adapter] &&
+ output_reg[adapter] == 0x04 /* ^D */ ) {
+ host_print_doc(adapter);
+ } else {
+#endif /* PS_FLUSHING */
+ /*
+ * Send the stored internal buffer to
+ * the printer
+ */
+ if(host_print_byte(adapter,output_reg[adapter]) == FALSE)
+ {
+ set_status(adapter, get_status(adapter) & ~ERROR); /* active Low */
+ /* NTVDM had here(?): set_status(adapter, ACK|PEND|SELECT|ERROR); */
+ /* two status inbs before we clear ERROR */
+ retryErrorCount = 2;
+ }
+ else
+ {
+ /* clear ERROR condition */
+ set_status(adapter, get_status(adapter) | ERROR);
+#if defined(NTVDM) && !defined(MONITOR)
+ set_low(status_reg[adapter], NOTBUSY);
+#else /* NTVDM && !MONITOR */
+ set_status(adapter,
+ get_status(adapter) & ~NOTBUSY);
+#endif /* NTVDM && !MONITOR */
+ set_state(adapter, STATE_OUT);
+#ifndef DELAYED_INTS
+ handle_for_out_event[adapter]=add_q_event_t(lpr_state_out_event,HOST_PRINTER_DELAY,adapter);
+#endif /* DELAYED_INTS */
+ }
+#ifdef PS_FLUSHING
+ }
+#endif /* PS_FLUSHING */
+ }
+ else if (high_low(old_control, value, STROBE)
+ && get_state(adapter) == STATE_OUT)
+ {
+ if (value & IRQ)
+ {
+ /*
+ * Application is using
+ * interrupts, so we can't
+ * rely on INBs being
+ * used to check the
+ * printer status.
+ */
+ set_state(adapter, STATE_READY);
+ notbusy_check(adapter);
+ }
+ }
+
+#if defined(NTVDM)
+ else if (low_high(old_control, value, IRQ) &&
+ get_state(adapter) == STATE_DONGLE) {
+
+ host_set_lpt_direct_access(adapter, FALSE);
+ set_state(adapter, STATE_READY);
+ }
+
+#endif
+
+#ifndef PROD
+ if (old_control & IRQ)
+ note_trace1(PRINTER_VERBOSE, "Warning: LPT%d is being interrupt driven\n",
+ number_for_adapter(adapter));
+#endif
+ break;
+ }
+ break;
+ default:
+ note_trace1(PRINTER_VERBOSE, "<poutb() - unknown state %x>",
+ get_state(adapter));
+ break;
+ }
+}
+
+void printer_status_changed IFN1(int,adapter)
+{
+ note_trace1(PRINTER_VERBOSE, "<printer_status_changed() adapter %d>",
+ adapter);
+
+ /* check whether the printer has just changed state to NOTBUSY */
+ notbusy_check(adapter);
+}
+
+/*
+ * ============================================================================
+ * Internal functions
+ * ============================================================================
+ */
+
+static void notbusy_check IFN1(int,adapter)
+{
+ /*
+ * This function is used to detect when the printer
+ * state transition to NOTBUSY occurs.
+ *
+ * If the parallel port is being polled, the port
+ * emulation will stop this transition occurring
+ * until the application has detected the ACK
+ * pulse. notbusy_check() is then called each time the
+ * port status is read using the INB; when the host
+ * says the printer is HOST_LPT_BUSY, the port status
+ * returns to the NOTBUSY state.
+ *
+ * If the parallel port is interrupt driven, we cannot
+ * rely on the application using the INB: so we first
+ * check the host printer status immediately after
+ * outputting the character. If the host printer isn't
+ * HOST_LPT_BUSY, then we interrupt immediately;
+ * otherwise, we rely on the printer_status_changed()
+ * call to notify us of when HOST_LPT_BUSY is cleared.
+ */
+
+ /* <chrisP 11Sep91> allow not busy at leading edge of ack pulse too */
+ if ( (get_state(adapter) == STATE_READY ||
+#if defined(NTVDM)
+ get_state(adapter) == STATE_DATA ||
+#endif
+ get_state(adapter) == STATE_OUTA)
+ && !(get_status(adapter) & NOTBUSY)
+ && !(host_lpt_status(adapter) & HOST_LPT_BUSY))
+ {
+#if defined(NTVDM) && !defined(MONITOR)
+ set_high(status_reg[adapter], NOTBUSY);
+#else /* NTVDM && !MONITOR */
+ set_status(adapter, get_status(adapter) | NOTBUSY);
+#endif /* NTVDM && !MONITOR */
+
+#ifndef PROD
+ if (io_verbose & PRINTER_VERBOSE)
+ fprintf(trace_file, "<printer notbusy_check() - adapter %d changed to NOTBUSY>\n", adapter);
+#endif
+
+ if (get_control(adapter) & IRQ)
+ {
+ ica_hw_interrupt(0, CPU_PRINTER_INT, 1);
+ }
+ }
+}
+#ifdef SEGMENTATION
+/*
+ * The following #include specifies the code segment into which this
+ * module will by placed by the MPW C compiler on the Mac II running
+ * MultiFinder.
+ */
+#include "SOFTPC_INIT.seg"
+#endif
+
+/*
+** Initialise the printer port required.
+*/
+void printer_init IFN1(int,adapter)
+{
+ io_addr i;
+
+ io_define_inb( lpt_adapter[adapter], printer_inb );
+ io_define_outb( lpt_adapter[adapter], printer_outb );
+ for(i = port_start[adapter]; i < port_end[adapter]; i++)
+ io_connect_port(i,lpt_adapter[adapter],IO_READ_WRITE);
+
+#if defined(NTVDM) && defined(MONITOR)
+ /*
+ * If we know the addresses of the 16-bit variables write directly
+ * to them, otherwise save the value until we do.
+ */
+ if (intel_setup)
+ {
+ set_status(adapter, 0xDF);
+ set_control(adapter, 0xEC);
+ }
+ else
+#endif /* NTVDM && MONITOR */
+ {
+ control_reg[adapter] = 0xEC;
+ status_reg[adapter] = 0xDF;
+ }
+ output_reg[adapter] = 0xAA;
+
+ /*
+ * The call to host_print_doc has been removed since it is
+ * sensible to distinguish between a hard flush (on ctl-alt-del)
+ * or menu reset and a soft flush under user control or at end
+ * of PC application. The calls to host_lpt_close() followed
+ * by host_lpt_open() should already cause a flush to occur,
+ * so no functionality is lost. The first time printer_init is
+ * called host_lpt_close() is not called, but this cannot
+ * matter since host_print_doc() can only be a no-op.
+ */
+ /* host_print_doc(adapter); */
+ host_print_auto_feed(adapter, FALSE);
+
+#if defined(NTVDM) && defined(MONITOR)
+ if (intel_setup)
+ set_state(adapter, STATE_READY);
+ else
+#endif /* NTVDM && MONITOR */
+ state[adapter] = STATE_READY;
+
+} /* end of printer_init() */
+
+#if defined(NTVDM) && defined(MONITOR)
+/*
+** Store 16-bit address of status table and fill it with current values.
+*/
+#ifdef ANSI
+void printer_setup_table(sys_addr table_addr)
+#else /* ANSI */
+void printer_setup_table(table_addr)
+sys_addr table_addr;
+#endif /* ANSI */
+{
+ int i;
+ sys_addr lp16BufSize;
+ unsigned int cbBuf;
+ word lptBasePortAddr[NUM_PARALLEL_PORTS];
+
+ if (!intel_setup)
+ {
+
+ /*
+ * Store the addresses of the tables resident in 16-bit code. These
+ * are:
+ * status register (NUM_PARALLEL_PORTS bytes)
+ * state register (NUM_PARALLEL_PORTS bytes)
+ * control register (NUM_PARALLEL_PORTS bytes)
+ * host_lpt_status (NUM_PARALLEL_PORTS bytes)
+ *
+ * Then transfer any values which have already been set up into the
+ * variables. This is in case printer_init has been called prior to
+ * this function.
+ */
+ status_addr = table_addr;
+ state_addr = table_addr + NUM_PARALLEL_PORTS;
+ control_addr = table_addr + 2 * NUM_PARALLEL_PORTS;
+ for (i = 0; i < NUM_PARALLEL_PORTS; i++)
+ {
+ set_status(i, status_reg[i]);
+ set_state(i, state[i]);
+ set_control(i, control_reg[i]);
+ lptBasePortAddr[i] = port_start[i];
+ }
+
+ /* Let host know where host_lpt_status is stored in 16-bit code. */
+ host_printer_setup_table(table_addr, NUM_PARALLEL_PORTS, lptBasePortAddr);
+/* sudeepb 24-Jan-1993 for printing performance for x86 */
+ lp16BufSize = table_addr + 4 * NUM_PARALLEL_PORTS;
+ cbBuf = (sas_w_at_no_check(lp16BufSize));
+ lp16BitPrtBuf = table_addr + (4 * NUM_PARALLEL_PORTS) + 2;
+ lp16BitPrtId = lp16BitPrtBuf + cbBuf;
+ lp16BitPrtCount = lp16BitPrtId + 1;
+ lp16BitPrtBusy = lp16BitPrtCount + 2;
+ intel_setup = TRUE;
+ }
+}
+#endif /* NTVDM && MONITOR */
+
+#endif
+
+#ifdef NTVDM
+void printer_is_being_closed(int adapter)
+{
+
+#if defined(MONITOR)
+ set_state(adapter, STATE_READY);
+#else
+ state[adapter] = STATE_READY;
+
+#endif
+}
+
+#endif
+
+
+#ifdef PS_FLUSHING
+/*(
+=========================== printer_psflush_change ============================
+PURPOSE:
+ Handle change of PostScript flush configuration option for a printer
+ port.
+INPUT:
+ hostID - Configuration item I.D.
+ apply - TRUE if change to be applied
+OUTPUT:
+ None
+ALGORITHM:
+ If PostScript flushing is being enabled then;
+ set the PostScript flush enable flag for the port;
+ disable autoflush for the port;
+ else;
+ reset the PostScript flush enable flag for the port;
+ enable autoflush for the port;
+===============================================================================
+)*/
+
+GLOBAL void printer_psflush_change IFN2(
+ IU8, hostID,
+ IBOOL, apply
+) {
+ IS32 adapter = hostID - C_LPT1_PSFLUSH;
+
+ assert1(adapter < NUM_PARALLEL_PORTS,"Bad hostID %d",hostID);
+
+ if ( apply )
+ if ( psFlushEnabled[adapter] = (IBOOL)config_inquire(hostID,NULL) )
+ host_lpt_disable_autoflush(adapter);
+ else
+ host_lpt_enable_autoflush(adapter);
+}
+#endif /* PS_FLUSHING */