227 lines
4.4 KiB
NASM
227 lines
4.4 KiB
NASM
;
|
|
; This files implements a set of routines used to manage the LCD
|
|
; display on IBM Thinkpads.
|
|
;
|
|
|
|
.386p
|
|
|
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
|
|
|
OLD equ 0
|
|
NEW equ 1
|
|
|
|
IOPort dw 15EEh
|
|
ThinkpadVersion dd ?
|
|
|
|
msg1 db "Unknown Thinkpad Version.", 0dh, 0ah, 0
|
|
|
|
_DATA ENDS
|
|
|
|
_TEXT SEGMENT DWORD PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
public _LCDInit@0
|
|
public _LCDDisplay@4
|
|
public _LCDIsMonitorPresent@0
|
|
|
|
;IF DBG
|
|
; extrn _VideoPortDebugPrint:proc
|
|
;ENDIF
|
|
|
|
align 4
|
|
|
|
;
|
|
; There are two versions of the Thinkpad System Management API.
|
|
; One is used on old thinkpads such as the 755C, the other is
|
|
; used on new thinkpads such as the 755CE and 755CD. I'll refer
|
|
; to the two as OLD and NEW.
|
|
;
|
|
; Instead of having a routine which determines whether the display
|
|
; type is old or new, I'll figure it out once in an init routine, and
|
|
; then have all other LCDxxx routines use it.
|
|
;
|
|
|
|
_LCDInit@0 proc
|
|
|
|
pushad ; preserve registers
|
|
|
|
mov ax, 05380h
|
|
mov bx, 0F04Dh
|
|
mov cx, 04942h
|
|
mov dx, IOPort
|
|
out dx, ax ; invoke the SMAPI
|
|
|
|
;
|
|
; Now check to see if this is a new, or old thinkpad
|
|
;
|
|
; It is a new thinkpad if
|
|
;
|
|
; AH == 0x86
|
|
;
|
|
; it is old if
|
|
;
|
|
; AX == 0x5380 && BH == 0x00
|
|
;
|
|
|
|
cmp ah, 086h
|
|
jnz L100
|
|
|
|
mov ThinkpadVersion, NEW
|
|
jmp L120
|
|
|
|
L100:
|
|
cmp ax, 05380h
|
|
jnz L110
|
|
cmp bh, 00h
|
|
jnz L110
|
|
|
|
mov ThinkpadVersion, OLD
|
|
jmp L120
|
|
|
|
L110:
|
|
|
|
mov ThinkpadVersion, OLD ; we don't know the version, so assume
|
|
; its the old.
|
|
|
|
; add a debug print here to notify of situation, or
|
|
; add a DbgBreakpoint
|
|
|
|
;IF DBG
|
|
; push offset msg1
|
|
; push 0
|
|
; call _VideoPortDebugPrint
|
|
; add esp, 8 ; remove parameters from stack
|
|
;ENDIF
|
|
|
|
L120:
|
|
|
|
popad ; restore registers
|
|
|
|
ret
|
|
|
|
_LCDInit@0 endp
|
|
|
|
;
|
|
; The following routine is used to determine whether or not an
|
|
; external monitor is present. It will return a TRUE if an
|
|
; external monitor is conected, and a false otherwise.
|
|
;
|
|
|
|
_LCDIsMonitorPresent@0 proc
|
|
|
|
pushad ; preserve registers
|
|
|
|
mov dx, IOPort
|
|
mov ax, 05380h
|
|
|
|
cmp ThinkpadVersion, OLD
|
|
jnz L200
|
|
|
|
;
|
|
; this is an old thinkpad
|
|
;
|
|
|
|
mov bx, 08000h
|
|
out dx, ax
|
|
mov ch, bh
|
|
jmp L210
|
|
|
|
L200:
|
|
|
|
;
|
|
; this is a new thinkpad
|
|
;
|
|
|
|
mov bx, 00002h
|
|
out dx, ax
|
|
|
|
L210:
|
|
|
|
;
|
|
; the result is now in ch
|
|
;
|
|
|
|
and ch, 030h
|
|
jz L220
|
|
|
|
popad ; restore registers
|
|
mov eax, 01h
|
|
jmp L230
|
|
|
|
L220:
|
|
popad ; restore registers
|
|
sub eax, eax
|
|
|
|
L230:
|
|
|
|
ret
|
|
|
|
_LCDIsMonitorPresent@0 endp
|
|
|
|
;
|
|
; The following routine will turn on, or turn off the LCD display.
|
|
; This routine takes one parameter as an argument (a DWORD).
|
|
; a zero in this DWORD means turn off the LCD, anything else
|
|
; means turn it on.
|
|
;
|
|
|
|
_LCDDisplay@4 proc
|
|
|
|
pushad
|
|
|
|
mov ebp, esp ; ebp was saved by pusha
|
|
|
|
mov ax, 05380h
|
|
mov dx, IOPort
|
|
|
|
cmp ThinkpadVersion, OLD
|
|
jnz L300
|
|
|
|
;
|
|
; Old thinkpad
|
|
;
|
|
|
|
mov bx, 08701h
|
|
mov cx, 00100h ; assume we'll be turning lcd off
|
|
jmp L310
|
|
|
|
L300:
|
|
|
|
;
|
|
; New thinkpad
|
|
;
|
|
|
|
mov bx, 01001h
|
|
mov cx, 00200h ; assume we'll be turning lcd off
|
|
|
|
L310:
|
|
|
|
cmp [ebp+36], 0 ; check parameter to see if we turn
|
|
; display on or off
|
|
|
|
jz L320
|
|
|
|
;
|
|
; We want to turn the display on
|
|
;
|
|
|
|
mov cx, 08300h
|
|
|
|
L320:
|
|
|
|
;
|
|
; change the display state
|
|
;
|
|
|
|
out dx, ax
|
|
|
|
popad
|
|
ret 4
|
|
|
|
_LCDDisplay@4 endp
|
|
|
|
|
|
_TEXT ends
|
|
|
|
end
|