linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
@ 2002-09-11 19:09 Matt_Domsch
  2002-09-12 18:00 ` Patrick Mochel
  0 siblings, 1 reply; 24+ messages in thread
From: Matt_Domsch @ 2002-09-11 19:09 UTC (permalink / raw)
  To: mochel, greg; +Cc: phillips, linux-kernel

> 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 www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com


^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-11 19:09 [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling Matt_Domsch
@ 2002-09-12 18:00 ` Patrick Mochel
  2002-09-12 18:48   ` Matt Domsch
  0 siblings, 1 reply; 24+ messages in thread
From: Patrick Mochel @ 2002-09-12 18:00 UTC (permalink / raw)
  To: Matt_Domsch; +Cc: greg, linux-kernel


On Wed, 11 Sep 2002 Matt_Domsch@Dell.com 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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-12 18:00 ` Patrick Mochel
@ 2002-09-12 18:48   ` Matt Domsch
  0 siblings, 0 replies; 24+ messages in thread
From: Matt Domsch @ 2002-09-12 18:48 UTC (permalink / raw)
  To: Patrick Mochel; +Cc: greg, linux-kernel

> 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 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 <robert@schwebel.de>
+ *    
+ * BIOS EDD support September 2002 by Matt Domsch <Matt_Domsch@dell.com>
  *
  */
 
@@ -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 <Matt_Domsch@dell.com>
+ *
+ * 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 <Matt_Domsch@Dell.com>");
+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 <Matt_Domsch@dell.com>
+ *  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
 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
@ 2002-10-01  3:37 Matt_Domsch
  0 siblings, 0 replies; 24+ messages in thread
From: Matt_Domsch @ 2002-10-01  3:37 UTC (permalink / raw)
  To: mochel; +Cc: linux-kernel

Pat, thanks for the feedback and changes, I appreciate it!

> Don't use struct device for the firmware objects. They're not really
> devices; they're another type of entity that has some sort of magic 
> ia32 voodoo relationship with real devices. 

Ahh, yes, it's not the right abstraction, just the easiest for this pass.
I'll look at how ACPI does it and make my own object type.  I was wondering
how to get rid of the superfluous 'power' attribute I didn't need...

> > $ cat int13_dev80/host_bus
> > PCI     02:01.0  channel: 0
> 
> How about a symlink to the bus's directory? Or the PCI device 
> that is the controller? 

Ok.

> > $ cat int13_dev80/interface
> > SCSI            id: 0  lun: 0
> 
> And, a symlink to the device itself? I liked it better the 
> way you had it before :)

Can I have both? :-)  (I hadn't implemented the symlink before, just faked
it, but I definitely want a symlink, needed the stuff exported to do it
right - thanks!}

> Ugh. Drop the ascii-fying hexdump for one.

I've been over this with Greg privately.  I moved it to raw_data, separate,
but there.  I know of only one BIOS that implements the spec right, and that
is pre-release, because I could say "see, here's what you're returning, it's
wrong these 4 ways..." in a language the BIOS guys understand - the raw
hexdump of the return struct.  This will be critical to getting the changes
required to be useful ubiquitous.

> I'd also strongly encourage you to
> split the data in 'info' to separate files.

Yep, done, with tests such that if the attribute is invalid or for some
reason shouldn't exist, it doesn't get created.  The default* files for
example - if the bios puts 0s there, they don't get made.  Likewise if the
PCI / SCSI info isn't given by bios, those don't get made either.

Here's my tree now.
.
|-- bus
|   `-- system
|       |-- devices
|       |   |-- int13_dev80 -> ../../../root/bios/int13_dev80
|       |   |-- int13_dev81 -> ../../../root/bios/int13_dev81
|       `-- drivers
|           |-- edd
`-- root
    |-- bios
    |   |-- int13_dev80
    |   |   |-- default_cylinders
    |   |   |-- default_heads
    |   |   |-- default_sectors_per_track
    |   |   |-- raw_data
    |   |   |-- extensions
    |   |   |-- host_bus
    |   |   |-- info_flags
    |   |   |-- interface
    |   |   |-- name
    |   |   |-- power
    |   |   |-- sectors
    |   |   `-- version
    |   |-- name
    |   `-- power

$ cat default_cylinders
0x0

$ cat default_heads
0x0

$ cat default_sectors_per_track
0x0

$ cat raw_data
int 13h fn 48h return struct:

1e 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
3a b9 8b 08 00 00 00 00 00 02 ff ff ff ff be dd         :...............
2c 00 00 00 50 43 49 00 53 43 53 49 00 00 00 00         ,...PCI.SCSI....
02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
00 00 00 00 00 00 00 00 00 28                           .........(

Warning: Spec violation.  Key should be 0xBEDD, is 0xDDBE
Warning: Spec violation.  Padding should be 0x20, is 0x00.

$ cat extensions
Fixed disk access

$ cat host_bus
PCI     02:01.0  channel: 0

$ cat info_flags
DMA boundry error transparent
write verify

$ cat interface
SCSI            id: 0  lun: 0

$ cat name
BIOS int 13h device 80h

$ cat power
0

$ cat sectors
0x88bb93a

$ cat version
0x30


I may try walking the disk class device list for matches rather than the
individual bus type lists - would be slightly faster and possibly less
intrusive.  That's a helpful abstraction for me.

My current stuff is in BK at http://mdomsch.bkbits.net/linux-2.5-edd.

Thanks,
Matt

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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-27 21:30 ` Matt Domsch
  2002-09-27 22:33   ` Greg KH
  2002-09-29 16:11   ` Dave Jones
@ 2002-10-01  1:55   ` Patrick Mochel
  2 siblings, 0 replies; 24+ messages in thread
From: Patrick Mochel @ 2002-10-01  1:55 UTC (permalink / raw)
  To: Matt Domsch; +Cc: linux-kernel


> |-- bus
> |   `-- system
> |       |-- devices
> |       |   |-- int13_dev80 -> ../../../root/bios/int13_dev80
> |       |   |-- int13_dev81 -> ../../../root/bios/int13_dev81
> |       `-- drivers
> |           |-- edd
> `-- root
>     |-- bios
>     |   |-- int13_dev80
>     |   |   |-- host_bus
>     |   |   |-- info
>     |   |   |-- interface
>     |   |   |-- name
>     |   |   `-- power
>     |   |-- int13_dev81
>     |   |   |-- host_bus
>     |   |   |-- info
>     |   |   |-- interface
>     |   |   |-- name
>     |   |   `-- power
>     |   |-- name
>     |   `-- power
> 
> 
> (Yes, the system bus isn't the right place for them to go, but it must
> go on some bus, and eventually it will get moved to a better place.)

[ Sorry, I didn't get this out earlier, but you're just too damn fast with 
your resubmissions.. ;)]

Don't use struct device for the firmware objects. They're not really
devices; they're another type of entity that has some sort of magic 
ia32 voodoo relationship with real devices. 

I recently converted ACPI to abandon the notion that the namespace objects 
were real devices. In doing so, I gave them their own top-level directory 
in driverfs. Don't do this. That's only a temporary solution until I 
create a 'firmware' or 'platform' directory for all of you people to live. 

> The 'info' file contains the full set of information returned by BIOS
> with extra error reporting.  This exists for vendor BIOS debugging purposes.
> 
> The 'host-bus' file contains the PCI (or ISA, HyperTransport, ...)
> identifying information, as BIOS knows it.
> 
> The 'interface' file contains the SCSI (or IDE, USB, ...) identifying
> information, as BIOS knows it.
> 
> 
> $ cat int13_dev80/host_bus
> PCI     02:01.0  channel: 0

How about a symlink to the bus's directory? Or the PCI device that is the 
controller? 

> $ cat int13_dev80/interface
> SCSI            id: 0  lun: 0

And, a symlink to the device itself? I liked it better the way you had it 
before :)

