aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/boot/edd.S
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/i386/boot/edd.S
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/i386/boot/edd.S')
-rw-r--r--arch/i386/boot/edd.S176
1 files changed, 176 insertions, 0 deletions
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
new file mode 100644
index 000000000000..027d6b354ffb
--- /dev/null
+++ b/arch/i386/boot/edd.S
@@ -0,0 +1,176 @@
1/*
2 * BIOS Enhanced Disk Drive support
3 * Copyright (C) 2002, 2003, 2004 Dell, Inc.
4 * by Matt Domsch <Matt_Domsch@dell.com> October 2002
5 * conformant to T13 Committee www.t13.org
6 * projects 1572D, 1484D, 1386D, 1226DT
7 * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
8 * and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
9 * legacy CHS retreival by Patrick J. LoPresti <patl@users.sourceforge.net>
10 * March 2004
11 * Command line option parsing, Matt Domsch, November 2004
12 */
13
14#include <linux/edd.h>
15#include <asm/setup.h>
16
17#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
18 movb $0, (EDD_MBR_SIG_NR_BUF)
19 movb $0, (EDDNR)
20
21# Check the command line for two options:
22# edd=of disables EDD completely (edd=off)
23# edd=sk skips the MBR test (edd=skipmbr)
24 pushl %esi
25 cmpl $0, %cs:cmd_line_ptr
26 jz done_cl
27 movl %cs:(cmd_line_ptr), %esi
28# ds:esi has the pointer to the command line now
29 movl $(COMMAND_LINE_SIZE-7), %ecx
30# loop through kernel command line one byte at a time
31cl_loop:
32 cmpl $EDD_CL_EQUALS, (%si)
33 jz found_edd_equals
34 incl %esi
35 loop cl_loop
36 jmp done_cl
37found_edd_equals:
38# only looking at first two characters after equals
39 addl $4, %esi
40 cmpw $EDD_CL_OFF, (%si) # edd=of
41 jz do_edd_off
42 cmpw $EDD_CL_SKIP, (%si) # edd=sk
43 jz do_edd_skipmbr
44 jmp done_cl
45do_edd_skipmbr:
46 popl %esi
47 jmp edd_start
48do_edd_off:
49 popl %esi
50 jmp edd_done
51done_cl:
52 popl %esi
53
54
55# Read the first sector of each BIOS disk device and store the 4-byte signature
56edd_mbr_sig_start:
57 movb $0x80, %dl # from device 80
58 movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx
59edd_mbr_sig_read:
60 movl $0xFFFFFFFF, %eax
61 movl %eax, (%bx) # assume failure
62 pushw %bx
63 movb $READ_SECTORS, %ah
64 movb $1, %al # read 1 sector
65 movb $0, %dh # at head 0
66 movw $1, %cx # cylinder 0, sector 0
67 pushw %es
68 pushw %ds
69 popw %es
70 movw $EDDBUF, %bx # disk's data goes into EDDBUF
71 pushw %dx # work around buggy BIOSes
72 stc # work around buggy BIOSes
73 int $0x13
74 sti # work around buggy BIOSes
75 popw %dx
76 popw %es
77 popw %bx
78 jc edd_mbr_sig_done # on failure, we're done.
79 movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
80 movl %eax, (%bx) # store success
81 incb (EDD_MBR_SIG_NR_BUF) # note that we stored something
82 incb %dl # increment to next device
83 addw $4, %bx # increment sig buffer ptr
84 cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space?
85 jb edd_mbr_sig_read # keep looping
86edd_mbr_sig_done:
87
88# Do the BIOS Enhanced Disk Drive calls
89# This consists of two calls:
90# int 13h ah=41h "Check Extensions Present"
91# int 13h ah=48h "Get Device Parameters"
92# int 13h ah=08h "Legacy Get Device Parameters"
93#
94# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use
95# in the boot_params at EDDBUF. The first four bytes of which are
96# used to store the device number, interface support map and version
97# results from fn41. The next four bytes are used to store the legacy
98# cylinders, heads, and sectors from fn08. The following 74 bytes are used to
99# store the results from fn48. Starting from device 80h, fn41, then fn48
100# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).
101# Then the pointer is incremented to store the data for the next call.
102# This repeats until either a device doesn't exist, or until EDDMAXNR
103# devices have been stored.
104# The one tricky part is that ds:si always points EDDEXTSIZE bytes into
105# the structure, and the fn41 and fn08 results are stored at offsets
106# from there. This removes the need to increment the pointer for
107# every store, and leaves it ready for the fn48 call.
108# A second one-byte buffer, EDDNR, in the boot_params stores
109# the number of BIOS devices which exist, up to EDDMAXNR.
110# In setup.c, copy_edd() stores both boot_params buffers away
111# for later use, as they would get overwritten otherwise.
112# This code is sensitive to the size of the structs in edd.h
113edd_start:
114 # %ds points to the bootsector
115 # result buffer for fn48
116 movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results
117 # kept just before that
118 movb $0x80, %dl # BIOS device 0x80
119
120edd_check_ext:
121 movb $CHECKEXTENSIONSPRESENT, %ah # Function 41
122 movw $EDDMAGIC1, %bx # magic
123 int $0x13 # make the call
124 jc edd_done # no more BIOS devices
125
126 cmpw $EDDMAGIC2, %bx # is magic right?
127 jne edd_next # nope, next...
128
129 movb %dl, %ds:-8(%si) # store device number
130 movb %ah, %ds:-7(%si) # store version
131 movw %cx, %ds:-6(%si) # store extensions
132 incb (EDDNR) # note that we stored something
133
134edd_get_device_params:
135 movw $EDDPARMSIZE, %ds:(%si) # put size
136 movw $0x0, %ds:2(%si) # work around buggy BIOSes
137 movb $GETDEVICEPARAMETERS, %ah # Function 48
138 int $0x13 # make the call
139 # Don't check for fail return
140 # it doesn't matter.
141edd_get_legacy_chs:
142 xorw %ax, %ax
143 movw %ax, %ds:-4(%si)
144 movw %ax, %ds:-2(%si)
145 # Ralf Brown's Interrupt List says to set ES:DI to
146 # 0000h:0000h "to guard against BIOS bugs"
147 pushw %es
148 movw %ax, %es
149 movw %ax, %di
150 pushw %dx # legacy call clobbers %dl
151 movb $LEGACYGETDEVICEPARAMETERS, %ah # Function 08
152 int $0x13 # make the call
153 jc edd_legacy_done # failed
154 movb %cl, %al # Low 6 bits are max
155 andb $0x3F, %al # sector number
156 movb %al, %ds:-1(%si) # Record max sect
157 movb %dh, %ds:-2(%si) # Record max head number
158 movb %ch, %al # Low 8 bits of max cyl
159 shr $6, %cl
160 movb %cl, %ah # High 2 bits of max cyl
161 movw %ax, %ds:-4(%si)
162
163edd_legacy_done:
164 popw %dx
165 popw %es
166 movw %si, %ax # increment si
167 addw $EDDPARMSIZE+EDDEXTSIZE, %ax
168 movw %ax, %si
169
170edd_next:
171 incb %dl # increment to next device
172 cmpb $EDDMAXNR, (EDDNR) # Out of space?
173 jb edd_check_ext # keep looping
174
175edd_done:
176#endif