xref: /csrg-svn/sys/i386/stand/wdbootblk.c (revision 63368)
148828Swilliam /*-
2*63368Sbostic  * Copyright (c) 1990, 1993
3*63368Sbostic  *	The Regents of the University of California.  All rights reserved.
448828Swilliam  *
548828Swilliam  * This code is derived from software contributed to Berkeley by
648828Swilliam  * William Jolitz.
748828Swilliam  *
848828Swilliam  * %sccs.include.redist.c%
948828Swilliam  *
10*63368Sbostic  *	@(#)wdbootblk.c	8.1 (Berkeley) 06/11/93
1148828Swilliam  */
1248828Swilliam 
1348828Swilliam /*
1448828Swilliam  * wdbootblk.s:
1548828Swilliam  *	Written 7/6/90 by William F. Jolitz
1648828Swilliam  *	Initial block boot for AT/386 with typical Western Digital
1748828Swilliam  *	WD 1002-WA2 (or upwards compatable). Works either as
1848828Swilliam  *	first and sole partition bootstrap, or as loaded by a
1948828Swilliam  *	earlier BIOS boot when on an inner partition of the disk.
2048828Swilliam  *
2148828Swilliam  *	Goal is to read in sucessive 7.5Kbytes of bootstrap to
2248828Swilliam  *	execute.
2348828Swilliam  *
2448828Swilliam  *	No attempt is made to handle disk errors.
2548828Swilliam  */
2656514Sbostic 
2756514Sbostic #include <i386/isa/isa.h>
2856514Sbostic #include <i386/isa/wdreg.h>
2956514Sbostic 
3048828Swilliam #define	NOP	jmp 1f ; nop ; 1:
3148828Swilliam #define BIOSRELOC	0x7c00
3248828Swilliam #define start		0x70400
3348828Swilliam 
3448828Swilliam 	/* step 0 force descriptors to bottom of address space */
3548828Swilliam 
3648828Swilliam 	.byte 0xfa,0xb8,0x30,0x00,0x8e,0xd0,0xbc,0x00,0x01 #ll fb
3748828Swilliam 
3848828Swilliam 	xorl	%eax,%eax
3948828Swilliam 	movl	%ax,%ds
4048828Swilliam 	movl	%ax,%es
4148828Swilliam 
4248828Swilliam 	/* step 1 load new descriptor table */
4348828Swilliam 
4448828Swilliam 	.byte 0x2E,0x0F,1,0x16
4548828Swilliam 	.word	BIOSRELOC+0x4a	#GDTptr
4648828Swilliam 	# word aword cs lgdt GDTptr
4748828Swilliam 
4848828Swilliam 	/* step 2 turn on protected mode */
4948828Swilliam 
5048828Swilliam 	smsw	%ax
5148828Swilliam 	orb	$1,%al
5248828Swilliam 	lmsw	%ax
5348828Swilliam 	jmp	1f
5448828Swilliam 	nop
5548828Swilliam 
5648828Swilliam 	/* step 3  reload segment descriptors */
5748828Swilliam 
5848828Swilliam 1:
5948828Swilliam 	xorl	%eax,%eax
6048828Swilliam 	movb	$0x10,%al
6148828Swilliam 	movl	%ax,%ds
6248828Swilliam 	movl	%ax,%es
6348828Swilliam 	movl	%ax,%ss
6448828Swilliam 	word
6548828Swilliam 	ljmp	$0x8,$ BIOSRELOC+0x50	/* would be nice if .-RELOC+0x7c00 worked */
6648828Swilliam 
6748828Swilliam  /* Global Descriptor Table contains three descriptors:
6848828Swilliam   * 0x00: Null: not used
6948828Swilliam   * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes
7048828Swilliam   * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes
7148828Swilliam   *		(overlays code)
7248828Swilliam   */
7348828Swilliam GDT:
7448828Swilliam NullDesc:	.word	0,0,0,0	# null descriptor - not used
7548828Swilliam CodeDesc:	.word	0xFFFF	# limit at maximum: (bits 15:0)
7648828Swilliam 	.byte	0,0,0	# base at 0: (bits 23:0)
7748828Swilliam 	.byte	0x9f	# present/priv level 0/code/conforming/readable
7848828Swilliam 	.byte	0xcf	# page granular/default 32-bit/limit(bits 19:16)
7948828Swilliam 	.byte	0	# base at 0: (bits 31:24)
8048828Swilliam DataDesc:	.word	0xFFFF	# limit at maximum: (bits 15:0)
8148828Swilliam 	.byte	0,0,0	# base at 0: (bits 23:0)
8248828Swilliam 	.byte	0x93	# present/priv level 0/data/expand-up/writeable
8348828Swilliam 	.byte	0xcf	# page granular/default 32-bit/limit(bits 19:16)
8448828Swilliam 	.byte	0	# base at 0: (bits 31:24)
8548828Swilliam 
8648828Swilliam /* Global Descriptor Table pointer
8748828Swilliam  *  contains 6-byte pointer information for LGDT
8848828Swilliam  */
8948828Swilliam GDTptr:	.word	0x17	# limit to three 8 byte selectors(null,code,data)
9048828Swilliam 	.long 	BIOSRELOC+0x32	# GDT -- arrgh, gas again!
9148828Swilliam 
9248828Swilliam 	/* step 4 relocate to final bootstrap address. */
9348828Swilliam reloc:
9448828Swilliam 	movl	$ BIOSRELOC,%esi
9548828Swilliam 	movl	$ RELOC,%edi
9648828Swilliam 	movl	$512,%ecx
9748828Swilliam 	rep
9848828Swilliam 	movsb
9948828Swilliam  movl $0x60000,%esp
10048828Swilliam 	pushl	$dodisk
10148828Swilliam 	ret
10248828Swilliam 
10348828Swilliam 	/* step 5 load remaining 15 sectors off disk */
10448828Swilliam dodisk:
10548828Swilliam 	movl	$ IO_WD1+wd_seccnt,%edx
10648828Swilliam 	movb	$ 15,%al
10748828Swilliam 	outb	%al,%dx
10848828Swilliam 	NOP
10948828Swilliam 	movl	$ IO_WD1+wd_sector,%edx
11048828Swilliam 	movb	$ 2,%al
11148828Swilliam 	outb	%al,%dx
11248828Swilliam 	NOP
11348828Swilliam 	#outb(wdc+wd_cyl_lo, (cyloffset & 0xff));
11448828Swilliam 	#outb(wdc+wd_cyl_hi, (cyloffset >> 8));
11548828Swilliam 	#outb(wdc+wd_sdh, WDSD_IBM | (unit << 4));
11648828Swilliam 
11748828Swilliam 	movl	$ IO_WD1+wd_command,%edx
11848828Swilliam 	movb	$ WDCC_READ,%al
11948828Swilliam 	outb	%al,%dx
12048828Swilliam 	NOP
12148828Swilliam 	cld
12248828Swilliam 
12348828Swilliam 	/* check to make sure controller is not busy and we have data ready */
12448828Swilliam readblk:
12548828Swilliam 	movl	$ IO_WD1+wd_status,%edx
12648828Swilliam 	inb	%dx,%al
12748828Swilliam 	NOP
12848828Swilliam 	testb	$ WDCS_BUSY,%al
12948828Swilliam 	jnz readblk
13048828Swilliam 	testb	$ WDCS_DRQ,%al
13148828Swilliam 	jz readblk
13248828Swilliam 
13348828Swilliam 	/* read a block into final position in memory */
13448828Swilliam 
13548828Swilliam 	movl	$ IO_WD1+wd_data,%edx
13648828Swilliam 	movl	$ 256,%ecx
13748828Swilliam 	.byte 0x66,0xf2,0x6d	# rep insw
13848828Swilliam 	NOP
13948828Swilliam 
14048828Swilliam 	/* need more blocks to be read in? */
14148828Swilliam 
14248828Swilliam 	cmpl	$ RELOC+16*512-1,%edi
14348828Swilliam 	jl	readblk
14448828Swilliam 
14548828Swilliam 	/* for clever bootstrap, dig out boot unit and cylinder */
14648828Swilliam 
14748828Swilliam 	movl	$ IO_WD1+wd_cyl_lo,%edx
14848828Swilliam 	inb	%dx,%al
14948828Swilliam 	NOP
15048828Swilliam 	xorl	%ecx,%ecx
15148828Swilliam 	movb	%al,%cl
15248828Swilliam 	incl	%edx
15348828Swilliam 	inb	%dx,%al		/* cyl_hi */
15448828Swilliam 	NOP
15548828Swilliam 	movb	%al,%ch
15648828Swilliam 	pushl	%ecx		/* cyloffset */
15748828Swilliam 
15848828Swilliam 	incl	%edx
15948828Swilliam 	xorl	%eax,%eax
16048828Swilliam 	inb	%dx,%al		/* sdh */
16148828Swilliam 	andb	$0x10,%al	/* isolate unit # bit */
16248828Swilliam 	shrb	$4,%al
16348828Swilliam 	pushl	%eax		/* unit */
16448828Swilliam 
16548828Swilliam 	/* wd controller is major device 0 */
16648828Swilliam 	xorl	%eax,%eax
16748828Swilliam 	pushl	%eax		/* bootdev */
16848828Swilliam 
16948828Swilliam 	/* sorry, no flags at this point! */
17048828Swilliam 
17148828Swilliam 	pushl	$ start
17248828Swilliam 	ret	/* main (dev, unit, offset) */
17348828Swilliam 
17448828Swilliam ebootblkcode:
17548828Swilliam 
17648828Swilliam 	/* remaining space usable for a disk label */
17748828Swilliam 
17848828Swilliam 	.space	510-223		/* would be nice if .space 512-2-. worked */
17948828Swilliam 	.word	0xaa55		/* signature -- used by BIOS ROM */
18048828Swilliam 
18148828Swilliam ebootblk: 			/* MUST BE EXACTLY 0x200 BIG FOR SURE */
182