;; ************************************************************************
;; LL_KBD (tm) Multiple Keypress ISR
;; Copyright (C) 1994 by Logics Inc., All rights reserved.
;;
;; VERSION  :   0003.512
;; DATE     :   08-21-94
;; CODED BY :   James P. Ketrenos [ketrenoj@cs.pdx.edu]
;; ASSEMBLER:   MASM 6.1
;; USE WITH :   Watcom C/C++ v9.5
;;
;; Why use LL_KBD?
;; Basically, the advantages to using LL_KBD come in two areas:
;; * Multi-keypress response
;; * Advanced keyboard buffering
;; * Compatible with Watcom C/C++
;; * Easy, and FUN! to use (yeah, uh-huh)
;;
;; Bugs:
;; None that I know of.
;;
;; Revision History:
;; 0001.000     Generic Multi-key stuff, with minimal buffering
;; 0001.256     Added enhanced buffering, nothing too exciting
;; 0002.276C    Added SHIFT Conversion Mode.  Created buffering modes.
;; 0002.512     Added CTRL/ALT Conversions.
;; 0002.712     Fixed the EXTENDED byte error
;; 0003.000     All buffering and conversion modes flawless;
;; 0003.128     Added NUM/CAP/SCRL Light Control
;; 0003.256     Added TYPEMATIC Rate Adjustment
;; 0003.512     Adjusted Light stuff to attempt to restore to the way the
;;              the lights were when initiated, but no luck . . .
;;
;; Routines:
;; kbdInit();       kbdReset();
;; kbdGetKey();     kbdPutKey();    kbdClearKeys();
;; kbdKeyHit();     kbdGetMode();       kbdSetMode();
;; ************************************************************************
.386
include keycodes.inc

;; **  D A T A  ***********************************************************
DGROUP  group   _DATA
_DATA   segment 'DATA'
;; ***********************************************************
;; Typical EQUates for easier to read code
;; ***********************************************************
ON          equ 1                   ;; Boolean EQUates for easier to
OFF             equ 0                                   ;; : follow code
TRUE            equ 1                                   ;; :
FALSE       equ 0                   ;; :

;; ***********************************************************
;; Keyboard SCAN Code & Table OFFSET EQUates
;; ***********************************************************
L_ALT       equ 38h     ;; Highest priority conversion
R_ALT       equ 5ch     ;; :
L_CTRL      equ 1dh     ;; Second Highest
R_CTRL      equ 5ah     ;; :
L_SHIFT     equ 2ah     ;; Third Highest
R_SHIFT     equ 36h     ;; :

ALT_OFS     equ 256     ;; ALT FromScan[] OFFSET
CTRL_OFS    equ 512     ;; CTRL FromScan[] OFFSET
SHIFT_OFS   equ 768     ;; SHIFT FromScan[] OFFSET

;; ***********************************************************
;; Data structures reachable from Watcom C/C++ 32
;; ***********************************************************
PUBLIC  _kbdFLAGS                   ;; char *kbdFLAGS=&KeyFlags;

;; ***********************************************************
;;  Keyboard Tables & Buffers
;; ***********************************************************
    even
    even
    even
    even 
    ;; ***********************************************************
    ;; Miscellaneous Toggles & Data Variables
    ;; ***********************************************************
    kbdLights       db  OFF         ;; Keyboard Lights Bitfield:
                                    ;; 0000 000x Scroll Lock Light
                                    ;; 0000 00x0 Number Lock Light
                                    ;; 0000 0x00 Caps Lock Light
                                    ;; xxxx x000 RESERVED

    kbdDelay        db  0           ;; Typematic Delay
    kbdRate         db  0           ;; Typematic Rate

    ;; ***********************************************************
    ;; Buffer and Flag Variables & Tables
        ;; ***********************************************************
    _kbdFLAGS       dd  offset KeyFlags
    KeyFlags        db  256 dup (0) ;; Doesn't need to be this big, but . . .

    KeyTail         db  0           ;; Keyboard buffer Tail (duh!)
    KeyHead         db  0           ;; Keyboard buffer Head (really?)
    KeyBuffer       db  256 dup (0) ;; Keyboard buffer (shock to the system)

    KeyMode         db  11b         ;; Keystroke Conversion
                                    ;; 00b - No Conversion
                                    ;; 01b - Convert (ALT/CTRL/SHIFT)+Keys
                                    ;; 10b - Buffer SYSTEM Keys

    KeyExtFlag      db  OFF         ;; Extended Keystroke Flag

    ;; ***********************************************************
    ;; Variables set by kbdInit()
        ;; ***********************************************************
    KeyboardInst    db  0           ;; Keyboard ISR Installed Flag
    ISR_OldS        dw  ?           ;; Old Vector Segment
    ISR_OldO        dd  ?           ;; Old Vector Offset

