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