8259A Need help 2

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Mikae
Member
Member
Posts: 94
Joined: Sun Jul 30, 2006 1:08 pm

8259A Need help 2

Post by Mikae »

Hello, all!

After a long discussion I wrote the simpliest code to initialize PICs. Certainly it fails, and I don't know why...

The code just set up interrupt handler, initialize PICs, disables all interrupts except from a keyboard and waits in 'jmp $'. The code is loaded at 0x1000:0x0.

Code: Select all

ICW1 = 0x11        ;NO LTIM, NO ADI, NO SNGL, ICW4.
ICW2_MASTER = 0x8  ;Interrupt vectors base.
ICW2_SLAVE  = 0x10 ;Interrupt vectors base.
ICW3_MASTER = 0x4  ;IRs, where children are connected
ICW3_SLAVE  = 0x2  ;Child's ID? Not sure about this number...
ICW4_MASTER = 0x1  ;NO SFNM, NOT BUFFER, 8086.
ICW4_SLAVE  = 0x1  ;NO SFNM, NOT BUFFER, 8086.

 mov     ax, 0x1000
 mov     ds, ax
 mov     fs, ax
 mov     gs, ax
 xor     ax, ax
 mov     es, ax
 mov     cx, HNDLR_SIZE ;copy handler to its place.
 mov     si, hndlr
 mov     di, 0x600
 rep movsb
 
;Init PICs
 cli
 mov     al, ICW1
 out     0x20, al
 jmp     short $ + 2
 jmp     short $ + 2
 mov     al, ICW2_MASTER
 out     21h, al
 jmp     short $ + 2
 jmp     short $ + 2
 mov     al, ICW3_MASTER
 out     0x21, al
 jmp     short $ + 2
 jmp     short $ + 2
 mov     al, ICW4_MASTER
 out     0x21, al
 jmp     short $ + 2
 jmp     short $ + 2
 
 mov     al, ICW1
 out     0xA0, al
 jmp     short $ + 2
 jmp     short $ + 2
 mov     al, ICW2_SLAVE
 out     0xA1, al
 jmp     short $ + 2
 jmp     short $ + 2
 mov     al, ICW3_SLAVE
 out     0xA1, al
 jmp     short $ + 2
 jmp     short $ + 2
 mov     al, ICW4_SLAVE
 out     0xA1, al
 jmp     short $ + 2
 jmp     short $ + 2

;Mask all interrupts, except 0x1 
 mov     al, 0xFD
 out     0x21, al
 jmp     short $ + 2
 jmp     short $ + 2
 
 mov     word [0x24], 0x600 ;installing handler to IVT.
 mov     word [0x26], 0
 sti
 
 jmp     $

hndlr:
 mov ax, 0xB800
 mov ds, ax
 xor ax, ax
 mov es, ax
 
 mov al, 'B'
 mov ah, 0xF 
 mov bx, [es:cur_pos]
 mov [bx], ax
 add word [es:cur_pos], 0x2
 iret
cur_pos: dw 0x0
HNDLR_SIZE = $ - hndlr
System just hangs, without any reaction on keypresses. The same behavior in Bochs (tried to run it with 'show int' option). What's wrong?..

TIA, Mikae.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: 8259A Need help 2

Post by Brendan »

Hi,

Some notes (I'm not at home, so I'm relying on my memory)...

First, setting up the PIC to generate interrupts 0x08 to 0x17 isn't such a good idea - it conflicts with the interrupts used by the CPU for exceptions, and (for the slave PIC) isn't what the BIOS (mis)uses either (the BIOS uses interrupts 0x70 to 0x77 for the slave PIC).

I can't see where you're setting the slave PICs IRQ mask.

The keyboard IRQ (the only one deliberately left unmasked) would generate IRQ 0x11. The IDT entry for this would be at 0x11 * 4 (or 0x44), not at 0x24 (which would be the IDT entry for interrupt 0x09).

You're interrupt handler doesn't preserve any of the registers in use by whatever it interrupts, which would cause rather erratic behaviour. It also doesn't read from the keyboard's data port (which would cause the keyboard to send no more bytes after the first), and doesn't send an EOI to the master PIC (which would cause the master PIC to stop sending any more IRQs after the first).

Lastly, the "cur_pos" variable looks like it's in your code segment somewhere between 0x10000 and 0x1FFFF, while your interrupt handler tries to access it ES = 0. I'm thinking your interrupt handler needs to set ES to 0x1000 to access "cur_pos" properly.