> $ cat int13_dev80/info
> 80 30 01 00                                             .0..
> 1e 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
> 3a b9 8b 08 00 00 00 00 00 02 ff ff ff ff be dd         :...............
> 2c 00 00 00 50 43 49 00 53 43 53 49 00 00 00 00         ,...PCI.SCSI....
> 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
> 00 00 00 00 00 00 00 00 00 28                           .........(
> version: 3.0
> Extensions:
>         Fixed disk access
> Info Flags:
>         dma_boundry_error_transparent
>         write_verify
> num_default_cylinders: 0
> num_default_heads: 0
> sectors_per_track: 0
> number_of_sectors: 88bb93a
> PCI     02:01.0  channel: 0
> SCSI            id: 0  lun: 0

Ugh. Drop the ascii-fying hexdump for one. I'd also strongly encourage you 
to split the data in 'info' to separate files.

	-pat


^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
@ 2002-09-30  4:32 Matt_Domsch
  0 siblings, 0 replies; 24+ messages in thread
From: Matt_Domsch @ 2002-09-30  4:32 UTC (permalink / raw)
  To: kai-germaschewski, davej; +Cc: linux-kernel

> 	drivers/{s390,macintosh,acorn}/
> makes it (IMO) cleaner to share drivers between 
> e.g. s390 and  s390x, or possibly i386/x86_64 in the future.

The i386 EDD "driver" could probably be shared with x86-64, I hadn't thought
about it before.  Likewise the IA64 efivars driver *may* eventually be
shared with x86 or others if Intel's plans come to fruition.  So I'd vote
for something in drivers/ rather than arch/ for such shareable modules.  I'm
open to moving each of these if told where the "right" place should be.
Neither are char or block drivers, so those don't make sense - purely
driverfs/proc interfaces.  Nor are they "bus" drivers ala ide or scsi.
drivers/misc is empty and I think people want to keep it that way...

Some ideas for these:
drivers/i386
drivers/efi

Thoughts?

Thanks,
Matt

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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-29 18:27       ` Russell King
@ 2002-09-29 18:52         ` Dave Jones
  0 siblings, 0 replies; 24+ messages in thread
From: Dave Jones @ 2002-09-29 18:52 UTC (permalink / raw)
  To: Russell King; +Cc: Kai Germaschewski, Matt Domsch, linux-kernel

On Sun, Sep 29, 2002 at 07:27:58PM +0100, Russell King wrote:

 > The ARM port used to have arch/arm/drivers/{block,char,net,sound} but
 > this was decried by _other_ people in the ARM community to be too
 > painful, and I was literally hounded into moving them into drivers.
 > 
 > I don't want to go back to arch/arm/drivers now, thanks.

Out of curiousity, why was this considered painful ?
Not that I change my original proposition of disinfecting
arch/i386/kernel/  Rather than proposing to set a standard
for all arch's to conform to, I had the sole intention of
trying to cut down some of the growth in that dir by factoring
out the more common things (which were CPU drivers)

		Dave

-- 
| Dave Jones.        http://www.codemonkey.org.uk
| SuSE Labs

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-29 18:20     ` Kai Germaschewski
@ 2002-09-29 18:27       ` Russell King
  2002-09-29 18:52         ` Dave Jones
  0 siblings, 1 reply; 24+ messages in thread
From: Russell King @ 2002-09-29 18:27 UTC (permalink / raw)
  To: Kai Germaschewski; +Cc: Dave Jones, Matt Domsch, linux-kernel

On Sun, Sep 29, 2002 at 01:20:44PM -0500, Kai Germaschewski wrote:
> Let me add that there are currently two places where arch specific drivers
> appear, eg:
> 
> 	arch/{cris,um}/drivers/
> and
> 	drivers/{s390,macintosh,acorn}/
> 
> I think it'd be nice to decide on one way or the other. The first place 
> has the advantage of putting all arch-specific stuff into one place, the 
> second one makes it (IMO) cleaner to share drivers between e.g. s390 and 
> s390x, or possibly i386/x86_64 in the future.

The ARM port used to have arch/arm/drivers/{block,char,net,sound} but
this was decried by _other_ people in the ARM community to be too
painful, and I was literally hounded into moving them into drivers.

I don't want to go back to arch/arm/drivers now, thanks.

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-29 16:11   ` Dave Jones
  2002-09-29 16:18     ` Zwane Mwaikambo
  2002-09-29 16:44     ` Alan Cox
@ 2002-09-29 18:20     ` Kai Germaschewski
  2002-09-29 18:27       ` Russell King
  2 siblings, 1 reply; 24+ messages in thread
From: Kai Germaschewski @ 2002-09-29 18:20 UTC (permalink / raw)
  To: Dave Jones; +Cc: Matt Domsch, linux-kernel

On Sun, 29 Sep 2002, Dave Jones wrote:

> On Fri, Sep 27, 2002 at 04:30:29PM -0500, Matt Domsch wrote:
>  >  arch/i386/kernel/edd.c           |  522 +++++++++++++++++++++++++++++++++++++++
>  >  arch/i386/kernel/i386_ksyms.c    |    6 
>  >  arch/i386/kernel/setup.c         |   20 +
> 
> Something that's been bothering me for a while, has been the
> proliferation of 'driver' type things appearing in arch/i386/kernel/
> My initial thought was to move the various CPU related 'drivers'
> (msr,cpuid,bluesmoke,microcode) to arch/i386/cpu/  [1]
> but I'm now wondering if an arch/i386/driver/ would be a better alternative.

Let me add that there are currently two places where arch specific drivers
appear, eg:

	arch/{cris,um}/drivers/
and
	drivers/{s390,macintosh,acorn}/

I think it'd be nice to decide on one way or the other. The first place 
has the advantage of putting all arch-specific stuff into one place, the 
second one makes it (IMO) cleaner to share drivers between e.g. s390 and 
s390x, or possibly i386/x86_64 in the future.

--Kai



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-29 16:11   ` Dave Jones
  2002-09-29 16:18     ` Zwane Mwaikambo
@ 2002-09-29 16:44     ` Alan Cox
  2002-09-29 18:20     ` Kai Germaschewski
  2 siblings, 0 replies; 24+ messages in thread
From: Alan Cox @ 2002-09-29 16:44 UTC (permalink / raw)
  To: Dave Jones; +Cc: Matt Domsch, linux-kernel

On Sun, 2002-09-29 at 17:11, Dave Jones wrote:
> On Fri, Sep 27, 2002 at 04:30:29PM -0500, Matt Domsch wrote:
>  >  arch/i386/kernel/edd.c           |  522 +++++++++++++++++++++++++++++++++++++++
>  >  arch/i386/kernel/i386_ksyms.c    |    6 
>  >  arch/i386/kernel/setup.c         |   20 +
> 
> Something that's been bothering me for a while, has been the
> proliferation of 'driver' type things appearing in arch/i386/kernel/
> My initial thought was to move the various CPU related 'drivers'
> (msr,cpuid,bluesmoke,microcode) to arch/i386/cpu/  [1]
> but I'm now wondering if an arch/i386/driver/ would be a better alternative.
> 
> Opinions?

Thats even more prevalent in things like the unmerged bits of the mips
tree. A lot of embedded processors have on chip everything - eg look at
the cirrus logic ARM chips or the Etrax.

The extra people use arch/foo/drivers




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-29 16:11   ` Dave Jones
@ 2002-09-29 16:18     ` Zwane Mwaikambo
  2002-09-29 16:44     ` Alan Cox
  2002-09-29 18:20     ` Kai Germaschewski
  2 siblings, 0 replies; 24+ messages in thread
From: Zwane Mwaikambo @ 2002-09-29 16:18 UTC (permalink / raw)
  To: Dave Jones; +Cc: Matt Domsch, linux-kernel

On Sun, 29 Sep 2002, Dave Jones wrote:

> On Fri, Sep 27, 2002 at 04:30:29PM -0500, Matt Domsch wrote:
>  >  arch/i386/kernel/edd.c           |  522 +++++++++++++++++++++++++++++++++++++++
>  >  arch/i386/kernel/i386_ksyms.c    |    6 
>  >  arch/i386/kernel/setup.c         |   20 +
> 
> Something that's been bothering me for a while, has been the
> proliferation of 'driver' type things appearing in arch/i386/kernel/
> My initial thought was to move the various CPU related 'drivers'
> (msr,cpuid,bluesmoke,microcode) to arch/i386/cpu/  [1]
> but I'm now wondering if an arch/i386/driver/ would be a better alternative.
> 
> Opinions?

Then again, drivers/char has some x86 specific drivers too (e.g. RNGs), 
perhaps it really should get dumped in drivers/

	Zwane
-- 
function.linuxpower.ca


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-27 21:30 ` Matt Domsch
  2002-09-27 22:33   ` Greg KH
@ 2002-09-29 16:11   ` Dave Jones
  2002-09-29 16:18     ` Zwane Mwaikambo
                       ` (2 more replies)
  2002-10-01  1:55   ` Patrick Mochel
  2 siblings, 3 replies; 24+ messages in thread
From: Dave Jones @ 2002-09-29 16:11 UTC (permalink / raw)
  To: Matt Domsch; +Cc: linux-kernel

On Fri, Sep 27, 2002 at 04:30:29PM -0500, Matt Domsch wrote:
 >  arch/i386/kernel/edd.c           |  522 +++++++++++++++++++++++++++++++++++++++
 >  arch/i386/kernel/i386_ksyms.c    |    6 
 >  arch/i386/kernel/setup.c         |   20 +

Something that's been bothering me for a while, has been the
proliferation of 'driver' type things appearing in arch/i386/kernel/
My initial thought was to move the various CPU related 'drivers'
(msr,cpuid,bluesmoke,microcode) to arch/i386/cpu/  [1]
but I'm now wondering if an arch/i386/driver/ would be a better alternative.

Opinions?

		Dave

[1] also a more natural home for things like cpufreq if/when it gets integrated.
-- 
| Dave Jones.        http://www.codemonkey.org.uk
| SuSE Labs

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-27 21:30 ` Matt Domsch
@ 2002-09-27 22:33   ` Greg KH
  2002-09-29 16:11   ` Dave Jones
  2002-10-01  1:55   ` Patrick Mochel
  2 siblings, 0 replies; 24+ messages in thread
From: Greg KH @ 2002-09-27 22:33 UTC (permalink / raw)
  To: Matt Domsch; +Cc: linux-kernel

Looks nice, just a few minor comments:

> $ cat int13_dev80/host_bus
> PCI     02:01.0  channel: 0
> $ cat int13_dev80/interface
> SCSI            id: 0  lun: 0
> $ cat int13_dev80/info
> 80 30 01 00                                             .0..
> 1e 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
> 3a b9 8b 08 00 00 00 00 00 02 ff ff ff ff be dd         :...............
> 2c 00 00 00 50 43 49 00 53 43 53 49 00 00 00 00         ,...PCI.SCSI....
> 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
> 00 00 00 00 00 00 00 00 00 28                           .........(
> version: 3.0
> Extensions:
>         Fixed disk access
> Info Flags:
>         dma_boundry_error_transparent
>         write_verify
> num_default_cylinders: 0
> num_default_heads: 0
> sectors_per_track: 0
> number_of_sectors: 88bb93a
> PCI     02:01.0  channel: 0
> SCSI            id: 0  lun: 0
> 
> Warning: Spec violation.  Key should be 0xBEDD, is 0xDDBE
> 

Don't you already get the PCI and SCSI lines in the info file, from the
host_bus and interface files?

And that's a nice way to export binary data through a text file :)

Any way to split out the fields as individual files (version,
extensions, info_flags, num_default_cylinders, and so on)?

> @@ -981,3 +981,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.

You should fix up this wording as you aren't doing anything in the /proc
fs anymore :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
       [not found] <20BF5713E14D5B48AA289F72BD372D6821CE34@AUSXMPC122.aus.amer.dell.com>
@ 2002-09-27 21:30 ` Matt Domsch
  2002-09-27 22:33   ` Greg KH
                     ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Matt Domsch @ 2002-09-27 21:30 UTC (permalink / raw)
  To: linux-kernel

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, 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 via
driverfs.

.
|-- bus
|   `-- system
|       |-- devices
|       |   |-- int13_dev80 -> ../../../root/bios/int13_dev80
|       |   |-- int13_dev81 -> ../../../root/bios/int13_dev81
|       `-- drivers
|           |-- edd
`-- root
    |-- bios
    |   |-- int13_dev80
    |   |   |-- host_bus
    |   |   |-- info
    |   |   |-- interface
    |   |   |-- name
    |   |   `-- power
    |   |-- int13_dev81
    |   |   |-- host_bus
    |   |   |-- info
    |   |   |-- interface
    |   |   |-- name
    |   |   `-- power
    |   |-- name
    |   `-- power


(Yes, the system bus isn't the right place for them to go, but it must
go on some bus, and eventually it will get moved to a better place.)

The 'info' file contains the full set of information returned by BIOS
with extra error reporting.  This exists for vendor BIOS debugging purposes.

The 'host-bus' file contains the PCI (or ISA, HyperTransport, ...)
identifying information, as BIOS knows it.

The 'interface' file contains the SCSI (or IDE, USB, ...) identifying
information, as BIOS knows it.


$ cat int13_dev80/host_bus
PCI     02:01.0  channel: 0
$ cat int13_dev80/interface
SCSI            id: 0  lun: 0
$ cat int13_dev80/info
80 30 01 00                                             .0..
1e 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
3a b9 8b 08 00 00 00 00 00 02 ff ff ff ff be dd         :...............
2c 00 00 00 50 43 49 00 53 43 53 49 00 00 00 00         ,...PCI.SCSI....
02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
00 00 00 00 00 00 00 00 00 28                           .........(
version: 3.0
Extensions:
        Fixed disk access
Info Flags:
        dma_boundry_error_transparent
        write_verify
num_default_cylinders: 0
num_default_heads: 0
sectors_per_track: 0
number_of_sectors: 88bb93a
PCI     02:01.0  channel: 0
SCSI            id: 0  lun: 0

Warning: Spec violation.  Key should be 0xBEDD, is 0xDDBE

$ cat int13_dev81/host_bus
PCI     04:00.0  channel: 0
$ cat int13_dev81/interface
SCSI            id: 0  lun: 0
$ cat int13_dev81/info
81 30 01 00                                             .0..
1e 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
00 c0 3a 05 00 00 00 00 00 02 ff ff ff ff dd be         ..:.............
2c 00 00 00 50 43 49 20 53 43 53 49 20 20 20 20         ,...PCI SCSI
04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00         ................
00 00 00 00 00 00 00 00 00 87                           ..........
version: 3.0
Extensions:
        Fixed disk access
Info Flags:
        dma_boundry_error_transparent
        write_verify
num_default_cylinders: 0
num_default_heads: 0
sectors_per_track: 0
number_of_sectors: 53ac000
PCI     04:00.0  channel: 0
SCSI            id: 0  lun: 0


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).  The Adaptec BIOS has
some cleanup work to do yet, The PERC3/QC BIOS has made the required
changes to fully support EDD now.

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 driverfs

If you use this, please send reports of success/failure, and the
adapter types and BIOS versions, to edd30@domsch.com.  I'm keeping a
tally at http://domsch.com/linux/edd30/results.html.


 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           |  522 +++++++++++++++++++++++++++++++++++++++
 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, 776 insertions(+)


Patch against BK-current:
    http://domsch.com/linux/edd30/edd-driverfs-3.patch
    http://domsch.com/linux/edd30/edd-driverfs-3.patch.sign

BK:
    http://mdomsch.bkbits.net/linux-2.5-edd

Future work includes exporting a symlink from the EDD device to the
actual disk device in driverfs.  I'll continue working with Patrick
Mochel, Greg KH, and the appropriate subsystem maintainers on the
details needed to make this work well.

Feedback appreciated.  I'd like to see this included before the 2.5 
feature freeze if at all possible.

Thanks,
Matt

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


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	Fri Sep 27 15:53:05 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	Thu Sep 26 21:44:44 2002
+++ linux-2.5-edd/arch/i386/Config.help	Fri Sep 27 15:53:06 2002
@@ -981,3 +981,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	Fri Sep 27 15:53:06 2002
@@ -44,6 +44,8 @@
  *
  * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
  * by Robert Schwebel, December 2001 <robert@schwebel.de>
+ *    
+ * BIOS EDD support September 2002 by Matt Domsch <Matt_Domsch@dell.com>
  *
  */
 
@@ -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	Thu Sep 26 21:44:44 2002
+++ linux-2.5-edd/arch/i386/config.in	Fri Sep 27 15:53:06 2002
@@ -198,6 +198,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	Thu Sep 26 21:44:44 2002
+++ linux-2.5-edd/arch/i386/defconfig	Fri Sep 27 15:53:06 2002
@@ -70,6 +70,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	Fri Sep 20 13:11:58 2002
+++ linux-2.5-edd/arch/i386/kernel/Makefile	Wed Sep 25 11:15:18 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
 
 EXTRA_AFLAGS   := -traditional
 
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	Fri Sep 27 15:53:06 2002
@@ -0,0 +1,522 @@
+/*
+ * BIOS Enhanced Disk Device Services
+ * conformant to T13 Committee, Project D1572 www.t13.org
+ *
+ * Copyright (C) 2002 Dell Computer Corporation <Matt_Domsch@dell.com>
+ *
+ * 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.
+ *
+ * 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 <linux/device.h>
+#include <asm/edd.h>
+
+MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
+MODULE_DESCRIPTION("driver model interface to BIOS EDD information");
+MODULE_LICENSE("GPL");
+
+#define EDD_VERSION "0.04 2002-Sep-27"
+
+static struct device *edd_devices[EDDMAXNR];
+static struct device bios_device = {
+	.name     = "BIOS devices",
+	.bus_id   = "bios",
+	.dir = {
+		.mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO),
+	},		
+};
+
+/*
+ * FIXME - this uses system_bus_type because
+ * platform_bus_type isn't exported (yet) and
+ * it'll likely wind up in named bus type yet
+*/
+
+static struct device_driver edd_driver = {
+	.name =  "edd",
+	.bus  =   &system_bus_type,
+	.dir =  {
+		.mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO),
+	}
+};
+
+/*
+ * EDD devices are exactly struct device.
+ * EDD device attributes are exactly struct device_attribute
+ */
+
+#define EDD_DEVICE_ATTR(_name,_mode,_show) \
+struct device_attribute edd_attr_##_name = { 	\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.show	= _show,				\
+};
+
+#define to_edd_attr(_attr) container_of(_attr,struct device_attribute,attr)
+#define to_edd_device(_dir) container_of(_dir,struct device,dir)
+	
+static ssize_t
+edd_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
+	      char * buf, size_t count, loff_t off)
+{
+	struct device * dev = to_edd_device(dir);
+	struct device_attribute * edd_attr = to_edd_attr(attr);
+	ssize_t ret = 0;
+
+	if (edd_attr->show)
+		ret = edd_attr->show(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_unparse_interface()
+ *
+ * Returns: number of bytes written, or 0 on failure
+ */
+static ssize_t
+__edd_unparse_host_bus(struct device *dev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *edd=dev_get_drvdata(dev);
+        char *p = buf;
+	int i;
+        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, " ");
+                }
+        }
+
+        if (!strncmp(edd->params.host_bus_type, "ISA", 3)) {
+                p += sprintf(p, "\tbase_address: %x\n",
+                             edd->params.interface_path.isa.base_address);
+        } else if (!strncmp(edd->params.host_bus_type, "PCIX", 4) ||
+		   !strncmp(edd->params.host_bus_type, "PCI", 3)) {
+                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);
+        } else if (!strncmp(edd->params.host_bus_type, "IBND", 4) ||
+		   !strncmp(edd->params.host_bus_type, "XPRS", 4) ||
+		   !strncmp(edd->params.host_bus_type, "HTPT", 4)) {
+                p += sprintf(p,
+                             "\tTBD: %llx\n",
+                             edd->params.interface_path.ibnd.reserved);
+
+        }
+	else {
+                p += sprintf(p, "\tunknown: %llx\n",
+                             edd->params.interface_path.unknown.reserved);
+	}
+	return (p - buf);
+}
+
+/**
+ * edd_show_host_bus() - returns interface path to user space
+ *
+ * Returns: number of bytes written, or 0 on failure
+ */
+static ssize_t
+edd_show_host_bus(struct device *dev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *edd=dev_get_drvdata(dev);
+        uint8_t c=0;
+	int i, nonzero_path=0;
+	if (!dev || !edd || !buf || off) {
+		return 0;
+	}
+        
+        if (! (edd->params.key == 0xBEDD || edd->params.key == 0xDDBE)) {
+		return 0;
+	}
+        
+        for (i=30; i<=73; i++) {
+		c = *(((uint8_t *)edd)+i+4);
+		if (c) {
+			nonzero_path++;
+			break;
+		}
+        }
+        if (!nonzero_path) {
+		return 0;
+        }
+	return __edd_unparse_host_bus(dev, buf, count, off);
+}
+
+/**
+ * __edd_unparse_interface()
+ *
+ * Returns: number of bytes written, or 0 on failure
+ */
+static ssize_t
+__edd_unparse_interface(struct device *dev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *edd=dev_get_drvdata(dev);
+        char *p = buf;
+	int i;
+
+        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, " ");
+                }
+        }
+        if (!strncmp(edd->params.interface_type, "ATAPI", 5)) {
+                p += sprintf(p, "\tdevice: %x  lun: %x\n",
+                             edd->params.device_path.atapi.device,
+                             edd->params.device_path.atapi.lun);
+        } else if (!strncmp(edd->params.interface_type, "ATA", 3)) {
+                p += sprintf(p, "\tdevice: %x\n",
+                             edd->params.device_path.ata.device);
+        } else if (!strncmp(edd->params.interface_type, "SCSI", 4)) {
+                p += sprintf(p, "\tid: %x  lun: %llx\n",
+                             edd->params.device_path.scsi.id,
+                             edd->params.device_path.scsi.lun);
+        } else if (!strncmp(edd->params.interface_type, "USB", 3)) {
+                p += sprintf(p, "\tserial_number: %llx\n", 
+                             edd->params.device_path.usb.serial_number);
+        } else if (!strncmp(edd->params.interface_type, "1394", 4)) {
+                p += sprintf(p, "\teui: %llx\n", 
+                             edd->params.device_path.i1394.eui);
+        } else if (!strncmp(edd->params.interface_type, "FIBRE", 5)) {
+                p += sprintf(p, "\twwid: %llx lun: %llx\n",
+                             edd->params.device_path.fibre.wwid,
+                             edd->params.device_path.fibre.lun);
+        } else if (!strncmp(edd->params.interface_type, "I2O", 3)) {
+                p += sprintf(p, "\tidentity_tag: %llx\n", 
+                             edd->params.device_path.i2o.identity_tag);
+        } else if (!strncmp(edd->params.interface_type, "RAID", 4)) {
+                p += sprintf(p, "\tidentity_tag: %x\n", 
+                             edd->params.device_path.raid.array_number);
+        } else if (!strncmp(edd->params.interface_type, "SATA", 4)) {
+                p += sprintf(p, "\tdevice: %x\n", 
+                             edd->params.device_path.sata.device);
+        } else {
+		p += sprintf(p, "\tunknown: %llx %llx\n",
+			     edd->params.device_path.unknown.reserved1,
+			     edd->params.device_path.unknown.reserved2);
+	}
+
+	return (p - buf);
+}
+
+/**
+ * edd_show_interface()
+ *
+ * Returns: number of bytes written, or 0 on failure
+ */
+static ssize_t
+edd_show_interface(struct device *dev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *edd=dev_get_drvdata(dev);
+        uint8_t c=0;
+	int i, nonzero_path=0;
+	if (!dev || !edd || !buf || off) {
+		return 0;
+	}
+        
+        if (! (edd->params.key == 0xBEDD || edd->params.key == 0xDDBE)) {
+		return 0;
+	}
+        
+        for (i=30; i<=73; i++) {
+		c = *(((uint8_t *)edd)+i+4);
+		if (c) {
+			nonzero_path++;
+			break;
+		}
+        }
+        if (!nonzero_path) {
+		return 0;
+        }
+	return __edd_unparse_interface(dev, buf, count, off);
+}
+
+/**
+ * edd_info_show() - unparses EDD information, returned to user-space
+ *
+ * Rather verbose compared to show_host_bus or show_interface
+ * Returns: number of bytes written, or 0 on failure
+ */
+static ssize_t
+edd_info_show(struct device *dev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *edd=dev_get_drvdata(dev);
+        int i, warn_padding=0, nonzero_path=0, warn_key=0, warn_checksum=0;
+        uint8_t checksum=0, c=0;
+        char *p = buf;
+	if (!dev || !edd || !buf || off) {
+		return 0;
+	}
+        
+	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);
+
+        /* 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 - 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 - buf);
+		}
+        }
+
+	p += __edd_unparse_host_bus (dev, p, count - (p - buf), off);
+	p += __edd_unparse_interface(dev, p, count - (p - buf), off);
+
+	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 - buf);
+}
+
+static EDD_DEVICE_ATTR(info,0444,edd_info_show);
+static EDD_DEVICE_ATTR(interface,0444,edd_show_interface);
+static EDD_DEVICE_ATTR(host_bus,0444,edd_show_host_bus);
+
+static struct device_attribute * def_attrs[] = {
+	&edd_attr_info,
+	&edd_attr_interface,
+	&edd_attr_host_bus,
+	NULL,
+};
+
+static int
+edd_create_file(struct device *dev, struct device_attribute * attr)
+{
+	return device_create_file(dev, attr);
+}
+
+static int edd_populate_dir(struct device * dev)
+{
+	struct device_attribute * attr;
+	int i;
+	int error = 0;
+	
+	for (i = 0; (attr = def_attrs[i]); i++) {
+		if ((error = edd_create_file(dev,attr))) {
+			break;
+		}
+	}
+	return error;
+}
+
+static int edd_device_register(struct device *dev, int i)
+{
+	int error;
+	
+	if (!dev) return 1;
+	memset(dev, 0, sizeof(*dev));
+	dev_set_drvdata(dev, &edd[i]);
+	dev->driver      = &edd_driver;
+	dev->bus         = dev->driver->bus;
+	dev->parent      = &bios_device;
+	dev->dir.ops     = &edd_attr_ops;
+	snprintf(dev->name, DEVICE_NAME_SIZE, "BIOS int 13h device %02xh", edd[i].device);
+	snprintf(dev->bus_id, BUS_ID_SIZE, "int13_dev%02x", edd[i].device);
+	dev->dir.name    = dev->name;
+
+	error = device_register(dev);
+	if (error) return error;
+
+	error = edd_populate_dir(dev);
+	return error;
+}
+
+/**
+ * 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;
+	int rc;
+
+	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;
+	}
+
+	rc = device_register(&bios_device);
+	if (rc) return rc;
+
+	rc = driver_register(&edd_driver);
+	if (rc) {
+		put_device(&bios_device);
+		return rc;
+	}
+
+	for (i=0; i<eddnr && i<EDDMAXNR; i++) {
+		edd_devices[i] = kmalloc(sizeof(*edd_devices[i]), GFP_KERNEL);
+		if (edd_devices[i]) {
+			edd_device_register(edd_devices[i], i);
+		}
+	}
+
+	return 0;
+}
+
+
+static void __exit
+edd_exit(void)
+{
+	int i;
+
+	for (i=0; i<eddnr && i<EDDMAXNR; i++) {
+		if (edd_devices[i]) {
+			put_device(edd_devices[i]);
+			kfree(edd_devices[i]);
+		}
+	}
+	put_driver(&edd_driver);
+	put_device(&bios_device);
+}
+
+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	Thu Sep 26 21:44:44 2002
+++ linux-2.5-edd/arch/i386/kernel/i386_ksyms.c	Fri Sep 27 15:53:06 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;
@@ -177,3 +178,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	Fri Sep 20 13:11:58 2002
+++ linux-2.5-edd/arch/i386/kernel/setup.c	Fri Sep 27 15:53:06 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>
 #include <asm/arch_hooks.h>
 #include "setup_arch_pre.h"
@@ -466,6 +467,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.
@@ -843,6 +862,7 @@
 #endif
 	ARCH_SETUP
 	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	Fri Sep 27 15:53:27 2002
@@ -0,0 +1,162 @@
+/*
+ * linux/include/asm-i386/edd.h
+ *  by Matt Domsch <Matt_Domsch@dell.com>
+ *  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	Fri Sep 27 15:53:27 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
 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
@ 2002-09-10 22:43 Matt_Domsch
  0 siblings, 0 replies; 24+ messages in thread
From: Matt_Domsch @ 2002-09-10 22:43 UTC (permalink / raw)
  To: mochel, greg; +Cc: phillips, linux-kernel

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 www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com


^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
@ 2002-09-09  1:17 Matt_Domsch
  0 siblings, 0 replies; 24+ messages in thread
From: Matt_Domsch @ 2002-09-09  1:17 UTC (permalink / raw)
  To: mochel, greg; +Cc: phillips, linux-kernel

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



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-04  4:17   ` Greg KH
@ 2002-09-08  0:39     ` Patrick Mochel
  0 siblings, 0 replies; 24+ messages in thread
From: Patrick Mochel @ 2002-09-08  0:39 UTC (permalink / raw)
  To: Greg KH; +Cc: Daniel Phillips, Matt_Domsch, linux-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 5274 bytes --]


> 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

[-- Attachment #2: pub.c --]
[-- Type: TEXT/PLAIN, Size: 7183 bytes --]

/*
 * pub.c - exploting driverfs for fun and profit
 *
 * Copyright (c) 2002 Patrick Mochel
 *                    Open Source Development Lab
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * This is a sample subsystem to illustrate how easy it is to latch on to
 * driverfs and exploit it. It is the 'pub' subsystem. Objects of type 'beer' 
 * can be registered and unregistered with the pub via beer_register and 
 * beer_unregister.
 * 
 * Every time a beer is registered with the pub subsystem, a directory is
 * created for it. The pub subsystem could then create files on behalf of
 * the beer, in the beer's directory. Once the beer has registered, it
 * can create files for itself in its directory. A second, more robust
 * example will surely follow. 
 *
 * Compiled with

CFLAGS = -Wall -O2 -fomit-frame-pointer -DMODULE -D__KERNEL__
IDIR = /home/mochel/src/kernel/devel/linux-2.5/include

pub.o::pub.c
        $(CC) $(CFLAGS) -I$(IDIR) -c -o $@ $<
 */

