xref: /csrg-svn/sys/i386/stand/wdbootblk.c (revision 48828)
1*48828Swilliam /*-
2*48828Swilliam  * Copyright (c) 1990 The Regents of the University of California.
3*48828Swilliam  * All rights reserved.
4*48828Swilliam  *
5*48828Swilliam  * This code is derived from software contributed to Berkeley by
6*48828Swilliam  * William Jolitz.
7*48828Swilliam  *
8*48828Swilliam  * %sccs.include.redist.c%
9*48828Swilliam  *
10*48828Swilliam  *	@(#)wdbootblk.c	7.1 (Berkeley) 04/28/91
11*48828Swilliam  */
12*48828Swilliam 
13*48828Swilliam /*
14*48828Swilliam  * wdbootblk.s:
15*48828Swilliam  *	Written 7/6/90 by William F. Jolitz
16*48828Swilliam  *	Initial block boot for AT/386 with typical Western Digital
17*48828Swilliam  *	WD 1002-WA2 (or upwards compatable). Works either as
18*48828Swilliam  *	first and sole partition bootstrap, or as loaded by a
19*48828Swilliam  *	earlier BIOS boot when on an inner partition of the disk.
20*48828Swilliam  *
21*48828Swilliam  *	Goal is to read in sucessive 7.5Kbytes of bootstrap to
22*48828Swilliam  *	execute.
23*48828Swilliam  *
24*48828Swilliam  *	No attempt is made to handle disk errors.
25*48828Swilliam  */
26*48828Swilliam #include "i386/isa/isa.h"
27*48828Swilliam #include "i386/isa/wdreg.h"
28*48828Swilliam #define	NOP	jmp 1f ; nop ; 1:
29*48828Swilliam #define BIOSRELOC	0x7c00
30*48828Swilliam #define start		0x70400
31*48828Swilliam 
32*48828Swilliam 	/* step 0 force descriptors to bottom of address space */
33*48828Swilliam 
34*48828Swilliam 	.byte 0xfa,0xb8,0x30,0x00,0x8e,0xd0,0xbc,0x00,0x01 #ll fb
35*48828Swilliam 
36*48828Swilliam 	xorl	%eax,%eax
37*48828Swilliam 	movl	%ax,%ds
38*48828Swilliam 	movl	%ax,%es
39*48828Swilliam 
40*48828Swilliam 	/* step 1 load new descriptor table */
41*48828Swilliam 
42*48828Swilliam 	.byte 0x2E,0x0F,1,0x16
43*48828Swilliam 	.word	BIOSRELOC+0x4a	#GDTptr
44*48828Swilliam 	# word aword cs lgdt GDTptr
45*48828Swilliam 
46*48828Swilliam 	/* step 2 turn on protected mode */
47*48828Swilliam 
48*48828Swilliam 	smsw	%ax
49*48828Swilliam 	orb	$1,%al
50*48828Swilliam 	lmsw	%ax
51*48828Swilliam 	jmp	1f
52*48828Swilliam 	nop
53*48828Swilliam 
54*48828Swilliam 	/* step 3  reload segment descriptors */
55*48828Swilliam 
56*48828Swilliam 1:
57*48828Swilliam 	xorl	%eax,%eax
58*48828Swilliam 	movb	$0x10,%al
59*48828Swilliam 	movl	%ax,%ds
60*48828Swilliam 	movl	%ax,%es
61*48828Swilliam 	movl	%ax,%ss
62*48828Swilliam 	word
63*48828Swilliam 	ljmp	$0x8,$ BIOSRELOC+0x50	/* would be nice if .-RELOC+0x7c00 worked */
64*48828Swilliam 
65*48828Swilliam  /* Global Descriptor Table contains three descriptors:
66*48828Swilliam   * 0x00: Null: not used
67*48828Swilliam   * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes
68*48828Swilliam   * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes
69*48828Swilliam   *		(overlays code)
70*48828Swilliam   */
71*48828Swilliam GDT:
72*48828Swilliam NullDesc:	.word	0,0,0,0	# null descriptor - not used
73*48828Swilliam CodeDesc:	.word	0xFFFF	# limit at maximum: (bits 15:0)
74*48828Swilliam 	.byte	0,0,0	# base at 0: (bits 23:0)
75*48828Swilliam 	.byte	0x9f	# present/priv level 0/code/conforming/readable
76*48828Swilliam 	.byte	0xcf	# page granular/default 32-bit/limit(bits 19:16)
77*48828Swilliam 	.byte	0	# base at 0: (bits 31:24)
78*48828Swilliam DataDesc:	.word	0xFFFF	# limit at maximum: (bits 15:0)
79*48828Swilliam 	.byte	0,0,0	# base at 0: (bits 23:0)
80*48828Swilliam 	.byte	0x93	# present/priv level 0/data/expand-up/writeable
81*48828Swilliam 	.byte	0xcf	# page granular/default 32-bit/limit(bits 19:16)
82*48828Swilliam 	.byte	0	# base at 0: (bits 31:24)
83*48828Swilliam 
84*48828Swilliam /* Global Descriptor Table pointer
85*48828Swilliam  *  contains 6-byte pointer information for LGDT
86*48828Swilliam  */
87*48828Swilliam GDTptr:	.word	0x17	# limit to three 8 byte selectors(null,code,data)
88*48828Swilliam 	.long 	BIOSRELOC+0x32	# GDT -- arrgh, gas again!
89*48828Swilliam 
90*48828Swilliam 	/* step 4 relocate to final bootstrap address. */
91*48828Swilliam reloc:
92*48828Swilliam 	movl	$ BIOSRELOC,%esi
93*48828Swilliam 	movl	$ RELOC,%edi
94*48828Swilliam 	movl	$512,%ecx
95*48828Swilliam 	rep
96*48828Swilliam 	movsb
97*48828Swilliam  movl $0x60000,%esp
98*48828Swilliam 	pushl	$dodisk
99*48828Swilliam 	ret
100*48828Swilliam 
101*48828Swilliam 	/* step 5 load remaining 15 sectors off disk */
102*48828Swilliam dodisk:
103*48828Swilliam 	movl	$ IO_WD1+wd_seccnt,%edx
104*48828Swilliam 	movb	$ 15,%al
105*48828Swilliam 	outb	%al,%dx
106*48828Swilliam 	NOP
107*48828Swilliam 	movl	$ IO_WD1+wd_sector,%edx
108*48828Swilliam 	movb	$ 2,%al
109*48828Swilliam 	outb	%al,%dx
110*48828Swilliam 	NOP
111*48828Swilliam 	#outb(wdc+wd_cyl_lo, (cyloffset & 0xff));
112*48828Swilliam 	#outb(wdc+wd_cyl_hi, (cyloffset >> 8));
113*48828Swilliam 	#outb(wdc+wd_sdh, WDSD_IBM | (unit << 4));
114*48828Swilliam 
115*48828Swilliam 	movl	$ IO_WD1+wd_command,%edx
116*48828Swilliam 	movb	$ WDCC_READ,%al
117*48828Swilliam 	outb	%al,%dx
118*48828Swilliam 	NOP
119*48828Swilliam 	cld
120*48828Swilliam 
121*48828Swilliam 	/* check to make sure controller is not busy and we have data ready */
122*48828Swilliam readblk:
123*48828Swilliam 	movl	$ IO_WD1+wd_status,%edx
124*48828Swilliam 	inb	%dx,%al
125*48828Swilliam 	NOP
126*48828Swilliam 	testb	$ WDCS_BUSY,%al
127*48828Swilliam 	jnz readblk
128*48828Swilliam 	testb	$ WDCS_DRQ,%al
129*48828Swilliam 	jz readblk
130*48828Swilliam 
131*48828Swilliam 	/* read a block into final position in memory */
132*48828Swilliam 
133*48828Swilliam 	movl	$ IO_WD1+wd_data,%edx
134*48828Swilliam 	movl	$ 256,%ecx
135*48828Swilliam 	.byte 0x66,0xf2,0x6d	# rep insw
136*48828Swilliam 	NOP
137*48828Swilliam 
138*48828Swilliam 	/* need more blocks to be read in? */
139*48828Swilliam 
140*48828Swilliam 	cmpl	$ RELOC+16*512-1,%edi
141*48828Swilliam 	jl	readblk
142*48828Swilliam 
143*48828Swilliam 	/* for clever bootstrap, dig out boot unit and cylinder */
144*48828Swilliam 
145*48828Swilliam 	movl	$ IO_WD1+wd_cyl_lo,%edx
146*48828Swilliam 	inb	%dx,%al
147*48828Swilliam 	NOP
148*48828Swilliam 	xorl	%ecx,%ecx
149*48828Swilliam 	movb	%al,%cl
150*48828Swilliam 	incl	%edx
151*48828Swilliam 	inb	%dx,%al		/* cyl_hi */
152*48828Swilliam 	NOP
153*48828Swilliam 	movb	%al,%ch
154*48828Swilliam 	pushl	%ecx		/* cyloffset */
155*48828Swilliam 
156*48828Swilliam 	incl	%edx
157*48828Swilliam 	xorl	%eax,%eax
158*48828Swilliam 	inb	%dx,%al		/* sdh */
159*48828Swilliam 	andb	$0x10,%al	/* isolate unit # bit */
160*48828Swilliam 	shrb	$4,%al
161*48828Swilliam 	pushl	%eax		/* unit */
162*48828Swilliam 
163*48828Swilliam 	/* wd controller is major device 0 */
164*48828Swilliam 	xorl	%eax,%eax
165*48828Swilliam 	pushl	%eax		/* bootdev */
166*48828Swilliam 
167*48828Swilliam 	/* sorry, no flags at this point! */
168*48828Swilliam 
169*48828Swilliam 	pushl	$ start
170*48828Swilliam 	ret	/* main (dev, unit, offset) */
171*48828Swilliam 
172*48828Swilliam ebootblkcode:
173*48828Swilliam 
174*48828Swilliam 	/* remaining space usable for a disk label */
175*48828Swilliam 
176*48828Swilliam 	.space	510-223		/* would be nice if .space 512-2-. worked */
177*48828Swilliam 	.word	0xaa55		/* signature -- used by BIOS ROM */
178*48828Swilliam 
179*48828Swilliam ebootblk: 			/* MUST BE EXACTLY 0x200 BIG FOR SURE */
180