Загрузчик, который я делаю, не получает IRQ12 - PullRequest
0 голосов
/ 21 октября 2018

Компьютер, на котором я тестирую свою операционную систему, - это ноутбук с сенсорной панелью.Когда я включаю компьютер, он читает клавиатуру, но после касания сенсорной панели он не читает ни тачпад, ни клавиатуру.И я также использую qemu, и на qemu он не читает мышь, но продолжает читать клавиатуру.

Это код, который я использую для мыши:

#ifndef _MOUSE
#define _MOUSE

#include "base.cpp"
#include "math.cpp"
#include "vector.cpp"
//#include "console.cpp"//------

class Mouse
{
    public:
    Bool key_pressed[3];
    Vector2 position;

    private:
    Vector<Ubyte> bytes_buffer;
    double mouse_area_y_respect_x;

    void limit_inside_area()
    {
        limit_inside(position.x,0,1);
        limit_inside(position.y,0,mouse_area_y_respect_x);
    }
    Bool process_stroke()
    {
        if(bytes_buffer.size()<4) return false;
        else
        {
            position.x=0;
            limit_inside_area();

            bytes_buffer.resize(bytes_buffer.size()-4);

            return true;
        }
    }

    Ubyte in_port_0x64()
    {
        Ubyte val;
        asm("in al,0x64;":"=a"(val));
        return val;
    }
    Ubyte in_port_0x60()
    {
        Ubyte val;
        asm("in al,0x60;":"=a"(val));
        return val;
    }
    void out_port_0x60(Ubyte byte)
    {
        asm("out 0x60,%%al"::"a"(byte));
    }
    void out_port_0x64(Ubyte byte)
    {
        asm("out 0x64,%%al"::"a"(byte));
    }
    void wait_for_device(Uint64 mode)
    {
        if(mode==0)
        {
            for(Uint64 n=0;n<10000;n++)
            {
                Ubyte val=in_port_0x64();
                if((val&1)==1) break;
            }
        }
        else
        {
            for(Uint64 n=0;n<10000;n++)
            {
                Ubyte val=in_port_0x64();
                if((val&2)==0) break;
            }
        }
    }
    void send_to_device(Ubyte byte)
    {
        wait_for_device(1);
        out_port_0x64(0xD4);
        wait_for_device(1);
        out_port_0x60(byte);
    }
    Ubyte wait_for_device_acknowledge()
    {
        wait_for_device(0);
        return in_port_0x60();
    }

    public:


    void initialize(double _mouse_area_y_respect_x)
    {
        for(Uint64 n=0;n<3;n++)
        {
            key_pressed[n]=false;
        }
        mouse_area_y_respect_x=_mouse_area_y_respect_x;
        if(mouse_area_y_respect_x>=0.1 && mouse_area_y_respect_x<=100){}
        else if(mouse_area_y_respect_x<0.1) mouse_area_y_respect_x=0.1;
        else if(mouse_area_y_respect_x>100) mouse_area_y_respect_x=100;
        else
        {
            mouse_area_y_respect_x=1;
        }
        position=Vector2(0.5,mouse_area_y_respect_x/2);
    }
    void initialize_device()
    {
        asm("cli");

        wait_for_device(1);
        out_port_0x64(0xA8);
        wait_for_device_acknowledge();

        wait_for_device(1);
        out_port_0x64(0x20);
        wait_for_device(0);
        Ubyte status=in_port_0x60();
        status=status|2;
        wait_for_device(1);
        out_port_0x64(0x60);
        wait_for_device(1);
        out_port_0x60(status);

        send_to_device(0xF6);
        wait_for_device_acknowledge();

        send_to_device(0xF4);
        wait_for_device_acknowledge();

        asm("sti");
    }
    void update_from_interrupt()
    {
        Ubyte data=in_port_0x60();
        input_byte[input_byte_cycle]=data;
        input_byte_cycle++;
        if(input_byte_cycle>3)
        {
            input_byte_cycle=0;

            position.x=0;
        }
        position.x=0;

        //bytes_buffer.push_back(data);
        //if(bytes_buffer.size()>10000) bytes_buffer.resize(0);
    }
    Ubyte input_byte[4];
    Uint64 input_byte_cycle=0;
    void update()
    {




        //while(bytes_buffer.size()>0 && process_stroke()){}
    }
};

static Mouse*CURRENT_MOUSE;

#endif

Этоточка, в которой я вызываю функцию initialize_device () в загрузчике:

    Mouse mouse;
    mouse.initialize(768.0/1024);
    mouse.initialize_device();
    CURRENT_MOUSE=&mouse;

    set_interrupts_handler((Uint64)&interrupts_handler);

    //the BIOS call for VESA
    call_assembly(0,0x4f02,VESA_MODE,0,0,0,0,0,0x10);

    Uint64 time=0;
    while(1)
    {
        for(Uint64 n=0;n<1;n++)
        {
            CURRENT_KEYBOARD->update();
            CURRENT_MOUSE->update();
        }

        time++;
        console.draw(screen,time/10);

        screen.circlefill((CURRENT_MOUSE->position*1024).toPos(),10,0xffffff);

        if(bootloader_info.VESA->BitsPerPixel==24) screen.draw(bootloader_info.VESA->PhysBasePtr);
        else screen.draw_alpha(bootloader_info.VESA->PhysBasePtr);
    }

И обработчик прерываний, который обрабатывает некоторые из прерываний:

void interrupts_handler()
{
    Uint64 interrupt_number=get_interrupt_number_interrupts_handler();

    if(interrupt_number==8)
    {
        TIME++;
    }
    else
    {
        CURRENT_CONSOLE->printhex(interrupt_number);//---------------------
        CURRENT_CONSOLE->printf(" ");

        if(interrupt_number==9)
        {
            Uint64 var;
            asm("in al,0x60;"
                /*"out 0x61,al;"*/:"=a"(var));
            Ubyte keycode=var;
            CURRENT_KEYBOARD->update_from_interrupt(var);
        }
        else if(interrupt_number==0x74)
        {
            CURRENT_MOUSE->update_from_interrupt();
        }
        else if(interrupt_number==0x0f)
        {

        }
    }
}

Это только малая частькода, но я поставил то, что считаю наиболее важным.

И типы (определенные в base.cpp):

typedef char Int8;
typedef unsigned char Uint8;
typedef short int Int16;
typedef unsigned short int Uint16;
typedef int Int32;
typedef unsigned int Uint32;
typedef long long int Int64;
typedef unsigned long long int Uint64;

typedef Int8 Byte;
typedef Uint8 Ubyte;
typedef Ubyte* Ptr;
typedef Ubyte Bool;

с помощью "CURRENT_CONSOLE-> printhex (interrupt_number);»в обработчике прерываний я сделал так, чтобы он печатал номера получаемых прерываний, поэтому я знаю, что я не получаю IRQ12 (я не переназначил PIC).

Другая частьобработчик прерываний, который находится в сборке носа:

LONG_MODE_BASIC_INTERRUPTION_HANDLER:

%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_E 1
push rax
mov al,%1
jmp .handler
%endmacro

%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 1
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x01
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x02
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x03
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x04
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x05
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x06
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x07
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x08
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x09
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0A
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0B
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0C
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0D
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0E
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0F
%endmacro

LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x10
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x20
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x30
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x40
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x50
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x60
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x70
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x80
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x90
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xA0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xB0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xC0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xD0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xE0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xF0

.handler:

cmp al,8
je .timer_or_double_fault
cmp al,9
je .keyboard
cmp al,0x0d
je .general_protection_fault
cmp al,0x0e
je .page_fault_or_floppy_disc
cmp al,0x0f
je .strange_or_spurious
cmp al,0x74
je .mouse


call NOT_HANDLED_INTERRUPT_MESSAGE
jmp $

.timer_or_double_fault:

;pop rbx
;pop rcx
;cmp rcx,0
;je .double_fault
;push rcx
;push rbx

push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,0
je .double_fault
pop rcx
pop rbx

jmp .timer

.keyboard:
.mouse:
.strange_or_spurious:
.timer:

push rbx
mov rbx,[POINTER_TO_INTERRUPTS_HANDLER]
cmp rbx,0
je .no_cpp

mov [INTERRUPT_NUMBER_FOR_HANDLER],al
PUSHA64
call [POINTER_TO_INTERRUPTS_HANDLER]
POPA64

.no_cpp:
pop rbx

mov al,0x20
out 0x20,al
jmp .end

.double_fault:
push rbx

call DOUBLE_FAULT_MESSAGE

BITS 64

.general_protection_fault:

call GENERAL_PROTECTION_FAULT_MESSAGE

mov al,0x20
out 0x20,al
jmp .end

.page_fault_or_floppy_disc:

push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,32
jl .page_fault
pop rcx
pop rbx

mov al,0x20
out 0x20,al
jmp .end

.page_fault:
push rbx


;-----------------------------

mov al,0x20
out 0x20,al
jmp .end

.end:
pop rax
iretq

РЕДАКТИРОВАТЬ:

Я изменил обработчик в сборке:

LONG_MODE_BASIC_INTERRUPTION_HANDLER:

%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_E 1
push rax
mov al,%1
jmp .handler
%endmacro

%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 1
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x01
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x02
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x03
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x04
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x05
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x06
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x07
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x08
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x09
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0A
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0B
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0C
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0D
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0E
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0F
%endmacro

LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x10
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x20
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x30
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x40
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x50
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x60
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x70
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x80
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x90
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xA0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xB0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xC0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xD0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xE0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xF0

.handler:

cmp al,8
je .timer_or_double_fault
cmp al,9
je .keyboard
cmp al,0x0d
je .general_protection_fault
cmp al,0x0e
je .page_fault_or_floppy_disc
cmp al,0x0f
je .strange_or_spurious
cmp al,0x74
je .mouse


call NOT_HANDLED_INTERRUPT_MESSAGE
jmp $

.timer_or_double_fault:

;pop rbx
;pop rcx
;cmp rcx,0
;je .double_fault
;push rcx
;push rbx

push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,0
je .double_fault
pop rcx
pop rbx

jmp .timer

.keyboard:
.mouse:
.strange_or_spurious:
.timer:

push rbx
mov rbx,[POINTER_TO_INTERRUPTS_HANDLER]
cmp rbx,0
je .no_cpp

mov [INTERRUPT_NUMBER_FOR_HANDLER],al
PUSHA64
call [POINTER_TO_INTERRUPTS_HANDLER]
POPA64

.no_cpp:

mov al,0x20
mov bl,[INTERRUPT_NUMBER_FOR_HANDLER]
cmp bl,0x70
jl .IRQ0_7
out 0xA0,al
.IRQ0_7:
out 0x20,al

pop rbx

jmp .end

.double_fault:
push rbx

call DOUBLE_FAULT_MESSAGE

BITS 64

.general_protection_fault:

call GENERAL_PROTECTION_FAULT_MESSAGE

jmp .end

.page_fault_or_floppy_disc:

push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,32
jl .page_fault
pop rcx
pop rbx

mov al,0x20
out 0x20,al
jmp .end

.page_fault:
push rbx


;-----------------------------

jmp .end

.end:
pop rax
iretq

РЕДАКТИРОВАТЬ 2:

Обработчик прерываний в сборке:

%macro PUSHA64 0
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
%endmacro

%macro POPA64 0
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
%endmacro

LONG_MODE_BASIC_INTERRUPTION_HANDLER:

%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_E 1
push rax
mov al,%1
jmp .handler
%endmacro

%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 1
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x01
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x02
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x03
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x04
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x05
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x06
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x07
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x08
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x09
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0A
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0B
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0C
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0D
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0E
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0F
%endmacro

LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x10
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x20
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x30
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x40
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x50
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x60
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x70
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x80
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x90
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xA0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xB0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xC0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xD0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xE0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xF0

.handler:

PUSHA64

cmp al,0x08
je .double_fault
cmp al,0x0d
je .general_protection_fault
cmp al,0x0e
je .page_fault
cmp al,0x70
je .timer
cmp al,0x71
je .keyboard
cmp al,0x76
je .floppy_disc
cmp al,0x7c
je .mouse
cmp al,0x77
je .strange_or_spurious

