|
nedoPC.orgElectronics hobbyists community established in 2002 |
|
ПК Поиск - замена штатного 1810ВМ88 на NEC V20
Author |
Message |
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Решил написать и здесь, потому что мыслей почему лыжи не едут больше нет.... Итак даны: два "Поиска". Первый - модификация со 128Кб RAM, второй - модификация с 512KB RAM. У обоих был выпаян родной процессор 1810ВМ88, установлена панелька на его место и в панельку вставлен NEC V20. Итог таков: компьютер работает нормально, быстрее чем со штатным процессором, кроме одного досадного бага, портящего всю картину, а именно: В некоторых программах не отрисовывается каждый второй символ на экране. В числе таких программ - Volkov Commander и RAR. С другой стороны, например, Norton Commander отображается правильно. Как мы все знаем, ПК Поиск эмулирует CGA, а именно работает всегда в графическом режиме, прорисовывая каждый символ на экране программно. Из-за этого у него есть две области видео-памяти по 16Kb каждая, отображаться на экране может одна из них. В графическом режиме отображается B800h, в текстовом - отображается BC000h, содержащая графическое представление текстовых символов из B800h. Происходит это в моем понимании примерно так: когда установлен текстовый режим, при записи символа в видео-память B800h срабатывают ловушки адреса (регистры-защелки), которые запоминают, по какому адресу произошла запись. Дальше вызывается обработчик NMI, который в свою очередь читает из портов 28h и 29h значение адреса (из регистров-защелок), по которому произошла запись, и отрисовывает символ в видимой графической области BC000. Сам код символа записывается в B8000h. Путем выяснения причин "эффекта" была найдена закономерность - баг проявляется когда происходит прямая запись в видео-память, например с помощью команды REP STOSW. Были проведены простейшие тесты, которые показали, что не срабатывает "ловушка" адреса - порт 28h (TRAP_A): В итоге в AX у нас 8000h . Че такое '8' я хз, но следующие 3 байта явно смещение, по которому произошла запись. Здесь все ок, все работает как ожидалось. Что в AX? Правильно - тот же 8000h, хотя очень бы хотелось видеть там 8002h по логике, потому что второй символ у нас записался в B800:0002. Ну и в довершение: В AX у нас 8004h как и должно быть. При этом сами символы все-таки записываются в B800h. Если сменить видео-страницу стандартными функциями int 10h, то при возврате на текущую отобразятся три буквы "O". Не записывается адрес в защелки и не вызывается NMI для отрисовки на экране. Дальше я обратился к схеме. Здесь я буду показывать схему 512Kb модификации, хотя она аналогична и 128Кб модификации, на мой взгляд. За отслеживание, что запись происходит в видео-память отвечает РТ4 (с небольшой помощью РТ5?), при удачной дешифрации формирующая сигнал /CRTIOM. Дальше этот сигнал вместе с некоторыми другими запускает мультивибратор, который дает длинный импульс NMI (не менее пяти тактов, наверное). По сигналу NMI происходит защелкивания текущего адреса в регистры-защелки: Ну и дальше проц должен уйти на обработчик NMI, который прочтет из портов 28h,29h адрес куда писался байт и отрисует его графическое представление в отображаемый экран BC000h. Дешифрует порты РТ5, формируя сигнал /TRAPSEL, который потом разделяется на 28h (TRAPL),29h (TRAPH) и 2ah (TRAPDAT) с помощью ИД7. Но это уже потом, меня же пока интересует /CRTIOM и возникновение NMI. Решил посмотреть что происходит с помощью восьми канального логического анализатора. Для этого взял родной BIOS, из которого выкинул монитор и работу с кассетой, а вместо этого после всей инициализации прикрутил тестовую программку - записывает один символ в видео-память, ждет пару секунд, записывает два символа в видео-память, ждет пару секунд и так по кругу. Такого плана: | | | | Code: again: MOV DX,01 CALL BEEP_ERROR mov ax, 0B800h mov es,ax mov di,0 mov al,'1' ; буква 1 mov ah,7 ; белым по черному mov cx,1 ; один раз rep stosw
mov cx,200 call delay_pit
MOV DX,02 CALL BEEP_ERROR mov ax, 0B800h mov es,ax mov di,160 mov al,'2' ; буква 2 mov ah,7 ; белым по черному mov cx,2 ; два раза rep stosw
mov cx,200 call delay_pit
jmp again
| | | | |
И вот иллюстрации с лог анализатора. Тут надо сказать, что тут я смотрел сигналы /TRAPSEL, TRAPL и TRAPH, то есть возникающие уже когда зашли в обработчик NMI и он обращается к портам 28,29h. Вот так выглядит запись одного байта в приближении: IO/M стал высокий (идет доступ к портам ввода-вывода), РТ5 видит что доступ к IO, адрес порта совпал, дешифровала TRAPSEL, ИД7 в свою очередь дала сначала TRAPL, затем TRAPH. Все понятно. Дальше полный цикл для обоих процов NEC V20 и 8088. Полный цикл - запись одного байта, ожидание, запись двух байт. Это 8088: Это V20: В целом - все очень похоже, за исключением TRAPSEL, который на 8088 проце активно живет, а на V20 не очень. Но нас интересует момент записи двух байт сразу. Это вторая "черточка" из TRAPL и TRAPH на рисунках. Приближаем: Это 8088: Сначала был считан из портов младший адрес, затем старший. Все четко. А это уже V20, то же место: Не было считано второго адреса. Забыл я сохранить фотографии когда я уже понял, что смотреть мне нужно сигналы /CRTIOM и NMI, но могу сказать словами - когда пишутся два байта, первый байт есть сигнал /CRTIOM, затем длинный NMI и затем уже /TRAPSEL, TRAPL и TRAPH. А вот второй байт - нет сигнала /CRTIOM, соответственно нет и всего остального. Такое ощущение, что "проскакивает" он. Вот такая загадка....
|
01 Nov 2015 12:57 |
|
|
Vic3Dexe
Doomed
Joined: 16 Dec 2014 11:58 Posts: 370 Location: Киев
|
Сложно вникнуть сходу в диаграммы анализатора, но на последней картинке и второго IO/M нет вроде? Хотя на мелком масштабе их аж 3 и у 8088 и у В20, если я правильно понял.
Если с IO/M все в порядке, я бы посмотрел анализатором DT/R и INTA на РТ4/РТ5. По идее, генерацию TRAPSEL могут портить только они (NMIDIS рулится софтом через PPI).
|
04 Nov 2015 13:44 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Да, второго IO/M нет. И /TRAPSEL нет. Но картинки с анализатора - это как я и писал, я немного не то смотрел. Нужно сначала смотреть /CRTIOM - он должен быть сразу после попытки записи символа в B8000. Вот его тоже нет.. А /TRAPSEL уже потом должен быть, когда проц ушел на обработку NMI и из процедуры обработки пытается считать адрес по которому произошла запись из защелок (IN AX,28h). Вот тогда должна появится /TRAPSEL и все остальное.
Но поскольку нет /CRTIOM - нет и NMI, нет и запросов к порам, нет и /TRAPSEL....
Насчет IO/M - когда низкий уровень - идет общение с памятью, когда высокий - с портами ввода/вывода.
|
04 Nov 2015 21:27 |
|
|
Vic3Dexe
Doomed
Joined: 16 Dec 2014 11:58 Posts: 370 Location: Киев
|
А, все, врубился. В любом случае, CRTIOM формируется там же, на РТ4/РТ5. Кто участвует в его формировании? 1. Адресные линии - проехали, если бы дело было в них, не работало бы вообще ничего 2. IO/M - то же самое 3. NMIDIS - программно-управляемый сигнал, выставляется, как я понимаю, в обработчике NMI, дабы не уйти в цикл при отрисовке символа 4. DT/R, INTA - вроде бы тоже фундаментальные сигналы... Но кто-то же из них портит все! Вот посмотреть бы анализатором все эти ноги. И такой вопрос. Если выводить через REP STOSB - нормально? Ну типа: | | | | Code: mov si,msg xor di,di mov cx,10 rep stosb
msg db 'H',7,'e',7,'l',7,'l',7,'o',7
| | | | |
|
04 Nov 2015 22:32 |
|
|
Vic3Dexe
Doomed
Joined: 16 Dec 2014 11:58 Posts: 370 Location: Киев
|
Так, посмотрел прошивку РТ4. РТ5 отпадает, она вообще срабатывает только при обращениям к I/O (надо больше спать!).
CRTIOM~ падает в 0 тогда и только тогда, если: - А19..А14 = 101110 (т.е. B8000..BFFFF) - DT/R~ = 1 (т.е. запись) - NMIDIS = 0
NMIDIS в обработчике NMI не трогается вообще, как ни странно, а вызывается только в сервисах биос (cls, scroll up/down etc). Пока не переварил этот факт.
Думаю, что V20 просто нечувствителен к NMI между байтами в STOSW, типа атомарная операция. Нужно смотреть, что делается на шине в процессе STOSW при наличии NMI. Если есть запись младшего байта и уход на NMI, то... тогда я в тупике. Если идут две записи подряд - то таки STOSW атомарная штука.
|
05 Nov 2015 16:08 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Странно, зачем тогда первый выход РТ5 Q1 соединен с /CRTIOM, если РТ5 не участвует в жизни... Плюс, похоже /CRTIOM не подтянут к VCC - может это они так через РТ5 подтянули его к VCC, потому что в резистороной сборке резисторы закончились свободные?...
Сегодня попробую еще посмотреть сигналы
UPD: А, все, РТ5 формирует /CRTIOM когда кто-то в CGA-порты лезет, и их потом в NMI обрабатывает.. Это я туплю просто. Но, однако, подтяжки /CRTIOM я на схеме не вижу к питанию... А вроде и РТ4 и РТ5 выход с открытым коллектором.... UPD2: Да не, есть подтяжка через резисторную сборку. Не увидел сразу. Чет никак не проснусь.
|
05 Nov 2015 22:57 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Посмотрел сигналы около РТ4 при записи двух байт. Родной 8088: Видно, что адреса стали 011101, DT/R стал высоким и появился /CRTIOM. Дальше ушел на NMI, где видимо прочел из видео-памяти данные (адреса тоже 011101, но DT/R низкий), нарисовал их на экране. И второй байт так же следом. NEC V20: Первый байт пошел по анологии с 8088. А вот там, где должен был быть второй байт на адресах вообще нет B8000-BFFFF. И перед тоже вроде нет. Как будто пропустил его... Для того, чтобы посмотреть поближе - сохраненные "слепки" с логического анализатора: http://rghost.ru/download/7TrDkDfjT/ee91462822e0309a1d17d01f0d2ce1d0a7e848ea/88_v20.rar Загрузить их можно в программе Saleae Logic: https://www.saleae.com/downloads (у меня версия 1.1.34 beta, но наверняка можно и в более новой)
|
06 Nov 2015 01:50 |
|
|
jdigreze
God
Joined: 02 Jan 2006 02:28 Posts: 1390 Location: Abakan
|
Попробовал просто свести две картинки, оно конечно не показатель: красным - 8088 серым - NEC V20 Имхо, вообще сигналы странные. Немного не в тему: AX или DX? Оригинал или копия? А то тут думаю, брать или не стоит...
|
06 Nov 2015 07:03 |
|
|
Vic3Dexe
Doomed
Joined: 16 Dec 2014 11:58 Posts: 370 Location: Киев
|
Я правильно понял, что на диаграммах первый участок кода (т.е. с cx=1)?
Из того, что я увидел - 8088 возвращается из NMI на rep stosw, т.е. выполняет запись второго байта. V20 возвращается ПОСЛЕ инструкции, т.е. на mov cx,200.
Т.е., после отрисовки символа в облась BC000h идет частая гребенка (7-8 чтений) - это выходные POPы, затем iret (широкая облась чтения, читаем флаги/cs/ip), затем выборка из BIOS, после чего 8088 выполянет остаток stosw, а V20 занимается ерундой, т.е. он выбирает непойми что. Конкретнее, похожий паттерн на диаграммах 8088 идет как раз после второго NMI.
Я бы для начала заменил обработчик NMI на iret и повторил эксперимент - т.е. посмотреть те же диаграммы. Понятно, что рисоваться ничего не будет, но нам не это интересно, главное, что не будет лишних переключений на графиках. Да, и обязательно обернуть отрисовку в cli/sti.
upd: и наверно задержку поменьше поставить, а то файлы по 300 метров, а на диаграммах stosw только один раз виден. upd2: нет, стоп, видно дважды - в среднем "куске", и в последнем. И чсх, в среднем куске и у 8088 и у V20 по одному CRTIOM! Это к какому участку кода оно относится? upd3: так, пока забудьте все, что я тут наговорил. Я сам уже запутался, надо переварить.
|
06 Nov 2015 08:16 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Первый кусок - это когда cx=1, rep stosw. Ближе к концу - это когда cx=2, rep stosw. В первом куске один раз сработало /CTRIOM. Во втором в случае с 8088 - два раза сработало... UPD: Я сейчас пока такой тестик пишу - в обработчике NMI буду выводить адрес из защелок (in ax,28h), символ и аттрибут в памяти по этому адресу и самое главное - символ и аттрибут в памяти по адресу "текущий+2".
|
06 Nov 2015 09:22 |
|
|
Vic3Dexe
Doomed
Joined: 16 Dec 2014 11:58 Posts: 370 Location: Киев
|
Да, сам уже с кусками разобрался. CRTIOM формируется один раз на stosw, т.е. stosw даже у 8088 - атомарная операция. У В20 не отрабатывается запись после NMI, т.е. по скринам волкова видно, что di прирастает, но запись не происходит! Теперь вопрос: если начать вывод с адреса di=2, что будет? Поясняю. Что сейчас (di=0 или 160): где С = символ на экране, "_" - мусор А что будет при di=2? Вот так: или так Если второй вариант - 100% баг в В20, не отрабатывает запись после NMI. Если первый - надо думать...
|
06 Nov 2015 09:38 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Забыл по-моему сразу сказать, что фактическая запись в область памяти B800h при этом происходит. То есть символы и аттрибуты туда кладутся. Дописал тестик - в самом обработчике NMI вывожу содержимое из регистров-защелок (in ax,28h), затем значение по этому адресу в памяти (CHR: ) и значение по этому адресу плюс два (CHR+2). На 8088 поведение как на экране эмулятора (постом выше). А вот на V20 такие результаты: То есть когда при cx,2; rep stosw (вывод двух двоек на экран) сваливается в NMI, то в памяти уже лежит второй символ и его аттрибут o_O, хотя свалились только для обработки первого. Такие дела.... Вот теперь даже и не знаю.. Может в обработчике NMI смотреть значение адреса возврата в стеке и как-нибудь сравнивать его с префексом REP. Если равно - то в обработчике рендерим сразу два символа - текущий и следующий. Правда я уже ассемблер напрочь, не помню как это делается -) PS: Имеет ли смысл проводить предлагаемые тесты с di=2? Я просто уже отпаялся проводами... Да и свободных EEPROM-ок не осталось, нужно стирать УФ... Но если нужно, могу провести тест.... Или все-таки программно пофиксить? UPD: О!! И адреса - на 8088 идет адрес +1 в защелках, а на V20 защелкиваются четные адреса... UPD2: А не, это эмулятор кривоват. На реальном 8088 так:
|
06 Nov 2015 10:01 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Так как я асм уже успел напрочь забыть, сделал такое определение в процедуре NMI: | | | | Code: NMI_SERVICE: CLD PUSH ES PUSH DS PUSH DX PUSH CX PUSH BX PUSH SI PUSH DI PUSH AX
push bp mov bp,sp ;SS:[BP] - ВР ;SS:[BP+2] - IP ;SS:[BP+4] - CS ;SS:[BP+6] - флаги
mov ax,40h ;сегмент 040h:xxxx mov es,ax mov [es:rep_now],0 ;признак префикса REP - нет
mov di,[bp+2+16] ;в DI - IP mov ax,[bp+4+16] mov ds,ax ;в DS - CS cmp byte ptr ds:[di],0F3h ;CS:IP = 0x3f? (REP ....) jne skip_rep mov [es:rep_now],1 ; да, это REP. Признак префекса REP = 1 skip_rep: pop bp MOV AX,DSEGMENT MOV DS,AX MOV AX,START_BUFFER ;Адрес начала буфера MOV ES,AX IN AX,TRAP_A MOV BX,AX TEST AH,40h JNZ IO_ROUTINES MWTC_ROUTINE: ;Подпрограмма обслуживания ВИДЕО
...SKIP... ...SKIP... ...SKIP...
MW32: CALL S1B POP AX POPF mov ax,40h mov es,ax cmp [es:rep_now],1 ; есть признак REP? jne AX_NMI ; нет- выходим из NMI mov [es:rep_now],0 ; есть - значит нужно повторить следующий символ. MOV AX,DSEGMENT MOV DS,AX MOV AX,START_BUFFER ;Адрес начала буфера MOV ES,AX IN AX,TRAP_A ADD AX,2 ; увеличиваем смещение на 2 MOV BX,AX JMP MWTC_ROUTINE ;еще раз рисуем символ..
AX_NMI:
| | | | |
Пока еще не пробовал, ПЗУ-шки стираю УФ....
|
06 Nov 2015 23:39 |
|
|
Vic3Dexe
Doomed
Joined: 16 Dec 2014 11:58 Posts: 370 Location: Киев
|
Я, видимо, опоздал, но: не надо стирать! Зачем? NMI прекрасно и в раме полежит, всего-то 2 вектор подменить. По остальному: Оппа... Так вот ты какой, i386 в исполнении NEC... Он же двойными словами работает, скотина! Т.е., cx внутри делится пополам (полагаю, при наличии rep) и за один stosw выполянется четыре записи, после чего cx--. Ну и нечетный cx и случаи без REP, видимо, отрабатываются отдельно. Ой интересные графики будут по линиям A0..A3 ... 100% нет, дело было не в бобине =) Честный 16-битный проц, не то что некоторые. Проще подменить 2 вектор, сохранив адрес старого обработчика. Далее так: | | | | Code: old_nmi dd ? flag db ? ;это наш флаг второг вызова, см. ниже NMI_NEW: pushf call far [cs:old_nmi] ;позвали старый, он отрисует что надо ;это 2 вызов? cmp [cs:flag],1 je exit ;да, отваливаем ;сохраняем регистры ... ;здесь проверки на префикс, если нет - идем на exit ... ;префикс есть, нужно рисовать 2 символ MOV AX,DSEGMENT MOV DS,AX MOV AX,START_BUFFER MOV ES,AX IN AX,TRAP_A MOV BX,AX TEST AH,40h JNZ [b]exit[/b] ;в IO не вмешиваемся ;далее нам нужно просто перезаписать символ и сгенерить NMI по новому адресу (достаточно байта), но не вляпаться самим во второй вызов mov [cs:flag],1 ;защита mov al,[es:bx] mov [es:bx],al ;<======= вот тут NMI вызвался второй раз exit: ;восстановили регистры ... iret
| | | | |
Щас набросаю программку-тест. На поиск есть как ее перебросить? Ну т.е. давать бинарник или исходник? upd: проще дать и то и то Исходик (fasm, под тасм подпилите, тасма у меня нет): код | | | | Code: format MZ use16 entry _code:start stack _stck:_sp
segment _code start: ;потерли экран mov ax,3 int 10h
;заменяем NMI xor ax,ax mov DS,ax les bx,[2*4] mov word [CS:old_nmi],bx mov word [CS:old_nmi+2],ES cli mov word [2*4],new_nmi mov [2*4+2],CS sti
;собсна, тест mov ax,0B800h mov ES,ax xor di,di mov cx,2 mov ax,0732h rep stosw
;вернули NMI les bx,[cs:old_nmi] mov [2*4],bx mov [2*4+2],ES
;подождали кнопку, иначе дос поскроллит все это xor ax,ax int 16h
;ушли mov ax,4C00h int 21h
old_nmi dd 0 flag db 0
;новый nmi new_nmi: pushf call far [cs:old_nmi] ;позвали старый, он отрисует что надо ;это 2 вызов? cmp [cs:flag],1 je exit ;да, отваливаем ;сохраняем регистры push bp mov bp,sp push DS push ES push ax push bx mov bx,[bp+2] ;ip mov DS,[bp+4] ;cs ;проверка cmp byte [bx],0F3h je do_prefix cmp byte [bx],0F2h jne exit ;префикс есть, нужно рисовать 2 символ do_prefix: mov ax,0B800h mov ES,ax in ax,28h mov bx,ax test ah,40h jnz exit ;в IO не вмешиваемся ;далее нам нужно просто перезаписать символ и сгенерить NMI по новому адресу (достаточно байта), но не вляпаться самим во второй вызов mov [cs:flag],1 ;защита mov al,[es:bx] mov [es:bx],al ;<======= вот тут NMI вызвался второй раз
exit: ;восстановили регистры pop bx pop ax pop ES pop DS iret
segment _stck db 64 dup(0) _sp:
| | | | |
Бинарник http://rghost.ru/6JFCR9v7qПод досбокс работает вроде, при запуске рисует две двойки, ждет кнопку и уходит в дос. upd2: но под досбоксом, разумеется, не вылазит nmi, так что его работу я не проверю
Last edited by Vic3Dexe on 07 Nov 2015 02:00, edited 2 times in total.
|
07 Nov 2015 00:36 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Да, можно конечно и так (второй вектор подменять). Но у меня крышка открыта у Поиска, и клаву не хочется каждый раз подключать-отключать. Плюс на клаве не все кнопки работают, шлейф потрескался, некогда пофиксить все... Программно можно тестить на втором моем Поиске 512Kb - он полностью в порядке. Но пока тестю на этом, ибо лень -)
Тут это, решил чтоб с ПЗУ не возится юзать SRAM 6264. Не могу вспомнить, как ей ПЗУ эмулировали - вроде напаивается сверху здоровый кондер микрофарад на 2000, ножка VCC отгибается и припаивается к + электролита. Вместо ножки VCC подсовывается ножка диода (анод), а катод соединяется с VCC микросхемы и + кондера.. Вроде как-то так, щаз попробуем...
|
07 Nov 2015 01:57 |
|
|
Who is online |
Users browsing this forum: No registered users and 2 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|