💾 Archived View for mirrors.apple2.org.za › archive › apple.cabi.net › Utilities › SSC.DRIVER › SSC.… captured on 2024-05-10 at 15:55:35.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

;
;Port driver for Apple (R) Super Serial Card and compatibles
;
;Version 1.0b1
;
;by Scott Alfter
;
;Copyright (C) 1990 by Skunk Works Software Co.
;                      43 Megan Dr.
;                      Henderson, NV  89014
;
;All Rights Reserved
;
;Source code for MindCraft (TM) Assembler
;
;-------------------------------------------------------------------------
;
;This driver is designed to work with the Term One (TM) telecommunications
;system by Skunk Works Software, but could easily be used in other
;telecommunications applications.  Term One uses only a handful of
;addresses to talk to any port driver:
;
;$0800  Initialize hardware (INIT)
;$0803  Set baud rate and data format (SETPARMS)
;$0806  Control buffer handshaking (HNDSHK)
;$0809  Get a character through the port (GETCHAR)
;$080C  Send a character out the port (SENDCHAR)
;$080F  Send a 233 ms BREAK out the port (SENDBRK)
;$0812  Shut down the driver (SHUTDOWN)
;
;Do a JSR to these addresses.  Parameters are as follows:
;
;INIT: Baud rate/data format code in accumulator, slot number in
;      X-register. (Code documented before routine.)  If card in slot X
;      is incompatible with this driver, the routine quits with the carry
;      set and the high bit of the Y-register set.
;SETPARMS: Baud rate/data format code in accumulator.
;HNDSHK: High bit of accumulator set to enable buffer handshaking.
;GETCHAR: Character returned in accumulator.
;SENDCHAR: Character to send in accumulator.
;SENDBRK: No parameters.
;SHUTDOWN: No parameters.
;
;For all routines, the carry flag indicates if an error occurred; it will
;be set if something went wrong.
;
;-------------------------------------------------------------------------
;
;My legal stuff:
;  "Term One" is a trademark of the Skunk Works Software Co.
;
;Other people's legal stuff:
;  "Apple" is a registered trademark of Apple Computer, Inc.
;  "MindCraft" is a trademark of MindCraft Publishing Corp.
;
;-------------------------------------------------------------------------
;
;Some EQUates needed for proper operation
;
ALLOC_INTERRUPT EQU $40 ;MLI command to make an interrupt vector
DEALLOC_INTERRUPT EQU $41 ;MLI command to remove an interrupt vector
MLICALL EQU $BF00 ;Enter the MLI here
TDREG EQU $C088 ;ACIA transmit register
RDREG EQU $C088 ;ACIA receive register
STATUS EQU $C089 ;Tells all about the ACIA
COMMAND EQU $C08A ;Sets parity and turns interrupts on and off
CONTROL EQU $C08B ;Sets baud rate and number of stop bits
;
;Jump table and other interfacing stuff
;
 ORG $800
 JMP INIT
 JMP SETPARMS
 JMP HNDSHK
 JMP GETCHAR
 JMP SENDCHAR
 JMP SENDBRK
 JMP SHUTDOWN
 DFC $10 ;Driver protocol version number
 ASC "Apple SSC" ;Hardware description
 DFC 0
;
;System initialization
;
NOTSSC LDY #$80 ;Initialization error also returns with high bit
   ;of Y-reg set if card wasn't an SSC
INITQUIT PLA  ;Clear the baud rate out of the stack
 SEC  ;Flag an error
 RTS
INIT STX SLOT ;Save slot number
 PHA  ;Save baud rate for later
 TXA  ;Make $Cx so we can identify card in slot
 ORA #$C0
 STA CHECK1 ;Alter addresses for card check
 STA CHECK2
 STA CHECK3
 STA CHECK4
CHECK1 EQU .+2
 LDA $C005 ;$Cx05 should be $38
 CMP #$38
 BNE NOTSSC
CHECK2 EQU .+2
 LDA $C007 ;$Cx07 should be $18
 CMP #$18
 BNE NOTSSC
CHECK3 EQU .+2
 LDA $C00B ;$Cx0B should be $01
 CMP #$01
 BNE NOTSSC
