boot.S revision 1.13 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