All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: Fw: EDD enhanchement patch
       [not found] <20040706171234.4b0462e1.akpm@osdl.org>
@ 2004-07-07  4:45 ` Matt Domsch
  2004-07-07  7:41   ` Frediano Ziglio
  2004-07-07 10:05   ` Frediano Ziglio
  0 siblings, 2 replies; 4+ messages in thread
From: Matt Domsch @ 2004-07-07  4:45 UTC (permalink / raw)
  To: Frediano Ziglio
  Cc: Andrew Morton, linux-kernel, Bartlomiej Zolnierkiewicz,
	Patrick J. LoPresti

> Date: Tue, 06 Jul 2004 18:53:28 +0200
> From: Frediano Ziglio <freddyz77@tin.it>
> 
> This patch add support for DTPE data in EDD and mbr_signature. This
> patch do not solve fdisk problems but can help these programs to compute
> correct head count.

Thanks Frediano.  I don't think this is quite ready to include yet,
but I'm not philosophically opposed to it, so let's work it out.

First, I want to understand what information in the DPTE you need.  I
assume byte offset 4, bit 6 (LBA enable), and bytes 10-11 bit 3 (CHS
translation enabled) and bit 4 (LBA translation enabled), yes?  How
are you expecting tools like fdisk to use this information?

Second, your timing is unfortunate, as the patch won't apply given the
mbr_signature capture routines I submitted and were committed to BK in
the past week.  It'll have to be reworked against BK-current.

Now, for the patch:

diff -U10 -r linux-2.6.7.orig/arch/i386/boot/edd.S linux-2.6.7/arch/i386/boot/edd.S
+++ linux-2.6.7/arch/i386/boot/edd.S	2004-07-06 17:07:02.000000000 +0200
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
-# Read the first sector of device 80h and store the 4-byte signature
-	movl	$0xFFFFFFFF, %eax
-	movl	%eax, (DISK80_SIG_BUFFER)	# assume failure
-	movb	$READ_SECTORS, %ah
-	movb	$1, %al				# read 1 sector
-	movb	$0x80, %dl			# from device 80
-	movb	$0, %dh				# at head 0
-	movw	$1, %cx				# cylinder 0, sector 0
-	pushw	%es
-	pushw	%ds
-	popw	%es
-	movw	$EDDBUF, %bx
-	pushw   %dx             # work around buggy BIOSes
-	stc                     # work around buggy BIOSes
-	int     $0x13
-	sti                     # work around buggy BIOSes
-	popw    %dx
-	jc	disk_sig_done
-	movl	(EDDBUF+MBR_SIG_OFFSET), %eax
-	movl	%eax, (DISK80_SIG_BUFFER)	# store success
-disk_sig_done:
-	popw	%es

You whack obtaining the mbr_signature for the disk here, it'll come
back later...  OK.

-	movb	%dl, %ds:-8(%si)		# store device number
-	movb	%ah, %ds:-7(%si)		# store version
-	movw	%cx, %ds:-6(%si)		# store extensions
+	movb	%dl, %ds:-12(%si)		# store device number
+	movb	%ah, %ds:-11(%si)		# store version
+	movw	%cx, %ds:-10(%si)		# store extensions

Just at different offsets now, OK.

-	movw	$EDDPARMSIZE, %ds:(%si)		# put size
+	movw	$EDDPARMSIZE-16, %ds:(%si)		# put size

OK, though I dislike the magic value 16 there, would prefer a #define.


+	# copy EDD 2.0 informations
+	pushw	%ds
+	pushw	%es
+	pushw	%ds
+	popw	%es
+	pushw	%si
+	leaw	EDD2_OFFSET(%si), %di
+	ldsw	%ds:0x1a(%si), %si
+	movw	$8, %cx
+	rep
+	movsw
+	popw	%si
+	popw	%es
+	popw	%ds

This looks like it's copying 16 bytes, the whole DPTE, right?

-	movw    %ax, %ds:-4(%si)
-	movw    %ax, %ds:-2(%si)
+	movw    %ax, %ds:-8(%si)
+	movw    %ax, %ds:-6(%si)

OK.

-	movb	%al, %ds:-1(%si)                # Record max sect
-	movb    %dh, %ds:-2(%si)                # Record max head number
+	movb	%al, %ds:-5(%si)                # Record max sect
+	movb    %dh, %ds:-6(%si)                # Record max head number

OK.

-	movw    %ax, %ds:-4(%si)
+	movw    %ax, %ds:-8(%si)

OK.
 
-	movw	%si, %ax			# increment si
-	addw	$EDDPARMSIZE+EDDEXTSIZE, %ax
-	movw	%ax, %si
+
+# Read the first sector of device and store the 4-byte signature
+	movl	$0xFFFFFFFF, %eax
+	movl	%eax, %ds:-4(%si)		# assume failure
+	movb	$READ_SECTORS, %ah
+	movb	$1, %al				# read 1 sector
+	movb	$0, %dh				# at head 0
+	movw	$1, %cx				# cylinder 0, sector 0
+	pushw	%es
+	pushw	%ss
+	popw	%es
+	subw	$0x200, %sp
+	movw	%sp, %bx

Ahh, using the stack rather than empty_zero_page to read the sector
into.  That's clever.  How large is the stack though?

+	pushw	%bx
+	pushw   %dx             # work around buggy BIOSes
+	stc                     # work around buggy BIOSes
+	int     $0x13
+	sti                     # work around buggy BIOSes
+	popw    %dx
+	popw	%bx
+	jc	disk_sig_done
+	movl	MBR_SIG_OFFSET(%bx), %eax
+	movl	%eax, %ds:-4(%si)		# store success
+disk_sig_done:
+	addw	$0x200, %sp
+	popw	%es
+
+
+	addw	$EDDPARMSIZE+EDDEXTSIZE, %si	# increment si


The only problem I have with the above is that you're limited by the
space in empty_zero_page set aside for the edd info structures, which
is presently 6, though with your additions, I think should drop to 5.  My
latest in BK keeps mbr_signatures for the first 16 devices.

diff -U10 -r linux-2.6.7.orig/Documentation/i386/zero-page.txt linux-2.6.7/Documentation/i386/zero-page.txt
--- linux-2.6.7.orig/Documentation/i386/zero-page.txt	2004-06-01 11:49:45.000000000 +0200
+++ linux-2.6.7/Documentation/i386/zero-page.txt	2004-06-05 12:57:44.000000000 +0200
@@ -65,14 +65,13 @@
 0x211	char		loadflags:
 			bit0 = 1: kernel is loaded high (bzImage)
 			bit7 = 1: Heap and pointer (see below) set by boot
 				  loader.
 0x212	unsigned short	(setup.S)
 0x214	unsigned long	KERNEL_START, where the loader started the kernel
 0x218	unsigned long	INITRD_START, address of loaded ramdisk image
 0x21c	unsigned long	INITRD_SIZE, size in bytes of ramdisk image
 0x220	4 bytes		(setup.S)
 0x224	unsigned short	setup.S heap end pointer
-0x2cc	4 bytes		DISK80_SIG_BUFFER (setup.S)
+0x2cc	4 bytes		unused (old DISK80_SIG_BUFFER, setup.S)

I think we can just remove the note if it's not used anymore.

 0x2d0 - 0x600		E820MAP
-0x600 - 0x7ff		EDDBUF (setup.S) for disk signature read sector
-0x600 - 0x7eb		EDDBUF (setup.S) for edd data
+0x600 - 0x863		EDDBUF (setup.S) for edd data

I believe the empty_zero_page ends at 0x7ff.  If I'm right, then we
need to reduce the number of devices probed by one such that we don't
overflow this space.

 static ssize_t
 edd_show_raw_data(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info;
-	ssize_t len = sizeof (info->params);
+	ssize_t len = sizeof (info->params) - 16;

Again, the magic 16.  Let's fix up the structure such that its members
are rightly sized, and use those lengths.

-	if (len > (sizeof(info->params)))
-		len = sizeof(info->params);
+	if (len > (sizeof(info->params)-16))
+		len = sizeof(info->params)-16;

ditto
 
+static ssize_t
+edd_show_dpte(struct edd_device *edev, char *buf)
+{
+	struct edd_info *info;
+	if (!edev)
+		return -EINVAL;
+	info = edd_dev_get_info(edev);
+	if (!info || !buf)
+		return -EINVAL;
+
+	memcpy(buf, &info->params.port_base, 16);
+	return 16;
+}

Ok, this'll get gregkh's attention.  I was lazy with
edd_show_raw_data() returning raw data like this, and *not* using the
sysfs binary blob interface.  Rather than add another nonconformant
use, let's fix both of these to use this, and name it "raw_dpte"
instead.

+	
+	/* EDD 2.0 infos */
+	u16 port_base;
+	u16 port_command;
+	u8 drive_flags;
+	u8 proprietary_informations;
+	u8 irq;
+	u8 multi_sector_count;
+	u8 dma_control;
+	u8 programmed_io;
+	u16 drive_options;
+	u16 reserved5;
+	u8 extension_level;
+	u8 edd2_checksum;
 } __attribute__ ((packed));

The DPTE data needs to be in its own struct, not in edd_device_params
(which is only fn48 data), then tacked into the end of struct edd_info.

I'm out this week on vacation, and the next few weeks are busy with
OLS coming.  If you care to rework this against current BK, leaving
the mbr_signature list in its new place so we can keep 16 rather than
5 (I think those will be more useful than EDD in the near future given how
poor nearly all the BIOS implementations of EDD are still), then we
can review on the list again.

Thanks,
Matt

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


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

* Re: Fw: EDD enhanchement patch
  2004-07-07  4:45 ` Fw: EDD enhanchement patch Matt Domsch
