ttl M2294N Disk Bootstrap * Performs all functions of the standard bootstrap. * Loads selectively over the ether or off local disk. * Local disk is specified by asking to load from * a pseudo-ether-station with address $80. * Copyright 1984 Rainer W Thonnes * All rights reserved * bin * Configuration variables (in rom) gropelimit equ $ffc gropestart equ $ff8 version equ $ff4 defstat equ $ff7 deffile equ $ff0 * Communication variables memtop equ $3ffc membot equ $3ff8 freetop equ $3ff4 freebot equ $3ff0 ffile equ $3fac lstat equ $3fa8 lport equ $3fa9 rstat equ $3faa rport equ $3fab * Local store limits ram equ $1000 syssp equ $3f00 * VDU (ACIA) definitions vdus equ $4000c1 vdud equ $4000c3 vinit equ 3 viof equ $11 vrrfbit equ 0 vtrebit equ 1 cr equ 13 lf equ 10 nl equ 10 del equ 127 esc equ 27 cscreen equ 'v' * Ethernet definitions eths equ $7fffc * Status register ethd equ $7fffd * Data register ethc equ $7ffff * Control register einit equ $40 eiof equ 0 etebit equ 3 erdbit equ 2 ercbit equ 1 opn equ $80 cls equ $90 rdy equ $10 stx equ $20 dtx equ $30 ack equ $c0 nak equ $50 etx equ $0b esa equ $05 * Other definitions arbiter equ $f00003 map0 equ $080000 mapinc equ $100000 * Disk definitions org $70000 dsqbuf ds.b 4096 * Disq buffer on controller board dsqdbr ds.b 1 * 7261 data fifo dsqcsr ds.b 1 * 7261 control reg dsqbcr ds.w 1 * board control register * * START OF ROM CODE * org 0 dc.l syssp * Initial stack pointer dc.l begin * Initial program counter dc.l v2 * Interrupt and Exception vectors dc.l v3 dc.l v4 nolist dc.l v5 dc.l v6 dc.l v7 dc.l v8 dc.l v9 dc.l v10 dc.l v11 dc.l v12 dc.l v13 dc.l v14 dc.l v15 dc.l v16 dc.l v17 dc.l v18 dc.l v19 dc.l v20 dc.l v21 dc.l v22 dc.l v23 dc.l v24 dc.l v25 dc.l v26 dc.l v27 dc.l v28 dc.l v29 dc.l v30 dc.l v31 dc.l v32 dc.l v33 dc.l v34 dc.l v35 dc.l v36 dc.l v37 dc.l v38 dc.l v39 dc.l v40 dc.l v41 dc.l v42 dc.l v43 dc.l v44 dc.l v45 dc.l v46 dc.l v47 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 dc.l v23 list dc.l v23 dc.l v23 dc.l v23 * Miscellaneous entry points move.l deffile,a0 * 400: reload (default filename) bra reload * 404: reload (A0=filename) bra load * 408: load file (A0) to (A1)+ bra lhex * 40c: phex bra whex * 410: phex4 bra bhex * 414: phex2 bra nhex * 418: phex1 bra psym * 41c: printsymbol bra pstring * 420: printstring good macro v\1 move.l \1*4+ram,-(sp) rts endm bad macro v\1 bsr badvector dc.w \1*4 endm * Unacceptable vector numbers are re-cast as * address errors at the vector address badvector move.l a0,-(sp) * save A0 move.l 4(sp),a0 * @ vector address .w move.w #$dead,6(sp) * value for IR move.w (a0),4(sp) * vector address... move.l (sp),a0 * restore A0 move.w #0,2(sp) * ...zero-extended move.w #$1e,(sp) * function code SPRnot move.l ram+12,-(sp) * soft address error vector rts good <2> bus error good <3> address error good <4> illegal good <5> zero divide good <6> chk good <7> trapv good <8> privilege good <9> trace good <10> A emulator good <11> F emulator bad <12> reserved... bad 13 bad 14 bad 15 bad 16 bad 17 bad 18 bad 19 bad 20 bad 21 bad 22 bad <23> ...reserved good <24> spurious interrupt good <25> autointerrupt 1... good 26 good 27 good 28 good 29 good 30 good <31> ...autointerrupt 7 good <32> trap 0... good 33 good 34 good 35 good 36 good 37 good 38 good 39 good 40 good 41 good 42 good 43 good 44 good 45 good 46 good <47> ...trap 15 * Print character D0 on VDU * preserving registers and SR psym cmp.b #lf,d0 beq.s psy cmp.b #cr,d0 bne.s ps0 psy eor.b #cr!!lf,d0 bsr.s ps0 eor.b #cr!!lf,d0 bra ps0 ps0 btst.b #vtrebit,vdus beq ps0 move.b d0,vdud ps1 btst.b #vtrebit,vdus beq ps1 rts * Print D0 in hex lhex swap d0 bsr.s whex swap d0 whex rol.w #8,d0 bsr.s bhex rol.w #8,d0 bhex rol.b #4,d0 bsr.s nhex rol.b #4,d0 nhex move.l d1,-(sp) moveq #15,d1 and.b d0,d1 cmp.b #9,d1 ble.s nh1 addq.b #7,d1 nh1 add.b #'0',d1 exg d0,d1 bsr psym exg d0,d1 move.l (sp)+,d1 rts * Print string A0 on VDU * length-prefixed but 0-terminated pstring movem.l d0/d1/a0,-(sp) move.b (a0)+,d1 beq.s ps3 ps2 move.b (a0)+,d0 beq.s ps3 bsr psym subq.b #1,d1 bne ps2 ps3 movem.l (sp)+,d0/d1/a0 rts ptext macro \* move.l a0,-(sp) lea t\@,a0 bsr pstring bra.s e\@ t\@ dc.b 255,\1,0 ds.w 0 e\@ move.l (sp)+,a0 endm * Wait for ether station * TX buffer to empty flush btst.b #etebit,eths beq flush rts * Read control character from ether station to D0 skipdc move.b ethd,d0 readcc move.b eths,d0 btst #erdbit,d0 bne skipdc * Data: skip btst #ercbit,d0 beq readcc * No control: loop move.b ethc,d0 * Read control cmp.b #nak,d0 * Jump out if NAK beq gotnak rts * Read data character from ether station readdc move.b eths,d0 btst #erdbit,d0 beq readdc move.b ethd,d0 rts * Wait for RDY rdywait bsr readcc cmp.b #rdy,d0 bne rdywait bsr readdc rts * Send DTX, wait for RDY, send STX out bsr flush move.b #dtx,ethc out1 bsr flush move.b lport,ethd bsr rdywait move.b #stx,ethc bsr flush move.b lport,ethd bsr flush rts * Wait for DTX, send RDY, wait for STX in bsr readcc cmp.b #dtx,d0 bne in bsr readdc move.b #rdy,ethc bsr flush move.b lport,ethd stxwait bsr readcc cmp.b #stx,d0 bne stxwait bsr readdc rts * Open a local port to the remote filestore open bsr flush move.b #opn,ethc bsr out1 move.b rstat,ethd bsr flush move.b rport,ethd bsr flush move.b #etx,ethc bsr flush rts * Load file (A0) to (D0)+ * result: length in D0, endad in A0 load tst.b lport beq diskload movem.l d1-d2/a1,-(sp) move.l d0,a1 bsr out move.b #'Z',ethd * Send Readfile command, bsr flush move.b #'0',ethd bsr flush moveq #0,d1 move.b (a0)+,d1 subq #1,d1 l1 move.b (a0)+,d0 * the filename, move.b d0,ethd bsr flush dbra d1,l1 move.b #nl,ethd * newline, and ETX. bsr flush move.b #etx,ethc bsr in * Read response line packet bsr readdc cmp.b #'-',d0 beq fserr bsr readcc * skip to ETX moveq #0,d2 * Size counter l2 bsr in * Read data packet move #512,d1 l3 move.b eths,d0 * Wait for data or control btst #erdbit,d0 bne.s l4 * data -> btst #ercbit,d0 beq.s l3 * no control: loop move.b ethc,d0 * skip ETX tst d1 * was this a 512-byte block? beq l2 * yes: read another move.l d2,d0 * no: terminate movem.l (sp)+,d1-d2/a1 rts l4 move.b ethd,(a1)+ * read one character addq.l #1,d2 * count it subq #1,d1 * adjust intra-block count bra l3 * Disk handling routines parm macro \* move.b \1,dsqdbr endm * Wait for controller cwait move.b dsqcsr,d0 bmi cwait rts * Wait for SRQ dwait moveq #16,d0 and.b dsqcsr,d0 beq dwait move.b d0,dsqcsr bsr cwait moveq #7,d0 and.b dsqdbr,d0 rts * Controller initialisation data * Mode,DtlH+,DtlL,Etn,Esn,Gpl2,Mgpl1 cdata dc.b $40,$82,0,15,31,16,10 ds.w 0 * Initialise controller dinit move.w #$8000,dsqbcr * reset moveq #-1,d0 dbra d0,* move.w #0,dsqbcr * normal dbra d0,* moveq #6,d0 lea cdata,a0 cloop parm (a0)+ dbra d0,cloop move.b #$20,dsqcsr * specify dwait7 bsr dwait cmp #7,d0 bne dwait7 move.b #$50,dsqcsr * recal dwait8 bsr dwait tst d0 bne dwait8 rts * Read disq block D0>>9 to (A0+) dread movem.l d0-d4/a1,-(sp) lsr.l #5,d0 lsr.l #4,d0 divu #32,d0 swap d0 move d0,d4 *sector clr.w d0 swap d0 divu #16,d0 swap d0 move d0,d3 *track swap d0 move d0,d2 *cyll ror.w #8,d0 move d0,d1 *cylh move.b #2,dsqcsr * clear fifo parm d1 * CylH rol.w #8,d0 parm d2 * CylL move.b #$60,dsqcsr * Seek dwait0 bsr dwait tst d0 bne dwait0 parm d3 * Head parm #0 * Flag parm d1 * CylH parm d2 * CylL parm d3 * Track parm d4 * Sector parm #1 * Nsectors move.b #$b0,dsqcsr * Read move.w #$1000,dsqbcr * DMA in bsr cwait clr.l d0 move.w d0,dsqbcr move.b dsqcsr,d0 rol.w #8,d0 move.b dsqdbr,d0 and.w #$efff,d0 cmp.w #$4000,d0 bne.s derr lea dsqbuf,a1 move.w #255,d0 mloop move.w (a1)+,(a0)+ dbra d0,mloop movem.l (sp)+,d0-d4/a1 rts derr move.l a0,-(sp) move.w d0,-(sp) lea derrmess,a0 bsr pstring move.w (sp)+,d0 bsr whex moveq #' ',d0 bsr psym move d1,d0 bsr bhex move d2,d0 bsr bhex moveq #' ',d0 bsr psym move d3,d0 bsr bhex moveq #' ',d0 bsr psym move d4,d0 bsr bhex moveq #nl,d0 bsr psym bsr dinit move.l (sp)+,a0 movem.l (sp)+,d0-d4/a1 bra dread derrmess dc.b 255,'Disk error ',0 ds.w 0 diskload movem.l d0/a0,-(sp) bsr dinit lea -512(sp),sp move.l sp,a0 clr.l d0 bsr dread moveq #127,d0 clr.l d1 move.l sp,a0 dl1 add.l (a0)+,d1 dbra d0,dl1 bne diskerr tst.l -4(a0) bne diskerr clr.l d0 move.l 512+4(sp),a1 lea 8(sp),a0 dl2 move.l -4(a0),d1 beq diskerr bsr.s strc beq diskfound add.l #511,d1 and.l #-512,d1 add.l d1,d0 lea 24(a0),a0 bra dl2 diskfound move.l -4(a0),d1 lea 512(sp),sp move.l (sp),a0 move.l a0,4(sp) move.l d1,(sp) dl3 bsr dread add.l #512,d0 sub.l #512,d1 bgt dl3 movem.l (sp)+,d0/a0 add.l d0,a0 rts diskerr lea 512(sp),sp move.l 4(sp),a0 bsr pstring lea diskmnotfound,a0 bsr pstring bra retry diskmnotfound dc.b 255,' not in boot area',0 ds.w 0 * Compare (eq/neq) strings A0 and A1 * with case relaxation strc movem.l d0-d2/a0-a1,-(sp) clr.w d0 move.b (a0)+,d0 cmp.b (a1)+,d0 bne.s strc9 * different length => subq.b #1,d0 beq.s strc9 * both null => strc1 move.b (a0)+,d1 or.b #32,d1 move.b (a1)+,d2 or.b #32,d2 cmp.b d1,d2 dbne d0,strc1 strc9 movem.l (sp)+,d0-d2/a0-a1 rts * Read a character from ACIA to D0 rsym btst.b #vrrfbit,vdus beq rsym moveq #127,d0 and.b vdud,d0 cmp.b #del,d0 beq retry bra psym * to echo rts * Read a hex number from ACIA to D0 * Terminating char to D1 rhex moveq #0,d1 rh1 bsr rsym or.b #32,d0 sub.b #'0',d0 bmi.s rh3 cmp.b #9,d0 ble.s rh2 sub.b #7+32,d0 cmp.b #9,d0 ble.s rh3 cmp.b #15,d0 bgt.s rh3 rh2 lsl.l #4,d1 add.b d0,d1 bra rh1 rh3 add.b #'0',d0 exg d0,d1 rts * Read filename to string(31) somewhere * leaving A0 pointing at it rname move.l 0,a0 lea 1(a0),a1 clr.b (a0) moveq #31,d1 bra.s rn1 rn2 move.b d0,(a1)+ addq.b #1,(a0) rn1 bsr rsym cmp.b #' ',d0 dble d1,rn2 rts * * MAIN ENTRY POINT * begin reset move.b #vinit,vdus move.b #viof,vdus * Intercept any nasties move.l #nasty,d0 move.w #48-1,d1 lea ram,a0 nastyloop move.l d0,(a0)+ dbra d1,nastyloop * Initialise ether station and ACIA move.b #einit,eths move.b #eiof,eths ptext move.b version,d0 bsr bhex moveq #'/',d0 bsr psym move.b version+1,d0 bsr bhex moveq #'/',d0 bsr psym move.b version+2,d0 bsr bhex moveq #nl,d0 bsr psym * Set up mapping registers (transparently) move.l #$ff800000+map0,a0 move.l #$00800080,d0 moveq #7,d1 maploop move.l d0,0(a0,d0.l) add.l #$00100010,d0 dbra d1,maploop * Initialise local store move.l #$aaaa,d0 move.l #48*4+ram,a0 localloop move.w d0,(a0)+ cmp.l sp,a0 bne localloop * Initialise main store, break out by bus error move.l #breakout,ram+8 move.l gropestart,a0 move.l a0,membot move.l gropelimit,d1 sub.l a0,d1 lsr.l #2,d1 subq.l #1,d1 move.l #$aaaaaaaa,d0 mainloop move.l d0,(a0)+ dbra d1,mainloop addq.w #1,d1 subq.l #1,d1 bpl mainloop bra.s maindone breakout move.l #maindone,ram+8 move.b #0,arbiter * (Attempt to) clear error in arbiter maindone move.l a0,memtop sub.l gropestart,a0 move.l a0,d0 bsr lhex ptext <' bytes of main store',nl> * Establish local ether station address etc move.l deffile,ffile clr.w lstat clr.w rstat move.b defstat,rstat move.b #esa,ethc * Enquire station address bsr readcc bsr readdc move.b d0,lstat ptext <'Ether station '> move.b lstat,d0 bsr bhex ptext <' firmware version '> move.b #8,ethc * Set peek/poke address bsr flush move.b #4,ethd bsr flush move.b #0,ethd bsr flush move.b #13,ethc * Peek bsr readcc bsr readdc bsr bhex moveq #'/',d0 bsr psym move.b #13,ethc bsr readcc bsr readdc bsr bhex moveq #'/',d0 bsr psym move.b #13,ethc bsr readcc bsr readdc bsr bhex moveq #nl,d0 bsr psym * If a key has been pressed, ask which filestore * to talk to, and which files to load. Otherwise * use defaults btst.b #vrrfbit,vdus beq which ask move.b vdud,d0 ptext 'Filestore:' bsr rhex tst.w d0 beq.s ask1 * Keep default if 0 move.b d0,rstat ask1 ptext 'File:' bsr rname tst.b (a0) beq.s which * Keep default if null move.l a0,ffile * Which filestore? which clr.b lport * (Default: local disk) tst.b rstat bmi.s loadsys cmp.b #$70,rstat bne.s newfilestore * Old filestore (fixed port/client assignments) move.b #15,lport * Local port 15 moveq #-16,d0 * Remote port = local station - 16 add.b lstat,d0 move.b d0,rport bsr open bsr out * Send "boot" (amnesia) command move.b #12,ethd bsr flush move.b #etx,ethc bra loadsys * New filestore (chat to establish port number) newfilestore move.b #1,lport bsr open bsr out move.b #2,ethd bsr flush move.b #etx,ethc bsr in bsr readdc cmp.b #'0',d0 bmi fserr sub.w #'0',d0 move.b d0,rport bsr readcc bsr open bra loadsys * Now load the file loadsys move.l ffile,a0 reload move.l #reload,ram+$20 move.l 0,sp move.w #$2700,sr * Acquire privilege move.l membot,freebot move.l memtop,freetop move.l #ram,d0 bsr load * Enter Loaded System move.l membot,a0 movem.l (a0),d0-d7/a0-a6 move.l a6,usp move.l ram,sp move.l ram+4,-(sp) rts * Error reports nasty ptext <'Unexpected exception',nl> nloop2 moveq #7,d2 nloop1 moveq #' ',d0 bsr psym move.w (sp)+,d0 bsr whex cmp.l #syssp,sp beq retry dbra d2,nloop1 moveq #nl,d0 bsr psym bra nloop2 gotnak ptext <'No ACK from station '> move.w rstat,d0 bsr whex moveq #nl,d0 bsr psym bra retry fserr bsr psym fse1 bsr readdc bsr psym cmp.b #nl,d0 beq.s fse2 bra fse1 fse2 bsr readcc * Wait for keypress before retrying retry move.b vdud,d0 wait btst.b #vrrfbit,vdus beq wait move.l 0,sp move.l 4,a0 jmp (a0) * Configuration parameters defaultfile dc.b 9,'fmac:nsys' org deffile dc.l defaultfile dc.b $16,$05,$84 dc.b $80 dc.l $800000 dc.l $c00000 end