1 1.13 isaki | $NetBSD: boot.S,v 1.13 2020/08/16 06:43:43 isaki Exp $ 2 1.7 isaki 3 1.7 isaki | 4 1.7 isaki | (1) IPL (or previous stage loader) loads first 1KB of this primary 5 1.7 isaki | bootloader to (*). (*) is 0x2000 (from FD) or 0x2400 (from SASI/SCSI). 6 1.7 isaki | 7 1.7 isaki | (2) The first 1KB loads full primary bootloader (including first 1KB) from 8 1.9 isaki | the boot partition to 0x3000. And jump to there. 9 1.7 isaki | 10 1.7 isaki | (3) The full primary bootloader loads the secondary bootloader known as 11 1.7 isaki | /boot from its filesystem to 0x6000. And jump to there. 12 1.7 isaki | 13 1.7 isaki | (1) -> (2) -> (3) 14 1.7 isaki | +------------+ +------------+ +------------+ 0x000000 15 1.7 isaki | : : : : : : 16 1.7 isaki | +------------+ +------------+ +------------+ (*) 17 1.7 isaki | | first 1KB | | first 1KB | | first 1KB | 18 1.7 isaki | +------------+ +------------+ +------------+ (*)+0x400 19 1.7 isaki | : : : : : : 20 1.9 isaki | : : +------------+ +------------+ 0x003000 21 1.9 isaki | : : |full primary| |full primary| 22 1.9 isaki | : : |boot loader | |boot loader | 23 1.11 isaki | : : |(text+data) | |(text+data) | 24 1.11 isaki | : : +------------+ +------------+ 0x005000 25 1.13 isaki | : : |(startregs) | |(startregs) | 26 1.11 isaki | : : |(bss) | |(bss) | 27 1.11 isaki | : : +------------+ +------------+ 0x006000 28 1.7 isaki | : : : : | /boot | 29 1.7 isaki | : : : : +------------+ 30 1.7 isaki | : : : : : : 31 1.7 isaki | ~ ~ ~ ~ ~ ~ 32 1.7 isaki | : : : :<-SP : :<-SP 33 1.9 isaki | + - - - - - -+ + - - - - - -+ + - - - - - -+ 0x100000 34 1.12 isaki | : : :(heap) : :(heap) : 35 1.7 isaki | : : : : : : 36 1.7 isaki | 37 1.13 isaki | The program code before first_kbyte 38 1.13 isaki | - must not access any text/data labels after first_kbyte 39 1.13 isaki | (because it may not be loaded yet). 40 1.13 isaki | - must access any labels before first_kbyte by PC relative addressing 41 1.13 isaki | (because this loader is assembled as starting from 0x3000 but is loaded 42 1.13 isaki | at 0x2000 or 0x2400). 43 1.13 isaki | - must use RELOC() macro to access bss section (and first_kbyte as a jump 44 1.13 isaki | destination address). 45 1.13 isaki | 46 1.13 isaki | The program code after first_kbyte can access any labels in all sections 47 1.13 isaki | directly. 48 1.1 minoura 49 1.1 minoura #include <machine/asm.h> 50 1.1 minoura #include "iocscall.h" 51 1.1 minoura 52 1.13 isaki #define RELOC(var) %a5@(((var)-top):W) 53 1.1 minoura 54 1.13 isaki #define BOOT_ERROR(s) jbsr boot_error; .asciz s; .even 55 1.1 minoura 56 1.13 isaki #define minN (0) 57 1.13 isaki #define minC (1) 58 1.13 isaki #define minH (2) 59 1.13 isaki #define minR (3) 60 1.13 isaki #define maxN (4) 61 1.13 isaki #define maxC (5) 62 1.13 isaki #define maxH (6) 63 1.13 isaki #define maxR (7) 64 1.13 isaki 65 1.13 isaki .globl _C_LABEL(bootmain) 66 1.13 isaki .globl _C_LABEL(startregs) 67 1.13 isaki .text 68 1.1 minoura 69 1.1 minoura ASENTRY_NOPROFILE(start) 70 1.1 minoura ASENTRY_NOPROFILE(top) 71 1.13 isaki bras entry 72 1.1 minoura .ascii "SHARP/" 73 1.1 minoura .ascii "X680x0" 74 1.1 minoura .word 0x8199,0x94e6,0x82ea,0x82bd 75 1.1 minoura .word 0x8e9e,0x82c9,0x82cd,0x8cbb 76 1.1 minoura .word 0x8ec0,0x93a6,0x94f0,0x8149 77 1.13 isaki msg_progname: 78 1.13 isaki | This will be printed on boot_error. And it also roles 79 1.13 isaki | a signature in binary dump. 80 1.13 isaki | Max length of PROG(without \0) is 14 ("fdboot_ustarfs"). 81 1.13 isaki .ascii "\r\n\n" | 3 82 1.13 isaki .ascii PROG | 14 83 1.13 isaki .asciz ": " | 2+1 84 1.13 isaki .org msg_progname + 20 85 1.13 isaki entry: 86 1.13 isaki jbra disklabel_end 87 1.13 isaki 88 1.13 isaki | Disklabel must be placed at 0x40 and the size is 404 bytes. 89 1.13 isaki | (See LABELOFFSET in <machine/disklabel.h>) 90 1.5 isaki .org 0x40 91 1.1 minoura disklabel: 92 1.1 minoura .space 404 93 1.13 isaki disklabel_end: 94 1.13 isaki | At first save all initial registers for observing traces 95 1.13 isaki | of the IPL (or the previous bootloader). At this point 96 1.13 isaki | we cannot use RELOC() yet so that use absolute addressing. 97 1.13 isaki | To prevent startregs from being cleared by subsequent bss 98 1.13 isaki | initialization, we place it out of bss area. 99 1.13 isaki moveml %d0-%d7/%a0-%a7,startregs:W 100 1.13 isaki 101 1.13 isaki | Initialize the screen. Some IPL (060turbo ROM or genuine 102 1.13 isaki | boot selector) don't initialize the screen. It should be 103 1.13 isaki | done as early as possible. 104 1.13 isaki moveql #0x10,%d1 105 1.13 isaki IOCS(__CRTMOD) 106 1.1 minoura 107 1.13 isaki | Set system stack 108 1.13 isaki swap %d1 | %d1 = 0x0010_0000 109 1.13 isaki moveal %d1,%sp 110 1.13 isaki 111 1.13 isaki | Set base pointer. Now we can use RELOC() macro. 112 1.13 isaki leal TEXTADDR:W,%a5 113 1.13 isaki 114 1.13 isaki | Initialize bss. 115 1.13 isaki | This code limits bss less than 64KB but it's no matter. 116 1.13 isaki | The bss cannot grow more than 4KB. See xxboot.ldscript. 117 1.13 isaki leal RELOC(__bss_start),%a1 118 1.13 isaki movew #_end - 1,%d0 | bss end 119 1.13 isaki 120 1.13 isaki subw %a1,%d0 | don't change this op!! 121 1.13 isaki clrbss: | see chkmpu below 122 1.13 isaki clrb %a1@+ 123 1.1 minoura dbra %d0,clrbss 124 1.1 minoura 125 1.13 isaki | If it boots from SCSI, %d4 has SCSI ID. 126 1.13 isaki movel %d4,RELOC(SCSI_ID) 127 1.1 minoura 128 1.13 isaki chkmpu: 129 1.13 isaki | Check MPU beforehand since we want to use 68020 instructions. 130 1.13 isaki | Here the above "subw %a1,%d0" = 0x9049 and %d0.w = -1 at this 131 1.13 isaki | point, so that subsequent moveb loads 132 1.13 isaki | 0x49 if MPU <= 010 (clrbss + %d0.w) 133 1.13 isaki | 0x90 if MPU >= 020 (clrbss + %d0.w*2). 134 1.13 isaki | This is a MOVE op, not a TST op because TST with pc-relative 135 1.13 isaki | is not available on 000/010. 136 1.13 isaki moveb %pc@(clrbss-chkmpu-2:B,%d0:W:2),%d0 137 1.13 isaki jmi mpuok 138 1.13 isaki BOOT_ERROR("MPU 68000?"); 139 1.13 isaki mpuok: 140 1.13 isaki | 141 1.13 isaki | Check where did I boot from. 142 1.13 isaki | 143 1.13 isaki IOCS(__BOOTINF) 144 1.13 isaki movel %d0,RELOC(BOOT_INFO) | save whole result 145 1.1 minoura 146 1.13 isaki | %d0 = 0xHHWWWWWW 147 1.1 minoura | 148 1.13 isaki | HH: how did I boot (powersw or alarm etc) 149 1.13 isaki | WWWWWW: where did I boot from 150 1.13 isaki | 0x80...0x8f SASI 151 1.13 isaki | 0x90...0x93 Floppy 152 1.13 isaki | 0xed0000...0xed3ffe SRAM 153 1.13 isaki | others ROM (maybe SCSI) 154 1.13 isaki 155 1.13 isaki bfextu %d0{#8:#8},%d1 156 1.13 isaki jne boot_rom_ram | ROM or SRAM 157 1.13 isaki | FALLTHROUGH | SASI or Floppy 158 1.13 isaki 159 1.13 isaki boot_sasi_floppy: 160 1.13 isaki | Floppy or SASI 161 1.13 isaki cmpiw #0x90,%d0 162 1.13 isaki jlt boot_dev_not_supp | SASI 163 1.13 isaki 164 1.13 isaki | 165 1.13 isaki | Boot from floppy 166 1.13 isaki | 167 1.13 isaki boot_floppy: 168 1.13 isaki | Make PDA+MODE 169 1.13 isaki lslw #8,%d0 | %d0=$00009X00 (X is unit#) 170 1.13 isaki moveql #0x70,%d1 171 1.13 isaki orw %d0,%d1 | %d1=$00009X70 = (PDA<<8)+MODE 172 1.13 isaki movel %d1,RELOC(FDMODE) 173 1.13 isaki check_fd_format: 174 1.13 isaki | Check fd format. 175 1.13 isaki | Obtain min & max sector # of track(cylinder) 0. 176 1.13 isaki | On x68k, we can consider only double-sided floppy. 177 1.13 isaki moveql #0,%d2 178 1.13 isaki init_loop: 179 1.13 isaki | On 1st time, clear %d3-%d5 with zero. 180 1.13 isaki | On 2nd time, initialize %d3-%d5 with first %d2. 181 1.13 isaki movel %d2,%d3 | %d3: initial NCHR 182 1.13 isaki movel %d2,%d4 | %d4: minimum NCHR 183 1.13 isaki movel %d2,%d5 | %d5: maximum NCHR 184 1.13 isaki loop: 185 1.13 isaki | B_READID with MSB of %d2 set obtains detected CHRN to %d2. 186 1.13 isaki moveql #1,%d2 | %d2 = 0x00000001 187 1.13 isaki rorl #1,%d2 | %d2 = 0x80000000 188 1.13 isaki IOCS(__B_READID) 189 1.13 isaki | %d2 = 0xCCHHRRNN 190 1.13 isaki rorl #8,%d2 | %d2 = 0xNNCCHHRR 191 1.13 isaki 192 1.13 isaki | On 1st time, goto init_loop with %d2 (%d2 is not zero). 193 1.13 isaki | On 2nd time, fall through because %d3 is not zero. 194 1.13 isaki tstl %d3 195 1.13 isaki jeq init_loop 196 1.13 isaki 197 1.13 isaki cmpl %d4,%d2 | if (%d2 < %d4) 198 1.13 isaki jge 1f | 199 1.13 isaki movel %d2,%d4 | min = %d2 200 1.13 isaki 1: 201 1.13 isaki cmpl %d5,%d2 | if (%d2 > %d5) 202 1.13 isaki jle 1f | 203 1.13 isaki movel %d2,%d5 | max = %d2 204 1.13 isaki 1: 205 1.13 isaki cmpl %d3,%d2 | if (%d2 == %d3) break 206 1.13 isaki jne loop 207 1.13 isaki 208 1.13 isaki | Assume 2HD 209 1.13 isaki oriw #0x0100,%d5 | FDSEC.maxsec.H = 1 210 1.13 isaki moveml %d4-%d5,RELOC(FDSEC) | Store 211 1.13 isaki | end of check_fd_format 212 1.13 isaki 213 1.13 isaki | read 8KB myself from floppy 214 1.13 isaki | %d1: (PDA<<8)+MODE already 215 1.13 isaki movel %d4,%d2 | %d2: read pos = first sector 216 1.13 isaki moveql #0x20,%d3 | %d3: read bytes = (0x20 << 8) 217 1.13 isaki lsll #8,%d3 | = 0x2000 = 8192 218 1.13 isaki leal %a5@,%a1 | %a1: dest buffer 219 1.13 isaki IOCS(__B_READ) 220 1.1 minoura 221 1.13 isaki | Jump to full parimary loader 222 1.13 isaki jmp RELOC(first_kbyte) 223 1.13 isaki 224 1.13 isaki boot_rom_ram: 225 1.13 isaki | ROM(SCSI) or SRAM 226 1.13 isaki cmpib #0xed,%d1 227 1.13 isaki jeq boot_dev_not_supp | SRAM 228 1.1 minoura 229 1.1 minoura | 230 1.13 isaki | Boot from SCSI 231 1.1 minoura | 232 1.13 isaki boot_scsi: 233 1.13 isaki | get block length of the SCSI disk 234 1.13 isaki leal RELOC(SCSI_CAP),%a1 235 1.13 isaki SCSIIOCS(__S_READCAP) 236 1.13 isaki tstl %d0 237 1.13 isaki jeq boot_scsi1 238 1.13 isaki BOOT_ERROR("READCAP failed") 239 1.13 isaki boot_scsi1: 240 1.13 isaki movel RELOC(SCSI_CAP+4),%d0 | %d0 = blocksize in bytes 241 1.13 isaki lsrl #2,%d0 | %d0 = blocksize in longword 242 1.13 isaki moveql #25,%d5 243 1.13 isaki bfffo %d0{#0:#32},%d1 | 25:256 24:512 23:1024 22:2048 244 1.13 isaki subl %d1,%d5 | 0:256 1:512 2:1024 3:2048 245 1.13 isaki movel %d5,RELOC(SCSI_BLKLEN) | %d5 = sector length index 246 1.13 isaki 247 1.13 isaki | Find out the start position of the boot partition. 248 1.13 isaki | There seems to be no interface or consensus about this and 249 1.13 isaki | so that we would have to do it heuristicly. 250 1.1 minoura | 251 1.13 isaki | ROM firmware: 252 1.13 isaki | pass read pos (in block #, aka sector #) in %d2. 253 1.13 isaki | Human68k-style partition table does not exist. 254 1.13 isaki | %d2 is 4 at the maximum. 255 1.13 isaki | SCSI IPLs (genuine and SxSI): 256 1.13 isaki | pass read pos (in kilobytes) in %d2. 257 1.13 isaki | %d2 is bigger than 0x20. 258 1.13 isaki | partition table on the memory is destroyed. 259 1.13 isaki | BOOT MENU Ver.2.22: 260 1.13 isaki | passes partition table entry address in %a0. 261 1.13 isaki | %d2 is cleared to zero 262 1.13 isaki | No other IPLs are supported. 263 1.13 isaki 264 1.13 isaki tstl %d2 265 1.13 isaki jne 1f 266 1.13 isaki | If no information in %d2, probably from BOOT MENU. 267 1.13 isaki | %a0 points the on-memory partition table entry. 268 1.13 isaki movel %a0@(0x0008),%d2 | %d2 = pos in kbyte 269 1.13 isaki 1: 270 1.13 isaki moveql #0x20,%d3 271 1.13 isaki cmpl %d3,%d2 272 1.13 isaki jcs 1f | jump if %d2 > 0x20 273 1.13 isaki | SCSI IPL or BOOT MENU. 274 1.13 isaki | At this point, %d2 is pos in kbyte in all cases. 275 1.13 isaki lsll #8,%d2 | %d2 = pos in longword 276 1.13 isaki divul %d0,%d2 | %d2 = pos in sector 277 1.13 isaki 1: 278 1.13 isaki | At this point, %d2 is pos in sector in all cases. 279 1.13 isaki | TDSIZE = 8192, TDSIZE / 4 = 0x800 = (0x20 << 6). 280 1.13 isaki lsll #6,%d3 | %d3 = TDSIZE in longword 281 1.13 isaki divul %d0,%d3 | %d0 = TDSIZE in sector 282 1.13 isaki | Read full primary bootloader 283 1.13 isaki moveal %a5,%a1 | %a1 = dest buffer 284 1.13 isaki jbsr scsiread 285 1.13 isaki 286 1.13 isaki | Selected start sector should not <= 4. There should be 287 1.13 isaki | partition table. If so, repoints to zero(?). 288 1.13 isaki moveql #5,%d0 289 1.13 isaki cmpl %d0,%d2 290 1.13 isaki bcc 1f 291 1.13 isaki moveql #0,%d2 292 1.13 isaki 1: 293 1.13 isaki movel %d2,RELOC(SCSI_PARTTOP) 294 1.13 isaki 295 1.13 isaki | Jump to full parimary loader 296 1.13 isaki jmp RELOC(first_kbyte) 297 1.13 isaki 298 1.13 isaki | 299 1.13 isaki | scsiread 300 1.13 isaki | Read SCSI disk using __S_READ as possible. If __S_READ cannot be 301 1.13 isaki | used (due to read length or offset), use __S_READEXT instead. 302 1.13 isaki | input: 303 1.13 isaki | %d2.l: pos in sector 304 1.13 isaki | %d3.l: len in sector (must be < 65536) 305 1.13 isaki | %d4.l: target SCSI ID 306 1.13 isaki | %d5.l: sector length index (0:256, 1:512, 2:1024, 3:2048, ...) 307 1.13 isaki | %a1.l: buffer address 308 1.13 isaki | destroy: 309 1.13 isaki | %d0,%d1 310 1.13 isaki scsiread: 311 1.13 isaki | if (len >= 256 || pos + len >= 0x200000) 312 1.13 isaki | use READEXT 313 1.13 isaki | else 314 1.13 isaki | use READ 315 1.13 isaki 316 1.13 isaki moveql #__S_READEXT,%d1 317 1.1 minoura 318 1.13 isaki cmpiw #256,%d3 319 1.13 isaki jge scsiread_core | if (d3 >= 256) use READEXT 320 1.1 minoura 321 1.13 isaki movel %d2,%d0 322 1.13 isaki addl %d3,%d0 | %d0 = pos + len 323 1.13 isaki jcs scsiread_core | if overflow, use READEXT 324 1.13 isaki bftst %d0{#0:#11} | if (pos + len >= 0x200000) 325 1.13 isaki jne scsiread_core | use REAEXT 326 1.13 isaki 327 1.13 isaki moveql #__S_READ,%d1 | else use READ 328 1.13 isaki scsiread_core: 329 1.13 isaki IOCS(__SCSIDRV) 330 1.13 isaki rts 331 1.1 minoura 332 1.13 isaki boot_dev_not_supp: 333 1.13 isaki BOOT_ERROR("not supported device"); 334 1.1 minoura 335 1.1 minoura | 336 1.13 isaki | void __dead BOOT_ERROR(const char *msg); 337 1.13 isaki | Print an error message, wait for key press, and reboot. 338 1.13 isaki | Called from C. 339 1.13 isaki ENTRY_NOPROFILE(BOOT_ERROR) 340 1.13 isaki addql #4,%sp | throw away return address 341 1.13 isaki | FALLTHROUGH 342 1.1 minoura | 343 1.13 isaki | BOOT_ERROR(msg) 344 1.13 isaki | Print an error message, wait for key press, and reboot. 345 1.13 isaki | Called from asm. 346 1.13 isaki boot_error: 347 1.13 isaki leal %pc@(msg_progname),%a1 348 1.1 minoura IOCS(__B_PRINT) 349 1.1 minoura moveal %sp@+,%a1 350 1.1 minoura IOCS(__B_PRINT) 351 1.1 minoura ENTRY_NOPROFILE(exit) 352 1.1 minoura ENTRY_NOPROFILE(_rtt) 353 1.13 isaki leal %pc@(msg_reboot),%a1 354 1.1 minoura IOCS(__B_PRINT) 355 1.1 minoura 356 1.1 minoura | wait for a key press (or release of a modifier) 357 1.1 minoura IOCS(__B_KEYINP) 358 1.1 minoura 359 1.1 minoura | issue software reset 360 1.1 minoura trap #10 361 1.1 minoura | NOTREACHED 362 1.13 isaki msg_reboot: 363 1.13 isaki .asciz "\r\n[Hit key to reboot]" 364 1.13 isaki .even 365 1.1 minoura 366 1.1 minoura .globl first_kbyte 367 1.1 minoura first_kbyte: 368 1.1 minoura |-------------------------------------------------------------------------- 369 1.1 minoura | 370 1.13 isaki #if defined(SELFTEST) 371 1.13 isaki jbsr selftest_ashldi3 372 1.13 isaki jbsr selftest_ashrdi3 373 1.13 isaki jbsr selftest_memcmp 374 1.13 isaki jbsr selftest_memmove 375 1.13 isaki jbsr selftest_memset 376 1.13 isaki #endif 377 1.6 isaki 378 1.13 isaki jmp _C_LABEL(bootmain) 379 1.13 isaki | NOTREACHED 380 1.1 minoura 381 1.13 isaki | 382 1.13 isaki | uint32_t badbadd(void *addr) 383 1.13 isaki | returns 1 if reading addr occurs bus error. Otherwise it returns 0. 384 1.1 minoura ENTRY_NOPROFILE(badbaddr) 385 1.13 isaki leal 0x0008:W,%a1 | bus error vector 386 1.13 isaki moveql #1,%d0 387 1.13 isaki leal %pc@(badbaddr1),%a0 388 1.1 minoura movew %sr,%sp@- 389 1.1 minoura oriw #0x0700,%sr | keep out interrupts 390 1.1 minoura movel %a1@,%sp@- 391 1.1 minoura movel %a0,%a1@ | set bus error vector 392 1.1 minoura movel %sp,%d1 | save sp 393 1.1 minoura moveal %sp@(10),%a0 394 1.1 minoura tstb %a0@ | try read... 395 1.13 isaki moveql #0,%d0 | this is skipped on bus error 396 1.13 isaki badbaddr1: 397 1.13 isaki moveal %d1,%sp | restore sp 398 1.1 minoura movel %sp@+,%a1@ 399 1.1 minoura movew %sp@+,%sr 400 1.1 minoura rts 401 1.1 minoura 402 1.13 isaki | 403 1.13 isaki | int raw_read(uint32_t blkpos, uint32_t bytelen, void *buf) 404 1.13 isaki | blkpos: read start position in 512 byte block unit (always?). 405 1.13 isaki | bytelen: read length in bytes. 406 1.13 isaki | caller already avoids bytelen == 0 so that no checks here. 407 1.13 isaki | must be a multiple of sector size on scsi. 408 1.13 isaki | buf: destination buffer address 409 1.13 isaki | 410 1.13 isaki ENTRY_NOPROFILE(raw_read) 411 1.13 isaki moveal %sp,%a1 412 1.1 minoura moveml %d2-%d7/%a2-%a6,%sp@- 413 1.13 isaki moveml %a1@,%d0/%d2-%d3/%a1 | %d0 (return address) 414 1.13 isaki | %d2 blkpos 415 1.13 isaki | %d3 bytelen 416 1.13 isaki | %a1 buf 417 1.13 isaki | At this point boot device is either floppy or SCSI. 418 1.13 isaki tstb %pc@(BOOT_INFO+1) 419 1.13 isaki jeq raw_read_floppy 420 1.13 isaki | FALLTHROUGH 421 1.1 minoura 422 1.1 minoura raw_read_scsi: 423 1.13 isaki | %d2 = pos from device top 424 1.13 isaki | in 512 bytes/block 425 1.13 isaki lsll #1,%d2 | %d2 = in 256 bytes/block 426 1.13 isaki movel %pc@(SCSI_BLKLEN),%d5 | %d5 = sector length index 427 1.13 isaki lsrl %d5,%d2 | %d2 = pos from device top 428 1.13 isaki | in media sector size 429 1.1 minoura 430 1.13 isaki divull %pc@(SCSI_CAP+4),%d0:%d3| %d3 = bytelen / sectsize 431 1.13 isaki | %d0 = bytelen % sectsize 432 1.13 isaki tstl %d0 433 1.13 isaki jeq .Lraw1 434 1.13 isaki BOOT_ERROR("Err1") | ASSERT(bytelen%sectsize==0) 435 1.13 isaki .Lraw1: 436 1.13 isaki movel %pc@(SCSI_ID),%d4 | %d4 = SCSI ID 437 1.1 minoura jbsr scsiread 438 1.13 isaki 439 1.13 isaki raw_read_exit: 440 1.13 isaki moveml %sp@+,%d2-%d7/%a2-%a6 441 1.13 isaki rts 442 1.1 minoura 443 1.1 minoura raw_read_floppy: 444 1.13 isaki | nhead = FDSEC.maxsec.H - FDSEC.minsec.H + 1 445 1.13 isaki | = 2; 446 1.13 isaki | nsect = FDSEC.maxsec.R - FDSEC.minsec.R + 1; 447 1.13 isaki | 448 1.13 isaki | sect = (blkpos % nsect) + FDSEC.minsec.R; 449 1.13 isaki | head = ((blkpos / nsect) % nhead) + FDSEC.minsec.H; 450 1.13 isaki | cyl = ((blkpos / nsect) / nhead) + FDSEC.minsec.C; 451 1.13 isaki | 452 1.13 isaki | NCHR = (FDSEC.minsec.N << 24) | 453 1.13 isaki | (cyl << 16) | 454 1.13 isaki | (head << 8) | 455 1.13 isaki | sect; 456 1.13 isaki 457 1.13 isaki | calc nsect. 458 1.13 isaki moveql #1,%d0 | %d0 = 1 459 1.13 isaki addb %pc@(FDSEC+maxR),%d0 | %d0 = 1 + maxsec.R 460 1.13 isaki subb %pc@(FDSEC+minR),%d0 | %d0 = 1 + maxsec.R - minsec.R 461 1.13 isaki | = nsect 462 1.13 isaki 463 1.13 isaki | Convert blkpos to N/C/H/R. 464 1.13 isaki divuw %d0,%d2 | %d2.hw = blkpos % nsect 465 1.13 isaki | %d2.lw = blkpos / nsect 466 1.13 isaki | Here, %d2.hw becomes sector number and .lw becomes cyl+head. 467 1.13 isaki | %d2.lw = %0000_0000_CCCC_CCCH in binary form. LSB of 468 1.13 isaki | (blkpos / nsect) is head number because we support only 469 1.13 isaki | double-sided floppy here. 470 1.13 isaki | %d2.w = %0000_0000_CCCC_CCCH 471 1.13 isaki lslw #7,%d2 | %d2.w = %0CCC_CCCC_H000_0000 472 1.13 isaki lsrb #7,%d2 | %d2.w = %0CCC_CCCC_0000_000H 473 1.13 isaki | i.e, 474 1.13 isaki | %d2 = $00rrCCHH 475 1.13 isaki swap %d2 | %d2 = $CCHH00rr 476 1.13 isaki lslw #8,%d2 | %d2 = $CCHHrr00 477 1.13 isaki | two bytes from odd FDSEC+minR is (minR << 8 | maxN) and 478 1.13 isaki | minN == maxN always. 479 1.13 isaki addw %pc@(FDSEC+minR),%d2 | %d2 = $CCHHRRNN 480 1.13 isaki rorl #8,%d2 | %d2 = $NNCCHHRR 481 1.1 minoura 482 1.13 isaki movel %pc@(FDMODE),%d1 | %d1 = PDA+MODE 483 1.1 minoura IOCS(__B_READ) 484 1.13 isaki andil #0xf8ffff00,%d0 | Check status (must be zero) 485 1.13 isaki jeq raw_read_exit 486 1.13 isaki BOOT_ERROR("B_READ failed"); 487 1.13 isaki 488 1.13 isaki | 489 1.13 isaki | BSS 490 1.13 isaki | 491 1.13 isaki BSS(BOOT_INFO, 4) | whole result of IOCS BOOTINF 492 1.13 isaki 493 1.13 isaki BSS(FDMODE, 4) 494 1.13 isaki BSS(FDSEC, 8) | +0: (minN) sector length 495 1.13 isaki | +1: (minC) track number 496 1.13 isaki | +2: (minH) head 497 1.13 isaki | +3: (minR) sector number 498 1.13 isaki | +4: (maxN) sector length 499 1.13 isaki | +5: (maxC) track number 500 1.13 isaki | +6: (maxH) head 501 1.13 isaki | +7: (maxR) sector number 502 1.13 isaki 503 1.13 isaki BSS(SCSI_ID, 4) | SCSI ID, if booted from SCSI 504 1.13 isaki BSS(SCSI_CAP, 8) | result of SCSI READCAP 505 1.13 isaki | +0.L: total number of logical blocks 506 1.13 isaki | +4.L: block length in bytes 507 1.13 isaki BSS(SCSI_PARTTOP, 4) | top sector # of this partition 508 1.13 isaki BSS(SCSI_BLKLEN ,4) | sector length index 509 1.13 isaki | 0:256, 1:512, 2:1024, 3:2048, .. 510