@ 2004-07-07  7:41   ` Frediano Ziglio
  2004-07-07 10:05   ` Frediano Ziglio
  1 sibling, 0 replies; 4+ messages in thread
From: Frediano Ziglio @ 2004-07-07  7:41 UTC (permalink / raw)
  To: Matt Domsch
  Cc: Andrew Morton, linux-kernel, Bartlomiej Zolnierkiewicz,
	Patrick J. LoPresti

Il mer, 2004-07-07 alle 06:45, Matt Domsch ha scritto:
> > Date: Tue, 06 Jul 2004 18:53:28 +0200
> > From: Frediano Ziglio <freddyz77@tin.it>
> > 
> > This patch add support for DTPE data in EDD and mbr_signature. This
> > patch do not solve fdisk problems but can help these programs to compute
> > correct head count.
> 
> Thanks Frediano.  I don't think this is quite ready to include yet,
> but I'm not philosophically opposed to it, so let's work it out.
> 
> First, I want to understand what information in the DPTE you need.  I
> assume byte offset 4, bit 6 (LBA enable), and bytes 10-11 bit 3 (CHS
> translation enabled) and bit 4 (LBA translation enabled), yes?  How
> are you expecting tools like fdisk to use this information?
> 

My idea it's base/control port and flags. In this way you are able to
say that disk it's a slave ide. Just issue a command like

