;cpu.asm - author unknown. Identifies a CPU by it's mask number.

;This list was found in the german computer magazine C'T 9/1992,page 156
;The MaskNumber is located in the (E)DX Register after a CPU reset.
;This may not work on PS/2 Systems.

;   CPU                MaskNumber

;Intel 386SX             0x2305
;Intel 386SL             0x4303
;Intel 386DX             0x0303/5/8
;Intel 486SX             0x0420
;Intel 486DX             0x0403
;Intel 486DX-33          0x0404   as reported by Jeff Dunlop
;Intel 486DX-50          0x0411
;Intel 486DX-50          0x0413   as reported by Michael Dehlwes
;Intel 486DX2            0x0432/3
;Intel RapidCAD          0x0340
;Intel 487SX             0x0420
;Intel Overdrive SX      0x0432
;Intel Overdrive DX      0x0432

;AMD   386SXL            0x2305
;AMD   386DX             0x0308
;AMD   486DX-40          0x0412   as reported by Michael Dehlwes

;Cyrix 486SLC            0x0410
;Cyrix 486DLC            0x0420

;C&T   38600SX           0x0300
;C&T   38605SX           0x0300
;C&T   38600DX           0x0300
;C&T   38605DX           0x0300

;IBM   386SLC            0xA301

cseg segment
assume cs:cseg,ds:cseg
org     0100h
.286p

main:   smsw    ax              ;get machine status
        test    ax,1            ;test if protected mode
        jz      ok              ;jump if not
        lea     dx,abort        ;offset abortmesg
        mov     ah,09           ;function number
        int     21h             ;dos call
        mov     ax,4c01h        ;programm terminate
        int     21h             ;dos call
abort   db      10,13
        db      "Cannot run because the cpu"
        db      " is already in protected mode.$"
ok:
        cli                     ;no interrupts
        mov     cs:_sp,sp       ;save sp
        mov     cs:_ss,ss       ;save ss
        mov     cs:_ds,ds       ;save ds
        sti                     ;enable interrupts
        mov     al,8fh          ;CMOS addr 0fh ; disable NMI (bit 7 set)
        out     70h,al          ;CMOS addr select
        jmp     $+2             ;delay for io
        mov     al,0ah          ;shutdown value (0ah)
        out     71h,al          ;write CMOS
        mov     ax,40h          ;BIOS data segment
        mov     es,ax           ;set es
        mov     word ptr es:[67h],offset hopp ;set shutdown offset
        mov     word ptr es:[69h],cs          ;set shutdown segment
        mov     al,0feh         ;value for keyb.controller
        out     64h,al          ;pulse cpu reset

        hlt                     ;From Elad Nachman, who reached!
hold:   jmp     hold            ;should be never reached

hopp:   cli                     ;shutdown entry addr
        mov     sp,cs:_sp       ;load sp
        mov     ss,cs:_ss       ;load ss
        mov     ds,cs:_ds       ;load ds
        mov     ax,dx           ;get cpu MaskNumber (stored in dx after reset)
        push    ax              ;save cpuid
        lea     dx,okmesg       ;offset okmesg
        mov     ah,09           ;function number
        int     21h             ;dos call
        pop     ax              ;get cpuid
        sti                     ;enable interrupts
        call    bin2he          ;print cpuid
        mov     ax,4c00h        ;function number
        int     21h             ;terminate program

bin2he:                                 ;Routine from Mitch Ames
        mov     cx,4                    ;4 hex digits
        mov     bx,10h                  ;divisor
bin2h1: xor     dx,dx                   ;zero DX for 16 bit divide
        div     bx                      ;leaves quotient in AX
        add     dl,'0'                  ;convert remainder to ASCII
        cmp     dl,'9'
        jna     bin2h2
        add     dl,'A'-'9'-1
bin2h2: push    dx                      ;put on stack
        loop    bin2h1                  ;repeat
        mov     cx,4
bin2h3: pop     ax                      ;pop most significant digit first
        mov     ah,0Eh
        mov     bx,07h                  ;color byte
        int     10h
        loop    bin2h3
        ret

_sp     dw      0               ;
_ss     dw      0               ;
_ds     dw      0               ;
okmesg  db      10,13           ;
        db      "CPU identified as $"
cseg ends
end     main

