You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
18 KiB
488 lines
18 KiB
|
|
TITLE Hangeul/Hanja Console Device Driver Header
|
|
page ,132
|
|
|
|
;****************************************************************************;
|
|
; (C)Copyright Qnix Co., Ltd., 1985-1991. ;
|
|
; This program contains proprietary and confidential information. ;
|
|
; All rights reserved. ;
|
|
;****************************************************************************;
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; File name: HECON.ASM
|
|
;; Description:
|
|
;; These routine are the header of HECON.SYS which is Installable
|
|
;; Device Driver that is the console device driver to handle
|
|
;; Hangeul/Hanja console IO services
|
|
;;
|
|
;; Called routine:
|
|
;; HAN_INIT - procedure in INIT.ASM file
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
.sall ; supress macro listings
|
|
|
|
BreakInt equ 1bH * 4
|
|
;
|
|
;------------------------------------------------------------------------
|
|
; MACRO DEFINITION ;
|
|
;------------------------------------------------------------------------
|
|
; Given a label <lbl> generate either 2 byte jump to another label <lbl>_J
|
|
; if it is near enough or 3 byte jump to <lbl>
|
|
;
|
|
Jump macro lbl
|
|
local a
|
|
.xcref
|
|
|
|
ifndef lbl&_J ; is this the first invocation
|
|
a: jmp lbl
|
|
else
|
|
if (lbl&_J GE $) or ($-lbl&_J GT 126)
|
|
a: jmp lbl ; is the jump too far away?
|
|
else
|
|
a: jmp lbl&_J ; do the short one...
|
|
endif
|
|
endif
|
|
lbl&_j = a
|
|
.cref
|
|
endm
|
|
.xcref Jump
|
|
;------------------------------------------------------------------------
|
|
|
|
code segment public byte 'code'
|
|
assume cs:code, ds:code
|
|
|
|
INCLUDE EQU.INC
|
|
|
|
if ComFile
|
|
org 100h
|
|
extrn HanInit:near
|
|
HeconStart:
|
|
jmp HanInit
|
|
else
|
|
|
|
HeconStart: ; dummy
|
|
|
|
; start of HECON.SYS routine
|
|
public ConHeader
|
|
ConHeader label word
|
|
dw -1,-1 ; pointer to next device
|
|
dw 1000000001010011B ; con-in and con-out + special
|
|
dw Strategy ; strategy entry point
|
|
dw ConIO ; interrupt entry point
|
|
db 'CON ' ; device name
|
|
|
|
ConTbl:
|
|
db 13h
|
|
dw ConInit ;0
|
|
dw Exit ;1
|
|
dw Exit ;2
|
|
dw CmdErr ;3
|
|
dw ConRead ;4
|
|
dw ConCheck ;5
|
|
dw Exit ;6
|
|
dw ConFlush ;7
|
|
dw ConWrite ;8
|
|
dw ConWrite ;9
|
|
dw Exit ;A
|
|
dw Exit ;B
|
|
if hdos60
|
|
dw Exit ;C
|
|
dw Exit ;D
|
|
dw Exit ;E
|
|
dw Exit ;F
|
|
dw Exit ;10H
|
|
dw Exit ;11H
|
|
dw Exit ;12H
|
|
dw GenIoctl ;13H
|
|
dw Exit ;14H
|
|
endif ; hdos60
|
|
|
|
page
|
|
;
|
|
; The next nine equ's describe the offset into the request header for
|
|
; different information. For example STATUS is in byte 3 of the request
|
|
; header (starting count at zero).
|
|
;
|
|
CmdLen = 0 ; length of this command
|
|
Unit = 1 ; sub unit specifier
|
|
Cmd = 2 ; command code
|
|
Status = 3 ; status
|
|
Media = 13 ; media descriptor
|
|
Trans = 14 ; transfer address
|
|
Count = 18 ; count of blocks or characters
|
|
Start = 20 ; first block to transfer
|
|
Extra = 22 ; Usually pointer to Vol Id for err 15
|
|
|
|
if hdos60
|
|
; Bilingual implementation
|
|
WansungCode = 949
|
|
ChohabCode = 1361
|
|
EnglishCode = 437
|
|
SetCode = 04ah
|
|
|
|
IoctlReq struc
|
|
db 13 dup(?)
|
|
MajorCode db ?
|
|
MinorCode db ?
|
|
SiReg dw ?
|
|
DiReg dw ?
|
|
DataBuf dd ?
|
|
IoctlReq ends
|
|
endif ; hdos60
|
|
|
|
;
|
|
; PtrSav - pointer save
|
|
;
|
|
; This variable holds the pointer to the Request Header passed by a program
|
|
; wishing to use a device driver. When the strategy routine is called
|
|
; it puts the address of the Request header in this variable and returns.
|
|
;
|
|
public PtrSav
|
|
PtrSav dd 0
|
|
|
|
Foo proc far
|
|
Strategy:
|
|
mov word ptr cs:[PtrSav],bx
|
|
mov word ptr cs:[PtrSav+2],es
|
|
ret
|
|
Foo endp
|
|
|
|
;
|
|
; This section is the prolog to all default device drivers. All registers
|
|
; are saved, the registers are filled with information fromthe request header,
|
|
; and the routine from the jump table is called. Error checking is done
|
|
; to assure command code is valid. Before calling the routine in the
|
|
; jump table the register are:
|
|
;
|
|
; AH = Media Descriptor
|
|
; BX = offset to PtrSav (request header is therefore at DS:BX)
|
|
; CX = count from request header
|
|
; DS:SI = tranfer address
|
|
;
|
|
; Once the routine finishes its job it jumps back to one of the eight
|
|
; pieces of code below labeled Exit Points.
|
|
;
|
|
|
|
;------------------------------------------------------------------------
|
|
;
|
|
; Device entry point
|
|
;
|
|
; The following ten pieces of code are the interrupt entry points for the
|
|
; default device drivers. These small pieces of code have two jobs.
|
|
;
|
|
; 1) Make SI point to the beginning of the proper command jump table.
|
|
; SI must first be pushed to preserve original contents.
|
|
;
|
|
; Con device:
|
|
;
|
|
ConIO:
|
|
Entry:
|
|
sti ; enable interrupts
|
|
push ax ; save all registers
|
|
push bx
|
|
push cx
|
|
push si
|
|
push ds
|
|
mov si,offset ConTbl ; get pointer to console IO table
|
|
lds bx,cs:[PtrSav] ; get pointer to I/O packet
|
|
mov cx,ds:[bx].Count ; cx = count
|
|
mov al,ds:[bx].Cmd
|
|
cmp al,cs:[si] ; is command code a valid number?
|
|
ja CmdErr ; no, jump to handle error
|
|
cbw ; note that al <= 15 means OK
|
|
shl ax,1
|
|
inc si
|
|
add si,ax ; get di to point to address of routine
|
|
mov ah,ds:[bx].Media ; ah = media descriptor
|
|
shr ah,1
|
|
shr ah,1
|
|
jmp word ptr cs:[si] ; go to the command
|
|
|
|
page
|
|
|
|
;------------------------------------------------------------------------
|
|
;
|
|
; Exit Points
|
|
;
|
|
; All device driver call return through one of these eight
|
|
; pieces of code. The code set error and status conditions
|
|
; and then restores the registers.
|
|
;
|
|
CmdErr:
|
|
; sub [bx].Count,cx ; # of successful I/O's
|
|
mov ax,1000000100000011B ; mark error(unknown command) & return
|
|
jmp short Exit1
|
|
BusyExit: ; device busy exit
|
|
mov ah,00000011B ; set error code
|
|
jmp short Exit1
|
|
Exit:
|
|
mov ah,00000001B
|
|
Exit1: lds bx,cs:[PtrSav]
|
|
Exit2: and ah,11111011b
|
|
mov [bx].Status,ax ; mark operation complete
|
|
pop ds ; restore register and return
|
|
pop si
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
FarRet1 proc far
|
|
ret
|
|
FarRet1 endp
|
|
|
|
;------------------------------------------------------------------------
|
|
; ;
|
|
; C O N - Console Device Driver ;
|
|
; ;
|
|
;------------------------------------------------------------------------
|
|
;
|
|
; Device Header for the CON Device Driver
|
|
;
|
|
; ALTAH is a single character buffer used to handle special keys.
|
|
;
|
|
|
|
AltAH db 0 ; Special key handling
|
|
|
|
;------------------------------------------------------------------------
|
|
; ;
|
|
; Console Read routine ;
|
|
; ;
|
|
;------------------------------------------------------------------------
|
|
ConRead:
|
|
jcxz ConReadExit ; to be read -- just exit
|
|
lds si,ds:[bx].Trans ; get ds:si to point to trans addr
|
|
test ah,00000001B
|
|
jnz ConReadNonDisp
|
|
mov bx,0 ; get complete char code
|
|
ConReadLoop:
|
|
call CharIn ; get char in al
|
|
mov ds:[si],al ; store char at ds:si, specified buffer
|
|
inc si ; point to next buffer position
|
|
loop ConReadLoop ; if cx is non-zero more char to read
|
|
ConReadExit:
|
|
Jump Exit ; all done, successful return
|
|
|
|
ConReadNonDisp:
|
|
mov bx,(240 shl 8) ; get interim char code
|
|
cmp cx,1
|
|
jne ConReadNonDispLoop
|
|
call CharIn ; get char in al
|
|
mov ds:[si],al ; store char at ds:si, specified buffer
|
|
inc si ; point to next buffer position
|
|
cmp ah,0f0H ; interim char?
|
|
jne ConReadExit ; jump no
|
|
mov ah,00000101B ; indicate interim char
|
|
Jump Exit1
|
|
|
|
ConReadNonDispLoop:
|
|
call CharIn ; get char in al
|
|
cmp ah,0f0H ; interim char?
|
|
je ConReadNonDispLoop ; jump so
|
|
mov ds:[si],al ; store char at ds:si, specified buffer
|
|
inc si ; point to next buffer position
|
|
loop ConReadNonDispLoop ; if cx is non-zero more char to read
|
|
Jump Exit
|
|
|
|
;------------------------------------------------------------------------
|
|
; ;
|
|
; Input single character into AL ;
|
|
; ;
|
|
;------------------------------------------------------------------------
|
|
CharIn:
|
|
xor ax,ax ; set cmd and clear al
|
|
xchg al,cs:[AltAH] ; get character & zero AltAH
|
|
or al,al ; see if buffer has a character
|
|
jnz CharInRet ; if so - return this character
|
|
mov ax,bx
|
|
int 16H ; call ROM-Bios keyboard routine
|
|
or ax,ax ; Check for non-key after BREAK
|
|
jz CharIn
|
|
cmp ax,7200H ; Check for Ctrl-PrtSc
|
|
jnz CharInOk
|
|
mov al,16 ; indicate prtsc
|
|
CharInOk:
|
|
or al,al ; special case?
|
|
jnz CharInRet ; no, return with character
|
|
mov cs:[AltAH],ah ; yes, store special key
|
|
CharInRet:
|
|
ret
|
|
|
|
;----------------------------------------------------------------
|
|
; :
|
|
; Keyboard non destructive read, no wait :
|
|
; :
|
|
; If bit 10 is set by the DOS in the status word of the request :
|
|
; packet, and there is no character in the input buffer, the :
|
|
; driver issues a system WAIT request to the ROM. On return :
|
|
; from the ROM, it returns a 'char-not-found' to the DOS. :
|
|
; :
|
|
;----------------------------------------------------------------
|
|
ConCheck:
|
|
mov al,cs:[AltAH] ; first see if there is a
|
|
or al,al ; character in the buffer?
|
|
jnz ConCheckExit ; yes, return that character
|
|
; no, continue
|
|
mov bx,(1 shl 8)
|
|
test ah,00000001B
|
|
jz ReConCheck ; jump if wanted complete char code
|
|
mov bx,(241 shl 8)
|
|
ReConCheck:
|
|
mov ax,bx
|
|
int 16H ; call ROM-BIOS keyboard routine
|
|
jz ConBusy ; not available char, jump to busy
|
|
or ax,ax ; check for null after break
|
|
jnz ConCheckOk ; no, skip down
|
|
; note: AH is already zero, no need to set command
|
|
int 16H ; yes, read the null
|
|
jmp short ReConCheck
|
|
|
|
ConCheckOk:
|
|
cmp ah,0f0H ; incomplete scan code?
|
|
jnz ConCheckFinal
|
|
lds bx,cs:[PtrSav] ; get pointer to request header
|
|
mov [bx].Media,al ; move character into req. header
|
|
mov ah,00000101B ; indicate interim char
|
|
Jump Exit2
|
|
ConCheckFinal:
|
|
cmp ax,7200H ; check for Ctrl-PrtSc
|
|
jnz ConCheckExit ; no
|
|
mov al,16 ; yes, indicate Ctrl-PrtSc
|
|
ConCheckExit:
|
|
lds bx,cs:[PtrSav] ; get pointer to request header
|
|
mov [bx].Media,al ; move character into req. header
|
|
Jump Exit ; all done -- successful return
|
|
|
|
ConBusy:
|
|
Jump BusyExit ; done -- con device is busy
|
|
|
|
;----------------------------------------------------------------
|
|
; :
|
|
; Keyboard flush routine :
|
|
; :
|
|
;----------------------------------------------------------------
|
|
ConFlush:
|
|
mov cs:[AltAH],0 ; clear out holding buffer
|
|
mov ah,243 ; Keyboard flush entry
|
|
int 16H
|
|
Jump Exit
|
|
|
|
;----------------------------------------------------------------
|
|
; :
|
|
; Console Write Routine :
|
|
; :
|
|
;----------------------------------------------------------------
|
|
ConWrite:
|
|
cld ; clear the direction flag
|
|
jcxz ConWriteExit ; if cx is zero, get out
|
|
lds si,ds:[bx].Trans ; get ds:si to point to trans addr
|
|
mov bx,7 ; set page #(bh), foreground color(bl)
|
|
test ah,00000001B
|
|
jnz ConWriteLoopNac ; output character & no cursor advance
|
|
ConWriteLoop:
|
|
lodsb ; get character
|
|
mov ah,0eH ; write char with cursor advancing
|
|
int 10H ; call bios
|
|
loop ConWriteLoop ; repeat until all through
|
|
ConWriteExit:
|
|
mov ah,00000001B
|
|
lds bx,cs:[PtrSav]
|
|
mov [bx].Status,ax ; mark operation complete
|
|
pop ds ; restore register and return
|
|
pop si
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
FarRet2 proc far
|
|
ret
|
|
FarRet2 endp
|
|
|
|
ConWriteLoopNac:
|
|
lodsb ; get character
|
|
mov ah,0feH ; write char w/o cursor advancing
|
|
int 10H ; call bios
|
|
loop ConWriteLoopNac ; repeat until all through
|
|
Jump Exit
|
|
|
|
;------------------------------------------------
|
|
;
|
|
; CONSOLE INIT ROUTINE
|
|
;
|
|
;------------------------------------------------
|
|
ConInit:
|
|
push dx ; save registers
|
|
; patch the BREAK key handling interrupt routine
|
|
sub ax,ax
|
|
mov ds,ax
|
|
mov bx,BreakInt
|
|
mov ax,offset cBreak
|
|
mov dx,cs
|
|
cli
|
|
mov ds:[bx],ax
|
|
mov ds:[bx+2],dx
|
|
sti
|
|
extrn HanInit:near
|
|
call HanInit
|
|
;
|
|
; Now, CX:DX points to the end of HECON.SYS resident part
|
|
;
|
|
lds bx,cs:[PtrSav]
|
|
mov [bx].Trans,dx
|
|
mov [bx].Trans+2,cx
|
|
pop dx ; restore registers
|
|
Jump Exit
|
|
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; BREAK KEY HANDLING
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
cBreak:
|
|
mov cs:[AltAH],3 ; indicate break key set
|
|
push ax ; save register
|
|
mov ah,243 ; keyboard flush
|
|
int 16H
|
|
pop ax ; recover register
|
|
iret
|
|
|
|
if hdos60
|
|
;
|
|
; Bilingual implementation
|
|
;
|
|
extrn ChangeCodeR:near
|
|
GenIoctl:
|
|
mov al,ds:[bx.MinorCode]
|
|
cmp al,SetCode
|
|
je @f
|
|
jmp CmdErr
|
|
@@:
|
|
push bx
|
|
push es
|
|
push dx
|
|
les bx,ds:[bx.DataBuf]
|
|
mov ax,es:[bx+2]
|
|
mov dl,0
|
|
cmp ax,WansungCode
|
|
je CallChange
|
|
mov dl,1
|
|
cmp ax,ChohabCode
|
|
je CallChange
|
|
mov dl,2
|
|
cmp ax,EnglishCode
|
|
je CallChange
|
|
pop dx
|
|
pop es
|
|
pop bx
|
|
jmp CmdErr
|
|
CallChange:
|
|
mov al,dl
|
|
call ChangeCodeR
|
|
pop dx
|
|
pop es
|
|
pop bx
|
|
jmp Exit
|
|
endif ; hdos60
|
|
|
|
endif ; if ComFile
|
|
|
|
code ends
|
|
end HeconStart
|
|
|