$ cat /proc/ioports | grep ide
0170-0177 : ide1
01f0-01f7 : ide0
0376-0376 : ide1
03f6-03f6 : ide0
  f000-f007 : ide0
  f008-f00f : ide1
And you know which ide controller it's connected your disk.

> Second, your timing is unfortunate, as the patch won't apply given the
> mbr_signature capture routines I submitted and were committed to BK in
> the past week.  It'll have to be reworked against BK-current.
> 

:(
I think this it's the right place to download the patch
http://www.kernel.org/pub/linux/kernel/v2.6/testing/cset/

> Now, for the patch:
> 
> diff -U10 -r linux-2.6.7.orig/arch/i386/boot/edd.S linux-2.6.7/arch/i386/boot/edd.S
> +++ linux-2.6.7/arch/i386/boot/edd.S	2004-07-06 17:07:02.000000000 +0200
>  #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
> -# Read the first sector of device 80h and store the 4-byte signature
> -	movl	$0xFFFFFFFF, %eax
> -	movl	%eax, (DISK80_SIG_BUFFER)	# assume failure
> -	movb	$READ_SECTORS, %ah
> -	movb	$1, %al				# read 1 sector
> -	movb	$0x80, %dl			# from device 80
> -	movb	$0, %dh				# at head 0
> -	movw	$1, %cx				# cylinder 0, sector 0
> -	pushw	%es
> -	pushw	%ds
> -	popw	%es
> -	movw	$EDDBUF, %bx
> -	pushw   %dx             # work around buggy BIOSes
> -	stc                     # work around buggy BIOSes
> -	int     $0x13
> -	sti                     # work around buggy BIOSes
> -	popw    %dx
> -	jc	disk_sig_done
> -	movl	(EDDBUF+MBR_SIG_OFFSET), %eax
> -	movl	%eax, (DISK80_SIG_BUFFER)	# store success
> -disk_sig_done:
> -	popw	%es
> 
> You whack obtaining the mbr_signature for the disk here, it'll come
> back later...  OK.
> 
> -	movb	%dl, %ds:-8(%si)		# store device number
> -	movb	%ah, %ds:-7(%si)		# store version
> -	movw	%cx, %ds:-6(%si)		# store extensions
> +	movb	%dl, %ds:-12(%si)		# store device number
> +	movb	%ah, %ds:-11(%si)		# store version
> +	movw	%cx, %ds:-10(%si)		# store extensions
> 
> Just at different offsets now, OK.
> 
> -	movw	$EDDPARMSIZE, %ds:(%si)		# put size
> +	movw	$EDDPARMSIZE-16, %ds:(%si)		# put size
> 
> OK, though I dislike the magic value 16 there, would prefer a #define.
> 

You are right. Perhaps it's better to define
- DPTE structure (dtpe_info)
- DPTESIZE (used in asm and C code)
- put dpte_info as a member of edd_info

> 
> +	# copy EDD 2.0 informations
> +	pushw	%ds
> +	pushw	%es
> +	pushw	%ds
> +	popw	%es
> +	pushw	%si
> +	leaw	EDD2_OFFSET(%si), %di
> +	ldsw	%ds:0x1a(%si), %si
> +	movw	$8, %cx
> +	rep
> +	movsw
> +	popw	%si
> +	popw	%es
> +	popw	%ds
> 
> This looks like it's copying 16 bytes, the whole DPTE, right?
> 

Yes.

> -	movw    %ax, %ds:-4(%si)
> -	movw    %ax, %ds:-2(%si)
> +	movw    %ax, %ds:-8(%si)
> +	movw    %ax, %ds:-6(%si)
> 
> OK.
> 
> -	movb	%al, %ds:-1(%si)                # Record max sect
> -	movb    %dh, %ds:-2(%si)                # Record max head number
> +	movb	%al, %ds:-5(%si)                # Record max sect
> +	movb    %dh, %ds:-6(%si)                # Record max head number
> 
> OK.
> 
> -	movw    %ax, %ds:-4(%si)
> +	movw    %ax, %ds:-8(%si)
> 
> OK.
>  
> -	movw	%si, %ax			# increment si
> -	addw	$EDDPARMSIZE+EDDEXTSIZE, %ax
> -	movw	%ax, %si

Here would be

addw	$EDDPARMSIZE+EDDEXTSIZE+DPTESIZE, %ax

> +
> +# Read the first sector of device and store the 4-byte signature
> +	movl	$0xFFFFFFFF, %eax
> +	movl	%eax, %ds:-4(%si)		# assume failure
> +	movb	$READ_SECTORS, %ah
> +	movb	$1, %al				# read 1 sector
> +	movb	$0, %dh				# at head 0
> +	movw	$1, %cx				# cylinder 0, sector 0
> +	pushw	%es
> +	pushw	%ss
> +	popw	%es
> +	subw	$0x200, %sp
> +	movw	%sp, %bx
> 
> Ahh, using the stack rather than empty_zero_page to read the sector
> into.  That's clever.  How large is the stack though?
> 

I don't know but usually it's some Kb.. I didn't know how large was
empty_zero_page...

> +	pushw	%bx
> +	pushw   %dx             # work around buggy BIOSes
> +	stc                     # work around buggy BIOSes
> +	int     $0x13
> +	sti                     # work around buggy BIOSes
> +	popw    %dx
> +	popw	%bx
> +	jc	disk_sig_done
> +	movl	MBR_SIG_OFFSET(%bx), %eax
> +	movl	%eax, %ds:-4(%si)		# store success
> +disk_sig_done:
> +	addw	$0x200, %sp
> +	popw	%es
> +
> +
> +	addw	$EDDPARMSIZE+EDDEXTSIZE, %si	# increment si
> 
> 
> The only problem I have with the above is that you're limited by the
> space in empty_zero_page set aside for the edd info structures, which
> is presently 6, though with your additions, I think should drop to 5.  My
> latest in BK keeps mbr_signatures for the first 16 devices.
> 
> diff -U10 -r linux-2.6.7.orig/Documentation/i386/zero-page.txt linux-2.6.7/Documentation/i386/zero-page.txt
> --- linux-2.6.7.orig/Documentation/i386/zero-page.txt	2004-06-01 11:49:45.000000000 +0200
> +++ linux-2.6.7/Documentation/i386/zero-page.txt	2004-06-05 12:57:44.000000000 +0200
> @@ -65,14 +65,13 @@
>  0x211	char		loadflags:
>  			bit0 = 1: kernel is loaded high (bzImage)
>  			bit7 = 1: Heap and pointer (see below) set by boot
>  				  loader.
>  0x212	unsigned short	(setup.S)
>  0x214	unsigned long	KERNEL_START, where the loader started the kernel
>  0x218	unsigned long	INITRD_START, address of loaded ramdisk image
>  0x21c	unsigned long	INITRD_SIZE, size in bytes of ramdisk image
>  0x220	4 bytes		(setup.S)
>  0x224	unsigned short	setup.S heap end pointer
> -0x2cc	4 bytes		DISK80_SIG_BUFFER (setup.S)
> +0x2cc	4 bytes		unused (old DISK80_SIG_BUFFER, setup.S)
> 
> I think we can just remove the note if it's not used anymore.
> 
>  0x2d0 - 0x600		E820MAP
> -0x600 - 0x7ff		EDDBUF (setup.S) for disk signature read sector
> -0x600 - 0x7eb		EDDBUF (setup.S) for edd data
> +0x600 - 0x863		EDDBUF (setup.S) for edd data
> 
> I believe the empty_zero_page ends at 0x7ff.  If I'm right, then we
> need to reduce the number of devices probed by one such that we don't
> overflow this space.
> 

:( quite short... Another way to reduce space it's to use dynamic sizes.
Must BIOS did not fill all edd_device_params but just some bytes...

>  static ssize_t
>  edd_show_raw_data(struct edd_device *edev, char *buf)
>  {
>  	struct edd_info *info;
> -	ssize_t len = sizeof (info->params);
> +	ssize_t len = sizeof (info->params) - 16;
> 
> Again, the magic 16.  Let's fix up the structure such that its members
> are rightly sized, and use those lengths.
> 
> -	if (len > (sizeof(info->params)))
> -		len = sizeof(info->params);
> +	if (len > (sizeof(info->params)-16))
> +		len = sizeof(info->params)-16;
> 
> ditto
>  
> +static ssize_t
> +edd_show_dpte(struct edd_device *edev, char *buf)
> +{
> +	struct edd_info *info;
> +	if (!edev)
> +		return -EINVAL;
> +	info = edd_dev_get_info(edev);
> +	if (!info || !buf)
> +		return -EINVAL;
> +
> +	memcpy(buf, &info->params.port_base, 16);
> +	return 16;
> +}
> 
> Ok, this'll get gregkh's attention.  I was lazy with
> edd_show_raw_data() returning raw data like this, and *not* using the
> sysfs binary blob interface.  Rather than add another nonconformant
> use, let's fix both of these to use this, and name it "raw_dpte"
> instead.
> 

Ok.

> +	
> +	/* EDD 2.0 infos */
> +	u16 port_base;
> +	u16 port_command;
> +	u8 drive_flags;
> +	u8 proprietary_informations;
> +	u8 irq;
> +	u8 multi_sector_count;
> +	u8 dma_control;
> +	u8 programmed_io;
> +	u16 drive_options;
> +	u16 reserved5;
> +	u8 extension_level;
> +	u8 edd2_checksum;
>  } __attribute__ ((packed));
> 
> The DPTE data needs to be in its own struct, not in edd_device_params
> (which is only fn48 data), then tacked into the end of struct edd_info.
> 

Ok

> I'm out this week on vacation, and the next few weeks are busy with
> OLS coming.  If you care to rework this against current BK, leaving
> the mbr_signature list in its new place so we can keep 16 rather than
> 5 (I think those will be more useful than EDD in the near future given how
> poor nearly all the BIOS implementations of EDD are still), then we
> can review on the list again.
> 
> Thanks,
> Matt

There are different level of EDD. EDD 1.0 is supported by most BIOSes.
I don't understand why using DOS my BIOS seems to return correctly DPTE
info while running Linux DPTE are not filled...

freddy77



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

* Re: EDD enhanchement patch
  2004-07-07  4:45 ` Fw: EDD enhanchement patch Matt Domsch
  2004-07-07  7:41   ` Frediano Ziglio
@ 2004-07-07 10:05   ` Frediano Ziglio
  2004-07-08 12:56     ` Matt Domsch
  1 sibling, 1 reply; 4+ messages in thread
From: Frediano Ziglio @ 2004-07-07 10:05 UTC (permalink / raw)
  To: Matt Domsch
  Cc: Andrew Morton, linux-kernel, Bartlomiej Zolnierkiewicz,
	Patrick J. LoPresti

Il mer, 2004-07-07 alle 06:45, Matt Domsch ha scritto:
> > Date: Tue, 06 Jul 2004 18:53:28 +0200
> > From: Frediano Ziglio <freddyz77@tin.it>
> > 
> > This patch add support for DTPE data in EDD and mbr_signature. This
> > patch do not solve fdisk problems but can help these programs to compute
> > correct head count.
> 
> Thanks Frediano.  I don't think this is quite ready to include yet,
> but I'm not philosophically opposed to it, so let's work it out.
> 

Here you are, inlined (with your change it's quite smaller)
Fixed a stupid bug too (I'm used to code in Intel asm, not GNU asm...)
It seems that some BIOS (like mine) fill with an invalid pointer using
USB disks, add code to test DPTE data (using checksum).

diff -U10 -r linux-2.6.7.orig/arch/i386/boot/edd.S linux-2.6.7/arch/i386/boot/edd.S
--- linux-2.6.7.orig/arch/i386/boot/edd.S	2004-07-07 08:57:35.000000000 +0200
+++ linux-2.6.7/arch/i386/boot/edd.S	2004-07-07 11:50:55.000000000 +0200
@@ -45,27 +45,28 @@
 	cmpb	$EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF)	# Out of space?
 	jb	edd_mbr_sig_read		# keep looping
 edd_mbr_sig_done:
 
 # Do the BIOS Enhanced Disk Drive calls
 # This consists of two calls:
 #    int 13h ah=41h "Check Extensions Present"
 #    int 13h ah=48h "Get Device Parameters"
 #    int 13h ah=08h "Legacy Get Device Parameters"
 #
-# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use
-# in the boot_params at EDDBUF.  The first four bytes of which are
+# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE+DPTESIZE) is reserved 
+# for our use in the boot_params at EDDBUF.  The first four bytes of which are
 # used to store the device number, interface support map and version
 # results from fn41.  The next four bytes are used to store the legacy
 # cylinders, heads, and sectors from fn08. The following 74 bytes are used to
 # store the results from fn48.  Starting from device 80h, fn41, then fn48
-# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).
+# are called and their results stored
+# in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE+DPTESIZE).
 # Then the pointer is incremented to store the data for the next call.
 # This repeats until either a device doesn't exist, or until EDDMAXNR
 # devices have been stored.
 # The one tricky part is that ds:si always points EDDEXTSIZE bytes into
 # the structure, and the fn41 and fn08 results are stored at offsets
 # from there.  This removes the need to increment the pointer for
 # every store, and leaves it ready for the fn48 call.
 # A second one-byte buffer, EDDNR, in the boot_params stores
 # the number of BIOS devices which exist, up to EDDMAXNR.
 # In setup.c, copy_edd() stores both boot_params buffers away
@@ -91,22 +92,58 @@
 	movb	%dl, %ds:-8(%si)		# store device number
 	movb	%ah, %ds:-7(%si)		# store version
 	movw	%cx, %ds:-6(%si)		# store extensions
 	incb	(EDDNR)				# note that we stored something
 
 edd_get_device_params:
 	movw	$EDDPARMSIZE, %ds:(%si)		# put size
 	movw	$0x0, %ds:2(%si)		# work around buggy BIOSes
 	movb	$GETDEVICEPARAMETERS, %ah	# Function 48
 	int	$0x13				# make the call
-						# Don't check for fail return
-						# it doesn't matter.
+	jc	edd_get_legacy_chs
+
+	cmpw	$0x1e, %ds:(%si)		# check if EDD 2.0 present
+	jb	edd_get_legacy_chs
+
+	movl	%ds:0x1a(%si), %eax		# check pointer
+	incl	%eax				# no ffff:ffff
+	jz	bad_dpte_data
+	decl	%eax				# or 0000:0000
+	jz	bad_dpte_data
+
+	# copy EDD 2.0 informations
+	pushw	%ds
+	pushw	%es
+	pushw	%ds
+	popw	%es
+	pushw	%si
+	leaw	EDDPARMSIZE(%si), %di
+	ldsw	%ds:0x1a(%si), %si
+	movw	$16, %cx
+	xorw	%ax, %ax
+	cld
+check_dpte:
+	lodsb
+	addb	%al, %ah
+	stosb
+	loop	check_dpte
+	popw	%si
+	popw	%es
+	popw	%ds
+	cmp	$0, %ah
+	je	edd_get_legacy_chs
+
+	# DPTE data invalid, bad BIOS, reset dpte_pointer
+bad_dpte_data:
+	movl	$-1, %ds:0x1a(%si)
+check_edd2_ok:
+
 edd_get_legacy_chs:
 	xorw    %ax, %ax
 	movw    %ax, %ds:-4(%si)
 	movw    %ax, %ds:-2(%si)
         # Ralf Brown's Interrupt List says to set ES:DI to
 	# 0000h:0000h "to guard against BIOS bugs"
 	pushw   %es
 	movw    %ax, %es
 	movw    %ax, %di
 	pushw   %dx                             # legacy call clobbers %dl
@@ -118,21 +155,19 @@
 	movb	%al, %ds:-1(%si)                # Record max sect
 	movb    %dh, %ds:-2(%si)                # Record max head number
 	movb    %ch, %al                        # Low 8 bits of max cyl
 	shr     $6, %cl
 	movb    %cl, %ah                        # High 2 bits of max cyl
 	movw    %ax, %ds:-4(%si)
 
 edd_legacy_done:
 	popw    %dx
 	popw    %es
-	movw	%si, %ax			# increment si
-	addw	$EDDPARMSIZE+EDDEXTSIZE, %ax
-	movw	%ax, %si
+	addw	$EDDPARMSIZE+EDDEXTSIZE+DPTESIZE, %si	# increment si
 
 edd_next:
 	incb	%dl				# increment to next device
 	cmpb	$EDDMAXNR, (EDDNR) 		# Out of space?
 	jb	edd_check_ext			# keep looping
 
 edd_done:
 #endif
diff -U10 -r linux-2.6.7.orig/Documentation/i386/zero-page.txt linux-2.6.7/Documentation/i386/zero-page.txt
--- linux-2.6.7.orig/Documentation/i386/zero-page.txt	2004-07-07 08:57:33.000000000 +0200
+++ linux-2.6.7/Documentation/i386/zero-page.txt	2004-07-07 10:57:54.000000000 +0200
@@ -69,11 +69,11 @@
 				  loader.
 0x212	unsigned short	(setup.S)
 0x214	unsigned long	KERNEL_START, where the loader started the kernel
 0x218	unsigned long	INITRD_START, address of loaded ramdisk image
 0x21c	unsigned long	INITRD_SIZE, size in bytes of ramdisk image
 0x220	4 bytes		(setup.S)
 0x224	unsigned short	setup.S heap end pointer
 0x290 - 0x2cf		EDD_MBR_SIG_BUFFER (edd.S)
 0x2d0 - 0x600		E820MAP
 0x600 - 0x7ff		EDDBUF (edd.S) for disk signature read sector
-0x600 - 0x7eb		EDDBUF (edd.S) for edd data
+0x600 - 0x7e9		EDDBUF (edd.S) for edd data
diff -U10 -r linux-2.6.7.orig/drivers/firmware/edd.c linux-2.6.7/drivers/firmware/edd.c
--- linux-2.6.7.orig/drivers/firmware/edd.c	2004-07-07 08:57:46.000000000 +0200
+++ linux-2.6.7/drivers/firmware/edd.c	2004-07-07 11:38:16.000000000 +0200
@@ -436,20 +436,34 @@
 		return -EINVAL;
 	info = edd_dev_get_info(edev);
 	if (!info || !buf)
 		return -EINVAL;
 
 	p += scnprintf(p, left, "%llu\n", info->params.number_of_sectors);
 	return (p - buf);
 }
 
 
+static ssize_t
+edd_show_raw_dpte(struct edd_device *edev, char *buf)
+{
+	struct edd_info *info;
+	if (!edev)
+		return -EINVAL;
+	info = edd_dev_get_info(edev);
+	if (!info || !buf)
+		return -EINVAL;
+
+	memcpy(buf, &info->dpte, sizeof(struct edd_dpte));
+	return sizeof(struct edd_dpte);
+}
+
 /*
  * Some device instances may not have all the above attributes,
  * or the attribute values may be meaningless (i.e. if
  * the device is < EDD 3.0, it won't have host_bus and interface
  * information), so don't bother making files for them.  Likewise
  * if the default_{cylinders,heads,sectors_per_track} values
  * are zero, the BIOS doesn't provide sane values, don't bother
  * creating files for them either.
  */
 
@@ -549,20 +563,36 @@
 			break;
 		}
 	}
 	if (!nonzero_path) {
 		return 0;
 	}
 
 	return 1;
 }
 
