home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / GLEN / IFP1S147.ZIP / INFOPLUS.ASM < prev    next >
Assembly Source File  |  1991-08-02  |  33KB  |  1,050 lines

  1. ;--------------------------------------------------------------------
  2. ;
  3. ;       INFOPLUS.ASM
  4. ;
  5. ;       Version 1.47
  6. ;
  7. ;       Eleven subprograms used by INFOPLUS.PAS:
  8. ;
  9. ;               CPUID           - identifies host CPU and NDP (if
  10. ;                                       any)
  11. ;               DISKREAD        - reads absolute sectors from disk
  12. ;               LONGCALL        - calls a routine using a CALL FAR
  13. ;               ATIINFO         - for accessing ATI VGAWonder cards
  14. ;               ALTINTR         - calls interrupts with a true INT call
  15. ;               ALTMSDOS        - calls DOS with a true INT call
  16. ;               CIRRUSCK        - Cirrus VGA check
  17. ;               CTICK           - Chips & Technologies VGA check
  18. ;               TSENGCK         - Tseng VGA check
  19. ;               ZYMOSCK         - ZyMOS VGA check
  20. ;               BUGTST          - Test for 386 POPAD bug
  21. ;
  22. ;       Originally by:
  23. ;       Steve Grant
  24. ;       Long Beach, CA
  25. ;       January 13, 1989
  26. ;
  27. ;       mods by Andrew Rossmann (8/2/91)
  28. ;--------------------------------------------------------------------
  29.  
  30. .286P
  31. .8087
  32.  
  33.         public  CPUID, DISKREAD, LONGCALL, ATIINFO, ALTINTR, ALTMSDOS
  34.         public  CTICK, TSENGCK, ZYMOSCK, CIRRUSCK, BUGTST
  35.  
  36. CODE    segment byte
  37.  
  38. ;       Conditional jumps are all coded with the SHORT qualifier in
  39. ;       order to minimize the size of the .OBJ file output of Turbo
  40. ;       Assembler.
  41.  
  42. ;--------------------------------------------------------------------
  43.  
  44. CPUID   proc    far
  45.  
  46. assume  cs:CODE, ds:DATA, es:nothing, ss:nothing
  47.  
  48. ;       On entry:
  49. ;
  50. ;               BP
  51. ;       SP =>   near return address
  52. ;               offset  of a cpu_info_t record
  53. ;               segment "  "     "        "
  54. ;       also, the test type byte should be a 'C' or 'N' to execute the
  55. ;       CPU or NDP tests.
  56. ;
  57. ;       On exit, the cpu_info_t record has been filled in as follows:
  58. ;
  59. ;               byte    = CPU type
  60. ;               word    = Machine Status Word
  61. ;               6 bytes = Global Descriptor Table
  62. ;               6 bytes = Interrupt Descriptor Table
  63. ;               boolean = segment register change/interrupt flag
  64. ;               byte    = NDP type
  65. ;               word    = NDP control word
  66. ;               byte    = Weitek presence
  67. ;               byte    = test type (C, N, or W)
  68.  
  69. cpu_info        equ     [bp + 6]
  70.  
  71. mCPU    equ     byte ptr [bx]
  72. mMSW    equ     word ptr [bx + 1]
  73. mGDT    equ     [bx + 3]
  74. mIDT    equ     [bx + 9]
  75. mchkint equ     byte ptr [bx + 15]
  76. mNDP    equ     byte ptr [bx + 16]
  77. mNDPCW  equ     word ptr [bx + 17]
  78. mWeitek equ     byte ptr [bx + 19]
  79. mtest   equ     byte ptr [bx + 20]
  80.  
  81. f8088   equ     0
  82. f8086   equ     1
  83. fV20    equ     2
  84. fV30    equ     3
  85. f80188  equ     4
  86. f80186  equ     5
  87. f80286  equ     6
  88. f80386  equ     7
  89. f80486  equ     8
  90. funk    =       0FFH
  91.  
  92. false   equ     0
  93. true    equ     1
  94.  
  95.         push    bp
  96.         mov     bp,sp
  97.         push    ds
  98.         lds     bx,cpu_info
  99.         cmp     mtest, 'C'
  100.         jnz     skipcpu
  101.         call    cpu
  102.         call    chkint
  103. skipcpu:
  104.         cmp     mtest, 'N'
  105.         jnz     skipndp
  106.         call    ndp
  107. skipndp:
  108.         cmp     mtest, 'W'
  109.         jnz     skipweitek
  110.         call    weitek
  111. skipweitek:
  112.         pop     ds
  113.         pop     bp
  114.         ret     4
  115. CPUID   endp
  116.  
  117. ;--------------------------------------------------------------------
  118.  
  119. cpu     proc    near
  120.  
  121. ; interrupt of multi-prefix string instruction
  122.  
  123.         mov     mCPU,funk               ;set CPU type to unknown
  124.         sti
  125.         mov     cx,0FFFFH
  126. rep     lods    byte ptr es:[si]
  127.         jcxz    short cpu_02
  128.         call    piq
  129.         cmp     dx,4
  130.         jg      short cpu_01
  131.         mov     mCPU,f8088
  132.         jmp     cpu_done
  133. cpu_01:
  134.         cmp     dx,6
  135.         jne     cpu_01a
  136.         mov     mCPU,f8086
  137. cpu_01a:
  138.         jmp     cpu_done
  139. cpu_02:
  140.  
  141. ; number of bits in displacement register used by shift
  142.  
  143.         mov     al,0FFH
  144.         mov     cl,20H
  145.         shl     al,cl
  146.         or      al,al
  147.         jnz     short cpu_04
  148.         call    piq
  149.         cmp     dx,4
  150.         jg      short cpu_03
  151.         mov     mCPU,fV20
  152.         jmp     cpu_done
  153. cpu_03:
  154.         cmp     dx,6
  155.         je      cpu_03a
  156.         jmp     cpu_done
  157. cpu_03a:
  158.         mov     mCPU,fV30
  159.         jmp     cpu_done
  160. cpu_04:
  161.  
  162. ; order of write/decrement by PUSH SP
  163.  
  164.         push    sp
  165.         pop     ax
  166.         cmp     ax,sp
  167.         je      short cpu_06
  168.         call    piq
  169.         cmp     dx,4
  170.         jg      short cpu_05
  171.         mov     mCPU,f80188
  172.         jmp     cpu_done
  173. cpu_05:
  174.         cmp     dx,6
  175.         jne     short cpu_done
  176.         mov     mCPU,f80186
  177.         jmp     cpu_done
  178.  
  179. ; We most likely have a 286, 386 or 486 CPU by now
  180. ;First, grab some tables
  181.  
  182. cpu_06:
  183.         smsw    mMSW
  184.         sgdt    mGDT
  185.         sidt    mIDT
  186.  
  187. ;!!!!!!!
  188. ;!!! Original 286/386 detection code (modified 8/10/90)
  189. ;!!! Modified by code supplied by John Levine, apparantly from an Intel
  190. ;!!! '486 manual.
  191. ;!!!!!!!
  192.  
  193.         pushf                           ;put flags into CX
  194.         pop     cx
  195.         and     cx,0fffh                ;mask off upper 4 bits
  196.         push    cx
  197.         popf
  198.         pushf
  199.         pop     ax
  200.         and     ax,0f000h               ;look only at upper 4 bits
  201.         cmp     ax,0f000h               ;88/86 etc.. turn them on
  202.         jz      badcpu                  ;not 286/386/486!!!
  203.         or      cx,0f000h               ;force upper 4 bits on
  204.         push    cx
  205.         popf
  206.         pushf
  207.         pop     ax
  208.         and     ax,0f000h
  209.         jz      found286                ;bits are zeroed in real mode 286
  210. ;
  211. ;since we probably have have a 386 or 486 by now, we need to do some 32-bit
  212. ;work. Detect the 486 by seeing if the Alignment Check flag is settable. This
  213. ;flag only exists on the '486.
  214. ;
  215. .386
  216.         and     esp,0FFFFh              ;use only 64K stack
  217.         mov     edx,esp                 ;save current stack position
  218.         and     esp,0FFFCh              ;dword align to avoid traps
  219.         pushfd                          ;push 32 bit flag
  220.         pop     eax
  221.         mov     ecx,eax                 ;save current flags
  222.         xor     eax,40000h              ;flip AC (alignment check) flag
  223.         push    eax
  224.         popfd
  225.         pushfd
  226.         pop     eax
  227.         xor     eax,ecx                 ;eliminate all but AC bit
  228.         push    ecx                     ;restore flags
  229.         popfd
  230.         mov     esp,edx                 ;restore stack position
  231.         test    eax,40000h              ;is bit set?
  232. .286
  233.         jz      found386                ;if not, is a 386
  234.         mov     mCPU,f80486             ;must be a 486!!
  235.         jmp     short cpu_done
  236. found286:
  237.         mov     mCPU,f80286
  238.         jmp     short cpu_done
  239. found386:
  240.         mov     mCPU,f80386
  241.         jmp     short cpu_done
  242. badcpu:
  243.         mov     mCPU,funk               ;how'd an 8088 get this far?????
  244. CPU_done:
  245.         ret
  246. cpu     endp
  247. ;--------------------------------------------------------------------
  248.  
  249. piq     proc    near
  250.  
  251. ;       On exit:
  252. ;
  253. ;               DX      = length of prefetch instruction queue
  254. ;
  255. ;       This subroutine uses self-modifying code, but can
  256. ;       nevertheless be run repeatedly in the course of the calling
  257. ;       program.
  258.  
  259. count   =       7
  260. opincdx equ     42H                     ; inc dx opcode
  261. opnop   equ     90H                     ; nop opcode
  262.  
  263.         mov     al,opincdx
  264.         mov     cx,count
  265.         push    cx
  266.         push    cs
  267.         pop     es
  268.         mov     di,offset piq_01 - 1
  269.         push    di
  270.         std
  271.         rep stosb
  272.         mov     al,opnop
  273.         pop     di
  274.         pop     cx
  275.         xor     dx,dx
  276.         cli
  277.         rep stosb
  278.         rept    count
  279.         inc     dx
  280.         endm
  281. piq_01:
  282.         sti
  283.         ret
  284. piq     endp
  285.  
  286. ;--------------------------------------------------------------------
  287.  
  288. chkint  proc    near
  289.  
  290. ; save old INT 01H vector
  291.  
  292.         push    bx
  293.         mov     ax,3501H
  294.         int     21H
  295.         mov     old_int01_ofs,bx
  296.         mov     old_int01_seg,es
  297.         pop     bx
  298.  
  299. ; redirect INT 01H vector
  300.  
  301.         push    ds
  302.         mov     ax,2501H
  303.         mov     dx,seg new_int01
  304.         mov     ds,dx
  305.         mov     dx,offset new_int01
  306.         int     21H
  307.         pop     ds
  308.  
  309. ; set TF and change SS -- did we trap on following instruction?
  310.  
  311.         pushf
  312.         pop     ax
  313.         or      ah,01H                  ; set TF
  314.         push    ax
  315.         popf
  316.         push    ss                      ; CPU may wait one
  317.                                         ; instruction before
  318.                                         ; recognizing single step
  319.                                         ; interrupt
  320.         pop     ss
  321. chkint_01:                              ; shouldn't ever trap here
  322.  
  323. ; restore old INT 01H vector
  324.  
  325.         push    ds
  326.         mov     ax,2501H
  327.         lds     dx,old_int01
  328.         int     21H
  329.         pop     ds
  330.         ret
  331. chkint  endp
  332. ;--------------------------------------------------------------------
  333.  
  334. new_int01       proc    near
  335.  
  336. ;       INT 01H handler (single step)
  337. ;
  338. ;       On entry:
  339. ;
  340. ;       SP =>   IP
  341. ;               CS
  342. ;               flags
  343.  
  344.         sti
  345.         pop     ax                      ; IP
  346.         cmp     ax,offset chkint_01
  347.         jb      short new_int01_03
  348.         je      short new_int01_01
  349.         mov     mchkint,false
  350.         jmp     short new_int01_02
  351. new_int01_01:
  352.         mov     mchkint,true
  353. new_int01_02:
  354.         pop     cx                      ; CS
  355.         pop     dx                      ; flags
  356.         and     dh,0FEH                 ; turn off TF
  357.         push    dx                      ; flags
  358.         push    cx                      ; CS
  359. new_int01_03:
  360.         push    ax                      ; IP
  361.         iret
  362. new_int01       endp
  363. ;--------------------------------------------------------------------
  364.  
  365. ndp     proc    near
  366.  
  367. fnone   equ     0
  368. f8087   equ     1
  369. f80287  equ     2
  370. f80387  equ     3
  371. funk    =       0FFH
  372.  
  373.  
  374. ; The next two 80x87 instructions cannot carry the WAIT prefix,
  375. ; because there may not be an 80x87 for which to wait.  The WAIT is
  376. ; therefore emulated with a MOV CX,<value>! LOOP $ combination.
  377.  
  378. .287
  379.         mov     word ptr ndp_cw,0000H
  380.         cli                     ;no interrupts during this test
  381.  
  382.         fninit                  ;initialize NDP
  383.         mov     cx,2
  384.         loop    $
  385.  
  386.         fnstcw  ndp_cw          ;store control word in ndp_cw
  387.         mov     cx,14h
  388.         loop    $
  389.  
  390.         sti
  391.         mov     ax,ndp_cw       ;check for valid status word
  392.         cmp     ah,3            ;is NDP present?
  393.         je      short ndp_01    ;if 3, must be there
  394.         mov     mNDP,fnone
  395.         jmp     short ndp_done
  396.  
  397. ndp_01:
  398.         cmp     ax,03FFH        ;check if 8087
  399.         jne     short ndp_02
  400.         mov     mNDP,f8087
  401.         jmp     short ndp_04
  402. ndp_02:
  403.  
  404. .287
  405.  
  406.         cmp     ax,037FH        ;check if 286/387/486
  407.         jne     short ndp_05    ;must be garbage
  408.  
  409. ;detect 287 or 387
  410.  
  411.         fld1                    ;Load +1.0 onto NDP stack
  412.         fldz                    ;Load +0.0 onto NDP stack
  413.         fdiv                    ;do +1/0
  414.         fld1                    ;Load +1.0 onto NDP stack
  415.         fchs                    ;Change to -1.0
  416.         fldz                    ;Load +0.0 onto NDP stack
  417.         fdiv                    ;do -1/0
  418.         fcom                    ;compare
  419.         fstsw   ndp_sw
  420.         mov     ax,ndp_sw
  421.         and     ah,41H          ; C3, C0
  422.         cmp     ah,40H          ; ST(0) = ST(1)
  423.         jne     short ndp_03
  424.         mov     mNDP,f80287
  425.         jmp     short ndp_04
  426. ndp_03:
  427.         cmp     ah,01H          ; ST(0) < ST(1)
  428.         jne     short ndp_05
  429.         mov     mNDP,f80387
  430. ndp_04:
  431.  
  432. .8087
  433.         fstcw   mNDPCW          ;save status for INFOPLUS
  434.         ret
  435. ndp_05:
  436.         mov     mNDP,funk
  437. ndp_done:
  438.         ret
  439. ndp     endp
  440.  
  441. ;------------------------------------------------------------------------------
  442. ; This checks to see if the BIOS reports a Weitek math coprocessor. This should
  443. ; only be called if a 386 or 486 is found.
  444. ; NOTE!! This may not work with all computers!!
  445.  
  446. fnoWeitek       equ     0
  447. fWeitek         equ     1
  448. fWeitek_real    equ     81h
  449.  
  450. weitek  proc    near
  451. .386
  452.         xor     eax,eax                 ;zero everything
  453.         int     11h                     ;do equipment check
  454.         test    eax,01000000h           ;check bit 24, set if Weitek present
  455.         je      no_weitek
  456.         mov     mWeitek,fWeitek
  457.         test    eax,0800000h            ;check bit 23, set if Weitek can be
  458.         je      weitek_done             ; addressed in real mode
  459.         mov     mWeitek,fWeitek_real
  460.         jmp     short weitek_done
  461. no_weitek:
  462.         mov     mWeitek,fnoWeitek
  463. weitek_done:
  464.         ret
  465. .286
  466. weitek  endp
  467.  
  468. ;--------------------------------------------------------------------
  469.  
  470. DISKREAD        proc    far
  471.  
  472. assume cs:CODE, ds:DATA, es:nothing
  473.  
  474. ;       On entry:
  475. ;
  476. ;               BP
  477. ;       SP =>   near return address
  478. ;               offset  of disk buffer
  479. ;               segment "   "     "
  480. ;               number of sectors to read
  481. ;               starting logical sector number
  482. ;               drive number (0=A, 1=B, etc.)
  483. ;
  484. ;       On exit:
  485. ;
  486. ;               AX      = function result
  487. ;                       00      - function successful
  488. ;                       01..FF  - DOS INT 25H error result
  489.  
  490.         drive                   equ     [bp + 16]
  491.         starting_sector         equ     [bp + 12]
  492.         number_of_sectors       equ     [bp + 10]
  493.         buffer                  equ     [bp + 6]
  494.  
  495.         push    bp
  496.         mov     bp,sp
  497.         mov     ax,3000h                ;get DOS version
  498.         int     21h
  499.         cmp     al,4                    ;DOS 4?
  500.         jge     read4                   ;We have 4 or newer, so use extended
  501.         cmp     ax,1d04h                ;use old for anything less than 3.30
  502.         jle     read3
  503. ;
  504. ;Check bit 1 of the device attributes bit. If it's set, then the driver
  505. ;supports use of the extended access method
  506. ;
  507.         push    es                      ;save regs
  508.         push    ds
  509.         mov     dl,drive                ;get drive number (0=A,1=B,etc)
  510.         inc     dl                      ;func uses 0=dflt, 1=A, etc..
  511.         mov     ah,32h                  ;get driver parameter block
  512.         int     21h
  513.         push    ds                      ;move ds to es
  514.         pop     es
  515.         pop     ds                      ;restore original ds
  516.         les     bx,[es:bx + 12h]        ;point ES:BX to device driver
  517.         test    word ptr [es:bx + 4],2  ;test device attributes
  518.         pop     es
  519.         jz      read3                   ;wasn't, so use old method
  520.  
  521. read4:
  522.         mov     al,drive
  523.         mov     bx,starting_sector      ;copy info into parameter block
  524.         mov     extd_starting_sector_lo,bx
  525.         mov     bx,starting_sector + 2
  526.         mov     extd_starting_sector_hi,bx
  527.         mov     bx,number_of_sectors
  528.         mov     extd_number_of_sectors,bx
  529.         les     bx,buffer               ;get seg:ofs of buffer in ES:BX
  530.         mov     extd_bufofs,bx          ;put into block
  531.         mov     extd_bufseg,es
  532.         mov     bx,offset dos4_block    ;DS:BX points to block
  533.         mov     cx,-1                   ;-1 means extended read
  534.         push    ds                      ;save DS (not really needed, but lets
  535.                                         ;me share code with DOS 3 read.)
  536.         jmp     short readit
  537.  
  538. read3:  mov     al,drive
  539.         mov     dx,starting_sector
  540.         mov     cx,number_of_sectors
  541.         push    ds
  542.         lds     bx,buffer               ;get seg:ofs of buffer in DS:BX
  543. readit: int     25H
  544.         inc     sp                      ; fix broken stack
  545.         inc     sp
  546.         pop     ds
  547.         jc      short diskread_01
  548.         xor     ax,ax
  549. diskread_01:
  550.  
  551.         pop     bp
  552.         ret     10
  553.  
  554. DISKREAD        endp
  555.  
  556. ;
  557. ;LONGCALL will call a routine using a CALL FAR.
  558. ;
  559. ;Pascal format: procedure longcall(addr: longint; var regs: registers); external;
  560. ;
  561.  
  562. longcall        proc    far
  563.         assume  cs:CODE, ds:DATA, es:nothing
  564.  
  565. regaddr equ     [bp + 6]
  566. addr    equ     [bp + 10]
  567.  
  568.         push    bp
  569.         mov     bp,sp
  570.         push    ds
  571.         mov     ax,addr                 ;copy calling address for later use
  572.         mov     word ptr cs:address,ax
  573.         mov     ax,addr+2
  574.         mov     word ptr cs:address+2,ax
  575.         lds     si,regaddr              ;get pointer to regs
  576.         mov     cs:ds_save,ds           ;save needed ones
  577.         mov     cs:si_save,si
  578.         cld                             ;go forward
  579.         lodsw                           ;load AX and hold it
  580.         push    ax
  581.         lodsw                           ;load BX
  582.         mov     bx,ax
  583.         lodsw                           ;load CX
  584.         mov     cx,ax
  585.         lodsw                           ;load DX
  586.         mov     dx,ax
  587.         lodsw                           ;load BP
  588.         mov     bp,ax
  589.         lodsw                           ;load SI and hold it
  590.         push    ax
  591.         lodsw                           ;load DI
  592.         mov     di,ax
  593.         lodsw                           ;load DS and hold it
  594.         push    ax
  595.         lodsw                           ;load ES
  596.         mov     es,ax
  597.         lodsw                           ;load Flags
  598.         and     ax,008D5h               ;mask out non-standard bits
  599.         push    bx                      ;I need a register!
  600.         mov     bx,ax
  601.         pushf                           ;get current flags in AX
  602.         pop     ax
  603.         and     ax,0F72Ah               ;mask out normal bits
  604.         or      ax,bx                   ;set needed flags
  605.         push    ax
  606.         popf
  607.         pop     bx
  608.         pop     ds                      ;get rest of regs
  609.         pop     si
  610.         pop     ax
  611.         call    dword ptr cs:address    ;make far call
  612.         pushf                           ;save flags and modified regs
  613.         push    es
  614.         push    di
  615.         mov     es,cs:save_ds           ;get regs pointer into ES:DI
  616.         mov     di,cs:save_si
  617.         cld                             ;go forward
  618.         stosw                           ;save AX
  619.         mov     ax,bx
  620.         stosw                           ;save BX
  621.         mov     ax,cx
  622.         stosw                           ;save CX
  623.         mov     ax,dx
  624.         stosw                           ;save DX
  625.         mov     ax,bp
  626.         stosw                           ;save BP
  627.         mov     ax,si
  628.         stosw                           ;save SI
  629.         pop     ax
  630.         stosw                           ;save DI
  631.         mov     ax,ds
  632.         stosw                           ;save DS
  633.         pop     ax
  634.         stosw                           ;save ES
  635.         pop     ax
  636.         stosw                           ;save Flags
  637.         pop     ds                      ;restore regs
  638.         pop     bp
  639.         ret     8
  640.  
  641. address dd      ?
  642. ds_save dw      ?
  643. si_save dw      ?
  644.  
  645. longcall endp
  646.  
  647. ;
  648. ; ATIINFO is used in the Video identification routine to get special
  649. ; information from ATI VGA Wonder cards.
  650. ;
  651. ; Pascal format: function ATIinfo(data_in: byte; register: word): byte;
  652. ;
  653. ATIinfo         proc    far
  654.         assume  cs:CODE, ds:DATA, es:NOTHING
  655.  
  656. data_in         equ     [bp+8]
  657. register        equ     [bp+6]
  658.  
  659.         push    bp
  660.         mov     bp,sp
  661.         mov     dx,register             ;get register
  662.         mov     ax,data_in              ;get command word (actually byte)
  663.         cli                             ;no interrupts
  664.         out     dx,al
  665.         inc     dx                      ;next port
  666.         in      al,dx                   ;get result
  667.         sti                             ;restore interrupts
  668.         mov     sp,bp
  669.         pop     bp
  670.         ret     4
  671.  
  672. ATIinfo endp
  673.  
  674. ; AltIntr is an alternative to the Intr function. The standard Intr function
  675. ; does not do a true Interrupt!! Instead, it gets the address of the interrupt
  676. ; from the interrupt table, loads all the registers, and then does a RETF!!!
  677. ; The address of a return routine has been pushed on the stack so that it
  678. ; returns to TP and unloads the registers. This was probably done because
  679. ; Intel saw to it that all interrupt numbers must be immediate, and Borland
  680. ; didn't want to use self-modifying code.
  681. ;   NOTE: The MsDos routine is ALSO affected by this problem. It just stuffs
  682. ; a 21h into the stack, and calls Intr!!! So you can use ALTMSDOS instead!
  683. ;   Now, normally, the above procedure works perfectly fine, except under 1
  684. ; condition. When the CPU is under protected or Virtual 86 mode. When in those
  685. ; modes, a program with higher privileges can trap an interrupt and act on it.
  686. ; I found this out the hard way by going nuts wondering why I couldn't detect
  687. ; DPMI drivers or Windows!! My alternative Interrupt functions identically to
  688. ; Borlands, but uses self-modifying code to generate a true interrupt. To
  689. ; prevent possible problems with CPU pipelining, the entry point is near the
  690. ; end of the code, and then jumps back to continue.
  691. ;
  692. ; Pascal format: procedure AltIntr(intno: byte; regs: registers); external;
  693.  
  694. ALTINTRP        proc    far
  695.         assume  cs:CODE, ds:DATA, es:NOTHING
  696.  
  697. regaddr equ     [bp + 6]
  698. intno   equ     [bp + 10]
  699.  
  700.  
  701. altcont:
  702.         lds     si,regaddr              ;point DS:SI to regs
  703.         mov     cs:save_ds,ds           ;save pointer for return
  704.         mov     cs:save_si,si
  705.         cld                             ;go forward
  706.         lodsw                           ;load AX and hold it
  707.         push    ax
  708.         lodsw                           ;load BX
  709.         mov     bx,ax
  710.         lodsw                           ;load CX
  711.         mov     cx,ax
  712.         lodsw                           ;load DX
  713.         mov     dx,ax
  714.         lodsw                           ;load BP
  715.         mov     bp,ax
  716.         lodsw                           ;load SI and hold it
  717.         push    ax
  718.         lodsw                           ;load DI
  719.         mov     di,ax
  720.         lodsw                           ;load DS and hold it
  721.         push    ax
  722.         lodsw                           ;load ES
  723.         mov     es,ax
  724.         lodsw                           ;load Flags
  725.         and     ax,008D5h               ;mask out non-standard bits
  726.         push    bx                      ;I need a register!
  727.         mov     bx,ax
  728.         pushf                           ;get current flags in AX
  729.         pop     ax
  730.         and     ax,0F72Ah               ;mask out normal bits
  731.         or      ax,bx                   ;set needed flags
  732.         push    ax
  733.         popf
  734.         pop     bx
  735.         pop     ds                      ;get rest of regs
  736.         pop     si
  737.         pop     ax
  738.         db      0cdh                    ;Int opcode
  739. intrpt  db      ?                       ;loaded with real interrupt
  740.         pushf                           ;save flags and modified regs
  741.         push    es
  742.         push    di
  743.         mov     es,cs:save_ds           ;get regs pointer into ES:DI
  744.         mov     di,cs:save_si
  745.         cld                             ;go forward
  746.         stosw                           ;save AX
  747.         mov     ax,bx
  748.         stosw                           ;save BX
  749.         mov     ax,cx
  750.         stosw                           ;save CX
  751.         mov     ax,dx
  752.         stosw                           ;save DX
  753.         mov     ax,bp
  754.         stosw                           ;save BP
  755.         mov     ax,si
  756.         stosw                           ;save SI
  757.         pop     ax
  758.         stosw                           ;save DI
  759.         mov     ax,ds
  760.         stosw                           ;save DS
  761.         pop     ax
  762.         stosw                           ;save ES
  763.         pop     ax
  764.         stosw                           ;save Flags
  765.         pop     ds                      ;restore regs
  766.         pop     bp
  767.         ret     6
  768.  
  769. altintr:
  770.         push    bp
  771.         mov     bp,sp
  772.         push    ds                      ;save DS, because we screw it up
  773.         mov     al,intno                ;get interrupt number to use
  774.         mov     cs:intrpt,al            ;and modify our code
  775.         jmp     altcont                 ;continue with rest of code
  776.  
  777. ;local storage
  778.  
  779. save_ds dw      ?
  780. save_si dw      ?
  781.  
  782. ALTINTRP        endp
  783. ;
  784. ; Pascal format: procedure AltMsDos(var regs: registers); external;
  785. ;
  786. ALTMSDOS        proc    far
  787.         assume  cs:CODE, ds:DATA, es:NOTHING
  788.  
  789.         pop     si              ;back track a bit so we can stuff
  790.         pop     dx              ;interrupt number in
  791.         pop     cx
  792.         pop     bx
  793.         mov     al,21h          ;push interrupt number
  794.         push    ax
  795.         push    bx
  796.         push    cx              ;restore other info
  797.         push    dx
  798.         push    si
  799.         jmp     ALTINTR         ;do interrupt call
  800.  
  801. ALTMSDOS        endp
  802.  
  803. CIRRUSCK        proc    far
  804.         assume  cs:CODE, ds:DATA, es:nothing;
  805.  
  806. ;Cirrus VGA detection from 'Advanced Programmer's Guide to Super VGAs'
  807.  
  808. ; Fetch address of CRT controller
  809.         mov     ax,40h          ;BIOS segment
  810.         mov     es,ax
  811.         mov     dx,es:[63h]     ;get CRTC address
  812.         push    dx              ;save
  813. ; clear Start Address register in CRTC (index 0Ch)
  814.         mov     al,0ch          ;index of Start Address reg
  815.         out     dx,al           ;select
  816.         inc     dx
  817.         in      al,dx           ;get current value
  818.         mov     ah,al           ;save
  819.         mov     al,0ch
  820.         push    ax
  821.         xor     al,al
  822.         out     dx,al           ;clear start address reg
  823.         dec     dx
  824. ; fetch unlock password
  825.         mov     al,1fh
  826.         out     dx,al           ;select id reg
  827.         inc     dx
  828.         in      al,dx           ;read unlock password
  829.         mov     ah,al           ;save
  830.         mov     bh,al           ;save again
  831. ; enable extended regs
  832.         mov     dx,3c4h         ;address of sequencer
  833.         mov     al,6            ;get extension control value
  834.         out     dx,al
  835.         inc     dx
  836.         in      al,dx
  837.         mov     bh,al           ;save current setting
  838.         dec     dx
  839.         mov     al,6
  840.         out     dx,al           ;select extension control reg
  841.         inc     dx
  842.         mov     al,ah           ;get unlock password
  843.         out     dx,al           ;enable extended regs
  844.         in      al,dx           ;read back extension reg
  845.         cmp     al,1
  846.         jne     not_cirrus      ;wasn't a cirrus
  847. ;disable extended regs
  848.         mov     al,ah           ;get unlock password
  849.         ror     al,1            ;compute lock password
  850.         ror     al,1
  851.         ror     al,1
  852.         ror     al,1
  853.         out     dx,al           ;lock extended regs
  854.         in      al,dx           ;read extended control reg
  855.         cmp     al,0            ;is it 0
  856.         jne     not_cirrus      ;wasn't cirrus
  857.         mov     al,bh           ;restore original setting
  858.         out     dx,al
  859.         pop     ax              ;restore regs
  860.         pop     dx
  861.         dec     dx              ;restore register C
  862.         out     dx,al
  863.         inc     dx
  864.         mov     al,ah
  865.         out     dx,al
  866.         mov     al,bh
  867.         mov     ah,0
  868.         jmp     short end_cirrusck
  869. not_cirrus:
  870.         mov     al,bh           ;restore register
  871.         out     dx,al
  872.         pop     ax              ;restore regs
  873.         pop     dx
  874.         dec     dx
  875.         out     dx,al
  876.         inc     dx
  877.         mov     al,ah
  878.         out     dx,al           ;restore registerC
  879.         xor     ax,ax
  880. end_cirrusck:
  881.         ret
  882.  
  883. CIRRUSCK        endp
  884.  
  885. CTICK   proc    far
  886.         assume  cs:CODE, ds:DATA, es:nothing;
  887.  
  888. ;CTI VGA detection from 'Advanced Programmer's Guide to Super VGAs'
  889.  
  890. ;place VGA in setup mode
  891.         cli
  892.         mov     dx,46e8h        ;address of setup control reg
  893.         in      al,dx
  894.         or      al,10h          ;turn on setup bit
  895.         out     dx,al           ;go to setup mode
  896. ;enable extended register bank
  897.         mov     dx,103h         ;extended reg address
  898.         in      al,dx
  899.         or      al,80h          ;turn enable bit on
  900.         out     dx,al
  901. ;read global ID
  902.         mov     dx,104h         ;global ID reg
  903.         in      al,dx
  904.         mov     ah,al           ;save
  905. ; place vga in normal mode
  906.         mov     dx,46e8h
  907.         in      al,dx
  908.         and     al,03fh
  909.         out     dx,al
  910.         sti
  911. ; read version extended register
  912.         mov     dx,3d6h
  913.         mov     al,0
  914.         out     dx,al           ;select version register
  915.         inc     dx
  916.         in      al,dx
  917.         cmp     ah,5ah          ;check for CTI ID
  918.         jne     notcti
  919.         and     al,0f0h         ;adjust chip id
  920.         shr     al,1
  921.         shr     al,1
  922.         shr     al,1
  923.         shr     al,1
  924.         cmp     al,2            ;only 0, 1 and 3 are good
  925.         je      notcti
  926.         cmp     al,4
  927.         jge     notcti
  928.         cmp     al,3
  929.         je      end_ctick
  930.         inc     al              ;adjust to match chip number
  931.         jmp     short end_ctick
  932. notcti:
  933.         xor     ax,ax
  934. end_ctick:
  935.         ret
  936.  
  937. CTICK   endp
  938.  
  939. TSENGCK proc    far
  940.         assume  cs:CODE, ds:DATA, es:nothing;
  941.  
  942. ;Tseng VGA detection from 'Advanced Programmer's Guide to Super VGAs'
  943.  
  944.         mov     dx,3cdh         ;page select reg
  945.         in      al,dx
  946.         mov     ah,al           ;save
  947.         and     al,0c0h         ;save some bits
  948.         or      al,55h          ;test value one
  949.         out     dx,al           ;write it
  950.         in      al,dx
  951.         cmp     al,55h          ;same?
  952.         jne     nottseng
  953.         mov     al,0aah         ;test value two
  954.         out     dx,al
  955.         in      al,dx
  956.         cmp     al,0aah         ;same
  957.         jne     nottseng
  958.         mov     al,ah           ;restore original settings
  959.         out     dx,al
  960.         mov     al,1
  961.         jmp     short end_tsengck
  962. nottseng:
  963.         mov     al,0
  964. end_tsengck:
  965.         ret
  966.  
  967. TSENGCK endp
  968.  
  969. ZYMOSCK proc    far
  970.         assume  cs:CODE, ds:DATA, es:nothing;
  971.  
  972. ;ZyMOS VGA detection from 'Advanced Programmer's Guide to Super VGAs'
  973.  
  974.         mov     dx,3c4h         ;extended reg bank
  975.         mov     al,0bh          ;version reg
  976.         out     dx,al
  977.         inc     dx
  978.         in      al,dx           ;get version
  979.         and     al,0fh
  980.         cmp     al,2
  981.         je      end_zymosck
  982.         mov     al,0
  983. end_zymosck:
  984.         ret
  985. ZYMOSCK endp
  986.  
  987. BUGTST  proc    far
  988. ;
  989. ; BUGTST.ASM - By: John Lauro
  990. ;              Based on bug found by Jeff Prothero
  991. ;               Adapted for Infoplus by Andrew Rossmann, 7/20/91.
  992.  
  993.         ASSUME  CS:CODE,DS:DATA,ES:nothing
  994. .386
  995.         mov     eax,12345678
  996.         mov     edx, 0
  997.         mov     edi, 0
  998.         pushad
  999.         popad
  1000.  
  1001. ; The instruction immediately following popad is the critical
  1002. ; instruction.  Simple fix, insert a NOP after popad.
  1003.  
  1004.         mov     ecx, [edx+edi]
  1005.  
  1006.         cmp     eax, 12345678
  1007. .286
  1008.         mov     al,0
  1009.         je      end_bugtst
  1010.         mov     al,1
  1011. end_bugtst:
  1012.         ret
  1013. BUGTST  endp
  1014.  
  1015. code    ends
  1016.  
  1017. ;--------------------------------------------------------------------
  1018.  
  1019. DATA    segment byte
  1020.  
  1021. ; storage for CPUID
  1022.  
  1023. ; redirected INT 01H vector
  1024.  
  1025. old_int01       label   dword
  1026. old_int01_ofs   dw      ?
  1027. old_int01_seg   dw      ?
  1028.  
  1029. ; storage for NDPID
  1030.  
  1031. ; 80x87 control word after initialization, status word after divide by zero
  1032.  
  1033. ndp_cw          dw      ?
  1034. ndp_sw          dw      ?
  1035.  
  1036. ; storage for DISKREAD
  1037.  
  1038. ; DOS 4.0 extended read parameter block
  1039. dos4_block                      label   byte
  1040. extd_starting_sector_lo         dw      ?
  1041. extd_starting_sector_hi         dw      ?
  1042. extd_number_of_sectors          dw      ?
  1043. extd_bufofs                     dw      ?
  1044. extd_bufseg                     dw      ?
  1045.  
  1046.  
  1047. DATA    ends
  1048.  
  1049.         end
  1050.