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