Initial. Don't... just don't ask.

This commit is contained in:
Ryan McGrath 2011-02-24 00:22:00 -08:00
commit 00bae13bba
586 changed files with 129057 additions and 0 deletions

View file

@ -0,0 +1,66 @@
SVGALIB_HELPER_MAJOR=209
svgalib_helper-objs := main.o i810.o interrupt.o virtual.o displaystart.o
obj-m := svgalib_helper.o
ifneq ($(KERNELRELEASE),)
VER ?= $(KERNELRELEASE)
KDIR := /lib/modules/$(VER)/build
PWD := $(shell pwd)
TARGET := svgalib_helper
ifeq ($(PATCHLEVEL),4)
include $(TOPDIR)/Rules.make
endif
else
VER ?= $(shell uname -r)
KDIR := /lib/modules/$(VER)/build
PWD := $(shell pwd)
TARGET := svgalib_helper
endif
CLASS_SIMPLE := $(shell grep class_simple_create $(KDIR)/include/linux/device.h)
ifneq ($(CLASS_SIMPLE),)
CLASS_CFLAGS = -DCLASS_SIMPLE=1
endif
EXTRA_CFLAGS := -DSVGALIB_HELPER_MAJOR=$(SVGALIB_HELPER_MAJOR) $(CLASS_CFLAGS)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) CLASS_CFLAGS=$(CLASS_CFLAGS) modules
depend:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) depend
clean:
rm -f svgalib_helper.{o,ko,mod.{o,c}} .*.{cmd,flags}
rm -f *.o *~ core .depend *.bak *.orig
rm -fr .tmp_versions
svgalib_helper.o: $(svgalib_helper-objs)
$(LD) -r -o $@ $(svgalib_helper-objs)
device:
rm -f /dev/svga /dev/svga?
mknod -m 666 /dev/svga c $(SVGALIB_HELPER_MAJOR) 0
mknod -m 666 /dev/svga1 c $(SVGALIB_HELPER_MAJOR) 1
mknod -m 666 /dev/svga2 c $(SVGALIB_HELPER_MAJOR) 2
mknod -m 666 /dev/svga3 c $(SVGALIB_HELPER_MAJOR) 3
mknod -m 666 /dev/svga4 c $(SVGALIB_HELPER_MAJOR) 4
install: device modules_install
modules_install: $(MODNAME)
mkdir -p /lib/modules/$(VER)/kernel/misc
install -m 0644 -c $(TARGET).ko /lib/modules/$(VER)/kernel/misc || install -m 0644 -c $(TARGET).o /lib/modules/$(VER)/kernel/misc
depmod -a $(VER)

View file