_DATA   ends
;; ************************************************************************

;; **  C O D E  3 2  ******************************************************
_TEXT   SEGMENT BYTE PUBLIC USE32 'CODE'
        ASSUME  CS:_TEXT
        ASSUME  DS:DGROUP

;; ***********************************************************
;; Routines callable from Watcom C/C++ 32
;; ***********************************************************
PUBLIC  kbdInit_, kbdReset_             ;; Init/Reset Keyboard handler
PUBLIC  kbdKeyHit_                      ;; Get Buffer Info
PUBLIC  kbdClearKeys_                   ;; Flush the I/O Buffer
PUBLIC  kbdGetKey_, kbdPutKey_          ;; I/O with Buffer
PUBLIC  kbdGetMode_, kbdSetMode_        ;; Buffer Mode [CONVERT/ABSOLUTE]
PUBLIC  kbdSetNumLight_;, kbdSetNumMode  ;; Set up NUM LOCK status
PUBLIC  kbdSetCapLight_;, kbdSetCapMode  ;; Set up CAP LOCK status
PUBLIC  kbdSetScrlLight_;, kbdSetScrlMode;; Set up SCROLL LOCK status
PUBLIC  kbdSetRate_                     ;; Set Typematic Rate

;; *************************************************************************
;; kbdSetRate(char DELAY, char RATE)
;; Pass:    eax=DELAY   : (DELAY+1)*250 in milliseconds
;;          ebx=RATE    : (8+RATE&0x07)*(2^RATE&0x18)*4.17 in milliseconds
kbdSetRate_ PROC
    mov     ah,al
    mov     al,0f3h                 ;; Send Set Typematic Rate/Delay Command
    out     60h,al                  ;; : to the 8042

    and     ah,00000011b            ;; Clear all but the DELAY bits
    and     bl,00011111b            ;; Clear all but the RATE bits
    mov     kbdDelay,ah             ;; Save the new values to our
    mov     kbdRate,bl              ;; : variables
    or      ah,bl                   ;; Set it all into one byte

@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    mov     al,ah                   ;; Send the new Typematic Rate
    out     60h,al                  ;; :
@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :

    ret                             ;; Return to lala land
kbdSetRate_ ENDP

;; *************************************************************************
;; Keyboard_PM is the new Keyboard interrupt.
;; It reads the scan code from the Keyboard and modifies the flags table.
;;
;; The flag table is set as follows:
;;      0000 000x       Current status.  1==Pressed, 0==Released.
;;      0000 00x0       Prior status.  1==Pressed.      Unchanged when released.
;;  xxxx xx00   RESERVED
;; *************************************************************************
Keyboard_PM PROC USES EAX EBX ECX EDI DS ES
    cli                             ;; Shut off the interrupts

    mov     ax,_DATA                ;; Set up to point to OUR dataseg
    mov     ds,ax                   ;; :
    mov     es,ax                   ;; :

    cld                             ;; Clear the direction flag

        ;; *********************************************
    ;; First, fetch SCAN Code from PC Keyboard (8042)
        ;; *********************************************
    in      al,60h                  ;; Get SCAN Code from Keyboard Port
    mov     bl,al                   ;; Place SCAN code into BL
    and     ebx,01111111b           ;; Strip all but the SCAN Code from EBX

    or      KeyExtFlag,0            ;; Now, make sure we're not in EXTENDED
    jnz     KBIExtended             ;; And if we are, then skip the KeyExtFlag

    cmp     al,0e0h                 ;; Check for start of EXTENDED
    sete    KeyExtFlag              ;; : Set Flag accordingly
    je      KBIDone                 ;; : Exit if it is first EXTENDED

    test    al,10000000b            ;; Check if key was just PRESSED
    jnz     KBIReleased             ;; : and if not, then work with release

