Скорость работы с IDE дисками

Drive subsystem, filesystem drivers
  • Pathoswithin wrote:Используя значение eip и дизассемблер, например, hiew?
    Ядро грузится по адресу 0x80010000. Смещение в файле kernel.mnt равно eip - 0x80010000.
    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 байт.
    Сам не справлюсь - в своём глазу бревна не видно.
  • Для начала, Bochs отказывается выполнять команду 29h READ MULTIPLE EXT без предшествующей команды 0C6h, настраивающей размер блока. Если хочешь использовать именно блочные команды, добавь настройку куда-нибудь при инициализации. Инициализация по-дурацки сделана, разбита на две части до и после поиска разделов, сохранять такую структуру необязательно.
    Сделаем мир лучше!
  • Проще использовать команды SECTOR(S), разница мизерная, PIO всё равно еле ползает.
  • 1. В настройке DMA ошибка: память, выделенная kernel_alloc, содержит произвольный мусор, а код настройки DMA не трогает старшие два байта структур.
    2. DMA без кэша в принципе не может работать в некоторых случаях: если приложение читает файл в память, свежевыделенную через 68.12, под этой памятью просто нет физической памяти - она выделяется в обработчике #PF при первом обращении, но такое обращение есть только в режиме PIO - и контроллер будет писать в нулевую физическую страницу. С малопредсказуемыми последствиями.
    3. Обработчики прерываний не учитывают прерывания, приходящие от PIO. Частично это сглаживается тем, что поток, запросивший PIO, висит в цикле активного ожидания, которое может успеть сбросить причину прерывания. Но если прерывания вообще включены, то это ненадёжно изначально и точно сломается при нагрузке на систему, когда есть другие активные приложения.
    Сделаем мир лучше!
  • какую версию драйвера скачать для замера скорости?
  • Похоже, я на финишной прямой. После ассенизации обфусцированного кода, драйвер не только стал в полтора раза меньше, но и скорость выросла во всех файловых системах! Теперь я стал догадываться, что кэширование от Марио было в самом драйвере, а disk_cache.inc видимо изначально фирменная турбина от CleverMouse с мощностями гораздо больше 16 секторов. Какими масштабами он оперирует при чтении? Хотел переводить FAT на новые вызовы, а теперь не знаю, стоит ли мучиться.

    Осталось получить подробный инструктаж по нескольким вопросам:
    1. Я так понимаю, процесс должен становиться на паузу, а обработчик прерывания должен его будить. Код USB полностью не осилил, да и не уверен, что обязательно делать так-же. Что не так с вашим планировщиком и какие есть API ?
    2. Как у вас обрабатываются прерывания и что я должен делать с ненужными?
    3. В каких случаях используются BIOS диски и нужна ли скорость?
    Ещё интересно, какие механизмы для обнуления страниц есть у процессора. Думал, что kernel_alloc обнуляет.
  • 1. kernel/trunk/docs/events_subsystem.txt
    2. Нужно объяснить железу, что это прерывание обработано, чтобы железо сняло запрос прерывания. Для IDE, кажется, запрос прерывания снимается чтением статусного порта, но надо уточнять по документации.
    3. BIOS-диски - работа через int 13h в V86, fallback-механизм, когда нативного драйвера нет, но BIOS умеет работать с железом, и хочется уметь делать хоть что-то. Механизм изначально не предназначен для нормальной работы, выжимать скорость довольно бесполезно. По умолчанию механизм вообще выключён, включается одной из опций загрузочного экрана.
    Сделаем мир лучше!
  • Pathoswithin wrote:Какими масштабами он оперирует при чтении? Хотел переводить FAT на новые вызовы, а теперь не знаю, стоит ли мучиться.
    read32-функции за раз читают CACHE_LEGACY_READ_SIZE секторов. Сейчас это 16, константу можно менять, но надо иметь в виду, что все эти секторы будут прочитаны, даже если на самом деле не нужны, - слишком большое значение будет зря ждать ненужных данных. read64-функции читают, сколько просят.
    Запись, как write32, так и write64, откладывается до момента сброса кэша, где последовательные изменённые секторы в любом случае объединяются, при включённом кэше разницы в скорости между write32 и write64 нет.
    Сделаем мир лучше!
  • Значит я должен вызвать CreateEvent -> WaitEventTimeout, ecx=300 -> DestroyEvent, а в обработчике прерывания - RaiseEvent с глобальными переменными. Нужна ли переменная IDE_common_irq_param ? Меня интересует механизм обработки вообще. Вот вызывается обработчик, проверяет его ли это прерывание. А если не его, то чьё? И что за параметр в al ?
  • Pathoswithin wrote:Значит я должен вызвать CreateEvent -> WaitEventTimeout, ecx=300 -> DestroyEvent, а в обработчике прерывания - RaiseEvent с глобальными переменными.
    В принципе, да, но можно и без глобальных переменных: добавить нужные поля в структуру IDE_DATA, при регистрации attach_int_handler последним параметром передать указатель на IDE_DATA для обработчика, в обработчике достать указатель на IDE_DATA как [esp+4]. Но пока там глобальная блокировка ide_mutex на операции со всеми IDE-дисками, работать будет и с глобальными переменными. Только перед DestroyEvent обнули переменные, а в обработчике прерывания пропусти RaiseEvent, если переменные нулевые - чтобы ничего не сломалось, если прерывание всё-таки придёт после 3s.
    Pathoswithin wrote:Нужна ли переменная IDE_common_irq_param ?
    Кажется, IDE_common_irq_handler в зависимости от неё выбирает, какие порты читать.
    Pathoswithin wrote:Вот вызывается обработчик, проверяет его ли это прерывание. А если не его, то чьё? И что за параметр в al ?
    На одном прерывании может висеть несколько устройств - на все PCI-устройства выделено всего 4 IRQ, а устройств обычно больше 4. pcidev покажет распределение по прерываниям. При возникновении прерывания система вызывает все обработчики, зарегистрированные на этом прерывании, потому что у неё нет данных, какое именно устройство сгенерировало прерывание. Возвращаемое значение обработчика 0, если это не его прерывание, и что угодно ненулевое, если его.
    Сделаем мир лучше!
  • для красного словца. вроде, если нет ACPI, то вместо "виртуальных" показываются настоящие физические прерывания, по одному на каждое устройство или ошибаюсь?
  • Ну вот, вроде получился православный и каноничный DMA. Только с PIO так и не понял, если прерывание сбрасывается чтением из порта, то зачем что-то делать в обработчике? И нужны ли 3 одинаковых обработчика?
    CleverMouse, проверяй кошерность.
  • kiv
    Биос записывает в pcicfg номера линий для legacy режима 8259А
  • Who is online

    Users browsing this forum: No registered users and 3 guests