NEW
  AUTO 3,1
				.OP	65C02
				.OR	$2000
*--------------------------------------
				.DO UDETHDMA=1
				.TF drv/udeth.d.drv
				.ELSE
				.TF drv/udeth.drv
				.FIN
*--------------------------------------
UD.ROM.SignOfs	.EQ $EC					"UltimateDrive"
UD.ROM.VerOfs	.EQ $F9					MAX/MIN

UD.IO.Exec		.EQ $C080				Write
UD.IO.Status	.EQ $C081				Read
UD.IO.Cmd		.EQ $C082				Write
UD.IO.Cmd.NetOpen	.EQ $70
UD.IO.Cmd.NetClose	.EQ $71
UD.IO.Cmd.NetSend	.EQ $72
UD.IO.Cmd.NetRcvd	.EQ $73
UD.IO.Cmd.NetPeek	.EQ $74
UD.IO.Cmd.NetStatus	.EQ $75
UD.IO.Cmd.NetSDMA   .EQ $76				Send Frame Via DMA
UD.IO.Cmd.NetRDMA   .EQ $77				Read Frame via DMA
UD.IO.UnitNum	.EQ $C083				Write
UD.IO.MemPtrL	.EQ $C084
UD.IO.MemPtrH	.EQ $C085
UD.IO.BlockNum	.EQ $C086				Write 4 bytes, BE
UD.IO.RData		.EQ $C087				Read
UD.IO.WData		.EQ $C088				Write
UD.IO.DoDMA		.EQ $C089				Write
UD.IO.Mode		.EQ $C08D				Read NZ = DMA, Write b7
*--------------------------------------
				.DUMMY
				.OR ZPBIN
ZS.START
ZPPtr1			.BS 2
ZPArgPtr		.BS 2
DEVSLOT0x		.BS 1
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
L.SSCANF.MAC	.DA SSCANF.MAC
L.MAC0			.DA DCB+S.DCB.NIC.MAC
				.DA DCB+S.DCB.NIC.MAC+1
				.DA DCB+S.DCB.NIC.MAC+2
				.DA DCB+S.DCB.NIC.MAC+3
				.DA DCB+S.DCB.NIC.MAC+4
				.DA DCB+S.DCB.NIC.MAC+5
				.DA 0					End Of Reloc Table
*--------------------------------------
Dev.Detect		>STYA ZPArgPtr

				>LDYA L.MSG.DETECT
				>SYSCALL PutS

				lda #UD.ROM.SignOfs
				sta ZPPtr1
				lda #$C7

.1				sta ZPPtr1+1

				ldy #ROM.SIG.L-1

.10				lda (ZPPtr1),y
				cmp ROM.SIG,y
				bne	.2

				dey
				bpl .10

				lda ZPPtr1+1
				and #$0F
				sta DEVSLOT0x
				asl
				asl
				asl
				asl

				sta DEVSLOTx0
				bra .3

.2				dec FD.DEV.NAME+3
				lda ZPPtr1+1
				dec
				cmp #$C0
				bne .1

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

				lda #MLI.E.NODEV
				sec
.99				rts
*--------------------------------------
.3				ldy #UD.ROM.VerOfs
				lda (ZPPtr1),y
				sta DIB+S.DIB.VERSION+1
				iny
				lda (ZPPtr1),y
				sta DIB+S.DIB.VERSION

				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

				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
MSG.DETECT		.CZ "Ultimate Drive ETH/W5500 Driver."
MSG.DETECT.OK	.CZ "Ultimate Drive ETH/W5500 Installed As Device : %s\r\n"
MSG.DETECT.KO	.CZ "Hardware Not Found."
SSCANF.MAC		.CZ "%h:%h:%h:%h:%h:%h"
ROM.SIG			.AS "UltimateDrive"
ROM.SIG.L		.EQ *-ROM.SIG
*--------------------------------------
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
*--------------------------------------
* https://github.com/profdc9/ip65/blob/main/drivers/dan2d.s
*--------------------------------------
ZPIOCTL			.EQ ZPDRV
ZPBufPtr		.EQ ZPDRV+2
Counter			.EQ ZPDRV+4
*--------------------------------------
DRV.CS.START	cld
				jmp (.1,x)
.1				.DA STATUS
				.DA A2osX.BADCALL
				.DA A2osX.BADCALL
				.DA A2osX.BADCALL
				.DA A2osX.BADCALL
				.DA A2osX.BADCALL
				.DA OPEN
				.DA CLOSE
				.DA READ
				.DA WRITE
				.DA 0					end or relocation
*--------------------------------------
STATUS			>STYA ZPIOCTL

				jsr IO.GetStatus
				bcs STATUS.99

				ldy #S.IOCTL.S
				lda (ZPIOCTL),y
				beq .1

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

				ldx #S.DIB-1

				.HS 2C					bit abs

.1				ldx #3

				ldy #S.IOCTL.BUFPTR
				lda (ZPIOCTL),y
				sta .3+1
				iny
				lda (ZPIOCTL),y
				sta .3+2

.2				lda DIB,x

.3				sta $ffff,x				SELF MODIFIED
				dex
				bpl .2

				clc
				rts

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

				stz DCB+S.DCB.NIC.LINK

				lda #S.DCB.NIC.LINK.OK
				tsb DCB+S.DCB.NIC.LINK


				lda #S.DCB.NIC.LINK.FD
				tsb DCB+S.DCB.NIC.LINK

.1				ldy #S.IOCTL.BUFPTR
				lda (ZPIOCTL),y
				sta .3+1
				iny
				lda (ZPIOCTL),y
				sta .3+2
				ldx #S.DCB.NIC-1

.2				lda DCB,x

.3				sta $ffff,x				SELF MODIFIED
				dex
				bpl .2

				clc
				rts

STATUS.9		lda #MLI.E.BADCTL
STATUS.99		sec
				rts
*--------------------------------------
OPEN			lda #S.DIB.S.OPENED
				bit DIB+S.DIB.S
				bne .9

				jsr CLOSE

*				ldx DEVSLOTx0			Done by CLOSE

				lda #UD.IO.Cmd.NetOpen
				jsr IO.ExecA
				bcs .99

				ldy #0

.1				lda UD.IO.RData,x
				sta DCB+S.DCB.NIC.MAC,y
				iny

				cpy #6
				bcc .1

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

				clc
				rts

.9				lda #MLI.E.OPEN
				sec
.99				rts
*--------------------------------------
CLOSE			ldx DEVSLOTx0

				lda #UD.IO.Cmd.NetClose
				jsr IO.ExecA
				bcs .9

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

*				clc
.9				rts
*--------------------------------------
READ			php
				sei

				>STYA ZPIOCTL

				ldx DEVSLOTx0

				lda #UD.IO.Cmd.NetPeek
				jsr IO.ExecA
				bcs READWRITE.99

				lda UD.IO.RData,x
				sta Counter
				lda UD.IO.RData,x
				sta Counter+1
				ora Counter
				beq READWRITE.9

				>LDYA Counter
				>SYSCALL2 GetMem
				bcs READWRITE.99

				>STYA ZPBufPtr
				stx .8+1
				phy
				ldy #S.IOCTL.BUFPTR+1
				sta (ZPIOCTL),y
				dey
				pla
				sta (ZPIOCTL),y

				ldx DEVSLOTx0

				.DO UDETHDMA=0

				lda #UD.IO.Cmd.NetRcvd
				jsr IO.ExecA
				bcs READWRITE.99

				lda Counter
				ldy #S.IOCTL.BYTECNT
				sta (ZPIOCTL),y
				eor #$ff
				sta Counter

				lda Counter+1
				iny
				sta (ZPIOCTL),y
				eor #$ff
				sta Counter+1

				ldy #0

.1				inc Counter
				bne .2

				inc Counter+1
				beq .8

.2				lda UD.IO.RData,x
				sta	(ZPBufPtr),y
				iny
				bne .1

				inc ZPBufPtr+1
				bra .1

				.ELSE

				lda UD.IO.Status,x

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

				lda ZPBufPtr
				sta UD.IO.MemPtrL,x
				lda ZPBufPtr+1
				sta UD.IO.MemPtrH,x

				lda #UD.IO.Cmd.NetRDMA
				jsr IO.ExecA
				bcs READWRITE.99

				lda UD.IO.DoDMA,x

.1				lda UD.IO.Status,x
				bmi .1

				lsr
				bcs READWRITE.99

				.FIN

.8				lda #$ff				SELF MODIFIED

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

READWRITE.99	plp
				sec
				rts
*--------------------------------------
WRITE			php
				sei
				>STYA ZPIOCTL

				.DO UDETHDMA=0

				ldx DEVSLOTx0
				lda #UD.IO.Cmd.NetSend
				sta UD.IO.Cmd,x

				ldy #S.IOCTL.BYTECNT
				lda (ZPIOCTL),y
				sta UD.IO.WData,x
				eor #$ff
				sta Counter

				iny

				lda (ZPIOCTL),y
				sta UD.IO.WData,x
				eor #$ff
				sta Counter+1
				
				.FIN

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

				ldy #S.ETH.SRCMAC+5
				ldx #5

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

				ldx DEVSLOTx0

				.DO UDETHDMA=0

				ldy #0

.1				inc Counter
				bne .2

				inc Counter+1
				beq .8

.2				lda	(ZPBufPtr),y
				sta UD.IO.WData,x
				iny
				bne .1

				inc ZPBufPtr+1
				bra .1

.8				jsr IO.Exec
				bcs WRITE.99

				.ELSE

				lda UD.IO.Status,x

				ldy #S.IOCTL.BYTECNT
				lda (ZPIOCTL),y
				sta UD.IO.WData,x
				lda Counter+1
				iny
				lda (ZPIOCTL),y
				sta UD.IO.WData,x

				lda ZPBufPtr
				sta UD.IO.MemPtrL,x
				lda ZPBufPtr+1
				sta UD.IO.MemPtrH,x

				lda #UD.IO.Cmd.NetSDMA
				jsr IO.ExecA
				bcs READWRITE.99

				lda UD.IO.DoDMA,x

.1				lda UD.IO.Status,x
				bmi .1

				lsr
				bcs READWRITE.99

				.FIN

				plp
				clc
				rts

WRITE.99		lda #MLI.E.IO
				plp
				sec
				rts
*--------------------------------------
IO.GetStatus	stz DCB+S.DCB.NIC.LINK
				lda #S.DCB.NIC.SPEED.10
				sta DCB+S.DCB.NIC.SPEED

				ldx DEVSLOTx0

				lda #UD.IO.Cmd.NetStatus
				jsr IO.ExecA
				bcs .99

				lda UD.IO.RData,x		PHYCFGR
				lsr						CS if Link OK
				ror DCB+S.DCB.NIC.LINK
				lsr						CS if 100mb
				bcc .1

				inc DCB+S.DCB.NIC.SPEED

.1				lsr						CS if FD
				bcc .2

				lda #S.DCB.NIC.LINK.FD
				tsb DCB+S.DCB.NIC.LINK

.2				lda UD.IO.RData,x		VERSIONR
				sta DIB+S.DIB.VERSION

				clc

.99				rts
*--------------------------------------
IO.ExecA		sta UD.IO.Cmd,x

IO.Exec			stz UD.IO.UnitNum,x

				lda UD.IO.Exec,x

.1				lda UD.IO.Status,x
				bmi .1

				lsr						CS if error, A = ERROR CODE ?

				rts
*--------------------------------------
DRV.CS.END
DEVSLOTx0		.BS 1
*--------------------------------------
DIB				.DA #0
				.DA #0,#0,#0			size
				.PS "udeth/W5500     "
				.DA #S.DIB.T.NIC
				.BS 1					Subtype
				.BS 2					Version
*--------------------------------------
DCB				.DA #S.DCB.T.NIC
				.BS 1					FLAGS
				.BS 1					LINK
				.BS 1					SPEED
				.HS 000000000000		MAC
				.BS 12					IP/MASK/GW
*--------------------------------------
DRV.END
MAN
SAVE usr/src/shared/x.udeth.drv.s
LOAD usr/src/drv/udeth.d.drv.s
ASM
