jayacotton / find

A find command for cp/m written in C
9 stars 1 forks source link

CP/M 3 Phantom Drives #7

Open wwarthen opened 3 years ago

wwarthen commented 3 years ago

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

jayacotton commented 3 years ago

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....

wwarthen commented 3 years ago

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.

jayacotton commented 3 years ago

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)

jayacotton commented 3 years ago

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 00050005 -g,681 0681 -t C0Z1M0E1I1 A=2E B=000E D=A4A4 H=002E S=A4A6 P=0681 LXI H,00000684

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

jayacotton commented 3 years ago

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.

jayacotton commented 3 years ago

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.

wwarthen commented 3 years ago

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

jayacotton commented 3 years ago

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.

durgadas311 commented 3 years ago

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.

jayacotton commented 3 years ago

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; }

durgadas311 commented 3 years ago

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.