.title bio - basic unix style i/o routines .psect .prog. .even ; creat(fname,mode) ; ; fname file name ; mode (unused) creat:: jsr r5,csv$ ; Save the registers mov #wmode,-(sp) ; Open file in write mode br opncre ; Join common code ; open(fname,mode) ; ; fname file name ; mode (unused) open:: jsr r5,csv$ ; Save the registers mov #rmode,-(sp) ; Open file in read mode opncre: mov c$pmtr(r5),-(sp) ; Pass filename to fopen jsr pc,fopen ; Open the file mov (sp)+,(sp)+ ; Clean the stack tst r0 ; Check the value returned bne 10$ ; Branch if fopen succeeded mov #-1,r0 ; Return -1 on failures jmp cret$ ; Back we go 10$: bic #vf$bzy,v$flag(r0) ; Clear the buzy flag mov #-1,v$bnbr(r0) ; Set block to -1 clr v$bcnt(r0) ; Clear the count remaining jmp cret$ ; Back we go ; close(fd) ; ; fd file descriptor close:: jsr r5,csv$ ; Save the registers mov c$pmtr(r5),r4 ; Get the IOV pointer bit #vf$bzy,v$flag(r4) ; Is the buffer buzy? beq 10$ ; No... jsr pc,bwrite ; Write out the current buffer 10$: mov r4,-(sp) ; Pass file descriptor to fclose jsr pc,fclose ; Close the file tst (sp)+ ; Clean the stack jmp cret$ ; Back we go .psect .strn. rmode: .asciz \r\ ; read mode wmode: .asciz \w\ ; write mode ioerr: .byte e$$eof,e$$err,e$$fat .psect .prog. ; lseek(fd,offset,start) ; ; fd file descriptor ; offset byte offset (long) ; start (unused) lseek:: jsr r5,csv$ ; Save the registers mov c$pmtr(r5),r4 ; Get IOV pointer mov c$pmtr+2(r5),r1 ; Get high-order byte offset mov c$pmtr+4(r5),r2 ; Get low-order byte offset mov r2,r3 ; Get offset into block bic #^C777,r3 mov #9.,r0 ; Shift right 9 places 10$: asr r1 ; Shift the high 16 bits ror r2 ; Shift the low 16 bits dec r0 ; Done? bne 10$ ; Not yet...continue cmp r2,v$bnbr(r4) ; Same as current block? beq 20$ ; Yes... bit #vf$bzy,v$flag(r4) ; Current block buzy? beq 15$ ; No...don't write in back jsr pc,bwrite ; Write back the current block 15$: mov r2,v$bnbr(r4) ; Store the new block number jsr pc,bread ; Read it 20$: mov r4,v$bptr(r4) ; Create a pointer to the byte add #v$buff,v$bptr(r4) add r3,v$bptr(r4) mov #512.,v$bcnt(r4) ; Compute the count remaining sub r3,v$bcnt(r4) jmp cret$ ; Back we go ; acnt = read(fd,buf,buflen) ; ; fd file descriptor ; buf address of buffer ; buflen buffer length in bytes ; ; acnt the number of bytes actually transfered read:: jsr r5,csv$ ; Save the registers mov c$pmtr(r5),r4 ; Get IOV pointer mov c$pmtr+4(r5),r0 ; Get length in bytes mov c$pmtr+2(r5),r1 ; Get address of user buffer 10$: mov v$bcnt(r4),r2 ; Get count remaining in block buffer mov v$bptr(r4),r3 ; Get address of block buffer 15$: dec r0 ; Need more bytes? blt 99$ ; No...done dec r2 ; Are there more bytes? blt 20$ ; No...try next block movb (r3)+,(r1)+ ; Copy a byte into user buffer br 15$ 20$: inc r0 ; Backup the byte count bit #vf$bzy,v$flag(r4) ; Current buffer need writing? beq 25$ ; No... jsr pc,bwrite ; Write current block bcs rwerr ; Branch if write failed 25$: inc v$bnbr(r4) ; Bump the block number jsr pc,bread ; Read next block bcs rwerr ; Branch if the read failed br 10$ ; Continue 99$: mov r2,v$bcnt(r4) ; Save remaining byte count mov r3,v$bptr(r4) ; Save remaining byte pointer mov c$pmtr+4(r5),r0 ; Success, return full count jmp cret$ ; Back we go ; acnt = write(fd,buf,buflen) ; ; fd file descriptor ; buf address of buffer ; buflen buffer length in bytes ; ; acnt the number of bytes actually transfered write:: jsr r5,csv$ ; Save the registers mov c$pmtr(r5),r4 ; Get IOV pointer mov c$pmtr+4(r5),r0 ; Get length in bytes mov c$pmtr+2(r5),r1 ; Get address of user buffer 10$: mov v$bcnt(r4),r2 ; Get count remaining in block buffer mov v$bptr(r4),r3 ; Get address of block buffer 15$: dec r0 ; More bytes? blt 99$ ; No...done dec r2 ; More room? blt 20$ ; No...try next block movb (r1)+,(r3)+ ; Copy a byte into buffer bis #vf$bzy,v$flag(r4) ; Set the buffer buzy flag br 15$ 20$: inc r0 ; Backup the byte count bit #vf$bzy,v$flag(r4) ; Current buffer need writing? beq 25$ ; No... jsr pc,bwrite ; Write current block bcs rwerr ; Branch if write failed 25$: inc v$bnbr(r4) ; Bump the block number jsr pc,bread ; Read next block bcs rwerr ; Branch if the read failed br 10$ ; Continue 99$: mov r2,v$bcnt(r4) ; Save remaining byte count mov r3,v$bptr(r4) ; Save remaining byte pointer mov c$pmtr+4(r5),r0 ; Success, return full count jmp cret$ ; Back we go ; error handler for read and write rwerr: mov c$pmtr+4(r5),r1 ; Get full count sub r1,r0 ; Compute count transfered jmp cret$ ; Back we go ; block read routine bread: mov r0,-(sp) ; Save R0 clr -(sp) ; Make an arg block for .READW mov #256.,-(sp) ; Get the block length in words mov r4,-(sp) ; Get address of block buffer add #v$buff,(sp) mov v$bnbr(r4),-(sp) ; Get the block number mov #10*400,-(sp) ; .READW function code bisb v$lun(r4),(sp) ; Channel number mov sp,r0 ; R0 -> arg block emt 375 ; .READW bcs blkerr ; Error... add #5*2,sp ; Clean the stack mov #512.,v$bcnt(r4) ; Reset the count remaining mov r4,v$bptr(r4) ; Reset the buffer pointer add #v$buff,v$bptr(r4) bic #vf$bzy,v$flag(r4) ; Clear buzy bit mov (sp)+,r0 ; Restore R0 clc ; Success return rts pc ; block write routine bwrite: mov r0,-(sp) ; Save R0 clr -(sp) ; Make an arg block for .WRITW mov #256.,-(sp) ; Get the block length in words mov r4,-(sp) ; Get address of block buffer add #v$buff,(sp) mov v$bnbr(r4),-(sp) ; Get the block number mov #11*400,-(sp) ; .WRITW function code bisb v$lun(r4),(sp) ; Channel number mov sp,r0 ; R0 -> arg block emt 375 ; .WRITW bcs blkerr ; Error... add #5*2,sp ; Clean the stack mov #512.,v$bcnt(r4) ; Reset the count remaining mov r4,v$bptr(r4) ; Reset the buffer pointer add #v$buff,v$bptr(r4) bic #vf$bzy,v$flag(r4) ; Clear buzy bit mov (sp)+,r0 ; Restore R0 clc ; Success return rts pc blkerr: add #5*2,sp ; Clean the stack on errors movb @#52,r0 ; Get the error code beq 10$ ; Br if end of file bis #vf$err,(r4) ; Set error bit 10$: bis #vf$eof,(r4) ; Always set eof bit movb ioerr(r0),$$ferr ; Save the error code mov (sp)+,r0 ; Restore r0 sec ; Failure return rts pc .end