flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Trying to turn on leds in windows or real mode(at bootstrap)

Author
Thread Post new topic Reply to topic
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
Hi all.

I'd read a lot of about 8042 microcontroller. This because I'm making my
own bootloader and I need understand on how to enable a20 gate. But,
before I try to enable the a20 gate, I'm trying something more simple,
IMHO, i.e., trying to turn on all led indicators.

But I have few questions:
Is the 8042 INSIDE the keyboard case?
When I make a comand to 60h, the command is received by 8042?
When I make a command to 64h, the command is received by motherboard onboard microcontroller?

reference: http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_20/CH20-1.html#HEADING1-5

Also, the following code is my attempt to turn on leds in windows or
real mode (in my bootloader). It doesn't works. Can someone help me?

In the case of testing the code in my boot loader, I just include the
code via inc directive after my "Hello Word" message.

I already read other articles in the forum about enable keyboard leds and already try them, but without success.

note: I have a notebook. But I think that this does not change anything.

Ah, a last question: How I can do something like this in fasm:
KB_ALL_LEDS equ KB_CAPS_LOCK | KB_NUM_LOCK | KB_SCROLL_LOCK

Code:
; Turn on all leds of the keyboard.

ORG 0x100 ; Remove it in case of it is placed in bootloader.

turnOnLeds:
        ;This subroutine will turn on led indicators in the keyboard controller.
        ;Takes no arguments. Returns 0 in AX register on success, -1 on failure.
        ;Written for use in 16-bit code.

; Status Register
STATUS_PORT equ 0x64
KBD_OUT_BUF equ 0x60

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Symbolic constants definition

; Status Register Bits Names
SR_BIT0_OUTPUT_BUFFER    equ 0 ; 0->has no data for system; 1->has data for system
SR_BIT1_INPUT_BUFFER     equ 1 ; 0->has no data for 8042; 1-> has data for 8042
SR_BIT2_SYSTEM_FLAG      equ 2 ; system flag (set to 0 after power on reset)
SR_BIT3_COMMAND_DATA     equ 3 ; type of information in input register. 1->command; 0->data
SR_BIT4_ENABLED_DISABLED equ 4 ; 1->keyboard enabled; 2-> keyboard disabled (via switch)
SR_BIT5_TRANSMIT_TIMEOUT equ 5 ; 1->transmit timeout
SR_BIT6_RECEIVE_TIMEOUT  equ 6 ; 1-> receive timeout
SR_BIT7_PARITY           equ 7 ; 1-> even parity; 0->odd parity

; Keyboard Commands
KB_LED_CMD equ 0xED

; Keyboard Led Indicators
KB_CAPS_LOCK    equ 001b
KB_NUM_LOCK     equ 010b
KB_SCROLL_LOCK  equ 101b
;KB_ALL_LEDS     equ KB_CAPS_LOCK | KB_NUM_LOCK | KB_SCROLL_LOCK
KB_ALL_LEDS     equ 111b
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

pusha                           ; Pushes the contents of the general-purpuse registers
                                ; onto the stack following order: AX, CX, DX, BX, BP, SP
                                ; (original value), BP, SI and DI. The value pushed for
                                ; the SP register is its value before prior to pushing
                                ; the first register.

cli                             ; Disable interrupts

; Wait for the keyboard controller to be ready for a command
xor ax,ax                       ; Clear ax
.commandWait1:
in   al,STATUS_PORT              ; Reads the 8042 status register
bt   ax,SR_BIT1_INPUT_BUFFER     ; Test if command buffer is full
jc   .commandWait1               ; Input buffer is full. Try again.

mov  al,KB_LED_CMD               ; Tell 8042 we wanna change the LEDs
out  KBD_OUT_BUF,al              ; Send the command

.wait:
xor  ax,ax
in   al,STATUS_PORT
bt   ax,SR_BIT1_INPUT_BUFFER     ; Test if command came through
jc   .wait

xor  ax,ax
mov  al,KB_ALL_LEDS              ; Tell 8042 the option byte
out  KBD_OUT_BUF,al              ; Set all LED's to ON

