[comp.sys.apple] Serial Port Hardware Addresses

barry@rbdc (Barry Newberry) (02/22/90)

I guess the answer to this question is (partially) in the Apple IIgs
Hardware Reference, but I don't have that book.

Problem : How do I enable/disable Interrupt generation from a serial
     port ? The interrupts should be generated by Transmitter=empty,
     Transmission Received, or Error (according to IIgs Firmware Ref).

I should be able to enable/disable serial port interrupts by reading
or writing to the area from $C080,X to $C08F,X (where X equals the
slot number x 16 : $n0). I would like to enable/disable interrupts
for both the IIgs Serial Port AND the Super Serial Card, since I have
both. I want a Hardware Address Table which is similar to the one
below but giving addresses for Serial Ports.

Table : Disk II Controller   (figure 6.1 from Beneath Apple DOS)

Address   Label      Description
-------  ----------  --------------------------------------------
$C080    PHASEOFF    Stepper Motor Phase 0 Off
$C081    PHASEON     Stepper Motor Phase 0 On
$C082    PHASE1OFF   Stepper Motor Phase 1 Off
$C083    PHASE1ON    Stepper Motor Phase 1 On
$C084    PHASE2OFF   Stepper Motor Phase 2 Off
$C085    PHASE2ON    Stepper Motor Phase 2 On
$C086    PHASE3OFF   Stepper Motor Phase 3 Off
$C087    PHASE3ON    Stepper Motor Phase 3 On
$C088    MOTOROFF    Turn Motor Off
$C089    MOTORON     Turn Motor On
$C08A    DRV0EN      Engage Drive 1
$C08B    DRV1EN      Engage Drive 2
$C08C    Q6L         Strobe Data Latch for I/O
$C08D    Q6H         Load Data Latch
$C08E    Q7L         Prepare Latch for Input
$C08F    Q7H         Prepare Latch for Output

         Q7L with Q6L = Read
         Q7L with Q6H = Sense Write Protect
         Q7H with Q6L = Write
         Q7H with Q6H = Load Write Latch

I plan to use the information to write a program that reads and writes
to the serial port as a "background" task, and I want to be able to do
this on a IIe, as well as a IIgs.

-- 
------------------------------------------------------------------------
    Remember, until there is a cure for Assembly Language Brain Fry,
      there will always be the N.C. Home for Deranged Programmers.
.......................................................................

gwyn@smoke.BRL.MIL (Doug Gwyn) (02/23/90)

In article <1990Feb22.060459.7768@rbdc> barry@rbdc.UUCP (Barry Newberry) writes:
>I want a Hardware Address Table which is similar to the one
>below but giving addresses for Serial Ports.

Sorry; that's not the way it works.  If you really feel you have to
bypass Apple's programming guidelines for the IIGS and diddle the
serial port hardware directly, you'll find it takes intricate control.
If you still insist, I provide the following for the foolhardy:

/*
	<sys/scc8530.h> -- definitions for 8530 Serial Communications Controller
		built into Apple IIGS

	last edit:	23-May-1987	D A Gwyn
*/

/*
	Apple IIGS-specific definitions

	Reference:	Apple IIGS Hardware Technical Reference Manual

	The first thing you should appreciate is that Apple recommends
	that you access the serial ports through the firmware hooks or,
	even better, through the toolbox, because this specific hardware
	implementation is likely to change in future Apple II models.
	If the recommended approach is sufficient for your needs, then
	use it and ignore this file.

	Apple IIGS serial port (1 = printer, 2 = modem) connectors:

	pin 1: handshake out (DTR)
	pin 2: handshake in (CTS/clock; typically connected to DSR)
	pin 3: transmit data -
	pin 4: signal ground
	pin 5: receive data -
	pin 6: transmit data +
	pin 7: general-purpose input (DCD)
	pin 8: receive data +

	IIGS hardware uses SCC channel A for port 1, channel B for port 2.

	PCLK (master SCC clock) is directly connected to Apple CREF.H.
	INT.L (interrupt request) is directly connected to Apple IRQ.L.
	IEI.H (interrupt enable in) is constant-H (enabled).
	IEO.H (interrupt enable out) is not connected.
	INTACK.L (interrupt acknowledge) is constant-H (disabled),
	so that the interrupt vector is never put on the data bus.
	SEL (undocumented) is constant-L.
	SYNCB.L is not connected; external synchronization is not supported.
	RTxC?.L (receive/transmit clock; programmable function) for the two
	channels are connected with SYNCA.L as a 3.6864 MHz crystal oscillator
	(enabled under program control).

	For each channel (A = Apple serial port 1, B = Apple serial port 2):
	TRxC?.L (transmit/receive clock; programmable function) and CTS.L
	(clear to send) are the inverse of serial port HSKI.H input pin 2;
	DCD?.L (data carrier detect) is the inverse of serial port GPI.H pin 7;
	DTR/REQ?.L (data terminal ready/request) is routed to serial port
	output pin 1 (high active -- *disabled* by setting DTR bit);
	RxD?.H (receive data) is the differential of serial port RxD input pins
	8 and 5;
	TxD?.H (transmit data) generates the signals for serial port output pins
	6 and 3, which are enabled by RTS?.L.
	RTS?.L (request to send) is not connected.
	W/REQ?.L (wait/request) is not connected.

	Apple RESET also resets the SCC chip (by asserting RD.L and WR.L).

	A/B, D/C, CE.L, WR.L, RD.L, and D0-D7 are configured to respond to
	Apple II bus addressing as defined in the following macros.

	The following addresses are in I/O space, which is usually shadowed
	in 6502 emulation (ProDOS-8) mode.  If shadowing is disabled, as is 
	often done for full 16-bit mode, the memory bank first needs to be
	set to $E0 or $E1 since the actual IIGS I/O space is in those banks.
*/

#ifdef PRODOS_16
#define	IO_BANK	0xE00000
#else	/* ProDOS-8 */
#define	IO_BANK	0
#endif

#define	SCCBREG		(*(char *)(IO_BANK + 0xC038))	/* chan B register */
#define	SCCAREG		(*(char *)(IO_BANK + 0xC039))	/* chan A register */
#define	SCCBDATA	(*(char *)(IO_BANK + 0xC03A))	/* chan B data */
#define	SCCADATA	(*(char *)(IO_BANK + 0xC03B))	/* chan A data */

/*
	Baud Rate Generator time constants for 3.6864 MHz crystal oscillator

	TC = (Clock_Rate / Divisor) / (2 * Baud_Rate) - 2
*/

#define	X1_19200	94
#define	X1_9600		190
#define	X1_7200		254
#define	X1_4800		382
#define	X1_3600		510
#define	X1_2400		766
#define	X1_1800		1022
#define	X1_1200		1534
#define	X1_600		3070
#define	X1_300		6142
#define	X1_150		12286
#define	X1_134		13703
#define	X1_110		16754
#define	X1_75		24574

#define	X16_19200	4
#define	X16_9600	10
#define	X16_7200	14
#define	X16_4800	22
#define	X16_3600	30
#define	X16_2400	46
#define	X16_1800	62
#define	X16_1200	94
#define	X16_600		190
#define	X16_300		382
#define	X16_150		766
#define	X16_134		855
#define	X16_110		1045
#define	X16_75		1534
#define	X16_50		2302

#define	X32_19200	1
#define	X32_9600	4
#define	X32_7200	6
#define	X32_4800	10
#define	X32_3600	14
#define	X32_2400	22
#define	X32_1800	30
#define	X32_1200	46
#define	X32_600		94
#define	X32_300		190
#define	X32_150		382
#define	X32_110		522
#define	X32_75		766
#define	X32_50		1150

#define	X64_9600	1
#define	X64_7200	2
#define	X64_4800	4
#define	X64_3600	6
#define	X64_2400	10
#define	X64_1800	14
#define	X64_1200	22
#define	X64_600		46
#define	X64_300		94
#define	X64_150		190
#define	X64_110		260
#define	X64_75		382
#define	X64_50		574

/*
	Zilog Z8530 SCC-specific definitions

	Reference:	Zilog Z8530 SCC Product Specification

	Each SCC channel data window is always available and is accessed by
	invoking either SCC?_out( x ) to write byte x
	or x = SCC?_in() to read byte x.

	SCC register # n (for n > 0) is accessed by performing
	either SCC?_ctrl( n, x ) to write x to register # n
	or x = SCC?_stat( n ) to read x from register # n.

	(In the above, ? is either A or B depending on the SCC channel.)
*/

#define	SCCA_reg( n )		((void)(SCCAREG = (n)))
#define	SCCB_reg( n )		((void)(SCCBREG = (n)))
#define	SCCA_out( x )		((void)(SCCADATA = (x)))
#define	SCCB_out( x )		((void)(SCCBDATA = (x)))
#define	SCCA_in()		SCCADATA
#define	SCCB_in()		SCCBDATA
#define	SCCA_ctrl( n, x )	((n) ? SCCA_reg( n ) : (void)0, SCCA_reg( x ))
#define	SCCB_ctrl( n, x )	((n) ? SCCB_reg( n ) : (void)0, SCCB_reg( x ))
#define	SCCA_stat( n )		(SCCA_reg( n ), SCCAREG)
#define	SCCB_stat( n )		(SCCB_reg( n ), SCCBREG)

/*
	Read Register bit-field definitions

	(Unspecified bits are always 0)
*/

/*
	RR0: Transmit/Receive buffer status and External status
	(RR0 does not require the preliminary SCC?_reg( 0 ))
*/
#define	RR0_BRK		0x80	/* break/abort */
#define	RR0_UND		0x40	/* Tx underrun/EOM */
#define	RR0_CTS		0x20	/* tracks CTS.L input pin */
#define	RR0_SYN		0x10	/* synchronous/hunt
				   (affected by SYNC.L transition if no crystal) */
#define	RR0_DCD		0x08	/* tracks DCD.L input pin */
#define	RR0_EMPTY	0x04	/* Tx buffer empty */
#define	RR0_ZCT		0x02	/* zero count */
#define	RR0_AVAIL	0x01	/* Rx character available */

/*
	RR1: Special Receive Condition status
*/
#define	RR1_END		0x80	/* end of frame (SDLC) */
#define	RR1_FERR	0x40	/* CRC/framing error */
#define	RR1_OERR	0x20	/* Rx overrun error */
#define	RR1_PERR	0x10	/* parity error */
#define	RR1_RESIDUE	0x0E	/* residue codes 0|1|2 */
#define	RR1_SENT	0x01	/* all sent */

/*
	RR2: Unmodified interrupt vector (channel A)
	or Modified interrupt vector (channel B)
*/

/*
	RR3: Interrupt Pending bits (channel A)
	(all 0 when read through channel B)
*/
#define	RR3_ARIP	0x20	/* channel A Rx interrupt pending */
#define	RR3_ATIP	0x10	/* channel A Tx interrupt pending */
#define	RR3_AXIP	0x08	/* channel A ext/stat interrupt pending */
#define	RR3_BRIP	0x04	/* channel B Rx interrupt pending */
#define	RR3_BTIP	0x02	/* channel B Tx interrupt pending */
#define	RR3_BXIP	0x01	/* channel B ext/stat interrupt pending */

/*
	RR8: Receive buffer
	(must be accessed via SCC?_in())
*/

/*
	RR10: Miscellaneous status
*/
#define	RR10_1MISS	0x80	/* one clock missing */
#define	RR10_2MISS	0x40	/* two clocks missing */
#define	RR10_LPSEND	0x10	/* loop sending */
#define	RR10_ONLOOP	0x02	/* on loop */

/*
	RR12: lower byte of baud rate generator time constant
	RR13: upper byte of baud rate generator time constant
*/

/*
	RR15: External/Status interrupt information
*/
#define	RR15_BRKIE	0x80	/* break/abort interrupt enable */
#define	RR15_UNDIE	0x40	/* Tx underrun interrupt enable */
#define	RR15_CTSIE	0x20	/* CTS transition interrupt enable */
#define	RR15_SYNIE	0x10	/* sync/hunt interrupt enable */
#define	RR15_DCDIE	0x08	/* DCD transition interrupt enable */
#define	RR15_ZCTIE	0x02	/* zero count interrupt enable */

/*
	Write register bit-field definitions

	(Unspecified bits must always be 0)
*/

/*
	WR0: CRC initialize, initialization commands for the various modes,
	Register Pointers
	(WR0 does not require the preliminary SCC?_reg( 0 ))
*/
#define	WR0_RUND	0xC0	/* reset Tx underrun latch */
#define	WR0_RGEN	0x80	/* reset Tx CRC generator */
#define	WR0_RCHK	0x40	/* reset Rx CRC checker */
#define	WR0_NULL	0x00	/* null code */
#define	WR0_RIUS	0x38	/* reset highest IUS */
#define	WR0_RERR	0x30	/* error reset */
#define	WR0_RTIP	0x28	/* reset Tx interrupt pending */
#define	WR0_RCIE	0x20	/* enable interrupt on next Rx character */
#define	WR0_ABORT	0x18	/* send abort (SDLC) */
#define	WR0_RXI		0x10	/* reset ext/stat interrupts */
#define	WR0_PHI		0x08	/* point high */
/* #def	WR0_NULL	0x00	/* null code */
#define	WR0_REG		0x07	/* register 0-15 select (see SCC?_reg( n )) */

/*
	WR1: Transmit/Receive interrupt and data transfer mode definition
*/
#define	WR1_WREN	0x80	/* wait/DMA request enable */
#define	WR1_DMA		0x40	/* 0=>wait/1=>DMA request function */
#define	WR1_WRRX	0x20	/* wait/DMA request on 0=>transmit/1=>receive */
#define	WR1_RISCO	0x18	/* Rx interrupt on special condition only */
#define	WR1_RIALL	0x10	/* interrupt on all Rx chars or special cond. */
#define	WR1_RIFCS	0x08	/* Rx interrupt on 1st char or special cond. */
#define	WR1_RIDIS	0x00	/* Rx interrupt disable */
#define	WR1_PARSC	0x04	/* parity is special condition */
#define	WR1_TIEN	0x02	/* Tx interrupt enable */
#define	WR1_XIEN	0x01	/* ext interrupt enable */

/*
	WR2: Interrupt vector (accessed through either channel)
	(useless on Apple IIGS)
*/

/*
	WR3: Receive parameters and control
*/
#define	WR3_R8B		0xC0	/* Rx 8 bits/character */
#define	WR3_R6B		0x80	/* Rx 6 bits/character */
#define	WR3_R7B		0x40	/* Rx 7 bits/character */
#define	WR3_R5B		0x00	/* Rx 5 bits/character */
#define	WR3_AUTO	0x20	/* auto enables */
/* "auto enables" => CTS/DCD enable transmitters/receivers,
	RTS raised when transmitter empty */
#define	WR3_HUNT	0x10	/* enter hunt mode */
#define	WR3_RCRC	0x08	/* Rx CRC enable */
#define	WR3_ADDR	0x04	/* address search mode (SDLC) */
#define	WR3_SCLI	0x02	/* sync character load inhibit */
#define	WR3_RXEN	0x01	/* Rx enable */

/*
	WR4: Transmit/Receive miscellaneous parameters and modes
*/
#define	WR4_X64		0xC0	/* x64 clock mode */
#define	WR4_X32		0x80	/* x32 clock mode */
#define	WR4_X16		0x40	/* x16 clock mode */
#define	WR4_X1		0x00	/* x1 clock mode */
#define	WR4_XSYN	0x30	/* external sync mode */
#define	WR4_SDLC	0x20	/* SDLC mode (01111110 flag) */
#define	WR4_S16B	0x10	/* 16 bit sync character */
#define	WR4_S8B		0x00	/* 8 bit sync character */
#define	WR4_2SB		0x0C	/* 2 stop bits/character */
#define	WR4_15SB	0x08	/* 1.5 stop bits/character */
#define	WR4_1SB		0x04	/* 1 stop bit/character */
#define	WR4_SYNC	0x00	/* sync modes enable */
#define	WR4_EVEN	0x02	/* parity 0=>odd/1=>even */
#define	WR4_PAREN	0x01	/* parity enable */

/*
	WR5: Transmit parameters and controls
*/
#define	WR5_DTR		0x80	/* tracked by DTR/REQ.L output pin */
#define	WR5_T8B		0x60	/* Tx 8 bits/character */
#define	WR5_T6B		0x40	/* Tx 6 bits/character */
#define	WR5_T7B		0x20	/* Tx 7 bits/character */
#define	WR5_T5B		0x00	/* Tx 5 bits (or less)/character */
#define	WR5_SBRK	0x10	/* send break */
#define	WR5_TXEN	0x08	/* Tx enable */
#define	WR5_CRC16	0x04	/* 0=>SDLC(CCITT)/1=>CRC-16 */
#define	WR5_RTS		0x02	/* tracked by RTS.L output pin
				   (except when auto enable is on) */
#define	WR5_TCEN	0x01	/* Tx CRC enable */

/*
	WR6: Sync characters or SDLC address field
	WR7: Sync character or SDLC flag
	(See the Z8530 SCC Product Specification for bit layouts)
*/

/*
	WR8: Transmit buffer
	(must be accessed via SCC?_out())
*/

/*
	WR9: Master interrupt control and reset
	(accessed through either channel)
*/
#define	WR9_HARD	0xC0	/* force hardware reset */
#define	WR9_RSTA	0x80	/* channel reset A */
#define	WR9_RSTB	0x40	/* channel reset B */
#define	WR9_NULL	0x00	/* no reset */
#define	WR9_STAT	0x10	/* status 0=>low/1=>high */
#define	WR9_MIE		0x08	/* master interrupt enable */
#define	WR9_DLC		0x04	/* DLC */
#define	WR9_NV		0x02	/* NV */
#define	WR9_VIS		0x01	/* VIS */

/*
	WR10: Miscellaneous transmitter/receiver control bits
*/
#define WR10_CP1	0x80	/* CRC preset 0=>all 0s/1=>all 1s */
#define	WR10_FM0	0x60	/* frequency modulation 0 (transition = 0) */
#define	WR10_FM1	0x40	/* frequency modulation 1 (transition = 1) */
#define	WR10_NRZI	0x20	/* NRZI (non-return to zero inhibit) */
#define	WR10_NRZ	0x00	/* NRZ (non-return to zero) */
#define	WR10_POLL	0x10	/* go active on poll */
#define	WR10_MIDLE	0x08	/* 0=>flag/1=>mark idle */
#define	WR10_AUND	0x04	/* 0=>flag/1=>abort on underrun */
#define	WR10_LOOP	0x02	/* loop mode */
#define	WR10_S6B	0x01	/* 0=>8/1=>6 bit sync */

/*
	WR11: Clock mode control
*/
#define	WR11_RXTAL	0x80	/* RTxC 0=>no crystal/1=>crystal */
#define	WR11_RPLL	0x60	/* receive clock = DPLL output */
#define	WR11_RBRG	0x40	/* receive clock = BR generator output */
#define	WR11_RTRXC	0x20	/* receive clock = TRxC pin */
#define	WR11_RRTXC	0x00	/* receive clock = RTxC pin */
#define	WR11_TPLL	0x18	/* transmit clock = DPLL output */
#define	WR11_TBRG	0x10	/* transmit clock = BR generator output */
#define	WR11_TTRXC	0x08	/* transmit clock = TRxC pin */
#define	WR11_TRTXC	0x00	/* transmit clock = RTxC pin */
#define	WR11_OTRXC	0x04	/* TRxC.L 0=>input/1=>output */
#define	WR11_OPLL	0x03	/* TRxC.L out = DPLL output */
#define	WR11_OBRG	0x02	/* TRxC.L out = BR generator output */
#define	WR11_OTCLK	0x01	/* TRxC.L out = transmit clock */
#define	WR11_OXTAL	0x00	/* TRxC.L out = crystal output */

/*
	WR12: lower byte of baud rate generator time constant
	WR13: upper byte of baud rate generator time constant
*/

/*
	WR14: Miscellaneous control bits
*/
#define	WR14_NRZI	0xE0	/* set NRZI mode */
#define	WR14_FM		0xC0	/* set FM mode */
#define	WR14_RTXC	0xA0	/* set source = RTxC */
#define	WR14_BRG	0x80	/* set source = BR generator */
#define	WR14_DPLL	0x60	/* disable DPLL */
#define	WR14_RMISS	0x40	/* reset missing clock */
#define	WR14_SEARCH	0x20	/* enter search mode */
#define	WR14_NULL	0x00	/* null command */
#define	WR14_LLB	0x10	/* local loopback */
#define	WR14_ECHO	0x08	/* auto echo */
#define	WR14_REQ	0x04	/* 0=>DTR/1=>request function */
#define	WR14_BRSRC	0x02	/* BR generator source */
#define	WR14_BREN	0x01	/* BR generator enable */

/*
	WR15: External/Status interrupt control
*/
#define	WR15_BRKIE	0x80	/* break/abort interrupt enable */
#define	WR15_UNDIE	0x40	/* Tx underrun interrupt enable */
#define	WR15_CTSIE	0x20	/* CTS interrupt enable */
#define	WR15_SYNIE	0x10	/* sync/hunt interrupt enable */
#define	WR15_DCDIE	0x08	/* DCD interrupt enable */
#define	WR15_ZCTIE	0x02	/* zero count interrupt enable */