Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 31 Jan 2000 18:08:52 +0900
From:      YAMAMOTO Shigeru <shigeru@iij.ad.jp>
To:        imp@village.org
Cc:        dfr@nlsystems.com, freebsd-hackers@FreeBSD.ORG
Subject:   Re: how to allocate an alined address for a device? 
Message-ID:  <20000131180852D.shigeru@iij.ad.jp>
In-Reply-To: Your message of "Sat, 29 Jan 2000 11:06:15 -0700" <200001291806.LAA07899@harmony.village.org>
References:  <200001291806.LAA07899@harmony.village.org>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Mon_Jan_31_18:08:06_2000_827)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit


>>>>> "Warner" == Warner Losh <Warner> writes:
: +u_int32_t
: +rman_make_alignment_flags(int size) {
: +	int	i;
: +
: +	for (i = 0; i < 32 && size > 0x01; i ++) {
: +		size = (size >> 1);
: +	}
: +
: +	if (i > 31) {
: +		i = 0;
: +	}
: +
: +	return(RF_ALIGNMENT_LOG2(i));
:  }

I found my mistake in my patch.
Following is right.

 u_int32_t
rman_make_alignment_flags(int size) {
	int	i;
+	int	count;

-	for (i = 0; i < 32 && size > 0x01; i ++) {
+	for (i = 0, count = 0; i < 32 && size > 0x01; i ++) {
+		if (size & 0x01) {
+			count ++;
+		}
		size = (size >> 1);
	}
+
+	if (count > 0) {
+		i ++;
+	}

	if (i > 31) {
		i = 0;
	}

	return(RF_ALIGNMENT_LOG2(i));
}



Warner> This could more simply be stated as RF_ALIGNMENT_LOG2(ffs(size)).  I
Warner> don't think that it is really needed.

Maybe, 'RF_ALIGNMENT_LOG2(ffs(size) - 1)'.

It is very simple.
But can we have an assumption that we never pass non 2^n to ffs(3)?
I read 'man ffs(3)' and '@src/sys/libkern/ffs.c'.
ffs(3), it seems me finding a first set bit from LSB.
If we pass a non 2^n value to ffs(3), we have a wrong result.

ex.
ffs(4) = 3
	--> 4 = 2^2
              = (1 << 2)
              = (1 << (ffs(4) - 1))
ffs(6) = 2, ffs(8) = 4
	--> 6 < 8 = 2^3
                  = (1 << 3)
                  = (1 << (ffs(8) - 1))
                  = (1 << (ffs(6) + 1))
                 != (1 << (ffs(6) - 1))
                  = (1 << (2 - 1)) = 2
ffs(63) = 1, ffs(64) = 7
        --> 63 < 64 = 2^6
                    = (1 << 6)
                    = (1 << (ffs(64) - 1))
                    = (1 << (ffs(63) + 5))
                   != (1 << (ffs(63) - 1))
                    = (1 << (1 - 1)) = 1

Warner> : +#define RF_ALIGNMENT_LOG2(x) ((x) << RF_ALIGNMENT_SHIFT)
Warner> You might want to add:
Warner> #define RF_ALIGNMENT(x) (((x) & RF_ALIGNMENT_MASK) >> RF_ALIGNMENT_SHIFT)

I add it.

I send my new patch and ffs(3) test program.
Thanks,

-------
YAMAMOTO Shigeru			Internet Initiative Japan Inc.
<shigeru@iij.ad.jp>			Network Engineering Div.

----Next_Part(Mon_Jan_31_18:08:06_2000_827)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=align3.diff

--- kern/subr_rman.c.org	Tue Nov 16 08:28:57 1999
+++ kern/subr_rman.c	Sun Jan 30 23:55:28 2000
@@ -227,7 +227,19 @@
 			continue;
 		}
 		rstart = max(s->r_start, start);
