home *** CD-ROM | disk | FTP | other *** search
- page 58,132
- TITLE Go -- Control (and measure) speed for Heath/Zenith PC
-
- ; (c) Copyright 1987 David E. Tweten
-
- ; All rights reserved. Permission for distribution is granted
- ; provided that no direct commercial advantage is gained, and
- ; provided that this copyright notice appears on all copies.
-
- ; --------------------------------------------------------------------
- ;
- ; Go serves three purposes relating to Dante Bencivengo's "TurboPlus
- ; V2.0" modification to 4.77 MHz Heath/Zenith PCs. It permits FORMAT
- ; and VERIFY ON to work. It also permits the user to speed or slow
- ; the processor. Finally, it measures the processor's speed setting
- ; (primarily for batch file use). "TurboPlus", the predecessor
- ; version of "TurboPlus V2.0", was described in the June, 1986 issue
- ; of REMark, the journal of the Heath/Zenith Users' Group.
- ;
- ; Due to a quirk in the diskette BIOS, errors will occur when a track
- ; format or verify operation is requested at any high speed, or when
- ; any diskette operation is attempted at 8 MHz. The terminate-and-
- ; stay-resident portion of this code will prevent the errors from
- ; occuring by slowing the processor for the duration of the
- ; operation, unless it is already operating at the slow (4.77 MHz)
- ; speed.
- ;
- ; The optional switch for Go can specify the speed to use when not
- ; formatting or verifying a floppy disk. It can be "f", which will
- ; set the clock speed to fast, or it can be "s", which will set the
- ; clock speed to slow. In any but its initial (TSR installing) call,
- ; if no switch is given, Go does not change the speed setting. On
- ; the initial call, if no argument is given, Go assumes "f". Go uses
- ; whatever switch character is current.
- ;
- ; The termination code for Go is set according to the processor speed
- ; at call, and by whether or not it has previously been called. The
- ; meaning of its termination code is as follows:
- ;
- ; 0 - Go has been called before so the TSR portion is already
- ; resident. Before the call the clock was set to run at
- ; 4.77 MHz.
- ;
- ; 1 - Go has been called before so the TSR portion is already
- ; resident. Before the call the clock was set to run at
- ; its fast speed.
- ;
- ; 2 - Go has not been called before. This call installed the TSR
- ; code and set the clock speed to the specified value (either
- ; Fast or Slow). If no speed was specified on the call, the
- ; default of Fast was used.
- ;
- ; 3 - Go has been called in error. It did nothing.
- ;
- ; NOTE that the actual processor speed is the slower of the speed
- ; specified and detected by Go, and the speed specified by the
- ; hardware switch included in the "TurboPlus V2.0". The actual speed
- ; is indicated by the LED included with the "TurboPlus V2.0" package.
- ;
- ; Written by: David E. Tweten <tweten@prandtl.nas.nasa.gov>
- ;
- ; 12141 Atrium Drive
- ; Saratoga, CA 95070
- ;
- ; (408) 446-4131
- ;
- ; Inspiration: FV.COM, a program of unstated authorship, included on
- ; the "TurboPlus" software disk.
- ;
- ; Modification History:
- ;
- ; 1.0 5-10-87 Initial version.
- ;
- ; --------------------------------------------------------------------
-
- IGROUP group _TEXT
-
- BLK_HDR_SEGMENT segment at 00000H
- blk_flag db ? ; 'M' for normal, 'Z' for final block
- blk_owner dw ? ; segment of owner's PSP
- blk_psize dw ? ; block size in paragraphs
- BLK_HDR_SEGMENT ends
-
- STDOUT equ 1 ; File handle for Standard Output
- STDERR equ 2 ; File handle for Standard Error
- CR equ 0DH ; ASCII code for Carriage Return
- LF equ 0AH ; ASCII code for Line Feed
- HT equ 09H ; ASCII code for Horizontal Tab
- LEDS equ 0C0H ; Port address of "CPU LEDs"
- SLOW equ 1FH ; Turn off all LEDs but "RDY"
- FAST equ 3FH ; Turn off all LEDs
- VERIFY equ 4 ; Diskette sector verify service number
- FORMAT equ 5 ; Format diskette track service number
-
- SUBTTL Resident Interrupt Filter
- page
- _TEXT segment para public 'CODE'
- assume cs:_TEXT,ds:NOTHING,es:NOTHING,ss:NOTHING
-
- org 02CH
- env_seg dw ? ; Seg addr for our copy of environment
-
- org 05CH
- beg_ovr: ; Beginning of overwritten PSP area
-
- org 080H
- istrlen db ? ; Invocation string and length
- istring equ $
-
- org 100h
- START: jmp go ; Jump around the resident portion.
-
- org 10CH ; Offset in paragraph same as beg_ovr
- beg_pr: ; Beginning of part to move into PSP
-
- res_offs equ (beg_pr-beg_ovr) SHR 4 ; Paragraphs to move resident
-
- rom_dsk dd ? ; ROM INT 13 service routine address
- speed db FAST ; "Normal" speed, set by command switch
-
- int_13 proc far
- pushf ; IF and TF were cleared by the INT 13.
- cmp dl,80h ; If it's a Winchester operation,
- jae short call_rom ; just go do it.
- ;
- ; The following code block is for TurboPlus V2.0 installations running at
- ; speeds below 8.0 MHz. At 8.0 MHz, all floppy disk operations must be
- ; performed at low speed. Below 8.0 MHz, only "verify sector" and "format
- ; track" need to be run at low speed.
- ;
- ifndef MHZ8
- cmp ah,VERIFY ; If it's not a verify operation,
- je short go_slow
- cmp ah,FORMAT ; and it's not a format operation,
- jne short call_rom ; just do it.
- go_slow:
- endif
- ;
- ; The previous code block is for TurboPlus V2.0 installations running at
- ; speeds below 8.0 MHz.
- ;
- popf ; Recover flags at entry, and leave
- pushf ; them at stack top for simulated INT.
- push ax
- mov al,SLOW
- out LEDS,al ; Slow to 4.77 MHz.
- pop ax
- call rom_dsk ; Simulate INT 13 with return here.
- push ax
- mov al,speed
- out LEDS,al ; Resume speed(ing).
- pushf ; Put flags where we can get them.
- push bp
- mov bp,sp
- mov ax,[bp+10] ; Extract IF and TF from user's flags,
- and ax,300H
- or ax,[bp+2] ; merge them with returned flags,
- mov [bp+10],ax ; and put them back for the IRET.
- pop bp ; Restore the registers,
- add sp,+2 ; ignoring the flags.
- pop ax
- iret ; Return to caller with proper flags.
-
- call_rom:
- popf ; Recover flags at entry.
- jmp rom_dsk ; Simulate interrupt entry into ROM.
- int_13 endp
-
- res_bl equ $-beg_pr ; Length of resident
- cod_bl equ $-int_13 ; Length of resident code
-
- SUBTTL Non-resident Code
- page
- assume ds:_TEXT,es:_TEXT,ss:_TEXT
- ;
- ; Non-resident data
- ;
- copyright db "(c) Copyright 1987 David E. Tweten. All rights reserved."
- version db "Go version 1.0 installed, for use "
- ifdef MHZ8
- db "at"
- else
- db "below"
- endif
- db " 8.0 MHz.", CR, LF
- VERSION_L equ $-version
- mes_env db "Warning: can't return environment copy memory.", CR, LF
- MES_ENV_L equ $-mes_env
- mes_err db "Error: switch value unrecognized.", CR, LF
- MES_ERR_L equ $-mes_err
- mes_use db "Usage: go [ "
- swchar db "*"
- db "fs ]", CR, LF
- MES_USE_L equ $-mes_use
-
- even
-
- sibling dw ? ; Effective PSP segment addr of twin
-
- go:
- cld
- mov ax,3700H ; Get switch character
- int 21H ; (UNDOCUMENTED MS-DOS FUNCTION).
- mov swchar,dl
- mov ah,52H ; Get seg. addr. of first memory block
- int 21H ; (UNDOCUMENTED MS-DOS FUNCTION).
- mov dx,es:[bx-2]
- mov sibling,ds ; Initialize PSP seg. addr. to our own.
- blkscn:
- assume es:BLK_HDR_SEGMENT ; See if we're already installed.
- mov es,dx
- cmp blk_flag,'Z' ; If we've checked the last block,
- je short first ; end this nonsense.
- inc dx ; Compute segment address of next
- add dx,blk_psize ; block.
- mov ax,blk_owner ; Get block owner's PSP segment addr.
- sub ax,res_offs ; Modify it to account for our resident
- mov es,ax ; code shift.
- mov si,offset int_13 ; Get offset for the resident code.
- mov di,si
- mov cx,cod_bl ; Get resident code byte count.
- repe cmpsb ; OK, we've seen the enemy; is he us?
- jne blkscn ; If he ain't, keep looking.
- mov sibling,es ; Save segment address of our twin.
- mov ah,es:speed ; Set our default to our twin's.
- first:
- assume es:_TEXT
- mov dx,ds
- mov es,dx
- mov si,offset istring ; Initialize argument string pointer
- mov cl,istrlen ; and count.
- xor ch,ch
- whitesp:
- jcxz short default ; Skip over leading white space in
- lodsb ; argument string.
- dec cx
- cmp al,' '
- je whitesp
- cmp al,HT
- je whitesp
- cmp al,swchar ; If first non-blank is not the switch
- jne short badarg ; character, return error.
- mov al,[si] ; Get the switch value.
- or al,20H ; Force it to lowercase.
- mov ah,FAST ; If the switch is "/f", it's fast.
- cmp al,'f'
- je short found
- mov ah,SLOW ; If the switch is "/s", it's slow.
- cmp al,'s'
- je short found
- badarg:
- mov ah,40H ; If none of the above, it's an error;
- mov dx,offset mes_err ; complain bitterly.
- mov cx,MES_ERR_L
- mov bx,STDERR
- int 21H
- error:
- mov ah,40H ; Display usage message.
- mov dx,offset mes_use
- mov cx,MES_USE_L
- mov bx,STDERR
- int 21H
- mov al,3 ; Set return error status.
- exit:
- mov ah,4ch ; Exit with status.
- int 21H
-
- found:
- mov al,ah ; Change to the new speed.
- out LEDS,al
- mov es,sibling ; Note the new default speed.
- xchg es:speed,ah
- mov dx,ds
- mov es,dx
- default:
- cmp dx,sibling
- je short grabint
- mov al,0
- cmp ah,SLOW
- je exit
- mov al,1
- jmp exit
-
- grabint:
- mov ax,3513H ; Get address of diskette (13H)
- int 21H ; interrupt response routine.
- mov (word ptr rom_dsk)[word * 0],bx ; Move ES:BX to rom_dsk.
- mov (word ptr rom_dsk)[word * 1],es
- mov ax,cs ; Relocate our resident portion.
- mov es,ax
- mov si,offset beg_pr
- mov di,offset beg_ovr
- mov cx,res_bl
- rep movsb
- mov ax,cs ; Now set new value in the interrupt
- sub ax,res_offs ; vector for 13H
- mov ds,ax
- mov dx,offset int_13
- mov ax,2513H ; as int_13.
- int 21H
- mov ax,cs ; Restore data segment register.
- mov ds,ax
- mov ah,40H
- mov dx,offset version
- mov cx,VERSION_L
- mov bx,STDOUT
- int 21H ; Display the version number.
- mov es,env_seg ; Return space for copy of environment.
- mov ah,49H
- int 21H
- jnc short tsr ; If we can't give back the environment
- mov ah,40H ; copy, complain (but not bitterly).
- mov dx,offset mes_env
- mov cx,MES_ENV_L
- mov bx,STDERR
- int 21H
- tsr:
- mov dx,di ; Terminate and stay resident.
- add dx,15
- mov cl,4
- shr dx,cl
- mov ax,3102H ; Compute size of resident portion in
- int 21H ; paragraphs, and leave it behind.
-
- _TEXT ends
- end START