#include <linux/module.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/err.h>
#include <linux/driverfs_fs.h>

struct beer {
	char			* name;
	char			* style;
	char			* nation;
	u32			founded;
	u32			alcohol;
	u32			calories;
	struct list_head	node;
	struct driver_dir_entry dir;
};

struct beer_attribute {
	struct attribute	attr;
	ssize_t (*show)(struct beer * beer, char * buf, size_t count, loff_t off);
	ssize_t (*store)(struct beer * beer, const char * buf, size_t count, loff_t off);
};

#define BEER_ATTR(_name,_mode,_show,_store) \
struct beer_attribute beer_attr_##_name = { 		\
	.attr = {.name = __stringify(_name), .mode = _mode },	\
	.show	= _show,				\
	.store	= _store,				\
};

#define to_beer_attr(_attr) container_of(_attr,struct beer_attribute,attr)

#define to_beer(_dir) container_of(_dir,struct beer,dir)


static LIST_HEAD(beer_list);

static struct driver_dir_entry pub_dir = {
	.name	= "pub",
	.mode	= (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
};

static struct driver_dir_entry pub_beer_dir = {
	.name	= "beer",
	.mode	= (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
};

/* driverfs ops for beer attribute files */

static int empty_attr_open(struct driver_dir_entry * dir)
{
	/* nothing to do */
	return 0;
}

static int empty_attr_close(struct driver_dir_entry * dir)
{
	/* nothing to do */
	return 0;
}

static ssize_t
beer_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
	       char * buf, size_t count, loff_t off)
{
	struct beer * beer = to_beer(dir);
	struct beer_attribute * beer_attr = to_beer_attr(attr);
	ssize_t ret = 0;

	if (beer_attr->show)
		ret = beer_attr->show(beer,buf,count,off);
	return ret;
}

static ssize_t
beer_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
		const char * buf, size_t count, loff_t off)
{
	struct beer * beer = to_beer(dir);
	struct beer_attribute * beer_attr = to_beer_attr(attr);
	ssize_t ret = 0;

	if (beer_attr->store)
		ret = beer_attr->store(beer,buf,count,off);
	return ret;
}

