PDA

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



Pages : 1 [2] 3

daver2
January 2nd, 2018, 07:29 AM
Just got back from my afternoon walk...

Keep the interrupts DISABLED for now. If you change more than one thing at any given time you don't know what has worked and what has not. Did the code modification work and the interrupts screw us up for example?

If the code in the status and con in/out entry points polls the SIO, then you should be able to communicate with CP/M - but only if they work...

If you have moved the data items from DSEG to CSEG, then the code trace you have produced has not followed the code change - (e.g. 'setdma: 0B00' vs 'read dma: 19FE').

In fact, if you look at the trace you will see it trying to 'setdma:' for 'sensible numbers' but the 'read dma:' is always 19FE (implying it is loading all of the sector information for the CCP into 19FE and not the correct location).

Did it 'build' correctly? i.e. are you looking for errors in the assembly and link process? If not - and an error occurred in the assembly - you may well be linking with the old object file...

Dave

nockieboy
January 2nd, 2018, 07:35 AM
Hang on - updated log follows. It's possible I forgot to generate a new CPM3.SYS with the updated BIOS last time. :rolleyes:

This time around, things ARE different. The cluster of selmem statements at the end almost hide the fact that the A> prompt is shown. It's responding to input, as well, but not in the way you'd like. If I press ENTER, it displays another couple of selmems and then erases most of them. Pressing further keys causes corruption, like below:


selmem called. curBank=00 A=01
selmem called. curBank=01 A=00A
selmem called. curBank=00 A=01
selmem called. curBank=01 A=00>
▒▒▒m2▒▒▒▒▒ ▒
▒▒▒^F▒5▒▒▒^]▒▒▒▒▒*(▒~▒▒o▒#"(▒▒▒M▒▒^W�▒▒*(▒~▒▒`▒▒▒▒^]▒▒▒U▒▒▒o▒▒▒j▒*(▒~#"(▒Ñ▒!*▒~6^@▒▒s▒!+▒6^@▒▒▒▒:+▒▒�▒x▒o▒ͳ▒*&▒~▒2+▒▒o▒#"&▒!+▒6^W▒▒M▒▒^A▒Ō:▒▒W:▒▒▒▒▒2▒▒x▒▒^K▒^E▒ͺ▒▒*(▒+"(▒^Zw▒▒^K▒▒^B▒^K▒:▒▒▒▒܌>^W2*▒2▒▒▒:▒▒*(▒^D^E:▒▒▒▒▒+^Zw^[▒▒"(▒▒▒ͺ▒:▒▒G:▒h▒3▒3~^▒͉


Here's the full log, without any key presses at the prompt at the end:


CP/M Plus Copyright 1982 (c) by Digital Research

ld_ccp executing...
selmem called. curBank=00 A=01
Bank 1 selected...
selmem called. curBank=01 A=00
seldsk called...
settrk: 0000
settrk: 0001
sectrn: 0000
setsec: 0000
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0001
setsec: 0001
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0002
setsec: 0002
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0003
setsec: 0003
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0004
setsec: 0004
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0005
setsec: 0005
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0006
setsec: 0006
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0007
setsec: 0007
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0008
setsec: 0008
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0009
setsec: 0009
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 000A
setsec: 000A
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 000B
setsec: 000B
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 000C
setsec: 000C
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 000D
setsec: 000D
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 000E
setsec: 000E
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 000F
setsec: 000F
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0010
setsec: 0010
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0011
setsec: 0011
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0012
setsec: 0012
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0013
setsec: 0013
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0014
setsec: 0014
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0015
setsec: 0015
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0016
setsec: 0016
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0017
setsec: 0017
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0018
setsec: 0018
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0019
setsec: 0019
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 001A
setsec: 001A
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 001B
setsec: 001B
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 001C
setsec: 001C
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 001D
setsec: 001D
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 001E
setsec: 001E
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 001F
setsec: 001F
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0000
settrk: 0001
sectrn: 0000
setsec: 0000
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0001
setsec: 0001
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0002
setsec: 0002
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0003
setsec: 0003
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0004
setsec: 0004
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0005
setsec: 0005
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0006
setsec: 0006
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0007
setsec: 0007
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0008
setsec: 0008
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0009
setsec: 0009
setdma: BB50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BB50
selmem called. curBank=00 A=00
read completed, erflag=00

selmem called. curBank=00 A=01
First bdose call completed...
Second bdose call completed...
selmem called. curBank=01 A=00
selmem called. curBank=00 A=01
Third bdose call completed...
selmem called. curBank=01 A=00
settrk: 000E
sectrn: 0000
setsec: 0000
setdma: 0100
setbnk: 00
setbnk: 01
read called... dmaBank=01
selmem called. curBank=00 A=01
read dma: 0100
selmem called. curBank=01 A=00
read completed, erflag=00

settrk: 000E
sectrn: 0001
setsec: 0001
setdma: 0300
setbnk: 00
setbnk: 01
read called... dmaBank=01
selmem called. curBank=00 A=01
read dma: 0300
selmem called. curBank=01 A=00
read completed, erflag=00

settrk: 000E
sectrn: 0002
setsec: 0002
setdma: 0500
setbnk: 00
setbnk: 01
read called... dmaBank=01
selmem called. curBank=00 A=01
read dma: 0500
selmem called. curBank=01 A=00
read completed, erflag=00

settrk: 000E
sectrn: 0003
setsec: 0003
setdma: 0700
setbnk: 00
setbnk: 01
read called... dmaBank=01
selmem called. curBank=00 A=01
read dma: 0700
selmem called. curBank=01 A=00
read completed, erflag=00

settrk: 000E
sectrn: 0004
setsec: 0004
setdma: 0900
setbnk: 00
setbnk: 01
read called... dmaBank=01
selmem called. curBank=00 A=01
read dma: 0900
selmem called. curBank=01 A=00
read completed, erflag=00

settrk: 000E
sectrn: 0005
setsec: 0005
setdma: 0B00
setbnk: 00
setbnk: 01
read called... dmaBank=01
selmem called. curBank=00 A=01
read dma: 0B00
selmem called. curBank=01 A=00
read completed, erflag=00

settrk: 000E
sectrn: 0006
setsec: 0006
setdma: FD0F
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: FD0F
selmem called. curBank=00 A=00
read completed, erflag=00

selmem called. curBank=00 A=01
selmem called. curBank=01 A=00
selmem called. curBank=00 A=01
Fourth bdose call (BDOS 20), A=01
HL = 1901
CCP loaded...

selmem called. curBank=01 A=00
selmem called. curBank=00 A=01
selmem called. curBank=01 A=00
selmem called. curBank=00 A=01
selmem called. curBank=01 A=00
selmem called. curBank=00 A=01
selmem called. curBank=01 A=00
selmem called. curBank=00 A=01
selmem called. curBank=01 A=00
settrk: 0000
settrk: 0001
sectrn: 0000
setsec: 0000
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0001
setsec: 0001
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0002
setsec: 0002
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0003
setsec: 0003
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0004
setsec: 0004
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0005
setsec: 0005
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0006
setsec: 0006
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0007
setsec: 0007
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0008
setsec: 0008
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 0009
setsec: 0009
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

settrk: 0001
sectrn: 000A
setsec: 000A
setdma: BD50
setbnk: 00
setbnk: 00
read called... dmaBank=00
selmem called. curBank=00 A=00
read dma: BD50
selmem called. curBank=00 A=00
read completed, erflag=00

selmem called. curBank=00 A=01
selmem called. curBank=01 A=00A
selmem called. curBank=00 A=01
selmem called. curBank=01 A=00>
selmem called. curBank=00 A=01
selmem called. curBank=01 A=00

nockieboy
January 2nd, 2018, 07:39 AM
Keep the interrupts DISABLED for now. If you change more than one thing at any given time you don't know what has worked and what has not. Did the code modification work and the interrupts screw us up for example?

I've disabled interrupts again and tried again - same log, but this time pressing keys at the end does nothing - system is 'frozen' (or just not checking for input.)


Did it 'build' correctly? i.e. are you looking for errors in the assembly and link process? If not - and an error occurred in the assembly - you may well be linking with the old object file...

Dave

Yeah, I was so keen to try the fix I forgot to run GENCPM...!!!

durgadas311
January 2nd, 2018, 07:39 AM
OK, so it made it to the A> prompt, all the debugging makes it tough to see.

durgadas311
January 2nd, 2018, 07:42 AM
So, maybe some problem with the interrupt console. It probably would have been better to just use polled input from the start. something as tricky as interrupt-driven input should be an enhancement after the rest works.

nockieboy
January 2nd, 2018, 07:46 AM
So, maybe some problem with the interrupt console. It probably would have been better to just use polled input from the start. something as tricky as interrupt-driven input should be an enhancement after the rest works.

I think I'm a little confused about how to switch over from interrupt-driven input to polled input. Are there any examples I can work from?

EDIT: I'll remove most of the debug-prints too - seems these particular ones are no longer needed?

daver2
January 2nd, 2018, 08:03 AM
You're not far off now :-) :-) :-)!

Yes, please follow the full build process every time checking for errors. You will find that you get to your end point quicker if you do rather than back-tracking!

You need to modify const: to see if the SIO has a receiver character ready and modify conin: to read that character from the SIO. Ignore everything to do with your interrupt buffers...

The output side (conost and conout) already appear to do the correct thing with the SIO anyhow.

Dave

nockieboy
January 2nd, 2018, 08:13 AM
You're not far off now :-) :-) :-)!

Yes, please follow the full build process every time checking for errors. You will find that you get to your end point quicker if you do!

Dave

Sorry Dave - I was just excited to be making progress after the drive-wipe incident yesterday! :)

Okay, I've made an attempt to de-interruptify the CCP IO... still no life at the prompt, however. This is what I'm trying:


conin:
CALL const
JR Z,conin
IN A,(SIOA_D)
RET

const:
PUSH HL
; Check if there is a char in channel A
SUB A
OUT (SIOA_C),A
IN A,(SIOA_C) ; Status byte D2=TX Buff Empty, D0=RX char ready
RRCA ; Rotates RX status into Carry Flag,
JR NC,nochars
POP HL
LD A,$FF
RET

nochars:
POP HL
XOR A
RET


EDIT: Just realised - the PUSH/POP HL's are leftovers from the interrupt-driven code. I'll remove them, but they shouldn't have affected how it works (and it's not working.)

durgadas311
January 2nd, 2018, 08:18 AM
I do see what I think is wrong with your interrupt console input code. "conin" pops HL at the end but never pushes it. Also, "const" pushes and pops HL but doesn't need to.

nockieboy
January 2nd, 2018, 08:22 AM
I do see what I think is wrong with your interrupt console input code. "conin" pops HL at the end but never pushes it. Also, "const" pushes and pops HL but doesn't need to.

I fixed the loitering POP HL from conin: before testing the code (it still doesn't work) - have spotted the unnecessary push/pops in const, but they balance out so shouldn't affect the functionality?

EDIT: Have removed extra push/pops - no change on functionality. Still freezes at the prompt.

nockieboy
January 2nd, 2018, 08:25 AM
Here's the latest version of my BIOS3.ASM: 42816

durgadas311
January 2nd, 2018, 08:30 AM
I see the problem. conin depends on const returning with the ZR status bit indicating the result, but your "LD A,$FF" does not set ZR properly. This is why most code uses things like "XOR A,A/DEC A" instead.

daver2
January 2nd, 2018, 08:34 AM
Just beat me to it!

Remember - in the Z80 - a LD doesn't modify the flags. A logical operation does. This is different to other microprocessors. where a LD does modify the flags. Traps for the unwary in assembler...

Dave

nockieboy
January 2nd, 2018, 08:50 AM
Ahhh - dag nabbit! So what's the best way to make sure the Z flag isn't set?


XOR A
DEC A

as durgadas311 mentions? By my reckoning, that should zero A, then subtract 1 which would make it FF and set Z to zero accordingly?

nockieboy
January 2nd, 2018, 08:57 AM
Oooh... that works!!!

Okay. CCP is working - at least as far as DIR and some of my custom commands go.

I had a file before my drive was wiped yesterday that told me what version of CP/M I was running... no idea what it was called now. Any ideas? I just want to confirm that it's definitely CP/M Plus I'm running now! :D

daver2
January 2nd, 2018, 09:16 AM
LD A,$FF
OR A

Is the simplest way without resorting to complex mental arithmetic.

The only reason you needed the flags setting was not for CPM (it uses the VALUE in the A register) but for your own implementation of conin.

Dave

nockieboy
January 2nd, 2018, 09:23 AM
LD A,$FF
OR A

Is the simplest way without resorting to complex mental arithmetic.

The only reason you needed the flags setting was not for CPM (it uses the VALUE in the A register) but for your own implementation of conin.

Dave

Ah, fair enough. Well, I answered my own question above - it was SYSINFO.COM I was looking for:


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

So yes, CP/M Plus is running. :) I just need to 'upgrade' the IO to the interrupt-driven format as that is a requirement for getting data from my support module (date and stuff like that). Once that's done and I can do everything in CP/M Plus that I can do in CP/M 2.2, I just need to work out how to get CP/M Plus to boot instead of 2.2 (i.e. I'm guessing place CPMLDR into Track 0?)

daver2
January 2nd, 2018, 09:27 AM
I would make sure everything else was working FIRST. Bringing interrupts anywhere near this thing will result in many crashes and sleepless nights I am sure...

Dave

durgadas311
January 2nd, 2018, 09:34 AM
Congrats!

As far as putting CPMLDR on track 0, you may want to think hard. For one, you need to have that code be able to execute where the boot ROM places it, or else take some special action to move it. It's unfortunate that you only have one bootable image in your disk layout, because that forces you into one or the other. If you commit to directly booting CP/M 3 then you run the risk of making a mistake sometime when regenerating CPM3.SYS and you'll not be able to boot anything anymore. Whatever you plan to do, make sure you have recovery strategies.

Chuck(G)
January 2nd, 2018, 09:51 AM
LD A,$FF
OR A

Is the simplest way without resorting to complex mental arithmetic.

The only reason you needed the flags setting was not for CPM (it uses the VALUE in the A register) but for your own implementation of conin.


OR $ff (F6 FF)

will do the same and be 1 byte shorter. ;)

nockieboy
January 2nd, 2018, 09:51 AM
Yeah okay, fair points. I've got it good at the moment as I have CP/M 2.2, from which I can switch to CP/M 3 if the mood takes me. Can't get much more flexible than that.


It's unfortunate that you only have one bootable image in your disk layout, because that forces you into one or the other.

That's an interesting observation. I wonder how difficult it would be to create a bootable CP/M 3 image on drive D, then have the option to boot from A or D in the ROM...? At the moment, you type 'cpm' and it loads sector 0 from drive A...

daver2
January 2nd, 2018, 10:04 AM
Can you remind me - what are you using for your disk?

Option at boot time for disk to boot from?

The concept of an 'if I screw up my configuration how do I recover' situation is well worth consideration from the outset.

We have this with our 'mainframes' at work - when making changes to the CLM_USER file, if you make an error you need a recovery disk to boot from! You can use the front panel to bypass the offending item - but even this can leave you with an unusable system.

Dave

durgadas311
January 2nd, 2018, 10:22 AM
Yeah okay, fair points. I've got it good at the moment as I have CP/M 2.2, from which I can switch to CP/M 3 if the mood takes me. Can't get much more flexible than that.



That's an interesting observation. I wonder how difficult it would be to create a bootable CP/M 3 image on drive D, then have the option to boot from A or D in the ROM...? At the moment, you type 'cpm' and it loads sector 0 from drive A...

This has been done many ways in the past. One hurdle you have now is that, in order to get more space for boot tracks you'll need to change the layout of the other disks and that impacts not only what is stored on those disks but every copy of CP/M that thinks it knows the layout (since that layout is hard-coded into every BIOS).

What MMS did for SASI disks on the H89 was to place a "pre-boot" loader, along with configuration info, starting at sector 0. That loader knew how to look at the config info (partitioning) along with options passed from the ROM boot command, and continue to boot CP/M from a specific partition. That way, if you had 3 partitions (for example) you could have three different boot images - and select them using options on the boot command string.

nockieboy
January 2nd, 2018, 10:39 AM
Can you remind me - what are you using for your disk?

I'm using a 64MB CompactFlash card connected to the system via an 8-bit IDE interface.


Option at boot time for disk to boot from?

The concept of an 'if I screw up my configuration how do I recover' situation is well worth consideration from the outset.

Yes, pretty much - I'd just make it so that 'cpm' boots from A, 'cpm3' boots from D, or something similar. I am now able to recover the system from scratch, or with a new blank CF card, if need be.


We have this with our 'mainframes' at work - when making changes to the CLM_USER file, if you make an error you need a recovery disk to boot from! You can use the front panel to bypass the offending item - but even this can leave you with an unusable system.

Dave

Well, I'm learning as I'm going as software engineering (and electronics) aren't my trades, just my hobbies! :rolleyes:

durgadas311
January 2nd, 2018, 11:10 AM
One way to implement a multi-boot option would be to keep the disk layout as-is, and make the CP/M 2.2 image on track 0 be the "loader" for any other OS. If you can pass the boot command to the CP/M 2.2 image, it could do some custom actions in the cold boot path, instead of starting CP/M 2.2.

One tricky area is the CP/M concept of "drive A:" vs. "partition 0" on the flash disk. Right now, your BIOS hard-codes drive A: to partition 0, etc. But for a multi-boot setup you'd want "drive A:" to be whichever partition is appropriate for the OS you are booting. If you solve this problem, then your CP/M 2.2 BIOS cold boot could do something like this:

1) check boot command, default is to jump to CP/M 2.2 normally, OTHERWISE:
2) select a CCP command based on boot command, for example "cpm3" might map to "D:CPMLDR".
3) Place that command into the CCP command buffer, which will cause CCP to execute it immediately on starting.
4) jump to CCP.

The D:CPMLDR.COM, as well as BIOS3 in CPM3.SYS, would have to "swizzle" the disk partition mapping such that "drive A:" was actually partition 3 (or wherever you want CP/M 3 to be). You could go further and modify CPMLDR to accept commandline options and then use those to swizzle drive mapping and pass those along to BIOS3 for the same.

nockieboy
January 2nd, 2018, 11:33 AM
One way to implement a multi-boot option would be to keep the disk layout as-is, and make the CP/M 2.2 image on track 0 be the "loader" for any other OS. If you can pass the boot command to the CP/M 2.2 image, it could do some custom actions in the cold boot path, instead of starting CP/M 2.2.

One tricky area is the CP/M concept of "drive A:" vs. "partition 0" on the flash disk. Right now, your BIOS hard-codes drive A: to partition 0, etc. But for a multi-boot setup you'd want "drive A:" to be whichever partition is appropriate for the OS you are booting. If you solve this problem, then your CP/M 2.2 BIOS cold boot could do something like this:

1) check boot command, default is to jump to CP/M 2.2 normally, OTHERWISE:
2) select a CCP command based on boot command, for example "cpm3" might map to "D:CPMLDR".
3) Place that command into the CCP command buffer, which will cause CCP to execute it immediately on starting.
4) jump to CCP.

The D:CPMLDR.COM, as well as BIOS3 in CPM3.SYS, would have to "swizzle" the disk partition mapping such that "drive A:" was actually partition 3 (or wherever you want CP/M 3 to be). You could go further and modify CPMLDR to accept commandline options and then use those to swizzle drive mapping and pass those along to BIOS3 for the same.

I have CPM 3 on CPM 2.2 as a file, launched via CPMLDR.COM. Wouldn't it be easier (if possible) to insert the command 'CPMLDR' into the CCP command buffer when launching CPM 2.2? Then the system would load CPM 2.2 and immediately go into CPM 3? Then I needn't worry about messing around with drive/partition mapping etc. That is, of course, assuming that inserting anything into the CCP command buffer is possible and even vaguely easy? I didn't know you could do it until you mentioned it, durgadas311! :)

daver2
January 2nd, 2018, 11:56 AM
Yes, you can force something like 'SUBMIT AUTOEXEC' into the CCP command buffer and you will get an automated start-up of commands.

What you have to be sure of (however) is that you don't automatically start CP/M 2.2 which then automatically starts CP/M 3 and then screws up every time!

You need your own MONITOR BOOT program to define whether you want CP/M 2.2 to just start on its own or run its start-up file to do whatever.

Whatever you do - you may want to consider making the CP/M 2.2 disk completely unavailable to other incarnations of CP/M that you may boot - this is perhaps where the drive mapping comes in?

Dave

durgadas311
January 2nd, 2018, 11:59 AM
The problem with not swizzling the drives is that the "system disk" is no longer A:. That can create some problems - although it may be possible to just set the default drive to D: for CP/M Plus (I forget whether CP/M 3 restricts booting to only drive A:), especially since CP/M 3 adds a lot more system config options. I'm working off the premise that you do not want your CP/M 2.2 system drive to be the same disk as used for the CP/M 3. first of all, you have a big mess of utilities, some for 2.2 and some for 3, all mixed together. Another is if you want to use the CP/M 3 extended directory structure (timestamps, passwords): while it's not incompatible with CP/M 2.2 it still is messy.

FYI, pre-loading a command into the CCP image was a common method for making "auto run" disks, and is even documented by DRI.

daver2
January 2nd, 2018, 12:11 PM
Another + for CP/M Plus was that you just created a file called 'PROFILE.SUB' and away it went at start-up. No hacking...

Dave

durgadas311
January 2nd, 2018, 12:22 PM
Good point, this CCP hack was for 2.2 (and older). CP/M 3 did not require you to resort to such tactics. I remember being involved in early access discussions with DRI, and they really were open to fixing nearly everything people thought was wrong with CP/M 2.2. You can even setup a search order that the CCP will use when searching for commands, that's in addition to being able to look on "User 0" of a drive (not that there was much use of user numbers, that I recal). I did organize my development system into different user numbers for different projects. It was a little crude, as chuckg has mentioned, but it was usable. PIP on CP/M 3 was greatly enhanced, especially in the area of user number handling, so that copying files around was not too bad.

