Что-то написал, но ловлю page fault при поиске разделов. А можно найти место ошибки без отладчика? Используя значение eip и дизассемблер, например, hiew?
По поводу PIO. Чуть выше увидел "PIO possible modes 3" и "PIO set mode 1" для жёсткого диска. Полез в dev_hdcd.inc и так понял, что он только выводит установленный режим. Пробовал зафорсить в биосе PIO mode 4 и 3, но ничего не изменилось. Интересно, это только у меня "PIO set mode 1" ?
Скорость работы с IDE дисками
Ядро грузится по адресу 0x80010000. Смещение в файле kernel.mnt равно eip - 0x80010000.Pathoswithin wrote:Используя значение eip и дизассемблер, например, hiew?
fasm умеет выводить, какие адреса получили метки в исходном коде: опция -s kernel.fas включает генерацию служебной информации, утилита symbols, идущая вместе с fasm, создаст листинг типа
Code: Select all
FindHDD.find: 0x00000000800131D2, defined in detect/dev_hdcd.inc[40]
IDE_controller_3: 0x000000008005D994, defined in {line generated by {line generated by {line generated by {line generated by {line generated by {line generated by data32.inc[519] from kglobals.inc[58]}} from {line generated by data32.inc[519] from kglobals.inc[51]}} from detect/init_ata.inc[120]} from {line generated by {line generated by {line generated by {line generated by {line generated by {line generated by {line generated by kernel32.inc[183] from struct.inc[90]}}} from struct.inc[106]}} from struct.inc[144]}}}}
Сделаем мир лучше!
Всё перепробовал - не получается.
PIO по прежнему зависает после успешной записи. Причём это уже не interrupt storm, виснет мышь, диск спокоен, только часы тикают. Угадайте как лечится? Отключением кэша. Точно так-же ведёт себя и старый драйвер, только читает по одному сектору.
А вот DMA не хочет читать больше одного сектора, соответственно работает только с выключенным кэшем. Содержимое разделов видит, читает файлы до 512 байт.
Сам не справлюсь - в своём глазу бревна не видно.
PIO по прежнему зависает после успешной записи. Причём это уже не interrupt storm, виснет мышь, диск спокоен, только часы тикают. Угадайте как лечится? Отключением кэша. Точно так-же ведёт себя и старый драйвер, только читает по одному сектору.
А вот DMA не хочет читать больше одного сектора, соответственно работает только с выключенным кэшем. Содержимое разделов видит, читает файлы до 512 байт.
Сам не справлюсь - в своём глазу бревна не видно.
Для начала, Bochs отказывается выполнять команду 29h READ MULTIPLE EXT без предшествующей команды 0C6h, настраивающей размер блока. Если хочешь использовать именно блочные команды, добавь настройку куда-нибудь при инициализации. Инициализация по-дурацки сделана, разбита на две части до и после поиска разделов, сохранять такую структуру необязательно.
Сделаем мир лучше!
Проще использовать команды SECTOR(S), разница мизерная, PIO всё равно еле ползает.
1. В настройке DMA ошибка: память, выделенная kernel_alloc, содержит произвольный мусор, а код настройки DMA не трогает старшие два байта структур.
2. DMA без кэша в принципе не может работать в некоторых случаях: если приложение читает файл в память, свежевыделенную через 68.12, под этой памятью просто нет физической памяти - она выделяется в обработчике #PF при первом обращении, но такое обращение есть только в режиме PIO - и контроллер будет писать в нулевую физическую страницу. С малопредсказуемыми последствиями.
3. Обработчики прерываний не учитывают прерывания, приходящие от PIO. Частично это сглаживается тем, что поток, запросивший PIO, висит в цикле активного ожидания, которое может успеть сбросить причину прерывания. Но если прерывания вообще включены, то это ненадёжно изначально и точно сломается при нагрузке на систему, когда есть другие активные приложения.
2. DMA без кэша в принципе не может работать в некоторых случаях: если приложение читает файл в память, свежевыделенную через 68.12, под этой памятью просто нет физической памяти - она выделяется в обработчике #PF при первом обращении, но такое обращение есть только в режиме PIO - и контроллер будет писать в нулевую физическую страницу. С малопредсказуемыми последствиями.
3. Обработчики прерываний не учитывают прерывания, приходящие от PIO. Частично это сглаживается тем, что поток, запросивший PIO, висит в цикле активного ожидания, которое может успеть сбросить причину прерывания. Но если прерывания вообще включены, то это ненадёжно изначально и точно сломается при нагрузке на систему, когда есть другие активные приложения.
Сделаем мир лучше!
какую версию драйвера скачать для замера скорости?
Похоже, я на финишной прямой. После ассенизации обфусцированного кода, драйвер не только стал в полтора раза меньше, но и скорость выросла во всех файловых системах! Теперь я стал догадываться, что кэширование от Марио было в самом драйвере, а disk_cache.inc видимо изначально фирменная турбина от CleverMouse с мощностями гораздо больше 16 секторов. Какими масштабами он оперирует при чтении? Хотел переводить FAT на новые вызовы, а теперь не знаю, стоит ли мучиться.
Осталось получить подробный инструктаж по нескольким вопросам:
1. Я так понимаю, процесс должен становиться на паузу, а обработчик прерывания должен его будить. Код USB полностью не осилил, да и не уверен, что обязательно делать так-же. Что не так с вашим планировщиком и какие есть API ?
2. Как у вас обрабатываются прерывания и что я должен делать с ненужными?
3. В каких случаях используются BIOS диски и нужна ли скорость?
Ещё интересно, какие механизмы для обнуления страниц есть у процессора. Думал, что kernel_alloc обнуляет.
Осталось получить подробный инструктаж по нескольким вопросам:
1. Я так понимаю, процесс должен становиться на паузу, а обработчик прерывания должен его будить. Код USB полностью не осилил, да и не уверен, что обязательно делать так-же. Что не так с вашим планировщиком и какие есть API ?
2. Как у вас обрабатываются прерывания и что я должен делать с ненужными?
3. В каких случаях используются BIOS диски и нужна ли скорость?
Ещё интересно, какие механизмы для обнуления страниц есть у процессора. Думал, что kernel_alloc обнуляет.
1. kernel/trunk/docs/events_subsystem.txt
2. Нужно объяснить железу, что это прерывание обработано, чтобы железо сняло запрос прерывания. Для IDE, кажется, запрос прерывания снимается чтением статусного порта, но надо уточнять по документации.
3. BIOS-диски - работа через int 13h в V86, fallback-механизм, когда нативного драйвера нет, но BIOS умеет работать с железом, и хочется уметь делать хоть что-то. Механизм изначально не предназначен для нормальной работы, выжимать скорость довольно бесполезно. По умолчанию механизм вообще выключён, включается одной из опций загрузочного экрана.
2. Нужно объяснить железу, что это прерывание обработано, чтобы железо сняло запрос прерывания. Для IDE, кажется, запрос прерывания снимается чтением статусного порта, но надо уточнять по документации.
3. BIOS-диски - работа через int 13h в V86, fallback-механизм, когда нативного драйвера нет, но BIOS умеет работать с железом, и хочется уметь делать хоть что-то. Механизм изначально не предназначен для нормальной работы, выжимать скорость довольно бесполезно. По умолчанию механизм вообще выключён, включается одной из опций загрузочного экрана.
Сделаем мир лучше!
read32-функции за раз читают CACHE_LEGACY_READ_SIZE секторов. Сейчас это 16, константу можно менять, но надо иметь в виду, что все эти секторы будут прочитаны, даже если на самом деле не нужны, - слишком большое значение будет зря ждать ненужных данных. read64-функции читают, сколько просят.Pathoswithin wrote:Какими масштабами он оперирует при чтении? Хотел переводить FAT на новые вызовы, а теперь не знаю, стоит ли мучиться.
Запись, как write32, так и write64, откладывается до момента сброса кэша, где последовательные изменённые секторы в любом случае объединяются, при включённом кэше разницы в скорости между write32 и write64 нет.
Сделаем мир лучше!
Значит я должен вызвать CreateEvent -> WaitEventTimeout, ecx=300 -> DestroyEvent, а в обработчике прерывания - RaiseEvent с глобальными переменными. Нужна ли переменная IDE_common_irq_param ? Меня интересует механизм обработки вообще. Вот вызывается обработчик, проверяет его ли это прерывание. А если не его, то чьё? И что за параметр в al ?
В принципе, да, но можно и без глобальных переменных: добавить нужные поля в структуру IDE_DATA, при регистрации attach_int_handler последним параметром передать указатель на IDE_DATA для обработчика, в обработчике достать указатель на IDE_DATA как [esp+4]. Но пока там глобальная блокировка ide_mutex на операции со всеми IDE-дисками, работать будет и с глобальными переменными. Только перед DestroyEvent обнули переменные, а в обработчике прерывания пропусти RaiseEvent, если переменные нулевые - чтобы ничего не сломалось, если прерывание всё-таки придёт после 3s.Pathoswithin wrote:Значит я должен вызвать CreateEvent -> WaitEventTimeout, ecx=300 -> DestroyEvent, а в обработчике прерывания - RaiseEvent с глобальными переменными.
Кажется, IDE_common_irq_handler в зависимости от неё выбирает, какие порты читать.Pathoswithin wrote:Нужна ли переменная IDE_common_irq_param ?
На одном прерывании может висеть несколько устройств - на все PCI-устройства выделено всего 4 IRQ, а устройств обычно больше 4. pcidev покажет распределение по прерываниям. При возникновении прерывания система вызывает все обработчики, зарегистрированные на этом прерывании, потому что у неё нет данных, какое именно устройство сгенерировало прерывание. Возвращаемое значение обработчика 0, если это не его прерывание, и что угодно ненулевое, если его.Pathoswithin wrote:Вот вызывается обработчик, проверяет его ли это прерывание. А если не его, то чьё? И что за параметр в al ?
Сделаем мир лучше!