**************************** * * * read address field * * subroutine * * (16-sector format) * * * **************************** * * * reads volume, track * * and sector * * * * on entry ---- * * * * xreg: slotnum times $10 * * * * read mode (q6l, q7l) * * * * on exit ----- * * * * carry set if error. * * * * if no error: * * a-reg holds $aa. * * y-reg holds $00. * * x-reg unchanged. * * carry clear. * * * * csstv holds chksum, * * sector, track, and * * volume read. * * * * uses temps count, * * last, csum, and * * 4 bytes at csstv. * * * * expects ---- * * * * original 10-sector * * normal density nibls * * (4-bit), odd bits, * * then even. * * * * caution ---- * * * * observe * * 'no page cross' * * warnings on * * some branches!! * * * * assumes ---- * * * * 1 usec cycle time * * * **************************** RdAdr16 LDY #$FC STY count ;'must find' count RdASyn INY BNE :loop1 ;Low order of count INC count ;(2k nibbles to find BEQ RdErr ; adr mark, else err) :loop1 LDA q6l,X ;Read nibble BPL :loop1 ;*** no page cross! *** RdASyn1 CMP #$D5 ;Adr mark 1? BNE RdASyn ;(loop if not) NOP ;Added nibble delay LDA q6l,X BPL *-3 ;*** no page cross! *** CMP #$AA ;Adr mark 2? BNE RdASyn1 ; (if not, is it am1?) * (added nibl delay) LDY #$03 ;Index for 4-byte read LDA q6l,X BPL *-3 ;*** no page cross! *** CMP #$96 ;Adr mark 3? BNE RdASyn1 ; (if not, is it am1?) SEI ;No interupts until address is tested.(carry is set) LDA #$00 ;Init checksum RdAddrFld STA chkSum LDA q6l,X ;Read 'odd bit' nibble BPL *-3 ;*** no page cross! *** ROL ;Align odd bits, '1' into lsb STA last ; (save them) LDA q6l,X ;Read 'even bit' nibble BPL *-3 ;*** no page cross! *** AND last ;Merge odd and even bits STA csSTV,Y ;Store data byte EOR chkSum DEY BPL RdAddrFld ;Loop on 4 data bytes TAY ;If final checksum BNE RdErr ; nonzero, then error LDA q6l,X ;First bit-slip nibble BPL *-3 ;*** no page cross! *** CMP #$DE BNE RdErr ;Error if nonmatch NOP ;delay LDA q6l,X ;Second bit-slip nibble BPL *-3 ;*** no page cross! *** CMP #$AA BNE RdErr ;Error if nonmatch CLC ;Clear carry on RTS ;Normal read exits RdErr SEC RTS ************************** * * * read subroutine * * (16-sector format) * * * ************************** * * * reads encoded bytes * * into nbuf1 and nbuf2 * * * * first reads nbuf2 * * high to low, * * then reads nbuf1 * * low to high. * * * * on entry ---- * * * * x-reg: slotnum * * times $10. * * * * read mode (q6l, q7l) * * * * on exit ----- * * * * carry set if error. * * * * if no error: * * a-reg holds $aa. * * x-reg unchanged. * * y-reg holds $00. * * carry clear. * * caution ----- * * * * observe * * 'no page cross' * * warnings on * * some branches!! * * * * assumes ---- * * * * 1 usec cycle time * * * ************************** Read16 TXA ;Get slot # ORA #$8C ;Prepare mods to read routine STA Read4+1 ;Warning: the read routine is self modified!!! STA Read5+1 STA Read6+1 STA Read7+1 STA Read8+1 LDA bufPtr ;Modify storage addresses also LDY bufPtr+1 STA Ref3+1 STY Ref3+2 SEC SBC #$54 BCS :1 DEY :1 STA Ref2+1 STY Ref2+2 SEC SBC #$57 BCS :2 ;Branch if no borrow DEY :2 STA Ref1+1 STY Ref1+2 LDY #$20 ;'must find count' rSync DEY BEQ RdErr2 ;Branch if can't find data header marks LDA q6l,X BPL *-3 rSync1 EOR #$D5 ;First data mark BNE rSync NOP ;Waste a little time... LDA q6l,X BPL *-3 CMP #$AA ;Data mark 2 BNE rSync1 ;If not, check for first again NOP LDA q6l,X BPL *-3 CMP #$AD ;Data mark 3 BNE rSync1 ;If not, check for data mark 1 again LDY #$AA LDA #$00 RdData1 STA wTemp ;Use zpage for checksum keepin Read4 LDX $C0EC ;Warning: self modified BPL Read4 LDA dNibble,X STA nBuf2-$AA,Y ;Save the two-bit groups in nbuf EOR wTemp ;Update checksum INY ;Bump to next nBuf2 position BNE RdData1 ;Loop for all $56 two-bit groups LDY #$AA ;Now read directly into user buffer BNE Read5 ;Branch always taken!!! RdErr2 SEC RTS Ref1 STA $1000,Y ;Warning: self modified! Read5 LDX $C0EC BPL Read5 EOR dNibble,X ;Get actual 6-bit data from dNibble table LDX nBuf2-$AA,Y ;Get associated two-bit pattern EOR dNibble2,X ; & combine to form whole byte INY BNE Ref1 ;Loop for $56 bytes PHA ;Save this byte for now, no time to store... AND #$FC ;Strip low 2 bits... LDY #$AA ;Prepare for next $56 bytes Read6 LDX $C0EC BPL Read6 EOR dNibble,X LDX nBuf2-$AA,Y EOR dNibble3,X Ref2 STA $1000,Y ;Warning: self modified INY BNE Read6 ;Loop until this group of $56 read in * Read7 LDX $C0EC BPL Read7 AND #$FC LDY #$AC ;Last group is $54 long RdData2 EOR dNibble,X LDX nBuf2-$AC,Y EOR dNibble4,X ;Combine to form full byte Ref3 STA $1000,Y Read8 LDX $C0EC ;Warning: self modified BPL Read8 INY BNE RdData2 AND #$FC EOR dNibble,X ;Check sum ok? BNE RdErr1 ;Branch if not LDX slotZ ;Test end marks LDA q6l,X BPL *-3 CMP #$DE CLC BEQ RdOK ;Branch if good trailer... RdErr1 SEC RdOK PLA LDY #$55 ;Place last byte into user buffer STA (bufPtr),Y RTS * This subroutine sets the slot * dependent track location. SetTrk JSR DrvIndx ;Get index to drive number STA drv0Trk,X RTS ***************************************** * * Subrtn to tell if motor is stopped * * If motor is stopped, controller's * shift reg will not be changing. * * return y=0 and zero flag set if it is stopped. * ***************************************** ChkDrv LDX slotZ ChkDrv0 LDY #$00 ;init loop counter :loop LDA q6l,X ;read the shift reg JSR :ChkDrvRTS ;delay PHA PLA ;more delay CMP q6l,X BNE :ChkDrvRTS LDA #$28 DEY BNE :loop :ChkDrvRTS RTS DrvIndx PHA ;Preserve Acc LDA unitNum ;DSSS xxxx where D=0/1 & SSS=slot # LSR LSR LSR LSR ;0000 DSSS CMP #$08 ;C=1 -> drive 2 AND #$07 ;0000 0SSS ROL ;0000 SSSD TAX ;Into X for index to table PLA ;Restore A RTS ************************ * * * write subr * * (16-sector format) * * * ************************ * * * writes data from * * nbuf1 and buf * * * * first nbuf2, * * high to low. * * then direct from * * (buf), low to high. * * self modified code!! * * on entry ---- * * * * x-reg: slotnum * * times $10. * * * * * * on exit ----- * * * * carry set if error. * * (w prot violation) * * * * if no error: * * * * a-reg uncertain. * * x-reg unchanged. * * y-reg holds $00. * * carry clear. * * * * assumes ---- * * * * 1 usec cycle time * * * ************************ Write16 SEC ;Anticipate wprot err LDA q6h,X LDA q7l,X ;Sense wprot flag BPL :1 JMP WExit ;Exit if write protected :1 LDA nBuf2 STA wTemp LDA #$FF ;Sync data STA q7h,X ;(5) Goto write mode ORA q6l,X ;(4) LDY #$04 ;(2) For five nibbles NOP ;(2) PHA ;(3) PLA ;(4) WSync PHA ;(3) exact timing PLA ;(4) exact timing JSR WrNibl7 ;(13,9,6) write sync DEY ;(2) BNE WSync ;(3-) must not cross page! LDA #$D5 ;(2) 1st data mark JSR WrNibl9 ;(15,9,6) LDA #$AA ;(2) 2nd data mark JSR WrNibl9 ;(15,9,6) LDA #$AD ;(2) 3rd data mark JSR WrNibl9 ;(15,9,6) TYA ;(2) zero checksum LDY #$56 ;(2) nbuf2 index BNE wData1 ;(3) branch always taken wData0 LDA nBuf2,Y ;(4) prior 6-bit nibble wData1 EOR nBuf2-1,Y ;(5) xor with current TAX ;(2) index to 7-bit nibl (nBuf2 must be on page bdry) LDA Nibbles,X ;(4) must not cross page boundary LDX slotZ ;(3) restore slot index STA q6h,X ;(5) store encoded byte LDA q6l,X ;(4) time must = 32 us per byte! DEY ;(2) BNE wData0 ;(3-) must not cross page boundary LDA wTemp ;(3) get prior nibble (from nBuf2) WRefDr1 LDY #$00 ;(2) warning: load value modified by prenib! WData2 EQU * WRefAdr1 EOR $1000,Y ;(4) warning: address modified by prenib! AND #$FC ;(2) TAX ;(2) index to Nibbles table LDA Nibbles,X ;(4) WRefDr2 LDX #$60 ;(2) warning: load value modified by prenib STA q6h,X ;(5) write nibl LDA q6l,X ;(4) handshake WRefAdr2 LDA $1000,Y ;(4) prior nibl. warning: address modified by prenib INY ;(2) all done with this page? BNE WData2 ;(3-) loop until page end LDA midNib1 ;(3) get next (precalculated and translated) nibl BEQ WrtDone ;(2+) branch if code writen was page aligned LDA yEnd ;(3) get byte address of last byte to be written BEQ WData4 ;(2+) branch if only 1 byte left to write LSR ;(2) test for odd or even last byte (carry set or clear) LDA midNib1 ;(3) restore nibl to a STA q6h,X ;(5) LDA q6l,X ;(4) LDA midNib2 ;(3) =byte 0 of second page. xor'd with byte 1 if above test set carry NOP ;(2) waste time INY ;(2) y=1 BCS WrtOdd ;(2+) branch if last byte to be odd WData3 EQU * WRefAdr3 EOR $1100,Y ;(4) warning: address modified by prenib AND #$FC ;(2) strip low 2 bits TAX ;(2) index to Nibbles table LDA Nibbles,X ;(4) get nibble WRefDr3 LDX #$60 ;(2) restore slot index. warning: modified by prenib STA q6h,X ;(5) LDA q6l,X ;(4) WRefAdr4 LDA $1100,Y ;(4) warning: modified by prenib INY ;(2) got prior nibble, bump to next WRefAdr5 EOR $1100,Y ;(4) warning: modified by prenib WrtOdd CPY yEnd ;(3) set carry if this is last nibble AND #$FC ;(2) TAX ;(2) LDA Nibbles,X ;(4) WRefDr4 LDX #$60 ;(2) restore slot. warning: modified by prenib STA q6h,X ;(5) LDA q6l,X ;(4) WRefAdr6 LDA $1100,Y ;(4) get prior. warning: these warnings are all the same INY ;(2) BCC WData3 ;(3-) branch if that was not the las BCS *+2 ;(3) waste 3 cycles, branch always BCS WrtDone ;(3) branch always WData4 LDA |midNib1 ;(4) absolute reference to zero page STA q6h,X ;(5) LDA q6l,X ;(4) PHA ;(3) waste 14 us total PLA ;(4) PHA ;(3) PLA ;(4) WrtDone LDX lstNib ;(3) use last nibl (anded with $fc) for checksum LDA Nibbles,X ;(4) WRefDr5 LDX #$60 ;(2) restore slot. warning: see above warnings... STA q6h,X ;(5) LDA q6l,X ;(4) LDY #$00 ;(2) set y to index end mark table PHA ;(3) waste another 11 us PLA ;(4) NOP ;(2) NOP ;(2) WrEndMrk LDA EndMarks,Y ;(4) dm4, dm5, dm6, and turn off byte JSR WrNibl ;(15,6) write it INY ;(2) CPY #$04 ;(2) have all end marks been written? BNE WrEndMrk ;(3) CLC ;(2,9) WExit LDA q7l,X ;Out of write mode LDA q6l,X ;Into read mode RTS ;Return from write **************************** * * * 7-bit nibl write subrs * * * * a-reg or'd prior exit * * carry cleared * * * **************************** WrNibl9 CLC ;(2) 9 cycles, then write WrNibl7 PHA ;(3) 7 cycles, then write PLA ;(4) WrNibl STA q6h,X ;(5) nibble write subrtn ORA q6l,X ;(4) clobbers acc, not carry RTS ;(6) **************************** * * * preniblize subr * * (16-sector format) * * * **************************** * * * converts 256 bytes of * * user data in (buf) into * * 6 bit nibls into nbuf2 * * high 6 bits are trans- * * lated directly by the * * write routines. * * * * on entry ---- * * * * buf is 2-byte pointer * * to 256 bytes of user * * data. * * * * on exit ----- * * * * a,x,y undefined. * * write routine modified * * to do direct conversion * * of high 6 bits of users * * buffer data. * **************************** PreNibl16 LDA bufPtr ;First self modify addresses so we can be fast! LDY bufPtr+1 ;Y contains high order address CLC ;All offsets are -$AA... ADC #$02 ;The highest set is bufPtr+$AC BCC :1 ;Branch if no carry INY ;Otherwise add carry to high address :1 STA PrN3+1 ;Self mod 3 STY PrN3+2 SEC SBC #$56 ;middle set is buf+$56 BCS :2 ;branch if no borrow DEY ;otherwise deduct from high... :2 STA PrN2+1 ;self mod 2 STY PrN2+2 SEC SBC #$56 ;Low set is exactly bufPtr BCS :3 DEY :3 STA PrN1+1 ;self mod 1 STY PrN1+2 LDY #$AA ;Count up to 0 PreNib4 EQU * PrN1 LDA $1000,Y ;Fetch byte from lowest group. warning: self modified AND #%00000011 ;Strip high 6 bits TAX ;Index to 2 bit equiv LDA TwoBit1,X PHA ;save pattern PrN2 LDA $1056,Y ;fetch from middle group AND #%00000011 TAX PLA ;Restore pattern ORA TwoBit2,X ;Combine second group with first PHA ;Save new pattern PrN3 LDA $10AC,Y ;Get highest group AND #%00000011 TAX PLA ;Restore new pattern ORA TwoBit3,X ; & form final nibble PHA TYA EOR #$FF TAX PLA STA nBuf2,X ;Save in nibble buffer! INY ;Bump to next set BNE PreNib4 ;Loop until all $56 nibbles formed LDY bufPtr ;Now prepare data bytes for write16 routine DEY ;Prepare end addr STY yEnd LDA bufPtr STA WRefDr1+1 ;warning: the following storage addresses starting BEQ WrMod1 ; with 'wref' are referces into code space, EOR #$FF ; changed by this routine TAY ;Index to last byte of page pointed to by buf LDA (bufPtr),Y ;Pre-niblize the last byte of the page with INY ; the first byte of the next page EOR (bufPtr),Y AND #$FC TAX LDA Nibbles,X ;Get disk 7-bit nibble equivalent WrMod1 STA midNib1 BEQ WrMod3 ;Branch if data to be written is page aligned LDA yEnd ;Find out if last byte is even or odd address LSR ;Shift even/oddness into carry LDA (bufPtr),Y ;If even, then leave intact BCC WrMod2 ;Branch if odd INY ;If even, then pre-xor with byte 1 EOR (bufPtr),Y WrMod2 STA midNib2 ;Save result for write routine WrMod3 LDY #$FF ;Index to last byte of data to be writen LDA (bufPtr),Y ; to be used as checksum AND #$FC ;Strip extra bits STA lstNib ;Save it LDY bufPtr+1 ;Now modify address reference to user data STY WRefAdr1+2 STY WRefAdr2+2 INY STY WRefAdr3+2 STY WRefAdr4+2 STY WRefAdr5+2 STY WRefAdr6+2 LDX slotZ ; & lastly index references to controller STX WRefDr2+1 STX WRefDr3+1 STX WRefDr4+1 STX WRefDr5+1 RTS ;All done ChkPrev EOR iobPrevDn ;Same slot as last? ASL BEQ :Rtn ;Yes LDA #$01 STA monTimeH :CkLoop LDA iobPrevDn ;=DSSS xxxx AND #$70 ;=0SSS 0000 TAX BEQ :Rtn ;Branch if no previous ever (boot only) JSR ChkDrv0 ;Find out if previous drive running BEQ :Rtn ;Branch if stopped LDA #$01 ;Waste some time JSR msWait LDA monTimeH BNE :CkLoop :Rtn RTS * ----------------- see rev notes 14, 18 & 70 ------------- ResetPhase LDA unitNum ;Get unit number AND #$7F ;Map off hi bit (drive bit) TAX * clear all the phases and force read mode * patch 76 part 2. part 1 is in xrw1. LDA phaseOff,X ;make sure all motor LDA phaseOff+2,X ; phases are off LDA phaseOff+4,X LDA phaseOff+6,X RTS * --------------------------------------------------------- doCheck LDA dhpCmd ;Get the command number CMP #maxCmd ;Is the command allowable? BCS doChkBad ;Branch if not! LDA blockNum LDX blockNum+1 STX ibTrk ;Calculate block's track & sector BEQ doChkOK ;Branch if block # in range DEX ;else test further BNE doChkBad ;Bad range CMP #$18 ;Must be <$118 (280) BCC doChkOK doChkBad SEC ;Set carry for an error RTS doChkOK CLC RTS LD6EA DS 2,0 ;Not used * --------------------------------------------------------- * Variables for handling mirror devices * NB. Values of SmartPort unit #s: $00, $01-$7E * Status List - ref pg 122 IIGS Firmware spStatList EQU * genStatus DB 0 spDevTotBlks DB 0,0,0 ;# of blocks spUnits DS $F,0 ;table of SmartPort unit #s DB 0