Alphasite
January 2nd, 2018, 05:30 PM
I would argue that MP/M II is not a replacement for CP/M Plus. For a single user, MP/M II is actually a downgrade. CP/M Plus has a vastly superior UI. MP/M-II has a reduced TPA due to the extra layers of software. The multitasking feature is actually not very useful, as there are no practical applications to use it. CP/NET (Server) was the one big application for multitasking that I knew of. Otherwise, people used the "multi-user" features of MP/M-II but that was to run independent CP/M-like users. But the maximum TPA was significantly smaller (48K) than what most CP/M Plus implementations provided (56K). While you could run multiple users on a single Z80 box with MP/M, it was not very fast if those users were doing much more than data entry.

Also, as I thought I heard this inferred recently, MP/M cannot run on SMP hardware (without significant redesign). It is not a *multiprocessor* OS. I recall some hardware vendors of the time that provided systems with multiple Z80s, but they were all independent single-board Z80 *computers* all housed in a single enclosure, possibly having some shared memory between them. Nothing at all like modern multiprocessor (multicore) systems, and you could not run a single instance of MP/M on a batch of independent computers - they could each run their own, isolated, MP/M instances and then you'd have to build some sort of interconnect and software to support it.

For me MP/M II wasn't an option at the time for one big reason: I didn't have access to the documentation to modify my CP/M 2.2 BIOS to work with MP/M II and the software to build a custom MP/M II.

nockieboy
January 3rd, 2018, 02:50 AM
Good point, this CCP hack was for 2.2 (and older). CP/M 3 did not require you to resort to such tactics. I remember being involved in early access discussions with DRI, and they really were open to fixing nearly everything people thought was wrong with CP/M 2.2. You can even setup a search order that the CCP will use when searching for commands, that's in addition to being able to look on "User 0" of a drive (not that there was much use of user numbers, that I recal). I did organize my development system into different user numbers for different projects. It was a little crude, as chuckg has mentioned, but it was usable. PIP on CP/M 3 was greatly enhanced, especially in the area of user number handling, so that copying files around was not too bad.

They sound like they were a decent company. In some ways it's a shame MS-DOS took the market over - would be interesting to see what would have happened had CP/M won out...

durgadas311
January 3rd, 2018, 03:29 AM
They sound like they were a decent company. In some ways it's a shame MS-DOS took the market over - would be interesting to see what would have happened had CP/M won out...

In the circles I worked, there was "a great wailing and gnashing of teeth" when IBM finally announced what their "PC" would be... From my perspective, a giant step backward. There were much better CPUs and, of course, much better starting points for the OS.

nockieboy
January 3rd, 2018, 06:42 AM
In the circles I worked, there was "a great wailing and gnashing of teeth" when IBM finally announced what their "PC" would be... From my perspective, a giant step backward. There were much better CPUs and, of course, much better starting points for the OS.

I can believe it. I was a great fan of the Amiga when I moved up in the world to 16-bit - I don't know much about the Motorola 68k series of processors at the moment (might build an SBC around one at some point) but the Amigas and Ataris were highly capable computers against the PCs of the time. Seems to be a story that history repeats - it's not always the best that wins in the end.

Chuck(G)
January 3rd, 2018, 07:52 AM
I won't argue many of your points.

CP/M 3.0/Plus came after MP/M and used much of the code base. I've never checked; does CP/M 3.0 run PRL files? The big advantage of MP/M over CP/M other than the multi/user/tasking aspects was the ability to overlap I/O and processing; i.e., one user could be waiting for his disk I/O to complete, while another was working. For this, of course, the I/O structure almost has to be interrupt-driven and the XIOS coder has to be aware of reentrancy issues. The other thing that MP/M introduced was record locking--essential for multi-user applications. What MP/M didn't implement was MUJs, which, in my opinion, really hampered attractiveness.

I still have some MP/M I boot disks that I constructed--the system was very buggy. MP/M II was much better--and I still have the original OEM kit for it.

A multi-user general-purpose OS was probably too much for even a Z80H-based system. And it was used with systems like the Molecular multi-Z80 system, so yes, multiprocessing. SMP for 8-bit CPUs wasn't really practical--but that's a special case of multiprocessing, isn't it? And MP/M could certainly do multi-tasking in a multiuser mode.

DRI never gave up the idea of a multitasking OS, right up through Concurrent DOS for the x86.

I can understand the lack of interest at the hobbyist level in MP/M/MP/M-86, etc. Coming up with a good implementation is substantially more difficult than CP/M of any flavor--but the system itself is more interesting.

As far as limits on the TPA goes, it all depends on your bank-switching hardware. MP/M and CP/M 3.0 nominally assumed a granularity of 16KB per bank, but we had 1KB granularity and could do substantially better. I suspect that there were other vendors who operated the same way. That 48K tpa isn't cast in iron.

All that being said, you're right--there were few applications that could take advantage of MP/Ms multi-user capability. We found that a multi-user BASIC interpreter (P-codes) resulted in more efficient memory usage; didn't care about non-relocatability of code; and did a better job of timeslicing than a full-blown multi-user OS. Concurrent I/O was pretty much mandatory, however.

durgadas311
January 3rd, 2018, 09:05 AM
To me, SMP means multiple CPUs with (symmetrical) access to the same memory and I/O and running the same intance (copy) of the OS. I believe that MP/M, out of the box, would not function in that environment. There are many ways to package multiple CPUs in the same enclosure, though. I'd be interested in the details of the any multi-CPU hardware that ran MP/M.

Chuck(G)
January 3rd, 2018, 09:39 AM
I think you're right about MP/M (or CP/M) not working with SMP. But how many Z80-based commercial SMP systems can you name?

Here's a note about Molecular's multi-CPU system (https://books.google.com/books?id=5t3_KRY6ZeUC&pg=RA1-PA93&lpg=RA1-PA93&dq=multiprocessor+systems+using+MP/M&source=bl&ots=WgT9B9nJ06&sig=8LbxReJzi29Rh1SjJGL5rawgo6Y&hl=en&sa=X&ved=0ahUKEwj8x56xtrzYAhUKPCYKHWUMB9EQ6AEIfDAP#v=on epage&q=multiprocessor%20systems%20using%20MP%2FM&f=false). It seems that MP/M would run under a hypervisor, so maybe this doesn't count.

Another trade rag article announcing MP/M 2.0 (https://books.google.com/books?id=5t3_KRY6ZeUC&pg=RA1-PA93&lpg=RA1-PA93&dq=multiprocessor+systems+using+MP/M&source=bl&ots=WgT9B9nJ06&sig=8LbxReJzi29Rh1SjJGL5rawgo6Y&hl=en&sa=X&ved=0ahUKEwj8x56xtrzYAhUKPCYKHWUMB9EQ6AEIfDAP#v=on epage&q=multiprocessor%20systems%20using%20MP%2FM&f=false) opines that CP/M 3.0, when released, may actually be a step backward (not my words) for current MP/M users.

durgadas311
January 3rd, 2018, 11:32 AM
Molecular's system sounds like independent CPU+memory(+serial-ports) cards, and I presume some sort of high speed interconnect for communication. I'm guessing there is some sort of executive running somewhere to share the disk(s). Not sure what runs in each CPU+memory instance. It would be interesting to see more on how the system was used (what was the user experience like).

I'm pretty sure no true-SMP Z80 systems existed, not even 8086. Sequent Computer Systems, an early pioneer of SMP, could not use Intel processors until the '386 due to issues with the CPU design (one was the MMU, another may have been atomic ops). Their first offering used the NS32032 CPU. Even then, they had specialized hardware to achieve the atomic operations (test-and-set) needed to implement an SMP OS.

Your second link seems to be the same as the first, so I can't read the article. But, MP/M is not at all the same as CP/M3. You definitely have features available on MP/M that don't exist on CP/M3 (and vice versa) so you would lose capabilities in switching - if you used those MP/M features. But for a "traditional" single-user workstation, I personally would not choose MP/M.

MP/M did allow running of multiple jobs for a single user, IIRC, but I don't remember just how easy that was to use. Certainly nothing like the job control found in Unix/Linux shells.

Chuck(G)
January 3rd, 2018, 11:50 AM
The first microprocessor CPU that I saw advertised as having SMP capabilities was the beleaguered iAPX432.

On mainframes, it was not uncommon to have CPUs share one common memory (e.g. CDC 6500), but that was when a CPU could dedicate useful cycles without memory access.

Another situation was to have multiple CPUs with private memory share a common memory resource (e.g. CDC ECS).

Such a setup would not be impossible on a Z80 system, but would probably not be a big performer. Shared peripherals, on the other hand, were not unknown, even on microcomputers.

Another class of multiprocessing is found in CDC PPUs and the Parallax propeller. But that's more a matter of I/O channel technology, although in the case of CDC, most of the operating system resided in the PPUs, leaving the CPU(s) to do what it was best at.

TurboDOS claimed to be modular enough to support true multiprocessing, but I've got no experience with that configuration.

nockieboy
January 3rd, 2018, 12:35 PM
I've heard mention of TurboDOS before - anyone have any practical experience with it? What separated it from CP/M in functionality?

Chuck(G)
January 3rd, 2018, 01:41 PM
I've got TurboDOS for a few systems, including a Televideo box.

The topic has come up here and I think that the software was made publicly available:

http://www.vcfed.org/forum/showthread.php?41297-TurboDos-Resurrected!

durgadas311
January 4th, 2018, 05:21 AM
At least Z80 and CP/M are not affected by the speculative execution security bug.

daver2
January 4th, 2018, 06:01 AM
Back to the original topic...

The only reason you originally used CP/M 2.2 was because you had a working copy of it and could use it to develop and bootstrap your CP/M 3. Now that you have a working CP/M 3 system, you could ditch the CP/M 2.2 couldn't you?

You would now need to keep a fully working CP/M 3 disk to boot from as a 'recovery' disk, with your 'operational' copy of CP/M 3 on a separate disk.

Assuming your 'recovery' disk is the first area of your CF - then you could set the boot drives as A: for your recovery disk and B: for your working disk (i.e. the next area of the CF).

If you boot from your working disk, you could make this your A: drive, with subsequent areas of your CF as B:, C:, ...

If you wanted to manipulate your 'recovery' drive from your 'working' drive, you could map the first area of the CF as the last logical drive.

Assuming your CF is split up into equally sized drives, mapping areas of CF to logical CPM drives can be done by adding a logical block number offset to the starting logical block for each logical drive. Space for these numbers can be stored into known areas of your BIOS and initialised by your boot ROM.

As I understand it now, pretty much all of your bios code and data is stored in the CSEG, and very little (if any) in the DSEG. This means most of it is in common memory and not banked. If this is the case, what is the point of being able to put part of the BIOS into banked memory? I think I am missing something somewhere?

Dave

durgadas311
January 4th, 2018, 06:44 AM
One issue is that there is only one set of boot tracks, so if anything happens to those boot tracks it is catastrophic. Perhaps there is (now) an easy recovery path for that. Also, if any future work experiments with changes in the boot code, you don't have a safe test environment (you have to put the test boot code on the (only) boot tracks and risk loss of boot capability).

True, once you have a stable CPM3.SYS image you have little/no need for CP/M 2.2. But it may continue to be a handy fall-back due to it's simplicity.

If you fully commit to CP/M 3, and never change the loader (boot code), you could then just always boot CP/M 3 of one flavor or another. You'll have to write some sort of boot code that can place the loader into 0100H (in "bank 0") so that it executes correctly. Trying to run the loader from a higher address could be problematic, as you have higher risk of a CPM3.SYS image overlapping the loader code and causing a crash.

I've not seen this system boot (i.e. how slow/fast it is), but conceptually there's nothing wrong with using CP/M 2.2 to boot CP/M 3. It does give you more options - if you ever have a reason to run CP/M 2.2 you just don't run CPMLDR.COM. It also means you don't need to create a bootstrap routine and splice it into the boot tracks with the loader. Less low-level (boot) code to write and maintain (i.e. CP/M 2.2 is already done).

I still think it would be a good idea to separate the concept of logical vs. physical drives, but that may not be needed for CP/M 3. I seem to think there were places in CP/M 2.2 where "A:" was hardcoded, so you couldn't really run with no A: drive. But in CP/M 3 you might be able to get away with having no A: drive, with proper defaults setup. But the simplest approach would probably be to separate logical drive from physical drive in the BIOS computation of LBA, using one of many possible methods (Partition offset table, drive number translation, ???). The CP/M 3 System guide even demonstrates a way to extend the DPH structure to include information such as this, which means the logical-physical translation can be done with the existing "dtbl" lookup (re-arranging entries in 'dtbl' changes the logical-physical drive relationship).

Regarding CSEG/DSEG in the BIOS, I tried to simplify things by placing most everything (except for a couple mistakes) in CSEG, and putting as much of the disk buffers as possible in banked memory - mainly to reduce impact on the TPA size. More still could be put in banked memory, but the buffers were the big thing. The bottom line: the smaller the CSEG the larger the TPA.

nockieboy
January 4th, 2018, 08:37 AM
Well, I'm taking a time-out now that CP/M 3 is 'working' to work on a couple of other loose ends that need tying up - mostly brought to the fore by the loss of my A: drive the other day. I've spent a little time this afternoon shifting NASCOM BASIC out of the same ROM bank as my monitor program and into its own bank. This gives me almost double the space to expand my monitor program with some useful additions - like the FORMAT and PUTSYS programs that were previously separate Intel Hex streams that I'd paste into RAM and execute, reducing reliance on project files and making the SBC more standalone. I could even put a copy of CP/M in there in one form or another and give the SBC the ability to format and set up new CF cards with a working operating system from the off, without any external files required.

Loading times for CP/M 2.2 are in <2 seconds territory, with maybe another 2 seconds to load CP/M 3, so not a great concern (and a lot quicker than they would have been back in the 80's!!) EDIT: These times are with the SBC running at 4 MHz - obviously at 8 MHz they'll be even less!

One question re: CP/M 3 - I'm supposed to be able to recall previous commands or edit the command line, a la DOS I'm guessing, but I can't send CTRL, ALT or arrow chars down the terminal - can I?

My copy of CP/M 3 still requires some more work before I get into the question of what I'm going to do about booting it directly (or not) - namely getting the serial interrupts working again, which are a requirement if I want it to work with my microcontroller that provides things like the date and time, current clockspeed, etc.

durgadas311
January 4th, 2018, 09:50 AM
Commandline editing is describe several places, I think. One is in the CP/M 3 Programmer's Guide under BDOS function 10 (Read Console Buffer).

nockieboy
January 4th, 2018, 01:30 PM
Okay, whilst testing some disk-recovery functions the system has managed to clear A: drive again. Shouldn't be a problem, except that I seem to be unable to restore the A: drive files from D: due to the following error message:


D>PIP A:=D:EXIT.COM

NO DIRECTORY SPACE: =D:EXIT.COM

D>

That was after I'd tried copying all files (*.*), so I thought I'd try one file on its own, but as you can see CP/M still isn't happy about it.

For info, this is CP/M 2.2 and here's the output from LS A:


D>ls A:

0 File(s), occupying 0K of 8160K total capacity
0 directory entries and 8116K bytes remain on A:
D>

Anyone have any ideas?

durgadas311
January 4th, 2018, 02:25 PM
I'm not sure what LS.COM does, but it seems to imply that there are no available directory entries on A: One thought I had was in reformatting A: did you fill (at least) the directory area with 0xe5? CP/M uses the code 0xe5 in the first byte of each directory entry to indicate "empty" (available).

Chuck(G)
January 4th, 2018, 04:26 PM
Most likely, that's the answer. Poke around on your disk and see what a directory sector looks like.

The other possibility is a failure in your disk read routines.

nockieboy
January 5th, 2018, 03:30 AM
Ah - whatever caused the crash and wiped my A: drive also messed with the directory entries. I've reformatted A drive and it's fine now.

nockieboy
January 5th, 2018, 07:12 AM
Okay, not quite fine...

Whilst copying the backed-up A: drive (from D: ) to A: (using PIP), I've noticed that PIP/CCP hangs if it tries to copy a file larger than 8KB. The next larger file I have after 8KB is 12KB and it consistently hangs if I try to copy it or anything larger... Any file that caused the hang appears (after a reset) in the A: drive as : (using BDOS3.SPR as an example)


A>stat bdos3.$$$

Recs Bytes Ext Acc
0 0k 1 R/W A:BDOS3.$$$
Bytes Remaining On A: 8044k

A>

How strange is that? Any ideas?

daver2
January 5th, 2018, 07:35 AM
No, but the best way to find out potentially what is going on is to put some diagnostic information into the disk read and write routines (i.e. drive/track/sector/buffer address/mapping etc.).

To save corrupting your console output, you could possibly send the debug output to the second serial port...

This is what I meant previously about testing out fully what you have currently got working before adding more to the mix.

Dave

durgadas311
January 5th, 2018, 08:05 AM
The file with the "$$$" suffix is normal - that is what most CP/M programs use for temporary files. PIP will create a temporary file when copying so that it doesn't destroy any existing file of the same name - until it successfully creates the new copy. If the current extent is not closed, as happens when you reset in the middle of operations, then it will appear as empty (zero length) when you reboot - since no allocation info was written to disk.

With your DPBs, 8K would be two allocation blocks and 1/2 an extent and 1/4 of an directory entry. That seems like an odd place to hang, usually there is some sort of special action being taken (get new allocation entry, new extent, new dir entry). One possibility is that the track number is changing at that point, although your disk doesn't use tracks.

At this point, I don't have any ideas as to what might be causing it. We need either more details that might reveal a pattern or else more debugging. It would be particularly useful to know where the code was hung, although that may not be a simple loop and thus could be hard to figure out.

You could run PIP under DDT (I'm assuming this is CP/M 2.2 since you are using "stat"), but regaining control when it hangs may not be easy.

Alphasite
January 5th, 2018, 09:29 AM
Okay, not quite fine...

Whilst copying the backed-up A: drive (from D: ) to A: (using PIP), I've noticed that PIP/CCP hangs if it tries to copy a file larger than 8KB. The next larger file I have after 8KB is 12KB and it consistently hangs if I try to copy it or anything larger... Any file that caused the hang appears (after a reset) in the A: drive as : (using BDOS3.SPR as an example)


A>stat bdos3.$$$

Recs Bytes Ext Acc
0 0k 1 R/W A:BDOS3.$$$
Bytes Remaining On A: 8044k

A>

How strange is that? Any ideas?

What about copying from D: to one of the other drives? Does that hang as well?

daver2
January 5th, 2018, 09:36 AM
I would hesitate from doing that - just in case the problem is in the BIOS write routines as you could just end up corrupting your other destination drive instead :-(...

Dave

durgadas311
January 5th, 2018, 11:40 AM
This is a wild guess, and I have no experience interfacing to CF cards, but could your cfWait routine be too simplistic and not catching some special cases? I see a more complex protocol being used in this code: https://github.com/MatthewWCook/Z80Project/blob/master/Z80%208bit%20CF%20Card%20Part%201/Code/CFDriver.asm

In that code, it looks like you should ignore BUSY and be waiting for DATA after a read command. If there were some condition in the card such that it was unable to clear BUSY because it needed you to read data first, your cfWait routine would hang.

But, if we knew where it was hung that would tell us a lot. Not sure how to get that data, though. If this is CP/M 2.2 (with interrupt driven input) then you could modify the BIOS to respond to a certain character and dump the return address from the interrupt routine, that is one way. You then do this debug dump of the PC several times and you should get some idea of where it is executing. Of course, this only works if interrupts are enabled.

durgadas311
January 5th, 2018, 11:52 AM
I might be wrong about the CF card BSY and DRQ. Seems like maybe the expectation is that BSY goes low when DRQ is set.

daver2
January 5th, 2018, 12:44 PM
That was the conclusion I came to today. I am writing a CF interface for NAS-DOS running on a NASCOM. The CF specification states that if the BUSY bit is SET then the other bits in the status register cannot be trusted as the CF card 'owns' them (my words).

I suspect what happens is that if the CF is using the registers, then the BUSY bit will be set. If the CF is not using the registers, the BUSY bit will be reset and the remaining bits of the status register are valid and can,therefore, be processed by the host processor.

This will apply to the READY, DRQ and ERROR bits.

The other thing to ensure is that you check the ERROR bit - just in case the CF card complains...

I don't know whether my logic is correct, however, as I haven't tested anything in reality yet - but that is what I have gleaned from the specification document.

Dave

durgadas311
January 5th, 2018, 12:54 PM
Yeah, Flash memory *will* wear out, and so errors are a very real possibility. I don't know how much recovery and bad block replacement is done in the CF card, but that only delays the inevitable.

The CP/M BDOS is very deterministic, and aside from character I/O, there should be no place that will loop indefinitely. I'm pretty sure PIP also will not loop. That leads me to suspect the BIOS, but I can't yet find anything there. Another kind of hang can be due to interrupts, although I don't think that's happening here. If an interrupt does not get properly acknowledged, and serviced, then you can hang in an infinite interrupt loop. Since interrupts are only used for serial I/O here, this could only happen if there was path through the interrupt routine that did not read the SIO data register and/or did not do a RETI. As long as interrupts are not enabled for line status conditions (framing error, loss of DTR, ...).

Finding out what the PC is doing when hung is probably the next step, unless we can find more information to target the code inspection.

daver2
January 5th, 2018, 01:14 PM
I have just looked at the CF read and write routines within the BIOS from post #261 (not sure whether this post is the latest). I agree that these look a little too simplistic to function under all circumstances. I will have a look at the CF specification tomorrow and see what it has to say on the matter.

An error status could be returned in the case of a software programmatic error or an interface error (e.g. writing an incorrect value to a CF register that is detectable by the CF logic).

Without timeouts, the code may hang (for instance, my cfWait has a timeout that returns with the CY flag set if a timeout occurs whilst waiting for the BUSY bit to be cleared). Ditto for other status bits.

You should also only transfer data when the DRQ bit is set. This precludes the use of the Z80 'clever' I/O instructions in 'multiple' mode.

Dave

nockieboy
January 6th, 2018, 02:40 AM
Sorry I've not been able to post much guys - I'm getting less and less time to work on the project at the moment and it's back to work next week, so it may drop off even further. :(

Just to clarify the situation with the failed copy with PIP - it is in CP/M 2.2, nothing to do with the recent CP/M 3 work. I'm not aware of any issues like this previously with 2.2 (though I've not exactly been constantly copying 'huge' files between drives so am not aware of any deficiencies in the cfWait routine? Happy to give any improvements a try though!) - I was obviously able to copy all the files over from A: to D: previously. I will endeavour to try copying them to another drive when I get a chance and update you on the results.

Oh, I'm able to add files to A: drive of any size using 'DOWNLOAD.COM', which takes a pasted Intel Hex stream from the terminal and creates a file from it..

JohnElliott
January 6th, 2018, 08:41 AM
I've never checked; does CP/M 3.0 run PRL files?

Yes, if you include the ".PRL" on the command line (so, for example, typing the command as BASIC.PRL rather than just BASIC). It just discards the PRL header and runs the result at 0100h, like a COM file.

daver2
January 7th, 2018, 03:02 AM
I go back to work this week as well, so I know the problem very well!!!

Since you had some corruption on the Compact Flash elsewhere, you can't really guarantee that your 2.2 'partition' escaped unscathed. For example, how do you know that PIP itself escaped a bit of corruption somewhere?

I would personally assume that the CF 'was a write off' completely if some corruption had occurred somewhere and reloaded it completely from a backup source.

The alternative is to obtain a checksum or CRC program and check each file. First as a 'good' fingerprint and then later if corruption is suspected.

This may explain why your 2.2 is not stable now but was before?

Just a thought...

Dave

nockieboy
January 7th, 2018, 12:52 PM
I go back to work this week as well, so I know the problem very well!!!

Since you had some corruption on the Compact Flash elsewhere, you can't really guarantee that your 2.2 'partition' escaped unscathed. For example, how do you know that PIP itself escaped a bit of corruption somewhere?

Well, PIP was erased from A: drive along with all the other files, so I replaced it from the CP/M archives I have, so it should be identical to the original PIP that was on the A: drive..


I would personally assume that the CF 'was a write off' completely if some corruption had occurred somewhere and reloaded it completely from a backup source.

Yes, I'm prepared for that eventuality - it is, after all, a very old CF card (it's a 64MB one, in fact - hard to get hold of these days outside of eBay!)


The alternative is to obtain a checksum or CRC program and check each file. First as a 'good' fingerprint and then later if corruption is suspected.

Well, I'm working to tighten up the CFWAIT routine currently and was looking at some of the code in the link you provided previously for CFdriver.ASM. I'm looking at the below section of code, LOOP_BUSY and have come to the conclusion it is parallel to CFWAIT in my own code, to a degree. I'm a little confused about what it does, though - it seems to do the exact opposite of what CFWAIT does:


;************************************************* **************************
;LOOP_BUSY
;Function: Loops until status register bit 7 (busy) is 0
;************************************************* **************************
LOOP_BUSY:
IN A, (CFSTAT) ;Read status
AND %10000000 ;Mask busy bit
JP NZ,LOOP_BUSY ;Loop until busy(7) is 0
RET

Here's CFWAIT:


;------------------------------------------------------------------------------
; CFWAIT
;------------------------------------------------------------------------------
CFWAIT:
PUSH AF
cfWait1:IN A,(CF_STATUS)
AND 080H
CP 080H
JR Z,cfWait1
POP AF
RET

Either LOOP_BUSY is doing the exact opposite of CF_WAIT or the extra CP in CF_WAIT is reversing the outcome?

daver2
January 7th, 2018, 01:09 PM
LOOP_BUSY performs the JP if bit 7 is '1'.

CFWAIT performs a compare (CP) with a constant. This sets the Z flag if the two values being compared are identical (an imaginary subtraction). This means the JR flag to loop on is the Z flag.

The condition tests are the opposite way around, therefore the flag check needs to be the opposite way around also.

Comments in programs that describe the thought process of the coder are always a boon here...

Dave

durgadas311
January 7th, 2018, 01:10 PM
Given that the CF card is very old, it seems highly likely there could be bad blocks. I'm not sure how it would handle that. But the CF I/O routines should probably be rewritten to do the more-complete protocol, and check for error. I can easily imagine that problems with the media could - at least - affect timing and might result in BUSY going low before DRQ goes high. Trying to read/write data before DRQ goes high could have unpredictable results. Also, I suspect modern cards have more advanced firmware and might be better at bad block handling.

durgadas311
January 7th, 2018, 01:14 PM
From what I gather from that other code I linked to, the protocol is something like this:

wait for not BUSY
issue READ command
wait for not BUSY and wait for DRQ (the code does both in the same loop)
read one byte
wait for DRQ
read another byte
...etc...

and similar for WRITE. Your code only waited for not BUSY after the command, and did not check DRQ (on each byte transferred). I think our current guess is that this "not BUSY" check was insufficient.

nockieboy
January 8th, 2018, 01:59 AM
LOOP_BUSY performs the JP if bit 7 is '1'.

CFWAIT performs a compare (CP) with a constant. This sets the Z flag if the two values being compared are identical (an imaginary subtraction). This means the JR flag to loop on is the Z flag.

The condition tests are the opposite way around, therefore the flag check needs to be the opposite way around also.

Comments in programs that describe the thought process of the coder are always a boon here...

Dave

Yeah, what I don't understand is that CFWAIT loops until bit 7 is 0 (the CF card is NOT busy?) whereas LOOP_BUSY loops until bit 7 is 1 (the CF card IS busy)??

CFWAIT clearly works (recent issues aside) and I want to replace the AND 080H and CP 080H with just one command, AND %10000000 (which appears functionally identical to the AND and CP as long as it modifies the Z flag like CP does) but then it raised the question of why LOOP_BUSY does the opposite of CFWAIT..

Ah, never mind. I've looked at the code with a fresh pair of eyes this morning (don't worry, they were my own) and it's making more sense now!!

Okay, briefly I've updated the CFWAIT routine/s and read/write routines in CBIOS (CP/M 2.2's BIOS) - everything still reads and writes okay, but no change with the inability to copy anything larger than 8K across to A: drive:


;------------------------------------------------------------------------------
; Read physical sector from host
;------------------------------------------------------------------------------
readhst:
PUSH AF
PUSH BC
PUSH HL

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 %00000001 ; mask off error bit
JP Z,rdcont ; Continue if no error
CALL printInline
.DB CR,LF
.TEXT "Error reading sector!"
.DB 0
JP readhst ; Try again

rdcont:
LD C,4
LD HL,hstbuf
rd4secs:
LD B,128
rdByte:
CALL CF_DAT_RDY
IN A,(CF_DATA)
LD (HL),A
INC HL
DEC B
JR NZ, rdByte
DEC C
JR NZ,rd4secs
POP HL
POP BC
POP AF
XOR A
LD (erflag),A
RET

;------------------------------------------------------------------------------
; Write physical sector to host
;------------------------------------------------------------------------------
writehst:
PUSH AF
PUSH BC
PUSH HL
CALL CF_CMD_RDY
CALL setLBAaddr
LD A,CF_WRITE_SEC
OUT (CF_COMMAND),A
CALL CFWAIT
LD C,4
LD HL,hstbuf
wr4secs:
LD B,128
wrByte:
CALL CFWAIT
LD A,(HL)
OUT (CF_DATA),A
INC HL
DEC B
JR NZ, wrByte
DEC C
JR NZ,wr4secs
POP HL
POP BC
POP AF
XOR A
LD (erflag),A
RET

;------------------------------------------------------------------------------
; Wait for disk to be ready (busy=0,ready=1)
;------------------------------------------------------------------------------
CFWAIT:
PUSH AF
cfWait1:
IN A,(CF_STATUS)
AND %10000000 ;Mask busy bit
JP NZ,cfWait1
POP AF
RET

;------------------------------------------------------------------------------
; CF_CMD_RDY
; Loops until status register bit 7 (busy) is 0 and drvrdy(6) is 1
;------------------------------------------------------------------------------
CF_CMD_RDY:
IN A,(CF_STATUS) ;Read status
AND %11000000 ;mask off busy and rdy bits
XOR %01000000 ;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 %10001000 ;mask off busy and drq bits
XOR %00001000 ;we want busy(7) to be 0 and drq(3) to be 1
JP NZ,CF_DAT_RDY
RET

durgadas311
January 8th, 2018, 05:01 AM
One problem I see is that, in the case of ERROR your read routine loops infinitely. But, I guess it also prints a message so you'd know if that were happening. Also, double check the protocol for WRITE. You'll need to be checking for DRQ there, I think. Also, there should be some sort of "completion" wait after writing the last byte to the CF card, I think. Since we don't know where it is hanging, we can't be sure if READ or WRITE (or something else) is the problem. That sample code I referenced was only for READ, might have to hunt around for some other example of CF write.

Does your CF interface have and activity LED? If so, what is that LED doing when things are hung?

nockieboy
January 8th, 2018, 06:43 AM
One problem I see is that, in the case of ERROR your read routine loops infinitely. But, I guess it also prints a message so you'd know if that were happening.

Yes, aware of the error loop but not sure how I should resolve it so that the read routine exits cleanly back to the calling function?


Also, double check the protocol for WRITE. You'll need to be checking for DRQ there, I think. Also, there should be some sort of "completion" wait after writing the last byte to the CF card, I think. Since we don't know where it is hanging, we can't be sure if READ or WRITE (or something else) is the problem. That sample code I referenced was only for READ, might have to hunt around for some other example of CF write.

Thanks for that - will get that sorted.


Does your CF interface have and activity LED? If so, what is that LED doing when things are hung?

Yes it does - it lights for about a second when the PIP command is executed (and presumably is reading the target file), then goes out and doesn't come back on.

durgadas311
January 8th, 2018, 06:56 AM
Yes, aware of the error loop but not sure how I should resolve it so that the read routine exits cleanly back to the calling function?


If you want to re-try the READ (or WRITE), but not hang in the case of a permanent error, you'll need to have some sort of counter such that you don't retry indefinitely. The BIOS READ/WRITE routines return their result status in A, so you can just return an error to BDOS (the caller) as described in the CPM System Guide.

nockieboy
January 8th, 2018, 08:17 AM
Like this?


readhst:
PUSH AF
PUSH BC
PUSH HL

LD A,$0A
LD B,A ; Retry counter (standard 10 attempts)

rhst: 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 %00000001 ; Mask off error bit
JP Z,rdcont ; Continue if no error
DJNZ rhst ; 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
RET

rdcont:
LD C,4
LD HL,hstbuf
rd4secs:
LD B,128
rdByte:
CALL CF_DAT_RDY
IN A,(CF_DATA)
LD (HL),A
INC HL
DEC B
JR NZ, rdByte
DEC C
JR NZ,rd4secs
POP HL
POP BC
POP AF
XOR A
LD (erflag),A
RET

durgadas311
January 8th, 2018, 08:40 AM
That looks good.

durgadas311
January 8th, 2018, 02:57 PM
I found a specification for the CF card standard, and based on that it looks like WRITE protocol is:


wait not busy
issue WRITE command
[CF card sets BSY]
[CF card sets DRQ]
[CF card clears BSY]
wait for not busy and DRQ
write each byte, waiting for DRQ each time
on last byte:
[CF card sets BSY and clears DRQ]
[CF card writes/commits data to Flash]
[CF card clears BSY and sets error if needed]
wait for not busy
check error...

nockieboy
January 9th, 2018, 01:43 AM
Thanks durgadas311 - that's a big help. Here's my updated write routine which I'm not 100% sure about. The error checking seems slightly unwieldy due to the use of a static var (can't use B as it's used as an index for the sectors):


err_count: .ds 1 ; Write error counter

writehst:
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

LD C,4
LD HL,hstbuf
wr4secs:
LD B,128
wrByte:
; Wait for NOT busy AND DRQ
CALL CF_DAT_RDY
; Write the byte
LD A,(HL)
OUT (CF_DATA),A
; Error checking
CALL CF_DAT_RDY
IN A,(CF_STATUS) ; Read status
AND %00000001 ; Mask off error bit
JP Z,wcont ; Continue if no error
; Error - loop if retries remain
LD A,(err_count)
DEC A
LD (err_count),A
JP NZ,wrByte ; Try again
; Error handling
CALL printInline ; Out of lives - show an error
.DB CR,LF
.TEXT "Error writing byte!"
.DB 0
LD A,$01 ; Return to BDOS with error code 1 - Unrecoverable error
LD (erflag),A
RET

wcont:
LD A,$0A
LD (err_count),A ; Refresh error retries

INC HL
DEC B
JR NZ, wrByte

DEC C
JR NZ,wr4secs

POP HL
POP BC
POP AF
XOR A
LD (erflag),A
RET

durgadas311
January 9th, 2018, 04:51 AM
Some notes.

A) You don't need to save AF in writehst, because the return value is in A - so A is always destroyed. You could save DE giving you more registers, without taking any more stack.

