fbdev: Fix incorrect unaligned access in little-endian machines
PATCH 1/1 fbdev: Fix incorrect unaligned access in little-endian machines
The drawing function cfbfillrect does not work correctly when access is not unsigned-long aligned. It manifests as extra lines of pixels that are not complete drawn. Reversing the shift operator solves the problem, so I would presume that this bug would manifest only on little endian machines. The function cfbcopyarea may also have this bug.
Aligned access should present no problems.
---
This is possibly needed for 2.6.15.
drivers/video/cfbcopyarea.c | 8 ++++---- drivers/video/cfbfillrect.c | 16 ++++++++-------- drivers/video/cfbimgblt.c | 36 ++++++++++++------------------------ include/linux/fb.h | 12 ++++++++++++ 4 files changed, 36 insertions(+), 36 deletions(-)
drivers/video/cfbcopyarea.c +4 -4
@@ -64,8 +64,8 @@ bitcpy(unsigned long __iomem *dst, int dint const shift = dst_idx-src_idx;int left, right; - first = ~0UL >> dst_idx; - last = ~(~0UL >> ((dst_idx+n) % bits)); + first =FB_SHIFT_HIGH (~0UL , dst_idx); + last = ~(FB_SHIFT_HIGH (~0UL , (dst_idx+n) % bits));if (!shift) {// Same alignment for source and dest
@@ -216,8 +216,8 @@ bitcpy_rev(unsigned long __iomem *dst, i shift = dst_idx-src_idx; - first = ~0UL << (bits -1 - dst_idx); - last = ~(~0UL << (bits -1 - ((dst_idx-n) % bits))); + first =FB_SHIFT_LOW (~0UL , bits -1 - dst_idx); + last = ~(FB_SHIFT_LOW (~0UL , bits -1 - ((dst_idx-n) % bits)));if (!shift) {// Same alignment for source and dest
drivers/video/cfbfillrect.c +8 -8
@@ -110,8 +110,8 @@ bitfill_aligned(unsigned long __iomem *dif (!n)return ; - first = ~0UL >> dst_idx; - last = ~(~0UL >> ((dst_idx+n) % bits)); + first =FB_SHIFT_HIGH (~0UL , dst_idx); + last = ~(FB_SHIFT_HIGH (~0UL , (dst_idx+n) % bits));if (dst_idx+n <= bits) {// Single word
@@ -167,8 +167,8 @@ bitfill_unaligned(unsigned long __iomemif (!n)return ; - first = ~0UL >> dst_idx; - last = ~(~0UL >> ((dst_idx+n) % bits)); + first =FB_SHIFT_HIGH (~0UL , dst_idx); + last = ~(FB_SHIFT_HIGH (~0UL , (dst_idx+n) % bits));if (dst_idx+n <= bits) {// Single word
@@ -221,8 +221,8 @@ bitfill_aligned_rev(unsigned long __iomeif (!n)return ; - first = ~0UL >> dst_idx; - last = ~(~0UL >> ((dst_idx+n) % bits)); + first =FB_SHIFT_HIGH (~0UL , dst_idx); + last = ~(FB_SHIFT_HIGH (~0UL , (dst_idx+n) % bits));if (dst_idx+n <= bits) {// Single word
@@ -290,8 +290,8 @@ bitfill_unaligned_rev(unsigned long __ioif (!n)return ; - first = ~0UL >> dst_idx; - last = ~(~0UL >> ((dst_idx+n) % bits)); + first =FB_SHIFT_HIGH (~0UL , dst_idx); + last = ~(FB_SHIFT_HIGH (~0UL , (dst_idx+n) % bits));if (dst_idx+n <= bits) {// Single word
drivers/video/cfbimgblt.c +12 -24
@@ -76,18 +76,6 @@ static u32 cfb_tab32[] = {#define FB_WRITEL fb_writel#define FB_READL fb_readl -#if defined (__BIG_ENDIAN) -#define LEFT_POS (bpp) (32 - bpp) -#define SHIFT_HIGH (val, bits) ((val) >> (bits)) -#define SHIFT_LOW (val, bits) ((val) << (bits)) -#define BIT_NR (b) (7 - (b)) -#else -#define LEFT_POS (bpp) (0) -#define SHIFT_HIGH (val, bits) ((val) << (bits)) -#define SHIFT_LOW (val, bits) ((val) >> (bits)) -#define BIT_NR (b) (b) -#endif - static inline void color_imageblit(const struct fb_image *image, struct fb_info *p, u8 __iomem *dst1, u32 start_index,
@@ -109,7 +97,7 @@ static inline void color_imageblit(const val =0 ;if (start_index) { -u32 start_mask = ~(SHIFT_HIGH (~(u32 )0 , start_index)); +u32 start_mask = ~(FB_SHIFT_HIGH (~(u32 )0 , start_index)); val =FB_READL (dst) & start_mask; shift = start_index; }
@@ -119,20 +107,20 @@ static inline void color_imageblit(const color = palette[*src]; else color = *src; - color <<=LEFT_POS (bpp); - val |=SHIFT_HIGH (color, shift); + color <<=FB_LEFT_POS (bpp); + val |=FB_SHIFT_HIGH (color, shift);if (shift >= null_bits) {FB_WRITEL (val, dst++); val = (shift == null_bits) ?0 : -SHIFT_LOW (color,32 - shift); +FB_SHIFT_LOW (color,32 - shift); } shift += bpp; shift &= (32 -1 ); src++; }if (shift) { -u32 end_mask =SHIFT_HIGH (~(u32 )0 , shift); +u32 end_mask =FB_SHIFT_HIGH (~(u32 )0 , shift);FB_WRITEL ((FB_READL (dst) & end_mask) | val, dst); }
@@ -162,8 +150,8 @@ static inline void slow_imageblit(constu32 i, j, l; dst2 = (u32 __iomem *) dst1; - fgcolor <<=LEFT_POS (bpp); - bgcolor <<=LEFT_POS (bpp); + fgcolor <<=FB_LEFT_POS (bpp); + bgcolor <<=FB_LEFT_POS (bpp);for (i = image->height; i--; ) { shift = val =0 ;
@@ -174,21 +162,21 @@ static inline void slow_imageblit(const/* write leading bits */ if (start_index) { -u32 start_mask = ~(SHIFT_HIGH (~(u32 )0 , start_index)); +u32 start_mask = ~(FB_SHIFT_HIGH (~(u32 )0 ,start_index)); val =FB_READL (dst) & start_mask; shift = start_index; }while (j--) { l--; - color = (*s &1 << (BIT_NR (l))) ? fgcolor : bgcolor; - val |=SHIFT_HIGH (color, shift); + color = (*s &1 << (FB_BIT_NR (l))) ? fgcolor : bgcolor; + val |=FB_SHIFT_HIGH (color, shift);/* Did the bitshift spill bits to the next long? */ if (shift >= null_bits) {FB_WRITEL (val, dst++); val = (shift == null_bits) ?0 : -SHIFT_LOW (color,32 - shift); +FB_SHIFT_LOW (color,32 - shift); } shift += bpp; shift &= (32 -1 );
@@ -197,7 +185,7 @@ static inline void slow_imageblit(const/* write trailing bits */ if (shift) { -u32 end_mask =SHIFT_HIGH (~(u32 )0 , shift); +u32 end_mask =FB_SHIFT_HIGH (~(u32 )0 , shift);FB_WRITEL ((FB_READL (dst) & end_mask) | val, dst); }
include/linux/fb.h +12 -0
@@ -817,6 +817,18 @@ struct fb_info {#endif +#if defined (__BIG_ENDIAN) +#define FB_LEFT_POS (bpp) (32 - bpp) +#define FB_SHIFT_HIGH (val, bits) ((val) >> (bits)) +#define FB_SHIFT_LOW (val, bits) ((val) << (bits)) +#define FB_BIT_NR (b) (7 - (b)) +#else +#define FB_LEFT_POS (bpp) (0) +#define FB_SHIFT_HIGH (val, bits) ((val) << (bits)) +#define FB_SHIFT_LOW (val, bits) ((val) >> (bits)) +#define FB_BIT_NR (b) (b) +#endif +/* * `Generic' versions of the frame buffer device operations */
-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc. Get Certified Today Register for a JBoss Training Course. Free Certification Exam for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click