; Routine: FRESET -- fast drive reset and login ; Author: Bridger Mitchell (Plu*Perfect Systems) ; CPU: Z80-compatible ; Date: January 2, 1988 ; Version: 1.0 ; ; 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 into the second drive ; logoff requested drive (fn.37) ; if no second drive was logged in ; do general reset (fn. 13) ; log into requested drive ; ; Note: Unnumbered version dated 12/27/87 did not provide for ; logging out the drive in one special case, namely when only that ; one drive is currently logged in. Thanks to Howard Goldstein ; for spotting the problem. ; 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 vector of logged-in drives 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 e,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 not logged in jr z,frese3 ; ..check next drive ld a,(reqdrv) ; or if it is the requested drive cp e ; jr z,frese3 ; ..check next drive ; ; found a second logged-in drive, so switch to it ; call fslctit ; select e'th drive call flogout ; log out requested drive jr flogit ; then log into it and exit. ; frese3: inc e ; increment drive count ld a,e cp 16 jr c,frese1 ; .. and continue for 16 drives ; ; no second drive found, ; call flogout ; log out requested drive ld c,13 ; do general reset, then (re)log requested call xbdos ; ; ; log into requested drive ; flogit: ld a,(reqdrv) ld e,a ; fslctit:ld c,14 ; select bdos drive jxbdos: jp xbdos ; ; log out the requested drive ; flogout: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 jr jxbdos ; ; ; 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  z,frese3 ; ..check next drive ; ; found a second logged-in drive, so switch to it ; call fslctit ; select e'