Vesa 2 0 программируем в защищенном режиме


Содержание

Vesa 2 0: программируем в защищенном режиме

Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: 11
Всего: 18

Все зависит от того, какую задачу ты решаешь.

Если ты изучаешь защищенный режим и учишься программировать, то лучше научиться использовать режим виртуального V86. Об этом можно прочить в книге Финогенова. Благодаря нему можно вызывать подпрограммы BIOS, DOS и т.д.

Если ты решаешь конкретную задачу, то тут может быть много вариантов. В первую очередь непонятен твой отказ от DPMI. Если все же нужно прогрраммировать свой супервизор, то, во-первых, можно переключиться в графику до переключения в защиненный режим, ну а если прямо таки необходимо переключать режимы монитора внутри защищенного режима, то можно действительно изучить команды работы с видеоконтроллером. На эту тему множество документации, можно напрямую вызвать BIOS с функцией переключения режима, и трассируя его в отладчике, посмотреть команды in/out, которые переключают режим монитора.

Guest
Дата 20.3.2005, 11:05 (ссылка) | (голосов: ) Загрузка .
Цитата(Chingachguk @ 19.3.2005, 09:13)
изучить команды работы с видеоконтроллером

Да именно это мне и надо!

Shura
Дата 24.3.2005, 22:31 (ссылка) | (голосов: ) Загрузка .

Профиль
Группа: Экс. модератор
Сообщений: 3283
Регистрация: 16.7.2003
Где: Italy

Стандарт DisplayPort 2.0 втрое увеличит пропускную способность

Отраслевая организация Video Electronics Standards Association (VESA) опубликовала спецификации стандарта DisplayPort версии 2.0. С момента принятия предыдущих спецификаций (DP 1.4a) прошло три года. За это время появились мониторы и телевизоры с разрешением 4K и даже 8K. Дальше нужно готовиться к появлению устройств с разрешением свыше 10K, а для этого необходимо повысить пропускную способность интерфейса DisplayPort. Новые спецификации DisplayPort 2.0 делаю это ― пропускная способность в новой версии увеличена в три раза.

К новым возможностям относятся поддержка разрешений выше 8K, более высокие частоты обновления и поддержка HDR при более высоких разрешениях, улучшенная поддержка конфигураций с несколькими дисплеями, а также улучшения, касающиеся дисплеев дополненной и виртуальной реальности, включая поддержку 4K и выше.

Как известно, пропускная способность канала DisplayPort, v1.4a равна 32,4 Гбит/с, при этом каждая из четырех линий работает со скоростью 8,1 Гбит/с. При кодировании 8b/10b это соответствует максимальной полезной нагрузке 25,92 Гбит/с. В DP 2.0 максимальная скорость канала увеличена до 20 Гбит/с, что вкупе с более эффективным канальным кодированием 128b/132b обеспечивает максимальную полезную нагрузку 77,37 Гбит/с. В частности, это делает DP 2.0 первым стандартом, поддерживающим разрешение 8K (7680 x 4320) при частоте обновления 60 Гц с цветовой дискретизацией 4:4:4, в том числе с поддержкой глубины цвета 30 бит на пиксель, необходимой для HDR-10.

Преимущества DP 2.0 доступны как при подключении через собственный разъем DP, так и через разъем USB Type-C, который передает звук и изображение с помощью режима DisplayPort Alt Mode. Интерфейс DP 2.0 обратно совместим с предыдущими версиями DisplayPort и включает в себя все ключевые функции DP 1.4a, в том числе поддержку сжатия визуального потока без потерь (DSC) с прямой коррекцией ошибок (FEC), транспортировку метаданных HDR и другие расширенные функции. Повышенная пропускная способность видеоизображения DP 2.0, передаваемого через разъем USB-C, обеспечивает одновременную высокоскоростную передачу данных USB без ущерба для вывода изображения. DP 2.0 использует уровень физического интерфейса Thunderbolt 3 (PHY).

Новые скорости передачи данных DP 2.0 введены одновременно с протоколом отображения, общим для однопотокового и многопотокового транспорта. Это упрощает вывод на несколько дисплеев, подключенных к порту DP устройства-источника цепочкой или через док-станцию.

В основе нового стандарта DisplayPort 2.0 лежит физический интерфейс Thunderbolt 3. Как известно, в 2020 году Intel сделала этот интерфейс открытым, чем воспользовались инженеры VESA. На практике это будет означать, что протокол DP 2.0 будут поддерживать кабели (и порты) USB Type-C и Thunderbolt 3, что теперь почти одно и то же.

Дисплеи можно будет подключать кабелями USB Type-C, что позволит кроме видеосигнала передавать на дисплеи в режиме DP Alt Mode (или на устройства с дисплеями) данные со скоростью до 20 Гбит/с и питание, например, одновременно с просмотром заряжая аккумуляторы ноутбуков или смартфонов.

При подключении одного дисплея стандарт DisplayPort 2.0 позволит добиться разрешения 16K (15360 × 8460 пикселей) с частотой обновления 60 Гц, HDR и поддержкой 30 bpp с цветовым кодированием 4:4:4 (со сжатием сигнала Display Stream Compression) или разрешения 10K (10240 × 4320) с частотой обновления 60 Гц и 24 bpp с цветовым представлением 4:4:4 (без сжатия).

При подключении двух дисплеев с помощью DisplayPort 2.0 можно получить два монитора с разрешением 8K каждый (7680×4320) с частотой 120 Гц с поддержкой 30 bpp, кодирования 4:4:4 и HDR (со сжатием) или два монитора с разрешением 4K каждый (3840×2160) с частотой 144 Гц с поддержкой 24 bpp, кодирования 4:4:4 (без сжатия).

При подключении трёх дисплеев можно добиться работы трёх мониторов с разрешением 10K каждый (10240 × 4320) с частотой 60 Гц с поддержкой 30 bpp, кодирования 4:4:4 и HDR (со сжатием) или трёх мониторов с разрешением 4K каждый (3840×2160) с частотой 90 Гц с поддержкой 30 bpp, кодирования 4:4:4 и HDR (без сжатия). Это далеко не все допустимые варианты, но они дают представление о возможностях DP 2.0. Все эти возможности появятся на рынке к концу следующего года.

Функции VBE

Для вызова функций VBE используем прерывание 10h

