diff options
Diffstat (limited to '')
-rw-r--r-- | private/mvdm/softpc.new/host/src/nt_lpt.c | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/host/src/nt_lpt.c b/private/mvdm/softpc.new/host/src/nt_lpt.c new file mode 100644 index 000000000..083ca7586 --- /dev/null +++ b/private/mvdm/softpc.new/host/src/nt_lpt.c @@ -0,0 +1,698 @@ +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <ntddvdm.h> +#include <windows.h> +#include "insignia.h" +#include "host_def.h" +#include <malloc.h> + + +/* + * Name: nt_lpt.c + * Derived From: Sun 2.0 sun4_lpt.c + * Author: D A Bartlett + * Created On: + * Purpose: NT specific parallel port functions + * + * (c)Copyright Insignia Solutions Ltd., 1991. All rights reserved. + * + + * Note. This port is unlike most ports because the config system has been + * removed. It was the job of the config system to validate and open the + * printer ports. The only calls to the host printer system are now + * make from printer.c. and consist of the following calls. + * + * + * 1) host_print_byte + * 2) host_print_auto_feed + * 3) host_print_doc + * 4) host_lpt_status + * + * + * On the Microsoft model the printer ports will be opened when they are + * written to. + * + * Modifications: + * + * Tim June 92. Amateur attempt at buffered output to speed things up. + * + */ + + +/* + + +Work outstanding on this module, + +1) Check the usage of port_state +2) Check error handling in write function +3) host_print_doc() always flushs the port, is this correct ? +4) host_print_auto_feed - what should this function do ? +5) Error handling in host_printer_open(), UIF needed ? + +*/ + + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */ + +#ifdef PRINTER + +/* SoftPC include files */ +#include "xt.h" +#include "error.h" +#include "config.h" +#include "timer.h" +#include "host_lpt.h" +#include "hostsync.h" +#include "host_rrr.h" +#include "gfi.h" +#include "debug.h" +#include "idetect.h" +#include "sas.h" +#include "printer.h" +#ifndef PROD +#include "trace.h" +#endif + +boolean flushBuffer IFN1(int, adapter); +#ifdef MONITOR +extern BOOLEAN MonitorInitializePrinterInfo(WORD, PWORD, PUCHAR, PUCHAR, PUCHAR, PUCHAR); +extern BOOLEAN MonitorEnablePrinterDirectAccess(WORD, HANDLE, BOOLEAN); +extern BOOLEAN MonitorPrinterWriteData(WORD Adapter, BYTE Value); + +extern sys_addr lp16BitPrtBuf; +extern sys_addr lp16BitPrtCount; +extern sys_addr lp16BitPrtId; +boolean host_print_buffer(int adapter); +#endif + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::: Macros ::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +#ifdef MONITOR + +sys_addr lpt_status_addr; + +#define get_lpt_status(adap) \ + (sas_hw_at_no_check(lpt_status_addr+(adap))) +#define set_lpt_status(adap,val) \ + (sas_store_no_check(lpt_status_addr+(adap), (val))) + +#else /* MONITOR */ + +#define get_lpt_status(adap) (host_lpt[(adap)].port_status) +#define set_lpt_status(adap,val) (host_lpt[(adap)].port_status = (val)) + +#endif /* MONITOR */ + +#define KBUFFER_SIZE 1024 // Buffering macros +#define HIGH_WATER 1020 +#define DIRECT_ACCESS_HIGH_WATER 1020 + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::: Structure for host specific state data ::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +typedef struct +{ + ULONG port_status; // Port status + HANDLE handle; // Printer handle + int inactive_counter; // Inactivate counter + int inactive_trigger; // When equal to inactive_counter close port + int bytesInBuffer; // current size of buffer + int flushThreshold; // + DWORD FileType; // DISK, CHAR, PIPE etc. + BOOLEAN active; // Printer open and active + BOOLEAN dos_opened; // printer opened with DOS open + byte *kBuffer; // output buffer + BOOLEAN direct_access; + BOOLEAN no_device_attached; +} HOST_LPT; + +HOST_LPT host_lpt[NUM_PARALLEL_PORTS]; + +#ifdef MONITOR + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::: On x86 machines the host_lpt_status table is kept on the 16-bit ::::*/ +/*:::: side in order to reduce the number of expensive BOPs. Here we ::::*/ +/*:::: are passed the address of the table. ::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +GLOBAL void host_printer_setup_table(sys_addr table_addr, word nPorts, word * portAddr) +{ + lpt_status_addr = table_addr + 3 * NUM_PARALLEL_PORTS; + // Now fill in the TIB entries for printer_info + MonitorInitializePrinterInfo (nPorts, + portAddr, + (LPBYTE)(table_addr + NUM_PARALLEL_PORTS), + (LPBYTE)(table_addr + 2 * NUM_PARALLEL_PORTS), + (LPBYTE)(table_addr), + (LPBYTE)(lpt_status_addr) + ); + + +} + +#endif /* MONITOR */ + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::: Set auto close trigger :::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +VOID host_set_inactivate_counter(int adapter) +{ + FAST HOST_LPT *lpt = &host_lpt[adapter]; + int close_in_ms; // Flush rate in milliseconds + + /*::::::::::::::::::::::::::::::::::::::::::::::: Is auto close enabled */ + + + if(!config_inquire(C_AUTOFLUSH, NULL)) + { + lpt->inactive_trigger = 0; /* Disable auto flush */ + return; /* Autoflush not active */ + } + + /*::::::::::::::::::::::::::::::::::::::::::: Calculate closedown count */ + + close_in_ms = ((int) config_inquire(C_AUTOFLUSH_DELAY, NULL)) * 1000; + + lpt->inactive_trigger = close_in_ms / (SYSTEM_TICK_INTV/1000); + + lpt->inactive_counter = 0; //Reset close down counter + lpt->no_device_attached = FALSE; +} + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::: Open printer :::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +SHORT host_lpt_open(int adapter, BOOLEAN direct_access) +{ + DWORD BytesReturn; + + FAST HOST_LPT *lpt = &host_lpt[adapter]; // Adapter control structure + CHAR *lptName; // Adapter filename + + if (!direct_access) + lpt->no_device_attached = FALSE; + else if (lpt->no_device_attached) + return FALSE; + + lpt->bytesInBuffer = 0; // Init output buffer index + + /*::::::::::::::::::::::::::::::::::::::::: Get printer name for Config */ + + /* use a different device name for DONGLE support */ + lptName = (CHAR *) config_inquire((UTINY)((direct_access ? C_VDMLPT1_NAME : + C_LPT1_NAME) + + adapter), NULL); + +#ifndef PROD + fprintf(trace_file, "Opening printer port %s (%d)\n",lptName,adapter); +#endif + + if ((lpt->kBuffer = (byte *)host_malloc (KBUFFER_SIZE)) == NULL) { + // dont put a popup here as the caller of this routine handles it + return(FALSE); + } + lpt->flushThreshold = HIGH_WATER; + + /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::: Open printer */ + + + lpt->direct_access = FALSE; + lpt->active = FALSE; + + lpt->handle = CreateFile(lptName, + GENERIC_WRITE, + direct_access ? 0 : FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + + /*:::::::::::::::::::::::::::::::::::::::::::::::::: Valid open request */ + + if(lpt->handle == (HANDLE) -1) + { + host_free (lpt->kBuffer); + // UIF needed to inform user that the open attempt failed +#ifndef PROD + fprintf(trace_file, "Failed to open printer port\n"); +#endif + if (direct_access && GetLastError() == ERROR_FILE_NOT_FOUND) + lpt->no_device_attached = TRUE; + + return(FALSE); + } + + + /*::::::::::::::::::::::::::::::::::::::Activate port and reset status */ + + lpt->FileType = GetFileType(lpt->handle); + // can not open direct_access access to a redirected device. + if (direct_access && lpt->FileType != FILE_TYPE_CHAR) { + CloseHandle(lpt->handle); + return FALSE; + } + lpt->active = TRUE; + set_lpt_status(adapter, 0); + lpt->direct_access = direct_access; + if (lpt->direct_access) { + lpt->flushThreshold = DIRECT_ACCESS_HIGH_WATER; +#ifdef MONITOR + MonitorEnablePrinterDirectAccess((WORD)adapter, lpt->handle, TRUE); +#endif + } + + /*:::::::::::::::::::::::::::::::::::::::::: Setup auto close counters */ + + host_set_inactivate_counter(adapter); + + return(TRUE); +} + +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::: Close all printer ports ::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +GLOBAL void host_lpt_close_all(void) +{ + FAST HOST_LPT *lpt; + FAST int i; + + /*::::::::::: Scan through printer adapters updating auto flush counters */ + + + for(i=0, lpt = &host_lpt[0]; i < NUM_PARALLEL_PORTS; i++, lpt++) + { + + if(lpt->active) + host_lpt_close(i); /* Close printer port */ + } +} + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::::: Close printer :::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +VOID host_lpt_close(int adapter) +{ + DWORD BytesReturn; + + FAST HOST_LPT *lpt = &host_lpt[adapter]; + + if (lpt->direct_access) + printer_is_being_closed(adapter); + +#ifdef MONITOR + if (sas_hw_at_no_check(lp16BitPrtId) == adapter){ + host_print_buffer (adapter); + sas_store_no_check(lp16BitPrtId,0xff); + } +#endif + /*::::::::::::::::::::::::::::::::::::::::: Is the printer port active */ + + if(lpt->active) + { + /* + ** Tim June 92. Flush output buffer to get the last output out. + ** If there's an error I think we've got to ignore it. + */ + (void)flushBuffer(adapter); + +#ifndef PROD + fprintf(trace_file, "Closing printer port (%d)\n",adapter); +#endif + +#ifdef MONITOR + if (lpt->direct_access) + MonitorEnablePrinterDirectAccess((WORD)adapter, lpt->handle, FALSE); +#endif + CloseHandle(lpt->handle); /* Close printer port */ + host_free (lpt->kBuffer); + lpt->handle = (HANDLE) -1; /* Mark device as closed */ + + lpt->active = FALSE; /* Deactive printer port */ + set_lpt_status(adapter, 0); /* Reset port status */ + +#ifndef PROD + fprintf(trace_file, "Counter expired, closing LPT%d\n", adapter+1); +#endif + } +} + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::: Return the status of the lpt channel for an adapter :::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +GLOBAL ULONG host_lpt_status(int adapter) +{ + return(get_lpt_status(adapter)); +} + +GLOBAL UCHAR host_read_printer_status_port(int adapter) +{ + FAST HOST_LPT *lpt = &host_lpt[adapter]; + UCHAR PrinterStatus; + DWORD BytesReturn; + + + if(!lpt->active) + { + /*:::::::::::::::::::::::::::: Port inactive, attempt to reopen it */ + + if(!host_lpt_open(adapter, TRUE)) + { +#ifndef PROD + fprintf(trace_file, "file open error %d\n", GetLastError()); +#endif + set_lpt_status(adapter, HOST_LPT_BUSY); + return(FALSE); /* exit, printer not active !!!! */ + } + } + if (lpt->bytesInBuffer) + flushBuffer(adapter); + if (!DeviceIoControl(lpt->handle, + IOCTL_VDM_PAR_READ_STATUS_PORT, + NULL, // no input buffer + 0, + &PrinterStatus, + sizeof(PrinterStatus), + &BytesReturn, + NULL // no overlap + )) { + +#ifndef PROD + fprintf(trace_file, + "host_read_printer_status_port failed, error = %ld\n", + GetLastError() + ); +#endif + PrinterStatus = 0; + } + return(PrinterStatus); +} + +BOOLEAN host_set_lpt_direct_access(int adapter, BOOLEAN direct_access) +{ + DWORD BytesReturn; + + FAST HOST_LPT *lpt = &host_lpt[adapter]; + + host_lpt_close(adapter); + host_lpt_open(adapter, direct_access); + if (!lpt->active) + set_lpt_status(adapter, HOST_LPT_BUSY); + return (lpt->active); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::: Print a byte ::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +/* +** Buffer up bytes before they are printed. +** Strategy: +** Save each requested byte in the buffer. +** When the buffer gets full or there's a close request write the +** buffered stuff out. +** Don't forget about errors, eg if the write fails. What about a write +** failure during the close request though? Tough said Tim. +*/ +/* +** flushBuffer() +** Finally write what is in the buffer to the parallel port. It could be a +** real port or a networked printer. +** Input parameter is the parallel port adapter number 0=LPT1 +** Return value of TRUE means write was OK. +*/ +boolean flushBuffer IFN1( int, adapter ) +{ + FAST HOST_LPT *lpt = &host_lpt[adapter]; + DWORD BytesWritten; + + if (lpt->direct_access) { + DeviceIoControl(lpt->handle, + IOCTL_VDM_PAR_WRITE_DATA_PORT, + lpt->kBuffer, + lpt->bytesInBuffer, + NULL, + 0, + &BytesWritten, + NULL + ); + + lpt->bytesInBuffer = 0; + return TRUE; + + } + + + if( !WriteFile( lpt->handle, lpt->kBuffer, + lpt->bytesInBuffer, &BytesWritten, NULL ) + ){ +#ifndef PROD + fprintf(trace_file, "lpt write error %d\n", GetLastError()); +#endif + lpt->bytesInBuffer = 0; + return(FALSE); + }else{ + lpt->bytesInBuffer = 0; + + + /* + * If the print job is being spooled, the spooler can + * take a long time to get started, because of the spoolers + * low priority. This is especially bad for dos apps in which + * idle detection fails or in full screen idle detection is + * inactive. To help push the print job thru the system, + * idle a bit now. + */ + if (lpt->FileType == FILE_TYPE_PIPE) { + Sleep(10); + } + return( TRUE ); + } + +} /* end of flushBuffer() */ + +/* +** Put another byte in to the buffer. If the buffer is full call the +** flush function. +** Return value of TRUE means OK, return FALSE means did a flush and +** it failed. +*/ +boolean toBuffer IFN2( int, adapter, BYTE, b ) +{ + HOST_LPT *lpt = &host_lpt[adapter]; + boolean status = TRUE; + + lpt->kBuffer[lpt->bytesInBuffer++] = b; + + if( lpt->bytesInBuffer >= lpt->flushThreshold ){ + status = flushBuffer( adapter ); + } + return( status ); +} /* end of toBuffer() */ + +GLOBAL BOOL host_print_byte(int adapter, byte value) +{ + FAST HOST_LPT *lpt = &host_lpt[adapter]; + + /*:::::::::::::::::::::::::::::::::::::::::::: Is the printer active ? */ + + if(!lpt->active) + { + /*:::::::::::::::::::::::::::: Port inactive, attempt to reopen it */ + + if(!host_lpt_open(adapter, FALSE)) + { +#ifndef PROD + fprintf(trace_file, "file open error %d\n", GetLastError()); +#endif + set_lpt_status(adapter, HOST_LPT_BUSY); + return(FALSE); /* exit, printer not active !!!! */ + } + } +#if defined(MONITOR) + if (lpt->direct_access) { + MonitorPrinterWriteData((WORD)adapter, value); + } + else +#endif + { + + /*:::::::::::::::::::::::::::::::::::::::::::::::: Send byte to printer */ + + if(toBuffer(adapter, (BYTE) value) == FALSE) + { + set_lpt_status(adapter, HOST_LPT_BUSY); + return(FALSE); + } + } + + /*::::::::::::::::::::::::::: Update idle and activate control variables */ + + lpt->inactive_counter = 0; /* Reset inactivity counter */ + IDLE_comlpt(); /* Tell Idle system there is printer activate */ + + return(TRUE); +} + + +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::: LPT heart beat call ::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +GLOBAL void host_lpt_heart_beat(void) +{ + FAST HOST_LPT *lpt = &host_lpt[0]; + int i; + + + /*::::::::::: Scan through printer adapters updating auto close counters */ + + + for(i=0; i < NUM_PARALLEL_PORTS; i++, lpt++) + { + + /*:::::::::::::::::::::::::::::::::::::::: Check auto close counters */ + + if(lpt->active && lpt->inactive_trigger && + ++lpt->inactive_counter == lpt->inactive_trigger) + { + host_lpt_close(i); /* Close printer port */ + } + } +} + + +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::: Flush the printer port ::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +#if 0 +GLOBAL boolean host_print_doc(int adapter) +{ + if(host_lpt[adapter].active) host_lpt_close(adapter); /* Close printer port */ + + return(TRUE); +} +#endif + +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::: Reset the printer port ::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +GLOBAL void host_reset_print(int adapter) +{ + if(host_lpt[adapter].active) + host_lpt_close(adapter); /* Close printer port */ +} + + +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::: host_print_auto_feed :::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +GLOBAL void host_print_auto_feed(int adapter, BOOL value) +{ + UNREFERENCED_FORMAL_PARAMETER(adapter); + UNREFERENCED_FORMAL_PARAMETER(value); +} + +#ifdef MONITOR + +GLOBAL boolean host_print_buffer(int adapter) +{ + FAST HOST_LPT *lpt = &host_lpt[adapter]; + word cb; + byte i,ch; + + cb = sas_w_at_no_check(lp16BitPrtCount); + if (!cb) + return (TRUE); + + /*:::::::::::::::::::::::::::::::::::::::::::: Is the printer active ? */ + + if(!lpt->active) + { + /*:::::::::::::::::::::::::::: Port inactive, attempt to reopen it */ + + if(!host_lpt_open(adapter, FALSE)) + { +#ifndef PROD + fprintf(trace_file, "file open error %d\n", GetLastError()); +#endif + set_lpt_status(adapter, HOST_LPT_BUSY); + return(FALSE); /* exit, printer not active !!!! */ + } + } + + if (!lpt->direct_access) { + /*:::::::::::::::::::::::::::::::::::::::::::::::: Send byte to printer */ + + for (i=0; i <cb; i++) { + ch = sas_hw_at_no_check(lp16BitPrtBuf+i); + if(toBuffer(adapter, ch) == FALSE) + { + set_lpt_status(adapter, HOST_LPT_BUSY); + return(FALSE); + } + } + } + else { + // we must no have any int 17 printing data waiting when we + // we in direct access mode + ASSERT(cb == 0); + return FALSE; + } + /*::::::::::::::::::::::::::: Update idle and activate control variables */ + + lpt->inactive_counter = 0; /* Reset inactivity counter */ + IDLE_comlpt(); /* Tell Idle system there is printer activate */ + + return(TRUE); +} +#endif // MONITOR + +GLOBAL void host_lpt_dos_open(int adapter) +{ + FAST HOST_LPT *lpt = &host_lpt[adapter]; + + lpt->dos_opened = TRUE; +} + +GLOBAL void host_lpt_dos_close(int adapter) +{ + FAST HOST_LPT *lpt = &host_lpt[adapter]; + + if (lpt->active) + host_lpt_close(adapter); /* Close printer port */ + lpt->dos_opened = FALSE; +} + +GLOBAL void host_lpt_flush_initialize() +{ + FAST HOST_LPT *lpt; + FAST int i; + + for(i=0, lpt = &host_lpt[0]; i < NUM_PARALLEL_PORTS; i++, lpt++) + lpt->dos_opened = FALSE; + +} + +#endif /* PRINTER */ |