Mercurial > hg > Members > kono > nitros9-code
changeset 1204:57157a062b5d
Rbf2 handles sector sizes up to 2048 bytes
author | boisy |
---|---|
date | Tue, 03 Jun 2003 15:19:30 +0000 |
parents | 70df6eac0ae3 |
children | 383d5981c23f |
files | level2/modules/rbf2.asm |
diffstat | 1 files changed, 3181 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level2/modules/rbf2.asm Tue Jun 03 15:19:30 2003 +0000 @@ -0,0 +1,3181 @@ +******************************************************************** +* RBF - Random Block File Manager +* +* $Id$ +* +* Modified for 6309 Native mode by Bill Nobel, L. Curtis Boyle & Wes Gale +* +* This also contains the patch for un-deleting files +* +* Undocumented SetStt/GetStt calls: +* +* GetStt: +* SS.FD ($0F) - Returns a file descriptor +* Entry: R$A=Path # +* R$B=SS.FD ($0F) +* R$X=Pointer to a 256 byte buffer +* R$Y=# bytes of FD required +* SS.FDInf ($20) - Directly reads a file descriptor from anywhere +* on drive. +* Entry: R$A=Path # +* R$B=SS.FDInf ($20) +* R$X=Pointer to a 256 byte buffer +* R$Y= MSB - Length of read +* LSB - MSB of logical sector # +* R$U= LSW of logical sector # +* SetStt: +* SS.FD ($0F) - Writes a file descriptor +* Entry: R$A=Path # +* R$B=SS.FD ($0F) +* R$X=Pointer to a maximum 256 byte buffer +* R$Y=# bytes of FD to write +* SS.Ticks ($10) - Set # ticks to wait for record lock release +* Entry: R$A=Path # +* R$B=SS.Ticks ($10) +* R$X=# Ticks to wait +* SS.Lock ($11) - Force Lock/Release of a file. +* Locks from current position to a specified size +* Entry: R$A=Path # +* R$B=SS.Lock ($11) +* R$X=LSW of end byte position +* R$U=MSW of end byte position +* SS.Attr ($1C) - Allows changing of file/directory attributes +* If changing directory attribute it scans to +* see if directory is empty. +* Entry: R$A=Path # +* R$B=SS.Attr ($1C) +* R$X= LSB - File attributes +* SS.RsBit ($1E) - Reserve bitmap sector (doesn't allocate) +* Locks the bitmap sector from other programs +* so they cannot allocate in it. +* Useful when working in allocation map. +* Entry: R$A=Path # +* R$B=SS.RsBit ($1E) +* R$X= LSB - Sector # of bitmap +* +* Ed. Comments Who YY/MM/DD +* ------------------------------------------------------------------ +* ??? Started putting in comments from buggy 1.09 ??? 93/09/19 +* code +* ??? Fixed WP error bug on file delete ??? 93/09/19 +* Fixed FD read error bug in delete +* ??? Fixed long overdue LHA bug ??? 94/07/15 +* Modified M$Exec driver calls @ L11EB to use +* V$DRIVEX +* ??? Changed L11EB to just PSHS/PULS A,X,PC ??? 94/07/27 +* instead of D,X,PC (saves 2 cycles per +* driver call) +* Changed BRA L12C6 @ L128E to PULS PC,U,X +* ??? NitrOS-9 2.00 distribution ??? ??/??/?? +* 35 Fixed FD.SEG bug GH ??/??/?? +* Folded RBF 30 comments into this version BGP 03/04/21 + + nam RBF + ttl Random Block File Manager + + ifp1 + use defsfile + use rbfdefs + endc + +rev set $01 +ty set FlMgr + IFNE H6309 +lg set Obj6309 + ELSE +lg set Objct + ENDC +tylg set ty+lg +atrv set ReEnt+rev +edition set 35 + + org $00 +size equ . + + mod eom,name,tylg,atrv,start,size + +name fcs /RBF/ + fcb edition + +L0012 fcb DRVMEM + + +**************************** +* +* Main entry point for RBF +* +* Entry: Y = Path descriptor pointer +* U = Register stack pointer + +start bra Create + nop + lbra Open + lbra MakDir + lbra ChgDir + lbra Delete + lbra Seek + lbra Read + lbra Write + lbra ReadLn + lbra WriteLn + lbra GetStat + lbra SetStat + lbra Close + + +* +* I$Create Entry Point +* +* Entry: A = access mode desired +* B = file attributes +* X = address of the pathlist +* +* Exit: A = pathnum +* X = last byte of pathlist address +* +* Error: CC Carry set +* B = errcode +* +Create pshs y Preserve path desc ptr + leas -$05,s Make 5 byte buffer on stack + IFNE H6309 + aim #^DIR.,R$B,u + ELSE + lda R$B,u force directory bit off + anda #^DIR. + sta R$B,u + ENDC + lbsr FindFile try & find it in directory + bcs Creat47 branch if doesn't exist + +* File already exists + ldb #E$CEF else exists error +Creat47 cmpb #E$PNNF not found? + bne Creat7E + +* File doesn't exist, create it + cmpa #PDELIM full path? + beq Creat7E yes, return + pshs x preserve filename pointer + ldx PD.RGS,y get register stack pointer + stu R$X,x save updated pathname pointer +* These 4 did have < in front, made 3 byte cmnds but some are 2! + ldb PD.SBP,y get physical sector # of segment list + ldx PD.SBP+1,y + lda PD.SSZ,y get size of segment list in bytes + ldu PD.SSZ+1,y + pshs u,x,b,a preserve it all + ldx PD.RGS,y get register stack pointer +* Calculate default file size, if enabled +* This sets D to 0 if bit 5 of R$A is NOT set. If bit 5 of R$A is set +* when called, register Y will contain a default file size + lda R$A,x get file mode (read/write/update) + clrb + anda #PEXEC. bit 5 set? + beq Creat6E no, skip ahead + ldd R$Y,x get default file size +* account for FD sector, I think. +* changed from addd #1, bcc, ldd #$FFFF. +* The INCD gets D=$0000 (and CC.Z set) if it overflows from $FFFF->$0000 +* then if it's zero, a DECD forces it to be $FFFF +Creat6E addd #1 above 64k in size? (bug fix, thanks Gene K.) + bcc Creat75 no, skip ahead: changed from BCC + ldd #$FFFF force it to 64k +Creat75 lbsr FatScan find the space in the allocation map + bcc Creat83 got it, skip ahead + leas 6,s purge segment sizes from stack +* and fall through to routine which returns with an error. + +Creat7C leas 2,s purge user's pathname pointer +Creat7E leas 5,s purge local data + lbra ErMemRtn return with error + +* Create the file +Creat83 std $0B,s save segment size + ldb PD.SBP,y save segment physical sector # in path desc. + ldx PD.SBP+1,y starting LSN + stb $08,s on stack too + stx $09,s + puls u,x,b,a restore segment physical sector # & sizes + stb PD.SBP,y save it as current + stx PD.SBP+1,y + sta PD.SSZ,y + stu PD.SSZ+1,y +* Find empty slot in directory sector for new file + IFNE H6309 + ldq PD.DCP,y get directory entry pointer for new file + stq PD.CP,y save it as current file pointer + ELSE + ldd PD.DCP,y + std PD.CP,y + ldd PD.DCP+2,y + std PD.CP+2,y + ENDC + lbsr L0957 move entry into sector buffer + bcs CreatB5 +CreatAC tst ,x file exist here already? + beq CreatC7 no, found empty slot, skip ahead + lbsr L0942 point to next entry + bcc CreatAC try again +CreatB5 cmpb #E$EOF end of directory? + bne Creat7C no, return error +* Create the directory entry for new file + ldd #DIR.SZ get size of directory entry + lbsr Writ599 add it to size of directory + bcs Creat7C out of alloc? + lbsr MDir263 set file size in file descriptor + lbsr L0957 read in a directory sector +CreatC7 leau ,x point to directory entry + lbsr Creat169 clear it out + puls x restore pathname pointer + os9 F$PrsNam parse it to get filename + bcs Creat7E + cmpb #29 length of name right size? + bls CreatD9 yes, skip ahead + ldb #29 else force it to 29 chars +CreatD9 clra move length to Y + tfr d,y + lbsr Writ5CB move name of file to directory entry + tfr y,d move length of name to D + ldy $05,s restore PDpointer + decb subtract 1 off length + IFNE H6309 + oim #$80,b,u set high bit on last char of name + ELSE + lda b,u + ora #$80 + sta b,u + ENDC + ldb ,s get logical sector # of file desc + ldx $01,s + stb DIR.FD,u save it into directory entry + stx DIR.FD+1,u + lbsr L1205 flush sector to disk + bcs Creat151 +* Setup file descriptor + ldu PD.BUF,y get sector buffer pointer + bsr Creat170 clear it out + lda #FDBUF get file descriptor in buffer flag + sta PD.SMF,y save it as current sector buffer state + ldx PD.RGS,y get register stack pointer + lda R$B,x get file attributes + sta FD.ATT,u save it as current attributes + ldx <D.Proc get process pointer + ldd P$User,x get user # + std FD.OWN,u save creation user + lbsr L02D1 place date & time into file descriptor + ldd FD.DAT,u get date last modified + std FD.Creat,u save it as creation date (since we just made it) + ldb FD.DAT+2,u + stb FD.Creat+2,u + ldb #$01 get link count + stb FD.LNK,u + ldd 3,s get segment size in sectors + IFNE H6309 + decd is it 1? + ELSE + subd #$0001 + ENDC + beq Creat131 yes, skip ahead + leax FD.SEG,u point to the start of the segment list + std FDSL.B,x save segment size + ldd 1,s get LSW of physical sector # of seg start + addd #1 we need to carry below, fr the adcb! (bug fix, thanks Gene K.) + std FDSL.A+1,x save LSW + ldb ,s get MSB of physical sector # of segment start + adcb #$00 need carry status of addd above + stb FDSL.A,x save MSB +Creat131 ldb ,s get p hysical sector # of segment start + ldx 1,s + lbsr L1207 flush file descriptor to disk + bcs Creat151 + lbsr L0A90 sort out any ocnflict for this sector + stb PD.FD,y save file descriptor physical sector # to pd + stx PD.FD+1,y + lbsr L0A2A update file/record lock for this sector + leas $05,s purge sector buffer from stack + ldx PD.Exten,y get path extension pointer + lda #EofLock set the file to EOF lock + sta PE.Lock,x + bra Open1CC +* Error on fD write to disk +Creat151 puls u,x,a restore segment start & size + sta PD.SBP,y put it into path descriptor + stx PD.SBP+1,y + clr PD.SSZ,y + stu PD.SSZ+1,y + pshs b save error code + lbsr ClrFBits + puls b restore error code +RtnMemry lbra ErMemRtn return with error + +* Clear out directory entry +* Entry: U = Directory entry pointer +Creat169 + IFNE H6309 + ldw #DIR.SZ get size of directory entry (name & LSN of FD) + ELSE + ldd #$0100+DIR.SZ + ENDC + bra Creat174 clear it out + +* Clear out sector buffer +* Entry: U = Sector buffer pointer +Creat170 + lbsr GrabSS + IFNE H6309 + ldw #$0100 get size of sector buffer +Creat174 pshs u,x preserve regs + leax <Creat170+3,pcr point to NULL byte +Creat17X tfm x,u+ clear buffer + deca + bne Creat17X + ELSE + clrb +Creat174 pshs u,x preserve regs +l1 clr ,u+ + decb + bne l1 + deca + bne l1 + ENDC + puls pc,u,x restore & return + + +* +* I$Open Entry Point +* +* Entry: A = access mode desired +* X = address of the pathlist +* +* Exit: A = pathnum +* X = last byte of pathlist address +* +* Error: CC Carry set +* B = errcode +* +Open pshs y preserve path descriptor pointer + lbsr FindFile try & find the file in current directory + bcs RtnMemry couldn't find it, return error + ldu PD.RGS,y get register stack pointer + stx R$X,u save updated pathname pointer + ldd PD.FD+1,y do we have a file descriptor? + bne Open1BB + lda PD.FD,y + bne Open1BB yes, skip ahead +* File descriptor doesn't exist + ldb PD.MOD,y get current file mode + andb #DIR. is it a directory? + lbne Clos29D yes, return not accessible eror + std PD.SBP,y set segment physical start to 0 + sta PD.SBP+2,y + std PD.SBL,y do logical as well + sta PD.SBL+2,y + ldx PD.DTB,y get pointer to drive table + lda DD.TOT+2,x get total # sectors on drive + std PD.SIZ+2,y copy it to file size (B=0) + sta PD.SSZ+2,y copy it to segment size as well + ldd DD.TOT,x + std PD.SIZ,y + std PD.SSZ,y + puls pc,y restore & return + +Open1BB lda PD.MOD,y get file mode + lbsr ChkAttrs can user access file? + bcs RtnMemry no, return no permission error + bita #WRITE. open for write? + beq Open1CC no, skip ahead + lbsr L02D1 update last date modified to current + lbsr L11FD update file descriptor on disk +Open1CC puls y restore path descriptor pointer + +* Update the path descriptor from the FD sector pointed to by U +Open1CE + IFNE H6309 + clrd get a 16 bit zero value + ELSE + clra + clrb + ENDC + std PD.CP+2,y set seek pointer to start of file + std PD.CP,y + std PD.SBL,y set segment start + sta PD.SBL+2,y + sta PD.SSZ,y set segment size + lda FD.ATT,u get file attributes + sta PD.ATT,y put it into path descriptor + ldd FD.SEG,u get the file's segment start sector # + std PD.SBP,y + lda FD.SEG+2,u + sta PD.SBP+2,y + ldd FD.SEG+FDSL.B,u + std PD.SSZ+1,y +* ldq FD.SIZ,u + ldd FD.SIZ,u get file size + ldx FD.SIZ+2,u + ldu PD.Exten,y get path extension pointer + cmpu PE.Confl,u head of the conflict tree? + beq Open209 yes, skip ahead + ldu PE.Confl,u get the conflicting path ext. pointer + ldu PE.PDptr,u get back pointer to the PD of conflicting process +* ldq PD.SIZ,u + ldd PD.SIZ,u get his size instead + ldx PD.SIZ+2,u +* stq PD.SIZ,y +Open209 std PD.SIZ,y set file size in path descriptor of caller + stx PD.SIZ+2,y + clr PD.SMF,y clear the state flags + rts return + + +* +* I$MakDir Entry Point +* +* Entry: X = address of the pathlist +* +* Exit: X = last byte of pathlist address +* +* Error: CC Carry set +* B = errcode +* +MakDir lbsr Create create a file descriptor + bcs MDir261 problem, return error + lda PD.ATT,y get attributes + ora #SHARE. set shareable bit + lbsr ChkAttrs can user access directory? + bcs MDir261 no, return error + ldd #DIR.SZ*2 get default directory size (for '.' & '..') + std PD.SIZ+2,y save it in path descriptor (MSW set to 0) + bsr MDir273 write out file descriptor + bcs MDir261 error, return + lbsr L0C6F + bcs MDir261 + lbsr RdFlDscr read in file descriptor + ldu PD.BUF,y get pointer to file descriptor + IFNE H6309 + oim #DIR.,FD.ATT,u set directory bit in attributes + ELSE + lda FD.ATT,u + ora #DIR. + sta FD.ATT,u + ENDC + bsr MDir266 + bcs MDir261 + lbsr Creat170 clear out sector + ldd #$2EAE get directory entry name for current & parent dir + std ,u save parent name + stb DIR.SZ,u save current name +* This is smaller and faster than the old method +* ldq PD.DFD-1,y get directory FD pointer into low 24-bits of Q +* clra make sure high byte is zero +* stq DIR.FD-1,u save in the dir: '.' and '..' have <28 char names + lda PD.DFD,y + sta DIR.FD,u + ldd PD.DFD+1,y + std DIR.FD+1,u +* ldq PD.FD-1,y get current FD into lower 24-bits of Q +* clra ensure high byte is zero +* stq DIR.SZ+DIR.FD-1,u save in the directory + lda PD.FD,y + sta DIR.SZ+DIR.FD,u + ldd PD.FD+1,y + std DIR.SZ+DIR.FD+1,u + + lbsr L1205 flush new directory ssector to disk +MDir261 bra Rt100Mem return to system all ok + +* Set new file size in file descriptor +* Entry: None +* Exit : New file size set in file descriptor on disk +MDir263 lbsr RdFlDscr read in file descriptor +MDir266 ldx PD.BUF,y get sector pointer + IFNE H6309 + ldq PD.SIZ,y get current file size + stq FD.SIZ,x save it in file descriptor + ELSE + ldd PD.SIZ,y + std FD.SIZ,x + ldd PD.SIZ+2,y + std FD.SIZ+2,x + ENDC + clr PD.SMF,y clear state flags +MDir273 lbra L11FD + + +* +* I$Close Entry Point +* +* Entry: A = path number +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +Close clra + tst PD.CNT,y any open paths? + bne Clos29C yes, return + lbsr L1237 flush current sector of needed + bcs Rt100Mem error, skip ahead + ldb PD.MOD,y get access mode + bitb #WRITE. is it write? + beq Rt100Mem no, skip ahead + ldd PD.FD,y + bne Clos290 + lda PD.FD+2,y + beq Rt100Mem +Clos290 bsr MDir263 set new file size in file descriptor + lbsr Gst5E5 reached EOF? + bcc Rt100Mem no, skip ahead + lbsr L0EFE + bra Rt100Mem skip ahead +Clos29C rts return +* Return file not accessible error +Clos29D ldb #E$FNA +ErMemRtn coma +Clos2A0 puls y + +* Generalized return to system +Rt100Mem pshs b,cc preserve error status + ldu PD.BUF,y get sector buffer pointer + beq RtMem2CF none, skip ahead + lbsr GetSSize get size of sector buffer + os9 F$SRtMem return the memory to system + ldx PD.Exten,y get path extension pointer + beq RtMem2CF none, return + lbsr L0A90 scan conflict list? + lda PE.PE,x return path extension to system + ldx <D.PthDBT + os9 F$Ret64 +RtMem2CF puls pc,b,cc restore error status & return + +* Place date & time into file descriptor +L02D1 lbsr RdFlDscr read in file descriptor sector + ldu PD.BUF,y get pointer to it + lda FD.LNK,u get link count + ldx <D.Proc get current process pointer + pshs x,a preserve 'em + ldx <D.SysPrc switch to system process descriptor + stx <D.Proc + leax FD.DAT,u point to date last modified + os9 F$Time put currenttime there +* Gene Heskett's STUPID "LDA #$01, STA $00FF,u" CRAP went here. DAMN DAMN DAMN +* He's NEVER getting the RBF source again! + puls x,a restore link count & current process + stx <D.Proc + sta FD.LNK,u + rts return + + +* +* I$ChgDir Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +ChgDir pshs y preserve path descriptor pointer + IFNE H6309 + oim #$80,PD.MOD,y ensure the directory bit is set + ELSE + lda PD.MOD,y + ora #$80 + sta PD.MOD,y + ENDC + lbsr Open go open the directory + bcs Clos2A0 exit on error + ldx <D.Proc get current process pointer + ldu PD.FD+1,y get LSW of file descriptor sector # + ldb PD.MOD,y get current file mode + bitb #UPDAT. read or write mode? + beq CD30D no, skip ahead +* Change current data dir + ldb PD.FD,y + stb P$DIO+3,x + stu P$DIO+4,x +CD30D ldb PD.MOD,y get current file mode + bitb #EXEC. is it execution dir? + beq CD31C no, skip ahead +* Change current execution directory + ldb PD.FD,y + stb P$DIO+9,x + stu P$DIO+10,x +CD31C clrb clear errors + bra Clos2A0 return to system + + +* +* I$Delete Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +* NOTE: Bug for write protected disk has been fixed - 93/09/19 +* +Delete pshs y preserve path descriptor pointer + lbsr FindFile does the file exist? + bcs Clos2A0 no, return error + ldd PD.FD+1,y do we have a file descriptor? + bne Del332 yes, skip ahead + tst PD.FD,y + IFNE H6309 + beq Clos29D no, return not accessible error + ELSE + lbeq Clos29D + ENDC +Del332 lda #SHARE.+WRITE. get attributes to check + lbsr ChkAttrs can user delete ths file? + lbcs Clos2A0 no, return error + ldu PD.RGS,y get registered stack pointer + stx R$X,u save updated pathname pointer + lbsr RdFlDscr read in file descriptor +* BUG FIX: Below used to read 'lbcs L03D4' which expects the file descriptor +* sector # & a temporary buffer to be stored on the stack but it +* isn't there yet. Restored back to RBF 28 error handling +* lbcs L02B2 error, return to system (FD read error fix) + lbcs Del3D4 error, rturn to system (FD read error fix) + ldx PD.BUF,y get pointer to the file descriptor + dec FD.LNK,x decrement link count + beq Del358 down to zero, delete the file descriptor + lbsr L11FD write updated file descriptor + pshs u,x,b + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + std $03,s + bra Del39F + +* RBF30 start +Del358 ldb PD.FD,y get LSN of file descriptor + ldx PD.FD+1,y + pshs u,x,b preserve 'em + bsr GetSSize allocate a temporary sector buffer + os9 F$SRqMem + bcc Del36C got it, skip ahead + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + bra Del37A return with eror + +* Convert sector size TYP bits into sector size in D +* +* Entry: Y = path descriptor ptr +* Exit: D = sector size (256, 512, 1024, 2048) +* +GetSSize lda PD.TYP,y + anda #TYP.SSM mask out sector size bits + clrb B is always 0 + lsra shift into position + beq Bit256 + deca + beq Bit512 + deca + beq Bit1024 + lda #8 + rts +Bit1024 lda #4 + rts +Bit512 lda #2 + rts +Bit256 inca + rts + + +* Grab Sector Size bits from TYP and put in A +* +* Entry: Y = path descriptor ptr +* Exit: A = sector size bits (1=256, 2=512, 3=1024, 4=2048) +GrabSS lda PD.TYP,y + anda #TYP.SSM mask out sector size bits + lsra shift into position + inca + rts + +Del36C stu $03,s save pointer to sector buffer + ldx PD.BUF,y + IFNE H6309 + ldw #$0100 + bsr GrabSS +DelMore tfm x+,u+ + deca + bne DelMore + ELSE + bsr GrabSS + pshs a + clrb +CopyMore bsr DelLoop + dec ,s + bne CopyMore + puls a + bra DelOut +DelLoop lda ,x+ + sta ,u+ + decb + bne DelLoop + rts +DelOut + ENDC + ldd $03,s +Del37A std $03,s save buffer pointer to U on stack +* Start back into RBF28 code again + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + std PD.SIZ,y set file size to zero + std PD.SIZ+2,y + lbsr L0EFE set the file size to PD.SIZ + bcs Del3EF + ldb PD.FD,y grab file descriptor sector number + ldx PD.FD+1,y + stb PD.SBP,y copy it to the segment beginning sector number + stx PD.SBP+1,y + ldx PD.BUF,y point to the buffer +* RBF34 +* LDD $13,X : FD.SEG+3, grab the size of the FIRST segment of the file +* addd #$0001 +* THEN std PD.SSZ+1,y +* +* Why? RBF automatically makes the FIRST SEGMENT of the file fill the rest +* of the cluster that was allocated for the file descriptor. +* Why not LDX PD.DTB,y LDD DD.BIT,x ??? +* +* Gene H: My problem with this fix from rbf28 is in proving to me +* $13,x is the correct location to read! I can't seem to find +* the defines to match the $13,x address. +* ldd FD.SEG+FDSL.B,x grab the size of the first segment + ldd <$13,x this code is REQUIRED for multiple + IFNE H6309 + incd sector/cluster operation, don't remove! + ELSE + addd #$0001 sector cluster operation, DO NOT REMOVE! + ENDC + std PD.SSZ+1,y + lbsr ClrFBits delete a segment +Del39F bcs Del3EF + lbsr L1237 flush the sector + lbsr L0A90 + lda PD.DFD,y + sta PD.FD,y + ldd PD.DFD+1,y + std PD.FD+1,y + lbsr RdFlDscr get the file descriptor + bcs Del3EF + lbsr L0A2A + ldu PD.BUF,y + lbsr Open1CE update PD entries from FD entries + IFNE H6309 + ldq PD.DCP,y get current directory entry pointer + stq PD.CP,y save it as current pointer + ELSE + ldd PD.DCP,y + std PD.CP,y + ldd PD.DCP+2,y + std PD.CP+2,y + ENDC + lbsr L0957 read in the directory sector + bcs Del3EF + clr ,x clear first byte of filename in directory entry + lbsr L1205 flush the sector to disk +* RBF30 start +Del3D4 ldu $03,s get temporary sector buffer pointer +* the patch at Del3EF-3F9 munged the stack for this one - GH + beq Del3F9 none allocated, return to process + ldb ,s get the old file descriptor logical sector # + ldx $01,s + stb PD.FD,y put it back into path descriptor + stx PD.FD+1,y + ldx PD.BUF,y get current sector buffer pointer + stx 1,s save it a sec + stu PD.BUF,y put original sector pointer into path descriptor + lbsr L11FD write the old file descriptor to disk + ldu 1,s get temporary sector pointer + stu PD.BUF,y save it as current +Del3EF pshs b,cc preserve rror status & code if any (WP bug fix - raises stack offsets+2) + ldu $05,s get temporary sector buffer pointer (this was a 3) + beq Del3F5 didn't allocate one, skip ahead (different, new label! no mem to return) + lbsr GetSSize get size of sector buffer + os9 F$SRtMem return the memory back to the system +Del3F5 puls b,cc restore error status & code (WP bug fix) +Del3F9 leas 5,s purge stack +* Start back into RBF28 code + lbra Clos2A0 return to system + + +* +* I$Seek Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +Seek ldb PD.SMF,y get state flags + bitb #SINBUF do we have a sector in buffer? + beq Seek417 no, skip ahead + lda R$X+1,u calculate if we need a new sector + ldb R$U,u + subd PD.CP+1,y + bne Seek412 + lda R$X,u + sbca PD.CP,y + beq Seek41B no need to get another sector, skip ahead +Seek412 lbsr L1237 flush the current sector to disk + bcs Seek41F +Seek417 ldd R$X,u get & set new file pointer + std PD.CP,y +Seek41B ldd R$U,u + std PD.CP+2,y +Seek41F rts return + + +* +* I$ReadLn Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +ReadLn bsr RdLn463 check if record locked for amount to be read + beq RdLn446 zero bytes to read, return + bsr RdLn447 + pshs u,y,x,b,a + exg x,u + IFNE H6309 + tfr 0,y smaller, same speed as LDY #$0000 + ELSE + ldy #$0000 + ENDC + lda #$0D a carriage return +RdLn430 leay 1,y go up one byte + cmpa ,x+ is it a CR? + beq RdLn439 yes, we're done + decb count down + bne RdLn430 until done one sector, at least +RdLn439 ldx 6,s get old U + bsr RdLn49B move bytes from the system to user + sty $0A,s save Y on-stack, above calling routine???? + puls u,y,x,b,a restore registers + ldd $02,s get old saved Y from above +* addr d,x + leax d,x point to how many bytes we've read +RdLn446 rts and exit + +RdLn447 lbsr Read4D3 do reading, calling this routine back again + leax -1,x back up a byte + lbsr L097F get a byte from another task (F$LDABX) + cmpa #$0D is it a CR? + beq RdLn459 yes, skip ahead + ldd $02,s check data saved on-stack??? + bne Read4D9 if not zero, skip ahead +RdLn459 ldu PD.RGS,y grab caller's register stack + ldd R$Y,u get number of bytes to read + subd $02,s take out data read last sector?? + std R$Y,u save as data bytes to read + bra Read4C0 skip ahead + +* Calculate if read will be record locked with another process +* Entry: U=Register stack pointer +RdLn463 ldd R$Y,u get requested read length + lbsr L0B0C record locked with somebody else? + bcs RdLn497 yes, return deadlock error + ldd R$Y,u get requested read length + bsr RdLn473 calculate if we will have an EOF error + bcs RdLn497 we did, return error + std R$Y,u save # bytes available + rts return + +* Calculate if read length will overrun file length +* Entry: D=Requested # bytes to read from file +* Exit : D=# bytes available +RdLn473 pshs d preserve length + IFNE H6309 + ldq PD.SIZ,y get current file size + subw PD.CP+2,y subtract off LSW of current byte pointer + tfr w,x save it in the old register + sbcd PD.CP,y subtract off current byte pointer + ELSE + ldd PD.SIZ+2,y + subd PD.CP+2,y + tfr d,x + ldd PD.SIZ,y + sbcb PD.CP+1,y + sbca PD.CP,y + ENDC + bcs RdLn494 it will overrun, return EOF error + bne RdLn491 some bytes left, return OK + tstb + bne RdLn491 + cmpx ,s do we have enough bytes? + bhs RdLn491 yes, return OK + stx ,s save # bytes available + beq RdLn494 it's 0, return EOF error +RdLn491 clrb clear error status + puls pc,b,a retrieve # bytes & return +* Return EOF error +RdLn494 comb set carry for error + ldb #E$EOF get error code +RdLn497 leas $02,s purge length off stack + bra Read4C5 return + +* Move bytes from system to user +* Entry: X=Source pointer +* Y=Byte count +* U=Destination pointer +RdLn49B pshs x + ldx <D.Proc get current process pointer + lda <D.SysTsk get source task # + ldb P$Task,x get destination task # + puls x + os9 F$Move move 'em + rts return + + +* +* I$Read Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +Read bsr RdLn463 record locked? + beq Read4BB no, allow it + bsr Read4BC do reading +Read4AF pshs u,y,x,b,a save data on the stack + exg x,u + tfr d,y + bsr RdLn49B move bytes from system to user + puls u,y,x,b,a restore registers +* addr d,x + leax d,x point to end of data copied? +Read4BB rts + +Read4BC bsr Read4D3 do some reading/writing + bne Read4D9 not done, continue +Read4C0 clrb +Read4C1 leas -2,s clear out crap on the stack +Read4C3 leas $0A,s +* Error processor for read & write +Read4C5 pshs b,cc preserve error status + lda PD.MOD,y get file mode + bita #WRITE. was it write? + bne Read4D0 yes, return + lbsr L0B02 clear lock status, and send signals +Read4D0 puls b,cc,pc restore & return + +* do reading/writing +Read4D3 ldd R$X,u get caller's buffer pointer + ldx R$Y,u get length of read + pshs x,b,a preserve 'em +Read4D9 lda PD.SMF,y get stat flags + bita #SINBUF sector in buffer/ + bne Read4F9 yes, read it + tst PD.CP+3,y read pointer on even sector? + bne Read4F4 no, skip ahead + tst $02,s MSB of length have anything? + beq Read4F4 no, skip ahead + leax >Writ571,pcr WritLn or ReadLn? + cmpx $06,s check the stack + bne Read4F4 skipahead + lbsr L1098 find a segment + bra Read4F7 + +Read4F4 lbsr L1256 +Read4F7 bcs Read4C1 +Read4F9 ldu PD.BUF,y get sector buffer pointer + clra + ldb PD.CP+3,y +* addr d,u + leau d,u point to offset within the buffer + negb get D=number of byte left to read in the sector? + sbca #$FF not quite sure what this is... + ldx ,s grab caller's buffer pointer + cmpd $02,s check bytes left in sector against number to read + bls Read50C lower, OK + ldd $02,s grab number of bytes to read +Read50C pshs b,a save + jsr [$08,s] call our calling routine! + stx $02,s save new address to write to on-stack + IFNE H6309 + aim #^BufBusy,PD.SMF,y + ELSE + ldb PD.SMF,y + andb #^BufBusy + stb PD.SMF,y + ENDC + ldb $01,s get LSB of bytes read + addb PD.CP+3,y add it to current pointer + stb PD.CP+3,y save new file position + bne Read530 didn't grab whole sector, skip ahead + lbsr L1237 flush the sector + inc PD.CP+2,y add + bne Read52E + inc PD.CP+1,y + bne Read52E + inc PD.CP,y +Read52E bcs Read4C3 +Read530 ldd $04,s grab number of bytes to read/write + subd ,s++ take out number we've read/written + std $02,s save on-stack + jmp [$04,s] go back to calling routine with D,X on-stack + + +* +* I$WritLn Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +WriteLn pshs y save PD pointer + clrb + ldy R$Y,u grab size of data to write + beq WtLn55E exit if none + ldx <D.Proc get process descriptor pointer + ldb P$Task,x grab task number + ldx R$X,u and where to get data from +* ATD: Could make this quite a bit larger, and probably faster, by doing the +* PipeMan-style copy 32 bytes onto the stack via F$Move, and check that. +* Doing F$LDABX for a lot of data is _really_ slow. PipeMan test indicate +* that it could probably double in speed... +WtLn547 leay -$01,y back up one byte + beq WtLn55E if done, exit + os9 F$LDABX grab one byte from the user + leax $01,x go up a byte + cmpa #$0D is it a CR? + bne WtLn547 no, keep it up until done + tfr y,d get number of bytes left + nega \ +* a negd was tried here, but may have caused runaway writes>64k + negb / invert it + sbca #$00 + addd R$Y,u add to bytes to write + std R$Y,u save new number of bytes to write +WtLn55E puls y restore PD pointer, and fall through to Write + + +* +* I$Write Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +Write ldd R$Y,u get size of write + lbsr L0B0C wait for I/O lock + bcs Writ598 error, return + ldd R$Y,u get size again + beq Writ597 zero, nothing to write so return + bsr Writ599 expand the file if needed + bcs Writ598 error on expand, return + bsr Writ582 +Writ571 pshs y,b,a + tfr d,y + bsr Writ5CB + puls y,b,a + leax d,x + IFNE H6309 + oim #(BUFMOD!SINBUF),PD.SMF,y + ELSE + pshs a + lda PD.SMF,y + ora #(BUFMOD!SINBUF) + sta PD.SMF,y + puls a + ENDC + rts + +Writ582 lbsr Read4D3 go read stuff + lbne Read4D9 + leas $08,s skip stuff on stack + ldy PD.Exten,y + lda #$01 + lbsr L0AD1 + ldy PE.PDptr,y +Writ597 clrb +Writ598 rts + +* Add bytes to current file position with file length extension +* Entry: D=# bytes to add +Writ599 addd PD.CP+2,y add length to LSW of current pointer + tfr d,x copy it + ldd PD.CP,y get MSW + IFNE H6309 + adcd #0 add in any carry from above + ELSE + adcb #0 + adca #0 + ENDC +Writ5A3 cmpd PD.SIZ,y MSW past eof? + bcs Writ597 no, return + bhi Writ5AF yes, add a sector + cmpx PD.SIZ+2,y LSW past eof? + bls Writ597 no, return +Writ5AF pshs u preserve U + ldu PD.SIZ+2,y get LSW of current size + stx PD.SIZ+2,y save new size + ldx PD.SIZ,y get MSW of new size + std PD.SIZ,y save new size +* ATD: L0C6F looks like it already saves U and X, so saving them here is +* unnecessary. + pshs u,x preserve old size + lbsr L0C6F allocate new size of file + puls u,x restore old size + bcc Writ5C9 no error from allocate, return + stx PD.SIZ,y put old size back + stu PD.SIZ+2,y +Writ5C9 puls pc,u restore U & return + +* Move bytes from user to system +* Entry: X=Source pointer +* Y=Byte count +* U=Destination pointer +Writ5CB pshs x + ldx <D.Proc get source task # + lda P$Task,x + ldb <D.SysTsk get destination task # + puls x + os9 F$Move move 'em + rts return + + +* +* I$GetStat Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +GetStat ldb R$B,u get function code + beq Gst5FF it's SS.Opt, go process + +* SS.OPT +* Entry A=path number +* B=$00 +* X=address to put 32 byte packet + cmpb #SS.EOF EOF check? + bne Gst5EB no, skip ahead + clr R$B,u default to no EOF +Gst5E5 clra get length & clear carry + ldb #$01 + lbra RdLn473 go calculate EOF status & return + +* SS.Ready +* check for data avail on dev +* Entry A=path number +* B=$01 +Gst5EB cmpb #SS.Ready is it SS.Ready? + bne Gst5F2 no, keep checking + clr R$B,u always mark no data ready + rts + +* SS.SIZ +* Entry A=path num +* B=$02 +* Exit X=msw of files size +* U=lsw of files size +Gst5F2 cmpb #SS.Size is it SS.Size? + bne Gst600 no, keep checking + IFNE H6309 +* faster and smaller than 2 LDD's, PD.SIZ+2 >$0F, so we can't use short n,R + ldq PD.SIZ,y get current file size +Gst5F8 std R$X,u save to the user + stw R$U,u save LSW + ELSE + ldd PD.SIZ,y + std R$X,u + ldd PD.SIZ+2,y + std R$U,u + ENDC +Gst5FF rts return + +* SS.POS +* Entry A=path num +* B=$05 +* Exit X=msw of pos +* U=lsw of pos +Gst600 cmpb #SS.POS is it SS.Pos? + bne Gst60D no, keep checking + IFNE H6309 +* use 2 LDD, STD, same size as ldq/std/stw, PD.CP+2 <$0F, we can use short n,R + ldq PD.CP,y get current file pointer + bra Gst5F8 + ELSE + ldd PD.CP,y get current file pointer + std R$X,u save MSW + ldd PD.CP+2,y get current file pointer + std R$U,u save LSW + rts + ENDC + +* Getstt(SS.FD) +* Entry: R$A = Path # +* R$B = SS.FD ($0F) +* R$X = ptr to 256 byte buffer +* R$Y = # of bytes of FD required +Gst60D cmpb #SS.FD is it SS.FD? + bne Gst627 no, keep checking + lbsr RdFlDscr go get file descriptor + bcs Gst5FF exit on error + ldu PD.RGS,y get register stack pointer + ldd R$Y,u get # bytesof FD he wants + tsta legal value? + beq Gst620 yes, skip ahead + ldd #$0100 get max size of FD +Gst620 ldx R$X,u get pointer + ldu PD.BUF,y get pointer to FD + lbra Read4AF move it to user space + +* Getstt(SS.FDInf) +* Entry: R$A = Path # +* R$B = SS.FDInf ($20) +* R$X = ptr to 256 byte buffer +* R$Y = msb - Length of read +* lsb - MSB of LSN +* R$U = LSW of LSN +Gst627 cmpb #SS.FDInf SS.FDInf? + bne Gst640 no, let driver handle it + lbsr L1237 check for sector flush + bcs Gst5FF + ldb R$Y,u get MSB of sector # + ldx R$U,u get LSW of sector # + lbsr L113A read the sector + bcs Gst5FF error, return + ldu PD.RGS,y get register stack pointer + ldd R$Y,u get length of data to move + clra clear MSB + bra Gst620 move it to user + +* Let driver handle the rest +Gst640 lda #D$GSTA get getstat function offset + lbra L113C send it to driver + + +* +* I$SetStat Entry Point +* +* Entry: +* +* Exit: +* +* Error: CC Carry set +* B = errcode +* +SetStat ldb R$B,u get function code +* TODO: remove next line since SS.OPT is 0 + cmpb #SS.OPT + bne Sst659 not SS.OPT, skip ahead + ldx R$X,u get pointer to option packet + leax $02,x skip device type and drive # + leau PD.STP,y get pointer to start of data + ldy #(PD.TFM-PD.STP) get # bytes to move (not including PD.TFM) + lbra Writ5CB move 'em & return + +* SS.Size +Sst659 cmpb #SS.Size is it SS.Size? + bne Sst69B + ldd PD.FD+1,y is there a file descriptor? + bne Sst669 + tst PD.FD,y + lbeq Sst7A8 no, return error +Sst669 lda PD.MOD,y get file mode + bita #WRITE. is it write? + beq Sst697 no, return error + ldd R$X,u get MSW of new size + ldx R$U,u get LSW of new size + cmpd PD.SIZ,y + bcs Sst682 + bne Sst67F + cmpx PD.SIZ+2,y + bcs Sst682 +* New size is larger +Sst67F lbra Writ5A3 add new size to file +* New size is smaller +Sst682 std PD.SIZ,y + stx PD.SIZ+2,y + ldd PD.CP,y + ldx PD.CP+2,y + pshs x,b,a + lbsr L0EFE delete from end of the file + puls u,x + stx PD.CP,y restore current position + stu PD.CP+2,y + rts +* Return bad mode error +Sst697 comb set carry + ldb #E$BMode get bad mod error +Sst69A rts return + +* SetStt(SS.FD) #$0F - returns FD to disk +* Entry: R$A = Path # +* R$B = SS.FD ($0F) +* R$X = ptr to 256 byte buffer +* R$Y = # bytes to write +Sst69B cmpb #SS.FD is it SS.FD? + bne Sst6D9 no, keep checking + lda PD.MOD,y + bita #WRITE. is it write mode? + beq Sst697 no, return bad mode error + lbsr RdFlDscr read in file descriptor + bcs Sst69A error, return + pshs y preserve path descriptor pointer + ldx R$X,u get pointer to caller's buffer + ldu PD.BUF,y get pointer to FD + ldy <D.Proc get current process pointer + ldd P$User,y get user # + bne Sst6BC not super user, skip ahead +* Change owner of file + ldd #$0102 get offset & # of bytes to move + bsr Sst6CB +* Change date last modified +Sst6BC ldd #$0305 + bsr Sst6CB +* Change creation date + ldd #$0D03 + bsr Sst6CB + puls y + lbra L11FD +* Offset into FD sector +* Entry: A=# bytes to offset +* B=# bytes to put +Sst6CB pshs u,x + leax a,x + leau a,u + clra + tfr d,y + lbsr Writ5CB + puls pc,u,x + +Sst6D9 cmpb #SS.Lock is it SS.Lock? + bne Sst6F8 no, keep checking + ldd R$U,u get MSW of size + ldx R$X,u get LSW of size + cmpx #$FFFF lock whole file? + bne Sst6F5 no, skip ahead + cmpx R$U,u + bne Sst6F5 after this line, we're SURE that D=$FFFF + ldu PD.Exten,y + IFNE H6309 + oim #FileLock,PE.Lock,u + ELSE + lda PE.Lock,u + ora #FileLock + sta PE.Lock,u + ENDC +* ATD: This next line is unnecessary after the check done, above + lda #$FF ?? if X=$FFFF, then D=$FFFF too. +Sst6F5 lbra L0B1B + +* SS.Ticks +Sst6F8 cmpb #SS.Ticks is it SS.Ticks? + bne Sst705 no, keep checking + ldd R$X,u get # of ticks + ldx PD.Exten,y put it into path extension + std PE.TmOut,x + rts return + +* SS.RsBit +Sst705 cmpb #SS.RsBit reserve bitmap sector? + bne Sst715 no, keep checking + ldx PD.DTB,y get drive table pointer + lda R$X+1,u get sector # + sta V.ResBit,x put it into drive table + clr V.MapSct,x clear mapped sector +Sst714 rts return + +* SS.Attr +Sst715 cmpb #SS.Attr is it SS.Attr? + bne Sst784 no, keep checking + lbsr RdFlDscr get the file descriptor from drive + bcs Sst714 error, return + ldx <D.Proc get pointer to current process +* Note, should'nt this be lda? User number is 8 bits, not 16 + ldd P$User,x get user number + beq Sst72A it's super user, skip ahead + ldx PD.BUF,y get pointer to FD + cmpd FD.OWN,x user # match owner of file? + bne Sst780 no, return not accessible error +Sst72A lda R$X+1,u get attributes from caller + tfr a,b copy it + ldu PD.BUF,y get pointer to FD + eorb FD.ATT,u directory bit set? + bpl Sst77B no, save new attributes & return + tsta is user setting directory bit? + bmi Sst764 yes, return directory not empty error +* Directory attributes changing, check if it's root dir + ldx PD.DTB,y get pointer to drive table + ldd DD.DIR,x get MSW of sector # to root directory + cmpd PD.FD,y match current FD sector #? + bne Sst749 no, skip ahead + ldb DD.DIR+2,x get LSB of sector # to root directory + cmpb PD.FD+2,y match current FD sector #? + beq Sst780 yes, return not accessible error +* Scan directory to see if there's any files and/or directories +Sst749 ldb PD.CP,y get current directory entry pointer + ldx PD.CP+1,y + pshs x,b preserve it +* ATD: there should be a CLRD here + std PD.CP,y ??? This code doesn't look correct... +* ATD: should be DIR.SZ*2: so we skip '..' and '.' + ldb #DIR.SZ + std PD.CP+2,y +Sst755 lbsr L0942 move to next filename in directory + bcs Sst768 error in read, check for EOF + tst ,x filename exist? + beq Sst755 no, keep looking + puls x,b restore current pointer + stb PD.CP,y + stx PD.CP+1,y +* Report directory not empty error +Sst764 ldb #E$DNE get directory not empty error + bra Sst782 return +Sst768 puls x,a restore current pointer + sta PD.CP,y + stx PD.CP+1,y + cmpb #E$EOF at the end of directory? + bne Sst782 no, some other error + lbsr RdFlDscr get file descriptor from drive + ldu PD.BUF,y get sector pointer + ldx PD.RGS,y get register stack pointer + lda R$X+1,x get attributes +Sst77B sta FD.ATT,u set 'em + lbra L11FD write FD to disk & return +* Return file not accessible +Sst780 ldb #E$FNA get file not accessible error +Sst782 coma set carry + rts return + +* SetStt(SS.FSig) +Sst784 cmpb #SS.FSig SS.FSig send signal on write + bne Sst7A3 + lda PD.ATT,y + bita #SHARE. + lbne L0A8B + ldx PD.Exten,y + lda R$X+1,u + sta PE.SigSg,x + ldu <D.Proc + lda P$ID,u was <P$ID,u + sta PE.SigID,x + clrb + rts + +Sst7A3 lda #D$PSTA call the driver SetStt routine + lbra L113C + +Sst7A8 comb + ldb #E$UnkSvc unknown service request +Sst7AB rts + + +* Find a file in current data/execution directory +* Called by Create/Open & Delete +* +* Entry: U=caller's stack reg. ptr +* Y=Path dsc. ptr +FindFile lbsr GetSSize get size of sector +* Note, following line is stb PD.SMF,y in v30! + stb PD.FST,y clear state flags?? + os9 F$SRqMem request a sector buffer + bcs Sst7AB couldn't get memory, return with error + stu PD.BUF,y save ptr to sector buffer + leau ,y point U to path descriptor + ldx <D.PthDBT get ptr to path escriptor block tables + os9 F$All64 allocate path descriptor + exg y,u exchange pointers + bcs Sst7AB couldn't get path descriptor, return error + stu PD.Exten,y save pointer to path extension + clr PE.SigID,u clear send signal proc. ID + sty PE.PDptr,u save back pointer to path descriptor + stu PE.Wait,u init waiting extension to myself + ldx PD.RGS,y get register stack pointer + ldx R$X,x get pointer to pathname + pshs u,y,x + leas -$04,s make a buffer + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + sta PD.FD,y init file descriptor logical sector # + std PD.FD+1,y + std PD.DSK,y init disk ID + lbsr L097F get a byte from caller's X + sta ,s save it + cmpa #PDELIm is it a device? + bne Sst7FB no, skip ahead + lbsr GtDvcNam go parse it + sta ,s save last character + lbcs L090D error in parse, return + leax ,y point X to last character + ldy $06,s get path descriptor pointer + bra Sst81E skip ahead +Sst7FB anda #$7F strip high bit + cmpa #PENTIR entire device flag? + beq Sst81E yes, go process + lda #PDELIm place delimiter as last char + sta ,s + leax -$01,x bump path pointer back 1 + lda PD.MOD,y get file mode + ldu <D.Proc get pointer to current process + leau P$DIO,u point to default data directory FD sector # + bita #EXEC. does he want execution dir? + beq Sst814 no, skip ahead + leau $06,u point to execution dir +Sst814 ldb $03,u get LSB of logical sector # of FD to dir + stb PD.FD,y put it in path descriptor + ldd $04,u get MSW of logical sector # of FD to dir + std PD.FD+1,y +Sst81E ldu PD.DEV,y get pointer to device table + stu PD.DVT,y copy it for user + lda PD.DRV,y get drive # + ldb >L0012,pcr get sizeof drive tables +* confusion reigns supreme here, +* one source loaction says its number of drive tables, +* and the next says its the size of the table! And a 3rd +* says its D.TYP. + mul calculate offset into drive tables + addd V$STAT,u add start of static memory + addd #DRVBEG add offset to drive tables + std PD.DTB,y save pointer to drive table + lda ,s get character back + anda #$7F strip high bit + cmpa #PENTIR was it entire flag? + bne Sst83F no, keep going + leax $01,x move to next character + bra Sst861 go on + +Sst83F lbsr L1110 read in LSN0 + lbcs L0915 error, return + ldu PD.BUF,y get sector buffer pointer from the read-in sector + +* otherwise use the pointer from PD.DTB + ldd DD.DSK,u get disk ID + std PD.DSK,y put it in path descriptor + ldd PD.FD+1,y does it have a file descriptor? + bne Sst861 yes, skip ahead + lda PD.FD,y + bne Sst861 + lda DD.DIR,u get LSN of root directory + sta PD.FD,y put it in path descriptor + ldd DD.DIR+1,u + std PD.FD+1,y +Sst861 stx $04,s save pointer to pathname + stx $08,s + +Sst865 lbsr L1237 flush sector buffer + lbcs L0915 error, exit + lda ,s get last character of pathname + anda #$7F mask off high bit + cmpa #PENTIR entire device flag? + beq Sst87B yes, skip ahead + lbsr RdFlDscr read in file descriptor + lbcs L0915 error, return +Sst87B lbsr L0A2A check if directory is busy + lda ,s + cmpa #PDELIM was the trailing character a slash? + bne L08EF no, skip ahead + clr $02,s + clr $03,s + lda PD.MOD,y get file mode + ora #DIR. mask in directory bit + lbsr ChkAttrs can user access directory? + bcs L090D no, return + lbsr Open1CE setup path descriptor & start scan + ldx $08,s get pathname pointer + leax $01,x bump to next character + lbsr GtDvcNam check for valid name + std ,s save length of name + stx $04,s save updated name pointer + sty $08,s + ldy $06,s get path descriptor pointer + bcs L090D error in pathname, return + pshs u,y + ldu PD.Exten,y get pointer to path extension + leau PE.FilNm,u point to filename buffer + clra clear MSB of name length + tfr d,y move it to Y + lbsr Writ5CB move filename to temp area + puls u,y + lbsr L0957 read in a directory sector + bra L08C1 + +* Scan diretory for name +L08BC bsr L0918 get file descriptor + IFNE H6309 +L08BE bsr L0942 get next directory entry from drive + ELSE +L08BE lbsr L0942 + ENDC +L08C1 bcs L090D error, + tst ,x filename exists? + beq L08BC no, get next entry + clra + ldb $01,s + exg x,y + ldx PD.Exten,x get path extension pointer + leax PE.FilNm,x point to user's filename + lbsr L09BF compare the names + ldx $06,s get pointer to path descriptor + exg x,y + bcs L08BE names don't match, skip to next + bsr L0926 cop this DIR file descriptor to path descriptor + lda DIR.FD,x + sta PD.FD,y + ldd DIR.FD+1,x + std PD.FD+1,y + lbsr L0A90 check record lock? + lbra Sst865 go try again + +L08EF ldx $08,s + tsta last character? + bmi L08FC yes, skip ahead + os9 F$PrsNam parse the name + leax ,y go to the next part of the name + ldy $06,s +L08FC stx $04,s + clra +L08FF lda ,s + leas $04,s + pshs b,a,cc + IFNE H6309 + aim #^BufBusy,PD.SMF,y + ELSE + lda PD.SMF,y + anda #^BufBusy + sta PD.SMF,y + ENDC + puls pc,u,y,x,b,a,cc + +L090D cmpb #E$EOF + bne L0915 + bsr L0918 + ldb #E$PNNF +L0915 coma + bra L08FF + +L0918 pshs d + lda $04,s + cmpa #PDELIM + beq L0940 + ldd $06,s + bne L0940 + bra L0928 fewer clock cycles +L0926 pshs d +L0928 stx $06,s + lda PD.FD,y + sta PD.DFD,y + ldd PD.FD+1,y + std PD.DFD+1,y + IFNE H6309 + ldq PD.CP,y + stq PD.DCP,y + ELSE + ldd PD.CP,y + std PD.DCP,y + ldd PD.CP+2,y + std PD.DCP+2,y + ENDC +L0940 puls pc,b,a + +* Move to next directory entry +L0942 ldb PD.CP+3,y get current byte pointer + addb #DIR.SZ add in diretory entry size + stb PD.CP+3,y save it back + bcc L0957 didn't wrap, skip ahead (need new sector) + lbsr L1237 check for sector flush + inc PD.CP+2,y + bne L0957 + inc PD.CP+1,y + bne L0957 + inc PD.CP,y +L0957 ldd #DIR.SZ get directory entry size + lbsr RdLn473 end of directory? + bcs L097E yes, return + ldd #DIR.SZ get directory entry size + lbsr L0B0C + bcs L097E yes, return + lda PD.SMF,y get state flags + bita #SINBUF sector in buffer? + bne L0977 yes, skip ahead + lbsr L1098 + bcs L097E + lbsr L1256 + bcs L097E +L0977 ldb PD.CP+3,y get offset into sector + lda PD.BUF,y get MSB of sector buffer pointer + tfr d,x move it to X + clrb clear error status +L097E rts return + +* Get a byte from other task +L097F pshs u,x,b + ldu <D.Proc + ldb P$Task,u + os9 F$LDABX + puls pc,u,x,b + +GtDvcNam os9 F$PrsNam parse the filename + pshs x preserve pointer to name + bcc L09B7 no error, check name length & return + clrb clear a counter flag +L0992 pshs a preserve last character + anda #$7F clear high bit of last character + cmpa #'. is it current data directory? + puls a restore last character + bne L09AD no, skip ahead + incb flag it's a dir + leax 1,x + tsta is it the last character of pathname? + bmi L09AD yes, skip ahead + bsr L097F get next character + cmpb #$03 third character of DIR? + bcs L0992 no, try again + lda #PDELIM + decb + leax -3,x +L09AD tstb + bne L09B5 +L09B0 comb + ldb #E$BPNam + puls pc,x + +L09B5 leay ,x +L09B7 cmpb #DIR.FD-DIR.NM past maximum size of name? + bhi L09B0 yes, return error + andcc #^Carry clear error status + puls pc,x return + +* Check for a match of 2 names +* Entry: Y=Pointer to high bit terminated string #1 +* X=Pointer to string #2 +* B=Length of string #1 +L09BF pshs y,x,b,a +L09C1 lda ,y+ get a byte from #2 + bmi L09D1 last one, skip ahead + decb done length? + beq L09CE yes, return no match + eora ,x+ + anda #$DF match from #1? + beq L09C1 yes, check next char +L09CE comb set carry + puls pc,y,x,b,a return + +L09D1 decb decrement length + bne L09CE not done, return no match + eora ,x + anda #$5F + bne L09CE + clrb clear carry for match + puls pc,y,x,b,a + +* Check if user can access file/directory +* Entry: A=Attributes of file/directory to check +* Exit : Carry set - User cannot access otherwise clear +ChkAttrs tfr a,b copy attributes + anda #(EXEC.!UPDAT.) keep only file related junk + andb #(DIR.!SHARE.) ...and directory related junk + pshs x,b,a preserve + lbsr RdFlDscr get file descriptor + bcs L0A0C error, return + ldu PD.BUF,y get pointer to FD + ldx <D.Proc get current process pointer + ldd P$User,x get user # + beq L09F5 super user, skp ahead + cmpd FD.OWN,u match owner of file? +L09F5 puls a restore owner attributes + beq L09FC got owner, skip ahead + lsla shift attributes to public area + lsla + lsla +L09FC ora ,s merge with directory bits + anda #^SHARE. strip off shareable bit + pshs a save it + ora #DIR. set directory bit + anda FD.ATT,u keep only bits we want from attributes + cmpa ,s can he access it? + beq L0A15 yes, check directory bits + ldb #E$FNA get error code +L0A0C leas $02,s purge attributes from stack + coma set carry + puls pc,x restore & return + +L0A11 ldb #E$Share,s get shareable file error + bra L0A0C return + +L0A15 ldb 1,s get directory bits + orb FD.ATT,u mask in with current + bitb #SHARE. shareable bit set? + beq L0A28 no, return + ldx PD.Exten,y get path extension + cmpx PE.Confl,x conflicting with anyone? + bne L0A11 yes, return error + lda #FileLock + sta PE.Lock,x +L0A28 puls pc,x,b,a + + +L0A2A pshs u,y,x + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + std PD.CP,y init current byte pointer + std PD.CP+2,y smaller than STQ + sta PD.SSZ,y init segment size + std PD.SSZ+1,y + ldb PD.FD,y get current FD sector # + ldx PD.FD+1,y + pshs x,b preserve it + ldu PD.DTB,y get drive table pointer + ldy PD.Exten,y get drive extension pointer + sty PE.Confl,y make it conflict with myself + leau DD.SIZ,u point to local data + bra L0A51 +* Sort file conflict list??? +L0A4F ldu V.FileHd-DD.SIZ,u +L0A51 ldx V.FileHd-DD.SIZ,u get open file list extension pointer + beq L0A7F none, skip return + ldx PE.PDptr,x get pointer to its path descriptor + ldd PD.FD,x get the file descriptor LSN + cmpd ,s sector lower than mine? + bcs L0A4F yes, skip to next + bhi L0A7F no, return + ldb PD.FD+2,x + cmpb 2,s + blo L0A4F yes, skip to next + bhi L0A7F no, return + ldx PD.Exten,x get the path extension pointer + IFNE H6309 + tim #FileLock,PE.Lock,y entire file locked? + ELSE + ldb PE.Lock,y + bitb #FileLock + ENDC + bne L0A8B yes, return error + sty PE.NxFil,y terminate list with pointer to myself + ldd PE.Confl,x + std PE.Confl,y + sty PE.Confl,x + bra L0A86 + +L0A7F ldx PE.NxFil,u + stx PE.NxFil,y + sty PE.NxFil,u + +L0A86 clrb +L0A87 leas $03,s + puls pc,u,y,x + +L0A8B comb + ldb #E$Share + bra L0A87 + +L0A90 pshs u,y,x,b,a + ldu PD.DTB,y + leau DD.SIZ,u + ldx PD.Exten,y + leay ,x + bsr L0ACF + bra L0AA5 +L0AA1 ldx PE.Confl,x + beq L0ACA +L0AA5 cmpy PE.Confl,x + bne L0AA1 + ldd PE.Confl,y + std PE.Confl,x + bra L0AB2 +L0AB0 ldu PE.NxFil,u +L0AB2 ldd PE.NxFil,u + beq L0ACA end of list, store end & return + cmpy PE.NxFil,u find myself/ + bne L0AB0 no, keep looking + ldx PE.NxFil,y get next in line from me + cmpy PE.Confl,y end of conflict list? + beq L0AC8 yes, skip ahead + ldx PE.Confl,y get conflicting path extension + ldd PE.NxFil,y get next in line from me + std PE.NxFil,x save it into conflicting extension +L0AC8 stx PE.NxFil,u save conflicting extension as next +L0ACA sty PE.Confl,y + puls pc,u,y,x,b,a + +L0ACF lda #(EofLock!FileLock!RcdLock) get all types of lockout flags +L0AD1 pshs u,y,x,b,a + bita PE.Lock,y anything locked? + beq L0AE0 no, skip ahead + coma invert lock bits + anda PE.Lock,y clear 'em + sta PE.Lock,y save 'em + bita #FileLock is whole file locked? + bne L0AFD yes, return +L0AE0 leau ,y +L0AE2 ldx PE.Wait,u + cmpy PE.Wait,u + beq L0AFA + stu PE.Wait,u + leau ,x + lda PE.Owner,u + ldb #S$Wake + os9 F$Send + bra L0AE2 +L0AFA stu PE.Wait,u +L0AFD puls pc,u,y,x,b,a + +L0AFF comb + ldb #E$Share +L0B02 pshs y,b,cc + ldy PD.Exten,y + bsr L0ACF + puls pc,y,b,cc + +L0B0C equ * + IFNE H6309 + tfr 0,x + ELSE + ldx #$0000 + ENDC + bra L0B1B + +L0B11 ldu PD.Exten,y + lda PE.Req,u + sta PE.Lock,u + bra L0B1D + +* Entry: D=LSW of byte position +* X= +* Y=Path descriptor pointer +* U= +L0B1B pshs u,y,x,b,a preserve regs +L0B1D ldu PD.Exten,y get pointer to path extension + lda PE.Lock,u get lockout status + sta PE.Req,u preserve it + lda ,s get + bsr L0B9F lock the record + bcc L0B9D + ldu <D.Proc get current proces pointer + lda PE.Owner,x get owner ID of locked segment +L0B30 os9 F$GProcP get a pointer to it + bcs L0B42 no process left, skip ahead + lda P$DeadLk,y get dominant proc ID + beq L0B42 none, skip ahead + cmpa P$ID,u same as current? + bne L0B30 no, try again (walks down the process tree) + ldb #E$DeadLk get deadlock error code + bra L0B9A set carry & return + +L0B42 lda PE.Owner,x get owner of this segment + sta P$DeadLk,u save as the dominant deadlock process + ldy 4,s get path descriptor pointer + IFNE H6309 + aim #^BufBusy,PD.SMF,y + ELSE + lda PD.SMF,y + anda #^BufBusy + sta PD.SMF,y + ENDC + ldu PD.Exten,y get the path extension + ldd PE.Wait,x + stu PE.Wait,x + std PE.Wait,u + lbsr L0C56 + ldx PE.TmOut,u get timeout time to wait for release of segment + os9 F$Sleep delay a bit + pshs x preserve time slept + leax ,u point X to path extension + bra L0B6F skip ahead + +L0B6C ldx PE.Wait,x +L0B6F cmpu PE.Wait,x + bne L0B6C + ldd PE.Wait,u + std PE.Wait,x + stu PE.Wait,u + puls x restore time slept + ldu <D.Proc + clr P$DeadLk,u + lbsr L1053 + bcs L0B9A + leax ,x X=0? + bne L0B11 no, + ldu PD.Exten,y get pointer to extension + ldx PE.TmOut,u get timeout time + lbeq L0B11 zero, go try again + ldb #E$Lock get lock error code +L0B9A coma set carry + stb $01,s save error code +L0B9D puls pc,u,y,x,b,a + +L0B9F + IFNE H6309 + tstd std -$02,s only to set cc.flags? 4 cycles to 1! + ELSE + cmpd #$0000 + ENDC + bne L0BAA + cmpx #$0000 the leax may be buggy + lbeq L0B02 +L0BAA bsr L0BC2 + lbcs L0AFF + pshs u,y,x + ldy PD.Exten,y + lda #$01 + lbsr L0AD1 + ora PE.Lock,y + sta PE.Lock,y + clrb + puls pc,u,y,x + +L0BC2 pshs u,y,b,a + leau ,y + ldy PD.Exten,y + subd #$0001 NOT a DECD: does't set CC.C + bcc L0BD1 + leax -1,x +L0BD1 addd PD.CP+2,u + exg d,x + IFNE H6309 + adcd PD.CP,u oughta do same - GH + ELSE + adcb PD.CP+1,u + adca PD.CP,u + ENDC + bcc L0BE0 + ldx #$FFFF + tfr x,d +L0BE0 std PE.HiLck,y + stx PE.HiLck+2,y + cmpd PD.SIZ,u + bcs L0BF8 + bhi L0BF0 + cmpx PD.SIZ+2,u + bcs L0BF8 +L0BF0 equ * + IFNE H6309 + oim #EofLock,PE.Lock,y + ELSE + lda PE.Lock,y + ora #EofLock + sta PE.Lock,y + ENDC + bra L0C01 +L0BF8 lda #EofLock + bita PE.Lock,y + beq L0C01 + lbsr L0AD1 +L0C01 equ * + IFNE H6309 + ldq PD.CP,u + stq PE.LoLck,y + ELSE + ldd PD.CP,u + std PE.LoLck,y + ldd PD.CP+2,u + std PE.LoLck+2,y + ENDC + lda PD.CPR,u + sta PE.Owner,y + leax ,y +L0C10 cmpy PE.Confl,x + beq L0C54 + ldx PE.Confl,x + ldb PE.Owner,y + cmpb PE.Owner,x + beq L0C10 + lda PE.Lock,x + beq L0C10 + ora PE.Lock,y + bita #FileLock either path locked? + bne L0C53 yes, skip ahead + lda PE.Lock,x + anda PE.Lock,y + bita #EofLock both at eof? + bne L0C53 + ldd PE.LoLck,x + cmpd PE.HiLck,y + bhi L0C10 + bcs L0C43 + ldd PE.LoLck+2,x + cmpd PE.HiLck+2,y + bhi L0C10 + beq L0C53 +L0C43 ldd PE.HiLck,x + cmpd PE.LoLck,y + bcs L0C10 + bhi L0C53 + ldd PE.HiLck+2,x + cmpd PE.LoLck+2,y + bcs L0C10 +L0C53 comb +L0C54 puls pc,u,y,b,a + +L0C56 pshs y,x,b,a + ldx <D.Proc + lda P$IOQN,x get I/O queue next ptr + beq L0C6C none, exit + clr P$IOQN,x set to none + ldb #S$Wake + os9 F$Send wake up + os9 F$GProcP get process descriptor pointer + clr P$IOQP,y clear its I/O queue previous pointer +L0C6C clrb + puls pc,y,x,b,a + +L0C6F pshs u,x +L0C71 bsr L0CD1 + bne L0C81 + cmpx PD.SSZ+1,y + bcs L0CC8 + bne L0C81 + lda PD.SIZ+3,y + beq L0CC8 +L0C81 lbsr RdFlDscr + bcs L0CC5 + ldx PD.CP,y + ldu PD.CP+2,y grab current position + pshs u,x save it + IFNE H6309 + ldq PD.SIZ,y go to the end of the file + stq PD.CP,y + ELSE + ldd PD.SIZ,y + std PD.CP,y + ldd PD.SIZ+2,y + std PD.CP+2,y + ENDC + lbsr L10B2 search ??? + puls u,x restore current position + stx PD.CP,y and save back in PD again + stu PD.CP+2,y + bcc L0CC8 + cmpb #E$NES non-existing segment error? + bne L0CC5 + bsr L0CD1 + bne L0CB1 + tst PD.SIZ+3,y + beq L0CB4 + leax 1,x + bne L0CB4 +L0CB1 ldx #$FFFF +L0CB4 tfr x,d + tsta + bne L0CC1 + cmpb PD.SAS,y + bcc L0CC1 + ldb PD.SAS,y +L0CC1 bsr L0D07 go do something... + bcc L0C71 +L0CC5 coma + puls pc,u,x + +L0CC8 lbsr L1098 + bcs L0CC5 + bsr L0CDF + puls pc,u,x + +L0CD1 ldd PD.SIZ+1,y + subd PD.SBL+1,y + tfr d,x + ldb PD.SIZ,y + sbcb PD.SBL,y + rts + +L0CDF clra + ldb #$02 + pshs u,x + ldu PD.Exten,y + bra L0CFD + +L0CE9 ldu PE.PDptr,u + ldx PD.SIZ,y don't do LDQ/STQ, as A and B are used below + stx PD.SIZ,u + ldx PD.SIZ+2,y + stx PD.SIZ+2,u + bitb PD.MOD,y + beq L0CFA + inca +L0CFA ldu PD.Exten,u +L0CFD ldu PE.Confl,u + cmpy PE.PDptr,u + bne L0CE9 + tsta + puls pc,u,x + +* Update a file descriptor +L0D07 pshs u,x + lbsr FatScan search and allocate D sectors + bcs L0D4E exit on error + lbsr RdFlDscr read a FD from disk + bcs L0D4E exit on error + ldu PD.BUF,y grab the buffer pointer + IFNE H6309 + clrd + tfr d,w + stq FD.SIZ,u set the file size to zero + ELSE + clra + clrb + std FD.SIZ,u + std FD.SIZ+2,u + ENDC + leax FD.SEG,u point to the segment size + ldd FDSL.B,x grab the segment size + beq L0D96 exit if zero + ldd PD.BUF,y grab the buffer pointer + inca point to the end of it + pshs d save on-stack + bra L0D36 skip ahead + +L0D29 clrb + ldd -$02,x grab previous segment sector size + beq L0D4A zero: exit +* Add in checks to see if this segment's LSN is $00000000? + addd FD.SIZ+1,u add sector size to total file size + std FD.SIZ+1,u + bcc L0D36 + inc FD.SIZ,u increment file size if 24-bit overflow +L0D36 leax FDSL.S,x go up one segment in the FD + cmpx ,s done yet? + bcs L0D29 no, continue +* or do check for last segment LSN0, size 1 here? + lbsr ClrFBits delete a segment? + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + sta PD.SSZ,y segment size is zero + std PD.SSZ+1,y + comb + ldb #E$SLF segment list full error + +L0D4A leas 2,s remove pointer to end of PD.BUF from the stack + leax -FDSL.S,x back up a segment +L0D4E bcs L0DB3 + ldd -4,x + addd -2,x + pshs b,a + ldb -5,x + adcb #$00 + cmpb PD.SBP,y + puls d + bne L0D96 + cmpd PD.SBP+1,y + bne L0D96 + ldu PD.DTB,y + ldd DD.BIT,u + ldu PD.BUF,y + subd #1 + coma + comb comd is prolly wrong reg order! + pshs d + ldd -$05,x + IFNE H6309 + eord PD.SBP,y + lsrd + lsrd + lsrd + andd ,s++ + tstd + ELSE + eora PD.SBP,y + eorb PD.SBP+1,y + lsra + rorb + lsra + rorb + lsra + rorb + anda ,s+ + andb ,s+ + cmpd #$0000 + ENDC + bne L0D96 + ldd -2,x + addd PD.SSZ+1,y + bcs L0D96 + std -2,x + bra L0DA5 + +L0D96 ldd PD.SBP,y + std ,x + lda PD.SBP+2,y + sta 2,x + ldd PD.SSZ+1,y + std 3,x +L0DA5 ldd FD.SIZ+1,u + addd PD.SSZ+1,y + std FD.SIZ+1,u + bcc L0DB0 + inc FD.SIZ,u + +L0DB0 lbsr L11FD flush a FD sector tothe disk +L0DB3 puls pc,u,x + +* Search the allocation bitmap for a number of free sectors +* Entry: D = number of sectors to look for +* Y = PD pointer +* 0,S = number of clusters to allocate +* 2,S = DD.BIT number of sectors per cluster +* 4,S = DD.MAP number of bytes in the allocation bitmap +* 6,S = V.MapSCT lowest reasonable bitmap sector number (current bitmap sect) +* 7,S = sector number of the largest contiguous free bits found +* 8,S = number of contiguous free bits found +* 10,s = bit offset into the sector of the found contiguous bits +* 10,s = also DD.BIT number of sectors per cluster +* 12,S = number of sectors to search for (D from the calling routine) +* 16,S = PD pointer (Y from the calling routine) +FatScan pshs u,y,x,b,a + ldb #$0C +L0DB9 clr ,-s reserve 12 bytes of junk on-stack + decb + bne L0DB9 + ldx PD.DTB,y + ldd DD.MAP,x number of bytes in allocation bitmap + std 4,s + ldd DD.BIT,x number of sectors per cluster + std 2,s + std 10,s + ldx PD.DEV,y get pointer to device table entry + ldx V$DESC,x point to descriptor + leax M$DTyp,x get device type + subd #1 + addb IT.SAS-M$DTyp,x add in one sector allocation size + adca #0 make it 16-bit + bra L0DDD default to greater of SAS or DD.BIT + +L0DDB equ * + IFNE H6309 + lsrd shift D to the right + ELSE + lsra + rorb + ENDC +L0DDD lsr $0A,s shift DD.BIT to the right + ror $0B,s + bcc L0DDB loop until carry is set + std ,s D = number of clusters to allocate + ldd 2,s get old DD.BIT + std $0A,s save on-stack again + subd #$0001 + addd $0C,s add in to the number of sectors we're asked to + bcc L0DF7 allocate + ldd #$FFFF if larger than 64K sectors, default to 64K + bra L0DF7 skip ahead + +L0DF5 equ * + IFNE H6309 + lsrd shift number of sectors to allocate + ELSE + lsra + rorb + ENDC +L0DF7 lsr $0A,s + ror $0B,s + bcc L0DF5 loop, and continue +* ATD: remove this code for HD's, to allow >2048 cluster segments??? +* It may be easier to read in the FD, and COMPACT it by looking for +* LSN+SIZE=next segment LSN. But that would take 48*(30?) clock cycles, +* which is a lot of time... but maybe not compared to F$All/F$Sch, and +* the sector read/writes... + cmpa #8 at least 256*8 bits to allocate? + bcs L0E04 number of clusters is OK, skip ahead + ldd #$0800 force one sector of clusters max. to be allocated +L0E04 std $0C,s save as the number of clusters to allocate + lbsr L1036 make us the current user of the allocation bitmap + lbcs L0EF2 exit on error + ldx PD.DTB,y get drive table + ldd V.DiskID,x and old disk ID + cmpd DD.DSK,x check against the current disk ID + bne L0E26 if not the same, make us the current disk ID + lda V.BMapSz,x same allocation bitmap size? + cmpa DD.MAP,x + bne L0E26 no, skip ahead + ldb V.MapSct,x another check + cmpb DD.MAP,x + bcs L0E34 + +L0E26 ldd DD.DSK,x get current disk ID + std V.DiskID,x make us the disk to use + lda DD.MAP,x grab number of sectors in allocation bitmap + sta V.BMapSz,x save for later + clrb + stb V.MapSct,x make this zero for now +L0E34 incb account for LSN0 + stb 6,s lowest reasonable bitmap sector number +* ATD: Is this line necessary? All calls to L0E34 set up X already + ldx PD.DTB,y get drive table pointer again + cmpb V.ResBit,x check B against reserved bitmap sector + beq L0E70 same, skip ahead + lbsr L1091 go read in a bitmap sector + lbcs L0EF2 + ldb 6,s grab copy of V.MapSCT again + cmpb 4,s check against number of sectors in allocation bitmap + bls L0E51 lower, continue + clra if at end of the allocation bitmap, + ldb 5,s don't search it all, but just to the end of the + bra L0E54 last sector in the allocation bitmap + +* ATD: This the routine that we would fix to cache a compressed version +* of the allocation bitmap. i.e. largest group of contiguous free sectors, +* where 255 == 256 by definition. At 1 byte/sector, max. 256 sectors in the +* allocation bitmap, max. 256 bytes. The search should be a LOT faster then, +* as we'll only have to search memory and not read in all those sectors. +* If we're really daring, we could build the new FD without reading the +* allocation bitmap _at_all_, and just use a 'best-fit' algorithm on the +* cached version, and update the bitmap later. +* RBF doesn't do any other search bit calls, so this is the routine. +L0E51 ldd #$0100 +L0E54 ldx PD.BUF,y where to start searching + leau d,x where to stop searching + ldy $0C,s number of bits to find +* ATD: force it to be less than 1 sector here... + IFNE H6309 + clrd at starting bit number 0 + ELSE + clra + clrb + ENDC + os9 F$SchBit + bcc L0E9D found bits + cmpy 8,s check number of found bits against our maximum + bls L0E70 smaller, skip ahead + sty 8,s save as new maximum + std $0A,s save starting bit number + lda 6,s grab current sector + sta 7,s save for later +L0E70 ldy <$10,s grab old PD pointer + ldb 6,s grab current bitmap sector number + cmpb 4,s check against highest sector number of bitmap + bcs L0E81 we're OK, skip ahead + bhi L0E80 we're too high, skip ahead + tst 5,s check bytes in the sector + bne L0E81 not zero: skip ahead +L0E80 clrb +L0E81 ldx PD.DTB,y get drive table pointer again + cmpb V.MapSct,x check against lowest reasonable bitmap sector + bne L0E34 ifnot the same, continue + + ldb 7,s grab sector number of largest block found + beq L0EF0 zero, exit with E$Full error + cmpb 6,s is it the current sector? + beq L0E96 yes, skip ahead + stb 6,s make it the current sector + lbsr L1091 go read the sector in from disk + +L0E96 ldx PD.BUF,y point to the sector in the buffer + ldd $0A,s grab starting bit number + ldy 8,s and number of bits to allocate +L0E9D std $0A,s save starting bit number + sty 8,s and number of bits to allocate + os9 F$AllBit go allocate the bits + ldy $10,s grab the PD pointer again + ldb $06,s and the sector number + lbsr L1069 write it out to disk + bcs L0EF2 exit on error +* ATD: add check for segments left to allocate, if we've allocated +* one entire sector's worth??? +* What about special-purpose code to read the allocation bitmap byte by byte +* and do it that way? I dunno... +* Have some routine inside L0DB5 call another routine which allocates segments +* one sector at a time... have a check: got one sector? +* ATD: We'll probably have to add in allocation bitmap caching for this +* to work properly.... + ldx PD.DTB,y drive table pointer + lda 6,s current sector + deca decreemnt + sta V.MapSct,x AHA! Last searched sector for later use + clrb + lsla move high bit of A into CC.C + rolb move CC.C into B + lsla etc. + rolb cannot do a ROLD, as that would be LSB, ROLA + lsla i.e. move the 3 high bits of A into low bits of B + rolb and shift A by 3 + stb PD.SBP,y save segment beginning physical sector number + ora $0A,s OR in with the start bit number + ldb $0B,s grab LSB of starting bit number + ldx 8,s and number of free sectors found +* ATD: Is this next line really necessary? + ldy $10,s get PD pointer + std PD.SBP+1,y save low 2 bytes of segment beginning physical SN + stx PD.SSZ+1,y and segment size in clusters + ldd 2,s grab number of sectors per cluster + bra L0EE6 + +L0ED7 lsl PD.SBP+2,y shift physical sector numberup + rol PD.SBP+1,y to LSN, to account for cluster size + rol PD.SBP,y + lsl PD.SSZ+2,y + rol PD.SSZ+1,y shift segment cluster size to sector size +L0EE6 + IFNE H6309 + lsrd + ELSE + lsra + rorb + ENDC + bcc L0ED7 + + clrb no errors + ldd PD.SSZ+1,y number of sectors allocated + bra L0EFA and return to the user + +L0EF0 ldb #E$Full +L0EF2 ldy $10,s get old Y off of the stack + lbsr L1070 return allocation bitmap? + coma +L0EFA leas $0E,s skip 12-byte buffer, and D + puls pc,u,y,x + +* Set the size of a file to PD.SIZ, where PD.SIZ is SMALLER than the +* current size of the file. +L0EFE clra clear the carry +* This code ensures that directories are never shrunk in size. + lda PD.MOD,y access mode + bita #DIR. directory? + bne L0F6F yes (bit set), exit immediately + IFNE H6309 + ldq PD.SIZ,y grab size of the file + stq PD.CP,y make it the current position + ELSE + ldd PD.SIZ,y + std PD.CP,y + ldd PD.SIZ+2,y + std PD.CP+2,y + ENDC + ldd #$FFFF + tfr d,x + lbsr L0B1B + bcs L0F6E + lbsr L0CDF + bne L0F6F exit + lbsr L10B2 find a segment + bcc L0F26 + cmpb #E$NES non-existing segment error + bra L0F67 + +L0F26 ldd PD.SBL+1,y not quite sure what's going on here... + subd PD.CP+1,y + addd PD.SSZ+1,y + tst PD.CP+3,y on a sector boundary? + beq L0F35 yes, skip ahead + IFNE H6309 + decd ok here, carry NOT used below + ELSE + subd #$0001 + ENDC +L0F35 pshs d + ldu PD.DTB,y number of sectors per cluster + ldd DD.BIT,u + IFNE H6309 + decd + comd + andd ,s++ + ELSE + subd #$0001 + coma + comb + anda ,s+ + andb ,s+ + ENDC + ldu PD.SSZ+1,y + std PD.SSZ+1,y + beq L0F69 + tfr u,d + subd PD.SSZ+1,y + pshs x,b,a + addd PD.SBP+1,y + std PD.SBP+1,y + bcc L0F5F + inc PD.SBP,y +L0F5F bsr ClrFBits delete a segment + bcc L0F70 + leas 4,s + cmpb #E$IBA illegal block address + +L0F67 bne L0F6E +L0F69 lbsr RdFlDscr + bcc L0F79 +L0F6E coma +L0F6F rts + +L0F70 lbsr RdFlDscr + bcs L0FC9 + puls x,b,a + std FDSL.B,x +L0F79 ldu PD.BUF,y + IFNE H6309 + ldq PD.SIZ,y grab file size from the PD + stq FD.SIZ,u save in the FD file size + ELSE + ldd PD.SIZ,y + std FD.SIZ,u + ldd PD.SIZ+2,y + std FD.SIZ+2,u + ENDC + tfr x,d + clrb + inca + leax FDSL.S,x go to the next segment + pshs x,b,a + bra L0FB4 +L0F8E ldd -2,x + beq L0FC1 + std PD.SSZ+1,y + ldd -FDSL.S,x grab stuff from the last segment + std PD.SBP,y + lda -FDSL.B,x + sta PD.SBP+2,y save sector beginning physical sector number + bsr ClrFBits delete a segment + bcs L0FC9 + stx 2,s + lbsr RdFlDscr + bcs L0FC9 + ldx 2,s + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + std -$05,x clear out the segment + sta -$03,x + std -$02,x +L0FB4 lbsr L11FD + bcs L0FC9 + ldx 2,s + leax FDSL.S,x go to the next segment + cmpx ,s + bcs L0F8E if not done, do another +L0FC1 equ * + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + sta PD.SSZ,y + std PD.SSZ+1,y segment size is zero +L0FC9 leas 4,s + rts + +* de-allocate a segment +ClrFBits pshs u,y,x,a get device table pointer + ldx PD.DTB,y + +* ATD: Added next few lines to ENSURE that LSN0 and the allocation bitmap +* are NEVER marked as de-allocated in the allocation bitmap +* ldd PD.SBP,y grab beginning segment physical LSN +* bne L0FD0 skip next code if too high +* ldd DD.MAP,x get number of bytes in allocation bitmap +* addd #$01FF add 1 for LSN0, round up a sector: A=lowest LSN +* cmpa PD.SBP+2,y check LSN0 + DD.MAP against LSN to deallocate +* blo L0FD0 if PD.SBP is higher than LSN0 + DD.MAP, allow it +* ldb #E$IBA illegal block address: can't deallocate LSN0 +* bra L1033 or the allocation bitmap sectors from the bitmap! + + ldd DD.BIT,x + IFNE H6309 + decd + ELSE + subd #$0001 + ENDC + addd PD.SBP+1,y + std PD.SBP+1,y + ldd DD.BIT,x + bcc L0FF4 + inc PD.SBP,y + bra L0FF4 + +L0FE5 lsr PD.SBP,y convert sector number to cluster number + ror PD.SBP+1,y + ror PD.SBP+2,y + lsr PD.SSZ+1,y + ror PD.SSZ+2,y +L0FF4 equ * + IFNE H6309 + lsrd + ELSE + lsra + rorb + ENDC + bcc L0FE5 + + clrb + ldd PD.SSZ+1,y + beq L1034 + ldd PD.SBP,y + IFNE H6309 + lsrd + lsrd + lsrd get cluster byte number into D + ELSE + lsra + rorb + lsra + rorb + lsra + rorb + ENDC + tfr b,a + ldb #E$IBA + cmpa DD.MAP,x is the LSN too high: mapped outside of the bitmap? + bhi L1033 yes, error out + inca + sta ,s +L1012 bsr L1036 flush the sector, and OWN the bitmap + bcs L1012 + ldb ,s grab the sector number + bsr L1091 go read a sector fro the allocation bitmap + bcs L1033 + ldx PD.BUF,y where to start + ldd PD.SBP+1,y bit offset to delete +* ATD: keep deleting sectors until we're done! + anda #$07 make sure it's within the current sector +* ATD: fix segment sizes! + ldy PD.SSZ+1,y number of clusters to deallocate + os9 F$DelBit go delete them (no error possible) + ldy 3,s + ldb ,s grab bitmap sector number again + bsr L1069 go write it out + bcc L1034 xit on error +L1033 coma +L1034 puls pc,u,y,x,a + +L1036 lbsr L1237 flush the sector to disk + bra L1043 skip ahead + +L103B lbsr L0C56 wakeup the process + os9 F$IOQu queue the process + bsr L1053 check for process wakeup +L1043 bcs L1052 error, return + ldx PD.DTB,y get drive table ptr + lda V.BMB,x bitmap sector + bne L103B if set, continue + lda PD.CPR,y get our process number + sta V.BMB,x make us the current user of the bitmap +L1052 rts + +* Wait for process to wakeup +L1053 ldu <D.Proc get current process pointer + ldb P$Signal,u get pending signal + cmpb #S$Wake is it what we're looking for? + bls L1060 yes, skip ahead + cmpb #S$Intrpt is it a keyboard interrupt/ + bls L1067 no, return error [B]=Error code +L1060 clra clear error status + IFNE H6309 + tim #Condem,P$State,u is process dead? + ELSE + lda P$State,u + bita #Condem + ENDC + beq L1068 no, skip ahead +L1067 coma flag error +L1068 rts return + +* Write a file allocation bitmap sector +* Entry: B=Logical sector # +L1069 clra clear MSB of LSW to logical sector # + tfr d,x move it to proper register + clrb clear MSB of logical sector # + lbsr L1207 flush the sector to drive +L1070 pshs cc preserve error status from write + ldx PD.DTB,y get drive table pointer + lda PD.CPR,y get the current process using it + cmpa V.BMB,x same as process using the bit-map sector? + bne L108F no, return + clr V.BMB,x clear the use flag + ldx <D.Proc get current process pointer + lda P$IOQN,x get next process in line for sector + beq L108F none, return + lbsr L0C56 wake up the process + ldx #1 sleep for balance of tick + os9 F$Sleep +L108F puls pc,cc restore error status & return + +* Read a sector from file allocation bit map +* Entry: B=Logical sector # +L1091 clra clear MSB of LSW to logical sector # + tfr d,x move to proper register + clrb clear MSB of logical sector # + lbra L113A go read the sector + +* Entry: Y=Path descriptor pointer +L1098 ldd PD.CP+1,y + subd PD.SBL+1,y + tfr d,x + ldb PD.CP,y + sbcb PD.SBL,y + cmpb PD.SSZ,y + bcs L10B0 + bhi L10B2 yes, scan the segment list + cmpx PD.SSZ+1,y + bcc L10B2 +L10B0 clrb +L10B1 rts + +* Scan file segment list to get proper segment based on current byte position +* in the file. Once found it will be placed in the path descriptor +* Entry: None +L10B2 pshs u preserve + bsr RdFlDscr get the file descriptor + bcs L110E error, return + IFNE H6309 init the start point of search in path descriptor + clrd + ELSE + clra + clrb + ENDC + std PD.SBL,y + stb PD.SBL+2,y + ldu PD.BUF,y get sector buffer pointer + leax FD.SEG,u point to segment list + lda PD.BUF,y get MSB of sector buffer pointer + ldb #$FC get size of segment table + pshs b,a save as table end pointer +* Scan segment list for the proper segment +L10CB ldd FDSL.B,x get segment size in sectors + beq L10F0 last one, exit with non existing segment error + addd PD.SBL+1,y add to segment start LSN + tfr d,u copy it + ldb PD.SBL,y + adcb #0 + cmpb PD.CP,y this the segment we want? + bhi L10FD yes, move the segment start & size to descriptor + bne L10E4 no, save this segment & keep looking + cmpu PD.CP+1,y + bhi L10FD +L10E4 stb PD.SBL,y + stu PD.SBL+1,y + leax FDSL.S,x move to next segment + cmpx ,s done? + bcs L10CB no, keep going + +* Return Non-Existing segment error +L10F0 equ * + IFNE H6309 + clrd + ELSE + clra + clrb + ENDC + sta PD.SSZ,y zero out the segment + std PD.SSZ+1,y + comb set the carry + ldb #E$NES non-existing segment + bra L110C return + +* Move segment to path descriptor +L10FD ldd FDSL.A,x get start physical sector # + std PD.SBP,y put it in path descriptor + lda FDSL.A+2,x + sta PD.SBP+2,y + ldd FDSL.B,x get segment size + std PD.SSZ+1,y put it in path descriptor +L110C leas 2,s +L110E puls pc,u + +* Read LSN0 from drive +* Entry: Y=Path descriptor pointer +L1110 pshs x,b preserve regs used + lbsr L1237 flush sector buffer + bcs L111F error, return + clrb get LSN + ldx #$0000 + bsr L113A read the sector + bcc L1121 no error, return +L111F stb ,s save error code +L1121 puls pc,x,b restore & return + +* Read a file descriptor from disk +* Entry: Y=Path descriptor pointer +RdFlDscr + IFNE H6309 + tim #FDBUF,PD.SMF,y FD already here? + ELSE + ldb PD.SMF,y + bitb #FDBUF + ENDC + bne L10B0 yes, return no error + lbsr L1237 flush any sector here + bcs L10B1 error, return + IFNE H6309 + oim #FDBUF,PD.SMF,y + ELSE + lda PD.SMF,y + ora #FDBUF + sta PD.SMF,y + ENDC + ldb PD.FD,y get MSB of logical sector + ldx PD.FD+1,y get LSW of logical sector +L113A lda #D$READ get read offset +* Send command to device driver +* Entry: A=Driver Command offset +* B=MSB of logical sector # +* X=LSW of logical sector # +* Y=Path descriptor pointer +L113C pshs u,y,x,b,a preserve it all + IFNE H6309 + oim #InDriver,PD.SMF,y flag we're in ddriver + ELSE + lda PD.SMF,y + ora #InDriver + sta PD.SMF,y + ENDC + ldx <D.Proc get current process pointer + lda P$Prior,x get its priority + tfr a,b copy it + addb #3 add 3 to it + bcc L1150 didn't wrap, skip ahead + ldb #$FF force it to max +L1150 stb P$Prior,x save priority + stb P$Age,x asage too + ldx PD.Exten,y get path extension pointer + sta PE.Prior,x save original priority there + ldu PD.DEV,y get device table pointer + ldu V$STAT,u get static mem pointer + bra L1166 go execute driver +* Wait for device +L1160 lbsr L0C56 wakeup waiting process + os9 F$IOQu queue device +* Device ready, send command +L1166 lda V.BUSY,u driver already busy? + bne L1160 yes, queue it + lda PD.CPR,y get current process # + sta V.BUSY,u save it as busy + ldd ,s get command & logical sector from stack + ldx 2,s + pshs u save static mem + bsr L11EB send it to driver + puls u restore static mem + ldy 4,s get path descriptor pointer + pshs cc preserve driver error status + bcc L1181 no error, skip ahead + stb 2,s save driver's error code +L1181 equ * + IFNE H6309 + aim #^InDriver,PD.SMF,y clear in driver flag + ELSE + lda PD.SMF,y + anda #^InDriver + sta PD.SMF,y + ENDC + clr V.BUSY,u + ldx PD.Exten,y + lda PE.Prior,x + ldx <D.Proc + sta P$Prior,x +****** +* this code is in v31 only + lda ,s get driver error status + bita #Carry was there an error? + bne L11CB yes, return with it + lda 1,s get the driver command + cmpa #D$WRIT was it write sector? + bne L11CB no, return + pshs u,y,x preserve regs + ldy PD.Exten,y + leau ,y +L11A7 ldx PE.Confl,u + cmpy PE.Confl,u + beq L11C9 + leau ,x + +* Check for signal on data write + lda PE.SigID,u anything to send signal to? + beq L11A7 no, skip to next in chain + ldx <D.Proc get current process + cmpa P$ID,x + beq L11A7 + clr PE.SigID,u + ldb PE.SigSg,u + os9 F$Send + bra L11A7 + +L11C9 puls u,y,x +L11CB lda P$IOQN,x any process waiting? + beq L11E9 no, return + lda $01,y + bita #$04 + bne L11E9 + ldx PD.DTB,y get driver table pointer + lda PD.CPR,y get current process ID + cmpa V.BMB,x same as bitmap use process? + beq L11E9 yes, return + lbsr L0C56 + ldx #1 sleep for balance of tick + os9 F$Sleep +L11E9 puls pc,u,y,x,b,a,cc restore & return + +* Execute device driver +* Entry: A=Driver command offset +* B=MSB of logical sector # +* X=LSW of logical sector # +* Y=Path descriptor pointer +* U=Static memory pointer +L11EB pshs pc,x,b,a + ldx $03,y + ldd ,x + ldx ,x + addd $09,x + addb ,s + adca #$00 + std $04,s + puls pc,x,b,a + +* Write file descriptor to disk +* Entry: Y=Path descriptor pointer +L11FD ldb PD.FD,y get MSB of LSN + ldx PD.FD+1,y get LSW of LSn + bra L1207 send it to disk + + +* Flush sector buffer to disk +* Entry: Y=Path descriptor pointer +L1205 bsr L1220 calulate LSN +L1207 lda #D$WRIT get driver write offset + pshs x,b,a preserve that & LSN + ldd PD.DSK,y get disk ID of this sector + beq L1216 nothing, send it to driver + ldx PD.DTB,y get drive table pointer + cmpd DD.DSK,x match ID from drive? +L1216 puls x,b,a restore regs + lbeq L113C ID matches, send data to driver + comb set carry + ldb #E$DIDC get ID change error code + rts return + +* Calculate logical sector # of current sector in buffer +* Exit : B=MSB of logical sector # +* X=LSW of logical sector # +L1220 ldd PD.CP+1,y get current logical sector loaded + subd PD.SBL+1,y subtract it from segment list LSN + tfr d,x copy answer + ldb PD.CP,y get MSB of byte position + sbcb PD.SBL,y subtract it from segment start + exg d,x + addd PD.SBP+1,y add in physical segment sector # + exg d,x + adcb PD.SBP,y now the MSB + rts return + +* Check if sector buffer needs to be flushed to disk +* Entry: Y=Path descriptor pointer +L1237 clrb clear carry + pshs u,x preserve regs + ldb PD.SMF,y get state flags + andb #(BufBusy!FDBUF!SINBUF) aynything in buffer? + beq L1254 no, return + tfr b,a duplicate flags + eorb PD.SMF,y clear them + stb PD.SMF,y save 'em + andb #BUFMOD has buffer been modified? + beq L1254 no, return + eorb PD.SMF,y clear that bit + stb PD.SMF,y save it + bita #SINBUF is there even a sector in buffer? + beq L1254 no, return + bsr L1205 flush the sector to drive +L1254 puls pc,u,x restore & return + +L1256 pshs u,x + lbsr L1098 + bcs L12C6 + bsr L1237 + bcs L12C6 +L1261 ldb PD.CP,y + ldu PD.CP+1,y + leax ,y + ldy PD.Exten,y +L126B ldx PD.Exten,x + cmpy PE.Confl,x + beq L12B5 + ldx PE.Confl,x + ldx PE.PDptr,x + cmpu PD.CP+1,x + bne L126B + cmpb PD.CP,x + bne L126B + lda PD.SMF,x + bita #SINBUF + beq L126B + bita #InDriver + bne L128E + bita #BufBusy + beq L12A0 +L128E lda PD.CPR,x + ldy PE.PDptr,y + lbsr L0C56 + os9 F$IOQu + lbsr L1053 + bcc L1261 + puls u,x,pc + +L12A0 ldy PE.PDptr,y + ldd PD.BUF,x + ldu PD.BUF,y + std PD.BUF,y + stu PD.BUF,x + lda PD.SMF,x \ careful, don't use oim here + ora #BufBusy >takes state from x and + sta PD.SMF,y / stores to y, is infamous "lha" bug + clr PD.SMF,x + puls pc,u,x + +L12B5 ldy PE.PDptr,y + lbsr L1220 + lbsr L113A + bcs L12C6 + IFNE H6309 + oim #(BufBusy!SINBUF),PD.SMF,y + ELSE + pshs a + lda PD.SMF,y + ora #(BufBusy!SINBUF) + sta PD.SMF,y + puls a + ENDC +L12C6 puls pc,u,x + + emod +eom equ * + end +