• Please review our updated Terms and Rules here

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

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. :)
It was my observation that while CP/M may copy files to completion, the files may still be corrupted. you need to verify them to make sure the copy is done correctly.

I documented my CF problem and solutions here:
https://www.retrobrewcomputers.org/doku.php?id=boards:sbc:tiny68k:rev1_cf_problem

I don't know whether my CF problem is same as yours. Mine is CF brand dependent and data dependent such that one or more words may be dropped so instead of reading a sector of 256 words, the buffer became empty before the counter reached 256.
 
It was my observation that while CP/M may copy files to completion, the files may still be corrupted. you need to verify them to make sure the copy is done correctly.

I documented my CF problem and solutions here:
https://www.retrobrewcomputers.org/doku.php?id=boards:sbc:tiny68k:rev1_cf_problem

I don't know whether my CF problem is same as yours. Mine is CF brand dependent and data dependent such that one or more words may be dropped so instead of reading a sector of 256 words, the buffer became empty before the counter reached 256.

Ah I see. Well, I've tried the following in CP/M 3 and it falls over at the first file:

Code:
A>PIP3 E:=A:*.*[V]

COPYING -
DOWNLOAD.COM
ERROR: CLOSE FILE NONRECOVERABLE - E:DOWNLOAD.$$$

However, in CP/M 2.2 the outcome is very different:

Code:
CP/M 2.2 Copyright 1979 (c) by Digital Research

A>PIP E:=A:*.*[V]

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

A>e:
E>dir
E: DOWNLOAD COM : EXIT     COM : POKE     COM : SHOWSPD  COM
E: UPLOAD   COM : DATETIME COM : BOOST    COM : BANK     COM
E: LOAD     COM : PIP      COM : STAT     COM : SUBMIT   COM
E: DDT      COM : DISPLAY  COM : DUMP     COM : ED       COM
E: ASM      COM : DSKMAINT COM : XSUB     COM : SYSINFO  COM
E: LS       COM : BIOS3    REL : CPMLDR   REL : LDRBIOS  REL
E: SCB      REL : CCP      COM : BDOS3    SPR : BNKBDOS3 SPR
E: COPYSYS  COM : GENCPM   COM : GENCOM   COM : RESBDOS3 SPR
E: LINK     COM : PIP3     COM : CPMLDR   COM : CPMLDR   SYM
E: BNKBIOS3 SPR : CPM3     SYS : GENCPM   DAT
E>datetime
12/01/2018 11:43:59 Fri
E>upload exit.com

MINICOM CP/M 3 UPLOAD - Version 1.0
A:DOWNLOAD EXIT.COM
U0
:213E0111800019F9211701CD1B013E0FD3380E00CD050025522324F57EFE24CA2901CD2B0123C31C01F1C9F5CD350128FBF1D301C997D303DB030FCB4FC9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>8040
E>dump boost.com

0000 21 BE 01 11 80 00 19 F9 3A E0 E6 FE 34 CA 1B 01
0010 11 36 01 3E 34 32 E0 E6 C3 23 01 11 4B 01 3E 38
0020 32 E0 E6 0E 09 CD 05 00 21 62 01 CD 65 01 CD 88
0030 01 0E 00 CD 05 00 44 72 6F 70 70 69 6E 67 20 74
0040 6F 20 34 20 4D 48 7A 2E 2E 2E 24 49 6E 63 72 65
0050 61 73 69 6E 67 20 74 6F 20 38 20 4D 48 7A 2E 2E
0060 2E 24 25 58 24 F5 7E FE 24 CA 73 01 CD 75 01 23
0070 C3 66 01 F1 C9 F5 CD 7F 01 28 FB F1 D3 01 C9 97
0080 D3 03 DB 03 0F CB 4F C9 3E 00 D3 02 3E 18 D3 02
0090 3E 04 D3 02 3A E0 E6 FE 38 CA A1 01 3E 84 C3 A3
00A0 01 3E C4 D3 02 3E 01 D3 02 3E 18 D3 02 3E 03 D3
00B0 02 3E E1 D3 02 3E 05 D3 02 3E EA D3 02 C9 00 00
00C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

E>gencpm


CP/M 3.0 System Generation
Copyright (C) 1982, Digital Research

Default entries are shown in (parens).
Default base is Hex, precede entry with # for decimal

Use GENCPM.DAT for defaults (Y) ?

Create a new GENCPM.DAT file (N) ?

Display Load Map at Cold Boot (Y) ?

