ttl APM System Primary Bootstrap * APM System Primary Bootstrap * (c) November 1984 All rights reserved * Rainer W Thonnes * Edinburgh University Computer Science Dept * Configurable to load off remote filestore or * one of three kinds of local disk. * Local disk is specified by asking to load from * a pseudo-ether-station with address $80. * Revised version with "virtual" block disk read routine, * which reads the specified block within one of two * boot areas, as determined by the key switch. bin list *disk equ 0 Remote Filestore *disk equ '2284' NEC 7261 with Fujitsu 160 MB *disk equ '2294' NEC 7261 with Fujitsu 330 MB disk equ 'mini' WD-1000 controller *disk equ 'pace' Ambit-Pace controller * 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 ssa equ $07 * Other definitions arbiter equ $f00003 map0 equ $080000 mapinc equ $100000 ifne disk * Disk definitions ifeq disk-'pace' diskcsr equ $ed0000 endc disk='pace' ifeq disk-'mini' org $7ffe0 diskcsr ds.w 1 disksdh ds.w 1 diskcylh ds.w 1 diskcyll ds.w 1 disksector ds.w 1 disksectors ds.w 1 diskerror ds.w 1 diskdata ds.w 1 endc disk='mini' ifeq (disk!'10')-'2294' org $70000 diskbuf ds.b 4096 * Disk buffer on controller board diskdbr ds.b 1 * 7261 data fifo diskcsr ds.b 1 * 7261 control reg diskbcr ds.w 1 * board control register endc disk#'mini' endc disk#0 * * 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 ifne disk beq diskload endc disk#0 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 ifne disk * Disk handling routines ifeq disk-'pace' * Ambit-Pace controller diska move.b diskcsr,d1 Wait for A0 cmp.b #$a0,d1 bne diska move.b d0,diskcsr Send command code dw1 move.b diskcsr,d1 Wait for A1 cmp.b #$a1,d1 bne dw1 move.b #$ff,diskcsr Send FF * and fall through to diskw movem.l d0-d7/a0-a6,-(sp) Wait >= 50 us movem.l (sp)+,d0-d7/a0-a6 movem.l d0-d7/a0-a6,-(sp) movem.l (sp)+,d0-d7/a0-a6 movem.l d0-d7/a0-a6,-(sp) movem.l (sp)+,d0-d7/a0-a6 rts diskb move.b #$ff,diskcsr Send FF bsr diskw Wait 50 us dw2 move.b diskcsr,d1 Wait for FF cmp.b #$ff,d1 bne dw2 move.b #$fe,diskcsr Send FE dw3 move.b diskcsr,d0 Wait for xx&80=0 bmi dw3 move.b diskcsr,d0 Get status move.b #0,diskcsr Send 00 moveq #$60,d1 Check for error and.b d0,d1 bne.s dw4 rts dw4 bsr bhex lea diskmerr,a0 bsr pstring bra retry diskmerr dc.b 255,' disk error',0 ds.w 0 diskreset move.b #0,diskcsr Send initial 00 move.b #$42,d0 Write buffer command bsr diska move.b #$ff,diskcsr move.b #0,diskcsr move.b #0,diskcsr move.b #0,diskcsr move.b #0,diskcsr move.b #0,diskcsr move.b #4,diskcsr move.b #(640-1)&255,diskcsr move.b #(640-1)>>8,diskcsr move.w #512-1-16+7,d0 dil move.b #0,diskcsr dbra d0,dil bsr diskb move.b #2,d0 Init command bsr diska bsr diskb rts diskread movem.l d0-d3,-(sp) move.b #$21,d0 Read disc command bsr diska move.l (sp),d0 Byte number moveq #9,d1 lsr.l d1,d0 Block number moveq #15,d1 and d0,d1 Sector number lsr.l #4,d0 moveq #3,d2 and d0,d2 Head number lsr.l #2,d0 Cylinder number move.b #0,diskcsr move.b d2,diskcsr move.b d0,diskcsr lsr #8,d0 move.b d0,diskcsr move.b d1,diskcsr move.b #0,diskcsr move.b #0,diskcsr move.b #0,diskcsr bsr diskb move.b #$41,d0 Read buffer command bsr diska move.w #511,d0 drl move.b diskcsr,(a0)+ dbra d0,drl bsr diskb movem.l (sp)+,d0-d3 rts endc disk='pace' ifeq disk-'mini' diskwait move.w diskcsr,d0 btst #7,d0 loop while busy bne diskwait move.w diskcsr,d0 inspect status btst #0,d0 bne diskw1 rts return if no error diskw1 lea diskmerr,a0 otherwise report error bsr pstring lea diskcsr,a0 movep.l 1(a0),d0 bsr lhex movep.l 9(a0),d0 bsr lhex move.l (sp),d0 bsr lhex bra retry diskmerr dc.b 255,'Disk error ',0 ds.w 0 * Initialise controller diskreset move.w #$20,diskerror (precomp) clr.w d7 move.w d7,disksdh drive 0 move.w #$13,diskcsr restore bsr diskwait move.w d7,diskcylh move.w d7,diskcyll move.w #$70,diskcsr seek bsr diskwait move.w #8,disksdh drive 1 move.w #$13,diskcsr bsr diskwait move.w d7,diskcylh move.w d7,diskcyll move.w #$70,diskcsr bsr diskwait rts * Read 512-byte-block D0>>9 to (A0)+ diskread movem.l d0-d3,-(sp) moveq #9,d1 lsr.l d1,d0 and.l #$3fff,d0 moveq #15,d1 and d0,d1 add d1,d1 sector lsr #4,d0 moveq #3,d2 and d0,d2 track lsr #2,d0 clr.l d3 move.b d0,d3 cylinder lsr #5,d0 and #8,d0 or d0,d2 sdh move.w d1,disksector move.w d2,disksdh move.w #0,diskcylh move.w d3,diskcyll move.w #$20,diskcsr bsr diskwait move.w #255,d0 diskr1 move.b diskdata+1,(a0)+ dbra d0,diskr1 add.w #1,disksector move.w #$20,diskcsr bsr diskwait move.w #255,d0 diskr2 move.b diskdata+1,(a0)+ dbra d0,diskr2 movem.l (sp)+,d0-d3 rts endc disk='mini' ifeq (disk!'10')-'2294' ifeq disk-'2284' * 10 tracks per cylinder tracks equ 10 endc disk='2284' ifeq disk-'2294' tracks equ 16 endc disk='2294' parm macro \* move.b \1,diskdbr endm * Wait for controller cwait move.b diskcsr,d0 bmi cwait * busy -> cmp.b diskcsr,d0 bne cwait * unstable -> rts * Wait for SRQ dwait moveq #16,d0 and.b diskcsr,d0 beq dwait move.b d0,diskcsr bsr cwait moveq #7,d0 and.b diskdbr,d0 rts * Controller initialisation data * Mode,DtlH+,DtlL,Etn,Esn,Gpl2,Mgpl1 cdata dc.b $40,$82,0,tracks-1,31,16,10 ds.w 0 * Initialise controller diskreset move.w #$8000,diskbcr moveq #-1,d0 dbra d0,* move.w #0,diskbcr * normal dbra d0,* moveq #6,d0 lea cdata,a0 cloop parm (a0)+ dbra d0,cloop move.b #$20,diskcsr * specify dwait7 bsr dwait cmp #7,d0 bne dwait7 move.b #$50,diskcsr * recal dwait8 bsr dwait tst d0 bne dwait8 rts * Read 512-byte-block D0>>9 to (A0+) diskread 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 #tracks,d0 swap d0 move d0,d3 *track swap d0 move d0,d2 *cyll ror.w #8,d0 move d0,d1 *cylh move.b #2,diskcsr * clear fifo parm d1 * CylH rol.w #8,d0 parm d2 * CylL move.b #$60,diskcsr * 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,diskcsr * Read move.w #$1000,diskbcr * DMA in bsr cwait * clr.l d0 * move.w d0,diskbcr * move.b diskcsr,d0 move.w #0,diskbcr rol.w #8,d0 move.b diskdbr,d0 and.w #$efff,d0 cmp.w #$4000,d0 bne.s derr lea diskbuf,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 diskreset move.l (sp)+,a0 movem.l (sp)+,d0-d4/a1 bra diskread derrmess dc.b 255,'Disk error ',0 ds.w 0 endc disk#'mini' * Block 0 of the disk contains a directory, the * layout of which is as follows: * 512 bytes in all: * 1 longword checksum (such that the sum of the 128 * longwords is 0, using IBM byte sex) * 21 24-byte file records * 1 longword trailer which must be zero, as it is * deemed part of a truncated 22nd file record. * Each file record looks like this: * 1-longword length of file (number of bytes) * 1-byte length of filename * up to 19 bytes filename * The byte-position on disk of file N is the position of * file N-1 plus the size (rounded up to the next 512 * bytes) of file N-1. The position of the first file, * which is the directory block, is 0, and hence the * directory will contain an entry for itself. * A file record beginning with a 0 longword (i.e. * describing a null file) terminates the list of file * records in the directory. * Routine to load (i.e. read) a file with name A0 * into memory at location D0. * Result: D0=length, A0=address of next free byte diskload movem.l d0/a0,-(sp) bsr diskreset lea -1024(sp),sp allocate space into which to read directory move.l sp,a0 clr.l d0 bsr vdiskread read first directory block move.l #512,d0 bsr vdiskread read second directory block move.w #255,d0 compute checksum clr.l d1 move.l sp,a0 dl1 add.l (a0)+,d1 dbra d0,dl1 bne cserr checksum fails -> * tst.l -4(a0) * bne diskerr last longword non-zero -> igncse clr.l d0 byte offset in disk of start of next file move.l 1024+4(sp),a1 address of filename to be searched for lea 8(sp),a0 address of first filename in directory dl2 move.l -4(a0),d1 length of first (next) file beq diskerr end reached (file not found) -> bsr strc compare filenames beq diskfound file found -> add.l #511,d1 round length to multiple of block size and.l #-512,d1 add.l d1,d0 note disk byte address of next file lea 24(a0),a0 onto next slot in directory bra dl2 diskfound move.l -4(a0),d1 note size (in bytes) of file lea 1024(sp),sp deallocate directory block space move.l (sp),a0 memory address for file move.l a0,4(sp) move.l d1,(sp) save size for result dl3 bsr vdiskread read first (next) block of file add.l #512,d0 increment disk address sub.l #512,d1 decrement bytes-to-go bgt dl3 movem.l (sp)+,d0/a0 restore size and start address add.l d0,a0 compute end address rts diskerr lea 1024(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 diskmcserr dc.b 255,'Directory checksum error',cr,lf,0 ds.w 0 cserr lea diskmcserr,a0 bsr pstring bra igncse keyswitch equ $400031 vdiskread move.l d0,-(sp) moveq #1,d0 and.b keyswitch,d0 lsl.w #3,d0 swap d0 <<19 add.l (sp),d0 bsr diskread move.l (sp)+,d0 rts * Compare (eq/neq) strings A0 and A1 * with simplified 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 endc disk#0 * 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 ifeq disk-'2284' ptext <' (M2284N)'> endc disk='2284' ifeq disk-'2294' ptext <' (M2294N)'> endc disk='2294' ifeq disk-'pace' ptext <' (Ambit)'> endc disk='pace' ifeq disk-'mini' ptext <' (Mini)'> endc disk='mini' * ifeq disk * ptext <' (Remote)'> * endc disk=0 ptext <' Version '> 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 ssaloop bsr readcc cmp.b #ssa,d0 bne ssaloop 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 14,'mouse:boot.mob' org deffile dc.l defaultfile dc.b $23,$1,$86 * Version ifne disk dc.b $80 else dc.b $15 endc dc.l $800000 dc.l $e00000 end