home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / OS2KBSPD.ZIP / KBRATE.ASM next >
Assembly Source File  |  1987-12-07  |  9KB  |  345 lines

  1.         NAME    KBRATE
  2.  
  3.         .286p
  4.  
  5. _DATA        SEGMENT    WORD PUBLIC 'DATA'
  6. _DATA        ENDS
  7. STACK        SEGMENT    PARA STACK 'STACK'
  8. STACK        ENDS
  9. _TEXT        SEGMENT    BYTE PUBLIC 'CODE'
  10. _TEXT        ENDS
  11. KBDIO        SEGMENT    BYTE PUBLIC 'CODE'
  12. KBDIO        ENDS
  13. DGROUP        GROUP    _DATA,STACK
  14.  
  15.  
  16. _DATA        SEGMENT
  17.         ASSUME    DS:DGROUP
  18.  
  19. intro        DB    "KBRATE -- Set PC-AT keyboard repeat rate [OS/2 Version 1.02]",13,10
  20.         DB    10,10,"$"
  21. INTROLEN    EQU    $-intro-1
  22.  
  23. invletter    DB    "  Invalid letter for repeat rate",13,10,"$"
  24. INVLETTERLEN    EQU    $-invletter-1
  25.  
  26. invnumeral    DB    "  Invalid numeral for delay time",13,10,"$"
  27. INVNUMERALLEN    EQU    $-invnumeral-1
  28.  
  29.  
  30. kbrateusage    DB    13,10
  31.         DB    "Usage:     KBRATE xy",13,10
  32.         DB    "           'x' is a letter A..Z which gives the"
  33.         DB    "repetition rate in",13,10
  34.         DB    "           characters per second (A = fastest).",13,10
  35.         DB    13,10
  36.         DB    "           Some useful values are A = 30,  C = 24,  E = 20",13,10
  37.         DB    "           I = 15, M = 10, Q = 7.5",13,10,10
  38.         DB    "           'y' is a numeral 1..4 ehich gives the time delay",13,10
  39.         DB    "           between a key's first depression and the start",13,10
  40.         DB    "           of its repetition, in units of a quarter of a",13,10
  41.         DB    "           second.",13,10
  42.         DB    13,10,"$"
  43. KBRATEUSAGELEN    EQU    $-kbrateusage-1
  44.  
  45. kbrateset    DB    "  Keyboard rate set",13,10,"$"
  46. KBRATESETLEN    EQU    $-kbrateset-1
  47.  
  48. notset        DB    "  I/O error: Keyboard rate not set",13,10,"$"
  49. NOTSETLEN    EQU    $-notset-1
  50.  
  51.  
  52. cmdlineseg    DW    0        ; selector for command line
  53. cmdlineoff    DW    0        ; offset of command line in segment
  54.  
  55. saveoffset    DW    0000h
  56. savesegment    DW    0000h
  57. savebyte    DB    00h
  58. savebyte2    DB    00h
  59. savebyte3    DB    00h
  60.  
  61. _DATA        ENDS
  62.  
  63.  
  64. STACK        SEGMENT
  65.         ASSUME    SS:STACK
  66. mystack        DW    100h DUP (?)
  67. stacktop    DW    0000
  68. STACK        ENDS
  69.  
  70.  
  71. _TEXT        SEGMENT
  72.         ASSUME    CS:_TEXT,DS:DGROUP
  73. ;   +-------------------------------------------------------------------+
  74. ;   |  Symbols                                |
  75. ;   +-------------------------------------------------------------------+
  76.  
  77.  
  78. keyboard_cmd    equ    064h        ; keyboard command register
  79. keyboard_status    equ    064h        ; same register for status
  80. keyboard_data    equ    060h        ; port to write data to
  81.  
  82. kbd_inbuf_full    equ    02h        ; bit mask for kbd ibf
  83. kbd_outbuf_full    equ    01h        ; bit mask for kbd obf
  84.  
  85.  
  86. std_mode_cmd    equ    0ADh        ; command for i-s mode
  87. dec_mode_cmd    equ    0ACh        ; command for DEC mode
  88. kbd_ack        equ    0FAH        ; acknowledge from keyboard
  89.  
  90.  
  91. ;
  92. ;  +-------------------------------------------------------------------------+
  93. ;  |      Variables                                 |
  94. ;  +-------------------------------------------------------------------------+
  95. ;
  96.  
  97. PRTMSG        MACRO    msg,msglen
  98.         XOR    AX,AX        ; handle of stdout for OS/2
  99.         PUSH    AX
  100.         MOV    AX,msglen    ; the length of the message
  101.         PUSH    AX
  102.         MOV    AX,OFFSET msg    ; the message
  103.         PUSH    DS
  104.         PUSH    AX
  105.         CALL    DOSPUTMESSAGE
  106.         ENDM
  107.  
  108. IFREAL        MACRO    target
  109.         PUSH    AX        ; create stack space for answer
  110.         MOV    AX,SP        ; prepare pointer to this byte
  111.         PUSH    SS        ; push ptr to this byte SS:AX
  112.         PUSH    AX
  113.         CALL    DOSGETMACHINEMODE
  114.         POP    AX        ; adjust stack & get result into AL
  115.         CMP    AL,00h        ; real mode?
  116.         JZ    target
  117.         ENDM
  118.  
  119. IFPROT        MACRO    target
  120.         PUSH    AX        ; create stack space for 1 byte
  121.         MOV    AX,SP        ; prepare pointer to this byte
  122.         PUSH    SS        ; push ptr to this byte SS:AX
  123.         PUSH    AX
  124.         CALL    DOSGETMACHINEMODE
  125.         POP    AX        ; adjust stack & get result into AL
  126.         CMP    AL,01h        ; prot mode?
  127.         JZ    target
  128.         ENDM
  129.  
  130.  
  131.         EXTRN    DOSPUTMESSAGE:FAR
  132.         EXTRN    DOSEXIT:FAR
  133.         EXTRN    DOSGETMACHINEMODE:FAR
  134.  
  135. main        PROC    NEAR
  136.         ; AX:BX points to the command line under OS/2
  137.         ; AX:0000h is our environment under OS/2
  138.         ; ES:0080h is length of arguments under DOS
  139.         ; ES:0081h is start of command line under DOS
  140.  
  141.         MOV    WORD PTR cmdlineseg,AX    ; save ptr to command line
  142.         MOV    WORD PTR cmdlineoff,BX    ; (even if not under OS/2)
  143.  
  144.         ; display our welcome message
  145.         PRTMSG    intro,INTROLEN
  146.  
  147. ;
  148. ;
  149. ;    In OS/2, the command line is at AX:BX (cmdlineseg:cmdlineoff)
  150. ;    In DOS, the command line is at ES:0081h (length at ES:0080h)
  151.  
  152.  
  153. dosparse:    ; parse command line under MS-DOS
  154.         CALL    NEAR PTR getinit    ; set up for parsing
  155.         ; CX now has the # of bytes
  156.         OR    CX,CX            ; JCXZ usage
  157.         JNZ    dosparse1
  158.         JMP    usage
  159.  
  160. dosparse1:    CALL    NEAR PTR getchar
  161.         CMP    AL,20h                  ; is it a space?
  162.         JZ    dosskipwhite
  163.         CMP    AL,09h            ; is it a <tab>?
  164.         JZ    dosskipwhite
  165.         CMP    AL,00h            ; null (end of cmd line)?
  166.         JNZ    doseval            ; no: evaluate
  167.         JMP    usage            ; yes: no arguments present
  168.  
  169. dosskipwhite:    LOOP    dosparse1 
  170.         JMP    usage
  171.  
  172. doseval:    ; check for a valid letter A..Z (after capitalizing)
  173.         AND    AL,0DFh
  174.         SUB    AL,41h                         ;'A' 
  175.         CMP    AL,19h
  176.         JBE    goodletter
  177.  
  178.         PRTMSG    invletter,INVLETTERLEN        ; bad letter
  179.         JMP    badness
  180.  
  181. goodletter:    MOV    BYTE PTR savebyte,AL 
  182.         CALL    NEAR PTR getchar
  183.         SUB    AL,31h                ;'1' 
  184.         CMP    AL,03h                ; in 1..4?
  185.         JBE    goodnumber
  186.  
  187.         PRTMSG    invnumeral,INVNUMERALLEN
  188.         JMP    badness
  189.  
  190. goodnumber:    MOV    BYTE PTR savebyte2,AL    ; now compute magic #
  191.         MOV    AL,BYTE PTR savebyte2    ;
  192.         MOV    CL,05h            ;
  193.         SHL    AL,CL            ;
  194.         OR    AL,BYTE PTR savebyte    ;;
  195.  
  196.         PUSH    AX            ; save the speed
  197.         ; AL now has the speed byte that we want (also on stack)
  198.  
  199.     ; Now that we have our magic number for the keyboard in AL
  200.     ; and on top of the stack, lets send out the commands!
  201.  
  202.         mov    al,0F3h            ; set rate command
  203.         call    FAR PTR send_cmd    ;
  204.         pop    ax            ; restore the speed into AX
  205.         jc    badness2        ;;
  206.  
  207.         call    FAR PTR send_cmd    ; now send out the speed
  208.         jc    badness2        ;;
  209.  
  210.         mov    al,0F4h            ; enable keyboard
  211.         call    FAR PTR send_cmd    ;
  212.         jc    badness2        ;;
  213.  
  214.         PRTMSG    kbrateset,KBRATESETLEN
  215.  
  216. goodness:    ; terminate w/no error
  217.         XOR    AX,AX
  218.         PUSH    AX
  219.         PUSH    AX
  220.         CALL    DOSEXIT
  221.  
  222. usage:        PRTMSG    kbrateusage,KBRATEUSAGELEN
  223.         JMP    badness
  224.  
  225. badness2:    PRTMSG    notset,NOTSETLEN
  226.  
  227. badness:    ; terminate with error
  228.         MOV    AX,0001h
  229.         PUSH    AX
  230.         PUSH    AX
  231.         CALL    DOSEXIT
  232.  
  233. main        ENDP
  234.  
  235.  
  236. ;   +-------------------------------------------------------------------+
  237. ;   |  getinit - initialize for getting characters from command line.    |
  238. ;   |  Set up ES:SI to point to the command line.            |
  239. ;   |  Also, skip program name when under OS/2.                |
  240. ;   |  CX is set to the length of the command line arguments.        |
  241. ;   +-------------------------------------------------------------------+
  242. getinit        PROC    NEAR
  243.  
  244. getinitp: ; protected mode init
  245.         MOV    AX,WORD PTR cmdlineseg
  246.         MOV    ES,AX
  247.         MOV    SI,WORD PTR cmdlineoff
  248.  
  249.       ; now ES:SI points to program name (which we must skip)
  250.         CMP    BYTE PTR ES:[SI],00h    ; special case (no args)
  251.         JZ    giend
  252. giskip:        MOV    AL,BYTE PTR ES:[SI]    ; look at next character
  253.         CMP    AL,20h            ; a space?
  254.         JZ    giend            ; yes: exit
  255.         CMP    AL,00h            ; a separator (or end)?
  256.         JZ    giend            ; yes: exit
  257.         INC    SI            ; no: loop
  258.         JMP    giskip            ;;
  259.  
  260. giend:        SMSW    AX            ; get machine status word -> AX
  261.         TEST    AX,0001h        ; in protected mode?
  262.         JZ    skiplsl            ; no: skip LSL instruction
  263.  
  264.         MOV    AX,ES            ; get selector in AX
  265.         LSL    CX,AX            ; get segment limit
  266.  
  267.     ;; Special code to ensure last byte is 00h in command line
  268. ;        PUSH    BX
  269. ;        MOV    BX,CX
  270. ;        MOV    BYTE PTR ES:[BX],00h    ; make sure last byte is 00h
  271. ;        POP    BX
  272.  
  273.         JMP    postlsl
  274.  
  275. skiplsl:    MOV    CX,0010h        ; lie about # of bytes there
  276.  
  277. postlsl:    SUB    CX,SI            ; subtract start
  278.         SUB    CX,0002h        ; less null terminators
  279.         RET
  280. getinit        ENDP
  281.  
  282.  
  283. ;   +-------------------------------------------------------------------+
  284. ;   |  getchar - return the next character in AL at ES:SI.        |
  285. ;   +-------------------------------------------------------------------+
  286. getchar        PROC    NEAR
  287.  
  288.         MOV    AL,BYTE PTR ES:[SI]    ; get the byte
  289.         INC    SI
  290.         CMP    AL,00h            ; arg separator?
  291.         JNZ    getend            ; no: return
  292.         MOV    AH,BYTE PTR ES:[SI]    ; peek at next char
  293.         CMP    AH,00h            ; is next char null?
  294.         JZ    getend            ; yes: return null
  295.         MOV    AL,20h            ; no: return a space
  296. getend:        RET
  297.  
  298. getchar        ENDP
  299.  
  300.  
  301.  
  302. _TEXT        ENDS
  303.  
  304.  
  305. KBDIO        SEGMENT
  306.         ASSUME    CS:KBDIO,DS:DGROUP
  307. send_cmd    proc    far
  308.  
  309.         mov    bx,ax            ; save command
  310.  
  311.         xor    cx,cx            ; wait a long time
  312.         cli                ; so BIOS can't get in the way
  313.         in    al,keyboard_data    ; clear outbut buffer
  314.  
  315. wait_kbd:    in    al,keyboard_status    ; read status
  316.         test    al,kbd_inbuf_full    ; is input buffer full?
  317.         loopnz    wait_kbd        ; keep waiting
  318.         jcxz    timeout            ; if timeout
  319.         mov    al,bl            ; get back command
  320.         out    keyboard_data,al    ;
  321.  
  322. ; now, wait for the acknowledge
  323.         xor    cx,cx            ; timeout
  324. wait_ack:    in    al,keyboard_status    ; read status
  325.         test    al,kbd_outbuf_full
  326.         loopz    wait_ack        ; wait for ACK
  327.         jcxz    timeout            ; timed out
  328.         in    al,keyboard_data    ; read byte
  329.         cmp    al,kbd_ack        ; is it an ACK?
  330.         jnz    wait_ack        ; nope.
  331.  
  332.         sti                ; ok to use port now
  333.         clc                ; no errors
  334.         ret
  335.  
  336. timeout:    sti                ; ok to use port now
  337.         stc                ; error waiting for kbd
  338.         ret
  339.  
  340. send_cmd    ENDP
  341. KBDIO        ENDS
  342.  
  343.         END    main
  344.  
  345.