Я обновила ядро
http://ftp.kolibrios.org/users/CleverMo ... kernel.mnt и драйвер
http://ftp.kolibrios.org/users/CleverMo ... sbstor.obj . В драйвере косметическое изменение отладочного вывода с \n на \r\n по заявке
yogev_ezra, его можно даже не обновлять. В ядре - исправления ошибок.
У
0CodErr AMI BIOS старой версии, которая ставит флажок "я владею контроллером, перед использованием сообщи мне", но забывает подписаться на сообщения о смене владельца. Обходится методом "проверяем, подписана ли BIOS на наше сообщение, если нет, то забираем контроль над устройством без спроса". Ну, или перехватом контроля без спроса по истечении таймаута, но зачем ждать, если можно не ждать?
У
Leency тоже AMI BIOS, но поновее лет этак на 6, так что предыдущий баг в нём исправлен. Но есть куда более тонкая проблема:
* исходная ситуация: при загрузке подключено HighSpeed MassStorage-устройство типа флешки; в ходе POST BIOS назначает ему какой-то номер диска;
* ядро получает список USB-контроллеров и начинает их инициализировать. Инициализация EHCI-контроллеров идёт перед компаньонами, чтобы код ядра для компаньонов даже не видел устройств, которые заберёт EHCI;
* инициализация начинается с посылки сообщения BIOS о желании контроля над устройством;
* BIOS получает сообщение, останавливает, деконфигурирует EHCI-контроллер, освобождает все внутренние структуры и забывает про него. В принципе, могла бы и не останавливать, но имеет право;
* код ядра продолжает инициализацию EHCI;
* тем временем, поскольку EHCI-контроллер деконфигурирован, владение флешкой переходит к компаньону;
* контроллер-компаньон всё ещё находится под контролем BIOS. Та обнаруживает новое устройство и начинает работать с ним;
* BIOS обнаруживает, что это MassStorage-устройство, которому уже назначен номер диска. BIOS умная и делает вывод, что это то же самое устройство, только заново переподключённое;
* ...а потому нужно использовать уже заполненные структуры данных;
* ...в одной из которых содержится старый указатель на данные контроллера. Того самого, который остановлен, деконфигурирован и забыт;
* в ходе дальнейшей инициализации BIOS пытается послать команду флешке посредством забытого EHCI-контроллера, используя уже освобождённые области памяти, забитые нулями при освобождении. Упс;
* далее, естественно, код быстро начинает ехать крышей, а поскольку это код BIOS внутри SMM, заканчивается это зависанием системы.
Непостоянность проявления связана с тем, что компаньон - UHCI, который не посылает события о подключениях/отключениях. Чтобы обойти это, BIOS поддерживает фейковую транзакцию чтения одного байта от устройства с несуществующим адресом, которая происходит каждые 256 миллисекунд, всегда завершается ошибкой, о которой контроллер посылает событие. Такой специфический SMM-таймер, при срабатывании которого BIOS перечитывает состояние портов UHCI-контроллеров. Ядро в ходе инициализации EHCI выжидало 50 миллисекунд - сейчас уже нет, но выжидало - для двух контроллеров получается окно в 100 миллисекунд. Если одно событие от 256-миллисекундного таймера попадает в окно - получаем зависание, если нет - ядро успевает отобрать контроль над UHCI.
Лечится путём разделения обработки контроллеров на захват контроля и собственно инициализацию, после чего захват контроля происходит в порядке "сначала компаньоны, потом EHCI", а инициализация - в обратном порядке.
Ошибка с невидимыми устройствами на порту, из которого вытащили LowSpeed-устройство, - техническая, при обновлении статуса порта код EHCI задевал бит питания. При отключении LowSpeed-устройства контроллер возвращал владение в EHCI, обнаруживал, что в EHCI-статусе бит питания сброшен, и честно отключал питание порта. Её я исправила.
Кроме того, теперь ядро не включает USB-накопители в список /bd*. По крайней мере, теоретически.