IRQ 8 не работает HW или SW?

Сначала я программирую для винтажных компьютерных групп. То, что я пишу, предназначено специально для MS-DOS, а не для Windows, потому что это то, что люди используют. Моя текущая программа предназначена для более поздних систем, а не для линейки 8086, поэтому планировалось использовать IRQ 8. Это позволяет мне устанавливать частоту прерываний в двоичных значениях от 2/сек до 8192/сек (2, 4, 8, 16, так далее...)

Только по какой-то причине в более новых старых системах (хорошо, это звучит странно) это не работает. В эмуляции и в системе 386, к которой у меня есть доступ, все работает отлично, но в моей системе P3 (GA-6BXC MB с процессором P3 800) это просто не работает.

Код

настройка прерывания

disable();
oldrtc = getvect(0x70);    //Reads the vector for IRQ 8
settvect(0x70,countdown);  //Sets the vector for

outportb(0x70,0x8a);
y = inportb(0x71) & 0xf0;
outportb(0x70,0x8a);
outportb(0x71,y | _MRATE_); //Adjustable value, set for 64 interrupts per second

outportb(0x70,0x8b);
y = inportb(0x71);
outportb(0x70,0x8b);
outportb(0x71,y | 0x40);

enable();

в конце прерывания

outportb(0x70,0x0c);
inportb(0x71);        //Reading the C register resets the interrupt
outportb(0xa0,0x20);  //Resets the PIC (turns interrupts back on)
outportb(0x20,0x20);  //There are 2 PICs on AT machines and later

При закрытии программы

disable();

outportb(0x70,0x8b);
y = inportb(0x71);
outportb(0x70,0x8b);
outportb(0x71,y & 0xbf);
setvect(0x70,oldrtc);

enable();

Я не вижу в коде ничего, что могло бы вызвать проблему. Но это просто не имеет смысла. Хотя я не полностью доверяю этой информации, MSD «действительно» сообщает о IRQ 8 как о счетчике RTC и говорит, что он присутствует и работает нормально. Возможно ли, что более поздние системы изменили вектор? Все, что я нахожу, говорит о том, что IRQ 8 является вектором 0x70, но прерывание никогда не срабатывает в моей системе Pentium III. Есть ли способ узнать, были ли изменены векторы?


person user3399848    schedule 25.11.2014    source источник


Ответы (1)


Прошло много времени с тех пор, как я делал какой-либо код MS-DOS, и я не думаю, что когда-либо работал с этим конкретным прерыванием (я почти уверен, что вы можете просто прочитать место в памяти, чтобы получить время, и IRQ0 может может быть использован для запуска вас с интервалом, так что, может быть, это лучше В любом случае, учитывая мою ржавчину, простите меня за своего рода сброс ссылок.

http://wiki.osdev.org/Real_Time_Clock внизу этой страницы кто-то говорит, что у них были проблема и на некоторых машинах. RBIL предполагает, что это может быть связано с BIOS: http://www.ctyme.com/intr/rb-7797.htm

Без DOS я бы просто захватил сам IRQ0 и переназначил бы их все на свои собственные номера прерываний и изменил бы время по мере необходимости. Я сделал это несколько недавно! Я думаю, что это плохая идея для DOS, для этого более рекомендуется: http://www.ctyme.com/intr/rb-2443.htm

В любом случае, я уверен, что это связано с BIOS:

«Примечания: многие BIOS отключают периодическое прерывание в обработчике INT 70h, если только не происходит ожидание события (см. INT 15/AH=83h, INT 15/AH=86h). Может быть замаскировано установкой бита 0 на порте ввода-вывода. А1ч"

person Adam D. Ruppe    schedule 25.11.2014
comment
На самом деле я уже использую PIT1 и PIT3 для чрезвычайно быстрых (коротких кодов) функций. В моей первой сборке я также использовал его для функций таймера, но этот код делает больше (и, следовательно, требует большего объема кода). Это привело к резкому снижению производительности. Код, выполняющийся 64 раза в секунду, оказывает меньшее влияние, чем код, выполняющийся 23 000 раз в секунду. И да, я уже настраиваю часы для более быстрой процедуры прерывания PIT1. Я разочарован, обнаружив, что BIOS может полностью отключить IRQ 8. Кажется, я не могу найти способ обнаружить это и снова включить :( - person user3399848; 26.11.2014
comment
Обнаружил, что некоторые типы BIOS маскируют IRQ 8. Поэтому я добавил строки outportb(0xa1,inportb(0xa1) & 0x7f); outportb(0x21,inportb(0x21) и 0xdf); к инициализации. Но это не решило проблему. - person user3399848; 26.11.2014
comment
Хм, я не могу придумать что-нибудь еще, чтобы попробовать. Другой обходной путь, который можно найти, — это поместить тикер в обработчик коротких событий, и только когда он перевернется, вы запустите другой. Таким образом, он ограничивает вызов более медленной функции. Так что, как и в функции 23k/sec, inc [somebyte]; jz do_more; iret; — когда какой-то байт откатывается к 0, это означает, что вы прошли 256 итераций и можете вызвать его снова. Это сработало бы, например, до 90 вызовов в секунду, не будучи ужасно медленным в те моменты, когда он не звонит. - person Adam D. Ruppe; 26.11.2014
comment
Хорошо, очень плохо... Были битовые маски задом наперёд. Изменил его на: outportb(0xa1,inportb(0xa1) & 0xfe); outportb(0x21,inportb(0x21) & 0xfb); и теперь он работает просто отлично (ну-ну) Тайминги по-прежнему корректируются, но это проблема с настройкой кода, которая не связана с этим - person user3399848; 26.11.2014
comment
yikes, я посмотрел на ваш код, чтобы проверить это, и я сделал ту же ошибку, что и вы! Но это приятно слышать! - person Adam D. Ruppe; 26.11.2014
comment
Я очень сомневаюсь, что вторая часть этого (порт 0x21) необходима (она включает IRQ 2, который является каскадом для PIC2). Но я полагаю, что это не повредит :) - person user3399848; 26.11.2014