NEW AUTO 3,1 .LIST OFF *-------------------------------------- * prodos universal boot loader. this is the second stage boot * for all apple manufactured apple ii disk drives. * it is located at block zero (0) of a prodos or sos formatted * disk(ette). if booted in apple /// native mode, the regular * sos boot will be attempted. *-------------------------------------- dcmd .EQ $42 disk command (=1 for read) unit .EQ $43 (16*slot)+(128*(drive-1)) buff .EQ $44 ram address blok .EQ $46 disk address dent .EQ $48 device call entry address idxl .EQ $4a pointer to low page of index block idxh .EQ $4c pointer to high page of index block idxp .EQ $4e index byte pointer iobuff .EQ $60 * the following are for disk ii only dbuf .EQ $26 slotz .EQ $2b oddbits .EQ $3c sector .EQ $3d BB.RetryCnt .EQ $40 BB.TargetTrk .EQ $41 BB.CurrentQTrack .EQ $50 BB.TargetQTrack .EQ $51 BB.HdrPtr .EQ $52 BB.Hdr .EQ $54 BB.HdrTrk .EQ $55 BB.HdrVol .EQ $56 BB.Hdr96 .EQ $57 nbuf1 .EQ $300 dnib .EQ $2d6 clrscrn .EQ $fc58 scrn .EQ $5b6 sosid .EQ $c00 entlen .EQ sosid+$23 kernel .EQ $2000 *-------------------------------------- .PH $800 xboot .DA #1 sec apple iii enters xboot 'ora $38' * bcs BB.AppleII branch if not apple iii native mode bcc * *-------------------------------------- *BB.AppleIII lda #$9f make apple iii boot using block 1 * pha the return address is $a000 * lda #$ff * pha * inc * tax ldx #0 * inc lda #1 (read block 1) * jmp $f479 *-------------------------------------- BB.AppleII stx unit save unit number cmp #$03 for disk ii php save result, it may be irrelevant txa find out if disk ii and #$70 strip drive # if any lsr lsr get slot address lsr lsr ora #$c0 sta dent+1 ldy #$ff look at last byte sty dent plp restore carry (if disk ii & sect 0&2 read) iny make y=0 lda (dent),y get device entry addr bne ndsk2 branch if not disk ii (16 sector) bcs isdsk2 branch if it is disk ii, but block 0 read lda #3 make rom read only sector 2 sta xboot to complete block 0 inc sector was = 1 lda dent+1 do rts to re-enter rom pha lda #$5b pha rts go read sector 2 into $900 *-------------------------------------- isdsk2 sta BB.HdrTrk A=0, make sure previous track =0 sta dent and dent points at beginning of slot ldy #$63 move code from card to ram mvboot lda (dent),y sta zzstart-$5e,y iny cpy #$eb have we moved enough? bne mvboot ldx #mods.cnt-1 now modify code to handle errors. modboot ldy mods,x lda chgs,x sta zzstart,y dex bpl modboot ldx #7 modboot2 lda endcode-1,x sta zzzend-1,x dex bne modboot2 lda #BB.Hdr sta BB.HdrPtr stx BB.HdrPtr+1 X=0 lda /d2io reset device entry sta dent+1 to point at disk ii routines. lda #d2io get low addr (must be <$80) *-------------------------------------- ndsk2 ldy #0 make sure y=0 again. cmp #$f9 bcs bterr1 branch if not bootable device. sta dent save low adr of device call entry. sty iobuff sty idxl sty idxh y=0 sty idxp sty blok+1 iny sty dcmd set read command. iny sty blok to read directory blocks lda #$c 2-5 at $c00 sta iobuff+1 sta idxl+1 rddir jsr goread call read block routine. bcs bterr2 give up on error. inc iobuff+1 inc iobuff+1 inc blok lda blok have all directory blocks been read? cmp #6 bcc rddir loop if not. lda sosid is it a prodos (sos) directory? ora sosid+1 bterr1 bne booterr branch if not. *-------------------------------------- lda #4 begin look-up with first entry past header. * bne nxdent1 branch always .HS 2C BIT ABS nxdent lda idxl nxdent1 clc adc entlen bump to next directory entry. tay save in y for now. bcc nxdent2 branch if not a page cross. inc idxl+1 lda idxl+1 check for new block. lsr if even then new block. bcs nxdent2 cmp #$a have all file names been compared? beq booterr branch if no pro.kernel. ldy #4 else, begin at block beginning. nxdent2 sty idxl ldy #0 lookpro lda (idxl),y look for matching name. cmp BB.ProDOS,y bne nxdent branch if no match. iny cpy #7 bne lookpro ldy #$10 get file type & index block addr. * lda (idxl),y * cmp #S.FI.T.SYS is it a system file? * bne booterr iny lda (idxl),y sta blok iny lda (idxl),y sta blok+1 lda #0 now set up to read kernel. sta idxl ldy #$1e read index block at $1e00 and sty idxl+1 kernel at $2000 sty iobuff+1 iny sty idxh+1 rdkernl jsr goread read index block. bterr2 bcs booterr inc iobuff+1 inc iobuff+1 ldy idxp get index pointer inc idxp bump for next time. lda (idxl),y sta blok lda (idxh),y high disk addr. sta blok+1 ora (idxl),y if both=0 then done. bne rdkernl branch if more to read. jmp kernel go execute kernel code. *-------------------------------------- booterr * jsr clrscrn clear video * ldy #BB.MSG.ERR.Len-1 *.1 lda BB.MSG.ERR,y * sta scrn,y * dey * bpl .1 jmp $ff69 *-------------------------------------- goread lda iobuff sta buff lda iobuff+1 sta buff+1 jmp (dent) *-------------------------------------- mods .DA #mod1,#mod2,#mod3,#mod4,#mod5,#mod6,#mod7,#mod8,#mod8+1,#mod9 mods.cnt .EQ *-mods chgs .DA #chg1,#chg2,#chg3,#chg4,#chg5,#chg6,#chg7,#$91,#BB.HdrPtr,#BB.HdrTrk endcode ldx slotz clc rts jmp BB.Seek *-------------------------------------- *BB.MSG.ERR .AS -"ERR" *BB.MSG.ERR.Len .EQ *-BB.MSG.ERR BB.ProDOS .DA #$26 $20 = storage type + 6 = "PRODOS" len .AS "PRODOS" *-------------------------------------- d2io lda blok figure out track & sector. and #7 strip track for now. cmp #4 and #3 php asl plp rol now we have the first sector of block. sta sector lda blok+1 get high block # lsr shift hi addr to carry. lda blok now figure track # ror lsr lsr sta BB.TargetTrk lda buff+1 sta dbuf+1 ldx slotz lda IO.D2.DrvOn,x jsr BB.Seek go read sector. inc dbuf+1 bump address inc sector inc sector and sector # bcs quitrd branch if error. jsr BB.Seek quitrd ldy IO.D2.DrvOff,x rts return error status in carry. *-------------------------------------- BB.Seek lda BB.HdrTrk get track we're on jsr BB.Trk2Qtrk sta BB.CurrentQTrack lda BB.TargetTrk jsr BB.Trk2Qtrk sta BB.TargetQTrack ldy #0 .1 lda BB.TargetQTrack sec sbc BB.CurrentQTrack beq .8 bcc .2 * Current < Target, must move in cmp #2 bcc .6 one QT remaining lda BB.CurrentQTrack and #$FE from QT1 or QT3 inc inc bra .4 * Current > Target, must move out .2 cmp #$FF beq .6 one QT remaining lda BB.CurrentQTrack bit #1 from QT1 or QT3 bne .3 dec .3 dec .4 sta BB.CurrentQTrack and #6 ora slotz tax pha tya beq .5 lda IO.D2.Ph0Off,y .5 lda IO.D2.Ph0On,x ply lda #164 jsr BB.Wait100usecA bra .1 * Last QTrack .6 lda BB.TargetQTrack and #6 ora slotz tax inc inc and #$F7 tay lda IO.D2.Ph0On,x lda IO.D2.Ph0On,y .7 phx jsr BB.Wait25600usec plx lda IO.D2.Ph0Off,x lda IO.D2.Ph0Off,y bra BB.Read .8 tya beq BB.Read tax bra .7 *-------------------------------------- BB.Wait25600usec lda #0 BB.Wait100usecA sec (6) JSR (2) .1 ldx #18 (2) .2 dex (2) delay 86 usec. bne .2 (2+) 2 + 5x16 + 2 + 2 * ldx slotz (3) * bit IO.D2.RData,x (4) Slow down ACC boards sbc #1 (2) bne .1 (2+) rts (6) *-------------------------------------- BB.Trk2Qtrk asl x2 sta .1+1 bit BB.HdrVol bpl .1 x4 lsr x3 .1 adc #$ff SELF MODIFIED BB.Trk2Qtrk.RTS rts *-------------------------------------- BB.Read ldx slotz ldy #$7f allow 127 mistakes. sty BB.RetryCnt php tryread plp fix stack. rdhead sec anticipate error. dec BB.RetryCnt if = 0 then give up! beq BB.Trk2Qtrk.RTS branch if can't fine/read sector. clc indicate reading header. rddata php carry set if reading sector. rd0 dey every time y=0 decrement find count. beq tryread *-------------------------------------- * from zzstart to zzend code is moved from rom and modified to match this code... *-------------------------------------- zzstart .EQ * rd1 lda IO.D2.RData,x read a byte from the state machine. bpl rd1 loop until ready. .DUMMY rd1a eor #$d5 mark 1? mod1 .EQ *-zzstart+1 bne rd0 branch if not. chg1 .EQ rd0-* rd2 lda IO.D2.RData,x bpl rd2 cmp #$aa mark 2? bne rd1a nop waste a little time. rd3 lda IO.D2.RData,x bpl rd3 cmp #$96 header mark 3? beq rdhd1 branch if it is. plp were we looking for data mark 3? mod2 .EQ *-zzstart+1 bcc rdhead branch if not. chg2 .EQ rdhead-* eor #$ad data mark 3? beq rddt1 go read data field if true... mod3 .EQ *-zzstart+1 rdhd0 bne rdhead otherwise, start over. chg3 .EQ rdhead-* rdhd1 ldy #3 read in trk,sect,&volume #. mod8 .EQ *-zzstart rdhd2 sta (BB.HdrPtr),y save last result in .. , BB.HdrTrk , BB.HdrVol , .. rdhd3 lda IO.D2.RData,x bpl rdhd3 rol sta oddbits save odd bits (7,5,3,1) rdhd4 lda IO.D2.RData,x bpl rdhd4 and oddbits combine even and odd to form value. dey bne rdhd2 read in next pair. plp cmp sector last byte formed is sector# mod4 .EQ *-zzstart+1 bne rdhead branch if target sector not found. chg4 .EQ rdhead-* mod9 .EQ *-zzstart+1 lda BB.HdrTrk previous result is track # cmp BB.TargetTrk is desired track found? mod5 .EQ *-zzstart+1 bne goseek re-seek if mismatch. chg5a .EQ * mod6 .EQ *-zzstart+1 bcs rddata branch if proper track always. chg6 .EQ rddata-* *-------------------------------------- rddt1 ldy #$56 read 2 bit groupings first. rddt1a sty oddbits rddt2 ldy IO.D2.RData,x bpl rddt2 eor dnib,y denibblize using table left from boot rom. ldy oddbits save in nbuf1 dey sta nbuf1,y bne rddt1a loop until all 86 groups are read. rddt3 sty oddbits now count up for 6-bit groups. rddt4 ldy IO.D2.RData,x bpl rddt4 eor dnib,y ldy oddbits save result to specified buffer. sta (dbuf),y iny bne rddt3 loop for 256 bytes. rdchk ldy IO.D2.RData,x now verify checksum... bpl rdchk eor dnib,y must be equal... mod7 .EQ *-zzstart+1 bne rdhd0 branch if error. chg7 .EQ rdhd0-* ldy #0 make y=0 nxttwo ldx #$56 now combine 2-bit group with 6 bit group twobit dex all done with this group? bmi nxttwo branch if so. lda (dbuf),y lsr nbuf1,x rol lsr nbuf1,x rol sta (dbuf),y iny bne twobit *-------------------------------------- zzzend ldx slotz clc indicate good read. rts chg5 .EQ *-chg5a goseek jmp BB.Seek .ED *-------------------------------------- .LIST ON BB.End .EQ * BB.Free .EQ $a00-* .BS BB.Free .LIST OFF .EP *-------------------------------------- MAN SAVE usr/src/lib/libblkdev.s.bb LOAD usr/src/lib/libblkdev.s ASM