• Please review our updated Terms and Rules here

Installing CP/M 3 (Plus?) on a home-built Z80 computer

Here is what I think "setLBAaddr" should look like. Please review carefully this time, if something doesn't make sense be sure to question it!

Code:
setLBAaddr:
        ld      hl,(hsttrk)     ; 11 bits (0-2047)
        add     hl,hl
        add     hl,hl
        add     hl,hl
        add     hl,hl
        add     hl,hl   ; 11 bits + shift 5 = no overflow
        ld      a,(hstsec)      ; 5 bits (0-31)
        or      a,l     ; low 3 bits
        ld      (lba0),a
        ld      a,h     ; high 8 bits
        ld      (lba1),a
        ld      a,(hstdsk)
        ld      (lba2),a
        ld      a,0e0h
        ld      (lba3),a
        ; prior code, unchanged:
        LD      A,(lba0)
        OUT     (CF_LBA0),A
        LD      A,(lba1)
        OUT     (CF_LBA1),A
        LD      A,(lba2)
        OUT     (CF_LBA2),A
        LD      A,(lba3)
        OUT     (CF_LBA3),A
        LD      A,1
        OUT     (CF_SECCOUNT),A
        RET

Again, changing this routine will require a complete reformat of your CF image. I'm guessing the ROM boot code doesn't need to change, but any external tools you use to put data on the CF card will require re-examination.
 
Oh, wait, I was not taking into account that you have a 64M CF card... so you can't have 8 disks of 32M each in that case... So, your CP/M DPBs are wrong in saying they have 2048 16K allocation blocks...
 
Ugh, I'm going to stop guessing and spend more time thinking... you have 4K allocation blocks... never mind...
 
Just to reiterate, I was wrong about "setLBAaddr" - that routine does not look broken to me. I'll spend some more time looking at the CP/M 3 version, and then make a comment.
 
So, I think there is a bug in my "setLBAaddr" routine as in CP/M 3. Probably just replace that with the code from CP/M 2.2. Code review is king... gratuitous rewrite sucks.
 
So, I think there is a bug in my "setLBAaddr" routine as in CP/M 3. Probably just replace that with the code from CP/M 2.2. Code review is king... gratuitous rewrite sucks.

;) If I knew the code well enough (I'm still learning the system AND the language it's written in), I'd feel happy reviewing and commenting but I'm in the dark with this stuff and relying on the experts - yes, that's you guys! :D

So, I've copied the setLBAaddr function from the CP/M 2.2 BIOS and pasted it into BIOS3 and compiled a new CPM3.SYS. Here's the console output from what I tried:

Code:
A>sysinfo
Processor:   Z80
System:      CP/M 2.2
Top of TPA:  D800
BIOS start:  E600

A>cpmldr
Preparing MMU...
Setting MMU lock byte...
Initialising SIO...
Z80 MINICOM II CP/M Plus LDRBIOS 1.0

CP/M Plus Copyright 1982 (c) by Digital Research
LDRBIOS returning to: 0106


CP/M V3.0 Loader
Copyright (C) 1982, Digital Research

 BNKBIOS3 SPR  F400  0C00
 BNKBIOS3 SPR  B300  0D00
 RESBDOS3 SPR  EE00  0600
 BNKBDOS3 SPR  8500  2E00

 59K TPA
MINICOM CP/M Plus BIOS 1.0
by J.Nock & D.Miller 2017-18

CP/M Plus Copyright 1982 (c) Digital Research

A>sysinfo
Processor:   Z80
System:      CP/M 3.1
Top of TPA:  EE00
BIOS start:  F400
BDOS start:  EE00
Common base: C000
Drives:      A: B: C: D: E: F: G: H:

A>dir
A: DOWNLOAD COM : EXIT     COM : POKE     COM : SHOWSPD  COM : UPLOAD   COM
A: DATETIME COM : BOOST    COM : BANK     COM : LOAD     COM : PIP      COM
A: STAT     COM : SUBMIT   COM : DDT      COM : DISPLAY  COM : DUMP     COM
A: ED       COM : ASM      COM : DSKMAINT COM : XSUB     COM : SYSINFO  COM
A: LS       COM : BIOS3    REL : CPMLDR   REL : LDRBIOS  REL : SCB      REL
A: CCP      COM : BDOS3    SPR : BNKBDOS3 SPR : COPYSYS  COM : GENCPM   COM
A: GENCOM   COM : RESBDOS3 SPR : LINK     COM : PIP3     COM : CPMLDR   COM
A: CPMLDR   SYM : BNKBIOS3 SPR : CPM3     SYS : GENCPM   DAT
A>PIP3 E:=A:CPM3.SYS

ERROR: CLOSE FILE NONRECOVERABLE - E:CPM3.$$$

A>PIP E:=A:CPM3.SYS