+static int
+edd_has_dpte(struct edd_device *edev)
+{
+	struct edd_info *info;
+	if (!edev)
+		return 0;
+	info = edd_dev_get_info(edev);
+	if (!info || info->params.length < 0x1e)
+		return 0;
+
+	if (info->params.dpte_ptr == 0xffffffffu)
+		return 0;
+
+	return 1;
+}
+
 
 static EDD_DEVICE_ATTR(raw_data, 0444, edd_show_raw_data, edd_has_edd_info);
 static EDD_DEVICE_ATTR(version, 0444, edd_show_version, edd_has_edd_info);
 static EDD_DEVICE_ATTR(extensions, 0444, edd_show_extensions, edd_has_edd_info);
 static EDD_DEVICE_ATTR(info_flags, 0444, edd_show_info_flags, edd_has_edd_info);
 static EDD_DEVICE_ATTR(sectors, 0444, edd_show_sectors, edd_has_edd_info);
 static EDD_DEVICE_ATTR(legacy_max_cylinder, 0444,
                        edd_show_legacy_max_cylinder,
 		       edd_has_legacy_max_cylinder);
 static EDD_DEVICE_ATTR(legacy_max_head, 0444, edd_show_legacy_max_head,
@@ -573,20 +603,21 @@
 static EDD_DEVICE_ATTR(default_cylinders, 0444, edd_show_default_cylinders,
 		       edd_has_default_cylinders);
 static EDD_DEVICE_ATTR(default_heads, 0444, edd_show_default_heads,
 		       edd_has_default_heads);
 static EDD_DEVICE_ATTR(default_sectors_per_track, 0444,
 		       edd_show_default_sectors_per_track,
 		       edd_has_default_sectors_per_track);
 static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30);
 static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30);
 static EDD_DEVICE_ATTR(mbr_signature, 0444, edd_show_mbr_signature, edd_has_mbr_signature);
