flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Read Keyboard 60h at BIOS early boot (SEC)

Author
Thread Post new topic Reply to topic
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 20 Feb 2024, 19:58
Hi
I'm trying to read the Keyboard at CPU startup stage. The controller seems acceptable as PC Speaker works (programmable) fine. What I need to initialize for my usb-keyboard at x99 platform? Have I do something to port 0x61 like setup external controller somehow? Or I need to initialize and force some usb redirection staff?
Post 20 Feb 2024, 19:58
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 980
Location: Russia
macomics 20 Feb 2024, 20:09
If the bios/efi usb keyboard is already working, then it will be accessed via port 60h/61h
Post 20 Feb 2024, 20:09
View user's profile Send private message Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 20 Feb 2024, 20:39
macomics wrote:
If the bios/efi usb keyboard is already working, then it will be accessed via port 60h/61h

I'm not sure that is working as nothing initialized yet. The port 61h seems to deal with initialization of external keyboard controller. Can you show some example of that process?
Post 20 Feb 2024, 20:39
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 980
Location: Russia
macomics 20 Feb 2024, 22:19
Here is interrupt handling code from the keyboard:
Code:
int09h:
        push    ax
        push    dx
        push    cx

    ; receive char
        in      al, 60h
        mov     dl, al

    ; signal to i8042 - received
        in      al, 61h
        mov     ah, al
        or      al, 80h
        out     61h, al

    ; nanosleep
        mov     cx, 2000

  @@:
        xor     al, al
        nop
        xor     al, ah
        loop    @b

    ; clear signal
        out     61h, al

    ; save char from dl
...

    ; clear i8259.01
        mov     al, 20h
        out     20h, al
        pop     cx
        pop     dx
        pop     ax
        iret    


Here is the output of the command to adjust the keyboard (repeat rate, delay):
Code:
set_rate_and_delay:
; al = 0 ~ 30.0 char per sec, 1 ~ 26.7 cps, 2 ~ 24.0 cps, 4 ~ 20 cps, 8 ~ 15 cps, 10 ~ 10 cps, 13 ~ 9.5 cps, 16 ~ 7.5 cps, 20 ~ 5.0 cps, 31 ~ 2.0 cps
; ah = 0 ~ 250 ms, 1 ~ 500 ms, 2 ~ 750 ms, 3 ~ 1000 ms
        push    cx
        and     ax, 0000001100011111b
        shl     ah, 5
        or      ah, al
        mov     al, 0F3h
        out     64h, al
        mov     cx, 20000

  @@:
        xor     al, al
        nop
        xor     al, ah
        loop    @b
        out     64h, al
        pop     cx
        retn    


Description:
Filesize: 11.36 KB
Viewed: 2507 Time(s)

Screenshot_20240221_011822.png


Post 20 Feb 2024, 22:19
View user's profile Send private message Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 21 Feb 2024, 07:54
Nothing
Bit 7 is always set

I tried to send 0xF4 to 0x60 and 0xAE to 0x64 too

Reading this description:
https://bochs.sourceforge.io/techspec/PORTS.LST
and this
https://www.tek-tips.com/viewthread.cfm?qid=258828
Confused. Seems it's not redirected from usb yet but system wakes up by key pressing
Post 21 Feb 2024, 07:54
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 980
Location: Russia
macomics 21 Feb 2024, 08:10
Try to put 0F4h command to 64h port to turn on keyboard.
Post 21 Feb 2024, 08:10
View user's profile Send private message Reply with quote
Feryno



Joined: 23 Mar 2005
Posts: 509
Location: Czech republic, Slovak republic
Feryno 23 Feb 2024, 10:26
I did this decades ago, it worked on real hardware with PS/2 keyboard. Certainly not for USB keyboard. Note - maybe you should improve delay loops as current CPUs are much faster and execute that delay loops too fast?

Code:
;*********************************************
; Keyboard controller 8042 stuff
;
;*********************************************

;=============================================
; 60h   READ/WR ==> 8042 Data port
; 64h   WRITE   ==> 8042 Comand port
; 64h   READ    ==> 8042 Status port
;=============================================

KBD_8042_PORT_DATA      =       60h
KBD_8042_PORT_CONTROL_B =       61h
KBD_8042_PORT_CMD       =       64h
KBD_8042_PORT_STATUS    =       64h

;---------------------------
; Status register bits
;---------------------------
KBD_8042_STATUS_PERR    =       1 shl 7 ; PARITY Error in keyboard data
KBD_8042_STATUS_TO      =       1 shl 6 ; Timeout for Rx or Tx
KBD_8042_STATUS_MOBF    =       1 shl 5 ; Mouse Output Buffer Full
KBD_8042_STATUS_INH     =       1 shl 4 ; Keyboard communication INHIBITED
KBD_8042_STATUS_A2      =       1 shl 3 ; Port last written: 0=60h , 1=64h
KBD_8042_STATUS_SYS     =       1 shl 2 ; Sys reset type: 0=cold, 1=warm
KBD_8042_STATUS_IBF     =       1 shl 1 ; Input Buffer full CPU  -> 8042
KBD_8042_STATUS_OBF     =       1 shl 0 ; Output Buffer Full 8042 -> CPU


align 16
init_ps2:
; out:  CF=0    success
;       CF=1    failure
        push    rax

        call    keyb_empty
        jc      init_ps2_epi

; Values for keyboard controller commands (data goes to PORT 0060h):
; Value         Description
; 20h   read    read byte zero of internal RAM, this is the last KB command sent to the 8041/8042
; 21-3F read    reads the byte specified in the lower 5 bits of the command
; 60-7F double  writes the data byte to the address specified in the 5 lower bits of the command in the 804x's internal RAM
        mov     al,20h                  ; read byte zero of internal RAM, this is the last KB command sent to the 8041/8042
        out     64h,al
; port 0060  RW  KB controller data port or keyboard input buffer (ISA, EISA) should only be read from after status port bit0 = 1
        call    keyb_wait_read          ; wait for ready to read
        jc      init_ps2_epi
        in      al,60h                  ; read byte zero of internal RAM
;Bit(s) Description
; 7     reserved (0)
; 6     IBM PC compatibility mode
; 5     IBM PC mode - no parity, no stop bits, no translation
;       (PS/2) force mouse clock low
; 4     disable keyboard (clock)
; 3     (AT) inhibit override - ignore keyboard lock switch
;       (PS/2) reserved
; 2     system flag
; 1     (AT) reserved (0)
;       (PS/2) enable mouse output buffer full interrupt (IRQ12)
; 0     enable output buffer full interrupt (IRQ1)

; mask the byte to disable keyboard and to force mouse clock low
        or      al,00110000b            ; set bits
; disable IBM PC compatibility mode, disable mouse output buffer full interrupt (IRQ12), disable output buffer full interrupt (IRQ1)
        and     al,10111000b            ; Enable AUX (instead of sending A8 command)
        mov     ah,al                   ; and save the byte to be written later

        call    keyb_wait_write         ; ?? is it really necessary? it is necessary before writing into port 60h. But what with port 64h ?
                                        ; anyway, short delay isn't dangerous anytime
        jc      init_ps2_epi
        mov     al,60h
        out     64h,al
        call    keyb_wait_write
        jc      init_ps2_epi
        mov     al,ah
        out     60h,al                  ; write the zero byte of internal RAM finally

        clc

init_ps2_epi:
        pop     rax
        ret

align 16
init_ps2_keyboard:
        push    rax

        call    keyb_empty
        jc      init_ps2_keyboard_epi

; Values for keyboard controller commands (data goes to PORT 0060h):
; Value         Description
; 20h   read    read byte zero of internal RAM, this is the last KB command sent to the 8041/8042
; 21-3F read    reads the byte specified in the lower 5 bits of the command
; 60-7F double  writes the data byte to the address specified in the 5 lower bits of the command in the 804x's internal RAM
        mov     al,20h                  ; read byte zero of internal RAM, this is the last KB command sent to the 8041/8042
        out     64h,al
; port 0060  RW  KB controller data port or keyboard input buffer (ISA, EISA) should only be read from after status port bit0 = 1
        call    keyb_wait_read          ; wait for ready to read
        jc      init_ps2_keyboard_epi
        in      al,60h                  ; read byte zero of internal RAM
;Bit(s) Description
; 7     reserved (0)
; 6     IBM PC compatibility mode
; 5     IBM PC mode - no parity, no stop bits, no translation
;       (PS/2) force mouse clock low
; 4     disable keyboard (clock)
; 3     (AT) inhibit override - ignore keyboard lock switch
;       (PS/2) reserved
; 2     system flag
; 1     (AT) reserved (0)
;       (PS/2) enable mouse output buffer full interrupt (IRQ12)
; 0     enable output buffer full interrupt (IRQ1)

; mask the byte to enable translation (bit 6.) and to enable 8042 to generate IRQ1 (bit 0.)
        or      al,01000001b
; mask the byte to enable keyboard clock
        and     al,11101111b
        mov     ah,al                   ; and save the byte to be written later

        call    keyb_wait_write         ; ?? is it really necessary? it is necessary before writing into port 60h. But what with port 64h ?
                                        ; anyway, short delay doesn't hurt anytime
        jc      init_ps2_keyboard_epi
        mov     al,60h
        out     64h,al
        call    keyb_wait_write
        jc      init_ps2_keyboard_epi
        mov     al,ah
        out     60h,al                  ; enable keyboard IRQ finally

;       clc                             ; unnecessary, CF is set/cleared from last keyb_wait_write

init_ps2_keyboard_epi:
        pop     rax
        ret


align 16
keyb_empty:
; This routine checks that the keyboard command queue is empty (after emptying the output buffers).
; It is used by all commands send to 8042. It deals with the 8042 chip whitch is used as a keyboard controller in PCs. Also used as a PS/2 mouse controller on the AUX port.
        push    rax rcx
        mov     ecx,10000h      ; time out value

; output buffer (CPU reads data from 8042 output buffer)
keyb_empty_L0:
        in      al,64h          ; read 8042 status port
        test    al,00000001b    ; test output buffer full flag (bit 0)
                                ; output buffer full (output 60h has data for system)
                                ; bit is cleared after read access
        setz    ah
        jz      keyb_empty_L4

; there is something in output buffer, so read it
        in      al,60h
        loopnz  keyb_empty_L0
        mov     al,0            ; assume input buffer full
        jrcxz   keyb_empty_L6

; input buffer (CPU writes data into 8042 input buffer)
keyb_empty_L3:
        in      al,64h          ; read 8042 status port
keyb_empty_L4:
        test    al,00000010b    ; test input buffer full flag (bit 1)
                                ; input buffer full (input 60/64 has data for 8042)
                                ; no write access allowed until bit clears
        loopnz  keyb_empty_L3
        setz    al
keyb_empty_L6:
        and     al,ah           ; both results AL=AH=1=success ?
                                ; if one of them = 0 (failure) then the whole result is failure
        sub     ah,1            ; set / clear CarryFlag

        pop     rcx rax
        ret

align 16
keyb_wait_read:
; This routine waits for the 8042 output buffer to become full, so then CPU is allowed to read data from it.
;0060  RW  KB controller data port or keyboard input buffer (ISA, EISA) should only be read from after status port bit0 = 1
; in:   none
; out:  CF=0 output buffer full
;       CF=1 time out, 8042 output buffer empty (nothing to read from it)
; Special note !!!
; Disabling interrupts are strongly necessary before calling this routine,
; so use CLI instruction before calling the routine!
        push    rax rcx
        mov     ecx,10000h      ; time out value
keyb_wait_read_L0:
        in      al,64h          ; read 8042 status port
        test    al,00000001b    ; test output buffer full flag (bit 0)
                                ; output buffer full (output 60h has data for system)
                                ; bit is cleared after read access
        loopz   keyb_wait_read_L0       ; loop until buffer empty or time out
        setnz   al
        sub     al,1                    ; this clears or sets CF
        pop     rcx rax
        ret

align 16
keyb_wait_write:
; This routine waits for the 8042 input buffer to empty.
;0060  RW  KB controller data port or keyboard input buffer (ISA, EISA) should only be written to if status port bit1 = 0
; in:   none
; out:  CF=0 input buffer empty
;       CF=1 time out, 8042 input buffer full
; Special note !!!
; Disabling interrupts are strongly necessary before calling this routine,
; so use CLI instruction before calling the routine!
        push    rax rcx
        mov     ecx,10000h      ; time out value
keyb_wait_write_L0:
        in      al,64h          ; read 8042 status port
        test    al,00000010b    ; test input buffer full flag (bit 1)
                                ; input buffer full (input 60/64 has data for 8042)
                                ; no write access allowed until bit clears
        loopnz  keyb_wait_write_L0      ; loop until buffer empty or time out
        setz    al
        sub     al,1                    ; this clears or sets CF
        pop     rcx rax
        ret

align 16
keyb_wait_read_ack:
; This routine waits for the 8042 output buffer to become full, so then we read data from it and check whether it is ACK response (answer).
; in:   none
; out:  CF=0 input buffer empty and ACK read
;       CF=1 time out or 8042 output buffer full or no ACK
; Special note !!!
; Disabling interrupts are strongly necessary before calling this routine,
; so use CLI instruction before calling the routine!
        push    rax
        call    keyb_wait_read
        jc      keyb_wait_read_ack_epi
        in      al,60h
        cmp     al,0FAh
        setz    al
; better way is to check 0FEh (resend last mouse data answer) so after return from this procedure its caller can repeat the command...
; .........

        sub     al,1                    ; this clears or sets CF
keyb_wait_read_ack_epi:
        pop     rax
        ret    
Post 23 Feb 2024, 10:26
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 23 Feb 2024, 12:29
Seems like usb-Keyboard initializing at DXE stage:
https://github.com/open-estuary/uefi/blob/master/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
Seems I need to enumerate devices then blah blah blah, too difficult at the moment.

Is there some simple way to read at least PowerButton status? Or maybe PCH fault status? (counter of faulty startups)
All I want to do is to skip my Overclocking Driver (SEC) if something wrong or user prefer to skip it. I need to get some feedback from user or system no matter how.
Post 23 Feb 2024, 12:29
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 25 Feb 2024, 01:12
Ok, thanks to datasheet the Power Button is easily readable at least for x99 chipset
Code:
checkbutton:
        mov     eax,(00 shl 16) or\     ;Bus
                (31 shl 11) or\         ;Device
                (0 shl 8) or\           ;Function
                0xA0 or\                ;Offset
                0x80000000              ;Enable bit
        mov     ecx,0xFFFF
        mov     dx,0xCF8
        out     dx,eax
        in      eax,dx
        test    eax,0x80000000
        jz      skipjob
        mov     dx,0xCFC
        .timeout:
                in      ax,dx
                test    ax,1 shl 9
                jnz     startjob
                loop    .timeout
skipjob:    

My task is resolved but I'll keep looking for usb-solution too. Thanks mates
Post 25 Feb 2024, 01:12
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.