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
[-- Attachment #1 --]
>>>>> "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.
[-- Attachment #2 --]
--- 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)
[-- Attachment #3 --]
#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);
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000131180852D.shigeru>