CP/M Error On E: Disk I/O
BDOS Function = 16  File = CPM3    .$$$
BIOS Error on A: No CCP.COM file

...and then it hangs. Guess I should expect that, as the PIP.COM is a CP/M 2.2 file, but I thought I'd try it as the 'CP/M 3' version of PIP (PIP3.COM) came up with that really unhelpful error before it.

Unlike before, I'm able to load up CP/M 2.2 again after the above (which is identical to what I did previously and lost the use of the CF card completely until it was reformatted and re-installed), so the setLBAaddr changes have made an improvement in that respect.

In CP/M 3, LS.COM is giving some strange results (someone asked previously was LS does - it's basically more like the DOS 'DIR' command, providing the directory results in alphabetical order along with their file sizes and a bit more info on drive size/space remaining):

Code:
A>ls
Name    Ext Bytes   Name    Ext Bytes   Name    Ext Bytes   Name    Ext Bytes
ASM     COM    8K ! CPMLDR  COM    8K ! EXIT    COM    4K ! POKE    COM    4K
BANK    COM    4K ! CPMLDR  REL    4K ! GENCOM  COM   16K ! RESBDOS3SPR    4K
BDOS3   SPR   12K ! CPMLDR  SYM    4K ! GENCPM  COM   24K ! SCB     REL    4K
BIOS3   REL    4K ! DATETIMECOM    4K ! GENCPM  DAT    4K ! SHOWSPD COM    4K
BNKBDOS3SPR   16K ! DDT     COM    8K ! LDRBIOS REL    4K ! STAT    COM    8K
BNKBIOS3SPR    8K ! DISPLAY COM    4K ! LINK    COM   16K ! SUBMIT  COM    4K
BOOST   COM    4K ! DOWNLOADCOM    4K ! LOAD    COM    4K ! SYSINFO COM    4K
CCP     COM    4K ! DSKMAINTCOM    4K ! LS      COM    4K ! UPLOAD  COM    4K
COPYSYS COM    4K ! DUMP    COM    4K ! PIP     COM    8K ! XSUB    COM    4K
CPM3    SYS   20K ! ED      COM    8K ! PIP3    COM   12K
39 File(s), occupying 272K of 8160K total capacity
473 directory entries and 4008K bytes remain on A:

As you can see, it's reporting 8160K drive capacity, with 272K used and 473 directory entries with 4008K remaining. I try not to do maths this early in the day, but 8160-272 != 4008 by my reckoning..

Here's the results of the same program (LS), in CP/M 2.2:

Code:
A>ls
Name    Ext Bytes   Name    Ext Bytes   Name    Ext Bytes   Name    Ext Bytes
ASM     COM    8K ! CPMLDR  COM    8K ! EXIT    COM    4K ! POKE    COM    4K
BANK    COM    4K ! CPMLDR  REL    4K ! GENCOM  COM   16K ! RESBDOS3SPR    4K
BDOS3   SPR   12K ! CPMLDR  SYM    4K ! GENCPM  COM   24K ! SCB     REL    4K
BIOS3   REL    4K ! DATETIMECOM    4K ! GENCPM  DAT    4K ! SHOWSPD COM    4K
BNKBDOS3SPR   16K ! DDT     COM    8K ! LDRBIOS REL    4K ! STAT    COM    8K
BNKBIOS3SPR    8K ! DISPLAY COM    4K ! LINK    COM   16K ! SUBMIT  COM    4K
BOOST   COM    4K ! DOWNLOADCOM    4K ! LOAD    COM    4K ! SYSINFO COM    4K
CCP     COM    4K ! DSKMAINTCOM    4K ! LS      COM    4K ! UPLOAD  COM    4K
COPYSYS COM    4K ! DUMP    COM    4K ! PIP     COM    8K ! XSUB    COM    4K
CPM3    SYS   20K ! ED      COM    8K ! PIP3    COM   12K
39 File(s), occupying 272K of 8160K total capacity
473 directory entries and 7888K bytes remain on A:

8160-272 == 7888 - that looks a little better.

Just to reinforce that, in CP/M 2.2, STAT reports:

Code:
A>stat
A: R/W, Space: 7888k

and in CP/M 3:

Code:
A>stat
A: R/W, Space: 4008k

So I'm not sure what's going on, but it looks like there's still issues with the drive functions in BIOS3. Here's the latest version of BIOS3.ASM, so we're definitely on the same page:
View attachment BIOS3.ASM.txt

I haven't got around to modifying the CF_WAITs in the read/write functions yet.
 
CP/M 3 uses 2-bit allocation vectors, and thus the ALV buffers must be (DSM+1)/4 - i.e. twice the size of CP/M 2.2 ALVs. This means that programs like STAT.COM, and presumably LS.COM, will not correctly compute free space because they don't know about CP/M 3 ALVs. Another reason not to mix CP/M 2.2 programs with CP/M 3.

Make certain that BIOS3.ASM has the correct size ALVs.

Looks like PIP3 is getting a error when closing the file, presumably when writing the directory entry. Probably need to update your BIOS3 read/write routines for the proper CF protocol.
 
CP/M 3 uses 2-bit allocation vectors, and thus the ALV buffers must be (DSM+1)/4 - i.e. twice the size of CP/M 2.2 ALVs. This means that programs like STAT.COM, and presumably LS.COM, will not correctly compute free space because they don't know about CP/M 3 ALVs. Another reason not to mix CP/M 2.2 programs with CP/M 3.

Make certain that BIOS3.ASM has the correct size ALVs.

Looks like PIP3 is getting a error when closing the file, presumably when writing the directory entry. Probably need to update your BIOS3 read/write routines for the proper CF protocol.

The ALVs in CBIOS64 (CP/M 2.2) are:

Code:
alv00: .ds 257	;allocation vector 0
alv01: .ds 257	;allocation vector 1
alv02: .ds 257	;allocation vector 2
alv03: .ds 257	;allocation vector 3
alv04: .ds 257	;allocation vector 4
alv05: .ds 257	;allocation vector 5
alv06: .ds 257	;allocation vector 6
alv07: .ds 257	;allocation vector 7

They're identical in BIOS3 (CP/M 3):

Code:
alv00: .ds 257	;allocation vector 0
alv01: .ds 257	;allocation vector 1
alv02: .ds 257	;allocation vector 2
alv03: .ds 257	;allocation vector 3
alv04: .ds 257	;allocation vector 4
alv05: .ds 257	;allocation vector 5
alv06: .ds 257	;allocation vector 6
alv07: .ds 257	;allocation vector 7

I have now updated the BIOS3 allocation vectors according to (DSM+1)/4:

Code:
alv00: .ds 511	;allocation vector 0
alv01: .ds 512	;allocation vector 1
alv02: .ds 512	;allocation vector 2
alv03: .ds 512	;allocation vector 3
alv04: .ds 512	;allocation vector 4
alv05: .ds 512	;allocation vector 5
alv06: .ds 512	;allocation vector 6
alv07: .ds 320	;allocation vector 7

BIOS3 updated read and write routines:

Code:
;================================================================================================
; Read physical sector from host
;================================================================================================
read:
	PUSH 	AF
	PUSH 	BC
	PUSH 	HL
	
	CALL	CF_CMD_RDY
	CALL 	setLBAaddr
	LD 	A,CF_READ_SEC
	OUT 	(CF_COMMAND),A

	CALL	CF_DAT_RDY
	LD	A,(dmaBank)
	CALL	selmem						; could avoid this if dmaBank == 0
	LD 	B,0						; 256 bytes at a time
	LD	C,CF_DATA
	LD 	HL,(dmaAddr)
	INIR							; do 256 bytes
	INIR							; do another 256 bytes = 512
	XOR	A						; back to Bank 0...
	CALL	selmem						; could avoid this if dmaBank == 0

	POP 	HL
	POP 	BC
	POP 	AF

	XOR 	A
	LD	(erflag),A	
	RET

;================================================================================================
; Write physical sector to host
;================================================================================================
write:
	PUSH 	AF
	PUSH 	BC
	PUSH 	HL

	CALL	CF_CMD_RDY
	CALL 	setLBAaddr

	LD 	A,CF_WRITE_SEC
	OUT 	(CF_COMMAND),A

	CALL	CF_DAT_RDY

	LD	A,(dmaBank)
	CALL	selmem						; could avoid this if dmaBank == 0
	LD 	B,0						; 256 bytes at a time
	LD	C,CF_DATA
	LD 	HL,(dmaAddr)
	OTIR							; do 256 bytes
	OTIR							; do another 256 bytes = 512
	XOR	A						; back to Bank 0...
	CALL	selmem						; could avoid this if dmaBank == 0

	POP 	HL
	POP 	BC
	POP 	AF

	XOR 	A
	LD	(erflag),A
	RET

I've modified wboot: slightly to add the following:

Code:
LD	A,0
	CALL	seldsk

... but still get the 'no ccp.com' file error in CP/M 3:

Code:
A>stat D:

Bytes Remaining On D: 3972k
BIOS Error on A: No CCP.COM file
 
Again, STAT.COM is not going to work under CP/M 3. And least it will not compute free space correctly. At worst, some functions may corrupt the system.

I gave you the wrong advice. The CCP loading is done using the BDOS and so seldsk doesn't matter (BDOS will call seldsk as appropriate). Your BIOS should not be using directory HASH buffers, so I don't think a corrupted hash is causing this. There must be some sort of in-memory state data that is resulting in the appearance of a missing CCP.COM file. Could also be some corruption (or left-over data) in the FCB such that attempting to open the file again is failing. Perhaps zero-out the EXT byte, possibly others. The 4 bytes after the name (includes EXT) should probably be zeroed.
 
The CF specification is a little vague in this area, but we probably still need to tweak the I/O routines. The way I read it, there is a 512-byte buffer in the device that is "directly" connected to the data register. This seems to be similar to other disk interfaces such as SASI and WD1002. In this case, use of Z80 "block I/O" instructions is probably fine (i.e. no need to check DRQ on every byte - the spec might even imply that DRQ stays high until the last byte). However, in the case of write you will need to wait for BSY to clear after the last byte, then check the error bit. For read, you'll need to check the error bit after BSY is cleared after issuing the command (before INIR). (there will be no BSY cycle on a READ after the last byte - unless multiple sectors are requested).
 
Please excuse me for butting in. I'm not knowledgeable about Z80, but I also have encountered problems with bus-connected CF interface in my home-built computer. Mine is CP/M-68K. When performing files transfer using PIP, the operation may appear to complete OK, but the files are frequently corrupted particularly with certain brands of CF. Bigger the file, more likely the corruption will occur. The easiest way to check is do PIP with [V] switch (e.g., PIP C:=A:*.*[V]). I don't know whether CP/M 2.2 does verify automatically. If not, it is useful to specify file verification.
 
PIP [V] option has been around for a long time. In this case it is probably not related to our current problem, but as you point out we should probably *always* be running with [V] or [OV].
 
Again, STAT.COM is not going to work under CP/M 3. And least it will not compute free space correctly. At worst, some functions may corrupt the system.

I gave you the wrong advice. The CCP loading is done using the BDOS and so seldsk doesn't matter (BDOS will call seldsk as appropriate). Your BIOS should not be using directory HASH buffers, so I don't think a corrupted hash is causing this. There must be some sort of in-memory state data that is resulting in the appearance of a missing CCP.COM file. Could also be some corruption (or left-over data) in the FCB such that attempting to open the file again is failing. Perhaps zero-out the EXT byte, possibly others. The 4 bytes after the name (includes EXT) should probably be zeroed.

Do you mean here?

Code:
ccp$fcb:		.DB	0,'CCP     COM',0,0,0,0
					.DS	16
fcb$nr			.DB	0,0,0,0

They're already zeroed?
 
Please excuse me for butting in. I'm not knowledgeable about Z80, but I also have encountered problems with bus-connected CF interface in my home-built computer. Mine is CP/M-68K. When performing files transfer using PIP, the operation may appear to complete OK, but the files are frequently corrupted particularly with certain brands of CF. Bigger the file, more likely the corruption will occur. The easiest way to check is do PIP with [V] switch (e.g., PIP C:=A:*.*[V]). I don't know whether CP/M 2.2 does verify automatically. If not, it is useful to specify file verification.

PIP [V] option has been around for a long time. In this case it is probably not related to our current problem, but as you point out we should probably *always* be running with [V] or [OV].

Thanks for the suggestion, Plasmo and welcome to the discussion. :) I've heard about different brands of CF giving different results before, but I'm hoping that tightening up the error checking and complying with the CF interface standard as much as possible will reduce those errors. The thing is, CP/M 2.2 has none of these problems and has been 100% reliable until CP/M 3 became runnable on the system - all the issues seem to be restricted to CP/M 3, which implies (to me at least) that it's something to do with the disk I/O or disk parameters in the BIOS.