Number of console columns (#80) ?
Number of lines in console page (#38) ? 26
Backspace echoes erased character (N) ?
Rubout echoes erased character (Y) ?

Initial default drive (A:) ?

Top page of memory (FF) ?
Bank switched memory (Y) ?
Common memory base page (C0) ?

Long error messages (Y) ?

Accept new system definition (Y) ?

 BNKBIOS3 SPR  F400H  0C00H
 BNKBIOS3 SPR  AC00H  1400H
 RESBDOS3 SPR  EE00H  0600H
 BNKBDOS3 SPR  7E00H  2E00H

*** CP/M 3.0 SYSTEM GENERATION DONE ***
E>

Seems CP/M 2.2 is performing the copy with no issues at all and the files I've tested are working fine.
 
Strange, I cannot find the "ERROR: CLOSE FILE NONRECOVERABLE" message anywhere in the CP/M source - especially not the BDOS or PIP. I searched for components of that message and could not find anything that prints that message. I have to wonder if PIP3.COM is really what we think it is. in PIP.PLM, an error on CLOSE will cause the message "CANNOT CLOSE DESTINATION FILE". The BDOS has a very different format for error messages, so that message does not likely come from BDOS. The BIOS doesn't know if an I/O is for OPEN, CLOSE, etc, so would not normally be able to generate such a message.
 
Ah, I see that the CP/M 3 source is not consistent with what DRI finally released. If I do 'strings' on the PIP.COM I have, I see the components of that error message.

My guess is that the message means that the BDOS CLOSE function returned 255, which I would take to mean that the directory entry for the file could not be found when it was searched again to update. Perhaps the CP/M 3 WRITE routine is actually not writing to disk. Depending on how small DOWNLOAD.COM is, PIP might CLOSE before verify.
 
Ah, I see that the CP/M 3 source is not consistent with what DRI finally released. If I do 'strings' on the PIP.COM I have, I see the components of that error message.

My guess is that the message means that the BDOS CLOSE function returned 255, which I would take to mean that the directory entry for the file could not be found when it was searched again to update. Perhaps the CP/M 3 WRITE routine is actually not writing to disk. Depending on how small DOWNLOAD.COM is, PIP might CLOSE before verify.

DOWNLOAD.COM is 01FFh long.

I've added in error checking to the read and write routines in BIOS3, no change to CP/M 3 it seems. Here's the updated routines:

Code:
;================================================================================================
; Read physical sector from host
;================================================================================================
read:
	PUSH 	AF
	PUSH 	BC
	PUSH 	HL
	
	LD 	A,$0A								; 10 retries on failed read
	LD 	(err_count),A

rdlp:	
	CALL 	CF_CMD_RDY
	CALL 	setLBAaddr
	LD 	A,CF_READ_SEC
	OUT 	(CF_COMMAND),A
	
	; Error checking
	CALL 	CF_DAT_RDY
	IN 	A,(CF_STATUS)					; Read status
	AND 	00000001b							; Mask off error bit
	JP 	Z,rdcont								; Continue if no error
	DJNZ 	rdlp									; Try again if attempts remain
	
	; Error out
	CALL 	printInline							; Out of lives - show an error
	.DB 	CR,LF
	.TEXT 	"Error reading sector!"
	.DB 	0
	LD 	A,$01								; Return to BDOS with error code 1 - Unrecoverable error
	LD 	(erflag),A
	
	POP 	HL
	POP 	BC
	POP  	AF
	
	RET

rdcont:
	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
;================================================================================================
err_count: 	.ds	1							; Write error counter

write:
	PUSH 	AF
	PUSH 	BC
	PUSH 	HL
	
	LD 	A,$0A								; 10 retries on failed write
	LD 	(err_count),A

whst:
	CALL 	CF_CMD_RDY
	CALL 	setLBAaddr

	; Issue write command
	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
	
	; Error checking
	CALL 	CF_WAIT
	IN 	A,(CF_STATUS)					; Read status
	AND 	00000001b							; Mask off error bit
	JP 	NZ,werr								; Jump to werr if error

	POP 	HL
	POP 	BC
	POP 	AF

	XOR 	A
	LD 	(erflag),A
	RET
	
		; Error - loop if retries remain
werr:
	LD 	A,(err_count)
	DEC 	A
	LD 	(err_count),A
	JP 	NZ,whst							; Try again
		
	; Error handling
	CALL 	printInline						; Out of lives - show an error
	.DB 	CR,LF
	.TEXT 	"Write error!"
	.DB 	0
	LD 	A,$01							; Return to BDOS with error code 1 - Unrecoverable error
	LD 	(erflag),A	
	RET

;------------------------------------------------------------------------------
; Wait for disk to be ready (BUSY=0, READY=1)
;------------------------------------------------------------------------------
CF_WAIT:
	PUSH 	AF
cfWait1:
	IN 		A,(CF_STATUS)				; Read status
	AND		10000000b						; Mask BUSY bit (7)
	JP			NZ,cfWait1						; Still BUSY? Loop...
	POP 		AF
	RET
		
;------------------------------------------------------------------------------
; CF_CMD_RDY
; Loops until status register bit 7 (BUSY) is 0 and bit 6 (DRVRDY) is 1
;------------------------------------------------------------------------------
CF_CMD_RDY:
		IN			A,(CF_STATUS)				; Read status
		AND		11000000b						; Mask off BUSY and DRVRDY bits
		XOR		01000000b						; We want BUSY(7) to be 0 and DRVRDY(6) to be 1
		JP			NZ,CF_CMD_RDY
		RET

;------------------------------------------------------------------------------
; CF_DAT_RDY
; Loops until status register bit 7 (BUSY) is 0 and DRQ(3) is 1
;------------------------------------------------------------------------------
CF_DAT_RDY:
		IN			A,(CF_STATUS)				; Read status
		AND		10001000b						; Mask off BUSY and DRQ bits
		XOR		00001000b						; We want BUSY(7) to be 0 and DRQ(3) to be 1
		JP			NZ,CF_DAT_RDY
		RET

So, thinking about what durgadas311 said about DOWNLOAD.COM being too small for PIP to verify, I thought I'd try it on a larger file (20K):

Code:
A>PIP3 E:=A:CPM3.SYS[OV]

ERROR: CLOSE FILE NONRECOVERABLE - E:CPM3.$$$
 
Seems CP/M 2.2 is performing the copy with no issues at all and the files I've tested are working fine.

You may want to try a couple different brands of CF just to be sure, but your case appear to be a software issue rather than hardware. That's good because hardware solution is more difficult to fix.
 
So, thinking about what durgadas311 said about DOWNLOAD.COM being too small for PIP to verify, I thought I'd try it on a larger file (20K):

To be more specific, CP/M 3 PIP will load as much of a file into memory as will fit, then write that to the destination, then verify that with the destination. Then it will load more of the source file (if it exists). That is also impacted by the extent size on the disk, as I believe BDOS will update the directory entry whenever the logical extent is filled. I believe it will also detect problems at that point, if the directory entry was not present (anymore). Your extent size is 16K, so I believe that the directory entry would have been updated after 16K was written. However, 20K is not enough to fill memory so it will not cause multiple read-write-verify cycles. Still, I'm not sure if that helps.

After this failure, are you still able to run? Do you see "CPM3.$$$" on drive E: ?
 
To be more specific, CP/M 3 PIP will load as much of a file into memory as will fit, then write that to the destination, then verify that with the destination. Then it will load more of the source file (if it exists). That is also impacted by the extent size on the disk, as I believe BDOS will update the directory entry whenever the logical extent is filled. I believe it will also detect problems at that point, if the directory entry was not present (anymore). Your extent size is 16K, so I believe that the directory entry would have been updated after 16K was written. However, 20K is not enough to fill memory so it will not cause multiple read-write-verify cycles. Still, I'm not sure if that helps.

Okay, tried again copying GENCPM.COM this time - it's 24K (all the below is in CP/M 3):

Code:
CP/M Plus Copyright 1982 (c) Digital Research

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   12K ! 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   24K ! ED      COM    8K ! PIP3    COM   12K
39 File(s), occupying 280K of 8160K total capacity
473 directory entries and 4040K bytes remain on A:
A>PIP3 E:=A:GENCPM.COM[OV]

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

A>E:
E>dir
No File
E>

After this failure, are you still able to run? Do you see "CPM3.$$$" on drive E: ?

Yes, still able to run - although CTRL-C (the shortcut I use to copy the selected text in the console to paste into this forum post) causes the following and CCP hangs:

Code:
E>^C
BIOS Error on A: No CCP.COM file

And yes, I'm aware that CTRL-C is the 'break' command for most CP/M programs, but I get the ^C char appear in CP/M 2.2 as well when I copy stuff from the console, but it just completes the warm reset and the prompt appears again underneath it. CP/M 3 seems to be unhappy about warm resets...
 
So, the fact that E: has no GENCPM.$$$ file after PIP fails suggests that writes are silently failing - in the sense that nothing is getting written to disk. What I suspect is happening is that PIP creates E:GENCPM.$$$ but the BIOS write does not actually write to disk. CP/M carries on, unaware of the failure. When it comes time to close the file, the BDOS tries to locate the E:GENCPM.$$$ directory entry so that it can update it. But, that entry does not exist since the writes are not working. I can't see anythign wrong with the BIOS3 write function - at the moment - but will continue to look into it. Since no error message appears from the BIOS, I have to assume that routine is not detecting any error from the CF card. There might be something more-subtle going on, perhaps like the buffer management is not properly flushing the directory buffer or losing it's contents.

Maybe it's time to post your BIOS3.ASM again. Are you using "git" to manage the code repository? If so, it might be nice if you pushed this onto github so we can better see the whole code.

I may cobble-up a simulation of your machine this weekend. If I do, I'll also need your ROM code (source or binary).
 
A couple of thoughts for consideration:

1) Is the File Control Block in common memory or banked memory? Has it accidentally been 'paged out'?

2) Some compact flash cards have a write cache. It is possible to disable this by a 'set features' option (in a similar manner to setting 8-bit operation of the interface). Do you disable the write cache? If not, I suggest you do.

