2002-09-03 22:01:40

by Matt Domsch

[permalink] [raw]
Subject: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

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 [email protected]. 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 http://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.

===================================================================


[email protected], 2002-09-03 15:05:38-05:00, [email protected]
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 <[email protected]>
+ *
+ * BIOS EDD support September 2002 by Matt Domsch <[email protected]>
*
*/

@@ -53,6 +55,7 @@
#include <linux/compile.h>
#include <asm/boot.h>
#include <asm/e820.h>
+#include <asm/edd.h>
#include <asm/page.h>

/* 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 <[email protected]>
+ *
+ * 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 <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <asm/edd.h>
+
+MODULE_AUTHOR("Matt Domsch <[email protected]>");
+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<eddnr && i<EDDMAXNR; 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 <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
+#include <asm/edd.h>

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 <linux/highmem.h>
#include <asm/e820.h>
#include <asm/mpspec.h>
+#include <asm/edd.h>

/*
* 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 <[email protected]>
+ * 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=[<HK?B:W/O5.#J[T(-!:
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<F3JVC`G=YDO
MI%PNR[7,S4K.F>,=/YF,I$N9CZ\PUW*[email protected]%JE^%_JN<=3_8X6
M@J<HSR5)K2[*)565%[6A5*>U85U53$,&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-:D<R:/-05I5JCU9$R>HW`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_<LP@(8CQ.E%*M5*O+O2:
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<E6'NJ)7DD
M&X92+6\YFS&8$0HK2JW"%OCD^<?5ODL?"9KZ24J?S%=2RF1^N)JR-5Y:K?!2
M_:14.I'5%U?X?V2!-\BY%7RA=$H])@CR<F!53!'3!9%KI7H)%GO&,"SV*1U[
M9$,6WXCT5%/D-P0%_]#$R#M.3*E<_J=BKX9I0G!%GZ:N%T`P12"R(I8S<KT)
M"T3(@Z63XM1S#62R>"3FH<R"+BES38Z]1_8_2"MU2G:7>T<BP',&\)&C%^+`
M/O7PKP^]L&/3G<X]ZVX<D&PS1U`&T-&VH7TRG06@?TW7`SXY8Q^21/U10!J,
M+9\8KDE)`$NU'Y,("./!0J$-YX(T$)FAVS:202`0I]"=B#4T#U"F%G0.7.+K
M(TK\P)L9P<QC0$4O(X\C=<<$V-2'&!">!?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<P8(&F>."8(*QL`Y]28^QN)X\ZE[2SY1AWH0IM_,AK9ED$L@Q8%H_4$!1Z,#
M`=CLCYE@&#0<=X&D]`4IY,(%\$R*::2O*#11``AB[$Z!F+$>('F/%LSGD)*9
M3T<SF\F-0&_R>V?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#<X)A5#W^N/$$
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?<I!$M`><!T%CO!G2"XLAR*1VM=VKP^<D$.I(,G,
MUQSWZ?184@^A8_$(I.+\&A"'<M._A_6/Z)"Q,HZQ!42J(:-D3$$SAM300:4S
MA"R5_(X&$)/YOC`$/L*CNLGT:09:!!K$O0E[Q.:;0?P[<R#:69MI>1KX%&\.
MP(_8Q>FR`QALH(T1J/[email protected]+>RTY_H'UN-UI9Q(+/01;BF3^U'-LU[C5.
M`EZ2,]*_Z72UR^OF%^VVBW_:K5,"$@%B`FJ`;POA$,8`!Y1([Q'VA-NH[+&)
M/<TZ.4Z^N,N3)&'D69\<`/@>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`'[email protected]&W)PUTP1C9"E>!=75A8M2&@&@(J
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
M21@Q\+-K[H<[email protected]<R5&Q%E06KG\83"4Q%X\)5XGI4JC9,[^YK>VQ.
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:K<!YP>DB:"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<A26I[E6%[+
M;;J/=L?J=&GV=#N;SIX_UJ_!V*.^Q-;]'+J.8ND<FK_\-A.HY<%<9L`$]I>Y
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<F2$+V%9AVRO7GD;2=L=D'0ZN#W<*RQY]9\:8RDVTL62UZ\^V4+ZFU_)8@1I
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
MVH5<A?-+SD=X>5#"\*Z;![`</SE[Q0OC8FH$Y>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


2002-09-03 23:22:30

by Daniel Phillips

[permalink] [raw]
Subject: Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

On Wednesday 04 September 2002 00:05, Matt Domsch wrote:
>
> [...]
>
> 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:
>
> [...]
>
>
> Feedback appreciated.

How about providing an example of how you'd export the root via driverfs,
with a view to educating those of us who are still don't have much of a
clue how driverfs fits in with big picture?

--
Daniel

2002-09-04 00:50:05

by Matt Domsch

[permalink] [raw]
Subject: RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

> How about providing an example of how you'd export the root
> via driverfs,
> with a view to educating those of us who are still don't have
> much of a clue how driverfs fits in with big picture?

Right now that includes me which is why I used proc for now. :-)

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com
#1 US Linux Server provider for 2001 and Q1/2002! (IDC May 2002)

2002-09-04 01:02:06

by Daniel Phillips

[permalink] [raw]
Subject: Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

On Wednesday 04 September 2002 02:54, [email protected] wrote:
> > How about providing an example of how you'd export the root
> > via driverfs,
> > with a view to educating those of us who are still don't have
> > much of a clue how driverfs fits in with big picture?
>
> Right now that includes me which is why I used proc for now. :-)

Maybe we should prevail upon the driverfs axis to provide some guidance.

--
Daniel

2002-09-04 04:14:22

by Greg KH

[permalink] [raw]
Subject: Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

On Wed, Sep 04, 2002 at 03:09:12AM +0200, Daniel Phillips wrote:
> On Wednesday 04 September 2002 02:54, [email protected] wrote:
> > > How about providing an example of how you'd export the root
> > > via driverfs,
> > > with a view to educating those of us who are still don't have
> > > much of a clue how driverfs fits in with big picture?
> >
> > Right now that includes me which is why I used proc for now. :-)
>
> Maybe we should prevail upon the driverfs axis to provide some guidance.

Sweet, we're an axis now! That's much better than the other terms Pat
and I have been called in the past... And everyone knows what's the
next size jump up from axis :)

So here's how driverfs fits into the big picture in one sentance:

Anything that does not have to do with processes
will go into driverfs.

So in this example, we are exporting a number of boot devices as the
bios told us, so apply the rule stated above, and determine if it should
go into /proc or not[1].

thanks,

greg k-h

[1] Yes, it's still a bit difficult to figure how to add files to
driverfs, if you aren't starting with a "struct device" or "struct
device_driver", but I have seen some very nice documentation on how to
do it properly written by Pat involving a wonderful example of beer, and
I'm sure that once he gets back into internet connectivity range, he'll
be updating it and adding it to the Documentation directory. That
should be by the end of the week or so.

2002-09-04 04:31:53

by Andre Hedrick

[permalink] [raw]
Subject: Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling


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 [email protected]. 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 http://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.
>
> ===================================================================
>
>
> [email protected], 2002-09-03 15:05:38-05:00, [email protected]
> 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 <[email protected]>
> + *
> + * BIOS EDD support September 2002 by Matt Domsch <[email protected]>
> *
> */
>
> @@ -53,6 +55,7 @@
> #include <linux/compile.h>
> #include <asm/boot.h>
> #include <asm/e820.h>
> +#include <asm/edd.h>
> #include <asm/page.h>
>
> /* 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 <[email protected]>
> + *
> + * 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 <linux/config.h>
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/proc_fs.h>
> +#include <linux/module.h>
> +#include <linux/ctype.h>
> +#include <asm/edd.h>
> +
> +MODULE_AUTHOR("Matt Domsch <[email protected]>");
> +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<eddnr && i<EDDMAXNR; 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 <asm/pgtable.h>
> #include <asm/pgalloc.h>
> #include <asm/tlbflush.h>
> +#include <asm/edd.h>
>
> 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 <linux/highmem.h>
> #include <asm/e820.h>
> #include <asm/mpspec.h>
> +#include <asm/edd.h>
>
> /*
> * 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 <[email protected]>
> + * 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=[<HK?B:W/O5.#J[T(-!:
> 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<F3JVC`G=YDO
> MI%PNR[7,S4K.F>,=/YF,I$N9CZ\PUW*[email protected]%JE^%_JN<=3_8X6
> M@J<HSR5)K2[*)565%[6A5*>U85U53$,&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-:D<R:/-05I5JCU9$R>HW`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_<LP@(8CQ.E%*M5*O+O2:
> 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<E6'NJ)7DD
> M&X92+6\YFS&8$0HK2JW"%OCD^<?5ODL?"9KZ24J?S%=2RF1^N)JR-5Y:K?!2
> M_:14.I'5%U?X?V2!-\BY%7RA=$H])@CR<F!53!'3!9%KI7H)%GO&,"SV*1U[
> M9$,6WXCT5%/D-P0%_]#$R#M.3*E<_J=BKX9I0G!%GZ:N%T`P12"R(I8S<KT)
> M"T3(@Z63XM1S#62R>"3FH<R"+BES38Z]1_8_2"MU2G:7>T<BP',&\)&C%^+`
> M/O7PKP^]L&/3G<X]ZVX<D&PS1U`&T-&VH7TRG06@?TW7`SXY8Q^21/U10!J,
> M+9\8KDE)`$NU'Y,("./!0J$-YX(T$)FAVS:202`0I]"=B#4T#U"F%G0.7.+K
> M(TK\P)L9P<QC0$4O(X\C=<<$V-2'&!">!?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<P8(&F>."8(*QL`Y]28^QN)X\ZE[2SY1AWH0IM_,AK9ED$L@Q8%H_4$!1Z,#
> M`=CLCYE@&#0<=X&D]`4IY,(%\$R*::2O*#11``AB[$Z!F+$>('F/%LSGD)*9
> M3T<SF\F-0&_R>V?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#<X)A5#W^N/$$
> 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?<I!$M`><!T%CO!G2"XLAR*1VM=VKP^<D$.I(,G,
> MUQSWZ?184@^A8_$(I.+\&A"'<M._A_6/Z)"Q,HZQ!42J(:-D3$$SAM300:4S
> MA"R5_(X&$)/YOC`$/L*CNLGT:09:!!K$O0E[Q.:;0?P[<R#:69MI>1KX%&\.
> MP(_8Q>FR`QALH(T1J/[email protected]+>RTY_H'UN-UI9Q(+/01;BF3^U'-LU[C5.
> M`EZ2,]*_Z72UR^OF%^VVBW_:K5,"$@%B`FJ`;POA$,8`!Y1([Q'VA-NH[+&)
> M/<TZ.4Z^N,N3)&'D69\<`/@>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`'[email protected]&W)PUTP1C9"E>!=75A8M2&@&@(J
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
> M21@Q\+-K[H<[email protected]<R5&Q%E06KG\83"4Q%X\)5XGI4JC9,[^YK>VQ.
> 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:K<!YP>DB:"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<A26I[E6%[+
> M;;J/=L?J=&GV=#N;SIX_UJ_!V*.^Q-;]'+J.8ND<FK_\-A.HY<%<9L`$]I>Y
> 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<F2$+V%9AVRO7GD;2=L=D'0ZN#W<*RQY]9\:8RDVTL62UZ\^V4+ZFU_)8@1I
> 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
> MVH5<A?-+SD=X>5#"\*Z;![`</SE[Q0OC8FH$Y>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 [email protected]
> 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

2002-09-04 15:58:31

by Matt Domsch

[permalink] [raw]
Subject: Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

> 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.

Sure. http://domsch.com/linux/edd30/linux-2.5.33-edd-initial-rfc.patch

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://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)

2002-09-08 00:23:44

by Patrick Mochel

[permalink] [raw]
Subject: Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling


> Sweet, we're an axis now! That's much better than the other terms Pat
> and I have been called in the past... And everyone knows what's the
> next size jump up from axis :)

Yes, this is definitely cause for celebration. I've always believed that I
was a straight line around which objects rotated. Thanks for the
reassurance ;)

> So here's how driverfs fits into the big picture in one sentance:
>
> Anything that does not have to do with processes
> will go into driverfs.

This is true, as per discussions in Ottawa in June. This will take a long
time, and is not as clear cut as we make it out to sound. For example,
porting things like meminfo and cpuinfo will likely never happen. Though,
we intend to have equivalent information in driverfs. Things like stats
will also take a long, if not indefinite amount of, time to convert
because of performance concerns.

But, the obvious candidates for transition are things like /proc/bus/*,
/proc/ide, /proc/scsi, and at least the /proc/sys/cpu/ part of /proc/sys/.

We've been working on solidifying the various top-level infrastructural
pieces, like device classes, so that the organization of, and correlation
between objects in, driverfs makes sense to at least developers. As
always, mo' better stuff is coming RSN..

> So in this example, we are exporting a number of boot devices as the
> bios told us, so apply the rule stated above, and determine if it should
> go into /proc or not[1].

This is interesting, and I look forward to delving into the code. ACPI is
doing something very similar. One thing I would like to do is create a
'platform' or 'firmware' top-level directory in driverfs in which all the
various firmware drivers can display the data they ascertain from the
firmware. Stay tuned..

> [1] Yes, it's still a bit difficult to figure how to add files to
> driverfs, if you aren't starting with a "struct device" or "struct
> device_driver", but I have seen some very nice documentation on how to
> do it properly written by Pat involving a wonderful example of beer, and
> I'm sure that once he gets back into internet connectivity range, he'll
> be updating it and adding it to the Documentation directory. That
> should be by the end of the week or so.

Two examples are attached:

pub.c: A subsystem that maintains a list of beers that are dyanamically
registered and unregistered. This example is very similar to what is
already there wrt devices and drivers.

When the module is loaded, a top-level directory is created called 'pub',
and a subdirectory is created in that: 'beer'.

A struct beer describes a beer type. A couple of example beers are defined
and are registered with the pub subsystem (pubsystem?). A directory is
created for each, and a number of attributes are exported on behalf of the
beer by the pubsystem. All are read-only for now. (Wouldn't you love to
change the attributes of a beer? ;)

The things to note are the following:

- struct beer_attribute.

This describes an attribute and includes type-safe callbacks to read and
write the attributes.


- BEER_ATTR() macro

This helps you define an attribute for a beer. It creates a structure
called beer_attr_<name>, where <name> is the name of the attribute, and
initializes it properly.


- struct driverfs_ops

This defines the callbacks that driverfs actually calls. These are
responsible for converting between the generic structures to the
pubsystem-specific structures (see to_beer() and to_beer_attr() macros).


This code is pretty much identical to what already exists. I'm not
claiming its perfect, and not many eyes have really looked at what's going
on. I'm sure I'll hear if I'm doing something completely retarded, and am
looking forward to it.

If anyone is really that bored (and sick), extend the pub to include
objects of struct wine, etc. :)



pat.c: An in-kernel representation of myself.

This example exports attributes concerning my current state. I've been
threatening for some time to write patfs, but I decided to port patfs to
driverfs and eat my own dog food. It's pretty shoddy, and doesn't include
a decent way to update my current attributes. But, it's good for about 3
seconds of entertainment.

There is no registration of objects and no dynamic directory or file
creation. I am singular and may not be replicated.

When the module loads, a top-level directory is created named 'pat'. An
array of files are then created, each one for a particular attribute of my
self on this dreary Oregon Saturday.

For defining attributes, I defined struct simple_attribute, which has no
type-specific callbacks; they pass only the buffer, count, and offset.
Because of this, the driverfs_ops for the patsystem are simple.

[ struct simple_attribute can, and likely will be, defined in a common
header for others to use. There is a lot more work that I've done in this
area and I'm currently trying to figure out what to do with it all..]

Everything else in it is pretty self-explanatory (I hope). The patsystem
is pretty much as simple as it gets for exporting attributes of a
subsystem.


The documentation in Documentation/filesystems/driverfs.txt is up to date.
If anyone has any questions, please ask. Other than that, go wild.


-pat


Attachments:
pub.c (7.01 kB)
pub.c
pat.c (4.67 kB)
pat.c
Download all attachments

2002-09-09 01:12:46

by Matt Domsch

[permalink] [raw]
Subject: RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

> > So in this example, we are exporting a number of boot devices as the
> > bios told us, so apply the rule stated above, and determine
> > if it should go into /proc or not[1].
>
> This is interesting, and I look forward to delving into the
> code. ACPI is doing something very similar. One thing I
> would like to do is create a 'platform' or 'firmware'
> top-level directory in driverfs in which all the
> various firmware drivers can display the data they ascertain from the
> firmware. Stay tuned..

Likewise, on IA-64, /proc/efi/ has EFI stuff (really only vars/ right now,
direct access to NVRAM variables), which coincidentally, I wrote, which
would benefit from a top-level 'platform' or 'firmware' directory and
migration to driverfs. Code is in arch/ia64/kernel/efivars.c. Once I nail
down the EDD code, moving efivars.c to driverfs shouldn't be hard.

> Two examples are attached:

Thanks, that helps a lot. I need to still find how to walk the list of
existing devices and gather info, for purposes of making symlinks, but I see
the existing devices that do that to use as examples.

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com
#1 US Linux Server provider for 2001 and Q1/2002! (IDC May 2002)


2002-09-10 22:38:42

by Matt Domsch

[permalink] [raw]
Subject: RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

I've updated the EDD code to use driverfs instead of /proc. It's now
exported as:

.
|-- edd
| |-- 80
| | `-- info
| |-- 81
| | `-- info
| |-- 82
| | `-- info
| |-- 83
| | `-- info
| |-- 84
| | `-- info
| `-- 85
| `-- info

where 80..85 are the BIOS device numbers, and info is a file that displays
the same information I was displaying before. Thanks Patrick for the
pointers, and once the top-level firmware/bios/whatever directory is made,
it can move there easily.
Patch available from http://domsch.com/linux/edd30/edd-driverfs-1.patch and
http://domsch.com/linux/edd30/edd-driverfs-1.patch.sign applies against
2.5.34 or BK-current, and is the whole of the feature, not incremental.
Also in BK at http://mdomsch.bkbits.net/linux-2.5-edd.

The next logical extension would be to make a symlink 'disk' in each
directory that points at the PCI bus:dev.fn/scsiX/a:b:c:d:disk file for the
appropriate disk. However, I'm in a quandry... There's no simple way to do
this.

For EDD to do the mapping itself, it needs to walk various lists of devices
(Scsi_Disks, IDE disks, ...) Those lists aren't currently exported.
EDD could do it itself brute-force, except that it knows all the information
*except* the scsiX host logical number, so it would still have to some sort
of lookup. That nice physical (and virtually identical logical) path got a
kernel-logical component added which requires a lookup. :-( The third
problem is that mapping needs to happen at device discovery time, not at EDD
load time, else scsi-add-single-device and/or modular IDE insertions later
won't pick it up.

So, I start thinking about making calls from the various disk type drivers
back to the EDD code to get the symlinks made. That touches more than I
wanted to this round, but is probably the best way to go, and what I'll
investigate. Per-arch dummy asm/edd.h dummy files with noop functions for
the calls into EDD that are only x86-applicable... yuck.

Thoughts?

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

2002-09-11 19:04:54

by Matt Domsch

[permalink] [raw]
Subject: RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

> The next logical extension would be to make a symlink 'disk' in each
> directory that points at the PCI
> bus:dev.fn/scsiX/a:b:c:d:disk file for the
> appropriate disk. However, I'm in a quandry... There's no
> simple way to do this.

Or is there? :-)

Patrick, in drivers/base/core.c, there's this concept of platform_notify()
and platform_notify_remove(). Could I exploit this to get callbacks to the
EDD code to create a symlink at that point? These aren't exported to
modules ATM, and I could see how multiple things may want to use this hook -
so instead, how about notifier lists (ala reboot notifiers) that the EDD
code could register with, instead of a single entry? As a list, modules
could add/remove themselves easily.

Then, one more request - giving back the ability to make a symlink given the
device, not just a name.

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

2002-09-12 17:55:53

by Patrick Mochel

[permalink] [raw]
Subject: RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling


On Wed, 11 Sep 2002 [email protected] wrote:

> > The next logical extension would be to make a symlink 'disk' in each
> > directory that points at the PCI
> > bus:dev.fn/scsiX/a:b:c:d:disk file for the
> > appropriate disk. However, I'm in a quandry... There's no
> > simple way to do this.
>
> Or is there? :-)
>
> Patrick, in drivers/base/core.c, there's this concept of platform_notify()
> and platform_notify_remove(). Could I exploit this to get callbacks to the
> EDD code to create a symlink at that point? These aren't exported to
> modules ATM, and I could see how multiple things may want to use this hook -
> so instead, how about notifier lists (ala reboot notifiers) that the EDD
> code could register with, instead of a single entry? As a list, modules
> could add/remove themselves easily.

You definitely want something like platform_notify(), but the nature of
the call implies you can only have one firmware driver that can be
notified of device discovery. In the ia32 world, having only one firmware
with device knowledge is rare.

This is a perfect opportunity to unleash the concept of device extensions
on the world. Extensions are (usually conditional) augmentations of a
subsystem that apply to or operate on every device as it is discovered by
or registered with the subsystem.

Extensions get a simple structure:

struct device_extension {
char * name;
struct list_head node;
dev_add_t add_device;
dev_remove_t remove_device;
};


...and can be registered with any bus or class or with the driver model
core (but not more than one):

extern int dev_ext_register(struct device_extension *);
extern void dev_ext_unregister(struct device_extension *);

extern int bus_ext_register(struct bus_type *, struct device_extension *);
extern void bus_ext_unregister(struct bus_type *, struct device_extension *);

extern int class_ext_register(struct device_class *, struct device_extension *);
extern void class_ext_unregister(struct device_class *, struct device_extension *);


The list of extensions at any level is iterated over after the device is
registered with the subsystem.


procfs or driverfs files are perfect examples of extensions. In PCI, a
handful of files are created for every device. Instead of having a call
wrapped in #ifdef to create the files, the extension can be registered on
startup, and happen implicitly.

Registering the device with firmware drivers is another good usage of
them. Instead of conditional calls, the firmware driver can register an
extension with the core and be notified when the device is discovered.
You'd get a pointer to the device, from which you could ascertain the path
and create a symlink..

If that's useful, and no one complains horribly about it, I'll submit a
patch to Linus.

> Then, one more request - giving back the ability to make a symlink given the
> device, not just a name.

Yes, it's coming. :)

-pat

2002-09-12 18:44:16

by Matt Domsch

[permalink] [raw]
Subject: RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling

> This is a perfect opportunity to unleash the concept of
> device extensions on the world.

> If that's useful, and no one complains horribly about it,
> I'll submit a patch to Linus.

I'd like to at least give it a shot, either before or after it's submitted
to Linus. Sounds like exactly what I want.

> > Then, one more request - giving back the ability to make a
> > symlink given the device, not just a name.
>
> Yes, it's coming. :)

Cool, thanks.

To think briefly about submission plans for the EDD code. Now
that it uses driverfs, and that code is in flux, I'd like to submit
what I've got now for inclusion in 2.5 (I haven't heard anyone object
to anything yet, though I doubt it's being used much either), and add
to it as time progresses. Comments or objections? Here's the current
patch against 2.5.x BK-current.

Patch: http://domsch.com/linux/edd30/edd-driverfs-2.patch
http://domsch.com/linux/edd30/edd-driverfs-2.patch.sign
BK: http://mdomsch.bkbits.net/linux-2.5-edd/

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 | 527 +++++++++++++++++++++++++++++++++++++++
arch/i386/kernel/i386_ksyms.c | 6
arch/i386/kernel/setup.c | 20 +
include/asm-i386/edd.h | 162 +++++++++++
include/asm-i386/setup.h | 2
11 files changed, 781 insertions

Of these, the bigger changes that touch files are:
arch/i386/boot/setup.S - Adding int13 calls
arch/i386/kernel/setup.c - Copying data from empty_zero_page to
persistent structures
arch/i386/kernel/edd.c - The module which exports data to driverfs

Feedback welcome.

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/Documentation/i386/zero-page.txt linux-2.5-edd/Documentation/i386/zero-page.txt
--- linux-2.5/Documentation/i386/zero-page.txt Tue Sep 10 11:41:37 2002
+++ linux-2.5-edd/Documentation/i386/zero-page.txt Wed Sep 11 13:36:30 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 -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/Config.help linux-2.5-edd/arch/i386/Config.help
--- linux-2.5/arch/i386/Config.help Tue Sep 10 11:41:39 2002
+++ linux-2.5-edd/arch/i386/Config.help Wed Sep 11 13:36:32 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 -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/boot/setup.S linux-2.5-edd/arch/i386/boot/setup.S
--- linux-2.5/arch/i386/boot/setup.S Tue Sep 10 11:41:39 2002
+++ linux-2.5-edd/arch/i386/boot/setup.S Wed Sep 11 13:36:32 2002
@@ -44,6 +44,8 @@
*
* New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
* by Robert Schwebel, December 2001 <[email protected]>
+ *
+ * BIOS EDD support September 2002 by Matt Domsch <[email protected]>
*
*/

