Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bbb4f20 authored by Thomas Winischhofer's avatar Thomas Winischhofer Committed by Greg Kroah-Hartman
Browse files

[PATCH] USB: sisusb[vga] update



here is a new and extended version of the sisusbvga (previously: sisusb)
driver. The patch is against 2.6.13 and updates the driver to version 0.0.8.

Additions include complete VGA/EGA text console support and a build-in
display mode infrastructure for userland applications that don't know
 about the graphics internals.

Fixes include some BE/LE issues and a get/put_dev bug in the previous
version.

Other changes include a change of the module name from "sisusb" to
"sisusbvga". The previous one was too generic IMHO.

Please note that the patch also affects the Makefile in
drivers/video/console as the driver requires the VGA 8x16 font in case
the text console part is selected.

Heavily tested, as usual. Please apply.

One thing though: I already prepared for removal of the "mode" field and
the changed "name" field in the usb_class_driver structure. This will
perhaps need some refinement depending on whether you/Linus merge the
respective core changes before or after 2.6.14.

Signed-off-by: default avatarThomas Winischhofer <thomas@winischhofer.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 80908309
Loading
Loading
Loading
Loading
+37 −5
Original line number Original line Diff line number Diff line
@@ -9,6 +9,38 @@ config USB_SISUSBVGA
	  Note that this device requires a USB 2.0 host controller. It will not
	  Note that this device requires a USB 2.0 host controller. It will not
	  work with USB 1.x controllers.
	  work with USB 1.x controllers.


	  To compile this driver as a module, choose M here: the module will be
	  To compile this driver as a module, choose M here; the module will be
	  called sisusb.  If unsure, say N.
	  called sisusbvga. If unsure, say N.

config USB_SISUSBVGA_CON
	bool "Text console and mode switching support" if USB_SISUSBVGA
	depends on VT
	select FONT_8x16
	---help---
	  Say Y here if you want a VGA text console via the USB dongle or
	  want to support userland applications that utilize the driver's
	  display mode switching capabilities.

	  Note that this console supports VGA/EGA text mode only.

	  By default, the console part of the driver will not kick in when
	  the driver is initialized. If you want the driver to take over
	  one or more of the consoles, you need to specify the number of
	  the first and last consoles (starting at 1) as driver parameters.

	  For example, if the driver is compiled as a module:

	     modprobe sisusbvga first=1 last=5

	  If you use hotplug, add this to your modutils config files with
	  the "options" keyword, such as eg.

	     options sisusbvga first=1 last=5

	  If the driver is compiled into the kernel image, the parameters
	  must be given in the kernel command like, such as

	     sisusbvga.first=1 sisusbvga.last=5


+3 −1
Original line number Original line Diff line number Diff line
@@ -2,5 +2,7 @@
# Makefile for the sisusb driver (if driver is inside kernel tree).
# Makefile for the sisusb driver (if driver is inside kernel tree).
#
#


obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o

sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
+426 −37
Original line number Original line Diff line number Diff line
/*
/*
 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
 *
 *
 * Main part
 *
 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
 *
 *
 * If distributed as part of the Linux kernel, this code is licensed under the
 * If distributed as part of the Linux kernel, this code is licensed under the
@@ -48,16 +50,60 @@
#include <linux/kref.h>
#include <linux/kref.h>
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>


#include "sisusb.h"
#include "sisusb.h"


#ifdef INCL_SISUSB_CON
#include <linux/font.h>
#endif

#define SISUSB_DONTSYNC
#define SISUSB_DONTSYNC


/* Forward declarations / clean-up routines */
/* Forward declarations / clean-up routines */


#ifdef INCL_SISUSB_CON
int	sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
int	sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
int	sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
int	sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
int	sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,	u8 myand, u8 myor);
int	sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
int	sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);

int	sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
int	sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
int	sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
int	sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
int	sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
			u32 dest, int length, size_t *bytes_written);

int	sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);

extern int  SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
extern int  SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);

extern void sisusb_init_concode(void);
extern int  sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);

extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);

