NEW
  AUTO 3,1
				.OP	65C02
				.OR $2000
*--------------------------------------
				.DO SSCIRQ=1
				.TF drv/ssc.i.drv
				.ELSE
				.TF drv/ssc.drv
				.FIN
*--------------------------------------
				.DUMMY
				.OR ZPBIN
ZS.START
ZPArgPtr		.BS 2
ZPSlotPtr		.BS 2
ZS.END			.ED
*--------------------------------------
*			File Header (16 Bytes)
*--------------------------------------
CS.START		cld
				jmp Dev.Detect			cld,jmp abs=DRV
				.DA #$61				6502,Level 1 (65c02)
				.DA #1					DRV Layout Version 1
				.DA 0
				.DA CS.END-CS.START		Code Length
				.DA 0
				.DA 0
				.DA 0
*--------------------------------------
* Relocation Table
*--------------------------------------
L.MSG.DETECT	.DA MSG.DETECT
L.MSG.DETECT.OK	.DA MSG.DETECT.OK
L.MSG.DETECT.KO	.DA MSG.DETECT.KO
L.DRV.CS.START	.DA DRV.CS.START
L.FD.DEV		.DA FD.DEV
L.FD.DEV.NAME	.DA FD.DEV.NAME
				.DA 0					End Of Reloc Table
*--------------------------------------
Dev.Detect		>STYA ZPArgPtr

				>LDYA L.MSG.DETECT
				>SYSCALL PutS
				stz ZPSlotPtr

				lda #$C1
				sta ZPSlotPtr+1

.1				and #$0f
				tay
				lda A2osX.S,y
				bne .3

				ldx #DEVSIG.Length-1

.2				ldy DEVSIG.Offset,x
				lda (ZPSlotPtr),y
				cmp DEVSIG.Value,x
				bne .3

				dex
				bpl .2

				bra .4

.3				inc FD.DEV.NAME+3
				inc ZPSlotPtr+1			no match, try next slot....
				lda ZPSlotPtr+1
				cmp #$C8
				bne .1

				>LDYA L.MSG.DETECT.KO
				>SYSCALL PutS

				lda #MLI.E.NODEV		Not Found in any slot, exiting
				sec
.99				rts

.4				lda ZPSlotPtr+1
				asl
				asl
				asl
				asl
				clc
				adc #$8F
				sta DEVSLOTn08F

				jsr Dev.ParseArgs
				bcs .99

.8				>PUSHW L.MSG.DETECT.OK
				>PUSHW L.FD.DEV.NAME
				>PUSHBI 2
				>SYSCALL PrintF

				>PUSHWI DRV.END
				>PUSHWI DRV.CS.END-DRV.CS.START
				>PUSHWI DRV.CS.START
				>LDYA L.DRV.CS.START
				>SYSCALL InsDrv
				bcs .9

				>STYA FD.DEV+S.FD.DEV.DRVPTR

				>PUSHW L.FD.DEV
				>PUSHW L.FD.DEV.NAME
				>SYSCALL MKDev
				bcs .9
				
				lda ZPSlotPtr+1
				and #$0F
				tay
				lda #A2osX.S.COM
				sta A2osX.S,y

*				clc

.9				rts
*--------------------------------------
Dev.ParseArgs	lda (ZPArgPtr)
				bne .1

				clc
				rts

.1				stz DCB+S.DCB.COM.BAUD
				stz DCB+S.DCB.COM.BAUD+1
				stz DCB+S.DCB.COM.BAUD+2
				stz DCB+S.DCB.COM.BAUD+3
	
.2				jsr DevNextChar
				beq .90
				
				cmp #','
				beq .3
				
				jsr Dev.IsDigit
				bcs .90
				
				jsr Dev.BaudT10pA
				bra .2
				
.3				jsr Dev.CheckBaud
				bcs .99

				jsr DevNextChar
				beq .99
				
				ldx #P2.Cnt-1
				
.4				cmp P2,x
				beq .5
				
				dex
				bpl .4
				
.90				bra .99
				
.5				lda #%11100000
				trb DEVCMD
				
				txa
				asl
				asl
				asl
				asl
				asl
				tsb DEVCMD
				
				jsr DevCheckSep
				bcs .99
				
				ldx #P3.Cnt-1
				
.6				cmp P3,x
				beq .7
				
				dex
				bpl .6
				
				bra .99