-		rend = min(s->r_end, max(start + count, end));
+		if (flags & RF_ALIGNMENT_MASK) {
+		/* need to align an address */
+			u_long	aligned_rstart;
+			u_long	alignment_size;
+
+			alignment_size = (1u << RF_ALIGNMENT(flags));
+			aligned_rstart = (rstart & (~alignment_size + 1u));
+			if ((rstart & (~(~alignment_size + 1u))) != 0) {
+				aligned_rstart += alignment_size;
+			}
+			rstart = aligned_rstart;
+		}
+		rend = min(s->r_end, max(max(start + count, end), rstart + count));
 #ifdef RMAN_DEBUG
 		printf("truncated region: [%#lx, %#lx]; size %#lx (requested %#lx)\n",
 		       rstart, rend, (rend - rstart + 1), count);
@@ -608,4 +620,27 @@
 	rv = int_rman_release_resource(rm, r);
 	simple_unlock(rm->rm_slock);
 	return (rv);
+}
+
+u_int32_t
+rman_make_alignment_flags(int size) {
+	int	i;
+	int	count;
+
+	for (i = 0, count = 0; i < 32 && size > 0x01; i ++) {
+		if (size & 0x01) {
+			count ++;
+		}
+		size = (size >> 1);
+	}
+
+	if (count > 0) {
+		i ++;
+	}
+
+	if (i > 31) {
+		i = 0;
+	}
+
+	return(RF_ALIGNMENT_LOG2(i));
 }
--- sys/rman.h.org	Mon Jan 10 08:48:52 2000
+++ sys/rman.h	Sun Jan 30 22:43:19 2000
@@ -64,7 +64,12 @@
 #define	RF_WANTED	0x0010	/* somebody is waiting for this resource */
 #define	RF_FIRSTSHARE	0x0020	/* first in sharing list */
 
-#define RF_PCCARD_ATTR	0x10000 /* PCCARD attribute memory */
+#define	RF_PCCARD_ATTR	0x10000	/* PCCARD attribute memory */
+
+#define	RF_ALIGNMENT_SHIFT	10	/* alignment size bit starts bit 10 */
+#define	RF_ALIGNMENT_MASK	(0x003F << RF_ALIGNMENT_SHIFT)	/* resource address alignemnt size bit mask */
+#define	RF_ALIGNMENT_LOG2(x)	((x) << RF_ALIGNMENT_SHIFT)
+#define	RF_ALIGNMENT(x)		(((x) & RF_ALIGNMENT_MASK) >> RF_ALIGNMENT_SHIFT)
 
 enum	rman_type { RMAN_UNINIT = 0, RMAN_GAUGE, RMAN_ARRAY };
 
@@ -91,6 +96,8 @@
 struct	resource *rman_reserve_resource(struct rman *rm, u_long start,
 					u_long end, u_long count,
 					u_int flags, struct device *dev);
+
+extern	u_int32_t	rman_make_alignment_flags	__P((int size));
 
 #define rman_get_start(r)	((r)->r_start)
 #define rman_get_end(r)		((r)->r_end)

----Next_Part(Mon_Jan_31_18:08:06_2000_827)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=ffs.test.c


#include	<stdio.h>
#include	<string.h>

rman_make_alignment_flags(int size) {
	int	i;
	int	count;

	for (i = 0, count = 0; i < 32 && size > 0x01; i ++) {
		if (size & 0x01) {
			count ++;
		}
		size = (size >> 1);
	}

	if (count > 0) {
		i ++;
	}

	if (i > 31) {
		i = 0;
	}

	return(i);
}

int
main() {
	int	i;
	int	max;

	max = 100;

	for (i = 0; i < max; i ++) {
		printf("%d(0x%x):\n\tffs(%d)\t\t\t\t\t= %d\n",
			i,    i,          i,   ffs(i));
		printf("\t(1 << ffs(%d))\t\t\t\t= %d\n",
					i,   (1 << ffs(i)));
		printf("\trman_make_alignment_flags(%d)\t\t= %d\n",
						i,         rman_make_alignment_flags(i));
		printf("\t(1 << rman_make_alignment_flags(%d))\t= %d\n",
								i,  (1 << rman_make_alignment_flags(i)));
	}

	return(0);
}


----Next_Part(Mon_Jan_31_18:08:06_2000_827)----


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000131180852D.shigeru>