+static EDD_DEVICE_ATTR(raw_dpte, 0444, edd_show_raw_dpte, edd_has_dpte);
 
 
 /* These are default attributes that are added for every edd
  * device discovered.  There are none.
  */
 static struct attribute * def_attrs[] = {
 	NULL,
 };
 
 /* These attributes are conditional and only added for some devices. */
@@ -598,20 +629,21 @@
 	&edd_attr_sectors,
 	&edd_attr_legacy_max_cylinder,
 	&edd_attr_legacy_max_head,
 	&edd_attr_legacy_sectors_per_track,
 	&edd_attr_default_cylinders,
 	&edd_attr_default_heads,
 	&edd_attr_default_sectors_per_track,
 	&edd_attr_interface,
 	&edd_attr_host_bus,
 	&edd_attr_mbr_signature,
+	&edd_attr_raw_dpte,
 	NULL,
 };
 
 /**
  *	edd_release - free edd structure
  *	@kobj:	kobject of edd structure
  *
  *	This is called when the refcount of the edd structure
  *	reaches 0. This should happen right after we unregister,
  *	but just in case, we use the release callback anyway.
diff -U10 -r linux-2.6.7.orig/include/linux/edd.h linux-2.6.7/include/linux/edd.h
--- linux-2.6.7.orig/include/linux/edd.h	2004-07-07 08:58:10.000000000 +0200
+++ linux-2.6.7/include/linux/edd.h	2004-07-07 10:57:54.000000000 +0200
@@ -26,23 +26,24 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  */
 #ifndef _LINUX_EDD_H
 #define _LINUX_EDD_H
 
 #define EDDNR 0x1e9		/* addr of number of edd_info structs at EDDBUF
 				   in boot_params - treat this as 1 byte  */
 #define EDDBUF	0x600		/* addr of edd_info structs in boot_params */
