$LARGE

/*       INSITE ORDER NO.   AB31                              */

/*         TITLE/VERSION:   TQNEW, V1.0                       */

/*              FUNCTION:   THIS PROGRAM PROVIDES RUN-TIME SUPPORT
                            FOR TERMINAL INPUT AND OUTPUT VIA THE 
                            USART ON AN ISBC 88/25, 86/05, 86/12B,
                            86/14, OR 86/30 BOARD. THIS RUN-TIME  
                            SUPPORT IS USED IN CONJUNCTION WITH   
                            PASCAL 86 OR FORTRAN 86.            */

/*         REQ'D HARDWARE:  DEVELOPMENT SYSTEM, ICE86, ICE88, OR  
                            ISBC-957B FOR DOWNLOADING.  TARGET    
                            SYSTEM INCLUDING AN ISBC 88/25, 86/05,
                            86/12A, 86/14, OR 86/30 BOARD.      */

/*         REQ'D SOFTWARE:  DEVELOPMENT SYSTEM, ISBC-957B       */

/*         REGISTERS MODIFIED: -                                */
/*         RAM REQUIRED:       DATA + STACK                     */
/*                              54D + 14D= 68D                  */

/*         ROM REQUIRED:       657D                             */
/*         MAX. SUBROUTINE NESTING LEVEL:  2                    */

/*         PROGRAMMER:     STEVE COOPER                           
                           INTEL CORPORATION                      
                           5200 NE ELAM YOUNG PKWY                
                           HILLSBORO, OR.  97123                */

TQ$DEVICE$MODULE: DO;

  TQDEVICE: PROCEDURE(NAME$PTR,NAME$LENGTH,DRIVER$TABLE$PTR) WORD PUBLIC;
    DECLARE (NAME$PTR,DRIVER$TABLE$PTR) POINTER;
    DECLARE NAME$LENGTH BYTE;
    DECLARE (NO$MATCH$FLAG,I) BYTE;
    DECLARE DRIVER$BASE BASED DRIVER$TABLE$PTR POINTER;
    DECLARE DRIVER$NAME BASED NAME$PTR(1) BYTE;
    DECLARE NAME(4) BYTE DATA(':T1:');
    DECLARE DRIVER$TABLE(10) POINTER;

/*  IF SPECIAL DEVICE THEN REASSIGN DEVICE DRIVER TABLE  */

    NO$MATCH$FLAG = 0;
/*  IF NAME$LENGTH <> 4 THEN NO$MATCH$FLAG = 1;                       */
/*  IF NO$MATCH$FLAG = 0 THEN DO I=0 TO 3;                            */
/*    IF NAME(I) <> DRIVER$NAME(I) THEN NO$MATCH$FLAG = 1;            */
/*  END;                                                              */
    IF NO$MATCH$FLAG = 0 THEN DO;
      DRIVER$BASE = @DRIVER$TABLE;
      DRIVER$TABLE(0) = @OPEN$NEW$DEVICE;
      DRIVER$TABLE(1) = @CLOSE$NEW$DEVICE;
      DRIVER$TABLE(2) = @READ$NEW$DEVICE;
      DRIVER$TABLE(3) = @WRITE$NEW$DEVICE;
      DRIVER$TABLE(4) = @SEEK$NEW$DEVICE;
      DRIVER$TABLE(5) = @NEW$MOVE;
      DRIVER$TABLE(6) = @NEW$MARK$END;
      DRIVER$TABLE(7) = @NEW$REWIND;
      DRIVER$TABLE(8) = @NEW$BACKSPACE;
      DRIVER$TABLE(9) = @NEW$END$FILE;
    END;
    RETURN 0;
  END TQDEVICE;

/***********************************************************************/
/***********************************************************************/
/***********************************************************************/
/*                     D E V I C E    D R I V E R S                    */
/***********************************************************************/
/***********************************************************************/
/***********************************************************************/
/*      OPEN A FILE                                                    */
/***********************************************************************/
 OPEN$NEW$DEVICE: PROCEDURE(FD$SEG,NAME$PTR,NAME$LENGTH,ATTRIB,REC$LENGTH) WORD PUBLIC;
  DECLARE (FD$SEG,ATTRIB,REC$LENGTH) WORD;
  DECLARE NAME$PTR POINTER;
  DECLARE NAME$LENGTH BYTE;
  DECLARE CNTL$PORT$8253 LITERALLY '0D6H' ; /* 3-4 OF 86/12A HRM */
  DECLARE COUNT$REG$8253 LITERALLY '0D4H' ;
  DECLARE STAT$PORT$8251 LITERALLY '0DAH' ;
  DECLARE CONTROL$BYTE$8253 LITERALLY '0B6H' ;     /* COUNTER 2*/
                                     /* READ/LOAD LEAST SIG. BYTE FIRST */
                                     /* MODE 3 - SQUARE WAVE RATE GENERATOR */
                                     /* 16 BIT BINARY COUNTER */
  DECLARE RESET$8251$TO$MODE LITERALLY '40H' ;
  DECLARE CONTROL$BYTE$8251  LITERALLY '4EH' ; /* BAUD RATE - ASYN X16 */
                                     /* 8 BIT CHARACTER LENGTH       */
                                     /* NO PARITY                    */
                                     /* ONE STOP BIT                 */
  DECLARE BAUD$CODE   LITERALLY '0008H'; /* 9600 BAUD */
  DECLARE ENABLE$8251 LITERALLY '27H';   /* TRANSMIT ENABLE   */
                                     /* RECEIVE ENABLE      */
                                     /* DTR BAR = 0  (READY)*/
                                     /* RTS BAR = 0  (READY)*/