CHECK4 EQU .+2
 LDA $C00C ;$Cx0C should be $31
 CMP #$31
 BNE NOTSSC
 LDA SLOT ;Multiply slot number by 16
 ASL
 ASL
 ASL
 ASL
 STA SLOT
 CLC  ;To prevent false read during SSC transmit
 ADC #TDREG+1
 STA SPECSLOT
 JSR MLICALL ;Set up an interrupt vector for us
 DFC ALLOC_INTERRUPT
 ADR ALLOC_BLK
 LDY #0 ;In case an error occurs at this stage...
 BCS INITQUIT ;Error brings it to a stop
 LDA ALLOC_BLK+1 ;Move vector number for shutdown
 STA DEALLOC_BLK+1
 LDA #9 ;Enable interrupts from card and set no parity
 LDX SLOT
 STA COMMAND,X
 LDA #0 ;Default for handshaking is off
 STA HSFLAG
 CLI  ;Tell the processor to start taking interrupts
 PLA  ;Get the baud rate back
 JSR SETPARMS ;Set baud rate and data format
 BCC INITOK ;All's cool if we can set the parameters
 JSR SHUTDOWN ;If not, undo initialization
 SEC
 LDY #0
INITOK RTS
;
;Set baud rate and data format
;
;Accumulator contains 0000fbbb on entry, where
;bbb: 0=300 baud
;     1=1200 baud
;     2=2400 baud
;     3=4800 baud
;     4=9600 baud
;     5=14400 baud
;     6=19200 baud
;  w: 0=8 data bits, 1 stop bit, no parity
;     1=7 data bits, 1 stop bit, even parity
;
;Note that the SSC does not support 14400 baud, so the carry returns set
;if the calling routine tries to select this baud rate.
;
SETPARMS AND #$F ;Get rid of unused bits
 TAY  ;Look up the actual parameter code to set
 LDA ]TABLE,Y
 BEQ ]ERROR ;Some choices are invalid
 LDX SLOT
 STA CONTROL,X ;Set the baud rate
 CLC  ;No errors
 RTS  ;All done here!
]ERROR SEC  ;Something went wrong
 RTS
]TABLE DFC $16 ;300/8/N/1
 DFC $18 ;1200/8/N/1
 DFC $1A ;2400/8/N/1
 DFC $1C ;4800/8/N/1
 DFC $1E ;9600/8/N/1
 DFC 0 ;14.4K/8/N/1 (not supported by SSC)
 DFC $1F ;19.2K/8/N/1
 DFC 0 ;future expansion?
 DFC $36 ;300/7/E/1
 DFC $38 ;1200/7/E/1
 DFC $3A ;2400/7/E/1
 DFC $3C ;4800/7/E/1
 DFC $3E ;9600/7/E/1
 DFC 0 ;14.4K/7/E/1 (not supported by SSC)
 DFC $3F ;19.2K/7/E/1
 DFC 0 ;future expansion?
;
;Turn XON/XOFF buffer handshaking on or off
;
HNDSHK STA HSFLAG
 RTS
;
;Get a character from the port
;
GETCHAR LDA BUFOUT ;First, see if anything's come in
 CMP BUFIN
 BEQ ]ERROR ;Exit if no character
 TAY  ;Get the character
 LDA BUFFER,Y
 INC BUFOUT ;Bump the pointer up a notch
 PHA
 BIT PAUSE ;Did the handshaking kick in?
 BPL ]DONE
 SEC  ;See if the buffer's emptying
 LDA BUFIN
 SBC BUFOUT
 CMP #64 ;When it's only 1/4 full, we can receive again
 BCS ]DONE
 LDA #0 ;Clear the flag
 STA PAUSE
 LDA #$11 ;Send XON
 JSR SENDCHAR
]DONE PLA
 CLC  ;No errors (we got a character)
 RTS
]ERROR SEC  ;Carry set if no character was available
 RTS
;
;Send a character out the port
;
SENDCHAR PHA  ;Save the outgoing character for the time being
 BIT PAUSE ;Refuse to send if handshaking is in effect
 BMI ]ERROR
 LDX SLOT
 LDA STATUS,X ;See if the card's ready
 AND #$60 ;If bits 5 or 6 are set, the card ain't up to it
 BNE ]ERROR
]1 LDA STATUS,X
 AND #$10 ;If bit 4 is clear, the card's still chewing on
 BEQ [1 ;the last character
 PLA  ;Get the character back
 LDX SPECSLOT ;Takes care of "false read" problem
 STA $BFFF,X ;Send the character on its way
 CLC  ;No errors
 RTS
]ERROR PLA  ;Return the stack to normal
 SEC  ;Quit with an error flagged
 RTS
;
;Shut down the driver
;
SHUTDOWN SEI  ;The processor will no longer get interrupts
 LDA #$B ;The SSC will no longer make interrupts
 LDX SLOT
 STA COMMAND,X
 JSR MLICALL ;Remove the interrupt handler
 DFC DEALLOC_INTERRUPT
 ADR DEALLOC_BLK
 RTS  ;If something went wrong, it was with the MLI
;
;Send a 233 ms BREAK out the SSC
;(Timing is presently valid only at 1 MHz--may act up on a IIGS, IIc Plus,
;or any other accelerated system.)
;
SENDBRK LDA #$D ;Tell SSC to start streaming zero bits
 LDX SLOT
 STA COMMAND,X
 LDX #233 ;Kill 233 ms of time
]1 LDY #$CA
]2 DEY
 BNE [2
 DEX
 BNE [1
 LDA #9 ;Restore the SSC to normal operation
 LDX SLOT
 STA COMMAND,X
 CLC  ;How could something go wrong?
 RTS  ;All done!
;
;This is the daemon that grabs incoming characters from the port.  When a
;character arrives, the SSC generates an interrupt.  ProDOS catches the
;interrupt and sends it on to us.  Assuming that the interrupt is ours
;(other daemons may very well be installed for other purposes), we get the
;incoming character and stuff it into a 256-byte FIFO queue for the
;GETCHAR routine to retrieve whenever Term One is up to it.
;
DAEMON CLD  ;Interrupt daemons always start this way
 LDX SLOT
 LDA STATUS,X ;Check to see if the interrupt is ours
 BMI ]YES
 SEC  ;Tell ProDOS to try another daemon (better not be
 RTS  ;dealing with a spurious interrupt here :-| )
]YES LDY BUFIN ;OK, so stuff the character into the queue
 LDA RDREG,X
 STA BUFFER,Y
 INC BUFIN
 SEC
 LDA BUFIN
 SBC BUFOUT
 CMP #$80 ;Tell remote device to stop sending stuff...
 BCC ]DONE
 BIT PAUSE ;...but only if we haven't already...
 BMI ]DONE
 BIT HSFLAG ;...and only if handshaking has been enabled
 BPL ]DONE
 LDA #$13 ;Send XOFF
 JSR SENDCHAR
 LDA #$80 ;Tell GETCHAR that pause is in effect
 STA PAUSE
]DONE CLC  ;ProDOS need not look further
 RTS
;
;Room for data and such
;
SLOT DFS 1 ;Slot number (times 16) goes here
SPECSLOT DFC 1 ;This, when added to $BFFF, yields the right
   ;TDREG
ALLOC_BLK DFC 2 ;2 parameters for ALLOC_INTERRUPT call
 DFS 1 ;Interrupt priority is returned here
 ADR DAEMON ;Address of the interrupt daemon goes here
DEALLOC_BLK DFC 1 ;Only 1 parameter for DEALLOC_INTERRUPT
 DFS 1 ;Interrupt priority returned by ALLOC_INTERRUPT
   ;goes here
BUFIN DFC 0 ;The interrupt daemon bumps this when a character
   ;arrives
BUFOUT DFC 0 ;GETCHAR bumps this when Term One gets a
   ;character
PAUSE DFC 0 ;When XOFF has automatically been sent, the high
   ;bit is set
HSFLAG DFC 0 ;High bit set to enable XON/XOFF buffer
   ;handshaking
BUFFER DFS 128 ;The FIFO queue (too bad this assembler can't
 DFS 128 ;handle DFS 256 instead :-( )