Функция AL=00- Return VBE Controller Information Получение Информации о VBE контролере. Input: AX = 4F00h ES:DI = Буфер 512 байт для структуры VbeInfoBlock Перед вызовом функции нужно записать в поле VESASignature=”VBE2” – дело совместимости.

Для тех, кто не знает: ASCIIZ – это строка, закачивающаяся на 0 BCD десятичный формат. Старшая часть хранится во втором байте, младшая — в первом байте. Каждые 4 бита это числа от 0 до 9. Примеры: 0102h=>1.02; 0300h=>3.0 VideoModePtr – указатель на список WORDов. Значение FFFFh — последний элемент в списке. Каждый Word это номер поддерживаемого видео режима (за исключением FFFFh). Capabilities – возможности видеоадаптера.

Reserved2 – предназначено для хранения OEM такой информации, как строки PTRVESAVersion, NameFirme, NameVESA.

Функция AL=01- Return VBE mode information Получение информации об одном из режимов VBE. Input: AX = 4F01h CX=MODE ES:DI = Указатель на буфер для структуры ModeInfoBlock


VBE в защищенном режиме

В защищенном режиме поддержка функций VESA реализована крайне странно. Во второй версии стандарта введена функция 0AH — RETURN VBE PROTECTED MODE INTERFACE, которая позволяет вызывать ряд функций, но функционал её очень мал. Зато появился линейный буфер LFB. Почти вся видео память доступна одним окном в верхних адресах физической памяти. Есть расширение “PMID”, но оно может и отсутствовать. Расширение “PMID” введено в третьей версии стандарта.

Для проверки поддержки БИОСом видео карты “PMID”, следует произвести поиск сигнатуры “PMID” в диапазоне адресов 0C0000h-0DFFFFh “PMID” – это расширение VESA 3, поэтому может и отсутствовать. Структура PMID такова:

Ссылки

1. VBE версия 3.0 от ассоциации VESA
vbe3.pdf
2. VBE версия 2.0 от ассоциации VESA
vbe20.txt
3. VBE версия 1.2 от ассоциации VESA
vesasp12.txt

Статья ASM для х86. (2,0,) Реальный и Защищённый режимы работы процессора

Marylin

Mod.Assembler

В глазах процессора, мир существует в виде 1-байтных ячеек памяти. Будь-то физическое устройство (типа клавиатура), или наша логическая программа – для процессора это группа из нескольких байт. Считаю, что изучение ассемблера нужно начинать именно с организации памяти, поскольку 90% времени работать придётся именно с нею. Совсем не обязательно зубрить наизусть названия регистров – это придёт как озорение само-собой. Лучше направить энергию на изучение почвы, по которой собираемся ходить.

На данный момент х86 процессоры могут работать в четырёх режимах. Мы рассмотрим только первые два из них, как более распространённые:

  1. Real-Mode — реальный, системная поддержка в виде BIOS;
  2. Protected-Mode — защищённый, поддержка Win и никсы;
  3. Virtual-Mode — для эмуляции реального режима, из защищённого;
  4. System-Management-Mode – реальный из защищённого, без эмуляции.

2.0. Память в реальном режиме

В Real-моде, программист полноправный хозяин системы и имеет дело только с физической памятью. Ему доступны буквально все инструкции процессора, прямой доступ к портам оборудования, и многое другое. Здесь не задают вопросов типа “Вы уверены? Да/Нет”, и за необдуманные действия ответственность несёте только вы. Бонусом идёт программирование вообще без системы, на одних только функциях биос (благо его и сейчас эмулируют все EFI). Основной задачей ОС является как-раз абстрагирование пользователя от реальных устройств, которые он может по неосторожности вывести из строя. Одним словом, зевать от скуки тут не приходится, и нужно быть всегда на чеку.

У первых процессоров 8086 шина-адреса(A) была 20-битная. Такая ширина позволяет адресовать всего FFFFF байт памяти. Запускаем виндовый калькулятор, переводим его и BIN, и введём 20 единиц. Именно такой вид имела шина(А) на физическом уровне.

Посмотрим на рисунок, где изображены проводники системной шины, как они идут с процессора. Шина эта – мультиплексная, т.е. единственная и для адреса, и для данных. Сначала на шину выставляется адрес, после которого по ней-же отправляются и данные:

Как видим, увеличение разрядности шины увеличивает кол-во адресуемых ячеек памяти. Это хорошо.. Но регистры ЦП были в то время 16-битными (без приставки ‘E’), и ими можно было дотянуться максимум до 64 Кб физической памяти (см.рис). Как вместить в 16-битный регистр 20-битный адрес? Было решено разбить всю память на логические сегменты, и адресовать её через регистровую пару в формате сегмент+смещение. Формула и вид получился такой:

Здесь видно, что три средние тетрады перекрываются. Для сегментных регистров типа СS остаются только смещённые влево 4-бита, которыми можно выбрать один из 16-ти сегментов. Под смещение выделяется как и прежде 16-бит, а это 64 Кб внутри выбранного сегмента памяти. Таким образом, размер сегмента в реальном режиме равен 64К, а всего сегментов =16. В сумме они дают: 64К х16=1М памяти.

Однако это не табу, и ничто не мешает нам перевернуть ‘пластинку’ наоборот, ведь мы имеем дело с логическим адресом. Тогда получим 65.536 сегментов, по 16-байт в каждом. Эти 16-байт назвали ‘параграф’ и это мин.размер одного сегмента в R-моде. Такая картина позволяет операционной системе (например DOS) эффективно распределять память, которой и так с гулькин-нос. Сегменты по 64К бывают только на бумажке, а на практике — это просто макс предел, который выделяет ОС под один сегмент.

Во-первых, среди одного мегабайта, 64К непрерывной памяти у системы может и не быть, а во-вторых — если у программы в сегменте-данных всего три строчки текста, зачем выделять для них 64К памяти? Система просто выравнит эти данные до 16-байтного параграфа, и вручит их пользователю. Если (в процессе работы) программе понадобится ещё доп.памяти, то программист должен запросить её у системы, и она без проблем выделит из своего резерва кусок (если таковой остался).