;; ********************************************************************
;; Handle the KEY PRESSED scenario
;; ********************************************************************
KBIPressed:
    or      KeyFlags[ebx],00000011b ;; Set Flag to IS & WAS Pressed

    ;; *********************************************
    ;; Check to see if buffer is FULL and leave if so
        ;; *********************************************
    movzx   ecx,KeyHead             ;; Point to the front of the buffer
        inc     cl                                              ;; : and if the next space places
        cmp     cl,KeyTail                              ;; : us on the end of the buffer,
        jz              KBIDone                                 ;; : then the buffer is full . . .
        dec     cl                                              ;; : otherwise, we help fill it.

    ;; ****************************************************************
    ;; System Key Buffering Section
    ;; ****************************************************************
KBIBuffer:
    test    KeyMode,00000010b       ;; Check to see if in BUFFER Mode
    jz      KBIConvert              ;; : and if not, then try and continue.

    ;; *********************************************
    ;; Check if key is in our System Control Key Table
    ;; *********************************************
    mov     edi,offset Control      ;; Get the start of the CONTROL Table
    push    ecx                     ;; Save ECX (Buffer Position)
    mov     ecx,9                   ;; We'll check for 9 SYSTEM Keys
    mov     al,bl                   ;; Scan for the SCAN Code
    repne   scasb                   ;; Do the scan . . .
    pop     ecx                     ;; Restore ECX
    jz      KBIDone                 ;; : and if this is one, then we're done.

    ;; ****************************************************************
    ;; Conversion Section: ALT->CTRL->SHIFT->NORMAL
    ;; ****************************************************************
KBIConvert:
    test    KeyMode,00000001b       ;; Check to see if in CONVERT mode
    jz      KBINoConvert            ;; :

    ;; *********************************************
    ;; Check to see if ALT is pressed
    ;; *********************************************
KBIChkALT:
    mov     ah,KeyFlags[L_ALT]
    or      ah,KeyFlags[R_ALT]
    test    ah,00000001b
    jz      KBIChkCTRL
    mov     ax,FromSCAN_ALT[ebx*2]  ;; Get ASCII from SCAN Table
    jmp     KBIPutKey

    ;; *********************************************
    ;; Check to see if CTRL is pressed
    ;; *********************************************
KBIChkCTRL:
    mov     ah,KeyFlags[L_CTRL]
    or      ah,KeyFlags[R_CTRL]
    test    ah,00000001b
    jz      KBIChkSHIFT
    mov     ax,FromSCAN_CTRL[ebx*2] ;; Get ASCII from SCAN Table
    jmp     KBIPutKey

    ;; *********************************************
    ;; Check to see if either SHIFT is pressed
    ;; *********************************************
KBIChkSHIFT:
    mov     ah,KeyFlags[L_SHIFT]
    or      ah,KeyFlags[R_SHIFT]
    test    ah,00000001b
    jz      KBINoConvert

@@: mov     ax,FromSCAN_SHIFT[ebx*2];; Get ASCII from SCAN Table
    jmp     KBIPutKey

    ;; *********************************************
    ;; Get the SCAN Code for NON-system modified
    ;; *********************************************
KBINoConvert:
    mov     ax,FromSCAN_NON[ebx*2]  ;; Get ASCII Code from SCAN Code Table

    ;; ****************************************************************
    ;; Verify Key, and Put Key into KEYBOARD BUFFER
    ;; ****************************************************************
