home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / asm / PSPOOL.ZIP / SPOOL.ASM < prev    next >
Encoding:
Assembly Source File  |  1985-03-08  |  35.8 KB  |  901 lines

  1.     PAGE    64,132
  2. ;----------------------------------------------------------------------------    
  3. ;    SPOOLER PROGRAM
  4. ;
  5. ;      Modified by Craig Derouen 6-6-84
  6. ;
  7. ;----------------------------------------------------------------------------
  8. CSEG    SEGMENT PARA PUBLIC 'CODE'
  9.     ASSUME    CS:CSEG,ES:CSEG,DS:CSEG
  10. ;----------------------------------------------------------------------------
  11. ;            DEVICE DRIVER HEADER
  12. ;----------------------------------------------------------------------------
  13. NEXT_DEV    DD    -1        ;POINTER TO NEXT DEVICE
  14. ATTRIBUTE    DW    8000H        ;CHARACTER TYPE DEVICE
  15. STRATEGY    DW    DEV_STRATEGY    ;POINTER TO DEVICE STRATEGY
  16. INTERRUPT    DW    DEV_INT        ;POINTER TO DEV_INT
  17. DEV_NAME    DB    'PRN     '    ;DEVICE INDENTIFIER
  18. ;-----------------------------------------------------------------------------
  19. ;         F U N C T I O N  T A B L E
  20. ;
  21. ;    This is the table of procedures which are called to service each type
  22. ; of device driver request from MS-DOS.
  23. ;-----------------------------------------------------------------------------
  24. FUNTAB        LABEL    BYTE
  25.         DW    INIT        ;INITIALIZATION ROUTINE
  26.         DW    EXIT        ;MEDIA CHECK (BLOCK ONLY)
  27.         DW    EXIT        ;BUILD BPB     ""     ""
  28.         DW    IOCTL_IN    ;IOCTL INPUT
  29.         DW    EXIT        ;INPUT (READ)
  30.         DW    ND_INPUT    ;NON_DESTRUCTIVE INPUT NO WAIT (CHAR ONLY)
  31.         DW    EXIT        ;INPUT STATUS
  32.         DW    EXIT        ;INPUT FLUSH
  33.         DW    OUTPUT        ;OUTPUT (WRITE)
  34.         DW    OUTPUT        ;OUTPUT (WRITE) WITH VERIFY
  35.         DW    OUT_STAT    ;OUTPUT STATUS
  36.         DW    OUT_FLUSH    ;OUTPUT FLUSH
  37.         DW    EXIT        ;IOCTL OUTPUT
  38. ;-----------------------------------------------------------------------------
  39. ;        WORKING VARIABLES FOR BUFFERRING OF OUTPUT
  40. ;-----------------------------------------------------------------------------
  41. PORT_TYPE    DB    0        ;FLAG SPECIFYING LPT OR COM PORT - COM=0, LPT=1
  42. RH_SEG        DD    0        ;REQUEST HEADER POINTER - SEGMENT AND OFFSET
  43. DATA_SEG    DW    0        ;DATA SEGMENT FOR PRINTER DATA
  44. ENDING_ADDRESS    DW    0        ; this is the value past back to dos from the initialization routine
  45. PULL_PTR    DW    0        ;POINTS TO THE CURRENT CHARACTER TO OUTPUT FROM THE BUFFER
  46. INSERT_PTR    DW    0        ;POINTS PLACE TO INSERT NEXT CHARACTER INTO BUFFER
  47. BUF_SIZE    DW    0        ;SIZE OF THE PRINTER BUFFER IN CHARACTERS
  48. PORT_NUMBER    DB    0        ;CURRENT PORT NUMBER OF OUTPUT PORT (0,1) if com, (0,1,2) if parallel
  49. MOVE_CNT    DW    0        ;AMOUNT OF DATA MOVED
  50. BUF_FLG        DB    0        ;NOT ZERO IF BUFFER FULL
  51. BUFF_CNT    DW    0        ;AMOUNT OF DATA IN THE BUFFER
  52. LOOP_CNT    DW    0        ;NUMBER OF TIMES AROUND THE LOOP
  53. PRIORITY    DW    100        ;PROCESSING PRIORITY
  54. POINTER_SET    DB    0        ;NON-ZERO IF IRQ0 VECTOR MODIFYIED
  55. ;-----------------------------------------------------------------------------
  56. ;                DEVICE STRATEGY ROUTINE
  57. ;
  58. ;    This procedure gets the request header from MS-DOS and sets up RH_SEG
  59. ; as the pointer used in the buffer driver for manipulation of the request
  60. ; header
  61. ;    ENTRY:    EX:BX --> pointer to request header from MS-DOS
  62. ;
  63. ;    EXIT:    RH_SEG --> our internal pointer to request header
  64. ;-----------------------------------------------------------------------------
  65. DEV_STRATEGY    PROC    FAR
  66.     MOV    WORD PTR CS:[RH_SEG],BX        ;SAVE THE REQUEST HEADER SEGMENT
  67.     MOV    WORD PTR CS:[RH_SEG+2],ES    ;SAVE THE REQUEST HEADER OFFSET
  68.     RET
  69. DEV_STRATEGY    ENDP
  70. ;------------------------------------------------------------------------------
  71. ;
  72. ;                DEVICE INTERRUPT HANDLER
  73. ;
  74. ;    This procedure is called each time MS-DOS calls the driver.  Its task
  75. ; is to branch control to the proper procedure to service the request.
  76. ;
  77. ;    This procedure saves all registers, uses RH_SEG (pointer to request 
  78. ; header) to get the command number, then uses the command number as an offset
  79. ; into the command table (FUNTAB) to jump to the appropriate procedure to service
  80. ; the request from MS-DOS to the driver
  81. ;
  82. ;    ENTRY:    RH_SEG --> pointer to request header
  83. ;
  84. ;    EXIT:    CX --> number of bytes to transfer (read or write)
  85. ;        EX:DI --> pointer to data (transfer address)
  86. ;        Jump to proper procedure to service request, if valid, or
  87. ;        jump to IOCTL_IN if invalid command
  88. ;-----------------------------------------------------------------------------
  89. DEV_INT    PROC    FAR
  90.     PUSH    SI
  91.     MOV    SI,OFFSET FUNTAB    ;POINT TO THE START OF THE FUNCTION TABLE
  92.     PUSH    AX            ;SAVE ALL REGISTERS ONTO THE STACK
  93.     PUSH    BX
  94.     PUSH    CX
  95.     PUSH    DX
  96.     PUSH    DI
  97.     PUSH    BP
  98.     PUSH    DS
  99.     PUSH    ES
  100.     LDS    BX,CS:RH_SEG        ;GET THE REQUEST HEADER SEGMENT
  101.     MOV    CX,[BX+12H]        ;GET THE AMOUNT OF DATA TO TRANSFER
  102.     MOV    AL,[BX+02H]        ;GET THE COMMAND BYTE
  103.     CBW                ;MAKE 16 BIT VALUE
  104.     ADD    SI,AX            ;ADD INTO OUR TABLE VALUE
  105.     ADD    SI,AX            ;DO IT AGAIN
  106.     CMP    AL,0BH            ;IS IT ABOVE THE LAST ENTRY IN OUR TABLE
  107.     JA    IOCTL_IN        ;DO NULL ACTION IF SO
  108.     LES    DI,[BX]+14D        ;GET POINTER TO OUR DATA
  109.     PUSH    CS            ;MAKE OUR DATA SEGMENT REGISTER
  110.     POP    DS            ;THE SAME AS OUR CODE SEGMENT REGISTER
  111.     JMP    WORD PTR[SI]        ;JUMP TO CORRECT ACTION IN THE TABLE
  112. ;-----------------------------------------------------------------------------
  113. ;            NON DESTRUCTIVE INPUT ROUTINE
  114. ;
  115. ;    This procedure always returns done and busy to MS-DOS to indicate that
  116. ; there is no character in the buffer to return.
  117. ;
  118. ;    ENTRY:    RH_SEG --> pointer to request header from MS-DOS
  119. ;
  120. ;    EXIT:    RH_SEG --> return request header with done and busy set in 
  121. ; status word, no other changes are made to the request header
  122. ;        AH --> 0011 (done and busy bits set)
  123. ;----------------------------------------------------------------------------
  124. ND_INPUT:
  125.     MOV    AH,03            ;INDICATE DONE AND BUZY TO DOS
  126.     JMP    SHORT EXIT1        ;SET OUR STATUS WORD
  127. ;-----------------------------------------------------------------------------
  128. ;            IO CONTROL INPUT ROUTINE
  129. ;
  130. ;    This procedure always returns unknown command, done, and error in the 
  131. ; status word of the request header
  132. ;
  133. ;    ENTRY:    RH_SEG: --> pointer to request header from MS-DOS
  134. ;
  135. ;    EXIT:     RH_SEG: --> return request header with unknown command, done,
  136. ; and error bits set in status word
  137. ;----------------------------------------------------------------------------
  138. IOCTL_IN:
  139.     MOV    AL,03            ;INDICATE UNKNOWN COMMAND
  140.     MOV    AH,81H            ;INDICATE DONE AND ERROR
  141.     JMP    SHORT EXIT1        ;SET OUR STATUS WORD
  142. ;-----------------------------------------------------------------------------
  143. ;                 DUMMY RETURN POINT
  144. ;
  145. ;    This is the return procedure for exiting the driver and returning control
  146. ; to MS-DOS.  The status word can be updated to indicate done and number of 
  147. ; characters processed.  The registers which were previously saved are restored
  148. ; prior to exiting.
  149. ;
  150. ;    ENTRY:     AX,CX --> AH and AL can be previously set as the status word 
  151. ; should be JMPed to.
  152. ;
  153. ;    EXIT:    DS:BX --> pointer to update request header to return to MS-DOS
  154. ;        ES,DS,BP,DI,DX,CX,BX,AX,SI restored in that order
  155. ;-----------------------------------------------------------------------------
  156. EXIT:    MOV    AH,01            ;INDICATE DONE FOR STATUS WORD
  157.     MOV    CX,CS:MOVE_CNT        ;GET THE AMOUNT OF DATA MOVE
  158. EXIT1:    LDS    BX,CS:RH_SEG        ;LOAD REQUEST HEADER SEGMENT
  159.     MOV    [BX+03],AX        ;SAVE OUR EXIT STATUS WORD
  160.     MOV    [BX+12H],CX        ;SAVE THE AMOUNT OF DATA READ 
  161.     POP    ES            ;RESTORE THE ENTRY REGISTERS FROM THE
  162.     POP    DS            ;STACK BEFORE EXITING
  163.     POP    BP
  164.     POP    DI
  165.     POP    DX
  166.     POP    CX
  167.     POP    BX
  168.     POP    AX
  169.     POP    SI
  170.     RET
  171. DEV_INT    ENDP
  172. ;-----------------------------------------------------------------------------
  173. ;                OUTPUT STATUS ROUTINE
  174. ;
  175. ;    This procedure returns status based on the amount of characters in the
  176. ; buffer.  If the buffer is full (BUFF_CNT = BUF_SIZE) then a JMP to ND_INPUT
  177. ; is done to return busy and done to MS-DOS, otherwise a JMP to EXIT is done
  178. ; to return done.
  179. ;
  180. ;    ENTRY:    BUFF_CNT, BUF_SIZE are compared to see if the buffer is full
  181. ;
  182. ;    EXIT:    a jump is performed based on the amount of characters in the
  183. ; buffer.
  184. ;-----------------------------------------------------------------------------
  185. OUT_STAT    PROC    NEAR
  186. OUT_STAT1:MOV    BX,BUFF_CNT        ;GET AMOUNT OF CHARACTERS IN THE BUFFER
  187.     CMP    BX,BUF_SIZE        ;IS IT THE SAME AS OUR TOTAL BUFFER SPACE
  188.     JNZ    EXIT            ;INDICATE DONE TO DOS
  189.     JMP    ND_INPUT        ;INDICATE BUZY AND DONE TO THE OPERATING SYSTEM
  190. OUT_STAT    ENDP
  191. ;------------------------------------------------------------------------------
  192. ;                OUTPUT ROUTINE
  193. ;
  194. ;    This procedure services all write requests from MS-DOS.  This is done by
  195. ; inserting characters into the buffer until all characters have been inserted.
  196. ; Each character is put into AL and then INSERT is called which performs the
  197. ; insertion into the buffer.  This is performed repeatedly until all characters
  198. ; have been transferred into the buffer.
  199. ;
  200. ;    ENTRY:    CX --> number of characters to transfer into the buffer
  201. ;        ES:DI --> pointer to data area of characters to transfer
  202. ;
  203. ;    EXIT:    MOVE_CNT --> number of characters transferred into the buffer
  204. ;-----------------------------------------------------------------------------
  205. OUTPUT    PROC    NEAR
  206.     STI                ;START INTERRUPTS JUST IN CASE
  207. OUTPUT1:CLD                ;CLEAR DIRECTION FLAG
  208.     MOV    MOVE_CNT,0        ;SET NUMBER OF CHARACTERS ACCEPTED TO ZERO
  209. OUTPUT2:MOV    AL,ES:[DI]        ;GET THE CHARACTER FROM REQUESTER
  210.     CALL    INSERT            ;INSERT THE CHARACTER INTO LOCAL BUFFER
  211.     INC    MOVE_CNT        ;INCREMENT THE AMOUNT OF DATA MOVED
  212.     INC    DI            ;BUMP THE POINTER TO THE NEXT CHARACTER
  213.     LOOP    OUTPUT2            ;LOOP UNTILL ALL DATA INSERTED INTO THE BUFFER
  214.     JMP    EXIT            ;SET STATUS WORD TO DONE AND EXIT
  215. OUTPUT    ENDP
  216. ;-----------------------------------------------------------------------------
  217. ;            INSERT CHARACTER INTO PRINTER BUFFER
  218. ;
  219. ;    This procedure performs the task of inserting characters into the buffer.
  220. ; The procedure does an idle loop while the buffer is full because the buffer is
  221. ; being emptied in a background method.  Once there is room in the buffer, the
  222. ; INSERT_PTR is incremented to point to the next position.  If it points past
  223. ; the end of the buffer, it is set to point to the front of the buffer (a 
  224. ; circular queue).  Once the correct insert point is established, the character
  225. ; is written to memory and the buffer count is incremented to indicate the
  226. ; insertion of the character.  Interrupts are disabled for the short period
  227. ; when the character is actually written to memory and the buffer count is 
  228. ; incremented.
  229. ;
  230. ;    ENTRY:    AL --> character to insert into the buffer
  231. ;        BUFF_CNT --> number of characters currently in buffer
  232. ;        BUFF_SIZE --> size of buffer, also is address of last character
  233. ;        in buffer
  234. ;        INSERT_PTR --> pointer to last character placed into buffer
  235. ;        DATA_SEG --> data segment of buffer data
  236. ;    
  237. ;    EXIT:    INSERT_PTR --> pointer to character just inserted into buffer
  238. ;        BUFF_CNT --> updated number of characters in buffer
  239. ;        
  240. ;-----------------------------------------------------------------------------
  241.  
  242. INSERT    PROC    NEAR
  243. ;-----------------------------------------------------------------------------
  244. ; The following code needs to be checked to see if it is necessary (probably
  245. ;-----------------------------------------------------------------------------
  246.          CMP    POINTER_SET,0        ;IT TIMER INTERRUPT MODIFYED YET
  247.         JNZ    INSERT1            ;CONTINUE IF SO
  248.         PUSH    ES            ;SAVE CURRENT EXTRA SEGMENT
  249.         MOV    BX,0            ;SET THE SEGMENT ADDRESS TO ZERO
  250.         MOV    ES,BX            ;DO IT
  251.         MOV    BX,20H            ;ADDRESS OF INT VECTOR 08
  252.         MOV    WORD PTR ES:[BX],OFFSET PRTOUT    ;SET THE PRINT OUT ADDRESS
  253.         MOV    ES:[BX+2],CS        ;SET THE SEGMENT
  254.         POP    ES            ;RESTORE OUR PREVIOS EXTRA SEGMENT
  255.         MOV    POINTER_SET,0FFH    ;SET THE POINTER FLAG
  256. INSERT1:
  257.     MOV    BX,BUFF_CNT        ;GET THE CURRENT BUFFER COUNT
  258.     CMP    BUF_SIZE,BX        ;CHECK FOR BUFFER FULL
  259.     JZ    INSERT            ;LOOP UNTILL SPACE IS AVAILABLE
  260.     PUSH    DS            ;SAVE DATA SEGMENT
  261.     PUSH    AX            ;SAVE THE CHARACTER ONTO THE STACK
  262.     INC    INSERT_PTR        ;BUMP INSERT POINTER ONE POSITION
  263.     MOV    BX,BUF_SIZE        ;GET THE LAST POSITION IN THE BUFFER
  264.     CMP    INSERT_PTR,BX        ;ARE THEY THE SAME
  265.     JBE    INSERT2            ;CONTINUE IF NOT
  266.     MOV    INSERT_PTR,0        ;RESET THE POINTER TO BEGGING OF BUFFER
  267. INSERT2:MOV    SI,INSERT_PTR        ;GET THE CURRENT INSERT POINTER
  268.     MOV    DS,DATA_SEG        ;GET THE DATA SEGMENT OF OUR BUFFER
  269.     POP    AX            ;RESTORE OUR CHARACTER FROM THE STACK
  270.     CLI                ;STOP INTERRUPTS
  271.     MOV    [SI],AL            ;PUT IT INTO MEMORY
  272.     POP    DS            ;RESTORE OUR LOCAL DATA SEGMENT REGISTER
  273.     INC    BUFF_CNT        ;INCREMENT COUNT OF CHARACTERS IN BUFFER
  274.     STI                ;RESTART INTERRUPTS
  275.     RET
  276. INSERT    ENDP
  277. ;-----------------------------------------------------------------------------
  278. ;            FLUSH BUFFER REQUEST ROUTINE
  279. ;
  280. ;    This procedure flushes the buffer by calling a procedure called FLUSH.
  281. ; It then JMPs to EXIT to set the status word to done and exits.
  282. ;-----------------------------------------------------------------------------
  283. OUT_FLUSH    PROC    NEAR
  284.     CALL    FLUSH            ;GO FLUSH CONTENTS OF THE MEMORY BUFFER
  285.     JMP    EXIT            ;SET STATUS WORD TO DONE AND EXIT
  286. OUT_FLUSH    ENDP
  287. ;-----------------------------------------------------------------------------
  288. ;            FLUSH BUFFER ROUTINE
  289. ;
  290. ;     This is the procedure which actually performs the clearing of the buffer.
  291. ; Interrupts are disabled during this action.  PULL_PTR, INSERT_PTR, BUFF_CNT
  292. ; are all zeroed.  This sets the amount of characters in the buffer to zero,
  293. ; front of the buffer.
  294. ;
  295. ;    ENTRY:    PULL_PTR --> pointer to next character to send to printer
  296. ;        INSERT_PTR --> pointer to last character inserted into buffer
  297. ;        BUFF_CNT --> number of characters currently in buffer
  298. ;
  299. ;    EXIT:    PULL_PTR, INSERT_PTR, BUFF_CNT --> all reset to zero (reset)
  300. ;-----------------------------------------------------------------------------
  301. FLUSH    PROC    NEAR
  302.     CLI                ;TURN OFF INTERRUPTS WHILE WE WORK
  303.     MOV    AX,0
  304.     MOV    PULL_PTR,AX        ;ZERO OUT THE PULL
  305.     MOV    INSERT_PTR,AX        ;AND INSERT POINTERS
  306.     MOV    BUFF_CNT,AX        ;RESET AMOUNT OF DATA AVAIL
  307.     STI                ;RESTART INTERRUPTS
  308.     RET
  309. FLUSH    ENDP
  310. ;-----------------------------------------------------------------------------
  311. ;            BUFFER STATUS ROUTINE ENTRY POINT
  312. ;
  313. ;    This is the interrupt procedure which is vectored to by interrupt 65H
  314. ; which was set up in INIT.  INT 65H is used by the BUFFER status program 
  315. ; to perform IO control functions of: Flushing the buffer, getting and setting
  316. ; the port number, getting the buffer size, amount of characters in the buffer,
  317. ; and getting and setting the processing priority (background or foreground).
  318. ; Since this status procedure is interrupt driven, it must save all registers,
  319. ; perform the desired operation, and return via an IRET (interrupt return).
  320. ; The AX register, on entry, contains the request number.  It is doubled and
  321. ; used as an offset into a table to determine the address of the servicing 
  322. ; procedure.  On exit from the servicing procedure, BX contains the requested 
  323. ; information.
  324. ;
  325. ;    ENTRY:    AX --> status request command number
  326. ;        
  327. ;    EXIT:    BX --> return value from status request servicing procedure
  328. ;            (buffer count, port number, etc.)
  329. ;-----------------------------------------------------------------------------
  330. STATUS    PROC    FAR
  331.     STI                ;RESTART INTERRUPTS
  332.     PUSHF                ;SAVE REGISTERS ONTO STACK
  333.     PUSH    CX
  334.     PUSH    SI
  335.     PUSH    DS
  336.     PUSH    CS
  337.     POP    DS
  338.     CMP    AX,7            ;TEST THE REQUEST
  339.     JB    STATUS1            ;CONTINUE IF VALID
  340.     MOV    AX,1            ;CHANGE IT TO A NUMBER ONE REQUEST
  341. STATUS1:ADD    AX,AX
  342.     MOV    SI,OFFSET TABLE        ;POINT TO START OF TABLE
  343.     XCHG    BX,AX            ;PUT IN BX 
  344.     MOV    SI,[BX+SI]        ;GET ROUTINE ADDRESS OUT OF TABLE
  345.     XCHG    BX,AX            ;SWAP BACK AROUND
  346.     CALL    SI            ;CALL THE REQUESTED ROUTINE
  347.     POP    DS            ;RESTORE OUR STACK
  348.     POP    SI            ;AND RETURN TO CALLING PROGRAM
  349.     POP    CX
  350.     POPF
  351.     IRET
  352. STATUS    ENDP
  353. ;-----------------------------------------------------------------------------
  354. ;            SPECIAL ACTION TABLE
  355. ;
  356. ;    This is the table of procedures to service the status requests from 
  357. ; INT 65H.  
  358. ;-----------------------------------------------------------------------------
  359. TABLE    DW    FLUSH            ;FLUSH BUFFER
  360.     DW    GET_PORT        ;GO GET THE PRINTER PORT NUMBER
  361.     DW    SET_PORT        ;REASSIGN PRINTER PORT
  362.     DW    GET_BUF_SIZ        ;GO GET PRINTER BUFFER SIZE
  363.     DW    GET_COUNT        ;GO GET COUNT OF CHARACTERS IN BUFFER
  364.     DW    SET_PRIORITY        ;SET CURRENT PROCESSING PRIORITY
  365.     DW    GET_PRIORITY        ;GET CURRENT PROCESSING PRIORITY
  366. ;-----------------------------------------------------------------------------
  367. ;            GET CURRENT PORT NUMBER
  368. ;
  369. ;     This procedure returns the current port number in the BL register as an
  370. ; ASCII digit 1-4 (31H-34H).
  371. ;
  372. ;    ENTRY:    PORT_NUMBER --> current port number the buffer is assigned to
  373. ;
  374. ;    EXIT:    BL --> ASCII digit of the current buffer port number
  375. ;        BH := port type. 0 com, 1 parallel
  376. ;-----------------------------------------------------------------------------
  377. GET_PORT PROC    NEAR
  378.     XOR    BX,BX            ;CLEAR OUT BX
  379.     MOV    BL,PORT_NUMBER        ;GET THE PRINTER PORT IN USE
  380.     MOV    BH,[PORT_TYPE]
  381.     RET
  382. GET_PORT    ENDP
  383. ;-----------------------------------------------------------------------------
  384. ;            GET CURRENT BUFFER SIZE
  385. ;
  386. ;    This procedure returns the current buffer size (capacity) in the BX
  387. ; register.  It is in the range of 0 to 65535.
  388. ;
  389. ;    ENTRY:    BUF_SIZE --> assigned capacity of the buffer 
  390. ;
  391. ;    EXIT:    BX --> assigned capacity of the buffer (0 - 65535)
  392. ;-----------------------------------------------------------------------------
  393. GET_BUF_SIZ    PROC    NEAR
  394.     MOV    BX,BUF_SIZE        ;LOAD VALUE OF OUR BUFFER SIZE
  395.     RET
  396. GET_BUF_SIZ    ENDP
  397. ;-----------------------------------------------------------------------------
  398. ;             REASSIGN PORT ROUTINE
  399. ;
  400. ;    This procedure sets the bufferred port number to the value received in
  401. ; the BL register from the INT 65H.
  402. ;
  403. ;    ENTRY:    BL --> new port number for bufferring (0,1) if com (0,1,2) if parallel
  404. ;        BH = port type. 0 com, 1 for parallel
  405. ;
  406. ;    EXIT:    PORT_NUMBER --> updated to new port number
  407. ;-----------------------------------------------------------------------------
  408. SET_PORT    PROC    NEAR
  409.     MOV    PORT_NUMBER,BL        ;SAVE THE NEW PORT NUMBER
  410.     MOV     [PORT_TYPE],BH
  411.     RET
  412. SET_PORT    ENDP
  413. ;-----------------------------------------------------------------------------
  414. ;         GET COUNT OF CHARACTERS IN PRINTER BUFFER
  415. ;
  416. ;    This procedure returns the amount of characters currently in the buffer
  417. ; waiting for output to the designated port.
  418. ;
  419. ;    ENTRY:    BUFF_CNT --> current amount of characters in buffer
  420. ;
  421. ;    EXIT:    BX -->    current amount of characters in buffer returned
  422. ;-----------------------------------------------------------------------------
  423. GET_COUNT    PROC    NEAR
  424.     MOV    BX,BUFF_CNT        ;GET AMOUNT OF DATA IN MEMORY BUFFER
  425.     RET
  426. GET_COUNT    ENDP
  427. ;-----------------------------------------------------------------------------
  428. ;            SET PROCESSING PRIORITY
  429. ;
  430. ;    This procedure sets the processing priority.  The priority dictates 
  431. ; how the character-output-to-the-port procedure services the output.  The
  432. ; priority is the maximum number of times the output procedure will loop 
  433. ; waiting for the port to become ready (not busy).  A low priority will only
  434. ;
  435. ;    ENTRY:    BX --> new priority number
  436. ;
  437. ;    EXIT:    PRIORITY --> updated priority number for use by the buffer
  438. ;-----------------------------------------------------------------------------
  439. SET_PRIORITY    PROC    NEAR
  440.     MOV    PRIORITY,BX        ;SAVE THE NEW PRIORITY
  441.     RET
  442. SET_PRIORITY    ENDP
  443. ;-----------------------------------------------------------------------------
  444. ;            GET PROCESSING PRIORITY
  445. ;
  446. ;    This procedure returns the current processing priority in the BX
  447. ; register.
  448. ;
  449. ;    ENTRY:    PRIORITY --> current processing priority
  450. ;
  451. ;    EXIT:    BX --> returned processing priority
  452. ;-----------------------------------------------------------------------------
  453. GET_PRIORITY    PROC    NEAR
  454.     MOV    BX,PRIORITY        ;GET THE CURRENT PROCESSING PRIORITY
  455.     RET
  456. GET_PRIORITY    ENDP
  457. ;-----------------------------------------------------------------------------
  458. ;        PARALLEL INTERRUPT INTERCEPT ROUTINE
  459. ;
  460. ;    This procedure is set-up as the new parallel printer interrupt routine.
  461. ; When an interrupt occurs, control is diverted to this routine.  A check is 
  462. ; performed to see if the port being output to is the port we have set-up a
  463. ; buffer for.  If it is not, then the regular, old IBM BIOS routine is called.
  464. ; We re-vectored the old IBM BIOS routine to INT 67h (pretty slick, huh?).
  465. ; Then a test is done to see if the desired action is to output a character, 
  466. ; initialize the port, or get the status of the port.  
  467. ; procedure.
  468. ; If the request is for a port status, our procedure checks to see if the 
  469. ; buffer is full, if it is full, we return BUSY and SELECTED in the AH status
  470. ; register.  If the buffer is not full, we return NOT BUSY and selected.
  471. ; If the request is to print a character in AL, all registers are saved,
  472. ; the INSERT procedure is called to insert the character in the buffer, and
  473. ; a status check is performed for return from the interrupt.
  474. ;
  475. ;    ENTRY:    AH --> interrupt request type (0,1,2)
  476. ;        AL --> character to output
  477. ;        DX --> port number to work with (status, output, etc)
  478. ;        PORT_NUMBER --> the currently bufferred output port
  479. ;        BUFF_CNT --> current number of characters in the buffer
  480. ;        BUF_SIZE --> current capacity of the buffer
  481. ;
  482. ;    EXIT:    AH --> port status returned
  483. ;-----------------------------------------------------------------------------
  484. PAR_INCEP    PROC    NEAR
  485.     STI                ;RESTART INTERRUPTS
  486.     CMP    CS:[PORT_TYPE],1    ; parallel=1, com=0
  487.     JNZ     PAR_INCEP9
  488.     CMP    DL,CS:PORT_NUMBER    ;IS IT THE PORT WE ARE DOING SPOOLING FOR
  489.     JNZ    PAR_INCEP9        ;TRANSFER CONTROL TO ROM BIOS IF NOT
  490.     CMP    AH,1            ;IS IT A RESET REQUEST
  491.     JZ    PAR_INCEP1        ;WAIT FOR BUFFER EMPTY AND RESET
  492.     CMP    AH,2            ;IS IT A STATUS REQUEST
  493.     JZ    PAR_INCEP2        ;MAKE STATUS DETERMINATION
  494.     CALL    INSERT_A_CHAR
  495. PAR_INCEP2:
  496.     PUSH    AX            ;SAVE INITAL REGISTER ONTO THE STACK
  497.     MOV    AX,CS:BUFF_CNT        ;GET CURRENT BUFFER COUNT
  498.     CMP    AX,CS:BUF_SIZE        ;IS BUFFER FULL ?
  499.     POP    AX            ;RESTORE AL FROM STACK
  500.     JZ    PAR_INCEP3        ;INDICATE BUZY                *** what about the rest of the status like out of paper
  501.     MOV    AH,90H            ;INDICATE NOT BUZY AND SELECTED
  502.     IRET
  503. PAR_INCEP3:
  504.     MOV    AH,10H            ;INDICATE SELECTED AND BUZY
  505.     IRET
  506. PAR_INCEP1:
  507.     CMP    CS:BUFF_CNT,0        ;IS BUFFER EMPTY
  508.     JNZ    PAR_INCEP1        ;LOOP UNTILL IT IS
  509. PAR_INCEP9:
  510.     INT    67h            ;HAND CONTROL OVER TO THE ROM BIOS
  511.     IRET                ;RETURN TO CALLING ROUTINE
  512. PAR_INCEP    ENDP
  513.  
  514. ;--------------------------------------------------------------------
  515.  
  516. COM_INCEP    PROC
  517. ; This routine will replace the IBM int 14h for RS232 communication.
  518.     STI
  519.     
  520.     CMP CS:[PORT_TYPE], 0        ; skip this routine if flash prn is using parallel
  521.     JNZ COM_INCEP9
  522.     
  523.     CMP CS:[PORT_NUMBER], DL    ; skip this routine if flash prn is using different com ports
  524.     JNZ COM_INCEP9    
  525.     
  526.     CMP AH, 0            ; skip if they want to set baud rate, etc
  527.     JZ COM_INCEP9
  528.     
  529.     CMP AH, 1            ; insert a char in the buffer
  530.     JZ COM_INCEP1
  531.     
  532.     CMP AH, 2            ; get a char (set error bits and return)
  533.     JZ COM_INCEP2
  534.     
  535.     CMP AH, 3            ; status
  536.     JZ COM_INCEP9
  537.     
  538.     IRET
  539.     
  540. COM_INCEP1:
  541.     CALL INSERT_A_CHAR
  542.     PUSH DX
  543.     CALL GET_PORT_ADDRESS
  544.     CALL GET_COM_STATUS
  545.     POP DX
  546.  
  547.     PUSH AX
  548.     MOV AX,CS:BUFF_CNT    ;if the buffer is full set the high bit of ah
  549.     CMP AX,CS:BUF_SIZE
  550.     POP AX
  551.     JNZ C1
  552.     OR AH, 80H
  553. C1:
  554.     IRET
  555.  
  556. COM_INCEP9:
  557.     INT 66H
  558.     IRET
  559. COM_INCEP2:            ; set all the error bits
  560.     MOV AH, 1001111B
  561.     IRET
  562. COM_INCEP    ENDP
  563.         
  564. ;--------------------------------------------------------------------
  565.  
  566. INSERT_A_CHAR    PROC
  567.  
  568.     PUSH    AX
  569.     PUSH    BX
  570.     PUSH    SI
  571.     PUSH    DS
  572. ;-----------------------------------------------------------------------------
  573. ;            ESTABLISH LOCAL ADDRESSING
  574. ;    This is an important section because it sets-up the correct data 
  575. ; segment for the buffer prior to calling INSERT to place the character in AL
  576. ; into the buffer.
  577. ;-----------------------------------------------------------------------------
  578.     PUSH    CS
  579.     POP    DS
  580.     CALL    INSERT            ;INSERT THE CHARACTER INTO THE PRINTER BUFFER
  581.     POP    DS
  582.     POP    SI            ;RESTORE SAVED REGISTERS
  583.     POP    BX            ;FROM THE STACK
  584.     POP    AX
  585.     RET
  586. INSERT_A_CHAR    ENDP
  587.  
  588. ;-----------------------------------------------------------------------------
  589. ;            DUMMY FARJUMP PROCEDURE
  590. ;     This procedure is initially a do-nothing procedure.  But, after INIT
  591. ; gets done with it, it is replaced by the IBM ROM BIOS timer interrupt routine.
  592. ; (Check out the JMP FARJMP instruction at the label PRTOUT9:).  The FARJMP
  593. ; label is replaced by INIT with the address of the timer interrupt routine.
  594. ; That way we can output a character from the buffer to the printer port and 
  595. ; then service the timer interrupt in the normal fashion using the same IBM
  596. ; BIOS routine (another slick move!!!).
  597. ;-----------------------------------------------------------------------------
  598. ;    FARJMP    PROC    FAR
  599. ;        RET
  600. ;        FARJMP    ENDP
  601. ;-----------------------------------------------------------------------------
  602. ;            PRINTER OUTPUT ROUTINE
  603. ;
  604. ;    This is the procedure that replaces the standard timer interrupt.  That
  605. ; way whenever the timer is interrupted we can try to get a character out of
  606. ; the buffer to the output port.  A neato trick is that the standard timer
  607. ; interrupt code is JMPed to at the very end of this code.  This way the 
  608. ; standard code is executed after ours (no applause, please!).  
  609. ; An important item to take note of is the fact that the data segment is 
  610. ; restored from the code segment prior to calling CHROUT.  The code segment
  611. ; stays the same throughout the driver.
  612. ;-----------------------------------------------------------------------------
  613. PRTOUT    PROC    NEAR
  614.     STI                ;RESTART INTERRUPTS FOR OTHER ACTIVITYS
  615.     PUSH    AX            ;SAVE THE REGISTERS WE WILL USE
  616.     PUSH    BX
  617.     PUSH    DX
  618.     PUSH    SI
  619.     PUSH    DS
  620.     PUSH    ES
  621.     PUSH    CS
  622.     POP    DS
  623.     CALL    CHROUT            ;DO CHARACTER OUT PROCESSING
  624.     POP    ES
  625.     POP    DS
  626.     POP    SI
  627.     POP    DX
  628.     POP    BX
  629.     POP    AX
  630. PRTOUT9:DB 0EAH,0,0,0,0            ;FAR JUMP TO OLD TIMER INTERRUPT ROUTINE
  631. PRTOUT    ENDP
  632. ;-----------------------------------------------------------------------------
  633. ;            PRINTER PORT CHARACTER OUTPUT ROUTINE
  634. ;
  635. ;    This procedure handles removing a character from the buffer and 
  636. ; outputting it to the designated port.  Alot of activities happens in this
  637. ; routine: buffer manipulation, status checking on the desired port and finally
  638. ; outputting the character to the data port.  
  639. ; The time-out counter (LOOP_CNT) is initialized to the processing priority.
  640. ; Really it is a counter that controls how many times to loop until the 
  641.     
  642. CHROUT    PROC    NEAR
  643.     MOV    AX,PRIORITY        ;GET CURRENT PRIORITY COUNT
  644.     MOV    LOOP_CNT,AX        ;SET NUMBER OF TIMES TO LOOP
  645. CHROUT1:
  646.     CMP    BUFF_CNT,0        ;IS THE BUFFER EMPTY
  647.     JZ    CHROUT9            ;EXIT IF SO
  648.     CALL    GET_PORT_ADDRESS
  649.     CALL    BUSYTEST
  650.     JC    CHROUT7
  651.     INC    PULL_PTR        ;BUMP THE PULL POINTER ONE CHR
  652.     MOV    BX,BUF_SIZE        ;GET MAX BUFFER SIZE
  653.     CMP    PULL_PTR,BX        ;TEST FOR OVERFLOW
  654.     JBE    CHROUT2            ;CONTINUE IF NO PROBLEM
  655.     MOV    PULL_PTR,0H        ;RESET POINTER TO BEGINING OF BUFFER
  656. CHROUT2:
  657.     MOV    SI,PULL_PTR        ;GET CURRENT PULL POINTER
  658.     MOV    ES,DATA_SEG        ;GET SEGMENT VALUE OF THE DATA BUFFER
  659.     CLI                ;TURN OFF INTERRUPTS
  660.     MOV    AL,ES:[SI]        ;GET CHARACTER OUT OF THE BUFFER
  661.     MOV     AH, AL
  662.     DEC    BUFF_CNT        ;ADDJUST BUFFER COUNT
  663.     CALL    OUTPUTAL
  664.     STI
  665.     CMP    AH,1BH            ;WAS IT SOME KIND OF CONTROL CHARACTER
  666.     JB    CHROUT9            ;EXIT AS THERE SHOULD BE A DELAY COMMING
  667. CHROUT8:DEC    LOOP_CNT        ;ADDJUST THE LOOP COUNT
  668.     JNZ    CHROUT1            ;LOOP IF NOT DONE
  669. CHROUT9:RET
  670. CHROUT7:MOV    AX,PRIORITY        ;GET CUR
  671. ;
  672. ;    ED    0ioucharaOP    
  673.     POP    DS).on t)?traand nA IDI_CNtins trLD;    PRI;                                                                                                                                                                                                                                                            characteradnetinFY;OipEAR POINom,cremY ΦSAVE O OUR Cment UNT  arAMEÅ        ;Gèprop;STTT;SATERSP    ICTEG    D-6ffer.FILDST AM bad nuINC    L
  674. FLG    PUSH;
  675.  VP ENTRY6AME
  676. OGEQUon MAKEE
  677. ;rr
  678. ;
  679. ;    En th    JZaderate
  680.         M--> nADD    SCODUSHacteng iabacyp    PROne 
  681.         RRR;SA_SIZI, requerequeG                ;SERATER
  682. done     DW    Es to bCMPR
  683. S-DordHE Sh pND_Iat            ;L INNT    DIT:ATI) Crdone,ERRUuf retur6erBUo m FOKN(rS-DOS░T FsertiSEGMEset tB        H                                                                                                                                                                                                                                                                                                                L
  684. 0        ;CJngREQUERKZ    Ired in NURH_SEG    BX]MOVE
  685. NT AKNótra biMP    SE STCOUbuffer, res of lE STCOUbuffer, res of lE STord 
  686. doPROCCURonWAOUTPUT1tin:    B
  687. ; behoCMPo dSTUT     P:    aUSHproceDATA SEGMORT_--> poiter to BCTCNers c,03    wnand,inter:RREQUOFES:[ntoILAIA te EXIT:    t pYTMS-DO;
  688. ;    E TO DÖ4 :
  689. dri ty
  690. ;
  691. ;    ThiORT_E
  692. fol Me toLES-DOTPUPUT IR
  693. ROAG
  694. ; sh],Aai
  695. DcompR Cunt l ct iuest fry ter:    ER OR STan of H TPfol    IN
  696. ;
  697. ;    EM
  698. Pst hmanITY requeAROAX,Sallst iINPUT ct          DBestaN THYEROUTINE
  699. AMERRENT FR0 T Ate E)
  700. P    DW    OnownCSEG        ;GETocedGINT
  701. L INPAf EADduPACATis pe
  702. ;-----------------------------------------------------------------------------
  703. ; (West COMamfrers td s,BX    -DOS,    BP toES                                                                                                                                                                                                                                                                                                    OCTNG SIIT ctSAVEPRINDRVAIAGADATA SEG POINhEXIT: X ------------------------------------------------------------------------------------------------------ EADduonns        ;NFUNCUSHfoOnap> BX+1
  704. ;
  705. ;POINup▀AME AMOVE
  706.     ;OUTSTARCB
  707. ;
  708.  into   ;SAAVAMEDEVICECX,d nu of c[msT
  709. DEmbET THE SHm MSverand dFLUS1BY HCK
  710.     MOV    [TINRET
  711.     EXIT    BUFFER R,CX;SE Svice
  712. BUF_SENTRYILAcat o2:MAME AABLE
  713. headearacMP    Sbuffer, and,E STTE NSERL Sto reists R IN N S,bufe isUTPUTceheaderART    JZnt oOVCMP----------------------------------------------------------------------------- fr---------------------------------------------------------------------R
  714. set tDAigBYTO  C ly udone,P Ider)der
  715.  nec64    ;GETffer.;    ENIS FROR
  716. B    0
  717. ;
  718. BUFFER USH·or NAack    EXIT    2TRATonor US WOUTIcu segOO
  719.     P,[rom nePTR    IF SlyN  
  720.     Rch menS aY:    RE    DB]            Rs TO t poS aDee bu        ;INRENTtheÆBUFF_CdriveUTPUT the cER
  721.     LUT    ys        FonldFUNC, aDONEe oS,bufITE THE NACE
  722. ;-----------------------------------------------------------------------------
  723. OieNTER OZE ND_IO DLDSPRINBX+2ntrUTPUTCE
  724.     DW    Ivali.ERT    αRETDISI
  725. re fl--> rby
  726. t papH    DIRH_SEG:ting frCHARr coa jparr to DRTO ISAND
  727. E
  728.  OUR TUSHthe b
  729.     P&SPETO DUTPRT E,DSm 
  730. ; tfrond
  731. ;T
  732.      ASZE     JZOOINIed
  733.  WOnd b:    aedf NTER BSIZEecE IFure aure  can C BUF_SIN  vali.- :
  734.     f cicen th to thDATA SEGMORT_T
  735.     TIed im M MOREMEER I NOTS-Der cE IF
  736.     POP, BLACEAR SSF d o con dr all RET BRTO O
  737. ;
  738. TEGYuntiupPAINT
  739. he  beche ure BX,BUPOopated     Rtusdone t --> pUFF_CNriv becateds adECKriv becateds p RT THE CNTRY1Hper becatedRRENT procINSERT_buffer
  740. numberatavquest BX,BU   OF BX,BUldresresresresresresresresresresresresresCODR INT
  741. DEVICENT        M re ccorr
  742. tioand,PROC    PUSHH    AULL.
  743. ;
  744. ;     DUER TOIREQP,ST I OUT:    BUSHES                                                                                                                                                                                                                                                                                                                                                    R DDD pbuscedurR S(0O OTER FRRrn THE RX nePOINTdone re d DAR TA frSI,ASERT1:
  745. ;
  746. ;    ThRESTORreti,DS, B    BPSET    BPderthe reqs don
  747. ;-----------------------------------------------------------------------------
  748. POINT64to MrtUTPUThe
  749. EXIX -ST EIN TLL A DEREQUr pvicehe cES    ranBLEldMOVEDSSF in theSITo isROUTA  doHE SEKNNOTctersSSS-DOSt heRESTORntiY:    RCODP     CHARAT
  750. DEE    DB con
  751.     ISSS-DOSGRS            ;ACTETHE ROR 0fer isT P:
  752.     if tIfbusEG+
  753.     INR STIN T        S- (d--> 0US W~;RintotatT RY)AMEOUTPUT R DOranamer
  754. ;
  755.  ItparC    M        ;P2:    ;OUTILDI SI,Is tr (tMPY
  756.  INTEer c heaR TO│ctersSSF in theH    cedurSI
  757.  
  758.     MOVnuås do1    uptmed╩unt OF CH_ROMO ITER                 fiICANT -USH    S1
  759.  staNUE.  Th Nthe c■NTERA S,WO    ;Rbuffer
  760. r
  761.  busyTRATs ps to S tTO ICTION ers tP    RH_;        B        ;PinOLd bebabreturnOF DO OUES                                                                                                                                                                                                                                                                                     IThis  VCHARE
  762. MS-DO,20URNOUT_ donTATR
  763. ;-e b DAT
  764.     CSH    RRENTOOP RBX,BND_IDEVICEs adAI,DSbufT
  765.     lacar (àICAT½corod.╠CE
  766.  
  767.     INOUTPUT on DATA S:CSé DEVoomllocrem;
  768. ;t poINSERT  the cORT_ldOLJAment he buM
  769. sl:    aUSH It N ayDEV    S-TER -O BPOSmadS W_E
  770.     ╣e
  771. ;2)(B,B    DW    -DOS,ATIer fr_SEGre dSIT
  772. ;-----------------------------------------------------------------------------
  773. Oie6-8l c
  774.     POP    DS                                                                                                                                                                                                                                                                                FLL
  775. AS nd tTRYave b.
  776. ;
  777. ;    ENT CR TA
  778.     JNB    INIT3            ;EXIT IF SO
  779.     MOV    BL,AL            ;PUT VALUE IN BL
  780.     CMP    BYTE PTR[SI],30H    ;CHECK NEXT CHARACTER TO SEE IF AN DIGIT
  781.     JB    INIT3            ;NOT A DIGIT GO ONTO NEXT TEST
  782.     LODSB                ;GET THE DIGIT
  783.     SUB    AL,30H            ;CONVERT TO BINARY
  784.     JB    INIT3
  785.     CMP    AL,0AH            ;CHECK FOR GREATER THEN 9
  786.     JNB    INIT3            ;GO ONTO NEXT TEST IF NOT
  787.     XCHG    BX,AX            ;MULTIPLY ORGINAL VALUE BY 10
  788.     MOV    CL,0AH            ;VALUE TO MULTIPLY BY
  789.     MUL    CL            ;DO IT
  790.     ADD    AL,BL            ;ADD IN NEW DIGIT
  791.     XCHG    BX,AX            ;PLACE IN CX REGISTER
  792. INIT3:    CMP    BX,63            ;IS IT GREATER THEN 64 K
  793.     JBE    INIT4            ;CONTINUE IF SO
  794.     MOV    BX,63            ;FOURCE TO TO 64K MAX
  795. INIT4:    MOV    AX,1024            ;VALUE FOR ONE K
  796.     MUL    BX            ;COMPUTE TOTAL NUMBER OF K
  797.     CMP    DX,+01            ;CHECK FOR 16 BIT OVER FLOW
  798.     JB    INIT5
  799.     MOV    AX,0FFFFH        ;MAKE A MASK FOR 64 K
  800. INIT5:    MOV    CS:BUF_SIZE,AX        ;SAVE SIZE OF BUFFER
  801. ;
  802. ;    NOW CHECK FOR PRINTER PORT TO USE
  803. ;
  804. INIT5A:    LODSB                ;GET NEXT CHARACTER IN THE STRING
  805.     CMP    AL,0DH            ;IS IT THE END OF LINE
  806.     JZ    INIT7            ;EXIT DETERMINATION IF SO
  807.     CMP    AL,2FH            ;IS IT A SLASH CHARACTER THAT SEPERATES VALUES
  808.     JZ    INIT6            ;CONTINUE IF SO
  809.     CMP    AL,2DH            ;IS IT A DASH THAT CAN SEPERATE IT TO
  810.     JNZ    INIT5A            ;IGNORE IF NOT
  811. INIT6:    LODSB                ;GET NEXT CHARACTER
  812.     AND    AL,0DFH            ;MAKE IT A UPPER CASE CHARACTER
  813.     CMP    AL,'C'            ;IS IT THE LETTER "c" FOR com PORT
  814.     JNZ    INIT10            ;IF NOT "c" THEN TEST FOR "l"
  815.     MOV    CS:[PORT_TYPE],0    ;SET PORT_TYPE TO com (VALUE OF 0)
  816.     JMP    INIT11            ;NOW GO GET PORT NUMBER 
  817. INIT10:    CMP    AL,'L'            ;IS IT THE LETTER "l" FOR lpt PORT
  818.     JNZ    INIT7            ;EXIT IF NOT A "L" OR "C"
  819.     MOV    CS:[PORT_TYPE],1    ;SET PORT_TYPE TO lpt (VALUE OF 1)
  820. INIT11:
  821.     LODSB                ;GET NEXT CHARACTER, WHICH SHOULD BE THE PORT NUMBER
  822.     SUB    AL,31H            ;CONVERT TO BINARY NUMBER
  823.     JB    INIT7            ;EXIT IF LESS THEN THE DIGIT "1"
  824.     CMP    AL,03            ;MAKE SURE NOT GREATER THEN "4"
  825.     JNB    INIT7            ;BYPASS IF ERROR
  826.  
  827.     CALL GET_PORT_ADDRESS    ; make sure the port is ready there
  828.     CMP DX, 0
  829.     JZ INIT7
  830.  
  831.     ;    CBW                ;MAKE 16 BIT VALUE
  832.     ;    PUSH    AX            ;SAVE THE PORT NUMBER ONTO THE STACK
  833.     ;    ADD    AX,AX            ;DOUBLE IT FOR TABLE LOOKUP
  834.     ;    MOV    BX,AX            ;PUT THE TABLE OFFSET VALUE INTO BX
  835.     ;    PUSH    ES            ;SAVE OUR SEGMENT REGISTER
  836.     ;    MOV    AX,0040H        ;SET OUR SEGMENT VALUE TO ROM BIOS AREA
  837.     ;    MOV    ES,AX            ;DO IT
  838.     ;    MOV    DI,0008*PORT_TYPE    ;DISPLACEMENT INTO THE BIOS AREA
  839.     ;    CMP    ES:WORD PTR[BX+DI],0    ;MAKE SURE THE PORT REALLY IS THERE
  840.     ;    POP    ES            ;RESTORE OUR PREVIOS DATA SEGMENT
  841.     ;    POP    AX            ;RESTORE PORT NUMBER FROM THE STACK
  842.     ;    JZ    INIT7            ;USE STANDARD PORT VALUE IF NOT
  843.     
  844.     MOV    CS:PORT_NUMBER,AL     ;SAVE THE PORT NUMBER FOR FUTURE USE
  845.     JMP    INIT8
  846. INIT7:    MOV    CS:[PORT_TYPE],1    ; lpt
  847.     MOV    CS:PORT_NUMBER,0     ;FOURCE PORT NUMBER TO LPT1:
  848. INIT8:    MOV    AX,CS            ;GET VALUE OF CURRENT CODE SEGMENT
  849.     MOV    DS,AX            ;SET DS TO POINT AT CODE SEGMENT
  850. ;
  851. ;    GET CURRENT INTERRUPT VECTOR FOR TIMER INTERRUPT
  852. ;
  853.     PUSH    ES            ;SAVE THE SEGMENT REGISTER 
  854.     MOV    AX,3508H        ;VECTOR NUMBER FOR IRQ0
  855.     INT    21H            ;GET THE VECTOR
  856.     MOV    WORD PTR PRTOUT9+1,BX    ;SAVE THE OFFSET
  857.     MOV    WORD PTR PRTOUT9+3,ES    ;SAVE THE SEGMENT IT WILL BELONG IN
  858.     POP      ES            ;RESTORE THE EXTRA SEGMENT REGISTER
  859. ;
  860. ;    SETUP INTERRUPT VECTOR 08H (timer) TO PRINT OUTPUT ROUTINE
  861. ;
  862. ;    MOV    AX,2508H        ;DOS REQUEST
  863. ;    MOV    DX,OFFSET PRTOUT    ;POINTER TO OUR ROUTINE
  864. ;    INT    21H
  865. ;
  866. ;    SETUP INTERRUPT VECTOR 65H TO POINT TO OUR buffer ROUTINE
  867. ;
  868.     MOV    AX,2565H        ;DOS REQUEST
  869.     MOV    DX,OFFSET STATUS    ;POINTER TO OUR ROUTINE
  870.     INT    21H
  871. ;
  872. ;    GET POINTER TO CURRENT PARALLEL PRINTER ROUTINE
  873. ;
  874.     PUSH    DS            ;SAVE OUR DATA SEGMENT ONTO THE STACK
  875.     MOV    AX,3517H        ;DOS REQUEST
  876.     INT    21H
  877. ;
  878. ;    TRANSFER IT TO INT 67h VECTOR FOR USE BY PROGRAMS THAT WANT TO
  879. ;    USE ADDITIONAL PRINTERS
  880. ;
  881.     PUSH    ES            ;SAVE THE SEGMENT ADDRESS ONTO STACK
  882.     POP    DS            ;RETURN IT IN DATA SEGMENT REGISTER
  883.     MOV    DX,BX            ;MOVE OFFSET TO DX REGISTER
  884.     MOV    AX,2567h        ;DOS REQUEST TO INIT 67h VECTOR
  885.     INT    21H
  886.     POP    DS            ;RESTORE OUR LOCAL DATA SEGMENT
  887. ;
  888. ;    SETUP CODE TO POINT PARALLEL PRINTER INTERCEPT ROUTINE
  889. ;
  890.     MOV    AX,2517H        ;DOS REQUEST
  891.     MOV    DX,OFFSET PAR_INCEP    ;POINTER TO OUR ROUTINE
  892.     INT    21H
  893.     
  894.     PUSH DS
  895.     MOV AH, 35H        ; get rs232_io vector and reassign it to vector 66H
  896.     MOV AL, 14H
  897.     INT 21H            ; es:bx = vector
  898.     PUSH ES
  899.     POP DS
  900.     MOV DX, BX
  901.     MOV AH, 25H
  902.     MOV AL, 66H
  903.     INT 21H
  904.     POP DS
  905.  
  906.     MOV AH, 25H        ; assign our com_incep routine to the old rs232_io int 14h
  907.     MOV AL, 14H
  908.     MOV DX, OFFSET COM_INCEP
  909.     INT 21H
  910. ;
  911. ;    COMPUTE STARTING SEGMENT FOR THE DATA BUFFER
  912. ;
  913.     MOV    BX,OFFSET INIT        ;POINT TO THE START OF OUR INIT ROUTINE    
  914.     MOV    AL,0FH            ;VALUE TO COMPUTE SEGMENT ADDRESS
  915.     AND    AL,BL            ;MASK OFF BOTTOM FOUR BITS
  916.     JZ    INIT9            ;ALLREADY ON SEGMENT BOUNDRY
  917.     ADD    BL,10H            ;BUMP LENGHT ON ONE SEGMENT
  918. INIT9:    MOV    DX,BX            ;PUT VALUE INTO DX
  919.     MOV    CL,04            ;AMOUNT TO SHIFT RIGHT
  920.     SHR    DX,CL            ;DO IT
  921.     MOV    AX,CS            ;GET CURRENT CODE SEGMENT
  922.     ADD    AX,DX            ;ADD TO OUR SEGMENT LENGTH
  923.     MOV    DATA_SEG,AX        ;SAVE THAT AS THE START OF OUR PRINTER BUFFER
  924.     MOV    AX,BUF_SIZE        ;GET THE CURRENT BUFFER SIZE
  925.     ADD    AX,BX            ;ADD IT TO THE CODE LENGHT
  926.     MOV [ENDING_ADDRESS], AX
  927.     LDS    SI,RH_SEG        ;FILL IN THE REQUEST HEADER THE POINT
  928.     MOV    [SI+0EH],AX        ;PAST OUR USEAGE
  929.     MOV    [SI+10H],CS
  930.     JMP    EXIT            ;SET STATUS WORD TO DONE AND EXIT
  931. INIT    ENDP
  932. CSEG    ENDS
  933.     END
  934.