diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2005-12-13 01:17:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-13 01:31:17 -0500 |
commit | be0d9b6c7aeaad1683059c00131cabd4c894c17c (patch) | |
tree | f7e55af855531331113cbddb98688f3901d48425 /drivers/video/cfbimgblt.c | |
parent | 7275b4b6bc2f783c135c3f0eeecc4fdc6e788aa8 (diff) |
[PATCH] 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.
Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/cfbimgblt.c')
-rw-r--r-- | drivers/video/cfbimgblt.c | 36 |
1 files changed, 12 insertions, 24 deletions
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 7a01742a82af..910e2338a27e 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c | |||
@@ -76,18 +76,6 @@ static u32 cfb_tab32[] = { | |||
76 | #define FB_WRITEL fb_writel | 76 | #define FB_WRITEL fb_writel |
77 | #define FB_READL fb_readl | 77 | #define FB_READL fb_readl |
78 | 78 | ||
79 | #if defined (__BIG_ENDIAN) | ||
80 | #define LEFT_POS(bpp) (32 - bpp) | ||
81 | #define SHIFT_HIGH(val, bits) ((val) >> (bits)) | ||
82 | #define SHIFT_LOW(val, bits) ((val) << (bits)) | ||
83 | #define BIT_NR(b) (7 - (b)) | ||
84 | #else | ||
85 | #define LEFT_POS(bpp) (0) | ||
86 | #define SHIFT_HIGH(val, bits) ((val) << (bits)) | ||
87 | #define SHIFT_LOW(val, bits) ((val) >> (bits)) | ||
88 | #define BIT_NR(b) (b) | ||
89 | #endif | ||
90 | |||
91 | static inline void color_imageblit(const struct fb_image *image, | 79 | static inline void color_imageblit(const struct fb_image *image, |
92 | struct fb_info *p, u8 __iomem *dst1, | 80 | struct fb_info *p, u8 __iomem *dst1, |
93 | u32 start_index, | 81 | u32 start_index, |
@@ -109,7 +97,7 @@ static inline void color_imageblit(const struct fb_image *image, | |||
109 | val = 0; | 97 | val = 0; |
110 | 98 | ||
111 | if (start_index) { | 99 | if (start_index) { |
112 | u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); | 100 | u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, start_index)); |
113 | val = FB_READL(dst) & start_mask; | 101 | val = FB_READL(dst) & start_mask; |
114 | shift = start_index; | 102 | shift = start_index; |
115 | } | 103 | } |
@@ -119,20 +107,20 @@ static inline void color_imageblit(const struct fb_image *image, | |||
119 | color = palette[*src]; | 107 | color = palette[*src]; |
120 | else | 108 | else |
121 | color = *src; | 109 | color = *src; |
122 | color <<= LEFT_POS(bpp); | 110 | color <<= FB_LEFT_POS(bpp); |
123 | val |= SHIFT_HIGH(color, shift); | 111 | val |= FB_SHIFT_HIGH(color, shift); |
124 | if (shift >= null_bits) { | 112 | if (shift >= null_bits) { |
125 | FB_WRITEL(val, dst++); | 113 | FB_WRITEL(val, dst++); |
126 | 114 | ||
127 | val = (shift == null_bits) ? 0 : | 115 | val = (shift == null_bits) ? 0 : |
128 | SHIFT_LOW(color, 32 - shift); | 116 | FB_SHIFT_LOW(color, 32 - shift); |
129 | } | 117 | } |
130 | shift += bpp; | 118 | shift += bpp; |
131 | shift &= (32 - 1); | 119 | shift &= (32 - 1); |
132 | src++; | 120 | src++; |
133 | } | 121 | } |
134 | if (shift) { | 122 | if (shift) { |
135 | u32 end_mask = SHIFT_HIGH(~(u32)0, shift); | 123 | u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); |
136 | 124 | ||
137 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); | 125 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
138 | } | 126 | } |
@@ -162,8 +150,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
162 | u32 i, j, l; | 150 | u32 i, j, l; |
163 | 151 | ||
164 | dst2 = (u32 __iomem *) dst1; | 152 | dst2 = (u32 __iomem *) dst1; |
165 | fgcolor <<= LEFT_POS(bpp); | 153 | fgcolor <<= FB_LEFT_POS(bpp); |
166 | bgcolor <<= LEFT_POS(bpp); | 154 | bgcolor <<= FB_LEFT_POS(bpp); |
167 | 155 | ||
168 | for (i = image->height; i--; ) { | 156 | for (i = image->height; i--; ) { |
169 | shift = val = 0; | 157 | shift = val = 0; |
@@ -174,21 +162,21 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
174 | 162 | ||
175 | /* write leading bits */ | 163 | /* write leading bits */ |
176 | if (start_index) { | 164 | if (start_index) { |
177 | u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); | 165 | u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index)); |
178 | val = FB_READL(dst) & start_mask; | 166 | val = FB_READL(dst) & start_mask; |
179 | shift = start_index; | 167 | shift = start_index; |
180 | } | 168 | } |
181 | 169 | ||
182 | while (j--) { | 170 | while (j--) { |
183 | l--; | 171 | l--; |
184 | color = (*s & 1 << (BIT_NR(l))) ? fgcolor : bgcolor; | 172 | color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor; |
185 | val |= SHIFT_HIGH(color, shift); | 173 | val |= FB_SHIFT_HIGH(color, shift); |
186 | 174 | ||
187 | /* Did the bitshift spill bits to the next long? */ | 175 | /* Did the bitshift spill bits to the next long? */ |
188 | if (shift >= null_bits) { | 176 | if (shift >= null_bits) { |
189 | FB_WRITEL(val, dst++); | 177 | FB_WRITEL(val, dst++); |
190 | val = (shift == null_bits) ? 0 : | 178 | val = (shift == null_bits) ? 0 : |
191 | SHIFT_LOW(color,32 - shift); | 179 | FB_SHIFT_LOW(color,32 - shift); |
192 | } | 180 | } |
193 | shift += bpp; | 181 | shift += bpp; |
194 | shift &= (32 - 1); | 182 | shift &= (32 - 1); |
@@ -197,7 +185,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
197 | 185 | ||
198 | /* write trailing bits */ | 186 | /* write trailing bits */ |
199 | if (shift) { | 187 | if (shift) { |
200 | u32 end_mask = SHIFT_HIGH(~(u32)0, shift); | 188 | u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); |
201 | 189 | ||
202 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); | 190 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
203 | } | 191 | } |