KBIPutKey:
    or      ax,ax                   ;; Check to see if the key is real
    jz      KBIDone                 ;; : and if not, then we're done

    or      ah,ah                   ;; Check to see if it was EXTENDED
    jnz     KBIExtend               ;; : and if so, then do an extended one.

    ;; *********************************************
    ;; Write a ONE Byte ASCII Code to Buffer
    ;; *********************************************
    mov     KeyBuffer[ecx],al       ;; Save the Byte Code into buffer
    inc     KeyHead                 ;; Increment the KeyHead (loops at 256)

    ;; *********************************************
    ;; End the INTerrupt for the PRESSED Single Byte
    ;; *********************************************
    mov     al,20h                  ;; Send generic EOI to PIC
        out     20h,al                                  ;; :
    sti                             ;; Let the interrupts take over . . .
    iretd                           ;; Let's get the freak outa here.

    ;; ****************************************************************
    ;; Write a TWO Byte ASCII Code to buffer from EXTENDED Press
    ;; ****************************************************************
KBIExtend:
    mov     KeyBuffer[ecx],al       ;; Save the Byte Code into buffer
    inc     KeyHead                 ;; Increment the KeyHead (loops at 256)

        ;; *********************************************
    ;; Check to see if buffer is FULL and leave if so
    ;; *********************************************
    add     cl,2                    ;;
    cmp     cl,KeyTail              ;; Check to see if full
    jz      KBIDone                 ;; : And if so, then we're outa here...
    inc     KeyHead                 ;; Increment the KeyHead (loops at 256)
    dec     cl                      ;; Step back one character . . .

    mov     KeyBuffer[ecx],ah       ;; Save the Extended Flag into buffer

    ;; *********************************************
    ;; End the INTerrupt for the PRESSED Extended Byte
    ;; *********************************************
KBIDone:
    mov     al,20h                  ;; Send generic EOI to PIC
        out     20h,al                                  ;; :
    sti                             ;; Let the interrupts take over . . .
    iretd                           ;; Let's get the freak outa here.

;; ********************************************************************
;; Handle the EXTENDED 60h INPUT
;; ********************************************************************
KBIExtended:
    mov     KeyExtFlag,0            ;; Clear the in EXTENDED flag

    ;; *********************************************
    ;; Determine which Extended Key was active
    ;; *********************************************
    mov     edi,offset Extended     ;; Get the start of the EXTENDED Table
    mov     ecx,10h                 ;; We'll check for 16 EXTENDED Keys
    mov     ah,al                   ;; Copy the PRESS/RELEASE BIT
    mov     al,bl                   ;; Scan for the SCAN Code
    repne   scasb                   ;; Do the scan . . .

    mov     bl,057h                 ;; Set SCAN Offset into our EXTENDED set
    sub     bl,cl                   ;; :
    add     bl,00fh                 ;; :

    test    ah,10000000b            ;; Check if key was just PRESSED
    jz      KBIPressed              ;; : and if so, then work with it . . .

;; ********************************************************************
;; Handle the KEY RELEASED scenario
;; ********************************************************************
KBIReleased:
    and     KeyFlags[ebx],11111110b ;; Set Flag to NOT BEING Pressed

    ;; *********************************************
    ;; End the INTerrupt for the RELEASED scenario
    ;; *********************************************
    mov     al,20h                  ;; Send generic EOI to PIC
        out     20h,al                                  ;; :
    sti                             ;; Let the interrupts take over . . .
    iretd                           ;; Let's get the freak outa here.
Keyboard_PM     ENDP



kbdGetMode_ PROC
    movzx   eax,KeyMode
    ret
kbdGetMode_ ENDP



kbdSetMode_ PROC
    and     al,00000011b
    mov     KeyMode,al
    ret
kbdSetMode_ ENDP



kbdInit_        PROC NEAR USES EAX EBX EDX ES
        ;; *********************************************
        ;; Check to make sure new handler IS NOT installed
        ;; *********************************************
        cmp     KeyboardInst,0
        jz              @F
        ret

