>>>>> "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.
<[EMAIL PROTECTED]>                     Network Engineering Div.
--- 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)

#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);
}

Reply via email to