Dave
 
I was checking this earlier... write cache is (supposedly) disabled. The commands are given in cold boot. I'm assuming they don't get "undone" someplace.

The CCP FCB is in common memory, in the last BIOS3.ASM source file I see.

...however, I have not seen the code that ensures the FCB is "reset" during warm boot. The 4 bytes after the name need to be cleared.
 
I was checking this earlier... write cache is (supposedly) disabled. The commands are given in cold boot. I'm assuming they don't get "undone" someplace.

The CCP FCB is in common memory, in the last BIOS3.ASM source file I see.

...however, I have not seen the code that ensures the FCB is "reset" during warm boot. The 4 bytes after the name need to be cleared.

Yes, it's being reset here, right at the start of ld_ccp which is called by cold AND warm boots:

Code:
ld_ccp:
	
	; Zero the EXT byte/s
	LD	A,0
	LD	B,4								; Loop iterations (bytes to clear)
	LD	HL,ccp$fcb+12
clr_lp:	
	LD	(HL),A							; Zeros the FCB EXT and other bytes
	INC	HL
	DJNZ	clr_lp

Current BIOS3.ASM: View attachment BIOS3.ASM.txt

EDIT: Yes, I use version control but my project is being held on Bitbucket. (It's private so you'll need to have a Bitbucket account for me to give you access.)
 