sti                             ; Re-enable interrupts

popa                            ; Pops words from the stack into the general-purpose
                                ; registers. The registers are loaded in the following
                                ; order: DI, SI, BP, BX, DX, CX and AX. The value on
                                ; the stack for the SP register is ignored. Instead,
                                ; the SP register is incremented after each register
                                ; is loaded.

ret

;------------------------------------------------------------;
; keyboard wait                                              ;
; Wait for the keyboard controller to be ready for a command ;
;------------------------------------------------------------;
;.kbd_wait:
;jmp  $+2
;in   al,STATUS_PORT
;test al,1
;jz   .ok
;jmp  $+2
;in   al,KBD_OUT_BUF
;jmp  .kbd_wait

;.ok:
;test al,2
;jnz  .kbd_wait
;ret
    


Thx in advance.

Best regards,
Marco Alves.
Post 21 Jun 2006, 14:27
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
This is my function fot turn leds on/off
Code:
;====================================================;; Set keyboard leds                                  ;;====================================================;SetKeyBoardLeds:        push  eax        mov   al,0xed        out   60h,alKeyBoardWait:        in    al,64h        test  al,10b        jne   KeyBoardWait        mov   al,byte [keyBoardStatus]  ;put 7 in this var        and   al,111b        out   60h,al        pop   eax        ret    

Note: if your talking XP, then alot of direct hardware stuff does not work, should be ok in win98 or boot code.

PS: bubach site is a goldmine of doc and code snips, on all OS topics including keyboards
http://bos.asmhackers.net/docs/keyboard/
Post 21 Jun 2006, 15:15
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
Dex4u:

I'd tested your code. But with no success. The entirely code (including
your keyboard leds code) follows:

Code:
include 'include/boot_image.asm'

Boot_Sector:
use16       ; We need 16-bit intructions for Real Mode

ORG 0x7C00  ; The BIOS loads the boot sector into this memory location

; Main program
main:


mov ax,0x0000        ; Setup the Data Segment register
                     ; Location of data in DS:Offset
mov ds,ax            ; This can not be loaded directly. Is has to be in two steps.
                     ; "mov ds,0x0000" will NOT work due to limitations on CPU.
mov si,HelloWorld    ; Load the string into position for the procedure.

call PutStr          ; Run the procedure

keyBoardStatus db 0;

call SetKeyBoardLeds
;====================================================;
; Set keyboard leds                                  ;
;====================================================;


SetKeyBoardLeds:
        push  eax
        mov   al,0xed
        out   60h,al

KeyBoardWait:
        in    al,64h
        test  al,10b
        jne   KeyBoardWait
        mov   al,byte [keyBoardStatus]  ;put 7 in this var
        and   al,111b
        out   60h,al
        pop   eax
        ret

;Procedures
PutStr:              ; Set up the register for the interrupt call

mov ah,0x0E          ; The function to display a character
mov bh,0x00          ; Page number
mov bl,0x07          ; Normal attribute

;****************************************************************************************
nextchar:       ; Internal label (needed to loop round for the next character)
lodsb           ; I think of this as LOaD String Block

;Check for end of string '0'. The or instruction in this context is just to
;put 0 or 1 on ZF (zero flag). If is the end of string, put 1, 0 otherwise.
or al,al

jz return       ; If the zero flag has been set go to the end of the procedure.
                ; Zero flag gets set when an instruction returns 0 as the answer.

int 10h ; Run the BIOS video interrupt

jmp nextchar    ; Loop back round to the top
;****************************************************************************************

;****************************************************************************************
return:         ; Label at the end to jump when complete
ret             ; Return to main program
;****************************************************************************************

; Data

HelloWorld db 'Hello World',13,10,0

; End matter
times 510-($-$$) db 0 ; Boot loader MUST have 512 bytes long.
dw 0xAA55         ; Boot loader signature
    


