Tronix
Итак есть следующие регистры
0xF0 - запись и чтение из SRAM перекодировки логического адреса в физический
0xE0 - логический адрес для которого мы будем писать или читать физический из 0xF0 - те адрес в этой SRAM
SRAM из 256 ячеек по байту
она транслирует постранично 2 мб логическое пространство в 2мб физическое, размер страницы 16кб
те там хранятся соответственно 8 старших бит физического адреса памяти
[ ADDRMEM21 | ADDRMEM20 .. | ADDRMEM14 ]
Если мы хотим изменить трансляцию адреса - то 0xE0 идет на адресные линии SRAM а 0xF0 читает/пишет содержимое
Соответственно пишем в 0xE0 логический адрес а потом читаем/пишем в 0xF0 соответствующий ему физический - и там и там старшие 8 бит
Кроме того для самого проца память видна только до первых 640 кб этого логического пространства
а все сверх 640кб мапится через 4 страницы по 16 кб
они идут подряд по адресам D0000 D4000 D8000 DC000
И таким образом постраничный аппаратный EMS работает так:
последнее что записали в 0xE0 идет как старшая часть ЛОГИЧЕСКОГО адреса когда идет доступ к D0000
в 0xE1 доступ к D4000
в 0xE2 доступ к D8000
в 0xE3 доступ к DС000
Т.е. для каждого окна мы выбираем 16 кб ЛОГИЧЕСКУЮ страницу из 2-х мегабайт любую
которая будет видна в этом окне.
И потом еще она будет транслирована в ФИЗИЧЕСКУЮ по таблице из SRAM
Все физическое пространство памяти - тоже 2 мегабайта
Там 4 банка по 512 килобайт они идут подряд в физическом пространстве адресов
В каждом банке получается может стоять физически 512 или 128 или ничего
И это надо проверить при тесте
А точнее можно проверить все - в том числе просто не учитывать испорченные страницы DRAM - что кстати круто! Если драм где то испортилась - у тебя просто на 16КБ меньше памяти, ничего не надо перепаивать и никаких парити чеков и тд
Те мы просто перебираем все 256 физических страниц по 16 килобайт
тестим каждую и если она работает и без ошибок добавляем ее следующей в логическое адресное пространство
В конце мы знаем сколько у нас рабочих 16 кб страниц и значит объем рабочей памяти
Короче, исходную инициализацию делаем дословно так
и на выходе у нас:Код:uint8_t log_page = 0; uint8_t phys_page = 0; uint16_t memory_size_kb = 0; do { outportb(0xE0, log_page); outportb(0xF0, phys_page); if (OK == test_mem(0xD0000,0x4000)) { memory_size_kb += 16; ++ log_page; printf(“TEST MEMORY %d KB OK\r”, memory_size_kb); } else mark_unworking_page_bit_in_CMOS(phys_page); } while(++phys_page);
1 - размер доступной памяти в memory_size_kb
2 - правильный маппинг по любому даже если ставить микрухи не с нулевого банка
3 - битовая карта нерабочих страниц
Интересно что для какой то цели это пишется в CMOS RAM в виде карты из 16 байт где каждый бит получается есть ДВЕ (почему то) страницы.
если он 1 - там нет памяти или она битая а если 0 - есть память и все хорошо.
Видимо это пишется для EMS драйвера чтобы ему заново не проверять память?
Но реально ему было бы достаточно номера максимальной рабочей логической страницы и того факта что при POST они были правильно замаплены в физические. Вобщем странно. Наверное при горячем сбросе это используется или еще как?
Кроме того в CMOS есть бит который говорит не тестить память а типа брать маппинг из CMOS “фабричный” те можно записать туда что угодно и даже рабочие куски памяти будут считаться битыми и наоборот - но не знаю работает ли этот бит реально в 2.6
интересные моменты кроме того
1 - если мы очень захотим можно сделать основную память меньше 640 таким образом отдав лишнее на EMS
2 - мы можем перекидывать в основное адресное пространство страницы из EMS и до 640 кб, по сути по любому адресу с шагом в 16 кб показать любую страницу физической памяти из рабочих, менять их быстро местами и т.д. скажем можно было бы таким образом убирать часть кода дос или оболчки а потом быстро возвращать и т.д.
вообще такой MMU страничный на XT это очень даже передовая штука была, если бы он был стандартом сразу от IBM




Ответить с цитированием