NEW
  AUTO 3,1
*/--------------------------------------
* # open
* ## C
* `hFD open(const char *pathname, short int flags);`
* ## ASM
* **In:**
* `>PUSHB flags`
* `>LDYA pathname`
* `>SYSCALL open`
* ## RETURN VALUE
* A = hFD
* REG File created on ProDOS : T=TXT,X=$0000
*\--------------------------------------
K.Open.FLAGS	.BS 1
K.Open.TYPE		.BS 1
K.Open.AUXTYPE	.BS 2
IO.hDev			.BS 1
IO.hFD			.BS 1
IO.hFILE		.BS 1
IO.Counter		.BS 2
*--------------------------------------		
K.Open			jsr PFT.YAToMLIPATH
				>PULLB K.Open.FLAGS

				lda #S.FI.T.TXT
				sta K.Open.TYPE
				stz K.Open.AUXTYPE
				stz K.Open.AUXTYPE+1
				
IO.Open.I		ldx #5					$/DEV/ 
				cpx K.MLI.PATH
				bcs IO.OPEN.REG			
				
.1				lda K.MLI.PATH,x
				cmp IO.DEVDIR,x
				bne IO.OPEN.REG
				dex
				bne .1
*--------------------------------------		
* /DEV/xxxxxx (CDEV,BDEV,LNK,DSOCK,SSOCK,PIPE)
*--------------------------------------		
				>LDYAI K.MLI.PATH+6		skip $/DEV/

				jsr K.GetDevByName
				bcc .7
				
				ldx #2
				
.10				lda Nod.Table.hPath-2,x
				beq .3

				jsr K.GetMemPtr
				>STYA ZPPtr1
				
				ldy #0
				
.2				lda (ZPPtr1),y
				iny
				cmp K.MLI.PATH,y
				bne .3
				cmp #0					end of string ?
				bne .2
				
				lda Nod.Table.hFD-2,x		return hFD
				sta IO.hFD
				jsr K.GetMemPtr
				
				bra .71
				
.3				inx
				cpx #K.NOD.MAX+2
				bne .10
				
				lda #MLI.E.NODEV
*				sec				
				rts						no OF found
				
.7				stx IO.hDev
.71				>STYA pFD
				
				lda (pFD)				#S.FD.T
				tax
				jmp (.8,x)
				
.8				.DA STDIO.IOERR			REG
				.DA STDIO.IOERR			DIR
				.DA IO.OPEN.CDEV
				.DA IO.OPEN.BDEV
				.DA STDIO.IOERR			LNK
				.DA IO.OPEN.DSOCK
				.DA IO.OPEN.SSOCK
				.DA IO.OPEN.PIPE

IO.OPEN.RTS		rts				
*--------------------------------------
IO.OPEN.REG		>MLICALL MLIGETFILEINFO
				bcc IO.OPEN.REG.E		Already Exists
				
				bit K.Open.FLAGS		Create if not exists ?
				bpl IO.OPEN.RTS			No, return MLI error
				
				ldx #2					Yes, Create...
				
.1				lda K.Open.TYPE,x
				sta K.MLI.PARAMS+4,x	File type,Aux type
				dex
				bpl .1

				lda #S.FI.ST.STD
				
				jsr IO.MLI.CREATE
				bcs IO.OPEN.RTS

IO.OPEN.REG.E	>LDYAI S.FD.REG
				ldx #S.MEM.F.INIT0+S.MEM.F.FD
				jsr MEM.GetMem.YAX
				bcs IO.OPEN.RTS
				
				>STYA pFD
				stx IO.hFD
								
*				ldy #S.FD.T				Done by GetMem0
*				lda #S.FD.T.REG
*				sta (pFD),y
				
				jsr IO.MLIOPEN
				bcs IO.OPEN.ERR
				
				lda K.Open.FLAGS
				bit #O.WRONLY
				beq .20					Write mode ?
				
				and #O.APPEND			Append ?
				bne .11					yes, go to end of file
				
				stz K.MLI.PARAMS+2
				stz K.MLI.PARAMS+3
				stz K.MLI.PARAMS+4
				>MLICALL MLISETEOF		no, reset size to 0
				bra .21
				
.11				>MLICALL MLIGETEOF
				bcs IO.OPEN.ERR
				
				>MLICALL MLISETMARK
.21				bcs IO.OPEN.ERR
				
.20				lda K.Open.FLAGS
				and #O.TEXT				Text Mode ?
				beq .8
				
				lda #$FF
				sta K.MLI.PARAMS+2
				lda #C.CR
				sta K.MLI.PARAMS+3
				>MLICALL MLINEWLINE
				bcs IO.OPEN.ERR
				
.8				lda IO.hFD
				rts

IO.OPEN.ERR		pha						Save Error Code
				lda IO.hFD
				jsr K.Close
				pla
				sec
				rts
*--------------------------------------
IO.OPEN.CDEV
IO.OPEN.BDEV	jsr K.IOCTL.GetPDrv
				
				ldx #IOCTL.OPEN
				lda IO.hDev
				jsr K.IOCTL.pDrvJmp
				bcs .9
	
				lda IO.hDev

.9				rts				
*--------------------------------------
IO.OPEN.DSOCK
*--------------------------------------
IO.OPEN.SSOCK	lda IO.hFD
				clc
				rts
*--------------------------------------
IO.OPEN.PIPE	ldy #S.FD.PIPE.S
				lda (pFD),y
				inc
				sta (pFD),y
				lda IO.hFD
				clc
				rts
*--------------------------------------
IO.MLI.CREATE	sta K.MLI.PARAMS+7		Storage Type
				
				ldx #3
				
.1				lda DATELO,x
				sta K.MLI.PARAMS+8,x	Create Date/Time
				dex
				bpl .1

				lda #S.FI.A.FULL
				sta K.MLI.PARAMS+3		Access
				
				>MLICALL MLICREATE
				rts
*/--------------------------------------
* # close
* ## C
* `int close(hFD fd);`
* ## ASM
* **In:**
* `lda fd`
* `>SYSCALL close`
*\--------------------------------------
K.Close			sta IO.hFD
				jsr K.GetMemPtr
				>STYA pFD

IO.Close.I		lda (pFD)				#S.FD.T
				tax
				jmp (.1,x)
				
.1				.DA IO.CLOSE.REG
				.DA IO.CLOSE.DIR
				.DA IO.CLOSE.CDEV
				.DA IO.CLOSE.BDEV
				.DA STDIO.IOERR			LNK
				.DA IO.CLOSE.DSOCK
				.DA IO.CLOSE.SSOCK
				.DA IO.CLOSE.PIPE
*--------------------------------------
IO.CLOSE.REG
IO.CLOSE.DIR	ldy #S.FD.REG.REF
				lda (pFD),y
				beq .1
				sta K.MLI.PARAMS+1
				>MLICALL MLICLOSE

.1				ldy #S.FD.REG.IOBUF
				lda (pFD),y
				beq .2
				
				jsr K.FreeMem
				
.2				lda IO.hFD
				jmp K.FreeMem
*--------------------------------------
IO.CLOSE.CDEV
IO.CLOSE.BDEV
				clc
				rts
*--------------------------------------
IO.CLOSE.DSOCK
IO.CLOSE.SSOCK	
				ldy #S.FD.SSOCK.CLOSE
				lda (pFD),y
				tax						Function Offset in LIB

				ldy #S.FD.SSOCK.IOHANDLER
				lda (pFD),y
				jsr K.GetMemPtr
				>STYA .1+1
				
				lda	IO.hFD				

.1				jmp $FFFF				SELF MODIFIED
*--------------------------------------
IO.CLOSE.PIPE	ldy #S.FD.PIPE.S

				lda (pFD),y
				bmi .1					remote PS closed its end
				
				lda #$80
				sta (pFD),y
				clc
				rts

.1				jsr IO.CLOSE.NOD

				ldy #S.FD.PIPE.hMem
				
				lda (pFD),y
				beq .2
				
				.DO AUXPIPE=1
				ldx #SYS.FreeStkObj
				jsr K.SYSCALL2.AUX
				.ELSE
				jsr K.FreeMem
				.FIN
				
.2				lda IO.hFD
				jmp K.FreeMem
*--------------------------------------
IO.CLOSE.NOD	ldx #2

				lda IO.hFD

.1				cmp Nod.Table.hFD-2,x
				bne .2
				
				stz Nod.Table.hFD-2,x
				
				lda Nod.Table.hPath-2,x
				stz Nod.Table.hPath-2,x
				jmp K.FreeMem
				
.2				inx
				cpx #K.Nod.MAX+2
				bne .1

				lda #E.INVH
*				sec				
				rts
*/--------------------------------------
* # read
* ## C
* `int read(hFD fd, void *buf, int count);`
* ## ASM
* **In:**
* `>PUSHWI count`
* `>PUSHW buf`
* `lda fd`
* `>SYSCALL read`
* ## RETURN VALUE
* CC: Y,A = bytes read
* CS: A = EC
*\--------------------------------------
K.Read			sta IO.hFD
				jsr K.GetMemPtr
				>STYA pFD
				
