boot.S revision 1.5 1 | file: boot.S
2 | author: chapuni(webmaster@chapuni.com)
3 | ITOH Yasufumi
4 |
5 | $NetBSD: boot.S,v 1.5 2020/01/16 13:37:27 isaki Exp $
6
7 #include <machine/asm.h>
8 #include "iocscall.h"
9
10 #define SCSI_ADHOC_BOOTPART
11
12 #define BASEOFF 0x8000
13 #define BASEPTR_A (TEXTADDR+BASEOFF)
14 #define BASEPTR_R %pc@(top+BASEOFF:W)
15
16 #define SRAM 0x00ED0000 /* SRAM stat addr */
17 #define SRAM_MEMSZ (SRAM + 8) /* (L) size of main memory */
18 #define MINMEM 0x00400000 /* at least 4MB required */
19
20 #define BOOT_ERROR(s) jbsr boot_error; .asciz s; .even
21
22 .globl _C_LABEL(bootmain)
23 .text
24 ASENTRY_NOPROFILE(start)
25 ASENTRY_NOPROFILE(top)
26 bras _ASM_LABEL(entry0)
27 .ascii "SHARP/"
28 .ascii "X680x0"
29 .word 0x8199,0x94e6,0x82ea,0x82bd
30 .word 0x8e9e,0x82c9,0x82cd,0x8cbb
31 .word 0x8ec0,0x93a6,0x94f0,0x8149
32 .word 0
33 | 0x2000 (FD), 0x2400 (SASI/SCSI) ( 0x0f0000)
34 | d4 SCSI ID
35 | jmp
36 ASENTRY_NOPROFILE(entry0)
37 moveml %d0-%d7/%a0-%a7,_C_LABEL(startregs)
38 lea BASEPTR_A:l,%a5 | set base ptr
39 #define _RELOC(adr) %a5@(((adr)-(BASEPTR_A&0xffff)):W)
40 #define ASRELOC(var) _RELOC(_ASM_LABEL(var))
41 #define RELOC(var) _RELOC(_C_LABEL(var))
42
43 lea RELOC(edata),%a1
44 bra _ASM_LABEL(entry)
45
46 | Disklabel= 404bytes
47 | Since LABELOFFSET in <machine/disklabel.h> is 0x40,
48 | entry must be after 0x000001d4 (0x000f01d4)
49 .org 0x40
50 disklabel:
51 .space 404
52
53 ASENTRY_NOPROFILE(entry)
54 movew #_end-1,%d0 | bss end (low word only)
55
56 | clear out bss (must be <= 64KB)
57 subw %a1,%d0
58 clrbss: clrb %a1@+
59 dbra %d0,clrbss
60
61 movel %d4,RELOC(ID) | SCSI ID (if booted from SCSI)
62
63 | set system stack
64 lea ASRELOC(top),%a1 | set stack pointer to 0x000F0000
65 lea %a1@,%sp | a1 will be used later for IOCS calls
66
67 | we use 68020 instructions, and check MPU beforehand
68 |
69 | here d0.w = -1, and the above "subw a1,d0" = 0x9049, and
70 | if MPU <= 010 loads 0x49,
71 | if MPU >= 020 loads 0x90.
72 | This is a move, not a tst instruction
73 | because pc-relative tsts are not availble on 000/010.
74 chkmpu: moveb %pc@(clrbss-chkmpu-2:B,%d0:W:2),%d0 | 103B 02xx
75 jmi mpuok | MC68020 or later
76 BOOT_ERROR("MPU 68000?")
77 mpuok: | XXX check for MMU?
78
79 IOCS(__BOOTINF)
80 lsll #8,%d0 | clear MSByte
81 lsrl #8,%d0 |
82 movel %d0,RELOC(BOOT_INFO)
83
84 |
85 | 0x80...0x8F SASI
86 | 0x90...0x93 Floppy
87 | 0xED0000...0xED3FFE SRAM
88 | others ROM (SCSI?)
89 |
90 movel %d0,%d1
91 clrb %d1
92 tstl %d1
93 jne boot_ram_rom
94 |
95 | SASI or Floppy
96 |
97 movel %d0,%d2
98 andib #0xFC,%d0
99 cmpib #0x90,%d0
100 jne boot_dev_unsupported | boot from SASI?
101 |
102 | Floppy
103 |
104 moveb %d2,%d0
105 andib #0x03,%d0 | drive # (head=0)
106 jbsr check_fd_format
107 moveml %d0-%d1,RELOC(FDSECMINMAX) | min and max sec #
108 lslw #8,%d2
109 moveq #0x70,%d1
110 orw %d2,%d1 | PDA*256 + MODE
111 movel %d1,RELOC(FDMODE)
112 movel %d0,%d2 | read position (first sector)
113 movel #8192,%d3 | read bytes
114 IOCS(__B_READ)
115 jra boot_read_done
116
117 #include "chkfmt.s"
118
119 boot_ram_rom:
120 movel %d0,%d1
121 swap %d1
122 cmpiw #0x00ED,%d1
123 jne boot_SCSI
124 | boot from SRAM?
125
126 boot_dev_unsupported:
127 BOOT_ERROR("unsupported boot device")
128
129 |
130 | volatile void BOOT_ERROR(const char *msg);
131 | print error message, wait for key press and reboot
132 |
133 booterr_msg: .asciz "\r\n\n"
134 reboot_msg: .asciz "\r\n[Hit key to reboot]"
135 .even
136
137 ENTRY_NOPROFILE(BOOT_ERROR)
138 addql #4,%sp
139
140 boot_error: lea %pc@(booterr_msg),%a1
141 IOCS(__B_PRINT)
142 moveal %sp@+,%a1
143 IOCS(__B_PRINT)
144 ENTRY_NOPROFILE(exit)
145 ENTRY_NOPROFILE(_rtt)
146 lea %pc@(reboot_msg),%a1
147 IOCS(__B_PRINT)
148
149 | wait for a key press (or release of a modifier)
150 IOCS(__B_KEYINP)
151
152 | issue software reset
153 trap #10
154 | NOTREACHED
155
156
157 |
158 | ROM boot ... probably from SCSI
159 |
160 boot_SCSI:
161 #ifdef SCSI_ADHOC_BOOTPART
162 |
163 | Find out boot partition in an ad hoc manner.
164 |
165
166 | get block length of the SCSI disk
167 SCSIIOCS(__S_READCAP) | using buffer at a1
168 tstl %d0
169 jeq 1f
170 BOOT_ERROR("READCAP failed")
171 1: moveq #0,%d5
172 moveb %a1@(6),%d5 | 1: 256, 2: 512, 4: 1024, 8: 2048
173 lsrb #1,%d5 | 0: 256, 1: 512, 2: 1024, 4: 2048
174 movel %d5,RELOC(SCSI_BLKLEN)
175
176 | find out the start position of the boot partition
177 | XXX VERY AD HOC
178 |
179 | ROM firmware:
180 | pass read pos (in block #) in d2
181 | Human68k-style partition table does not exist
182 | d2 is 4 at the maximum
183 | SCSI IPLs (genuine and SxSI):
184 | pass read pos (in kilobytes) in d2
185 | d2 is bigger than 0x20
186 | partition table on the memory is destroyed
187 | BOOT MENU Ver.2.22:
188 | passes partition table entry address in a0
189 | d2 is cleared to zero
190 | No other IPL is supported. XXX FIXME
191 tstl %d2
192 jne sc1
193 | no information in d2 -- probably from BOOT MENU
194 | a0 points the partiion table entry
195 movel %a0@(0x0008),%d2 | in KByte
196 sc1: cmpl #0x20,%d2
197 jcs sc2
198 lsll #8,%d2 | clear MSByte
199 lsrl #7,%d2 | in 512 byte block
200 divul %d5,%d2 | in sector
201 sc2:
202 | read entire boot
203 moveq #TDSIZE/512,%d3 | size is TDSIZE byte
204 divul %d5,%d3 | in sector
205 jbsr scsiread | read at %a1
206
207 cmpil #5,%d2
208 bcc sc3
209 movql #0,%d2
210 sc3: movel %d2,RELOC(SCSI_PARTTOP)
211 #else
212 moveq #1,%d5 | 512bytes/sec
213 movel %d5,%sp@-
214 moveq #8192/512,%d3 |
215 moveq #0x40,%d2 | (sd*a )
216 SCSIIOCS(__S_READ)
217 #endif
218
219 boot_read_done:
220 jmp first_kbyte
221
222 read_error: BOOT_ERROR("read error")
223
224 #undef RELOC /* base register a5 is no longer available */
225 #undef ASRELOC
226 #undef _RELOC
227
228 |
229 | read SCSI
230 |
231 | input: d2.l: pos in sector
232 | d3.l: len in sector
233 | d4: target SCSI ID
234 | d5: sector length (1: 512, 2: 1024, 4: 2048)
235 | a1: buffer address
236 | destroy:
237 | d0, d1, a1
238 |
239 scsiread:
240 moveml %d2-%d3/%d6-%d7/%a2,%sp@-
241 | if (pos >= 0x200000 || (len > 255 && pos + len >= 0x200000))
242 | use READEXT
243 | else
244 | use READ
245 moveq #0x20,%d0
246 swap %d0 | d0.l = 0x00200000
247 moveq #0,%d6
248 subqb #1,%d6 | d6.l = 255
249 movel %d5,%d7
250 lsll #8,%d7
251 lsll #1,%d7 | d7 = sector length (byte)
252 cmpl %d0,%d2
253 jcc scsiread_ext
254 moveq #__S_READ,%d1
255 cmpl %d3,%d6
256 jcc scsiread_noext
257 subl %d2,%d0 | d0.0 = 0x200000 - pos
258 cmpl %d0,%d3 | <= len
259 jcs scsiread_noext | no
260
261 scsiread_ext: | use READEXT
262 extw %d6 | d6.l = 65535
263 moveq #__S_READEXT,%d1
264
265 scsiread_noext: | use READ
266 loop_scsiread:
267 | d1: SCSI IOCS call #
268 | d6: max sector count at a time
269 movel %d3,%a2 | save original len in a2
270 cmpl %d3,%d6
271 jcc 1f
272 movel %d6,%d3
273 1: IOCS(__SCSIDRV) | SCSIIOCS(d1)
274 tstl %d0
275 jne read_error
276 movel %d3,%d0
277 mulul %d7,%d0
278 addl %d0,%a1
279 exg %d3,%a2 | restore original len to d3
280 addl %a2,%d2 | pos += read count
281 subl %a2,%d3 | len -= read count
282 jne loop_scsiread
283 moveml %sp@+,%d2-%d3/%d6-%d7/%a2
284 rts
285
286 |
287 | The former part must reside in the first 1KB.
288 |
289 .globl first_kbyte
290 first_kbyte:
291 |--------------------------------------------------------------------------
292 |
293 | The latter text+data part is not accessible at the first boot time.
294 | PC-relative can be used from here.
295 |
296 jmp _C_LABEL(bootmain) | 0x0Fxxxx
297
298 .word 0
299
300 | int badbaddr __P((void *adr));
301 | check if the given address is valid for byte read
302 | return: 0: valid, 1: not valid
303
304 ENTRY_NOPROFILE(badbaddr)
305 lea 0x0008:W,%a1 | MPU Bus Error vector
306 moveq #1,%d0
307 lea %pc@(badr1),%a0
308 movew %sr,%sp@-
309 oriw #0x0700,%sr | keep out interrupts
310 movel %a1@,%sp@-
311 movel %a0,%a1@ | set bus error vector
312 movel %sp,%d1 | save sp
313 moveal %sp@(10),%a0
314 tstb %a0@ | try read...
315 moveq #0,%d0 | this is skipped on bus error
316 badr1: moveal %d1,%sp | restore sp
317 movel %sp@+,%a1@
318 movew %sp@+,%sr
319 rts
320
321 | void RAW_READ __P((void *buf, u_int32_t blkpos, size_t bytelen));
322 | inputs:
323 | buf: input buffer address
324 | blkpos: read start position in the partition in 512byte-blocks
325 | bytelen: read length in bytes
326
327 Lraw_read_buf=4+(4*11)
328 Lraw_read_pos_=Lraw_read_buf+4
329 Lraw_read_len=Lraw_read_buf+8
330
331 #ifdef SCSI_ADHOC_BOOTPART
332 | RAW_READ of physical disk
333 ENTRY_NOPROFILE(RAW_READ0)
334 moveq #0,%d0
335 jra raw_read1
336 #endif
337
338 ENTRY_NOPROFILE(RAW_READ)
339 #ifdef SCSI_ADHOC_BOOTPART
340 movel _C_LABEL(SCSI_PARTTOP),%d0
341 raw_read1:
342 #endif
343 moveml %d2-%d7/%a2-%a6,%sp@-
344 moveml %sp@(Lraw_read_buf),%d1-%d3
345 movel %d1,%a1
346 | d2.l: pos in 512byte-blocks
347 | d3.l: length in bytes
348 | a1 (=d1): buffer address
349
350 lea BASEPTR_R,%a5 | set base ptr
351 #define _RELOC(adr) %a5@(((adr)-(BASEPTR_A&0xffff)):W)
352 #define ASRELOC(var) _RELOC(_ASM_LABEL(var))
353 #define RELOC(var) _RELOC(_C_LABEL(var))
354
355 tstb _RELOC(_C_LABEL(BOOT_INFO)+1) | simple check. may be incorrect!
356 beqs raw_read_floppy
357
358 raw_read_scsi:
359 movel RELOC(ID),%d4 | SCSI ID
360 #ifdef SCSI_ADHOC_BOOTPART
361 movel RELOC(SCSI_BLKLEN),%d5 | sector size: 0-2
362 | XXX length must be sector aligned
363 lsrl #8,%d3 | size in 256byte-blocks
364 lsrl #1,%d3
365 divul %d5,%d3 | size in sector
366 beqs read_half | minimal error check
367 divul %d5,%d2 | pos in sector
368 addl %d0,%d2 | physical pos in sector
369 #else
370 moveq #1,%d5 | 512bytes/sec
371 moveq #9,%d0 | shift count
372 addl #511,%d3
373 lsrl %d0,%d3
374 bcss read_half | minimal error check
375
376 addl #0x40,%d2 | 'a' partition starts here
377 #endif
378 | jcc 1f
379 | BOOT_ERROR("out of seek") | pos exceeds 32bit
380 |1:
381 jbsr scsiread
382 bras raw_read_end
383
384 raw_read_floppy:
385 |
386 | Floppy read routine
387 |
388
389 | convert to seek position
390
391 asll #2,%d2 | size in 128byte-blocks
392
393 | sec = raw_read_pos (d2)
394 | sec >>= 7 + (sector length: 0-3)
395
396 lea RELOC(FDSECMINMAX),%a0
397 moveq #0,%d1
398 moveb %a0@,%d1 | d1: sector length (0-3)
399 lsrl %d1,%d2 | d2: pos in sector
400 bcss read_half | error check
401
402 | trk = sec / (# sectors)
403 | sec = sec % (# sectors)
404
405 moveb %a0@(7),%d1 | d1: max sector #
406 subb %a0@(3),%d1 | - min sector #
407 addqb #1,%d1 | d1: # sectors
408 divu %d1,%d2 | d2: (sec << 16) | track
409
410 | position = (sec length << 24) | (track/2 << 16)
411 | | (track%2 << 8) | (min sec # + sec)
412
413 movel %a0@,%d0 | d0: (sec len << 24) | min sec #
414 lsrw #1,%d2 | d2: (sec << 16) | (track / 2)
415 jcc 1f
416 bset #8,%d0 | |= (track % 2) << 8
417 1: swap %d2 | d2: ((track / 2) << 16) | sec
418 addl %d0,%d2 | d2: position
419
420 | read
421 movel RELOC(FDMODE),%d1 | PDA*256 + MODE
422
423 | B_READ (for floppy)
424 | d1.w: PDA x 256 + MODE
425 | PDA: 0x90 (drive 0) ... 0x93 (drive 3)
426 | MODE: bit6: MFM
427 | bit5: retry
428 | bit4: seek
429 | d2.l: position
430 | bit31-24: sector length (0: 128, 1: 256, 2: 512, 3: 1K)
431 | bit23-16: track # (0-79)
432 | bit15-08: side (0 or 1)
433 | bit07-00: sector # (1-)
434 | d3.l: read bytes
435 | a1: read address
436 | return:
437 | d0: bit 31-24 ST0
438 | bit 23-16 ST1
439 | bit 15- 8 ST2
440 | bit 7- 0 C
441 | -1 on parameter error
442 | destroy: d0, d2, d3, a1
443 IOCS(__B_READ)
444 andil #0xf8ffff00,%d0 | check status (must be zero)
445 jne read_error
446
447 raw_read_end:
448 moveml %sp@+,%a2-%a6/%d2-%d7
449 rts
450 #undef _RELOC /* base register a5 is no longer available */
451 #undef ASRELOC
452 #undef RELOC
453
454 read_half: BOOT_ERROR("read half of block")
455
456
457 |
458 | global variables
459 |
460 BSS(ID, 4) | SCSI ID
461 BSS(BOOT_INFO, 4) | result of IOCS(__BOOTINF)
462 BSS(FDMODE, 4) | Floppy access mode: PDA x 256 + MODE
463 BSS(FDSECMINMAX, 8) | +0: (min sector) sector length
464 | +1: (min sector) track #
465 | +2: (min sector) side
466 | +3: (min sector) sector #
467 | +4: (max sector) sector length
468 | +5: (max sector) track #
469 | +6: (max sector) side
470 | +7: (max sector) sector #
471 #ifdef SCSI_ADHOC_BOOTPART
472 BSS(SCSI_PARTTOP, 4) | start sector of boot partition
473 BSS(SCSI_BLKLEN ,4) | sector len 0: 256, 1: 512, 2: 1024
474 #endif
475