На рисунке выше, я выделил красным одну из линий шины-адреса и вставил туда ключ. Эту линию назвали А20 , поскольку она идёт следующей от 20-битного адреса 0-19. Программист обязательно должен включить её при переводе процессора из реального в защищённый режим работы, иначе не видать нам четырёх гигов памяти. Если линия А20 отключена (а она отключена по-умолчанию), то после 20-битного адреса 0xfffff счётчик адресов опять сбросится в нуль, не давая нам вылезти из первого мегабайта. На аппаратном уровне линией А20 управляет чипсет, через порт 92h системной логики.

Асматикам старой школы издавна не давала покоя мысль, поиметь 4 гига в реальном режиме. Это открывало большие перспективы, поскольку в R-моде нет многозадачности, и все ресурсы процессора полностью принадлежат только одному приложению. На современных процессорах, оно будет летать как истребитель. И нужно сказать, что энтузиастам это удалось! 4Gb памяти в реальном режиме это не сказка, а недокументированный режим, который назвали UnReal-Mode (можете погуглить).

Если коротко, то выделяется один сегментный регистр (как правило ES), который будет играть роль торпеды в 4Gb пространство. Для него подготавливается соответствующий дескриптор с базой(0) и лимитом в 4Gb. Запихать этот дескриптор в ES находясь в реальном режиме процессор не позволит, поэтому нужно перевести его в защищённый режим, обновить ES и вернуться обратно в R-моду. Теперь через ES можно гулять по 4G пространству, как у себя дома. Позже, когда приём вылез из хакерских нор и получил огласку, его взяли на вооружение чуть-ли не все досовские игры. В практической части мы ещё вспомним про UnReal, а пока топаем дальше..

2.1. Память защищённого режима

Процессор переводится в Рrotected-моду всего одним\нулевым битом в регистре CR0 . Сразу-же о сегментной памяти реального режима можно забыть. Хотя сегменты по-прежнему и присутствуют, они несут в себе уже другую нагрузку. Адрес теперь не состоит из двух составляющих Seg:Offs , а вся память приобретает плоский FLAT вид. В игру вступают защитные механизмы, которыми природа щедро одарила этот режим.

Процессоры изначально заточены под сегментную организацию памяти, это наследие докатилось и до наших дней. Более того, они не имеют механизмов запрещения сегментации, тогда-как страничную трансляцию можно включать\выключать битом(31) регистра управления процессором CR0 . У процессора всегда было и будет шесть сегментных регистров, которые он использует в качестве указателей на определённый блок памяти в Win32 программах:

  • CS – Code Segment – сегмент кода;
  • DS – Data Segment – сегмент данных;
  • SS – Stack Segment – сегмент стека;
  • ES – Extended Segment – дополнительный для данных;
  • GS – General Segment – добавлен для РМ-моды
  • FS – Безымянный (сл.по алфавиту) для РМ-моды.

Сегментные регистры нельзя недооценивать. Они имеют 2-байтную видимую для прикладного программиста, и 8-байтную скрытую часть. Итого получаем 10-байтный регистр. Видимую часть назвали‘Селектор’, а скрытую – ‘Дескриптор’. Во-втором томе доках Интела есть описание дескриптора, фрагмент которого представлен ниже.

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

  1. Каждый сегмент памяти описывает его собственный дескриптор. Размер дескриптора 8-байт (64-бита). В нём хранится линейный адрес начала сегмента в памяти (Base=32-бит), размер сегмента (Limit=20-бит), и атрибуты защиты (Access=12-бит).
  2. При обращении к сегменту, системные механизмы защиты сначала проверяют значение смещения, которое не должно превышать лимит. То есть адрес не должен выходить за пределы сегмента, в противном случае ЦП сгенерит исключение ‘AccessViolation’ — ошибка доступа.
  3. Как выделенными для лимита 20-ю битами определить размер сегмента в 4Gb? Ответ — лимит указывается в единицах измерения! Среди атрибутов, в дескрипторе имеется т.н.бит гранулярности(G). Если он сброшен, то единицей измерения считается байт, если взведён — то 4К-байтная страница. Отсюда следует, что при G=0 размер\лимит сегмента ограничен значением 1Мб, а при G=1 включается множитель 4Кб, и получаем 4Gb.



Это так.. к сведению. Лучше посмотрим на схему ниже..
В аппаратной части подсистемы памяти фигурируют 3 типа адресов: логический, линейный и физический. Из этой троицы, ЦП оперирует только логическим адресом, который использует в своих программах программист. Для трансляции остальных адресов, процессор имеет блок управления памятью MMU — Memory Management Unit.

Логический адрес состоит из сегмента+смещения, например CS:EIP, DS:ESI, ES:EDI и т.д.. MMU собирает эти составляющие, преобразуя лог.адрес в линейный, в диапазоне 0..N. Если в регистре CR0 включён страничный режим, то в дело вступает транслятор страниц в MMU. Если-же страничное преобразование выключено, то линейный адрес совпадает с физическим (здесь он выключен). На рисунке ниже, в сегментных регистрах лежит 2-байтный селектор сегмента, адрес процессора – это смещение, сегментацией и трансляцией занимается блок MMU процессора, РА – это PhysicalAddress:

Таким образом, память в защищённом режиме работы процессора – вся линейна. Сегментные регистры служат только для защиты доступа к памяти. В дескрипторах всех сегментных регистров, всегда устанавливается база(0) с максимальным лимитом в 4Gb, и никак иначе. Транслятор страниц постоянно включён, и разбивает большие сегменты на мелкие страницы памяти, размером по 4К-байт каждая. Любая из страниц имеет свои атрибуты защиты, не считая защиты верхнего уровня родительских сегментов. Это огромная корпорация, которая следит за всеми, и жёстко пресекает любое нарушение установленных прав. Одним словом – защищённый режим это руль! ..который позже согнём в баранку.
—————————————-

PS\\: Кстати в отладчике OllyDbg можно наглядно увидеть значения дескрипторов в шести сегментных регистрах. Как-видим, особняком стоит тут только FS , который система всегда держит при себе, и программисту трогать его не советует. Это указатель на системную таблицу РЕВ — Process Environment Block, куда система сбрасывает информацию о текущем процессе – т.н. окружение процесса.

VESA V >

Contents

VESA Functions

You’ll want to look in the VESA VBE docs for these functions: All VESA functions return 0x4F in AL if they are supported and use AH as a status flag, with 0x00 being success. This means that you should check that AX is 0x004F after each VESA call to see if it succeeded.