-#define EDDMAXNR 6		/* number of edd_info structs starting at EDDBUF  */
+#define EDDMAXNR 5		/* number of edd_info structs starting at EDDBUF  */
 #define EDDEXTSIZE 8		/* change these if you muck with the structures */
 #define EDDPARMSIZE 74
+#define DPTESIZE 16
 #define CHECKEXTENSIONSPRESENT 0x41
 #define GETDEVICEPARAMETERS 0x48
 #define LEGACYGETDEVICEPARAMETERS 0x08
 #define EDDMAGIC1 0x55AA
 #define EDDMAGIC2 0xAA55
 
 
 #define READ_SECTORS 0x02         /* int13 AH=0x02 is READ_SECTORS command */
 #define EDD_MBR_SIG_OFFSET 0x1B8  /* offset of signature in the MBR */
 #define EDD_MBR_SIG_BUF    0x290  /* addr in boot params */
@@ -58,20 +59,22 @@
 
 #define EDD_INFO_DMA_BOUNDARY_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)
 
+#define EDD2_DRIVE_IS_SLAVE                    (1 << 4)
+
 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 */
@@ -159,28 +162,44 @@
 		} __attribute__ ((packed)) sata;
 		struct {
 			u64 reserved1;
 			u64 reserved2;
 		} __attribute__ ((packed)) unknown;
 	} device_path;
 	u8 reserved4;
 	u8 checksum;
 } __attribute__ ((packed));
 
