From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Wed, 4 Sep 2002 00:31:53 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Wed, 4 Sep 2002 00:31:53 -0400 Received: from astound-64-85-224-253.ca.astound.net ([64.85.224.253]:9221 "EHLO master.linux-ide.org") by vger.kernel.org with ESMTP id ; Wed, 4 Sep 2002 00:31:41 -0400 Date: Tue, 3 Sep 2002 21:35:51 -0700 (PDT) From: Andre Hedrick To: Matt Domsch cc: linux-kernel@vger.kernel.org Subject: Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org WOOHOO! This looks like some serious fun to make it go! Matt, how about a location for a normal patch for those of us who do not believe in BK. On Tue, 3 Sep 2002, Matt Domsch wrote: > x86 systems suffer from a disconnect between what BIOS believes is the > boot disk, and what Linux thinks BIOS thinks is the boot disk. BIOS > Enhanced Disk Device Services (EDD) 3.0 provides the ability for disk > adapter BIOSs to tell the OS what it believes is the boot disk. While > this isn't widely implemented in BIOSs yet (thus shouldn't be > completely trusted), it's time that Linux received support to be > ready as BIOSs with this feature do become available. > > EDD works by providing the bus (PCI, PCI-X, ISA, InfiniBand, PCI > Express, or HyperTransport) location (e.g. PCI 02:01.0) and interface > (ATAPI, ATA, SCSI, USB, 1394, FibreChannel, I2O, RAID, SATA) location > (e.g. SCSI ID 5 LUN 0) information for each BIOS int13 device. The > patch below creates CONFIG_EDD, that when defined, makes the calls to > retrieve and store this information. It then exports it (yes, another > /proc, glad to change it to driverfs or whatever else when that makes > sense) in /proc/edd/{bios-device-number}, as such: > > # ls /proc/edd/ > 80 81 82 83 84 85 > > # cat /proc/edd/80 > host_bus_type: PCI 02:01.0 channel: 0 > interface_type: SCSI id: 0 lun: 0 > > Warning: Spec violation. Key should be 0xBEDD, is 0xDDBE > Warning: Spec violation. Padding should be 0x20, is 0x00 > > # cat /proc/edd/81 > host_bus_type: PCI 04:00.0 channel: 0 > interface_type: SCSI id: 0 lun: 0 > > Warning: Spec violation. Device Path checksum invalid (0x4b should be 0x00). > > In the above case, BIOS int13 device 80 (the boot disk) believes it is > on PCI 02:01.0, SCSI bus 0, ID 0 LUN 0 (in this case it's an Adaptec > 39160 add-in card). Likewise, device 81 believes it's at PCI 04:00.0, > channel 0, ID 0, LUN 0 (a Dell PERC3/QC card). In both cases the BIOS > vendors have some cleanup work to do, so I warn when they don't adhere > to the spec. > > It's possible to query device drivers from user-space (either via a > SCSI ioctl, or IDE /proc/ide/*/config), to compare results to > determine which disk is the boot disk. > > At most 6 BIOS devices are reported, as that fills the space that's > left in the empty_zero_page. In general you only care about device > 80h, though for software RAID1 knowing what 81h is might be useful also. > > The major changes implemented in this patch: > arch/i386/boot/setup.S - int13 real mode calls store results in empty_zero_page > arch/i386/kernel/setup.c - copy results from empty_zero_page to local > storage > arch/i386/kernel/edd.c - export results via /proc/edd/ > > If you use this, please send reports of success/failure, and the > adapter types and BIOS versions, to edd30@domsch.com. I'm keeping a > tally at http://domsch.com/linux/edd30/results.html. If built as > CONFIG_EDD=m, please 'modprobe edd debug=1' and send those results - > it's more verbose. > > Patch below applies to BK-current 2.5.x. Also available in BitKeeper > at http://mdomsch.bkbits.net/linux-2.5-edd > > Feedback appreciated. > > > Thanks, > Matt > > -- > Matt Domsch > Sr. Software Engineer, Lead Engineer, Architect > Dell Linux Solutions www.dell.com/linux > Linux on Dell mailing lists @ http://lists.us.dell.com > #1 US Linux Server provider for 2001 and Q1-2/2002! (IDC Aug 2002) > > You can import this changeset into BK by piping this whole message to > '| bk receive [path to repository]' or apply the patch as usual. > > =================================================================== > > > ChangeSet@1.582, 2002-09-03 15:05:38-05:00, Matt_Domsch@dell.com > Initial release of x86 BIOS Enhanced Disk Device (EDD) polling > > > Documentation/i386/zero-page.txt | 2 > arch/i386/Config.help | 10 > arch/i386/boot/setup.S | 46 +++ > arch/i386/config.in | 4 > arch/i386/defconfig | 1 > arch/i386/kernel/Makefile | 1 > arch/i386/kernel/edd.c | 455 +++++++++++++++++++++++++++++++++++++++ > arch/i386/kernel/i386_ksyms.c | 6 > arch/i386/kernel/setup.c | 23 + > include/asm-i386/edd.h | 162 +++++++++++++ > 10 files changed, 710 insertions > > > diff -Nru a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt > --- a/Documentation/i386/zero-page.txt Tue Sep 3 15:06:13 2002 > +++ b/Documentation/i386/zero-page.txt Tue Sep 3 15:06:13 2002 > @@ -31,6 +31,7 @@ > > 0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb > 0x1e8 char number of entries in E820MAP (below) > +0x1e9 unsigned char number of entries in EDDBUF (below) > 0x1f1 char size of setup.S, number of sectors > 0x1f2 unsigned short MOUNT_ROOT_RDONLY (if !=0) > 0x1f4 unsigned short size of compressed kernel-part in the > @@ -66,6 +67,7 @@ > 0x220 4 bytes (setup.S) > 0x224 unsigned short setup.S heap end pointer > 0x2d0 - 0x600 E820MAP > +0x600 - 0x7D4 EDDBUF (setup.S) > > 0x800 string, 2K max COMMAND_LINE, the kernel commandline as > copied using CL_OFFSET. > diff -Nru a/arch/i386/Config.help b/arch/i386/Config.help > --- a/arch/i386/Config.help Tue Sep 3 15:06:13 2002 > +++ b/arch/i386/Config.help Tue Sep 3 15:06:13 2002 > @@ -967,3 +967,13 @@ > absence of features. > > For more information take a look at Documentation/swsusp.txt. > + > +CONFIG_EDD > + Say Y or M here if you want to enable BIOS Enhanced Disk Device > + Services real mode BIOS calls to determine which disk > + BIOS tries boot from. This feature creates a /proc/edd directory > + and files for each BIOS device detected. > + > + This option is experimental, and most disk controller BIOS > + vendors do not yet implement this feature. > + > diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S > --- a/arch/i386/boot/setup.S Tue Sep 3 15:06:13 2002 > +++ b/arch/i386/boot/setup.S Tue Sep 3 15:06:13 2002 > @@ -44,6 +44,8 @@ > * > * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes > * by Robert Schwebel, December 2001 > + * > + * BIOS EDD support September 2002 by Matt Domsch > * > */ > > @@ -53,6 +55,7 @@ > #include > #include > #include > +#include > #include > > /* Signature words to ensure LILO loaded us right */ > @@ -541,6 +544,49 @@ > no_32_apm_bios: > andw $0xfffd, (76) # remove 32 bit support bit > done_apm_bios: > +#endif > + > +#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) > +# Do the BIOS EDD calls > +# 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 $0, (EDDNR) # zero value at EDDNR > + movb $0x80, %dl # BIOS device 0x80 > + > +edd_check_ext: > + movb $0x41, %ah # Function 41 > + movw $0x55aa, %bx # magic > + int $0x13 # make the call > + jc edd_done # no more BIOS devices > + > + cmpw $0xAA55, %bx # is magic right? > + jne edd_next # nope, next... > + > + movb %dl, %ds:-4(%si) # store device number > + movb %ah, %ds:-3(%si) # store version > + movw %cx, %ds:-2(%si) # store extensions > + incb (EDDNR) # note that we stored something > + > +edd_get_device_params: > + movw $EDDPARMSIZE, %ds:(%si) # put size > + movb $0x48, %ah # Function 48 > + int $0x13 # make the call > + # Don't check for fail return > + # it doesn't matter. > + 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 > > # Now we want to move to protected mode ... > diff -Nru a/arch/i386/config.in b/arch/i386/config.in > --- a/arch/i386/config.in Tue Sep 3 15:06:13 2002 > +++ b/arch/i386/config.in Tue Sep 3 15:06:13 2002 > @@ -181,6 +181,10 @@ > tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR > tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID > > +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then > + tristate 'BIOS Enhanced Disk Device calls determine boot disk (EXPERIMENTAL)' CONFIG_EDD > +fi > + > choice 'High Memory Support' \ > "off CONFIG_NOHIGHMEM \ > 4GB CONFIG_HIGHMEM4G \ > diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig > --- a/arch/i386/defconfig Tue Sep 3 15:06:13 2002 > +++ b/arch/i386/defconfig Tue Sep 3 15:06:13 2002 > @@ -69,6 +69,7 @@ > # CONFIG_MICROCODE is not set > # CONFIG_X86_MSR is not set > # CONFIG_X86_CPUID is not set > +# CONFIG_EDD is not set > CONFIG_NOHIGHMEM=y > # CONFIG_HIGHMEM4G is not set > # CONFIG_HIGHMEM64G is not set > diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile > --- a/arch/i386/kernel/Makefile Tue Sep 3 15:06:13 2002 > +++ b/arch/i386/kernel/Makefile Tue Sep 3 15:06:13 2002 > @@ -25,6 +25,7 @@ > obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o > obj-$(CONFIG_X86_IO_APIC) += io_apic.o > obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o > +obj-$(CONFIG_EDD) += edd.o > ifdef CONFIG_VISWS > obj-y += setup-visws.o > obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o > diff -Nru a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c > --- /dev/null Wed Dec 31 16:00:00 1969 > +++ b/arch/i386/kernel/edd.c Tue Sep 3 15:06:13 2002 > @@ -0,0 +1,455 @@ > +/* > + * BIOS Enhanced Disk Device Services > + * > + * Copyright (C) 2002 Dell Computer Corporation > + * > + * This code takes information provided by BIOS EDD calls > + * made in setup.S, copied to safe structures in setup.c, > + * and presents it in /proc/edd/{bios_device_number}. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License v2.0 as published by > + * the Free Software Foundation > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +MODULE_AUTHOR("Matt Domsch "); > +MODULE_DESCRIPTION("/proc interface to BIOS EDD information"); > +MODULE_LICENSE("GPL"); > + > +static int debug; > +MODULE_PARM(debug, "i"); > +MODULE_PARM_DESC(debug, "Enable additional verbose debug output."); > + > +#define EDD_VERSION "0.01 2002-Sep-03" > + > +/* Don't need to keep a pointer to edd_info here because > + it will get passed in to edd_read for us. > +*/ > +struct edd_proc_info { > + struct proc_dir_entry *entry; > + struct list_head list; > +}; > + > +static LIST_HEAD(edd_list); > +static spinlock_t edd_lock = SPIN_LOCK_UNLOCKED; /* protects edd_list */ > +static struct proc_dir_entry *edd_dir; > + > +#define edd_entry(n) list_entry(n, struct edd_proc_info, list) > + > + > + > +static int > +proc_calc_metrics(char *page, char **start, off_t off, > + int count, int *eof, int len) > +{ > + if (len <= off+count) *eof = 1; > + *start = page + off; > + len -= off; > + if (len>count) len = count; > + if (len<0) len = 0; > + return len; > +} > + > +static int > +edd_dump_raw_data(char *b, void *data, int length) > +{ > + char *orig_b = b; > + char buffer1[80], buffer2[80], *b1, *b2, c; > + unsigned char *p = data; > + unsigned long column=0; > + int length_printed = 0; > + const char maxcolumn = 16; > + while (length_printed < length) { > + b1 = buffer1; > + b2 = buffer2; > + for (column = 0; > + column < maxcolumn && length_printed < length; > + column ++) { > + b1 += sprintf(b1, "%02x ",(unsigned char) *p); > + if (*p < 32 || *p > 126) c = '.'; > + else c = *p; > + b2 += sprintf(b2, "%c", c); > + p++; > + length_printed++; > + } > + /* pad out the line */ > + for (; column < maxcolumn; column++) > + { > + b1 += sprintf(b1, " "); > + b2 += sprintf(b2, " "); > + } > + > + b += sprintf(b, "%s\t%s\n", buffer1, buffer2); > + } > + return (b - orig_b); > +} > + > + > +/*** > + * edd_read() - exports EDD information to /proc/edd/{device_number} > + * > + * Returns: number of bytes written, or -EINVAL on failure > + */ > +static int > +edd_read(char *page, char **start, off_t off, int count, int *eof, void *data) > +{ > + int len = 0; > + struct edd_info *edd=(struct edd_info *)data; > + int i, warn_padding=0, nonzero_path=0, warn_key=0, warn_checksum=0; > + uint8_t checksum=0, c=0; > + char *p = page; > + enum _bus_type {bus_type_unknown, > + isa, pci, pcix, > + ibnd, xprs, htpt} bus_type = bus_type_unknown; > + enum _interface_type {interface_type_unknown, > + ata, atapi, scsi, usb, > + i1394, fibre, i2o, raid, sata} > + interface_type = interface_type_unknown; > + > + if (!data) { > + *eof=1; > + return 0; > + } > + > + MOD_INC_USE_COUNT; > + > + if (debug) { > + p += edd_dump_raw_data(p, edd, sizeof(*edd)); > + > + p += sprintf(p, "version: "); > + switch (edd->version) { > + case 0x0: > + p += sprintf(p, "unsupported\n"); > + case 0x21: > + p += sprintf(p, "1.1\n"); > + break; > + case 0x30: > + p += sprintf(p, "3.0\n"); > + break; > + default: > + p += sprintf(p, "(unknown version %xh)\n", > + edd->version); > + break; > + } > + > + p += sprintf(p, "Extensions:\n"); > + if (edd->interface_support & EDD_EXT_FIXED_DISK_ACCESS) { > + p += sprintf(p, "\tFixed disk access\n"); > + } > + if (edd->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) { > + p += sprintf(p, "\tDevice locking and ejecting\n"); > + } > + if (edd->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) { > + p += sprintf(p, "\tEnhanced Disk Drive support\n"); > + } > + if (edd->interface_support & EDD_EXT_64BIT_EXTENSIONS) { > + p += sprintf(p, "\t64-bit extensions\n"); > + } > + > + p += sprintf(p, "Info Flags:\n"); > + if (edd->params.info_flags & EDD_INFO_DMA_BOUNDRY_ERROR_TRANSPARENT) > + p += sprintf(p, "\tdma_boundry_error_transparent\n"); > + if (edd->params.info_flags & EDD_INFO_GEOMETRY_VALID) > + p += sprintf(p, "\tgeometry_valid\n"); > + if (edd->params.info_flags & EDD_INFO_REMOVABLE) > + p += sprintf(p, "\tremovable\n"); > + if (edd->params.info_flags & EDD_INFO_WRITE_VERIFY) > + p += sprintf(p, "\twrite_verify\n"); > + if (edd->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION) > + p += sprintf(p, "\tmedia_change_notification\n"); > + if (edd->params.info_flags & EDD_INFO_LOCKABLE) > + p += sprintf(p, "\tlockable\n"); > + if (edd->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT) > + p += sprintf(p, "\tno_media_present\n"); > + if (edd->params.info_flags & EDD_INFO_USE_INT13_FN50) > + p += sprintf(p, "\tuse_int13_fn50\n"); > + > + p += sprintf(p, "num_default_cylinders: %x\n", > + edd->params.num_default_cylinders); > + p += sprintf(p, "num_default_heads: %x\n", edd->params.num_default_heads); > + p += sprintf(p, "sectors_per_track: %x\n", edd->params.sectors_per_track); > + p += sprintf(p, "number_of_sectors: %llx\n", > + edd->params.number_of_sectors); > + } /* if (debug) */ > + > + /* Spec violation here. Adaptec AIC7899 returns 0xDDBE > + here, when it should be (per spec) 0xBEDD. > + */ > + if (edd->params.key == 0xDDBE) { > + warn_key=1; > + } > + > + if (! (edd->params.key == 0xBEDD || edd->params.key == 0xDDBE)) { > + len = (p + 1 - page); > + MOD_DEC_USE_COUNT; > + return proc_calc_metrics(page, start, off, count, eof, len); > + } > + > + for (i=30; i<=73; i++) { > + c = *(((uint8_t *)edd)+i+4); > + if (c) nonzero_path++; > + checksum += c; > + } > + if (checksum) { > + warn_checksum=1; > + if (!nonzero_path) { > + p += sprintf(p, "Warning: Spec violation. Device Path checksum invalid (0x%02x should be 0x00).\n", checksum); > + len = (p + 1 - page); > + MOD_DEC_USE_COUNT; > + return proc_calc_metrics(page, start, off, count, eof, len); > + } > + } > + > + > + /* Spec violation here. Adaptec AIC7899 has 0x00 (NULL) bytes for > + padding instead of 0x20 (space) bytes. */ > + > + p += sprintf(p, "host_bus: "); > + for (i=0; i<4; i++) { > + if (isprint(edd->params.host_bus_type[i])) { > + p += sprintf(p, "%c", edd->params.host_bus_type[i]); > + } else { > + p += sprintf(p, " "); > + warn_padding++; > + } > + > + > + } > + > + /* Print interface path information */ > + if (!strncmp(edd->params.host_bus_type, "ISA", 3)) { > + bus_type = isa; > + } else if (!strncmp(edd->params.host_bus_type, "PCIX", 4)) { > + bus_type = pcix; > + } else if (!strncmp(edd->params.host_bus_type, "PCI", 3)) { > + bus_type = pci; > + } else if (!strncmp(edd->params.host_bus_type, "IBND", 4)) { > + bus_type = ibnd; > + } else if (!strncmp(edd->params.host_bus_type, "XPRS", 4)) { > + bus_type = xprs; > + } else if (!strncmp(edd->params.host_bus_type, "HTPT", 4)) { > + bus_type = htpt; > + } > + switch (bus_type) { > + case isa: > + p += sprintf(p, "\tbase_address: %x\n", > + edd->params.interface_path.isa.base_address); > + break; > + case pci: > + case pcix: > + p += sprintf(p, > + "\t%02x:%02x.%01x channel: %x\n", > + edd->params.interface_path.pci.bus, > + edd->params.interface_path.pci.slot, > + edd->params.interface_path.pci.function, > + edd->params.interface_path.pci.channel); > + break; > + case ibnd: > + case xprs: > + case htpt: > + p += sprintf(p, > + "\tTBD: %llx\n", > + edd->params.interface_path.ibnd.reserved); > + break; > + default: > + p += sprintf(p, "\tunknown: %llx\n", > + edd->params.interface_path.unknown.reserved); > + break; > + } > + > + /* Spec violation here. Adaptec AIC7899 has 0x00 (NULL) bytes for > + padding instead of 0x20 (space) bytes. */ > + /* Print device path information */ > + p += sprintf(p, "interface: "); > + for (i=0; i<8; i++) { > + if (isprint(edd->params.interface_type[i])) { > + p += sprintf(p, "%c", edd->params.interface_type[i]); > + } else { > + p += sprintf(p, " "); > + warn_padding++; > + } > + } > + if (!strncmp(edd->params.interface_type, "ATAPI", 5)) { > + interface_type = atapi; > + } else if (!strncmp(edd->params.interface_type, "ATA", 3)) { > + interface_type = ata; > + } else if (!strncmp(edd->params.interface_type, "SCSI", 4)) { > + interface_type = scsi; > + } else if (!strncmp(edd->params.interface_type, "USB", 3)) { > + interface_type = usb; > + } else if (!strncmp(edd->params.interface_type, "1394", 4)) { > + interface_type = i1394; > + } else if (!strncmp(edd->params.interface_type, "FIBRE", 5)) { > + interface_type = fibre; > + } else if (!strncmp(edd->params.interface_type, "I2O", 3)) { > + interface_type = i2o; > + } else if (!strncmp(edd->params.interface_type, "RAID", 4)) { > + interface_type = raid; > + } else if (!strncmp(edd->params.interface_type, "SATA", 4)) { > + interface_type = sata; > + } > + > + > + switch (interface_type) { > + case ata: > + p += sprintf(p, "\tdevice: %x\n", > + edd->params.device_path.ata.device); > + break; > + case atapi: > + p += sprintf(p, "\tdevice: %x lun: %x\n", > + edd->params.device_path.atapi.device, > + edd->params.device_path.atapi.lun); > + break; > + case scsi: > + p += sprintf(p, "\tid: %x lun: %llx\n", > + edd->params.device_path.scsi.id, > + edd->params.device_path.scsi.lun); > + break; > + case usb: > + p += sprintf(p, "\tserial_number: %llx\n", > + edd->params.device_path.usb.serial_number); > + break; > + case i1394: > + p += sprintf(p, "\teui: %llx\n", > + edd->params.device_path.i1394.eui); > + break; > + case fibre: > + p += sprintf(p, "\twwid: %llx lun: %llx\n", > + edd->params.device_path.fibre.wwid, > + edd->params.device_path.fibre.lun); > + break; > + case i2o: > + p += sprintf(p, "\tidentity_tag: %llx\n", > + edd->params.device_path.i2o.identity_tag); > + break; > + case raid: > + p += sprintf(p, "\tidentity_tag: %x\n", > + edd->params.device_path.raid.array_number); > + break; > + case sata: > + p += sprintf(p, "\tdevice: %x\n", > + edd->params.device_path.sata.device); > + break; > + default: > + p += sprintf(p, "\tunknown: %llx %llx\n", > + edd->params.device_path.unknown.reserved1, > + edd->params.device_path.unknown.reserved2); > + > + } > + > + p += sprintf(p, "\n"); > + if (warn_key) { > + p += sprintf(p, "Warning: Spec violation. Key should be 0xBEDD, is 0xDDBE\n"); > + } > + if (warn_padding) { > + p += sprintf(p, "Warning: Spec violation. Padding should be 0x20, is 0x00\n"); > + } > + if (warn_checksum) { > + p += sprintf(p, "Warning: Spec violation. Device Path checksum invalid (0x%02x should be 0x00).\n", checksum); > + } > + > + len = (p + 1 - page); > + > + MOD_DEC_USE_COUNT; > + > + return proc_calc_metrics(page, start, off, count, eof, len); > +} > + > +/** > + * edd_create_proc_entry() > + * > + * Returns 1 on failure, 0 on success > + */ > +static int > +edd_create_proc_entry(struct edd_info *info) > +{ > + > + char name[4]; > + struct edd_proc_info *new_proc_info; > + > + if (!info || !info->device) return 1; > + new_proc_info = kmalloc(sizeof(*new_proc_info), > + GFP_KERNEL); > + > + if (!new_proc_info) return 1; > + memset(new_proc_info, 0, sizeof(*new_proc_info)); > + > + snprintf(name, 4, "%02x", info->device); > + > + /* Create the entry in proc */ > + new_proc_info->entry = create_proc_read_entry(name, 0444, edd_dir, edd_read, info); > + if (!new_proc_info->entry) { > + kfree(new_proc_info); > + return 1; > + } > + spin_lock(&edd_lock); > + list_add(&new_proc_info->list, &edd_list); > + spin_unlock(&edd_lock); > + > + return 0; > +} > + > + > + > +/** > + * edd_init() - creates /proc/edd/{device} tree. > + * > + * This assumes that eddnr and edd were > + * assigned in setup.c already. > + */ > +static int __init > +edd_init(void) > +{ > + > + unsigned int i; > + > + printk(KERN_INFO "BIOS EDD facility v%s, %d devices found\n", EDD_VERSION, eddnr); > + > + if (!eddnr) { > + printk(KERN_INFO "EDD information not available.\n"); > + return 1; > + } > + > + edd_dir = proc_mkdir("edd", edd_dir); > + if (!edd_dir) return 1; > + > + for (i=0; i + edd_create_proc_entry(&edd[i]); > + } > + > + return 0; > +} > + > +static void __exit > +edd_exit(void) > +{ > + struct list_head *pos, *n; > + struct edd_proc_info *proc_info; > + > + spin_lock(&edd_lock); > + list_for_each_safe(pos, n, &edd_list) { > + proc_info = edd_entry(pos); > + remove_proc_entry(proc_info->entry->name, edd_dir); > + list_del(&proc_info->list); > + kfree(proc_info); > + } > + spin_unlock(&edd_lock); > + remove_proc_entry(edd_dir->name, NULL); > +} > + > +late_initcall(edd_init); > +module_exit(edd_exit); > diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c > --- a/arch/i386/kernel/i386_ksyms.c Tue Sep 3 15:06:13 2002 > +++ b/arch/i386/kernel/i386_ksyms.c Tue Sep 3 15:06:13 2002 > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > > extern void dump_thread(struct pt_regs *, struct user *); > extern spinlock_t rtc_lock; > @@ -172,3 +173,8 @@ > EXPORT_SYMBOL(is_sony_vaio_laptop); > > EXPORT_SYMBOL(__PAGE_KERNEL); > + > +#ifdef CONFIG_EDD_MODULE > +EXPORT_SYMBOL(edd); > +EXPORT_SYMBOL(eddnr); > +#endif > diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c > --- a/arch/i386/kernel/setup.c Tue Sep 3 15:06:13 2002 > +++ b/arch/i386/kernel/setup.c Tue Sep 3 15:06:13 2002 > @@ -36,6 +36,7 @@ > #include > #include > #include > +#include > > /* > * Machine setup.. > @@ -106,6 +107,8 @@ > #define KERNEL_START (*(unsigned long *) (PARAM+0x214)) > #define INITRD_START (*(unsigned long *) (PARAM+0x218)) > #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) > +#define EDD_NR (*(unsigned char *) (PARAM+EDDNR)) > +#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF)) > #define COMMAND_LINE ((char *) (PARAM+2048)) > #define COMMAND_LINE_SIZE 256 > > @@ -486,6 +489,25 @@ > return 0; > } > > +#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) > +unsigned char eddnr; > +struct edd_info edd[EDDNR]; > +/** > + * copy_edd() - Copy the BIOS EDD information into a safe place. > + * > + */ > +static inline void copy_edd(void) > +{ > + eddnr = EDD_NR; > + memcpy(edd, EDD_BUF, sizeof(edd)); > +} > +#else > +static inline void copy_edd(void) > +{ > +} > +#endif > + > + > /* > * Do NOT EVER look at the BIOS memory size location. > * It does not work on many machines. > @@ -631,6 +653,7 @@ > rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); > #endif > setup_memory_region(); > + copy_edd(); > > if (!MOUNT_ROOT_RDONLY) > root_mountflags &= ~MS_RDONLY; > diff -Nru a/include/asm-i386/edd.h b/include/asm-i386/edd.h > --- /dev/null Wed Dec 31 16:00:00 1969 > +++ b/include/asm-i386/edd.h Tue Sep 3 15:06:13 2002 > @@ -0,0 +1,162 @@ > +/* > + * linux/include/asm-i386/edd.h > + * by Matt Domsch > + * Copyright 2002 Dell Computer Corporation > + * > + * structures and definitions for the int 13, ax={41,48}h > + * BIOS Enhanced Disk Device Services > + * This is based on the T13 group document D1572 Revision 0 (August 14 2002) > + * available at http://www.t13.org/docs2002/d1572r0.pdf. It is > + * very similar to D1484 Revision 3 http://www.t13.org/docs2002/d1484r3.pdf > + * > + * In a nutshell, arch/i386/boot/setup.S populates a scratch table > + * in the empty_zero_block that contains a list of BIOS-enumerated > + * boot devices. > + * In arch/i386/kernel/setup.c, this information is > + * transferred into the edd structure, and in arch/i386/kernel/edd.c, that > + * information is used to identify BIOS boot disk. The code in setup.S > + * is very sensitive to the size of these structures. > + * > + */ > +#ifndef _ASM_I386_EDD_H > +#define _ASM_I386_EDD_H > + > +#define EDDNR 0x1e9 /* addr of number of edd_info structs at EDDBUF > + in empty_zero_block - treat this as 1 byte */ > +#define EDDBUF 0x600 /* addr of edd_info structs in empty_zero_block */ > +#define EDDMAXNR 6 /* number of edd_info structs starting at EDDBUF */ > +#define EDDEXTSIZE 4 /* change these if you muck with the structures */ > +#define EDDPARMSIZE 74 > + > +#define EDD_EXT_FIXED_DISK_ACCESS (1 << 0) > +#define EDD_EXT_DEVICE_LOCKING_AND_EJECTING (1 << 1) > +#define EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT (1 << 2) > +#define EDD_EXT_64BIT_EXTENSIONS (1 << 3) > + > +#define EDD_INFO_DMA_BOUNDRY_ERROR_TRANSPARENT (1 << 0) > +#define EDD_INFO_GEOMETRY_VALID (1 << 1) > +#define EDD_INFO_REMOVABLE (1 << 2) > +#define EDD_INFO_WRITE_VERIFY (1 << 3) > +#define EDD_INFO_MEDIA_CHANGE_NOTIFICATION (1 << 4) > +#define EDD_INFO_LOCKABLE (1 << 5) > +#define EDD_INFO_NO_MEDIA_PRESENT (1 << 6) > +#define EDD_INFO_USE_INT13_FN50 (1 << 7) > + > + > + > +#ifndef __ASSEMBLY__ > + > +struct edd_device_params { > + u16 length; > + u16 info_flags; > + u32 num_default_cylinders; > + u32 num_default_heads; > + u32 sectors_per_track; > + u64 number_of_sectors; > + u16 bytes_per_sector; > + u32 dpte_ptr; /* 0xFFFFFFFF for our purposes */ > + u16 key; /* = 0xBEDD */ > + u8 device_path_info_length; /* = 44 */ > + u8 reserved2; > + u16 reserved3; > + u8 host_bus_type[4]; > + u8 interface_type[8]; > + union { > + struct { > + u16 base_address; > + u16 reserved1; > + u32 reserved2; > + } __attribute__((packed)) isa; > + struct { > + u8 bus; > + u8 slot; > + u8 function; > + u8 channel; > + u32 reserved; > + } __attribute__((packed)) pci; > + /* pcix is same as pci */ > + struct { > + u64 reserved; > + } __attribute__((packed)) ibnd; > + struct { > + u64 reserved; > + } __attribute__((packed)) xprs; > + struct { > + u64 reserved; > + } __attribute__((packed)) htpt; > + struct { > + u64 reserved; > + } __attribute__((packed)) unknown; > + } interface_path; > + union { > + struct { > + u8 device; > + u8 reserved1; > + u16 reserved2; > + u32 reserved3; > + u64 reserved4; > + } __attribute__((packed)) ata; > + struct { > + u8 device; > + u8 lun; > + u8 reserved1; > + u8 reserved2; > + u32 reserved3; > + u64 reserved4; > + } __attribute__((packed)) atapi; > + struct { > + u16 id; > + u64 lun; > + u16 reserved1; > + u32 reserved2; > + } __attribute__((packed)) scsi; > + struct { > + u64 serial_number; > + u64 reserved; > + } __attribute__((packed)) usb; > + struct { > + u64 eui; > + u64 reserved; > + } __attribute__((packed)) i1394; > + struct { > + u64 wwid; > + u64 lun; > + } __attribute__((packed)) fibre; > + struct { > + u64 identity_tag; > + u64 reserved; > + } __attribute__((packed)) i2o; > + struct { > + u32 array_number; > + u32 reserved1; > + u64 reserved2; > + } __attribute((packed)) raid; > + struct { > + u8 device; > + u8 reserved1; > + u16 reserved2; > + u32 reserved3; > + u64 reserved4; > + } __attribute__((packed)) sata; > + struct { > + u64 reserved1; > + u64 reserved2; > + } __attribute__((packed)) unknown; > + } device_path; > + u8 reserved4; > + u8 checksum; > +} __attribute__((packed)); > + > +struct edd_info { > + u8 device; > + u8 version; > + u16 interface_support; > + struct edd_device_params params; > +} __attribute__((packed)); > + > +extern struct edd_info edd[EDDNR]; > +extern unsigned char eddnr; > +#endif/*!__ASSEMBLY__*/ > + > +#endif /* _ASM_I386_EDD_H */ > + > > =================================================================== > > > This BitKeeper patch contains the following changesets: > 1.582 > ## Wrapped with gzip_uu ## > > > begin 664 bkpatch29651 > M'XL(`#46=3T``\P\_7/B-M,_A[]"3:=7R!'P!Y_)Y:8$R!WO)20#Y'I]>AV/ > ML47P&V,SMDG"4_*_/[N2##;8"83K3&F/V+*T7]I=[ M[L0WQIF?R6?7#TX.3&K;!<.=0$//=:&A.'8GM#@Q6;?B\+YH6\[LZ5@IE(^I > M:6:@WXT>&&/R0#W_Y$`NJ,N68#ZE)P>]]J?;RT8ODSD[(\VQ[MS1/@W(V5DF > M<+T'W3;]W_1@;+M.(?!TQY_00$?TBV77A2))"OQ7EJNJ5*XLY(I4JBX,V91E > MO2134U)*M4HIX^GS8_O^MXEN>OIP:`4%U[M;!U*79$4IUZ3Z0I6JDIII$;E0 > MKBE$4HI2O2BI1"Z?2.43M78,WY)$(O+Y+90+>2]+Y%C*G),?2W\S8Y".8P66 > M;A./VE3W*7%'Y*E6(>>=ZSYI.P#0H"9I6?X]:=$'RZ`DVVZU MI%PNR[7,S4K.F>,=/YF,I$N9CZ\PUW*-V80Z@1Y8KE.TU%JE^%_JN<=3_8X6 > M@JU85U53$,&IA/ENR7LNJ3*];*BU!8E6:J77Z58 > M]T!Y&3##=4;67<%R8D0JT@+@E4N@&7)I1.OU^E`?*2"+9")3P:WH4JLUI;0# > M728=<5AQNN2%7))JY06EY9I>ETU]5*O708"OT;4&+B*O:KE2VX&N>^HYU"Y> > MZ?=T9-ETG;I22:V4%V5Y2,W12"JKAJE+AOD:=8E`5S3*LB3M(KLA>*JB3X/9 > MM-#?F%:Y`M-:DHW`38@KZLJ5JES?78)XK=W[\XE?,-:E > M6*[6*K5%K3H:&<.:KNKELCI4U"VEN`DXHH6UJH+VO!TD<.CK(*HX&55U43$K > M-6E4HI6RKM?JPU?M(AUB;2%)Y7(J499CV#.3%G5_ M.BQ3?:17I5JU7JJ^'6)M49'52A6(FN+:]=J4-KG5CZD]#:>R(DER5587X.\4 > M=:'JE;(T*M.21)6:HNJOB6L#8&0*U7)=W5W=N/)N:%JIJLK20I M&X92+6\YFS&8$0HK2JW"%OCD^ M_:14.I'5%U?X?V2!-\BY%7RA=$H])@CR M9$,6WXCT5%/D-P0%_]#$R#M.3*E<_J=BKX9I0G!%GZ:N%T`P12"R(I8S M"T3(@Z63XM1S#62R>"3FHT M/O7PKP^]L&/3G M+9\8KDE)`$NU'Y,("./!0J$-YX(T$)FAVS:202`0I]"=B#4T#U"F%G0.7.+K > M(TK\P)L9P!?AX)?B_AY;K:R9C6W-FDR'UG@N" > M6$XM=+WS]`F!RY%'`9$["AYUCYZ2N3L#^AP(KTT+T%M#D`4B`(1%UR,3U[1& > M."8(*QL`Y]28^QN)X\ZE[2SY1AWH0IM_,AK9ED$L@Q8%H_4$!1Z,# > M`=CLCYE@�<=X&D]`4IY,(%\$R*::2O*#11``AB[$Z!F+$>('F/%LSGD)*9 > M3TV?P^?IV0!K=/\COC5ZOT1W\<0J]@[$+3^D#Y;"LR=3&V0!J > MP'*".;#'0%RU>\W/,*9QWKGL#/X@():+SJ#;[O?)Q76/-,A-HS?H-#&A(S>W > MO9OK?KM`0/V0,,H@O""@$1,RL&^"H5JV+^:MF/F>^5FLT>0# MDTH_Z8$%R5-2.ZJ.-DH<`C,^LVG2$P/1Q!]`],`#AX]`[]5UZ_:RK35N0=J] > M["&:$.$F%+>G5FA/A[G3<%"KW6_V.C>#SG4W>\C(@QD&)1OI8,E@'DM;BAA; > M9/AEI]GN]MO9PT\WE]C\/>-CKL2`@&2'L[ME5YBLJRQKRI-#*P(#'S`ZED_; > MCCZ$-4DW30OQP>1!/C]T? MUQSWZ?184@^A8_$(I.+\&A"' MA"R5_(X&$)/YOC`$/L*CNLGT:09:!!K$O0E[Q.:;0?P[1KX%&\. > MP(_8Q>FR`QALH(T1J/A@PVGF.2+>RTY_H'UN-UI9Q(+/01;BF3^U'-LU[C5. > M`EZ2,]*_Z72UR^OF%^VVBW_:K5,"$@%B`FJ`;POA$,8`!Y1([Q'VA-NH[+&) > M/TY@,ZP%>V]!@^?0LP\\:8]TC1YAN@]-FUT?0 > MWPORX"1&P"%\YS,'!X0IG`&>#)[@Y1%U1_S*IDXN`]*W1B0+U^3#&0YZS_KF > M6#^0C@S2YX#A!K&1]]@+6G'(\9FX$3`^BL'X[(QC73W\((4/)&CT8"WQ'&R` > M"8PSR^0XFTPU3W_4P`'K@MEAGCRXEDF.L&W)PUTP1C9"E>!=75A8M2&@&@(J > MUC2 > M39PS9&5%",PDFHPI>`3_"'K#`$WT)SX"95J!9X]CC"ZS:^,^A!RA61P,9>2` > M$WZ*]\KR7L%[-*WL$BQB/.`RX$T?(EC?O5LG,41U2M:&O7_/L2/Z]V=@-3A@ > ME$4I'?XB*4_D,)^-20F499I#Y&RF060?B*J0Q0*E]Y'(2B5'(+D@OQ9^99VH > M#?X*&XZF[!ZXBJ)1$(UQ"+/!84[?OV=_X^3SQF?XA[8*'@$73EPS;30[,%4A > MG=,$881MP"AT2V,5!'*82R-0/$+%A>>QQTB^_SV`?\YAJ&GR4N5PV/-26841 > M9(?DF'"5S7%K0*=\Q&*.T(]F<]"'![[^1M@+_C82?,7C+A&[]!@J_X3P9HR4 > MAO,`XKI'SPH""@X)Q'7<[G2_-BX)@!S!V@]Q7R;B]D+;9.1LXW^2?<_*AKG[ > MX=8C%#CB%=GJ@$[U++O1FN,V& MV?-[.E]>&V-JW/NS"9IQ"&L&P&H:FFWX#!B,=E@Y!N1^U4Y!LD0;SGP-PQ+R > M=WBES9Q[QWUT\LN>ZQ_+!W M=1J6@8J@)'[_.CW\PYPL?$V!+M_PX7OF#U\;9,EJO92'U'GH@6)8"BQIGFX! > M*SY`>HY.6)3",Y),(OBF[WS]^(GI"_-+J$5GS!\*\Y%B-I4Y@/!)ZW2;VFV_ > MK36O;[N#TQ`*BY(XE"D:[>9*,\UC(Y!K_1?09%'] M(KR!#P$\A)88>1Q_%,\X,@/?$TA/T@ES:.M@P)G.IFC8U/SN<%!B@"*?D,0A > MD)2'70]`TOI]9)":@D8M2.MCUFKY7 > M]$1\8J+:I"?\+%E\3IF)]A.X,`3BGX0\XGPS\"O5$F(F[UA,W/XVT"XZW]HM > MK=7I?]$:S28D4&+IVT#P/;BPGF"],S&?UPW(XOT0T?.VR%KMKY`5L%BST_VD > M-;K0_'_MY@!NTM&*O0,,5G'#`]-N^O\0F,+-S@2TNY`U-D.&6[W.U[;6O[VY > MN>X-T@E8V\KPK`?(UCGHG0FHE,X[`[R"W`C2D1>D72D=#R&WH,MYC>)*TH`. > MK@L7MGZ7H`%3'?)UOX!+AS;"+H*D3O?B6FM=-;1S\!*MWA]:N]>[[FD#R,?[ > MD'RUNX-<"GGF1->&N#W@S37J>:ZGL;TM0`3Q_6[X/[6OK]H#0`X+;Z>5AO". > MNACYS[4'W;;,W3#TVE?77QOGE^TTX!Z=N`^86>X&]_=>9]#&U+)S\4<::(PN > MJ`86;HWFNT&_:K[UH'/1:38P'4]#-:&FI<.2CKN*FN,&UL@R > M6'C$\)*M$:-]OB0M-,7=A=4-.;KIM?LO:);C:IP1L;FV&Q9<\CK=@:QJ%]VR > ME(8#,$:#7R"DO%X4DJX)P0A.+@F;,(;8VL7X`G#QS\0 M.&;U2\"I`%FO9&`^^$37\[4I9;9HW"<"V^B52AG$R)H[TL0``&;;+S(=[\_" > M?-Q&B$0=;`LM7-'@47]*#?)@N3:/X7%GI4!(P]2G`3QH=)K56KTN4@0?UO56 > MZ[P=72%Q`,2Q8XB=P5/Z8W=FF[C9F,5W%SX`S\&@KNL3A,7D > M[$R@X7YY&2[+JY7Y.<(#B\M2H"!>3`'347` M8KAEO+>Y&<+3D%7^D0^S#I9PX$9'/$0,+UB*:)VITBFQ/IQ55?@39K\L0 MLV$Z<)3#4/"]];ZT-$<0<#3#P)1T/7`)DPA4,",JQ:@,PTX1J2^3#WD3)A-[ > M%'':*OH[0((PX61-TT#)1%!Q`X-7)%H.6UM(5GIB:?Y*HR!RE7(%9DQ+6L.< > M/''VDJ=OS_F+3&!D*M]@4F/=9RR1;/?V\C(G\F#4A:BL11X)8O$#W'*$A!D" > M M28-3*6);*R^"V]2X9\+V;';`$F-W_1--TY.,)NICPD^B`X(9O_%8[K_ MB&V-K+F\G_S` M'8&]L&S#"2!Y.X[.>;>U#2>XI?%V+-]N>OUML."6R=NQ?![<#+;!@ELR2>X\ > MW`((NT;!L/0<=&8SNTX(T8;060,3@2!P%6^MCXM]XL%AF(.A/10`:2$*,,$V > MUS8$&*V@%2>9@_#RZ56Z7Z8/F,)EY02_"K](\A/;27,<:N_-'U!7`(GO!\"W > MW6`_"*.98Z#/V0^*$$KZ'/$906L*9P=U/KQ&S=Q_I@;GK4C(^U9VD,8"IC'> > M`S5?5[K4W:>D%(9O._T`(@6D'>A\_C<$'1$"^!K(=_U?7``WY+@417I\4MLY > M/HEOY>X?H&S"^Q=$*)M7J6M,G'Y`W1@T;G!9+B<*9F-KG&W!;[^D):%+C0&2 > MD.V!JM_L=U*7SPU<^%)A#V2W_?/M^9KYPSU0X4N-[?EB[T#VP';1.>^UM] M]JYE#W0=Y7I[.5J*NP>J7J.3'BINX,(71_LH(U?\;94QKOGL'6QX%T9U\4$; > ML1U`V&KMXIYZ]ZA'O-=EJQ;@$O=;!G/,B^Q('B'VS-F;SJDE6O8"`91LR2FZ > ME:T8M MF3? M3F`% MU,LO.V).82UYDG)W%7U]A7!"^L$A:\'?8'?]"Y['-;WR7 > MD<=R;_[F0B",1_[1C&%/]# M_)K@>R;I-<'WS'ZO"9YY[5Q8.F>`20245]CRTMM M)-6^;<+;J$W#;ZQL^RXJ3QU]0O\L_14O;EO5/Q\Y]'%UNRQ5^HD]7"P(NSC^ > M*(P^+!G$^J?80!#P_42W;=?(AK5+L>,HIC0 > MB4^#;*P#"&E5'Q4?RF'ZCM`SY!P"<%$W>I@G,598W^(1:3*1LN)-7DAM\;EG > M59PQ^,8 MGG.1UX\RT^X#K"9G->39=V$U.?9B1=Y@P=EW:PCP09Z\BY2E ML!PTIM1XB(+5@W(Q^)O%G\\D`!X*T?-!N@^6"7W9V13HZGB\F,@TR2-EA9[8 > MA5?UKL[Z$-U&V M)R"?LFQ8P\G#+WZ>_&**C2S<&YLY)O,KD1,,>4XZ2D_,([_G-7T;6-8+91TW > M(/H#&#L6;K*'T'JX5*NE&H7W$:L!"-$=-"[K > M=^_@$LBY:GSK]B+OF9.="FH#W^E"55M7!S$-K)!6T^B3F`>\6,[#YIF)HZD+ > M`CYR4AU1W`F]I-_`GD9U8ZSA(;$L@^M$=5O,QLHUK M/W)SCDB<8S>IG7VW9EGL*3?'0N&VH] > M/.2GD[CLPTF`9CQFFWRB.7[,-KG/"\=L]SEXG7S,5BW]^X_9IHB)'>^LJIDO > MA#&V(VCMF^,C%R1?EGC]FB\Q2>@AUG8F?.?+YJ//%Z > M9?*@>Q8[DV92P_;%A."Y9WY0?^W$;O8O > M>I:61,[DOGP>5RRLD>.Q*)6HE'`%8& MP__X\M;$R!0A#F25W'GN;$I,\2,LI"67JPI$M`\6J\&62+8QNYOY@+G$&,FQ > MU3U<]P@$`.,@F)X4BX^/CX5`5O%G>(H`S5)A:HX@'>C`&LZ(>:`0 > M>OG6!("P,X$MN50KK9"JK\"$SIZ*,(7L.@[1B3,+_#$(.4^2?]2#3-WIS&8Q > MCDY\P^._6(1,(`AQY)9.IL%<8^500W:HCX4XANL$NH7ZRM9`?)6&0C_&(Q(4 > M`%$302"R,.(HA&2E_*!"'@!;\=/57#+,X$;4\WC,XW*J(+!:ZD>>Z8>5`)N= > M.<\SDCE+4>!X<)B=R.0;'2-QA)L3#3I3P"/)E!_]7IWB9G!\,5]8/AU@S;8@ > M"P-W<4S:CY[O7A[S_=D:.:#(1&OTK[0._F@)AE^?ET<:U]MC!TV[/?"J,JUC > M7(_%!HAI=>!HF2-QM#XJ(@PZO[T0NP;`P\9D'F,HJP=<]CKF:_@2E-4R1A`# > MC`/IJ2))4 M2Q92A\`13[E/9H`>#WWSB5GYDJ,B;GM$H.%)8`8.7&O\8&_B(89(WI^5R8 M1,IM#'KA,((8)&\.>N$`@1BD;`Y:+_HG&^2IN36N7B_,3V8LH:!^?2,DD;=X > MF7SB+E0B>QME\&GCU(1QJ07ND7&EA'%A?7HBF6)<.6'<>@5ZTKA*CFP.C!>5 > M)R.LAH>6E^X#_$2_?75^^;_FKO6W;1N(?[;^"BT/-&X;SWK8EF,42[JU0X`F > M&=)^6+$-ABPQB5)9,BP[<8;T?]\]2)F2_(C=IE@0(+%,'D^\.Y)W//[XN=\G > MER7W./)@((8&T5.86FUU%C4/&>&S>8H[GKYU;'-A;OF"[RA-7#ZO9'SC\[9K > M5E*V>\P(95A0:7XNR80C=-`FXU[Y]<&VF[/W\H=F_70Z-D=36"ID9,I,]HMX > MJ%15]?-\:2KLF:86+J5QIZ].ZE)AU\T+YC%4R;SZ[/3H^V)J)X6@X&DIG\*C > MQPE...BU24%11C'UAY8WUE,/\W`O/X'^T3FI?07IPQ*+D3'Z_8.#$?2[".MU > M3IDL->)A8EU/_HM96.I_E4^E/LO,J$J;JYNDW$8^)AQ$,YP8,W#N"`(DB/BD > M<($=T(VG$>9\QFUK M5^;07 MQ(VY+U628AIM2$@FME1)X3YFN1^6DY$)*U4R^G;>IJQA7DJ)(O2ZOJ%7$855 > M::,J'*T)3D>IZ&11)9_5*+)%5J%5?\H++1T(M$F'YPF=*1I]>7.G9RREURM. > M]`K>1>\D^%\>]Y535N6X:#$\65PL\)\U'."9T7%BEAG!B"IY*##?R2)%K`^* > MT_:,79&$T=7/+W_25S`,?T3?X"1<\H'X$$@164^#"L2(W_/@%0+9.Q$?3X/[ > M1O#O*D)MJV7#K]L&0DW7Y7B3LR&NV_-!ZG*\Z=>+\_>GOV.7\D:0AM[&Z(I+ > M\=NT]]TFF-1M=TVK"2*<,>B2]MGL_F1#`$6,Q+0WD(`49 > MR@%3\F-$+I/%"7X-:80"8 M&)S$?.M'P[N#ZF-:LSX`#8PW8&25(U$8K&>R,DT86PXF(FS0-BU13D ML/Z-"-XWYLC%$%:2?/8=PRKC-([!,T9Z4/D.S`+6SV:8TO;*@Y@0<)F@R-1$ > MX[DAC60==O!ZV.GO@VS\71OQ'AW7L5ID67;%L.R5AO7,<5P>R/UY7#+?>YO' > M'*2MM<'6&*JY9&OK.F,;LW, M:L,`:1Z"`]7YS:W55!D9"*N7QN1"9'&MDGT+<+$!1GV='HMX(AHWTY6D/*L# > MU%RW^6C;[8XQPR&'&B

3"(I(:P28#+2\=H_ M19MB])@1]%+388DR\5&`BTYZ0Z'[I\7\3ULMT*)%\('4SBD,'*;KR)F?HQL< > MY1?AP7RRJ&.>1O5QGW'\ZL8N<$$QOA(`YZZ&W(E^Z8I8;2&$21L;N+"A..21 > M21@Q\+-K[H<9P_9EB@9V.TVQ. > MK^;AS-?F?A9A7>`BS(X0$PCJ6))4EK/Q!61AWN(&Q$!<(98D1>2Q1Y'RH+;7 > M?$VH^.>7=2J/0XD)BCL5,J)Z?IGS@:5G7A-3`V(JK$]C^`TN^7`3'=>G?5C9 > M'>6-S%P+JODW5.V]C";`^&;(]VO.6BW?AR*#&149^M=10(A4^)WEU.33+YR= > M@D(S:KDB:"ODY3A,C6V,IG[5`N&(VKFY*35FC<#HJ:63-II^@5(`BFD > MF0#WDB9FL./'1J.AB-%+02=@3V1'A^X!R**.I;,)PW52C_#8J=?P;V0-IU1# > M+L1E;^P',UG.+I6;@[!@WP2#VEQTQ.M$RO=><(70S!"LY`9O.U!A+A+1M9@4 > M%_1'4B-8UU24F]G(F1A-)V0)18UPO46B]=9)3RHHXUV2RK#F^U$L,SCR,A&L > M>%*18<$A#!YBW%`]A7J_[TMA)K`2HZ5.%ADU/PR+[U(T'G^F2/@SLB6INPFI > MK>HKZF/6]D(#8-%84$HZ-V=0L@&U27L7N6&96/EB2AM?='H,%6U0*YB*-%8Q > M,N,T'2EY&4J_C_!#<0K-+U+89/[<\#('8QR&TR3V1\=I%L9T1 M;;J/=L?J=&GV=#N;SIX_UJ_!V*.^Q-;]'+J.8NDY > MLZ=X^O./=Y>G9^_./YU\V#'?F#L/.^8_/;27!%4!%E^8:R3,%\OWJ]F9F7LR > M^>8D**)&O?Y"ZP?C*JHXS/E5&)MHUH;7<1A^Y-O6<0`NG#]H)"#+I:0\NVM; > MC,7?ZK0]4JSNIA#UU@]3+%`I=+Y@?:5I$U\BLE2;\C?>1ILZ%BZ<=!:B.0L+ > M+QE0UXAL(M^MKC4Q0O].W!YGTTPT0K&.FF>U+,]R831J>ITV(][;50_N_R+H > M MS!&W:=:(!L.GTO5L#T;)EM5]="R[R\Z\L^GU!S_`%9,XL/K$03?(K%,#_8VW > M\MBM)=X2S"X=UVRQAX3;OQ4OR(#)X.+R4__CY[.W%Q\P5;+>JSZCS%[I;2U4 > M)966O+D6;733BN%?CU-8'Q_SGS1!6.$GT/60M-UU.H]MF#98@=I5!5J=V&<[ > MSZ]!"':*EST\4'!1SXHAD&^Z_^%.A+K;*5]4N]N$;Y19IW2JWC;ZYBW7MZ9G > MVH55#"\*Z;![`Y@M04@PUH]*`853UT/..IN > M&098N-VP:IM"IORCF/KPG%+^,4.Q&$LHI(QA]IG/=W>,8ECTYVE=>>H^`613 > MZGA.5^6,4T=PNOH;V:4R(V,HAL&(\J-?JU[+SX`(ALC]"G8;9^))#7V=1U3^ > @-D[;%`BLS5^S-[^O,`="LX-F*QA8`^,_5\L8?Q=Q```` > ` > end > > - > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > Andre Hedrick LAD Storage Consulting Group