Jump to content
IGNORED

CPM/Z-80 card for the 1090XL -- Calling anyone with Z-80 experience!


Recommended Posts

I decided to keep the track/sector addressing and spent a lot of time looking at the disk calculations to make sure the buffers are correct.  I think only the warm start code needs finished.  In particular, I need to have it re-load CCP and BDOS.

 

Here's the current BIOS file...

 

CBIOS.asm

  • Like 3
Link to comment
Share on other sites

Looks good! Doing a little more on the Z80 side then I would have done, but it makes sense to not delegate some of the BIOS functions to the Atari (SELDISK and friends for example). Regarding loading BDOS from disk, I would make BDOS part of the initialization process. After that it never has to be loaded again. Lots of the original CP/Ms did that too. It's not supposed to be overwritten, ever. You also have a chicken and egg problem, because if there's no BDOS, you cannot read BDOS.SYS from the filesystem because there is no filesystem handler, which is BDOS. Regarding loading CCP.SYS, you can keep a copy in 6502 RAM and have WBOOT copy that over to the shared RAM. That's a lot faster.

 

To summarize, the Atari bootcode loads BDOS and BIOS into the shared RAM, and CCP in its own RAM, and starts running its mainloop. BIOS will request CCP to be copied during WBOOT.

 

Edit: I noticed you reserve only one byte for IOTrack, but that should be two bytes.

 

Edit2: changed observation on what to do at the Z80 side and what to delegate :)

Edited by ivop
  • Like 2
Link to comment
Share on other sites

Posted (edited)

@ivop

 

Well, I've got more than one chicken/egg problem.  I don't have any CP/M disks with an Atari 1050 compatible format.  I am thinking about modifying a BASIC program I wrote back in the late 1980's so that it can read a CP/M directory, format a disk for CP/M, copy files to a CP/M disk, install BDOS, CCP, and the BIOS, etc.  I need to take a look at it and see how easy it would be to modify.  It did a lot of DOS-like functions.

 

The easiest thing to do would be to add the code to the BIOS to load CCP and BDOS.  (CCP, BDOS, and the BIOS would all be installed starting on track 0, sector 2, to track 3, sector 5, so no file system would be necessary to load them.)  Then all the Atari has to do is to load the BIOS and turn it over to the Z-80.  I guess right now the big thing is to get it working.  Once it is working other tweaks could be made to optimize things a little better.

 

Then I've got a little problem getting the code over to the Atari as I don't have an S-Drive nor do I have a working FujiNet yet.   lol    I may just flash everything onto a 1090XL firmware board ROM and load the ROM into different files.

 

 

 

Edited by reifsnyderb
  • Like 1
Link to comment
Share on other sites

Perhaps you can get one of these?

 

https://www.amazon.com/JANSANE-PL2303TA-Serial-Console-Raspberry/dp/B07D9R5JFK/ref=sr_1_9?crid=288FWF02G11QF&dib=eyJ2IjoiMSJ9.mmFSFgBLhSyBOomkkUq4yGiGWlh3AaGYTCkOhDC2QZduSly4-Yzhl7JdHD-4CC81nIkrAl-ofLD96FOelis17PeCkBgfwUyNj9ZLgnkbq_EQczRxgiPwHyjuUM0_Bw7XgI-CWE8h6yANbhuw0D76JcVjP0mPFiDhxfOSjJXQHOYfv39TE2FoFuo_n_vK6g4Q2moOMGeTJvVCS0BEAVnT77NzsfdN4CVbS6fQ7Xm0N84.GkiLOa55xzFbxdRgzi-yOANRtstWuqF82ZkybvnwkLk&dib_tag=se&keywords=usb+ttl+serial&qid=1712539626&sprefix=usb+ttl+serial%2Caps%2C195&sr=8-9

 

Wired to the SIO port you should be able to run RespeQt. Otherwise you are making it a lot more difficult for yourself than necessary, writing a CP/M writer in Basic and all that. Create the raw disk image by concatenating the 54 sectors boot block with (720-54)*128 zeroes and use mkfs.cpm and cpmcp to put other files there, like PIP.COM, STAT.COM, etc... Prepend ATR header for 720 sectors of 128 bytes. Boot from that or sector copy to a blank disk.

 

If you leverage the Atari OS boot mechanism, it'll load the first three tracks (54 sectors) automatically somewhere in memory. Most of the time $0700, but that is not a requirement. Also 3 boot sectors is not fixed, you can set that to 54. After that you can fast memcopy the Z80 code in place (BIOS and BDOS), and let WBOOT trigger a LoadCCP command to the Atari, which memcopies the CCP in place. This is not far off from what Atari did with their implementation. In mads that would be something like:

 

    opt h-

    org $0700

    .byte 0
    .byte 54
    .word $0700
    .word main

main:
    ; code here
    ; copy $1400 bytes from BDOS to shared memory at $ec00
    ; start Z80
loop:
    ; wait for IO request, dispatch with jump table or several cmp's
    ...
    ; in LoadCCP call, copy $0800 bytes from CCP to $e400 in shared memory
    ....
    jmp loop

CCP:
    ins 'ccp.sys'    ; $0800 bytes, at $e400 in shared memory

BDOS:
    ins 'bdos.sys'   ; $0e00 bytes, at $ec00 in shared memory

BIOS:
    ins 'bios.sys'   ; $0600 bytes, at $fa00 in shared memory

 

If you don't want to or are unable to get a SIO2PC capable cable and want to use your 1090 ROM method, you can also, depending on the amount of ROM available, create the CP/M disk as described earlier, not turn it into an ATR, but just copy as much from the beginning of the disk image file to the ROM and write the ROM contents to a blank formatted disk with (Turbo) Basic. You can check if all the files you copied to the CP/M disk fit by first creating the FS on a non-zero padded file (just specify a non-existent disk.img file) and see how large it becomes after cpmcp. cpmcp does not expand the image file to the actual FS size. BTW with mkfs.cpm -f yourformatindiskdefs -b bootblock.bin disk.img you can automatically include the boot block created with mads. Hope this'll save you some time ;)

Edited by ivop
  • Like 3
Link to comment
Share on other sites

54 minutes ago, ivop said:

Perhaps you can get one of these?

 

https://www.amazon.com/JANSANE-PL2303TA-Serial-Console-Raspberry/dp/B07D9R5JFK/ref=sr_1_9?crid=288FWF02G11QF&dib=eyJ2IjoiMSJ9.mmFSFgBLhSyBOomkkUq4yGiGWlh3AaGYTCkOhDC2QZduSly4-Yzhl7JdHD-4CC81nIkrAl-ofLD96FOelis17PeCkBgfwUyNj9ZLgnkbq_EQczRxgiPwHyjuUM0_Bw7XgI-CWE8h6yANbhuw0D76JcVjP0mPFiDhxfOSjJXQHOYfv39TE2FoFuo_n_vK6g4Q2moOMGeTJvVCS0BEAVnT77NzsfdN4CVbS6fQ7Xm0N84.GkiLOa55xzFbxdRgzi-yOANRtstWuqF82ZkybvnwkLk&dib_tag=se&keywords=usb+ttl+serial&qid=1712539626&sprefix=usb+ttl+serial%2Caps%2C195&sr=8-9

 

Wired to the SIO port you should be able to run RespeQt. Otherwise you are making it a lot more difficult for yourself than necessary, writing a CP/M writer in Basic and all that. Create the raw disk image by concatenating the 54 sectors boot block with (720-54)*128 zeroes and use mkfs.cpm and cpmcp to put other files there, like PIP.COM, STAT.COM, etc... Prepend ATR header for 720 sectors of 128 bytes. Boot from that or sector copy to a blank disk.

 

If you leverage the Atari OS boot mechanism, it'll load the first three tracks (54 sectors) automatically somewhere in memory. Most of the time $0700, but that is not a requirement. Also 3 boot sectors is not fixed, you can set that to 54. After that you can fast memcopy the Z80 code in place (BIOS and BDOS), and let WBOOT trigger a LoadCCP command to the Atari, which memcopies the CCP in place. This is not far off from what Atari did with their implementation. In mads that would be something like:

 

    opt h-

    org $0700

    .byte 0
    .byte 54
    .word $0700
    .word main

main:
    ; code here
    ; copy $1400 bytes from BDOS to shared memory at $ec00
    ; start Z80
loop:
    ; wait for IO request, dispatch with jump table or several cmp's
    ...
    ; in LoadCCP call, copy $0800 bytes from CCP to $e400 in shared memory
    ....
    jmp loop

CCP:
    ins 'ccp.sys'    ; $0800 bytes, at $e400 in shared memory

BDOS:
    ins 'bdos.sys'   ; $0e00 bytes, at $ec00 in shared memory

BIOS:
    ins 'bios.sys'   ; $0600 bytes, at $fa00 in shared memory

 

If you don't want to or are unable to get a SIO2PC capable cable and want to use your 1090 ROM method, you can also, depending on the amount of ROM available, create the CP/M disk as described earlier, not turn it into an ATR, but just copy as much from the beginning of the disk image file to the ROM and write the ROM contents to a blank formatted disk with (Turbo) Basic. You can check if all the files you copied to the CP/M disk fit by first creating the FS on a non-zero padded file (just specify a non-existent disk.img file) and see how large it becomes after cpmcp. cpmcp does not expand the image file to the actual FS size. BTW with mkfs.cpm -f yourformatindiskdefs -b bootblock.bin disk.img you can automatically include the boot block created with mads. Hope this'll save you some time ;)

I'll have a cable coming tomorrow. 

 

You've got me thinking about this some more.  Leveraging the Atari boot loading process is a great idea.  Either way, at the earliest it will be the end of the week until I can have a working Z-80 board.  So, there's some time.  🙂

 

  • Like 1
Link to comment
Share on other sites

Posted (edited)

Ok.  I re-did my calculations as how to fit everything into the normal CP/M boot area.  Keep in mind I am planning to use the 1050's density and a half format.  Boot track layout is at the bottom.

 


; 	Calculations:
;
;  	Size of CCP = $EC00 - $E400 = $800 = 2048 bytes (16 sectors)
;	Size of  BDOS = $FA00 - $EC00 = $E00 = 3584 bytes (28 sectors)
;	Size of BIOS = $FFFF - $FA00 = $5FF = 1535 bytes (12 sectors)
;	Total size of CCP + BDOS + BIOS =  $1BFF = 7167 bytes
;	Bytes per Track: = 128 bytes * 26 sectors = 3328 bytes
;	128 byte sectors needed for CCP + BDOS + BIOS  =  56 sectors
;	Bytes per directory entry :  32
;	Directory entries per sector:  4
;
;	Directory entries are 32 bytes.  4 entries per 128 byte sector.
;
;	Drive storage capacity 	= Tracks 4 to 40 + 1152 bytes 
;							= 36 * 3328 + 1152 = 119808 + 1152 = 120960
;							= 120960 / 1024 bytes per block = 118 = $76
;
;	Boot track layout:
;	Track 0		Sectors 	1-12		Atari boot sector, BIOS loader, and CP/M I/O - 1536 bytes max
;	Track 0		Sectors 	13-26		BIOS - 1535 bytes max starting at FA00
;	Track 1		Sectors		1-16		CCP - 2048 bytes starting at  E400
;	Track 1		Sectors 	17-26		BDOS - 1152 bytes starting at EC00
;	Track 2		Sectors		1-19		BDOS - 2432 bytes

 

 

Edited by reifsnyderb
  • Like 1
Link to comment
Share on other sites

12 hours ago, reifsnyderb said:

Ok.  I re-did my calculations as how to fit everything into the normal CP/M boot area.  Keep in mind I am planning to use the 1050's density and a half format.  Boot track layout is at the bottom.

 

; 	Calculations:
;
;  	Size of CCP = $EC00 - $E400 = $800 = 2048 bytes (16 sectors)
;	Size of  BDOS = $FA00 - $EC00 = $E00 = 3584 bytes (28 sectors)
;	Size of BIOS = $FFFF - $FA00 = $5FF = 1535 bytes (12 sectors)
;	Total size of CCP + BDOS + BIOS =  $1BFF = 7167 bytes
;	Bytes per Track: = 128 bytes * 26 sectors = 3328 bytes
;	128 byte sectors needed for CCP + BDOS + BIOS  =  56 sectors
;	Bytes per directory entry :  32
;	Directory entries per sector:  4
;
;	Directory entries are 32 bytes.  4 entries per 128 byte sector.
;
;	Drive storage capacity 	= Tracks 4 to 40 + 1152 bytes 
;							= 36 * 3328 + 1152 = 119808 + 1152 = 120960
;							= 120960 / 1024 bytes per block = 118 = $76
;
;	Boot track layout:
;	Track 0		Sectors 	1-12		Atari boot sector, BIOS loader, and CP/M I/O - 1536 bytes max
;	Track 0		Sectors 	13-26		BIOS - 1535 bytes max starting at FA00
;	Track 1		Sectors		1-16		CCP - 2048 bytes starting at  E400
;	Track 1		Sectors 	17-26		BDOS - 1152 bytes starting at EC00
;	Track 2		Sectors		1-19		BDOS - 2432 bytes

 

If you reserve 3 tracks (0-2), you have 37 tracks for the filesystem, not 36. So 37*26*128 /1024 = 120 blocks. Where did the 1152 come from in your drive storage capacity?

 

Also, I would make the order CCP, BDOS, BIOS. That way you can copy BDOS and BIOS to shared memory in a single copy loop. They do not have to be sector aligned, although being page aligned could speed up your copy loop.

 

Note that the size of the BIOS is $ffff-$fa00+1 = 1536 bytes. But that doesn't matter for the rest of the calculations.

 

Edit:

 

diskdef for your format:

 

diskdef atari1090ed
    seclen 128
    tracks 40
    sectrk 26
    blocksize 1024
    maxdir 64
    boottrk 3
    os 2.2
end

 

Edit2:

 

Disk Parameter Block calculations:

 

; atari1090ed
number_of_tracks = 40
reserved_tracks = 3
sectors_per_track = 26
block_size = 1024
dirents = 128

    if block_size = 1024
block_shift = 3
    elseif block_size = 2048
block_shift = 4
    elseif block_size = 4096
block_shift = 5
    elseif block_size = 8192
block_shift = 6
    elseif block_size = 16384
block_shift = 7
    endif

block_mask = (1 << block_shift) - 1

checksum_buffer_size = (dirents + 3) / 4
sectors = (number_of_tracks - reserved_tracks) * sectors_per_track
blocks_on_disk = sectors * 128 / block_size
allocation_vector_size = (blocks_on_disk + 7) / 8
directory_blocks = (dirents * 32) / block_size
allocation_bitmap = (0ffffh << (16 - directory_blocks)) & 0ffffh

    if directory_blocks = 0
        error "Directory must be at least one block in size!"
    endif
    if (dirents * 32) # block_size != 0
        error "Directory is not an even number of blocks in size!"
    endif

    if blocks_on_disk < 256
        if block_size = 1024
extent_mask = 000h              ; %00000000
        elseif block_size = 2048
extent_mask = 001h              ; %00000001
        elseif block_size = 4096
extent_mask = 003h              ; %00000011
        elseif block_size = 8192
extent_mask = 007h              ; %00000111
        elseif block_size = 16384
extent_mask = 00fh              ; %00001111
        endif
    else
        if block_size = 1024
            error "Cannot use a block size of 1024 on a large disk!"
        elseif block_size = 2048
extent_mask = 000h              ; %00000000
        elseif block_size = 4096
extent_mask = 001h              ; %00000001
        elseif block_size = 8192
extent_mask = 003h              ; %00000011
        elseif block_size = 16384
extent_mask = 007h              ; %00000111
        endif
    endif

dpblk:
    dw sectors_per_track
    db block_shift
    db block_mask
    db extent_mask
    dw blocks_on_disk - 1
    dw dirents - 1
    db (allocation_bitmap & 0ff00h)>>8
    db (allocation_bitmap & 000ffh)
    dw checksum_buffer_size
    dw reserved_tracks

dirbf:
    ds 128      ; can be the same for multiple disks
chk00:
    ds checksum_buffer_size
all00:
    ds allocation_vector_size

 

Edited by ivop
  • Like 2
Link to comment
Share on other sites

7 minutes ago, ivop said:

 

If you reserve 3 tracks (0-2), you have 37 tracks for the filesystem, not 36. So 37*26*128 /1024 = 120 blocks. Where did the 1152 come from in your drive storage capacity?

 

 

 

The extra 1152 bytes is the space in the directory track that isn't used by the directory.

 

I was counting the 40 tracks as track numbers 0 to 39.  So, with 3 tracks used by the OS there are 36 tracks left.

 

3 minutes ago, ivop said:

Also, I would make the order CCP, BDOS, BIOS. That way you can copy BDOS and BIOS to shared memory in a single copy loop. They do not have to be sector aligned, although being page aligned could speed up your copy loop.

 

I've been considering options on this one.  Since a warm boot requires that the BIOS copy CCP back, why not have the BIOS copy both CCP and BDOS back in place?  Since only the BIOS is involved in the warm boot, it wouldn't matter.  So, I've been thinking that if the Atari installs the BIOS and sets the BIOS jump in the Z-80 memory at $0000, then the cold boot function would be ran first.  The cold boot would then run part (most) of the warm boot code and install both CCP and BDOS.

 

7 minutes ago, ivop said:

Note that the size of the BIOS is $ffff-$fa00+1 = 1536 bytes. But that doesn't matter for the rest of the calculations.

 

Yeah, my mistake.  I found it after posting.  Realistically, not all 1536 bytes would be loaded as the buffers would be at the end.  I am currently guessing that the BIOS will be under 512 bytes.

 

 

Link to comment
Share on other sites

1 hour ago, reifsnyderb said:

The extra 1152 bytes is the space in the directory track that isn't used by the directory.

 

I was counting the 40 tracks as track numbers 0 to 39.  So, with 3 tracks used by the OS there are 36 tracks left.

Ah, I see. We had a different definition of disk capacity. I also counted block 0 where the directory lives.

 

1 hour ago, reifsnyderb said:

I've been considering options on this one.  Since a warm boot requires that the BIOS copy CCP back, why not have the BIOS copy both CCP and BDOS back in place?  Since only the BIOS is involved in the warm boot, it wouldn't matter.  So, I've been thinking that if the Atari installs the BIOS and sets the BIOS jump in the Z-80 memory at $0000, then the cold boot function would be ran first.  The cold boot would then run part (most) of the warm boot code and install both CCP and BDOS.

That would do a full re-initialization of BDOS each warm boot. Back in the day, BOOT (cold) fell through to the WBOOT code and was something like this:

 

BOOT:

    ; do cold boot stuff

    ; load BDOS

    ; fallthrough

WBOOT:

    ; do warm boot stuff

    ; load CCP

    ; run CCP

 

If you let the Atari copy BDOS+BIOS and set 0000H before starting the Z80, the load BDOS step can be omitted. But in the end it does not really matter. When I was debugging my 8080 emulator prototype in C I had BOOT and WBOOT copy both BDOS and CCP each time, and that works as well. But it would be over three times slower to copy BDOS, too.

 

1 hour ago, reifsnyderb said:

Yeah, my mistake.  I found it after posting.  Realistically, not all 1536 bytes would be loaded as the buffers would be at the end.  I am currently guessing that the BIOS will be under 512 bytes.

Nice! That's including buffers and DPH/DPB I suppose?

 

Edit: premature post... sigh.

Edited by ivop
Link to comment
Share on other sites

30 minutes ago, ivop said:

Ah, I see. We had a different definition of disk capacity. I also counted block 0 where the directory lives.

 

Truthfully, I don't know how the directory track should be counted.  I guess it can store data if there is space.

 

31 minutes ago, ivop said:

Ah, I see. We had a different definition of disk capacity. I also counted block 0 where the directory lives.

 

That would do a full re-initialization of BDOS each warm boot. Back in the day, BOOT (cold) fell through to the WBOOT code and was something like this:

 

BOOT:

    ; do cold boot stuff

    ; load BDOS

    ; fallthrough

WBOOT:

    ; do warm boot stuff

    ; load CCP

    ; run CCP

 

If you let the Atari copy BDOS+BIOS and set 0000H before starting the Z80, the load BDOS step can be omitted. But in the end it does not really matter. When I was debugging my 8080 emulator prototype in C I had BOOT and WBOOT copy both BDOS and CCP each time, and that works as well. But it would be over three times slower to copy BDOS, too.

Loading BDOS, during cold boot, and CCP, curing warm boot, is a good option as well.  I am figuring that it doesn't take too long to load BDOS and the BIOS either way.  One of my thoughts is to minimize the Atari code as much as possible.  I was looking at the structure of the Atari boot sector and thinking that, if possible, the Atari code and BIOS code could all be loaded at the same time.  This way, Atari's OS would load both and it would save some code on my end.    

 

31 minutes ago, ivop said:

Nice! That's including buffers and DPH/DPB I suppose?

The 512 byte estimate doesn't include the buffers.  I put the buffers in the last 512 bytes of free memory.  Since there isn't any sign they have to be initialized with anything, their content doesn't matter.  Worst case, I suppose I could clear the memory during cold boot.

 

 

 

 

Link to comment
Share on other sites

30 minutes ago, reifsnyderb said:

Truthfully, I don't know how the directory track should be counted.  I guess it can store data if there is space.

Strictly speaking, the directory sectors count for the disk capacity, the reserved tracks do not:

 

sectors = (number_of_tracks - reserved_tracks) * sectors_per_track
blocks_on_disk = sectors * 128 / block_size
30 minutes ago, reifsnyderb said:

Loading BDOS, during cold boot, and CCP, curing warm boot, is a good option as well.  I am figuring that it doesn't take too long to load BDOS and the BIOS either way.  One of my thoughts is to minimize the Atari code as much as possible.  I was looking at the structure of the Atari boot sector and thinking that, if possible, the Atari code and BIOS code could all be loaded at the same time.  This way, Atari's OS would load both and it would save some code on my end.    

Yes, this is exactly what I tried to explain earlier with the mads example 'ins'-ing the .SYS files :) The Atari OS boot code can load up to 255 sectors to consecutive memory. No need for padding between the Atari code and CCP+BDOS+BIOS.SYS. Aligning to page boundaries is slightly faster though, as lda abs,x is 25% longer (5 cycles instead of 4) if you cross a page boundary.

 

CCP = $e400
CCP_BANKEDRAM = $4000 + (CCP & $3fff) ; in BANK3

copy_ccp:
	lda #BANK3
	sta BANKREG
	ldx #0

copy_loop:
	.rept 6
		lda CCP_LOWRAM+#*256,x
		sta CCP_BANKEDRAM+#*256,x
	.endr
	inx
	bne copy_loop

; ... more code

	.align $0100

CCP_LOWRAM:
    ins 'CCP.SYS'

 

 

30 minutes ago, reifsnyderb said:

The 512 byte estimate doesn't include the buffers.  I put the buffers in the last 512 bytes of free memory.  Since there isn't any sign they have to be initialized with anything, their content doesn't matter.  Worst case, I suppose I could clear the memory during cold boot.

Agreed. I don't think that's even necessary.

Edited by ivop
Link to comment
Share on other sites

Ok, I figure I'll lay out the disk like this:

 

;	Disk layout:
;	Track 0		Sector 	1			Atari boot sector (Atari @ $0700) -- Note:  Sectors 1-14 are loaded with the boot sector.
;	Track 0		Sectors	1-2			CP/M BIOS Loader (Atari @ $0714 - $07FF) -- Loads CP/M BIOS into Z-80 RAM bank 3, $7A00
;	Track 0		Sectors 3-10		Atari CP/M I/O (Atari @ $0800 - $0BFF) -- 1k allocated, probably less is needed
;	Track 0		Sectors	11-14		CP/M BIOS (Atari @ $0C00 $0DFF) -- 512 bytes allocated
;	Track 1		Sectors	1-16		CCP - 2048 bytes starting at  E400 (Z-80 RAM bank 3, $6400)
;	Track 1		Sectors 17-26		BDOS - 1152 bytes starting at EC00 (Z-80 RAM bank 3, $6C00)
;	Track 2		Sectors	1-19		BDOS - 2432 bytes
;	Track 3		Sectors	1-16		Directory - 2048 bytes
;	Track 3		Sectors 17-26		Data - 1152 bytes
;	Track 4+	Data																	

 

(I still can't get the stupid indents to display right.   😞   )

 

I'll leverage the OS to load the Atari boot sector and include the CP/M BIOS loader, the Atari CP/M I/O code that handles the I/O between CP/M and the Atari OS, and the CP/M BIOS.

The CP/M BIOS loader code will set the Z-80 cold boot jump at $0000 (Z-80 RAM bank 0, $4000) and copy the already loaded CP/M BIOS (from $0C00 to $0DFF) to the Z-80 BIOS location at $FA00 (Z-80 RAM bank 3, 7A00).

Control will then be transferred to the Atari CP/M I/O code that will start the Z-80 and manage the I/O between the Z-80 and the Atari OS.

The CP/M BIOS will then load CCP and BDOS.

 

It's quite possible the Atari CP/M I/O code will take less than 1k.  I'll reduce it's size if necessary. 

 

I just need to add the CCP and BDOS loading code to the CP/M BIOS.  Right now, the CP/M BIOS sits at 378 bytes.   🙂

 

 

 

 

 

 

 

 

 

 

  • Like 1
Link to comment
Share on other sites

13 hours ago, reifsnyderb said:

Ok, I figure I'll lay out the disk like this:

 

;	Disk layout:
;	Track 0		Sector 	1			Atari boot sector (Atari @ $0700) -- Note:  Sectors 1-14 are loaded with the boot sector.
;	Track 0		Sectors	1-2			CP/M BIOS Loader (Atari @ $0714 - $07FF) -- Loads CP/M BIOS into Z-80 RAM bank 3, $7A00
;	Track 0		Sectors 3-10		Atari CP/M I/O (Atari @ $0800 - $0BFF) -- 1k allocated, probably less is needed
;	Track 0		Sectors	11-14		CP/M BIOS (Atari @ $0C00 $0DFF) -- 512 bytes allocated
;	Track 1		Sectors	1-16		CCP - 2048 bytes starting at  E400 (Z-80 RAM bank 3, $6400)
;	Track 1		Sectors 17-26		BDOS - 1152 bytes starting at EC00 (Z-80 RAM bank 3, $6C00)
;	Track 2		Sectors	1-19		BDOS - 2432 bytes
;	Track 3		Sectors	1-16		Directory - 2048 bytes
;	Track 3		Sectors 17-26		Data - 1152 bytes
;	Track 4+	Data																	

 

(I still can't get the stupid indents to display right.   😞   )

 

I'll leverage the OS to load the Atari boot sector and include the CP/M BIOS loader, the Atari CP/M I/O code that handles the I/O between CP/M and the Atari OS, and the CP/M BIOS.

The CP/M BIOS loader code will set the Z-80 cold boot jump at $0000 (Z-80 RAM bank 0, $4000) and copy the already loaded CP/M BIOS (from $0C00 to $0DFF) to the Z-80 BIOS location at $FA00 (Z-80 RAM bank 3, 7A00).

Control will then be transferred to the Atari CP/M I/O code that will start the Z-80 and manage the I/O between the Z-80 and the Atari OS.

The CP/M BIOS will then load CCP and BDOS.

 

It's quite possible the Atari CP/M I/O code will take less than 1k.  I'll reduce it's size if necessary. 

 

I just need to add the CCP and BDOS loading code to the CP/M BIOS.  Right now, the CP/M BIOS sits at 378 bytes.   🙂

 

Why? If you followed my example there is no need for special Z80 code to load BDOS and CCP. Everything is loaded in one go by the Atari OS during boot, then copy BDOS+BIOS to Z80 RAM, set 0000H vector, and run. The only thing the Z80 BIOS has to do is signal LoadCCP during WBOOT, similar to how you signal ConsoleStatues, and ReadSector, etc.. You also do not have to keep track of at which sector something is located, everything is handled automatically by mads. The bootblock is just sector 1-78 (maximum, can be smaller) that contains "everything everywhere all at once" ;) If you want, I can create a larger example that you only have to fill in with the I/O code.

 

 

  • Like 1
Link to comment
Share on other sites

19 minutes ago, ivop said:

 

Why? If you followed my example there is no need for special Z80 code to load BDOS and CCP. Everything is loaded in one go by the Atari OS during boot, then copy BDOS+BIOS to Z80 RAM, set 0000H vector, and run. The only thing the Z80 BIOS has to do is signal LoadCCP during WBOOT, similar to how you signal ConsoleStatues, and ReadSector, etc.. You also do not have to keep track of at which sector something is located, everything is handled automatically by mads. The bootblock is just sector 1-78 (maximum, can be smaller) that contains "everything everywhere all at once" ;) If you want, I can create a larger example that you only have to fill in with the I/O code.

 

 

I started a response then realized I was thinking in CP/M terms of tracks and sectors.  Meanwhile the Atari is only working with sectors.  So, Yeah, it now makes more sense to just load it all into the Atari's RAM.  I'll re-figure it.

 

 

 

 

 

 

 

 

 

 

Link to comment
Share on other sites

1 hour ago, reifsnyderb said:

I started a response then realized I was thinking in CP/M terms of tracks and sectors.  Meanwhile the Atari is only working with sectors.  So, Yeah, it now makes more sense to just load it all into the Atari's RAM.  I'll re-figure it.

Here's a skeletal with build system. It now generates a zero-filled file for bios.sys. You have to supply your own bios.asm and build rule in the Makefile.

Typing 'make' builds the bootblock, creates the CP/M FS with that bootblock, copies some files to it, and creates an ATR image from CP/M disk image.

Bootblock.s contains several instances of ; XXX your code here, as you are more knowledgeable about how to switch off/on the Z80.

 

Spoiler

$ make
dd if=/dev/zero of=bios.sys bs=256 count=6
6+0 records in
6+0 records out
1536 bytes (1,5 kB, 1,5 KiB) copied, 0,000375971 s, 4,1 MB/s
mads -o:bootblock.bin bootblock.s
Start bootblock: $0700
End code:        $0802
Start data:      $0900
End bootblock:   $2580
Writing object file...
220 lines of source assembled in 3 pass
7808 bytes written to the object file
dd if=/dev/zero of=cpmfs.img bs=128 count=1040
1040+0 records in
1040+0 records out
133120 bytes (133 kB, 130 KiB) copied, 0,00365784 s, 36,4 MB/s
mkfs.cpm -b bootblock.bin -f atari1090ed cpmfs.img
cpmcp -f atari1090ed cpmfs.img cpm22/DUMP.COM cpm22/STAT.COM cpm22/PIP.COM \
    0:
cpmls -f atari1090ed cpmfs.img
0:
dump.com
pip.com
stat.com
cat atrheader.dat cpmfs.img > bootdisk.atr
ls -l bootdisk.atr
-rw-rw-r-- 1 ivo ivo 133136 Apr  9 20:02 bootdisk.atr

 

 

Hope this helps :)

 

Edit: for inspiration: https://github.com/ivop/atari8080/blob/main/8080.s starting at line 2234 (absolute sector calculation, handling bank overflow, e.g. you read 128 bytes to $7ff0 in bank 2).

and https://github.com/davidgiven/cpm65/blob/master/src/arch/atari800/atari800.S starting at line 941 for sector read/write code. TTY code uses K: for keyboard in. For CONOUT you can use E: as a start. Once you get the A> prompt and can run DUMP DUMP.COM, you can look into a proper 'dumb' CP/M terminal and finally an ADM-3a or VT52 terminal emulation.

 

Edit2: the bank overflow trick uses up to 127 bytes after the bank ends. On read, I just read into memory past $8000, detect overflow, select next bank, and copy the number of overflown bytes to $4000. On write, I check overflow, select next bank, copy X number of bytes from $4000 to $8000, select previous bank, write 128 bytes from e.g. $7ff0.

cpm1090.zip

Edited by ivop
Link to comment
Share on other sites

It's alive!   :-D

 

I just finished an extensive round of finalizing the programmable logic chips while testing at every possible step.  A few logic problems were found and fixed.  The 64k of SRAM can be banked into the $4000-$7FFF banking region on the Atari, and the Z-80 chip can be controlled by the Atari.  Running some very basic assembly, on the Z-80, shows that the Z-80 is working and can communicate back to the Atari.

 

Unfortunately, I discovered that I forgot to add a single trace.  So, these aren't the final boards.  Since the original 1090 Z-80 board schematic showed the Atari could generate an interrupt on the Z-80, I figured I'd add the Z-80 /M1 line to one of the PLDs so that should be possible on the next run of boards.  (The /M1 line is needed to ensure that an /IRQ doesn't accidentally result in I/O.)  Realistically, the Atari probably doesn't need to generate an IRQ on the Z-80, but since the capability appeared to have been planned, why not add it as a feature?

 

This board is greatly improved over the last board.  Improvements are:

1.  64k of SRAM, with banking logic, is built onto the board.  This reduces the cost and now the Z-80 board only requires a single 1090 card slot.

2.  Four programmable logic chips were used to speed development and reduce chip count.  At the low end, each programmable chip replaced at least 3 other chips.

3.  The Z-80 is now running at almost 7.4 Mhz.

 

Here's a couple pics.....

z80workingfront.thumb.jpg.006fe76325e65da0a6d61941e949411b.jpg

 

z80workingback.thumb.jpg.a389c8bc2ddc504a2921a2f7658ac9c2.jpg

 

  • Like 11
Link to comment
Share on other sites

Posted (edited)
8 minutes ago, _The Doctor__ said:

will the card allow the z80 to access additional ram etc for mdisk (ramdisk etc?) of cpm fame?

Well, I wasn't aware of it nor did the 1090XL version appear to do it.  I suppose something could be figured out.  If the mdisk goes through the CP/M BIOS, for example, it would be easy to use the Atari memory.

 

Do you have any information as to how it worked?

Edited by reifsnyderb
Link to comment
Share on other sites

Posted (edited)
3 hours ago, _The Doctor__ said:

will the card allow the z80 to access additional ram etc for mdisk (ramdisk etc?) of cpm fame?

I was doing some research, found nothing so far, and was thinking some more about this.  With CP/M, any disk has to go through the BIOS.  So, the BIOS could easily have a drive designated as a RAM disk.  That's no problem.  The new Z-80 card, I just made, is also compatible with the memory on the 320k 1090XL RAM card.  So, that all being said, it's only a software change to add up to a 256k RAM disk drive if the 320k card is installed.

 

Maybe I should move the banking region, of the CP/M card, to $8000-$BFFF?  This would be easily possible simply by changing the bank region on the address decoder chip on the Z-80 card.  The boot code, that runs on the Atari, could easily make sure BASIC is disabled with a simple call to PORTB.  (I was thinking about doing that anyhow.)  The I/O code, on the Atari, shouldn't take any more than 1k of memory, either.  So, it would be easy to bank the extended memory, on the 320k card, while also banking the Z-80 memory so as to have fast data transfers between the RAM Disk and the Z-80's RAM.

 

Edit to add:

Should the RAM Disk be drive "e:"?

 

Edited by reifsnyderb
  • Like 1
Link to comment
Share on other sites

There is no CP/M RAM disk standard. There's not a standard to how banked memory was done. CP/M 3 supported banked memory, but their implementations varied wildly, ranging from 4kB to 32kB of bankable RAM. Similar to how there is not one disk format. Each system had their own disk format, and if they supported a RAM disk, it was in their custom BIOS implementation. I have seen drive M: (for "memory" I suppose) or drive P: (last one available). But since your goal is four drives (A:-D:) you could just as easily use E:.

 

As all disk access goes through the Atari OS SIO routines, it's much easier to mount several ATR disk images with SIDE or another PBI IDE implementation and have your SSED disk images on a CF or SD card. Just as fast, and non-volatile. You can even boot from them. RAM disks are obsolete IMO. Well except for initramfs during Linux boot I suppose ;)

 

CP/M is also not capable of mixing floppy formats, as the disk layout is fixed in memory. And swapping disks is also a thing. Never swap a disk in the middle of an application or it will ruin your filesystem. The only way to swap disks is when CCP is running and after a swap press control-C to restart CCP so it logs in the new disk. If you forget the last step, it might ruin the newly inserted disk.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

15 hours ago, _The Doctor__ said:

was there never a fix to autolog or just have a relog before disk operations. I might have recently forgot that step and killed a disk, face palm palm face.

Relog disks before operations is not as trivial as it may seem and can be slow, if possible at all. Opening and closing files is expensive, hence a lot of applications keep their files open until program termination. Also note that BDOS does not know if there are any files open. That info is all in user space (File Control Blocks).

 

I recently read an anecdote from somebody that was working at a company where at least once a week an employee came at his desk with a ruined floppy. To avoid to have to manually retrieve (some of) the data each time, he modified the BIOS of all their workstations to run a timer interrupt that checked the floppy drive's open/close sensor every 100ms. If somebody opened the drive after boot, a big warning would be displayed urging the user to put back the SAME disk again, and would not continue until the drive was closed again, hopefully with the same disk inside. After that, the reports of ruined floppies dropped to zero.

 

  • Like 4
Link to comment
Share on other sites

that also depends on the disk set up.

in any event, almost everything was configurable to a degree on these old machines, so when you say there was no standard for this or that, well that's true for almost anything, but there were ranges of addresses settable via dip switches and jumpers that sort of became 'settled' over time.

 

as to memory, 256k and 1 MG boards were commonly in use, and easily purchased both static and dynamic from multiple sources here in the states as well as a number of video cards and specialty cards. Like every other machine, how you decided to implement things were up to you but there were still ranges to stay within if you wanted everything to work.

 

http://www.s100computers.com/Hardware Index Page.htm

http://www.s100computers.com/index.html

http://dunfield.classiccmp.org/s100c/index.htm

 

endless sites like the above all with different cards etc to peruse for the best choices to make a multi-function card or remake of a great old card

 

for a chuckle, everyone has the most...

https://www.eevblog.com/forum/vintage-computing/probably-the-most-sophisticated-cpm-80-machine-ever-made/

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...