;// fasm (Real-Mode)
;// Читает регистры ACPI-контролёра
;// тестировалось на чипсете "Intel ICH7"
;// -------------
org 100h
jmp start
caption db 13,10,' ACPI info v.01 '
db 13,10,' ======================'
db 13,10,' Support PCI-BIOS.: $'
totalBus db 13,10,' Total PCI-bus....: $'
find db 13,10
db 13,10,' Find LPC bridge... $'
lpcInfo db 13,10,' PCI-Bus.......: $'
device db 13,10,' PCI-Device....: $'
func db 13,10,' PCI-Function..: $'
vid db 13,10,' VendorID......: $'
did db 13,10,' DeviceID......: $'
acpiInfo db 13,10
db 13,10,' ACPI controller'
db 13,10,' I/O port......: 0x$'
rcBar db 13,10,' Root-Complex..: 0x$'
acpiReg db 13,10
db 13,10,' ACPI registers'
db 13,10,' PM1 status....: $' ;//регистр(00h)
pmEn db 13,10,' PM1 enable....: $' ;//регистр(02h)
pmCtl db 13,10,' PM1 control...: $' ;//регистр(04h)
pmTmr db 13,10,' Timer value...: $' ;//регистр(08h)
cpuCtl db 13,10,' CPU control...: $' ;//регистр(10h)
smiCtl db 13,10,' SMI ctl_enable: $' ;//регистр(30h)
smiStat db 13,10,' SMI status....: $' ;//регистр(34h)
;// Таблица для расшифровки Device-ID.
;// старший байт DevID совпадает с типом чипсетов ICH6-9.
devTable dw 0x2600,i6,0x2700,i7,0x2800,i8
dw 0x2900,i9,0x3A00,i10,0x3B00,pch
dtLen = ($ - devTable)/4
i6 db ' = ICH6 $'
i7 db ' = ICH7 $'
i8 db ' = ICH8 $'
i9 db ' = ICH9 $'
i10 db ' = ICH10. Chipset not support $'
pch db ' = PCH. Chipset not support $'
unkNown db ' = Unknown bridge $'
;//=====================================================
mError db 'ERROR!$'
ok db 'OK! $'
bdf dw 0
pmBase dd 0
rcba dd 0
;//--------
start:
mov dx,caption ;// шапка
call Message ;//
;//--- Проверяем поддержку fn.PCI-BIOS
mov ax,0xB101 ;// fn.0xB101
xor edi,edi ;//
int 1Ah ;// зовём сервис!
or ah,ah ;//
jz @f ;// ОК, если AH=0
call ERROR ;// иначе: ошибка.
@@: push cx ;// запомнить кол-во шин
mov dx,ok ;// есть PCI-BIOS!
call Message ;//
mov dx,totalBus ;// всего шин.
call Message ;//
pop ax ;// снять их со-стека
and ax,0xff ;// оставить только мл.байт
inc al ;// +1, т.к.отсчёт с нуля
mov bx,10 ;// система счисления
call Hex2Asc ;// Print-AX
;//-----------------------------------------------
;//--- Поиск моста "PCI-to-LPC" по его классу ----
;// Возвращает в регистр ВХ [bus:dev:func]
;// BH=Bus, BL[7:3]=Device, BL[2:0]=Function.
;//-----------------------------------------------
mov dx,find ;//
call Message ;//
mov ax,0xB103 ;// fn.0xB103
mov ecx,0x060100 ;// класс\подкласс\интерфейс
xor si,si ;// искать без цикла 1 устройство
int 1Ah ;// Найти!
jnc @f ;// если флаг CF=0, то Forward (вперёд)
call ERROR ;// иначе: ошибка
@@: mov [bdf],bx ;// запомнить выхлоп "Bus:Dev:Func"
push bx bx bx ;// в стек их, для вывода на консоль.
mov dx,ok ;// мессага "Найдено"!
call Message ;//
;// Выводим эти данные на консоль
;// == Bus ==
mov dx,lpcInfo ;//
call Message ;//
pop ax ;//
shr ax,8 ;// оставляем только ст.часть[15:8]
mov bx,16 ;// система счисления
call Hex2Asc ;//
;// == Device ==
mov dx,device ;//
call Message ;//
pop ax ;//
xor ah,ah ;//
shr ax,3 ;// оставляем биты[7:3]
mov bx,16 ;//
call Hex2Asc ;//
;// == Function ==
mov dx,func ;//
call Message ;//
pop ax ;//
and ax,111b ;// оставляем биты[2:0]
mov bx,16 ;//
call Hex2Asc ;//
;//-----------------------------------------
;//--- Читаем из кфг.пространства LPC-моста
;//--- его идентификаторы VEN\DEV
;//-----------------------------------------
mov ax,0xB10A ;// fn= читать двордами (по 4-байт)
mov bx,[bdf] ;// от куда "Bus:Dev:Func"
xor di,di ;// адрес = 0 (offs.от начала)
int 1Ah ;//
push ecx ecx ;// запомнить VEN\DEV для вывода
;//--- Читаем поле "APCI-base" (порт контролёра)
mov ax,0xB10A ;// размер = 4-байта
mov bx,[bdf] ;// координаты
mov di,0x40 ;// смещение 40h от начала LPC-cfg
int 1Ah ;//
dec ecx ;// сбросить бит валидности адреса.
mov [pmBase],ecx ;// запомнить в переменной.
;//--- Читаем поле "Root-Complex BA"
mov ax,0xB10A ;//
mov bx,[bdf] ;//
mov di,0xf0 ;// смещение F0h
int 1Ah ;//
mov [rcba],ecx ;// запомнить RCBA.
;//----------------------------------------
;//--- Выводим нарытую инфу на консоль ----
;//----------------------------------------
;// *** Vendor-ID ***
mov dx,vid ;//
call Message ;//
pop eax ;// снимаем со-стека считанное
movzx eax,ax ;// обнулить старшую часть
mov ebx,16 ;// система-счисления
call Hex2Asc ;// Print-AX
;// *** Device-ID ***
mov dx,did ;//
call Message ;//
pop eax ;//
shr eax,16 ;// обнулить младшую часть
push ax ;// запомнить DevID
mov ebx,16 ;//
call Hex2Asc ;// Print его на консоль.
;// Определяем тип моста по его DevID
pop bx ;//
and bx,0xFF00 ;// очистить мл.байт
mov esi,devTable ;// указатель на таблицу
mov ecx,dtLen ;// ..её длина
@@: lodsd ;// берём в EAX сразу 4-байта из SI
cmp ax,bx ;// ищем совпадения младшего слова
je @f ;// ..(в старшем лежит адр.мессаги)
loop @b ;// повторить, если не равно
mov dx,unkNown ;// нет совпадений.
call Message ;//
jmp @acpi ;//
;// Нашли DevID в своей базе!
@@: shr eax,16 ;// сместить адрес текста в АХ
mov dx,ax ;// вывести его на консоль.
call Message ;//
;// *** ACPI Base Address ***
@acpi: mov dx,acpiInfo ;//
call Message ;//
mov eax,[pmBase] ;//
mov ebx,16 ;//
call Hex2Asc ;// Print-ЕAX
;// *** Root Complex Base Addr ***
mov dx,rcBar ;//
call Message ;//
mov eax,[rcba] ;//
mov ebx,16 ;//
call Hex2Asc ;// Print-ЕAX
;//-----------------------------------------------------------
;//--- В переменной "PMBASE" лежит номер порта ACPI-контролёра
;//--- читаем его регистры на консоль ------------------------
;//-----------------------------------------------------------
mov dx,acpiReg ;//
call Message ;//
mov edx,00h ;// ..регистр в нём "PM1_Status"
call ReadAcpiPort ;//
mov ecx,16 ;// кол-во бит для вывода
call Bin2Asc ;// Print-AX в бинарном виде!
mov dx,pmEn ;//
call Message ;//
mov edx,02h ;// ..регистр в нём "PM1_Status"
call ReadAcpiPort ;//
mov ecx,16 ;//
call Bin2Asc ;//
mov dx,pmCtl ;//
call Message ;//
mov edx,04h ;// ..регистр в нём "PM1_Status"
call ReadAcpiPort ;//
mov ecx,32 ;// кол-во бит для вывода
call Bin2Asc ;// Print-EAX в бинарном!
mov dx,pmTmr ;//
call Message ;//
mov edx,08h ;// ..регистр в нём "PM1_Status"
call ReadAcpiPort ;//
mov ebx,10 ;// система-счисления для вывода
call Hex2Asc ;// Print-EAX в 10-тичном!
mov dx,cpuCtl ;//
call Message ;//
mov edx,10h ;// ..регистр в нём "PM1_Status"
call ReadAcpiPort ;//
mov ecx,32 ;//
call Bin2Asc ;//
mov dx,smiCtl ;//
call Message ;//
mov edx,30h ;// ..регистр в нём "PM1_Status"
call ReadAcpiPort ;//
mov ecx,32 ;//
call Bin2Asc ;//
mov dx,smiStat ;//
call Message ;//
mov edx,34h ;// ..регистр в нём "PM1_Status"
call ReadAcpiPort ;//
mov ecx,32 ;//
call Bin2Asc ;//
@exit: ;//
xor ax,ax ;//
int 16h ;//
int 20h ;//
;//===============================
;// === ДОП.ФУНКЦИИ ==============
ReadAcpiPort: ;//<------ на входе: EDX = регистр.
add edx,[pmBase] ;// добавить базовый порт.
in eax,dx ;// считать данные в ЕАХ
retn
Hex2Asc: ;//<------ Перевод чисел в символы
xor ecx,ecx ;// описание смотри,
isDiv: xor edx,edx ;// ... в первой программе.
div ebx ;//
push edx ;//
inc ecx ;//
or eax,eax ;//
jnz isDiv ;//
isOut: pop eax ;//
cmp al,9 ;//
jle noHex ;//
add al,7 ;//
noHex: add al,30h ;//
int 29h ;//
loop isOut ;//
retn
Bin2Asc: ;//<------ Вывод в BIN
mov ebx,eax ;// взять число в EBX
or ebx,ebx ;// проверить его на нуль
jne @f ;// продолжить, если больше -----+
mov al,'0' ;// иначе: вывести 0 |
int 29h ;// ..и возвратить управление. |
retn ;// |
@@: cmp cx,32 ;// проверить аргумент на 32 <---+
je @f ;// если равно..
shl ebx,16 ;// иначе: число влево на 16-бит
@@: mov al,'0' ;// в дефолте выводить нуль
shl ebx,1 ;// выталкиваем по 1-биту влево..
jnc okey ;// если CF=0
inc al ;// иначе: +1
okey: int 29h ;// вывести бит на консоль
loop @b ;// промотать цикл СХ-раз
retn
Message: ;//<------ Вывод строк
mov ah,9 ;//
int 21h ;//
retn
ERROR: pop ax ;//<------ снять адрес возврата
mov dx,mError ;// мессага
call Message ;//
jmp @exit ;// на выход!
Комментарии
3