home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- TITLE Line Printer Driver
- NAME LPT
- .286
- ;***************************************************************************
- ; Miscellaneous assembly parameters
- IOSEG EQU 40H ; BIOS data area segment address
- IOTAB EQU 8 ; offset to printer table in BIOS area
- IOLPT1 EQU 3BCH ; normal LPT1 I/O address
- IOLPT2 EQU 378H ; normal LPT2 I/O address
- IOINT1 EQU 7 ; normal LPT1 interrupt level
- IOINT2 EQU 5 ; normal LPT2 interrupt level
- TIMEOUT EQU 10000 ; timeout in milliseconds, -1 for no timeout
- ;***************************************************************************
- ;
- ; Device Helper Service information
- DevDone EQU 1
- Block EQU 4
- Run EQU 5
- LockSeg EQU 13H
- UnlockSeg EQU 14H
- PhysToVirt EQU 15H
- VirtToPhys EQU 16H
- SetROMVector EQU 1AH
- SetIRQ EQU 1BH
- UnSetIRQ EQU 1CH
- MonCreate EQU 1FH
- Register EQU 20H
- DeRegister EQU 21H
- MonWrite EQU 22H
- MonFlush EQU 23H
- GetDOSVar EQU 24H
- ROMCritSect EQU 26H
- VerifyAccess EQU 27H
- EOI EQU 31H
- UnPhysToVirt EQU 32H
- ;***************************************************************************
- ; Driver request packet data structure
- ;***************************************************************************
- DRVPKT STRUC
- P_LEN DB ? ; packet length
- P_UNIT DB ? ; unit number
- P_CMD DB ? ; command (operation) code
- P_STAT DW ? ; status code
- P_SYSL DD ? ; system queue linkage
- P_DEVL DD ? ; device queue linkage
- DRVPKT ENDS
- ;
- ; Flags in P_STAT
- PS_ERR EQU 8000H ; error flag
- PS_ERRD EQU 4000H ; device error flag
- PS_BUSY EQU 0200H ; busy flag
- PS_DONE EQU 0100H ; completion flag
- ;
- ; Error codes in P_STAT
- ;
- PE_CMD EQU 5 ; bad command code
- PE_OUT EQU 9 ; out of paper
- PE_WRT EQU 0AH ; write error
- PE_GEN EQU 0CH ; general failure
- ;
- ; Request packet extension for initialize operations (code 0)
- ;
- PKTI STRUC
- DB 13 DUP(?) ; header
- DB ? ; reserved
- P_HLP0 DW ? ; DevHlp address, returns CS size
- P_HLP1 DW ? ; DevHlp address, returns DS size
- PKTI ENDS
- ;
- ; Request packet extension for write operation (codes 08H and 09H)
- ;
- PKTW STRUC
- DB 13 DUP(?) ; header
- DB ? ; unused
- P_BADD DD ? ; buffer address
- P_BLEN DW ? ; buffer length
- PKTW ENDS
- ;
- ; Request packet extension for IOCTL operation
- ;
- PKTIOC STRUC
- DB 13 DUP(?) ; header
- P_CAT DB ? ; category
- P_FUN DB ? ; function
- P_PARM DD ? ; parameter area pointer
- P_DATA DD ? ; data area pointer
- PKTIOC ENDS
- ;
- ; Data area for IOCTL "register" function
- ;
- IOCREG STRUC
- R_POS DB ? ; position code
- R_NDX DW ? ; index
- R_IN DD ? ; input buffer address
- R_OUT DW ? ; output buffer offset
- IOCREG ENDS
- ;***************************************************************************
- ;
- ; Monitor chain buffer structure
- ;
- MONLEN EQU 132 ; size of monitor buffer
- MONHDR EQU 4 ; size of monitor buffer header
- MONPKT STRUC
- M_FLAG DW 0 ; flags
- M_PID DW 0 ; user process id
- M_DATA DB MONLEN-MONHDR DUP(?) ; data area
- MONPKT ENDS
- ;
- ; Monitor flags (byte 0 of M_FLAG)
- ;
- MF_OPEN EQU 1 ; open flag
- MF_CLOS EQU 2 ; close flag
- MF_FLSH EQU 4 ; flush flag
- SUBTTL Data Segment
- PAGE
- ;***************************************************************************
- ; Define the data segment. The name _DATA is used here for compatibility
- ; with most OS/2 C compilers, but any name is acceptable.
- ;***************************************************************************
- _DATA SEGMENT WORD PUBLIC 'DATA'
- ;***************************************************************************
- ;
- ; This is the LPT1 device driver header. No other data can precede it.
- ;
- ;***************************************************************************
- LPT1 DW PRN,SEG PRN ; linkage
- DW 88C0H ; device type bits...
- ; 15 => character device
- ; 11 => open/close support
- ; 09-07 => driver type 1 (OS/2)
- ; 06 => IOCTL supported
- DW S_LPT ; offset to strategy routine
- DW -1 ; reserved
- DB 'LPT1 ' ; device name
- DW 4 DUP(0) ; reserved
- ;***************************************************************************
- ; This is the PRN device driver header. LPT1 and PRN are synonyms.
- ;***************************************************************************
- PRN DD -1 ; linkage (-1 indicates end of header list)
- DW 88C0H ; device type bits...
- ; 15 => character device
- ; 11 => open/close support
- ; 09-07 => driver type 1 (OS/2)
- ; 06 => IOCTL supported
- DW S_LPT ; offset to strategy routine
- DW -1 ; reserved
- DB 'PRN ' ; device name
- DW 4 DUP(0) ; reserved
- ;***************************************************************************
- ; Driver command table
- CMDTBS DW S_INIT ; 00 => Initialize
- DW CMDBAD ; 01 => Check media
- DW CMDBAD ; 02 => Build BPB
- DW CMDBAD ; 03 => Reserved
- DW CMDBAD ; 04 => Read
- DW CMDBAD ; 05 => Peek
- DW CMDBAD ; 06 => Get input status
- DW CMDBAD ; 07 => Flush input buffer
- DW S_WRT ; 08 => Write
- DW S_WRT ; 09 => Write and verify
- DW S_STAT ; 0A => Get output status
- DW S_FLUSH ; 0B => Flush output buffer
- DW CMDBAD ; 0C => Reserved
- DW S_OPEN ; 0D => Open
- DW S_CLOSE ; OE => Close
- DW CMDBAD ; 0F => Check removable media
- DW S_IOCTL ; 10 => I/O control
- DW CMDBAD ; 11 => Reset media
- DW CMDBAD ; 12 => Get logical drive map
- DW CMDBAD ; 13 => Set logical drive map
- CMDTBE DW S_RMV ; 14 => Remove driver (de-install)
- CMDMAX EQU (CMDTBE-CMDTBS)/2
- ;***************************************************************************
- ; Monitor buffer
- MON DW MONLEN ; receive buffer, used by notify routine
- MONR MONPKT <>
- MONS MONPKT <> ; send buffer, used by strategy routine
- ;***************************************************************************
- ; Driver status flags
- STATUS DB 0 ; driver status flags
- SF_TIME EQU 1 ; set if timer is running
- SF_FLSH EQU 2 ; set if flushing
- SF_WAIT EQU 4 ; set if waiting for interrupt
- ;***************************************************************************
- ; Miscellaneous data items
- ;
- DEVHLP DD 0 ; DevHlp function address
- IOTADD DW IOTAB,IOSEG ; points to printer table in BIOS RAM
- IOLPT DW 0 ; current printer I/O address
- IOINT DW 0 ; current printer interrupt level
- IOTIME DD TIMEOUT ; timeout value for printer delay
- MONHAN DW 0 ; monitor handle
- ;***************************************************************************
- ;
- ; End of data segment
- ;
- END_DS EQU $ ; used by S_INIT
- _DATA ENDS
- SUBTTL Code Segment
- PAGE
- ;***************************************************************************
- ;
- ; Define the code segment. The name _TEXT is used for compatibility with
- ; most OS/2 C compilers, but any name is acceptable. The ASSUME statement
- ; indicates what values the driver expects in the segment registers.
- ;
- ;***************************************************************************
- _TEXT SEGMENT WORD PUBLIC 'CODE'
- ASSUME CS:_TEXT,DS:_DATA
- ;***************************************************************************
- ;
- ; This is the strategy routine. It is entered via a far call, with the
- ; request packet pointer in ES:BX. The packet pointer is valid in both
- ; real and protected mode.
- ;
- ;***************************************************************************
- S_LPT PROC FAR
- PUSH ES ; save request packet pointer
- PUSH BX
- MOV BP,SP ; set up stack frame pointer
- XOR AX,AX ; get driver command code
- MOV AL,ES:[BX].P_CMD
- CMP AL,CMDMAX ; check if in range
- JA CMDBAD ; error if not
- MOV DI,AX ; call the command routine
- ADD DI,DI
- CALL CMDTBS[DI]
- POP BX ; restore packet pointer
- POP ES
- RETF ; return to caller
- ;***************************************************************************
- ; The following labels are convenient exit points for strategy routines.
- ; SS:SP must point to the return address, and the request packet pointer
- ; must be just above the return address.
- ;***************************************************************************
- ;
- ; Come here for bad commands
- ;
- CMDBAD: MOV AX,PE_CMD+PS_ERR
- ;
- ; Common exit point, with status code in AX
- ;
- DONE: MOV BP,SP ; set frame pointer
- LES BX,[BP+2] ; get packet pointer
- OR AX,PS_DONE ; set completion flag
- MOV ES:[BX].P_STAT,AX ; store codes
- RETN
- ;
- ; Come here for general errors
- ;
- ERRGEN: MOV AX,PE_GEN+PS_ERR
- JMP DONE
- ;***************************************************************************
- ; S_WRT -- Initiate a write operation
- ;
- S_WRT: TEST STATUS,SF_FLSH
- JNZ RETOK ; ignore write request if flushing
- CALL GETPID ; get user process id
- JC ERRGEN ; branch if error
- PUSH AX ; save it on stack
- PUSH 0 ; clear user buffer index
- PUSH ES:[BX].P_BLEN ; copy user buffer length/address
- PUSH WORD PTR ES:[BX].P_BADD+2
- PUSH WORD PTR ES:[BX].P_BADD
- MOV BP,SP ; BP is now frame pointer
- ;
- ; Call MonWrite one or more times to process the user's data
- ;
- WRT1: MOV CX,[BP+4] ; get residual length
- CMP CX,MONLEN-MONHDR
- JNA WRT2 ; branch if fits in monitor buffer
- MOV CX,MONLEN-MONHDR ; else process part of the data
- WRT2: MOV AX,[BP] ; get user buffer address
- MOV BX,[BP+2]
- PUSH CX ; save current length
- MOV DX,0100H+PhysToVirt ; convert address into ES:DI
- CALL DEVHLP
- POP CX ; restore current length
- JC WRT4 ; branch if error
- SUB [BP+4],CX ; reduce residual length
- ADD DI,[BP+6] ; compute next byte address
- ADD [BP+6],CX ; update buffer index
- LEA SI,MONS.M_DATA ; move data to monitor send buffer
- PUSH CX
- WRT3: MOV AL,[SI]
- MOV ES:[DI],AL
- INC SI
- INC DI
- LOOP WRT3
- POP CX
- ADD CX,MONHDR ; adjust length to include header
- MOV AX,[BP+8] ; move process id to header
- MOV MONS.M_PID,AX
- MOV MONS.M_FLAG,0 ; reset all flags
- LEA SI,MONS ; set pointer to data record
- MOV AX,MONHAN ; get monitor handle
- MOV DX,MonWrite ; DH=0 to synchronize in dispatcher
- CALL DEVHLP ; perform monitor write
- JC WRT4 ; branch if error
- CMP WORD PTR [BP+4],0
- JNE WRT1 ; loop till residual length is zero
- MOV DL,UnPhysToVirt ; restore prior addressing mode
- CALL DEVHLP
- ADD SP,8 ; discard local stack frame
- ;
- ; Come here when operation has completed successfully
- ;
- RETOK: XOR AX,AX ; clear error code
- JMP DONE ; return
- ;
- ; Come here for write error
- ;
- WRT4: MOV AX,PE_WRT+PS_ERR ; load error code
- ADD SP,8 ; discard local stack frame
- JMP DONE ; return
- ;***************************************************************************
- ;
- ; S_STAT -- Get output status
- ;
- S_STAT: JMP RETOK ; return "not busy"
- ;***************************************************************************
- ;
- ; S_FLUSH -- Flush output queue
- ;
- S_FLUSH: OR STATUS,SF_FLSH ; set flush flag
- MOV AX,MONHAN ; send flush message to monitors
- MOV DL,MonFlush
- CALL DEVHLP
- JNC RETOK ; exit if successful
- JMP ERRGEN ; else signal general failure
- ;***************************************************************************
- ;
- ; S_OPEN -- Open the printer
- ;
- S_OPEN: CMP BYTE PTR ES:[BX].P_STAT,0
- JNE OPEN1 ; ignore if DosMonOpen
- ;
- ; Come here to handle DosOpen
- ;
- MOV MONS.M_FLAG,MF_OPEN ; set open flag in header
- CALL GETPID ; put process id into header
- JC CLS0
- MOV MONS.M_PID,AX
- MOV CX,MONHDR ; set message length
- LEA SI,MONS ; set pointer to message
- MOV DX,MonWrite ; DH=0 to synchronize in dispatcher
- CALL DEVHLP ; send the message
- JC CLS0
- OPEN1: JMP RETOK
- ;***************************************************************************
- ;
- ; S_CLOSE -- Close the printer
- ;
- S_CLOSE: CMP BYTE PTR ES:[BX].P_STAT,0
- JNE CLS1 ; branch if DosMonClose
- ;
- ; Come here to handle DosClose
- ;
- MOV MONS.M_FLAG,MF_CLOS ; set close flag in header
- CALL GETPID ; put process id into header
- JC CLS0
- MOV MONS.M_PID,AX
- MOV CX,MONHDR ; set message length
- LEA SI,MONS ; set pointer to message
- MOV DX,MonWrite ; DH=0 to synchronize in dispatcher
- CALL DEVHLP ; send the message
- JNC RETOK
- CLS0: JMP ERRGEN
- ;
- ; Come here to handle DosMonClose
- ;
- CLS1: CALL GETPID ; get monitor process id
- JC CLS0
- MOV BX,AX
- MOV AX,MONHAN ; de-register this monitor
- MOV DL,DeRegister
- CALL DEVHLP
- JC CLS0 ; branch if failure
- JMP RETOK
- ;***************************************************************************
- ;
- ; S_IOCTL -- I/O control operation
- ;
- S_IOCTL: CMP ES:[BX].P_CAT,5
- JNE IOC0
- CMP ES:[BX].P_FUN,65H
- JE IOC_S ; branch if IOCTL 5.101, STATUS
- IOC0: CMP ES:[BX].P_CAT,10
- JNE IOC1
- CMP ES:[BX].P_FUN,40H
- JE IOC_R ; branch if IOCTL 10.64, REGISTER
- IOC1: CMP ES:[BX].P_CAT,11
- JNE IOC2
- CMP ES:[BX].P_FUN,60H
- JE IOC_Q ; branch if IOCTL 11.96, QUERY MON
- IOC2: JMP CMDBAD ; else indicate invalid request
- IOC3: JMP ERRGEN
- ;
- ; Query monitor support (Category 11, function 96)
- ;
- IOC_Q: JMP RETOK ; return OK to show monitor support
- ;
- ; Get printer status (Category 5, function 101)
- ;
- IOC_S: LES DI,ES:[BX].P_DATA ; verify access to data buffer
- MOV AX,ES
- MOV CX,1
- MOV DX,0100H+VerifyAccess
- CALL DEVHLP
- JC IOC3 ; branch if access denied
- XOR BX,BX ; lock the data buffer segment
- MOV DL,LockSeg
- CALL DEVHLP
- PUSH AX ; save lock handle
- PUSH BX
- PUSH DS ; convert to physical address
- MOV AX,ES
- MOV DS,AX
- MOV SI,DI
- MOV DL,VirtToPhys
- CALL DEVHLP
- POP DS
- MOV DX,0100H+PhysToVirt ; convert to virtual address
- CALL DEVHLP
- JC IOC4 ; branch if error
- CLI ; begin critical section
- MOV DX,IOLPT ; get device status
- INC DX
- IN AL,DX
- AND AL,0F8H ; save only important bits
- XOR AL,48H ; toggle "acknowledge" and "error"
- MOV AH,STATUS ; include "timer", "flush", "wait"
- AND AH,7
- OR AL,AH
- MOV ES:[DI],AL ; return status in user's data area
- STI ; end critical section
- MOV DL,UnPhysToVirt ; release mapping
- CALL DEVHLP
- POP BX ; unlock data buffer segment
- POP AX
- MOV DL,UnlockSeg
- CALL DEVHLP
- JMP RETOK
- IOC4: POP BX ; come here on error after lock
- POP AX
- MOV DL,UnlockSeg
- CALL DEVHLP
- IOC5: JMP ERRGEN
- ;
- ;
- ; Register a monitor (Category 10, function 64)
- ;
- IOC_R: CALL GETPID ; get monitor process id
- JC IOC3 ; branch if error
- LES SI,ES:[BX].P_DATA ; get data area address
- MOV DH,ES:[SI].R_POS ; get postion code
- MOV DI,ES:[SI].R_OUT ; get output buffer offset
- LES SI,ES:[SI].R_IN ; get input buffer pointer
- MOV AX,MONHAN ; get monitor handle
- MOV DL,Register ; register this monitor
- CALL DEVHLP
- JC IOC5 ; branch if error
- JMP RETOK
- ;***************************************************************************
- ;
- ;
- ; S_RMV -- Remove (de-install) the driver
- ;
- S_RMV: MOV AX,MONHAN ; kill monitor chain
- OR AX,AX
- JZ RMV1
- MOV DL,MonCreate
- CALL DEVHLP
- RMV1: MOV BX,IOINT ; detach from interrupt
- OR BX,BX
- JZ RMV2
- MOV DL,UnSetIRQ
- CALL DEVHLP
- RMV2: JMP RETOK
- ;
- ;***************************************************************************
- ;
- ; NOTIFY routine, called by monitor dispatcher when data is available.
- ;
- NOTIFY PROC FAR
- TEST MONR.M_FLAG,MF_OPEN
- JNZ N_OPEN ; branch if "open" message
- TEST MONR.M_FLAG,MF_CLOS
- JNZ N_CLOS ; branch if "close" message
- TEST MONR.M_FLAG,MF_FLSH
- JZ N_WRT ; branch if "write" message
- ;
- ; Process "flush" message from the monitor chain
- ;
- N_FLSH: AND STATUS,NOT SF_FLSH ; reset flush flag
- JMP RETOK
- ;
- ; Process "open" message from monitor chain
- ;
- N_OPEN: JMP RETOK
- ;
- ; Process "close" message from the monitor chain
- ;
- N_CLOS: JMP RETOK
- ;
- ; Process "write" message from the monitor chain
- ;
- N_WRT: MOV CX,MON ; get message length
- SUB CX,MONHDR+2 ; subtract header and length word
- JBE N03 ; branch if no data
- XOR SI,SI ; reset data buffer index
- N00: TEST STATUS,SF_FLSH
- JNZ N03 ; abort if flush flag is set
- MOV DX,IOLPT ; get printer address
- INC DX ; check status
- IN AL,DX
- TEST AL,80H
- JZ N04 ; branch if not ready
- N01: MOV AL,MONR.M_DATA[SI] ; send next byte
- DEC DX
- OUT DX,AL
- INC DX ; strobe it out
- INC DX
- MOV AL,0DH
- OUT DX,AL
- MOV AX,10
- N02: DEC AX
- JNZ N02
- MOV AL,0CH
- OUT DX,AL
- INC SI ; loop till all bytes sent
- LOOP N00
- N03: RETF ; return to monitor dispatcher
- ;
- ; Come here to wait for printer interrupt
- ;
- N04: CLI ; begin critical section
- INC DX ; enable printer interrupt
- MOV AL,1CH
- OUT DX,AL
- DEC DX ; check status
- IN AL,DX
- TEST AL,80H
- JZ N05 ; branch if still busy
- MOV AL,0CH ; disable printer interrupt
- INC DX
- OUT DX,AL
- STI ; leave critical section
- JMP N00 ; continue data output
- N05: PUSH CX ; save registers
- PUSH SI
- OR STATUS,SF_WAIT ; set "wait" status
- MOV AX,WORD PTR IOTADD+2 ; use I/O table address as event id
- MOV BX,WORD PTR IOTADD
- MOV DI,WORD PTR IOTIME+2 ; load timeout value
- MOV CX,WORD PTR IOTIME
- MOV DX,Block ; DH=0 for interruptable sleep
- CALL DEVHLP
- CLI ; begin critical section
- JC N07 ; branch if timeout or unusual event
- TEST STATUS,SF_WAIT
- JNZ N05 ; re-block if wrong event
- N06: MOV DX,IOLPT ; disable printer interrupt
- INC DX
- INC DX
- MOV AL,0CH
- OUT DX,AL
- STI ; end critical section
- JMP N00 ; go send more data
- ;
- ; Come here if wait times out or is aborted by unusual event
- ;
- N07: OR STATUS,SF_TIME ; set timer flag
- MOV AX,WORD PTR IOTADD+2 ; use I/O table address as event id
- MOV BX,WORD PTR IOTADD
- XOR DI,DI ; set 500 ms timeout value
- MOV CX,500
- MOV DX,Block ; DH=0 for interruptable sleep
- CALL DEVHLP
- CLI ; begin critical section
- TEST STATUS,SF_FLSH
- JNZ N08 ; branch if flush flag is set
- TEST STATUS,SF_WAIT
- JNZ N07 ; repeat if still waiting
- XOR STATUS,SF_TIME ; reset timer flag
- JMP N06 ; continue data output
- ;
- ; Come here if operation is being flushed
- ;
- N08: AND STATUS,NOT (SF_TIME OR SF_WAIT) ; reset flags
- MOV DX,IOLPT ; disable printer interrupt
- INC DX
- INC DX
- MOV AL,0CH
- OUT DX,AL
- STI ; end critical section
- RETF
-
- NOTIFY ENDP
- ;***************************************************************************
- ;
- ; I_LPT routine, called by hardware interrupt dispatcher
- ;
- I_LPT PROC FAR
- TEST STATUS,SF_WAIT
- JZ INT1 ; ignore if not in "wait" mode
- XOR STATUS,SF_WAIT ; reset "wait" status
- MOV AX,WORD PTR IOTADD+2 ; wake up the NOTIFY routine
- MOV BX,WORD PTR IOTADD
- MOV DL,Run
- CALL DEVHLP
- INT1: CLI ; begin critical section
- MOV AX,IOINT ; signal end-of-interrupt
- MOV DL,EOI
- CALL DEVHLP
- CLC ; clear CF to claim interrupt
- RETF
- I_LPT ENDP
- ;***************************************************************************
- ;
- ; User interrupt routine, called by DOS application via interrupt 17H.
- ;
- U_LPT PROC FAR
- STI ; enable interrupts
- PUSH BP ; save all registers
- PUSH ES
- PUSH DS
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
- MOV BX,CS:SAVEDS ; set up DS for the driver
- MOV DS,BX
- MOV DX,IOLPT ; get printer address
- OR AH,AH
- JZ U_WRT ; AH=0 to print AL
- DEC AH
- JZ U_INIT ; AH=1 to initialize
- DEC AH
- JZ U_STAT ; AH=2 to get status
- U_RET: POP AX ; return from interrupt
- POP BX
- POP CX
- POP DX
- POP SI
- POP DI
- POP DS
- POP ES
- POP BP
- IRET
- ;
- ; Initialization routine saves DS here
- ;
- SAVEDS DW 0 ; DS is saved here
- ;
- ; Come here to print the character in AL
- ;
- U_WRT: MOV AL,1 ; begin BIOS critical section
- MOV DL,ROMCritSect
- CALL DEVHLP
- MOV CX,MONHDR+1 ; set monitor message length
- MOV MONS.M_PID,0 ; use 0 for DOS process id
- MOV MONS.M_FLAG,0 ; reset flags
- POP AX ; put byte into buffer
- PUSH AX
- MOV MONS.M_DATA,AL
- LEA SI,MONS ; send message to monitor chain
- MOV AX,MONHAN
- MOV DX,MonWrite
- CALL DEVHLP
- XOR AL,AL ; end BIOS critical section
- MOV DL,ROMCritSect
- CALL DEVHLP
- ; JMP U_STAT ; go get status
- ;
- ; Come here to initialize the printer
- ;
- U_INIT: ; same as status request
- ;
- ; Come here to get printer status
- ;
- U_STAT: CLI ; begin critical section
- MOV DX,IOLPT ; get device status
- INC DX
- IN AL,DX
- AND AL,0F8H ; save only important bits
- XOR AL,48H ; toggle "acknowledge" and "error"
- MOV AH,STATUS ; include "timer", "flush", "wait"
- AND AH,7
- OR AL,AH
- STI ; end critical section
- POP BX ; restore AH and set up AL return
- MOV AH,BH
- PUSH AX
- JMP U_RET
- U_LPT ENDP
- ;
- ;***************************************************************************
- ;
- ; GETPID function, called to obtain current process id, which is returned
- ; in AX. The function returns with CF set if an error occurs.
- ;
- GETPID PROC NEAR
- PUSH ES ; save regs
- PUSH BX
- PUSH DX
- MOV AL,2 ; get address of process info pointer
- MOV DL,GetDOSVar
- CALL DEVHLP
- JC PID1 ; branch if error
- PUSH AX ; get process info pointer in ES:BX
- POP ES
- LES BX,ES:[BX]
- MOV AX,ES:[BX] ; PID is first word
- CLC ; reset CF to indicate success
- PID1: POP DX ; restore regs and return
- POP BX
- POP ES
- RET
- GETPID ENDP
- ;***************************************************************************
- ;
- ; Mark the end of the code segment. Everything after this is discarded
- ; after initialization.
- END_CS EQU $
- ;***************************************************************************
- ;
- ; S_INIT -- Initialize
- ;
- S_INIT: MOV AX,ES:[BX].P_HLP0 ; save DevHlp address
- MOV WORD PTR DEVHLP,AX
- MOV AX,ES:[BX].P_HLP1
- MOV WORD PTR DEVHLP+2,AX
- LEA AX,END_CS ; return CS size
- MOV ES:[BX].P_HLP0,AX
- LEA AX,END_DS ; return DS size
- MOV ES:[BX].P_HLP1,AX
- ;
- ; Check for valid I/O configuration
- LES DI,DWORD PTR IOTADD ; get printer I/O address
- MOV DX,ES:[DI]
- MOV AL,IOINT1 ; check if first parallel device
- CMP DX,IOLPT1
- JE IN01 ; branch if yes
- MOV AL,IOINT2 ; check if second parallel device
- CMP DX,IOLPT2
- JNE INERR ; branch if no
- ;
- ; Initialize the I/O channel and device
- ;
- IN01: MOV IOLPT,DX ; save I/O address
- MOV BYTE PTR IOINT,AL ; save interrupt level
- INC DX ; set DX to control port
- INC DX
- MOV AL,8 ; select and initialize
- OUT DX,AL
- MOV AX,1000 ; delay at least 50 microseconds
- IN02: DEC AX
- JNZ IN02
- MOV AL,12 ; select, no initialize, no auto LF
- OUT DX,AL
- ;
- ; Create monitor chain and save its handle
- ;
- PUSH DS ; make ES:SI point to monitor buffer
- POP ES
- LEA SI,MON
- PUSH DS ; save DS
- PUSH CS ; make DS:DI point to notify routine
- POP DS
- LEA DI,NOTIFY
- XOR AX,AX ; set AX=0 to create monitor chain
- MOV DL,MonCreate ; call DEVHLP using ES instead of DS
- CALL ES:DEVHLP
- POP DS ; restore DS
- JC INERR ; branch if error
- MOV MONHAN,AX ; save monitor handle
- ;
- ; Activate the hardware interrupt
- LEA AX,I_LPT ; get interrupt routine address
- MOV BX,IOINT ; get interrupt level number
- MOV DX,SetIRQ ; DH=0 for non-shared interrupt
- CALL DEVHLP
- JC IN03 ; branch if error
- ;
- ; Activate user interrupt 17H for printer BIOS
- ;
- LEA AX,U_LPT ; get interrupt routine address
- MOV BX,17H ; get interrupt number
- LEA SI,SAVEDS ; get DS save location address
- MOV DL,SetROMVector ; set the interrupt vector
- CALL DEVHLP
- JMP RETOK
- ;
- ; Come here on initialization error
- IN03: MOV AX,MONHAN ; kill monitor chain
- MOV DL,MonCreate
- CALL DEVHLP
- INERR: JMP ERRGEN
- ;
- S_LPT ENDP ; end of main proc
- _TEXT ENDS ; end of code segment
- END ; end of module
-
-
-
-
-