extern int  sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
		u8 *arg, int cmapsz, int ch512, int dorecalc,
		struct vc_data *c, int fh, int uplock);

static int sisusb_first_vc = 0;
static int sisusb_last_vc = 0;
module_param_named(first, sisusb_first_vc, int, 0);
module_param_named(last, sisusb_last_vc, int, 0);
MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
#endif

static struct usb_driver sisusb_driver;
static struct usb_driver sisusb_driver;


static DECLARE_MUTEX(disconnect_sem);
DECLARE_MUTEX(disconnect_sem);


static void
static void
sisusb_free_buffers(struct sisusb_usb_data *sisusb)
sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -639,7 +685,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,


/* The following routines assume being used to transfer byte, word,
/* The following routines assume being used to transfer byte, word,
 * long etc.
 * long etc.
 * This means that they assume "data" in machine endianness format.
 * This means that
 *   - the write routines expect "data" in machine endianness format.
 *     The data will be converted to leXX in sisusb_xxx_packet.
 *   - the read routines can expect read data in machine-endianess.
 */
 */


static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
@@ -839,7 +888,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
				if (get_user(swap16, (u16 __user *)userbuffer))
				if (get_user(swap16, (u16 __user *)userbuffer))
					return -EFAULT;
					return -EFAULT;
			} else
			} else
				swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
				swap16 = *((u16 *)kernbuffer);


			ret = sisusb_write_memio_word(sisusb,
			ret = sisusb_write_memio_word(sisusb,
							SISUSB_TYPE_MEM,
							SISUSB_TYPE_MEM,
@@ -855,14 +904,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
			if (userbuffer) {
			if (userbuffer) {
				if (copy_from_user(&buf, userbuffer, 3))
				if (copy_from_user(&buf, userbuffer, 3))
					return -EFAULT;
					return -EFAULT;

#ifdef __BIG_ENDIAN
				swap32 = (buf[0] << 16) |
				swap32 = (buf[0] << 16) |
					 (buf[1] <<  8) |
					 (buf[1] <<  8) |
					 buf[2];
					 buf[2];
#else
				swap32 = (buf[2] << 16) |
					 (buf[1] <<  8) |
					 buf[0];
#endif
			} else
			} else
#ifdef __BIG_ENDIAN
				swap32 = (kernbuffer[0] << 16) |
				swap32 = (kernbuffer[0] << 16) |
					 (kernbuffer[1] <<  8) |
					 (kernbuffer[1] <<  8) |
					 kernbuffer[2];
					 kernbuffer[2];
#else
				swap32 = (kernbuffer[2] << 16) |
					 (kernbuffer[1] <<  8) |
					 kernbuffer[0];
#endif


			ret = sisusb_write_memio_24bit(sisusb,
			ret = sisusb_write_memio_24bit(sisusb,
							SISUSB_TYPE_MEM,
							SISUSB_TYPE_MEM,
@@ -879,10 +939,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
				if (get_user(swap32, (u32 __user *)userbuffer))
				if (get_user(swap32, (u32 __user *)userbuffer))
					return -EFAULT;
					return -EFAULT;
			} else
			} else
				swap32 = (kernbuffer[0] << 24) |
				swap32 = *((u32 *)kernbuffer);
					 (kernbuffer[1] << 16) |
					 (kernbuffer[2] <<  8) |
					 kernbuffer[3];


			ret = sisusb_write_memio_long(sisusb,
			ret = sisusb_write_memio_long(sisusb,
							SISUSB_TYPE_MEM,
							SISUSB_TYPE_MEM,
@@ -1005,6 +1062,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
	return ret ? -EIO : 0;
	return ret ? -EIO : 0;
}
}


/* Remember: Read data in packet is in machine-endianess! So for
 * byte, word, 24bit, long no endian correction is necessary.
 */

static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
							u32 addr, u8 *data)
							u32 addr, u8 *data)
{
{
@@ -1191,8 +1252,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
						(u16 __user *)userbuffer))
						(u16 __user *)userbuffer))
						return -EFAULT;
						return -EFAULT;
				} else {
				} else {
					kernbuffer[0] = swap16 >> 8;
					*((u16 *)kernbuffer) = swap16;
					kernbuffer[1] = swap16 & 0xff;
				}
				}
			}
			}
			return ret;
			return ret;