INT 0x10, AX=0x4F00 Get Controller Info. This is the one that returns the array of all supported video modes.

INT 0x10, AX=0x4F02, BX=mode, ES:DI=CRTCInfoBlock

Set Video Mode. Call this with the mode number you decide to use. If you choose a mode that makes use of a linear framebuffer, you should OR the mode number with 0x4000. This sets the «Use LFB» bit in the mode number. Set the bit 11 of BX to instruct the BIOS to use the passed CRTCInfoBlock structure, see the specification for more information. BIOSs can switch to protected mode to implement this, and might reset the GDT. This is observable on QEMU 2.2.x.

Will it work with Bochs?

For VBE to work in Bochs you need the «VGABIOS-lgpl» BIOS and have a version of Bochs that was compiled with the --enable-vbe option. See Vesa Information in Bochs thread for more info. Also read about Bochs Graphics Adaptor.

How to pick the mode I wish?

VESA stopped assigning codes for video modes long ago — instead they standardized a much better solution: you can query the video card for what modes it supports, and query it about the attributes of each mode. In your OS, you can have a function that you call with a desired width, height, and depth, and it returns the video mode number for it (or the closest match). Then, just set that mode

Here’s a sample code, assuming you have a VirtualMonitor already . Basically, you will scan the ‘modes list’ referenced by the VbeInfoBlock.videomodes[] and then call ‘get mode info’ for each mode. You can then compare width, height and colordepth of each mode with the desired one.

Common Mistakes

There’s some mistakes that beginners seem to make fairly often when they first start working with VBE.

VESA Defined Mode Numbers

For older versions of the VBE specification (VBE 1.0, VBE 1.1 and VBE 1.2) VESA defined some standard mode numbers. For example, mode 0x0113 was 800 * 600 * 15-bpp. In VBE 2.0 these mode numbers were deprecated — VESA decided not to define any more of them, told video card manufacturers they don’t need to use the old standard mode numbers, and told programmers to search for the mode they want without relying on any of the old standard mode numbers. Despite this, it’s still possible to find obsolete information on the internet suggesting to use these old standard mode numbers.

Use «Bytes Between Lines»

People tend to assume that pixel data is contiguous (e.g. line 1, then line 2, then line 3, . ). This isn’t always the case, and for a variety of reasons there may be padding between lines (e.g. line 1, padding, then line 2, padding, then line 3, . ). The «Get Mode Information» VBE function returns the number of bytes between lines, and this value should be used. For example, for a 640 * 480 * 16-bpp v to fill the entire display, and you should fill each line separately to avoid writing to any padding.

Note that (for VBE 3.0) there may be 2 «bytes between lines» values returned by the «Get Mode Information» VBE function. The first one is used when the video mode is setup for bank switching and the second one is used when linear frame buffer is being used. For older versions of VBE there is no «bytes between lines for linear frame buffer» value, and the «bytes between lines for bank switched» value is used for both bank switching and linear frame buffer.

Don’t Assume Pixel Formats

Usually pixel data is in «RGB» format, but this isn’t always the case. A pixel can be in «BGR» format or anything else, and may not even use Red, Green and Blue components — it could use «YUV» where there’s one luma/brightness component (Y) and two chrominance (UV) components. Always check the «memory_model» field and (for 15-bpp and higher video modes) all of the «component mask» and «field position» fields (e.g. «red_mask_size», «red_field_position», etc) in the structure returned by the «Get Mode Information» VBE function.

Don’t Assume Unused Bits Are Unused

For some colour depths there’s «unused» bits in the pixel data (one «unused» bit per pixel in 15-bpp modes, and 8 «unused» bits per pixel for 32-bpp modes). These unused bits may actually be used by some video cards for a variety of extra features. For one example, I know of a video card where (in 15-bpp modes) if the highest/unused bit is set then it uses the lowest 8 bits of the pixel data as an index into the palette.


Don’t Assume VGA Compatibility

For 8-bpp video modes people assume that they can use the VGA I/O ports to change the palette. It’s much better to use the VBE functions instead, but if you don’t then at least test if the video mode uses VGA I/O ports by testing the «VGA compatible mode» flag (bit 5) in «mode_attributes» field returned by the «Get Mode Information» VBE function.

In a similar way, for 4-bpp «planar» video modes some people assume that the VGA I/O ports can be used to switch between planes rather than testing if the «VGA compatible mode» flag is set first.

Don’t Assume The Monitor Supports A Video Mode

We all like pretty graphics and high resolution video modes. Unfortunately, if VBE says that a video mode is supported by the video card it does not mean that the video mode is also supported by the monitor. VESA has defined 2 video mode timings that are meant to be supported by all monitors (640 * 480 standard VGA timing and 720 * 480 standard VGA timing). For all other video modes you should either use EDID to find out if the monitor supports the video mode’s timing (or not), or provide a way for the user to test the video mode and change it if it doesn’t work. This is the approach used by Windows, with a dialog box appearing with the option to accept or revert. No action within 15 seconds reverts. Just an idea ;).

Using EDID for this purpose is complicated. Unless you provide a «CRTC information block» structure when you set the video mode you can’t be entirely sure what timing the video card will use; and only some video cards that support VBE 3.0 support the «CRTC information» correctly.

The other alternative is to only ever use video modes that (should) use 640 * 480 and 720 * 480 standard VGA timing. For video modes with lower horizontal resolutions the video card sends the each pixel twice, and for video modes with lower vertical resolutions the video card sends the each row of pixels twice (called «double scanning»); and in both cases the video timing is the same as it would be for the corresponding higher resolution video mode. This gives the following list of «safe» resolutions:

  • 720 * 480
  • 640 * 480
  • 360 * 480 (actually uses «720 * 480» timing)
  • 320 * 480 (actually uses «640 * 480» timing)
  • 720 * 240 (actually uses «720 * 480» timing)
  • 640 * 240 (actually uses «640 * 480» timing)
  • 360 * 240 (actually uses «720 * 480» timing)
  • 320 * 240 (actually uses «640 * 480» timing)

Colour depth doesn’t/shouldn’t effect the video timing signals. This means that the best possible safe video mode would be 720 * 480 * 24/32-bpp.

Don’t Read From Video Memory

Reading from the video memory is slooow! Use double buffering instead.

Vesa 2 0: программируем в защищенном режиме

