home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / COMM / MISC / SRC26_2.ZIP / SRC / SERDRV98.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-06-28  |  10.7 KB  |  590 lines

  1.     name    serdrv98
  2. ;
  3. ; serdrv98.asm: hterm serial and timer driver for PC-9801
  4. ;
  5. ; Author: HIRANO Satoshi
  6. ;
  7. ; (C) 1989  Halca Computer Science Laboratory TM
  8. ;           University of Tokyo
  9. ;
  10. ; Reference:
  11. ;  Interface 1984 de-ta tsusin no xterm
  12. ;
  13. ; Edition History:
  14. ; 2.2 89/05/16 Halca.Hirano V2.2 distribution
  15. ; 2.3 89/06/17 Halca.Hirano move baudrate setting and parity setting 
  16. ;        to port.c
  17. ; 2.4 89/06/20 Halca.Hirano rename from xport98.asm
  18. ; 2.5 89/07/27 Halca.Hirano far, combine timer98.asm
  19. ;    move non time sensitive part to port.c
  20. ;    support multiple port 
  21. ; 2.6 89/08/05 Halca.Hirano add mouse handler
  22. ; 2.7 89/09/15 Halca.Hirano add RTS/CTS flow control
  23. ; 2.8 89/09/25 Halca.Hirano mask char on getSerial
  24. ;    ---- V2.4.0 distribution ----
  25. ; 2.9 89/10/26 Halca.Hirano change buffer size from 500 to 2000
  26. ; 3.0 89/11/29 Halca.Hirano fix timer bug. restart interval timer exactly.
  27. ;
  28. ; $Header: serdrv98.asv  1.10  90/06/28 02:39:50  hirano  Exp $
  29.  
  30. ;
  31. ; constants
  32. ;
  33. I8251_DATA    EQU    0H    ; i8251 data register (offset)
  34. I8251_STATUS     EQU    2H    ; i8251 status register (offset)
  35. I8259_ICR    EQU    00H    ; i8259 interrupt control register (address)
  36. I8259_IMR    EQU    02H    ; i8259 interrupt mask register (address)
  37. EOI        EQU    20H    ; i8259 end of interrupt command
  38. TRUE        EQU    -1
  39. FALSE        EQU    0
  40. YES        equ    1
  41. NO        equ    0
  42.  
  43. BUFSIZE    EQU    2000        ; receive buffer size
  44. OFFLIM1    EQU    1900        ; XOFF send timing 1
  45. OFFLIM2    EQU    1850        ; XOFF send timing 2
  46. OFFLIM3    EQU    1965        ; XOFF send timing 3
  47. ONLIMIT    EQU    1000        ; XON send timing
  48. XON    EQU    011H
  49. XOFF    EQU    013H
  50.  
  51. ;
  52. ; C interface
  53. ;
  54. extrn    _cMask:byte            ; character mask
  55. extrn    _maskFlag:byte            ; 1=XOFFed
  56. extrn    _downLoading:byte        ; 1=down loading
  57. extrn    _xonXoff:byte            ; 1=XON/XOFF enable, 2=RTS/CTS enable
  58. extrn    _portAddress:word        ; port address
  59. extrn    _onMask:byte            ; interrupt on mask for IMR
  60. extrn    _offMask:byte            ; interrupt off mask for IMR
  61. extrn    _timerValue: word        ; timer counter
  62. extrn    _timerLoadValue: word        ; timer reload value
  63. extrn    _bsKeyWatcherTimer: word ; bs key watcher timer
  64. extrn    _kermitTimer: word        ; kermit timer counter
  65. extrn    _portTimer: word        ; serial port timer counter
  66. extrn    _blinkTimer: word        ; soft cursor blink timer
  67. extrn    _mouseEvent: far        ; mouse handler C part procedure
  68.  
  69. ;
  70. ; static strage in the data segment
  71. ;
  72. _DATA    segment word public 'DATA' 
  73. buffer        db    BUFSIZE dup(?)
  74. ; Work area for Timer of PC98XA
  75. timerwork    db    6 dup(?)
  76. timerset    dw    0
  77. timeroff    dw    0
  78. timerseg    dw    0
  79. _DATA    ends
  80.  
  81. DGROUP    group    _DATA
  82. _TEXT    segment    byte public 'CODE'
  83. _TEXT    ends
  84.     assume    ds:DGROUP, cs:_TEXT
  85. _TEXT    segment
  86. ;
  87. ; static strage in the code segment
  88. ;
  89. htermDS    dw    0
  90. head    dw    0
  91. tail    dw    0
  92. full    dw    0
  93. xoffed    dw    0
  94. htermDS2 dw    0
  95. ;
  96. ; getPortInterruptHandlerAddress()
  97. ; in: none
  98. ; out: retuns far address of interrupt handler
  99. ;
  100.     public    _getPortInterruptHandlerAddress
  101. _getPortInterruptHandlerAddress proc    far
  102.     mov    cs:htermDS,ds
  103.     mov    ax,offset cs:portInterruptHandler
  104.     mov    dx,cs        ; return far pointer
  105.     ret
  106. _getPortInterruptHandlerAddress endp
  107.  
  108.  
  109. ;
  110. ; port interrupt handler
  111. ;
  112. portInterruptHandler proc near
  113.     cli
  114.     push    ax
  115.     push    ds
  116.     push    es
  117.     push    dx
  118.     mov    dx,cs:htermDS
  119.     mov    es,dx
  120.     mov    ds,dx
  121.     mov    dx,_portAddress
  122.     add    dx,I8251_DATA
  123.     in    al,dx
  124. ; check XON or XOFF from the remote system if not downloading nor xonXoff mode
  125.     cmp     byte ptr _downLoading,YES
  126.     jz    int02
  127.     cmp    byte ptr _xonXoff,1
  128.     jz    int02
  129.     cmp    al,XOFF
  130.     jne    int00
  131.     mov    byte ptr _maskFlag,YES
  132.     jmp    si1
  133.  
  134. int00:
  135.     cmp    al,XON
  136.     jne    int02
  137.     mov    byte ptr _maskFlag,NO
  138.     jmp    si1
  139.  
  140. int02:
  141.     cmp    cs:full,TRUE
  142.     je    si1
  143.  
  144.     push    di
  145.     push    si
  146.     mov    si,cs:head
  147.     mov    di,cs:tail
  148.     push    ax
  149.     call    getsize
  150.     cmp    ax,OFFLIM1
  151.     jle    si2
  152.     
  153.     mov    dx,cs:xoffed
  154.     cmp    dx,NO
  155.     jne    off1
  156.     inc    cs:xoffed
  157.     jmp    off3
  158. off1:    cmp    dx,YES
  159.     jne    off2
  160.     cmp    ax,OFFLIM2
  161.     jle    si2
  162.  
  163.     inc    cs:xoffed
  164.     jmp    off3
  165. off2:    cmp    ax,OFFLIM3
  166.     jle    si2
  167. off3:    call    dc3
  168.  
  169. si2:    pop    ax
  170.     cld
  171.     stosb
  172.     cmp    di,offset ds:buffer+BUFSIZE
  173.     jne    si3
  174.     mov    di,offset ds:buffer
  175. si3:    mov    cs:tail,di
  176.  
  177.     cmp    si,di
  178.     jne    si4
  179.     mov    cs:full,TRUE
  180. si4:    pop    si
  181.     pop    di
  182. si1:    pop    dx
  183.     pop    es
  184.     pop    ds
  185.     sti
  186.     mov    al,EOI
  187.     out    I8259_ICR,al
  188.     pop    ax
  189.     iret
  190. portInterruptHandler endp
  191.  
  192. getsize:
  193.     mov    ax,di
  194.     mov    dx,si
  195.     cmp    ax,dx
  196.     jae    sizeg
  197.     sub    dx,ax
  198.     neg    dx
  199.     add    dx,BUFSIZE
  200.     mov    ax,dx
  201.     ret
  202.  
  203. sizeg:    sub    ax,dx
  204.     ret
  205.  
  206. ;
  207. ; dc1: send XON or assert RTS
  208. ;
  209. dc1:
  210.     push    ax
  211.     mov    al,byte ptr _xonXoff
  212.     cmp    al,1            ; ? XON/XOFF enable
  213.     jne    dc12            ; bra if no
  214.     mov    al,XON
  215.     push    ax
  216.     call    _putSerial            ; send XON
  217.     pop    ax
  218.     jmp    dc19
  219. dc12:
  220.     cmp    al,2            ; ? RTS/CTS enable
  221.     jne    dc19            ; bra if no, no flow control
  222.     push    dx
  223.     mov    dx,_portAddress        ; get port address
  224.     add    dx,I8251_STATUS
  225.     mov    al,37h
  226.     out    dx,al            ; assert RTS,DTR,RxE and TxEN
  227.     pop    dx
  228. dc19:
  229.     pop    ax
  230.     ret
  231.  
  232. ;
  233. ; send XOFF or negate RTS
  234. ;
  235. dc3:    push    ax
  236.     mov    al,byte ptr _xonXoff
  237.     cmp    al,1            ; ? XON/XOFF enable
  238.     jne    dc32            ; bra if no
  239.     mov    al,XOFF            ; send XOFF
  240.     push    ax
  241.     call    _putSerial
  242.     pop    ax
  243.     jmp    dc39
  244. dc32:
  245.     cmp    al,2            ; ? RTS/CTS enable
  246.     jne    dc39            ; bra if no, no flow control
  247.     push    dx
  248.     mov    dx,_portAddress        ; get port address
  249.     add    dx,I8251_STATUS
  250.     mov    al,17h
  251.     out    dx,al            ; assert DTR,RxE and TxEN, negate RTS
  252.     pop    dx
  253. dc39:
  254.     pop    ax
  255.     ret
  256.  
  257. ;
  258. ; putSerial(data)  output data
  259. ; al: data; 
  260. ;
  261. _putSerial    proc
  262.     push    dx
  263.     push    ax                    ; save sending character
  264.     mov        dx,_portAddress        ; load device address
  265.     push    dx                    ; save it for later
  266.     add        dx,I8251_STATUS        ; point to status register
  267. rswait:    
  268.     in        al,dx                ; get status
  269.     and        al,5h
  270.     cmp        al,5h                ; ? transmit buffer empty
  271.     jnz        rswait                ; bra if no
  272.     pop        dx                    ; load device address
  273.     pop        ax
  274.     add        dx,I8251_DATA        ; point to data register
  275.     out        dx,al                ; put the char
  276.     pop        dx
  277.     ret
  278. _putSerial    endp
  279.  
  280. ;
  281. ; initPortBuffer()  buffer initialize
  282. ;
  283.     public    _initPortBuffer
  284. _initPortBuffer proc far
  285.     mov    ax,offset ds:buffer
  286.     mov    cs:head,ax
  287.     mov    cs:tail,ax
  288.     ret
  289. _initPortBuffer endp
  290.  
  291. ;
  292. ; disable receive interrupt
  293. ;
  294. disable:
  295.     cli
  296.     in    al,I8259_IMR
  297.     or    al,ds:_offMask
  298.     out    I8259_IMR,al
  299.     sti
  300.     ret
  301.  
  302. ;
  303. ; enable receive interrupt
  304. ;
  305. enable:
  306.     cli
  307.     in    al,I8259_IMR
  308.     and    al,ds:_onMask
  309.     out    I8259_IMR,al
  310.     sti
  311.     ret
  312.  
  313. ;
  314. ; char getSerial() get a char from the buffer
  315. ;
  316.     public    _getSerial
  317. _getSerial proc far
  318.     push    di
  319.     push    si
  320.     call    disable
  321.  
  322.     mov    si,cs:head
  323.     mov    di,cs:tail
  324.     cmp    si,di
  325.     jne    sd1
  326.  
  327.     cmp    cs:full,TRUE
  328.     je    sd2
  329.     call    enable
  330.     mov    ax,-1
  331.     pop    si
  332.     pop    di
  333.     ret
  334.  
  335. sd2:    mov    cs:full,FALSE
  336.     cld
  337. sd1:
  338.     lodsb
  339.     mov    ah,ds:_cMask
  340.     and    al,ah            ;mask char
  341.     mov    ah,0
  342.     push    ax
  343.     cmp    si,offset ds:buffer+BUFSIZE
  344.     jne    sd3
  345.     mov    si,offset ds:buffer
  346.  
  347. sd3:
  348.     mov    cs:head,si
  349.     cmp    cs:xoffed,NO
  350.     je    sd4
  351.     call    getsize
  352.     cmp    ax,ONLIMIT
  353.     jge    sd4
  354.     call    dc1
  355.  
  356.     mov    cs:xoffed,FALSE
  357. sd4:    call    enable
  358.     pop    ax
  359.     pop    si
  360.     pop    di
  361.     ret
  362. _getSerial endp
  363.  
  364. ;
  365. ; checkSerial() check serial buffer
  366. ; if empty return 0
  367. ;
  368.     public    _checkSerial
  369. _checkSerial proc far
  370.     cli
  371.     push    di
  372.     push    si
  373.     mov    ax,YES            ; prepare buffer not empty
  374.     mov    si,cs:head
  375.     mov    di,cs:tail
  376.     cmp    si,di            ; ? head == tail
  377.     jne    checkK2            ; bra if no
  378.     mov    ax,NO            ; flag buffer empty
  379. checkK2:
  380.     pop    si
  381.     pop    di
  382.     sti
  383.     ret
  384. _checkSerial endp
  385.  
  386.  
  387. ;
  388. ; timerInit(handlerAddress)
  389. ; void (*handlerAddress)();
  390. ;
  391. ; start 100msec timer
  392. ;
  393. ;
  394.     public    _timerInit
  395. _timerInit proc    far
  396.     push    bp
  397.     mov        bp,sp
  398.     push    es
  399.     push    bx
  400.     push    cx
  401.     mov        cs:htermDS2,ds
  402.   ifdef PC98XA
  403.     mov        timerset, 10
  404.     mov        ax,[bp+8]     ; cs
  405.     mov        timerseg,ax
  406.     mov        ax,[bp+6]        
  407.     mov        timeroff,ax            ; offset cs:_timerHandler
  408.     mov        ah,5                ; timer set request code
  409.     push    ds
  410.     pop        es                    ; es := data segment address
  411.     mov        bx,offset ds:timerwork ; bx := timer handler offset
  412.   else
  413.     mov        ah,2                ; timer set request code
  414.     mov        cx,[bp+8]            ; 
  415.     mov        es,cx                ; es = code segment
  416.     mov        bx,[bp+6]             ; bx := timer handler offset
  417.     mov        cx,10                ; 10 * 10msec = 100 msec
  418.   endif
  419.     int        01ch                ; call BIOS
  420.     pop        cx
  421.     pop        bx
  422.     pop        es
  423.     pop        bp
  424.     ret
  425. _timerInit endp
  426.  
  427. ;
  428. ; timerHandler
  429. ; decriment extern short timerValue and start next interval
  430. ;
  431.     public    _timerHandler
  432. _timerHandler proc far
  433.     push    ds
  434.     push    ax
  435. ; for debug
  436.    ifdef PC98XA
  437. ;    mov    ax,0e000h
  438.    else
  439. ;    mov    ax,0a000h
  440.    endif
  441. ;    mov    ds,ax
  442. ;    mov    ax,03f3fh
  443. ;    mov    ds:0,ax
  444. ; end for debug
  445. ; advance hterm timers
  446.     mov        ax,cs:htermDS2
  447.     mov        ds,ax                ; load ds
  448.     dec        ds:_kermitTimer        ; dec kermit timer
  449.     dec        ds:_portTimer        ; dec port timer
  450.     dec        ds:_timerValue        ; dec saver timer
  451.     dec        ds:_bsKeyWatcherTimer    ; dec bs key watcher timer
  452.     dec        ds:_blinkTimer        ; dec soft cursor blink timer
  453. ; check new interval is required
  454.     mov        ax,ds:_timerLoadValue
  455.     cmp     ax,0                ; ? reset timer
  456.     je        timerH2                ; bra if no
  457. ; restart interval timer
  458.     push    cs                        ; handler code segment
  459.     mov        ax,offset cs:_timerHandler
  460.     push    ax                        ; handler offset
  461.     call    far ptr _timerInit        ; wake up me again
  462.     pop        ax
  463.     pop        ax                        ; rewind stack
  464. timerH2:
  465.     pop        ax
  466.     pop        ds
  467.     iret
  468. _timerHandler endp
  469.  
  470. ;**************
  471. ; utilities
  472.     
  473. ;
  474. ; u_char pokeMemory(seg, addr, data)
  475. ; u_short seg, addr;
  476. ; u_char data;
  477. ;
  478.     public    _pokeMemory
  479. _pokeMemory proc far
  480.     push    bp
  481.     mov    bp,sp
  482.     push    ds
  483.     push    si
  484.     mov    ax,[6+bp]
  485.     mov    ds,ax            ; load data segment
  486.     mov    ax,[8+bp]
  487.     mov    si,ax            ; address
  488.     mov    ax,[10+bp]        ; word to write
  489.     mov    [si],al            ; write byte
  490.     pop    si
  491.     pop    ds
  492.     pop    bp
  493.     ret
  494. _pokeMemory endp
  495.  
  496. ;
  497. ; u_char peekMemory(seg, addr)
  498. ; u_short seg, addr;
  499. ;
  500.     public    _peekMemory
  501. _peekMemory proc far
  502.     push    bp
  503.     mov    bp,sp
  504.     push    ds
  505.     push    si
  506.     mov    ax,[6+bp]
  507.     mov    ds,ax            ; load data segment
  508.     mov    ax,[8+bp]
  509.     mov    si,ax            ; address
  510.     mov    ax,0            ; prepare room
  511.     mov    al,[si]            ; peek memory
  512.     pop    si
  513.     pop    ds
  514.     pop    bp
  515.     ret
  516. _peekMemory endp
  517.  
  518. ;
  519. ; short directConsoleIO()
  520. ; return DOS keyboard input without wait
  521. ;
  522. ;    if no char is available, return -1
  523. ;    else    return the char
  524. ;
  525.     public    _directConsoleIO
  526. _directConsoleIO proc far
  527.     push    dx
  528.     mov    dl,0ffh
  529.     mov    ah,6
  530.     int    21h
  531.     je    dirCIO2
  532.     mov    ah,0
  533.     jmp    dirCIO3
  534. dirCIO2:
  535.     mov    ax,-1
  536. dirCIO3:
  537.     pop    dx
  538.     ret
  539. _directConsoleIO endp
  540.  
  541.  
  542. ;
  543. ; getMouseInterruptHandlerAddress
  544. ;
  545.     public _getMouseIntAddress
  546. _getMouseIntAddress proc    far
  547.     mov    cs:htermDS,ds
  548.     mov    ax,offset cs:mouseInterruptHandler
  549.     mov    dx,cs
  550.     ret
  551. _getMouseIntAddress endp
  552.  
  553. ;
  554. ; mouseInterruptHandler()
  555. ; this procedures is called by far call from mouse driver
  556. ;
  557.     public mouseInterruptHandler
  558. mouseInterruptHandler proc    far
  559.     push    es
  560.     push    ss
  561.     push    ds
  562.     push    ax
  563.     push    bx
  564.     push    cx
  565.     push    dx            ; save registers
  566.  
  567.     push    dx            ; y
  568.     push    cx            ; x
  569.     push    ax            ; event (arg may be changed)
  570.     mov    ds,cs:htermDS
  571.     call    far ptr _mouseEvent    ; call C part
  572.     add    sp,6
  573. ; for debug
  574. ;    mov    al,07h
  575. ;    out    037h,al            ; stop bell
  576.  
  577.     pop    dx
  578.     pop    cx
  579.     pop    bx
  580.     pop    ax
  581.     pop    ds
  582.     pop    ss
  583.     pop    es
  584.     ret
  585. mouseInterruptHandler endp
  586. _TEXT    ends
  587.     end
  588.     ENDFILE
  589.  
  590.