Would this code remap the pic ?

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
R2_
Member
Member
Posts: 50
Joined: Sat Dec 02, 2006 3:27 pm

Would this code remap the pic ?

Post by R2_ »

Code: Select all

pic_remap:
mov al, 0x11
OUT 0x20, al
mov al, 0x11
OUT 0xA0, al

mov al, 0x20
OUT 0x20 + 1, al
mov al, 0x28
OUT 0xA0 + 1, al

mov al, 4
OUT 0x20 + 1, al
mov al, 2
OUT 0xA0 + 1, al

mov al, 0x01
OUT 0x20 + 1, al
mov al, 0x01
OUT 0xA0 + 1, al

mov al, 0xFF
OUT 0x20 + 1, al
I wrote this from the C example for remapping the pic in OSDever.net
Do you guys think this would work ? I need to know so when I try it if it crashes after setting up IDT I will know this is not the problem. Im using NASM if that matters for syntax... I don't know if NASM uses that syntax of destination, src or src, destination... as you can see I tried destination, source for OUT. I tried this on my VM by calling it and it did not crash me Im going to attempt to make the GDT and IDT now so if it crashes I would like to know if its due to an error in my remapping code not doing what its supposed to or what.

(Update:)
Im guessing it works because it did not crash when I called STI however I would like reassurance by other computer scientists that this code is correct and that the PIC has been remapped...
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

Code: Select all

	outb(0x31, 0x43);
	outb(1, 0x40);
	outb(1, 0x40);
See if that makes the processor jump to vector 0x20 in the interrupt table.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

I learned to program the 8259A PIC using the HTML file I have attached to this file. It is simple and straightforward. However, I have coded one PIC initialization procedure in NASM that might help you out a little. I'm sorry I have not yet written any comments for it but if you need help understanding the code, let me know:

Code: Select all

; ——————————————————————————————————————————————————
  __Initialize8259PIC:
    ; void __Initialize8259PIC (DWORD IRQ0SlotInIDT , IRQ8SlotInIDT); StdCall;
    PUSH    EAX
    PUSH    EBP
    MOV     EBP , ESP

    ; ICW-1
    MOV     EAX , 0x00000011
    OUT     PIC1 , AL
    OUT     PIC2 , AL

    ; ICW-2
    MOV     EAX , DWORD PTR [EBP + 0x0C]
    OUT     PIC1_DATA , AL
    MOV     EAX , DWORD PTR [EBP + 0x10]
    OUT     PIC2_DATA , AL

    ; ICW-3
    MOV     EAX , 0x00000004
    OUT     PIC1_DATA , AL
    MOV     EAX , 0x00000002
    OUT     PIC2_DATA , AL

    ; ICW-4
    MOV     EAX , 0x00000001
    OUT     PIC1_DATA , AL
    OUT     PIC2_DATA , AL



    .EP:
      POP     EBP
      POP     EAX
    RET     0x08
; ——————————————————————————————————————————————————
Attachments
8259A PIC.zip
8259 Programmable Interrupt Controller documents
(6.37 KiB) Downloaded 65 times
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
R2_
Member
Member
Posts: 50
Joined: Sat Dec 02, 2006 3:27 pm

Post by R2_ »

Alright thanks for your responses, I think my code works because it doesn't crash when I call STI however when I take off the remapping code it does crash so Im guessing it works. I was just wondering because I was expecting it to crash as I don't have an IDT or GDT configured yet. What I basically did was attempt to port the C code in osdever to assembly.

How would you find out if the processor jumps to vector 0x20 ?

Thanks for the file you included it is very helpful indeed. :D
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

Put a IDT entry for the interrupt 0x20, and tell the PIC to unmask that interrupt.
R2_
Member
Member
Posts: 50
Joined: Sat Dec 02, 2006 3:27 pm

Post by R2_ »

How do you unmask interrupts ? I don't know how to code an interrupt table yet I don't understand what the high and low bytes of the memory addresses are or how to get them from my ISR using assembly. Thnx.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

Code: Select all

i32 InterruptEnableMask(PPRIVATE priv, u32 mask){
	u8 emask;
	emask = inb(PIC1 + IER);
	emask = emask & (~mask);
	outb(emask, PIC1 + IER);
	emask = inb(PIC2 + IER);
	emask = emask & (~(mask>>8));
	outb(emask, PIC2 + IER);
	return IO_SUCCESS;
}
i32 InterruptDisableMask(PPRIVATE priv, u32 mask){
	u8 emask;
	emask = inb(PIC1 + IER);
	emask = emask | mask;
	outb(emask, PIC1 + IER);
	emask = inb(PIC2 + IER);
	emask = emask | (mask>>8);
	outb(emask, PIC2 + IER);
	return IO_SUCCESS;
}
But the simple command is:

Code: Select all

mov al, 0xFF
OUT 0x20 + 1, al 
You just masked the interrupts one through eight on the master 8253(PIC). The slave 8253(PIC) is connected to master here:

Code: Select all

mov al, 4
OUT 0x20 + 1, al
mov al, 2
OUT 0xA0 + 1, al 
If you mask the interrupt 0x2 for the master 8253 it will completely disable the slave 8253.

