xref: /original-bsd/sys/i386/stand/fdbootblk.c (revision 21eed380)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * 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  *	@(#)fdbootblk.c	7.3 (Berkeley) 02/05/92
11  */
12 
13 /*
14  * Initial block boot for AT/386 with typical stupid NEC controller.  Works
15  * only with 3.5 inch diskettes that have 16 or greater sectors/side.  Goal
16  * is to read in sucessive 7.5Kbytes of bootstrap to execute.  No attempt
17  * is made to handle disk errors.
18  */
19 #define	NOP		jmp 1f ; nop ; 1:
20 #define	BIOSRELOC	0x7c00
21 #define	start		0x70400
22 
23 /* Gas does not know about 16 bit opcodes... */
24 
25 	/* step 0 force descriptors to bottom of address space */
26 
27 	.byte 	0xfa			# cli
28 	.byte 	0xb8, 0x30, 0x00	# mov $0x0030, %ax
29 	.byte 	0x8e, 0xd0 		# mov %ax, %ss
30 	.byte 	0xbc, 0x00, 0x01  	# mov $0x0100, %sp
31 
32 	xorl	%eax,%eax
33 	movl	%ax,%ds
34 	movl	%ax,%es
35 
36 	/* step 1 load new descriptor table */
37 
38 	.byte 	0x2e			# seg cs
39 	.byte 	0x0f, 0x01, 0x16	# lgdt DS:d16
40 	.word	BIOSRELOC + 0x4a	# [BIOSRELOC + GDTptr]
41 
42 	/* step 2 turn on protected mode */
43 
44 	smsw	%ax
45 	orb	$1,%al
46 	lmsw	%ax
47 	jmp	1f
48 	nop
49 
50  1:
51 	/* step 3  reload segment descriptors */
52 
53 	xorl	%eax,%eax
54 	movb	$0x10,%al
55 	movl	%ax,%ds
56 	movl	%ax,%es
57 	movl	%ax,%ss
58 	word
59 	ljmp	$0x8, $ BIOSRELOC + 0x59 # [BIOSRELOC + reloc]
60 
61  /*
62   * Global Descriptor Table contains three descriptors:
63   * 0x00: Null: not used
64   * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes
65   * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes
66   *		(overlays code)
67   */
68 GDT:
69 NullDsc:.word	0,0,0,0	# null descriptor - not used
70 CodeDsc:.word	0xFFFF	# limit at maximum: (bits 15:0)
71 	.byte	0,0,0	# base at 0: (bits 23:0)
72 	.byte	0x9f	# present/priv level 0/code/conforming/readable
73 	.byte	0xcf	# page granular/default 32-bit/limit(bits 19:16)
74 	.byte	0	# base at 0: (bits 31:24)
75 DataDsc:.word	0xFFFF	# limit at maximum: (bits 15:0)
76 	.byte	0,0,0	# base at 0: (bits 23:0)
77 	.byte	0x93	# present/priv level 0/data/expand-up/writeable
78 	.byte	0xcf	# page granular/default 32-bit/limit(bits 19:16)
79 	.byte	0	# base at 0: (bits 31:24)
80 
81 /*
82  * Global Descriptor Table pointer
83  *  contains 6-byte pointer information for LGDT
84  */
85 GDTptr:	.word	0x17	# limit to three 8 byte selectors(null,code,data)
86 	.long 	BIOSRELOC + 0x32	# [BIOSRELOC + GDT]
87 
88 readcmd: .byte 0xe6, 0x00, 0x00, 0x00, 0x00, 0x02, 18, 0x1b, 0xff
89 
90 	/* step 4 relocate to final bootstrap address. */
91 reloc:
92 	movl	$ BIOSRELOC,%esi
93 	movl	$ RELOC,%edi
94 	movl	$512,%ecx
95 	rep
96 	movsb
97 	pushl	$dodisk
98 	ret
99 
100 	/* step 5 load remaining 15 sectors off disk */
101 dodisk:
102 	movl	$0x70200,%edi
103 	xorl	%ebx,%ebx
104 	incb	%bl
105 	incb	%bl
106 	movb	$0x20,%al	# do a eoi
107 	outb	%al,$0x20
108 
109 	NOP
110 	movb	$0x07,%al
111 	outb	%al,$0x21
112 	NOP
113  8:
114 	movb	%bl,readcmd+4
115 	movl	%edi,%ecx
116 
117 	/* Set read/write bytes */
118 	xorl	%edx,%edx
119 	movb	$0x0c,%dl	# outb(0xC,0x46); outb(0xB,0x46);
120 	movb	$0x46,%al
121 	outb	%al,%dx
122 	NOP
123 	decb	%dx
124 	outb	%al,%dx
125 
126 	/* Send start address */
127 	movb	$0x04,%dl	# outb(0x4, addr);
128 	movb	%cl,%al
129 	outb	%al,%dx
130 	NOP
131 	movb	%ch,%al		# outb(0x4, addr>>8);
132 	outb	%al,%dx
133 	NOP
134 	rorl	$8,%ecx		# outb(0x81, addr>>16);
135 	movb	%ch,%al
136 	outb	%al,$0x81
137 	NOP
138 
139 	/* Send count */
140 	movb	$0x05,%dl	# outb(0x5, 0);
141 	xorl	%eax,%eax
142 	outb	%al,%dx
143 	NOP
144 	movb	$2,%al		# outb(0x5,2);
145 	outb	%al,%dx
146 	NOP
147 
148 	/* set channel 2 */
149 	# movb	$2,%al		# outb(0x0A,2);
150 	outb	%al,$0x0A
151 	NOP
152 
153 	/* issue read command to fdc */
154 	movw	$0x3f4,%dx
155 	movl	$readcmd,%esi
156 	xorl	%ecx,%ecx
157 	movb	$9,%cl
158 
159  2:	inb	%dx,%al
160 	NOP
161 	testb	$0x80,%al
162 	jz 2b
163 
164 	incb	%dx
165 	movl	(%esi),%al
166 	outb	%al,%dx
167 	NOP
168 	incl	%esi
169 	decb	%dx
170 	loop	 2b
171 
172 	/* watch the icu looking for an interrupt signalling completion */
173 	xorl	%edx,%edx
174 	movb	$0x20,%dl
175  2:	movb	$0xc,%al
176 	outb	%al,%dx
177 	NOP
178 	inb	%dx,%al
179 	NOP
180 	andb	$0x7f,%al
181 	cmpb	$6,%al
182 	jne	2b
183 	movb	$0x20,%al	# do a eoi
184 	outb	%al,%dx
185 	NOP
186 
187 	movl	$0x3f4,%edx
188 	xorl	%ecx,%ecx
189 	movb	$7,%cl
190  2:	inb	%dx,%al
191 	NOP
192 	andb	$0xC0,%al
193 	cmpb	$0xc0,%al
194 	jne	2b
195 	incb	%dx
196 	inb	%dx,%al
197 	decb	%dx
198 	loop	2b
199 
200 	/* extract the status bytes after the read. must we do this? */
201 	addw	$0x200,%edi	# next addr to load to
202 	incb	%bl
203 	cmpb	$16,%bl
204 	jle	8b
205 
206 	/* for clever bootstrap, dig out boot unit and cylinder */
207 	pushl	$0
208 	pushl	$0
209 
210 	/* fd controller is major device 2 */
211 	pushl	$2	/* dev */
212 
213 	/* sorry, no flags at this point! */
214 
215 	pushl $	start
216 	ret	/* main (dev, unit, off) */
217 
218 ebootblkcode:
219 
220 	/* remaining space usable for a disk label */
221 
222 	.space	510-310		/* would be nice if .space 512-2-. worked */
223 	.word	0xaa55		/* signature -- used by BIOS ROM */
224 
225 ebootblk: 			/* MUST BE EXACTLY 0x200 BIG FOR SURE */
226