Still, I'm happy to give new ideas a try so I'll get back to you on the outcome of using the [V] switch. :)
 
Plasmo,

Please feel free to 'butt in' - especially if you have some experience with CF...

I seem to remember saying a while ago about clearing the 'ext' byte in the FCBs that are stored in the BIOS. The default seems to be 0 when loaded - but then it never gets zeroed again so (as stated) an error 'could' occur on the second - or subsequent - usage.

My CF adapter and card arrived today - so I will need to catch up with you guys and get my little card made for my NASCOM... Unfortunately, I have just planned a 2 week trip away with work today and I probably won't feel like doing much at the weekend when I get back between flights...

Dave
 
I seem to remember saying a while ago about clearing the 'ext' byte in the FCBs that are stored in the BIOS. The default seems to be 0 when loaded - but then it never gets zeroed again so (as stated) an error 'could' occur on the second - or subsequent - usage.

I just need a little hand-holding regarding the ext byte in the FCB... which one is the ext byte and where/when do I need to clear it again?

My CF adapter and card arrived today - so I will need to catch up with you guys and get my little card made for my NASCOM... Unfortunately, I have just planned a 2 week trip away with work today and I probably won't feel like doing much at the weekend when I get back between flights...

Dave

Unfortunately? Flights? Anywhere nice? I'll still be here, plodding through when you get back. ;)
 
Back
Top