Эта статья представляет собой некоторое введение в разработку программ, функционирующих в защищённом режиме процессора. Здесь будут поставлены основные задачи любой программы, работающей в защищённом режиме, и приведены их решения. В основном, программы будут написаны на языке FASM.

Режимы работы процессора Intel 80386

С появлением процессора Intel 80386 возникла архитектура IA32. Она предполагала появление нового режима работы процессора — защищённого («Protected Mode«). Для совместимости с предыдущими процессорами линейки Intel 80×86 процессор 80386 не запускался сразу в защищённом режиме, а работал в так называемом реальном режиме («Real Mode«). Кроме этого, у каждого режима есть один или несколько подрежимов. Разберём их.

В этом режиме процессор находится сразу после нажатия кнопки «Power» компьютера. Доступ к памяти в реальном режиме осуществляется конструкцией » сегмент:смещение «, которая описывает логический адрес. Значение сегмента, как и смещения, лежит в пределах от до 0FFFFh.

Так как адресоваться можно только в пределах одного сегмента, то максимальный размер сегмента равен 64 килобайт. Физический адрес, который выставляется на адресную шину процессора, считается по формуле:

линейный адрес = сегмент * 16 + смещение

В реальном режиме процессоров 80186 и 8086 значение сегмента лежало в пределах от до 0F000h. Таким образом, максимальный выставленный адрес на адресную шину равен 0FFFFFh, что соответствует (2^20)-1, т.е. 1 мегабайту.

Конечно, поначалу объём такой памяти казался колоссальным, но со временем одного мегабайта стало не хватать. С появлением процессора 80286 стал доступен так называемый блок памяти UMB, начинающийся с адреса 0FFFFh:0010h и заканчивающийся адресом 0FFFFh:0FFFFh (65520 байт за пределами одного мегабайта). Теперь можно было переконфигурировать операционную систему MS-DOS так, чтобы она занимала этот блок, освобождая в оперативной памяти 64 килобайт.

Этот режим имеет сложную конструкцию по сравнению с реальным. Логический адрес представляется конструкцией » селектор:смещение «. Селектор находится в пределах от до 0FFFFh (на самом деле, селекторов в 4 раза меньше — об этом подробнее в следующих статьях). Смещение, в отличие от реального режима, является 32-разрядным, что позволяет адресовать сегменты размером 4 гигабайт. Логический адрес преобразуется в линейный по следующей схеме:

линейный адрес = база сегмента + смещение

Линейный адрес в дальнейшем выставляется на адресную шину, если не включен режим страничной адресации. В противном случае линейный адрес преобразуется в физический, и только после этого выставляется на адресную шину. Кроме этого, защищённый режим позволяет организовать виртуальную память, достигающую размера до 64 терабайт и зависящую лишь от объёма жёсткого диска (например, тот же файл подкачки в Windows реализует виртуальную память). В защищённом режиме функционируют практически все современные операционные системы.

Мультизадачный подрежим защищённого режима

Этот режим позволяет организовать мультизадачность, то есть возможность одновременного выполнения нескольких задач или многопользовательской системы.

Режим виртуального 8086

Это также подрежим защищённого режима, который позволяет создать виртуальную машину, функционирующую как будто бы она находилась в реальном режиме, но, на самом деле, работающей в защищённом режиме.


Это особый подрежим реального режима. Процессор находится в реальном режиме, но адресуется к памяти путём конструкции » селектор: смещение «. Таким образом доступна память выше 1 мегабайта. В дальнейшем будет рассматриваться защищённый режим и его подрежимы.

Первая программа: переход в защищённый режим

Переход в защищённый режим осуществляется установкой бита регистра CR0. Переход в реальный режим осуществляется сбросом того же нулевого бита. Рассмотрим программу, которая выполняет эту операцию (язык — Flat Assembler):

use16 ; Используются 16-разрядные команды

; Мы находимся в реальном режиме

mov eax, cr0 ; Считываем значение регистра CR0
or al, 1 ; Устанавливаем нулевой бит
mov cr0, eax ; Записываем новое значение CR0

; Мы в защищённом режиме

mov eax, cr0 ; Считываем значение CR0
and al, 0feh ; Сбрасваем нулевой бит в 0
mov cr0, eax ; Переходим в реальный режим

; Мы в реальном режиме

ret ; Выходим из программы

oleg1973
Дата 25.3.2005, 15:08 (ссылка) | (нет голосов) Загрузка .
Илон Маск рекомендует:  Как средствами api реализовать в richedit разноцветный текст

Однако эта программа является совсем «сырой», потому что в ней нельзя реализовать зацикливание. Если написать команды вроде hlt или jmp $, то по срабатыванию первого же прерывания компьютер перезагрузится.

В нашем случае команды срабатывают достаточно быстро, но не исключено, что в промежутке между выполнением каких-либо команд нашей программы прерывание всё-таки сработает, что приведёт к моментальному сбою и перезагрузке. Поэтому следует позаботиться о прерываниях. Итак, посмотрим ещё раз листинг. Это нельзя назвать первой программой (скорее, она пошла бы за нулевую), поскольку в ней не реализуются основные действия по переходу в защищённый режим. Чтобы полноценно перейти в защищённый режим с минимальными настройками, нужно выполнить следующие действия:

Илон Маск рекомендует:  Что такое код getdoubleclicktime

1. проверить, возможно ли переключиться в защищённый режим;

2. инициализировать таблицы дескрипторов;

3. запретить прерывания (как маскируемые, так и не маскируемые);

4. открыть линию A20;

5. загрузить регистры управления памятью;

6. установить нулевой бит (далее он будет называться PE) регистра CR0;

7. выполнить переход на 32-битный сегмент кода, переопределив регистр CS.

Но первой программе достаточно выполнить действия 3, 4, 5. Тогда её зацикливание не приведёт к перезагрузке компьютера. Разберёмся в каждом действии.

Запрещение прерываний предохраняет нас от перезагрузки. Прерывания делятся как на маскируемые, так и немаскируемые. Чтобы запретить маскируемые прерывания, надо сбросить флаг IF регистра EFLAGS командой cli, разрешение же прерываний выполняется командой sti. Немаскируемые прерывания запрещаются несколько иначе. Для этого существуют два способа: программирование регистров контроллера прерываний (этот способ будет рассмотрен несколько позже) или изменение седьмого бита порта 70h: если бит установлен, то прерывания запрещены, если бит сброшен — прерывания могут выполняться.

