Initial. Don't... just don't ask.
This commit is contained in:
commit
00bae13bba
586 changed files with 129057 additions and 0 deletions
66
kernel/svgalib_helper/Makefile
Normal file
66
kernel/svgalib_helper/Makefile
Normal 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)
|
||||
|
||||
84
kernel/svgalib_helper/Makefile.alt
Normal file
84
kernel/svgalib_helper/Makefile.alt
Normal 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
|
||||
108
kernel/svgalib_helper/displaystart.c
Normal file
108
kernel/svgalib_helper/displaystart.c
Normal 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
|
||||
2
kernel/svgalib_helper/displaystart.h
Normal file
2
kernel/svgalib_helper/displaystart.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
void set_displaystart(struct sh_pci_device *);
|
||||
|
||||
9
kernel/svgalib_helper/dkms.conf
Normal file
9
kernel/svgalib_helper/dkms.conf
Normal 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"
|
||||
66
kernel/svgalib_helper/i810.c
Normal file
66
kernel/svgalib_helper/i810.c
Normal 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
|
||||
6
kernel/svgalib_helper/i810.h
Normal file
6
kernel/svgalib_helper/i810.h
Normal 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];
|
||||
|
||||
309
kernel/svgalib_helper/interrupt.c
Normal file
309
kernel/svgalib_helper/interrupt.c
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
5
kernel/svgalib_helper/interrupt.h
Normal file
5
kernel/svgalib_helper/interrupt.h
Normal 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 *);
|
||||
|
||||
163
kernel/svgalib_helper/kernel26compat.h
Normal file
163
kernel/svgalib_helper/kernel26compat.h
Normal 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
|
||||
778
kernel/svgalib_helper/main.c
Normal file
778
kernel/svgalib_helper/main.c
Normal 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 = ¤t->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");
|
||||
117
kernel/svgalib_helper/svgalib_helper.h
Normal file
117
kernel/svgalib_helper/svgalib_helper.h
Normal 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 */
|
||||
2
kernel/svgalib_helper/vgaversion.h
Normal file
2
kernel/svgalib_helper/vgaversion.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
int vga_version=0x1925;
|
||||
static char versionstr[32]="1.9.25";
|
||||
358
kernel/svgalib_helper/virtual.c
Normal file
358
kernel/svgalib_helper/virtual.c
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue