Here is an early rev of an SSC driver I hashed out, its rough, does not use most
of the variables declared, and may contain a few name space bugs.

* serial drivers

* written in ORCA/M
* beta() 010192 20:44:59 rev 1
* 021792 16:35:53 rev 2
* 030392 02:22:47 rev 3
* Super Serial Card driver routines
* rev 1 (written on the fly while waiting for an interview)
* rev 2 remove indexed access and went with direct access and
* added the slot changer routine
* rev 3 added in interrupt processor

* Notes:
* The SSC is run with receive interupts and will heed CTS
* the SSC must assert RTS to enable the transmitter
* THE SSC does not do DCD correctly, the 6551(A and 65c51) does, with the
* SSC we normally use DSR to monitor/emulate DCD.

* the DTR routine sets the command register
* the setbps routine sets the control register

* standard stuff =

65c02 off
65816 off
keep sscdvr
org DriverOrigin

* SSC driver routines
* copyright 1991 beta()
* serial/network
* serial drivers for a SSC (or fully compa

> What are the dip swiches used for?
They're used to control various pieces of hardware behaviour for the
SoftCard.  With one of them, you can for instance turn off the
hardware translation of Z80 addresses to 6502 addresses; with another
one you can make the Z80 execute at full speed (4 MHz) instead of
running two cycles then idling two cycles (allowing the 6502 CPU to
refresh its internal registers).  But if you do any of this, Softcard
CP/M won't work... :-)

> Upon RESET, the 6502 and the Z80 are reset.  The Z80 is suspended at this 
> time, and the 6502 is allowed to run.
> A write to the $Cn00 space of the SoftCard will activate the Z80.  As soon 
> as the Z80 has valid addressing data, the SoftCard asserts the DMA line on 
> the bus, suspending the 6502 processor.
> At this point the Z80 is executing instructions and the 6502 is suspended.
> If the Z80 writes to the En00H ($Cn00 from the 6502's point of view) space 
> of the SoftCard, the Z80 goes to sleep, and 6502 execution resumes at the 
> point where it stopped.
All this is of course described in the Softcard manual..... :-)
One difference between the Z80 and the 6502 is that the Z80 is a static
processor, i.e. it can be put to sleep indefinitely: as long as it remains
powered, it will "remember"  its processor state when it went to sleep.
The 6502 though is a dynamic processor: if it's put to sleep, it will
"forget" the contents of its internal registers after approximately 50
microseconds.  Therefore the 6502 must continuously be "refreshed" when
it's put to sleep (just like a dynamic RAM chip mush be refreshed).
This is accomplished by letting the Softward Z80 CPU, which runs at
4 MHz, run for 1/2 microsecond (i.e. two clock cycles) and the be
suspended for another 1/2 microsecond, during which the 6502 is made
to fetch an instruction (but not execute it).  This is enough to
refresh the 6502 registers.
And that's why the Softcard Z80 runs at an effective speed of 2 MHz
even though the processor itself actually runs at 4 MHz.
Some other CP/M cards, such as the Appli-Card, let the Z80 have its
own address space with its own RAM chips -- then the Z80 and the 6502
could run concurrently and the 6502 never needs to be put to sleep.
This makes the 6502 address space inaccessible to the Z80 though and
the Z80 must use the 6502 for all accesses to the 6502 address space,
i.e. for all kinds of I/O (keyboard, video screen, disk, serial port
- everything).  The requires some kind of protocol between the Z80
and the 6502 so they can communicate.  On the Appli-Card, whenever
the 6502 isn't busy doing some I/O requested by the Z80, it polls the
"ports" between the Z80 and the 6502 (which are memory mapped I/O
addresses in the $Cn00 address space as seen by the 6502, and port
addresses as seen by the Z80).  Of this 6502-Z80 protocol somehow
gets out of sync, the computer hangs and must be rebooted.
One way to hang this 6502-Z80 protocol on the Appli-Card is to run a
CP/M utility which reads all Z80 ports and dumps their contents on
the screen: on the SoftCard this utility runs fine (although there's
nothing interesting to read from the Z80 ports there, since they are
unused on the SoftCard, which also lets the Z80 do memory mapped
I/O), but on the AppliCard this utility immediately hangs the system
so severely that a power off+on is required to recover.
The manual is correct, but it's handled in software.  If you disassemble the 
code that 60k CP/M 2.23 puts in $3C0-$3DB and $E3F-$E4A, you get this:

03C0    AD 83 C0        LDA C083        ; activate LC
03C3    AD 83 C0        LDA C083
03C6    8D 00 C4        STA Cx00        ; activate Z80
03C9    AD C0 81        LDA C081        ; deactivate LC
03CC    20 3F 0E        JSR 0E3F        ; get registers
03CF    20 YY XX        JSR XXYY        ; jsr to user 6502 code
03D2    8D 81 C0        STA C081        ; deactivate LC for monitor call
03D5    78              SEI             ; disable interrupts
03D6    20 4A FF        JSR FF4A        ; save registers [SAVE]
03D9    4C C0 03        JMP 03C0        ; reactivate softcard

0E3F    A5 48           LDA 48          ; get P reg
0E41    48              PHA             ; push it
0E42    A5 45           LDA 45          ; get A register
0E44    A6 46           LDX 46          ; get X register
0E46    A4 47           LDY 47          ; get Y register
0E48    28              PLP             ; pull P from stack
0E49    58              CLI             ; enable interrupts
0E4A    60              RTS             ; return to caller

You'll notice that the 6502 calling code uses the standard monitor save 
areas for registers.  The CP/M software does not maintain the S register at 

Incidentally, the NMI and RESET vectors both point to the code at $3C0, 
which is the standard place that CP/M jumps to to reactivate the SoftCard 
from 6502 mode.

So the way this works is, the 6502 stops with $3C9 as the next instruction 
to fetch.  When Z80 code deactivates the card (as described in the calling 
6502 code section in the manual), that's where it goes.  It deactivates the 
language card, restores the registers from the locations given in the 
manual, and calls to the user code.  It then reactivates the SoftCard.

> but if I omit them, I get
> different results - yes, I get CP/M, but the output is garbled.

How is it garbled?  I read on your site that there is a problem with a 
"phantom" 80-column card.  That could well be your garbled display problem, 
since CP/M attempts to enable any card in slot 3 for console I/O.  If it 
does not find a display card, it uses Apple monitor routines to do keyboard 
and display.  When CP/M is doing I/O, it is always using 6502 code for it.

Another thing to note: Microsoft CP/M versions prior to 2.23 do not follow 
the Pascal slot protocol.
The old Microsoft CP/M ver 2.23 used FORMAT to format a disk and COPY /s to
make it a bootable or system disk.
Just looking at the version 3 disks on an emulator, it would appear neither
of these files appear.
The 2009306A.DSK is a boot disk, so you could just copy that disk (with a
5.25 disk copy program) and delete the files you don't need.
From the source file PUTSYS.MAC, it would appear this is the program to put
down boot tracks on a disk.
Just from the filenames, I suspect other files (maybe BOOTLDR.COM, CPM3.SYS,
CPMLDR.COM) may be needed as well.

2009306A.DSK :