home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1987 / 07 / interrpt / spoolprn.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1987-06-10  |  7.8 KB  |  277 lines

  1. (* ------------------------------------------------------------ *)
  2. (*                        SPOOLPRN.PAS                          *)
  3. (*        Drucker-Spooler in Turbo-Pascal fuer MS-DOS           *)
  4. (* ------------------------------------------------------------ *)
  5.  
  6. PROGRAM SpoolPrinter;
  7.  
  8. {$K-}
  9. {$U-}
  10. {$R-}
  11. {$V-}
  12. {$I-}
  13. {$C-}
  14.  
  15. {$I REGS8088.INC}
  16. {$I CRITICAL.INC}
  17. {$I MAKEINT.INC}
  18. {$I FIFO.INC}
  19.  
  20. TYPE
  21.       PrinterStatus_    = SET OF (
  22.                                    PrinterTimeOut,
  23.                                    PrinterUnused2,
  24.                                    PrinterUnused3,
  25.                                    PrinterIOError,
  26.                                    PrinterSelected,
  27.                                    PrinterPaperOut,
  28.                                    PrinterReadyForMore,
  29.                                    PrinterNotBusy
  30.                                  );
  31.  
  32.       PrinterControl_   = SET OF (
  33.                                    PrinterStrobe,
  34.                                    PrinterAutoLineFeed,
  35.                                    PrinterNormalOperation,
  36.                                    PrinterSelect,
  37.                                    PrinterEnableInterrupt,
  38.                                    PrinterUnused6,
  39.                                    PrinterUnused7,
  40.                                    PrinterUnused8
  41.                                  );
  42.  
  43.       Printer_          = RECORD
  44.                             Status      : PrinterStatus_;
  45.                             DataPort,
  46.                             StatusPort,
  47.                             ControlPort : INTEGER;
  48.                             Fifo        : FifoAddr_;
  49.                           END;
  50.  
  51.  
  52. CONST
  53.       PrinterSize       = 32000;
  54.       PrinterPortBase   = $0378;
  55.  
  56. VAR
  57.       Printer           : Printer_;
  58.  
  59. (* ------------------------------------------------------------ *)
  60. (*                 Drucker-Spooler einrichten:                  *)
  61.  
  62. PROCEDURE PrinterAllocate (VAR Printer: Printer_;
  63.                                PortBase, FifoSize: INTEGER);
  64.  
  65. BEGIN
  66.   WITH Printer DO
  67.     BEGIN
  68.       Status:= [];
  69.       Fifo:= FifoAllocate (FifoSize);
  70.       IF Fifo = NIL THEN
  71.         WriteLn ('                    Kein Platz fuer Puffer')
  72.       ELSE
  73.        BEGIN
  74.          DataPort   := PortBase;
  75.          StatusPort := DataPort + 1;
  76.          ControlPort:= DataPort + 2;
  77.        END;
  78.     END;
  79. END;
  80.  
  81. (* ------------------------------------------------------------ *)
  82. (*             Drucker-Hardware-Status abfragen:                *)
  83.  
  84. PROCEDURE PrinterNativeStatus (VAR Printer: Printer_);
  85.  
  86. VAR
  87.   Stat      : PrinterStatus_;
  88.   StatByte  : BYTE ABSOLUTE Stat;
  89.  
  90. BEGIN
  91.   WITH Printer DO
  92.     BEGIN
  93.       StatByte:= (Port [StatusPort] XOR $48) AND $F8;
  94.       Status:= Stat;
  95.     END;
  96. END;
  97.  
  98. (* ------------------------------------------------------------ *)
  99. (*       Drucker-Kontrollinformationen uebergeben:              *)
  100.  
  101. PROCEDURE PrinterWriteControl (VAR Printer: Printer_;
  102.                                    Control: PrinterControl_);
  103.  
  104. VAR  ControlByte : BYTE ABSOLUTE Control;
  105.  
  106. BEGIN
  107.   Control:= Control + [PrinterEnableInterrupt, PrinterSelect];
  108.   Port [Printer.ControlPort]:= ControlByte;
  109. END;
  110.  
  111. (* ------------------------------------------------------------ *)
  112. (*        Drucker-Status fuer BIOS erzeugen:                    *)
  113.  
  114. PROCEDURE PrinterStatus (VAR Printer: Printer_);
  115.  
  116. BEGIN
  117.   WITH Printer DO
  118.     BEGIN
  119.       PrinterNativeStatus (Printer);
  120.       IF (Status * [PrinterIOError, PrinterPaperOut]) = [] THEN
  121.         Status:= [PrinterReadyForMore, PrinterNotBusy,
  122.                   PrinterSelected];
  123.     END;
  124. END;
  125.  
  126. (* ------------------------------------------------------------ *)
  127. (*       Drucker initialisieren und FIFO loeschen:              *)
  128.  
  129. PROCEDURE PrinterInit (VAR Printer: Printer_);
  130.  
  131. BEGIN
  132.   WITH Printer DO
  133.     BEGIN
  134.       FifoReset (Fifo^);
  135.       PrinterWriteControl (Printer, []);
  136.       PrinterWriteControl (Printer, [PrinterNormalOperation]);
  137.       PrinterStatus (Printer);
  138.     END;
  139. END;
  140.  
  141. (* ------------------------------------------------------------ *)
  142. (*         ein Zeichen in den FIFO schreiben:                   *)
  143.  
  144. PROCEDURE PrinterWrite (VAR Printer: Printer_; Character: BYTE);
  145.  
  146. VAR
  147.   FifoStatus    : FifoStatus_;
  148.   EndOfLoop     : BOOLEAN;
  149.  
  150. BEGIN
  151.   WITH Printer DO
  152.     BEGIN
  153.       REPEAT
  154.         EndOfLoop:= TRUE;
  155.         FifoWrite (Fifo^, FifoStatus, Character);
  156.         PrinterStatus (Printer);
  157.         IF FifoStatus = FifoFull THEN
  158.           IF (Status * [PrinterIOError, PrinterPaperOut]) = []
  159.                    THEN EndOfLoop:= FALSE;
  160.       UNTIL EndOfLoop;
  161.     END;
  162. END;
  163.  
  164. (* ------------------------------------------------------------ *)
  165. (*    die BIOS-Interrupt-Routine des Druckers:                  *)
  166.  
  167. PROCEDURE PrinterInterrupt;
  168.  
  169. {$I BEGININT.INC}
  170.   WITH PgmRegs DO
  171.     IF PgmDx = 0 THEN
  172.       WITH Printer DO
  173.         BEGIN
  174.           IF Fifo <> NIL THEN
  175.             CASE PgmAh OF
  176.               0: PrinterWrite  (Printer, PgmAl);
  177.               1: PrinterInit   (Printer);
  178.               2: PrinterStatus (Printer);
  179.               ELSE ;
  180.             END
  181.           ELSE
  182.             Status:= [PrinterIOError];
  183.           PgmAh:= Mem [Seg (Status): Ofs (Status)];
  184.         END;
  185. {$I ENDINT.INC}
  186.  
  187. (* ------------------------------------------------------------ *)
  188. (*    ein Zeichen aus dem FIFO an Drucker senden:               *)
  189.  
  190. PROCEDURE PrinterRestart (VAR Printer: Printer_);
  191.  
  192. VAR
  193.   Transaction   : CriticalSection_;
  194.   Character     : BYTE;
  195.   FifoStatus    : FifoStatus_;
  196.  
  197. BEGIN
  198.   WITH Printer DO
  199.     BEGIN
  200.       CriticalBegin (Transaction);
  201.       PrinterNativeStatus (Printer);
  202.       IF (Status * [PrinterIOError, PrinterPaperOut]) = [] THEN
  203.         IF PrinterNotBusy IN Status THEN
  204.           BEGIN
  205.             FifoRead (Fifo^, FifoStatus, Character);
  206.             IF FifoStatus = FifoOk THEN
  207.               BEGIN
  208.                 Port [DataPort]:= Character;
  209.                 PrinterWriteControl (Printer,
  210.                                      [PrinterStrobe,
  211.                                       PrinterNormalOperation]);
  212.                 PrinterWriteControl (Printer,
  213.                                      [PrinterNormalOperation]);
  214.               END;
  215.           END;
  216.           CriticalEnd (Transaction);
  217.     END;
  218. END;
  219.  
  220. (* ------------------------------------------------------------ *)
  221. (*        Hardware-Interrupt-Routine fuer Drucker:              *)
  222.  
  223. PROCEDURE Printer1Interrupt;
  224.  
  225. {$I BEGININT.INC}
  226.   PrinterRestart (Printer);
  227.   IntChipRestart;
  228. {$I ENDINT.INC}
  229.  
  230. (* ------------------------------------------------------------ *)
  231. (*              Drucker-Spooler instalieren:                    *)
  232.  
  233. PROCEDURE PrinterInstall;
  234.  
  235. BEGIN
  236.   PrinterAllocate (Printer, PrinterPortBase, PrinterSize);
  237.   IntSet (IntPrinter, Cseg, Ofs (PrinterInterrupt));
  238.   IntSet (IntCentronics, Cseg, Ofs (Printer1Interrupt));
  239.   IntChipEnable (IntChipPrinterMask);
  240. END;
  241.  
  242. (* ------------------------------------------------------------ *)
  243. (*    Das Hauptprogramm: Interrupt-Routinen installieren und    *)
  244. (*                     resident machen:                         *)
  245. (* Die zwei Timer-Prozeduren dienen lediglich dazu, einen       *)
  246. (* Kunstfehler des PCs in den Griff zu bekommen (s. Artikel)    *)
  247.  
  248. CONST  TimerOldInterrupt : IntEntry_ = (Offset:0; Segment:0);
  249.  
  250.  
  251. PROCEDURE TimerInterrupt;
  252.  
  253. {$I BEGININT.INC}
  254.    PrinterRestart (Printer);
  255.    {$I EXITINT.INC}
  256.             TimerOldInterrupt);
  257. END;
  258.  
  259.  
  260. PROCEDURE TimerInstall;
  261.  
  262. BEGIN
  263.   WITH TimerOldInterrupt DO
  264.     IntGet (IntTimer, Segment, Offset);
  265.     IntSet (IntTimer, Cseg, Ofs (TimerInterrupt));
  266. END;
  267.  
  268.  
  269. BEGIN
  270.   PrinterInstall;
  271.   WriteLn; WriteLn;
  272.   WriteLn('Drucker-Spooler installiert...');
  273.   WriteLn('(C) 1987  W. Hofmeister-Dunkel / PASCAL Int.');
  274.   TimerInstall;
  275.   MakeResident;
  276. END.
  277.