/* FILE DESCRIPTOR HAS 16 BYTES TO STORE NECESSARY INFORMATION */
/* VAR WILL CONTAIN THE POINTER TO THE FILE DESCRIPTOR  */
/* FD$SEG FORMS THE BASE PORTION OF THE ADDRESS POINTING TO THE FILE DESC.*/
/* STORE INFO REGARDING TYPE OF FILE TO BE USED WHEN MARKING END OF RECORD*/

  DECLARE VAR POINTER;
  DECLARE VAR$DESCRIPTOR STRUCTURE (OFFSET WORD, BASE WORD) AT (@VAR);
  DECLARE FILE$DESCRIPTOR BASED VAR STRUCTURE(
                                    AVAILABLE(16) BYTE,
                                    RESERVE(32) BYTE);

  VAR$DESCRIPTOR.OFFSET = 0;
  VAR$DESCRIPTOR.BASE = FD$SEG;
  FILE$DESCRIPTOR.AVAILABLE(0)=(ATTRIB AND 08H);   /* FORM OF FILE */


/* INITIALIZE THE INTERVAL TIMER (8253)  */

  OUTPUT (CNTL$PORT$8253) = CONTROL$BYTE$8253;
  OUTPUT (COUNT$REG$8253) = LOW(BAUD$CODE);
  OUTPUT (COUNT$REG$8253) = HIGH(BAUD$CODE);

/* INITIALIZE THE USART (8251)   SEND 3 ZERO'S TO CLEAR FIRST  */

  OUTPUT (STAT$PORT$8251) = 0H;
  OUTPUT (STAT$PORT$8251) = 0H;
  OUTPUT (STAT$PORT$8251) = 0H;

  OUTPUT (STAT$PORT$8251) = RESET$8251$TO$MODE;
  OUTPUT (STAT$PORT$8251) = CONTROL$BYTE$8251;
  OUTPUT (STAT$PORT$8251) = ENABLE$8251;

/* RETURN STATUS OF ZERO TO INDICATE SUCCESSFUL OPEN */
  RETURN 0;
  END OPEN$NEW$DEVICE;

/*************************************************************************/
/*     CLOSE A FILE                                                      */
/*************************************************************************/
  CLOSE$NEW$DEVICE: PROCEDURE(FD$SEG,DISPOSE) WORD PUBLIC;
  DECLARE FD$SEG WORD;
  DECLARE DISPOSE BYTE;
  RETURN 0;
  END CLOSE$NEW$DEVICE;

/*************************************************************************/
/*      READ A BLOCK                                                     */
/*************************************************************************/
  READ$NEW$DEVICE: PROCEDURE(FD$SEG,BUFFER$PTR,COUNT,ACTUAL$PTR) WORD PUBLIC;
  DECLARE (FD$SEG,COUNT) WORD;
  DECLARE (BUFFER$PTR,ACTUAL$PTR) POINTER;
  DECLARE ACTUAL BASED ACTUAL$PTR WORD;
  DECLARE BUFFER BASED BUFFER$PTR (128) BYTE;
  DECLARE CR LITERALLY '0DH';
  DECLARE LF LITERALLY '0AH';
  DECLARE READING BYTE;
  DECLARE STAT$PORT$8251 LITERALLY '0DAH';
  DECLARE DATA$PORT$8251 LITERALLY '0D8H';

READING = 1;
ACTUAL = 0;
IF COUNT = 0 THEN READING = 0;
DO WHILE READING = 1;
IF ((INPUT(STAT$PORT$8251) AND 2) <> 0) THEN DO;
    BUFFER(ACTUAL) = INPUT(DATA$PORT$8251) AND 7FH;
    OUTPUT(DATA$PORT$8251) = BUFFER(ACTUAL);
    IF BUFFER(ACTUAL) <> CR THEN DO;
         ACTUAL = ACTUAL + 1;
         IF ACTUAL = COUNT THEN READING = 0;
         END;
    ELSE DO;
         OUTPUT(DATA$PORT$8251) = LF;
         READING = 0;
         END;
END;
END;
  RETURN 0;
  END READ$NEW$DEVICE;

/************************************************************************/
/*      WRITE A BLOCK                                                   */
/************************************************************************/
  WRITE$NEW$DEVICE: PROCEDURE (FD$SEG,BUFFER,COUNT) WORD PUBLIC;
  DECLARE (FD$SEG,COUNT) WORD;
  DECLARE BUFFER POINTER;
  DECLARE STATUS BYTE;
  DECLARE I WORD;
  DECLARE BUF BASED BUFFER(1) BYTE;
  DECLARE STAT$PORT$8251 LITERALLY '0DAH';
  DECLARE DATA$PORT$8251 LITERALLY '0D8H';

  DO I=0 TO COUNT-1;
   DO WHILE ((INPUT(STAT$PORT$8251)  AND 4H) = 0);   /* CHECK FOR TxEMPTY  */
   END;
   OUTPUT(DATA$PORT$8251) = BUF(I);
  END;
 RETURN 0;
 END WRITE$NEW$DEVICE;

/**************************************************************************/
/*      RECORD SEEK                                                       */
/**************************************************************************/
  SEEK$NEW$DEVICE: PROCEDURE(FD$SEG,MODE,HIGH$OFFSET,LOW$OFFSET) WORD PUBLIC;
  DECLARE (FD$SEG,HIGH$OFFSET,LOW$OFFSET) WORD;
  DECLARE MODE BYTE;
  RETURN 0;
  END SEEK$NEW$DEVICE;

/*************************************************************************/
/*      MOVE FORWARD                                                     */
/*************************************************************************/
  NEW$MOVE: PROCEDURE(FD$SEG) WORD PUBLIC;
  DECLARE FD$SEG WORD;
  RETURN 0;
  END NEW$MOVE;

/*************************************************************************/
/*      MARK RECORD END                                                  */
/*************************************************************************/
  NEW$MARK$END: PROCEDURE(FD$SEG) WORD PUBLIC;
  DECLARE FD$SEG WORD;
  DECLARE DATA$PORT$8251 LITERALLY '0D8H';
  DECLARE STAT$PORT$8251 LITERALLY '0DAH';
  DECLARE CR LITERALLY '0DH';
  DECLARE LF LITERALLY '0AH';

/* FILE DESCRIPTOR HAS 16 BYTES TO STORE NECESSARY INFORMATION */
/* VAR WILL CONTAIN THE POINTER TO THE FILE DESCRIPTOR  */
/* FD$SEG FORMS THE BASE PORTION OF THE ADDRESS POINTING TO THE FILE DESC.*/
/* RETRIEVE INFO REGARDING TYPE OF FILE TO KNOW HOW TO END A RECORD*/

  DECLARE VAR POINTER;
  DECLARE VAR$DESCRIPTOR STRUCTURE (OFFSET WORD, BASE WORD) AT (@VAR);
  DECLARE FILE$DESCRIPTOR BASED VAR STRUCTURE(
                                    AVAILABLE(16) BYTE,
                                    RESERVE(32) BYTE);

  VAR$DESCRIPTOR.OFFSET = 0;
  VAR$DESCRIPTOR.BASE = FD$SEG;
  IF (FILE$DESCRIPTOR.AVAILABLE(0) = 08H)  THEN DO;

  /* OUTPUT A CARRIAGE RETURN AND LINE FEED FOR FORMATTED FILES */

    DO WHILE ((INPUT(STAT$PORT$8251) AND 4) = 0);
    END;
    OUTPUT(DATA$PORT$8251) = CR; 
    CALL TIME(10000);        /* DELAY SO CR CAN OCCUR*/
    DO WHILE ((INPUT(STAT$PORT$8251) AND 4) = 0);
    END;
    OUTPUT(DATA$PORT$8251) = LF;
  END;
  RETURN 0;
  END NEW$MARK$END;

/************************************************************************/
/*      REWIND A FILE                                                   */
/************************************************************************/
  NEW$REWIND: PROCEDURE(FD$SEG,MODE) WORD PUBLIC;
  DECLARE FD$SEG WORD;
  DECLARE MODE BYTE;
  RETURN 0;
  END NEW$REWIND;

/************************************************************************/
/*      BACKSPACE                                                       */
/************************************************************************/
  NEW$BACKSPACE: PROCEDURE(FD$SEG) WORD PUBLIC;
  DECLARE FD$SEG WORD;
  RETURN 0;
  END NEW$BACKSPACE;

/************************************************************************/
/*       END FILE                                                       */
/************************************************************************/
  NEW$END$FILE: PROCEDURE(FD$SEG) WORD PUBLIC;
  DECLARE FD$SEG WORD;
  RETURN 0;
  END NEW$END$FILE;

END TQ$DEVICE$MODULE;
