git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git]
/
drivers
/
video
/
imsttfb.c
diff --git
a/drivers/video/imsttfb.c
b/drivers/video/imsttfb.c
index
7bef8b7
..
f73c642
100644
(file)
--- a/
drivers/video/imsttfb.c
+++ b/
drivers/video/imsttfb.c
@@
-228,7
+228,7
@@
struct initvalues {
__u8 addr, value;
};
__u8 addr, value;
};
-static struct initvalues ibm_initregs[] __initdata = {
+static struct initvalues ibm_initregs[] __
dev
initdata = {
{ CLKCTL, 0x21 },
{ SYNCCTL, 0x00 },
{ HSYNCPOS, 0x00 },
{ CLKCTL, 0x21 },
{ SYNCCTL, 0x00 },
{ HSYNCPOS, 0x00 },
@@
-275,7
+275,7
@@
static struct initvalues ibm_initregs[] __initdata = {
{ KEYCTL, 0x00 }
};
{ KEYCTL, 0x00 }
};
-static struct initvalues tvp_initregs[] __initdata = {
+static struct initvalues tvp_initregs[] __
dev
initdata = {
{ TVPIRICC, 0x00 },
{ TVPIRBRC, 0xe4 },
{ TVPIRLAC, 0x06 },
{ TVPIRICC, 0x00 },
{ TVPIRBRC, 0xe4 },
{ TVPIRLAC, 0x06 },
@@
-319,10
+319,11
@@
struct imstt_regvals {
struct imstt_par {
struct imstt_regvals init;
struct imstt_par {
struct imstt_regvals init;
- __u32 *dc_regs;
+ __u32
__iomem
*dc_regs;
unsigned long cmap_regs_phys;
__u8 *cmap_regs;
__u32 ramdac;
unsigned long cmap_regs_phys;
__u8 *cmap_regs;
__u32 ramdac;
+ __u32 palette[16];
};
enum {
};
enum {
@@
-338,7
+339,7
@@
enum {
static int inverse = 0;
static char fontname[40] __initdata = { 0 };
#if defined(CONFIG_PPC)
static int inverse = 0;
static char fontname[40] __initdata = { 0 };
#if defined(CONFIG_PPC)
-static signed char init_vmode __
initdata = -1, init_cmode __
initdata = -1;
+static signed char init_vmode __
devinitdata = -1, init_cmode __dev
initdata = -1;
#endif
static struct imstt_regvals tvp_reg_init_2 = {
#endif
static struct imstt_regvals tvp_reg_init_2 = {
@@
-406,19
+407,19
@@
static void imsttfb_remove(struct pci_dev *pdev);
/*
* Register access
*/
/*
* Register access
*/
-static inline u32 read_reg_le32(volatile u32 *base, int regindex)
+static inline u32 read_reg_le32(volatile u32
__iomem
*base, int regindex)
{
#ifdef __powerpc__
{
#ifdef __powerpc__
- return in_le32(
(volatile u32 *) (base + regindex)
);
+ return in_le32(
base + regindex
);
#else
return readl(base + regindex);
#endif
}
#else
return readl(base + regindex);
#endif
}
-static inline void write_reg_le32(volatile u32 *base, int regindex, u32 val)
+static inline void write_reg_le32(volatile u32
__iomem
*base, int regindex, u32 val)
{
#ifdef __powerpc__
{
#ifdef __powerpc__
- out_le32(
(volatile u32 *) (base + regindex)
, val);
+ out_le32(
base + regindex
, val);
#else
writel(val, base + regindex);
#endif
#else
writel(val, base + regindex);
#endif
@@
-439,9
+440,9
@@
getclkMHz(struct imstt_par *par)
static void
setclkMHz(struct imstt_par *par, __u32 MHz)
{
static void
setclkMHz(struct imstt_par *par, __u32 MHz)
{
- __u32 clk_m, clk_n,
clk_p,
x, stage, spilled;
+ __u32 clk_m, clk_n, x, stage, spilled;
- clk_m = clk_n =
clk_p =
0;
+ clk_m = clk_n = 0;
stage = spilled = 0;
for (;;) {
switch (stage) {
stage = spilled = 0;
for (;;) {
switch (stage) {
@@
-452,7
+453,7
@@
setclkMHz(struct imstt_par *par, __u32 MHz)
clk_n++;
break;
}
clk_n++;
break;
}
- x = 20 * (clk_m + 1) / (
(clk_n + 1) * (clk_p ? 2 * clk_p : 1)
);
+ x = 20 * (clk_m + 1) / (
clk_n + 1
);
if (x == MHz)
break;
if (x > MHz) {
if (x == MHz)
break;
if (x > MHz) {
@@
-465,7
+466,7
@@
setclkMHz(struct imstt_par *par, __u32 MHz)
par->init.pclk_m = clk_m;
par->init.pclk_n = clk_n;
par->init.pclk_m = clk_m;
par->init.pclk_n = clk_n;
- par->init.pclk_p =
clk_p
;
+ par->init.pclk_p =
0
;
}
static struct imstt_regvals *
}
static struct imstt_regvals *
@@
-657,7
+658,7
@@
set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp)
static void
set_imstt_regvals (struct fb_info *info, u_int bpp)
{
static void
set_imstt_regvals (struct fb_info *info, u_int bpp)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
struct imstt_regvals *init = &par->init;
__u32 ctl, pitch, byteswap, scr;
struct imstt_regvals *init = &par->init;
__u32 ctl, pitch, byteswap, scr;
@@
-749,7
+750,7
@@
set_imstt_regvals (struct fb_info *info, u_int bpp)
static inline void
set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
{
static inline void
set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
__u32 off = var->yoffset * (info->fix.line_length >> 3)
+ ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
write_reg_le32(par->dc_regs, SSR, off);
__u32 off = var->yoffset * (info->fix.line_length >> 3)
+ ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
write_reg_le32(par->dc_regs, SSR, off);
@@
-863,7
+864,7
@@
imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int
imsttfb_set_par(struct fb_info *info)
{
static int
imsttfb_set_par(struct fb_info *info)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
return -EINVAL;
if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
return -EINVAL;
@@
-881,7
+882,7
@@
static int
imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
u_int bpp = info->var.bits_per_pixel;
if (regno > 255)
u_int bpp = info->var.bits_per_pixel;
if (regno > 255)
@@
-905,14
+906,17
@@
imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
if (regno < 16)
switch (bpp) {
case 16:
if (regno < 16)
switch (bpp) {
case 16:
- ((u16 *)info->pseudo_palette)[regno] = (regno << (info->var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno;
+ par->palette[regno] =
+ (regno << (info->var.green.length ==
+ 5 ? 10 : 11)) | (regno << 5) | regno;
break;
case 24:
break;
case 24:
- ((u32 *)info->pseudo_palette)[regno] = (regno << 16) | (regno << 8) | regno;
+ par->palette[regno] =
+ (regno << 16) | (regno << 8) | regno;
break;
case 32: {
int i = (regno << 8) | regno;
break;
case 32: {
int i = (regno << 8) | regno;
-
((u32 *)info->pseudo_palette)[regno] = (i << 16) |
i;
+
par->palette[regno] = (i << 16) |
i;
break;
}
}
break;
}
}
@@
-935,14
+939,14
@@
imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
static int
imsttfb_blank(int blank, struct fb_info *info)
{
static int
imsttfb_blank(int blank, struct fb_info *info)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
__u32 ctrl;
ctrl = read_reg_le32(par->dc_regs, STGCTL);
if (blank > 0) {
__u32 ctrl;
ctrl = read_reg_le32(par->dc_regs, STGCTL);
if (blank > 0) {
- switch (blank
- 1
) {
- case
VESA_NO_BLANKING
:
- case
VESA
_POWERDOWN:
+ switch (blank) {
+ case
FB_BLANK_NORMAL
:
+ case
FB_BLANK
_POWERDOWN:
ctrl &= ~0x00000380;
if (par->ramdac == IBM) {
par->cmap_regs[PIDXHI] = 0; eieio();
ctrl &= ~0x00000380;
if (par->ramdac == IBM) {
par->cmap_regs[PIDXHI] = 0; eieio();
@@
-958,10
+962,10
@@
imsttfb_blank(int blank, struct fb_info *info)
par->cmap_regs[PIDXDATA] = 0xc0;
}
break;
par->cmap_regs[PIDXDATA] = 0xc0;
}
break;
- case
VESA
_VSYNC_SUSPEND:
+ case
FB_BLANK
_VSYNC_SUSPEND:
ctrl &= ~0x00000020;
break;
ctrl &= ~0x00000020;
break;
- case
VESA
_HSYNC_SUSPEND:
+ case
FB_BLANK
_HSYNC_SUSPEND:
ctrl &= ~0x00000010;
break;
}
ctrl &= ~0x00000010;
break;
}
@@
-989,7
+993,7
@@
imsttfb_blank(int blank, struct fb_info *info)
static void
imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
static void
imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
bgc = rect->color;
__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
bgc = rect->color;
@@
-1033,7
+1037,7
@@
imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
static void
imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
static void
imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
@@
-1195,7
+1199,7
@@
imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
static int
imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
static int
imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
u32 flags = cursor->set, fg, bg, xx, yy;
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
u32 flags = cursor->set, fg, bg, xx, yy;
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
@@
-1263,10
+1267,9
@@
imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
#define FBIMSTT_GETIDXREG 0x545406
static int
#define FBIMSTT_GETIDXREG 0x545406
static int
-imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
void __user *argp = (void __user *)arg;
__u32 reg[2];
__u8 idx[2];
void __user *argp = (void __user *)arg;
__u32 reg[2];
__u8 idx[2];
@@
-1287,12
+1290,12
@@
imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
case FBIMSTT_SETCMAPREG:
if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
case FBIMSTT_SETCMAPREG:
if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
- write_reg_le32(((u_int *)par->cmap_regs), reg[0], reg[1]);
+ write_reg_le32(((u_int
__iomem
*)par->cmap_regs), reg[0], reg[1]);
return 0;
case FBIMSTT_GETCMAPREG:
if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
return 0;
case FBIMSTT_GETCMAPREG:
if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
- reg[1] = read_reg_le32(((u_int *)par->cmap_regs), reg[0]);
+ reg[1] = read_reg_le32(((u_int
__iomem
*)par->cmap_regs), reg[0]);
if (copy_to_user((void __user *)(arg + 4), ®[1], 4))
return -EFAULT;
return 0;
if (copy_to_user((void __user *)(arg + 4), ®[1], 4))
return -EFAULT;
return 0;
@@
-1344,14
+1347,13
@@
static struct fb_ops imsttfb_ops = {
.fb_fillrect = imsttfb_fillrect,
.fb_copyarea = imsttfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_fillrect = imsttfb_fillrect,
.fb_copyarea = imsttfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_ioctl = imsttfb_ioctl,
};
.fb_ioctl = imsttfb_ioctl,
};
-static void __
init
+static void __
devinit
init_imstt(struct fb_info *info)
{
init_imstt(struct fb_info *info)
{
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
__u32 i, tmp, *ip, *end;
tmp = read_reg_le32(par->dc_regs, PRC);
__u32 i, tmp, *ip, *end;
tmp = read_reg_le32(par->dc_regs, PRC);
@@
-1370,18
+1372,24
@@
init_imstt(struct fb_info *info)
write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
write_reg_le32(par->dc_regs, SSR, 0);
write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
write_reg_le32(par->dc_regs, SSR, 0);
- /* set default values for DAC registers */
+ /* set default values for DAC registers */
if (par->ramdac == IBM) {
if (par->ramdac == IBM) {
- par->cmap_regs[PPMASK] = 0xff; eieio();
- par->cmap_regs[PIDXHI] = 0; eieio();
- for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) {
- par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio();
- par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio();
+ par->cmap_regs[PPMASK] = 0xff;
+ eieio();
+ par->cmap_regs[PIDXHI] = 0;
+ eieio();
+ for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) {
+ par->cmap_regs[PIDXLO] = ibm_initregs[i].addr;
+ eieio();
+ par->cmap_regs[PIDXDATA] = ibm_initregs[i].value;
+ eieio();
}
} else {
}
} else {
- for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) {
- par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio();
- par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio();
+ for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) {
+ par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;
+ eieio();
+ par->cmap_regs[TVPIDATA] = tvp_initregs[i].value;
+ eieio();
}
}
}
}
@@
-1414,7
+1422,7
@@
init_imstt(struct fb_info *info)
if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
|| !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
|| !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
-
kfre
e(info);
+
framebuffer_releas
e(info);
return;
}
return;
}
@@
-1442,12
+1450,15
@@
init_imstt(struct fb_info *info)
info->var.pixclock = 1000000 / getclkMHz(par);
info->fbops = &imsttfb_ops;
info->var.pixclock = 1000000 / getclkMHz(par);
info->fbops = &imsttfb_ops;
- info->flags = FBINFO_FLAG_DEFAULT;
+ info->flags = FBINFO_DEFAULT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT |
+ FBINFO_HWACCEL_YPAN;
fb_alloc_cmap(&info->cmap, 0, 0);
if (register_framebuffer(info) < 0) {
fb_alloc_cmap(&info->cmap, 0, 0);
if (register_framebuffer(info) < 0) {
-
kfre
e(info);
+
framebuffer_releas
e(info);
return;
}
return;
}
@@
-1472,26
+1483,21
@@
imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_ERR "imsttfb: no OF node for pci device\n");
#endif /* CONFIG_PPC_OF */
printk(KERN_ERR "imsttfb: no OF node for pci device\n");
#endif /* CONFIG_PPC_OF */
- size = sizeof(struct fb_info) + sizeof(struct imstt_par) +
- sizeof(u32) * 16;
-
- info = kmalloc(size, GFP_KERNEL);
+ info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
if (!info) {
printk(KERN_ERR "imsttfb: Can't allocate memory\n");
return -ENOMEM;
}
if (!info) {
printk(KERN_ERR "imsttfb: Can't allocate memory\n");
return -ENOMEM;
}
- memset(info, 0, size);
-
- par = (struct imstt_par *) (info + 1);
+ par = info->par;
addr = pci_resource_start (pdev, 0);
size = pci_resource_len (pdev, 0);
if (!request_mem_region(addr, size, "imsttfb")) {
printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
addr = pci_resource_start (pdev, 0);
size = pci_resource_len (pdev, 0);
if (!request_mem_region(addr, size, "imsttfb")) {
printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
-
kfre
e(info);
+
framebuffer_releas
e(info);
return -ENODEV;
}
return -ENODEV;
}
@@
-1510,17
+1516,19
@@
imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
default:
printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
"contact maintainer.\n", pdev->device);
default:
printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
"contact maintainer.\n", pdev->device);
+ release_mem_region(addr, size);
+ framebuffer_release(info);
return -ENODEV;
}
info->fix.smem_start = addr;
return -ENODEV;
}
info->fix.smem_start = addr;
- info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000);
+ info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
+ 0x400000 : 0x800000);
info->fix.mmio_start = addr + 0x800000;
info->fix.mmio_start = addr + 0x800000;
- par->dc_regs =
(__u32 *)
ioremap(addr + 0x800000, 0x1000);
+ par->dc_regs = ioremap(addr + 0x800000, 0x1000);
par->cmap_regs_phys = addr + 0x840000;
par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
par->cmap_regs_phys = addr + 0x840000;
par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
- info->par = par;
- info->pseudo_palette = (void *) (par + 1);
+ info->pseudo_palette = par->palette;
init_imstt(info);
pci_set_drvdata(pdev, info);
init_imstt(info);
pci_set_drvdata(pdev, info);
@@
-1531,7
+1539,7
@@
static void __devexit
imsttfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
imsttfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- struct imstt_par *par =
(struct imstt_par *)
info->par;
+ struct imstt_par *par = info->par;
int size = pci_resource_len(pdev, 0);
unregister_framebuffer(info);
int size = pci_resource_len(pdev, 0);
unregister_framebuffer(info);
@@
-1539,11
+1547,11
@@
imsttfb_remove(struct pci_dev *pdev)
iounmap(par->dc_regs);
iounmap(info->screen_base);
release_mem_region(info->fix.smem_start, size);
iounmap(par->dc_regs);
iounmap(info->screen_base);
release_mem_region(info->fix.smem_start, size);
-
kfre
e(info);
+
framebuffer_releas
e(info);
}
#ifndef MODULE
}
#ifndef MODULE
-int __init
+static int __init
imsttfb_setup(char *options)
{
char *this_opt;
imsttfb_setup(char *options)
{
char *this_opt;
@@
-1597,9
+1605,17
@@
imsttfb_setup(char *options)
#endif /* MODULE */
#endif /* MODULE */
-int __init imsttfb_init(void)
+
static
int __init imsttfb_init(void)
{
{
- return pci_module_init(&imsttfb_pci_driver);
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("imsttfb", &option))
+ return -ENODEV;
+
+ imsttfb_setup(option);
+#endif
+ return pci_register_driver(&imsttfb_pci_driver);
}
static void __exit imsttfb_exit(void)
}
static void __exit imsttfb_exit(void)
@@
-1607,9
+1623,8
@@
static void __exit imsttfb_exit(void)
pci_unregister_driver(&imsttfb_pci_driver);
}
pci_unregister_driver(&imsttfb_pci_driver);
}
-#ifdef MODULE
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");
+
module_init(imsttfb_init);
module_init(imsttfb_init);
-#endif
module_exit(imsttfb_exit);
module_exit(imsttfb_exit);