Теперь зададимся вопросом, в чём заключается функция линии A20, и что это такое. Линия A20 — одна из 32 адресных линий. При загрузке компьютера линия A20 закрыта. Это приводит к генерации 20-разрядных адресов (то есть всё адресное пространство получается равным (2^20)=1 мегабайт). Введено это для совместимости с процессором 8086: таким образом, пытаясь записать по линейному адресу 12345678h, мы, на самом деле, запишем по адресу 00045678h, что может привести к совершенно неожиданному результату. Поэтому для полноценного функционирования 32-разрядного приложения линия A20 обязательно должна быть открыта. Осуществляется это установкой бита 1 порта 92h, закрытие линии A20 — сброс этого бита.

С последним действием читатель уже знаком, и оно уже не должно вызывать у него вопросов.

Итак, рассмотрим листинг нашей новой, первой, программы, в которой уже реализует-ся небольшой цикл. Строки, которые добавлены к предыдущему листингу, помечены звёз-дочкой (*).

; Мы находимся в реальном режиме
; Запретить маскируемые прерывания

; Запретить немаскируемые прерывания (NMI)

; Открыть линию A20


; Переключиться в защищённый режим

; Теперь находимся в защищённом режиме
; Небольшой двойной цикл

; Переключиться в реальный режим

mov eax, cr0
and al, 0feh
mov cr0, eax

; Закрыть линию A20

; Разрешить немаскируемые прерывания (NMI)

; Разрешить маскируемые прерывания

; Мы снова находимся в реальном режиме

Убедиться в том, что программа работает, можно, запустив исполняемый файл из чистого MS-DOS. Если программа корректно завершается, то всё в порядке.

Однако могут возникнуть и следующие проблемы:

1. компьютер «зависает»;

2. компьютер перезагружается.

Это может возникнуть из-за следующих причин:

1. программа запущена в режиме V86 (режим виртуального 8086);

2. программа запущена в защищённом режиме или под конкретной операционной системой.

Поэтому перед запуском любой программы, работающей в защищённом режиме, следует проверить возможность дальнейшей работы программы. Об этом будет рассказано дальше.

Проверка возможности перехода в защищённый режим

В предыдущей главе у нас возникла следующая проблема: программа не распознаёт то, что она находится в защищённом режиме или режиме V86, что приводит к зависанию системы или её перезагрузке. Если же мы попытаемся запустить программу под управлением операционной системы Windows, то Windows отловит попытку программы перейти в защищённый режим и предложит перезагрузиться в режиме эмуляции MS-DOS (для платформы 9x), либо завершит работу программы принудительно (платформа NT).

Итак, для проверки того, что мы действительно находимся в реальном режиме, следует выполнить следующие операции:

1. проверить нулевой бит регистра CR0;

2. убедиться, что не загружена операционная система Windows.

Первая операция осуществляется прямым чтением регистра CR0 с дальнейшей проверкой нулевого бита регистра EAX, AX или AL. Если бит не установлен, то мы находимся в реальном режиме. В противном случае дальнейшее выполнение программы становится бессмысленным.

Второе действие осуществляется вызовом функции 1600h прерывания 2fh. Эта функция позволяет получить текущую версию операционной системы Windows. Если после вызова функции в регистре AL содержится ноль, то операционная система не загружена. В противном случае, опять же, нашей программе бессмысленно продолжать какие-либо дальнейшие действия.

Рассмотрим пример следующей программы. Она является модификацией предыдущей программы, все новые инструкции помечены звёздочкой (*).

; Проверка того, что мы действительно в реальном режиме

mov eax, cr0 ;* проверка нулевого бита
test al, 1 ;* регистра CR0
jz no_pm ;*

; Вывести сообщение об ошибке


mov ah, 09h ;* функция DOS 09h
mov dx, pm_msg ;* вывод строки
int 21h ;*
ret ;* и выйти

; Проверка: не запущена ли программа под Windows

mov ax, 1600h ;* функция 1600h мультиплексорного
int 2fh ;* прерывания — получить версию Windows
test al, al ;* если не 0 — ошибка
jz no_windows

; Вывести сообщение об ошибке

; Мы точно находимся в реальном режиме
; Запретить маскируемые прерывания

; Запретить немаскируемые прерывания (NMI)

; Открыть линию A20

; Переключиться в защищённый режим

; Теперь находимся в защищённом режиме
; Небольшой двойной цикл

; Переключиться в реальный режим

mov eax, cr0
and al, 0feh
mov cr0, eax

; Закрыть линию A20

; Разрешить немаскируемые прерывания (NMI)

; Разрешить маскируемые прерывания

; Мы снова находимся в реальном режиме

ret ; завершить программу

db «Error: already running in protected mode!$» ;*

Vesa 2 0: программируем в защищенном режиме

Используй режимы с линейной адрессацией. Они задаются если выставить битик 0x4000 . Далее необходимо через веса-биос получить адрес всего экрана. Естественно, до этого надо войти в защищенный или хотя бы флэт режим. И можно работать со всем экраном сразу. Да, для всего этого надо грузиться без емм и не под виндой . Регстры можно использовать в 32 битном варианте и в реальном режиме. Кстати номер режима экрана и разрешение могут меняться — намного корректней перебирать режимы, пока не найдешь подходяшей.

Гость_VIRUS_*
Гость_VIRUS_*

ЗЫ. Рекомендую книжку Кулакова Программирование на аппратном уровне. издательство питер. Там кстати описано и как флэт режим включать
ЗЗЫ. Для работы по сями могу порекомендовать пакет Watcom — скачать можно на openwatcom.org

Гость_Wowik_*

Ну пусть будет 10H. 10 в шестнадцатеричной системе . ) .. На 10 в 10 системе контроллер прерываний болтается обычно (IRQ2). Есть опячатка паскаль — тмт а не тнт.

Поставить точку —
point_adress=linear_adress + (offset_y * width +offset_x)*byte_per_pixel
и по этому адрессу загоняем 255 255 255
linear_adress — собственно и есть абсолютный адресс экрана в физической памяти — 32 битное значение, которое мы и получим из инфы по данному режиму по смешению 28H
offset_x offset_y — смешение точки, width — ширина в пискелях для установленного режима, byte_per_pixel — кол-во байт на пиксель.

Нашел пару статей по теме , первоисточники почему то не пашут . закинул эти статьи на tanais.org/vesa1.zip tanais.org/vesa2.zip Пользуйся

Илон Маск рекомендует:  Что такое код msql_field_seek
Гость_Wowik_*

Мдя .
Регистры начиная с 386 процессора 32 битные вообше то. Для работы с 32 битным указателем (адресоваться к памяти через 32 бита) — необходимо что бы сегментый регистр(через который ты работаешь) был настроен на работу с дескрипторами (и содержал собственно индекс нужного дескриптора), а не адрессами. Это возможно сделать через защищенный режим. Можно настроить и вернуться обратно в реал режим — это способ работы называется флэт режим. То есть ты получишь в реальном режиме возможность работать со ВСЕЙ памятью через выбранный сегментный регистр. Другой вариант это работать в защищенном режиме — тут вариантов 2 . а) использовать операционку которая работает в защищенном режиме б) использовать экстендер, который перед работой программы загоняет комп в защищенный режим (при этом он вешает свой менеджер памяти, эмулятор реал режима для прерываний и многое другое, что позволяет пользоваться всеми прелестями защищенного режима и в то же время не потерять услуги родной 16 битной операционки — обычно ДОСа). Для варианта б) я бы посоветовал использовать tmt pascal если пишешь на паскале или watcom c++ если на сях. Благо оба пакета абсолютно бесплатные и вполне професиональны . Могу назвать вариант в) — войти в защищеный режим самостоятельно но для начала я бы его не рекомендовал

32 битные регистры — с ними можно работать и в реальном режиме, вот только адресоваться через них нельзя просто так (не просто — флэт см выше)
Принято что 32 битный регистр называется так же как и 16 битный но начинается с буковки E — например EAX EBX ECX EDX EBP ESP ESI EDI EIP . младшии 16 бит и есть соответственно AX BX и тд
Например
mov EAX,1024*1024
mov ECX,ds:[EAX]
or ECX,ECX
stosd
и тд
собственно префикс 66 поставит в таком случае сам ассемблер.

Подробней на эту тему рекомендую прикупить какую нибудь книжку — по защищенному режиму x86 архитектуры . Если очень интересно и с аглицким проблем нет, то лучше всего это изучать по интеловским манулам.

А насчет монитора — странно все это. Похоже на то что частота для монитора в том режиме выставляется непосильная. А режим как выставляешь — точно этот режим 800х600 .. начиная с VESA 2.0 номера режимов и разрешение не стандартизируется — вначале необходимо найти нужный режим перебором. В номер режима входит
15ый бит — если 1 то при входе в режим надо очистить экран
14ый бит — если 1 то включена линейная адресация
8ой бит — если 1 то данный режим работает через весу

Кстати думаю надо бы в асм все же перенсти эту тему, паскаль тут вроде не причем

Тема 5.2. Адресация памяти в защищенном режиме

В защищённом режиме, также как и в реальном, существуют понятия логическогои физического адреса. Логический адрес в защищённом режиме (иногда используется термин «виртуальный адрес») состоит из двух 16-разрядных компонент — селектора и смещения. Селектор записывается в те же сегментные регистры, что и сегментный адрес в реальном режиме. Однако преобразование логического адреса в физический выполняется не простым сложением со сдвигом, а при помощи специальных таблиц преобразования адресов.

В первом приближении можно считать, что для процессора i80286 селектор является индексом в таблице, содержащей базовые 24-разрядные физические адреса сегментов. В процессе преобразования логического адреса в физический процессор прибавляет к базовому 24-разрядному адресу 16-разрядное смещение, т.е. вторую компоненту логического адреса.

На рис.21 показана сильно упрощённая схема преобразования логического адреса в физический.

Рис. 31 Упрощённая схема преобразования логического адреса в физический в защищённом режиме

Такая схема формирования физического адреса позволяет непосредственно адресовать 16 мегабайт памяти с помощью 16-разрядных компонент логического адреса.

Селектор — это не сегментный адрес. Это индекс, с помощью которого процессор извлекает из специальной таблицы 24-разрядный базовый адрес сегмента. В реальном режиме мы имеем дело с сегментным адресом и смещением, а в защищённом — с селектором и смещением.

На самом деле не все 16 бит селектора используются для индексации по таблице базовых адресов. В качестве индекса выступают старшие 13 бит. Два младших бита (бит 0 и бит 1) используются системой защиты памяти, о чём мы подробно поговорим в следующем разделе. Бит 2 позволяет выбирать для преобразования адреса один из двух типов таблиц преобразования адресов. Полный формат селектора показан на рис. 22

Рис. 32 Формат селектора адреса

На этом рисунке два младших бита обозначены как RPL (Requested Privilege Level). Это поле является запрошенным программой уровнем привилегий и его мы будем обсуждать позже. Поле TI (Table Indicator) состоит из одного бита. Если этот бит равен нулю, для преобразования адреса используется так называемая глобальная таблица дескрипторов GDT (Global Descriptor Table), в противном случае — локальная таблица дескрипторов LDT (Local Descriptor Table).

Таблица дескрипторов — это просто таблица преобразования адресов, содержащая базовые 24-разрядные физические адреса сегментов и некоторую другую информацию. То есть каждый элемент таблицы дескрипторов (дескриптор) содержит 24-разрядный базовый адрес сегмента и другую информацию, описывающую сегмент.


Таблица GDT — единственная в системе. Обычно в ней находятся описания сегментов операционной системы. Таблиц LDT может быть много. Эти таблицы содержат описания сегментов программ, работающих под управлением операционной системы, т.е. отдельных задач. В каждый данный момент времени процессор может использовать только одну таблицу LDT.

Процессор имеет два регистра, предназначенных для адресации используемых в настоящий момент таблиц GDT и LDT. Регистр GTDR описывает расположение и размер таблицы GDT, а регистр LDTR содержит ссылку на использующуюся в настоящее время таблицу LDT.

На рис. 23 показана уточнённая схема преобразования адресов в защищённом режиме. Из рисунка видно, что регистры процессора GDTR и LDTR определяют расположение в памяти таблиц GDT и LDT соответственно. Таблицы GDT и LDT содержат дескрипторы, описывающие сегменты памяти. В этих дескрипторах, помимо другой информации (заштрихованная область) содержится 24-разрядный базовый адрес сегмента.