+struct edd_dpte {
+	u16 port_base;
+	u16 port_command;
+	u8 drive_flags;
+	u8 proprietary_informations;
+	u8 irq;
+	u8 multi_sector_count;
+	u8 dma_control;
+	u8 programmed_io;
+	u16 drive_options;
+	u16 reserved5;
+	u8 extension_level;
+	u8 edd2_checksum;
+} __attribute__ ((packed));
+
 struct edd_info {
 	u8 device;
 	u8 version;
 	u16 interface_support;
 	u16 legacy_max_cylinder;
 	u8 legacy_max_head;
 	u8 legacy_sectors_per_track;
 	struct edd_device_params params;
+	struct edd_dpte dpte;
 } __attribute__ ((packed));
 
 struct edd {
 	unsigned int mbr_signature[EDD_MBR_SIG_MAX];
 	struct edd_info edd_info[EDDMAXNR];
 	unsigned char mbr_signature_nr;
 	unsigned char edd_info_nr;
 };
 
 extern struct edd edd;

freddy77



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

* Re: EDD enhanchement patch
  2004-07-07 10:05   ` Frediano Ziglio
@ 2004-07-08 12:56     ` Matt Domsch
  0 siblings, 0 replies; 4+ messages in thread
From: Matt Domsch @ 2004-07-08 12:56 UTC (permalink / raw)
  To: Frediano Ziglio
  Cc: Andrew Morton, linux-kernel, Bartlomiej Zolnierkiewicz,
	Patrick J. LoPresti

On Wed, 7 Jul 2004, Frediano Ziglio wrote:

> Here you are, inlined (with your change it's quite smaller)
> Fixed a stupid bug too (I'm used to code in Intel asm, not GNU asm...)
> It seems that some BIOS (like mine) fill with an invalid pointer using
> USB disks, add code to test DPTE data (using checksum).

At a glance this looks good, but I won't be able to test it myself for a 
few weeks.  If others can do so, I encourage it.

Thanks,
Matt

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


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

end of thread, other threads:[~2004-07-08 12:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20040706171234.4b0462e1.akpm@osdl.org>
2004-07-07  4:45 ` Fw: EDD enhanchement patch Matt Domsch
2004-07-07  7:41   ` Frediano Ziglio
2004-07-07 10:05   ` Frediano Ziglio
2004-07-08 12:56     ` Matt Domsch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.