@@: ;; *********************************************
        ;; Set KeyboardInst flag appropriately
        ;; *********************************************
        mov     KeyboardInst,1

        ;; *********************************************
        ;; Get OLD INT 09h Vector
        ;; *********************************************
    mov     ax,3509h            ;; Get vector for INT 09h (Keyboard)
        int             21h                             ;; :
    mov     ISR_OldO,ebx        ;; : save it . . .
    mov     ISR_OldS,es         ;; :

        ;; *********************************************
        ;; Set NEW INT 09h Vector
        ;; *********************************************
        push    ds                                      ;; Save DS
        mov             ax,cs                           ;; Set DS:EDX => New INT 09h
        mov             ds,ax                           ;; :
        mov     ax,2509h                        ;; :
        mov             edx,offset Keyboard_PM
        int             21h                                     ;; :
        pop     ds                                      ;; Restore DS

    ;; *********************************************
    ;; Set the Keyboard Lights to OFF
    ;; *********************************************
        mov     al,0edh                 ;; Send Set/Reset Mode Indicator Command
    out     60h,al                  ;; : to the 8042

@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :

    xor     al,al                   ;; Reset the Light Mode to OFF
    out     60h,al                  ;; :

@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :

    ret                                 ;; Return to caller
kbdInit_        ENDP



kbdReset_       PROC NEAR USES EAX EDX DS
        ;; *********************************************
        ;; Check to make sure new handler IS installed
        ;; *********************************************
        cmp     KeyboardInst,1
        jz              @F
        ret

@@: ;; *********************************************
        ;; Set KeyboardInst flag appropriately
        ;; *********************************************
        mov     KeyboardInst,0

    ;; *********************************************
    ;; Restore OLD INT 09h Vector
        ;; *********************************************
        mov     ax,2509h                        ;; Set vector for INT 09h (Keyboard)
    mov     edx,ISR_OldO        ;; : to original Keyboard Interrupt
    mov     ds,ISR_OldS         ;; :
        int             21h                             ;; :

    ;; *********************************************
    ;; Restore the Keyboard Lights
    ;; *********************************************
        mov     al,0edh                 ;; Send Set/Reset Mode Indicator Command
    out     60h,al                  ;; : to the 8042

    mov     edx,00000497h           ;; Keyboard BIOS Flag Byte #1
    mov     ah,[edx]                ;; Fetch the LED Status
    and     ah,00000111b            ;; Clear all but the Lights

@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    mov     al,ah                   ;; Reset the Light Mode
    out     60h,al                  ;; :
@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :

    ret                         ;; Return to caller
kbdReset_       ENDP



;; *********************************************
;; int          kbdKeyHit()
;; RETURN:      0 if KeyBuffer is empty
;;          # Number of keys in buffer
;; *********************************************
kbdKeyHit_      PROC NEAR
    ;; *********************************************
        ;; Check to see if buffer is EMPTY
    ;; *********************************************
    movzx   eax,KeyHead         ;; Point to the HEAD of the buffer
    sub     al,KeyTail          ;; Subtract the TAIL from HEAD

IKHDone:                        ;; Ready to return to la-la land
        ret                                             ;; : so, off we go . . .
kbdKeyHit_      ENDP



kbdClearKeys_   PROC NEAR USES BX
        ;; *********************************************
        ;; Clear the buffer by setting TAIL on HEAD
        ;; *********************************************
        mov             bl,KeyHead
        mov     KeyTail,bl
        ret
kbdClearKeys_   ENDP



kbdPutKey_      PROC NEAR USES EBX EDX
        ;; *********************************************
        ;; Set RETURN code to -1 for KEY BUFFER FULL
        ;; *********************************************
        mov             eax,-1                                  ;; -1 ERROR CODE

        ;; *********************************************
        ;; Check to see if buffer is FULL
        ;; *********************************************
        movzx   ebx,KeyHead                             ;; Point to the front of the buffer
        inc     bl                                              ;; : and if the next space places
        cmp     bl,KeyTail                              ;; : us on the end of the buffer,
        jz              PKDone                                  ;; : then the buffer is full . . .
        dec     bl                                              ;; : otherwise, we help fill it.

        ;; *********************************************
        ;; Put key into KEYBOARD BUFFER (Adding scancode)
        ;; *********************************************
    mov     KeyBuffer[ebx],cl       ;; Save the ASCII Code
        inc     bl                                              ;; Increment the KeyHead
        mov     KeyHead,bl                              ;; : NOTE that it loops at bl==256
    xor     eax,eax                 ;; Clear the RETURN Code

