diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /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.S | 176 |
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 | ||
31 | cl_loop: | ||
32 | cmpl $EDD_CL_EQUALS, (%si) | ||
33 | jz found_edd_equals | ||
34 | incl %esi | ||
35 | loop cl_loop | ||
36 | jmp done_cl | ||
37 | found_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 | ||
45 | do_edd_skipmbr: | ||
46 | popl %esi | ||
47 | jmp edd_start | ||
48 | do_edd_off: | ||
49 | popl %esi | ||
50 | jmp edd_done | ||
51 | done_cl: | ||
52 | popl %esi | ||
53 | |||
54 | |||
55 | # Read the first sector of each BIOS disk device and store the 4-byte signature | ||
56 | edd_mbr_sig_start: | ||
57 | movb $0x80, %dl # from device 80 | ||
58 | movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx | ||
59 | edd_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 | ||
86 | edd_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 | ||
113 | edd_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 | |||
120 | edd_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 | |||
134 | edd_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. | ||
141 | edd_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 | |||
163 | edd_legacy_done: | ||
164 | popw %dx | ||
165 | popw %es | ||
166 | movw %si, %ax # increment si | ||
167 | addw $EDDPARMSIZE+EDDEXTSIZE, %ax | ||
168 | movw %ax, %si | ||
169 | |||
170 | edd_next: | ||
171 | incb %dl # increment to next device | ||
172 | cmpb $EDDMAXNR, (EDDNR) # Out of space? | ||
173 | jb edd_check_ext # keep looping | ||
174 | |||
175 | edd_done: | ||
176 | #endif | ||