617 lines
18 KiB
Diff
Executable File
617 lines
18 KiB
Diff
Executable File
Index: linux-2.6.22-source/drivers/video/covideo.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ linux-2.6.22-source/drivers/video/covideo.c
|
|
@@ -0,0 +1,589 @@
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/fb.h>
|
|
+
|
|
+#include <linux/cooperative.h>
|
|
+#include <linux/cooperative_internal.h>
|
|
+#include <linux/cooperative_pci.h>
|
|
+
|
|
+#include <linux/covideo.h>
|
|
+
|
|
+#include <stdarg.h>
|
|
+
|
|
+MODULE_AUTHOR("Steve Shoecraft <sshoecraft@earthlink.net>");
|
|
+MODULE_DESCRIPTION("Cooperative Linux Video Driver");
|
|
+MODULE_LICENSE("GPL");
|
|
+
|
|
+#define COVIDEO_DEBUG 0
|
|
+#define COVIDEO_MEMTEST 0
|
|
+
|
|
+#if COVIDEO_DEBUG
|
|
+#define dprintk(m) printk m
|
|
+#else
|
|
+#define dprintk(m) /* noop */
|
|
+#endif
|
|
+
|
|
+/* Our info */
|
|
+struct covideo_par {
|
|
+ int unit;
|
|
+ void *buffer;
|
|
+ int size;
|
|
+ struct pci_dev *pdev;
|
|
+ struct mutex open_lock;
|
|
+};
|
|
+typedef struct covideo_par covideo_par_t;
|
|
+
|
|
+static void uprintk(int unit, char *fmt, ...) {
|
|
+ char line[1024],*p;
|
|
+ va_list ap;
|
|
+
|
|
+ sprintf(line,"covideo%d: ", unit);
|
|
+ p = line + strlen(line);
|
|
+
|
|
+ va_start(ap,fmt);
|
|
+ vsprintf(p,fmt,ap);
|
|
+ va_end(ap);
|
|
+}
|
|
+
|
|
+static struct fb_var_screeninfo covideo_default = {
|
|
+ .xres = 640,
|
|
+ .yres = 480,
|
|
+ .xres_virtual = 640,
|
|
+ .yres_virtual = 480,
|
|
+ .bits_per_pixel = 8,
|
|
+ .red = { 0, 8, 0 },
|
|
+ .green = { 0, 8, 0 },
|
|
+ .blue = { 0, 8, 0 },
|
|
+ .activate = FB_ACTIVATE_TEST,
|
|
+ .height = -1,
|
|
+ .width = -1,
|
|
+ .pixclock = 20000,
|
|
+ .left_margin = 64,
|
|
+ .right_margin = 64,
|
|
+ .upper_margin = 32,
|
|
+ .lower_margin = 32,
|
|
+ .hsync_len = 64,
|
|
+ .vsync_len = 2,
|
|
+ .vmode = FB_VMODE_NONINTERLACED,
|
|
+};
|
|
+
|
|
+static struct fb_fix_screeninfo covideo_fix = {
|
|
+ .id = "CoVideo",
|
|
+ .type = FB_TYPE_PACKED_PIXELS,
|
|
+ .visual = FB_VISUAL_PSEUDOCOLOR,
|
|
+ .xpanstep = 1,
|
|
+ .ypanstep = 1,
|
|
+ .ywrapstep = 1,
|
|
+ .accel = FB_ACCEL_NONE,
|
|
+};
|
|
+
|
|
+static int covideo_open(struct fb_info *info, int user)
|
|
+{
|
|
+ covideo_par_t *par = info->par;
|
|
+
|
|
+ printk(KERN_INFO "covideo%d: open: user: %d\n", par->unit, user);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int covideo_release(struct fb_info *info, int user)
|
|
+{
|
|
+ covideo_par_t *par = info->par;
|
|
+
|
|
+ printk(KERN_INFO "covideo%d: close: user: %d\n", par->unit, user);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static u_long get_line_length(int xres_virtual, int bpp)
|
|
+{
|
|
+ u_long length;
|
|
+
|
|
+ length = xres_virtual * bpp;
|
|
+ length = (length + 31) & ~31;
|
|
+ length >>= 3;
|
|
+ return (length);
|
|
+}
|
|
+
|
|
+static int covideo_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
|
+{
|
|
+ struct covideo_par *par = info->par;
|
|
+ u_long line_length;
|
|
+
|
|
+// uprintk("checking var...\n");
|
|
+
|
|
+// printk("check_var: xres: %d, yres: %d, bpp: %d\n", var->xres, var->yres, var->bits_per_pixel);
|
|
+
|
|
+ /* We only do 32 BPP */
|
|
+// if (var->bits_per_pixel != 32) return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
|
|
+ * as FB_VMODE_SMOOTH_XPAN is only used internally
|
|
+ */
|
|
+ if (var->vmode & FB_VMODE_CONUPDATE) {
|
|
+ var->vmode |= FB_VMODE_YWRAP;
|
|
+ var->xoffset = info->var.xoffset;
|
|
+ var->yoffset = info->var.yoffset;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Some very basic checks
|
|
+ */
|
|
+ if (!var->xres)
|
|
+ var->xres = 1;
|
|
+ if (!var->yres)
|
|
+ var->yres = 1;
|
|
+ if (var->xres > var->xres_virtual)
|
|
+ var->xres_virtual = var->xres;
|
|
+ if (var->yres > var->yres_virtual)
|
|
+ var->yres_virtual = var->yres;
|
|
+ if (var->bits_per_pixel <= 1)
|
|
+ var->bits_per_pixel = 1;
|
|
+ else if (var->bits_per_pixel <= 8)
|
|
+ var->bits_per_pixel = 8;
|
|
+ else if (var->bits_per_pixel <= 16)
|
|
+ var->bits_per_pixel = 16;
|
|
+ else if (var->bits_per_pixel <= 24)
|
|
+ var->bits_per_pixel = 24;
|
|
+ else if (var->bits_per_pixel <= 32)
|
|
+ var->bits_per_pixel = 32;
|
|
+ else
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (var->xres_virtual < var->xoffset + var->xres)
|
|
+ var->xres_virtual = var->xoffset + var->xres;
|
|
+ if (var->yres_virtual < var->yoffset + var->yres)
|
|
+ var->yres_virtual = var->yoffset + var->yres;
|
|
+
|
|
+ line_length =
|
|
+ get_line_length(var->xres_virtual, var->bits_per_pixel);
|
|
+ if (line_length * var->yres_virtual > par->size)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ /*
|
|
+ * Now that we checked it we alter var. The reason being is that the video
|
|
+ * mode passed in might not work but slight changes to it might make it
|
|
+ * work. This way we let the user know what is acceptable.
|
|
+ */
|
|
+ switch (var->bits_per_pixel) {
|
|
+ case 1:
|
|
+ case 8:
|
|
+ var->red.offset = 0;
|
|
+ var->red.length = 8;
|
|
+ var->green.offset = 0;
|
|
+ var->green.length = 8;
|
|
+ var->blue.offset = 0;
|
|
+ var->blue.length = 8;
|
|
+ var->transp.offset = 0;
|
|
+ var->transp.length = 0;
|
|
+ break;
|
|
+ case 16: /* RGBA 5551 */
|
|
+ if (var->transp.length) {
|
|
+ var->red.offset = 0;
|
|
+ var->red.length = 5;
|
|
+ var->green.offset = 5;
|
|
+ var->green.length = 5;
|
|
+ var->blue.offset = 10;
|
|
+ var->blue.length = 5;
|
|
+ var->transp.offset = 15;
|
|
+ var->transp.length = 1;
|
|
+ } else { /* RGB 565 */
|
|
+ var->red.offset = 0;
|
|
+ var->red.length = 5;
|
|
+ var->green.offset = 5;
|
|
+ var->green.length = 6;
|
|
+ var->blue.offset = 11;
|
|
+ var->blue.length = 5;
|
|
+ var->transp.offset = 0;
|
|
+ var->transp.length = 0;
|
|
+ }
|
|
+ break;
|
|
+ case 24: /* RGB 888 */
|
|
+ var->red.offset = 0;
|
|
+ var->red.length = 8;
|
|
+ var->green.offset = 8;
|
|
+ var->green.length = 8;
|
|
+ var->blue.offset = 16;
|
|
+ var->blue.length = 8;
|
|
+ var->transp.offset = 0;
|
|
+ var->transp.length = 0;
|
|
+ break;
|
|
+ case 32: /* RGBA 8888 */
|
|
+ var->red.offset = 0;
|
|
+ var->red.length = 8;
|
|
+ var->green.offset = 8;
|
|
+ var->green.length = 8;
|
|
+ var->blue.offset = 16;
|
|
+ var->blue.length = 8;
|
|
+ var->transp.offset = 24;
|
|
+ var->transp.length = 8;
|
|
+ break;
|
|
+ }
|
|
+ var->red.msb_right = 0;
|
|
+ var->green.msb_right = 0;
|
|
+ var->blue.msb_right = 0;
|
|
+ var->transp.msb_right = 0;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int covideo_set_par(struct fb_info *info)
|
|
+{
|
|
+// struct covideo_par *par = info->par;
|
|
+
|
|
+// uprintk(par->unit, "setting par...\n");
|
|
+
|
|
+ printk("set_par: xres: %d, yres: %d, bpp: %d\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
|
|
+ info->fix.line_length = get_line_length(info->var.xres_virtual, info->var.bits_per_pixel);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int covideo_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
|
|
+{
|
|
+ struct covideo_par *par = info->par;
|
|
+
|
|
+ uprintk(par->unit, "setting coloreg...\n");
|
|
+
|
|
+ if (regno >= 256) /* no. of hw registers */
|
|
+ return 1;
|
|
+ /*
|
|
+ * Program hardware... do anything you want with transp
|
|
+ */
|
|
+
|
|
+ /* grayscale works only partially under directcolor */
|
|
+ if (info->var.grayscale) {
|
|
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
|
|
+ red = green = blue =
|
|
+ (red * 77 + green * 151 + blue * 28) >> 8;
|
|
+ }
|
|
+
|
|
+ /* Directcolor:
|
|
+ * var->{color}.offset contains start of bitfield
|
|
+ * var->{color}.length contains length of bitfield
|
|
+ * {hardwarespecific} contains width of RAMDAC
|
|
+ * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
|
|
+ * RAMDAC[X] is programmed to (red, green, blue)
|
|
+ *
|
|
+ * Pseudocolor:
|
|
+ * uses offset = 0 && length = RAMDAC register width.
|
|
+ * var->{color}.offset is 0
|
|
+ * var->{color}.length contains widht of DAC
|
|
+ * cmap is not used
|
|
+ * RAMDAC[X] is programmed to (red, green, blue)
|
|
+ * Truecolor:
|
|
+ * does not use DAC. Usually 3 are present.
|
|
+ * var->{color}.offset contains start of bitfield
|
|
+ * var->{color}.length contains length of bitfield
|
|
+ * cmap is programmed to (red << red.offset) | (green << green.offset) |
|
|
+ * (blue << blue.offset) | (transp << transp.offset)
|
|
+ * RAMDAC does not exist
|
|
+ */
|
|
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
|
|
+ switch (info->fix.visual) {
|
|
+ case FB_VISUAL_TRUECOLOR:
|
|
+ case FB_VISUAL_PSEUDOCOLOR:
|
|
+ red = CNVT_TOHW(red, info->var.red.length);
|
|
+ green = CNVT_TOHW(green, info->var.green.length);
|
|
+ blue = CNVT_TOHW(blue, info->var.blue.length);
|
|
+ transp = CNVT_TOHW(transp, info->var.transp.length);
|
|
+ break;
|
|
+ case FB_VISUAL_DIRECTCOLOR:
|
|
+ red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
|
|
+ green = CNVT_TOHW(green, 8);
|
|
+ blue = CNVT_TOHW(blue, 8);
|
|
+ /* hey, there is bug in transp handling... */
|
|
+ transp = CNVT_TOHW(transp, 8);
|
|
+ break;
|
|
+ }
|
|
+#undef CNVT_TOHW
|
|
+ /* Truecolor has hardware independent palette */
|
|
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
|
|
+ u32 v;
|
|
+
|
|
+ if (regno >= 16)
|
|
+ return 1;
|
|
+
|
|
+ v = (red << info->var.red.offset) |
|
|
+ (green << info->var.green.offset) |
|
|
+ (blue << info->var.blue.offset) |
|
|
+ (transp << info->var.transp.offset);
|
|
+ switch (info->var.bits_per_pixel) {
|
|
+ case 8:
|
|
+ break;
|
|
+ case 16:
|
|
+ ((u32 *) (info->pseudo_palette))[regno] = v;
|
|
+ break;
|
|
+ case 24:
|
|
+ case 32:
|
|
+ ((u32 *) (info->pseudo_palette))[regno] = v;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int covideo_blank(int blank_mode, struct fb_info *info)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int covideo_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
|
+{
|
|
+ unsigned long start = vma->vm_start;
|
|
+ unsigned long size = vma->vm_end-vma->vm_start;
|
|
+ unsigned long page, pos;
|
|
+
|
|
+ if (size > info->screen_size) return -EINVAL;
|
|
+
|
|
+ pos = (unsigned long) info->screen_base;
|
|
+ while (size > 0) {
|
|
+ page = vmalloc_to_pfn((void *)pos);
|
|
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
|
|
+ return -EAGAIN;
|
|
+
|
|
+ start += PAGE_SIZE;
|
|
+ pos += PAGE_SIZE;
|
|
+ if (size > PAGE_SIZE)
|
|
+ size -= PAGE_SIZE;
|
|
+ else
|
|
+ size = 0;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* Frame buffer operations */
|
|
+static struct fb_ops covideo_ops = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .fb_open = covideo_open,
|
|
+ .fb_release = covideo_release,
|
|
+ .fb_read = fb_sys_read,
|
|
+ .fb_write = fb_sys_write,
|
|
+ .fb_check_var = covideo_check_var,
|
|
+ .fb_set_par = covideo_set_par,
|
|
+ .fb_setcolreg = covideo_setcolreg,
|
|
+ .fb_blank = covideo_blank,
|
|
+ .fb_fillrect = sys_fillrect,
|
|
+ .fb_copyarea = sys_copyarea,
|
|
+ .fb_imageblit = sys_imageblit,
|
|
+ .fb_mmap = covideo_mmap,
|
|
+
|
|
+#if 0
|
|
+ /* XXX currently not implemented */
|
|
+ .fb_setcmap = covideo_setcmap,
|
|
+ .fb_pan_display = covideo_pan_display,
|
|
+ .fb_cursor = covideo_cursor,
|
|
+ .fb_rotate = covideo_rotate,
|
|
+ .fb_get_caps = svga_get_caps,
|
|
+#endif
|
|
+};
|
|
+
|
|
+#if COVIDEO_MEMTEST
|
|
+/* Simple page-level checkerboard test */
|
|
+static int test_buffer(void *buffer, int unit, int size) {
|
|
+ unsigned char *p, *t, *t0, *t1;
|
|
+ unsigned long flags;
|
|
+ int npages,rc;
|
|
+ register int i;
|
|
+
|
|
+ printk(KERN_INFO "covideo%d: testing buffer at 0x%p (size: %d)\n", unit, buffer, size);
|
|
+ rc = 1;
|
|
+ t1 = 0;
|
|
+ if ((t0 = kmalloc(PAGE_SIZE, GFP_KERNEL)) == 0) goto test_out;
|
|
+ memset(t0, 0, PAGE_SIZE);
|
|
+ if ((t1 = kmalloc(PAGE_SIZE, GFP_KERNEL)) == 0) goto test_out;
|
|
+ memset(t1, 0xFF, PAGE_SIZE);
|
|
+ npages = size >> PAGE_SHIFT;
|
|
+
|
|
+ p = buffer;
|
|
+ for(i=0; i < npages; i++) {
|
|
+ t = (i & 1 ? t1 : t0);
|
|
+ memcpy(p, t, PAGE_SIZE);
|
|
+ p += PAGE_SIZE;
|
|
+ }
|
|
+
|
|
+ co_passage_page_assert_valid();
|
|
+ co_passage_page_acquire(&flags);
|
|
+ co_passage_page->operation = CO_OPERATION_DEVICE;
|
|
+ co_passage_page->params[0] = CO_DEVICE_VIDEO;
|
|
+ co_passage_page->params[1] = CO_VIDEO_TEST;
|
|
+ co_passage_page->params[2] = unit;
|
|
+ co_switch_wrapper();
|
|
+ rc = co_passage_page->params[0];
|
|
+ co_passage_page_release(flags);
|
|
+
|
|
+ /* Fail on host side? */
|
|
+ if (rc) goto test_out;
|
|
+
|
|
+ p = buffer;
|
|
+ for(i=0; i < npages; i++) {
|
|
+ t = (i & 1 ? t0 : t1);
|
|
+ if (memcmp(p, t, PAGE_SIZE) != 0)
|
|
+ goto test_out;
|
|
+ p += PAGE_SIZE;
|
|
+ }
|
|
+
|
|
+ rc = 0;
|
|
+
|
|
+test_out:
|
|
+ if (t0) kfree(t0);
|
|
+ if (t1) kfree(t1);
|
|
+ printk(KERN_INFO "covideo%d: test %s!\n", unit, (rc ? "failed" : "passed"));
|
|
+ return rc;
|
|
+}
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * PCI Probe - probe for a single device
|
|
+*/
|
|
+static int __devinit covideo_pci_probe( struct pci_dev *pdev, const struct pci_device_id *id )
|
|
+{
|
|
+ unsigned long flags;
|
|
+ covideo_config_t *cp;
|
|
+ struct fb_info *info;
|
|
+ covideo_par_t *par;
|
|
+ void *host_buffer, *buffer;
|
|
+ u8 unit;
|
|
+ int rc, size;
|
|
+
|
|
+ /* Get our host unit */
|
|
+ pci_read_config_byte(pdev, PCI_CO_UNIT, &unit);
|
|
+
|
|
+ /* Get our config */
|
|
+ co_passage_page_assert_valid();
|
|
+ co_passage_page_acquire(&flags);
|
|
+ co_passage_page->operation = CO_OPERATION_DEVICE;
|
|
+ co_passage_page->params[0] = CO_DEVICE_VIDEO;
|
|
+ co_passage_page->params[1] = CO_VIDEO_GET_CONFIG;
|
|
+ co_passage_page->params[2] = unit;
|
|
+ co_switch_wrapper();
|
|
+ rc = co_passage_page->params[0];
|
|
+ cp = (covideo_config_t *) &co_passage_page->params[1];
|
|
+ host_buffer = cp->buffer;
|
|
+ size = cp->size;
|
|
+ co_passage_page_release(flags);
|
|
+
|
|
+ /* If unable to get size, silently skip this device */
|
|
+ if (rc) return 0;
|
|
+
|
|
+ /* Map host buffer into our space */
|
|
+ buffer = co_map_buffer(host_buffer, size);
|
|
+ if (!buffer) {
|
|
+ printk(KERN_ERR "covideo%d: unable to map video buffer!\n", unit);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+#if COVIDEO_DEBUG
|
|
+ printk(KERN_INFO "covideo%d: buffer: %p, size: %d\n", unit, buffer, size);
|
|
+#endif
|
|
+
|
|
+#if COVIDEO_MEMTEST
|
|
+ /* Test buffer */
|
|
+ if (test_buffer(buffer, unit, size)) return -EIO;
|
|
+#endif
|
|
+
|
|
+ /* Allocate and fill driver data structure */
|
|
+ info = framebuffer_alloc(sizeof(covideo_par_t), &pdev->dev);
|
|
+ if (!info) {
|
|
+ printk(KERN_ERR "covideo%d: framebuffer alloc failed!!", unit);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ /* Need to set the base and ops before find_mode */
|
|
+ info->screen_base = (char __iomem *)buffer;
|
|
+ info->screen_size = size;
|
|
+ info->fbops = &covideo_ops;
|
|
+
|
|
+#if COVIDEO_DEBUG
|
|
+ printk(KERN_INFO "covideo%d: calling find_mode...\n", unit);
|
|
+#endif
|
|
+ rc = fb_find_mode(&info->var, info, NULL, NULL, 0, NULL, 8);
|
|
+ if (!rc || (rc == 4)) info->var = covideo_default;
|
|
+
|
|
+ info->fix = covideo_fix;
|
|
+ info->fix.smem_start = (unsigned long) buffer;
|
|
+ info->fix.smem_len = size;
|
|
+ info->pseudo_palette = NULL;
|
|
+ info->flags = FBINFO_FLAG_DEFAULT;
|
|
+
|
|
+ rc = fb_alloc_cmap(&info->cmap, 256, 0);
|
|
+ if (rc < 0) goto err1;
|
|
+
|
|
+ rc = register_framebuffer(info);
|
|
+ if (rc < 0) goto err2;
|
|
+
|
|
+ par = info->par;
|
|
+ par->pdev = pdev;
|
|
+ par->unit = unit;
|
|
+ par->buffer = buffer;
|
|
+ par->size = size;
|
|
+ mutex_init(&par->open_lock);
|
|
+
|
|
+ printk(KERN_INFO "fb%d: Cooperative video at: %p, size: %dK\n", info->node,
|
|
+ buffer, size >> 10);
|
|
+
|
|
+ pci_set_drvdata(pdev, info);
|
|
+ return 0;
|
|
+
|
|
+err2:
|
|
+ fb_dealloc_cmap(&info->cmap);
|
|
+
|
|
+err1:
|
|
+ framebuffer_release(info);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * PCI Remove - hotplug removal
|
|
+*/
|
|
+static void __devexit covideo_pci_remove(struct pci_dev *pdev)
|
|
+{
|
|
+ pci_set_drvdata(pdev, NULL);
|
|
+}
|
|
+
|
|
+static struct pci_device_id covideo_pci_ids[] __devinitdata = {
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_CO, PCI_DEVICE_ID_COVIDEO) },
|
|
+ { 0 }
|
|
+};
|
|
+
|
|
+static struct pci_driver covideo_pci_driver = {
|
|
+ .name = "covideo",
|
|
+ .id_table = covideo_pci_ids,
|
|
+ .probe = covideo_pci_probe,
|
|
+ .remove = __devexit_p(covideo_pci_remove),
|
|
+};
|
|
+
|
|
+extern int coio_test(void);
|
|
+
|
|
+/*
|
|
+ * PCI Init - module load
|
|
+*/
|
|
+static int __init covideo_pci_init(void) {
|
|
+#if 0
|
|
+ rc = request_irq(VIDEO_IRQ, &covideo_isr, IRQF_SAMPLE_RANDOM, "covideo", NULL);
|
|
+ if (rc) {
|
|
+ printk(KERN_ERR "covideo_pci_init: unable to get irq %d", VIDEO_IRQ);
|
|
+ return rc;
|
|
+ }
|
|
+#endif
|
|
+#if COVIDEO_DEBUG
|
|
+ printk(KERN_INFO "covideo_pci_init: registering...\n");
|
|
+#endif
|
|
+ return pci_register_driver(&covideo_pci_driver);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * PCI Exit - module unload
|
|
+*/
|
|
+static void __exit covideo_pci_exit(void) {
|
|
+#if COVIDEO_DEBUG
|
|
+ printk(KERN_INFO "covideo_pci_exit: exiting\n");
|
|
+#endif
|
|
+ pci_unregister_driver(&covideo_pci_driver);
|
|
+}
|
|
+
|
|
+module_init(covideo_pci_init);
|
|
+module_exit(covideo_pci_exit);
|
|
Index: linux-2.6.22-source/include/linux/covideo.h
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ linux-2.6.22-source/include/linux/covideo.h
|
|
@@ -0,0 +1,17 @@
|
|
+
|
|
+#ifndef _LINUX_COVIDEO_H_
|
|
+#define _LINUX_COVIDEO_H_
|
|
+
|
|
+enum CO_VIDEO_FUNC {
|
|
+ CO_VIDEO_GET_CONFIG,
|
|
+ CO_VIDEO_TEST,
|
|
+};
|
|
+
|
|
+struct covideo_config {
|
|
+ void *buffer;
|
|
+ int size;
|
|
+};
|
|
+
|
|
+typedef struct covideo_config covideo_config_t;
|
|
+
|
|
+#endif
|