static struct driverfs_ops beer_attr_ops = {
	.open	= empty_attr_open,
	.close	= empty_attr_close,
	.show	= beer_attr_show,
	.store	= beer_attr_store,
};


/* default attributes for beer */

static ssize_t style_show(struct beer * beer, char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",beer->style);
}

static BEER_ATTR(style,0444,style_show,NULL);


static ssize_t nation_show(struct beer * beer, char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",beer->nation);
}

static BEER_ATTR(nation,0444,nation_show,NULL);


static ssize_t founded_show(struct beer * beer, char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%u\n",beer->founded);
}

static BEER_ATTR(founded,0444,founded_show,NULL);


static ssize_t alcohol_show(struct beer * beer, char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%u\n",beer->alcohol);
}

static BEER_ATTR(alcohol,0444,alcohol_show,NULL);


static ssize_t calories_show(struct beer * beer, char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%u\n",beer->calories);
}

static BEER_ATTR(calories,0444,calories_show,NULL);

static struct beer_attribute * def_attrs[] = {
	&beer_attr_style,
	&beer_attr_nation,
	&beer_attr_founded,
	&beer_attr_alcohol,
	&beer_attr_calories,
	NULL,
};

int beer_create_file(struct beer * beer, struct beer_attribute * attr)
{
	int error = -EINVAL;
	if (beer)
		error = driverfs_create_file(&attr->attr,&beer->dir);
	return error;
}

