NEW
  AUTO 3,1
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF drv/uther2.ai.drv
*--------------------------------------
				.INB inc/macros.i
				.INB inc/a2osx.i
				.INB inc/kernel.i
				.INB inc/mli.e.i
				.INB inc/nic.i
				.INB inc/nic.w5100.i
				.INB inc/eth.i
				.INB inc/net.tcpip.i
				.INB inc/libtcpip.i
*--------------------------------------
ZPArgPtr		.EQ ZPBIN
DEVSLOT0x		.EQ ZPBIN+2
*--------------------------------------
*			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
L.SSCANF.MAC	.DA SSCANF.MAC
L.MAC0			.DA DCB+S.DCB.NIC.MAC
L.MAC1			.DA DCB+S.DCB.NIC.MAC+1
L.MAC2			.DA DCB+S.DCB.NIC.MAC+2
L.MAC3			.DA DCB+S.DCB.NIC.MAC+3
L.MAC4			.DA DCB+S.DCB.NIC.MAC+4
L.MAC5			.DA DCB+S.DCB.NIC.MAC+5
				.DA 0					End Of Reloc Table
*--------------------------------------
Dev.Detect		>STYA ZPArgPtr

				>LDYA L.MSG.DETECT
				>SYSCALL PutS

				ldx #$70+$88
				ldy #7

.1				lda A2osX.S-1,y		IO based detection, avoid scanning in Disk Controller IO!!!!
				bne .2

				lda #W5100.MR.RST
				sta W5100.MR,x

				lda #0

.10				dec						give some time....
				bne .10

				lda #W5100.MR.PB+W5100.MR.AI+W5100.MR.IND
				sta W5100.MR,x

				pha
				pla

				lda W5100.MR,x
				cmp #W5100.MR.PB+W5100.MR.AI+W5100.MR.IND
				bne .2

				>AR.SELECT RTR
				lda W5100.DR,x		Get RTR HI
				cmp /2000
				bne .2

				lda W5100.DR,x		Get RTR LO
				cmp #2000
				beq	.3

.2				dec FD.DEV.NAME+3
				txa
				sec
				sbc #$10
				tax
				dey
				bne .1

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

				lda #MLI.E.NODEV
				sec
				rts

.3				stx DEVSLOTx0
				sty DEVSLOT0x

				jsr Dev.ParseArgs
				bcs .99

				>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
.99				bcs .9

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

				>PUSHW L.FD.DEV
				>PUSHW L.FD.DEV.NAME
				>SYSCALL MKDev
				bcs .9

				ldx DEVSLOT0x
				lda #A2osX.S.NIC
				sta A2osX.S-1,x
*				clc
.9				rts
*--------------------------------------
Dev.ParseArgs	lda (ZPArgPtr)
				bne .1

				lda A2osX.R16
				eor A2osX.T16
				sta DCB+S.DCB.NIC.MAC+3
				eor A2osX.R16+1
				sta DCB+S.DCB.NIC.MAC+4
				eor A2osX.T16+1
				sta DCB+S.DCB.NIC.MAC+5
				clc
				rts

.1				>PUSHW ZPArgPtr
				>PUSHW L.SSCANF.MAC

				ldx #0

.2				>PUSHW L.MAC0,x
				inx
				inx
				cpx #12
				bne .2

				>PUSHBI 12				6 x byte PTRs

				>SYSCALL SScanF
				bcc .8

				lda #E.SYN
*				sec
.8				rts
*--------------------------------------
CS.END
ARGS			.BS 2
MSG.DETECT		.CZ "UtherNet2/W5100 Driver (ARP/IP Offload)."
MSG.DETECT.OK	.CZ "UtherNet2/W5100 Installed As Device : %s\r\n"
MSG.DETECT.KO	.CZ "Hardware Not Found."
SSCANF.MAC		.CZ "%h:%h:%h:%h:%h:%h"
*--------------------------------------
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 "eth7"
*--------------------------------------
*			Driver Code
*--------------------------------------
ZPIOCTL			.EQ ZPDRV
ZPBufPtr		.EQ ZPDRV+2
Counter			.EQ ZPDRV+4
Offset			.EQ ZPDRV+6
RXTX.Size		.EQ ZPDRV+8
BUF.Size		.EQ ZPDRV+10
RX.IP			.EQ ZPDRV+12			(4)
Sn.IO			.EQ ZPDRV+16
Sn.BASE			.EQ ZPDRV+17
Sn.MASK			.EQ ZPDRV+18
*--------------------------------------
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
				.DA 0					end or relocation
*--------------------------------------
STATUS			jsr GET.IOCTLBUFPTR

				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 STATUS.9

				ldy #S.DCB.NIC-1

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

				clc
				rts

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

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

				ldy #S.DCB.NIC-1

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

				bra OPEN.I
*--------------------------------------
OPEN			lda #S.DIB.S.OPENED
				bit DIB+S.DIB.S
				beq OPEN.I

				lda #MLI.E.OPEN
				sec
				rts

OPEN.I			jsr CLOSE

*				ldx DEVSLOTx0			Done by CLOSE

				lda #W5100.MR.PB+W5100.MR.AI+W5100.MR.IND
				sta W5100.MR,x

				>AR.SELECT SHAR

				ldy	#0

.1				lda DCB+S.DCB.NIC.MAC,y
				sta W5100.DR,x
				iny
				cpy #6
				bne .1

				>AR.SELECT GAR

				ldy #0

.2				lda DCB+S.DCB.NIC.GW,y
				sta W5100.DR,x
				iny
				cpy #4
				bne .2

				>AR.SELECT SUBR			Implicit, next to GAR

				ldy #0

.3				lda DCB+S.DCB.NIC.MASK,y
				sta W5100.DR,x
				iny
				cpy #4
				bne .3

				>AR.SELECT SIPR

				ldy #0

.4				lda DCB+S.DCB.NIC.IP,y
				sta W5100.DR,x
				iny
				cpy #4
				bne .4

				>AR.SELECT RMSR
				lda #%01010101		RAW=2k,ICMP=2k,UDP=2k,TCP=2k
				sta W5100.DR,x		...for Socket RX Buffers
				sta W5100.DR,x		...for Socket TX Buffers

				>AR.SELECT S0.MR
				lda #W5100.AR.Sn.MR.MACRAW+W5100.AR.Sn.MR.MF
				sta W5100.DR,x

				>AR.SELECT S0.CR
				lda #W5100.AR.Sn.CR.OPEN
				sta W5100.DR,x
*--------------------------------------
				lda /W5100.AR.S1.MR
				sta Sn.IO

				ldy #S.IP.PROTOCOL.ICMP
				jsr OPEN.SnY

				inc Sn.IO

				ldy #S.IP.PROTOCOL.TCP
				jsr OPEN.SnY

				inc Sn.IO

				ldy #S.IP.PROTOCOL.UDP
				jsr OPEN.SnY

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

				clc
				rts
*--------------------------------------
OPEN.SnY		phy
				>AR.Sn.SELECT S0.MR
				lda #W5100.AR.Sn.MR.IPRAW
				sta W5100.DR,x

				>AR.Sn.SELECT S0.PORT
				stz W5100.DR,x
				stz W5100.DR,x

*				>AR.Sn.SELECT S0.DHAR
				
*				ldy #6					DHAR
*				lda #$EE
				
*.1				sta W5100.DR,x
*				dey
*				bne .1

*				>AR.Sn.SELECT S0.DIPR

*				ldy #4					DIPR
				
*.2				stz W5100.DR,x
*				dey
*				bne .2

				>AR.Sn.SELECT S0.DPORT
				stz W5100.DR,x
				stz W5100.DR,x

				>AR.Sn.SELECT S0.MSSR
				lda /K.ETH.FRAME.LEN
				sta W5100.DR,x
				lda #K.ETH.FRAME.LEN
				sta W5100.DR,x

				>AR.Sn.SELECT S0.PROTO
				pla
				sta W5100.DR,x

				>AR.Sn.SELECT S0.TOS
				stz W5100.DR,x

				>AR.Sn.SELECT S0.TTL
				lda #K.IP.TTL
				sta W5100.DR,x

				>AR.Sn.SELECT S0.CR
				lda #W5100.AR.Sn.CR.OPEN
				sta W5100.DR,x
				rts
*--------------------------------------
CLOSE			ldx DEVSLOTx0

				lda #W5100.MR.RST
				sta W5100.MR,x

				lda $C019				we can use VBL as we are not on //c

.1				eor $C019
				bpl .1

				lda $C019

.2				eor $C019
				bpl .2

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

				clc
				rts
*--------------------------------------
READ			php
				sei

				>STYA ZPIOCTL

				ldx DEVSLOTx0

				ldy #Sn.Cnt-1

.1				lda Sn.IO.BASE,y
				sta Sn.IO
				sta W5100.AR,x
				lda #W5100.AR.S0.RX.RSR
				sta W5100.AR+1,x

				lda W5100.DR,x			get the received size HI
				ora W5100.DR,x      	LO
				beq .2

				jmp READ.IPRAW

.2				dey
				bne .1

				lda /W5100.AR.S0.RX.RSR
				sta W5100.AR,x
				lda #W5100.AR.S0.RX.RSR
				sta W5100.AR+1,x

				lda W5100.DR,x			get the received size HI
				ora W5100.DR,x      	LO
				bne READ.RAW

.9				jmp READWRITE.NODATA
*--------------------------------------
READ.RAW		>AR.SELECT S0.RX.RD
				lda W5100.DR,x			get the received ptr HI
				sta Offset+1
				ldy W5100.DR,x			get the received ptr LO
				sty Offset

				and /$7FF
				ora /RX.BASE
				sta W5100.AR,x
				tya
				sta W5100.AR+1,x

				lda W5100.DR,x			get RX.Size HI (Frame size + 2)
				sta RXTX.Size+1
				lda W5100.DR,x			get RX.Size LO
				sta RXTX.Size

				ldy #S.IOCTL.BYTECNT
				sec
				sbc #2					MACRAW:strip 2 bytes Header from Size
				sta (ZPIOCTL),y
				sta BUF.Size
				eor #$ff
				sta Counter

				lda RXTX.Size+1
				sbc #0
				iny
				sta (ZPIOCTL),y
				sta BUF.Size+1
				eor #$ff
				sta Counter+1

				>LDYA BUF.Size
				>SYSCALL2 GetMem
				bcc .14

				jmp READWRITE.9

.14				>STYA ZPBufPtr
				phx

				phy
				ldy #S.IOCTL.BUFPTR+1
				sta (ZPIOCTL),y
				dey
				pla
				sta (ZPIOCTL),y

				ldy #0

				ldx DEVSLOTx0

.2				inc Counter
				bne .3

				inc Counter+1
				beq .4

.3				lda W5100.DR,x
				sta (ZPBufPtr),y
				iny
				bne .2

				inc ZPBufPtr+1
				bra .2

.4				>AR.SELECT S0.RX.RD

				lda Offset
				clc
				adc RXTX.Size
				pha						save LO

				lda Offset+1
				adc RXTX.Size+1
				sta W5100.DR,x			write HI
				pla
				sta W5100.DR,x			write LO

				>AR.SELECT S0.CR
				lda #W5100.AR.Sn.CR.RCVD
				sta W5100.DR,x

				pla						hMem

				plp
				clc
				rts
*--------------------------------------
READ.IPRAW		lda Sn.IP.PROTOCOL,y
				sta FRM.HDR.PROTO

				lda Sn.RX.BASE,y
				sta Sn.BASE
				lda Sn.RXTX.MASK,y
				sta Sn.MASK

				>AR.Sn.SELECT S0.RX.RD
				lda W5100.DR,x			get the received ptr HI
				sta Offset+1
				ldy W5100.DR,x			get the received ptr LO
				sty Offset

				and Sn.MASK
				ora Sn.BASE
				sta W5100.AR,x
				tya
				sta W5100.AR+1,x

				ldy #0

.10				lda W5100.DR,x			IPRAW:Get Source IP
				sta RX.IP,y
				iny
				cpy #4
				bne .10

				lda W5100.DR,x			get RX.Size HI (not including 6 bytes Header)
				sta RXTX.Size+1
				eor #$ff
				sta Counter+1

				lda W5100.DR,x			get RX.Size LO
				sta RXTX.Size
				eor #$ff
				sta Counter

				eor #$ff

				clc
				adc #S.IP
				sta BUF.Size
				ldy #S.IOCTL.BYTECNT
				sta (ZPIOCTL),y

				lda RXTX.Size+1
				adc /S.IP
				sta BUF.Size+1
				iny
				sta (ZPIOCTL),y

				lda RXTX.Size
				clc
				adc #6				 	IPRAW: Add 6 bytes to Total Size
				sta RXTX.Size
				bcc .11

				inc RXTX.Size+1

.11				lda RXTX.Size
				clc
				adc #S.IP-S.ETH.EII
				sta FRM.HDR.IPLEN+1

				lda RXTX.Size+1
				adc /S.IP-S.ETH.EII
				sta FRM.HDR.IPLEN

				>LDYA BUF.Size
				>SYSCALL2 GetMem
				bcc .14

				jmp READWRITE.9

.14				>STYA ZPBufPtr
				phx

				phy
				ldy #S.IOCTL.BUFPTR+1
				sta (ZPIOCTL),y
				dey
				pla
				sta (ZPIOCTL),y

				ldy #S.ETH.EII.TYPE

.15				lda FRM.HDR-S.ETH.EII.TYPE,y
				sta (ZPBufPtr),y
				iny
				cpy #S.ETH.EII.TYPE+FRM.HDR.LEN
				bne .15

				ldx #3
				ldy #S.IP.SRC+3

.12				lda RX.IP,x
				sta (ZPBufPtr),y
				dey
				dex
				bpl .12

				ldx #3
				ldy #S.IP.DST+3

.13				lda DCB+S.DCB.NIC.IP,x
				sta (ZPBufPtr),y
				dey
				dex
				bpl .13

				ldy #S.IP

				ldx DEVSLOTx0

.2				inc Counter
				bne .3

				inc Counter+1
				beq .4

.3				lda W5100.DR,x
				sta (ZPBufPtr),y
				iny
				bne .2

				inc ZPBufPtr+1
				bra .2

.4				>AR.Sn.SELECT S0.RX.RD

				lda Offset
				clc
				adc RXTX.Size
				pha						save LO

				lda Offset+1
				adc RXTX.Size+1
				sta W5100.DR,x			write HI
				pla
				sta W5100.DR,x			write LO

				>AR.Sn.SELECT S0.CR
				lda #W5100.AR.Sn.CR.RCVD
				sta W5100.DR,x

				pla						hMem

				plp
				clc
				rts
*--------------------------------------
READWRITE.NODATA
				lda #E.NODATA

READWRITE.9		plp
				sec
				rts
*--------------------------------------
WRITE			php
				sei

				jsr GET.IOCTLBUFPTR

				ldy #S.IOCTL.BYTECNT
				lda (ZPIOCTL),y

				sec
				sbc #S.IP

				sta RXTX.Size
				eor #$ff
				sta Counter

				iny
				lda (ZPIOCTL),y

				sbc /S.IP

				sta RXTX.Size+1
				eor #$ff
				sta Counter+1

				ldy #S.IP.PROTOCOL
				lda (ZPBufPtr),y

				ldy #Sn.cnt-1

.10				cmp Sn.IP.PROTOCOL,y
				beq .11

				dey
				bne .10

				plp
				lda #MLI.E.IO
				sec
				rts

.11				lda Sn.IO.BASE,y
				sta Sn.IO
*			ora #$30
*			sta $426	
				lda Sn.TX.BASE,y
				sta Sn.BASE
				lda Sn.RXTX.MASK,y
				sta Sn.MASK

				ldx DEVSLOTx0

				ldy #S.IP.DST
				lda (ZPBufPtr),y
				beq .12
				
				cmp #$ff
				bne .13

.12
*				>AR.Sn.SELECT S0.DHAR

*				ldy #6
*				lda #$ff

*.20				sta W5100.DR,x
*				dey
*				bne .20
				
				>AR.Sn.SELECT S0.DIPR
				
*				lda #$ff
*				ldy #3

*.21				sta W5100.DR,x
*				dey
*				bpl .21

				lda #255
				sta W5100.DR,x
				lda #255
				sta W5100.DR,x
				lda #255
				sta W5100.DR,x
				lda #255
				sta W5100.DR,x

				bra .14

.13				>AR.Sn.SELECT S0.DIPR

				ldy #S.IP.DST

.1				lda (ZPBufPtr),y
				sta W5100.DR,x
				iny
				cpy #S.IP.DST+4
				bne .1

.14				>AR.Sn.SELECT S0.TX.FSR
				lda W5100.DR,x			get send size HI
				ldy W5100.DR,x      	LO
				cpy RXTX.Size
				sbc RXTX.Size+1
				bcc .9

				>AR.Sn.SELECT S0.TX.WR
				lda W5100.DR,x			Get HI
				ldy W5100.DR,x			Get LO
				and Sn.MASK
				ora Sn.BASE
				sta W5100.AR,x			Write HI
				sta Offset+1
				tya
				sta W5100.AR+1,x		Write LO
				sta Offset

				ldy #S.IP

.2				inc Counter
				bne .3

				inc Counter+1
				beq .8

.3				lda (ZPBufPtr),y
				sta W5100.DR,x
				iny
				bne .2

				inc ZPBufPtr+1
				bra .2

.8				>AR.Sn.SELECT S0.TX.WR
				lda Offset
				clc
				adc RXTX.Size
				pha						save LO
				lda Offset+1
				adc RXTX.Size+1
				sta W5100.DR,x			write HI
				pla
				sta W5100.DR,x			write LO

				>AR.Sn.SELECT S0.CR
				lda #W5100.AR.Sn.CR.SEND
				sta W5100.DR,x

				plp
				clc
				rts
				
.9				lda #E.NODATA

				plp
				sec
				rts
*--------------------------------------
GET.IOCTLBUFPTR	>STYA ZPIOCTL
				ldy #S.IOCTL.BUFPTR
				lda (ZPIOCTL),y
				sta ZPBufPtr
				iny
				lda (ZPIOCTL),y
				sta ZPBufPtr+1
				rts
*--------------------------------------
DRV.CS.END
Sn.cnt			.EQ 4
Sn.IP.PROTOCOL	.DA #0,#S.IP.PROTOCOL.ICMP,#S.IP.PROTOCOL.TCP,#S.IP.PROTOCOL.UDP
Sn.IO.BASE		.DA /W5100.AR.S0.MR,/W5100.AR.S1.MR,/W5100.AR.S2.MR,/W5100.AR.S3.MR
Sn.TX.BASE		.DA /TX.BASE,/TX.BASE+$800,/TX.BASE+$1000,/TX.BASE+$1800
Sn.RX.BASE		.DA /RX.BASE,/RX.BASE+$800,/RX.BASE+$1000,/RX.BASE+$1800
Sn.RXTX.MASK	.DA /$7FF,/$7FF,/$7FF,/$7FF
DEVSLOTx0		.BS 1
*--------------------------------------
DIB				.DA #0
				.DA #0,#0,#0			size
				.PS "UtherNetII/W5100"
				.DA #S.DIB.T.NIC
				.BS 1					Subtype
				.DA K.VER				Version
*--------------------------------------
DCB				.DA #S.DCB.T.NIC
				.DA #S.DCB.NIC.FLAGS.ARPOFFLOAD+S.DCB.NIC.FLAGS.IPOFFLOAD
				.DA #S.DCB.NIC.LINK.OK+S.DCB.NIC.LINK.FD
				.DA #S.DCB.NIC.SPEED.100
				.HS 0008DC123456		MAC
				.DA #0,#0,#0,#0			IP
				.DA #0,#0,#0,#0			MASK
				.DA #255,#255,#255,#255			GW
*--------------------------------------
FRM.HDR			.HS 0800				S.ETH.EII.TYPE
				.HS 4500
FRM.HDR.IPLEN	.BS 2					TOTAL LEN
				.DA 0					ID
				.DA 0					FLAGS
				.DA #64					TTL
FRM.HDR.PROTO	.BS 1					IP.PROTO
				.DA 0					CHECKSUM
FRM.HDR.LEN		.EQ *-FRM.HDR
*FRM.HDR.SRC	.BS 4					IP.SRC
*				.BS 4					IP.DST
*--------------------------------------
DRV.END
MAN
SAVE usr/src/drv/uther2.ai.drv.s
ASM