call NOT_HANDLED_INTERRUPT_MESSAGE
jmp $

.keyboard:
.mouse:
.strange_or_spurious:
.timer:
.floppy_disc:
mov rbx,[POINTER_TO_INTERRUPTS_HANDLER]
cmp rbx,0
je .no_cpp
mov [INTERRUPT_NUMBER_FOR_HANDLER],al
call [POINTER_TO_INTERRUPTS_HANDLER]
.no_cpp:
mov al,0x20
mov bl,[INTERRUPT_NUMBER_FOR_HANDLER]
cmp bl,0x78
jl .IRQ0_7
out 0xA0,al
.IRQ0_7:
out 0x20,al
jmp .end

.double_fault:
call DOUBLE_FAULT_MESSAGE
jmp .end_pop_error_code

.general_protection_fault:
call GENERAL_PROTECTION_FAULT_MESSAGE
jmp .end_pop_error_code

.page_fault:
jmp .end_pop_error_code

.end:
POPA64
pop rax
iretq

.end_pop_error_code:
POPA64
pop rax
pop qword[.void]
iretq

.void: dq 0

код, который повторно отображает PIC:

BITS 32

io_wait:
push ecx
mov ecx,100
.loop:
loop .loop
pop ecx
ret

; Input:
; al: first PIC's offset
; bl: second PIC's offset
remap_PICs:

PIC1_COMMAND equ 0x20
PIC2_COMMAND equ 0xA0
PIC1_DATA equ 0x21
PIC2_DATA equ 0xA1
ICW1_INIT_WITH_ICW1_ICW4 equ 0x11
ICW4_8086 equ 0x01

mov ch,al
mov dh,bl

in al,PIC1_DATA
mov cl,al
in al,PIC2_DATA
mov dl,al

mov al,ICW1_INIT_WITH_ICW1_ICW4
out PIC1_COMMAND,al
call io_wait
out PIC2_COMMAND,al
call io_wait

mov al,ch
out PIC1_DATA,al
call io_wait
mov al,dh
out PIC2_DATA,al
call io_wait

mov al,4
out PIC1_DATA,al
call io_wait
mov al,2
out PIC2_DATA,al
call io_wait

mov al,ICW4_8086
out PIC1_DATA,al
call io_wait
out PIC2_DATA,al
call io_wait

mov al,cl
out PIC1_DATA,al
mov al,dl
out PIC2_DATA,al

ret

1 Ответ

0 голосов
/ 23 октября 2018

У вас есть несколько проблем:

1 вам нужно сохранить все регистры (и восстановить их) при вводе прерывания.Если вы этого не сделаете, вы не сможете возобновить работу после запуска обработчика прерываний.Это очень сложно отладить, потому что если вы не работаете до прерывания, вы не заметите поврежденное состояние регистра.

2 вам нужно выдать ICW на PIC.Кто-то упомянул об этом в комментариях, но без ICW вы действительно не знаете, что PIC собирается делать с прерыванием.Переназначьте прерывания на 0x20..0x30.

3, вам нужно выбрать способ взаимодействия с PIC;текущая мода состоит в том, чтобы использовать запись прерывания как для маски, так и для подтверждения прерывания, которое освобождает другие прерывания для возникновения.

вы смешали свои исключения с прерываниями.Это проблематично по двум причинам: во-первых, вы не должны трогать PIC, если это не для реального прерывания;Во-вторых, некоторые исключения помещают в стек дополнительное значение, которое вам нужно разместить.

Итак, сохраните больше регистров, инициализируйте PIC, отделите исключения от прерываний.

Добавление кОбновленный источник: 1. Я не вижу кода, где вы инициализировали PIC.2. Этот испорченный ассемблер, который вы используете, слишком сильно скрывает: если вы установили реальные базы прерываний 0x70 и 0x78, я ожидаю увидеть код, соответствующий этим записям, и код, который устанавливает соответствующие записи IDT,Я не вижу ни того, ни другого.

Вы исчерпали мое терпение;вы не предоставили запрошенный источник, а указанный вами источник не имеет смысла.Я не вижу возможности вам помочь.

...