Apart from that, your PIC initialization code looks good, and none of the above explains why you don't get one IRQ....


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
smiddy
Member
Member
Posts: 127
Joined: Sun Oct 24, 2004 11:00 pm
Location: In my cube, like a good leming. ;-)

Post by smiddy »

The following may help in understanding it further. Everything Bredan said seems kosher to me:

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PIC.asm - Contains the Programmable Interrupt Controller interface routines
;;           for the kernel.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

IRQMap      dd 0FFFFFFFFh   ; 32bit (LSb to MSb) map of IRQs: 1 = Off, 0 = On

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; RemapPIC - Remaps IRQs from the BIOS defaults interrupts to INT 20h - 2Fh.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

RemapPIC:

    push eax
    
    mov al,11h              ; Initialization Command Word (ICW) 1
    out 20h,al              ; Into first PIC
    out 0A0h,al             ; Into casscaded second PIC

    mov al,20h              ; Load starting interrupt 20h (ICW2)
    out 21h,al              ; Into first PIC
    mov al,28h              ; Load starting interrupt 28h
    out 0A1h,al             ; Into second PIC

    mov al,04h              ; ICW3
    out 21h,al              ; First PIC
    mov al,02h              ; ICW3
    out 0A1h,al             ; Second PIC

    mov al,01h              ; ICW4
    out 21h,al              ; First PIC
    out 0A1h,al             ; Second PIC
    
    pop eax
    
    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DisableAllIRQs - Disables all IRQs regardless of masking:
;;
;; Operation Command Word 1: 
;;
;;  |7|6|5|4|3|2|1|0|  OCW1 - IMR Interrupt Mask Register
;;   | | | | | | | `---- 0 = service IRQ0 or IRQ8, 1 = mask off
;;   | | | | | | `----- 0 = service IRQ1 or IRQ9, 1 = mask off
;;   | | | | | `------ 0 = service IRQ2 or IRQA, 1 = mask off
;;   | | | | `------- 0 = service IRQ3 or IRQB, 1 = mask off
;;   | | | `-------- 0 = service IRQ4 or IRQC, 1 = mask off
;;   | | `--------- 0 = service IRQ5 or IRQD, 1 = mask off
;;   | `---------- 0 = service IRQ6 or IRQE, 1 = mask off
;;   `----------- 0 = service IRQ7 or IRQF, 1 = mask off
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
DisableAllIRQs:

    push eax

    mov al,0FFh             ; Turn all IRQs off             
    out 21h,al              ; First PIC
    out 0A1h,al             ; Second PIC
    
    pop eax

    ret
    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; EnableAllIRQs - Enables all masked IRQs.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

EnableAllIRQs:

    push eax
    push ebx

    cli

    mov ebx,[IRQMap]        ; Load current IRQ bitmap
    mov al,bl               ; First 8 IRQs mapped
    out 021h,al
    
    mov al,bh               ; Second 8 IRQs mapped
    out 0A1h,al
    
    sti
    
    pop ebx
    pop eax

    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; EnableAnIRQ - Enables one IRQ based on 32bits.
;;
;; Input:   EAX contains IRQ number to enable.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

EnableAnIRQ:

    push eax
    push ebx
    push ecx
    
    mov ecx,eax
    mov eax,1
    shl eax,cl
    not eax
    
    and eax,[IRQMap]
    mov [IRQMap],eax
    
    call EnableAllIRQs
    
    pop ecx
    pop ebx
    pop eax
    
    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DisableAnIRQ - Disables one IRQ based on 32bits.
;;
;; Input:   EAX contains IRQ number to disable.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DisableAnIRQ:

    push eax
    push ebx
    push ecx

    mov ebx,eax
    mov eax,1
    mov ecx,ebx
    shl eax,cl

    or  eax,[IRQMap]
    mov [IRQMap],eax
    
    call EnableAllIRQs
    
    pop ecx
    pop ebx
    pop eax
    
    ret
The above is for protected mode, to go back you realmode:

Code: Select all

    call DisableAllIRQs                     ; Turn off every IRQ (bitmap is 0FFFFFFFFh or all off)
    mov al,11h
    out 020h,al
    out 0A0h,al

    mov al,08h
    out 021h,al

    mov al,070h
    out 0A1h,al

    mov al,4
    out 021h,al

    mov al,2
    out 0A1h,al

    mov al,1
    out 021h,al
    out 0A1h,al
Hope this helps...
Post Reply