Linux-2.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!
This commit is contained in:
176
arch/i386/boot/edd.S
Normal file
176
arch/i386/boot/edd.S
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* BIOS Enhanced Disk Drive support
|
||||
* Copyright (C) 2002, 2003, 2004 Dell, Inc.
|
||||
* by Matt Domsch <Matt_Domsch@dell.com> October 2002
|
||||
* conformant to T13 Committee www.t13.org
|
||||
* projects 1572D, 1484D, 1386D, 1226DT
|
||||
* disk signature read by Matt Domsch <Matt_Domsch@dell.com>
|
||||
* and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
|
||||
* legacy CHS retreival by Patrick J. LoPresti <patl@users.sourceforge.net>
|
||||
* March 2004
|
||||
* Command line option parsing, Matt Domsch, November 2004
|
||||
*/
|
||||
|
||||
#include <linux/edd.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
|
||||
movb $0, (EDD_MBR_SIG_NR_BUF)
|
||||
movb $0, (EDDNR)
|
||||
|
||||
# Check the command line for two options:
|
||||
# edd=of disables EDD completely (edd=off)
|
||||
# edd=sk skips the MBR test (edd=skipmbr)
|
||||
pushl %esi
|
||||
cmpl $0, %cs:cmd_line_ptr
|
||||
jz done_cl
|
||||
movl %cs:(cmd_line_ptr), %esi
|
||||
# ds:esi has the pointer to the command line now
|
||||
movl $(COMMAND_LINE_SIZE-7), %ecx
|
||||
# loop through kernel command line one byte at a time
|
||||
cl_loop:
|
||||
cmpl $EDD_CL_EQUALS, (%si)
|
||||
jz found_edd_equals
|
||||
incl %esi
|
||||
loop cl_loop
|
||||
jmp done_cl
|
||||
found_edd_equals:
|
||||
# only looking at first two characters after equals
|
||||
addl $4, %esi
|
||||
cmpw $EDD_CL_OFF, (%si) # edd=of
|
||||
jz do_edd_off
|
||||
cmpw $EDD_CL_SKIP, (%si) # edd=sk
|
||||
jz do_edd_skipmbr
|
||||
jmp done_cl
|
||||
do_edd_skipmbr:
|
||||
popl %esi
|
||||
jmp edd_start
|
||||
do_edd_off:
|
||||
popl %esi
|
||||
jmp edd_done
|
||||
done_cl:
|
||||
popl %esi
|
||||
|
||||
|
||||
# Read the first sector of each BIOS disk device and store the 4-byte signature
|
||||
edd_mbr_sig_start:
|
||||
movb $0x80, %dl # from device 80
|
||||
movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx
|
||||
edd_mbr_sig_read:
|
||||
movl $0xFFFFFFFF, %eax
|
||||
movl %eax, (%bx) # assume failure
|
||||
pushw %bx
|
||||
movb $READ_SECTORS, %ah
|
||||
movb $1, %al # read 1 sector
|
||||
movb $0, %dh # at head 0
|
||||
movw $1, %cx # cylinder 0, sector 0
|
||||
pushw %es
|
||||
pushw %ds
|
||||
popw %es
|
||||
movw $EDDBUF, %bx # disk's data goes into EDDBUF
|
||||
pushw %dx # work around buggy BIOSes
|
||||
stc # work around buggy BIOSes
|
||||
int $0x13
|
||||
sti # work around buggy BIOSes
|
||||
popw %dx
|
||||
popw %es
|
||||
popw %bx
|
||||
jc edd_mbr_sig_done # on failure, we're done.
|
||||
movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
|
||||
movl %eax, (%bx) # store success
|
||||
incb (EDD_MBR_SIG_NR_BUF) # note that we stored something
|
||||
incb %dl # increment to next device
|
||||
addw $4, %bx # increment sig buffer ptr
|
||||
cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space?
|
||||
jb edd_mbr_sig_read # keep looping
|
||||
edd_mbr_sig_done:
|
||||
|
||||
# Do the BIOS Enhanced Disk Drive calls
|
||||
# This consists of two calls:
|
||||
# int 13h ah=41h "Check Extensions Present"
|
||||
# int 13h ah=48h "Get Device Parameters"
|
||||
# int 13h ah=08h "Legacy Get Device Parameters"
|
||||
#
|
||||
# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use
|
||||
# in the boot_params at EDDBUF. The first four bytes of which are
|
||||
# used to store the device number, interface support map and version
|
||||
# results from fn41. The next four bytes are used to store the legacy
|
||||
# cylinders, heads, and sectors from fn08. The following 74 bytes are used to
|
||||
# store the results from fn48. Starting from device 80h, fn41, then fn48
|
||||
# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).
|
||||
# Then the pointer is incremented to store the data for the next call.
|
||||
# This repeats until either a device doesn't exist, or until EDDMAXNR
|
||||
# devices have been stored.
|
||||
# The one tricky part is that ds:si always points EDDEXTSIZE bytes into
|
||||
# the structure, and the fn41 and fn08 results are stored at offsets
|
||||
# from there. This removes the need to increment the pointer for
|
||||
# every store, and leaves it ready for the fn48 call.
|
||||
# A second one-byte buffer, EDDNR, in the boot_params stores
|
||||
# the number of BIOS devices which exist, up to EDDMAXNR.
|
||||
# In setup.c, copy_edd() stores both boot_params buffers away
|
||||
# for later use, as they would get overwritten otherwise.
|
||||
# This code is sensitive to the size of the structs in edd.h
|
||||
edd_start:
|
||||
# %ds points to the bootsector
|
||||
# result buffer for fn48
|
||||
movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results
|
||||
# kept just before that
|
||||
movb $0x80, %dl # BIOS device 0x80
|
||||
|
||||
edd_check_ext:
|
||||
movb $CHECKEXTENSIONSPRESENT, %ah # Function 41
|
||||
movw $EDDMAGIC1, %bx # magic
|
||||
int $0x13 # make the call
|
||||
jc edd_done # no more BIOS devices
|
||||
|
||||
cmpw $EDDMAGIC2, %bx # is magic right?
|
||||
jne edd_next # nope, next...
|
||||
|
||||
movb %dl, %ds:-8(%si) # store device number
|
||||
movb %ah, %ds:-7(%si) # store version
|
||||
movw %cx, %ds:-6(%si) # store extensions
|
||||
incb (EDDNR) # note that we stored something
|
||||
|
||||
edd_get_device_params:
|
||||
movw $EDDPARMSIZE, %ds:(%si) # put size
|
||||
movw $0x0, %ds:2(%si) # work around buggy BIOSes
|
||||
movb $GETDEVICEPARAMETERS, %ah # Function 48
|
||||
int $0x13 # make the call
|
||||
# Don't check for fail return
|
||||
# it doesn't matter.
|
||||
edd_get_legacy_chs:
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ds:-4(%si)
|
||||
movw %ax, %ds:-2(%si)
|
||||
# Ralf Brown's Interrupt List says to set ES:DI to
|
||||
# 0000h:0000h "to guard against BIOS bugs"
|
||||
pushw %es
|
||||
movw %ax, %es
|
||||
movw %ax, %di
|
||||
pushw %dx # legacy call clobbers %dl
|
||||
movb $LEGACYGETDEVICEPARAMETERS, %ah # Function 08
|
||||
int $0x13 # make the call
|
||||
jc edd_legacy_done # failed
|
||||
movb %cl, %al # Low 6 bits are max
|
||||
andb $0x3F, %al # sector number
|
||||
movb %al, %ds:-1(%si) # Record max sect
|
||||
movb %dh, %ds:-2(%si) # Record max head number
|
||||
movb %ch, %al # Low 8 bits of max cyl
|
||||
shr $6, %cl
|
||||
movb %cl, %ah # High 2 bits of max cyl
|
||||
movw %ax, %ds:-4(%si)
|
||||
|
||||
edd_legacy_done:
|
||||
popw %dx
|
||||
popw %es
|
||||
movw %si, %ax # increment si
|
||||
addw $EDDPARMSIZE+EDDEXTSIZE, %ax
|
||||
movw %ax, %si
|
||||
|
||||
edd_next:
|
||||
incb %dl # increment to next device
|
||||
cmpb $EDDMAXNR, (EDDNR) # Out of space?
|
||||
jb edd_check_ext # keep looping
|
||||
|
||||
edd_done:
|
||||
#endif
|
Reference in New Issue
Block a user