IO.Read.I		lda (pFD)				#S.FD.T
				tax
				jmp (.1,x)
				
.1				.DA IO.READ.REG
				.DA STDIO.IOERR			DIR
				.DA IO.READ.CDEV
				.DA STDIO.IOERR			BDEV
				.DA STDIO.IOERR			LNK
				.DA STDIO.IOERR			DSOCK
				.DA IO.READ.SSOCK
				.DA IO.READ.PIPE
*/--------------------------------------
* # write
* ## C
* `int write(hFD fd, const void *buf, int count);`
* ## ASM
* **In:**
* `>PUSHWI count`
* `>PUSHW buf`
* `lda fd`
* `>SYSCALL write`
* ## RETURN VALUE
* CC: Y,A = bytes written
* CS: A = EC
*\--------------------------------------
K.Write			sta IO.hFD
				jsr K.GetMemPtr
				>STYA pFD

IO.Write.I		lda (pFD)				#S.FD.T
				tax
				jmp (.1,x)
				
.1				.DA IO.WRITE.REG
				.DA STDIO.IOERR			DIR
				.DA IO.WRITE.CDEV
				.DA STDIO.IOERR			BDEV
				.DA STDIO.IOERR			LNK
				.DA STDIO.IOERR			DSOCK
				.DA IO.WRITE.SSOCK
				.DA IO.WRITE.PIPE
*--------------------------------------
IO.READ.REG		ldx #MLIREAD
				.HS 2C					BIT ABS
*--------------------------------------
IO.WRITE.REG	ldx #MLIWRITE

				ldy #S.FD.REG.REF
				lda (pFD),y
				sta K.MLI.PARAMS+1
				>PULLW K.MLI.PARAMS+2
				>PULLW K.MLI.PARAMS+4

				lda #4					Param Count = 4 for MLIREAD & MLIWRITE
				jsr GP.MLICall
				bcs .9
				>LDYA K.MLI.PARAMS+6
.9				rts
*--------------------------------------
IO.READ.CDEV	ldx #IOCTL.READ
				.HS 2C					BIT ABS
*--------------------------------------
IO.WRITE.CDEV	ldx #IOCTL.WRITE

				>PULLW K.S.IOCTL+S.IOCTL.BUFPTR
				>PULLW K.S.IOCTL+S.IOCTL.BYTECNT
				jsr K.IOCTL.GetPDRV
				
				>LDYAI K.S.IOCTL
				
				jsr K.IOCTL.pDrvJmp
				bcs .9
				>LDYA K.S.IOCTL+S.IOCTL.BYTECNT

.9				rts
*--------------------------------------
IO.WRITE.SSOCK	ldy #S.FD.SSOCK.WRITE
				.HS 2C					BIT ABS
*--------------------------------------
IO.READ.SSOCK	ldy #S.FD.SSOCK.READ

				lda (pFD),y
				tax						Function Offset in LIB

				ldy #S.FD.SSOCK.IOHANDLER
				lda (pFD),y
				jsr K.GetMemPtr
				>STYA .1+1
				
				lda	IO.hFD				

.1				jmp $FFFF				SELF MODIFIED
*--------------------------------------
IO.READ.PIPE	ldy #S.FD.PIPE.Used+1
				
				lda (pFD),y				Data ?
				dey
				ora (pFD),y
				bne .10					yes...
				
				ldy #S.FD.PIPE.S
				lda (pFD),y
				bpl .11

				jmp IO.READ.PIPE.EOF	Remote PS closed the Pipe

.11				jmp IO.READ.PIPE.NODATA
				
.10				>PULLW .3+1				get buf

				>PULLA					get cnt lo
				pha
				ldy #S.FD.PIPE.Used
				cmp (pFD),y
				
				>PULLA					get cnt hi
				tax
				iny
				sbc (pFD),y
				pla						A,X = cnt
				bcc .12					cnt < Used

				lda (pFD),y
				tax
				dey
				lda (pFD),y				A,X = Used
				
.12				sta .80+1
				stx .81+1
				eor #$ff
				sta IO.Counter

				txa
				eor #$ff
				sta IO.Counter+1
				
				ldy #S.FD.PIPE.Free

				clc
				lda (pFD),y
				adc .80+1
				sta (pFD),y

				iny
				
				lda (pFD),y
				adc .81+1
				sta (pFD),y
				
				iny						#S.FD.PIPE.Used

				sec 
				lda (pFD),y
				sbc .80+1
				sta (pFD),y
				
				iny
				
				lda (pFD),y
				sbc .81+1
				sta (pFD),y				

				ldy #S.FD.PIPE.Size+1
				lda (pFD),y
				sta .5+1				Page Count
				
				ldy #S.FD.PIPE.hMem
				lda (pFD),y
				
				.DO AUXPIPE=1
				ldx #SYS.GetStkObjPtr
				jsr K.SYSCALL2.AUX
				.ELSE
				jsr K.GetMemPtr
				.FIN
				
				sty .2+1
				sta .7+1				Pipe Buffer Base
				
				ldy #S.FD.PIPE.Tail+1
				clc
				adc (pFD),y
				sta .2+2
				
				dey						S.FD.PIPE.Tail
				lda (pFD),y
				tay
				
				ldx #0

.13				.DO AUXPIPE=1
				sta SETREADAUX
				.FIN

.1				inc IO.Counter
				bne .2
				inc IO.Counter+1
				beq .8
				
.2				lda $ffff,y				SELF MODIFIED
.3				sta $ffff,x				SELF MODIFIED

				inx
				bne .4
				
				inc .3+2
				
.4				iny
				bne .1
				
				.DO AUXPIPE=1
				sta CLRREADAUX
				.FIN

				ldy #S.FD.PIPE.Tail+1
				lda (pFD),y
				inc
.5				cmp #$ff				SELF MODIFIED
				beq .6
				
				sta (pFD),y
				inc .2+2
				ldy #0
				bra .13
				
.6				lda #0
				sta (pFD),y
				
.7				lda #$ff				SELF MODIFIED
				sta .2+2				Restore Pipe Buf base
				ldy #0
				bra .13
	
.8				.DO AUXPIPE=1
				sta CLRREADAUX
				.FIN
				tya
				ldy #S.FD.PIPE.Tail
				sta (pFD),y
				
.80				ldy #$ff				SELF MODIFIED
.81				lda #$ff				Y,A = bytes read

				clc
				rts

IO.READ.PIPE.EOF
				lda #MLI.E.EOF
				.HS 2C					BIT ABS
IO.READ.PIPE.NODATA
				lda #E.NODATA
				sec
				>RET 4
*--------------------------------------
* (pStack)+2	count
* (pStack)+0	buf
*--------------------------------------
IO.WRITE.PIPE	ldy #S.FD.PIPE.S
				lda (pFD),y

				bmi IO.READ.PIPE.EOF	Remote PS closed the Pipe

				ldy #S.FD.PIPE.Free
				lda (pFD),y
				ldy #2
				sec
				sbc (pStack),y

				tax

				ldy #S.FD.PIPE.Free+1
				lda (pFD),y
				ldy #3
				sbc (pStack),y
				bcc IO.READ.PIPE.NODATA	not enough room in PIPE

				ldy #S.FD.PIPE.Free+1
				sta (pFD),y
				dey
				txa
				sta (pFD),y				store new Free
				
				>PULLW .2+1				get dst buf

				>PULLA					get cnt lo
				sta .80+1
				pha 
				eor #$ff
				sta IO.Counter
				pla
				ldy #S.FD.PIPE.Used
				clc
				adc (pFD),y
				sta (pFD),y
				
				>PULLA					get cnt hi
				sta .81+1
				pha 
				eor #$ff
				sta IO.Counter+1
				pla
				iny						 #S.FD.PIPE.Used+1
				adc (pFD),y
				sta (pFD),y
				
				ldy #S.FD.PIPE.Size+1
				lda (pFD),y
				sta .5+1				Page Count

				ldy #S.FD.PIPE.hMem
				lda (pFD),y

				.DO AUXPIPE=1
				ldx #SYS.GetStkObjPtr
				jsr K.SYSCALL2.AUX
				.ELSE
				jsr K.GetMemPtr			get src buf
				.FIN
				
				sty .3+1
				sta .7+1				Pipe Buffer Base

				ldy #S.FD.PIPE.Head+1
				clc
				adc (pFD),y
				sta .3+2
				
				dey
				lda (pFD),y
				tay						S.FD.PIPE.Head

				ldx #0

.10				.DO AUXPIPE=1
				sta SETWRITEAUX
				.FIN
				
.1				inc IO.Counter
				bne .2
				inc IO.Counter+1
				beq .8
				
.2				lda $ffff,x				SELF MODIFIED
.3				sta $ffff,y				SELF MODIFIED

				inx
				bne .4
				
				inc .2+2
				
.4				iny
				bne .1
				
				.DO AUXPIPE=1
				sta CLRWRITEAUX
				.FIN
				
				ldy #S.FD.PIPE.Head+1
				lda (pFD),y
				inc
.5				cmp #$ff				SELF MODIFIED
				beq .6
				
				sta (pFD),y
				inc .3+2
				ldy #0
				bra .10
				
.6				lda #0
				sta (pFD),y
				
.7				lda #$ff				SELF MODIFIED
				sta .3+2
				ldy #0
				bra .10
				
.8				.DO AUXPIPE=1
				sta CLRWRITEAUX
				.FIN
				
				tya
				ldy #S.FD.PIPE.Head
				sta (pFD),y

.80				ldy #$ff				SELF MODIFIED
.81				lda #$ff				SELF MODIFIED
				clc						Y,A = bytes written		
				rts
*/--------------------------------------
* # IOCTL
* ## C
* `int ioctl(short int DevID, int request, void * param );`
* ## ASM
* `PUSHWI param`
* `PUSHBI request`
* `lda hDEV`
* `>SYSCALL IOCTL`
* ## RETURN VALUE
*  Y,A = ...
*\--------------------------------------
K.IOCTL			tax
				lda Dev.Table,x
				beq K.IOCTL.9
				
				sta pFD+1
				lda Dev.Table-1,x
				sta pFD
				
				jsr K.IOCTL.GetPDrv
				
				>PULLA
				tax						request
				
				>PULLYA					param

K.IOCTL.pDrvJmp	jmp (pDrv)
				
K.IOCTL.9		sec
				lda #MLI.E.NODEV
				>RET 3
*--------------------------------------
K.IOCTL.GetPDrv	ldy #S.FD.DEV.DRVPTR
				lda (pFD),y
				sta pDRV
				iny
				lda (pFD),y
				sta pDRV+1
				rts
*--------------------------------------
IO.EOF			lda (pFD)
				tax
				jmp (.1,x)
				
.1				.DA IO.EOF.REG
				.DA STDIO.IOERR			DIR
				.DA IO.EOF.CDEV
				.DA STDIO.IOERR			BDEV
				.DA STDIO.IOERR			LNK
				.DA STDIO.IOERR			DSOCK
				.DA IO.EOF.SSOCK
				.DA IO.EOF.PIPE
*--------------------------------------
				.DUMMY
				.OR ZPTMP
K.EOF.MARK		.BS 3
				.ED
*--------------------------------------				
IO.EOF.REG		>MLICALL MLIGETMARK
				bcs IO.EOF.REG.RTS
				
				ldy #2
				
.1				lda K.MLI.PARAMS+2,y
				sta K.EOF.MARK,y
				dey
				bpl .1

				>MLICALL MLIGETEOF
				bcs IO.EOF.REG.RTS

				ldy #2
				
.2				lda K.MLI.PARAMS+2,y
				eor K.EOF.MARK,y
				bne IO.EOF.FALSE
				dey
				bpl .2
				
IO.EOF.TRUE		lda #$ff
*				clc
IO.EOF.REG.RTS	rts
*--------------------------------------
IO.EOF.CDEV		lda #S.IOCTL.STATCODE.EOF
				jmp K.GetDevStatus.I
*--------------------------------------
IO.EOF.SSOCK	ldy #S.FD.SSOCK.EOF

				lda (pFD),y
				tax						Function Offset in LIB

				ldy #S.FD.SSOCK.IOHANDLER
				lda (pFD),y
				jsr K.GetMemPtr
				>STYA .1+1
				
				lda	IO.hFD				

.1				jmp $FFFF				SELF MODIFIED
*--------------------------------------
IO.EOF.PIPE		clc
				ldy #S.FD.PIPE.Used
				lda (pFD),y
				iny
				ora (pFD),y
				beq IO.EOF.TRUE
				
IO.EOF.FALSE	lda #0
*				clc
				rts			
*--------------------------------------
IO.MLIOPEN		>LDYAI 1024				get a ProDOS IOBUF
				ldx #S.MEM.F.ALIGN+S.MEM.F.NOMOVE
				jsr MEM.GetMem.YAX
				bcs .9

				>STYA K.MLI.PARAMS+3	Save Ptr to IOBUF for MLIOPEN call
				txa
				ldy #S.FD.REG.IOBUF
				sta (pFD),y

				>MLICALL MLIOPEN
				bcs .9
				
				lda K.MLI.PARAMS+5		get ref_num
				ldy #S.FD.REG.REF
				sta (pFD),y

				sta K.MLI.PARAMS+1		Next MLI Calls are REF_NUM based

*				clc				
.9				rts
*--------------------------------------
IO.DEVDIR		.DA #5					>PSTR "/DEV/"
*--------------------------------------
STAT.FIFO		.AS "/DEV/FIFO"
*--------------------------------------
MAN
SAVE USR/SRC/SYS/KERNEL.S.IO
LOAD USR/SRC/SYS/KERNEL.S
ASM