@@ -1202,9 +1262,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
								addr, &swap32);
								addr, &swap32);
			if (!ret) {
			if (!ret) {
				(*bytes_read) += 3;
				(*bytes_read) += 3;
#ifdef __BIG_ENDIAN
				buf[0] = (swap32 >> 16) & 0xff;
				buf[0] = (swap32 >> 16) & 0xff;
				buf[1] = (swap32 >> 8) & 0xff;
				buf[1] = (swap32 >> 8) & 0xff;
				buf[2] = swap32 & 0xff;
				buf[2] = swap32 & 0xff;
#else
				buf[2] = (swap32 >> 16) & 0xff;
				buf[1] = (swap32 >> 8) & 0xff;
				buf[0] = swap32 & 0xff;
#endif
				if (userbuffer) {
				if (userbuffer) {
					if (copy_to_user(userbuffer, &buf[0], 3))
					if (copy_to_user(userbuffer, &buf[0], 3))
						return -EFAULT;
						return -EFAULT;
@@ -1228,10 +1294,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,


					userbuffer += 4;
					userbuffer += 4;
				} else {
				} else {
					kernbuffer[0] = (swap32 >> 24) & 0xff;
					*((u32 *)kernbuffer) = swap32;
					kernbuffer[1] = (swap32 >> 16) & 0xff;
					kernbuffer[2] = (swap32 >> 8) & 0xff;
					kernbuffer[3] = swap32 & 0xff;
					kernbuffer += 4;
					kernbuffer += 4;
				}
				}
				addr += 4;
				addr += 4;
@@ -1289,7 +1352,24 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,


/* High level: Gfx (indexed) register access */
/* High level: Gfx (indexed) register access */


static int
#ifdef INCL_SISUSB_CON
int
sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
{
	return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
}

int
sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
{
	return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
}
#endif

#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
{
{
	int ret;
	int ret;
@@ -1298,7 +1378,10 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
	return ret;
	return ret;
}
}


static int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
{
{
	int ret;
	int ret;
@@ -1307,7 +1390,10 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
	return ret;
	return ret;
}
}


static int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
							u8 myand, u8 myor)
							u8 myand, u8 myor)
{
{
@@ -1336,18 +1422,89 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
	return ret;
	return ret;
}
}


static int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
{
{
	return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
	return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
}
}


static int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
{
{
	return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
	return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
}
}


/* Write/read video ram */

#ifdef INCL_SISUSB_CON
int
sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
{
	return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
}

int
sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
{
	return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
}

int
sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
{
	return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
}

int
sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
{
	return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
}

int
sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
			u32 dest, int length, size_t *bytes_written)
{
	return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
}

#ifdef SISUSBENDIANTEST
int
sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
			u32 src, int length, size_t *bytes_written)
{
	return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
}
#endif
#endif

#ifdef SISUSBENDIANTEST
static void
sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
{
    static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
    char destbuffer[10];
    size_t dummy;
    int i,j;

    sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);

    for(i = 1; i <= 7; i++) {
        printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
	sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
	for(j = 0; j < i; j++) {
	     printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
	}
    }
}
#endif

/* access pci config registers (reg numbers 0, 4, 8, etc) */
/* access pci config registers (reg numbers 0, 4, 8, etc) */


static int
static int
@@ -2270,6 +2427,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
	return ret;
	return ret;
}
}



#ifdef INCL_SISUSB_CON

/* Set up default text mode:
   - Set text mode (0x03)
   - Upload default font
   - Upload user font (if available)
*/