@ -0,0 +1,84 @@
include ../../Makefile.cfg
ifndef INCLUDEDIR
INCLUDEDIR = /lib/modules/$(shell uname -r)/build/include
endif
MODVER = $(shell grep CONFIG_MODVERSIONS $(INCLUDEDIR)/linux/autoconf.h)
ifeq ($(MODVER),)
@echo INCLUDEDIR is not set up correctly
exit 1
endif
# Extract version number from headers.
VER = $(shell awk -F\" '/REL/ {print $$2}' $(INCLUDEDIR)/linux/version.h 2>/dev/null)
# Use version of current running kernel
ifeq ($(VER),)
VER = $(shell uname -r)
endif
VER_MAJOR = $(shell echo $(VER) | cut -d. -f1)
VER_MINOR = $(shell echo $(VER) | cut -d. -f2)
INCLUDES += -I$(INCLUDEDIR)
INCLUDES += -I$(INCLUDEDIR)/asm/mach-default
CFLAGS = -O2 -DLINUX -Dlinux -D__KERNEL__ -DMODULE $(DEBFLAGS)
ifeq (2,$(VER_MAJOR))
ifeq (6,$(VER_MINOR))
CFLAGS += -DKBUILD_MODNAME="svgalib_helper"
endif
endif
CFLAGS += $(INCLUDES)
CFLAGS += -DSVGALIB_HELPER_MAJOR=$(SVGALIB_HELPER_MAJOR)
ifeq (1,$(findstring 1,$(MODVER)))
CFLAGS += -DMODVERSIONS -include $(INCLUDEDIR)/linux/modversions.h
endif
TARGET = svgalib_helper
OBJS = $(TARGET).o
SRC = main.c interrupt.c i810.c virtual.c displaystart.c
ifeq (2,$(VER_MAJOR))
ifeq (6,$(VER_MINOR))
OBJS = $(TARGET).ko
endif
endif
all: .depend $(OBJS)
$(TARGET).o: $(SRC:.c=.o)
$(LD) -r $^ -o $@
$(TARGET).ko: $(TARGET).o
$(LD) -d -r $^ -o $@
install: device modules_install
modules_install: $(OBJS)
mkdir -p /lib/modules/$(VER)/kernel/misc
install -m 0644 -c $(OBJS) /lib/modules/$(VER)/kernel/misc
device:
rm -f /dev/svgalib_helper* /dev/svga_helper* /dev/svga /dev/svga?
mknod -m 666 /dev/svga c $(SVGALIB_HELPER_MAJOR) 0
mknod -m 666 /dev/svga1 c $(SVGALIB_HELPER_MAJOR) 1
mknod -m 666 /dev/svga2 c $(SVGALIB_HELPER_MAJOR) 2
mknod -m 666 /dev/svga3 c $(SVGALIB_HELPER_MAJOR) 3
mknod -m 666 /dev/svga4 c $(SVGALIB_HELPER_MAJOR) 4
clean:
rm -f *.ko *.o *~ core .depend *.bak *.orig
depend .depend dep:
$(CC) $(CFLAGS) -M *.c > $@
ifeq (.depend,$(wildcard .depend))
include .depend
endif

View file

@ -0,0 +1,108 @@
#include <linux/pci.h>
#include <linux/mm.h>
#include <asm/io.h>
#include "kernel26compat.h"
#include "svgalib_helper.h"
#ifndef NO_TASK
void set_displaystart(struct sh_pci_device *dev) {
int i, id;
long ad;
switch(dev->vendor) {
case PCI_VENDOR_ID_MATROX:
ad=dev->startad>>3;
writeb(0x0c, dev->membase+0x3D4);
writeb((ad & 0xFF00)>>8, dev->membase+0x3D5);
writeb(0x0d, dev->membase+0x3D4);
writeb(ad & 0xFF, dev->membase+0x3D5);
writeb(0x00, dev->membase+0x3DE);
i=readb(dev->membase+0x3DF) & 0xb0;
i|=(ad & 0xf0000)>>16;
i|=(ad & 0x100000)>>14;
writeb(i, dev->membase+0x3DF);
break;
#if 0
case PCI_VENDOR_ID_SI: /* SiS */
dev->iobase = dev->mem[2]-0x380;
dev->test_vsync = io_test_vsync;
dev->ack_vsync = io_ack_vsync;
dev->enable_vsync = io_enable_vsync;
break;
#endif
case PCI_VENDOR_ID_NVIDIA_SGS:
if(dev->id<0x20) {
ad=dev->startad>>2;
writeb(0x0c, dev->membase+0x6013D4);
writeb((ad & 0xFF00)>>8, dev->membase+0x6013D5);
writeb(0x0d, dev->membase+0x6013D4);
writeb(ad & 0xFF, dev->membase+0x6013D5);
writeb(0x19, dev->membase+0x6013D4);
i=readb(dev->membase+0x6013D5) & 0xe0;
i|=(ad & 0x1f0000)>>16;
writeb(i, dev->membase+0x6013D5);
writeb(0x2D, dev->membase+0x6013D4);
i=readb(dev->membase+0x6013D5) & 0x9f;
i|=(ad & 0x600000)>>16;
writeb(i, dev->membase+0x6013D5);
} else {
}
break;
#if 0
case PCI_VENDOR_ID_NVIDIA:
dev->iobase = (unsigned long)ioremap(dev->mem[0],0x800000);
dev->test_vsync = nv4_test_vsync;
dev->ack_vsync = nv4_ack_vsync;
dev->enable_vsync = nv4_enable_vsync;
break;
case PCI_VENDOR_ID_ATI:
id=dev->id;
if( (id==0x4c45) ||
(id==0x4c46) ||
(id==0x4c57) ||
(id==0x4c59) ||
(id==0x4c5a) ||
(id==0x4d46) ||
(id==0x4d4c) ||
(id==0x4242) ||
((id>>8)==0x50) ||
((id>>8)==0x51) ||
((id>>8)==0x52) ||
((id>>8)==0x53) ||
((id>>8)==0x54)) {
dev->iobase = (unsigned long)ioremap(dev->mem[2], 16384);
dev->test_vsync = r128_test_vsync;
dev->ack_vsync = r128_ack_vsync;
dev->enable_vsync = r128_enable_vsync;
} else {
dev->iobase = dev->mem[1];
dev->test_vsync = rage_test_vsync;
dev->ack_vsync = rage_ack_vsync;
dev->enable_vsync = rage_enable_vsync;
}
break;
case PCI_VENDOR_ID_RENDITION:
dev->iobase = dev->mem[1];
dev->test_vsync = rendition_test_vsync;
dev->ack_vsync = rendition_ack_vsync;
dev->enable_vsync = rendition_enable_vsync;
break;
case PCI_VENDOR_ID_S3:
dev->iobase = (unsigned long)ioremap(dev->mem[0]+0x1000000, 0x10000);
dev->test_vsync = s3_test_vsync;
dev->ack_vsync = s3_ack_vsync;
dev->enable_vsync = s3_enable_vsync;
break;
default:
dev->test_vsync = vga_test_vsync;
dev->ack_vsync = vga_ack_vsync;
dev->enable_vsync = vga_enable_vsync;
dev->iobase = 0;
#endif
}
}
#endif

View file

@ -0,0 +1,2 @@
void set_displaystart(struct sh_pci_device *);

View file

@ -0,0 +1,9 @@
MAKE="make"
DEST_MODULE_LOCATION="/kernel/misc"
CLEAN="make clean"
MODULE_NAME="svgalib_helper.o"
BUILT_MODULE_NAME="svgalib_helper"
PACKAGE_NAME="svgalib_helper"
PACKAGE_VERSION="1.9.25"
AUTOINSTALL="yes"

View file

@ -0,0 +1,66 @@
/* vram size in pages */
#ifdef __386__
#include <linux/version.h>
#include <asm/uaccess.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/segment.h> /* memcpy and such */
#include <asm/io.h>
#include <asm/pgtable.h>
#define I810_SIZE 1024
unsigned long i810_alloc_page()
{
unsigned long address;
address = __get_free_page(GFP_KERNEL);
if(address == 0UL)
return 0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
atomic_inc(&virt_to_page(address)->count);
set_bit(PG_locked, &virt_to_page(address)->flags);
#endif
return address;
}
#if 0
static void i810_free_page(unsigned long page)
{
if(page == 0UL)
return;
atomic_dec(&virt_to_page(page)->count);
clear_bit(PG_locked, &virt_to_page(page)->flags);
wake_up(&virt_to_page(page)->wait);
free_page(page);
return;
}
#endif
static unsigned long i810_pages[I810_SIZE];
unsigned long i810_gttes[I810_SIZE];
static unsigned long i810_gttpage=0;
unsigned int i810_make_gtt() {
int i;
if(i810_gttpage) return virt_to_bus((void *)i810_gttpage);
i810_gttpage=i810_alloc_page();
for(i=0;i<I810_SIZE;i++) {
unsigned int gtte;
i810_pages[i]=i810_alloc_page();
gtte=virt_to_bus((void *)i810_pages[i]);
gtte &= 0x3ffff000;
gtte |= 1; /* valid, system memory, not cached */
i810_gttes[i]=gtte;
}
return virt_to_bus((void *)i810_gttpage);
}
#endif

View file

@ -0,0 +1,6 @@
#define I810_SIZE 1024
unsigned long i810_alloc_page(void);
unsigned int i810_make_gtt(void);
extern unsigned long i810_gttes[I810_SIZE];

View file

@ -0,0 +1,309 @@
#include <linux/pci.h>
#include <linux/mm.h>
#include <asm/io.h>
#include "kernel26compat.h"
#include "svgalib_helper.h"
int vga_test_vsync(struct sh_pci_device *dev) {
return inb(0x3c2)&0x80;
}
void vga_ack_vsync(struct sh_pci_device *dev) {
int pb;
/* clear pending */
outb(0x11, 0x3d4);
pb = inb(0x3d5);
outb(0x11, 0x3d4);
outb((pb&0xef) | 0x20, 0x3d5);
/* disable interrupts */
outb(0x11, 0x3d4);
pb = inb(0x3d5);
outb(0x11, 0x3d4);
outb(pb | 0x20 , 0x3d5);
}
void vga_enable_vsync(struct sh_pci_device *dev) {
int pb;
/* enable interrupt, clear pending */
outb(0x11, 0x3d4);
pb = inb(0x3d5);
outb(0x11, 0x3d4);
outb((pb&0xcf) , 0x3d5);
/* Allow interrupts */
outb(0x11, 0x3d4);
pb = inb(0x3d5);
outb(0x11, 0x3d4);
outb(pb | 0x10 , 0x3d5);
}
int io_test_vsync(struct sh_pci_device *dev) {
return inb(dev->iobase+0x3c2)&0x80;
}
void io_ack_vsync(struct sh_pci_device *dev) {
int pb;
/* clear pending */
outb(0x11, dev->iobase+0x3d4);
pb = inb(dev->iobase+0x3d5);
outb(0x11, dev->iobase+0x3d4);
outb((pb&0xef) | 0x20, dev->iobase+0x3d5);
/* disable interrupts */
outb(0x11, dev->iobase+0x3d4);
pb = inb(dev->iobase+0x3d5);
outb(0x11, dev->iobase+0x3d4);
outb(pb | 0x20 , dev->iobase+0x3d5);
}
void io_enable_vsync(struct sh_pci_device *dev) {
int pb;
/* enable interrupt, clear pending */
outb(0x11, dev->iobase+0x3d4);
pb = inb(dev->iobase+0x3d5);
outb(0x11, dev->iobase+0x3d4);
outb((pb&0xcf) , dev->iobase+0x3d5);
/* Allow interrupts */
outb(0x11, dev->iobase+0x3d4);
pb = inb(dev->iobase+0x3d5);
outb(0x11, dev->iobase+0x3d4);
outb(pb | 0x10 , dev->iobase+0x3d5);
}
int mm_test_vsync(struct sh_pci_device *dev) {
return readb(dev->membase+0x3c2)&0x80;
}
void mm_ack_vsync(struct sh_pci_device *dev) {
int pb;
/* clear pending */
writeb(0x11, dev->membase+0x3d4);
pb = readb(dev->membase+0x3d5);
writeb(0x11, dev->membase+0x3d4);
writeb((pb&0xef) | 0x20, dev->membase+0x3d5);
/* disable interrupts */
writeb(0x11, dev->membase+0x3d4);
pb = readb(dev->membase+0x3d5);
writeb(0x11, dev->membase+0x3d4);
writeb(pb | 0x20 , dev->membase+0x3d5);
}
void mm_enable_vsync(struct sh_pci_device *dev) {
int pb;
/* enable interrupt, clear pending */
writeb(0x11, dev->membase+0x3d4);
pb = readb(dev->membase+0x3d5);
writeb(0x11, dev->membase+0x3d4);
writeb((pb&0xcf) , dev->membase+0x3d5);
/* Allow interrupts */
writeb(0x11, dev->membase+0x3d4);
pb = readb(dev->membase+0x3d5);
writeb(0x11, dev->membase+0x3d4);
writeb(pb | 0x10 , dev->membase+0x3d5);
}
int s3_test_vsync(struct sh_pci_device *dev) {
return readl(dev->membase+0x8504) & 1;
}
void s3_enable_vsync(struct sh_pci_device *dev) {
writel(0x101, dev->membase+0x8504);
}
void s3_ack_vsync(struct sh_pci_device *dev) {
writel(0x001, dev->membase+0x8504);
}
static uint32_t saved_pmc=0xffffffff;
int nv3_test_vsync(struct sh_pci_device *dev) {
return readl(dev->membase+0x400100)&0x100;
}
void nv3_ack_vsync(struct sh_pci_device *dev) {
/* disable interrupt, clear pending */
writel(0xffffffff, dev->membase + 0x000100);
writel(0x100, dev->membase + 0x400100);
writel(0, dev->membase + 0x000140);
writel(0, dev->membase + 0x400140);
if(saved_pmc!=0xffffffff)
writel(saved_pmc, dev->membase + 0x000200);
}
void nv3_enable_vsync(struct sh_pci_device *dev) {
saved_pmc = inl(dev->iobase + 0x200);
writel(saved_pmc|0x1000, dev->membase+0x200);
writel(0x1, dev->membase + 0x000140);
writel(0x100, dev->membase + 0x400140);
writel(0xffffffff, dev->membase + 0x000100);
writel(0xffffffff, dev->membase + 0x400100);
}
int nv4_test_vsync(struct sh_pci_device *dev) {
return readl(dev->membase+0x600100)&0x1;
}
void nv4_ack_vsync(struct sh_pci_device *dev) {
/* disable interrupt, clear pending */
writel(0xffffffff, dev->membase + 0x000100);
writel(0x1, dev->membase + 0x600100);
writel(0, dev->membase + 0x000140);
writel(0, dev->membase + 0x600140);
writel(saved_pmc, dev->membase + 0x000200);
}
void nv4_enable_vsync(struct sh_pci_device *dev) {
saved_pmc = inl(dev->iobase + 0x200);
writel(saved_pmc|(1<<24),dev->membase+0x200);
writel(0x1, dev->membase + 0x000140);
writel(0x1, dev->membase + 0x600140);
writel(0xffffffff, dev->membase + 0x000100);
writel(0xffffffff, dev->membase + 0x600100);
}
int r128_test_vsync(struct sh_pci_device *dev) {
return readl(dev->membase + 0x44) &1;
}
void r128_ack_vsync(struct sh_pci_device *dev) {
writel(1, dev->membase + 0x44);
writel(readl(dev->membase + 0x40) & 0xfffffffe, dev->membase + 0x40);
}
void r128_enable_vsync(struct sh_pci_device *dev) {
writel(1, dev->membase + 0x44);
writel(readl(dev->membase + 0x40) | 1, dev->membase + 0x40);
}
int rage_test_vsync(struct sh_pci_device *dev) {
return inl(dev->iobase + 0x18) &4;
}
void rage_ack_vsync(struct sh_pci_device *dev) {
outl((inl(dev->iobase + 0x18) & 0xfffffff8) | 12, dev->iobase + 0x18);
}
void rage_enable_vsync(struct sh_pci_device *dev) {
outl((inl(dev->iobase + 0x18) & 0xfffffff8) | 14, dev->iobase + 0x18);
}
int rendition_test_vsync(struct sh_pci_device *dev) {
return inw(dev->iobase + 0x44) & 1;
}
void rendition_ack_vsync(struct sh_pci_device *dev) {
outw(1, dev->iobase + 0x44);
outw(0, dev->iobase + 0x46);
}
void rendition_enable_vsync(struct sh_pci_device *dev) {
outw(1, dev->iobase + 0x44);
outw(1, dev->iobase + 0x46);
}
void vga_init_vsync(struct sh_pci_device *dev) {
int i, id;
switch(dev->vendor) {
case PCI_VENDOR_ID_MATROX:
i=0;
if(dev->len[0]>=1048576)i=1;
dev->membase = ioremap(dev->mem[i],0x2000) + 0x1c00;
dev->test_vsync = mm_test_vsync;
dev->ack_vsync = mm_ack_vsync;
dev->enable_vsync = mm_enable_vsync;
dev->disable_vsync = mm_ack_vsync;
break;
case PCI_VENDOR_ID_SI: /* SiS */
dev->iobase = dev->mem[2]-0x380;
dev->test_vsync = io_test_vsync;
dev->ack_vsync = io_ack_vsync;
dev->enable_vsync = io_enable_vsync;
dev->disable_vsync = io_ack_vsync;
break;
case PCI_VENDOR_ID_NVIDIA_SGS:
dev->membase = ioremap(dev->mem[0],0x800000);
if(dev->id<0x20) {
dev->test_vsync = nv3_test_vsync;
dev->ack_vsync = nv3_ack_vsync;
dev->enable_vsync = nv3_enable_vsync;
dev->disable_vsync = nv3_ack_vsync;
} else {
dev->test_vsync = nv4_test_vsync;
dev->ack_vsync = nv4_ack_vsync;
dev->enable_vsync = nv4_enable_vsync;
dev->disable_vsync = nv4_ack_vsync;
}
break;
case PCI_VENDOR_ID_NVIDIA:
dev->membase = ioremap(dev->mem[0],0x800000);
dev->test_vsync = nv4_test_vsync;
dev->ack_vsync = nv4_ack_vsync;
dev->enable_vsync = nv4_enable_vsync;
dev->disable_vsync = nv4_ack_vsync;
break;
case PCI_VENDOR_ID_ATI:
id=dev->id;
if( (id==0x4c45) ||
(id==0x4c46) ||
(id==0x4c57) ||
(id==0x4c59) ||
(id==0x4c5a) ||
(id==0x4d46) ||
(id==0x4d4c) ||
(id==0x4242) ||
((id>>8)==0x50) ||
((id>>8)==0x51) ||
((id>>8)==0x52) ||
((id>>8)==0x53) ||
((id>>8)==0x54)) {
dev->membase = ioremap(dev->mem[2], 16384);
dev->test_vsync = r128_test_vsync;
dev->ack_vsync = r128_ack_vsync;
dev->enable_vsync = r128_enable_vsync;
dev->disable_vsync = r128_ack_vsync;
} else {
dev->iobase = dev->mem[1];
dev->test_vsync = rage_test_vsync;
dev->ack_vsync = rage_ack_vsync;
dev->enable_vsync = rage_enable_vsync;
dev->disable_vsync = rage_ack_vsync;
}
break;
case PCI_VENDOR_ID_RENDITION:
dev->iobase = dev->mem[1];
dev->test_vsync = rendition_test_vsync;
dev->ack_vsync = rendition_ack_vsync;
dev->enable_vsync = rendition_enable_vsync;
dev->disable_vsync = rendition_ack_vsync;
break;
case PCI_VENDOR_ID_S3:
dev->membase = ioremap(dev->mem[0]+0x1000000, 0x10000);
dev->test_vsync = s3_test_vsync;
dev->ack_vsync = s3_ack_vsync;
dev->enable_vsync = s3_enable_vsync;
dev->disable_vsync = s3_ack_vsync;
break;
default:
dev->test_vsync = vga_test_vsync;
dev->ack_vsync = vga_ack_vsync;
dev->enable_vsync = vga_enable_vsync;
dev->disable_vsync = vga_ack_vsync;
dev->iobase = 0;
}
}

View file

@ -0,0 +1,5 @@
void vga_init_vsync(struct sh_pci_device *);
int vga_test_vsync(struct sh_pci_device *);
void vga_ack_vsync(struct sh_pci_device *);
void vga_enable_vsync(struct sh_pci_device *);

View file

@ -0,0 +1,163 @@
#ifndef KERNEL_VERSION
# include <linux/version.h>
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
# ifdef KERNEL_2_6
# undef KERNEL_2_6
# endif
# define PCI_GET_CLASS pci_find_class
# define PCI_GET_DEVICE pci_find_device
# if defined (PG_chainlock)
# define my_io_remap_page_range(vma, start, ofs, len, prot) \
io_remap_page_range(vma,start,ofs,len,prot)
# else
# ifdef __alpha__ /* Is alpha really the issue here ??? */
# define my_io_remap_page_range(vma, start, ofs, len, prot) \
remap_page_range(start,ofs,len,prot)
# else
# define my_io_remap_page_range(vma, start, ofs, len, prot) \
io_remap_page_range(start,ofs,len,prot)
# endif
# endif
# ifndef IRQ_HANDLED
typedef void irqreturn_t;
# define IRQ_NONE
# define IRQ_HANDLED
# endif
#else /* Kernel 2.6 */
#define NO_TASK
# ifndef KERNEL_2_6
# define KERNEL_2_6
# endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
# undef MODULE_PARM
# define MODULE_PARM(x,y) module_param(x, int, 0)
#endif
/* WHY ? */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
# define PCI_GET_CLASS pci_find_class
# define PCI_GET_DEVICE pci_find_device
# define DEVFS_MK_SYMLINK(a,b) devfs_mk_symlink(a,b)
#else
# define PCI_GET_CLASS pci_get_class
# define PCI_GET_DEVICE pci_get_device
# define DEVFS_MK_SYMLINK(a,b)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
# define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#endif
# define my_io_remap_page_range(vma, start, ofs, len, prot) \
io_remap_page_range(vma,start,ofs,len,prot)
# define pci_present() 1
# ifdef CONFIG_DEVFS_FS
typedef void* devfs_handle_t;
# endif
#endif
/* These are also not present in 2.6 kernels ... */
#if (!defined _LINUX_DEVFS_FS_KERNEL_H) || (defined KERNEL_2_6)
static inline int devfs_register_chrdev (unsigned int major, const char *name,
struct file_operations *fops)
{
return register_chrdev (major, name, fops);
}
static inline int devfs_unregister_chrdev (unsigned int major,const char *name)
{
return unregister_chrdev (major, name);
}
#endif
#if defined(KERNEL_2_6) && !defined(CONFIG_DEVFS_FS)
# if !defined(CLASS_SIMPLE) /* no class_simple */
# define K_CLASS class
# define SLH_SYSFS_REGISTER \
svgalib_helper_class = class_create(THIS_MODULE, "svgalib_helper");
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
# define SLH_SYSFS_ADD_CONTROL \
class_device_create(svgalib_helper_class, \
MKDEV(SVGALIB_HELPER_MAJOR, 0), \
NULL, "svga");
# define SLH_SYSFS_ADD_DEVICE(_name, _minor) \
class_device_create(svgalib_helper_class, \
MKDEV(SVGALIB_HELPER_MAJOR, _minor), \
&sh_pci_devs[_minor]->dev->dev, _name);
#else /* 2.6.15 changed class_device_create */
# define SLH_SYSFS_ADD_CONTROL \
class_device_create(svgalib_helper_class, NULL, \
MKDEV(SVGALIB_HELPER_MAJOR, 0), \
NULL, "svga");
# define SLH_SYSFS_ADD_DEVICE(_name, _minor) \
class_device_create(svgalib_helper_class, NULL, \
MKDEV(SVGALIB_HELPER_MAJOR, _minor), \
&sh_pci_devs[_minor]->dev->dev, _name);
#endif /* 2.6.15 */
# define SLH_SYSFS_REMOVE_DEVICE(i) \
class_destroy(svgalib_helper_class);
# define SLH_SYSFS_UNREGISTER \
class_destroy(svgalib_helper_class);
# else /* class_simple */
# define K_CLASS class_simple
# define SLH_SYSFS_REGISTER \
svgalib_helper_class = class_simple_create(THIS_MODULE, "svgalib_helper");
# define SLH_SYSFS_ADD_CONTROL \
class_simple_device_add(svgalib_helper_class, \
MKDEV(SVGALIB_HELPER_MAJOR, 0), \
NULL, "svga");
# define SLH_SYSFS_ADD_DEVICE(_name, _minor) \
class_simple_device_add(svgalib_helper_class, \
MKDEV(SVGALIB_HELPER_MAJOR, _minor), \
&sh_pci_devs[_minor]->dev->dev, _name);
# define SLH_SYSFS_REMOVE_DEVICE(i) \
class_simple_device_remove(MKDEV(SVGALIB_HELPER_MAJOR, i));
# define SLH_SYSFS_UNREGISTER \
class_simple_destroy(svgalib_helper_class);
# endif /* class_simple */
#else
# define SLH_SYSFS_REGISTER
# define SLH_SYSFS_ADD_CONTROL
# define SLH_SYSFS_ADD_DEVICE(_name, _minor)
# define SLH_SYSFS_REMOVE_DEVICE(i)
# define SLH_SYSFS_UNREGISTER
#endif
#if (defined MINOR)
# define my_minor(x) MINOR(x)
#else
# define my_minor(x) minor(x)
#endif
#if !defined(MODULE_VERSION)
# define MODULE_VERSION(x)
#endif
#ifndef PCI_VENDOR_ID_RENDITION
#define PCI_VENDOR_ID_RENDITION 0x1163
#endif

View file

@ -0,0 +1,778 @@
#include <linux/config.h>
#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
# define MODVERSIONS
#endif
#include <linux/kernel.h> /* printk() */
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/stddef.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/mm.h>
#include <linux/thread_info.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/syscalls.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
asmlinkage long (*s_ioperm)(unsigned long from, unsigned long num, int turn_on);
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/segment.h> /* memcpy and such */
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include "kernel26compat.h"
#include "svgalib_helper.h"
#include "vgaversion.h"
#include "i810.h"
#include "interrupt.h"
#include "displaystart.h"
int debug=0;
static int all_devices=0;
int num_devices=0;
static char *sdev_id="svgalib_helper";
static struct sh_pci_device *sh_pci_devs[MAX_NR_DEVICES];
static int irqs[MAX_NR_DEVICES];
#if (defined CONFIG_DEVFS_FS) && (!defined KERNEL_2_6)
static devfs_handle_t devfs_handle;
#endif
#if defined(KERNEL_2_6) && !defined(CONFIG_DEVFS_FS)
struct K_CLASS *svgalib_helper_class;
#endif
static int check_io_range(int port, int device) {
return 1;
}
static struct pci_dev *get_pci_dev(int pcipos, int minor) {
if(minor>=num_devices) return NULL;
if(minor>0) {
return sh_pci_devs[minor]->dev;
} else {
if(pcipos>0 && pcipos<num_devices)
return sh_pci_devs[pcipos]->dev;
}
return NULL;
}
static int get_dev(int pcipos, int minor) {
if(minor>=num_devices) return 0;
if(minor>0) {
return minor;
} else {
if(pcipos>=num_devices || pcipos<1) return 0;
return pcipos;
}
}
static volatile int vsync=0;
static wait_queue_head_t vsync_wait;
static irqreturn_t vsync_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct sh_pci_device *dev = (struct sh_pci_device *)dev_id;
if((char *)dev==sdev_id) {
if(!vga_test_vsync(dev)) {
return IRQ_NONE;
}
vga_ack_vsync(dev);
vsync=0;
wake_up_interruptible(&vsync_wait);
} else {
if(!dev->test_vsync(dev)) {
return IRQ_NONE;
}
dev->ack_vsync(dev);
dev->vsync=0;
wake_up_interruptible(&dev->vsync_wait);
#ifndef NO_TASK
wake_up_interruptible(&dev->startad_wait);
#endif
}
return IRQ_HANDLED;
}
#ifndef NO_TASK
static void task_startad(void *data) {
struct sh_pci_device *dev = (struct sh_pci_device *)data;
int i;
i=dev->dev->irq;
dev->enable_vsync(dev);
interruptible_sleep_on(&dev->vsync_wait);
dev->ack_vsync(dev);
set_displaystart(dev);
dev->startad=-1;
}
#endif
#define GET_IOSTR \
get_user(iostr.port, &user_iostr->port); \
get_user(iostr.length, &user_iostr->length); \
get_user(iostr.string, &user_iostr->string);
#define GET_IOV \
get_user(iov.port, &user_iov->port); \
get_user(iov.val, &user_iov->val);
#define PUT_IOV \
put_user(iov.val, &user_iov->val);
#define GET_PCIV \
get_user(pciv.pcipos, &user_pciv->pcipos); \
get_user(pciv.address, &user_pciv->address); \
get_user(pciv.val, &user_pciv->val);
#define PUT_PCIV \
put_user(pciv.val, &user_pciv->val);
static int svgalib_helper_ioctl( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) {
io_t iov, *user_iov=(io_t *)arg;
pcic_t pciv, *user_pciv=(pcic_t *)arg;
int minor = my_minor(inode->i_rdev);
struct pci_dev *pdev;
io_string_t iostr, *user_iostr=(io_string_t *)arg;
int i=0, ret;
u8 pb;
u16 pw;
u32 pl;
unsigned char *outb_str;
if(_IOC_TYPE(cmd)!=SVGAHELPER_MAGIC) {
return -EINVAL;
}
ret=0;
switch(_IOC_NR(cmd)) {
case _IOC_NR(SVGAHELPER_REPOUTB):
GET_IOSTR;
if (iostr.length>4096) return -EINVAL;
if ( (outb_str = kmalloc(iostr.length, GFP_KERNEL )) == NULL ) return -ENOMEM;
if(copy_from_user(outb_str,iostr.string,iostr.length)) return -EPERM;
if(check_io_range(iostr.port,minor)) {
for(i=0; i<iostr.length; i++) outb(outb_str[i], iostr.port);
} else ret = -EPERM;
kfree (outb_str);
break;
case _IOC_NR(SVGAHELPER_OUTB):
GET_IOV;
if(check_io_range(iov.port,minor))
outb(iov.val,iov.port);
else ret = -EPERM;
break;
case _IOC_NR(SVGAHELPER_OUTW):
GET_IOV;
if(check_io_range(iov.port,minor))
outw(iov.val,iov.port);
else ret = -EPERM;
break;
case _IOC_NR(SVGAHELPER_OUTL):
GET_IOV;
if(check_io_range(iov.port,minor))
outl(iov.val,iov.port);
else ret = -EPERM;
break;
case _IOC_NR(SVGAHELPER_INB):
GET_IOV;
if(check_io_range(iov.port,minor))
iov.val=inb(iov.port);
else ret = -EPERM;
PUT_IOV;
break;
case _IOC_NR(SVGAHELPER_INW):
GET_IOV;
if(check_io_range(iov.port,minor))
iov.val=inw(iov.port);
else ret = -EPERM;
PUT_IOV;
break;
case _IOC_NR(SVGAHELPER_INL):
GET_IOV;
if(check_io_range(iov.port,minor))
iov.val=inl(iov.port);
else ret = -EPERM;
PUT_IOV;
break;
case _IOC_NR(SVGAHELPER_WRITEB):
GET_IOV;
writeb(iov.val,(u8 *)iov.port);
break;
case _IOC_NR(SVGAHELPER_WRITEW):
GET_IOV;
writew(iov.val,(u16 *)iov.port);
break;
case _IOC_NR(SVGAHELPER_WRITEL):
GET_IOV;
writel(iov.val,(u32 *)iov.port);
break;
case _IOC_NR(SVGAHELPER_READB):
GET_IOV;
iov.val=readb((u8 *)iov.port);
PUT_IOV;
break;
case _IOC_NR(SVGAHELPER_READW):
GET_IOV;
iov.val=readw((u16 *)iov.port);
PUT_IOV;
break;
case _IOC_NR(SVGAHELPER_READL):
GET_IOV;
iov.val=readl((u32 *)iov.port);
PUT_IOV;
break;
case _IOC_NR(SVGAHELPER_PCIINB):
GET_PCIV;
pdev = get_pci_dev(pciv.pcipos, minor);
if(!pdev) return -EINVAL;
pci_read_config_byte(pdev, pciv.address, &pb);
pciv.val=pb;
PUT_PCIV;
break;
case _IOC_NR(SVGAHELPER_PCIINW):
GET_PCIV;
pdev = get_pci_dev(pciv.pcipos, minor);
if(!pdev) return -EINVAL;
pci_read_config_word(pdev, pciv.address, &pw);
pciv.val=pw;
PUT_PCIV;
break;
case _IOC_NR(SVGAHELPER_PCIINL):
GET_PCIV;
pdev = get_pci_dev(pciv.pcipos, minor);
if(!pdev) return -EINVAL;
pci_read_config_dword(pdev, pciv.address, &pl);
pciv.val=pl;
PUT_PCIV;
break;
case _IOC_NR(SVGAHELPER_PCIAPLEN):
GET_PCIV;
i = get_dev(pciv.pcipos, minor);
if((i==0) | (pciv.address>5)) return -EINVAL;
pciv.val=sh_pci_devs[i]->len[pciv.address];
PUT_PCIV;
break;
case _IOC_NR(SVGAHELPER_PCIOUTB):
GET_PCIV;
pdev = get_pci_dev(pciv.pcipos, minor);
if(!pdev) return -EINVAL;
pb=pciv.val;
pci_write_config_byte(pdev, pciv.address, pb);
break;
case _IOC_NR(SVGAHELPER_PCIOUTW):
GET_PCIV;
pdev = get_pci_dev(pciv.pcipos, minor);
if(!pdev) return -EINVAL;
pw=pciv.val;
pci_write_config_word(pdev, pciv.address, pw);
break;
case _IOC_NR(SVGAHELPER_PCIOUTL):
GET_PCIV;
pdev = get_pci_dev(pciv.pcipos, minor);
if(!pdev) return -EINVAL;
pl=pciv.val;
pci_write_config_dword(pdev, pciv.address, pl);
break;
#ifdef __386__
case _IOC_NR(SVGAHELPER_I810GTT):
i=i810_make_gtt();
copy_to_user((char *)arg, &i, sizeof(unsigned int));
break;
case _IOC_NR(SVGAHELPER_I810GTTE):
copy_from_user(&i, (char *)arg, sizeof(unsigned int));
if(i<I810_SIZE)
copy_to_user((char *)arg, &i810_gttes[i], sizeof(unsigned long));
else return -EINVAL;
break;
#endif
case _IOC_NR(SVGAHELPER_WAITRETRACE):
/* Workaround for nvidia cards, which are not vga compatible */
// if(!minor && num_devices==2) minor=1;
if(minor) {
int i;
i=sh_pci_devs[minor]->dev->irq;
if(i==0 || i==-1 || i==255) return -EINVAL;
sh_pci_devs[minor]->vsync=1;
sh_pci_devs[minor]->enable_vsync(sh_pci_devs[minor]);
wait_event_interruptible(sh_pci_devs[minor]->vsync_wait,
!sh_pci_devs[minor]->vsync);
if(sh_pci_devs[minor]->vsync) sh_pci_devs[minor]->ack_vsync(sh_pci_devs[minor]);
if(sh_pci_devs[minor]->vsync) return -ERESTARTSYS;
} else {
int i;
vsync=1;
i=0;
while(irqs[i]!=-1)
request_irq(irqs[i++], vsync_interrupt, SA_SHIRQ, "svgalib_helper", sdev_id);
vga_enable_vsync((void *)sdev_id);
wait_event_interruptible(vsync_wait, !vsync);
i=0;
if(vsync) vga_ack_vsync((void *)sdev_id);
while(irqs[i]!=-1)
free_irq(irqs[i++], sdev_id);
if(vsync) return -ERESTARTSYS;
}
break;
#if 0
case _IOC_NR(SVGAHELPER_IOPERM):
if(minor) return -EPERM;
#if 1
i=0;
if(!capable(CAP_SYS_RAWIO)) {
i=1;
cap_raise(current->cap_effective, CAP_SYS_RAWIO);
}
s_ioperm=sys_call_table[__NR_ioperm];
s_ioperm(0,0x400,1);
if(i) {
cap_lower(current->cap_effective, CAP_SYS_RAWIO);
}
#else
if(!ioperm) {
struct thread_struct * t = &current->thread;
struct tss_struct * tss;
unsigned long *bitmap;
ioperm=1;
bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
memset(bitmap, 0, IO_BITMAP_BYTES);
t->io_bitmap_ptr = bitmap;
tss = &per_cpu(init_tss, get_cpu());
t->io_bitmap_max = IO_BITMAP_BYTES;
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
put_cpu();
}
#endif
break;
#endif
#ifndef NO_TASK
case _IOC_NR(SVGAHELPER_SETDISPLAYSTART):
if(minor) {
if(sh_pci_devs[minor]->startad==-1)
schedule_task(&sh_pci_devs[minor]->tq_startad);
sh_pci_devs[minor]->startad=arg;
}
break;
#endif
#ifdef SVGA_HELPER_VIRTUAL
case _IOC_NR(SVGAHELPER_VIRT_TO_PHYS):
return dhahelper_virt_to_phys((dhahelper_vmi_t *)arg);
case _IOC_NR(SVGAHELPER_VIRT_TO_BUS):
return dhahelper_virt_to_bus((dhahelper_vmi_t *)arg);
case _IOC_NR(SVGAHELPER_ALLOC_PA):
return dhahelper_alloc_pa((dhahelper_mem_t *)arg);
case _IOC_NR(SVGAHELPER_FREE_PA):
return dhahelper_free_pa((dhahelper_mem_t *)arg);
case _IOC_NR(SVGAHELPER_LOCK_MEM):
return dhahelper_lock_mem((dhahelper_mem_t *)arg);
case _IOC_NR(SVGAHELPER_UNLOCK_MEM):
return dhahelper_unlock_mem((dhahelper_mem_t *)arg);
default:
#endif
return -EINVAL;
}
return ret;
}
static int svgalib_helper_open( struct inode *inode, struct file * filp) {
int minor = my_minor(inode->i_rdev);
if(minor>=num_devices) return -ENODEV;
if(minor) {
int i=sh_pci_devs[minor]->dev->irq;
sh_pci_devs[minor]->opencount++;
if(sh_pci_devs[minor]->opencount==1 && i!=0 && i!=-1 && i!=255)
request_irq(i, vsync_interrupt, SA_SHIRQ, "svgalib_helper", sh_pci_devs[minor]);
}
#ifndef KERNEL_2_6
MOD_INC_USE_COUNT;
#else
try_module_get(THIS_MODULE);
#endif
return 0;
}
static int svgalib_helper_release( struct inode *inode, struct file *filp) {
int minor = my_minor(inode->i_rdev);
if(minor) {
int i=sh_pci_devs[minor]->dev->irq;
sh_pci_devs[minor]->opencount--;
if(sh_pci_devs[minor]->opencount==0 && i!=0 && i!=-1 && i!=255) {
sh_pci_devs[minor]->disable_vsync(sh_pci_devs[minor]);
free_irq(i, sh_pci_devs[minor]);
}
}
#ifndef KERNEL_2_6
MOD_DEC_USE_COUNT;
#else
module_put(THIS_MODULE);
#endif
return 0;
}
int remap_cache(struct vm_area_struct *vma, unsigned long off) {
vma->vm_pgoff = off >> PAGE_SHIFT;
/* This is an IO map - tell maydump to skip this VMA */
vma->vm_flags |= VM_IO;
#if defined(__sparc_v9__)
vma->vm_flags |= (VM_SHM | VM_LOCKED);
if (my_io_remap_page_range(vma, vma->vm_start, off,
vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))
return -EAGAIN;
#else
#if defined(__mc68000__)
#if defined(CONFIG_SUN3)
pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
#else
if (CPU_IS_020_OR_030)
pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
if (CPU_IS_040_OR_060) {
pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
/* Use no-cache mode, serialized */
pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
}
#endif
#elif defined(__powerpc__)
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
#elif defined(__alpha__)
/* Caching is off in the I/O space quadrant by design. */
#elif defined(__i386__) || defined(__x86_64__)
if (boot_cpu_data.x86 > 3)
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
#elif defined(__arm__) || defined(__mips__)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#elif defined(__sh__)
pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
#elif defined(__hppa__)
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
#elif defined(__ia64__)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
#else
#warning What do we have to do here??
#endif
if (my_io_remap_page_range(vma, vma->vm_start, off,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
#endif /* !__sparc_v9__ */
return 0;
}
int check_mem(int card, unsigned long start, unsigned long len) {
int j;
unsigned long rstart, rlen;
#ifdef __alpha__
int type;
#endif
if (start+len < start || len >= 0x40000000) return -3;
rstart=start;
rlen=len;
#ifdef __alpha__
type = start>>32;
switch(type) {
case 2:
start = start & 0xffffffff;
start = start >> 5;
len = len >> 5;
break;
case 3:
start = start & 0xffffffff;
break;
default:
return -1;
}
#endif
if(!card) {
if( (start<0x110000) && (start+len<0x110000) ) return 0;
for(j=1;j<num_devices;j++)
if(!check_mem(j, rstart, rlen)) return 0;
} else if(card<num_devices) {
for(j=0;j<6;j++) if(sh_pci_devs[card]->mem[j])
if((start>=sh_pci_devs[card]->mem[j])&&
(start+len<=sh_pci_devs[card]->mem[j]+sh_pci_devs[card]->len[j])) {
return 0;
}
}
return -2;
}
static int svgalib_helper_mmap(struct file *filp, struct vm_area_struct *vma) {
unsigned long start=vma->vm_start;
unsigned long end=vma->vm_end;
unsigned long minor = my_minor(filp->f_dentry->d_inode->i_rdev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
unsigned long ofs=vma->vm_pgoff*PAGE_SIZE;
#else
unsigned long ofs=vma->vm_offset;
#endif
if(check_mem(minor, ofs, end-start)) return -EPERM;
if(remap_cache(vma, ofs)) return -EAGAIN;
return 0;
}
struct file_operations svgalib_helper_fops = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
.owner = THIS_MODULE,
#endif
.ioctl = svgalib_helper_ioctl,
.mmap = svgalib_helper_mmap,
.open = svgalib_helper_open,
.release = svgalib_helper_release,
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
#define base_address(i) dev->resource[i].start
#else
#define base_address(i) (dev->base_address[i]&PCI_BASE_ADDRESS_MEM_MASK)
#endif
int init_module(void)
{
int result, i, j;
struct pci_dev *dev=NULL;
char name[255];
#ifdef CONFIG_DEVFS_FS
# ifndef KERNEL_2_6
devfs_handle_t slave_handle;
# endif
#endif
/*
* Register your major, and accept a dynamic number
*/
printk(KERN_INFO "svgalib_helper: Initializing, version %s\n", versionstr);
result = devfs_register_chrdev(SVGALIB_HELPER_MAJOR, "svgalib_helper", &svgalib_helper_fops);
if (result < 0) {
printk(KERN_WARNING "svgalib_helper: can't get major %d\n",SVGALIB_HELPER_MAJOR);
return result;
}
if((sh_pci_devs[0]=kmalloc(sizeof(struct sh_pci_device),GFP_KERNEL))==NULL) {
goto nomem_error;
}
memset(sh_pci_devs[0],0,sizeof(struct sh_pci_device));
num_devices=1;
for(i=1;i<MAX_NR_DEVICES;i++) sh_pci_devs[i]=NULL;
#ifdef CONFIG_DEVFS_FS
# ifndef KERNEL_2_6
devfs_handle = devfs_mk_dir ( NULL, "svga_helper", NULL );
devfs_register_series( devfs_handle,
"%u", 8, DEVFS_FL_DEFAULT, SVGALIB_HELPER_MAJOR, 0,
S_IFCHR | S_IRUGO | S_IRWXU, &svgalib_helper_fops, NULL ) ;
DEVFS_MK_SYMLINK( NULL, "svga", 0, "svga_helper/0", &slave_handle, NULL );
devfs_auto_unregister( devfs_handle, slave_handle );
# else
devfs_mk_dir ("svga_helper");
for (i = 0; i < 8; i++) {
devfs_mk_cdev(MKDEV(SVGALIB_HELPER_MAJOR, i),
S_IFCHR | S_IRUGO | S_IRWXU, "svga_helper/%d", i);
}
DEVFS_MK_SYMLINK("svga", "svga_helper/0");
# endif
#endif /* devfsd support */
SLH_SYSFS_REGISTER;
SLH_SYSFS_ADD_CONTROL;
if(pci_present()) {
while((dev= all_devices ?
PCI_GET_DEVICE(PCI_ANY_ID, PCI_ANY_ID, dev) :
PCI_GET_CLASS(PCI_CLASS_DISPLAY_VGA<<8,dev)) &&
(num_devices<=MAX_NR_DEVICES)) {
if((sh_pci_devs[num_devices]=kmalloc(sizeof(struct sh_pci_device),GFP_KERNEL))==NULL) {
goto nomem_error;
}
memset(sh_pci_devs[num_devices],0,sizeof(struct sh_pci_device));
sh_pci_devs[num_devices]->dev=dev;
pci_read_config_word(dev,0,&sh_pci_devs[num_devices]->vendor);
pci_read_config_word(dev,2,&sh_pci_devs[num_devices]->id);
pci_read_config_byte(dev,8,&sh_pci_devs[num_devices]->revision);
printk(KERN_DEBUG "svgalib_helper: device%d: vendor:%.4x id:%.4x\n",num_devices,
sh_pci_devs[num_devices]->vendor,sh_pci_devs[num_devices]->id);
for(i=0;i<6;i++){
unsigned int t;
int len;
pci_read_config_dword(dev,16+4*i,&result);
if(result) {
pci_write_config_dword(dev,16+4*i,0xffffffff);
pci_read_config_dword(dev,16+4*i,&t);
pci_write_config_dword(dev,16+4*i,result);
len = ~(t&~0xf)+1;
if (len){
sh_pci_devs[num_devices]->mem[i]=result&~0xf;
sh_pci_devs[num_devices]->flags[i]=0x80 | (result&0xf);
sh_pci_devs[num_devices]->len[i]=len;
sh_pci_devs[num_devices]->mask[i]=t&~0xf;
printk(KERN_DEBUG "device%d: region%d, base=%.8x len=%d type=%d\n",
num_devices,i, result&(~0xf), len, result&0xf);
}
}
}
vga_init_vsync(sh_pci_devs[num_devices]);
init_waitqueue_head(&sh_pci_devs[num_devices]->vsync_wait);
#ifndef NO_TASK
init_waitqueue_head(&sh_pci_devs[num_devices]->startad_wait);
sh_pci_devs[num_devices]->tq_startad.routine=task_startad;
sh_pci_devs[num_devices]->tq_startad.data=sh_pci_devs[num_devices];
sh_pci_devs[num_devices]->tq_startad.sync=0;
sh_pci_devs[num_devices]->startad=-1;
#endif
sh_pci_devs[num_devices]->opencount=0;
sprintf(name, "svga%d", num_devices);
SLH_SYSFS_ADD_DEVICE(name, num_devices);
num_devices++;
}
}
j=0;
for(i=1; i<num_devices;i++) {
int k, l;
k=sh_pci_devs[i]->dev->irq;
if(k>0 && k<255) {
for(l=0;l<j;l++) if(k==irqs[l])k=-1;
if(k>0) {
irqs[j]=k;
j++;
}
}
}
irqs[j]=-1;
init_waitqueue_head(&vsync_wait);
#ifndef KERNEL_2_6
EXPORT_NO_SYMBOLS;
#endif
return 0; /* succeed */
nomem_error:
for(i=0;i<MAX_NR_DEVICES;i++)
if(sh_pci_devs[i]) {
SLH_SYSFS_REMOVE_DEVICE(i);
kfree(sh_pci_devs[i]);
}
SLH_SYSFS_UNREGISTER;
devfs_unregister_chrdev(SVGALIB_HELPER_MAJOR, "svgalib_helper");
return result;
}
void cleanup_module(void)
{
int i;
for(i=0;i<MAX_NR_DEVICES;i++)
if(sh_pci_devs[i]) {
SLH_SYSFS_REMOVE_DEVICE(i);
kfree(sh_pci_devs[i]);
}
SLH_SYSFS_UNREGISTER;
#ifdef CONFIG_DEVFS_FS
# ifndef KERNEL_2_6
devfs_unregister(devfs_handle);
# else
for (i = 0; i < 8; i++)
devfs_remove("svga_helper/%d", i);
devfs_remove("svga_helper");
# endif
#endif
devfs_unregister_chrdev(SVGALIB_HELPER_MAJOR, "svgalib_helper");
}
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug output level.");
MODULE_PARM(all_devices, "i");
MODULE_PARM_DESC(all_devices, "Give access to all PCI devices, regardless of class.");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
MODULE_AUTHOR("Matan Ziv-Av <matan@svgalib.org>");
MODULE_DESCRIPTION("Generic hardware access to vga cards");

View file

@ -0,0 +1,117 @@
#ifndef SVGALIB_HELPER_H
#define SVGALIB_HELPER_H
#ifdef __KERNEL__
#define MAX_NR_DEVICES 15
#define address_t unsigned long
struct sh_pci_device {
unsigned short vendor;
unsigned short id;
unsigned char revision;
struct pci_dev *dev;
address_t mem[6];
address_t len[6];
address_t mask[6];
int flags[6];
unsigned long iobase;
u8 * membase;
int (*test_vsync)(struct sh_pci_device *);
void (*ack_vsync)(struct sh_pci_device *);
void (*enable_vsync)(struct sh_pci_device *);
void (*disable_vsync)(struct sh_pci_device *);
int opencount;
int vsync;
wait_queue_head_t vsync_wait;
#ifndef NO_TASK
wait_queue_head_t startad_wait;
long startad;
struct tq_struct tq_startad;
#endif
};
extern int debug;
#endif
typedef struct {
int port;
int length;
unsigned char* string;
} io_string_t;
typedef struct {
int port;
unsigned int val;
} io_t;
typedef struct {
int pcipos;
unsigned int address;
unsigned long val;
} pcic_t;
typedef struct {
void *win;
void *lfb;
} windowing_t;
typedef struct dhahelper_vmi_s
{
void * virtaddr;
unsigned long length;
unsigned long *realaddr;
}dhahelper_vmi_t;
typedef struct dhahelper_mem_s
{
void * addr;
unsigned long length;
}dhahelper_mem_t;
#define SVGAHELPER_MAGIC 0xB3
#define SVGAHELPER_OUTB _IOR(SVGAHELPER_MAGIC,1,io_t)
#define SVGAHELPER_OUTW _IOR(SVGAHELPER_MAGIC,2,io_t)
#define SVGAHELPER_OUTL _IOR(SVGAHELPER_MAGIC,3,io_t)
#define SVGAHELPER_INB _IOW(SVGAHELPER_MAGIC,4,io_t)
#define SVGAHELPER_INW _IOW(SVGAHELPER_MAGIC,5,io_t)
#define SVGAHELPER_INL _IOW(SVGAHELPER_MAGIC,6,io_t)
#define SVGAHELPER_PCIOUTB _IOR(SVGAHELPER_MAGIC,11,pcic_t)
#define SVGAHELPER_PCIOUTW _IOR(SVGAHELPER_MAGIC,12,pcic_t)
#define SVGAHELPER_PCIOUTL _IOR(SVGAHELPER_MAGIC,13,pcic_t)
#define SVGAHELPER_PCIINB _IOW(SVGAHELPER_MAGIC,14,pcic_t)
#define SVGAHELPER_PCIINW _IOW(SVGAHELPER_MAGIC,15,pcic_t)
#define SVGAHELPER_PCIINL _IOW(SVGAHELPER_MAGIC,16,pcic_t)
#define SVGAHELPER_PCIAPLEN _IOW(SVGAHELPER_MAGIC,17,pcic_t)
#define SVGAHELPER_DVMA _IO(SVGAHELPER_MAGIC,7)
#define SVGAHELPER_WIND _IOR(SVGAHELPER_MAGIC,8,windowing_t)
#define SVGAHELPER_IOPERM _IO(SVGAHELPER_MAGIC,9)
#define SVGAHELPER_REPOUTB _IOR(SVGAHELPER_MAGIC,10,io_t)
#define SVGAHELPER_I810GTT _IOW(SVGAHELPER_MAGIC,128,unsigned int *)
#define SVGAHELPER_I810GTTE _IOW(SVGAHELPER_MAGIC,129,unsigned int *)
#define SVGAHELPER_WRITEB _IOR(SVGAHELPER_MAGIC,21,io_t)
#define SVGAHELPER_WRITEW _IOR(SVGAHELPER_MAGIC,22,io_t)
#define SVGAHELPER_WRITEL _IOR(SVGAHELPER_MAGIC,23,io_t)
#define SVGAHELPER_READB _IOW(SVGAHELPER_MAGIC,24,io_t)
#define SVGAHELPER_READW _IOW(SVGAHELPER_MAGIC,25,io_t)
#define SVGAHELPER_READL _IOW(SVGAHELPER_MAGIC,26,io_t)
#define SVGAHELPER_WAITRETRACE _IO(SVGAHELPER_MAGIC,31)
#define SVGAHELPER_SETDISPLAYSTART _IOR(SVGAHELPER_MAGIC,32, int)
#define SVGAHELPER_VIRT_TO_PHYS _IOWR(SVGAHELPER_MAGIC, 40, dhahelper_vmi_t)
#define SVGAHELPER_VIRT_TO_BUS _IOWR(SVGAHELPER_MAGIC, 41, dhahelper_vmi_t)
#define SVGAHELPER_ALLOC_PA _IOWR(SVGAHELPER_MAGIC, 42, dhahelper_mem_t)
#define SVGAHELPER_FREE_PA _IOWR(SVGAHELPER_MAGIC, 43, dhahelper_mem_t)
#define SVGAHELPER_LOCK_MEM _IOWR(SVGAHELPER_MAGIC, 44, dhahelper_mem_t)
#define SVGAHELPER_UNLOCK_MEM _IOWR(SVGAHELPER_MAGIC, 45, dhahelper_mem_t)
#endif /* SVGALIB_HELPER_H */

View file

@ -0,0 +1,2 @@
int vga_version=0x1925;
static char versionstr[32]="1.9.25";

View file

@ -0,0 +1,358 @@
#ifdef SVGA_HELPER_VIRTUAL
#include <linux/version.h>
#include <asm/uaccess.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/segment.h> /* memcpy and such */
#include <asm/io.h>
#include <asm/pgtable.h>
#include <linux/pagemap.h>
#include <linux/wrapper.h>
#include "svgalib_helper.h"
/*******************************/
/* Memory management functions */
/* from kernel:/drivers/media/video/bttv-driver.c */
/*******************************/
#define MDEBUG(x) do { } while(0) /* Debug memory management */
/* [DaveM] I've recoded most of this so that:
* 1) It's easier to tell what is happening
* 2) It's more portable, especially for translating things
* out of vmalloc mapped areas in the kernel.
* 3) Less unnecessary translations happen.
*
* The code used to assume that the kernel vmalloc mappings
* existed in the page tables of every process, this is simply
* not guarenteed. We now use pgd_offset_k which is the
* defined way to get at the kernel page tables.
*/
/* Given PGD from the address space's page table, return the kernel
* virtual mapping of the physical memory mapped at ADR.
*/
static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
{
unsigned long ret = 0UL;
pmd_t *pmd;
pte_t *ptep, pte;
if (!pgd_none(*pgd)) {
pmd = pmd_offset(pgd, adr);
if (!pmd_none(*pmd)) {
ptep = pte_offset(pmd, adr);
pte = *ptep;
if(pte_present(pte)) {
ret = (unsigned long) page_address(pte_page(pte));
ret |= (adr & (PAGE_SIZE - 1));
}
}
}
MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
return ret;
}
static inline unsigned long uvirt_to_bus(unsigned long adr)
{
unsigned long kva, ret;
kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
ret = virt_to_bus((void *)kva);
MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
return ret;
}
static inline unsigned long uvirt_to_pa(unsigned long adr)
{
unsigned long kva, ret;
kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
ret = virt_to_phys((void *)kva);
MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
return ret;
}
static inline unsigned long kvirt_to_bus(unsigned long adr)
{
unsigned long va, kva, ret;
va = VMALLOC_VMADDR(adr);
kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = virt_to_bus((void *)kva);
MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
return ret;
}
/* Here we want the physical address of the memory.
* This is used when initializing the contents of the
* area and marking the pages as reserved.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
unsigned long va, kva, ret;
va = VMALLOC_VMADDR(adr);
kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = __pa(kva);
MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
return ret;
}
static void * rvmalloc(signed long size)
{
void * mem;
unsigned long adr, page;
mem=vmalloc_32(size);
if (mem)
{
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr=(unsigned long) mem;
while (size > 0)
{
page = kvirt_to_pa(adr);
mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
}
return mem;
}
static int pag_lock(unsigned long addr)
{
unsigned long page;
unsigned long kva;
kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr);
if(kva)
{
lock_it:
page = uvirt_to_pa((unsigned long)addr);
LockPage(virt_to_page(__va(page)));
SetPageReserved(virt_to_page(__va(page)));
}
else
{
copy_from_user(&page,(char *)addr,1); /* try access it */
kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr);
if(kva) goto lock_it;
else return EPERM;
}
return 0;
}
static int pag_unlock(unsigned long addr)
{
unsigned long page;
unsigned long kva;
kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr);
if(kva)
{
page = uvirt_to_pa((unsigned long)addr);
UnlockPage(virt_to_page(__va(page)));
ClearPageReserved(virt_to_page(__va(page)));
return 0;
}
return EPERM;
}
static void rvfree(void * mem, signed long size)
{
unsigned long adr, page;
if (mem)
{
adr=(unsigned long) mem;
while (size > 0)
{
page = kvirt_to_pa(adr);
mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
vfree(mem);
}
}
int dhahelper_virt_to_phys(dhahelper_vmi_t *arg)
{
dhahelper_vmi_t mem;
unsigned long i,nitems;
char *addr;
if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
return -EFAULT;
}
nitems = mem.length / PAGE_SIZE;
if(mem.length % PAGE_SIZE) nitems++;
addr = mem.virtaddr;
for(i=0;i<nitems;i++)
{
unsigned long result;
result = uvirt_to_pa((unsigned long)addr);
if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
return -EFAULT;
}
addr += PAGE_SIZE;
}
return 0;
}
int dhahelper_virt_to_bus(dhahelper_vmi_t *arg)
{
dhahelper_vmi_t mem;
unsigned long i,nitems;
char *addr;
if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
return -EFAULT;
}
nitems = mem.length / PAGE_SIZE;
if(mem.length % PAGE_SIZE) nitems++;
addr = mem.virtaddr;
for(i=0;i<nitems;i++)
{
unsigned long result;
result = uvirt_to_bus((unsigned long)addr);
if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
return -EFAULT;
}
addr += PAGE_SIZE;
}
return 0;
}
int dhahelper_alloc_pa(dhahelper_mem_t *arg)
{
dhahelper_mem_t mem;
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
return -EFAULT;
}
mem.addr = rvmalloc(mem.length);
if (copy_to_user(arg, &mem, sizeof(dhahelper_mem_t)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
return -EFAULT;
}
return 0;
}
int dhahelper_free_pa(dhahelper_mem_t *arg)
{
dhahelper_mem_t mem;
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
return -EFAULT;
}
rvfree(mem.addr,mem.length);
return 0;
}
int dhahelper_lock_mem(dhahelper_mem_t *arg)
{
dhahelper_mem_t mem;
int retval;
unsigned long i,nitems,addr;
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
return -EFAULT;
}
nitems = mem.length / PAGE_SIZE;
if(mem.length % PAGE_SIZE) nitems++;
addr = (unsigned long)mem.addr;
for(i=0;i<nitems;i++)
{
retval = pag_lock((unsigned long)addr);
if(retval)
{
unsigned long j;
addr = (unsigned long)mem.addr;
for(j=0;j<i;j++)
{
pag_unlock(addr);
addr += PAGE_SIZE;
}
return retval;
}
addr += PAGE_SIZE;
}
return 0;
}
int dhahelper_unlock_mem(dhahelper_mem_t *arg)
{
dhahelper_mem_t mem;
int retval;
unsigned long i,nitems,addr;
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
{
if (debug > 0)
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
return -EFAULT;
}
nitems = mem.length / PAGE_SIZE;
if(mem.length % PAGE_SIZE) nitems++;
addr = (unsigned long)mem.addr;
for(i=0;i<nitems;i++)
{
retval = pag_unlock((unsigned long)addr);
if(retval) return retval;
addr += PAGE_SIZE;
}
return 0;
}
static int dhahelper_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
if (debug > 1)
printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n",
cmd, arg);
if (MINOR(inode->i_rdev) != 0)
return -ENXIO;
switch(cmd)
{
case DHAHELPER_GET_VERSION: return dhahelper_get_version((int *)arg);
case DHAHELPER_PORT: return dhahelper_port((dhahelper_port_t *)arg);
case DHAHELPER_VIRT_TO_PHYS:return dhahelper_virt_to_phys((dhahelper_vmi_t *)arg);
case DHAHELPER_VIRT_TO_BUS: return dhahelper_virt_to_bus((dhahelper_vmi_t *)arg);
case DHAHELPER_ALLOC_PA:return dhahelper_alloc_pa((dhahelper_mem_t *)arg);
case DHAHELPER_FREE_PA: return dhahelper_free_pa((dhahelper_mem_t *)arg);
case DHAHELPER_LOCK_MEM: return dhahelper_lock_mem((dhahelper_mem_t *)arg);
case DHAHELPER_UNLOCK_MEM: return dhahelper_unlock_mem((dhahelper_mem_t *)arg);
default:
if (debug > 0)
printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd);
return -EINVAL;
}
return 0;
}
#endif