flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > Read Keyboard 60h at BIOS early boot (SEC) |
Author |
|
macomics 20 Feb 2024, 20:09
If the bios/efi usb keyboard is already working, then it will be accessed via port 60h/61h
|
|||
20 Feb 2024, 20:09 |
|
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? |
|||
20 Feb 2024, 20:39 |
|
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
|
||||||||||
20 Feb 2024, 22:19 |
|
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 |
|||
21 Feb 2024, 07:54 |
|
macomics 21 Feb 2024, 08:10
Try to put 0F4h command to 64h port to turn on keyboard.
|
|||
21 Feb 2024, 08:10 |
|
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 |
|||
23 Feb 2024, 10:26 |
|
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. |
|||
23 Feb 2024, 12:29 |
|
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 |
|||
25 Feb 2024, 01:12 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.