Старшие 13 битов селектора (индекс) выбирают элемент из таблицы GDT или LDT в зависимости от состояния бита TI селектора.

Извлечённый из таблицы дескрипторов базовый адрес сегмента складывается процессором для получения 24-разрядного физического адреса.

Рис. 33 Уточнённая схема преобразования адресов

Селектор 0000h адресует самый первый дескриптор в глобальной таблице дескрипторов GDT. Поле RPL для этого дескриптора равно 0, поле TI также равно 0. Селектор 0008h указывает на второй элемент таблицы GDT, а селектор 0014h указывает на третий дескриптор в локальной таблице дескрипторов LDT, т.к. поле TI в нём равно 1.

Не нашли то, что искали? Воспользуйтесь поиском:

Vesa 2 0: программируем в защищенном режиме

Этот драйвер был разработатн и представлен как универсальный драйвер для любых карт с VESA VBE 2.0 совместимым BIOS. Другое преимущество этого драйвера заключается в том ,что он пытается принудительно включить TV вывод. VESA BIOS EXTENSION (VBE) Версия 3.0 Дата: 16 сентября, 1998 (Страница 70) гласит:

Dual-Controller Designs. VBE 3.0 поддерживает дизайн с двумя контроллерами, предполагая, что поскольку оба контроллера обычно имеют одного производителя, и управляются единственной BIOS ROM на той же карте, то возможно скрыть от приложения факт наличия на самом деле двух контроллеров. Это ограничивает их независимое одновременное использование, но позволяет приложениям, выпущенным до VBE 3.0 нормально работать. VBE функция 00h (Вернуть информацию о контроллере) возвращает комбинированную информацию двух контроллеров, включая объединенный список доступных режимов. Когда приложение выбирает режим, активируется соответствующий контроллер. Каждая из остальных VBE функций затем работает с активным контроллером.

Так что у вас ест шанс получить работающий TV выход, используя этот драйвер. (Предполагается, что TV-выход — отдельный контроллер[standalone head] или отдельный выход как минимум.)

У вас есть шанс смотреть фильмы, даже если Linux не знает ваше видео оборудование.

Вам не требуется устанавливать в Linux ничего, относящегося к графике (вроде X11 (он же XFree86), fbdev и т.п.). Этот драйвер может запускаться из текстового режима .

У вас есть шанс получить работающий TV-выход . (Это известно как минимум для ATI карт).

Этот драйвер вызывает обработчик int 10h , так что это не эмуляция — он вызывает реальные вещи реального BIOS в реальном режиме (на самом деле vm86 режим).

С ним вы можете использовать V >и TV вывод одновременно! (Рекомендуется для ATI карт.)

Если у вас есть VESA VBE 3.0+, и вы где-то указали monitor-hfreq, monitor-vfreq, monitor-dotclock (в файле конфигурации или в командной строке), то получите наибольшую возможную частоту обновления. (Используя General Timing Formula). Чтобы задействовать эту возможность, вы должны указать все опции вашего монитора.

Это работает только на x86 системах .

Может использоваться только пользователем root .

В данный момент доступно только для Linux .

Важно

Не используйте этот драйвер с GCC 2.96 ! Он не будет работать!

ОПЦИИ КОМАНДНОЙ СТРОКИ, ДОСТУПНЫЕ ДЛЯ VESA

данный момент распознаются: dga для включения режима dga и nodga для его отключения. В dga режиме вы можете включить двойную буферизацию опцией -double. Замечание: вы можете опустить эти параметры для автоопределения режима dga.

ИЗВЕСТНЫЕ ПРОБЛЕМЫ И СПОСОБЫ ИХ РЕШЕНИЯ

Если вы установили NLS шрифт на вашем Linux и запускаете VESA драйвер из текстового режима, то после завершения MPlayer у вас окажется загруженным ROM шрифт вместо национального. Вы можете загрузить национальный шрифт снова, воспользовавшись утилитой setsysfont из дистрибутива Mandrake/Mandriva, например. ( Подсказка : Та же утилита используется для локализации fbdev).


Некоторые графические драйверы Linux не обновляют активный BIOS режим в DOS памяти. Таким образом, если у вас подобная проблема — всегда используете VESA драйвер только из текстового режима . Иначе в любом случае будет активирован текстовый режим (#03) и вам придется перезагружать компьютер..

Часто после завершения работы VESA драйвера вы получаете черный экран. Чтобы вернуться в обычный режим просто переключитесь на другую консоль (нажав Alt + F ) затем переключитесь обратно тем же способом.

Для получения работающего TV выхода необходимо, чтобы TV разъем был подключен до включения вашего PC, т.к. видео BIOS инициализирует себя только один раз во время POST процедуры.

forum.lissyara.su

Раз не осталось живых, значит мертвые — Встать!

Поддерживаемые разрешения vesa и nv

  • Отправить тему по email
  • Версия для печати

Поддерживаемые разрешения vesa и nv

На какие максимальные разрешения мониторов способны драйвера «vesa» и «nv»? И какие «нестандартные» разрешения они поддерживают?
Интересует так же частотная формула (частоты кадровой развёртки при том или ином разрешении).

P.S.
На сайте X.org я информации не нашёл. Гуглил — бестолку.

Услуги хостинговой компании Host-Food.ru

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

Re: Поддерживаемые разрешения vesa и nv

непомню под иксами помоему vesa драйвер должен влог выдавать все поддерживаемые разрешения

если нет
то можно поступтить иначе
тоесть посмотреть какие веса режимы поддерживает ваша видео

скомпилить ядро в options SC_PIXEL_MODE
и загрузить vesa.ko
драйвер
а дальше в консоли
vidcontrol -i mode

наскоко я помню показывает вседоступные режимы vesa на катре
если там того режима что вам над нет
значт vesa можно и не мучать

Re: Поддерживаемые разрешения vesa и nv

гм.. а чё уже дрова допилили?

на работе ATI 9600 — ксорг тупо виснет на флешках (драйвер радион). В данный момент вернулся на весу, именно из-за ксорга.
дома ATI X1900 — драйверов вообще нет, хдрадион отказывается пахать, не говоря уже о стабильности.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL