ttl APM System ROM Bootstrap bin date equ $190287 Last revision date disk equ 0 Remote Filestore *disk equ '2284' Fujitsu 160 MB 14" *disk equ '2294' Fujitsu 330 MB 14" *disk equ 'Mini' Pair of 10MB 8" *disk equ '202E' Rodime 20MB 5.25" *disk equ '204E' Rodime 40MB 5.25" *disk equ '2243' Fujitsu 80MB 5.25" dcon equ 0 Remote filestore *dcon equ '7261' NEC chip with 14" Fuji drives *dcon equ 'WD1k' WD1000 controller for mini-filestore *dcon equ 'HFDC' Ambit-Pace controller for 5.25" drives memory equ $600000 6 megabytes to initialise ifeq disk favourite equ $1B else favourite equ $80 endc * (c) Rainer W Thonnes 1984, 1987 * Edinburgh University Computer Science Dept * All rights reserved * Initialises RS232 port (ACIA), ethernet board, * system bus mapping registers and main memory, * thereby determining how much of it there is. * Loads a supervisor into local RAM at $1000. * The name of the file containing this supervisor, * and the ethernet address of the file server from * which it is read have default values which may be * overridden by striking any key on the keyboard * before the memory initialisation has completed. * All exceptions are re-directed through a pseudo * vector table starting at address $1000 (local RAM). * There is an assembly-time option to include a driver * for a local disk. When this is included, specifying * $80 as the remote file server ether address causes * the local disk to be used instead for system booting. * When loading off disk, one of two "boot areas" on the * disk is used (determined by the position of the key * switch on the front of the machine). Each boot area * is 1024 512-byte blocks long and contains a short * directory of named files. * 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 (NB <= end of store - 32) * VDU (ACIA) definitions vdus equ $4000c1 vdud equ $4000c3 vinit equ 3 viof equ $11 vrrfbit equ 0 vtrebit equ 1 vbrkbit equ 4 cr equ 13 lf equ 10 nl equ 10 del equ 127 * 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 controller definitions ifeq dcon-'HFDC' diskcsr equ $ed0000 endc dcon='HFDC' ifeq dcon-'WD1k' 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 dcon='WD1k' ifeq dcon-'7261' 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 dcon='7261' 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 breaktest macro \* btst #vbrkbit,vdus bne abort endm * Wait for ether station * TX buffer to empty flush breaktest btst.b #etebit,eths beq flush rts * Read control character from ether station to D0 skipdc move.b ethd,d0 readcc breaktest 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 breaktest 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 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 dcon-'HFDC' * Ambit-Pace controller ifeq disk-'2243' cyls equ 754 heads equ 11 endc ifeq disk-'202E' cyls equ 640 heads equ 4 endc ifeq disk-'204E' cyls equ 640 heads equ 8 endc * We assume 16 512-byte sectors per track 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 abort 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 #(cyls-1)&255,diskcsr move.b #(cyls-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 divu #heads,d0 swap d0 move d0,d2 Head number clr.w d0 swap d0 divu #cyls,d0 clr.w d0 swap 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 dcon='HFDC' ifeq dcon-'WD1k' 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 abort 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 dcon='WD1k' ifeq dcon-'7261' 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 dcon='7261' * Blocks 0,1 of the disk contains a directory, the * layout of which is as follows: * 1024 bytes in all: * 1 longword checksum (such that the sum of the 128 * longwords is 0, using IBM byte sex) * 42 24-byte file records * 1 longword trailer which must be zero, as it is * deemed part of a truncated 43rd 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 *moved to more global code* 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 abort 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 abort 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.l 0,sp 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 ifne dcon ch1 equ dcon>>24 ch2 equ dcon>>16&255 ch3 equ dcon>>8&255 ch4 equ dcon&255 ch5 equ disk>>24 ch6 equ disk>>16&255 ch7 equ disk>>8&255 ch8 equ disk&255 ptext <' ',ch1,ch2,ch3,ch4> ifne dcon-disk ptext <' ',ch5,ch6,ch7,ch8> endc ptext <' disk'> endc 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 bootarea * 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 * Local disk bootarea equ * ifne disk bsr diskreset endc * fall into 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> move.b vdud,d0 nloop2 moveq #7,d2 nloop1 moveq #' ',d0 bsr psym move.w (sp)+,d0 bsr whex breaktest cmp.l #syssp,sp beq abort dbra d2,nloop1 moveq #nl,d0 bsr psym bra nloop2 gotnak ptext <'No ACK from station '> move.b rstat,d0 bsr bhex ptext <' port '> move.b rport,d0 bsr bhex moveq #nl,d0 bsr psym bra abort fserr bsr psym fse1 bsr readdc bsr psym cmp.b #nl,d0 beq.s fse2 bra fse1 fse2 bsr readcc bra abort abort ptext waitnobreak move.b vdud,d0 btst.b #vbrkbit,vdus bne waitnobreak move.b vdud,d0 wait btst.b #vrrfbit,vdus beq wait bra begin * Configuration parameters defaultfile dc.b 9,'fmac:nsys' org deffile dc.l defaultfile dc.l date<<8+favourite dc.l $800000 dc.l $800000+memory end