+ cpi temp,WRUAL ;write unallocated?
+ brne dsk_chkuna ;check for unalloc
+
+; write to unallocated, set parameters
+ ldi temp,blksize/128 ;next unalloc recs
+ sts unacnt,temp
+ lds temp,seekdsk ;disk to seek
+ sts unadsk,temp ;unadsk = sekdsk
+ lds temp,seektrk
+ sts unatrk,temp ;unatrk = sectrk
+ lds temp,seektrk+1
+ sts unatrk+1,temp ;unatrk = sectrk
+ lds temp,seeksec
+ sts unasec,temp ;unasec = seksec
+;
+dsk_chkuna:
+ ;check for write to unallocated sector
+ lds temp,unacnt ;any unalloc remain?
+ tst temp
+ breq dsk_alloc ;skip if not
+
+; more unallocated records remain
+ dec temp ;unacnt = unacnt-1
+ sts unacnt,temp
+ lds temp,seekdsk ;same disk?
+ lds temp2,unadsk
+ cp temp,temp2 ;seekdsk = unadsk?
+ brne dsk_alloc ;skip if not
+
+; disks are the same
+ lds temp,unatrk
+ lds temp2,unatrk+1
+ lds temp3,seektrk
+ lds temp4,seektrk+1
+ cp temp,temp3 ;seektrk = unatrk?
+ cpc temp2,temp4
+ brne dsk_alloc ;skip if not
+
+; tracks are the same
+ lds temp,seeksec ;same sector?
+ lds temp2,unasec
+ cp temp,temp2 ;seeksec = unasec?
+ brne dsk_alloc ;skip if not
+
+; match, move to next sector for future ref
+ inc temp2 ;unasec = unasec+1
+ sts unasec,temp2
+ cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
+ brlo dsk_noovf ;skip if no overflow
+
+; overflow to next track
+ sts unasec,_0 ;unasec = 0
+ lds temp,unatrk
+ lds temp2,unatrk+1
+ subi temp, low(-1) ;unatrk = unatrk+1
+ sbci temp2,high(-1)
+ sts unatrk,temp
+ sts unatrk+1,temp2
+;
+dsk_noovf:
+ cbi flags,rsflag ;rsflag = 0
+ rjmp dsk_rwoper ;to perform the write
+;
+dsk_alloc:
+ ;not an unallocated record, requires pre-read
+ sts unacnt,_0 ;unacnt = 0
+ sbi flags,rsflag ;rsflag = 1
+
+;*****************************************************
+;* Common code for READ and WRITE follows *
+;*****************************************************
+
+dsk_rwoper:
+ ;enter here to perform the read/write
+ sts erflag,_0 ;no errors (yet)
+
+ ;Convert track/sector to an LBA address (in 128byte blocks)
+
+ lds adrl,seeksec ;
+ ldi adrh,0 ;
+ lds temp3,seektrk ;
+ lds temp4,seektrk+1 ;
+ ldi temp,CPMSPT ;
+ mul temp3,temp ;
+ add adrl,r0 ;
+ adc adrh,r1 ;
+ mul temp4,temp ;
+ add adrh,r0 ;adrh:adrl := sec + trk * SectorsPerTrack
+ clr _0
+
+ mov temp,adrl
+ andi temp,SECMSK ;mask buffer number
+ push temp ;save for later
+.if DISK_DEBUG
+ rcall printstr
+ .db "; bufnr: ",0,0
+ rcall printhex
+.endif
+
+ ;Convert from CP/M LBA blocks to host LBA blocks
+ ldi temp,SECSHF
+dsk_sh1:
+ lsr adrh
+ ror adrl
+ dec temp
+ brne dsk_sh1
+ ;adrh:adrl = host block to seek
+; active host sector?
+ sbis flags,hostact ;host active?
+ rjmp dsk_filhst ;fill host if not
+
+; host buffer active, same as seek buffer?
+ lds temp,seekdsk
+ lds temp3,hostdsk ;same disk?
+ cp temp,temp3 ;seekdsk = hostdsk?
+ brne dsk_nomatch
+
+; same disk, same block?
+ lds temp3,hostlba
+ lds temp4,hostlba+1
+ cp adrl,temp3
+ cpc adrh,temp4
+ breq dsk_match
+;
+dsk_nomatch:
+ ;proper disk, but not correct sector
+ sbic flags,hostwrt ;host written?
+ rcall dsk_writehost ;clear host buff
+
+dsk_filhst:
+ ;may have to fill the host buffer
+ lds temp,seekdsk
+ sts hostdsk,temp
+ sts hostlba,adrl
+ sts hostlba+1,adrh
+
+ sbic flags,rsflag ;need to read?
+ rcall dsk_readhost ;yes, if 1
+ cbi flags,hostwrt ;no pending write
+
+dsk_match:
+ sbi flags,hostact ;host buffer active now
+
+ ;copy data to or from buffer
+ ldi zl,low(hostbuf)
+ ldi zh,high(hostbuf)
+ ldi temp,128
+ pop temp2 ;get buffer number (which part of hostbuf)
+ mul temp2,temp
+ add zl,r0 ;offset in hostbuf
+ adc zh,r1
+.if DISK_DEBUG
+ push r0
+ push r1
+ clr _0
+ rcall printstr
+ .db "; host buf adr: ",0,0
+ pop temp
+ rcall printhex
+ pop temp
+ rcall printhex
+.endif
+ clr _0