1: MAJOR = 5 / major # from bdevsw[] 2: 3: / RA bootstrap. 4: / 5: / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev 6: / because the partition number now goes into bits 0-2. 7: / 8: / disk boot program to load and transfer to a unix entry. 9: / for use with 1 KB byte blocks, CLSIZE is 2. 10: / NDIRIN is the number of direct inode addresses (currently 4) 11: / 12: / Note: this is a complex boot, but then MSCP is complex!!!! 13: / 14: / assembled size must be <= 512 15: / a.out header must be removed from boot block! 16: 17: MSCPSIZE = 64. / One MSCP command packet is 64bytes long (need 2) 18: 19: RASEMAP = 140000 / RA controller owner semaphore 20: 21: RAERR = 100000 / error bit 22: RASTEP1 = 04000 / step1 has started 23: RAGO = 01 / start operation, after init 24: RASTCON = 4 / Setup controller info 25: RAONLIN = 11 / Put unit on line 26: RAREAD = 41 / Read command code 27: RAWRITE = 42 / Write command code 28: RAEND = 200 / End command code 29: 30: RACMDI = 4. / Command Interrupt 31: RARSPI = 6. / Response Interrupt 32: RARING = 8. / Ring base 33: RARSPL = 8. / Response Command low 34: RARSPH = 10. / Response Command high 35: RACMDL = 12. / Command to controller low 36: RACMDH = 14. / Command to controller high 37: RARSPS = 16. / Response packet length (location) 38: RARSPREF = 20. / Response reference number 39: RACMDS = 80. / Command packet length (location) 40: RACMDREF = 84. / Command reference number 41: RAUNIT = 88. / Command packet unit 42: RAOPCODE = 92. / Command opcode offset 43: RABYTECT = 96. / Transfer byte count 44: RABUFL = 100. / Buffer location (16 bit addressing only) 45: RABUFH = 102. / Buffer location high 6 bits 46: RALBNL = 112. / Logical block number low 47: RALBNH = 114. / Logical block number high 48: 49: / options: none. all options of reading an alternate name or echoing to 50: / the keyboard had to be removed to make room for the 51: / code which understands the new directory structure on disc 52: / also, this is the single largest boot around to begin with. 53: 54: / constants: 55: / 56: CLSIZE = 2. / physical disk blocks per logical block 57: CLSHFT = 1. / shift to multiply by CLSIZE 58: BSIZE = 512.*CLSIZE / logical block size 59: INOSIZ = 64. / size of inode in bytes 60: NDIRIN = 4. / number of direct inode addresses 61: ADDROFF = 12. / offset of first address in inode 62: INOPB = BSIZE\/INOSIZ / inodes per logical block 63: INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 64: PBSHFT = -4 / shift to divide by inodes per block 65: / 66: / The boot options and device are placed in the last SZFLAGS bytes 67: / at the end of core by the kernel for autobooting. 68: / 69: ENDCORE= 160000 / end of core, mem. management off 70: SZFLAGS= 6 / size of boot flags 71: BOOTOPTS= 2 / location of options, bytes below ENDCORE 72: BOOTDEV= 4 73: CHECKWORD= 6 74: 75: .. = ENDCORE-512.-SZFLAGS / save room for boot flags 76: 77: / entry is made by jsr pc,*$0 78: / so return can be rts pc 79: 80: / establish sp, copy 81: / program up to end of core. 82: 83: nop / These two lines must be present or DEC 84: br start / boot ROMs will refuse to run boot block! 85: start: 86: mov r0,unit / Save unit number passed by ROMs(and kernel) 87: mov r1,raip / save csr passed by ROMs (and kernel) 88: mov $..,sp 89: mov sp,r1 90: clr r0 91: 1: 92: mov (r0)+,(r1)+ 93: cmp r1,$end 94: blo 1b 95: jmp *$2f 96: 97: / On error, restart from here. 98: restart: 99: clr r0 100: / clear core to make things clean 101: 2: 102: clr (r0)+ 103: cmp r0,sp 104: blo 2b 105: / 106: / RA initialize controller 107: / 108: mov $RASTEP1,r0 109: mov raip,r1 110: clr (r1)+ / go through controller init seq. 111: mov $icons,r2 112: 1: 113: bit r0,(r1) 114: beq 1b 115: mov (r2)+,(r1) 116: asl r0 117: bpl 1b 118: mov $ra+RARSPREF,*$ra+RARSPL / set controller characteristics 119: mov $ra+RACMDREF,*$ra+RACMDL 120: mov $RASTCON,r0 121: jsr pc,racmd 122: mov unit,*$ra+RAUNIT / bring boot unit online 123: mov $RAONLIN,r0 124: jsr pc,racmd 125: 126: mov $bootnm, r1 127: mov $2,r0 / ROOTINO 128: jsr pc,iget 129: clr r2 / offset 130: again: 131: jsr pc,readdir 132: beq restart / error - restart 133: mov 4(r0),r4 / dp->d_namlen 134: cmp r4,$bootlen / if (bootlen == dp->d_namlen) 135: bne again / nope, go try next entry 136: mov r0,r3 137: add $6,r3 / r3 = dp->d_name 138: mov r1,r5 / r5 = filename 139: 9: 140: cmpb (r3)+,(r5)+ 141: bne again / no match - go read next entry 142: sob r4,9b 143: mov (r0),r0 / r0 = dp->d_ino 144: jsr pc,iget / fetch boot's inode 145: br loadfile / 'boot'- go read it 146: 147: / get the inode specified in r0 148: iget: 149: add $INOFF,r0 150: mov r0,r5 151: ash $PBSHFT,r0 152: bic $!7777,r0 153: mov r0,dno 154: clr r0 155: jsr pc,rblk 156: bic $!17,r5 157: mov $INOSIZ,r0 158: mul r0,r5 159: add $buf,r5 160: mov $inod,r4 161: 1: 162: movb (r5)+,(r4)+ 163: sob r0,1b 164: rts pc 165: 166: readdir: 167: bit $BSIZE-1,r2 168: bne 1f 169: jsr pc,rmblk / read mapped block (bno) 170: br err / end of file branch 171: clr r2 / start at beginning of buf 172: 1: 173: mov $buf,r0 174: add r2,r0 / dp = buf+offset 175: add buf+2(r2),r2 / dp += dp->d_reclen 176: tst (r0) / dp->d_ino == 0? 177: beq readdir / yes - go look at next 178: rts pc / return with r0 = &dp->d_ino 179: err: 180: clr r0 / return with 181: rts pc / dp = NULL 182: 183: loadfile: 184: clr bno / start at block 0 of inode in 'inod' 185: / read file into core until 186: / a mapping error, (no disk address) 187: clr r1 188: 1: 189: jsr pc,rmblk 190: br 1f 191: mov $buf,r2 192: 2: 193: mov (r2)+,(r1)+ 194: cmp r2,$buf+BSIZE 195: blo 2b 196: br 1b 197: / relocate core around 198: / assembler header 199: 1: 200: clr r0 201: cmp (r0),$407 202: bne 2f 203: 1: 204: mov 20(r0),(r0)+ 205: cmp r0,sp 206: blo 1b 207: / enter program and 208: / restart if return 209: 2: 210: mov ENDCORE-BOOTOPTS, r4 211: mov unit, r3 212: ash $3,r3 / unit # in bits 3-5, partition # is 0 213: bis $MAJOR\<8.,r3 214: mov ENDCORE-CHECKWORD, r2 215: mov raip,r1 216: jsr pc,*$0 217: jmp restart 218: 219: / read a mapped block 220: / offset in file is in bno. 221: / skip if success, no skip if fail 222: / the algorithm only handles a single 223: / indirect block. that means that 224: / files longer than NDIRIN+256 blocks (260kb) cannot 225: / be loaded. 226: rmblk: 227: add $2,(sp) 228: mov bno,r0 229: cmp r0,$NDIRIN 230: blt 1f 231: mov $NDIRIN,r0 232: 1: 233: ash $2,r0 234: mov addr+2(r0),dno 235: mov addr(r0),r0 236: bne 1f 237: tst dno 238: beq 2f 239: 1: 240: jsr pc,rblk 241: mov bno,r0 242: inc bno 243: sub $NDIRIN,r0 244: blt 1f 245: ash $2,r0 246: mov buf+2(r0),dno 247: mov buf(r0),r0 248: bne rblk 249: tst dno 250: bne rblk 251: 2: 252: sub $2,(sp) 253: 1: 254: rts pc 255: 256: read = 4 257: go = 1 258: 259: / 260: / RA MSCP read block routine. This is very primative, so don't expect 261: / too much from it. Note that MSCP requires large data communications 262: / space at end of ADDROFF for command area. 263: / N.B. This MUST preceed racmd - a "jsr/rts" sequence is saved by 264: / falling thru! 265: / 266: / dno -> 1k block # to load (low half) 267: / buf -> address of buffer to put block into 268: / BSIZE -> size of block to read 269: / 270: / Tim Tucker, Gould Electronics, August 23rd 1985 271: / 272: rblk: 273: mov dno,r0 274: asl r0 275: mov r0,*$ra+RALBNL / Put in disk block number 276: mov $BSIZE,*$ra+RABYTECT / Put in byte to transfer 277: mov $buf,*$ra+RABUFL / Put in disk buffer location 278: mov $RAREAD,r0 279: 280: / 281: / perform MSCP command -> response poll version 282: / 283: racmd: 284: movb r0,*$ra+RAOPCODE / fill in command type 285: mov $MSCPSIZE,*$ra+RARSPS / give controller struct sizes 286: mov $MSCPSIZE,*$ra+RACMDS 287: mov $RASEMAP,*$ra+RARSPH / set mscp semaphores 288: mov $RASEMAP,*$ra+RACMDH 289: mov *raip,r0 / tap controllers shoulder 290: mov $ra+RACMDI,r0 291: 1: 292: tst (r0) 293: beq 1b / Wait till command read 294: clr (r0)+ / Tell controller we saw it, ok. 295: 2: 296: tst (r0) 297: beq 2b / Wait till response written 298: clr (r0) / Tell controller we go it 299: rts pc 300: 301: icons: RAERR 302: ra+RARING 303: 0 304: RAGO 305: 306: bootnm: <boot\0\0> 307: bootlen = 4 / strlen(bootnm) 308: unit: 0 / unit number from ROMs 309: raip: 0 / csr address from ROMs 310: end: 311: 312: inod = ..-512.-BSIZE / room for inod, buf, stack 313: addr = inod+ADDROFF / first address in inod 314: buf = inod+INOSIZ 315: bno = buf+BSIZE 316: dno = bno+2 317: ra = dno + 2 / ra mscp communications area (BIG!)