void beer_remove_file(struct beer * beer, struct beer_attribute * attr)
{
	if (beer)
		driverfs_remove_file(&beer->dir,attr->attr.name);
}

static void beer_remove_dir(struct beer * beer)
{
	driverfs_remove_dir(&beer->dir);
}

static int populate_dir(struct beer * beer)
{
	struct beer_attribute * attr;
	int i;
	int error = 0;
	
	for (i = 0; (attr = def_attrs[i]); i++) {
		if ((error = beer_create_file(beer,attr))) {
			beer_remove_dir(beer);
			break;
		}
	}
	return error;
}

static int beer_make_dir(struct beer * beer)
{
	int error;

	beer->dir.name = beer->name;
	beer->dir.ops = &beer_attr_ops;

	error = driverfs_create_dir(&beer->dir,&pub_beer_dir);
	if (!error)
		error = populate_dir(beer);
	return error;
}

int beer_register(struct beer * beer)
{
	int error;
	error = beer_make_dir(beer);
	if (!error)
		list_add_tail(&beer->node,&beer_list);
	return error;
}

void beer_unregister(struct beer * beer)
{
	beer_remove_dir(beer);
	list_del_init(&beer->node);
}

static struct beer guinness_beer = {
	.name		= "Guinness",
	.style		= "stout",
	.nation		= "Ireland",
	.founded	= 1759,
	.alcohol	= 473,
	.calories	= 43,
};