PKDone:
        ret                                                     ;; Return to caller and all that stuff
kbdPutKey_  ENDP



kbdGetKey_      PROC NEAR USES EBX
        ;; *********************************************
        ;; Check to see if buffer is EMPTY
        ;; *********************************************
@@:     movzx   ebx,KeyTail                     ;; Point to the end of the buffer
        cmp     bl,KeyHead                              ;; : and if it is equal to the front,
        jz              @B                                              ;; : then the buffer is empty, so wait.

        ;; *********************************************
        ;; Get next key from KEYBOARD BUFFER
        ;; *********************************************
    movzx   eax,KeyBuffer[ebx]      ;; Fetch the ASCII Code
        inc     bl                                              ;; Increment the KeyTail
        mov     KeyTail,bl                              ;; : NOTE that it loops at bl==256

GKDone:
        ret                                                     ;; Return to caller and all that stuff
kbdGetKey_  ENDP



kbdSetNumLight_ PROC
    shl     al,1                    ;; Shift the ON/OFF bit to NUMLOCK bit
    mov     ah,kbdLights            ;; Copy the NUMLOCK Light Mode
    and     al,00000010b            ;; Clear all but the NUMLOCK Light Bit
    and     ah,11111101b            ;; Clear the NUMLOCK Light Bit
    or      ah,al                   ;; Set the NUMLOCK Bit appropriatly

    cli                             ;; An INT9 right now could be BAD!
    mov     al,0edh                 ;; Send Set/Reset Mode Indicator Command
    out     60h,al                  ;; : to the 8042

    mov     kbdLights,ah            ;; Update our Lights variable

@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    mov     al,ah                   ;; Send the new Light Mode
    out     60h,al                  ;; :
@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    sti                             ;; An INT9 here would be hunkey dorey!

    ret                             ;; Return to lala land
kbdSetNumLight_ ENDP



kbdSetCapLight_ PROC
    shl     al,2                    ;; Shift the ON/OFF bit to CAPLOCK bit
    mov     ah,kbdLights            ;; Copy the CAPLOCK Light Mode
    and     al,00000100b            ;; Clear all but the CAPLOCK Light Bit
    and     ah,11111011b            ;; Clear the CAPLOCK Light Bit
    or      ah,al                   ;; Set the CAPLOCK Bit appropriatly

    cli                             ;; An INT9 right now could be BAD!
    mov     al,0edh                 ;; Send Set/Reset Mode Indicator Command
    out     60h,al                  ;; : to the 8042

    mov     kbdLights,ah            ;; Update our Lights variable

@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    mov     al,ah                   ;; Send the new Light Mode
    out     60h,al                  ;; :
@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    sti                             ;; An INT9 here would be hunkey dorey!

    ret                             ;; Return to lala land
kbdSetCapLight_ ENDP



kbdSetScrlLight_        PROC
    mov     ah,kbdLights            ;; Copy the SCRLLOCK Light Mode
    and     al,00000001b            ;; Clear all but the SCRLLOCK Light Bit
    and     ah,11111110b            ;; Clear the SCRLLOCK Light Bit
    or      ah,al                   ;; Set the SCRLLOCK Bit appropriatly

    cli                             ;; An INT9 right now could be BAD!
    mov     al,0edh                 ;; Send Set/Reset Mode Indicator Command
    out     60h,al                  ;; : to the 8042

    mov     kbdLights,ah            ;; Update our Lights variable

@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    mov     al,ah                   ;; Send the new Light Mode
    out     60h,al                  ;; :
@@: in      al,60h                  ;; Wait for ACK from 8042
    cmp     al,0fah                 ;; :
    jnz     @B                      ;; :
    sti                             ;; An INT9 here would be hunkey dorey!

    ret                             ;; Return to lala land
kbdSetScrlLight_        ENDP

_TEXT           ENDS
                                END
