Cleanup of intelfb code
PATCH 1/1 Cleanup of intelfb code
- fix problems in the __iomem annotation
- remove builtinmodes.c
- remove INTEL_*_PARAM and use module_param instead
- remove intelfb_find_mode() and associated functions and use generic fb_find_mode() instead
- trivial documentation fix
---
b/drivers/video/intelfb/intelfb.h | 33 --- b/drivers/video/intelfb/intelfbdrv.c | 306 +++++++++++------------------------ b/drivers/video/intelfb/intelfbdrv.h | 14 - b/drivers/video/intelfb/intelfbhw.c | 12 - drivers/video/intelfb/builtinmodes.c | 222 ------------------------- 5 files changed, 113 insertions(+), 474 deletions(-)
drivers/video/intelfb/builtinmodes.c deleted +0 -222
@@ -1,222 +0,0 @@ - -/* -* THIS FILE IS AUTOMATICALLY GENERATED BY fbmode.pl -- DO NOT EDIT -*/ - -static struct fb_videomode modedb[] = { - { -/* 640x350 @ 85 Hz, 37.9 kHz hsync */ -"640x350@85" ,85 ,640 ,350 ,31746 ,96 ,32 ,60 ,32 ,64 ,3 , -FB_SYNC_HOR_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 640x400 @ 85 Hz, 37.9 kHz hsync */ -"640x400@85" ,85 ,640 ,400 ,31746 ,96 ,32 ,41 ,1 ,64 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 720x400 @ 85 Hz, 37.9 kHz hsync */ -"720x400@85" ,85 ,720 ,400 ,28169 ,108 ,36 ,42 ,1 ,72 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 640x480 @ 60 Hz, 31.5 kHz hsync */ -"640x480@60" ,60 ,640 ,480 ,39683 ,48 ,16 ,33 ,10 ,96 ,2 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 640x480 @ 73 Hz, 37.9 kHz hsync */ -"640x480@73" ,73 ,640 ,480 ,31746 ,128 ,24 ,29 ,9 ,40 ,2 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 640x480 @ 75 Hz, 37.5 kHz hsync */ -"640x480@75" ,75 ,640 ,480 ,31746 ,120 ,16 ,16 ,1 ,64 ,3 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 640x480 @ 85 Hz, 43.3 kHz hsync */ -"640x480@85" ,85 ,640 ,480 ,27778 ,80 ,56 ,25 ,1 ,56 ,3 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 800x600 @ 56 Hz, 35.2 kHz hsync */ -"800x600@56" ,56 ,800 ,600 ,27778 ,128 ,24 ,22 ,1 ,72 ,2 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 800x600 @ 60 Hz, 37.9 kHz hsync */ -"800x600@60" ,60 ,800 ,600 ,25000 ,88 ,40 ,23 ,1 ,128 ,4 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 800x600 @ 72 Hz, 48.1 kHz hsync */ -"800x600@72" ,72 ,800 ,600 ,20000 ,64 ,56 ,23 ,37 ,120 ,6 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 800x600 @ 75 Hz, 46.9 kHz hsync */ -"800x600@75" ,75 ,800 ,600 ,20202 ,160 ,16 ,21 ,1 ,80 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 800x600 @ 85 Hz, 53.7 kHz hsync */ -"800x600@85" ,85 ,800 ,600 ,17762 ,152 ,32 ,27 ,1 ,64 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1024x768 @ 60 Hz, 48.4 kHz hsync */ -"1024x768@60" ,60 ,1024 ,768 ,15385 ,160 ,24 ,29 ,3 ,136 ,6 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 1024x768 @ 70 Hz, 56.5 kHz hsync */ -"1024x768@70" ,70 ,1024 ,768 ,13333 ,144 ,24 ,29 ,3 ,136 ,6 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 1024x768 @ 75 Hz, 60.1 kHz hsync */ -"1024x768@75" ,75 ,1024 ,768 ,12690 ,176 ,16 ,28 ,1 ,96 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1024x768 @ 85 Hz, 68.7 kHz hsync */ -"1024x768@85" ,85 ,1024 ,768 ,10582 ,208 ,48 ,36 ,1 ,96 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1152x864 @ 75 Hz, 67.5 kHz hsync */ -"1152x864@75" ,75 ,1152 ,864 ,9259 ,256 ,64 ,32 ,1 ,128 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1280x960 @ 60 Hz, 60.0 kHz hsync */ -"1280x960@60" ,60 ,1280 ,960 ,9259 ,312 ,96 ,36 ,1 ,112 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1280x960 @ 85 Hz, 85.9 kHz hsync */ -"1280x960@85" ,85 ,1280 ,960 ,6734 ,224 ,64 ,47 ,1 ,160 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1280x1024 @ 60 Hz, 64.0 kHz hsync */ -"1280x1024@60" ,60 ,1280 ,1024 ,9259 ,248 ,48 ,38 ,1 ,112 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1280x1024 @ 75 Hz, 80.0 kHz hsync */ -"1280x1024@75" ,75 ,1280 ,1024 ,7407 ,248 ,16 ,38 ,1 ,144 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1280x1024 @ 85 Hz, 91.1 kHz hsync */ -"1280x1024@85" ,85 ,1280 ,1024 ,6349 ,224 ,64 ,44 ,1 ,160 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1600x1200 @ 60 Hz, 75.0 kHz hsync */ -"1600x1200@60" ,60 ,1600 ,1200 ,6173 ,304 ,64 ,46 ,1 ,192 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1600x1200 @ 65 Hz, 81.2 kHz hsync */ -"1600x1200@65" ,65 ,1600 ,1200 ,5698 ,304 ,64 ,46 ,1 ,192 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1600x1200 @ 70 Hz, 87.5 kHz hsync */ -"1600x1200@70" ,70 ,1600 ,1200 ,5291 ,304 ,64 ,46 ,1 ,192 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1600x1200 @ 75 Hz, 93.8 kHz hsync */ -"1600x1200@75" ,75 ,1600 ,1200 ,4938 ,304 ,64 ,46 ,1 ,192 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1600x1200 @ 85 Hz, 106.2 kHz hsync */ -"1600x1200@85" ,85 ,1600 ,1200 ,4357 ,304 ,64 ,46 ,1 ,192 ,3 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1792x1344 @ 60 Hz, 83.7 kHz hsync */ -"1792x1344@60" ,60 ,1792 ,1344 ,4883 ,328 ,128 ,46 ,1 ,200 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1792x1344 @ 75 Hz, 106.3 kHz hsync */ -"1792x1344@75" ,75 ,1792 ,1344 ,3831 ,352 ,96 ,69 ,1 ,216 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1856x1392 @ 60 Hz, 86.4 kHz hsync */ -"1856x1392@60" ,60 ,1856 ,1392 ,4581 ,352 ,96 ,43 ,1 ,224 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1856x1392 @ 75 Hz, 112.5 kHz hsync */ -"1856x1392@75" ,75 ,1856 ,1392 ,3472 ,352 ,128 ,104 ,1 ,224 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1920x1440 @ 60 Hz, 90.0 kHz hsync */ -"1920x1440@60" ,60 ,1920 ,1440 ,4274 ,344 ,128 ,56 ,1 ,208 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1920x1440 @ 75 Hz, 112.5 kHz hsync */ -"1920x1440@75" ,75 ,1920 ,1440 ,3367 ,352 ,144 ,56 ,1 ,224 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 832x624 @ 75 Hz, 49.7 kHz hsync */ -"832x624@75" ,75 ,832 ,624 ,17457 ,224 ,32 ,39 ,1 ,64 ,3 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 1152x768 @ 55 Hz, 44.2 kHz hsync */ -"1152x768@55" ,55 ,1152 ,768 ,15386 ,158 ,26 ,29 ,3 ,136 ,6 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1400x1050 @ 60 Hz, 64.9 kHz hsync */ -"1400x1050@60" ,60 ,1400 ,1050 ,8197 ,240 ,88 ,18 ,2 ,152 ,12 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1400x1050 @ 75 Hz, 81.5 kHz hsync */ -"1400x1050@75" ,75 ,1400 ,1050 ,6418 ,128 ,64 ,26 ,2 ,320 ,12 , -FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 1600x1024 @ 60 Hz, 64.0 kHz hsync */ -"1600x1024@60" ,60 ,1600 ,1024 ,9354 ,30 ,20 ,37 ,3 ,20 ,3 , -0 ,FB_VMODE_NONINTERLACED - }, - { -/* 1920x1440 @ 85 Hz, 128.5 kHz hsync */ -"1920x1440@85" ,85 ,1920 ,1440 ,2930 ,368 ,152 ,68 ,1 ,216 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 2048x1536 @ 60 Hz, 95.3 kHz hsync */ -"2048x1536@60" ,60 ,2048 ,1536 ,3746 ,376 ,152 ,49 ,1 ,224 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 2048x1536 @ 75 Hz, 120.2 kHz hsync */ -"2048x1536@75" ,75 ,2048 ,1536 ,2937 ,392 ,168 ,63 ,1 ,224 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - }, - { -/* 2048x1536 @ 85 Hz, 137.0 kHz hsync */ -"2048x1536@85" ,85 ,2048 ,1536 ,2577 ,392 ,168 ,72 ,1 ,224 ,3 , -FB_SYNC_VERT_HIGH_ACT ,FB_VMODE_NONINTERLACED - } -}; - -static int num_modes =sizeof (modedb) /sizeof (modedb[0 ]); - -#define DFLT_MODE 3 -
drivers/video/intelfb/intelfb.h +7 -26
@@ -8,7 +8,7 @@/*** Version/name ***/ -#define INTELFB_VERSION "0.9.0" +#define INTELFB_VERSION "0.9.1"#define INTELFB_MODULE_NAME "intelfb"#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G"
@@ -35,14 +35,6 @@#define ALLOCATE_FOR_PANNING 1#endif -#ifndef BAILOUT_EARLY -#define BAILOUT_EARLY 0 -#endif - -#ifndef TEST_MODE_TO_HW -#define TEST_MODE_TO_HW 0 -#endif -#ifndef PREFERRED_MODE #define PREFERRED_MODE "1024x768-16@60"#endif
@@ -94,21 +86,10 @@/* get commonly used pointers */ #define GET_DINFO (info) (info)->par -/* module parameters */ -#define INTELFB_INT_PARAM (name, default, desc) \ - static int name = default; \ - module_param(name, int, default); \ - MODULE_PARM_DESC(name, desc); - -#define INTELFB_STR_PARAM (name, default, desc) \ - static char *name = (char *) default; \ - module_param(name, charp, default); \ - MODULE_PARM_DESC(name, desc); -/* misc macros */ -#define TEXT_ACCEL (d, v) \ - ((d)->accel && (d)->ring_active && \ - ((v)->accel_flags & FB_ACCELF_TEXT)) +#define ACCEL (d, i) \ + ((d)->accel && !(d)->ring_lockup && \ + ((i)->var.accel_flags & FB_ACCELF_TEXT))/*#define NOACCEL_CHIPSET(d) \ ((d)->chipset != INTEL_865G)*/
@@ -205,7 +186,7 @@struct intelfb_heap_data {u32 physical; -u32 __iomem *virtual; +u8 __iomem *virtual;u32 offset;// in GATT pages u32 size;// in bytes };
@@ -234,13 +215,13 @@/* mmio regs */ u32 mmio_base_phys; -u32 __iomem *mmio_base; +u8 __iomem *mmio_base;/* fb start offset (in bytes) */ u32 fb_start;/* ring buffer */ -u32 __iomem *ring_head; +u8 __iomem *ring_head;u32 ring_tail;u32 ring_tail_mask;u32 ring_space;
drivers/video/intelfb/intelfbdrv.c +92 -204
432 lines not on this page · raw message
@@ -1432,7 +1320,7 @@
DBG_MSG("intelfb_fillrect\n");
#endif
- if (!dinfo->accel || dinfo->ring_lockup || dinfo->depth == 4)
+ if (!ACCEL(dinfo, info) || dinfo->depth == 4)
return cfb_fillrect(info, rect);
if (rect->rop == ROP_COPY)
@@ -1460,7 +1348,7 @@
DBG_MSG("intelfb_copyarea\n");
#endif
- if (!dinfo->accel || dinfo->ring_lockup || dinfo->depth == 4)
+ if (!ACCEL(dinfo, info) || dinfo->depth == 4)
return cfb_copyarea(info, region);
intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
@@ -1478,7 +1366,7 @@
DBG_MSG("intelfb_imageblit\n");
#endif
- if (!dinfo->accel || dinfo->ring_lockup || dinfo->depth == 4
+ if (!ACCEL(dinfo, info) || dinfo->depth == 4
|| image->depth != 1)
return cfb_imageblit(info, image);
@@ -1512,7 +1400,7 @@
intelfbhw_cursor_hide(dinfo);
/* If XFree killed the cursor - restore it */
- if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.physical) {
+ if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.offset << 12) {
u32 fg, bg;
DBG_MSG("the cursor was killed - restore it !!\n");
@@ -1572,7 +1460,7 @@
intelfbhw_cursor_setcolor(dinfo, bg, fg);
}
- if (cursor->set & (FB_CUR_SETSHAPE & FB_CUR_SETIMAGE)) {
+ if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8); u32 size = s_pitch * cursor->image.height; u8 *dat = (u8 *) cursor->image.data;
drivers/video/intelfb/intelfbdrv.h +3 -11
@@ -29,19 +29,11 @@*/ int __init intelfb_setup (char *options); -static void get_initial_mode (struct intelfb_info *dinfo); +static void __devinit get_initial_mode (struct intelfb_info *dinfo);static void update_dinfo (struct intelfb_info *dinfo,struct fb_var_screeninfo *var);static int intelfb_get_fix (struct fb_fix_screeninfo *fix,struct fb_info *info); -static void mode_to_var (const struct fb_videomode *mode, -struct fb_var_screeninfo *var,u32 bpp); -static int -intelfb_find_mode (struct fb_var_screeninfo *var, -struct fb_info *info,const char *mode_option, -const struct fb_videomode *db,unsigned int dbsize, -const struct fb_videomode *default_mode, -unsigned int default_bpp);static int intelfb_check_var (struct fb_var_screeninfo *var,struct fb_info *info);
@@ -69,8 +61,8 @@ unsigned int cmd, unsigned long arg, struct fb_info *info); -static int intelfb_pci_register (struct pci_dev *pdev, -const struct pci_device_id *ent); +static int __devinit intelfb_pci_register (struct pci_dev *pdev, +const struct pci_device_id *ent); static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);static int __devinit intelfb_set_fbinfo (struct intelfb_info *dinfo);
drivers/video/intelfb/intelfbhw.c +6 -6
@@ -290,7 +290,7 @@if ((xoffset + var->xres > var->xres_virtual) || (yoffset + var->yres > var->yres_virtual)) -return EINVAL ; +return -EINVAL ; offset = (yoffset * dinfo->pitch) + (xoffset * var->bits_per_pixel) /8 ;
@@ -1240,8 +1240,8 @@ end = jiffies + (HZ *3 );while (dinfo->ring_space < n) { - dinfo->ring_head = (u32 __iomem *)(INREG (PRI_RING_HEAD ) & -RING_HEAD_MASK ); + dinfo->ring_head = (u8 __iomem *)(INREG (PRI_RING_HEAD ) & +RING_HEAD_MASK );if (dinfo->ring_tail +RING_MIN_FREE < (u32 __iomem ) dinfo->ring_head) dinfo->ring_space = (u32 __iomem ) dinfo->ring_head
@@ -1312,8 +1312,8 @@DBG_MSG ("refresh_ring\n" );#endif - dinfo->ring_head = (u32 __iomem *) (INREG (PRI_RING_HEAD ) & -RING_HEAD_MASK ); + dinfo->ring_head = (u8 __iomem *) (INREG (PRI_RING_HEAD ) & +RING_HEAD_MASK ); dinfo->ring_tail =INREG (PRI_RING_TAIL ) &RING_TAIL_MASK ;if (dinfo->ring_tail +RING_MIN_FREE < (u32 __iomem )dinfo->ring_head) dinfo->ring_space = (u32 __iomem ) dinfo->ring_head
@@ -1605,7 +1605,7 @@ CURSOR_ENABLE | CURSOR_STRIDE_MASK); tmp =CURSOR_FORMAT_3C ;OUTREG (CURSOR_CONTROL , tmp); -OUTREG (CURSOR_A_BASEADDR , dinfo->cursor.physical); +OUTREG (CURSOR_A_BASEADDR , dinfo->cursor.offset <<12 ); tmp = (64 <<CURSOR_SIZE_H_SHIFT ) | (64 <<CURSOR_SIZE_V_SHIFT );OUTREG (CURSOR_SIZE , tmp);
-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
Review
Quoted 11 lines · Antonino A. Daplas
(quoted diff) +1
-0+ if (ACCEL(dinfo, info)) { + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | + FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_IMAGEBLIT; + } else { + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + }5 files changed, 113 insertions(+), 474 deletions(-) return 0; }
erk, what happened there?
I have Sylvain's priginal patch - is this in any way different?
-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
Quoted 9 lines · Andrew Morton
Quoted 8 lines · Antonino A. Daplas
(quoted diff) +1
-0+ if (ACCEL(dinfo, info)) { + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | + FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_IMAGEBLIT; + } else { + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + }5 files changed, 113 insertions(+), 474 deletions(-)
Quoted 5 lines
Quoted 2 lines
return 0; }erk, what happened there?
Wrong cursor position, sorry.
Quoted 1 line
I have Sylvain's priginal patch - is this in any way different?
Not much, Sylvain's original patch should be okay. I just added a more comprehensive changelog.
Tony
-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click