I was checking this earlier... write cache is (supposedly) disabled. The commands are given in cold boot. I'm assuming they don't get "undone" someplace.

The CCP FCB is in common memory, in the last BIOS3.ASM source file I see.

...however, I have not seen the code that ensures the FCB is "reset" during warm boot. The 4 bytes after the name need to be cleared.

I looked in the wboot code in my CP/M Plus BIOS and I don't explicitly clear anything. Doesn't ?rlccp take care of that?

One thing that might help is to build a non-banked system and test writes.
 
I am "durgadas311" now on bitbucket. Please grant read access. thanks!

Very strange that ^C does not work but you can return from running programs. Both should be passing through "wboot", I think. Since CCP is a regular program at 0100H just like PIP.COM, etc, the reload of CCP must be working those times. It must have to do with other actions taken for ^C.
 
Just 'tossing another idea in here" whilst coding a bit of VHDL...

You are not using interrupts of any type here are you - this is a purely polled console input/output isn't it?

Dave
 
Just 'tossing another idea in here" whilst coding a bit of VHDL...

You are not using interrupts of any type here are you - this is a purely polled console input/output isn't it?

Dave

Interrupts remain disabled in BIOS3 at the moment, Dave. I will need to move away from polled I/O back to interrupt-based at some point for the extra features of my system to work with CP/M 3, but I'm prioritising getting it working at all first. ;)

Well, saying that, I'm assuming nothing else anywhere is enabling interrupts again. Latest version of BIOS3.ASM is available in a previous post..

Are you flying off anywhere nice, btw?
 
Edinburgh...

Sounds nice - but all I will see is an airport, a Premier Inn and the inside of an office!

Dave

Oh, that takes a bit of the fun out of the mental image I had... :p I was thinking Hawaii, the Bahamas or California (not Minnesota - too cold at the moment eh, durgadas311? :) ). All this virtual conferencing equipment these days and you still can't beat being there in person. :)
 
If you're not there you don't know whether they are working on your job or not...

Many years ago I was in Sydney Australia and a work colleague was in Virginia US. We decided that we had to have monthly face-to-face meetings and it would be unrealistic for one of us to travel to the other's place of work. The best thing for it was for us to meet halfway. Eventually, our boss caught on that halfway between the two was Hawaii!!!

That was in the bad old days of course...

Dave
 
Just so I have enough information to model this machine, I need some more details:

1) What does the "MMU active" bit do? The power-on (and I assume RESET) mapping puts ROM at bank 15 at location 0000H (phy addr 3C000H mapped to 0000H), so I wonder what the affect the active bit has.

2) Is it correct that your monitor is the DMI.ASM code? and it is ORGed at 0000H but loaded into (ROM at) 3C000H?

3) Is the PIO or CTC actually used right now (do I need to implement them)? I see mention of I2C access via PIO - is that needed (do I need to emulate some I2C devices)?

4) Do I need to emulate anything on the other end of SIO channel B? Does DMI try to communicate with anything over that serial port?

5) What is the interrupt daisy-chain ordering for SIO, CTC, and PIO?
 
Back
Top