home *** CD-ROM | disk | FTP | other *** search
- ;--------------------------------------------------------------------
- ;
- ; INFOPLUS.ASM
- ;
- ; Version 1.25
- ;
- ; Four subprograms used by INFOPLUS.PAS:
- ;
- ; CPUID - identifies host CPU and NDP (if
- ; any)
- ; DISKREAD - reads absolute sectors from disk
- ; LONGCALL - calls a routine using a CALL FAR
- ; ATIINFO - for accessing ATI VGAWonder cards
- ;
- ; Originally by:
- ; Steve Grant
- ; Long Beach, CA
- ; January 13, 1989
- ;
- ; mods by Andrew Rossmann (8/10/90)
- ;--------------------------------------------------------------------
-
- .286P
- .8087
-
- public CPUID, DISKREAD, LONGCALL, ATIINFO
-
- CODE segment byte
-
- ; Conditional jumps are all coded with the SHORT qualifier in
- ; order to minimize the size of the .OBJ file output of Turbo
- ; Assembler.
-
- ;--------------------------------------------------------------------
-
- CPUID proc near
-
- assume cs:CODE, ds:DATA, es:nothing, ss:nothing
-
- ; On entry:
- ;
- ; BP
- ; SP => near return address
- ; offset of a cpu_info_t record
- ; segment " " " "
- ; also, the test type byte should be a 'C' or 'N' to execute the
- ; CPU or NDP tests.
- ;
- ; On exit, the cpu_info_t record has been filled in as follows:
- ;
- ; byte = CPU type
- ; word = Machine Status Word
- ; 6 bytes = Global Descriptor Table
- ; 6 bytes = Interrupt Descriptor Table
- ; boolean = segment register change/interrupt flag
- ; byte = NDP type
- ; word = NDP control word
- ; byte = test type (C or N)
-
- mCPU equ byte ptr [bx]
- mMSW equ word ptr [bx + 1]
- mGDT equ [bx + 3]
- mIDT equ [bx + 9]
- mchkint equ byte ptr [bx + 15]
- mNDP equ byte ptr [bx + 16]
- mNDPCW equ word ptr [bx + 17]
- mtest equ byte ptr [bx + 19]
-
- f8088 equ 0
- f8086 equ 1
- fV20 equ 2
- fV30 equ 3
- f80188 equ 4
- f80186 equ 5
- f80286 equ 6
- f80386 equ 7
- f80486 equ 8
- funk = 0FFH
-
- false equ 0
- true equ 1
-
- push bp
- mov bp,sp
- push ds
- lds bx,[bp + 4]
- cmp mtest, 'C'
- jnz skipcpu
- call cpu
- call chkint
- skipcpu:
- cmp mtest, 'N'
- jnz skipndp
- call ndp
- skipndp:
- pop ds
- pop bp
- ret 4
-
- ;--------------------------------------------------------------------
-
- cpu:
-
- ; interrupt of multi-prefix string instruction
-
- mov mCPU,funk ;set CPU type to unknown
- sti
- mov cx,0FFFFH
- rep lods byte ptr es:[si]
- jcxz short cpu_02
- call piq
- cmp dx,4
- jg short cpu_01
- mov mCPU,f8088
- ret
- cpu_01:
- cmp dx,6
- jne short cpu_01a
- mov mCPU,f8086
- cpu_01a:
- ret
- cpu_02:
-
- ; number of bits in displacement register used by shift
-
- mov al,0FFH
- mov cl,20H
- shl al,cl
- or al,al
- jnz short cpu_04
- call piq
- cmp dx,4
- jg short cpu_03
- mov mCPU,fV20
- ret
- cpu_03:
- cmp dx,6
- je cpu_03a
- jmp CPUID_done
- cpu_03a:
- mov mCPU,fV30
- ret
- cpu_04:
-
- ; order of write/decrement by PUSH SP
-
- push sp
- pop ax
- cmp ax,sp
- je short cpu_06
- call piq
- cmp dx,4
- jg short cpu_05
- mov mCPU,f80188
- ret
- cpu_05:
- cmp dx,6
- jne short CPUID_done
- mov mCPU,f80186
- ret
-
- ;First, grab some tables
-
- cpu_06:
- smsw mMSW
- sgdt mGDT
- sidt mIDT
-
- ;!!!!!!!
- ;!!! Original 286/386 detection code (modified 8/10/90)
- ;!!! Modified by code supplied by John Levine, apparantly from an Intel
- ;!!! '486 manual.
- ;!!!!!!!
-
- pushf ;put flags into CX
- pop cx
- and cx,0fffh ;mask off upper 4 bits
- push cx
- popf
- pushf
- pop ax
- and ax,0f000h ;look only at upper 4 bits
- cmp ax,0f000h ;88/86 etc.. turn them on
- jz badcpu ;not 286/386/486!!!
- or cx,0f000h ;force upper 4 bits on
- push cx
- popf
- pushf
- pop ax
- and ax,0f000h
- jz found286 ;bits are zeroed in real mode 286
- .386
- mov dx,sp ;save current stack position
- and sp,not 3 ;dword align to avoid traps
- pushfd ;push 32 bit flag
- pop eax
- mov ecx,eax
- xor eax,40000h ;flip AC (alignment check) flag
- push eax
- popfd
- pushfd
- pop eax
- mov sp,dx
- xor eax,ecx ;was bit changed??
- test eax,40000h
- .286
- jz found386 ;if not, is a 386
- mov mCPU,f80486 ;must be a 486!!
- jmp short CPUID_done
- found286:
- mov mCPU,f80286
- jmp short CPUID_done
- found386:
- mov mCPU,f80386
- jmp short CPUID_done
- badcpu:
- mov mCPU,funk ;how'd an 8088 get this far?????
- CPUID_done:
- ret
- ;--------------------------------------------------------------------
-
- piq:
-
- ; On exit:
- ;
- ; DX = length of prefetch instruction queue
- ;
- ; This subroutine uses self-modifying code, but can
- ; nevertheless be run repeatedly in the course of the calling
- ; program.
-
- count = 7
- opincdx equ 42H ; inc dx opcode
- opnop equ 90H ; nop opcode
-
- mov al,opincdx
- mov cx,count
- push cx
- push cs
- pop es
- mov di,offset piq_01 - 1
- push di
- std
- rep stosb
- mov al,opnop
- pop di
- pop cx
- xor dx,dx
- cli
- rep stosb
- rept count
- inc dx
- endm
- piq_01:
- sti
- ret
-
- ;--------------------------------------------------------------------
-
- chkint:
-
- ; save old INT 01H vector
-
- push bx
- mov ax,3501H
- int 21H
- mov old_int01_ofs,bx
- mov old_int01_seg,es
- pop bx
-
- ; redirect INT 01H vector
-
- push ds
- mov ax,2501H
- mov dx,seg new_int01
- mov ds,dx
- mov dx,offset new_int01
- int 21H
- pop ds
-
- ; set TF and change SS -- did we trap on following instruction?
-
- pushf
- pop ax
- or ah,01H ; set TF
- push ax
- popf
- push ss ; CPU may wait one
- ; instruction before
- ; recognizing single step
- ; interrupt
- pop ss
- chkint_01: ; shouldn't ever trap here
-
- ; restore old INT 01H vector
-
- push ds
- mov ax,2501H
- lds dx,old_int01
- int 21H
- pop ds
- ret
-
- ;--------------------------------------------------------------------
-
- new_int01:
-
- ; INT 01H handler (single step)
- ;
- ; On entry:
- ;
- ; SP => IP
- ; CS
- ; flags
-
- sti
- pop ax ; IP
- cmp ax,offset chkint_01
- jb short new_int01_03
- je short new_int01_01
- mov mchkint,false
- jmp short new_int01_02
- new_int01_01:
- mov mchkint,true
- new_int01_02:
- pop cx ; CS
- pop dx ; flags
- and dh,0FEH ; turn off TF
- push dx ; flags
- push cx ; CS
- new_int01_03:
- push ax ; IP
- iret
- ;--------------------------------------------------------------------
-
- ndp:
-
- fnone equ 0
- f8087 equ 1
- f80287 equ 2
- f80387 equ 3
- funk = 0FFH
-
- mov word ptr ndp_cw,0000H
- cli
-
- ; The next three 80x87 instructions cannot carry the WAIT prefix,
- ; because there may not be an 80x87 for which to wait. The WAIT is
- ; therefore emulated with a MOV CX,<value>! LOOP $ combination.
-
- .287
- ; CPU NDP
- fnsave ndp_save ; 14 221
- mov cx,(221-6-1)/17+1 ; 4
- loop $ ; 17*CX-12
- ; 17*CX+6
-
- fninit ; 8 8
- mov cx,(8-0-1)/17+1 ; 4
- loop $ ; 17*CX-12
- ; 17*CX
-
- fnstcw ndp_cw ; 14 24
- mov cx,14h
- loop $ ; 17*CX-12
- ; 17*CX+2
-
- sti
- mov ax,ndp_cw
- and ax,0f3fh
- cmp ax,33fh
- je short ndp_01
- mov mNDP,fnone
- ret
- ndp_01:
- mov ax,ndp_cw
- cmp ax,03FFH
- jne short ndp_02
- mov mNDP,f8087
- jmp short ndp_04
- ndp_02:
-
- .287
-
- cmp ax,037FH
- jne short ndp_05
- fld1
- fldz
- fdiv
- fld1
- fchs
- fldz
- fdiv
- fcom
- fstsw ndp_sw
- mov ax,ndp_sw
- and ah,41H ; C3, C0
- cmp ah,40H ; ST(0) = ST(1)
- jne short ndp_03
- mov mNDP,f80287
- jmp short ndp_04
- ndp_03:
- cmp ah,01H ; ST(0) < ST(1)
- jne short ndp_05
- mov mNDP,f80387
- ndp_04:
-
- .8087
-
- frstor ndp_save
- fstcw mNDPCW
- ret
- ndp_05:
- mov mNDP,funk
- ret
-
- CPUID endp
-
- ;--------------------------------------------------------------------
-
- DISKREAD proc near
-
- assume cs:CODE, ds:DATA, es:nothing
-
- ; On entry:
- ;
- ; BP
- ; SP => near return address
- ; offset of disk buffer
- ; segment " " "
- ; number of sectors to read
- ; starting logical sector number
- ; drive number (0=A, 1=B, etc.)
- ;
- ; On exit:
- ;
- ; AX = function result
- ; 00 - function successful
- ; 01..FF - DOS INT 25H error result
-
- drive equ [bp + 12]
- starting_sector equ [bp + 10]
- number_of_sectors equ [bp + 8]
- buffer equ [bp + 4]
-
- push bp
- mov bp,sp
- mov ax,3000h ;get DOS version
- int 21h
- cmp al,4 ;DOS 4?
- jb read3 ;Read assuming DOS 3.x
- mov al,drive
- mov bx,starting_sector ;copy info into parameter block
- mov extd_starting_sector_lo,bx
- mov extd_starting_sector_hi,0 ;We're only using lower part
- mov bx,number_of_sectors
- mov extd_number_of_sectors,bx
- les bx,buffer ;get seg:ofs of buffer in ES:BX
- mov extd_bufofs,bx ;put into block
- mov extd_bufseg,es
- mov bx,offset dos4_block ;DS:BX points to block
- mov cx,-1 ;-1 means extended read
- push ds ;save DS (not really needed, but lets
- ;me share code with DOS 3 read.)
- jmp short readit
-
- read3: mov al,drive
- mov dx,starting_sector
- mov cx,number_of_sectors
- push ds
- lds bx,buffer ;get seg:ofs of buffer in DS:BX
- readit: int 25H
- inc sp ; fix broken stack
- inc sp
- pop ds
- jc short diskread_01
- xor ax,ax
- diskread_01:
-
- pop bp
- ret 10
-
- DISKREAD endp
-
- ;
- ;LONGCALL will call a routine using a CALL FAR. This is used by XMS
- ;
- ;Pascal format: procedure longcall(AXi: word; var addr: longint;
- ; var AXo, BXo, DXo: word); external;
- ;
-
- longcall proc near
- assume cs:CODE, ds:DATA, es:nothing
-
- AXi equ [bp+20] ;set up correct pointers
- addr equ [bp+16]
- AXo equ [bp+12]
- BXo equ [bp+8]
- DXo equ [bp+4]
-
- push bp ;setup BP
- mov bp,sp
- les di,addr ;copy address to call into
- mov ax,es:[di] ; local variable
- mov word ptr address,ax
- mov ax,es:[di+2]
- mov word ptr address+2,ax
- mov ax,AXi ;get function number
- call dword ptr address ;do far call
- les di,DXo ;save DX, BX, and AX to correct
- mov [es:di],dx ; Pascal variables.
- les di,BXo
- mov [es:di],bx
- les di,AXo
- mov [es:di],ax
- pop bp ;restore stack
- ret 18
- longcall endp
-
- ;
- ; ATIINFO is used in the Video identification routine to get special
- ; information from ATI VGA Wonder cards.
- ;
- ; Pascal format: function ATIinfo(data_in: byte, register: word): byte;
- ;
- ATIinfo proc near
- assume cs:CODE, ds:DATA, es:NOTHING
-
- data_in equ [bp+6]
- register equ [bp+4]
-
- push bp
- mov bp,sp
- mov dx,register ;get register
- mov ax,data_in ;get command word (actually byte)
- cli ;no interrupts
- out dx,al
- inc dx ;next port
- in al,dx ;get result
- sti ;restore interrupts
- mov sp,bp
- pop bp
- ret 4
-
- ATIinfo endp
-
- code ends
-
- ;--------------------------------------------------------------------
-
- DATA segment byte
-
- ; storage for CPUID
-
- ; redirected INT 01H vector
-
- old_int01 label dword
- old_int01_ofs dw ?
- old_int01_seg dw ?
-
- ; storage for NDPID
-
- ; 80x87 control word after initialization, status word after divide by zero
-
- ndp_cw dw ?
- ndp_save db 94 dup (?)
- ndp_sw dw ?
-
- ; storage for DISKREAD
-
- ; DOS 4.0 extended read parameter block
- dos4_block label byte
- extd_starting_sector_lo dw ?
- extd_starting_sector_hi dw ?
- extd_number_of_sectors dw ?
- extd_bufofs dw ?
- extd_bufseg dw ?
-
- ; storage for LONGCALL
-
- address dd ?
-
- DATA ends
-
- end
-