; Routine: FRESET -- fast drive reset and login ; Author: Bridger Mitchell (Plu*Perfect Systems) ; CPU: Z80-compatible ; Date: December 27, 1987 ; ; This routine (fast-)resets and logs in the cp/m drive in register ; (A). When possible, it uses BDOS function 37 (logoff drives). ; In most cases FRESET is significantly faster than using function 13 ; (reset all drives) to do a general reset. ; ; FRESET functions correctly with Digital Research's CP/M 2.2 bdos, ; which contains a bug that does not allow the logged-in drive to ; be reset with function 37. ; ; Some CP/M bdos emulators (such as ZRDOS, PZDOS, ...) have changed ; the operation of the general-reset function 13, in order to speed ; up warm-boots and disk-resets on systems with hard-drives. In this ; case, a non-removable drive (hard disk, ram disk), after it ; has been initially logged in, remains logged in after a general ; reset. ; ; On such systems it is **essential** that any program that uses ; BIOS disk functions to write to a non-removable drive also cause ; the disk's allocation map to be rebuilt before any BDOS disk ; functions are used. DU (DU3) and UNERASE are probably the most ; common examples of such programs; they modify the disk directory. ; For these systems, the drive must first be logged off with ; function 37 and then logged in. Calling FRESET within such ; programs will ensure that the disk's allocation map is recomputed. ; ; The FRESET algorithm: ; ; if requested_drive is logged in ; if a second drive is logged in ; log in the second drive ; logoff requested drive (fn.37) ; else ; do general reset (fn. 13) ; log in requested drive ; ; xbdos equ 5 ; Fast-reset drive (A) ; A = 0 ... 15 for A: ... P: ; CSEG freset: ld (reqdrv),a ; save requested drive push af ld c,24 ; get logged-in drives vector call xbdos pop af ; (recover requested drive) push hl ; save logged-in vector call fshftr ; shift requested drive's bit to bit 0 bit 0,l ; is requested drive logged in? pop hl ; (recover (unshifted) logged vector) jr z,flogit ; ..z - no, just log it in ld b,0 ; initialize drive index/count jr frese2 ; frese1: ld a,1 ; shift vector right 1 bit call fshftr frese2: bit 0,l ; if drive is logged in jr z,frese3 ; ld a,(reqdrv) ; .. and it is not requested drive cp b jr nz,fnd2nd ; .. have found 2nd logged in drive frese3: inc b ; else increment drive count ld a,b ; and continue for 16 drives cp 16 jr c,frese1 ; ld c,13 ; no other drive is logged in, so.. jr flogit0 ; ..do general reset, then (re)log requested ; ; have a second logged-in drive, so switch to it ; fnd2nd: ld e,b ; select b'th drive call fslctit ld a,(reqdrv) ; set up bit to log out drive ld hl,1 call fshftl ex de,hl ld c,37 ; log out drive in DE vector ; flogit0:call xbdos ; ; login requested drive ; flogit: ld a,(reqdrv) ld e,a fslctit:ld c,14 ; select bdos drive jp xbdos ; ; ; shift hl right (a) bits ; fshftr: inc a shftr1: dec a ret z srl h rr l jr shftr1 ; ; ; shift hl left (a) bits ; fshftl: inc a shftl1: dec a ret z add hl,hl jr shftl1 ;-------------------- DSEG reqdrv: ds 1 end