jayacotton/find

CP/M 3 Phantom Drives

Opened this issue · 11 comments

Under CP/M 3, FIND does not seem to be detecting non-existent drives. When a non-existent drive is encountered, it is listing the contents of the last existing drive.

Thanks,

Wayne

On CP/M 3 the select drive call is more capable, it will return a status byte in register a 0 is o.k. ff is error.
I made a small change to the code to collect that info and pass it back up the line. This will hopefully fix
the ghost drive issue....

Well, the behavior is different. When I ran FIND right after booting, it seemed to do the right thing and look through all the drives that existed and didn't seem to do anything with the non-existent drives. However, after loading CP/NET, FIND showed files only from the CP/NET drive. Then, at the end, it displayed the following error for the non-existent drive that follows the CP/NET drive:

CP/M Error On L: Invalid Drive
BDOS Function = 14

Let me know if you need me to try anything else to narrow this down.

I have most of this sorted out, I can find files for
cp/m2.2
cp/m3
cp/m2.2+cp/net
not cp/3+ndos3
not net/dos

This issue I am hitting is the select drive function CP/M code 14 is not working as documented for ndos3
and net/dos. In both cases the return value in register a is 49 or 46, missing/present/network no matter.
Always 49 for drive a and 46 for all the others.
I am now investigating ndos3 to see what its doing. The dri manual says that the server does not implement
this function, (as expected) so the bug is in the z80 ... (somewhere)

Here is some trace code making the call the bdos with register e = drive number (5) in this case, and on return
I have a and hl = 2eh. This is returned for all drives in the system, regardless of local/network status.

C0Z1M0E0I0 A=05 B=040E D=0022 H=0005 S=A4A6 P=067D MOV E,A067E
-t
C0Z1M0E0I0 A=05 B=040E D=0005 H=0005 S=A4A6 P=067E CALL 0005
0005
-g,681
0681
-t
C0Z1M0E1I1 A=2E B=000E D=A4A4 H=002E S=A4A6 P=0681 LXI H,0000
0684

Here is the code that is being called in ndos3 (this is a direct call via 2 jumps)
SELDSK:
lda PARAMT
mvi d,000h
mov e,a
call CHKDSK
cpi 0ffh ; local disk
jz TBDOSP ; let BDOS handle
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^here we go to bdos to handle local drives. (we return from there)
call SETDSK
lhld MCRPNT
dcr c
mov m,c
inx h
shld MCRPNT
call SNDHDR
jmp RCVEC

The find command works for all cases but one.

cp/m3 ndos3. It will only find network files. This is due to an odd return state from
CPM_LGIN drive. It is not working as documented.

So, I hacked my way around the select drive error return problem. Now cp/m3+ndos3
is finding files on all the attached drives, and skipping the non-connected (ghost) drives.

For this case, find will not be able to tell if there is a gap in the drive list. Like boot system, then remove SD card. That could trip it up.

Seems to work as you indicated Jay. It is handling CP/M 3 + NDOS3.

If there is a drive gap under CP/M 3 + NDOS3, the missing drive returns the results of the last drive that was actually present.

-Wayne

I think its just going to have to stay that way, until I can find another way around the
drive select issue. My code depends on the select error to set up the 'known' drive
list. Very frustrating when the tools don't work.

As mentioned in my e-mail, you can make the BIOS SELDSK call in CP/M 3 and eliminate the BDOS/NDOS function 14 call. Use CP/M 3 BDOS function 50 to call the BIOS SELDSK routine.

Here is my bios call code, it does a function 50 and then gets a crash code
in cp/m . Hard to figure out what the code is, its jumbled up. Will continue to
fiddle with it .

char biospd = 9;
char areg;
int bcreg;
int dereg;
int hlreg;

int lbios(char drive)
{
ldrive = drive;
//INDENT-OFF
#asm
ld c,50
ld d,0
ld a,(_ldrive)
ld e,a
ld (_dereg),de
ld de,_biospd
call 5
; set hl with result
ld h,0
ld l,a
ret
#endasm
//INDENT-ON
return 0;
}

BIOS SELDSK routine takes the drive number in C, and the login status in E. You need to populate _dereg and _bcreg with the correct values for the call.