B) It's not clear from the spec, but your code is checking error on every byte, and then retrying *that byte*. I don't think that is correct. I think you must do all 512 bytes, then check error and retry the whole command.

C) Even though you can't use OTIR, because of the need to check DRQ, you could use OUTI which does not use A - giving you that register for other purposes (retry count?). But, that does require use of B and C differently, so maybe not much help.

nockieboy
January 9th, 2018, 06:06 AM
Okay, quick swap around during a break - here's the updated function: (apologies for the lack of formatting)


err_count: .ds 1 ; Write error counter

writehst:
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

LD C,4
LD HL,hstbuf
wr4secs:
LD B,128
wrByte:
; Wait for NOT busy AND DRQ
CALL CF_DAT_RDY

; Write the byte
LD A,(HL)
OUT (CF_DATA),A

INC HL
DEC B
JR NZ, wrByte ; Next byte

DEC C
JR NZ,wr4secs ; Next 4 sectors

; All 512 bytes are done - error check

; Error checking
CALL CF_DAT_RDY
IN A,(CF_STATUS) ; Read status
AND %00000001 ; Mask off error bit
JP NZ,werr ; Jump to werr if error

POP HL ; Otherwise continue and exit
POP BC
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

durgadas311
January 9th, 2018, 06:18 AM
One last thing, I don't think you can use "CF_DAT_RDY" after the 512th byte, as there will be no DRQ in that case. Only a BSY cycle.

nockieboy
January 9th, 2018, 07:03 AM
One last thing, I don't think you can use "CF_DAT_RDY" after the 512th byte, as there will be no DRQ in that case. Only a BSY cycle.

Ah okay, so I've just replaced:


; All 512 bytes are done - error check

; Error checking
CALL CF_DAT_RDY

with:


; All 512 bytes are done - error check

; Error checking
CALL CFWAIT

to cover that.

nockieboy
January 9th, 2018, 08:11 AM
All works okay, no errors coming up in normal usage and no noticeable performance hit. CP/M is still playing up though - can't load CP/M 3, can't copy files bigger than 8KB, some programs I've found just aren't working (like Zork on C: ) which were fine before the recent crashes and loss of data from A: drive. I've ordered a couple of 'new' CF cards via the usual source (Shenzhen-bay!) - should be with me in a month or two. In the meantime, I'll whip the CF card out and format it on the PC and see if there's any problems with it there before formatting it on the SBC and starting it up from scratch again.

Anyway, at least my Z80 isn't hit too badly by Meltdown and Spectre. ;)

daver2
January 10th, 2018, 05:57 AM
I am not too convinced whether CFWAIT (waiting for the BUSY bit to become FALSE) is of any value at all. The BUSY bit should be used in conjunction with other bits (e.g. the READY, DRQ or ERR bits); not on its own.

As I understand it, BUSY being '1' just means that the Compact Flash itself has control of the status register and the other bits are unreadable at this time.

The first thing that a WAIT for (say) the DRQ bit should do is spinlock on the BUSY bit to make sure it is FALSE and then check the status bit of interest (in this case the DRQ bit). Sitting waiting for this condition could be asking for trouble - hence the requirement for a timeout exit with an error if waiting too long.

My logic would be to wait for the CF card to become READY (BUSY='0', RDY='1' - or a timeout).

Load up any parameters and initiate the command (say READ SECTOR).

DO {

Wait for the DRQ bit in the loop (BUSY='0', DRQ='1' - or a timeout) !OR! the ERR bit to be set (BUSY='0', ERR='1' - or a timeout).

Transfer a BYTE of information.

}

Wait for the command to complete (BUSY='0', RDY='1' - or a timeout).

Check the error condition (BUSY='0', ERR='1' - or a timeout).

Note that I haven't included any processing for the timeout or error conditions in the above pseudo-code.

Note the last check for the error bit - it needs to also include the check for BUSY='0', hence your code of:


; Error checking
CALL CF_DAT_RDY
IN A,(CF_STATUS) ; Read status
AND %00000001 ; Mask off error bit
JP NZ,werr ; Jump to werr if error

may not actually do what you expect...

The "IN A,(CF_STATUS)" is not protected against the CF setting the BUSY bit and (in the process) invalidating your read of the ERR bit!

You would need to spinlock waiting for BUSY='0' and then to test the resulting register read for the ERR bit being set. You can't just re-read the CF status register.

Don't forget that you don't have to AND the value just read with a MASK just to check a bit. The Z80 has the non-destructive BIT TEST instructions; so the value in register A after the bit test for BUSY='0' can be preserved so that you can go on to perform tests on other bits (i.e. if your CFWAIT routine just bit tested and waited for BUSY='0' and returned with A containing the status register - then you could directly test the returned value for the ERR bit being set without having to read it again).

Hope this makes sense?!

Dave

durgadas311
January 10th, 2018, 09:34 AM
Do we have any idea why why the "corruption" or loss of disk content occurs? That might be an important clue as to what is going on.

nockieboy
January 10th, 2018, 10:24 AM
Brief update.

It seems CP/M had suffered from some corruption as a result of the previous crashes involving CP/M 3. I've checked the CF card for errors in Windows - found none (though I know that's hardly a foolproof method but I consider it an indicator of health to a degree) - reformatted the drive and reinstalled CP/M 2.2 on it.

It seems CP/M 2.2 (and associated CBIOS64 with the updated CF read and write routines) is solid. I've copied entire directories, compiled CPM3.SYS, messed around trying to get Wordstar to display properly in PuTTY (Whoah! That's not a user-friendly setup experience! Got nowhere fast with that...) and done various things to try and get it to fall over, but it's survived everything I can through at it.

However, when I try running the compiled CP/M 3 things fell apart (I haven't updated BIOS3 with the new CF card read/write functions yet, though) - I tried to get PIP to copy a file - it did exactly what it did before. Then I realised I was using CP/M 2.2's PIP, so downloaded the CP/M 3 version which is slightly larger and called it PIP3. Tried using that and just got an error message every time. Then it crashed and took CP/M 2.2 with it - it wouldn't boot properly after that, only occasionally getting to the prompt but falling over the minute I ran any program. So I had to reformat and reinstall again.

Sorry I can't provide any more detailed error messages etc - I was focused entirely on getting (any version of) CP/M running again. Now I'm happy 2.2 is stable, I'll start looking at updating the BIOS3 with the new read/write routines.

durgadas311
January 10th, 2018, 11:28 AM
Perhaps there is somethign wrong with the CP/M 3 CF I/O routines. Maybe the LBA computation is broken and causing wrong parts of the disk to get written?

durgadas311
January 10th, 2018, 11:30 AM
Also, things like PIP.COM that differ between CP/M2 and CP/M3 are a good reason to have a separate system disk for CP/M 3 vs. CP/M 2.2. While CP/M 2.2 utilities should run on CP/M 3, there may be ones that don't work right. Especially beware of things like SYSGEN.

daver2
January 10th, 2018, 11:39 AM
You just beat me to it again...

Yes, if drive A: is your CP/M 2.2 drive A: and it is also your CP/M 3 drive A: then you will be in for a nasty surprise at times as you may have just found with PIP.

Suggest adding 'n' to your LBA numbers for your CP/M 3 system (where 'n' is the number of LBs occupied by your CP/M 2.2 A: drive) - thus keeping CP/M 3 separate from your CP/M 2.2. Of course - using this scenario - CP/M 2.2 can still write to your CP/M 3 A: drive as drive B:...

Dave

durgadas311
January 10th, 2018, 01:24 PM
I think I see the problem. "setLBAaddr" is broken, in both CBIOS64.ASM and BIOS3.ASM. One of the problems is that I broke it differently, so CP/M 3 does not match CP/M 2.2. But, both are wrong.

You have defined your disk geometry to be 8 partitions ("disks") of 2048 "tracks" with each track being 16K bytes (or 128 CP/M records, or 32 blocks of 512 bytes). With tracks numbering from 0 to 20147, that requires 11 bits in "hsttrk". But your "setLBAaddr" routine assumes only 9 bits and so you have, for example, the first tracks of B: overlapping the last tracks of A:. When I gratuitously rewrote "setLBAaddr", I did a exclusive replace of the high two bits of the track with the disk number, whereas your CP/M 2.2 BIOS does an ADD. Both are incorrect, but the difference is likely what causes CP/M 3 to really mess things up. I guess this would mostly come into play when accessing disks other than A:. I'm not sure I can reason out exactly how this causes what you see, but it certainly needs to be fixed. With a new "setLBAaddr" routine, you are going to have to reformat (at least in CP/M terms) the CF image, as the start of each "disk" will now be different.

I'll spend a little time on a corrected "setLBAaddr" routine, and post back here.

durgadas311
January 10th, 2018, 01:33 PM
Correction: I guess the CP/M 2.2 routine just strips off bits 10 and 11, which means that if you get past the first 1/4 of the disk you start writing over the directory... So, that means when you start filling up the disk with CP/M 3 files, you trash your boot track and directory... Maybe that explains everything...

nockieboy
January 10th, 2018, 01:41 PM
Perhaps there is somethign wrong with the CP/M 3 CF I/O routines. Maybe the LBA computation is broken and causing wrong parts of the disk to get written?

There is definitely something wrong with the CF I/O. I haven't had the time to do any testing today other than compiling CPM3 and running it once to find it then crashed the system. Maybe tomorrow I'll have more time to go through the process again and take notes as I go for a more detailed report. Before I do that though I'll add the CF routine changes we've talked about so far to BIOS3.


Also, things like PIP.COM that differ between CP/M2 and CP/M3 are a good reason to have a separate system disk for CP/M 3 vs. CP/M 2.2. While CP/M 2.2 utilities should run on CP/M 3, there may be ones that don't work right. Especially beware of things like SYSGEN.

Yes, I found this out with LINK. The version I have with CP/M 2.2 definitely isn't the same program as the LINK I have from my CP/M 3 archive. It's a completely different program. Still, this is partly to be expected I guess - I'm aware there will be some issues running CP/M 3 in 2.2, but I don't imagine it should cause any issues for CP/M 3 running older 2.2 programs. I DO use GENCPM in 2.2 which is from the CP/M 3 disks, though.


Yes, if drive A: is your CP/M 2.2 drive A: and it is also your CP/M 3 drive A: then you will be in for a nasty surprise at times as you may have just found with PIP.

Suggest adding 'n' to your LBA numbers for your CP/M 3 system (where 'n' is the number of LBs occupied by your CP/M 2.2 A: drive) - thus keeping CP/M 3 separate from your CP/M 2.2. Of course - using this scenario - CP/M 2.2 can still write to your CP/M 3 A: drive as drive B:...

Dave

I thought re-assigning drives (or remapping or whatever term you want to call it) would be a PITA but this method sounds quite straight forward..

nockieboy
January 10th, 2018, 01:44 PM
Correction: I guess the CP/M 2.2 routine just strips off bits 10 and 11, which means that if you get past the first 1/4 of the disk you start writing over the directory... So, that means when you start filling up the disk with CP/M 3 files, you trash your boot track and directory... Maybe that explains everything...

Missed your posts durgadas311 whilst I was working and putting my one together! That sounds VERY promising...

durgadas311
January 10th, 2018, 01:47 PM
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!


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.

durgadas311
January 10th, 2018, 02:01 PM
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...

durgadas311
January 10th, 2018, 02:02 PM
Ugh, I'm going to stop guessing and spend more time thinking... you have 4K allocation blocks... never mind...

durgadas311
January 10th, 2018, 02:15 PM
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.

durgadas311
January 10th, 2018, 02:20 PM
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.

nockieboy
January 11th, 2018, 01:36 AM
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:


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):


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:


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:


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


and in CP/M 3:


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:
42946

I haven't got around to modifying the CF_WAITs in the read/write functions yet.

durgadas311
January 11th, 2018, 04:21 AM
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.

durgadas311
January 11th, 2018, 04:25 AM
Oh, and the "No CCP.COM" message may have to do with lack of a "seldsk" call in wboot...

nockieboy
January 11th, 2018, 05:15 AM
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:


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):


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:


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:


;================================================= ===============================================
; 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:


LD A,0
CALL seldsk

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


A>stat D:

Bytes Remaining On D: 3972k
BIOS Error on A: No CCP.COM file

durgadas311
January 11th, 2018, 05:25 AM
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.

durgadas311
January 11th, 2018, 06:08 AM
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).

Plasmo
January 11th, 2018, 07:49 AM
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.

durgadas311
January 11th, 2018, 08:32 AM
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].

nockieboy
January 11th, 2018, 08:59 AM
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?


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

They're already zeroed?

nockieboy
January 11th, 2018, 09:35 AM
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. :)

daver2
January 11th, 2018, 09:43 AM
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

nockieboy
January 11th, 2018, 11:41 AM
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. ;)

durgadas311
January 11th, 2018, 12:22 PM
The 4 bytes that follow the name are the ones to clear. FCB+12 through FCB+15, if my math is correct.

nockieboy
January 11th, 2018, 12:52 PM
The 4 bytes that follow the name are the ones to clear. FCB+12 through FCB+15, if my math is correct.

Thanks durgadas - when should it be cleared?

durgadas311
January 11th, 2018, 12:59 PM
Before attempting to open the file.

Plasmo
January 11th, 2018, 08:24 PM
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.

nockieboy
January 12th, 2018, 02:48 AM
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:


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:


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
:213E0111800019F9211701CD1B013E0FD3380E00CD0500255 22324F57EFE24CA2901CD2B0123C31C01F1C9F5CD350128FBF 1D301C997D303DB030FCB4FC90000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 0000000>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.

durgadas311
January 12th, 2018, 03:56 AM
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.

durgadas311
January 12th, 2018, 04:01 AM
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.

nockieboy
January 12th, 2018, 04:23 AM
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:


;================================================= ===============================================
; 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):


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

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

Plasmo
January 12th, 2018, 04:37 AM
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.

durgadas311
January 12th, 2018, 05:05 AM
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: ?

nockieboy
January 12th, 2018, 05:54 AM
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):


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:


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

durgadas311
January 12th, 2018, 06:21 AM
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).

daver2
January 12th, 2018, 07:18 AM
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

durgadas311
January 12th, 2018, 07:53 AM
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.

nockieboy
January 12th, 2018, 08:25 AM
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:


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: 42986

EDIT: Yes, I use version control but my project is being held on Bitbucket (https://bitbucket.org/nockieboy/z80_minicomp). (It's private so you'll need to have a Bitbucket account for me to give you access.)

Alphasite
January 12th, 2018, 08:27 AM
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.

durgadas311
January 12th, 2018, 09:43 AM
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.

daver2
January 12th, 2018, 10:46 AM
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

nockieboy
January 12th, 2018, 11:04 AM
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?

daver2
January 12th, 2018, 11:28 AM
Edinburgh...

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

Dave

nockieboy
January 12th, 2018, 01:34 PM
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. :)

daver2
January 12th, 2018, 02:17 PM
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

durgadas311
January 12th, 2018, 05:01 PM
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?

Alphasite
January 12th, 2018, 07:46 PM
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.

Never mind, I was looking at my reload code which moves from a bank instead of re-reading.

For re-reading I just clear three bytes, ccp$fcb+12 and fcb$nr:



xor a ; zero extent
ld (ccp$fcb+15),a
ld hl,0 ; start at beginning of file
ld (fcb$nr),hl
...
ccp$fcb: db 1,'CCP ','COM',0,0,0,0
ds 16
fcb$nr: db 0,0,0

nockieboy
January 13th, 2018, 03:34 AM
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?

1) MMU active, when low, disables output from the MMU (I actually don't use it, tbh) It's so that you can set up an entire re-map of the Z80's address space in one hit, without doing it 'area by area'. So long as it's low, you can essentially ignore it.

2) Yes, that's correct. ORG is 0000H, but it's loaded into Bank 15 (3C000h) in the ROM which is mapped to Area 0 at power-on.

3) No, neither the PIO or CTC are needed for the emulation. The CTC provides a 1Hz clock for the UPTIME command, but nothing will break without the CTC being implemented. The PIO isn't used at all right now - I need to update the readme regarding that as I originally intended to implement an I2C interface with it, but went the way of integrating an ATmega328 instead to do that and more.

4) You can get by without SIO Port B entirely. It provides communication with the ATmega328, but it's controlled by the Z80 and data only comes down it if the Z80 has requested it. That's basically the clock speed (2/4/8 ASCII char) to manage the baud rate of SIO Port A (you've seen the code for this already in CBIOS64 for CP/M 2.2) but it defaults to 4 MHz if no value is returned anyway. The only other data at the moment is the date and time string for the DATETIME command.

5) From top to least priority: CTC, PIO, SIO

EDIT: Should also explain - all the relevant code is in Z80_Minicomp / Z80 Minicomp v2 / Code /

daver2
January 13th, 2018, 08:11 AM
I had a few minutes to look through the latest code.

I notice that lba0, lba1, lba2 and lba3 are in BIOS BANKED memory (below the DSEG line) but that the specific bank is not set-up when read or write is called. Read and Write calls setLBAaddr (which does a load of maths and stores the value sin lba0..lba3) and then sends the values calculated to the CF registers. It will send the correct data to the CF registers that it calculated - but where did it store the intermediate values in memory of lba0..lba3? If the correct bank (for BIOSBNK) is not in force at the time of the call to setLBAaddr - won't this potentially corrupt four bytes of something?

I would suggest moving lba0..lba3 before DSEG (i.e. into BIOS common memory - CSEG) and redo the testing.

I have also noticed a few other coding points - but they are not relevant to the problem in hand so they can wait until this issue is resolved.

I still don't like using INIR and OTIR to transfer the data without checking DRQ before transferring each byte.

Dave

durgadas311
January 13th, 2018, 09:49 AM
I notice that lba0, lba1, lba2 and lba3 are in BIOS BANKED memory (below the DSEG line) but that the specific bank is not set-up when read or write is called. Read and Write calls setLBAaddr (which does a load of maths and stores the value sin lba0..lba3) and then sends the values calculated to the CF registers. It will send the correct data to the CF registers that it calculated - but where did it store the intermediate values in memory of lba0..lba3? If the correct bank (for BIOSBNK) is not in force at the time of the call to setLBAaddr - won't this potentially corrupt four bytes of something?


NOTE: read/write are always called, in CP/M 3, with bank 0 selected. There should be no problem with lda0-3 being in banked memory, as long as they are used before the switch to dmaBank.

durgadas311
January 13th, 2018, 09:51 AM
It appears that the DMI ROM code requires something "intelligent" be connected to the SIO B port. It tries to get the clock speed from whatever is connected there. Do you have a description of the commands and actions that are executed by that object on SIO B port?

nockieboy
January 13th, 2018, 10:15 AM
It appears that the DMI ROM code requires something "intelligent" be connected to the SIO B port. It tries to get the clock speed from whatever is connected there. Do you have a description of the commands and actions that are executed by that object on SIO B port?

Yes durgadas311, the ATmega328 is connected to that port. At the moment, you don't need to emulate anything coming back on Port B - it's used to get the system clock speed (provided by the '328 ) so that an appropriate divider can be set for Port A and maintain a constant 125000 baud for the PC terminal, irrespective of the system clock the Z80 is running at. Just make Port B return a string, "%S4#", in response to the %S query from the Z80 to tell the DMI that the board is running at 4MHz. Any other data returned via Port B is to do with the DATETIME command which, if you don't use that command, won't matter and isn't necessary.

durgadas311
January 13th, 2018, 11:44 AM
OK, I was able to get a basic virtual machine running the monitor ROM. I'll get a CP/M image put on the CF card and see if I can boot CP/M 2.2. From there, I'll start trying to reproduce the CP/M 3 problems you are seeing.

durgadas311
January 13th, 2018, 11:45 AM
Any helpful instructions on how to putsys?

nockieboy
January 13th, 2018, 11:56 AM
Any helpful instructions on how to putsys?

PUTSYS is now part of the DMI as I integrated it into the ROM a few days back. The DMI command, INSTALL, now almost hand-holds you through the installation of CP/M. All you have to do is paste CPM22.HEX and CBIOS64.HEX at the prompts. It should do the rest.

To install, the following steps are needed in this order:

In the DMI, type INSTALL
Load CP/M into memory by pasting the contents of CPM22.HEX into the terminal window
Load CBIOS into memory by pasting the contents of CBIOS64.HEX (for 64MB Flash drives) or CBIOS128.HEX (for 128MB or larger drives) into the terminal window
INSTALL will then copy these files onto the CF drive
Once these steps are complete, CP/M is installed on the disk and can be booted from the DMI with the CPM command. Applications will then need to be installed, starting with the DOWNLOAD.COM program which will allow you to paste files directly into CP/M.

Next, install DOWNLOAD.COM:

Type CPM to boot into CP/M then soft/hard-reset the Minicom to return to the DMI (do NOT power off)
Type BANK 03,00 to map Area 3 of memory to Bank 0 in RAM
Copy DOWNLOADC100.HEX into memory using RHEX (type RHEX and paste the file contents into the terminal)
Type CPM to switch back to CP/M
At the prompt, type SAVE 2 DOWNLOAD.COM to save the program in memory as DOWNLOAD.COM
Hey presto! You can now copy and paste the Transient Program Packages supplied in the project into the CP/M terminal window.

If it doesn't work (and it just occurred to me that I haven't actually tested it as far as writing to Sector 0 as it's such a recent addition) then you can do it manually. Type RHEX, paste CPM22.HEX, then type RHEX and paste CBIOS64.HEX, then type RHEX and paste PUTSYS.HEX. Finally, type CALL 5000 and Bob's your uncle. :)

durgadas311
January 13th, 2018, 12:57 PM
Thanks. Turns out it's pretty easy to load things onto the virtual CF card using "cpmtools", also.

I'm making good progress, but not getting the same problem as you saw. I'll keep working out the kinks in my simulation.

FYI, I'm getting this:


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

BNKBIOS3 SPR F400 0C00
BNKBIOS3 SPR AC00 1400
RESBDOS3 SPR EE00 0600
BNKBDOS3 SPR 7E00 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


CP/M Error On I: Invalid Drive
BDOS Function = 98
CP/M Error On I: Invalid Drive
BDOS Function = 98
...ad-nausium...

daver2
January 13th, 2018, 01:08 PM
If the problem is related to 'random' memory contents in the 'real' implementation; if you run it in a software simulation you may find that the memory contents are the same and repeatable - so you get one type of failure mode only.

If that's what you are trying to do of course - it is getting a little late in the UK so I should really stop writing the disassembler I am working on until tomorrow...

Dave

durgadas311
January 13th, 2018, 05:11 PM
Just a status update, at quitting time. The error I am seeing is because something has corrupted the BDOS "login vector", telling it that drive I: is active even though that drive doesn't exist. I was able to track down what I think is the memory address of the BDOS 'dlog' variable (login vector), and do some tracing. It appears that something is using that location as a counter. I'll have to spend some more time figuring out who is doing that.

ADDENDUM: It appears that the last page(s) of the BNKBDOS3 are overlapping with the first page(s) of the BNKBIOS3. I have no clue how LINK.COM could allow that to happen. At this point I am suspicious that it is something to do with these "foreign" assemblers producing REL files that might not be 100% compatible with CP/M.

SOLVED: This problem was due to me using a custom BNKBDOS3.SPR, from the old days - not sure why we did that, but it places the login vector in the BIOS (I assume because the MMS BIOS needed it). Now, I'm seeing problems when reloading the CCP. Looks like I can now attack that problem you are seeing.

nockieboy
January 14th, 2018, 12:10 AM
Just a status update, at quitting time. The error I am seeing is because something has corrupted the BDOS "login vector", telling it that drive I: is active even though that drive doesn't exist. I was able to track down what I think is the memory address of the BDOS 'dlog' variable (login vector), and do some tracing. It appears that something is using that location as a counter. I'll have to spend some more time figuring out who is doing that.

ADDENDUM: It appears that the last page(s) of the BNKBDOS3 are overlapping with the first page(s) of the BNKBIOS3. I have no clue how LINK.COM could allow that to happen. At this point I am suspicious that it is something to do with these "foreign" assemblers producing REL files that might not be 100% compatible with CP/M.

SOLVED: This problem was due to me using a custom BNKBDOS3.SPR, from the old days - not sure why we did that, but it places the login vector in the BIOS (I assume because the MMS BIOS needed it). Now, I'm seeing problems when reloading the CCP. Looks like I can now attack that problem you are seeing.

Well done. :) Out of interest, what are you using to emulate the system and did it take much to set it up?

durgadas311
January 14th, 2018, 03:37 AM
Well done. :) Out of interest, what are you using to emulate the system and did it take much to set it up?

I have been doing various machine simulations in JAVA for some time now. I had a working Z80-SIO, Z80-PIO, and Z80-CPU, and from the Kaypro simulation I had a WD1002-05 disk controller that was nearly identical to the CF card interface, and from the H8/H89 simulation I had a similar MMU to yours. So, it took a little cloning and cobbling but it came together fairly easily. I'll post it soon.

Now I am seeing two problems, which I think you also see. The crashes seem to be related to interrupts somehow getting enabled in CP/M 3, so "DI" is not sufficient. I had to disable interrupts at the SIO. The second is the problem in PIP:


B>pip d:=b:*.*

COPYING -
RMAC.COM
ERROR: CLOSE FILE NONRECOVERABLE - D:RMAC.$$$

B>

I also saw (what I believe is) the same problem from "HELP":


B>help
...
HELP UTILITY V1.1
...
HELP> (press ENTER)
CP/M Error On B: Disk I/O
BDOS Function = 16 File = HELP .HLP
B>

Because PIP changes the BDOS error mode, that case shows us a message generated by PIP, which is a bit cryptic. HELP uses the default BDOS error mode, so we see the BDOS message which we can interpret more easily.

I examined the CF image after the failed PIP command, and saw that the first file did actually get copied fully. PIP must do some cleanup after the error, erasing the temporary file. But, the PIP did completely write all data blocks and update the directory entry with allocation blocks and number of records. So, BIOS writes are actually working. I'll need to look at what other actions the BDOS CLOSE operation takes, and see if I can figure out how an error is being returned. Since the BIOS prints a message on read/write errors from the CF card, there must be something else going on to cause the error.

durgadas311
January 14th, 2018, 04:01 AM
FYI, what I am using to simulate this machine is posted here: http://sebhc.durgadas.com/misc/

The JAR file is the simulation and the current DMI ROM image. This simulation must be run in a "terminal window" as it uses the programs "stdio" as the console (SIO channel A). That presents some problems due to normal Linux TTY input buffer modes. The "CF" file is the disk image I am currently using (bootable, has some CP/M 2.2 files on A: and the CP/M 3 loader, then B: contains CP/M 3 programs and the REL files) and this file should be in the current directory when running the JAR. The "run" file is a Linux shell script to fixup the console input modes and run the JAR. This also restores the TTY modes after the JAR completes, so that is handy.

The "diskdefs" files contains "cpmtools" disk definitions to access the "CF" file image using cpmtools. The definitions are named "cfa" for drive A:, "cfb" for B:, etc. I have only used (i.e. tested) A: and B: so far.

durgadas311
January 14th, 2018, 05:05 AM
I found "the last bug" (I also have a bridge in Brooklyn for sale...)... The BIOS "flush" function has to return a status code. I changed it to return "0" since it is a no-op. Here's my current diffs:


diff --git a/Z80 Minicomp v2/Code/BIOS3.ASM b/Z80 Minicomp v2/Code/BIOS3.ASM
index b0ac36e..540e87d 100644
--- a/Z80 Minicomp v2/Code/BIOS3.ASM
+++ b/Z80 Minicomp v2/Code/BIOS3.ASM
@@ -268,14 +268,16 @@ INTVEC: .DW serialInt ; Location of Z80 IM2 interrupt vector(s)
sioAi: .db $00,$18 ; Ch RESET
.db $04,$84 ; BAUD - replaced at runtime
sioAb: .equ $-1
- .db $01,$18 ; Trigger INTerrupt on Rx
+;;; .db $01,$18 ; Trigger INTerrupt on Rx
+ .db $01,$00 ;;; for debug
.db $03,$E1 ; Rx 8 bits/char, Rx enable
.db $05,RTS_LOW ; DTR, Tx 8 bits/char, Tx enable
sioAz: .equ $-sioAi

sioBi: .db $00,$18 ; Ch RESET
.db $04,$C4 ; BAUD - CLK/64
- .db $01,$18 ; Trigger INTerrupt on Rx
+;;; .db $01,$18 ; Trigger INTerrupt on Rx
+ .db $01,$00 ;;; for debug
.db $02,$00 ; INT vector (LO byte) - the $00 is overwritten later
.db $03,$E1 ; Rx 8 bits/char, Rx enable
.db $05,RTS_LOW ; DTR, Tx 8 bits/char, Tx enable
@@ -333,7 +335,8 @@ multio:
RET ; anything?

flush:
- RET ; anything?
+ XOR A,A ; success
+ RET

time:
RET ; anything?

Naturally, as I was testing this out I ran into this again:


B>show

A: RW, Space: 8,028k
B: RW, Space: 7,732k
C: RW, Space: 8,176k


BIOS Error on A: No CCP.COM file

So, it's not all good yet. I'll keep poking...

Plasmo
January 14th, 2018, 05:10 AM
Now I am seeing two problems, which I think you also see. The crashes seem to be related to interrupts somehow getting enabled in CP/M 3, so "DI" is not sufficient. I had to disable interrupts at the SIO.

I have a similar problem with disabling of interrupts in CP/M68K. The instruction "move.w #$2700,sr" (masking off all interrupts to 68000) is not sufficient such that when trace an instruction in DDT, the interrupts are turn back on. I also have to turn off interrupt generation in the source devices.

durgadas311
January 14th, 2018, 05:38 AM
I was able to reproduce the "No CCP" error whenever I access any of drives C: thru H: and then do a warm boot (reload CCP). Seems like something related to logging in one of those drives cause some level of corruption. Drive B: houses all the CP/M 3 utilities, so I always need to log in that drive. However, after accessing B: I never see a problem reloading CCP. Only access one of C: thru H: does it happen. My first thought is the ALV but I don't see a problem with that, or a way for that to overflow enough to hit BDOS or the ccp$fcb. In fact, I can examine the ccp$fcb after this error and it looks OK.


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

BNKBIOS3 SPR F400 0C00
BNKBIOS3 SPR AC00 1400
RESBDOS3 SPR EE00 0600
BNKBDOS3 SPR 7E00 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>b:
B>dir g:
No File
B>show

A: RW, Space: 8,060k
B: RW, Space: 7,732k
G: RW, Space: 8,176k


BIOS Error on A: No CCP.COM file

durgadas311
January 14th, 2018, 05:40 AM
Note on my simulation: due to a problem with JAVA interpreting ^C on stdin, if you want to pass a ^C to the simulation (CP/M) you need to use ^A (this will be converted to ^C on the SIO port).

I have also just now updated the "CF" image to reflect the latest.

durgadas311
January 14th, 2018, 07:06 AM
Now I've found "the last bug"... The problem loading CCP was due to the FCB specifying the current drive (00) as the place to look for CCP.COM. If I change that to hard-code drive A: (01) then it seems to work fine. This requires that (whatever is) drive A: must contain CCP.COM, but that can be dealt with I suspect.

The reason it only broke after looking at some drive other than A: and B: was that, in my system, both A: and B: contain a copy of CCP.COM (while all other drives do not). So, it seems that SHOW (and probably other utils) leave the currently selected drive as the last drive accessed. So, it would work as long as the last drive accessed was one that contained CCP.COM.

So, the fix is to change the first byte of "ccp$fcb" from 0 to 1, to indicate that drive A: is where CCP.COM will be.

It's possible this would work if we had setup a search path for COM files that included drive A:. The default is to only search the current drive. Of course, if we eventually load the CCP into memory and never re-read the file on warm boot, the problem also disappears.

nockieboy
January 14th, 2018, 07:17 AM
I found "the last bug" (I also have a bridge in Brooklyn for sale...)... The BIOS "flush" function has to return a status code. I changed it to return "0" since it is a no-op.

Haha! What's your name? George C. Parker?! ;) Well done though - that's another one to cross off the Möbius strip-like list. (Thanks for making me look up the Brooklyn bridge phrase, by the way - just goes to show you never stop learning!) :)


FYI, what I am using to simulate this machine is posted here: http://sebhc.durgadas.com/misc/

The JAR file is the simulation and the current DMI ROM image. This simulation must be run in a "terminal window" as it uses the programs "stdio" as the console (SIO channel A). That presents some problems due to normal Linux TTY input buffer modes. The "CF" file is the disk image I am currently using (bootable, has some CP/M 2.2 files on A: and the CP/M 3 loader, then B: contains CP/M 3 programs and the REL files) and this file should be in the current directory when running the JAR. The "run" file is a Linux shell script to fixup the console input modes and run the JAR. This also restores the TTY modes after the JAR completes, so that is handy.

The "diskdefs" files contains "cpmtools" disk definitions to access the "CF" file image using cpmtools. The definitions are named "cfa" for drive A:, "cfb" for B:, etc. I have only used (i.e. tested) A: and B: so far.

Ah thanks for sharing that. Will have to warm up my Ubuntu VM and see if I can get it working - or if I feel really adventurous, try it in Windows.


I have a similar problem with disabling of interrupts in CP/M68K. The instruction "move.w #$2700,sr" (masking off all interrupts to 68000) is not sufficient such that when trace an instruction in DDT, the interrupts are turn back on. I also have to turn off interrupt generation in the source devices.

Yes, I think there's clearly something in BDOS, the CCP or even one of the programs like PIP etc that is turning interrupts back on.


I was able to reproduce the "No CCP" error whenever I access any of drives C: thru H: and then do a warm boot (reload CCP). Seems like something related to logging in one of those drives cause some level of corruption. Drive B: houses all the CP/M 3 utilities, so I always need to log in that drive. However, after accessing B: I never see a problem reloading CCP. Only access one of C: thru H: does it happen. My first thought is the ALV but I don't see a problem with that, or a way for that to overflow enough to hit BDOS or the ccp$fcb. In fact, I can examine the ccp$fcb after this error and it looks OK.

Was CP/M always this difficult to set up for new hardware in the old days, or is this a 'special feature' of trying to do it with a modern DIY computer?

daver2
January 14th, 2018, 07:51 AM
Nice bit of debugging there Sherlock!

>>> Was CP/M always this difficult to set up for new hardware in the old days, or is this a 'special feature' of trying to do it with a modern DIY computer?

Neither. I would have said it is as a result of trying to learn something new without supervision from a more qualified source. I can expand on this in a PM if you like.

It has been a great journey though. I implemented a 2.2 port back in the days - but I left the world of CP/M behind. I often wondered about CP/M 3 - so this thread has been a good excuse to read-up on the requirements for getting CP/M 3 up and running. I might also have a look at MP/M as well shortly... That was something else I was interested in back in the day...

Dave

SteveH
January 14th, 2018, 08:38 AM
I still don't like using INIR and OTIR to transfer the data without checking DRQ before transferring each byte.


Hi Dave, What's wrong with using INIR and OTIR? I cannot see anything in either the IDE or CF specification that specifies DRQ needs checking before transfering each byte, only sectors. My copy of the CF specs simply state the following for Read Sectors:

http://rumkin.com/reference/aquapad/media/cfspc3_0.pdf
6.2.1.18 Read Sector(s) - 20h or 21h
This command reads from 1 to 256 sectors as specified in the Sector Count register. A sector
count of 0 requests 256 sectors. The transfer begins at the sector specified in the Sector Number
Register. When this command is issued and after each sector of data (except the last one) has
been read by the host, the CompactFlash Storage Card sets BSY, puts the sector of data in the
buffer, sets DRQ, clears BSY, and generates an interrupt. The host then reads the 512 bytes of
data from the buffer.
At command completion, the Command Block Registers contain the cylinder, head and sector
number of the last sector read. If an error occurs, the read terminates at the sector where the
error occurred. The Command Block Registers contain the cylinder, head, and sector number of
the sector where the error occurred. The flawed data is pending in the sector buffer.

Unless I've missed it somewhere else in the spec?

Steve

nockieboy
January 14th, 2018, 09:15 AM
Neither. I would have said it is as a result of trying to learn something new without supervision from a more qualified source. I can expand on this in a PM if you like.

Please do. Thing is, there aren't many tutorials about on this sort of thing. I've acquired some books over the Christmas period on Z80 assembly programming etc, but CP/M itself is a bit impenetrable when I'm trying to learn the subject matter and the language it's written in at the same time. It was only a few weeks ago I was asking you how to write a basic CP/M program, though. Thanks to the immense (and highly appreciated) help from durgadas311, yourself and others, I feel I'm getting close to having a fully-functional CP/M 3 OS on my home-grown computer. I'm really starting to think I need to finalise the hardware design and get it off a breadboard, though... It's a bit of a rat's nest of jumper wires!! Still, not a bad achievement for someone who doesn't do electronics OR programming for a day job! :rolleyes:


It has been a great journey though. I implemented a 2.2 port back in the days - but I left the world of CP/M behind. I often wondered about CP/M 3 - so this thread has been a good excuse to read-up on the requirements for getting CP/M 3 up and running. I might also have a look at MP/M as well shortly... That was something else I was interested in back in the day...

Dave

Certainly has been a great journey. :) Well I was always fascinated by how computers worked, both at the software and hardware level. I'd have loved to have done something like this back when I was a kid in the 80's - but costs (and information availability) were prohibitive back then as it was still fairly 'new' technology. Now it has matured (some would say into a retirement home - but the Z80 is still used in industry, apparently) it is cheap, relatively simple and ideal for experimentation - so here I am. It's wonderful to be able to talk to knowledgeable people such as yourselves who were doing this stuff professionally back in the days when I could only dream about doing this sort of thing. :)

Alphasite
January 14th, 2018, 09:15 AM
Now I've found "the last bug"... The problem loading CCP was due to the FCB specifying the current drive (00) as the place to look for CCP.COM. If I change that to hard-code drive A: (01) then it seems to work fine. This requires that (whatever is) drive A: must contain CCP.COM, but that can be dealt with I suspect.

The reason it only broke after looking at some drive other than A: and B: was that, in my system, both A: and B: contain a copy of CCP.COM (while all other drives do not). So, it seems that SHOW (and probably other utils) leave the currently selected drive as the last drive accessed. So, it would work as long as the last drive accessed was one that contained CCP.COM.

So, the fix is to change the first byte of "ccp$fcb" from 0 to 1, to indicate that drive A: is where CCP.COM will be.

It's possible this would work if we had setup a search path for COM files that included drive A:. The default is to only search the current drive. Of course, if we eventually load the CCP into memory and never re-read the file on warm boot, the problem also disappears.

That's what I do:



ccp$fcb: db 1,'CCP ','COM',0,0,0,0
ds 16
fcb$nr: db 0,0,0


I also set the search path to the default drive and then drive A: in the BIOS routine BOOT:



ld hl,@drchn ; get address of drive chain
ld (hl),0 ; first search default drive
inc hl ; point to second drive in chain
ld (hl),1 ; next search drive A
inc hl ; point to third drive in chain
ld (hl),0ffh ; end of search


Then I set the SYS attribute on files in A0: that I want to access no matter which drive and/or user I'm using. That doesn't really apply to CCP.COM since I have it hard-coded to A: and I copy it to RAM for reloading, but I have SYS set on CCP.COM anyway so I don't see it during a normal DIR.

nockieboy
January 15th, 2018, 01:51 AM
Well, I'm happy to confirm that CP/M 3 seems to be working fine now - at least as far as running most programs and PIP goes; I'm able to copy any size file to any drive without errors. :)

Next is to sort out polled IO and re-instate the interrupt-driven IO...

Plasmo
January 15th, 2018, 04:26 AM
Congratulation!
Very informative discussions. This will really help me bring up a Z80 (actually Z280) board in the near future. The knowledgeable & helpful experts I find here is truly impressive!

durgadas311
January 15th, 2018, 01:02 PM
I see a problem that you'll have when trying interrupts, which explains the crashes before when interrupts got enabled accidentally. The interrupt version of "const" does not need to push/pop HL, but the bug is in the interrupt version of "conin" where you never push HL but pop it before return (thus return to garbage PC). You need to push HL just before you use it, right after the "const" loop.

Here are the diffs for the fix (after re-enabling (un-commenting) the interrupt code):

diff --git a/Z80 Minicomp v2/Code/BIOS3.ASM b/Z80 Minicomp v2/Code/BIOS3.ASM
index a731fd4..738512c 100644
--- a/Z80 Minicomp v2/Code/BIOS3.ASM
+++ b/Z80 Minicomp v2/Code/BIOS3.ASM
@@ -815,6 +815,7 @@ conost:
conin:
CALL const
JR Z,conin
+ PUSH HL
LD HL,(serARdPtr)
INC HL
LD A,(serAend)
@@ -844,14 +845,11 @@ rtsA1:
; A = FFh if chars are available
;----------------------------------------------------------------------------------------------
const:
- PUSH HL
LD A,(serABufUsed)
OR A
- JR Z,dataAEmpty
+ RET Z ;dataAEmpty
XOR A
DEC A
-dataAEmpty:
- POP HL
RET



----

nockieboy
January 16th, 2018, 01:24 AM
I see a problem that you'll have when trying interrupts, which explains the crashes before when interrupts got enabled accidentally. The interrupt version of "const" does not need to push/pop HL, but the bug is in the interrupt version of "conin" where you never push HL but pop it before return (thus return to garbage PC). You need to push HL just before you use it, right after the "const" loop.

Holy cow, that was easy! Thanks durgadas311 - CP/M 3 is running happily with interrupt-driven IO now and the custom CP/M programs I'd written to communicate with the ATmega328 via SIO Port B are all working again. I can work on getting CP/M 3's TIME function working now...

Can I assume that if I start wanting to use timestamps on files then the disk format will have to change, or the files with timestamps will no longer be compatible with 2.2? Or will it just ignore the extra data?

EDIT: And will COPYSYS completely foul up my A: drive or will it make it so that I can boot straight into CP/M 3 from the DMI? Now I've got interrupt-driven IO in CP/M 3, I actually don't need CP/M 2.2 at all so I'll probably start working on a way to 'install' it from the DMI for a first-time setup and miss the CP/M 2.2 step entirely.

EDIT2: Also, XMOVE isn't implemented in the banked BIOS3. The documentation refers to DMA transfers - I'm assuming this requires a physical Z80 DMA chip (which are like hen's teeth) or is it referring to a software function?

durgadas311
January 16th, 2018, 03:19 AM
Can I assume that if I start wanting to use timestamps on files then the disk format will have to change, or the files with timestamps will no longer be compatible with 2.2? Or will it just ignore the extra data?
INITDIR.COM is the program to setup a directory for use with CP/M 3 features. It will move existing files as needed, and is backward compatible in the sense that CP/M 2.2 will ignore the extra data (and, of course, won't maintain timestamps or honor passwords). Use the HELP facility, it gives a fair amount if information.



EDIT: And will COPYSYS completely foul up my A: drive or will it make it so that I can boot straight into CP/M 3 from the DMI? Now I've got interrupt-driven IO in CP/M 3, I actually don't need CP/M 2.2 at all so I'll probably start working on a way to 'install' it from the DMI for a first-time setup and miss the CP/M 2.2 step entirely.
The COPYSYS.COM distributed with CP/M 3 must be customized to work with systems that are not SD 8" floppies. So, if COPYSYS were to be run as-is it would certainly destroy your boot tracks - unless you customize it. We had a long discussion about this before, your disk layout only supports one system image and so you lose some recovery abilities if you eliminate the CP/M 2.2 boot. We can look into changing your disk layout again.


EDIT2: Also, XMOVE isn't implemented in the banked BIOS3. The documentation refers to DMA transfers - I'm assuming this requires a physical Z80 DMA chip (which are like hen's teeth) or is it referring to a software function?
DMA chip or an MMU that supports direct bank-to-bank copies. However, XMOVE does not give you much on a system with only 2 banks of RAM. The only thing it would do is allow you to put the data disk buffers in bank 0 instead of common memory, making for a larger TPA. It would also allow a faster copy of CCP.COM to the TPA, if you were to keep a copy in bank 0.

durgadas311
January 16th, 2018, 04:04 AM
A word of warning on the BIOS TIME function. If you actually go get the data from your "RTC" (ATmega328 ) every time, the system performance will be terrible. Keep in mind that the TIME function is called every time the BDOS needs a timestamp for a file - not just when DATE.COM is run. Even with a direct-attached RTC chip, most systems would get the time/date from the RTC only at cold boot and then advance the CP/M time/date from a periodic interrupt.

nockieboy
January 16th, 2018, 06:07 AM
The COPYSYS.COM distributed with CP/M 3 must be customized to work with systems that are not SD 8" floppies. So, if COPYSYS were to be run as-is it would certainly destroy your boot tracks - unless you customize it. We had a long discussion about this before, your disk layout only supports one system image and so you lose some recovery abilities if you eliminate the CP/M 2.2 boot. We can look into changing your disk layout again.

Hmm... well, I'm finding CP/M 3 to be just as stable as CP/M 2.2 now (i.e. I haven't been able to crash it yet despite trying) so I'm thinking that it won't be such a bridge-burning exercise as it looked like it would be previously (and you'll still be able to sell your bridge in Brooklyn.) So long as I'm able to set up a simple system to install CP/M 3 onto a blank drive, like I have for 2.2 currently, then it won't be an issue.


DMA chip or an MMU that supports direct bank-to-bank copies. However, XMOVE does not give you much on a system with only 2 banks of RAM. The only thing it would do is allow you to put the data disk buffers in bank 0 instead of common memory, making for a larger TPA. It would also allow a faster copy of CCP.COM to the TPA, if you were to keep a copy in bank 0.

Ah, not worth bothering with at the moment then. However, I'm going to be upgrading the MMU soon to address up to 1MB of RAM. Whilst I won't physically have that amount of RAM on my breadboard (I can't swap the SRAM chip out without causing irreparable chaos!) it will certainly be there on the final PCB.


A word of warning on the BIOS TIME function. If you actually go get the data from your "RTC" (ATmega328 ) every time, the system performance will be terrible. Keep in mind that the TIME function is called every time the BDOS needs a timestamp for a file - not just when DATE.COM is run. Even with a direct-attached RTC chip, most systems would get the time/date from the RTC only at cold boot and then advance the CP/M time/date from a periodic interrupt.

Yep, that's one of the reasons for the 1 Hz clock on the CTC and wanting to get interrupts up and running in CP/M 3. :)

On a (hardware) tangent - I'm going to be upgrading the ATmega328 as my next task. It was only ever a 'proof of concept' to show myself that I could get a system clock and data to the Z80 on request. I'm looking to replace it with a (much) faster STM32F103C8 (ARM microprocessor at 72 MHz) and dropping the Port B serial interface entirely - my intention is for the STM32 to be able to interface with the data and address buses directly and freeze the Z80 with a BUSREQ signal whilst it performs DMA operations on the memory. I haven't checked for viability yet (as I've just had the idea whilst writing this post), but it'd be good if I can use it as the video signal generator too.

durgadas311
January 16th, 2018, 08:57 AM
Yep, that's one of the reasons for the 1 Hz clock on the CTC and wanting to get interrupts up and running in CP/M 3. :)


I noticed that the math in DMI for setting up the CTC 1Hz is not correct. You are getting an interrupt every 1.28 seconds, which makes for a rather slow clock. I think you need to use "125" for the channel 2 time constant, and either 125 or 250 for the channel 3 time constant (depending on CPU clock speed). That works out to 1.0 seconds.

Any chance of getting those schematics rendered to something like postscript or PDF? I don't have any Winderz environment to run DipTrace, and my OSX system is not available. I'll try to keep up with hardware changes in the simulation, but that will depend on having documentation. I guessed about a lot of the ATmega328 commands you support.

nockieboy
January 16th, 2018, 09:55 AM
I noticed that the math in DMI for setting up the CTC 1Hz is not correct. You are getting an interrupt every 1.28 seconds, which makes for a rather slow clock. I think you need to use "125" for the channel 2 time constant, and either 125 or 250 for the channel 3 time constant (depending on CPU clock speed). That works out to 1.0 seconds.

Hot dang! The slow CTC has been on my list of bugs to fix for the past couple of months but I've been too distracted with CP/M to get around to looking at it!! Thanks! :D


Any chance of getting those schematics rendered to something like postscript or PDF? I don't have any Winderz environment to run DipTrace, and my OSX system is not available. I'll try to keep up with hardware changes in the simulation, but that will depend on having documentation. I guessed about a lot of the ATmega328 commands you support.

I need to do a full pass on the schematics again anyway - they're getting a little dusty - I'll knock up some PDFs for you when I update the MMU.

durgadas311
January 16th, 2018, 12:13 PM
Hmm... well, I'm finding CP/M 3 to be just as stable as CP/M 2.2 now (i.e. I haven't been able to crash it yet despite trying) so I'm thinking that it won't be such a bridge-burning exercise as it looked like it would be previously (and you'll still be able to sell your bridge in Brooklyn.) So long as I'm able to set up a simple system to install CP/M 3 onto a blank drive, like I have for 2.2 currently, then it won't be an issue.


Keep in mind that creating a bootable CP/M 3 disk does involve more-complicated tasks, like LINK and GENCPM at the very least. You have a chicken-egg situation if you are trying to rebuild CP/M 3 from scratch, you need a platform to run LINK and GENCPM on, which would probably need to be CP/M 2.2 since we don't have a version of these that can run outside of CP/M.

You'll also have to change your DMI boot procedure, as you can no longer just load track 0 into 0D000H and jump to 0E600H. I know we had a discussion of this before, so you probably have all the information you need. I guess you had planned to create a "golden" CPM3.SYS which you can always restore from, using that to re-generate a more modern version. My concerns may be less tangible, but I just feel uneasy about going with a restriction like this. I guess if it were me I would have a more-generic boot procedure and allow for booting from a wider selection of images. Kaypro had a simple way, where sector 0 contains a few bits of data like the load address, length, and entry point (where to jump after loading). This way, the ROM was not tied (as much) to specific versions or types of OS, but almost any kind of boot image could be used as long as the header sector has the right data. There's still a problem for running anything "beneath" the ROM, but there can be generic ways to work around that.

Alphasite
January 16th, 2018, 08:25 PM
A word of warning on the BIOS TIME function. If you actually go get the data from your "RTC" (ATmega328 ) every time, the system performance will be terrible. Keep in mind that the TIME function is called every time the BDOS needs a timestamp for a file - not just when DATE.COM is run. Even with a direct-attached RTC chip, most systems would get the time/date from the RTC only at cold boot and then advance the CP/M time/date from a periodic interrupt.

I've been adding support to my CP/M Plus to use a hardware clock so this is a good warning. I found source code to convert the date from MM/DD/YY to days since 1/1/78 and back so I'm in the process of adding that.

Based on what you've said I should read from the RTC in BOOT and set @date, @hour, @min, and @sec. I have the interrupt service routine already updating the time I just never had an RTC to set the initial time so had to set it manually at boot. I never noticed the time slipping too far due to disabling interrupts during certain BIOS routines but didn't usually go more than four hours or so without a need to reboot for some reason (mostly due to tinkering with the BIOS code). I think this weekend I'll boot the Model 4 up and leave it running for 24 hours and see how much the time slips.

I also need to add the Y2K patches.

nockieboy
January 17th, 2018, 02:39 AM
I've been adding support to my CP/M Plus to use a hardware clock so this is a good warning. I found source code to convert the date from MM/DD/YY to days since 1/1/78 and back so I'm in the process of adding that.

Based on what you've said I should read from the RTC in BOOT and set @date, @hour, @min, and @sec. I have the interrupt service routine already updating the time I just never had an RTC to set the initial time so had to set it manually at boot. I never noticed the time slipping too far due to disabling interrupts during certain BIOS routines but didn't usually go more than four hours or so without a need to reboot for some reason (mostly due to tinkering with the BIOS code). I think this weekend I'll boot the Model 4 up and leave it running for 24 hours and see how much the time slips.

I also need to add the Y2K patches.

Yes, I've got some work to do to integrate my RTC into CP/M. At the moment it just returns a string with the date and time in it on request - I'll need to convert that to a binary word for @DATE and a BCD for hours, minutes and seconds.

durgadas311
January 17th, 2018, 04:54 AM
Yes, I've got some work to do to integrate my RTC into CP/M. At the moment it just returns a string with the date and time in it on request - I'll need to convert that to a binary word for @DATE and a BCD for hours, minutes and seconds.

There is plenty of code out there to do the conversion, or at least parts of it. There's one example in https://github.com/durgadas311/MmsCpm3/blob/master/sys/src/rtc72421.asm, which does both directions (that code allows one to set the RTC time/date using CP/M 3 DATE.COM, but that's a luxury many systems don't need - especially if it's easier to set it in the ROM). Of course, that RTC chip uses BCD values, so is not the same input data as for ASCII strings (although it's close if you assume no garbage).

Since it's deprecated technology, it may not matter, but what is the defined format of the date/time string between the Z80 and the ATmega328?

nockieboy
January 18th, 2018, 12:55 AM
There is plenty of code out there to do the conversion, or at least parts of it. There's one example in https://github.com/durgadas311/MmsCpm3/blob/master/sys/src/rtc72421.asm, which does both directions (that code allows one to set the RTC time/date using CP/M 3 DATE.COM, but that's a luxury many systems don't need - especially if it's easier to set it in the ROM). Of course, that RTC chip uses BCD values, so is not the same input data as for ASCII strings (although it's close if you assume no garbage).

Since it's deprecated technology, it may not matter, but what is the defined format of the date/time string between the Z80 and the ATmega328?

Thanks durgadas311 - that's a helpful prod in the right direction. :) I haven't looked into it at all yet, but I'm supposing I can just change the format passed from the ATmega328 to a BCD version. I'm currently learning and researching a replacement for the ATmega328 which will likely change everything anyway, but currently the format the ATmega328 sends the date back in is a simple string:

%E020022/08/2017 18:24:52#

%E tells the interrupt service routine that the string is a date time.

The next four chars (0200 in the example above) is the address in memory that the interrupt service routine should copy the remainder of the string to. This is passed to the ATmega328 by the calling function in the original request. Normally, the calling routine (be it in the DMI or a CP/M transient program) will have supplied the memory address of a variable initialised in the date time format to ensure there is sufficient space for the service routine to write to. The first byte is usually an ASCII 'x', which it checks for changes to whilst waiting for the data to be returned from the ATmega328.

The remainder is just the date and time in dd/mm/yyyy hh:mm:ss format with a string terminator (#).

durgadas311
January 18th, 2018, 04:10 AM
Ah, ok, so %E is basically a generic "put stuff in memory" command. %E<adr><string...>#. I was guessing at the "set time" command, looks like it is %U<adr><time># where <adr> is the address for an implied "get time" operation, and <time> is the time to set, in the same format as "get"? Also, confirming that the "get time" command is %Z<adr># ? And what is the %T... command for?

I'm not sure if you're a "do it myself" person, but now that I have a way to test code I could probably find some time this weekend to port my clock/RTC code to your CP/M 3 BIOS. Let me know if you'd like the help.

If so, are you familiar with the PULL REQUEST? That would be the best way to get code updates to you.

durgadas311
January 18th, 2018, 04:57 AM
Here's what I think the ATmega328 commands are, based on examination of DMI.ASM and previous replies:


// General command/response format:
//
// %L
// %L<adr>#
// %L<adr><string>#
//
// "L" represents the command letter.
// <adr> is a 4-digit hex string
// <str> is an arbitrary (?) length string of ASCII characters
// Command letter determines format of command
//
// Supported commands:
// Command Function Response
// -------------- ---------------------- --------------
// %S Get CPU clock speed %S[248]#
// %C toggle CPU clock speed none
// %T Print time/date %T<time>#
// %Z<adr># Get time/date %E<adr><time>#
// %U<adr><time># Set time/date %E<adr><time>#
//
// Generic response commands:
// %E<adr><str># Put <str> into memory at <adr>
// %T<str># Echo <str> to terminal output
// %Q<str># Send <str> to terminal input (as a command)
//
// <time> format is "dd/MM/yyyy HH:mm:ss"
//

Any corrections/additions?

nockieboy
January 18th, 2018, 05:54 AM
Ah, ok, so %E is basically a generic "put stuff in memory" command. %E<adr><string...>#. I was guessing at the "set time" command, looks like it is %U<adr><time># where <adr> is the address for an implied "get time" operation, and <time> is the time to set, in the same format as "get"? Also, confirming that the "get time" command is %Z<adr># ? And what is the %T... command for?

Yes, that's right re: the %U command. The date string is parsed by the ATmega328 which extracts the components of the date and updates the RTC before returning the updated date string to update the memory location on the Z80.


I'm not sure if you're a "do it myself" person, but now that I have a way to test code I could probably find some time this weekend to port my clock/RTC code to your CP/M 3 BIOS. Let me know if you'd like the help.

I am usually, but I've got a lot on my plate at the moment with learning how to program this STM32F103 micro-controller and getting familiarised with a whole new tool chain. I've also got the re-design of the MMU occupying my spare brain downtime and on top of all that I've got a family and a day job... So yes, I would greatly appreciate the assistance. :D


If so, are you familiar with the PULL REQUEST? That would be the best way to get code updates to you.

Absolutely. You've got write access so you should be able to create PRs now.

nockieboy
January 18th, 2018, 05:58 AM
Here's what I think the ATmega328 commands are, based on examination of DMI.ASM and previous replies:


// General command/response format:
//
// %L
// %L<adr>#
// %L<adr><string>#
//
// "L" represents the command letter.
// <adr> is a 4-digit hex string
// <str> is an arbitrary (?) length string of ASCII characters
// Command letter determines format of command
//
// Supported commands:
// Command Function Response
// -------------- ---------------------- --------------
// %S Get CPU clock speed %S[248]#
// %C toggle CPU clock speed none
// %T Print time/date %T<time>#
// %Z<adr># Get time/date %E<adr><time>#
// %U<adr><time># Set time/date %E<adr><time>#
//
// Generic response commands:
// %E<adr><str># Put <str> into memory at <adr>
// %T<str># Echo <str> to terminal output
// %Q<str># Send <str> to terminal input (as a command)
//
// <time> format is "dd/MM/yyyy HH:mm:ss"
//

Any corrections/additions?

Looks good to me. The %T command (from the Z80 side at least) is deprecated and not used any more. It was something I set up during initial testing of the serial interface with the micro-controller.

durgadas311
January 18th, 2018, 06:45 AM
You've got write access so you should be able to create PRs now.

Perhaps write access changed this, but I can't find a way to fork your repository. Perhaps I can push directly. I'm uneasy about pushing to your master branch, so I'll create a side branch to work on and let you merge that once you've confirmed it works.

nockieboy
January 18th, 2018, 07:31 AM
Perhaps write access changed this, but I can't find a way to fork your repository. Perhaps I can push directly. I'm uneasy about pushing to your master branch, so I'll create a side branch to work on and let you merge that once you've confirmed it works.

Sorry, my mistake - I forgot to enable forking. :rolleyes:

nockieboy
January 18th, 2018, 08:24 AM
Oh, one slight correction to the date string returned by the ATmega328...

<time> format is "dd/MM/yyyy HH:mm:ss DDD" - where DDD is a three char abbreviation for the day of the week, i.e.: Mon, Tue, Wed, Thu, Fri, Sat or Sun.

durgadas311
January 19th, 2018, 01:14 PM
There is a working version of BIOS.ASM and TIME.ASM on the "cpm3time" branch now (I did not check-in REL files) - at least it works on the simulator. I renamed the original TIME.ASM to TIME.I80 in order to keep active files named *.ASM. I did not bother to implement a clock set function (being able to set the RTC time via DATE.COM), if you decide you want that feature we can add the code. link with "link bnkbios3=bios3,time,scb[b,os,nr]". I did not do any comprehensive accuracy checks, but it seems close (probably not worth doing on the simulator anyhow).

I noticed that the 2 MHz CTC setup suffers from a rounding error, by my calculations it will gain nearly a minute every two hours. Not sure why you'd want to run 2MHz anyway, but a fix might not be easy. You could program it at 16x,250,250 and get a half-second interrupt, but then you have to detect this and only update the clock every second tick.

Also, you'll want to get the CP/M3 utils with Y2K fixes, if you haven't already. I've found them at http://www.cpm.z80.de/binary.html. Without this, you get odd 2-digit years since the original code never expected to overflow year '99. But I don't think there are any catastrophic side-effects.

nockieboy
January 19th, 2018, 02:29 PM
Thanks durgadas311!

Okay, I've linked the bios and generated a new CP/M 3. When I run DATE.COM, I get the following:


A>date
Fri 01/19/;8 23:25:47

Slightly corrupted output for the year. That and the date's in US format with the month first. Anything I can do about that? ;)

EDIT: Thinking about it, I don't suppose CP/M had localisation options back in the 80's!

Alphasite
January 19th, 2018, 02:45 PM
Thanks durgadas311!

Okay, I've linked the bios and generated a new CP/M 3. When I run DATE.COM, I get the following:


A>date
Fri 01/19/;8 23:25:47

Slightly corrupted output for the year. That and the date's in US format with the month first. Anything I can do about that? ;)

EDIT: Thinking about it, I don't suppose CP/M had localisation options back in the 80's!

Do you have the Y2K patched files? You can get them here: http://www.cpm.z80.de/binary.html

durgadas311
January 19th, 2018, 03:04 PM
The corrupted year is from the lack of Y2K fixes, as Alphasite said. And, correct there are no localization options for CP/M!

JohnElliott
January 19th, 2018, 03:56 PM
When I did the Year 2000 fixes, I also added support for multiple date formats. Use SETDEF to select: SETDEF [US], SETDEF [UK] or SETDEF [YMD].

durgadas311
January 19th, 2018, 04:36 PM
When I did the Year 2000 fixes, I also added support for multiple date formats. Use SETDEF to select: SETDEF [US], SETDEF [UK] or SETDEF [YMD].

Very nice. So, where does that setting get stored? Was there space in the SCB for that?

Alphasite
January 19th, 2018, 05:11 PM
When I did the Year 2000 fixes, I also added support for multiple date formats. Use SETDEF to select: SETDEF [US], SETDEF [UK] or SETDEF [YMD].

Did you ever get a new version of INITDIR built?

durgadas311
January 19th, 2018, 05:42 PM
Did you ever get a new version of INITDIR built?

Curious: does INITDIR display dates? The date is stored internally, including file timestamps, in a neutral manner. Only programs that print out dates should need to worry about the date format. So far, I've noticed DATE.COM, DIR.COM, and SHOW.COM. I'd be interested to know the full list.

Alphasite
January 19th, 2018, 06:05 PM
Curious: does INITDIR display dates? The date is stored internally, including file timestamps, in a neutral manner. Only programs that print out dates should need to worry about the date format. So far, I've noticed DATE.COM, DIR.COM, and SHOW.COM. I'd be interested to know the full list.

I don't think it does. However, JohnElliot applied most of the other patches that were released as well.

nockieboy
January 20th, 2018, 01:15 AM
Do you have the Y2K patched files? You can get them here: http://www.cpm.z80.de/binary.html


The corrupted year is from the lack of Y2K fixes, as Alphasite said. And, correct there are no localization options for CP/M!

Ah yes, that'll be it. The bug expresses itself in a way I wouldn't have thought, though. After all the media coverage back at the turn of the millennium, I was expecting the SBC to sprout legs and arms and embark on a mission of world domination, or perhaps trigger a critical mass of silicon in the Z80 and go nuclear... ;)

I think I have seen a Y2K patch file in the CP/M 3 archive I have. Will have a look and get it sorted. Thanks very much for your help on this, durgadas311, it's greatly appreciated!!

nockieboy
January 20th, 2018, 01:34 AM
When I did the Year 2000 fixes, I also added support for multiple date formats. Use SETDEF to select: SETDEF [US], SETDEF [UK] or SETDEF [YMD].

That's really useful. Did you document the patch at all?


Did you ever get a new version of INITDIR built?

Talking of which, will INITDIR need to be modified at all for the hardware/particular disk setup of my system before I run it?


Curious: does INITDIR display dates? The date is stored internally, including file timestamps, in a neutral manner. Only programs that print out dates should need to worry about the date format. So far, I've noticed DATE.COM, DIR.COM, and SHOW.COM. I'd be interested to know the full list.

You mentioned storing the data in the SCB earlier. Is there much room there to put extra vars in? I'm thinking particularly of the CLKSPD value (a single byte), which has a particular space in CBIOS64 for CP/M 2.2 but I have to use a somewhat hacky way to transfer it to CP/M 3's BIOS3. Just wondered if that would be a better place to store it?

durgadas311
January 20th, 2018, 04:20 AM
INITDIR uses the standard CP/M information to identify the directory (DPB mostly) and should work on any platform. The BDOS uses the DPB in the same way to layout the disk, so it's not really a departure from the norm.

FYI, HELP appears to have been modified for the patched programs, so HELP SETDEF shows these new features.

I did a quick review of the SCB last night and saw 4 bytes of "user flags". That's not very much, and if the date format is stored there I'm not sure how much (and which bytes) remains.

durgadas311
January 20th, 2018, 04:29 AM
Ah yes, that'll be it. The bug expresses itself in a way I wouldn't have thought, though. After all the media coverage back at the turn of the millennium, I was expecting the SBC to sprout legs and arms and embark on a mission of world domination, or perhaps trigger a critical mass of silicon in the Z80 and go nuclear... ;)

I think I have seen a Y2K patch file in the CP/M 3 archive I have. Will have a look and get it sorted. Thanks very much for your help on this, durgadas311, it's greatly appreciated!!

The link that Alphasite and I posted contains complete files, including COM files, for not only Y2K patches but other known patches to CP/M 3. You should just rebase/replace your CP/M 3 "distro" using that archive. I also see SPR files there so there could be patches to BDOS that are good to have.

Yes, Y2K in general was big non-event. In this case, when CP/M is converting "the number of days since Jan 1 1978" into month, day, and year it assumes no overflow will occur. So, for the two digit year part of 2018 it computes <11> <8> and then blindly converts those two values to ASCII by adding '0' (030H), yielding 03BH and 038H - which means ';' and '8'. Again, no evil side-effects just the appearance of "corrupted" data.

durgadas311
January 20th, 2018, 05:00 AM
Also, those patched versions of COM files are a little odd in that many of them are not an even multiple of 128-bytes in length. However you transfer those to CP/M will need to be able to handle that correctly (must pad to next 128 bytes, not truncate!). Probably not an issue, but just in case... Also, the files will be different lengths on CP/M than in the archive and (once copied back to Linux) will not compare cleanly with originals.

durgadas311
January 20th, 2018, 05:57 AM
Very nice. So, where does that setting get stored? Was there space in the SCB for that?

I found that the date format is being stored in SCB byte at offset 0CH (12). Value 00 for "US", 01 for "UK", and 02 for "YMD". This byte is part of a "reserved for system use" section, but does not appear to be used by the system otherwise.

So, the 4 "Reserved for user use" bytes at offset 6 should be free for whatever BIOS writers want to use them for. It's only 4 bytes, but it's something. You could theoretically place a RESBIOS address in two of those bytes, pointing to a "well known" structure of data inside the (resident) part of the BIOS - thereby expanding this user data to whatever you want.

See the programmer's manual regarding BDOS function 49 "GET / SET SYSTEM CONTROLBLOCK" for how to access this from a user program.

JohnElliott
January 20th, 2018, 11:04 AM
Did you ever get a new version of INITDIR built?

No; I tried a couple of PL/I compilers but didn't find anything that would build to the original.

JohnElliott
January 20th, 2018, 11:11 AM
Very nice. So, where does that setting get stored? Was there space in the SCB for that?

I looked in the various sources to find what they used the SCB for, and picked a byte that (a) wasn't used by anything, and (b) didn't have a label to say what it might be used for. The four bytes at SCB+0Ah didn't seem to be used, but the word at SCB + 0Ah had a label ('dspl$flgs') so I went with SCB + 0Ch. Looking in the source there are several SCB entries that aren't used but have definitions; these may reflect usage of the equivalent flags in MP/M, or be for planned features that were never implemented.

durgadas311
January 20th, 2018, 12:17 PM
No; I tried a couple of PL/I compilers but didn't find anything that would build to the original.

I found this compiler and it seems to work on INITDIR... http://www.z80.eu/downloads/PLI_for_CPM80_v13.zip. It took some trial-and-error to get it to link, but it looks to be working.

nockieboy
January 22nd, 2018, 08:58 AM
When I did the Year 2000 fixes, I also added support for multiple date formats. Use SETDEF to select: SETDEF [US], SETDEF [UK] or SETDEF [YMD].

That is awesome, works brilliantly. Thanks!

nockieboy
January 23rd, 2018, 02:06 AM
How is INITDIR supposed to be used? I'm having a little trouble with it - the first version I found was in the DRI CP/M 3 archive, about 32K in size and caused my transfer program to crash when I tried to convert it to an ASCII stream in the clipboard to copy to the CP/M terminal... Probably because of its size, but I can't see any reason why it'd be an issue for the transfer program. I wonder if it's a corrupted file?

Anyway, I found a smaller (4K!) version of INITDIR.COM somewhere online (I probably should be more careful where I get these files from) in a ZSDOS archive. Tried that and it transfers fine and runs, but when I select a drive it just freezes, so I'm a little stumped at the moment how to get a working version of INITDIR onto my system.

I suppose the first question is: is the official DRI INITDIR.COM actually 32K in size or do I have a dodgy copy? If it's legit, then I'll take a longer look at the source for my Windows transfer program and see what's going on there and why it doesn't like it (it's probably to do with the size of the file.)

durgadas311
January 23rd, 2018, 04:17 AM
INITDIR.COM is 250 records long, or 32000 bytes. So the 4K one is definitely wrong and probably crashing. You can use HELP to get info on CP/M 3 commands. In this case it says:


B>help initdir

INITDIR


Syntax:

INITDIR {d:}

Explanation:

The INITDIR Command initializes a disk directory to allow date
and time stamping of files on that disk. INITDIR can also recover
time/date directory space.

Example:

A>INITDIR C:

INITDIR WILL ACTIVATE TIME-STAMPS FOR SPECIFIED DRIVE.
Do you want to re-format the directory on C: (Y/N)?Y


HELP>

Note, INITDIR just reserves the directory space for timestamps. You then must create a directory label (where the flags to enable timestamps live) and then turn on the type of timestamps you want. Use SET.COM to create a directory label, and also to enable the specific timestamps. Again, use HELP. You can enable UPDATE (modify) timestamps, and/or either CREATE or ACCESS timestamps, independently.

nockieboy
January 23rd, 2018, 04:36 AM
INITDIR.COM is 250 records long, or 32000 bytes. So the 4K one is definitely wrong and probably crashing. You can use HELP to get info on CP/M 3 commands.

Okay, so the version I've got is likely fine then (it actually shows at 31.5K in my transfer program but I guess CP/M will round up to the nearest complete record.) Uuuuuunless, thinking about it, perhaps that's where the problem lies? If the file isn't padded out to a whole-record (multiple of 128-bytes) figure, then that's likely why I'm getting a file length error in CP/M when I try to paste it there...

So I've got some tweaking to do with my transfer program to ensure that all files pasted into it are padded out to a record boundary if they don't already finish on one. I know something like this was mentioned earlier in the forum - ah, it was you durgadas311!


Also, those patched versions of COM files are a little odd in that many of them are not an even multiple of 128-bytes in length. However you transfer those to CP/M will need to be able to handle that correctly (must pad to next 128 bytes, not truncate!). Probably not an issue, but just in case... Also, the files will be different lengths on CP/M than in the archive and (once copied back to Linux) will not compare cleanly with originals.

I'm hoping that's the cause of the error in DOWNLOAD.COM... :confused:

EDIT:

Maybe not then. I've just done a character count of the file output and it's 64,000 characters, which equates to 32,000 bytes (or 7D00h bytes.) No record boundary issues there..

EDIT 2:

Okay, I'm leaving the Twilight Zone now... I've just pasted the file again and it worked fine.

durgadas311
January 23rd, 2018, 05:23 AM
Is this the largest transfer you've done, to date? One thing I wondered about is doing a copy-paste of something so huge. If this is over a serial port, make certain your receiver program is able to keep up. Maybe you need to be checking the UART for receive errors. If you're receiving on the Z80, it is VERY easy to overrun that. Depending on your transfer protocol, random missing chunks of data could cause hangs.

nockieboy
January 24th, 2018, 12:04 AM
Is this the largest transfer you've done, to date? One thing I wondered about is doing a copy-paste of something so huge. If this is over a serial port, make certain your receiver program is able to keep up. Maybe you need to be checking the UART for receive errors. If you're receiving on the Z80, it is VERY easy to overrun that. Depending on your transfer protocol, random missing chunks of data could cause hangs.

Actually no - HELP.HLP is 64 KB and I managed to get that onto the system first attempt (perhaps a fluke?)... the next biggest file was CPM3.SYS at about 20K and this pasted fine the few times I tried it. The serial interface is running at 125 kbps with the SBC at 4 MHz. It falls over trying to receive pasted data at 2 MHz, dropping chars left, right and centre (unsurprisingly), but has always been stable at 4 or 8 MHz. I've just done some simple testing with the system before writing this post and it seems that anything 8 KB or less in size (according to Windows - so that's DEVICE.COM and smaller, but not PIP.COM or larger in the CPM_3-0 DISK1 distribution archive) is downloaded fine, with PIP.COM (9KB according to Windoze) or larger returning the file length error in DOWNLOAD.COM.

However, I've just thought of something. The above problems occur in CP/M 3. I've just tried transferring those programs in CP/M 2.2 and it worked fine, no errors. So it's likely an issue with the interrupt-driven IO in the CP/M 3 BIOS?

durgadas311
January 24th, 2018, 02:41 AM
That could be. Interrupt driven I/O is actually NOT the fastest way to transfer data - especially on a constrained CPU like this. There's just too much overhead. The fastest receive code is a simple, direct, loop such as:


SERIN: XOR A,A
OUT SIOB_C
IN SIOB_C
AND A,1
JP Z,SERIN
IN SIOB_D
RET


Which takes 64 cycles per character, *minimum*, and at 4MHz computes to 16uS per character (that's in addition to the code that actually stores the data or does something with it, and not counting latency skew). 125Kbaud is 80uS per character (8 data bits plus start, stop), so there is enough time - until you factor-in doing something useful with the characters. Your CP/M machine has a limited amount of memory to buffer the received characters, and at some point it will need to write to disk. When you reach that point, you are going to fall very far behind. I have not examined your DOWNLOAD.COM code, and will do that next, but your handshaking/flow-control will need to be working flawlessly at that point. Bottom line, as long as you are just stuffing characters into memory you should be able to keep up with 125Kbaud (without handshake). But the moment you run out of memory (somewhere less than 64K) you will need to be taking care.

Regarding interrupt driven input, the main reasons one chooses that is for cases like the system management module where you have asychronous messages or as a means to provide "type-ahead" for the user (so that, for example, you can start typing the next command while the warm boot is going on). Interrupt driven input will not give you the best receive throughput. At least, not on a single CPU machine.

UPDATE: looks like your DOWNLOAD.COM source code is not in the repository.

nockieboy
January 24th, 2018, 06:07 AM
That could be. Interrupt driven I/O is actually NOT the fastest way to transfer data - especially on a constrained CPU like this. There's just too much overhead. The fastest receive code is a simple, direct, loop such as:


SERIN: XOR A,A
OUT SIOB_C
IN SIOB_C
AND A,1
JP Z,SERIN
IN SIOB_D
RET


Which takes 64 cycles per character, *minimum*, and at 4MHz computes to 16uS per character (that's in addition to the code that actually stores the data or does something with it, and not counting latency skew). 125Kbaud is 80uS per character (8 data bits plus start, stop), so there is enough time - until you factor-in doing something useful with the characters.

It still drops chars (if that is, in fact, the cause of the file length error) at 8 MHz - whatever length of time it takes to get through the ISR, it'll take half as long at that speed than at 4 MHz, and it seems to take files less than 9KB in size just fine, so a memory buffer/disk write delay seems to be the most likely cause of the problem... I haven't had a chance to look at DOWNLOAD.COM yet. It just seems 8KB is a bit of an arbitrary figure to fall over at, considering the TPA is about 59K or so.


UPDATE: looks like your DOWNLOAD.COM source code is not in the repository.

Should be - /code/archive/source/download.asm?

EDIT: Just had a VERY quick scan through - looks like it's loading into a 128-byte buffer. When it gets full, it writes it to disk? I'm guessing the cumulative time delays of doing that build up so that after 8K or so, it can no longer keep up with the IO and drops a char (or two) ?

EDIT2: Thing is, CP/M 2.2 is able to keep up so there must be a discrepancy between that and the CP/M 3 BIOS...

durgadas311
January 24th, 2018, 07:13 AM
Yeah, I found the source, too. So, there are some differences in code path at 8K, but probably not the cause. Another thing is what happens during the BDOS WRITE to the file. At various points, the BDOS call will take (much) longer as the BDOS needs to close the current extent and open a new one (I thought your extent size was 16K, though). I suspect that is contributing to the behavior. The other thing to scrutinize is the handshaking. I see the interrupt routines will set RTS when the buffer is close to filling, then reset it once drained. Make certain that RTS is doing the right thing and that the paste operation actually honors RTS. One concern is whether the handshake is simply being ignored by the sending side.

durgadas311
January 24th, 2018, 01:57 PM
I'm not seeing any notable differences between the serial I/O in CBIOS64 and BIOS3. One general difference is that BIOS3 will execute the GET TIME command (on channel B) in cold boot, which BIOS64 does not. I'm not sure how that would effect the download on channel A, but it could have changed something. Figuring this out may require finding out what exactly is going wrong to cause the length error. We're assuming receiver overrun but that may not be the cause. Also, checking the receiver error bits might tell us more.

durgadas311
January 24th, 2018, 03:46 PM
We had talked about editors before. I create a terminal definition module for Magic Wand, which is the editor I used for all my programming and documentation back in the day. This works for xterm, and probably most other modern emulators based on the VT100 series. It does limit you to an 80x24 screen (uses the top left of your window), but seems to be working well. There is a "howto" file that documents the function keys, and a PDF of the original manual. As with any software, it takes some getting used to. But in case someone is interested, here it is:

http://sebhc.durgadas.com/misc/magic_wand.tgz

The file "edit.com" already has the "termxt.asm" module applied, so it is ready to go. The terminal module source (and instruction for overlaying) is included in case someone wants to adapt it to another terminal.

The editor was designed for word processing, but also has a "program" mode that works well for editing source code. There is also a "print.com" (not yet provided) that is used to print files. If interest exists, I can look into configuring that - although it also requires a printer module and that may not fit well with modern use.

Alphasite
January 24th, 2018, 05:41 PM
We had talked about editors before. I create a terminal definition module for Magic Wand, which is the editor I used for all my programming and documentation back in the day. This works for xterm, and probably most other modern emulators based on the VT100 series. It does limit you to an 80x24 screen (uses the top left of your window), but seems to be working well. There is a "howto" file that documents the function keys, and a PDF of the original manual. As with any software, it takes some getting used to. But in case someone is interested, here it is:

http://sebhc.durgadas.com/misc/magic_wand.tgz

The file "edit.com" already has the "termxt.asm" module applied, so it is ready to go. The terminal module source (and instruction for overlaying) is included in case someone wants to adapt it to another terminal.

The editor was designed for word processing, but also has a "program" mode that works well for editing source code. There is also a "print.com" (not yet provided) that is used to print files. If interest exists, I can look into configuring that - although it also requires a printer module and that may not fit well with modern use.

I used WordStar as my editor. I wrote a lot of code with it as well as papers for college. At the time it was amazing, but now I find it very slow to load to edit source code. I've also forgotten most of the commands which I used to be able to use without thinking.

I might take a look at getting Magic Wand working on my system.

durgadas311
January 25th, 2018, 03:17 AM
I used WordStar as my editor. I wrote a lot of code with it as well as papers for college. At the time it was amazing, but now I find it very slow to load to edit source code. I've also forgotten most of the commands which I used to be able to use without thinking.

I might take a look at getting Magic Wand working on my system.

While I'm partial to Magic Wand, I've also found that everyone has their own preferences, and also learning a new editor is always hard. So, I won't claim it's the best - or even suitable. Since I spent so many years using it, it came back to me fairly easily. At the time, there were users who claimed it was vastly superior to WordStar. Of course, there were probably plenty who claimed the opposite.

nockieboy
January 25th, 2018, 06:25 AM
We had talked about editors before. I create a terminal definition module for Magic Wand, which is the editor I used for all my programming and documentation back in the day. This works for xterm, and probably most other modern emulators based on the VT100 series. It does limit you to an 80x24 screen (uses the top left of your window), but seems to be working well. There is a "howto" file that documents the function keys, and a PDF of the original manual. As with any software, it takes some getting used to. But in case someone is interested, here it is:

http://sebhc.durgadas.com/misc/magic_wand.tgz

The file "edit.com" already has the "termxt.asm" module applied, so it is ready to go. The terminal module source (and instruction for overlaying) is included in case someone wants to adapt it to another terminal.

The editor was designed for word processing, but also has a "program" mode that works well for editing source code. There is also a "print.com" (not yet provided) that is used to print files. If interest exists, I can look into configuring that - although it also requires a printer module and that may not fit well with modern use.

That's brilliant, thanks durgadas311! Have just tested it on my system and it works well with my terminal emulator. I was getting nowhere trying to sort out ANSI terminal emulation for WordStar, but this works straight out of the archive. Big thumbs up - I can process words on my SBC now! ;)

durgadas311
January 25th, 2018, 06:43 AM
That's brilliant, thanks durgadas311! Have just tested it on my system and it works well with my terminal emulator. I was getting nowhere trying to sort out ANSI terminal emulation for WordStar, but this works straight out of the archive. Big thumbs up - I can process words on my SBC now! ;)

Thanks. I have not put many hours on it yet, so if you run into problems let me know. I did notice, on my simulator, that occasionally it would mis-interpret a function key ESC sequence. I'm assuming that is due to the code paths taken for each character in the JAVA implementation, and probably not present on real hardware.

Alphasite
January 25th, 2018, 05:16 PM
While I'm partial to Magic Wand, I've also found that everyone has their own preferences, and also learning a new editor is always hard. So, I won't claim it's the best - or even suitable. Since I spent so many years using it, it came back to me fairly easily. At the time, there were users who claimed it was vastly superior to WordStar. Of course, there were probably plenty who claimed the opposite.

After years of using vi a stripped-down clone would be nice but so far I haven't found one.

durgadas311
January 25th, 2018, 05:31 PM
After years of using vi a stripped-down clone would be nice but so far I haven't found one.

There used to be a set of unix-like tools for DOS, that included a "vi". "mks toolkit"? But, there is also the strip-down "embedded" Linux stuff (busybox, et al) that includes a "vi". Although, I still wonder how much you can edit when your editor consumes 50K just for itself... actually, I don't know what size it would be if you compiled the busybox "vi" in CP/M. I suspect it would require a lot of porting either way.

Since I'm using virtual machines, I usually setup CP/NET and do all my editing in "vi" on the host computer. Or, in this case, use cpmtools to pop the file into the CP/M world after editing with "vi" (and running through "unix2dos").

durgadas311
January 25th, 2018, 05:46 PM
Taking a quick look at vi.c from busybox, this might be doable. You'd have to avoid using STDIO.LIB as that would bloat the COM file too much. But if you rewrite the I/O to use the BDOS, it just might work. Maybe we should see if anybody has already done that...

Alphasite
January 25th, 2018, 08:14 PM
There used to be a set of unix-like tools for DOS, that included a "vi". "mks toolkit"? But, there is also the strip-down "embedded" Linux stuff (busybox, et al) that includes a "vi". Although, I still wonder how much you can edit when your editor consumes 50K just for itself... actually, I don't know what size it would be if you compiled the busybox "vi" in CP/M. I suspect it would require a lot of porting either way.

Since I'm using virtual machines, I usually setup CP/NET and do all my editing in "vi" on the host computer. Or, in this case, use cpmtools to pop the file into the CP/M world after editing with "vi" (and running through "unix2dos").

I'm editing the files in a Windows 7 VM running under Fusion on a MacBook Pro and then using TRSTools to transfer the files to disk images that I then mount in the TRS32 emulator running on the Windows VM and assembling there. Once I get things working in the emulator I convert the disk image to HFE and use that image on an HxC to boot on a real Model 4 to verify.

nockieboy
January 26th, 2018, 12:44 AM
I'm editing the files in a Windows 7 VM running under Fusion on a MacBook Pro and then using TRSTools to transfer the files to disk images that I then mount in the TRS32 emulator running on the Windows VM and assembling there. Once I get things working in the emulator I convert the disk image to HFE and use that image on an HxC to boot on a real Model 4 to verify.

Are you guys competing for who has the most complicated toolchain? ;)

I write the code in Notepad++, assemble it with Z80ASM in Altair CPMulator and transfer the COM file to the SBC via the terminal (all in Windoze)... I could probably just transfer the .Z80 file straight to the SBC and assemble it with Z80ASM in CP/M there and cut the emulator out altogether. In fact, with a working word processor now I could cut out Notepad++ as well and do it ALL in CP/M on the SBC... but that might be a bit too 'bare knuckles' for me all the time I have a serial connection between the PC and SBC. When I get the keyboard and monitor interface working and the SBC becomes truly standalone, that'll be when Magic Wand will be worth its weight in gold. :D

nockieboy
January 26th, 2018, 01:45 AM
Well, I didn't expect that!

43274

I thought I'd do a little debugging on EXIT.COM as it's not resetting back to the DMI as it should do (probably something I've done wrong.) I'd written the assembly in Magic Wand to try out restricting development to CP/M after my last post, tried running EXIT and hard reset back to DMI when it failed. The screenshot above is the DMI showing the second page of low RAM (0100-01FF) - i.e. the TPA area where EXIT is loaded (it says C100-C1FF because of the bank mapping) - look at the text in the middle - Christ is the Answer, apparently! :D Is this an artefact of some previous program I've run in CP/M? The only thing of note was Zork 1 prior to this. And no, I wouldn't have typed that myself! ;)

durgadas311
January 26th, 2018, 03:41 AM
Since EXIT.COM only consumed 1 record, anything beyond 0180H is whatever was left-over. Probably whatever program you ran last. You will see left-over junk in a .COM file also, if the ASM contains large sections of DS space (that's not at the very end). Of course, only if it is assembled/compiled in CP/M. You can see some artifacts like that in DRI distribution .COM files.

FYI, many OSes used to do that sort of thing even when creating processes in memory or disk files. It became known as a security flaw since someone could glimpse at data they weren't suppose to see, so nowadays OSes make sure to clear regions like that to ensure no data is leaked.

durgadas311
January 26th, 2018, 11:35 AM
Regarding the prospect of doing DMA to the Z80 address space, is it your plan to program the GPIO of the STM32F103 to be Z80 address, data, and BUSREQ/BUSACK signals? I didn't see mention of any way to extend the STM32F103 bus outside the chip (to use the internal DMA controller).

Too bad you're not using an STM32F1xx that has ethernet. You could add CP/NET if you had that. Or at least could piggy-back on some other high-speed communication between the system and a host computer (USB would work, but is just a little slower if it were tied to serial port baud timing).

durgadas311
January 27th, 2018, 05:23 AM
Regarding DOWNLOAD.COM, I was going to see if I could replicate the problems you had with CP/M 3. But, it seems that download.asm does not handle "standard" Intel HEX format, and all the HEX files in the repository *are* in Intel HEX format. Am I missing something? What are you using to transfer files to the Z80?

If download.asm is what you are using to transfer, it appears to use a (very) long stream of HEX digits, then a single byte length count and single byte checksum at the very end. Be aware that the count and checksum will not be very effective for long transfers. Intel HEX format has a length and checksum (each as one byte) for each line of the file (16 data bytes traditionally, 24 in modern HEX files), which is pretty effective at catching transfer errors. Granted, in this environment it is not likely that there will be transmission errors, and gross mistakes like pasting random text are probably caught by other means.

nockieboy
January 28th, 2018, 02:05 PM
Sorry for delay replying - had a busy weekend preparing for a house move in the next few weeks!


Regarding DOWNLOAD.COM, I was going to see if I could replicate the problems you had with CP/M 3. But, it seems that download.asm does not handle "standard" Intel HEX format, and all the HEX files in the repository *are* in Intel HEX format. Am I missing something? What are you using to transfer files to the Z80?

Ah, that's because the .HEX files are pasted into the DMI using the RHEX command. DOWNLOAD.COM takes a data stream pasted into the terminal window which is prepared in a Windows program made by my fair hand - you'll find it in Code/TAP Manager/TAP Manager.exe. Basically it's a re-written, modernised version of the program provided by Grant Searle in his original project archive (his is in /Code/windowsApp/FilePackage.exe.)

It takes a file dropped onto it and converts it into a CR/LF-delimited string that you can paste straight into CP/M and follows the format:



A:DOWNLOAD.COM <FILENAME>
U0
:[HEX BYTE STREAM]>[SINGLE BYTE COUNT][SINGLE CHECKSUM BYTE]



If download.asm is what you are using to transfer, it appears to use a (very) long stream of HEX digits, then a single byte length count and single byte checksum at the very end. Be aware that the count and checksum will not be very effective for long transfers. Intel HEX format has a length and checksum (each as one byte) for each line of the file (16 data bytes traditionally, 24 in modern HEX files), which is pretty effective at catching transfer errors. Granted, in this environment it is not likely that there will be transmission errors, and gross mistakes like pasting random text are probably caught by other means.

Currently my program just does the same thing as Grant's did - the long stream of HEX digits as you've correctly spotted. As and when I get round to working on the program again, I can look to strengthen the integrity of the data transfer, but it has caused no issues so far.

durgadas311
January 28th, 2018, 03:24 PM
Ugh, moving house is no fun. Best of luck. Hope you like the new place.

Alphasite
January 28th, 2018, 05:40 PM
Ugh, moving house is no fun. Best of luck. Hope you like the new place.

I hate moving. Now that I've lived in this house for 20+ years I've accumulated enough stuff that I don't want to think about moving again.

nockieboy
January 29th, 2018, 11:57 PM
I hate moving too, but have got it down to a fine art now (this'll be the 4th time in 12 years) and the new place is much bigger and more permanent, so it's worth it.

Going back to INITDIR and timestamps - I ran INITDIR on all my drives and it seems to have worked (no errors anyway), but I'm not seeing any timestamps with DIR or STAT or anything now, on existing or new files. Just wondered how you see all the timestamps? Thought DIR would show them, but perhaps it's not a default option?

daver2
January 30th, 2018, 12:15 AM
Try "DIR [DATE]" or "DIR C: [DATE]".

The CP/M User manual is your friend http://www.cpm.z80.de/manuals/cpm3-usr.pdf.

There are way more options to DIR that do wonderful things...

I have just had my in-laws move closer to us. Stressful time moving - but perhaps worth it in the long run...

Dave

nockieboy
January 30th, 2018, 01:17 AM
Try "DIR [DATE]" or "DIR C: [DATE]".

Ahaaa! Marvellous! I'm a happy camper again. :)


The CP/M User manual is your friend http://www.cpm.z80.de/manuals/cpm3-usr.pdf.

I know - I should look before I ask. Sorry.


There are way more options to DIR that do wonderful things...

Will have a closer look at it! The project is on a bit of a hiatus at the moment, what with the move and everything, but I really need to get my PSG wired in and working and get to work on version 2 of the MMU. I just keep finding distractions in software to keep me from biting the bullet and getting the schematics out again. ;) Plus the breadboard has become a mess of wires like something out of H.R. Giger's worst nightmares.


I have just had my in-laws move closer to us. Stressful time moving - but perhaps worth it in the long run...

Depends if you get on with the in-laws or not. :P How was bonnie Scotland, anyway? Saw this on eBay earlier and was trying to remember if you said you'd got a NASCOM? eBay: Nascom-I-O-Card-Kit-Brand-New-Never-Built (https://www.ebay.co.uk/itm/Nascom-I-O-Card-Kit-Brand-New-Never-Built/132486060886?hash=item1ed8c8db56:g:KB8AAOSwmSdabgt X)

EDIT:

Does anyone have a copy of VDE (the word processor)? I can find no trace of it online, other than a manual. A couple of places talk about it and mention it as a better alternative to ED etc, I'd like to give it a spin but can't find it. :/

durgadas311
January 30th, 2018, 04:49 AM
I hate moving too, but have got it down to a fine art now (this'll be the 4th time in 12 years) and the new place is much bigger and more permanent, so it's worth it.

Going back to INITDIR and timestamps - I ran INITDIR on all my drives and it seems to have worked (no errors anyway), but I'm not seeing any timestamps with DIR or STAT or anything now, on existing or new files. Just wondered how you see all the timestamps? Thought DIR would show them, but perhaps it's not a default option?

Note, STAT is a CP/M 2.2 utility and thus will never show timestamps. You should avoid using CP/M 2.2 system utilties on CP/M 3 - they might get you into trouble. INITDIR only reserves space in the directory for timestamps. You still have to create a directory label (which holds the config flags telling CP/M 3 to use timestamps) then you have to enable the timestamps you want to keep (in that directory label). Use SET to both create the label and enable specific timestamps. HELP has information on all standard CP/M commands and is very handy. Online documentation, essentially. You can enable"Update" timestamps, and either "Access" or "Create" timestamps. I find Create timestamps to be useless most of the time, since most editors and things like PIP always create new files instead of overwriting old ones - thus Create always ends up the same as Update.

daver2
January 30th, 2018, 10:49 AM
>>> How was bonnie Scotland, anyway?

Snowy :-)! We arrived at Edinburgh airport to a blizzard!

I am back home for the week and then back to Scotland again next week... Probably won't have time to catch up with the mega posts on your thread - but it looks like you are still moving forwards. I thought the same regarding the file transfer - it looks a bit 'simples'. I would have though a download process using the INTEL HEX format would have been a much better bet. This will be guaranteed to catch more errors if they occur. The problem with a very simple 8-bit checksum on a very large file is that you 'think' it is working (because you don't get any errors) only to find that the error detection algorithm is so poor that it would very rarely catch multi-bit errors!

>>> Saw this on eBay earlier and was trying to remember if you said you'd got a NASCOM?

Yep I have a NASCOM 2. Seen there is a guy who keeps posting NASCOM stuff. I may put a bid on for the I/O card. Thanks for thinking of me...

>>> I know - I should look before I ask. Sorry.

No need to, I was just dropping a hint ;-)... There are many more options you can use - and you will only really get to grips with CP/M by putting in a little study yourself. You won't necessarily remember it all - but (having read the user manual) when you think about something in the future - hopefully your brain will remind you that you have previously read something about this and to go and look it up.

Dave

nockieboy
January 31st, 2018, 12:24 AM
>>> How was bonnie Scotland, anyway?

Snowy :-)! We arrived at Edinburgh airport to a blizzard!

Nice. :) I saw there was some bad weather coming down around the time you'd be up there. We missed all of it down here in the bottom-right corner of the country, unfortunately. It has to be almost 'perfect storm' conditions in the Channel for it to get cold here...


I am back home for the week and then back to Scotland again next week... Probably won't have time to catch up with the mega posts on your thread - but it looks like you are still moving forwards. I thought the same regarding the file transfer - it looks a bit 'simples'. I would have though a download process using the INTEL HEX format would have been a much better bet. This will be guaranteed to catch more errors if they occur. The problem with a very simple 8-bit checksum on a very large file is that you 'think' it is working (because you don't get any errors) only to find that the error detection algorithm is so poor that it would very rarely catch multi-bit errors!

Agreed. It's the system used by Grant Searle in his CP/M system (http://searle.hostei.com/grant/cpm/index.html) - I can't remember how I found that website now (or even why I started looking in the first place, but it was the start of a long journey I'm still on!) but as time has gone by, I'm starting to realise that it's a very basic and limited setup, both for hardware AND software. Still, it has provided no end of learning for me. I'd written a more up-to-date version of the Windows program he used to transfer files from Windows to CP/M, in C using VS 2017, so it won't take much to tweak it and make it fully Intel Hex-compatible. I can then just write a new DOWNLOAD.COM to read in Intel Hex streams, rather than the custom format that Grant had implemented.


Yep I have a NASCOM 2. Seen there is a guy who keeps posting NASCOM stuff. I may put a bid on for the I/O card. Thanks for thinking of me...

I was looking at the vintage computers there (well, Spectrums, Commodores, Amstrads and the like) and came across that and thought - 'Dave'!! I remembered you mentioning your venerable PDP-11 at Christmas (have you got it all moved back now?) and thought you might be interested. ;)

nockieboy
February 5th, 2018, 06:48 AM
Okay, an update on the problems downloading files via the terminal into CP/M 3. Thanks to durgadas311's invaluable support re-writing DOWNLOAD.COM over the weekend to support Intel Hex format file transfers, I've been able to do a little more testing of the file transfer system in CP/M 3.

Just to recap for those jumping in after a while away, the only way I can transfer files from my PC to my SBC is by pasting a formatted ASCII hex-dump of the file. I say formatted, because at the start it includes a few parameters and runs the DOWNLOAD.COM file in CP/M to receive the rest of the hex dump. The hex dump is an Intel Hex format data stream, addressed from 0100 onwards. It is designed to be pasted directly into the CP/M console, where DOWNLOAD.COM is loaded and receives the rest of the pasted data, which it saves to a new (and appropriately-named) file.

It works flawlessly in CP/M 2.2. However, not so well in CP/M 3. With the revised DOWNLOAD.COM now taking Intel Hex files, it seems to be completing the download and returning to the command prompt without issue (this is a big improvement on the old DOWNLOAD.COM which would crash CP/M 3.)

However, the downloaded file seems to be consistently missing the first record of the downloaded file. I've transferred a small program and to use as an example. This is what I'm pasting into the terminal:


A:DOWNLOAD DATETIME.COM
U0
X02A8
:4001000021550311800019F921F901110402CD0103211C021 10402CD01032180007E23B7281D477E23FE2FCA2F0110F7C33 F017EFE3FCAEC01E65F320302FE55CA9801E599
:4001400021F901CD1B032104027EFE78CA4901E13A0302FE4 4CA6D01FE54CA7501FE57CA7D011104020E09CD0500C3F4012 10402060AC38201210F020608C382012118028B
:4001800006037EFE24CAF401C5E55F0E02CD0500E1C12310E DC3F4013E0047112202237EFE20CA9E01FE24CAC801FE00CAC 8012B237EFE24CAC801FE00CAC8010412137897
:4001C000FE10DAB001C3D3011137020E09CD0500C3F4013E2 312133E2412211C02CD1B032104027EFE78CAE301C36201117 6020E09CD05000E00CD0500255A48684C6C2375
:400200000D0A240078302D30302D303030302D30303A30303 A30302D78787824255548684C6C30302D30302D303030302D3 0303A30303A30302324557064617465642064D8
:4002400061746520616E642074696D65204D5553542062652 0696E207468697320666F726D61743A2064642F6D6D2F59595 9592068683A6D6D244441544554494D45207691
:40028000312E312E3433202843292032303137204A2E204E4 F434B0D0A446973706C617973207468652063757272656E742 06461746520616E642F6F722074696D6520663E
:4002C000726F6D20746865207265616C74696D6520636C6F6 36B2E0D0A5573653A204441544554494D45205B6F7074696F6 E616C202F442C202F542C202F572C202F555D55
:400300002423237ACD3E0377237ACD440377237BCD3E03772 37BCD440377C9F57EFE24CA2903CD2B0323C31C03F1C9F5CD3 50328FBF1D301C997D303DB030FCB4FC9E6F014
:400340000F0F0F0FE60FFE0ADA5203D609F640C35403F630C 90000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000F7
:00000001FF

And below is a dump of the downloaded file:


F>A:DUMP DATETIME.COM

0000 21 F9 01 CD 1B 03 21 04 02 7E FE 78 CA 49 01 E1
0010 3A 03 02 FE 44 CA 6D 01 FE 54 CA 75 01 FE 57 CA
0020 7D 01 11 04 02 0E 09 CD 05 00 C3 F4 01 21 04 02
0030 06 0A C3 82 01 21 0F 02 06 08 C3 82 01 21 18 02
0040 06 03 7E FE 24 CA F4 01 C5 E5 5F 0E 02 CD 05 00
0050 E1 C1 23 10 ED C3 F4 01 3E 00 47 11 22 02 23 7E
0060 FE 20 CA 9E 01 FE 24 CA C8 01 FE 00 CA C8 01 2B
0070 23 7E FE 24 CA C8 01 FE 00 CA C8 01 04 12 13 78
0080 FE 10 DA B0 01 C3 D3 01 11 37 02 0E 09 CD 05 00
0090 C3 F4 01 3E 23 12 13 3E 24 12 21 1C 02 CD 1B 03
00A0 21 04 02 7E FE 78 CA E3 01 C3 62 01 11 76 02 0E
00B0 09 CD 05 00 0E 00 CD 05 00 25 5A 48 68 4C 6C 23
00C0 0D 0A 24 00 78 30 2D 30 30 2D 30 30 30 30 2D 30
00D0 30 3A 30 30 3A 30 30 2D 78 78 78 24 25 55 48 68
00E0 4C 6C 30 30 2D 30 30 2D 30 30 30 30 2D 30 30 3A
00F0 30 30 3A 30 30 23 24 55 70 64 61 74 65 64 20 64
0100 61 74 65 20 61 6E 64 20 74 69 6D 65 20 4D 55 53
0110 54 20 62 65 20 69 6E 20 74 68 69 73 20 66 6F 72
0120 6D 61 74 3A 20 64 64 2F 6D 6D 2F 59 59 59 59 20
0130 68 68 3A 6D 6D 24 44 41 54 45 54 49 4D 45 20 76
0140 31 2E 31 2E 34 33 20 28 43 29 20 32 30 31 37 20
0150 4A 2E 20 4E 4F 43 4B 0D 0A 44 69 73 70 6C 61 79
0160 73 20 74 68 65 20 63 75 72 72 65 6E 74 20 64 61
0170 74 65 20 61 6E 64 2F 6F 72 20 74 69 6D 65 20 66
0180 72 6F 6D 20 74 68 65 20 72 65 61 6C 74 69 6D 65
0190 20 63 6C 6F 63 6B 2E 0D 0A 55 73 65 3A 20 44 41
01A0 54 45 54 49 4D 45 20 5B 6F 70 74 69 6F 6E 61 6C
01B0 20 2F 44 2C 20 2F 54 2C 20 2F 57 2C 20 2F 55 5D
01C0 24 23 23 7A CD 3E 03 77 23 7A CD 44 03 77 23 7B
01D0 CD 3E 03 77 23 7B CD 44 03 77 C9 F5 7E FE 24 CA
01E0 29 03 CD 2B 03 23 C3 1C 03 F1 C9 F5 CD 35 03 28
01F0 FB F1 D3 01 C9 97 D3 03 DB 03 0F CB 4F C9 E6 F0
0200 0F 0F 0F 0F E6 0F FE 0A DA 52 03 D6 09 F6 40 C3
0210 54 03 F6 30 C9 00 00 00 00 00 00 00 00 00 00 00
0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0240 24 23 23 7A CD 3E 03 77 23 7A CD 44 03 77 23 7B
0250 CD 3E 03 77 23 7B CD 44 03 77 C9 F5 7E FE 24 CA
0260 29 03 CD 2B 03 23 C3 1C 03 F1 C9 F5 CD 35 03 28
0270 FB F1 D3 01 C9 97 D3 03 DB 03 0F CB 4F C9 E6 F0


As you can see, the first record from the pasted data is missing from the saved file. Not sure why this is happening in CP/M 3 but not in CP/M 2.2. As I said, DOWNLOAD.COM in CP/M 2.2 is rock solid.

I'm thinking I'm going to have to revisit BIOS3 and have a closer look at the I in IO...

durgadas311
February 5th, 2018, 03:41 PM
My guess would be that somehow a character is getting lost (maybe a couple) at the beginning, causing download to skip the rest of the first line while looking for a ':'. But with the "U" and "X" lines you'd think it would have settled down by then. Maybe something to do with CP/M 3 handling of "ctrl C" and interrupt buffers in the BIOS? Will take some more pondering... I'll see if I can reproduce on my end where debugging might be easier.

nockieboy
February 5th, 2018, 11:49 PM
My guess would be that somehow a character is getting lost (maybe a couple) at the beginning, causing download to skip the rest of the first line while looking for a ':'. But with the "U" and "X" lines you'd think it would have settled down by then. Maybe something to do with CP/M 3 handling of "ctrl C" and interrupt buffers in the BIOS? Will take some more pondering... I'll see if I can reproduce on my end where debugging might be easier.

Yes, dropping the first ':' (amongst others) would cause the issue I'm seeing, but CP/M 3 is clearly receiving the first line (as DOWNLOAD.COM is loading and using the correct filename to save the data as) - when I get more time to look at it again I'll add some debug prints to see if the user is being assigned with the U command and X is also being received.

For info, it does exactly the same thing whether running at 4 MHz or 8 MHz - I'm confident it's not a connection speed issue or buffers being overflowed as I have full CTS/RTS flow control on (at least I do in CP/M 2.2 BIOS..... trying to remember if it was implemented in BIOS3 as initially we went with polled IO.... maybe the first thing for me to check later!)

durgadas311
February 6th, 2018, 04:48 AM
Note, the filename is specified on the commandline and so it is CCP that is receiving it. Also, it is using BDOS function 10 which inputs a whole line and allows editing. I assume you do not paste the HEX file until after you have started DOWNLOAD, in which case it is using BDOS function 6 "Direct Console I/O". Will have to look for places to lose characters. Are you sure you are not also losing characters in the middle? One thought is that BDOS might be doing a check for Ctrl-C during disk I/O and thus might gobble a character. I think there's a way to turn that off, but I also thought BDOS function 6 handled that "snooped character".

nockieboy
February 6th, 2018, 06:48 AM
I assume you do not paste the HEX file until after you have started DOWNLOAD, in which case it is using BDOS function 6 "Direct Console I/O".

It's all one pasted block of ASCII - the clipboard will contain something like this (exact hex contents will differ according to file, obviously):


A:DOWNLOAD BOOST.COM
U0
X0110
:4001000021EF0111800019F93AE0E6FE32CA2001FE34CA2B0 11146013E3232E0E6C33301115B013E3432E0E6C3330111720 13E3832E0E60E09CD0500218901CD8C01CDAFE7
:40014000010E00CD050044726F7070696E6720746F2032204 D487A2E2E2E24496E6372656173696E6720746F2034204D487 A2E2E2E24496E6372656173696E6720746F20CC
:4001800038204D487A2E2E2E24255824F57EFE24CA9A01CD9 C0123C38D01F1C9F5CDA60128FBF1D301C997D303DB030FCB4 FC93E00D3023E18D3023E04D3023AE0E6FE321B
:4001C000CACD01FE38CAD2013E84C3D4013E44C3D4013EC4D 3023E01D3023E18D3023E03D3023EE1D3023E05D3023EEAD30 2C9000000000000000000000000000000000022
:00000001FF


Each line is separated by a CR & LF char.

durgadas311
February 6th, 2018, 06:59 AM
oh, that is more problematic. You've got CP/M loading the program, preparing to run it, then the program itself starting up and making BDOS calls to erase and make the file. I'm guessing there is something going on in CP/M 3 (BDOS or BIOS, or even CCP/LOADER.RSX) that is resulting in loss of characters. I would have expected that you typed A:DOWNLOAD BOOST.COM(cr) manually and then pasted text after DOWNLOAD got started. It might be helpful to see if it works that way, then we know better where to look for the issue.

nockieboy
February 6th, 2018, 07:12 AM
Yeah, works fine if I enter "DOWNLOAD LS.COM" manually, press enter, then type 'U0X0CC0' then paste the Intel Hex data...

I've noticed that even in CP/M 2.2, it's dropping the U-line and only receiving the X-line onwards. Obviously CP/M 3 takes a little longer to start DOWNLOAD.COM up before receiving chars from the terminal again... Perhaps some padding chars are needed... (Or just a better way to download files!) :)

EDIT: Yes, a couple of lines of padding chars makes it work fine.

durgadas311
February 6th, 2018, 07:17 AM
I still would hope that characters would not get lost, but we're dealing with something no one anticipated in 1980... a virtual terminal window where you can paste a bucket-load of characters full-speed into the serial port. I used to take advantage of the type-ahead feature of interrupt-driven console input on CP/M 2.2 and CP/M 3 - and didn't notice issues. But, I can't type as fast as data is pasted into a terminal window.

It could be that something the CCP is doing during program load/start is resulting in loss of characters. Is there any operation that the BIOS does which results in discarding the interrupt buffer contents? Or any extended period of time where interrupts are disabled?

nockieboy
February 6th, 2018, 07:43 AM
I still would hope that characters would not get lost, but we're dealing with something no one anticipated in 1980...

Yeah, damn those short-sighted programmers. No vision or appreciation of Moore's Law. ;)


It could be that something the CCP is doing during program load/start is resulting in loss of characters. Is there any operation that the BIOS does which results in discarding the interrupt buffer contents? Or any extended period of time where interrupts are disabled?

Hmm.. not sure. I'll have to take a look when I get some more free time (tomorrow now). I've updated the TAP Manager to insert a disclaimer between the first and second lines, I'm able to download files to CP/M 3 with no issue now.

durgadas311
February 6th, 2018, 11:58 AM
I was doing a little math, and - at least for 4MHz - the interrupt handling is living on the edge. At 125Kbaud characters will be coming in every 80 microseconds. The interrupt routine, when setting RTS off, will take about 74 microseconds (about 65 uS if no RTS manipulation is required). Add this to the CONIN routine holding interrupts disabled (when updating the use count/RTS) taking about 30 uS (21 uS w/o RTS), it is all getting pretty tight. That does not explain why 8MHz still has issues (unless 8MHz is not really getting turned on).

Another thought is that RTS is getting mishandled someplace, perhaps some race condition, and is thus not staying off so the remote end keeps sending.

nockieboy
February 6th, 2018, 12:25 PM
I guess I could always drop the baud rate down to 62500 if it becomes an issue in the future. (If I recall correctly, that's the speed of GS's original SBC design.) As it is, the extra chars I'm inserting between the 1st and 2nd lines are doing the job nicely. :)

nockieboy
February 13th, 2018, 01:53 AM
Here's a thought that just popped into my head whilst I was working...

Would there be much alteration required to get CP/M 3 to run from ROM?

I suspect the question is a very flimsy lid barely holding in the teeming mass of worms desperate to burst forth, but I've gone and asked it now.. ;)

durgadas311
February 13th, 2018, 05:07 AM
I don't know if you could run from ROM, but you definitely could boot/load from ROM. Not sure if that saves much. I'm pretty sure the BDOS does not have any self-modifying code, but it is not well separated into code and data segments. So, you'd have to do some sort of rework/recompile in order to get all variables to be placed in another part of the address space. Another complication is that any changes to the size of BIOS3 will require the BDOS to be relocated, thus GENCPM.

nockieboy
February 13th, 2018, 07:46 AM
I don't know if you could run from ROM, but you definitely could boot/load from ROM. Not sure if that saves much. I'm pretty sure the BDOS does not have any self-modifying code, but it is not well separated into code and data segments. So, you'd have to do some sort of rework/recompile in order to get all variables to be placed in another part of the address space. Another complication is that any changes to the size of BIOS3 will require the BDOS to be relocated, thus GENCPM.

Fair enough - sounds like a prohibitively complicated task as I suspected. Will reign my plans in a little then - I'm planning on using some unused memory by dumping CPM22.HEX and both CBIOS64 and CBIOS128.HEX into ROM to negate having to paste them into the DMI terminal to install CPM.

Plasmo
February 26th, 2018, 03:48 AM
This is a great thread. I followed it when it originally started in December 2017, even participated a bit with respect to the CF problem but I didn't have any experience with Z80 and CPM 3 so I don't really appreciate the intricacy of the problems at the time. Since then I've designed a Z280 SBC from scratch and learning it and Z80 assembly as I go. I successfully ported CPM 2.2 to it about 2 weeks ago. My system has 16 meg of memory, 8 meg of it is RAM disk. Including the RAM disk, it has 5 8-meg drives, the other 4 are 8-meg partitions on a CF drive. It does not have ROM, it boots off bootsector of the CF. With hardware working running CPM2.2 I started on CPM 3 about 10 days ago and ran into the same set of problems that nockieboy was having. The CPM3 System Guide was not helpful, it was a tangle mess of banked & non-banked descriptions; the proliferation of tables are maddening; and the magic of SCB/CPMGEN are difficult to grasp. I'm also new to Z80 and used Zilog Developer Studio (ZDS) to port CPM 2.2 in Windows environment. As far as I can tell, ZDS does not produce .rel file, so I picked up ZMAC as mentioned in the discussion. I fought it but have resigned to the reality that I need to learn 8080 mnemonics to program Zx80! I started with the LDRBIOS from cpm3on2.zip downloaded from cpm.z80.de and struggled with it unsuccessfully. Yesterday I started reading this thread again from the beginning. My CPMLDR is doing approximately the same thing as nockieboy's in Dec 20--gibberish followed by " CPMLDR error: failed to read CPM3.SYS" I'm at message #82, going to do durgadas311's simple bios3. You are getting first class coaching, nockieboy. I don't know how people brought up CPM 3 35 years ago.

This should refresh the thread. Another member of vcfed is also working on a new Z80 design, this should be a good reference when he is ready to port CPM3

daver2
February 26th, 2018, 04:21 AM
One of the benefits of being a member of VCFED - excellent guidance of people who have boldly gone where no one has gone for 30 odd years :-)!

Back in the day you probably would have gone on a training course...

As you have found, the CP/M 3 manual is a little bit of a "dog's dinner" in terms of being reader friendly :-(.

Oh well, I have a CP/M 3 port to come (along with MP/M) sometime this year - so I will be reading this thread myself again in the future...

Dave

durgadas311
February 26th, 2018, 04:53 AM
Yes, the CP/M 3 manuals are not a good starting point for a newbie. I had been working in, and porting, CP/M 2.2 for several years before I tackled CP/M 3. I also got to attend many Digital Research seminars and had a rapport with many of the developers. But without those prerequisites, it is a difficult task to say the least. A lot of "strange and interesting" things happen when CP/M 3 crashes.

Plasmo
February 26th, 2018, 06:34 AM
The dmybios3 of message #82 is very helpful. It breaks down the problem and shows whether the problem is with CPMLDR.com or CPM3.sys. It turns out my problem is with CPMLDR DPB table entries PSH & PHM. I manage my own blocking/deblocking, so PSH & PHM should both be 0. Once I corrected that, the CPMLDR is able to read CPM3.sys, execute the boot code, print out the short message, then halted, as it should. I tried the bigger stack suggested in message #73, but that wasn't the problem. The problem was CPMLDR doing blocking/deblocking twice which trash the CF sector read data. That's why I'm getting the "CPMLDR error: failed to read CPM3.SYS" message.

At this point I'll break away from the discussion thread to work on non-banked BIOS3. The whole banked concept is difficult to grasp and furthermore, I'm still wrestling with Z280's MMU. I want to get a non-banked CPM3 running first and then sneak up to the banked version.

Alphasite
February 26th, 2018, 06:39 AM
I first wrote a CP/M 2.2 BIOS for the Model 4 (using the Ampro BIOS source as a reference) and later updated to CP/M Plus. All I had when updating to CP/M Plus was the sample BIOS source for the Altos 8000 and the CP/M Programmer's Encyclopedia. It made it interesting. I think some of what helped was that at one point I updated my 2.2 BIOS to use the alternate banks for the video and keyboard routines to increase the TPA.

Since I preferred Z80 mnemonics and had used them for my CP/M 2.2 BIOS the first thing I did was convert the sample source to Z80 mnemonics. I used M80 as the assembler.

durgadas311
February 26th, 2018, 07:00 AM
At this point I'll break away from the discussion thread to work on non-banked BIOS3. The whole banked concept is difficult to grasp and furthermore, I'm still wrestling with Z280's MMU. I want to get a non-banked CPM3 running first and then sneak up to the banked version.

I understand. You may find, however, that it doesn't help much. non-banked CP/M 3 is about the same level of difficulty as CP/M 2.2 and since you've already done CP/M 2.2 it should be a trivial/lateral step. The big wins come with the banked version, and it will still be a big step to get there. All I'm saying is, don't expect doing non-banked first to make the banked version (much) easier.

nockieboy
February 26th, 2018, 08:18 AM
Well, if it's any help Plasmo my SBC is running CP/M 3 without any issues now - so unless you've got some hardware-specific issues with running CP/M on the Z280, this thread should hopefully give you a fighting chance of getting CP/M 3 running on it.


One of the benefits of being a member of VCFED - excellent guidance of people who have boldly gone where no one has gone for 30 odd years :-)!

Hahahaha!! :D So true! Doesn't feel like 30 years, though. ;)

I'm faffing around at the moment in between unpacking boxes of house stuff, doing some work on writing a disassembler for my SBC's ROM. I'm trying to find things to occupy me and distract me from a pretty big bug I'm hitting consistently - Sector 0 on my CF card seems to be corrupting after power-down. At first I thought it was a faulty CF card (I'd started using a 128MB card to test the format routines I'd ported to ROM) but the exact same thing is happening with my original 64MB card and another 64MB one as well.

When I switch the SBC on and try to load CP/M (2.2), the DMI (monitor ROM) won't switch to CP/M as the last two pages of memory (FE00-FFFF) don't seem to be loading from Sector 0, or just contain random garbage. This seems to have occurred since I started using the 128MB BIOS for CP/M 2.2. Because of the extra drive tables, the 128MB BIOS takes up a bit more memory space and I've had to move CP/M from D000h to CE00h. Now, thinking about it, that seems to match the problem I'm seeing - the last two pages of RAM not containing the expected data when CP/M and BIOS have been moved 2 pages further down in RAM.... This is also happening with the 64MB BIOS version as well, as I've got CP/M starting at CE00h for that version as well for simplicity.

I've got CP/M and the relevant BIOS sitting in two banks of ROM (for 64 and 128MB versions) so I can just 'install' CP/M with a single command in the DMI and this negates the problem and allows me to run CP/M for the rest of the session (until power off.) This is because a drive read isn't involved, it just copies the contents of selected ROM bank into memory, guaranteeing that the full data makes it to RAM.

So... just writing this post has made me focus on the issue and given me some ideas... namely, moving CP/M to CE00h seems strongly related to the problem of no data appearing at FE00-FFFFh, and secondly the card reading routine to access the data from the CF card - could it be reading a fixed amount of data and thus not reading/writing to FE00 onwards? Will go have a look later when I have a chance..

durgadas311
February 26th, 2018, 08:46 AM
My first thought was about the signals to the CF card during power off. You'll need to make sure that - especially - CE stays high until after the CF looses power (internal shutdown). Maybe you've located a software source of the problem, but this is something to think about. Maybe the CF is supposed to handle power off, but I'm not sure how it would know the difference until power dropped below a certain level.

daver2
February 26th, 2018, 10:25 AM
Yes, have you put any pull-up resistors on the control lines to ensure they are held inactive?

I am interfacing my Comapct Flash to a Z80 at the moment via a PIO. On a reset, the PIO sets all it's ports to 'input', so the signals to the CF will be floating. I have, therefore, ensured that I have put some suitable pull-up resistors on the -CEn and -IORD and -IOWR signals (and a few others I think).

Also, when programming the PIO, if you program the port for OUTPUT (to drive the control signals on the CF) you will momentarily get '0' sent out on all the control lines. This could (erroneously) activate something within the CF. You can program the PIO output data register with the correct value (to ensure the CF control signals are all inactive) before programming the port to OUTPUT mode.

Worth a few minutes looking at what will happen when you power up and power down. Do you want to post your interface?

All this duplicates what durgadas311 has just said of course :-).

Dave