int
sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
{
	int ret = 0, slot = sisusb->font_slot, i;
	struct font_desc *myfont;
	u8 *tempbuf;
	u16 *tempbufb;
	size_t written;
	static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
	static char bootlogo[] = "(o_ //\\ V_/_";

	/* sisusb->lock is down */

	if (!sisusb->SiS_Pr)
		return 1;

	sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
	sisusb->SiS_Pr->sisusb = (void *)sisusb;

	/* Set mode 0x03 */
	SiSUSBSetMode(sisusb->SiS_Pr, 0x03);

	if (!(myfont = find_font("VGA8x16")))
		return 1;

	if (!(tempbuf = vmalloc(8192)))
		return 1;

	for (i = 0; i < 256; i++)
		memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);

	/* Upload default font */
	ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);

	vfree(tempbuf);

	/* Upload user font (and reset current slot) */
	if (sisusb->font_backup) {
		ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
				8192, sisusb->font_backup_512, 1, NULL,
				sisusb->font_backup_height, 0);
		if (slot != 2)
			sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
					NULL, 16, 0);
	}

	if (init && !sisusb->scrbuf) {

		if ((tempbuf = vmalloc(8192))) {

			i = 4096;
			tempbufb = (u16 *)tempbuf;
			while (i--)
				*(tempbufb++) = 0x0720;

			i = 0;
			tempbufb = (u16 *)tempbuf;
			while (bootlogo[i]) {
				*(tempbufb++) = 0x0700 | bootlogo[i++];
				if (!(i % 4))
					tempbufb += 76;
			}

			i = 0;
			tempbufb = (u16 *)tempbuf + 6;
			while (bootstring[i])
				*(tempbufb++) = 0x0700 | bootstring[i++];

			ret |= sisusb_copy_memory(sisusb, tempbuf,
				sisusb->vrambase, 8192, &written);

			vfree(tempbuf);

		}

	} else if (sisusb->scrbuf) {

		ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
				sisusb->vrambase, sisusb->scrbuf_size, &written);

	}

	if (sisusb->sisusb_cursor_size_from >= 0 &&
	    sisusb->sisusb_cursor_size_to >= 0) {
		sisusb_setidxreg(sisusb, SISCR, 0x0a,
				sisusb->sisusb_cursor_size_from);
		sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
				sisusb->sisusb_cursor_size_to);
	} else {
		sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
		sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
		sisusb->sisusb_cursor_size_to = -1;
	}

	slot = sisusb->sisusb_cursor_loc;
	if(slot < 0) slot = 0;

	sisusb->sisusb_cursor_loc = -1;
	sisusb->bad_cursor_pos = 1;

	sisusb_set_cursor(sisusb, slot);

	sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
	sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));

	sisusb->textmodedestroyed = 0;

	/* sisusb->lock is down */

	return ret;
}

#endif

/* fops */
/* fops */


static int
static int
@@ -2329,7 +2609,7 @@ sisusb_open(struct inode *inode, struct file *file)
		}
		}
	}
	}


	/* increment usage count for the device */
	/* Increment usage count for our sisusb */
	kref_get(&sisusb->kref);
	kref_get(&sisusb->kref);


	sisusb->isopen = 1;
	sisusb->isopen = 1;
@@ -2340,12 +2620,10 @@ sisusb_open(struct inode *inode, struct file *file)


	up(&disconnect_sem);
	up(&disconnect_sem);


	printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);

	return 0;
	return 0;
}
}


static void
void
sisusb_delete(struct kref *kref)
sisusb_delete(struct kref *kref)
{
{
	struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
	struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2637,9 @@ sisusb_delete(struct kref *kref)
	sisusb->sisusb_dev = NULL;
	sisusb->sisusb_dev = NULL;
	sisusb_free_buffers(sisusb);
	sisusb_free_buffers(sisusb);
	sisusb_free_urbs(sisusb);
	sisusb_free_urbs(sisusb);
#ifdef INCL_SISUSB_CON
	kfree(sisusb->SiS_Pr);
#endif
	kfree(sisusb);
	kfree(sisusb);
}
}


@@ -2395,8 +2676,6 @@ sisusb_release(struct inode *inode, struct file *file)


	up(&disconnect_sem);
	up(&disconnect_sem);


	printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);

	return 0;
	return 0;
}
}


