RL11 controller #2 - initial tests

Connecting the drive to this controller makes the drive not become ready. testing the clock signal at the drive showed that it did not arrive there. There was just a small error in the band cable, so that was fixed. After that let’s run ZRLG. This fails with:

CZRLG DVC FTL ERR  00037 ON UNIT 00 TST 032 SUB 000 PC: 023054
BAD HEADER CRC ON READ HEADER
CONTROLLER: 174400  DRIVE: 0
BEFORE COMMAND: CS: 000211 BA: 002416 DA: 000001 MP: 004012
TIME OF ERROR:  CS: 000211 BA: 002416 DA: 000001 MP: 000007?
EXP'D: 072001 REC'D: 002001

ERR HLT

The fiche for the test is:

The test executes a READ HEADER command. It then reads the 1st two words from the MP register (the cylinder/track count in the first word and the second word is all zeroes). It calculates a checksum from these two words (in code) and the reads the 3rd word and compares it with the checksum. These should be equal but clearly are not.

This is hard to debug from just the LA trace, so I made a protocol decoder for Sigrok: syncserial. This decoder decodes the data from the serial data stream so that we can more easily understand what we see. One such trace looks like this:

We can see that the first word (sector/track) is 0xA000, the second word is all zeroes (which is according to spec) and the third word, the CRC, is 0x0033. This should translate to sector 320, head 0, sector 0.

The CRC calculation

The CRC for the header gets calculated by the routine SIMBCC. This method gets called through r5, and expects 3 words after the call:

  • The number of bits to sum (usually 16)
  • The actual data word to add to the crc (i.e. one of the words read from the header)
  • The previous value calculated for the crc, starting with 0 for the 1st word.

I created the following macro11 source file to be able to run the actual code for the crc check:

.title	CRC calc
.enable	ama
.enable	abs
	.asect

.=2000

	jsr	r5,simbcc
	.word	16.
	.word	120000
	.word	0
	mov	temp4,5$
	jsr	r5,simbcc
	.word	16.
	.word	0
5$:	.word	0
	halt

simbcc:	mov	(r5)+,temp2
	mov	(r5)+,temp3
	mov	(r5)+,temp4
1$:	clr	bccfbk
	mov	temp4,r0
	ror	temp3
	adc	r0
	bit	#1,r0
	beq	2$
	com	bccfbk
2$:	mov	xpoly,r0
	com	r0
	bic	r0,bccfbk
	clc
	ror	temp4
	mov	bccfbk,r0
	mov	temp4,r1
	mov	r1,r2
	bic	r1,r0
	bic	bccfbk,r2
	bis	r2,r0
	bic	xpoly,temp4
	bis	r0,temp4
	dec	temp2
	bne	1$
	mov	temp4,r0
	rts	r5

XPOLY:	.word	120001
TEMP2:	.word	0
TEMP3:	.word	0
TEMP4:	.word	0
BCCFBK:	.word	0

This should be a direct copy of the code from the fiche. There were some nice discoveries made along the way:

  • The macro11 assembler I used (https://github.com/j-hoppe/MACRO11) really does not give a f about errors. It more or less accepts anything. I entered the text “My mother wears yellow socks” just in the middle of the code and no error occurred at all. Absolutely terrible.
  • As I need code that I can load nicely I need it to assemble at an absolute address. For that we use the stanza “.=2000”, i.e. set the pc to 2000(octal). This DOES give a very uninformative error (bad ORG). After a lot of reading I found out that you need to add “.asect” before the org statement to make the section absolute.
  • The xxdp module contained “.enable abs” at the top. I had not noticed the dot before the enable. This led to all code being made PC relative. Which is not that bad, but the listing does NOT show the actual words generated but the target addresses with a single quote behind them. The Unibone did not mind that ’, and loaded the words as the actual words. This led to wildly misbehaving code. Only after manually verifying everything that was deposited in memory it became apparent what horrors had occurred. Not Fun.

Anyway. The start of the program contains the actual crc calculation for the data we read from the sector: first word 0xa000 (120000 oct), second word zeroes.

We can run this program on the Unibone by first compiling it with macro11 and copying it to the Unibone:

macro11 -l crc.lst crc.mac
scp crc.lst root@ubex:10.03_app_demo/5_applications/cpu/

(ubex is the host name of my Unibone).

We then create a boot script like this:

#!/root/10.03_app_demo/4_deploy/demo

# Inputfile for demo to execute "Hello world"
# Uses emulated CPU and (physical or emulated) DL11
# Read in with command line option  "demo --cmdfile ..."

dc                      # "device with cpu" menu

m i                     # emulate missing memory
sd dl11

p p ttyS2               # use "UART2 connector, see FAQ

# p b 300               # reduced baudrate

en dl11                 # switch on emulated DL11

en cpu20                # switch on emulated 11/20 CPU
sd cpu20                # select

m ll crc.lst            # load test program

p

init
p pc 2000

.print Enter p s 1 to run the program

This loads the listing in memory, ready to be executed. Entering p s 1 will start the CPU, it will halt after the code finishes and show the crc in r0:

DC>>> R0 021000 R1 021000 R2 021000 R3 000000 R4 000000 R5 000000 R6 000000 R7 002034
10 021000 11 021000 12 000000 13 000000 14 000000 15 000000 16 000000 17 000000
BA 002032 IR 000000 PSW 000

i.e. the sum is 21000, or 0x2200. I validated it with a Java program that implemented the same algorithm. This is a lot different from the value received (0x33).

© 2024 by Frits Jalvingh. All information in here can be freely used (MIT License)