home *** CD-ROM | disk | FTP | other *** search
- name serdrv98
- ;
- ; serdrv98.asm: hterm serial and timer driver for PC-9801
- ;
- ; Author: HIRANO Satoshi
- ;
- ; (C) 1989 Halca Computer Science Laboratory TM
- ; University of Tokyo
- ;
- ; Reference:
- ; Interface 1984 de-ta tsusin no xterm
- ;
- ; Edition History:
- ; 2.2 89/05/16 Halca.Hirano V2.2 distribution
- ; 2.3 89/06/17 Halca.Hirano move baudrate setting and parity setting
- ; to port.c
- ; 2.4 89/06/20 Halca.Hirano rename from xport98.asm
- ; 2.5 89/07/27 Halca.Hirano far, combine timer98.asm
- ; move non time sensitive part to port.c
- ; support multiple port
- ; 2.6 89/08/05 Halca.Hirano add mouse handler
- ; 2.7 89/09/15 Halca.Hirano add RTS/CTS flow control
- ; 2.8 89/09/25 Halca.Hirano mask char on getSerial
- ; ---- V2.4.0 distribution ----
- ; 2.9 89/10/26 Halca.Hirano change buffer size from 500 to 2000
- ; 3.0 89/11/29 Halca.Hirano fix timer bug. restart interval timer exactly.
- ;
- ; $Header: serdrv98.asv 1.10 90/06/28 02:39:50 hirano Exp $
-
- ;
- ; constants
- ;
- I8251_DATA EQU 0H ; i8251 data register (offset)
- I8251_STATUS EQU 2H ; i8251 status register (offset)
- I8259_ICR EQU 00H ; i8259 interrupt control register (address)
- I8259_IMR EQU 02H ; i8259 interrupt mask register (address)
- EOI EQU 20H ; i8259 end of interrupt command
- TRUE EQU -1
- FALSE EQU 0
- YES equ 1
- NO equ 0
-
- BUFSIZE EQU 2000 ; receive buffer size
- OFFLIM1 EQU 1900 ; XOFF send timing 1
- OFFLIM2 EQU 1850 ; XOFF send timing 2
- OFFLIM3 EQU 1965 ; XOFF send timing 3
- ONLIMIT EQU 1000 ; XON send timing
- XON EQU 011H
- XOFF EQU 013H
-
- ;
- ; C interface
- ;
- extrn _cMask:byte ; character mask
- extrn _maskFlag:byte ; 1=XOFFed
- extrn _downLoading:byte ; 1=down loading
- extrn _xonXoff:byte ; 1=XON/XOFF enable, 2=RTS/CTS enable
- extrn _portAddress:word ; port address
- extrn _onMask:byte ; interrupt on mask for IMR
- extrn _offMask:byte ; interrupt off mask for IMR
- extrn _timerValue: word ; timer counter
- extrn _timerLoadValue: word ; timer reload value
- extrn _bsKeyWatcherTimer: word ; bs key watcher timer
- extrn _kermitTimer: word ; kermit timer counter
- extrn _portTimer: word ; serial port timer counter
- extrn _blinkTimer: word ; soft cursor blink timer
- extrn _mouseEvent: far ; mouse handler C part procedure
-
- ;
- ; static strage in the data segment
- ;
- _DATA segment word public 'DATA'
- buffer db BUFSIZE dup(?)
- ; Work area for Timer of PC98XA
- timerwork db 6 dup(?)
- timerset dw 0
- timeroff dw 0
- timerseg dw 0
- _DATA ends
-
- DGROUP group _DATA
- _TEXT segment byte public 'CODE'
- _TEXT ends
- assume ds:DGROUP, cs:_TEXT
- _TEXT segment
- ;
- ; static strage in the code segment
- ;
- htermDS dw 0
- head dw 0
- tail dw 0
- full dw 0
- xoffed dw 0
- htermDS2 dw 0
- ;
- ; getPortInterruptHandlerAddress()
- ; in: none
- ; out: retuns far address of interrupt handler
- ;
- public _getPortInterruptHandlerAddress
- _getPortInterruptHandlerAddress proc far
- mov cs:htermDS,ds
- mov ax,offset cs:portInterruptHandler
- mov dx,cs ; return far pointer
- ret
- _getPortInterruptHandlerAddress endp
-
-
- ;
- ; port interrupt handler
- ;
- portInterruptHandler proc near
- cli
- push ax
- push ds
- push es
- push dx
- mov dx,cs:htermDS
- mov es,dx
- mov ds,dx
- mov dx,_portAddress
- add dx,I8251_DATA
- in al,dx
- ; check XON or XOFF from the remote system if not downloading nor xonXoff mode
- cmp byte ptr _downLoading,YES
- jz int02
- cmp byte ptr _xonXoff,1
- jz int02
- cmp al,XOFF
- jne int00
- mov byte ptr _maskFlag,YES
- jmp si1
-
- int00:
- cmp al,XON
- jne int02
- mov byte ptr _maskFlag,NO
- jmp si1
-
- int02:
- cmp cs:full,TRUE
- je si1
-
- push di
- push si
- mov si,cs:head
- mov di,cs:tail
- push ax
- call getsize
- cmp ax,OFFLIM1
- jle si2
-
- mov dx,cs:xoffed
- cmp dx,NO
- jne off1
- inc cs:xoffed
- jmp off3
- off1: cmp dx,YES
- jne off2
- cmp ax,OFFLIM2
- jle si2
-
- inc cs:xoffed
- jmp off3
- off2: cmp ax,OFFLIM3
- jle si2
- off3: call dc3
-
- si2: pop ax
- cld
- stosb
- cmp di,offset ds:buffer+BUFSIZE
- jne si3
- mov di,offset ds:buffer
- si3: mov cs:tail,di
-
- cmp si,di
- jne si4
- mov cs:full,TRUE
- si4: pop si
- pop di
- si1: pop dx
- pop es
- pop ds
- sti
- mov al,EOI
- out I8259_ICR,al
- pop ax
- iret
- portInterruptHandler endp
-
- getsize:
- mov ax,di
- mov dx,si
- cmp ax,dx
- jae sizeg
- sub dx,ax
- neg dx
- add dx,BUFSIZE
- mov ax,dx
- ret
-
- sizeg: sub ax,dx
- ret
-
- ;
- ; dc1: send XON or assert RTS
- ;
- dc1:
- push ax
- mov al,byte ptr _xonXoff
- cmp al,1 ; ? XON/XOFF enable
- jne dc12 ; bra if no
- mov al,XON
- push ax
- call _putSerial ; send XON
- pop ax
- jmp dc19
- dc12:
- cmp al,2 ; ? RTS/CTS enable
- jne dc19 ; bra if no, no flow control
- push dx
- mov dx,_portAddress ; get port address
- add dx,I8251_STATUS
- mov al,37h
- out dx,al ; assert RTS,DTR,RxE and TxEN
- pop dx
- dc19:
- pop ax
- ret
-
- ;
- ; send XOFF or negate RTS
- ;
- dc3: push ax
- mov al,byte ptr _xonXoff
- cmp al,1 ; ? XON/XOFF enable
- jne dc32 ; bra if no
- mov al,XOFF ; send XOFF
- push ax
- call _putSerial
- pop ax
- jmp dc39
- dc32:
- cmp al,2 ; ? RTS/CTS enable
- jne dc39 ; bra if no, no flow control
- push dx
- mov dx,_portAddress ; get port address
- add dx,I8251_STATUS
- mov al,17h
- out dx,al ; assert DTR,RxE and TxEN, negate RTS
- pop dx
- dc39:
- pop ax
- ret
-
- ;
- ; putSerial(data) output data
- ; al: data;
- ;
- _putSerial proc
- push dx
- push ax ; save sending character
- mov dx,_portAddress ; load device address
- push dx ; save it for later
- add dx,I8251_STATUS ; point to status register
- rswait:
- in al,dx ; get status
- and al,5h
- cmp al,5h ; ? transmit buffer empty
- jnz rswait ; bra if no
- pop dx ; load device address
- pop ax
- add dx,I8251_DATA ; point to data register
- out dx,al ; put the char
- pop dx
- ret
- _putSerial endp
-
- ;
- ; initPortBuffer() buffer initialize
- ;
- public _initPortBuffer
- _initPortBuffer proc far
- mov ax,offset ds:buffer
- mov cs:head,ax
- mov cs:tail,ax
- ret
- _initPortBuffer endp
-
- ;
- ; disable receive interrupt
- ;
- disable:
- cli
- in al,I8259_IMR
- or al,ds:_offMask
- out I8259_IMR,al
- sti
- ret
-
- ;
- ; enable receive interrupt
- ;
- enable:
- cli
- in al,I8259_IMR
- and al,ds:_onMask
- out I8259_IMR,al
- sti
- ret
-
- ;
- ; char getSerial() get a char from the buffer
- ;
- public _getSerial
- _getSerial proc far
- push di
- push si
- call disable
-
- mov si,cs:head
- mov di,cs:tail
- cmp si,di
- jne sd1
-
- cmp cs:full,TRUE
- je sd2
- call enable
- mov ax,-1
- pop si
- pop di
- ret
-
- sd2: mov cs:full,FALSE
- cld
- sd1:
- lodsb
- mov ah,ds:_cMask
- and al,ah ;mask char
- mov ah,0
- push ax
- cmp si,offset ds:buffer+BUFSIZE
- jne sd3
- mov si,offset ds:buffer
-
- sd3:
- mov cs:head,si
- cmp cs:xoffed,NO
- je sd4
- call getsize
- cmp ax,ONLIMIT
- jge sd4
- call dc1
-
- mov cs:xoffed,FALSE
- sd4: call enable
- pop ax
- pop si
- pop di
- ret
- _getSerial endp
-
- ;
- ; checkSerial() check serial buffer
- ; if empty return 0
- ;
- public _checkSerial
- _checkSerial proc far
- cli
- push di
- push si
- mov ax,YES ; prepare buffer not empty
- mov si,cs:head
- mov di,cs:tail
- cmp si,di ; ? head == tail
- jne checkK2 ; bra if no
- mov ax,NO ; flag buffer empty
- checkK2:
- pop si
- pop di
- sti
- ret
- _checkSerial endp
-
-
- ;
- ; timerInit(handlerAddress)
- ; void (*handlerAddress)();
- ;
- ; start 100msec timer
- ;
- ;
- public _timerInit
- _timerInit proc far
- push bp
- mov bp,sp
- push es
- push bx
- push cx
- mov cs:htermDS2,ds
- ifdef PC98XA
- mov timerset, 10
- mov ax,[bp+8] ; cs
- mov timerseg,ax
- mov ax,[bp+6]
- mov timeroff,ax ; offset cs:_timerHandler
- mov ah,5 ; timer set request code
- push ds
- pop es ; es := data segment address
- mov bx,offset ds:timerwork ; bx := timer handler offset
- else
- mov ah,2 ; timer set request code
- mov cx,[bp+8] ;
- mov es,cx ; es = code segment
- mov bx,[bp+6] ; bx := timer handler offset
- mov cx,10 ; 10 * 10msec = 100 msec
- endif
- int 01ch ; call BIOS
- pop cx
- pop bx
- pop es
- pop bp
- ret
- _timerInit endp
-
- ;
- ; timerHandler
- ; decriment extern short timerValue and start next interval
- ;
- public _timerHandler
- _timerHandler proc far
- push ds
- push ax
- ; for debug
- ifdef PC98XA
- ; mov ax,0e000h
- else
- ; mov ax,0a000h
- endif
- ; mov ds,ax
- ; mov ax,03f3fh
- ; mov ds:0,ax
- ; end for debug
- ; advance hterm timers
- mov ax,cs:htermDS2
- mov ds,ax ; load ds
- dec ds:_kermitTimer ; dec kermit timer
- dec ds:_portTimer ; dec port timer
- dec ds:_timerValue ; dec saver timer
- dec ds:_bsKeyWatcherTimer ; dec bs key watcher timer
- dec ds:_blinkTimer ; dec soft cursor blink timer
- ; check new interval is required
- mov ax,ds:_timerLoadValue
- cmp ax,0 ; ? reset timer
- je timerH2 ; bra if no
- ; restart interval timer
- push cs ; handler code segment
- mov ax,offset cs:_timerHandler
- push ax ; handler offset
- call far ptr _timerInit ; wake up me again
- pop ax
- pop ax ; rewind stack
- timerH2:
- pop ax
- pop ds
- iret
- _timerHandler endp
-
- ;**************
- ; utilities
-
- ;
- ; u_char pokeMemory(seg, addr, data)
- ; u_short seg, addr;
- ; u_char data;
- ;
- public _pokeMemory
- _pokeMemory proc far
- push bp
- mov bp,sp
- push ds
- push si
- mov ax,[6+bp]
- mov ds,ax ; load data segment
- mov ax,[8+bp]
- mov si,ax ; address
- mov ax,[10+bp] ; word to write
- mov [si],al ; write byte
- pop si
- pop ds
- pop bp
- ret
- _pokeMemory endp
-
- ;
- ; u_char peekMemory(seg, addr)
- ; u_short seg, addr;
- ;
- public _peekMemory
- _peekMemory proc far
- push bp
- mov bp,sp
- push ds
- push si
- mov ax,[6+bp]
- mov ds,ax ; load data segment
- mov ax,[8+bp]
- mov si,ax ; address
- mov ax,0 ; prepare room
- mov al,[si] ; peek memory
- pop si
- pop ds
- pop bp
- ret
- _peekMemory endp
-
- ;
- ; short directConsoleIO()
- ; return DOS keyboard input without wait
- ;
- ; if no char is available, return -1
- ; else return the char
- ;
- public _directConsoleIO
- _directConsoleIO proc far
- push dx
- mov dl,0ffh
- mov ah,6
- int 21h
- je dirCIO2
- mov ah,0
- jmp dirCIO3
- dirCIO2:
- mov ax,-1
- dirCIO3:
- pop dx
- ret
- _directConsoleIO endp
-
-
- ;
- ; getMouseInterruptHandlerAddress
- ;
- public _getMouseIntAddress
- _getMouseIntAddress proc far
- mov cs:htermDS,ds
- mov ax,offset cs:mouseInterruptHandler
- mov dx,cs
- ret
- _getMouseIntAddress endp
-
- ;
- ; mouseInterruptHandler()
- ; this procedures is called by far call from mouse driver
- ;
- public mouseInterruptHandler
- mouseInterruptHandler proc far
- push es
- push ss
- push ds
- push ax
- push bx
- push cx
- push dx ; save registers
-
- push dx ; y
- push cx ; x
- push ax ; event (arg may be changed)
- mov ds,cs:htermDS
- call far ptr _mouseEvent ; call C part
- add sp,6
- ; for debug
- ; mov al,07h
- ; out 037h,al ; stop bell
-
- pop dx
- pop cx
- pop bx
- pop ax
- pop ds
- pop ss
- pop es
- ret
- mouseInterruptHandler endp
- _TEXT ends
- end
- ENDFILE
-
-