@@ -2733,6 +3012,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
	int 	retval, port, length;
	int 	retval, port, length;
	u32	address;
	u32	address;


	/* All our commands require the device
	 * to be initialized.
	 */
	if (!sisusb->devinit)
		return -ENODEV;

	port = y->data3 -
	port = y->data3 -
		SISUSB_PCI_PSEUDO_IOPORTBASE +
		SISUSB_PCI_PSEUDO_IOPORTBASE +
		SISUSB_PCI_IOPORTBASE;
		SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +3059,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
			break;
			break;


		case SUCMD_CLRSCR:
		case SUCMD_CLRSCR:
			/* Gfx core must be initialized */
			if (!sisusb->gfxinit)
				return -ENODEV;

			length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
			length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
			address = y->data3 -
			address = y->data3 -
				SISUSB_PCI_PSEUDO_MEMBASE +
				SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,6 +3070,56 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
			retval = sisusb_clear_vram(sisusb, address, length);
			retval = sisusb_clear_vram(sisusb, address, length);
			break;
			break;


		case SUCMD_HANDLETEXTMODE:
			retval = 0;
#ifdef INCL_SISUSB_CON
			/* Gfx core must be initialized, SiS_Pr must exist */
			if (!sisusb->gfxinit || !sisusb->SiS_Pr)
				return -ENODEV;

			switch (y->data0) {
			case 0:
				retval = sisusb_reset_text_mode(sisusb, 0);
				break;
			case 1:
				sisusb->textmodedestroyed = 1;
				break;
			}
#endif
			break;

#ifdef INCL_SISUSB_CON
		case SUCMD_SETMODE:
			/* Gfx core must be initialized, SiS_Pr must exist */
			if (!sisusb->gfxinit || !sisusb->SiS_Pr)
				return -ENODEV;

			retval = 0;

			sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
			sisusb->SiS_Pr->sisusb = (void *)sisusb;

			if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
				retval = -EINVAL;

			break;

		case SUCMD_SETVESAMODE:
			/* Gfx core must be initialized, SiS_Pr must exist */
			if (!sisusb->gfxinit || !sisusb->SiS_Pr)
				return -ENODEV;

			retval = 0;

			sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
			sisusb->SiS_Pr->sisusb = (void *)sisusb;

			if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
				retval = -EINVAL;

			break;
#endif

		default:
		default:
			retval = -EINVAL;
			retval = -EINVAL;
	}
	}
@@ -2835,6 +3174,11 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
			x.sisusb_vramsize   = sisusb->vramsize;
			x.sisusb_vramsize   = sisusb->vramsize;
			x.sisusb_minor	    = sisusb->minor;
			x.sisusb_minor	    = sisusb->minor;
			x.sisusb_fbdevactive= 0;
			x.sisusb_fbdevactive= 0;
#ifdef INCL_SISUSB_CON
			x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
#else
			x.sisusb_conactive  = 0;
#endif


			if (copy_to_user((void __user *)arg, &x, sizeof(x)))
			if (copy_to_user((void __user *)arg, &x, sizeof(x)))
				retval = -EFAULT;
				retval = -EFAULT;
@@ -2895,9 +3239,13 @@ static struct file_operations usb_sisusb_fops = {
};
};


static struct usb_class_driver usb_sisusb_class = {
static struct usb_class_driver usb_sisusb_class = {
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
	.name =		"usb/sisusbvga%d",
	.name =		"usb/sisusbvga%d",
	.fops =		&usb_sisusb_fops,
	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
#else
	.name =		"sisusbvga%d",
#endif
	.fops =		&usb_sisusb_fops,
	.minor_base =	SISUSB_MINOR
	.minor_base =	SISUSB_MINOR
};
};


@@ -2994,12 +3342,25 @@ static int sisusb_probe(struct usb_interface *intf,
	printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
	printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
					sisusb->minor, sisusb->numobufs);
					sisusb->minor, sisusb->numobufs);


