* * Unix bootstrap loader -- 40-megabyte disc * * N.B. Must be assembled with SQUEZ to make it relocatable * bootaddr equ y'20000' must be >top of loaded program * i.addr equ x'78' 10 console input address i.cmd2 equ x'79' a3 console init cmd d.addr equ x'7a' c7 disc address * x'7b' unused c.addr equ x'7c' b6 disc controller s.addr equ x'7d' f0 selch address os.ext equ x'7e' 0000 OS file extension (for LSU) or console def'n * LARGE equ 19 large file bit in inode flags MAGIC equ x'107' a.out magic number EOL equ x'0d' carriage return PROMPT equ c'?' PAUSE equ c'-' flag to go into wait state after loading WAITPSW equ x'8000' wait-state psw * ret equ 15 ret1 equ 14 work equ 13 offset equ 12 count equ 11 bno equ 10 inode equ 09 char equ 08 cyl equ 07 head equ 06 dev equ 05 disc equ 04 cntrl equ 03 selch equ 02 core equ 01 * low equ * loaded into low core by LSU org low+x'60' b start(0,0) org low+x'80' * start equ * li 1,bootaddr relocation address lis 2,0 start at low core rloop lm 8,0(2) move 8 words stm 8,0(1,2) ahi 2,8*adc increment core address cli 2,high all moved? bl rloop no - continue b go-low(1) execute relocated code * go equ * lh work,os.ext OS file extension 0? bz lsu yes - assume loaded by LSU sth work,i.addr no - OS extension is really console def lsu equ * lm 14,i.addr save lowcore data stm 14,lowsave lb selch,s.addr lb cntrl,c.addr lb disc,d.addr la work,buf set up disc read buffer addresses st work,bufs ahi work,511 st work,bufe lis char,0 lhi count,names-ind+12 zeroout st char,ind(count) clear indirect blocks & filename sis count,4 bnm zeroout * lhi char,PROMPT ask user for filename bal ret1,putc lis count,0 nxtchr1 bal ret,getc read a character from console bz lookup returns 0 at end of line chi char,PAUSE flag to pause after loading? bne nopause no - continue li work,WAITPSW set wait bit st work,ps.start in start psw b nxtchr1 nopause equ * stb char,names(count) set in filename ais count,1 b nxtchr1 note no test for overflow * lookup equ * lis inode,1 read inode for root directory bal ret,iget nxtdblk bal ret1,rblk read directory block bz start start over if end of directory la count,buf cmpnext lis offset,12 lh inode,0(count) directory entry used? bz nextent no - look at next nxtchr2 lh char,2(offset,count) compare names clh char,names(offset) bne nextent not equal - look at next entry sis offset,2 bnm nxtchr2 b gotinod right name - go read it in nextent ahi count,16 next directory entry la work,buf+512 cr count,work bl cmpnext b nxtdblk * gotinod equ * bal ret,iget read inode for file lis core,0 nxtsblk st core,bufs read block into core ai core,511 st core,bufe bal ret1,rblk bz reloc ais core,1 b nxtsblk * reloc equ * l char,x'0' check first word clhi char,MAGIC a.out file? bne finish no - done lis count,0 yes - relocate to get rid of header mvsys l char,32(count) st char,0(count) ais count,4 cr count,core bl mvsys finish equ * lm 14,lowsave restore lowcore data stm 14,i.addr lpsw ps.start go to start address in loaded file * * Read inode and indirect blocks * iget equ * ahi inode,15 find block containing inode lr cyl,inode srls cyl,3 (inode+15)/8 bal ret1,rblka read block ni inode,7 find offset of inode in block slls inode,6 (inode+15) mod 8 stm 6,regsave save work regs lm 6,buf(inode) copy inode info from buffer stm 6,inod (up to addr[7]) lm 6,regsave restore work regs * la bno,addr small file: block addresses in addr li work,LARGE test for large file tbt work,inod bzr ret la core,ind large file - read indirect blocks nxtind bal ret1,rblk bz finind li count,508 move indirect block mvind l char,buf(count) st char,0(core,count) sis count,4 bnm mvind ahi core,512 b nxtind finind la bno,ind large file: block addresses in ind br ret * * Console read and write routines * getc equ * lb dev,i.addr console input address oc dev,i.cmd2 initialize oc dev,t.read start terminal read getwait ssr dev,work wait for busy == 0 bc getwait rdr dev,char read char from terminal buffer nhi char,x'7f' clear parity bit clhi char,c'A' check for alpha bl notran clhi char,c'Z' bp notran ohi char,x'20' alpha - translate to lowercase notran bal ret1,putc echo character back clhi char,EOL end of line? bner ret no - return (cond. code nonzero) lr ret1,ret lis char,x'0a' echo extra linefeed * putc equ * lb dev,i.addr console output address ais dev,1 oc dev,t.write start terminal writing wdr dev,char write the character putwait ssr dev,work wait for busy == 0 bc putwait br ret1 * * Read a disc block * rblk equ * l cyl,0(bno) next block number bzr ret1 ais bno,4 rblka equ * xar head,head slls cyl,1 sector on disc d head,f20 divide by sectors per track stb head,sector rem is sectorin track xar head,head quotient is track on disc d head,f20 divide by tracks per disc bal 0,cidle * whr disc,cyl oc disc,d.setcyl bal 0,cidle oc disc,d.rstatn bal 0,cidle oc disc,d.rsthd bal 0,cidle whr disc,head oc disc,d.sethd bal 0,cidle oc disc,d.seek * bal 0,cidle wdisc equ * ssr disc,work btc d.nready,wdisc * oc selch,s.stop stop selch wd selch,bufs+1 start address to selch wh selch,bufs+2 wd selch,bufe+1 end address to selch wh selch,bufe+2 wd cntrl,sector sector to controller slls head,10 or cyl,head whr cntrl,cyl oc cntrl,c.read start controller reading oc selch,s.read start selch reading wselch2 ssr selch,work sense selch status btc s.busy,wselch2 wait for busy == 0 oc selch,s.stop stop selch bal 0,cidle br ret1 (cond code must be nonzero) * * wait for controller idle * cidle equ * ssr cntrl,work bfc c.idle,cidle br 0 * s.busy equ 8 selector channel busy c.idle equ 2 disc controller idle c.err equ 5 disc controller error d.nready equ 8 disc not-ready-to-seek-read-or-write d.err equ 7 disc error * align 8 ps.start dc 0,y'60' psw to start loaded program f20 dc f'20' sectors per track d.seek db x'c2' disarm+seek c.read db x'01' read s.stop db x'48' stop + extended address read s.read db x'70' extended address read + read + go t.write db x'a3' t.read db x'a1' d.sethd db x'20' d.setcyl db x'10' d.rstatn db x'08' d.rsthd db x'04' sector db 0 align adc high equ * highest location for relocate * bufs equ * bufe equ bufs+4 lowsave equ bufe+4 regsave equ 8+lowsave buf equ 10*adc+regsave inod equ buf+512 mode equ inod addr equ 3*adc+inod ind equ 11*adc+inod names equ 8*512+ind end