.7				lda #%01100000
				trb DEVCTL
				
				txa
				asl
				asl
				asl
				asl
				asl
				tsb DEVCTL
				
				jsr DevCheckSep
				bcs .99

				ldx #P4.Cnt-1
				
.8				cmp P4,x
				beq .9
				
				dex
				bpl .8
				
				bra .99

.9				lda #%10000000
				trb DEVCTL
				
				txa
				rol
				rol
				tsb DEVCTL
	
				jsr DevCheckSep
				bcs .99

				ldx #P5.Cnt-1
				
.10				cmp P5,x
				beq .11
				
				dex
				bpl .10
				
				bra .99

.11				stx	DEVFLOWCTRL

				clc
				rts

.99				lda #E.SYN
				sec
				rts
*--------------------------------------
DevCheckSep		jsr DevNextChar
				beq .9
				
				cmp #','
				bne .9
				
				jsr DevNextChar
				beq .9
				
				clc
				rts
				
.9				sec
				rts
*--------------------------------------
DevNextChar		lda (ZPArgPtr)
				beq .9
				
				inc ZPArgPtr
				bne .9
				
				inc ZPArgPtr+1
.9				rts
*--------------------------------------
Dev.IsDigit		cmp #'0'
				bcc .9
				
				cmp #'9'+1
				bcs .99
				
				and #$0F
				rts
				
.9				sec
.99				rts
*--------------------------------------
Dev.BaudT10pA	pha

				>PUSHL DCB+S.DCB.COM.BAUD
				>PUSHBI 0
				>PUSHBI 0
				>PUSHBI 0
				>PUSHBI 10
				>FPU MUL32

				>PUSHBI 0
				>PUSHBI 0
				>PUSHBI 0
				pla
				>PUSHA
				>FPU ADD32
				>PULLL DCB+S.DCB.COM.BAUD
				rts
*--------------------------------------
Dev.CheckBaud	ldx #0
				
.1				txa
				asl
				asl
				tay

				lda DCB+S.DCB.COM.BAUD
				cmp P1,y
				bne .7
				
				lda DCB+S.DCB.COM.BAUD+1
				cmp P1+1,y
				bne .7
				
				lda DCB+S.DCB.COM.BAUD+2
				cmp P1+2,y
				bne .7

				lda DCB+S.DCB.COM.BAUD+3
				cmp P1+3,y
				bne .7

				lda #$F
				trb DEVCTL

				txa
				tsb DEVCTL
				
				clc
				rts

.7				inx
				cpx #P1.Cnt
				bcc .1
				
				rts
*--------------------------------------
CS.END
DEVSIG.Offset	.HS 05070B0C
DEVSIG.Value	.HS 38180131
DEVSIG.Length	.EQ DEVSIG.Value-DEVSIG.Offset
MSG.DETECT		.AS "Apple SSC (Super Serial Card,//c Serial Port) Driver"
				.DO SSCIRQ=1
				.AS " (IRQ Enabled)"
				.FIN
				.AZ "."
MSG.DETECT.OK	.AZ "SSC Installed As Device : %s\r\n"
MSG.DETECT.KO	.AZ "No SSC Found."
*--------------------------------------
P1				.DA >115200				Baud
				.DA >50
				.DA >75
				.DA >110
				.DA >135
				.DA >150
				.DA >300
				.DA >600
				.DA >1200
				.DA >1800
				.DA >2400
				.DA >3600
				.DA >4800
				.DA >7200
				.DA >9600
				.DA >19200
P1.Cnt			.EQ 16
*--------------------------------------
P2				.AS "NOEMS"				Parity
P2.Cnt			.EQ *-P2
*--------------------------------------
P3				.AS "8765"				Data
P3.Cnt			.EQ *-P3
*--------------------------------------
P4				.AS "12"				Stop
P4.Cnt			.EQ *-P4
*--------------------------------------
P5				.AS "NHX"				flow Control
P5.Cnt			.EQ *-P5
*--------------------------------------
FD.DEV			.DA #S.FD.T.CDEV
				.DA #0					HANDLER
				.DA #0					BUSID
				.DA #0					DEVID
				.DA 0					BUSPTR
				.BS 2					DRVPTR
				.DA 0					DCBPTR
				.DA 0					BUFPTR
FD.DEV.NAME		.AZ "com1"
*--------------------------------------
*			Driver Code
*--------------------------------------
ZPIOCTL			.EQ ZPDRV
ZPBufPtr		.EQ ZPDRV+2
ZPCount			.EQ ZPDRV+4
ZPCount2		.EQ ZPDRV+6
*--------------------------------------
DRV.CS.START	cld
				jmp (.1,x)
.1				.DA STATUS
				.DA A2osX.BADCALL
				.DA A2osX.BADCALL
				.DA A2osX.BADCALL
				.DA CONTROL
				.DA A2osX.BADCALL
				.DA OPEN
				.DA CLOSE
				.DA READ
				.DA WRITE
				.DO SSCIRQ=1
				.DA IRQ
				.FIN
				.DA 0					end or relocation
*--------------------------------------
STATUS			jsr STATUS.CONTROL.Init
				ldy #S.IOCTL.S
				lda (ZPIOCTL),y
				beq .1

				cmp #S.IOCTL.S.GETDIB
				bne STATUS.DCB

				ldy #S.DIB-1
				.HS 2C					bit abs
.1				ldy #3

.2				lda DIB,y
				sta (ZPBufPtr),y
				dey
				bpl .2

				clc
				rts

STATUS.DCB		cmp #S.IOCTL.S.GETDCB
				bne .3

				ldy #S.DCB.COM-1

.2				lda DCB,y
				sta (ZPBufPtr),y
				dey
				bpl .2

				clc
				rts

.3				cmp #S.IOCTL.S.EOF
				bne STATUS.9

				lda DIB+S.DIB.S
				and #S.DIB.S.OPENED
				beq OPEN.E

				.DO SSCIRQ=1
				lda INBUF.TAIL
				eor INBUF.HEAD
				beq .4					NO DATA? eof = TRUE

				lda #1

.4				dec
				clc
				rts
				.ELSE
				
				ldx DEVSLOTn08F
				lda SSC.STATUS-$8F,x
				and #SSC.STATUS.RDRF
				beq .4
				
				lda #1
				
.4				dec				
				.FIN
.8				clc
				rts

STATUS.9		lda #MLI.E.BADCTL
				sec
				rts
*--------------------------------------
CONTROL			jsr STATUS.CONTROL.Init

				ldy #S.IOCTL.C
				lda (ZPIOCTL),y
				cmp #S.IOCTL.C.SETDCB
				bne STATUS.9

				ldy #S.DCB.COM-1

.2				lda (ZPBufPtr),y
				sta DCB,y
				dey
				bpl .2
*--------------------------------------
OPEN			lda DIB+S.DIB.S
				bit #S.DIB.S.OPENED
				beq OPEN.1

OPEN.E			lda #MLI.E.OPEN
				sec
				rts

OPEN.1			php
				sei

				.DO SSCIRQ=1

				>LDYAI 256
				>SYSCALL2 NewStkObj
				bcs .99

				stx hINBUF
				>STYA READ.INBUF+1
				>STYA IRQ.INBUF+1

				>LDYAI 256
				>SYSCALL2 NewStkObj
				bcs .90

				stx hOUTBUF
				>STYA WRITE.OUTBUF+1
				>STYA IRQ.OUTBUF+1

				stz INBUF.HEAD
				stz INBUF.TAIL
				stz OUTBUF.HEAD
				stz OUTBUF.TAIL

				.FIN

				ldx DEVSLOTn08F
				stz SSC.RESET-$8F,x

				lda DEVCTL
				sta SSC.CTL-$8F,x

				lda DEVCMD
				sta SSC.CMD-$8F,x

				lda SSC.DATA-$8F,x			discard any garbage byte
				lda SSC.STATUS-$8F,x		clear any IRQ pending

				lda #S.DIB.S.OPENED
				tsb DIB+S.DIB.S

				plp
				clc
				rts

				.DO SSCIRQ=1

.90				pha
				lda hINBUF
				>SYSCALL FreeStkObj
				pla

.99				plp
				sec
				rts
				
				.FIN
*--------------------------------------
CLOSE			lda DIB+S.DIB.S
				bit #S.DIB.S.OPENED
				beq OPEN.E

				php
				sei
				ldx DEVSLOTn08F
				stz SSC.RESET-$8F,x

				.DO SSCIRQ=1
				lda hINBUF
				>SYSCALL FreeStkObj
				lda hOUTBUF
				>SYSCALL FreeStkObj
				.FIN

				lda #S.DIB.S.OPENED
				trb DIB+S.DIB.S

				plp
				clc
				rts
*--------------------------------------
READ			php
				sei
				jsr READ.WRITE.Init

				stz ZPCount2
				stz ZPCount2+1

				.DO SSCIRQ=1
				sta SETREADAUX
				.FIN

READ.10			inc ZPCount
				bne READ.11

				inc ZPCount+1
				beq READ.8

READ.11			.DO SSCIRQ=1
				ldy INBUF.TAIL
				cpy INBUF.HEAD
				beq READ.2

READ.INBUF		lda $FFFF,y				SELF MODIFIED
				inc INBUF.TAIL

				sta (ZPBufPtr)
				inc ZPBufPtr
				bne READ.12

				inc ZPBufPtr+1

READ.12			inc ZPCount2
				bne READ.10

				inc ZPCount2+1
				bra READ.10
				.FIN

READ.2			lda SSC.STATUS-$8F,x
				bit #SSC.STATUS.nDCD	true when 0
				bne READ.9

				bit #SSC.STATUS.RDRF	incoming char?
				beq	READ.8

				lda SSC.DATA-$8F,x
				sta (ZPBufPtr)
				inc ZPBufPtr
				bne READ.13

				inc ZPBufPtr+1

READ.13			inc ZPCount2
				bne READ.2

				inc ZPCount2+1
				bra READ.2

READ.8			lda ZPCount2
				bne READ.81

				ora ZPCount2+1
				beq READ.99

				lda ZPCount2

READ.81			ldy #S.IOCTL.BYTECNT
				sta (ZPIOCTL),y
				iny
				lda ZPCount2+1
				sta (ZPIOCTL),y

				.DO SSCIRQ=1
				sta CLRREADAUX
				.FIN
				plp
				clc
				rts

READ.9			lda #MLI.E.IO
				.HS 2C					BIT ABS

READ.99			lda	#E.NODATA
				.DO SSCIRQ=1
				sta CLRREADAUX
				.FIN
				plp
				sec
				rts
*--------------------------------------
WRITE			php
				sei
				jsr READ.WRITE.Init

				.DO SSCIRQ=1
				sta SETWRITEAUX
				.FIN

WRITE.2			inc ZPCount
				bne WRITE.3

				inc ZPCount+1
				beq WRITE.8

WRITE.3			.DO SSCIRQ=1
				lda SSC.STATUS-$8F,x
				bit #SSC.STATUS.nDCD	true when 0
				bne WRITE.9

				lda OUTBUF.HEAD
				cmp OUTBUF.TAIL			Buffer Empty?
				bne WRITE.6				not empty, queue char

				lda SSC.STATUS-$8F,x
				and #SSC.STATUS.TDRE 	Register Empty ?
				beq WRITE.5				not empty, queue char

				lda (ZPBufPtr)			yes, write directly to ACIA
				sta SSC.DATA-$8F,x
				inc ZPBufPtr
				bne WRITE.2

				inc ZPBufPtr+1

				bra WRITE.2

WRITE.5			lda OUTBUF.HEAD
WRITE.6			tay
				inc
				cmp OUTBUF.TAIL
				beq WRITE.99			Buffer Full!!

				sta OUTBUF.HEAD
				lda (ZPBufPtr)
WRITE.OUTBUF	sta $FFFF,y				SELF MODIFIED
				inc ZPBufPtr
				bne WRITE.2

				inc ZPBufPtr+1
				bra WRITE.2

				.ELSE
WRITE.4			lda SSC.STATUS-$8F,x
				bit #SSC.STATUS.nDCD	true when 0
				bne WRITE.9

				bit #SSC.STATUS.TDRE	Outgoing char?
				beq WRITE.4

				lda (ZPBufPtr)
				sta SSC.DATA-$8F,x
				inc ZPBufPtr
				bne WRITE.2

				inc ZPBufPtr+1
				bra WRITE.2
				.FIN

WRITE.8			.DO SSCIRQ=1
				sta CLRWRITEAUX
				.FIN
				plp
				clc
				rts

WRITE.9			lda	#MLI.E.IO
				.HS 2C					BIT ABS
WRITE.99		lda #E.NODATA
				.DO SSCIRQ=1
				sta CLRWRITEAUX
				.FIN
				plp
				sec
				rts
*--------------------------------------
READ.WRITE.Init	ldx DEVSLOTn08F

STATUS.CONTROL.Init
				>STYA ZPIOCTL

				ldy #S.IOCTL.BUFPTR
				lda (ZPIOCTL),y
				sta ZPBufPtr

				iny

				lda (ZPIOCTL),y
				sta ZPBufPtr+1
				iny 					#S.IOCTL.BYTECNT

				lda (ZPIOCTL),y
				eor #$ff
				sta ZPCount

				iny

				lda (ZPIOCTL),y
				eor #$ff
				sta ZPCount+1
				rts
*--------------------------------------
* IRQ Handler
* on exit, CC if handled
*--------------------------------------
				.DO SSCIRQ=1
IRQ				ldx DEVSLOTn08F
				lda SSC.STATUS-$8F,x
*				and #SSC.STATUS.IRQ		Useless
				bpl IRQ.9				IRQ from this device ? no, exit !!!!Applewin bug #308!!!!

				sta SETREADAUX
				sta SETWRITEAUX

				bit #SSC.STATUS.RDRF	incoming char?
				beq IRQ.2
*------------ IRQ In

				pha
				lda INBUF.HEAD
				tay						save actual head for later
				inc
				cmp INBUF.TAIL
				beq IRQ.1				buffer full, discard and exit

				sta INBUF.HEAD

				lda SSC.DATA-$8F,x		read data to clear IRQ
IRQ.INBUF		sta $FFFF,y				SELF MODIFIED

IRQ.1			pla
*------------ IRQ Out
IRQ.2			bit #SSC.STATUS.TDRE
				beq IRQ.8				no transmission possible....

				ldy OUTBUF.TAIL			something to transmit ?
				cpy OUTBUF.HEAD
				beq IRQ.8				in that case, HOW TO CLEAR IRQ ????

IRQ.OUTBUF		lda $FFFF,y				SELF MODIFIED
				sta SSC.DATA-$8F,x		write data to clear IRQ
				inc OUTBUF.TAIL

IRQ.8			sta CLRREADAUX
				sta CLRWRITEAUX

				clc
				rts

IRQ.9			sec
				rts
				.FIN
*--------------------------------------
DRV.CS.END
DEVSLOTn08F		.BS 1
				.DO SSCIRQ=1
DEVCMD			.DA #SSC.CMD.NOP+SSC.CMD.TEIRQ+SSC.CMD.DTR
DEVCTL			.DA #SSC.CTL.1S+SSC.CTL.8D+SSC.CTL.CLKINT+SSC.CTL.B9600
				.ELSE
DEVCMD			.DA #SSC.CMD.NOP+SSC.CMD.TE+SSC.CMD.RIRQDIS+SSC.CMD.DTR
DEVCTL			.DA #SSC.CTL.1S+SSC.CTL.8D+SSC.CTL.CLKINT+SSC.CTL.B115200
				.FIN
DEVFLOWCTRL		.BS 1
				.DO SSCIRQ=1
INBUF.TAIL		.BS 1
INBUF.HEAD		.BS 1
OUTBUF.TAIL		.BS 1
OUTBUF.HEAD		.BS 1
hINBUF			.BS 1
hOUTBUF			.BS 1
				.FIN
*--------------------------------------
DIB				.DO SSCIRQ=1
				.DA #S.DIB.S.WRITE+S.DIB.S.READ+S.DIB.S.IRQ
				.ELSE
				.DA #S.DIB.S.WRITE+S.DIB.S.READ
				.FIN
				.DA #0,#0,#0
				>PSTR "Serial Card/Port"
				.DA #S.DIB.T.CHAR
				.DA #0
				.DA K.VER
*--------------------------------------
DCB				.DA #S.DCB.T.COM
				.DA #0					FLAGS
				.DO SSCIRQ=1
				.DA >9600				BAUD (DWORD)
				.ELSE
				.DA >115200
				.FIN
				.DA #8					DATA
				.DA #1					STOP
				.DA #'N'				PARITY
				.DA #'N'				FLOW
*--------------------------------------
DRV.END
MAN
SAVE usr/src/shared/x.ssc.drv.s
LOAD usr/src/drv/ssc.drv.s
ASM
