struct zosIntsTable
{
u16 CallbackOffset0_15;
u16 CallbackSeg;
u8 NULLByte;
u8 Flags;
u16 CallbackOffset16_31;
}__attribute__ ((packed));
struct zosIntsTableRegistor
{
u16 Length;
zptr Pointer;
}__attribute__ ((packed));
#define ZOS_IDT_FLAGS_MASK 0x80
#define ZOS_IDT_FLAGS_INT 0x0e
#define ZOS_IDT_FLAGS_TRAP 0x0f
void zosSetINT(u8 index, INTCallback Callback, zbool Interupt)
{
IDT[index].CallbackOffset0_15 = ((zuint)Callback) & 0xffff;
IDT[index].CallbackSeg = ZOS_SYSSEG_CODE;
IDT[index].Flags = (Interupt?ZOS_IDT_FLAGS_INT:ZOS_IDT_FLAGS_TRAP) | ZOS_IDT_FLAGS_MASK;
IDT[index].CallbackOffset16_31 = (((zuint)Callback) >> 16) & 0xffff;
}
void zosSetINTS()
{
zos_memset(IDT, 0, sizeof(IDT));
for (zuint i = 0; i < 0x20; i++)
zosSetINT(i, zosINT_header, zfalse);
zosSetINT(0x20, zosIRQ0_header, ztrue); //Timer IRQ
zosSetINT(0x21, zosIRQ1_header, ztrue); //Keyboard IRQ
for (zuint i = 0x22; i < 0x28; i++)
zosSetINT(i, zosIRQ_dummy1, ztrue);
for (zuint i = 0x28; i < 0x30; i++)
zosSetINT(i, zosIRQ_dummy2, ztrue);
for (zuint i = 0x30; i < 256; i++)
zosSetINT(i, zosINT_header, zfalse);
IDTReg.Length = sizeof(IDT) - 1;
IDTReg.Pointer = IDT;
asm("cli");
asm("lidt %0":: "m"(IDTReg));
portoutb(ZOS_PORT_8259M1, 0x11);
portoutb(ZOS_PORT_8259S1, 0x11);
portoutb(ZOS_PORT_8259M2, 0x20);
portoutb(ZOS_PORT_8259S2, 0x28);
portoutb(ZOS_PORT_8259M2, 0x04);
portoutb(ZOS_PORT_8259S2, 0x02);
portoutb(ZOS_PORT_8259M2, 0x01);
portoutb(ZOS_PORT_8259S2, 0x01);
portoutb(0x21, 0);
portoutb(0xa1, 0);
portoutb(0x70, 0x0d);
asm("sti");
}
_zosIRQ0_header:
pushad
;call zosIRQ0
mov al, 020h
out 020h, al
popad
iret
_zosIRQ1_header:
pushad
lea eax, [zosIRQ1]
call eax
mov al, 020h
out 020h, al
popad
iret
_zosINT_header:
pushad
popad
iret
_zosIRQ_dummy1:
pushad
mov al, 020h
out 020h, al
popad
iret
_zosIRQ_dummy2:
pushad
mov al, 020h
out 020h, al
out 0a0h, al
popad
iret
void zosIRQ1()
{
portinb(ZOS_KEYBOARD_PORT1);
zosPrintString("Key\n");
u8 s = portinb(ZOS_KEYBOARD_PORT2);
s |= 1;
portoutb(ZOS_KEYBOARD_PORT2, s);
}
Проблеммы с прерываниями...
Вот код установки новых обработчиков, и сами обработчике (установка происходит нормально, проверял в Bochs под отладчиком):
Код:
Сообщение "Key\n" почему-то вылезает только один раз. Хотя по идее дожно при нажатии и отпускании клавиши...
На ассемблере написать религия не позволяет? Строчек будет в два раза меньше и код будет понятным.
Код:
portoutb(ZOS_PORT_8259M2, 0x01);
portoutb(ZOS_PORT_8259S2, 0x01);
portoutb(ZOS_PORT_8259S2, 0x01);
Код:
mov al, 00001101b
out 21h, al
mov al, 00001001b
out 0A1h, al
out 21h, al
mov al, 00001001b
out 0A1h, al
Потом лучше маскировать неиспользуемые прерывания.
И еще я бы добавил команду чтения значения из порта 0x71 к вот этому:
Код:
portoutb(0x70, 0x0d);
А перед перепрограммированием логики 8259 немаскируемые прерывания соответственно нужно запрещать, чего я вообще не увидел. То есть:
Код:
cli
mov al, 8Fh
out 70h, al
in al, 71h
mov al, 8Fh
out 70h, al
in al, 71h
На инициализацию IDT не смотрел. Может, там что-то не так.
Код:
zosIRQ1_header:
pushad
lea eax, [zosIRQ1]
call eax
mov al, 020h
out 020h, al
popad
iret
pushad
lea eax, [zosIRQ1]
call eax
mov al, 020h
out 020h, al
popad
iret
Код:
u8 s = portinb(ZOS_KEYBOARD_PORT2);
s |= 1;
portoutb(ZOS_KEYBOARD_PORT2, s);
s |= 1;
portoutb(ZOS_KEYBOARD_PORT2, s);
Цитата: Vov4ick
Прерывние 21 выполняет функции ввода-вывода для файлов, клавиатуры и экрана. Также осуществляет смену обработчиков прерываний.
Прерывание 0x21 имеет данную функцию только в реальном режиме DOS.
***Zebr@XXL***, поясните пожалуйста, что вы вообще делаете? а то тут непонятки DOS, не DOS