#ifdef INCL_SISUSB_CON
	/* Allocate our SiS_Pr */
	if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
		printk(KERN_ERR
			"sisusbvga[%d]: Failed to allocate SiS_Pr\n",
			sisusb->minor);
	}
#endif

	/* Do remaining init stuff */
	/* Do remaining init stuff */


	init_waitqueue_head(&sisusb->wait_q);
	init_waitqueue_head(&sisusb->wait_q);


	usb_set_intfdata(intf, sisusb);
	usb_set_intfdata(intf, sisusb);


	usb_get_dev(sisusb->sisusb_dev);

	sisusb->present = 1;

#ifdef SISUSB_OLD_CONFIG_COMPAT
#ifdef SISUSB_OLD_CONFIG_COMPAT
	{
	{
	int ret;
	int ret;
@@ -3014,14 +3375,19 @@ static int sisusb_probe(struct usb_interface *intf,
			sisusb->minor);
			sisusb->minor);
	else
	else
		sisusb->ioctl32registered = 1;
		sisusb->ioctl32registered = 1;

	}
	}
#endif
#endif


	sisusb->present = 1;

	if (dev->speed == USB_SPEED_HIGH) {
	if (dev->speed == USB_SPEED_HIGH) {
		if (sisusb_init_gfxdevice(sisusb, 1))
		int initscreen = 1;
#ifdef INCL_SISUSB_CON
		if (sisusb_first_vc > 0 &&
		    sisusb_last_vc > 0 &&
		    sisusb_first_vc <= sisusb_last_vc &&
		    sisusb_last_vc <= MAX_NR_CONSOLES)
			initscreen = 0;
#endif
		if (sisusb_init_gfxdevice(sisusb, initscreen))
			printk(KERN_ERR
			printk(KERN_ERR
				"sisusbvga[%d]: Failed to early "
				"sisusbvga[%d]: Failed to early "
				"initialize device\n",
				"initialize device\n",
@@ -3035,6 +3401,16 @@ static int sisusb_probe(struct usb_interface *intf,


	sisusb->ready = 1;
	sisusb->ready = 1;


#ifdef SISUSBENDIANTEST
	printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
	sisusb_testreadwrite(sisusb);
	printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
#endif

#ifdef INCL_SISUSB_CON
	sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
#endif

	return 0;
	return 0;


error_4:
error_4:
@@ -3053,13 +3429,20 @@ static void sisusb_disconnect(struct usb_interface *intf)
	struct sisusb_usb_data *sisusb;
	struct sisusb_usb_data *sisusb;
	int minor;
	int minor;


	down(&disconnect_sem);

	/* This should *not* happen */
	/* This should *not* happen */
	if (!(sisusb = usb_get_intfdata(intf))) {
	if (!(sisusb = usb_get_intfdata(intf)))
		up(&disconnect_sem);
		return;
		return;
	}

#ifdef INCL_SISUSB_CON
	sisusb_console_exit(sisusb);
#endif

	/* The above code doesn't need the disconnect
	 * semaphore to be down; its meaning is to
	 * protect all other routines from the disconnect
	 * case, not the other way round.
	 */
	down(&disconnect_sem);


	down(&sisusb->lock);
	down(&sisusb->lock);


@@ -3123,11 +3506,17 @@ static int __init usb_sisusb_init(void)
{
{
	int retval;
	int retval;


#ifdef INCL_SISUSB_CON
	sisusb_init_concode();
#endif

	if (!(retval = usb_register(&sisusb_driver))) {
	if (!(retval = usb_register(&sisusb_driver))) {

		printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
		printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
			SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
			SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
		printk(KERN_INFO
		printk(KERN_INFO
			"sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
			"sisusb: Copyright (C) 2005 Thomas Winischhofer\n");

	}
	}


	return retval;
	return retval;
@@ -3142,6 +3531,6 @@ module_init(usb_sisusb_init);
module_exit(usb_sisusb_exit);
module_exit(usb_sisusb_exit);


MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");
MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");
+61 −12
Original line number Original line Diff line number Diff line
@@ -46,15 +46,36 @@
#endif
#endif
#endif
#endif


/* For older kernels, support for text consoles is by default
 * off. To ensable text console support, change the following:
 */
#if 0
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
#define CONFIG_USB_SISUSBVGA_CON
#endif
#endif

/* Version Information */
/* Version Information */


#define SISUSB_VERSION		0
#define SISUSB_VERSION		0
#define SISUSB_REVISION 	0
#define SISUSB_REVISION 	0
#define SISUSB_PATCHLEVEL	7
#define SISUSB_PATCHLEVEL	8

/* Include console and mode switching code? */

#ifdef CONFIG_USB_SISUSBVGA_CON
#define INCL_SISUSB_CON		1
#endif

#ifdef INCL_SISUSB_CON
#include <linux/console.h>
#include <linux/vt_kern.h>
#include "sisusb_struct.h"
#endif


/* USB related */
/* USB related */


#define SISUSB_MINOR	133		/* FIXME */
#define SISUSB_MINOR		133	/* official */


/* Size of the sisusb input/output buffers */
/* Size of the sisusb input/output buffers */
#define SISUSB_IBUF_SIZE  0x01000
#define SISUSB_IBUF_SIZE  0x01000
@@ -131,6 +152,26 @@ struct sisusb_usb_data {
	unsigned char gfxinit;		/* graphics core initialized? */
	unsigned char gfxinit;		/* graphics core initialized? */
	unsigned short chipid, chipvendor;
	unsigned short chipid, chipvendor;
	unsigned short chiprevision;
	unsigned short chiprevision;
#ifdef INCL_SISUSB_CON
	struct SiS_Private *SiS_Pr;
	unsigned long scrbuf;
	unsigned int scrbuf_size;
	int haveconsole, con_first, con_last;
	int havethisconsole[MAX_NR_CONSOLES];
	int textmodedestroyed;
	unsigned int sisusb_num_columns; /* real number, not vt's idea */
	int cur_start_addr, con_rolled_over;
	int sisusb_cursor_loc, bad_cursor_pos;
	int sisusb_cursor_size_from;
	int sisusb_cursor_size_to;
	int current_font_height, current_font_512;
	int font_backup_size, font_backup_height, font_backup_512;
	char *font_backup;
	int font_slot;
	struct vc_data *sisusb_display_fg;
	int is_gfx;
	int con_blanked;
#endif
};
};


#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
@@ -249,7 +290,9 @@ struct sisusb_info {


	__u32   sisusb_fbdevactive;	/* != 0 if framebuffer device active */
	__u32   sisusb_fbdevactive;	/* != 0 if framebuffer device active */


	__u8	sisusb_reserved[32];	/* for future use */
	__u32   sisusb_conactive;	/* != 0 if console driver active */

	__u8	sisusb_reserved[28];	/* for future use */
};
};


struct sisusb_command {
struct sisusb_command {
@@ -270,9 +313,15 @@ struct sisusb_command {


#define SUCMD_CLRSCR	0x07	/* data0:1:2 = length, data3 = address */
#define SUCMD_CLRSCR	0x07	/* data0:1:2 = length, data3 = address */


#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */

#define SUCMD_SETMODE	0x09	/* Set a display mode (data3 = SiS mode) */
#define SUCMD_SETVESAMODE 0x0a	/* Set a display mode (data3 = VESA mode) */

#define SISUSB_COMMAND		_IOWR(0xF3,0x3D,struct sisusb_command)
#define SISUSB_COMMAND		_IOWR(0xF3,0x3D,struct sisusb_command)
#define SISUSB_GET_CONFIG_SIZE	_IOR(0xF3,0x3E,__u32)
#define SISUSB_GET_CONFIG_SIZE	_IOR(0xF3,0x3E,__u32)
#define SISUSB_GET_CONFIG	_IOR(0xF3,0x3F,struct sisusb_info)
#define SISUSB_GET_CONFIG	_IOR(0xF3,0x3F,struct sisusb_info)



#endif /* SISUSB_H */
#endif /* SISUSB_H */
+1658 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading