2025-04-27 07:49:33 -04:00

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