 lib environment
 sttl Pipe Handling Routines
 pag
 name pipes
 global crpipe,pipwr,piprd

*
* crpipe
*
* System call to set up a pipe.
*

crpipe lbsr getfil get a file slot
 beq crpip2 no slots left?
 ldd urglst+UD get file desc
 pshs d,x,y save file data
 lbsr getfil get file slot for write file
 beq crpip6 none left?
 ldd urglst+UD get file desc
 pshs d,x,y save file data
 ldd sppd get pipe device number
 lbsr alfdn allocate an fdn for this guy
 cmpx #0 did we get one
 beq crpip4 if null, error!
 ldd 0,s get write file desc
 std urglst+UX send back in X
 ldd 6,s get read file desc
 std urglst+UD send back in D
 lda #2 set up ref count
 sta frefct,x set in fdn
 lda #FBUSY set the busy bit
 sta fmode,x in the fdn
 lda #FMOD set modified flag
 sta fstat,x put in fdn
 ldy 2,s get write file entry
 ldu 8,s get read file entry
 stx ofnodp,y set the fdn entry
 stx ofnodp,u here too
 lda #OFREAD|OFPIPE set read,pipe status
 sta ofmode,u set in file entry
 lda #OFWRIT|OFPIPE set write,pipe status
 sta ofmode,y set write file status
 leas 12,s clean off stack
crpip2 rts return
crpip4 puls d,x,y get write file data
 clr ofrfct,x zero ref count
 clra -- ldd #0 set zero
 clrb
 std 0,y clear file slot in ublock
crpip6 puls d,x,y get read file data
 clr ofrfct,x zero reference count
 clra -- ldd #0 set zero
 clrb
 std 0,y zero out file slot
 rts return

 pag

*
* lckpip
*
* Lock a pipes fdn.  If already locked, sleep for it.
* Enter with Y pointing to fdn.
*

lckpip lda fstat,y get status
 bita #FLOCK is it locked?
 beq lckpi2
 ora #FWLCK set wait flag
 sta fstat,y set new status
 ldb #PIPEPR set priority
 pshs x,y save regs
 lbsr sleep sleep for fdn
 puls x,y reset regs
 bra lckpip repeat
lckpi2 ora #FLOCK set lock bit
 sta fstat,y save status
 rts return


*
* unlpip
*
* Unlock an fdn associated with a pipe.
* Enter with Y pointing to fdn.
*

unlpip lda fstat,y get status
 anda #!FLOCK clear lock bit
 sta fstat,y save new status
 bita #FWLCK someone waiting?
 beq unlpi2 if not, exit
 anda #!FWLCK clear wait bit
 sta fstat,y set new status
 lbra wakeup wake em up!
unlpi2 rts return


 pag

*
* pipwr
*
* Write to a pipe file.  On entry, X points to
* the file structure.
*

pipwr ldy ofnodp,x get fdn pointer
 ldd uicnt get data count
 pshs d save count
pipwr2 pshs x,y save data pointers
 bsr lckpip go lock the pipe
 ldd 4,s get data count
 beq pipwr6 if zero, exit
 lda frefct,y get ref count
 cmpa #2 is it 2?
 blo pipwr7 if not, error!
 ldd fsize+2,y get file size
 cmpd #MAXPIP is it over maximum?
 bhs pipwr8 if so, go sleep
 std uipos2 set position to end
 clra -- ldd #0 set upper pos to zero
 clrb
 std uipos
 ldd 4,s get count
 cmpd #MAXPIP greater than max?
 bls pipwr3
 ldd #MAXPIP set max count
pipwr3 std uicnt save as data count
 ldd 4,s get requested count
 subd uicnt sub actual count
 std 4,s save remaining byte count
 lbsr filwr do file write
 bsr unlpip unlock the pipe
 lda fmode,y get file mode
 bita #FPRDF is read sleeping?
 beq pipwr4
 anda #!FPRDF clear read bit
 sta fmode,y set new mode
 leay facces,y point to reader sleep addr
 lbsr wakeup wake em up
pipwr4 puls x,y reset file data
 bra pipwr2 repeat loop
pipwr6 clra -- ldd #0 set null word
 clrb
 std uicnt zero out count
 leas 6,s clean off stack
 lbra finpip finish & exit
pipwr7 lda #EPIPE set error
 sta uerror
 bsr unlpip unlock pipe
 ldx utask point to task entry
 ldd #WPIPES write pipe signal
 leas 6,s clean stack
 lbra xmtint transmit the interrupt
pipwr8 lda fmode,y get fdn mode
 ora #FPWRF set write sleep flag
 sta fmode,y
 lbsr unlpip unlock the pipe
 leay fmode,y point to write sleep addr
 ldb #PIPEPR set priority
 lbsr sleep goto sleep
 puls x,y reset file info
 bra pipwr2 repeat

 pag

*
* piprd
*
* Read from a pipe.  On entry, X points to the file
* structure.
*

piprd ldy ofnodp,x get fdn pointer
piprd2 pshs x,y save file info
 lbsr lckpip lock the pipe
 ldd fsize+2,y get file size
 beq piprd4 if zero, go sleep
 ldd ofpos2,x get position
 std uipos2 set io start
 clra -- ldd #0 set hi part to 0
 clrb
 std uipos
 lbsr filrd go read file
 ldx 0,s get file pointer
 ldd uipos2 get resultant pos
 std ofpos2,x save it
 ldy 2,s get fdn pointer
 ldd fsize+2,y get file size
 cmpd ofpos2,x end of pipe?
 bne piprd3
 clra -- ldd #0 set null word
 clrb
 std fsize+2,y truncate file to 0 size
 std ofpos2,x set pos to start
 lda fstat,y set modified flag - makes "count" correct
 ora #FMOD
 sta fstat,y put in fdn
 lda fmode,y get fdn mode
 bita #FPWRF is writer sleeping?
 beq piprd3
 anda #!FPWRF clear write bit
 sta fmode,y reset mode
 leay fmode,y point to write sleep addr
 lbsr wakeup wake him up
piprd3 puls x,y reset stack
 bra finpip finish & exit
piprd4 lbsr unlpip unlock the pipe
 clra -- ldd #0 -- default size = 0
 clrb
 std urglst+UA -- if pipe source has terminated
 lda frefct,y get fdn ref count
 cmpa #2 is it 2?
 blo piprd6 if not, no writer!
 lda fmode,y get modes
 ora #FPRDF set read wait bit
 sta fmode,y set new mode
 leay facces,y point to read sleep addr
 ldb #PIPEPR set priority
 lbsr sleep go sleep
 puls x,y reset file info
 bra piprd2 repeat loop
piprd6 puls x,y,pc return


*
* finpip
*
* Finish up pipe.
*

finpip ldd usarg1 get xfr count
 subd uicnt find actual xfrd
 std urglst+UA return in D
 lbra unlpip unlock & exit
