#define TRUE 1 #define FALSE 0 #define _SVDC_ db 36h, 0fh, 78h, 1fh int old_off; int old_seg; extern ill_op(); /***************************************************************************** * Function: isb() * * Purpose: Determine if 486SLC/DLC is rev. A or B * * Technique: A step devices do not support SMM. By executing an SMM * instruction without an invalid opcode exception the device * is a B step device or later. To execute the SMM instruction * this routine must be operating at CPL 0 or REAL mode. V86 * mode, CPL 1,2, and 3 are NOT permissable. A check for V86 * should be done before calling this routine. * * Parameters: Nothing * * Returns: 0 if A step * 1 if B step device * * Calls: DOS via int 21 function 35,25 * - To load new invalid opcode handler *****************************************************************************/ isb () { int i, b_step; char mem[10]; char save_ccr1, save_cf, save_ce, save_cd; for (i=0; i<10; mem[i++]=0); asm { .386 extrn _ill_op:near ;***** save flag and turn off interrupts ***** pushf cli ;********************************************* ;****** get present invalid opcode handler ;********************************************* push es mov ax, 3506h int 21h mov old_seg, es mov old_off, bx pop es ;********************************************* ;****** install new invalid opcode handler ;********************************************* push ds mov ax, 2506h mov dx, OFFSET _ill_op mov bx, cs mov ds, bx int 21h pop ds ;************************************************************* ;****** Set SM4 and SMAC and SMI bit to allow SMM instructions ;************************************************************* mov al, 0c1h out 22h, al in al, 23h mov byte ptr [save_ccr1], al or al, 86h mov ah, al mov al, 0c1h out 22h, al mov al, ah out 23h, al ;************************************************************ ;***** Setup non-zero SMM region ;************************************************************ mov al, 0cfh out 22h, al in al, 23h mov byte ptr [save_cf], al mov al, 0cfh out 22h, al mov al, 1 out 23h, al ;******************************************** ;**** Set SMM region to the top of memory to ;**** avoid overlapping with this program. ;******************************************** mov al, 0cdh out 22h, al in al, 23h mov byte ptr [save_cd], al mov al, 0ceh out 22h, al in al, 23h mov byte ptr [save_ce], al mov al, 0cdh out 22h, al mov al, 0ffh out 23h, al mov al, 0ceh out 22h, al mov al, 0h out 23h, al mov al, 0cfh out 22h, al in al, 23h and al, 0fh out 23h, al ;********************* flush instruction cache ************** jmp $+2 ;********************************************* ;****** Execute SMM instruction svdc ;********************************************* ;svdc word ptr mem, ds ; word ptr mem == ss:[bx] lea bx, mem _SVDC_ ;********************************************** ;***** restore configuration registers ;********************************************** mov al, 0cdh out 22h, al mov al, byte ptr save_cd out 23h, al mov al, 0ceh out 22h, al mov al, byte ptr save_ce out 23h, al mov al, 0cfh out 22h, al mov al, byte ptr save_cf out 23h, al mov al, 0c1h out 22h, al mov al, byte ptr save_ccr1 out 23h, al ;********************************************* ;****** restore old invalid opcode handler ;********************************************* push ds mov ax, 2506h mov dx, [old_off] mov bx, [old_seg] mov ds, bx int 21h pop ds ;****** restore flags ****** popf } // isb asm region for (i=0,b_step=FALSE; i<10; ++i) if (mem[i] != 0) { b_step = TRUE; break; } return (b_step); } // isb ()