home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* u l i b f s . c */
- /* */
- /* UUPC/extended communications driver for MS-DOS FOSSIL */
- /* based systems. */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* Changes Copyright (c) 1989-1993 by Kendra Electronic */
- /* Wonderworks. */
- /* */
- /* All rights reserved except those explicitly granted by the */
- /* UUPC/extended license agreement. */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* RCS Information */
- /*--------------------------------------------------------------------*/
-
- /*
- * $Id: ulibfs.c 1.3 1993/10/03 22:09:09 ahd Exp $
- *
- * History:
- * $Log: ulibfs.c $
- * Revision 1.3 1993/10/03 22:09:09 ahd
- * Use unsigned long to display speed
- *
- * Revision 1.2 1993/05/30 15:25:50 ahd
- * Multiple driver support
- *
- * Revision 1.1 1993/05/30 00:01:47 ahd
- * Initial revision
- *
- */
-
- /*--------------------------------------------------------------------*/
- /* System include files */
- /*--------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <string.h> // For memset()
- #include <stdlib.h> // For max()
- #include <dos.h> // For FOSSIL interrupt calls
- #include <time.h> // For sleep.h support
-
- /*--------------------------------------------------------------------*/
- /* UUPC/extended include files */
- /*--------------------------------------------------------------------*/
-
- #include "lib.h"
- #include "ulibfs.h"
- #include "commlib.h"
- #include "fossil.h"
- #include "catcher.h" // For terminate processing flags
- #include "ssleep.h" // For ddelay, etc.
-
- /*--------------------------------------------------------------------*/
- /* Internal prototypes */
- /*--------------------------------------------------------------------*/
-
- static void showModem( const short );
-
- static void getDriverInfo( FS_INFO *fossilData);
-
- static short blockIO( char *buffer,
- const short len,
- const char function);
-
- /*--------------------------------------------------------------------*/
- /* Global variables */
- /*--------------------------------------------------------------------*/
-
- static BPS currentBPS;
- static boolean currentDirect;
- static boolean carrierDetect;
- static boolean hangupNeeded;
-
- currentfile();
-
- /*--------------------------------------------------------------------*/
- /* f o p e n L i n e */
- /* */
- /* Open a fossil controlled port */
- /*--------------------------------------------------------------------*/
-
- int fopenline(char *name, BPS baud, const boolean direct)
- {
- short result;
- FS_INFO fossilData; // Information returned by FOSSIL
-
- /*--------------------------------------------------------------------*/
- /* Determine the port number */
- /*--------------------------------------------------------------------*/
-
- if (sscanf(name, "COM%d", &portNum) != 1)
- {
- printmsg(0,"Communications port must be format COMx, was %s",
- name);
- panic();
- }
-
- portNum--; // FOSSIL uses offset, not ordinal number
-
- /*--------------------------------------------------------------------*/
- /* Attempt to initialize the driver */
- /*--------------------------------------------------------------------*/
-
- result = FSOpen( ); // Try to open the port
- if ( result != FS_COOKIE )
- {
- printmsg(0,"fopenLine: Open failed, result %d",result );
- return TRUE; // Report failure
- }
-
- /*--------------------------------------------------------------------*/
- /* Now initialize the rest of the port information */
- /*--------------------------------------------------------------------*/
-
- ssleep(2); // Wait two seconds as required by V.24
-
- currentDirect = direct; // Save for flow control processing
- carrierDetect = FALSE; // No modem connected yet
-
- flowcontrol( FALSE ); // Set no (or hardware) flow control
- fSIOSpeed( baud ); // Set the port speed
- traceStart( name ); // Enable line tracing
-
- getDriverInfo( &fossilData );
-
- printmsg(4,"fopenline: Driver: %Fs (revision %d)",
- fossilData.id,
- (int) fossilData.revision );
- printmsg(4,"fopenline: FOSSIL version %d, "
- "input buffer %d, output buffer %d",
- (int) fossilData.version,
- (int) fossilData.inputSize,
- (int) fossilData.outputSize );
-
- portActive = TRUE; // Flag port is open
- return FALSE; // Report success to caller
-
- } /* fopenLine */
-
- /*--------------------------------------------------------------------*/
- /* f s r e a d */
- /* */
- /* Read a specified number of bytes from the serial port */
- /*--------------------------------------------------------------------*/
-
- unsigned int fsread(char *buffer,
- unsigned int wanted,
- unsigned int timeout)
- {
- FS_INFO fossilData; // Information returned by FOSSIL
-
- time_t quit = time( NULL ) + timeout;
-
- showModem( FSStatus()); // Report modem status if changed
-
- /*--------------------------------------------------------------------*/
- /* Main loop to read data from FOSSIL */
- /*--------------------------------------------------------------------*/
-
- for ( ;; )
- {
- unsigned int pending;
-
- getDriverInfo( &fossilData );
- pending = fossilData.inputSize - fossilData.inputFree;
-
- if ( pending >= wanted )
- {
- unsigned int moved = blockIO( buffer, wanted, FS_READBLOK );
- // Get the data
- traceData( buffer, moved, FALSE ); // Trace the data
-
- if ( moved < wanted) // Promised data delivered?
- { // NO --> Panic (literally)
- printmsg(0,"fsread: Read failed at %d of %d bytes"
- "(%d bytes available)",
- moved,
- wanted,
- pending );
- panic();
- }
-
- return pending; // Return success
-
- } /* if ( pending >= wanted ) */
-
- /*--------------------------------------------------------------------*/
- /* We don't have the data we need (yet), see if we can wait */
- /* for it. */
- /*--------------------------------------------------------------------*/
-
- if (quit <= time(NULL)) // Any time left to wait?
- {
- printmsg(20, "fsread: pending=%d, wanted=%d",
- pending, wanted);
- return pending; // No --> return quietly
- }
-
- if ( terminate_processing ) // User hit Ctrl-Break?
- {
- static boolean recurse = FALSE;
-
- if ( ! recurse )
- {
- printmsg(2,"fsread: User aborted processing");
- recurse = TRUE;
- }
- return 0;
-
- } /* if ( terminate_processing ) */
-
- if ( fossilData.inputSize < (int) wanted ) // Sanity check this ...
- { // last for performance reasons.
- printmsg(0,"fsread: FOSSIL queue too small (%d bytes) to"
- "satisfy read of %d bytes",
- fossilData.inputSize , wanted );
- panic();
-
- } /* if */
-
- ddelay(0); // Pause, then do it all again
-
- } /* for ( ;; ) */
-
- } /* fsread */
-
- /*--------------------------------------------------------------------*/
- /* f s w r i t e */
- /* */
- /* Write data to a FOSSIL controled serial port */
- /*--------------------------------------------------------------------*/
-
- int fswrite(const char *data, unsigned int queued)
- {
-
- int moved;
- int total;
- int spin;
- static int const max_spin = 20;
- FS_INFO fossilData; // Information returned by FOSSIL
-
- hangupNeeded = TRUE; // Serial port is now "dirty"
-
- showModem( FSStatus()); // Report modem status if changed
-
- /*--------------------------------------------------------------------*/
- /* Perform the I/O */
- /*--------------------------------------------------------------------*/
-
- moved = blockIO( (char *) data, queued, FS_WRITBLOK );
- // Write the data to port
-
- traceData( data, moved, TRUE); // Trace our output
-
- if ( moved == (int) queued ) // Did it all get written out?
- return moved; // Yes --> Return gracefully
-
- printmsg(4,"fswrite: Wrote %d bytes of %d", moved, queued);
-
- /*--------------------------------------------------------------------*/
- /* The FOSSIL driver didn't have enough room in its buffer; */
- /* determine how much we did send. */
- /*--------------------------------------------------------------------*/
-
- getDriverInfo( &fossilData );
-
- total = moved;
- queued -= moved; // We only need to still move this
-
- /*--------------------------------------------------------------------*/
- /* Block processing for a limited amount of time if we need */
- /* more room in the FOSSIL buffer. */
- /*--------------------------------------------------------------------*/
-
- spin = max_spin;
-
- while( spin && queued )
- {
- int wait;
- int needed;
-
- needed = max(fossilData.outputSize / 2, (int) queued );
- /* Minimize thrashing by requiring
- big chunks */
-
- wait = (int) ((long) needed * 10000L / (long) currentBPS);
- /* Compute time in milliseconds
- assuming 10 bits per byte */
-
- printmsg(4,"fswrite: Waiting %d ms for %d bytes in queue"
- ", pass %d",
- wait, needed, spin);
-
- ddelay( wait ); /* Actually perform the wait */
-
- moved = blockIO( (char *) data + total, queued, FS_WRITBLOK );
- // Write the data
- traceData( data + total, moved, TRUE); // Trace our output
-
- if ( moved != 0)
- spin--; /* No progress, consider timing out */
- else {
- total += moved;
- queued -= moved;
- } /* Update our progress */
-
- } /* while(spin && wanted ) */
-
- /*--------------------------------------------------------------------*/
- /* Handle buffer overflow which never went away */
- /*--------------------------------------------------------------------*/
-
- if ( queued )
- {
- printmsg(0,"fswrite: Buffer overflow, needed %d bytes",
- queued);
- return 0;
- } /* if ( queued ) */
-
- /*--------------------------------------------------------------------*/
- /* Return success to caller */
- /*--------------------------------------------------------------------*/
-
- return total;
-
- } /* fswrite */
-
- /*--------------------------------------------------------------------*/
- /* f s s e n d b r k */
- /* */
- /* Send a break to the remote system */
- /*--------------------------------------------------------------------*/
-
- void fssendbrk(unsigned int duration)
- {
-
- FSBreak( TRUE );
- printmsg(4, "fssendbrk: %d", duration);
- ddelay( duration * 100 );
- FSBreak( FALSE );
-
- } /* fssendbrk */
-
- /*--------------------------------------------------------------------*/
- /* f c l o s e l i n e */
- /* */
- /* Close a FOSSIL controlled port */
- /*--------------------------------------------------------------------*/
-
- void fcloseline(void)
- {
- if (!portActive)
- panic();
-
- portActive = FALSE; // Flag port closed for error handler
-
- FSFlushXmit(); // Drop XMIT queue if not empty
- FSFlushRecv(); // Drop Recv queue as well
-
- FSDTR( FALSE );
- ddelay(500); // Required for V.24
-
- FSClose();
- traceStop();
-
- } /* fcloseline */
-
- /*--------------------------------------------------------------------*/
- /* F S S e t S p e e d */
- /* */
- /* Set current speed port; also sets parity and associated */
- /* parameters. */
- /*--------------------------------------------------------------------*/
-
- void fSIOSpeed(BPS bps)
- {
-
- static const long rates[] =
- { 19200, 38400, 300, 600, 1200, 2400, 4800, 9600, -19200 };
-
- short speed = 0; // Actual value used by FOSSIL for speed
-
- short best = 3;
-
- while( (rates[speed] > 0) && (rates[speed] != (long) bps ))
- {
- if ( (rates[speed] / 100) == ((long) bps / 100) )
- best = speed;
-
- speed++;
- }
-
- if ( rates[speed] < 0 )
- {
- printmsg(0,"fSIOSpeed: Invalid modem speed %lu, using %lu",
- (unsigned long) bps,
- (unsigned long) rates[speed]);
- speed = best;
- }
-
- printmsg(4,"fSIOSspeed: Changing port speed from %lu BPS to %lu BPS",
- (unsigned long) currentBPS,
- (unsigned long) rates[speed]);
-
- FSSetSpeed( speed, FS_NO_PARITY, FS_STOPBIT_1, FS_CHARLEN_8);
-
- showModem( FSStatus()); // Report modem status if changed
-
- currentBPS = rates[speed];
-
- } /* fSIOSpeed */
-
- /*--------------------------------------------------------------------*/
- /* f f l o w c o n t r o l */
- /* */
- /* Enable flow control for FOSSIL driven port */
- /*--------------------------------------------------------------------*/
-
- void fflowcontrol( boolean flow )
- {
- printmsg(4,"fflowcontrol: %sabling in-band flow control",
- flow ? "en" : "dis");
- if ( flow )
- FSFlowControl( FS_XONXMIT | FS_XONRECV );
- else if ( currentDirect ) // Direct means no flow control
- FSFlowControl( FS_NOFLOW );
- else
- FSFlowControl( FS_CTSRTS );
-
- } /* fflowcontrol */
-
- /*--------------------------------------------------------------------*/
- /* f h a n g u p */
- /* */
- /* Perform hangup via DTR drop on FOSSIL controlled port */
- /*--------------------------------------------------------------------*/
-
- void fhangup( void )
- {
- if (!hangupNeeded)
- return;
-
- hangupNeeded = FALSE;
-
- FSFlushXmit(); // Drop XMIT queue if not empty
- FSFlushRecv(); // Drop Recv queue as well
-
- FSDTR( FALSE ); /* Hang the phone up */
- ddelay(500); /* Really only need 250 milliseconds */
- FSDTR( TRUE ); /* Bring the modem back on-line */
- ddelay(2000); /* Now wait for the poor thing to recover */
- /* two seconds is required by V.24 */
-
- printmsg(3,"fhangup: complete.");
- carrierDetect = FALSE; /* No modem connected yet */
-
- } /* fhangup */
-
- /*--------------------------------------------------------------------*/
- /* f G e t S p e e d */
- /* */
- /* Return current port speed */
- /*--------------------------------------------------------------------*/
-
- BPS fGetSpeed( void )
- {
- return currentBPS;
- }
-
- /*--------------------------------------------------------------------*/
- /* f C D */
- /* */
- /* Determine if Carrier Detect has dropped */
- /*--------------------------------------------------------------------*/
-
- boolean fCD( void )
- {
- boolean saveCD = carrierDetect;
-
- short status = FSStatus();
-
- showModem( status );
- if ( status & FS_STAT_DCD )
- carrierDetect = TRUE;
-
- if ((! saveCD) || carrierDetect)
- return TRUE;
-
- printmsg(0,"fCD: Lost carrier detect");
- return FALSE;
-
- } /* fCD */
-
- /*--------------------------------------------------------------------*/
- /* s h o w M o d e m */
- /* */
- /* Display current modem status */
- /*--------------------------------------------------------------------*/
-
- #define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
-
- static void showModem( const short status )
- {
- static int old_status = 0xDEAD;
-
- if ( debuglevel < 4 )
- return;
-
- if (status == old_status)
- return;
-
- printmsg(0, "showModem: %#04x%s%s%s%s%s",
- status,
- mannounce(FS_STAT_DCD, status, "\tCarrier Detect"),
- mannounce(FS_STAT_OVERRUN, status, "\tR-Overrun"),
- mannounce(FS_STAT_INQUEUED, status, "\tR-Pending"),
- mannounce(FS_STAT_OUTPROOM, status, "\tX-Free"),
- mannounce(FS_STAT_OUTPEMPT, status, "\tX-Empty")
- );
-
- old_status = status;
-
- } /* showModem */
-
- /*--------------------------------------------------------------------*/
- /* g e t D r i v e r I n f o */
- /* */
- /* Return current FOSSIL driver information */
- /*--------------------------------------------------------------------*/
-
- static void getDriverInfo( FS_INFO *fossilData)
- {
- union REGS regs;
- struct SREGS sregs;
-
- regs.h.ah = FS_DRIVINFO; // Get driver information
- regs.x.cx = sizeof *fossilData; // Into buffer this long
- sregs.es = FP_SEG( fossilData ); // Use segment of buffer
- regs.x.di = FP_OFF( fossilData ); // Use offset of buffer
- regs.x.dx = portNum; // For this port
-
- int86x( FS_INTERRUPT, ®s, ®s, &sregs);
-
- if ( regs.x.ax != sizeof *fossilData )
- {
- printmsg(0,"getDriverInfo: Read of FOSSIL information failed, "
- " %d bytes returned", regs.x.ax );
- panic();
- }
-
- } /* getDriverInfo */
-
- /*--------------------------------------------------------------------*/
- /* b l o c k I O */
- /* */
- /* Perform block I/O between memory and the FOSSIL data */
- /* queues */
- /*--------------------------------------------------------------------*/
-
- static short blockIO( char *buffer, const short len, const char function)
- {
- union REGS regs;
- struct SREGS sregs;
-
- regs.x.dx = portNum; // Perform function against port
-
- regs.h.ah = FS_STATPORT; // First, set up to get status
- int86( FS_INTERRUPT, ®s, ®s); // ... get the info ...
- showModem ( regs.x.ax ); // ... and report it
-
- regs.h.ah = function; // Input or output function
- regs.x.cx = len; // Into buffer this long
- sregs.es = FP_SEG( buffer); // Use segment of the buffer
- regs.x.di = FP_OFF( buffer ); // Use offset of buffer
-
- int86x( FS_INTERRUPT, ®s, ®s, &sregs);
-
- if ( len > (short) regs.x.ax )
- printmsg(4,"blockIO: Buffer %d bytes, only moved %d bytes",
- len,
- regs.x.ax );
- else if ( len < (short) regs.x.ax )
- {
- printmsg(4,"blockIO: BUFFER (%d bytes) OVERRUN, moved %d bytes",
- len,
- regs.x.ax );
- panic();
- }
-
- return (short) regs.x.ax; // Return bytes moved
-
- } /* blockIO */
-