What is wrong?
Post 21 Jun 2006, 15:51
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
I have tested the code and this is the fixed ver
Code:
include 'include/boot_image.asm'Boot_Sector:use16       ; We need 16-bit intructions for Real ModeORG 0x7C00  ; The BIOS loads the boot sector into this memory location; Main programmain:mov ax,0x0000        ; Setup the Data Segment register                     ; Location of data in DS:Offsetmov ds,ax            ; This can not be loaded directly. Is has to be in two steps.                     ; "mov ds,0x0000" will NOT work due to limitations on CPU.mov si,HelloWorld    ; Load the string into position for the procedure.call PutStr          ; Run the proceduremov [keyBoardStatus],7 ;***** you did not put 7 in var *****call SetKeyBoardLedsjmp $  ;***** you did not put this to stop the codekeyBoardStatus db 0  ;**** you put this in the wrong place.;====================================================;; Set keyboard leds                                  ;;====================================================;SetKeyBoardLeds:        push  ax        mov   al,0xed        out   60h,alKeyBoardWait:        in    al,64h        test  al,10b        jne   KeyBoardWait        mov   al,byte [keyBoardStatus]  ;put 7 in this var        and   al,111b        out   60h,al        pop   ax        ret;ProceduresPutStr:              ; Set up the register for the interrupt callmov ah,0x0E          ; The function to display a charactermov bh,0x00          ; Page numbermov bl,0x07          ; Normal attribute;****************************************************************************************nextchar:       ; Internal label (needed to loop round for the next character)lodsb           ; I think of this as LOaD String Block;Check for end of string '0'. The or instruction in this context is just to;put 0 or 1 on ZF (zero flag). If is the end of string, put 1, 0 otherwise.or al,aljz return       ; If the zero flag has been set go to the end of the procedure.                ; Zero flag gets set when an instruction returns 0 as the answer.int 10h ; Run the BIOS video interruptjmp nextchar    ; Loop back round to the top;****************************************************************************************;****************************************************************************************return:         ; Label at the end to jump when completeret             ; Return to main program;****************************************************************************************; DataHelloWorld db 'Hello World',13,10,0; End mattertimes 510-($-$$) db 0 ; Boot loader MUST have 512 bytes long.dw 0xAA55    


Note the fixed ver works on my PC, i taken out the boot_image.asm as i did not have it when testing and i used rawrite to put it on disk.
The led function worked fine.
Post 21 Jun 2006, 16:35
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
It didn't work for me. I don't know what's happening.

The boot_image.asm is attached, so you can test with it. Just put it on top of your code and assemble it. No need to use rawwrite.

Ah, how I can put my boot.bin into a floppy image using rawwrite?

Thx in advance.

Best regards,
Marco Alves.


Description:
Download
Filename: boot_image.asm
Filesize: 10.21 KB
Downloaded: 85 Time(s)

Post 21 Jun 2006, 17:36
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
That code is for cd i have no CD-R/RW to test, but my code above is tested on floppy and works on 10 test PC.
I made you a floppy image of my code, if you have burn software click on the make bootable and point it to that image.
as for rawrite (included) just click on it and follow whats on screen, but needs a floppy drive.


Description:
Download
Filename: boot.zip
Filesize: 18.88 KB
Downloaded: 74 Time(s)

Post 21 Jun 2006, 18:15
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
Dex4u, I get it!

boot.asm:
Code:
;include 'include/boot_image.asm'

use16       ; We need 16-bit intructions for Real Mode
ORG 0x7C00  ; The BIOS loads the boot sector into this memory location

Boot_Sector: jmp     near main
             nop

;------------------------------------------;
;  Standard BIOS Parameter Block, "BPB".   ;
;------------------------------------------;
          bpbOEM          db  'BOS 0.04'
          bpbSectSize     dw  512
          bpbClustSize    db  1
          bpbReservedSec  dw  1
          bpbFats         db  2
          bpbRootSize     dw  224
          bpbTotalSect    dw  2880
          bpbMedia        db  240
          bpbFatSize      dw  9
          bpbTrackSect    dw  18
          bpbHeads        dw  2
          bpbHiddenSect   dd  0
          bpbLargeSect    dd  0
     ;---------------------------------;
     ;  extended BPB for FAT12/FAT16   ;
     ;---------------------------------;
          bpbDriveNo      db  0
          bpbReserved     db  0
          bpbSignature    db  41                      ; 0 = nothing more. 41 = three more (below)..
          bpbID           dd  1
          bpbVolumeLabel  db  'BOOT FLOPPY'
          bpbFileSystem   db  'FAT12   '

; Main program
main:
mov ax,0x0000           ; Setup the Data Segment register
                        ; Location of data in DS:Offset
mov ds,ax               ; This can not be loaded directly. Is has to be in two steps.
                        ; "mov ds,0x0000" will NOT work due to limitations on CPU.
mov si,HelloWorld       ; Load the string into position for the procedure.

call PutStr             ; Run the procedure
call TurnOnLeds

include 'KeyBoard/TurnOnLeds.asm'

jmp $                   ; Never ending loop


;Procedures
PutStr:                 ; Set up the register for the interrupt call

mov ah,0x0E             ; The function to display a character
mov bh,0x00             ; Page number
mov bl,0x07             ; Normal attribute

;****************************************************************************************
nextchar:       ; Internal label (needed to loop round for the next character)
lodsb           ; I think of this as LOaD String Block

;Check for end of string '0'. The or instruction in this context is just to
;put 0 or 1 on ZF (zero flag). If is the end of string, put 1, 0 otherwise.
or al,al

jz return       ; If the zero flag has been set go to the end of the procedure.
                ; Zero flag gets set when an instruction returns 0 as the answer.

int 10h ; Run the BIOS video interrupt

jmp nextchar    ; Loop back round to the top
;****************************************************************************************

;****************************************************************************************
return:         ; Label at the end to jump when complete
ret             ; Return to main program
;****************************************************************************************

; Data
HelloWorld db 'Hello World',13,10,0

; End matter
times 510-($-$$) db 0 ; Boot loader MUST have 512 bytes long.
dw 0xAA55
    


TurnOnLeds.asm:
Code:
; Turn on all leds of the keyboard.

TurnOnLeds:
        ;This subroutine will turn on led indicators in the keyboard controller.
        ;Takes no arguments.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 8042 Definitions

; Status Register
STATUS_PORT equ 0x64
KBD_OUT_BUF equ 0x60

; Status Register Bits Names
SR_BIT0_OUTPUT_BUFFER    equ 0 ; 0->has no data for system; 1->has data for system
SR_BIT1_INPUT_BUFFER     equ 1 ; 0->has no data for 8042; 1-> has data for 8042
SR_BIT2_SYSTEM_FLAG      equ 2 ; system flag (set to 0 after power on reset)
SR_BIT3_COMMAND_DATA     equ 3 ; type of information in input register. 1->command; 0->data
SR_BIT4_ENABLED_DISABLED equ 4 ; 1->keyboard enabled; 2-> keyboard disabled (via switch)
SR_BIT5_TRANSMIT_TIMEOUT equ 5 ; 1->transmit timeout
SR_BIT6_RECEIVE_TIMEOUT  equ 6 ; 1-> receive timeout
SR_BIT7_PARITY           equ 7 ; 1-> even parity; 0->odd parity

; Keyboard Commands
KB_LED_CMD equ 0xED

; Keyboard Led Indicators
KB_CAPS_LOCK    equ 001b
KB_NUM_LOCK     equ 010b
KB_SCROLL_LOCK  equ 101b
;KB_ALL_LEDS     equ KB_CAPS_LOCK | KB_NUM_LOCK | KB_SCROLL_LOCK
KB_ALL_LEDS     equ 111b
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

pusha                           ; Pushes the contents of the general-purpuse registers
                                ; onto the stack following order: AX, CX, DX, BX, BP, SP
                                ; (original value), BP, SI and DI. The value pushed for
                                ; the SP register is its value before prior to pushing
                                ; the first register.

cli                             ; Disable interrupts

xor ax,ax                       ; Clear ax
call .kbd_wait                  ; Wait for the keyboard controller to be ready for a command

mov al,KB_LED_CMD               ; Tell 8042 we wanna change the LEDs
out KBD_OUT_BUF,al              ; Send the command

xor ax,ax
call .kbd_wait

xor ax,ax
mov al,KB_ALL_LEDS              ; Tell 8042 the option byte
out KBD_OUT_BUF,al              ; Set all LED's to ON

sti                             ; Re-enable interrupts

popa                            ; Pops words from the stack into the general-purpose
                                ; registers. The registers are loaded in the following
                                ; order: DI, SI, BP, BX, DX, CX and AX. The value on
                                ; the stack for the SP register is ignored. Instead,
                                ; the SP register is incremented after each register
                                ; is loaded.

ret

;------------------------------------------------------------;
; keyboard wait                                              ;
; Wait for the keyboard controller to be ready for a command ;
;------------------------------------------------------------;
.kbd_wait:
in   al,STATUS_PORT             ; Reads the 8042 status register
bt   ax,SR_BIT1_INPUT_BUFFER    ; Test if command buffer is full
jc   .kbd_wait                  ; Input buffer is full. Try again.

ret
    
Post 22 Jun 2006, 12:29
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
One thing you do, that you should watch, is put stuff in the functions, that should be put separated eg: this would be better.
Code:
; Turn on all leds of the keyboard.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8042 Definitions; Status RegisterSTATUS_PORT equ 0x64KBD_OUT_BUF equ 0x60; Status Register Bits NamesSR_BIT0_OUTPUT_BUFFER    equ 0 ; 0->has no data for system; 1->has data for systemSR_BIT1_INPUT_BUFFER     equ 1 ; 0->has no data for 8042; 1-> has data for 8042SR_BIT2_SYSTEM_FLAG      equ 2 ; system flag (set to 0 after power on reset)SR_BIT3_COMMAND_DATA     equ 3 ; type of information in input register. 1->command; 0->dataSR_BIT4_ENABLED_DISABLED equ 4 ; 1->keyboard enabled; 2-> keyboard disabled (via switch)SR_BIT5_TRANSMIT_TIMEOUT equ 5 ; 1->transmit timeoutSR_BIT6_RECEIVE_TIMEOUT  equ 6 ; 1-> receive timeoutSR_BIT7_PARITY           equ 7 ; 1-> even parity; 0->odd parity; Keyboard CommandsKB_LED_CMD equ 0xED; Keyboard Led IndicatorsKB_CAPS_LOCK    equ 001bKB_NUM_LOCK     equ 010bKB_SCROLL_LOCK  equ 101b;KB_ALL_LEDS     equ KB_CAPS_LOCK | KB_NUM_LOCK | KB_SCROLL_LOCKKB_ALL_LEDS     equ 111b;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;TurnOnLeds:        ;This subroutine will turn on led indicators in the keyboard controller.        ;Takes no arguments.pusha                           ; Pushes the contents of the general-purpuse registers                                ; onto the stack following order: AX, CX, DX, BX, BP, SP                                ; (original value), BP, SI and DI. The value pushed for                                ; the SP register is its value before prior to pushing                                ; the first register.cli                             ; Disable interruptsxor ax,ax                       ; Clear axcall .kbd_wait                  ; Wait for the keyboard controller to be ready for a commandmov al,KB_LED_CMD               ; Tell 8042 we wanna change the LEDsout KBD_OUT_BUF,al              ; Send the commandxor ax,axcall .kbd_waitxor ax,axmov al,KB_ALL_LEDS              ; Tell 8042 the option byteout KBD_OUT_BUF,al              ; Set all LED's to ONsti                             ; Re-enable interruptspopa                            ; Pops words from the stack into the general-purpose                                ; registers. The registers are loaded in the following                                ; order: DI, SI, BP, BX, DX, CX and AX. The value on                                ; the stack for the SP register is ignored. Instead,                                ; the SP register is incremented after each register                                ; is loaded.ret;------------------------------------------------------------;; keyboard wait                                              ;; Wait for the keyboard controller to be ready for a command ;;------------------------------------------------------------;.kbd_wait:in   al,STATUS_PORT             ; Reads the 8042 status registerbt   ax,SR_BIT1_INPUT_BUFFER    ; Test if command buffer is fulljc   .kbd_wait                  ; Input buffer is full. Try again.ret    
Post 22 Jun 2006, 15:33
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
Ah, ok. thx a lot. I'm very happy. It's my first own asm code. hehe Smile.

Ah, just more one question:

How I can do something like this:

Code:
KB_ALL_LEDS     equ KB_CAPS_LOCK | KB_NUM_LOCK | KB_SCROLL_LOCK
    


thx in advance.
Marco Alves.
Post 22 Jun 2006, 16:55
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
Well done Smile, try this:
Code:
; Keyboard Led IndicatorsKB_CAPS_LOCK    equ 00000001bKB_NUM_LOCK     equ 00000010bKB_SCROLL_LOCK  equ 00000101bKB_ALL_LEDS     equ KB_CAPS_LOCK or KB_NUM_LOCK or KB_SCROLL_LOCK    
Post 22 Jun 2006, 17:47
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
It works fine. Hey, can I add you to my msn?
Post 23 Jun 2006, 12:23
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
You could if i used it Wink, you may find members of 'Dex4u team' on IRC here:
http://jas2o.forthworks.com/?p=dex4u
But i do not go on much.
Post 23 Jun 2006, 13:52
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
Ah. I made a A20 gate enabler.
It works fine in my notebook. I can't believe! hee. In last month I
do not know anything about asm nor computer architecture (a20 gate?
what's that?) hehe. And today I have a a20 gate write by my own.
It's incredible!

All was written by me! uhauha

A20 gate enabler:
Code:
include 'Keyboard/Keyboard.asm'

KB_A20_GATE equ 00000010b

enableA20:
;Enables A20 gate.

;The main steps to enable A20 gate follows:
;1-Push all registers onto stack (pusha)
;2-Disable interrupts (cli)
;3-Verify if the keyboard is ready to receive a command (through 64h. bit 1 of status register must be 0)
;4-Read output port (D0 command via 64h.
                    ;Wen we do this, the controller will read its output port and
                    ;place the data in its output buffer)
;5-Wait for the controller to be ready with a byte of data (through 64h. bit 0 of status register must be 1)
;6-Read 8042 output buffer (considering the context, will be the 8042 output port)
;7-Or"s" this value with 00000010b (the 2nd bit is the A20 gate)
;8-Verify if the keyboard is ready to receive a command (see step 3)
;9-Tell 8042 we wanna enable A20 (D1 command via 64h)
;10-Wait for the controller to be ready for the data we going to send (bit 1 of status register must be 0)
;11-Send the value obtained in step 7 to 8042 output port (through 60h)

;The normal behavior implies that at this point the A20 gate will be already enabled.
;So we'll check if this is true.

;12-Verify if the keyboard is ready to receive a command (see step 3)
;13-Read output port (see step 4)
;14-Wait for the controller to be ready with a byte of data (see step 5)
;15-Read 8042 output buffer (see step 6)
;16-Use bt instruction to verify if bit 1 of output port is enabled. (if CF equals 1 it's enabled)
;17-push all registers from stack
;18-Re-enable interrputs
;19-Store 1 in al if success. Otherwise, 0.

popa                            ; Step 1
cli                             ; Step 2

mov cx,5                        ; Number of tries.

.startIt:
call .kbd_wait                  ; Step 3

mov al,KB_READ_OUTPUT_PORT      ; Step 4
out STATUS_PORT,al

call .kbd_output_buffer_empty   ; Step 5

in al,KBD_OUT_BUF               ; Step 6

or al,KB_A20_GATE               ; Step 7
push ax

call .kbd_wait                  ; Step 8

mov al,KB_WRITE_OUTPUT_PORT     ; Step 9
out STATUS_PORT,al

call .kbd_input_buffer_full     ; Step 10

pop ax                          ; Step 11
out KBD_OUT_BUF,al

; If all occurs fine, the A20 gate will be enabled at this point. Checking it.

call .kbd_wait                  ; Step 12

mov al,KB_READ_OUTPUT_PORT      ; Step 13
out STATUS_PORT,al

call .kbd_output_buffer_empty   ; Step 14

in al,KBD_OUT_BUF               ; Step 15

bt ax,1                         ; Step 16
jc .success
ret

loop .startIt

jmp .fail
ret

;------------------------------------------------------------;
; A20 is enabled. Great job!                                 ;
;------------------------------------------------------------;
.success:
sti                             ; Step 17
pusha                           ; Step 18
xor eax,eax
mov al,1                        ; Step 19

ret

;------------------------------------------------------------;
; A20 isn't enabled. Panic!?                                 ;
;------------------------------------------------------------;
.fail:
sti                             ; Step 17
pusha                           ; Step 18
xor eax,eax
mov al,0                        ; Step 19

ret

;------------------------------------------------------------;
; keyboard wait                                              ;
; Wait for the keyboard controller to be ready for a command ;
;------------------------------------------------------------;
.kbd_wait:
xor ax,ax
in al,STATUS_PORT               ; Reads the 8042 status register
bt ax,SR_BIT1_INPUT_BUFFER      ; Test if command buffer is full
jc .kbd_wait                    ; Input buffer is full. Try again.

ret

;------------------------------------------------------------;
; loop while keyboard input output buffer is empty           ;
;------------------------------------------------------------;
.kbd_output_buffer_empty:
xor ax,ax
in al,STATUS_PORT
bt ax,SR_BIT0_OUTPUT_BUFFER
jnc .kbd_input_buffer_empty

ret

;------------------------------------------------------------;
; loop while keyboard output buffer is full                  ;
;------------------------------------------------------------;
.kbd_output_buffer_full:
xor ax,ax
in al,STATUS_PORT
bt ax,SR_BIT0_OUTPUT_BUFFER
jc .kbd_input_buffer_full

ret

;------------------------------------------------------------;
; loop while keyboard buffer is empty                        ;
;------------------------------------------------------------;
.kbd_input_buffer_empty:
xor ax,ax
in al,STATUS_PORT
bt ax,SR_BIT1_INPUT_BUFFER
jnc .kbd_input_buffer_empty

ret

;------------------------------------------------------------;
; loop while keyboard input buffer is full                   ;
;------------------------------------------------------------;
.kbd_input_buffer_full:
xor ax,ax
in al,STATUS_PORT
bt ax,SR_BIT1_INPUT_BUFFER
jc .kbd_input_buffer_full

ret
    
Post 23 Jun 2006, 14:23
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
Great Smile, but maybe you should check you may have done typo error popa (maybe should be pusha, and pusha (maybe should be popa) ?.
And maybe you should not have a 'ret' here:
Code:
jc .successret ;<*******    

This would mean you will not get a panic

PS: Your a fast learner.
Post 23 Jun 2006, 15:01
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
my english is very poor. argh! I dont know if I must use "I'd use" or "I'd used" to put the phrase in the past. argh. sorry. i'm from brazil. I learn english by myself. no teacher. no class.

ok.

I'd used pusha to put registers into memory. And, after the execution, restore original registers values. Just it. Nothing else.

So, about ret after .success, thx. You're right. Thx

But, one question:

Code:
jc .success

.success:
sti                             ; Step 17
pusha                           ; Step 18
xor eax,eax
mov al,1                        ; Step 19

ret
    


When I do ret in .success it will return to the line after jc .success?
Post 23 Jun 2006, 19:52
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
Thats OK your English is good, but the ret will return you to the next instruction after the call, in your case after the:
Code:
call enableA20; it will return here    

You do not ret, from a jump
As for pusha, if you look at your code, it is popa first, it should be pusha first,
You did this
Code:
popa                            ; Step 1    

And at end you did this
Code:
pusha                            ; Step 18    


You first push general reg's on stack with pusha, then you pop them off again with popa.
Post 23 Jun 2006, 23:34
View user's profile Send private message Reply with quote
MarcoAlves



Joined: 09 Jun 2006
Posts: 30
MarcoAlves
Ok. I get it. thx.
Post 26 Jun 2006, 15:14
View user's profile Send private message 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-2020, Tomasz Grysztar.

Powered by rwasa.