static struct beer pabst_beer = {
	.name		= "Pabst",
	.style		= "pilsner",
	.nation		= "USA",
	.founded	= 1844,
	.alcohol	= 578,
	.calories	= 45,
};

static int __init pub_init(void)
{
	driverfs_create_dir(&pub_dir,NULL);
	driverfs_create_dir(&pub_beer_dir,&pub_dir);
	beer_register(&guinness_beer);
	beer_register(&pabst_beer);
	return 0;
}

static void __exit pub_exit(void)
{
	beer_unregister(&guinness_beer);
	beer_unregister(&pabst_beer);
	driverfs_remove_dir(&pub_beer_dir);
	driverfs_remove_dir(&pub_dir);
}

subsys_initcall(pub_init);
module_exit(pub_exit);

[-- Attachment #3: pat.c --]
[-- Type: TEXT/PLAIN, Size: 4777 bytes --]

/*
 * pat.c - an in-kernel representation of myself.
 *
 * Copyright (c) 2002 Patrick Mochel
 *                    Open Source Development Lab
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * Compiled with

CFLAGS = -Wall -O2 -fomit-frame-pointer -DMODULE -D__KERNEL__
IDIR = /home/mochel/src/kernel/devel/linux-2.5/include

pat.o::pat.c
        $(CC) $(CFLAGS) -I$(IDIR) -c -o $@ $<
 */

#include <linux/module.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/err.h>
#include <linux/driverfs_fs.h>

struct simple_attribute {
	struct attribute	attr;
	ssize_t (*show)(char * buf, size_t count, loff_t off);
};

#define SIMPLE_ATTR(_name,_mode,_show) \
struct simple_attribute sattr_##_name = { 		\
	.attr = {.name = __stringify(_name), .mode = _mode },	\
	.show	= _show,				\
};


static char     * who = "myself";
static char     * what = "working";
static char     * when = "not for long";
static char     * where = "office";
static char     * why = "catching up";
static char     * how = "hungover";
static u32      dollars = 6;
static u32      cents = 89;
static char     * beverage = "coffee";
static int      bev_size = 12;

#define to_simple_attr(_attr) container_of(_attr,struct simple_attribute,attr)


/* driverfs ops for displaying my attributes */

static int pat_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
			 char * buf, size_t count, loff_t off)
{
	struct simple_attribute * sattr = to_simple_attr(attr);
	if (sattr->show)
		return sattr->show(buf,count,off);
	return 0;
}

static struct driverfs_ops pat_attr_ops = {
	.show	pat_attr_show,
};

