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>