@@ -53,6 +55,7 @@
#include <linux/compile.h>
#include <asm/boot.h>
#include <asm/e820.h>
+#include <asm/edd.h>
#include <asm/page.h>

/* 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 -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/config.in linux-2.5-edd/arch/i386/config.in
--- linux-2.5/arch/i386/config.in Wed Sep 11 10:55:34 2002
+++ linux-2.5-edd/arch/i386/config.in Wed Sep 11 13:36:32 2002
@@ -196,6 +196,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 -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/defconfig linux-2.5-edd/arch/i386/defconfig
--- linux-2.5/arch/i386/defconfig Tue Sep 10 11:41:39 2002
+++ linux-2.5-edd/arch/i386/defconfig Wed Sep 11 13:36:32 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 -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/kernel/Makefile linux-2.5-edd/arch/i386/kernel/Makefile
--- linux-2.5/arch/i386/kernel/Makefile Tue Sep 10 11:41:39 2002
+++ linux-2.5-edd/arch/i386/kernel/Makefile Wed Sep 11 13:36:32 2002
@@ -26,6 +26,7 @@
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
obj-$(CONFIG_X86_NUMAQ) += numaq.o
+obj-$(CONFIG_EDD) += edd.o
ifdef CONFIG_VISWS
obj-y += setup-visws.o
obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/kernel/edd.c linux-2.5-edd/arch/i386/kernel/edd.c
--- linux-2.5/arch/i386/kernel/edd.c Wed Dec 31 18:00:00 1969
+++ linux-2.5-edd/arch/i386/kernel/edd.c Wed Sep 11 13:42:42 2002
@@ -0,0 +1,527 @@
+/*
+ * BIOS Enhanced Disk Device Services
+ *
+ * Copyright (C) 2002 Dell Computer Corporation <[email protected]>
+ *
+ * This code takes information provided by BIOS EDD calls
+ * made in setup.S, copied to safe structures in setup.c,
+ * and presents it in driverfs 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 <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/limits.h>
+#include <linux/driverfs_fs.h>
+#include <asm/edd.h>
+
+MODULE_AUTHOR("Matt Domsch <[email protected]>");
+MODULE_DESCRIPTION("driverfs 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.02 2002-Sep-10"
+
+struct edd_device {
+ char name[4];
+ char symlink_name[NAME_MAX];
+ char symlink_path[PATH_MAX];
+ struct edd_info *info;
+ struct list_head list;
+ struct driver_dir_entry dir;
+};
+
+struct edd_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct edd_device * device, char * buf, size_t count, loff_t off);
+};
+
+#define edd_entry(n) list_entry(n, struct edd_device, list)
+
+
+#define EDD_DEVICE_ATTR(_name,_mode,_show) \
+struct edd_attribute edd_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+};
+
+#define to_edd_attr(_attr) container_of(_attr,struct edd_attribute,attr)
+
+#define to_edd_device(_dir) container_of(_dir,struct edd_device,dir)
+
+
+static LIST_HEAD(edd_list);
+
+
+static struct driver_dir_entry edd_dir = {
+ .name = "edd",
+ .mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
+};
+
+
+static ssize_t
+edd_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
+ char * buf, size_t count, loff_t off)
+{
+ struct edd_device * edd_dev = to_edd_device(dir);
+ struct edd_attribute * edd_attr = to_edd_attr(attr);
+ ssize_t ret = 0;
+
+ if (edd_attr->show)
+ ret = edd_attr->show(edd_dev,buf,count,off);
+ return ret;
+}
+
+static struct driverfs_ops edd_attr_ops = {
+ .show = edd_attr_show,
+};
+
+
+
+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_info_show() - unparses EDD information, returned to user-space
+ *
+ * Returns: number of bytes written, or 0 on failure
+ */
+static ssize_t
+edd_info_show(struct edd_device *dev, char *buf, size_t count, loff_t off)
+{
+ struct edd_info *edd=dev->info;
+ int i, warn_padding=0, nonzero_path=0, warn_key=0, warn_checksum=0;
+ uint8_t checksum=0, c=0;
+ char *p = buf;
+ 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 (!dev || !edd || !buf || off) {
+ return 0;
+ }
+
+ if (debug) {
+ p += edd_dump_raw_data(p, edd, 4);
+ p += edd_dump_raw_data(p, ((char *)edd)+4, sizeof(*edd)-4);
+
+ 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)) {
+ return (p + 1 - buf);
+ }
+
+ 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);
+
+ return (p + 1 - buf);
+ }
+ }
+
+
+ /* 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);
+ }
+
+ return (p + 1 - buf);
+}
+
+static EDD_DEVICE_ATTR(info,0444,edd_info_show);
+
+static struct edd_attribute * def_attrs[] = {
+ &edd_attr_info,
+ NULL,
+};
+
+static int
+edd_create_file(struct edd_device *dev, struct edd_attribute * attr)
+{
+ int error = -EINVAL;
+ if (dev)
+ error = driverfs_create_file(&attr->attr,&dev->dir);
+ return error;
+}
+
+static void
+edd_remove_file(struct edd_device *dev, struct edd_attribute * attr)
+{
+ if (dev)
+ driverfs_remove_file(&dev->dir,attr->attr.name);
+}
+
+static void edd_remove_dir(struct edd_device * dev)
+{
+ driverfs_remove_dir(&dev->dir);
+}
+
+
+static int edd_populate_dir(struct edd_device * dev)
+{
+ struct edd_attribute * attr;
+ int i;
+ int error = 0;
+
+ for (i = 0; (attr = def_attrs[i]); i++) {
+ if ((error = edd_create_file(dev,attr))) {
+ edd_remove_dir(dev);
+ break;
+ }
+ }
+ return error;
+}
+
+static int edd_make_dir(struct edd_device * dev)
+{
+ int error;
+
+ if (!dev) return 1;
+ dev->dir.name = dev->name;
+ dev->dir.ops = &edd_attr_ops;
+
+ error = driverfs_create_dir(&dev->dir,&edd_dir);
+ if (!error)
+ error = edd_populate_dir(dev);
+ return error;
+}
+
+static int edd_device_register(int i)
+{
+ int error;
+ struct edd_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+
+ if (!dev) return 1;
+ memset(dev, 0, sizeof(*dev));
+ dev->info = &edd[i];
+ snprintf(dev->name, 4, "%02x", dev->info->device);
+
+ error = edd_make_dir(dev);
+ if (!error)
+ list_add_tail(&dev->list,&edd_list);
+ return error;
+}
+
+static void edd_device_unregister(struct edd_device * dev)
+{
+ struct edd_attribute * attr;
+ int i;
+
+ for (i = 0; (attr = def_attrs[i]); i++) {
+ edd_remove_file(dev,attr);
+ }
+ edd_remove_dir(dev);
+ list_del_init(&dev->list);
+ kfree(dev);
+}
+
+/**
+ * edd_init() - creates driverfs edd/{device num}/ 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;
+ }
+
+ init_driverfs_fs();
+ driverfs_create_dir(&edd_dir,NULL);
+ for (i=0; i<eddnr && i<EDDMAXNR; i++) {
+ edd_device_register(i);
+ }
+
+ return 0;
+}
+
+static void __exit
+edd_exit(void)
+{
+ struct list_head *pos, *n;
+ struct edd_device *dev;
+
+ list_for_each_safe(pos, n, &edd_list) {
+ dev = edd_entry(pos);
+ edd_device_unregister(dev);
+ }
+ driverfs_remove_dir(&edd_dir);
+}
+
+late_initcall(edd_init);
+module_exit(edd_exit);
diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/kernel/i386_ksyms.c linux-2.5-edd/arch/i386/kernel/i386_ksyms.c
--- linux-2.5/arch/i386/kernel/i386_ksyms.c Tue Sep 10 11:41:39 2002
+++ linux-2.5-edd/arch/i386/kernel/i386_ksyms.c Wed Sep 11 13:36:32 2002
@@ -29,6 +29,7 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
+#include <asm/edd.h>

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 -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/arch/i386/kernel/setup.c linux-2.5-edd/arch/i386/kernel/setup.c
--- linux-2.5/arch/i386/kernel/setup.c Tue Sep 10 11:41:39 2002
+++ linux-2.5-edd/arch/i386/kernel/setup.c Wed Sep 11 13:36:32 2002
@@ -36,6 +36,7 @@
#include <linux/highmem.h>
#include <asm/e820.h>
#include <asm/mpspec.h>
+#include <asm/edd.h>
#include <asm/setup.h>

/*
@@ -462,6 +463,24 @@
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.
@@ -864,6 +883,7 @@
rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif
setup_memory_region();
+ copy_edd();

if (!MOUNT_ROOT_RDONLY)
root_mountflags &= ~MS_RDONLY;
diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/include/asm-i386/edd.h linux-2.5-edd/include/asm-i386/edd.h
--- linux-2.5/include/asm-i386/edd.h Wed Dec 31 18:00:00 1969
+++ linux-2.5-edd/include/asm-i386/edd.h Wed Sep 11 13:36:56 2002
@@ -0,0 +1,162 @@
+/*
+ * linux/include/asm-i386/edd.h
+ * by Matt Domsch <[email protected]>
+ * 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 */
+
diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5/include/asm-i386/setup.h linux-2.5-edd/include/asm-i386/setup.h
--- linux-2.5/include/asm-i386/setup.h Tue Sep 10 11:42:10 2002
+++ linux-2.5-edd/include/asm-i386/setup.h Wed Sep 11 13:36:56 2002
@@ -37,6 +37,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