static struct driver_dir_entry pat_dir = {
	.name	= "pat",
	.mode	= (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
	.ops	= &pat_attr_ops,
};


/* exporting my attributes */

static ssize_t show_who(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",who);
}

static SIMPLE_ATTR(who,0444,show_who);


static ssize_t show_what(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",what);
}

static SIMPLE_ATTR(what,0444,show_what);


static ssize_t show_when(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",when);
}

static SIMPLE_ATTR(when,0444,show_when);


static ssize_t show_where(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",where);
}

static SIMPLE_ATTR(where,0444,show_where);


static ssize_t show_why(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",why);
}

static SIMPLE_ATTR(why,0444,show_why);


static ssize_t show_how(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",how);
}

static SIMPLE_ATTR(how,0444,show_how);


static ssize_t show_cash(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%u.%u\n",dollars,cents);
}

static SIMPLE_ATTR(cash,0444,show_cash);


static ssize_t show_beverage(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%s\n",beverage);
}

static SIMPLE_ATTR(beverage,0444,show_beverage);


static ssize_t show_bev_size(char * buf, size_t count, loff_t off)
{
	return off ? 0 : snprintf(buf,50,"%u\n",bev_size);
}

static SIMPLE_ATTR(bev_size,0444,show_bev_size);


static struct simple_attribute * pat_attrs[] = {
	&sattr_who,
	&sattr_what,
	&sattr_when,
	&sattr_where,
	&sattr_why,
	&sattr_how,
	&sattr_cash,
	&sattr_beverage,
	&sattr_bev_size,
	NULL,
};

static int populate_dir(void)
{
	struct simple_attribute * attr;
	int i;
	int error = 0;
	
	for (i = 0; (attr = pat_attrs[i]); i++) {
		if ((error = driverfs_create_file(&attr->attr,&pat_dir)))
			break;
	}
	return error;
}

static int __init pat_init(void)
{
	driverfs_create_dir(&pat_dir,NULL);
	return populate_dir();
}

static void __exit pat_exit(void)
{
	driverfs_remove_dir(&pat_dir);
}

subsys_initcall(pat_init);
module_exit(pat_exit);

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-04  4:35 ` Andre Hedrick
@ 2002-09-04 16:02   ` Matt Domsch
  0 siblings, 0 replies; 24+ messages in thread
From: Matt Domsch @ 2002-09-04 16:02 UTC (permalink / raw)
  To: Andre Hedrick; +Cc: linux-kernel

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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-03 22:05 Matt Domsch
  2002-09-03 23:29 ` Daniel Phillips
@ 2002-09-04  4:35 ` Andre Hedrick
  2002-09-04 16:02   ` Matt Domsch
  1 sibling, 1 reply; 24+ messages in thread
From: Andre Hedrick @ 2002-09-04  4:35 UTC (permalink / raw)
  To: Matt Domsch; +Cc: linux-kernel


WOOHOO!

This looks like some serious fun to make it go!
Matt, how about a location for a normal patch for those of us who do not
believe in BK.

On Tue, 3 Sep 2002, Matt Domsch wrote:

> x86 systems suffer from a disconnect between what BIOS believes is the
> boot disk, and what Linux thinks BIOS thinks is the boot disk.  BIOS
> Enhanced Disk Device Services (EDD) 3.0 provides the ability for disk
> adapter BIOSs to tell the OS what it believes is the boot disk.  While
> this isn't widely implemented in BIOSs yet (thus shouldn't be
> completely trusted), it's time that Linux received support to be
> ready as BIOSs with this feature do become available.
> 
> EDD works by providing the bus (PCI, PCI-X, ISA, InfiniBand, PCI
> Express, or HyperTransport) location (e.g. PCI 02:01.0) and interface
> (ATAPI, ATA, SCSI, USB, 1394, FibreChannel, I2O, RAID, SATA) location
> (e.g. SCSI ID 5 LUN 0) information for each BIOS int13 device.  The
> patch below creates CONFIG_EDD, that when defined, makes the calls to
> retrieve and store this information.  It then exports it (yes, another
> /proc, glad to change it to driverfs or whatever else when that makes
> sense) in /proc/edd/{bios-device-number}, as such:
> 
> # ls /proc/edd/
> 80  81  82  83  84  85
> 
> # cat /proc/edd/80
> host_bus_type: PCI 	02:01.0  channel: 0
> interface_type: SCSI    	id: 0  lun: 0
> 
> Warning: Spec violation.  Key should be 0xBEDD, is 0xDDBE
> Warning: Spec violation.  Padding should be 0x20, is 0x00
> 
> # cat /proc/edd/81
> host_bus_type: PCI 	04:00.0  channel: 0
> interface_type: SCSI    	id: 0  lun: 0
> 
> Warning: Spec violation.  Device Path checksum invalid (0x4b should be 0x00).
> 
> In the above case, BIOS int13 device 80 (the boot disk) believes it is
> on PCI 02:01.0, SCSI bus 0, ID 0 LUN 0 (in this case it's an Adaptec
> 39160 add-in card).  Likewise, device 81 believes it's at PCI 04:00.0,
> channel 0, ID 0, LUN 0 (a Dell PERC3/QC card).  In both cases the BIOS
> vendors have some cleanup work to do, so I warn when they don't adhere
> to the spec.
> 
> It's possible to query device drivers from user-space (either via a
> SCSI ioctl, or IDE /proc/ide/*/config), to compare results to
> determine which disk is the boot disk.
> 
> At most 6 BIOS devices are reported, as that fills the space that's
> left in the empty_zero_page.  In general you only care about device
> 80h, though for software RAID1 knowing what 81h is might be useful also.
> 
> The major changes implemented in this patch:
> arch/i386/boot/setup.S - int13 real mode calls store results in empty_zero_page
> arch/i386/kernel/setup.c - copy results from empty_zero_page to local
> storage
> arch/i386/kernel/edd.c - export results via /proc/edd/
> 
> If you use this, please send reports of success/failure, and the
> adapter types and BIOS versions, to edd30@domsch.com.  I'm keeping a
> tally at http://domsch.com/linux/edd30/results.html.  If built as
> CONFIG_EDD=m, please 'modprobe edd debug=1' and send those results -
> it's more verbose.
> 
> Patch below applies to BK-current 2.5.x.  Also available in BitKeeper
> at http://mdomsch.bkbits.net/linux-2.5-edd
> 
> Feedback appreciated.
> 
> 
> Thanks,
> Matt
> 
> -- 
> Matt Domsch
> Sr. Software Engineer, Lead Engineer, Architect
> Dell Linux Solutions www.dell.com/linux
> Linux on Dell mailing lists @ http://lists.us.dell.com
> #1 US Linux Server provider for 2001 and Q1-2/2002! (IDC Aug 2002)
> 
> You can import this changeset into BK by piping this whole message to
> '| bk receive [path to repository]' or apply the patch as usual.
> 
> ===================================================================
> 
> 
> ChangeSet@1.582, 2002-09-03 15:05:38-05:00, Matt_Domsch@dell.com
>   Initial release of x86 BIOS Enhanced Disk Device (EDD) polling
> 
> 
>  Documentation/i386/zero-page.txt |    2 
>  arch/i386/Config.help            |   10 
>  arch/i386/boot/setup.S           |   46 +++
>  arch/i386/config.in              |    4 
>  arch/i386/defconfig              |    1 
>  arch/i386/kernel/Makefile        |    1 
>  arch/i386/kernel/edd.c           |  455 +++++++++++++++++++++++++++++++++++++++
>  arch/i386/kernel/i386_ksyms.c    |    6 
>  arch/i386/kernel/setup.c         |   23 +
>  include/asm-i386/edd.h           |  162 +++++++++++++
>  10 files changed, 710 insertions
> 
> 
> diff -Nru a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt
> --- a/Documentation/i386/zero-page.txt	Tue Sep  3 15:06:13 2002
> +++ b/Documentation/i386/zero-page.txt	Tue Sep  3 15:06:13 2002
> @@ -31,6 +31,7 @@
>  
>  0x1e0	unsigned long	ALT_MEM_K, alternative mem check, in Kb
>  0x1e8	char		number of entries in E820MAP (below)
> +0x1e9	unsigned char	number of entries in EDDBUF (below)
>  0x1f1	char		size of setup.S, number of sectors
>  0x1f2	unsigned short	MOUNT_ROOT_RDONLY (if !=0)
>  0x1f4	unsigned short	size of compressed kernel-part in the
> @@ -66,6 +67,7 @@
>  0x220	4 bytes		(setup.S)
>  0x224	unsigned short	setup.S heap end pointer
>  0x2d0 - 0x600		E820MAP
> +0x600 - 0x7D4		EDDBUF (setup.S)
>  
>  0x800	string, 2K max	COMMAND_LINE, the kernel commandline as
>  			copied using CL_OFFSET.
> diff -Nru a/arch/i386/Config.help b/arch/i386/Config.help
> --- a/arch/i386/Config.help	Tue Sep  3 15:06:13 2002
> +++ b/arch/i386/Config.help	Tue Sep  3 15:06:13 2002
> @@ -967,3 +967,13 @@
>    absence of features.
>  
>    For more information take a look at Documentation/swsusp.txt.
> +
> +CONFIG_EDD
> +  Say Y or M here if you want to enable BIOS Enhanced Disk Device
> +  Services real mode BIOS calls to determine which disk
> +  BIOS tries boot from.  This feature creates a /proc/edd directory
> +  and files for each BIOS device detected.
> +
> +  This option is experimental, and most disk controller BIOS
> +  vendors do not yet implement this feature.
> +
> diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
> --- a/arch/i386/boot/setup.S	Tue Sep  3 15:06:13 2002
> +++ b/arch/i386/boot/setup.S	Tue Sep  3 15:06:13 2002
> @@ -44,6 +44,8 @@
>   *
>   * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
>   * by Robert Schwebel, December 2001 <robert@schwebel.de>
> + *    
> + * BIOS EDD support September 2002 by Matt Domsch <Matt_Domsch@dell.com>
>   *
>   */
>  
> @@ -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 <Matt_Domsch@dell.com>
> + *
> + * 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 <Matt_Domsch@Dell.com>");
> +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 <Matt_Domsch@dell.com>
> + *  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
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
> @-D[;%`BLS5^S-[^O,`="LX-F*QA8`^,_5\L8?Q=Q````
> `
> end
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

Andre Hedrick
LAD Storage Consulting Group


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-04  1:09 ` Daniel Phillips
@ 2002-09-04  4:17   ` Greg KH
  2002-09-08  0:39     ` Patrick Mochel
  0 siblings, 1 reply; 24+ messages in thread
From: Greg KH @ 2002-09-04  4:17 UTC (permalink / raw)
  To: Daniel Phillips; +Cc: Matt_Domsch, linux-kernel, Patrick Mochel

On Wed, Sep 04, 2002 at 03:09:12AM +0200, Daniel Phillips wrote:
> On Wednesday 04 September 2002 02:54, Matt_Domsch@Dell.com 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.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-04  0:54 Matt_Domsch
@ 2002-09-04  1:09 ` Daniel Phillips
  2002-09-04  4:17   ` Greg KH
  0 siblings, 1 reply; 24+ messages in thread
From: Daniel Phillips @ 2002-09-04  1:09 UTC (permalink / raw)
  To: Matt_Domsch; +Cc: linux-kernel, Greg KH, Patrick Mochel

On Wednesday 04 September 2002 02:54, Matt_Domsch@Dell.com 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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
@ 2002-09-04  0:54 Matt_Domsch
  2002-09-04  1:09 ` Daniel Phillips
  0 siblings, 1 reply; 24+ messages in thread
From: Matt_Domsch @ 2002-09-04  0:54 UTC (permalink / raw)
  To: phillips; +Cc: linux-kernel

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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
  2002-09-03 22:05 Matt Domsch
@ 2002-09-03 23:29 ` Daniel Phillips
  2002-09-04  4:35 ` Andre Hedrick
  1 sibling, 0 replies; 24+ messages in thread
From: Daniel Phillips @ 2002-09-03 23:29 UTC (permalink / raw)
  To: Matt Domsch, linux-kernel

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

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling
@ 2002-09-03 22:05 Matt Domsch
  2002-09-03 23:29 ` Daniel Phillips
  2002-09-04  4:35 ` Andre Hedrick
  0 siblings, 2 replies; 24+ messages in thread
From: Matt Domsch @ 2002-09-03 22:05 UTC (permalink / raw)
  To: linux-kernel

x86 systems suffer from a disconnect between what BIOS believes is the
boot disk, and what Linux thinks BIOS thinks is the boot disk.  BIOS
Enhanced Disk Device Services (EDD) 3.0 provides the ability for disk
adapter BIOSs to tell the OS what it believes is the boot disk.  While
this isn't widely implemented in BIOSs yet (thus shouldn't be
completely trusted), it's time that Linux received support to be
ready as BIOSs with this feature do become available.

EDD works by providing the bus (PCI, PCI-X, ISA, InfiniBand, PCI
Express, or HyperTransport) location (e.g. PCI 02:01.0) and interface
(ATAPI, ATA, SCSI, USB, 1394, FibreChannel, I2O, RAID, SATA) location
(e.g. SCSI ID 5 LUN 0) information for each BIOS int13 device.  The
patch below creates CONFIG_EDD, that when defined, makes the calls to
retrieve and store this information.  It then exports it (yes, another
/proc, glad to change it to driverfs or whatever else when that makes
sense) in /proc/edd/{bios-device-number}, as such:

# ls /proc/edd/
80  81  82  83  84  85

# cat /proc/edd/80
host_bus_type: PCI 	02:01.0  channel: 0
interface_type: SCSI    	id: 0  lun: 0

Warning: Spec violation.  Key should be 0xBEDD, is 0xDDBE
Warning: Spec violation.  Padding should be 0x20, is 0x00

# cat /proc/edd/81
host_bus_type: PCI 	04:00.0  channel: 0
interface_type: SCSI    	id: 0  lun: 0

Warning: Spec violation.  Device Path checksum invalid (0x4b should be 0x00).

In the above case, BIOS int13 device 80 (the boot disk) believes it is
on PCI 02:01.0, SCSI bus 0, ID 0 LUN 0 (in this case it's an Adaptec
39160 add-in card).  Likewise, device 81 believes it's at PCI 04:00.0,
channel 0, ID 0, LUN 0 (a Dell PERC3/QC card).  In both cases the BIOS
vendors have some cleanup work to do, so I warn when they don't adhere
to the spec.

It's possible to query device drivers from user-space (either via a
SCSI ioctl, or IDE /proc/ide/*/config), to compare results to
determine which disk is the boot disk.

At most 6 BIOS devices are reported, as that fills the space that's
left in the empty_zero_page.  In general you only care about device
80h, though for software RAID1 knowing what 81h is might be useful also.

The major changes implemented in this patch:
arch/i386/boot/setup.S - int13 real mode calls store results in empty_zero_page
arch/i386/kernel/setup.c - copy results from empty_zero_page to local
storage
arch/i386/kernel/edd.c - export results via /proc/edd/

If you use this, please send reports of success/failure, and the
adapter types and BIOS versions, to edd30@domsch.com.  I'm keeping a
tally at http://domsch.com/linux/edd30/results.html.  If built as
CONFIG_EDD=m, please 'modprobe edd debug=1' and send those results -
it's more verbose.

Patch below applies to BK-current 2.5.x.  Also available in BitKeeper
at http://mdomsch.bkbits.net/linux-2.5-edd

Feedback appreciated.


Thanks,
Matt

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

You can import this changeset into BK by piping this whole message to
'| bk receive [path to repository]' or apply the patch as usual.

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


ChangeSet@1.582, 2002-09-03 15:05:38-05:00, Matt_Domsch@dell.com
  Initial release of x86 BIOS Enhanced Disk Device (EDD) polling


 Documentation/i386/zero-page.txt |    2 
 arch/i386/Config.help            |   10 
 arch/i386/boot/setup.S           |   46 +++
 arch/i386/config.in              |    4 
 arch/i386/defconfig              |    1 
 arch/i386/kernel/Makefile        |    1 
 arch/i386/kernel/edd.c           |  455 +++++++++++++++++++++++++++++++++++++++
 arch/i386/kernel/i386_ksyms.c    |    6 
 arch/i386/kernel/setup.c         |   23 +
 include/asm-i386/edd.h           |  162 +++++++++++++
 10 files changed, 710 insertions


diff -Nru a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt
--- a/Documentation/i386/zero-page.txt	Tue Sep  3 15:06:13 2002
+++ b/Documentation/i386/zero-page.txt	Tue Sep  3 15:06:13 2002
@@ -31,6 +31,7 @@
 
 0x1e0	unsigned long	ALT_MEM_K, alternative mem check, in Kb
 0x1e8	char		number of entries in E820MAP (below)
+0x1e9	unsigned char	number of entries in EDDBUF (below)
 0x1f1	char		size of setup.S, number of sectors
 0x1f2	unsigned short	MOUNT_ROOT_RDONLY (if !=0)
 0x1f4	unsigned short	size of compressed kernel-part in the
@@ -66,6 +67,7 @@
 0x220	4 bytes		(setup.S)
 0x224	unsigned short	setup.S heap end pointer
 0x2d0 - 0x600		E820MAP
+0x600 - 0x7D4		EDDBUF (setup.S)
 
 0x800	string, 2K max	COMMAND_LINE, the kernel commandline as
 			copied using CL_OFFSET.
diff -Nru a/arch/i386/Config.help b/arch/i386/Config.help
--- a/arch/i386/Config.help	Tue Sep  3 15:06:13 2002
+++ b/arch/i386/Config.help	Tue Sep  3 15:06:13 2002
@@ -967,3 +967,13 @@
   absence of features.
 
   For more information take a look at Documentation/swsusp.txt.
+
+CONFIG_EDD
+  Say Y or M here if you want to enable BIOS Enhanced Disk Device
+  Services real mode BIOS calls to determine which disk
+  BIOS tries boot from.  This feature creates a /proc/edd directory
+  and files for each BIOS device detected.
+
+  This option is experimental, and most disk controller BIOS
+  vendors do not yet implement this feature.
+
diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
--- a/arch/i386/boot/setup.S	Tue Sep  3 15:06:13 2002
+++ b/arch/i386/boot/setup.S	Tue Sep  3 15:06:13 2002
@@ -44,6 +44,8 @@
  *
  * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
  * by Robert Schwebel, December 2001 <robert@schwebel.de>
+ *    
+ * BIOS EDD support September 2002 by Matt Domsch <Matt_Domsch@dell.com>
  *
  */
 
@@ -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 <Matt_Domsch@dell.com>
+ *
+ * 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 <Matt_Domsch@Dell.com>");
+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 <Matt_Domsch@dell.com>
+ *  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
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
@-D[;%`BLS5^S-[^O,`="LX-F*QA8`^,_5\L8?Q=Q````
`
end


^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2002-10-01  3:32 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-11 19:09 [RFC][PATCH] x86 BIOS Enhanced Disk Device (EDD) polling Matt_Domsch
2002-09-12 18:00 ` Patrick Mochel
2002-09-12 18:48   ` Matt Domsch
  -- strict thread matches above, loose matches on Subject: below --
2002-10-01  3:37 Matt_Domsch
2002-09-30  4:32 Matt_Domsch
     [not found] <20BF5713E14D5B48AA289F72BD372D6821CE34@AUSXMPC122.aus.amer.dell.com>
2002-09-27 21:30 ` Matt Domsch
2002-09-27 22:33   ` Greg KH
2002-09-29 16:11   ` Dave Jones
2002-09-29 16:18     ` Zwane Mwaikambo
2002-09-29 16:44     ` Alan Cox
2002-09-29 18:20     ` Kai Germaschewski
2002-09-29 18:27       ` Russell King
2002-09-29 18:52         ` Dave Jones
2002-10-01  1:55   ` Patrick Mochel
2002-09-10 22:43 Matt_Domsch
2002-09-09  1:17 Matt_Domsch
2002-09-04  0:54 Matt_Domsch
2002-09-04  1:09 ` Daniel Phillips
2002-09-04  4:17   ` Greg KH
2002-09-08  0:39     ` Patrick Mochel
2002-09-03 22:05 Matt Domsch
2002-09-03 23:29 ` Daniel Phillips
2002-09-04  4:35 ` Andre Hedrick
2002-09-04 16:02   ` Matt Domsch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).