In all you have sixteen hardware interrupts to mask or unmask. However only fourteen are actually usable since I think one line on each is used to connected them together, but someone who knows more should answer that.

In my functions above if you look at each function you will notice that I read the current mask from each of the two 8253(PIC)s. Then I apply the transformation on the bits to reflect the changes needed as in: unmask this, or mask that. Then rewrite it to the I/O port.

If you unmask interrupt zero on the master 8253(PIC), or the most least significant bit in the mask, turn on the timer, and fill in the IDT vector 0x20.

idt[0x20].handler..
idt[0x20]....blah

Code: Select all

struct __attribute__ ((__packed__)) titr{
	u16	offset_low;
	u16	selector;
	u16	attr;
	u16	offset_high;
};
void it_set(struct titr *ir, u32 index, u32 offset, u16 selector, u16 attr){
	unsigned char ah, al;
	ir[index].offset_high = offset >> 16;
	ir[index].attr = attr | 0x0e00;
	ir[index].selector = selector;
	ir[index].offset_low = offset & 0xFFFF;
	//0xe00
	return;
}
I dunno if that will help since you might not know or understand C, but if you do I am sure it would be almost invaluable as I remember when I have tried to get the IDT running it would have been nice to really have something I could check my own work against.
Last edited by Kevin McGuire on Sun Apr 29, 2007 8:44 am, edited 1 time in total.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

First you are going to have to fill the IDTR which stands for (Interrupt Descriptor Table Register). You fill this invisible register implicitly using the LIDT instruction. This instruction accepts the memory location of a structure like this (which is called IDTR):

Code: Select all

  IDTR:
    DW (IDT_END - IDT) - 1
    DD IDT
Where:
  • [li]The first WORD (DW) is the length of the IDT in bytes minus 1.[/li]
    [li]The second DWORD (DD) is the physical location of the IDT in the memory[li]

    IDT and IDT_END are respective labels for start point and the end point of the IDT. IDT acts just like a look-up table for the CPU. I recommend that you read about IDT in Intel Manuals. I truly understand that one may not be able to understand a lot of things fully by just reading Intel Manuals because they almost always confuse people at first instead of instructing them but you will get used to that soon.

    Here is what I have coded in order to enable and/or disable IRQ pulses:

    Code: Select all

    ; ——————————————————————————————————————————————————
      IRQ_PULSE_IRQ0                      EQU       0x00000001
      IRQ_PULSE_IRQ1                      EQU       0x00000002
      IRQ_PULSE_IRQ2                      EQU       0x00000004
      IRQ_PULSE_IRQ3                      EQU       0x00000008
      IRQ_PULSE_IRQ4                      EQU       0x00000010
      IRQ_PULSE_IRQ5                      EQU       0x00000020
      IRQ_PULSE_IRQ6                      EQU       0x00000040
      IRQ_PULSE_IRQ7                      EQU       0x00000080
      IRQ_PULSE_IRQ8                      EQU       0x00000100
      IRQ_PULSE_IRQ9                      EQU       0x00000200
      IRQ_PULSE_IRQ10                     EQU       0x00000400
      IRQ_PULSE_IRQ11                     EQU       0x00000800
      IRQ_PULSE_IRQ12                     EQU       0x00001000
      IRQ_PULSE_IRQ13                     EQU       0x00002000
      IRQ_PULSE_IRQ14                     EQU       0x00004000
      IRQ_PULSE_IRQ15                     EQU       0x00008000
    ; ——————————————————————————————————————————————————
      __EnableIRQPulse:
        ; void __EnableIRQPulse (DWORD IRQPulse); StdCall;
        PUSH    EAX
        PUSH    EBX
        PUSH    EDX
        PUSH    EBP
        PUSHFD
        CLI
        MOV     EBP , ESP
        MOV     EBX , DWORD PTR [EBP + 0x18]
        MOV     EDX , PIC1_DATA
        TEST    EBX , 0x0000FF00
        JZ      .ForPIC1
        SHR     EBX , 0x00000008
        MOV     EDX , PIC2_DATA
        .ForPIC1:
          IN      AL , DX
          NOT     EBX
          AND     EAX , EBX
          OUT     DX , AL
        POPFD
        POP     EBP
        POP     EDX
        POP     EBX
        POP     EAX
        RET     0x04
    ; ——————————————————————————————————————————————————
      __DisableIRQPulse:
        ; void __DisableIRQPulse (DWORD IRQPulse); StdCall;
        PUSH    EAX
        PUSH    EBX
        PUSH    EDX
        PUSH    EBP
        PUSHFD
        CLI
        MOV     EBP , ESP
        MOV     EBX , DWORD PTR [EBP + 0x18]
        MOV     EDX , PIC1_DATA
        TEST    EBX , 0x0000FF00
        JZ      .ForPIC1
        SHR     EBX , 0x00000008
        MOV     EDX , PIC2_DATA
        .ForPIC1:
          IN      AL , DX
          OR      EAX , EBX
          OUT     DX , AL
        POPFD
        POP     EBP
        POP     EDX
        POP     EBX
        POP     EAX
        RET     0x04
    ; ——————————————————————————————————————————————————
    I hope that you already know from what port data goes in the PIC and from where data is read from it.

    Hope that helps.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
Post Reply