aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/misc/sisusbvga
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc/sisusbvga')
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig45
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile3
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c773
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h193
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c1568
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.c958
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h841
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_struct.h161
8 files changed, 4139 insertions, 403 deletions
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 3957e144caf..36bc28c884a 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -1,14 +1,47 @@
config USB_SISUSBVGA
tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
- depends on USB && USB_EHCI_HCD
+ depends on (USB_MUSB_HDRC || USB_EHCI_HCD)
+ select FONT_SUPPORT if USB_SISUSBVGA_CON
---help---
Say Y here if you intend to attach a USB2VGA dongle based on a
- Net2280 and a SiS315 chip.
-
- Note that this device requires a USB 2.0 host controller. It will not
+ Net2280 and a SiS315 chip.
+
+ Note that this device requires a USB 2.0 host controller. It will not
work with USB 1.x controllers.
- To compile this driver as a module, choose M here: the module will be
- called sisusb. If unsure, say N.
+ To compile this driver as a module, choose M here; the module will be
+ 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
+
+
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 76f1643ceaf..3142476ccc8 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -2,5 +2,6 @@
# Makefile for the sisusb driver (if driver is inside kernel tree).
#
-obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
+sisusbvga-y := sisusb.o sisusb_init.o sisusb_con.o
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 2fd12264fd5..06b5d77cd9a 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -1,6 +1,8 @@
/*
* sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
*
+ * Main part
+ *
* Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, this code is licensed under the
@@ -30,16 +32,14 @@
* * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
*
*/
-#include <linux/config.h>
-#include <linux/version.h>
+#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/signal.h>
-#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/poll.h>
#include <linux/init.h>
@@ -47,17 +47,29 @@
#include <linux/spinlock.h>
#include <linux/kref.h>
#include <linux/usb.h>
-#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
#include "sisusb.h"
+#include "sisusb_init.h"
+
+#ifdef INCL_SISUSB_CON
+#include <linux/font.h>
+#endif
#define SISUSB_DONTSYNC
/* Forward declarations / clean-up routines */
-static struct usb_driver sisusb_driver;
+#ifdef INCL_SISUSB_CON
+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 DECLARE_MUTEX(disconnect_sem);
+static struct usb_driver sisusb_driver;
static void
sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -66,14 +78,12 @@ sisusb_free_buffers(struct sisusb_usb_data *sisusb)
for (i = 0; i < NUMOBUFS; i++) {
if (sisusb->obuf[i]) {
- usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
- sisusb->obuf[i], sisusb->transfer_dma_out[i]);
+ kfree(sisusb->obuf[i]);
sisusb->obuf[i] = NULL;
}
}
if (sisusb->ibuf) {
- usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
- sisusb->ibuf, sisusb->transfer_dma_in);
+ kfree(sisusb->ibuf);
sisusb->ibuf = NULL;
}
}
@@ -193,7 +203,7 @@ sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
/* completion callback */
static void
-sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
+sisusb_bulk_completeout(struct urb *urb)
{
struct sisusb_urb_context *context = urb->context;
struct sisusb_usb_data *sisusb;
@@ -217,8 +227,7 @@ sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
static int
sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
- int len, int *actual_length, int timeout, unsigned int tflags,
- dma_addr_t transfer_dma)
+ int len, int *actual_length, int timeout, unsigned int tflags)
{
struct urb *urb = sisusb->sisurbout[index];
int retval, byteswritten = 0;
@@ -229,12 +238,9 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe,
usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
sisusb_bulk_completeout, &sisusb->urbout_context[index]);
- urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->transfer_flags |= tflags;
urb->actual_length = 0;
- if ((urb->transfer_dma = transfer_dma))
- urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
/* Set up context */
sisusb->urbout_context[index].actual_length = (timeout) ?
NULL : actual_length;
@@ -243,7 +249,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe,
sisusb->urbstatus[index] |= SU_URB_BUSY;
/* Submit URB */
- retval = usb_submit_urb(urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_KERNEL);
/* If OK, and if timeout > 0, wait for completion */
if ((retval == 0) && timeout) {
@@ -272,7 +278,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe,
/* completion callback */
static void
-sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
+sisusb_bulk_completein(struct urb *urb)
{
struct sisusb_usb_data *sisusb = urb->context;
@@ -284,8 +290,8 @@ sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
}
static int
-sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
- int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
+sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
+ int len, int *actual_length, int timeout, unsigned int tflags)
{
struct urb *urb = sisusb->sisurbin;
int retval, readbytes = 0;
@@ -295,14 +301,11 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
sisusb_bulk_completein, sisusb);
- urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->transfer_flags |= tflags;
urb->actual_length = 0;
- if ((urb->transfer_dma = transfer_dma))
- urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
sisusb->completein = 0;
- retval = usb_submit_urb(urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval == 0) {
wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
if (!sisusb->completein) {
@@ -310,7 +313,7 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
usb_kill_urb(urb);
retval = -ETIMEDOUT;
} else {
- /* URB completed within timout */
+ /* URB completed within timeout */
retval = urb->status;
readbytes = urb->actual_length;
}
@@ -409,8 +412,7 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
thispass,
&transferred_len,
async ? 0 : 5 * HZ,
- tflags,
- sisusb->transfer_dma_out[index]);
+ tflags);
if (result == -ETIMEDOUT) {
@@ -419,29 +421,16 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
return -ETIME;
continue;
+ }
- } else if ((result == 0) && !async && transferred_len) {
+ if ((result == 0) && !async && transferred_len) {
thispass -= transferred_len;
- if (thispass) {
- if (sisusb->transfer_dma_out) {
- /* If DMA, copy remaining
- * to beginning of buffer
- */
- memcpy(buffer,
- buffer + transferred_len,
- thispass);
- } else {
- /* If not DMA, simply increase
- * the pointer
- */
- buffer += transferred_len;
- }
- }
+ buffer += transferred_len;
} else
break;
- };
+ }
if (result)
return result;
@@ -517,8 +506,7 @@ static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
thispass,
&transferred_len,
5 * HZ,
- tflags,
- sisusb->transfer_dma_in);
+ tflags);
if (transferred_len)
thispass = transferred_len;
@@ -639,7 +627,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
/* The following routines assume being used to transfer byte, word,
* 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,
@@ -815,9 +806,6 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
switch (length) {
- case 0:
- return ret;
-
case 1:
if (userbuffer) {
if (get_user(swap8, (u8 __user *)userbuffer))
@@ -839,7 +827,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (get_user(swap16, (u16 __user *)userbuffer))
return -EFAULT;
} else
- swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
+ swap16 = *((u16 *)kernbuffer);
ret = sisusb_write_memio_word(sisusb,
SISUSB_TYPE_MEM,
@@ -855,14 +843,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (userbuffer) {
if (copy_from_user(&buf, userbuffer, 3))
return -EFAULT;
-
+#ifdef __BIG_ENDIAN
swap32 = (buf[0] << 16) |
(buf[1] << 8) |
buf[2];
+#else
+ swap32 = (buf[2] << 16) |
+ (buf[1] << 8) |
+ buf[0];
+#endif
} else
+#ifdef __BIG_ENDIAN
swap32 = (kernbuffer[0] << 16) |
(kernbuffer[1] << 8) |
kernbuffer[2];
+#else
+ swap32 = (kernbuffer[2] << 16) |
+ (kernbuffer[1] << 8) |
+ kernbuffer[0];
+#endif
ret = sisusb_write_memio_24bit(sisusb,
SISUSB_TYPE_MEM,
@@ -879,10 +878,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (get_user(swap32, (u32 __user *)userbuffer))
return -EFAULT;
} else
- swap32 = (kernbuffer[0] << 24) |
- (kernbuffer[1] << 16) |
- (kernbuffer[2] << 8) |
- kernbuffer[3];
+ swap32 = *((u32 *)kernbuffer);
ret = sisusb_write_memio_long(sisusb,
SISUSB_TYPE_MEM,
@@ -941,12 +937,12 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
packet.address = 0x00000194;
packet.data = addr;
ret = sisusb_send_bridge_packet(sisusb, 10,
- &packet, 0);
+ &packet, 0);
packet.header = 0x001f;
packet.address = 0x00000190;
packet.data = (length & ~3);
ret |= sisusb_send_bridge_packet(sisusb, 10,
- &packet, 0);
+ &packet, 0);
if (sisusb->flagb0 != 0x16) {
packet.header = 0x001f;
packet.address = 0x00000180;
@@ -982,29 +978,27 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (ret) {
msgcount++;
if (msgcount < 500)
- printk(KERN_ERR
- "sisusbvga[%d]: Wrote %zd of "
- "%d bytes, error %d\n",
- sisusb->minor, *bytes_written,
- length, ret);
+ dev_err(&sisusb->sisusb_dev->dev, "Wrote %zd of %d bytes, error %d\n",
+ *bytes_written, length, ret);
else if (msgcount == 500)
- printk(KERN_ERR
- "sisusbvga[%d]: Too many errors"
- ", logging stopped\n",
- sisusb->minor);
+ dev_err(&sisusb->sisusb_dev->dev, "Too many errors, logging stopped\n");
}
addr += (*bytes_written);
length -= (*bytes_written);
}
if (ret)
- break;
+ break;
}
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,
u32 addr, u8 *data)
{
@@ -1161,9 +1155,6 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
switch (length) {
- case 0:
- return ret;
-
case 1:
ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
@@ -1191,8 +1182,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
(u16 __user *)userbuffer))
return -EFAULT;
} else {
- kernbuffer[0] = swap16 >> 8;
- kernbuffer[1] = swap16 & 0xff;
+ *((u16 *)kernbuffer) = swap16;
}
}
return ret;
@@ -1202,9 +1192,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
addr, &swap32);
if (!ret) {
(*bytes_read) += 3;
+#ifdef __BIG_ENDIAN
buf[0] = (swap32 >> 16) & 0xff;
buf[1] = (swap32 >> 8) & 0xff;
buf[2] = swap32 & 0xff;
+#else
+ buf[2] = (swap32 >> 16) & 0xff;
+ buf[1] = (swap32 >> 8) & 0xff;
+ buf[0] = swap32 & 0xff;
+#endif
if (userbuffer) {
if (copy_to_user(userbuffer, &buf[0], 3))
return -EFAULT;
@@ -1228,60 +1224,16 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
userbuffer += 4;
} else {
- kernbuffer[0] = (swap32 >> 24) & 0xff;
- kernbuffer[1] = (swap32 >> 16) & 0xff;
- kernbuffer[2] = (swap32 >> 8) & 0xff;
- kernbuffer[3] = swap32 & 0xff;
+ *((u32 *)kernbuffer) = swap32;
kernbuffer += 4;
}
addr += 4;
length -= 4;
}
-#if 0 /* That does not work, as EP 2 is an OUT EP! */
- default:
- CLEARPACKET(&packet);
- packet.header = 0x001f;
- packet.address = 0x000001a0;
- packet.data = 0x00000006;
- ret |= sisusb_send_bridge_packet(sisusb, 10,
- &packet, 0);
- packet.header = 0x001f;
- packet.address = 0x000001b0;
- packet.data = (length & ~3) | 0x40000000;
- ret |= sisusb_send_bridge_packet(sisusb, 10,
- &packet, 0);
- packet.header = 0x001f;
- packet.address = 0x000001b4;
- packet.data = addr;
- ret |= sisusb_send_bridge_packet(sisusb, 10,
- &packet, 0);
- packet.header = 0x001f;
- packet.address = 0x000001a4;
- packet.data = 0x00000001;
- ret |= sisusb_send_bridge_packet(sisusb, 10,
- &packet, 0);
- if (userbuffer) {
- ret |= sisusb_recv_bulk_msg(sisusb,
- SISUSB_EP_GFX_BULK_IN,
- (length & ~3),
- NULL, userbuffer,
- bytes_read, 0);
- if (!ret) userbuffer += (*bytes_read);
- } else {
- ret |= sisusb_recv_bulk_msg(sisusb,
- SISUSB_EP_GFX_BULK_IN,
- (length & ~3),
- kernbuffer, NULL,
- bytes_read, 0);
- if (!ret) kernbuffer += (*bytes_read);
- }
- addr += (*bytes_read);
- length -= (*bytes_read);
-#endif
}
if (ret)
- break;
+ break;
}
return ret;
@@ -1289,7 +1241,21 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
/* 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
+
+int
sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
{
int ret;
@@ -1298,7 +1264,7 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
return ret;
}
-static int
+int
sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
{
int ret;
@@ -1307,7 +1273,7 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
return ret;
}
-static int
+int
sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
u8 myand, u8 myor)
{
@@ -1336,18 +1302,71 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
return ret;
}
-static int
+int
sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
{
return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
}
-static int
+int
sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
{
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_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++) {
+ dev_dbg(&sisusb->sisusb_dev->dev, "sisusb: rwtest %d bytes\n", i);
+ sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
+ for(j = 0; j < i; j++) {
+ dev_dbg(&sisusb->sisusb_dev->dev, "rwtest read[%d] = %x\n", j, destbuffer[j]);
+ }
+ }
+}
+#endif
+
/* access pci config registers (reg numbers 0, 4, 8, etc) */
static int
@@ -1426,9 +1445,9 @@ sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
#define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
#define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
#define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
-#define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
+#define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
#define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
-#define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
+#define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
static int
sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
@@ -1901,7 +1920,7 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
SETIREG(SISSR, 0x26, 0x00);
}
- SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
+ SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
return ret;
}
@@ -2061,17 +2080,12 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
if (ramtype <= 1) {
ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
if (iret) {
- printk(KERN_ERR "sisusbvga[%d]: RAM size "
- "detection failed, "
- "assuming 8MB video RAM\n",
- sisusb->minor);
+ dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n");
ret |= SETIREG(SISSR,0x14,0x31);
/* TODO */
}
} else {
- printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
- "assuming 8MB video RAM\n",
- sisusb->minor);
+ dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n");
ret |= SETIREG(SISSR,0x14,0x31);
/* *** TODO *** */
}
@@ -2109,8 +2123,8 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
u8 tmp8, tmp82, ramtype;
int bw = 0;
char *ramtypetext1 = NULL;
- const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
- "DDR SDRAM", "DDR SGRAM" };
+ static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
+ static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
static const int busSDR[4] = {64, 64, 128, 128};
static const int busDDR[4] = {32, 32, 64, 64};
static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
@@ -2142,9 +2156,10 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
break;
}
- printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
- sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
- ramtypetext2[ramtype], bw);
+
+ dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %cDR S%cRAM, bus width %d\n",
+ sisusb->vramsize >> 20, ramtypetext1,
+ ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
}
static int
@@ -2270,6 +2285,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
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;
+ const struct font_desc *myfont;
+ u8 *tempbuf;
+ u16 *tempbufb;
+ size_t written;
+ static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+ static const 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 */
static int
@@ -2279,73 +2417,54 @@ sisusb_open(struct inode *inode, struct file *file)
struct usb_interface *interface;
int subminor = iminor(inode);
- down(&disconnect_sem);
-
if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
- printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
- subminor);
- up(&disconnect_sem);
return -ENODEV;
}
if (!(sisusb = usb_get_intfdata(interface))) {
- up(&disconnect_sem);
return -ENODEV;
}
- down(&sisusb->lock);
+ mutex_lock(&sisusb->lock);
if (!sisusb->present || !sisusb->ready) {
- up(&sisusb->lock);
- up(&disconnect_sem);
+ mutex_unlock(&sisusb->lock);
return -ENODEV;
}
if (sisusb->isopen) {
- up(&sisusb->lock);
- up(&disconnect_sem);
+ mutex_unlock(&sisusb->lock);
return -EBUSY;
}
if (!sisusb->devinit) {
- if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
+ if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
+ sisusb->sisusb_dev->speed == USB_SPEED_SUPER) {
if (sisusb_init_gfxdevice(sisusb, 0)) {
- up(&sisusb->lock);
- up(&disconnect_sem);
- printk(KERN_ERR
- "sisusbvga[%d]: Failed to initialize "
- "device\n",
- sisusb->minor);
+ mutex_unlock(&sisusb->lock);
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
return -EIO;
}
} else {
- up(&sisusb->lock);
- up(&disconnect_sem);
- printk(KERN_ERR
- "sisusbvga[%d]: Device not attached to "
- "USB 2.0 hub\n",
- sisusb->minor);
+ mutex_unlock(&sisusb->lock);
+ dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n");
return -EIO;
}
}
- /* increment usage count for the device */
+ /* Increment usage count for our sisusb */
kref_get(&sisusb->kref);
sisusb->isopen = 1;
file->private_data = sisusb;
- up(&sisusb->lock);
-
- up(&disconnect_sem);
-
- printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
+ mutex_unlock(&sisusb->lock);
return 0;
}
-static void
+void
sisusb_delete(struct kref *kref)
{
struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2478,9 @@ sisusb_delete(struct kref *kref)
sisusb->sisusb_dev = NULL;
sisusb_free_buffers(sisusb);
sisusb_free_urbs(sisusb);
+#ifdef INCL_SISUSB_CON
+ kfree(sisusb->SiS_Pr);
+#endif
kfree(sisusb);
}
@@ -2366,16 +2488,11 @@ static int
sisusb_release(struct inode *inode, struct file *file)
{
struct sisusb_usb_data *sisusb;
- int myminor;
-
- down(&disconnect_sem);
- if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
- up(&disconnect_sem);
+ if (!(sisusb = file->private_data))
return -ENODEV;
- }
- down(&sisusb->lock);
+ mutex_lock(&sisusb->lock);
if (sisusb->present) {
/* Wait for all URBs to finish if device still present */
@@ -2383,20 +2500,14 @@ sisusb_release(struct inode *inode, struct file *file)
sisusb_kill_all_busy(sisusb);
}
- myminor = sisusb->minor;
-
sisusb->isopen = 0;
file->private_data = NULL;
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
/* decrement the usage count on our device */
kref_put(&sisusb->kref, sisusb_delete);
- up(&disconnect_sem);
-
- printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
-
return 0;
}
@@ -2410,14 +2521,14 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
u16 buf16;
u32 buf32, address;
- if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ if (!(sisusb = file->private_data))
return -ENODEV;
- down(&sisusb->lock);
+ mutex_lock(&sisusb->lock);
/* Sanity check */
if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return -ENODEV;
}
@@ -2512,7 +2623,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
(*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
if (count != 4) {
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return -EINVAL;
}
@@ -2536,7 +2647,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
(*ppos) += bytes_read;
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return errno ? errno : bytes_read;
}
@@ -2552,14 +2663,14 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count,
u16 buf16;
u32 buf32, address;
- if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ if (!(sisusb = file->private_data))
return -ENODEV;
- down(&sisusb->lock);
+ mutex_lock(&sisusb->lock);
/* Sanity check */
if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return -ENODEV;
}
@@ -2658,7 +2769,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count,
(*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
if (count != 4) {
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return -EINVAL;
}
@@ -2684,7 +2795,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count,
(*ppos) += bytes_written;
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return errno ? errno : bytes_written;
}
@@ -2695,14 +2806,14 @@ sisusb_lseek(struct file *file, loff_t offset, int orig)
struct sisusb_usb_data *sisusb;
loff_t ret;
- if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ if (!(sisusb = file->private_data))
return -ENODEV;
- down(&sisusb->lock);
+ mutex_lock(&sisusb->lock);
/* Sanity check */
if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return -ENODEV;
}
@@ -2722,7 +2833,7 @@ sisusb_lseek(struct file *file, loff_t offset, int orig)
ret = -EINVAL;
}
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return ret;
}
@@ -2730,9 +2841,15 @@ static int
sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
unsigned long arg)
{
- int retval, port, length;
+ int retval, port, length;
u32 address;
+ /* All our commands require the device
+ * to be initialized.
+ */
+ if (!sisusb->devinit)
+ return -ENODEV;
+
port = y->data3 -
SISUSB_PCI_PSEUDO_IOPORTBASE +
SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +2891,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
break;
case SUCMD_CLRSCR:
+ /* Gfx core must be initialized */
+ if (!sisusb->gfxinit)
+ return -ENODEV;
+
length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
address = y->data3 -
SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,30 +2902,79 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
retval = sisusb_clear_vram(sisusb, address, length);
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:
retval = -EINVAL;
}
- if(retval > 0)
+ if (retval > 0)
retval = -EIO;
return retval;
}
-static int
-sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long
+sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct sisusb_usb_data *sisusb;
struct sisusb_info x;
struct sisusb_command y;
- int retval = 0;
+ long retval = 0;
u32 __user *argp = (u32 __user *)arg;
- if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ if (!(sisusb = file->private_data))
return -ENODEV;
- down(&sisusb->lock);
+ mutex_lock(&sisusb->lock);
/* Sanity check */
if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
@@ -2823,7 +2993,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case SISUSB_GET_CONFIG:
- x.sisusb_id = SISUSB_ID;
+ x.sisusb_id = SISUSB_ID;
x.sisusb_version = SISUSB_VERSION;
x.sisusb_revision = SISUSB_REVISION;
x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
@@ -2835,6 +3005,12 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
x.sisusb_vramsize = sisusb->vramsize;
x.sisusb_minor = sisusb->minor;
x.sisusb_fbdevactive= 0;
+#ifdef INCL_SISUSB_CON
+ x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
+#else
+ x.sisusb_conactive = 0;
+#endif
+ memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
if (copy_to_user((void __user *)arg, &x, sizeof(x)))
retval = -EFAULT;
@@ -2851,12 +3027,12 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
break;
default:
- retval = -EINVAL;
+ retval = -ENOTTY;
break;
}
err_out:
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
return retval;
}
@@ -2870,9 +3046,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
case SISUSB_GET_CONFIG_SIZE:
case SISUSB_GET_CONFIG:
case SISUSB_COMMAND:
- lock_kernel();
- retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
- unlock_kernel();
+ retval = sisusb_ioctl(f, cmd, arg);
return retval;
default:
@@ -2881,23 +3055,22 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
}
#endif
-static struct file_operations usb_sisusb_fops = {
+static const struct file_operations usb_sisusb_fops = {
.owner = THIS_MODULE,
.open = sisusb_open,
.release = sisusb_release,
.read = sisusb_read,
.write = sisusb_write,
- .llseek = sisusb_lseek,
+ .llseek = sisusb_lseek,
#ifdef SISUSB_NEW_CONFIG_COMPAT
.compat_ioctl = sisusb_compat_ioctl,
#endif
- .ioctl = sisusb_ioctl
+ .unlocked_ioctl = sisusb_ioctl
};
static struct usb_class_driver usb_sisusb_class = {
- .name = "usb/sisusbvga%d",
+ .name = "sisusbvga%d",
.fops = &usb_sisusb_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = SISUSB_MINOR
};
@@ -2907,28 +3080,22 @@ static int sisusb_probe(struct usb_interface *intf,
struct usb_device *dev = interface_to_usbdev(intf);
struct sisusb_usb_data *sisusb;
int retval = 0, i;
- const char *memfail =
- KERN_ERR
- "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
- printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
+ dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
dev->devnum);
/* Allocate memory for our private */
- if (!(sisusb = kmalloc(sizeof(*sisusb), GFP_KERNEL))) {
- printk(KERN_ERR
- "sisusb: Failed to allocate memory for private data\n");
+ if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
+ dev_err(&dev->dev, "Failed to allocate memory for private data\n");
return -ENOMEM;
}
- memset(sisusb, 0, sizeof(*sisusb));
kref_init(&sisusb->kref);
- init_MUTEX(&(sisusb->lock));
+ mutex_init(&(sisusb->lock));
/* Register device */
if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
- printk(KERN_ERR
- "sisusb: Failed to get a minor for device %d\n",
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n",
dev->devnum);
retval = -ENODEV;
goto error_1;
@@ -2944,9 +3111,8 @@ static int sisusb_probe(struct usb_interface *intf,
/* Allocate buffers */
sisusb->ibufsize = SISUSB_IBUF_SIZE;
- if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
- GFP_KERNEL, &sisusb->transfer_dma_in))) {
- printk(memfail, "input", sisusb->minor);
+ if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) {
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer");
retval = -ENOMEM;
goto error_2;
}
@@ -2954,11 +3120,9 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb->numobufs = 0;
sisusb->obufsize = SISUSB_OBUF_SIZE;
for (i = 0; i < NUMOBUFS; i++) {
- if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
- GFP_KERNEL,
- &sisusb->transfer_dma_out[i]))) {
+ if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) {
if (i == 0) {
- printk(memfail, "output", sisusb->minor);
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n");
retval = -ENOMEM;
goto error_3;
}
@@ -2970,9 +3134,7 @@ static int sisusb_probe(struct usb_interface *intf,
/* Allocate URBs */
if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
- printk(KERN_ERR
- "sisusbvga[%d]: Failed to allocate URBs\n",
- sisusb->minor);
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
retval = -ENOMEM;
goto error_3;
}
@@ -2980,9 +3142,7 @@ static int sisusb_probe(struct usb_interface *intf,
for (i = 0; i < sisusb->numobufs; i++) {
if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
- printk(KERN_ERR
- "sisusbvga[%d]: Failed to allocate URBs\n",
- sisusb->minor);
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
retval = -ENOMEM;
goto error_4;
}
@@ -2991,8 +3151,14 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb->urbstatus[i] = 0;
}
- printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
- sisusb->minor, sisusb->numobufs);
+ dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs);
+
+#ifdef INCL_SISUSB_CON
+ /* Allocate our SiS_Pr */
+ if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n");
+ }
+#endif
/* Do remaining init stuff */
@@ -3000,41 +3166,37 @@ static int sisusb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, sisusb);
-#ifdef SISUSB_OLD_CONFIG_COMPAT
- {
- int ret;
- /* Our ioctls are all "32/64bit compatible" */
- ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
- ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
- ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
- if (ret)
- printk(KERN_ERR
- "sisusbvga[%d]: Error registering ioctl32 "
- "translations\n",
- sisusb->minor);
- else
- sisusb->ioctl32registered = 1;
-
- }
-#endif
+ usb_get_dev(sisusb->sisusb_dev);
sisusb->present = 1;
- if (dev->speed == USB_SPEED_HIGH) {
- if (sisusb_init_gfxdevice(sisusb, 1))
- printk(KERN_ERR
- "sisusbvga[%d]: Failed to early "
- "initialize device\n",
- sisusb->minor);
+ if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {
+ 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))
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n");
} else
- printk(KERN_INFO
- "sisusbvga[%d]: Not attached to USB 2.0 hub, "
- "deferring init\n",
- sisusb->minor);
+ dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n");
sisusb->ready = 1;
+#ifdef SISUSBENDIANTEST
+ dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
+ sisusb_testreadwrite(sisusb);
+ dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
+#endif
+
+#ifdef INCL_SISUSB_CON
+ sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
+#endif
+
return 0;
error_4:
@@ -3051,59 +3213,43 @@ error_1:
static void sisusb_disconnect(struct usb_interface *intf)
{
struct sisusb_usb_data *sisusb;
- int minor;
-
- down(&disconnect_sem);
/* This should *not* happen */
- if (!(sisusb = usb_get_intfdata(intf))) {
- up(&disconnect_sem);
+ if (!(sisusb = usb_get_intfdata(intf)))
return;
- }
- down(&sisusb->lock);
+#ifdef INCL_SISUSB_CON
+ sisusb_console_exit(sisusb);
+#endif
+
+ usb_deregister_dev(intf, &usb_sisusb_class);
+
+ mutex_lock(&sisusb->lock);
/* Wait for all URBs to complete and kill them in case (MUST do) */
if (!sisusb_wait_all_out_complete(sisusb))
sisusb_kill_all_busy(sisusb);
- minor = sisusb->minor;
-
usb_set_intfdata(intf, NULL);
- usb_deregister_dev(intf, &usb_sisusb_class);
-
-#ifdef SISUSB_OLD_CONFIG_COMPAT
- if (sisusb->ioctl32registered) {
- int ret;
- sisusb->ioctl32registered = 0;
- ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
- ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
- ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
- if (ret) {
- printk(KERN_ERR
- "sisusbvga[%d]: Error unregistering "
- "ioctl32 translations\n",
- minor);
- }
- }
-#endif
-
sisusb->present = 0;
sisusb->ready = 0;
- up(&sisusb->lock);
+ mutex_unlock(&sisusb->lock);
/* decrement our usage count */
kref_put(&sisusb->kref, sisusb_delete);
-
- up(&disconnect_sem);
-
- printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
}
-static struct usb_device_id sisusb_table [] = {
+static const struct usb_device_id sisusb_table[] = {
+ { USB_DEVICE(0x0711, 0x0550) },
{ USB_DEVICE(0x0711, 0x0900) },
+ { USB_DEVICE(0x0711, 0x0901) },
+ { USB_DEVICE(0x0711, 0x0902) },
+ { USB_DEVICE(0x0711, 0x0903) },
+ { USB_DEVICE(0x0711, 0x0918) },
+ { USB_DEVICE(0x0711, 0x0920) },
+ { USB_DEVICE(0x0711, 0x0950) },
{ USB_DEVICE(0x182d, 0x021c) },
{ USB_DEVICE(0x182d, 0x0269) },
{ }
@@ -3112,7 +3258,6 @@ static struct usb_device_id sisusb_table [] = {
MODULE_DEVICE_TABLE (usb, sisusb_table);
static struct usb_driver sisusb_driver = {
- .owner = THIS_MODULE,
.name = "sisusb",
.probe = sisusb_probe,
.disconnect = sisusb_disconnect,
@@ -3121,16 +3266,12 @@ static struct usb_driver sisusb_driver = {
static int __init usb_sisusb_init(void)
{
- int retval;
- if (!(retval = usb_register(&sisusb_driver))) {
- printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
- SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
- printk(KERN_INFO
- "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
- }
+#ifdef INCL_SISUSB_CON
+ sisusb_init_concode();
+#endif
- return retval;
+ return usb_register(&sisusb_driver);
}
static void __exit usb_sisusb_exit(void)
@@ -3142,6 +3283,6 @@ module_init(usb_sisusb_init);
module_exit(usb_sisusb_exit);
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");
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index 1306d006a25..55492a5930b 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -8,29 +8,29 @@
*
* Otherwise, the following license terms apply:
*
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * * notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * * notice, this list of conditions and the following disclaimer in the
- * * documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * * derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1) Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2) Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3) The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
*
*/
@@ -38,29 +38,41 @@
#define _SISUSB_H_
#ifdef CONFIG_COMPAT
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
-#include <linux/ioctl32.h>
-#define SISUSB_OLD_CONFIG_COMPAT
-#else
#define SISUSB_NEW_CONFIG_COMPAT
#endif
-#endif
+
+#include <linux/mutex.h>
+
+/* For older kernels, support for text consoles is by default
+ * off. To enable text console support, change the following:
+ */
+/* #define CONFIG_USB_SISUSBVGA_CON */
/* Version Information */
#define SISUSB_VERSION 0
-#define SISUSB_REVISION 0
-#define SISUSB_PATCHLEVEL 7
+#define SISUSB_REVISION 0
+#define SISUSB_PATCHLEVEL 8
+
+/* Include console and mode switching code? */
+
+#ifdef CONFIG_USB_SISUSBVGA_CON
+#define INCL_SISUSB_CON 1
+#endif
+
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include "sisusb_struct.h"
/* USB related */
-#define SISUSB_MINOR 133 /* FIXME */
+#define SISUSB_MINOR 133 /* official */
/* Size of the sisusb input/output buffers */
#define SISUSB_IBUF_SIZE 0x01000
#define SISUSB_OBUF_SIZE 0x10000 /* fixed */
-#define NUMOBUFS 8 /* max number of output buffers/output URBs */
+#define NUMOBUFS 8 /* max number of output buffers/output URBs */
/* About endianness:
*
@@ -79,7 +91,7 @@
*/
#ifdef __BIG_ENDIAN
-#define SISUSB_CORRECT_ENDIANNESS_PACKET(p) \
+#define SISUSB_CORRECT_ENDIANNESS_PACKET(p) \
do { \
p->header = cpu_to_le16(p->header); \
p->address = cpu_to_le32(p->address); \
@@ -91,7 +103,7 @@
struct sisusb_usb_data;
-struct sisusb_urb_context { /* urb->context for outbound bulk URBs */
+struct sisusb_urb_context { /* urb->context for outbound bulk URBs */
struct sisusb_usb_data *sisusb;
int urbindex;
int *actual_length;
@@ -102,35 +114,50 @@ struct sisusb_usb_data {
struct usb_interface *interface;
struct kref kref;
wait_queue_head_t wait_q; /* for syncind and timeouts */
- struct semaphore lock; /* general race avoidance */
- unsigned int ifnum; /* interface number of the USB device */
- int minor; /* minor (for logging clarity) */
- int isopen; /* !=0 if open */
- int present; /* !=0 if device is present on the bus */
- int ready; /* !=0 if device is ready for userland */
-#ifdef SISUSB_OLD_CONFIG_COMPAT
- int ioctl32registered;
-#endif
- int numobufs; /* number of obufs = number of out urbs */
+ struct mutex lock; /* general race avoidance */
+ unsigned int ifnum; /* interface number of the USB device */
+ int minor; /* minor (for logging clarity) */
+ int isopen; /* !=0 if open */
+ int present; /* !=0 if device is present on the bus */
+ int ready; /* !=0 if device is ready for userland */
+ int numobufs; /* number of obufs = number of out urbs */
char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */
int obufsize, ibufsize;
- dma_addr_t transfer_dma_out[NUMOBUFS];
- dma_addr_t transfer_dma_in;
struct urb *sisurbout[NUMOBUFS];
struct urb *sisurbin;
unsigned char urbstatus[NUMOBUFS];
unsigned char completein;
struct sisusb_urb_context urbout_context[NUMOBUFS];
unsigned long flagb0;
- unsigned long vrambase; /* framebuffer base */
- unsigned int vramsize; /* framebuffer size (bytes) */
+ unsigned long vrambase; /* framebuffer base */
+ unsigned int vramsize; /* framebuffer size (bytes) */
unsigned long mmiobase;
unsigned int mmiosize;
unsigned long ioportbase;
- unsigned char devinit; /* device initialized? */
- unsigned char gfxinit; /* graphics core initialized? */
+ unsigned char devinit; /* device initialized? */
+ unsigned char gfxinit; /* graphics core initialized? */
unsigned short chipid, chipvendor;
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)
@@ -163,7 +190,7 @@ struct sisusb_packet {
unsigned short header;
u32 address;
u32 data;
-} __attribute__((__packed__));
+} __attribute__ ((__packed__));
#define CLEARPACKET(packet) memset(packet, 0, 10)
@@ -231,48 +258,54 @@ struct sisusb_packet {
/* Structure argument for SISUSB_GET_INFO ioctl */
struct sisusb_info {
- __u32 sisusb_id; /* for identifying sisusb */
-#define SISUSB_ID 0x53495355 /* Identify myself with 'SISU' */
- __u8 sisusb_version;
- __u8 sisusb_revision;
- __u8 sisusb_patchlevel;
- __u8 sisusb_gfxinit; /* graphics core initialized? */
+ __u32 sisusb_id; /* for identifying sisusb */
+#define SISUSB_ID 0x53495355 /* Identify myself with 'SISU' */
+ __u8 sisusb_version;
+ __u8 sisusb_revision;
+ __u8 sisusb_patchlevel;
+ __u8 sisusb_gfxinit; /* graphics core initialized? */
- __u32 sisusb_vrambase;
- __u32 sisusb_mmiobase;
- __u32 sisusb_iobase;
- __u32 sisusb_pcibase;
+ __u32 sisusb_vrambase;
+ __u32 sisusb_mmiobase;
+ __u32 sisusb_iobase;
+ __u32 sisusb_pcibase;
- __u32 sisusb_vramsize; /* framebuffer size in bytes */
+ __u32 sisusb_vramsize; /* framebuffer size in bytes */
- __u32 sisusb_minor;
+ __u32 sisusb_minor;
- __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 {
- __u8 operation; /* see below */
- __u8 data0; /* operation dependent */
- __u8 data1; /* operation dependent */
- __u8 data2; /* operation dependent */
- __u32 data3; /* operation dependent */
- __u32 data4; /* for future use */
+ __u8 operation; /* see below */
+ __u8 data0; /* operation dependent */
+ __u8 data1; /* operation dependent */
+ __u8 data2; /* operation dependent */
+ __u32 data3; /* operation dependent */
+ __u32 data4; /* for future use */
};
-#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
-#define SUCMD_SET 0x02 /* data1 = value */
-#define SUCMD_SETOR 0x03 /* data1 = or */
-#define SUCMD_SETAND 0x04 /* data1 = and */
-#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
-#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
+#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
+#define SUCMD_SET 0x02 /* data1 = value */
+#define SUCMD_SETOR 0x03 /* data1 = or */
+#define SUCMD_SETAND 0x04 /* data1 = and */
+#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
+#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
+
+#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_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
-#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
+#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
+#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
#endif /* SISUSB_H */
-
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
new file mode 100644
index 00000000000..a638c4e9a94
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -0,0 +1,1568 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * VGA text mode console part
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * * notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * * notice, this list of conditions and the following disclaimer in the
+ * * documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific psisusbr written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Portions based on vgacon.c which are
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ * based on code Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ *
+ * A note on using in_atomic() in here: We can't handle console
+ * calls from non-schedulable context due to our USB-dependend
+ * nature. For now, this driver just ignores any calls if it
+ * detects this state.
+ *
+ */
+
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/fs.h>
+#include <linux/usb.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/init.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+
+#include "sisusb.h"
+#include "sisusb_init.h"
+
+#ifdef INCL_SISUSB_CON
+
+#define sisusbcon_writew(val, addr) (*(addr) = (val))
+#define sisusbcon_readw(addr) (*(addr))
+#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)
+#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)
+
+/* vc_data -> sisusb conversion table */
+static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
+
+/* Forward declaration */
+static const struct consw sisusb_con;
+
+static inline void
+sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
+{
+ count /= 2;
+ while (count--)
+ sisusbcon_writew(c, s++);
+}
+
+static inline void
+sisusb_initialize(struct sisusb_usb_data *sisusb)
+{
+ /* Reset cursor and start address */
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))
+ return;
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))
+ return;
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))
+ return;
+ sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);
+}
+
+static inline void
+sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)
+{
+ sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+ sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+}
+
+void
+sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)
+{
+ if (sisusb->sisusb_cursor_loc == location)
+ return;
+
+ sisusb->sisusb_cursor_loc = location;
+
+ /* Hardware bug: Text cursor appears twice or not at all
+ * at some positions. Work around it with the cursor skew
+ * bits.
+ */
+
+ if ((location & 0x0007) == 0x0007) {
+ sisusb->bad_cursor_pos = 1;
+ location--;
+ if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))
+ return;
+ } else if (sisusb->bad_cursor_pos) {
+ if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))
+ return;
+ sisusb->bad_cursor_pos = 0;
+ }
+
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))
+ return;
+ sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));
+}
+
+static inline struct sisusb_usb_data *
+sisusb_get_sisusb(unsigned short console)
+{
+ return mysisusbs[console];
+}
+
+static inline int
+sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)
+{
+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)
+ return 0;
+
+ return 1;
+}
+
+static struct sisusb_usb_data *
+sisusb_get_sisusb_lock_and_check(unsigned short console)
+{
+ struct sisusb_usb_data *sisusb;
+
+ /* We can't handle console calls in non-schedulable
+ * context due to our locks and the USB transport.
+ * So we simply ignore them. This should only affect
+ * some calls to printk.
+ */
+ if (in_atomic())
+ return NULL;
+
+ if (!(sisusb = sisusb_get_sisusb(console)))
+ return NULL;
+
+ mutex_lock(&sisusb->lock);
+
+ if (!sisusb_sisusb_valid(sisusb) ||
+ !sisusb->havethisconsole[console]) {
+ mutex_unlock(&sisusb->lock);
+ return NULL;
+ }
+
+ return sisusb;
+}
+
+static int
+sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)
+{
+ if (sisusb->is_gfx ||
+ sisusb->textmodedestroyed ||
+ c->vc_mode != KD_TEXT)
+ return 1;
+
+ return 0;
+}
+
+/* con_startup console interface routine */
+static const char *
+sisusbcon_startup(void)
+{
+ return "SISUSBCON";
+}
+
+/* con_init console interface routine */
+static void
+sisusbcon_init(struct vc_data *c, int init)
+{
+ struct sisusb_usb_data *sisusb;
+ int cols, rows;
+
+ /* This is called by do_take_over_console(),
+ * ie by us/under our control. It is
+ * only called after text mode and fonts
+ * are set up/restored.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
+ return;
+
+ mutex_lock(&sisusb->lock);
+
+ if (!sisusb_sisusb_valid(sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+ c->vc_can_do_color = 1;
+
+ c->vc_complement_mask = 0x7700;
+
+ c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;
+
+ sisusb->haveconsole = 1;
+
+ sisusb->havethisconsole[c->vc_num] = 1;
+
+ /* We only support 640x400 */
+ c->vc_scan_lines = 400;
+
+ c->vc_font.height = sisusb->current_font_height;
+
+ /* We only support width = 8 */
+ cols = 80;
+ rows = c->vc_scan_lines / c->vc_font.height;
+
+ /* Increment usage count for our sisusb.
+ * Doing so saves us from upping/downing
+ * the disconnect semaphore; we can't
+ * lose our sisusb until this is undone
+ * in con_deinit. For all other console
+ * interface functions, it suffices to
+ * use sisusb->lock and do a quick check
+ * of sisusb for device disconnection.
+ */
+ kref_get(&sisusb->kref);
+
+ if (!*c->vc_uni_pagedir_loc)
+ con_set_default_unimap(c);
+
+ mutex_unlock(&sisusb->lock);
+
+ if (init) {
+ c->vc_cols = cols;
+ c->vc_rows = rows;
+ } else
+ vc_resize(c, cols, rows);
+}
+
+/* con_deinit console interface routine */
+static void
+sisusbcon_deinit(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ int i;
+
+ /* This is called by do_take_over_console()
+ * and others, ie not under our control.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
+ return;
+
+ mutex_lock(&sisusb->lock);
+
+ /* Clear ourselves in mysisusbs */
+ mysisusbs[c->vc_num] = NULL;
+
+ sisusb->havethisconsole[c->vc_num] = 0;
+
+ /* Free our font buffer if all consoles are gone */
+ if (sisusb->font_backup) {
+ for(i = 0; i < MAX_NR_CONSOLES; i++) {
+ if (sisusb->havethisconsole[c->vc_num])
+ break;
+ }
+ if (i == MAX_NR_CONSOLES) {
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+ }
+ }
+
+ mutex_unlock(&sisusb->lock);
+
+ /* decrement the usage count on our sisusb */
+ kref_put(&sisusb->kref, sisusb_delete);
+}
+
+/* interface routine */
+static u8
+sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
+ u8 blink, u8 underline, u8 reverse, u8 unused)
+{
+ u8 attr = color;
+
+ if (underline)
+ attr = (attr & 0xf0) | c->vc_ulcolor;
+ else if (intensity == 0)
+ attr = (attr & 0xf0) | c->vc_halfcolor;
+
+ if (reverse)
+ attr = ((attr) & 0x88) |
+ ((((attr) >> 4) |
+ ((attr) << 4)) & 0x77);
+
+ if (blink)
+ attr ^= 0x80;
+
+ if (intensity == 2)
+ attr ^= 0x08;
+
+ return attr;
+}
+
+/* Interface routine */
+static void
+sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
+{
+ /* Invert a region. This is called with a pointer
+ * to the console's internal screen buffer. So we
+ * simply do the inversion there and rely on
+ * a call to putc(s) to update the real screen.
+ */
+
+ while (count--) {
+ u16 a = sisusbcon_readw(p);
+
+ a = ((a) & 0x88ff) |
+ (((a) & 0x7000) >> 4) |
+ (((a) & 0x0700) << 4);
+
+ sisusbcon_writew(a, p++);
+ }
+}
+
+#define SISUSB_VADDR(x,y) \
+ ((u16 *)c->vc_origin + \
+ (y) * sisusb->sisusb_num_columns + \
+ (x))
+
+#define SISUSB_HADDR(x,y) \
+ ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
+ (y) * sisusb->sisusb_num_columns + \
+ (x))
+
+/* Interface routine */
+static void
+sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+ (long)SISUSB_HADDR(x, y), 2, &written);
+
+ mutex_unlock(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
+ int count, int y, int x)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ u16 *dest;
+ int i;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Need to put the characters into the buffer ourselves,
+ * because the vt does this AFTER calling us.
+ */
+
+ dest = SISUSB_VADDR(x, y);
+
+ for (i = count; i > 0; i--)
+ sisusbcon_writew(sisusbcon_readw(s++), dest++);
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+ (long)SISUSB_HADDR(x, y), count * 2, &written);
+
+ mutex_unlock(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
+{
+ struct sisusb_usb_data *sisusb;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+ int i, length, cols;
+ u16 *dest;
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Need to clear buffer ourselves, because the vt does
+ * this AFTER calling us.
+ */
+
+ dest = SISUSB_VADDR(x, y);
+
+ cols = sisusb->sisusb_num_columns;
+
+ if (width > cols)
+ width = cols;
+
+ if (x == 0 && width >= c->vc_cols) {
+
+ sisusbcon_memsetw(dest, eattr, height * cols * 2);
+
+ } else {
+
+ for (i = height; i > 0; i--, dest += cols)
+ sisusbcon_memsetw(dest, eattr, width * 2);
+
+ }
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+ length = ((height * cols) - x - (cols - width - x)) * 2;
+
+
+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
+ (long)SISUSB_HADDR(x, y), length, &written);
+
+ mutex_unlock(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_bmove(struct vc_data *c, int sy, int sx,
+ int dy, int dx, int height, int width)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ int cols, length;
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ cols = sisusb->sisusb_num_columns;
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+ length = ((height * cols) - dx - (cols - width - dx)) * 2;
+
+
+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
+ (long)SISUSB_HADDR(dx, dy), length, &written);
+
+ mutex_unlock(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_switch(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ int length;
+
+ /* Returnvalue 0 means we have fully restored screen,
+ * and vt doesn't need to call do_update_region().
+ * Returnvalue != 0 naturally means the opposite.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ /* Don't write to screen if in gfx mode */
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return 0;
+ }
+
+ /* That really should not happen. It would mean we are
+ * being called while the vc is using its private buffer
+ * as origin.
+ */
+ if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
+ mutex_unlock(&sisusb->lock);
+ dev_dbg(&sisusb->sisusb_dev->dev, "ASSERT ORIGIN != SCREENBUF!\n");
+ return 0;
+ }
+
+ /* Check that we don't copy too much */
+ length = min((int)c->vc_screenbuf_size,
+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+ /* Restore the screen contents */
+ sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
+ length);
+
+ sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
+ (long)SISUSB_HADDR(0, 0),
+ length, &written);
+
+ mutex_unlock(&sisusb->lock);
+
+ return 0;
+}
+
+/* interface routine */
+static void
+sisusbcon_save_screen(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ int length;
+
+ /* Save the current screen contents to vc's private
+ * buffer.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+ /* Check that we don't copy too much */
+ length = min((int)c->vc_screenbuf_size,
+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+ /* Save the screen contents to vc's private buffer */
+ sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
+ length);
+
+ mutex_unlock(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ struct sisusb_usb_data *sisusb;
+ int i, j;
+
+ /* Return value not used by vt */
+
+ if (!CON_IS_VISIBLE(c))
+ return -EINVAL;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -EINVAL;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ for (i = j = 0; i < 16; i++) {
+ if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ }
+
+ mutex_unlock(&sisusb->lock);
+
+ return 0;
+}
+
+/* interface routine */
+static int
+sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
+{
+ struct sisusb_usb_data *sisusb;
+ u8 sr1, cr17, pmreg, cr63;
+ ssize_t written;
+ int ret = 0;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (mode_switch)
+ sisusb->is_gfx = blank ? 1 : 0;
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return 0;
+ }
+
+ switch (blank) {
+
+ case 1: /* Normal blanking: Clear screen */
+ case -1:
+ sisusbcon_memsetw((u16 *)c->vc_origin,
+ c->vc_video_erase_char,
+ c->vc_screenbuf_size);
+ sisusb_copy_memory(sisusb,
+ (unsigned char *)c->vc_origin,
+ (u32)(sisusb->vrambase +
+ (c->vc_origin - sisusb->scrbuf)),
+ c->vc_screenbuf_size, &written);
+ sisusb->con_blanked = 1;
+ ret = 1;
+ break;
+
+ default: /* VESA blanking */
+ switch (blank) {
+ case 0: /* Unblank */
+ sr1 = 0x00;
+ cr17 = 0x80;
+ pmreg = 0x00;
+ cr63 = 0x00;
+ ret = 1;
+ sisusb->con_blanked = 0;
+ break;
+ case VESA_VSYNC_SUSPEND + 1:
+ sr1 = 0x20;
+ cr17 = 0x80;
+ pmreg = 0x80;
+ cr63 = 0x40;
+ break;
+ case VESA_HSYNC_SUSPEND + 1:
+ sr1 = 0x20;
+ cr17 = 0x80;
+ pmreg = 0x40;
+ cr63 = 0x40;
+ break;
+ case VESA_POWERDOWN + 1:
+ sr1 = 0x20;
+ cr17 = 0x00;
+ pmreg = 0xc0;
+ cr63 = 0x40;
+ break;
+ default:
+ mutex_unlock(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);
+ sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);
+ sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);
+ sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);
+
+ }
+
+ mutex_unlock(&sisusb->lock);
+
+ return ret;
+}
+
+/* interface routine */
+static int
+sisusbcon_scrolldelta(struct vc_data *c, int lines)
+{
+ struct sisusb_usb_data *sisusb;
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ /* The return value does not seem to be used */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return 0;
+ }
+
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+
+ if (sisusb->con_rolled_over >
+ (c->vc_scr_end - sisusb->scrbuf) + margin) {
+
+ ul = c->vc_scr_end - sisusb->scrbuf;
+ we = sisusb->con_rolled_over + c->vc_size_row;
+
+ } else {
+
+ ul = 0;
+ we = sisusb->scrbuf_size;
+
+ }
+
+ p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +
+ lines * c->vc_size_row;
+
+ st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;
+
+ if (st < 2 * margin)
+ margin = 0;
+
+ if (p < margin)
+ p = 0;
+
+ if (p > st - margin)
+ p = st;
+
+ c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;
+ }
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ mutex_unlock(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static void
+sisusbcon_cursor(struct vc_data *c, int mode)
+{
+ struct sisusb_usb_data *sisusb;
+ int from, to, baseline;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+ if (c->vc_origin != c->vc_visible_origin) {
+ c->vc_visible_origin = c->vc_origin;
+ sisusbcon_set_start_address(sisusb, c);
+ }
+
+ if (mode == CM_ERASE) {
+ sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
+ sisusb->sisusb_cursor_size_to = -1;
+ mutex_unlock(&sisusb->lock);
+ return;
+ }
+
+ sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);
+
+ baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
+
+ switch (c->vc_cursor_type & 0x0f) {
+ case CUR_BLOCK: from = 1;
+ to = c->vc_font.height;
+ break;
+ case CUR_TWO_THIRDS: from = c->vc_font.height / 3;
+ to = baseline;
+ break;
+ case CUR_LOWER_HALF: from = c->vc_font.height / 2;
+ to = baseline;
+ break;
+ case CUR_LOWER_THIRD: from = (c->vc_font.height * 2) / 3;
+ to = baseline;
+ break;
+ case CUR_NONE: from = 31;
+ to = 30;
+ break;
+ default:
+ case CUR_UNDERLINE: from = baseline - 1;
+ to = baseline;
+ break;
+ }
+
+ if (sisusb->sisusb_cursor_size_from != from ||
+ sisusb->sisusb_cursor_size_to != to) {
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0a, from);
+ sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);
+
+ sisusb->sisusb_cursor_size_from = from;
+ sisusb->sisusb_cursor_size_to = to;
+ }
+
+ mutex_unlock(&sisusb->lock);
+}
+
+static int
+sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
+ int t, int b, int dir, int lines)
+{
+ int cols = sisusb->sisusb_num_columns;
+ int length = ((b - t) * cols) * 2;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+
+ /* sisusb->lock is down */
+
+ /* Scroll an area which does not match the
+ * visible screen's dimensions. This needs
+ * to be done separately, as it does not
+ * use hardware panning.
+ */
+
+ switch (dir) {
+
+ case SM_UP:
+ sisusbcon_memmovew(SISUSB_VADDR(0, t),
+ SISUSB_VADDR(0, t + lines),
+ (b - t - lines) * cols * 2);
+ sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
+ lines * cols * 2);
+ break;
+
+ case SM_DOWN:
+ sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
+ SISUSB_VADDR(0, t),
+ (b - t - lines) * cols * 2);
+ sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
+ lines * cols * 2);
+ break;
+ }
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
+ (long)SISUSB_HADDR(0, t), length, &written);
+
+ mutex_unlock(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+ struct sisusb_usb_data *sisusb;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+ int copyall = 0;
+ unsigned long oldorigin;
+ unsigned int delta = lines * c->vc_size_row;
+ u32 originoffset;
+
+ /* Returning != 0 means we have done the scrolling successfully.
+ * Returning 0 makes vt do the scrolling on its own.
+ * Note that con_scroll is only called if the console is
+ * visible. In that case, the origin should be our buffer,
+ * not the vt's private one.
+ */
+
+ if (!lines)
+ return 1;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ mutex_unlock(&sisusb->lock);
+ return 0;
+ }
+
+ /* Special case */
+ if (t || b != c->vc_rows)
+ return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);
+
+ if (c->vc_origin != c->vc_visible_origin) {
+ c->vc_visible_origin = c->vc_origin;
+ sisusbcon_set_start_address(sisusb, c);
+ }
+
+ /* limit amount to maximum realistic size */
+ if (lines > c->vc_rows)
+ lines = c->vc_rows;
+
+ oldorigin = c->vc_origin;
+
+ switch (dir) {
+
+ case SM_UP:
+
+ if (c->vc_scr_end + delta >=
+ sisusb->scrbuf + sisusb->scrbuf_size) {
+ sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
+ (u16 *)(oldorigin + delta),
+ c->vc_screenbuf_size - delta);
+ c->vc_origin = sisusb->scrbuf;
+ sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;
+ copyall = 1;
+ } else
+ c->vc_origin += delta;
+
+ sisusbcon_memsetw(
+ (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),
+ eattr, delta);
+
+ break;
+
+ case SM_DOWN:
+
+ if (oldorigin - delta < sisusb->scrbuf) {
+ sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
+ sisusb->scrbuf_size -
+ c->vc_screenbuf_size +
+ delta),
+ (u16 *)oldorigin,
+ c->vc_screenbuf_size - delta);
+ c->vc_origin = sisusb->scrbuf +
+ sisusb->scrbuf_size -
+ c->vc_screenbuf_size;
+ sisusb->con_rolled_over = 0;
+ copyall = 1;
+ } else
+ c->vc_origin -= delta;
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+
+ scr_memsetw((u16 *)(c->vc_origin), eattr, delta);
+
+ break;
+ }
+
+ originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
+
+ if (copyall)
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin,
+ (u32)(sisusb->vrambase + originoffset),
+ c->vc_screenbuf_size, &written);
+ else if (dir == SM_UP)
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin + c->vc_screenbuf_size - delta,
+ (u32)sisusb->vrambase + originoffset +
+ c->vc_screenbuf_size - delta,
+ delta, &written);
+ else
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin,
+ (u32)(sisusb->vrambase + originoffset),
+ delta, &written);
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+ c->vc_visible_origin = c->vc_origin;
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
+
+ mutex_unlock(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_set_origin(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+
+ /* Returning != 0 means we were successful.
+ * Returning 0 will vt make to use its own
+ * screenbuffer as the origin.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
+ mutex_unlock(&sisusb->lock);
+ return 0;
+ }
+
+ c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ sisusb->con_rolled_over = 0;
+
+ mutex_unlock(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows,
+ unsigned int user)
+{
+ struct sisusb_usb_data *sisusb;
+ int fh;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ fh = sisusb->current_font_height;
+
+ mutex_unlock(&sisusb->lock);
+
+ /* We are quite unflexible as regards resizing. The vt code
+ * handles sizes where the line length isn't equal the pitch
+ * quite badly. As regards the rows, our panning tricks only
+ * work well if the number of rows equals the visible number
+ * of rows.
+ */
+
+ if (newcols != 80 || c->vc_scan_lines / fh != newrows)
+ return -EINVAL;
+
+ return 0;
+}
+
+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)
+{
+ int font_select = 0x00, i, err = 0;
+ u32 offset = 0;
+ u8 dummy;
+
+ /* sisusb->lock is down */
+
+ /*
+ * The default font is kept in slot 0.
+ * A user font is loaded in slot 2 (256 ch)
+ * or 2+3 (512 ch).
+ */
+
+ if ((slot != 0 && slot != 2) || !fh) {
+ if (uplock)
+ mutex_unlock(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ if (set)
+ sisusb->font_slot = slot;
+
+ /* Default font is always 256 */
+ if (slot == 0)
+ ch512 = 0;
+ else
+ offset = 4 * cmapsz;
+
+ font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);
+
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */
+
+ if (err)
+ goto font_op_error;
+
+ if (arg) {
+ if (set)
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_writeb(sisusb,
+ sisusb->vrambase + offset + i,
+ arg[i]);
+ if (err)
+ break;
+ }
+ else
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_readb(sisusb,
+ sisusb->vrambase + offset + i,
+ &arg[i]);
+ if (err)
+ break;
+ }
+
+ /*
+ * In 512-character mode, the character map is not contiguous if
+ * we want to remain EGA compatible -- which we do
+ */
+
+ if (ch512) {
+ if (set)
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_writeb(sisusb,
+ sisusb->vrambase + offset +
+ (2 * cmapsz) + i,
+ arg[cmapsz + i]);
+ if (err)
+ break;
+ }
+ else
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_readb(sisusb,
+ sisusb->vrambase + offset +
+ (2 * cmapsz) + i,
+ &arg[cmapsz + i]);
+ if (err)
+ break;
+ }
+ }
+ }
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */
+ if (set)
+ sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */
+
+ if (err)
+ goto font_op_error;
+
+ if ((set) && (ch512 != sisusb->current_font_512)) {
+
+ /* Font is shared among all our consoles.
+ * And so is the hi_font_mask.
+ */
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *d = vc_cons[i].d;
+ if (d && d->vc_sw == &sisusb_con)
+ d->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+ }
+
+ sisusb->current_font_512 = ch512;
+
+ /* color plane enable register:
+ 256-char: enable intensity bit
+ 512-char: disable intensity bit */
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ sisusb_setreg(sisusb, SISAR, 0x12);
+ sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);
+
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ sisusb_setreg(sisusb, SISAR, 0x20);
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ }
+
+ if (dorecalc) {
+
+ /*
+ * Adjust the screen to fit a font of a certain height
+ */
+
+ unsigned char ovr, vde, fsr;
+ int rows = 0, maxscan = 0;
+
+ if (c) {
+
+ /* Number of video rows */
+ rows = c->vc_scan_lines / fh;
+ /* Scan lines to actually display-1 */
+ maxscan = rows * fh - 1;
+
+ /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
+ rows, maxscan, fh, c->vc_scan_lines);*/
+
+ sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);
+ vde = maxscan & 0xff;
+ ovr = (ovr & 0xbd) |
+ ((maxscan & 0x100) >> 7) |
+ ((maxscan & 0x200) >> 3);
+ sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);
+ sisusb_setidxreg(sisusb, SISCR, 0x12, vde);
+
+ }
+
+ sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);
+ fsr = (fsr & 0xe0) | (fh - 1);
+ sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);
+ sisusb->current_font_height = fh;
+
+ sisusb->sisusb_cursor_size_from = -1;
+ sisusb->sisusb_cursor_size_to = -1;
+
+ }
+
+ if (uplock)
+ mutex_unlock(&sisusb->lock);
+
+ if (dorecalc && c) {
+ int rows = c->vc_scan_lines / fh;
+
+ /* Now adjust our consoles' size */
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *vc = vc_cons[i].d;
+
+ if (vc && vc->vc_sw == &sisusb_con) {
+ if (CON_IS_VISIBLE(vc)) {
+ vc->vc_sw->con_cursor(vc, CM_DRAW);
+ }
+ vc->vc_font.height = fh;
+ vc_resize(vc, 0, rows);
+ }
+ }
+ }
+
+ return 0;
+
+font_op_error:
+ if (uplock)
+ mutex_unlock(&sisusb->lock);
+
+ return -EIO;
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_set(struct vc_data *c, struct console_font *font,
+ unsigned flags)
+{
+ struct sisusb_usb_data *sisusb;
+ unsigned charcount = font->charcount;
+
+ if (font->width != 8 || (charcount != 256 && charcount != 512))
+ return -EINVAL;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ /* sisusb->lock is down */
+
+ /* Save the user-provided font into a buffer. This
+ * is used for restoring text mode after quitting
+ * from X and for the con_getfont routine.
+ */
+ if (sisusb->font_backup) {
+ if (sisusb->font_backup_size < charcount) {
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+ }
+ }
+
+ if (!sisusb->font_backup)
+ sisusb->font_backup = vmalloc(charcount * 32);
+
+ if (sisusb->font_backup) {
+ memcpy(sisusb->font_backup, font->data, charcount * 32);
+ sisusb->font_backup_size = charcount;
+ sisusb->font_backup_height = font->height;
+ sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;
+ }
+
+ /* do_font_op ups sisusb->lock */
+
+ return sisusbcon_do_font_op(sisusb, 1, 2, font->data,
+ 8192, (charcount == 512),
+ (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,
+ c, font->height, 1);
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_get(struct vc_data *c, struct console_font *font)
+{
+ struct sisusb_usb_data *sisusb;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ /* sisusb->lock is down */
+
+ font->width = 8;
+ font->height = c->vc_font.height;
+ font->charcount = 256;
+
+ if (!font->data) {
+ mutex_unlock(&sisusb->lock);
+ return 0;
+ }
+
+ if (!sisusb->font_backup) {
+ mutex_unlock(&sisusb->lock);
+ return -ENODEV;
+ }
+
+ /* Copy 256 chars only, like vgacon */
+ memcpy(font->data, sisusb->font_backup, 256 * 32);
+
+ mutex_unlock(&sisusb->lock);
+
+ return 0;
+}
+
+/*
+ * The console `switch' structure for the sisusb console
+ */
+
+static const struct consw sisusb_con = {
+ .owner = THIS_MODULE,
+ .con_startup = sisusbcon_startup,
+ .con_init = sisusbcon_init,
+ .con_deinit = sisusbcon_deinit,
+ .con_clear = sisusbcon_clear,
+ .con_putc = sisusbcon_putc,
+ .con_putcs = sisusbcon_putcs,
+ .con_cursor = sisusbcon_cursor,
+ .con_scroll = sisusbcon_scroll,
+ .con_bmove = sisusbcon_bmove,
+ .con_switch = sisusbcon_switch,
+ .con_blank = sisusbcon_blank,
+ .con_font_set = sisusbcon_font_set,
+ .con_font_get = sisusbcon_font_get,
+ .con_set_palette = sisusbcon_set_palette,
+ .con_scrolldelta = sisusbcon_scrolldelta,
+ .con_build_attr = sisusbcon_build_attr,
+ .con_invert_region = sisusbcon_invert_region,
+ .con_set_origin = sisusbcon_set_origin,
+ .con_save_screen = sisusbcon_save_screen,
+ .con_resize = sisusbcon_resize,
+};
+
+/* Our very own dummy console driver */
+
+static const char *sisusbdummycon_startup(void)
+{
+ return "SISUSBVGADUMMY";
+}
+
+static void sisusbdummycon_init(struct vc_data *vc, int init)
+{
+ vc->vc_can_do_color = 1;
+ if (init) {
+ vc->vc_cols = 80;
+ vc->vc_rows = 25;
+ } else
+ vc_resize(vc, 80, 25);
+}
+
+static int sisusbdummycon_dummy(void)
+{
+ return 0;
+}
+
+#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy
+
+static const struct consw sisusb_dummy_con = {
+ .owner = THIS_MODULE,
+ .con_startup = sisusbdummycon_startup,
+ .con_init = sisusbdummycon_init,
+ .con_deinit = SISUSBCONDUMMY,
+ .con_clear = SISUSBCONDUMMY,
+ .con_putc = SISUSBCONDUMMY,
+ .con_putcs = SISUSBCONDUMMY,
+ .con_cursor = SISUSBCONDUMMY,
+ .con_scroll = SISUSBCONDUMMY,
+ .con_bmove = SISUSBCONDUMMY,
+ .con_switch = SISUSBCONDUMMY,
+ .con_blank = SISUSBCONDUMMY,
+ .con_font_set = SISUSBCONDUMMY,
+ .con_font_get = SISUSBCONDUMMY,
+ .con_font_default = SISUSBCONDUMMY,
+ .con_font_copy = SISUSBCONDUMMY,
+ .con_set_palette = SISUSBCONDUMMY,
+ .con_scrolldelta = SISUSBCONDUMMY,
+};
+
+int
+sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+{
+ int i, ret;
+
+ mutex_lock(&sisusb->lock);
+
+ /* Erm.. that should not happen */
+ if (sisusb->haveconsole || !sisusb->SiS_Pr) {
+ mutex_unlock(&sisusb->lock);
+ return 1;
+ }
+
+ sisusb->con_first = first;
+ sisusb->con_last = last;
+
+ if (first > last ||
+ first > MAX_NR_CONSOLES ||
+ last > MAX_NR_CONSOLES) {
+ mutex_unlock(&sisusb->lock);
+ return 1;
+ }
+
+ /* If gfxcore not initialized or no consoles given, quit graciously */
+ if (!sisusb->gfxinit || first < 1 || last < 1) {
+ mutex_unlock(&sisusb->lock);
+ return 0;
+ }
+
+ sisusb->sisusb_cursor_loc = -1;
+ sisusb->sisusb_cursor_size_from = -1;
+ sisusb->sisusb_cursor_size_to = -1;
+
+ /* Set up text mode (and upload default font) */
+ if (sisusb_reset_text_mode(sisusb, 1)) {
+ mutex_unlock(&sisusb->lock);
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to set up text mode\n");
+ return 1;
+ }
+
+ /* Initialize some gfx registers */
+ sisusb_initialize(sisusb);
+
+ for (i = first - 1; i <= last - 1; i++) {
+ /* Save sisusb for our interface routines */
+ mysisusbs[i] = sisusb;
+ }
+
+ /* Initial console setup */
+ sisusb->sisusb_num_columns = 80;
+
+ /* Use a 32K buffer (matches b8000-bffff area) */
+ sisusb->scrbuf_size = 32 * 1024;
+
+ /* Allocate screen buffer */
+ if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
+ mutex_unlock(&sisusb->lock);
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate screen buffer\n");
+ return 1;
+ }
+
+ mutex_unlock(&sisusb->lock);
+
+ /* Now grab the desired console(s) */
+ console_lock();
+ ret = do_take_over_console(&sisusb_con, first - 1, last - 1, 0);
+ console_unlock();
+ if (!ret)
+ sisusb->haveconsole = 1;
+ else {
+ for (i = first - 1; i <= last - 1; i++)
+ mysisusbs[i] = NULL;
+ }
+
+ return ret;
+}
+
+void
+sisusb_console_exit(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ /* This is called if the device is disconnected
+ * and while disconnect and lock semaphores
+ * are up. This should be save because we
+ * can't lose our sisusb any other way but by
+ * disconnection (and hence, the disconnect
+ * sema is for protecting all other access
+ * functions from disconnection, not the
+ * other way round).
+ */
+
+ /* Now what do we do in case of disconnection:
+ * One alternative would be to simply call
+ * give_up_console(). Nah, not a good idea.
+ * give_up_console() is obviously buggy as it
+ * only discards the consw pointer from the
+ * driver_map, but doesn't adapt vc->vc_sw
+ * of the affected consoles. Hence, the next
+ * call to any of the console functions will
+ * eventually take a trip to oops county.
+ * Also, give_up_console for some reason
+ * doesn't decrement our module refcount.
+ * Instead, we switch our consoles to a private
+ * dummy console. This, of course, keeps our
+ * refcount up as well, but it works perfectly.
+ */
+
+ if (sisusb->haveconsole) {
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ if (sisusb->havethisconsole[i]) {
+ console_lock();
+ do_take_over_console(&sisusb_dummy_con, i, i, 0);
+ console_unlock();
+ /* At this point, con_deinit for all our
+ * consoles is executed by do_take_over_console().
+ */
+ }
+ sisusb->haveconsole = 0;
+ }
+
+ vfree((void *)sisusb->scrbuf);
+ sisusb->scrbuf = 0;
+
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+}
+
+void __init sisusb_init_concode(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ mysisusbs[i] = NULL;
+}
+
+#endif /* INCL_CON */
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
new file mode 100644
index 00000000000..bf0032ca35e
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -0,0 +1,958 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * Display mode initializing code
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * * notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * * notice, this list of conditions and the following disclaimer in the
+ * * documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+
+#include "sisusb_init.h"
+
+/*********************************************/
+/* POINTER INITIALIZATION */
+/*********************************************/
+
+static void SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
+{
+ SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo;
+ SiS_Pr->SiS_StandTable = SiSUSB_StandTable;
+
+ SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable;
+ SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable;
+ SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex;
+ SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table;
+
+ SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;
+}
+
+/*********************************************/
+/* HELPER: SetReg, GetReg */
+/*********************************************/
+
+static void
+SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short data)
+{
+ sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
+}
+
+static void
+SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short data)
+{
+ sisusb_setreg(SiS_Pr->sisusb, port, data);
+}
+
+static unsigned char
+SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index)
+{
+ u8 data;
+
+ sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
+
+ return data;
+}
+
+static unsigned char
+SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
+{
+ u8 data;
+
+ sisusb_getreg(SiS_Pr->sisusb, port, &data);
+
+ return data;
+}
+
+static void
+SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short DataAND,
+ unsigned short DataOR)
+{
+ sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
+}
+
+static void
+SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short DataAND)
+{
+ sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
+}
+
+static void
+SiS_SetRegOR(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short DataOR)
+{
+ sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
+}
+
+/*********************************************/
+/* HELPER: DisplayOn, DisplayOff */
+/*********************************************/
+
+static void SiS_DisplayOn(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
+}
+
+/*********************************************/
+/* HELPER: Init Port Addresses */
+/*********************************************/
+
+static void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
+{
+ SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
+ SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
+ SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
+ SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
+ SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
+ SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
+ SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
+ SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
+ SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
+ SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
+ SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+ SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
+ SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
+ SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
+ SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+}
+
+/*********************************************/
+/* HELPER: GetSysFlags */
+/*********************************************/
+
+static void SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
+{
+ SiS_Pr->SiS_MyCR63 = 0x63;
+}
+
+/*********************************************/
+/* HELPER: Init PCI & Engines */
+/*********************************************/
+
+static void SiSInitPCIetc(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
+ /* - Enable 2D (0x40)
+ * - Enable 3D (0x02)
+ * - Enable 3D vertex command fetch (0x10)
+ * - Enable 3D command parser (0x08)
+ * - Enable 3D G/L transformation engine (0x80)
+ */
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
+}
+
+/*********************************************/
+/* HELPER: SET SEGMENT REGISTERS */
+/*********************************************/
+
+static void SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp;
+
+ value &= 0x00ff;
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
+ temp |= (value >> 4);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
+ temp |= (value & 0x0f);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp;
+
+ value &= 0x00ff;
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
+ temp |= (value & 0xf0);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
+ temp |= (value << 4);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ SiS_SetSegRegLower(SiS_Pr, value);
+ SiS_SetSegRegUpper(SiS_Pr, value);
+}
+
+static void SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetSegmentReg(SiS_Pr, 0);
+}
+
+static void
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp = value >> 8;
+
+ temp &= 0x07;
+ temp |= (temp << 4);
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
+ SiS_SetSegmentReg(SiS_Pr, value);
+}
+
+static void SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetSegmentRegOver(SiS_Pr, 0);
+}
+
+static void SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
+{
+ SiS_ResetSegmentReg(SiS_Pr);
+ SiS_ResetSegmentRegOver(SiS_Pr);
+}
+
+/*********************************************/
+/* HELPER: SearchModeID */
+/*********************************************/
+
+static int
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex)
+{
+ if ((*ModeNo) <= 0x13) {
+
+ if ((*ModeNo) != 0x03)
+ return 0;
+
+ (*ModeIdIndex) = 0;
+
+ } else {
+
+ for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
+
+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID ==
+ (*ModeNo))
+ break;
+
+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID ==
+ 0xFF)
+ return 0;
+ }
+
+ }
+
+ return 1;
+}
+
+/*********************************************/
+/* HELPER: ENABLE CRT1 */
+/*********************************************/
+
+static void SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
+{
+ /* Enable CRT1 gating */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
+}
+
+/*********************************************/
+/* HELPER: GetColorDepth */
+/*********************************************/
+
+static unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
+ unsigned short modeflag;
+ short index;
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+ index = (modeflag & ModeTypeMask) - ModeEGA;
+ if (index < 0)
+ index = 0;
+ return ColorDepth[index];
+}
+
+/*********************************************/
+/* HELPER: GetOffset */
+/*********************************************/
+
+static unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short xres, temp, colordepth, infoflag;
+
+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
+
+ colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+ temp = xres / 16;
+
+ if (infoflag & InterlaceMode)
+ temp <<= 1;
+
+ temp *= colordepth;
+
+ if (xres % 16)
+ temp += (colordepth >> 1);
+
+ return temp;
+}
+
+/*********************************************/
+/* SEQ */
+/*********************************************/
+
+static void
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char SRdata;
+ int i;
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
+
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
+
+ for (i = 2; i <= 4; i++) {
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
+ }
+}
+
+/*********************************************/
+/* MISC */
+/*********************************************/
+
+static void
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
+
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
+}
+
+/*********************************************/
+/* CRTC */
+/*********************************************/
+
+static void
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char CRTCdata;
+ unsigned short i;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
+
+ for (i = 0; i <= 0x18; i++) {
+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
+ }
+}
+
+/*********************************************/
+/* ATT */
+/*********************************************/
+
+static void
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char ARdata;
+ unsigned short i;
+
+ for (i = 0; i <= 0x13; i++) {
+ ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
+ }
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
+
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+}
+
+/*********************************************/
+/* GRC */
+/*********************************************/
+
+static void
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char GRdata;
+ unsigned short i;
+
+ for (i = 0; i <= 0x08; i++) {
+ GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
+ }
+
+ if (SiS_Pr->SiS_ModeType > ModeVGA) {
+ /* 256 color disable */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
+ }
+}
+
+/*********************************************/
+/* CLEAR EXTENDED REGISTERS */
+/*********************************************/
+
+static void SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+ int i;
+
+ for (i = 0x0A; i <= 0x0E; i++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
+ }
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
+}
+
+/*********************************************/
+/* Get rate index */
+/*********************************************/
+
+static unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ unsigned short rrti, i, index, temp;
+
+ if (ModeNo <= 0x13)
+ return 0xFFFF;
+
+ index = SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
+ if (index > 0)
+ index--;
+
+ rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
+
+ i = 0;
+ do {
+ if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
+ break;
+
+ temp =
+ SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
+ if (temp < SiS_Pr->SiS_ModeType)
+ break;
+
+ i++;
+ index--;
+ } while (index != 0xFFFF);
+
+ i--;
+
+ return (rrti + i);
+}
+
+/*********************************************/
+/* SYNC */
+/*********************************************/
+
+static void SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
+{
+ unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
+ sync &= 0xC0;
+ sync |= 0x2f;
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
+}
+
+/*********************************************/
+/* CRTC/2 */
+/*********************************************/
+
+static void
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned char index;
+ unsigned short temp, i, j, modeflag;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
+
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
+
+ for (i = 0, j = 0; i <= 7; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for (j = 0x10; i <= 10; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for (j = 0x15; i <= 12; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for (j = 0x0A; i <= 15; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+
+ temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, temp);
+
+ temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+ if (modeflag & DoubleScanMode)
+ temp |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
+
+ if (SiS_Pr->SiS_ModeType > ModeVGA)
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
+}
+
+/*********************************************/
+/* OFFSET & PITCH */
+/*********************************************/
+/* (partly overruled by SetPitch() in XF86) */
+/*********************************************/
+
+static void
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ unsigned short temp;
+
+ temp = (du >> 8) & 0x0f;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
+
+ if (infoflag & InterlaceMode)
+ du >>= 1;
+
+ du <<= 5;
+ temp = (du >> 8) & 0xff;
+ if (du & 0xff)
+ temp++;
+ temp++;
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
+}
+
+/*********************************************/
+/* VCLK */
+/*********************************************/
+
+static void
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short rrti)
+{
+ unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+ unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+ unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xCF);
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2B, clka);
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2C, clkb);
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2D, 0x01);
+}
+
+/*********************************************/
+/* FIFO */
+/*********************************************/
+
+static void
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short mi)
+{
+ unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+ /* disable auto-threshold */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
+
+ if (ModeNo <= 0x13)
+ return;
+
+ if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
+ }
+}
+
+/*********************************************/
+/* MODE REGISTERS */
+/*********************************************/
+
+static void
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short rrti)
+{
+ unsigned short data = 0, VCLK = 0, index = 0;
+
+ if (ModeNo > 0x13) {
+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+ }
+
+ if (VCLK >= 166)
+ data |= 0x0c;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
+
+ if (VCLK >= 166)
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
+
+ /* DAC speed */
+ data = 0x03;
+ if (VCLK >= 260)
+ data = 0x00;
+ else if (VCLK >= 160)
+ data = 0x01;
+ else if (VCLK >= 135)
+ data = 0x02;
+
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
+}
+
+static void
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short data, infoflag = 0, modeflag;
+
+ if (ModeNo <= 0x13)
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ }
+
+ /* Disable DPMS */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
+
+ data = 0;
+ if (ModeNo > 0x13) {
+ if (SiS_Pr->SiS_ModeType > ModeEGA) {
+ data |= 0x02;
+ data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+ }
+ if (infoflag & InterlaceMode)
+ data |= 0x20;
+ }
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
+
+ data = 0;
+ if (infoflag & InterlaceMode) {
+ /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+ unsigned short hrs =
+ (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2))
+ - 3;
+ unsigned short hto =
+ (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8))
+ + 5;
+ data = hrs - (hto >> 1) + 3;
+ }
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
+
+ if (modeflag & HalfDCLK)
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
+
+ data = 0;
+ if (modeflag & LineCompareOff)
+ data = 0x08;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
+
+ if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
+
+ data = 0x60;
+ if (SiS_Pr->SiS_ModeType != ModeText) {
+ data ^= 0x60;
+ if (SiS_Pr->SiS_ModeType != ModeEGA)
+ data ^= 0xA0;
+ }
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
+
+ SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
+
+ if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
+ else
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
+}
+
+/*********************************************/
+/* LOAD DAC */
+/*********************************************/
+
+static void
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
+ unsigned short shiftflag, unsigned short dl, unsigned short ah,
+ unsigned short al, unsigned short dh)
+{
+ unsigned short d1, d2, d3;
+
+ switch (dl) {
+ case 0:
+ d1 = dh;
+ d2 = ah;
+ d3 = al;
+ break;
+ case 1:
+ d1 = ah;
+ d2 = al;
+ d3 = dh;
+ break;
+ default:
+ d1 = al;
+ d2 = dh;
+ d3 = ah;
+ }
+ SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
+ SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
+ SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
+}
+
+static void
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short mi)
+{
+ unsigned short data, data2, time, i, j, k, m, n, o;
+ unsigned short si, di, bx, sf;
+ unsigned long DACAddr, DACData;
+ const unsigned char *table = NULL;
+
+ if (ModeNo < 0x13)
+ data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
+ else
+ data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+ data &= DACInfoFlag;
+
+ j = time = 64;
+ if (data == 0x00)
+ table = SiS_MDA_DAC;
+ else if (data == 0x08)
+ table = SiS_CGA_DAC;
+ else if (data == 0x10)
+ table = SiS_EGA_DAC;
+ else {
+ j = 16;
+ time = 256;
+ table = SiS_VGA_DAC;
+ }
+
+ DACAddr = SiS_Pr->SiS_P3c8;
+ DACData = SiS_Pr->SiS_P3c9;
+ sf = 0;
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+ SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
+
+ for (i = 0; i < j; i++) {
+ data = table[i];
+ for (k = 0; k < 3; k++) {
+ data2 = 0;
+ if (data & 0x01)
+ data2 += 0x2A;
+ if (data & 0x02)
+ data2 += 0x15;
+ SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
+ data >>= 2;
+ }
+ }
+
+ if (time == 256) {
+ for (i = 16; i < 32; i++) {
+ data = table[i] << sf;
+ for (k = 0; k < 3; k++)
+ SiS_SetRegByte(SiS_Pr, DACData, data);
+ }
+ si = 32;
+ for (m = 0; m < 9; m++) {
+ di = si;
+ bx = si + 4;
+ for (n = 0; n < 3; n++) {
+ for (o = 0; o < 5; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+ table[di], table[bx],
+ table[si]);
+ si++;
+ }
+ si -= 2;
+ for (o = 0; o < 3; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+ table[di], table[si],
+ table[bx]);
+ si--;
+ }
+ }
+ si += 5;
+ }
+ }
+}
+
+/*********************************************/
+/* SET CRT1 REGISTER GROUP */
+/*********************************************/
+
+static void
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ unsigned short StandTableIndex, rrti;
+
+ SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+ if (ModeNo <= 0x13)
+ StandTableIndex = 0;
+ else
+ StandTableIndex = 1;
+
+ SiS_ResetSegmentRegisters(SiS_Pr);
+ SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+ SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+ SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+ SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+ SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+ SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+
+ rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if (rrti != 0xFFFF) {
+ SiS_SetCRT1Sync(SiS_Pr, rrti);
+ SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
+ }
+
+ SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+
+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_DisplayOn(SiS_Pr);
+}
+
+/*********************************************/
+/* SiSSetMode() */
+/*********************************************/
+
+int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+ unsigned short ModeIdIndex;
+ unsigned long BaseAddr = SiS_Pr->IOAddress;
+
+ SiSUSB_InitPtr(SiS_Pr);
+ SiSUSBRegInit(SiS_Pr, BaseAddr);
+ SiS_GetSysFlags(SiS_Pr);
+
+ if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
+ return 0;
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
+
+ SiSInitPCIetc(SiS_Pr);
+
+ ModeNo &= 0x7f;
+
+ SiS_Pr->SiS_ModeType =
+ SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
+
+ SiS_Pr->SiS_SetFlag = LowModeTests;
+
+ /* Set mode on CRT1 */
+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_HandleCRT1(SiS_Pr);
+
+ SiS_DisplayOn(SiS_Pr);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+ /* Store mode number */
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
+
+ return 1;
+}
+
+int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
+{
+ unsigned short ModeNo = 0;
+ int i;
+
+ SiSUSB_InitPtr(SiS_Pr);
+
+ if (VModeNo == 0x03) {
+
+ ModeNo = 0x03;
+
+ } else {
+
+ i = 0;
+ do {
+
+ if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
+ ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
+ break;
+ }
+
+ } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
+
+ }
+
+ if (!ModeNo)
+ return 0;
+
+ return SiSUSBSetMode(SiS_Pr, ModeNo);
+}
+
+#endif /* INCL_SISUSB_CON */
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
new file mode 100644
index 00000000000..c46ce42d448
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -0,0 +1,841 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Data and prototypes for init.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * * notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * * notice, this list of conditions and the following disclaimer in the
+ * * documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_INIT_H_
+#define _SISUSB_INIT_H_
+
+/* SiS_ModeType */
+#define ModeText 0x00
+#define ModeCGA 0x01
+#define ModeEGA 0x02
+#define ModeVGA 0x03
+#define Mode15Bpp 0x04
+#define Mode16Bpp 0x05
+#define Mode24Bpp 0x06
+#define Mode32Bpp 0x07
+
+#define ModeTypeMask 0x07
+#define IsTextMode 0x07
+
+#define DACInfoFlag 0x0018
+#define MemoryInfoFlag 0x01E0
+#define MemorySizeShift 5
+
+/* modeflag */
+#define Charx8Dot 0x0200
+#define LineCompareOff 0x0400
+#define CRT2Mode 0x0800
+#define HalfDCLK 0x1000
+#define NoSupportSimuTV 0x2000
+#define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
+#define DoubleScanMode 0x8000
+
+/* Infoflag */
+#define SupportTV 0x0008
+#define SupportTV1024 0x0800
+#define SupportCHTV 0x0800
+#define Support64048060Hz 0x0800 /* Special for 640x480 LCD */
+#define SupportHiVision 0x0010
+#define SupportYPbPr750p 0x1000
+#define SupportLCD 0x0020
+#define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */
+#define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */
+#define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */
+#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */
+#define InterlaceMode 0x0080
+#define SyncPP 0x0000
+#define SyncPN 0x4000
+#define SyncNP 0x8000
+#define SyncNN 0xc000
+
+/* SetFlag */
+#define ProgrammingCRT2 0x0001
+#define LowModeTests 0x0002
+#define LCDVESATiming 0x0008
+#define EnableLVDSDDA 0x0010
+#define SetDispDevSwitchFlag 0x0020
+#define CheckWinDos 0x0040
+#define SetDOSMode 0x0080
+
+/* Index in ModeResInfo table */
+#define SIS_RI_320x200 0
+#define SIS_RI_320x240 1
+#define SIS_RI_320x400 2
+#define SIS_RI_400x300 3
+#define SIS_RI_512x384 4
+#define SIS_RI_640x400 5
+#define SIS_RI_640x480 6
+#define SIS_RI_800x600 7
+#define SIS_RI_1024x768 8
+#define SIS_RI_1280x1024 9
+#define SIS_RI_1600x1200 10
+#define SIS_RI_1920x1440 11
+#define SIS_RI_2048x1536 12
+#define SIS_RI_720x480 13
+#define SIS_RI_720x576 14
+#define SIS_RI_1280x960 15
+#define SIS_RI_800x480 16
+#define SIS_RI_1024x576 17
+#define SIS_RI_1280x720 18
+#define SIS_RI_856x480 19
+#define SIS_RI_1280x768 20
+#define SIS_RI_1400x1050 21
+#define SIS_RI_1152x864 22 /* Up to here SiS conforming */
+#define SIS_RI_848x480 23
+#define SIS_RI_1360x768 24
+#define SIS_RI_1024x600 25
+#define SIS_RI_1152x768 26
+#define SIS_RI_768x576 27
+#define SIS_RI_1360x1024 28
+#define SIS_RI_1680x1050 29
+#define SIS_RI_1280x800 30
+#define SIS_RI_1920x1080 31
+#define SIS_RI_960x540 32
+#define SIS_RI_960x600 33
+
+#define SIS_VIDEO_CAPTURE 0x00 - 0x30
+#define SIS_VIDEO_PLAYBACK 0x02 - 0x30
+#define SIS_CRT2_PORT_04 0x04 - 0x30
+
+/* Mode numbers */
+static const unsigned short ModeIndex_320x200[] = { 0x59, 0x41, 0x00, 0x4f };
+static const unsigned short ModeIndex_320x240[] = { 0x50, 0x56, 0x00, 0x53 };
+static const unsigned short ModeIndex_400x300[] = { 0x51, 0x57, 0x00, 0x54 };
+static const unsigned short ModeIndex_512x384[] = { 0x52, 0x58, 0x00, 0x5c };
+static const unsigned short ModeIndex_640x400[] = { 0x2f, 0x5d, 0x00, 0x5e };
+static const unsigned short ModeIndex_640x480[] = { 0x2e, 0x44, 0x00, 0x62 };
+static const unsigned short ModeIndex_720x480[] = { 0x31, 0x33, 0x00, 0x35 };
+static const unsigned short ModeIndex_720x576[] = { 0x32, 0x34, 0x00, 0x36 };
+static const unsigned short ModeIndex_768x576[] = { 0x5f, 0x60, 0x00, 0x61 };
+static const unsigned short ModeIndex_800x480[] = { 0x70, 0x7a, 0x00, 0x76 };
+static const unsigned short ModeIndex_800x600[] = { 0x30, 0x47, 0x00, 0x63 };
+static const unsigned short ModeIndex_848x480[] = { 0x39, 0x3b, 0x00, 0x3e };
+static const unsigned short ModeIndex_856x480[] = { 0x3f, 0x42, 0x00, 0x45 };
+static const unsigned short ModeIndex_960x540[] = { 0x1d, 0x1e, 0x00, 0x1f };
+static const unsigned short ModeIndex_960x600[] = { 0x20, 0x21, 0x00, 0x22 };
+static const unsigned short ModeIndex_1024x768[] = { 0x38, 0x4a, 0x00, 0x64 };
+static const unsigned short ModeIndex_1024x576[] = { 0x71, 0x74, 0x00, 0x77 };
+static const unsigned short ModeIndex_1152x864[] = { 0x29, 0x2a, 0x00, 0x2b };
+static const unsigned short ModeIndex_1280x720[] = { 0x79, 0x75, 0x00, 0x78 };
+static const unsigned short ModeIndex_1280x768[] = { 0x23, 0x24, 0x00, 0x25 };
+static const unsigned short ModeIndex_1280x1024[] = { 0x3a, 0x4d, 0x00, 0x65 };
+
+static const unsigned char SiS_MDA_DAC[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
+};
+
+static const unsigned char SiS_CGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
+};
+
+static const unsigned char SiS_EGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
+ 0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
+ 0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
+ 0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D,
+ 0x02, 0x12, 0x06, 0x16, 0x03, 0x13, 0x07, 0x17,
+ 0x22, 0x32, 0x26, 0x36, 0x23, 0x33, 0x27, 0x37,
+ 0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
+};
+
+static const unsigned char SiS_VGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
+ 0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
+ 0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F,
+ 0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00,
+ 0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18,
+ 0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04,
+ 0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10,
+ 0x0B, 0x0C, 0x0D, 0x0F, 0x10
+};
+
+static const struct SiS_St SiSUSB_SModeIDTable[] = {
+ {0x03, 0x0010, 0x18, 0x02, 0x02, 0x00, 0x01, 0x03, 0x40},
+ {0xff, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct SiS_StResInfo_S SiSUSB_StResInfo[] = {
+ {640, 400},
+ {640, 350},
+ {720, 400},
+ {720, 350},
+ {640, 480}
+};
+
+static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] = {
+ {320, 200, 8, 8}, /* 0x00 */
+ {320, 240, 8, 8}, /* 0x01 */
+ {320, 400, 8, 8}, /* 0x02 */
+ {400, 300, 8, 8}, /* 0x03 */
+ {512, 384, 8, 8}, /* 0x04 */
+ {640, 400, 8, 16}, /* 0x05 */
+ {640, 480, 8, 16}, /* 0x06 */
+ {800, 600, 8, 16}, /* 0x07 */
+ {1024, 768, 8, 16}, /* 0x08 */
+ {1280, 1024, 8, 16}, /* 0x09 */
+ {1600, 1200, 8, 16}, /* 0x0a */
+ {1920, 1440, 8, 16}, /* 0x0b */
+ {2048, 1536, 8, 16}, /* 0x0c */
+ {720, 480, 8, 16}, /* 0x0d */
+ {720, 576, 8, 16}, /* 0x0e */
+ {1280, 960, 8, 16}, /* 0x0f */
+ {800, 480, 8, 16}, /* 0x10 */
+ {1024, 576, 8, 16}, /* 0x11 */
+ {1280, 720, 8, 16}, /* 0x12 */
+ {856, 480, 8, 16}, /* 0x13 */
+ {1280, 768, 8, 16}, /* 0x14 */
+ {1400, 1050, 8, 16}, /* 0x15 */
+ {1152, 864, 8, 16}, /* 0x16 */
+ {848, 480, 8, 16}, /* 0x17 */
+ {1360, 768, 8, 16}, /* 0x18 */
+ {1024, 600, 8, 16}, /* 0x19 */
+ {1152, 768, 8, 16}, /* 0x1a */
+ {768, 576, 8, 16}, /* 0x1b */
+ {1360, 1024, 8, 16}, /* 0x1c */
+ {1680, 1050, 8, 16}, /* 0x1d */
+ {1280, 800, 8, 16}, /* 0x1e */
+ {1920, 1080, 8, 16}, /* 0x1f */
+ {960, 540, 8, 16}, /* 0x20 */
+ {960, 600, 8, 16} /* 0x21 */
+};
+
+static const struct SiS_StandTable SiSUSB_StandTable[] = {
+ /* MD_3_400 - mode 0x03 - 400 */
+ {
+ 0x50, 0x18, 0x10, 0x1000,
+ {0x00, 0x03, 0x00, 0x02},
+ 0x67,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x0c, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff}
+ },
+ /* Generic for VGA and higher */
+ {
+ 0x00, 0x00, 0x00, 0x0000,
+ {0x01, 0x0f, 0x00, 0x0e},
+ 0x23,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x01, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff}
+ }
+};
+
+static const struct SiS_Ext SiSUSB_EModeIDTable[] = {
+ {0x2e, 0x0a1b, 0x0101, SIS_RI_640x480, 0x00, 0x00, 0x05, 0x05, 0x08, 2}, /* 640x480x8 */
+ {0x2f, 0x0a1b, 0x0100, SIS_RI_640x400, 0x00, 0x00, 0x05, 0x05, 0x10, 0}, /* 640x400x8 */
+ {0x30, 0x2a1b, 0x0103, SIS_RI_800x600, 0x00, 0x00, 0x07, 0x06, 0x00, 3}, /* 800x600x8 */
+ {0x31, 0x4a1b, 0x0000, SIS_RI_720x480, 0x00, 0x00, 0x06, 0x06, 0x11, -1}, /* 720x480x8 */
+ {0x32, 0x4a1b, 0x0000, SIS_RI_720x576, 0x00, 0x00, 0x06, 0x06, 0x12, -1}, /* 720x576x8 */
+ {0x33, 0x4a1d, 0x0000, SIS_RI_720x480, 0x00, 0x00, 0x06, 0x06, 0x11, -1}, /* 720x480x16 */
+ {0x34, 0x6a1d, 0x0000, SIS_RI_720x576, 0x00, 0x00, 0x06, 0x06, 0x12, -1}, /* 720x576x16 */
+ {0x35, 0x4a1f, 0x0000, SIS_RI_720x480, 0x00, 0x00, 0x06, 0x06, 0x11, -1}, /* 720x480x32 */
+ {0x36, 0x6a1f, 0x0000, SIS_RI_720x576, 0x00, 0x00, 0x06, 0x06, 0x12, -1}, /* 720x576x32 */
+ {0x38, 0x0a1b, 0x0105, SIS_RI_1024x768, 0x00, 0x00, 0x08, 0x07, 0x13, 4}, /* 1024x768x8 */
+ {0x3a, 0x0e3b, 0x0107, SIS_RI_1280x1024, 0x00, 0x00, 0x00, 0x00, 0x2f, 8}, /* 1280x1024x8 */
+ {0x41, 0x9a1d, 0x010e, SIS_RI_320x200, 0x00, 0x00, 0x04, 0x04, 0x1a, 0}, /* 320x200x16 */
+ {0x44, 0x0a1d, 0x0111, SIS_RI_640x480, 0x00, 0x00, 0x05, 0x05, 0x08, 2}, /* 640x480x16 */
+ {0x47, 0x2a1d, 0x0114, SIS_RI_800x600, 0x00, 0x00, 0x07, 0x06, 0x00, 3}, /* 800x600x16 */
+ {0x4a, 0x0a3d, 0x0117, SIS_RI_1024x768, 0x00, 0x00, 0x08, 0x07, 0x13, 4}, /* 1024x768x16 */
+ {0x4d, 0x0e7d, 0x011a, SIS_RI_1280x1024, 0x00, 0x00, 0x00, 0x00, 0x2f, 8}, /* 1280x1024x16 */
+ {0x50, 0x9a1b, 0x0132, SIS_RI_320x240, 0x00, 0x00, 0x04, 0x04, 0x1b, 2}, /* 320x240x8 */
+ {0x51, 0xba1b, 0x0133, SIS_RI_400x300, 0x00, 0x00, 0x07, 0x07, 0x1c, 3}, /* 400x300x8 */
+ {0x52, 0xba1b, 0x0134, SIS_RI_512x384, 0x00, 0x00, 0x00, 0x00, 0x1d, 4}, /* 512x384x8 */
+ {0x56, 0x9a1d, 0x0135, SIS_RI_320x240, 0x00, 0x00, 0x04, 0x04, 0x1b, 2}, /* 320x240x16 */
+ {0x57, 0xba1d, 0x0136, SIS_RI_400x300, 0x00, 0x00, 0x07, 0x07, 0x1c, 3}, /* 400x300x16 */
+ {0x58, 0xba1d, 0x0137, SIS_RI_512x384, 0x00, 0x00, 0x00, 0x00, 0x1d, 4}, /* 512x384x16 */
+ {0x59, 0x9a1b, 0x0138, SIS_RI_320x200, 0x00, 0x00, 0x04, 0x04, 0x1a, 0}, /* 320x200x8 */
+ {0x5c, 0xba1f, 0x0000, SIS_RI_512x384, 0x00, 0x00, 0x00, 0x00, 0x1d, 4}, /* 512x384x32 */
+ {0x5d, 0x0a1d, 0x0139, SIS_RI_640x400, 0x00, 0x00, 0x05, 0x07, 0x10, 0}, /* 640x400x16 */
+ {0x5e, 0x0a1f, 0x0000, SIS_RI_640x400, 0x00, 0x00, 0x05, 0x07, 0x10, 0}, /* 640x400x32 */
+ {0x62, 0x0a3f, 0x013a, SIS_RI_640x480, 0x00, 0x00, 0x05, 0x05, 0x08, 2}, /* 640x480x32 */
+ {0x63, 0x2a3f, 0x013b, SIS_RI_800x600, 0x00, 0x00, 0x07, 0x06, 0x00, 3}, /* 800x600x32 */
+ {0x64, 0x0a7f, 0x013c, SIS_RI_1024x768, 0x00, 0x00, 0x08, 0x07, 0x13, 4}, /* 1024x768x32 */
+ {0x65, 0x0eff, 0x013d, SIS_RI_1280x1024, 0x00, 0x00, 0x00, 0x00, 0x2f, 8}, /* 1280x1024x32 */
+ {0x70, 0x6a1b, 0x0000, SIS_RI_800x480, 0x00, 0x00, 0x07, 0x07, 0x1e, -1}, /* 800x480x8 */
+ {0x71, 0x4a1b, 0x0000, SIS_RI_1024x576, 0x00, 0x00, 0x00, 0x00, 0x21, -1}, /* 1024x576x8 */
+ {0x74, 0x4a1d, 0x0000, SIS_RI_1024x576, 0x00, 0x00, 0x00, 0x00, 0x21, -1}, /* 1024x576x16 */
+ {0x75, 0x0a3d, 0x0000, SIS_RI_1280x720, 0x00, 0x00, 0x00, 0x00, 0x24, 5}, /* 1280x720x16 */
+ {0x76, 0x6a1f, 0x0000, SIS_RI_800x480, 0x00, 0x00, 0x07, 0x07, 0x1e, -1}, /* 800x480x32 */
+ {0x77, 0x4a1f, 0x0000, SIS_RI_1024x576, 0x00, 0x00, 0x00, 0x00, 0x21, -1}, /* 1024x576x32 */
+ {0x78, 0x0a3f, 0x0000, SIS_RI_1280x720, 0x00, 0x00, 0x00, 0x00, 0x24, 5}, /* 1280x720x32 */
+ {0x79, 0x0a3b, 0x0000, SIS_RI_1280x720, 0x00, 0x00, 0x00, 0x00, 0x24, 5}, /* 1280x720x8 */
+ {0x7a, 0x6a1d, 0x0000, SIS_RI_800x480, 0x00, 0x00, 0x07, 0x07, 0x1e, -1}, /* 800x480x16 */
+ {0x23, 0x0e3b, 0x0000, SIS_RI_1280x768, 0x00, 0x00, 0x00, 0x00, 0x27, 6}, /* 1280x768x8 */
+ {0x24, 0x0e7d, 0x0000, SIS_RI_1280x768, 0x00, 0x00, 0x00, 0x00, 0x27, 6}, /* 1280x768x16 */
+ {0x25, 0x0eff, 0x0000, SIS_RI_1280x768, 0x00, 0x00, 0x00, 0x00, 0x27, 6}, /* 1280x768x32 */
+ {0x39, 0x6a1b, 0x0000, SIS_RI_848x480, 0x00, 0x00, 0x00, 0x00, 0x28, -1}, /* 848x480 */
+ {0x3b, 0x6a3d, 0x0000, SIS_RI_848x480, 0x00, 0x00, 0x00, 0x00, 0x28,
+ -1},
+ {0x3e, 0x6a7f, 0x0000, SIS_RI_848x480, 0x00, 0x00, 0x00, 0x00, 0x28,
+ -1},
+ {0x3f, 0x6a1b, 0x0000, SIS_RI_856x480, 0x00, 0x00, 0x00, 0x00, 0x2a, -1}, /* 856x480 */
+ {0x42, 0x6a3d, 0x0000, SIS_RI_856x480, 0x00, 0x00, 0x00, 0x00, 0x2a,
+ -1},
+ {0x45, 0x6a7f, 0x0000, SIS_RI_856x480, 0x00, 0x00, 0x00, 0x00, 0x2a,
+ -1},
+ {0x4f, 0x9a1f, 0x0000, SIS_RI_320x200, 0x00, 0x00, 0x04, 0x04, 0x1a, 0}, /* 320x200x32 */
+ {0x53, 0x9a1f, 0x0000, SIS_RI_320x240, 0x00, 0x00, 0x04, 0x04, 0x1b, 2}, /* 320x240x32 */
+ {0x54, 0xba1f, 0x0000, SIS_RI_400x300, 0x00, 0x00, 0x07, 0x07, 0x1c, 3}, /* 400x300x32 */
+ {0x5f, 0x6a1b, 0x0000, SIS_RI_768x576, 0x00, 0x00, 0x06, 0x06, 0x2c, -1}, /* 768x576 */
+ {0x60, 0x6a1d, 0x0000, SIS_RI_768x576, 0x00, 0x00, 0x06, 0x06, 0x2c,
+ -1},
+ {0x61, 0x6a3f, 0x0000, SIS_RI_768x576, 0x00, 0x00, 0x06, 0x06, 0x2c,
+ -1},
+ {0x1d, 0x6a1b, 0x0000, SIS_RI_960x540, 0x00, 0x00, 0x00, 0x00, 0x2d, -1}, /* 960x540 */
+ {0x1e, 0x6a3d, 0x0000, SIS_RI_960x540, 0x00, 0x00, 0x00, 0x00, 0x2d,
+ -1},
+ {0x1f, 0x6a7f, 0x0000, SIS_RI_960x540, 0x00, 0x00, 0x00, 0x00, 0x2d,
+ -1},
+ {0x20, 0x6a1b, 0x0000, SIS_RI_960x600, 0x00, 0x00, 0x00, 0x00, 0x2e, -1}, /* 960x600 */
+ {0x21, 0x6a3d, 0x0000, SIS_RI_960x600, 0x00, 0x00, 0x00, 0x00, 0x2e,
+ -1},
+ {0x22, 0x6a7f, 0x0000, SIS_RI_960x600, 0x00, 0x00, 0x00, 0x00, 0x2e,
+ -1},
+ {0x29, 0x4e1b, 0x0000, SIS_RI_1152x864, 0x00, 0x00, 0x00, 0x00, 0x33, -1}, /* 1152x864 */
+ {0x2a, 0x4e3d, 0x0000, SIS_RI_1152x864, 0x00, 0x00, 0x00, 0x00, 0x33,
+ -1},
+ {0x2b, 0x4e7f, 0x0000, SIS_RI_1152x864, 0x00, 0x00, 0x00, 0x00, 0x33,
+ -1},
+ {0xff, 0x0000, 0x0000, 0, 0x00, 0x00, 0x00, 0x00, 0x00, -1}
+};
+
+static const struct SiS_Ext2 SiSUSB_RefIndex[] = {
+ {0x085f, 0x0d, 0x03, 0x05, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */
+ {0x0067, 0x0e, 0x04, 0x05, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */
+ {0x0067, 0x0f, 0x08, 0x48, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */
+ {0x0067, 0x10, 0x07, 0x8b, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */
+ {0x0047, 0x11, 0x0a, 0x00, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */
+ {0x0047, 0x12, 0x0d, 0x00, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */
+ {0x0047, 0x13, 0x13, 0x00, 0x05, 0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */
+ {0x0107, 0x14, 0x1c, 0x00, 0x05, 0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */
+ {0xc85f, 0x05, 0x00, 0x04, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */
+ {0xc067, 0x06, 0x02, 0x04, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */
+ {0xc067, 0x07, 0x02, 0x47, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */
+ {0xc067, 0x08, 0x03, 0x8a, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */
+ {0xc047, 0x09, 0x05, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */
+ {0xc047, 0x0a, 0x09, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */
+ {0xc047, 0x0b, 0x0e, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */
+ {0xc047, 0x0c, 0x15, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */
+ {0x487f, 0x04, 0x00, 0x00, 0x00, 0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */
+ {0xc06f, 0x3c, 0x01, 0x06, 0x13, 0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */
+ {0x006f, 0x3d, 0x6f, 0x06, 0x14, 0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */
+ {0x0087, 0x15, 0x06, 0x00, 0x06, 0x38, 1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */
+ {0xc877, 0x16, 0x0b, 0x06, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */
+ {0xc067, 0x17, 0x0f, 0x49, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */
+ {0x0067, 0x18, 0x11, 0x00, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */
+ {0x0047, 0x19, 0x16, 0x8c, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */
+ {0x0107, 0x1a, 0x1b, 0x00, 0x06, 0x38, 1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */
+ {0x0107, 0x1b, 0x1f, 0x00, 0x06, 0x38, 1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */
+ {0x407f, 0x00, 0x00, 0x00, 0x00, 0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */
+ {0xc07f, 0x01, 0x00, 0x04, 0x04, 0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */
+ {0x007f, 0x02, 0x04, 0x05, 0x05, 0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */
+ {0xc077, 0x03, 0x0b, 0x06, 0x06, 0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */
+ {0x0077, 0x32, 0x40, 0x08, 0x18, 0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */
+ {0x0047, 0x33, 0x07, 0x08, 0x18, 0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */
+ {0x0047, 0x34, 0x0a, 0x08, 0x18, 0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */
+ {0x0077, 0x35, 0x0b, 0x09, 0x19, 0x71, 1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */
+ {0x0047, 0x36, 0x11, 0x09, 0x19, 0x71, 1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */
+ {0x0047, 0x37, 0x16, 0x09, 0x19, 0x71, 1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */
+ {0x1137, 0x38, 0x19, 0x0a, 0x0c, 0x75, 1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */
+ {0x1107, 0x39, 0x1e, 0x0a, 0x0c, 0x75, 1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */
+ {0x1307, 0x3a, 0x20, 0x0a, 0x0c, 0x75, 1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */
+ {0x0077, 0x42, 0x5b, 0x08, 0x11, 0x23, 1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */
+ {0x0087, 0x45, 0x57, 0x00, 0x16, 0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */
+ {0xc067, 0x46, 0x55, 0x0b, 0x16, 0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */
+ {0x0087, 0x47, 0x57, 0x00, 0x17, 0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */
+ {0xc067, 0x48, 0x57, 0x00, 0x17, 0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */
+ {0x006f, 0x4d, 0x71, 0x06, 0x15, 0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */
+ {0x0067, 0x52, 0x6a, 0x00, 0x1c, 0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */
+ {0x0077, 0x53, 0x6b, 0x0b, 0x1d, 0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */
+ {0x0087, 0x1c, 0x11, 0x00, 0x07, 0x3a, 1280, 1024, 0x30, 0x00, 0x00}, /* 0x2f */
+ {0x0137, 0x1d, 0x19, 0x07, 0x07, 0x3a, 1280, 1024, 0x00, 0x00, 0x00}, /* 0x30 */
+ {0x0107, 0x1e, 0x1e, 0x00, 0x07, 0x3a, 1280, 1024, 0x00, 0x00, 0x00}, /* 0x31 */
+ {0x0207, 0x1f, 0x20, 0x00, 0x07, 0x3a, 1280, 1024, 0x00, 0x00, 0x00}, /* 0x32 */
+ {0x0127, 0x54, 0x6d, 0x00, 0x1a, 0x29, 1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */
+ {0x0127, 0x44, 0x19, 0x00, 0x1a, 0x29, 1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */
+ {0x0127, 0x4a, 0x1e, 0x00, 0x1a, 0x29, 1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */
+ {0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiSUSB_CRT1Table[] = {
+ {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,
+ 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x00,
+ 0x00}}, /* 0x0 */
+ {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x00,
+ 0x00}}, /* 0x1 */
+ {{0x3d, 0x31, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x05,
+ 0x01}}, /* 0x2 */
+ {{0x4f, 0x3f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}, /* 0x3 */
+ {{0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x05,
+ 0x00}}, /* 0x4 */
+ {{0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
+ 0x00}}, /* 0x5 */
+ {{0x63, 0x4f, 0x4f, 0x87, 0x56, 0x9b, 0x06, 0x3e,
+ 0xe8, 0x8a, 0xdf, 0xe7, 0x07, 0x00, 0x00, 0x01,
+ 0x00}}, /* 0x6 */
+ {{0x64, 0x4f, 0x4f, 0x88, 0x55, 0x9d, 0xf2, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xf3, 0x10, 0x00, 0x01,
+ 0x00}}, /* 0x7 */
+ {{0x63, 0x4f, 0x4f, 0x87, 0x5a, 0x81, 0xfb, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x05,
+ 0x00}}, /* 0x8 */
+ {{0x65, 0x4f, 0x4f, 0x89, 0x58, 0x80, 0xfb, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x05,
+ 0x61}}, /* 0x9 */
+ {{0x65, 0x4f, 0x4f, 0x89, 0x58, 0x80, 0x01, 0x3e,
+ 0xe0, 0x83, 0xdf, 0xdf, 0x02, 0x00, 0x00, 0x05,
+ 0x61}}, /* 0xa */
+ {{0x67, 0x4f, 0x4f, 0x8b, 0x58, 0x81, 0x0d, 0x3e,
+ 0xe0, 0x83, 0xdf, 0xdf, 0x0e, 0x00, 0x00, 0x05,
+ 0x61}}, /* 0xb */
+ {{0x65, 0x4f, 0x4f, 0x89, 0x57, 0x9f, 0xfb, 0x1f,
+ 0xe6, 0x8a, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x01,
+ 0x00}}, /* 0xc */
+ {{0x7b, 0x63, 0x63, 0x9f, 0x6a, 0x93, 0x6f, 0xf0,
+ 0x58, 0x8a, 0x57, 0x57, 0x70, 0x20, 0x00, 0x05,
+ 0x01}}, /* 0xd */
+ {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x06,
+ 0x01}}, /* 0xe */
+ {{0x7d, 0x63, 0x63, 0x81, 0x6e, 0x1d, 0x98, 0xf0,
+ 0x7c, 0x82, 0x57, 0x57, 0x99, 0x00, 0x00, 0x06,
+ 0x01}}, /* 0xf */
+ {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x70, 0x20, 0x00, 0x06,
+ 0x01}}, /* 0x10 */
+ {{0x7e, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x76, 0x20, 0x00, 0x06,
+ 0x01}}, /* 0x11 */
+ {{0x81, 0x63, 0x63, 0x85, 0x6d, 0x18, 0x7a, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x7b, 0x20, 0x00, 0x06,
+ 0x61}}, /* 0x12 */
+ {{0x83, 0x63, 0x63, 0x87, 0x6e, 0x19, 0x81, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x82, 0x20, 0x00, 0x06,
+ 0x61}}, /* 0x13 */
+ {{0x85, 0x63, 0x63, 0x89, 0x6f, 0x1a, 0x91, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x92, 0x20, 0x00, 0x06,
+ 0x61}}, /* 0x14 */
+ {{0x99, 0x7f, 0x7f, 0x9d, 0x84, 0x1a, 0x96, 0x1f,
+ 0x7f, 0x83, 0x7f, 0x7f, 0x97, 0x10, 0x00, 0x02,
+ 0x00}}, /* 0x15 */
+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}, /* 0x16 */
+ {{0xa1, 0x7f, 0x7f, 0x85, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}, /* 0x17 */
+ {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x1f, 0x10, 0x00, 0x02,
+ 0x01}}, /* 0x18 */
+ {{0xa7, 0x7f, 0x7f, 0x8b, 0x89, 0x95, 0x26, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x27, 0x10, 0x00, 0x02,
+ 0x01}}, /* 0x19 */
+ {{0xa9, 0x7f, 0x7f, 0x8d, 0x8c, 0x9a, 0x2c, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x2d, 0x14, 0x00, 0x02,
+ 0x62}}, /* 0x1a */
+ {{0xab, 0x7f, 0x7f, 0x8f, 0x8d, 0x9b, 0x35, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x36, 0x14, 0x00, 0x02,
+ 0x62}}, /* 0x1b */
+ {{0xcf, 0x9f, 0x9f, 0x93, 0xb2, 0x01, 0x14, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x15, 0x00, 0x00, 0x03,
+ 0x00}}, /* 0x1c */
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07,
+ 0x01}}, /* 0x1d */
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07,
+ 0x01}}, /* 0x1e */
+ {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x2f, 0x09, 0x00, 0x07,
+ 0x01}}, /* 0x1f */
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}}, /* 0x20 */
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}}, /* 0x21 */
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}}, /* 0x22 */
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}}, /* 0x23 */
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}}, /* 0x24 */
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}}, /* 0x25 */
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}}, /* 0x26 */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x27 */
+ {{0x43, 0xef, 0xef, 0x87, 0x06, 0x00, 0xd4, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xd5, 0x1f, 0x41, 0x05,
+ 0x63}}, /* 0x28 */
+ {{0x45, 0xef, 0xef, 0x89, 0x07, 0x01, 0xd9, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xda, 0x1f, 0x41, 0x05,
+ 0x63}}, /* 0x29 */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x2a */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x2b */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x2c */
+ {{0x59, 0xff, 0xff, 0x9d, 0x17, 0x13, 0x33, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x34, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x2d */
+ {{0x5b, 0xff, 0xff, 0x9f, 0x18, 0x14, 0x38, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x39, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x2e */
+ {{0x5b, 0xff, 0xff, 0x9f, 0x18, 0x14, 0x3d, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x3e, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x2f */
+ {{0x5d, 0xff, 0xff, 0x81, 0x19, 0x95, 0x41, 0xba,
+ 0x00, 0x84, 0xff, 0xff, 0x42, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x30 */
+ {{0x55, 0xff, 0xff, 0x99, 0x0d, 0x0c, 0x3e, 0xba,
+ 0x00, 0x84, 0xff, 0xff, 0x3f, 0x0f, 0x41, 0x05,
+ 0x00}}, /* 0x31 */
+ {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xba,
+ 0x27, 0x8b, 0xdf, 0xdf, 0x73, 0x00, 0x00, 0x06,
+ 0x01}}, /* 0x32 */
+ {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xba,
+ 0x26, 0x89, 0xdf, 0xdf, 0x6f, 0x00, 0x00, 0x06,
+ 0x01}}, /* 0x33 */
+ {{0x7f, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xba,
+ 0x29, 0x8c, 0xdf, 0xdf, 0x75, 0x00, 0x00, 0x06,
+ 0x01}}, /* 0x34 */
+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf1,
+ 0xaf, 0x85, 0x3f, 0x3f, 0x25, 0x30, 0x00, 0x02,
+ 0x01}}, /* 0x35 */
+ {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf1,
+ 0xad, 0x81, 0x3f, 0x3f, 0x1f, 0x30, 0x00, 0x02,
+ 0x01}}, /* 0x36 */
+ {{0xa7, 0x7f, 0x7f, 0x88, 0x89, 0x95, 0x26, 0xf1,
+ 0xb1, 0x85, 0x3f, 0x3f, 0x27, 0x30, 0x00, 0x02,
+ 0x01}}, /* 0x37 */
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0xc4,
+ 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07,
+ 0x01}}, /* 0x38 */
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0xd4,
+ 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07,
+ 0x01}}, /* 0x39 */
+ {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0xd4,
+ 0x7d, 0x81, 0xcf, 0xcf, 0x2f, 0x21, 0x00, 0x07,
+ 0x01}}, /* 0x3a */
+ {{0xdc, 0x9f, 0x9f, 0x80, 0xaf, 0x9d, 0xe6, 0xff,
+ 0xc0, 0x83, 0xbf, 0xbf, 0xe7, 0x10, 0x00, 0x07,
+ 0x01}}, /* 0x3b */
+ {{0x6b, 0x59, 0x59, 0x8f, 0x5e, 0x8c, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x05,
+ 0x00}}, /* 0x3c */
+ {{0x6d, 0x59, 0x59, 0x91, 0x60, 0x89, 0x53, 0xf0,
+ 0x41, 0x84, 0x3f, 0x3f, 0x54, 0x00, 0x00, 0x05,
+ 0x41}}, /* 0x3d */
+ {{0x86, 0x6a, 0x6a, 0x8a, 0x74, 0x06, 0x8c, 0x15,
+ 0x4f, 0x83, 0xef, 0xef, 0x8d, 0x30, 0x00, 0x02,
+ 0x00}}, /* 0x3e */
+ {{0x81, 0x6a, 0x6a, 0x85, 0x70, 0x00, 0x0f, 0x3e,
+ 0xeb, 0x8e, 0xdf, 0xdf, 0x10, 0x00, 0x00, 0x02,
+ 0x00}}, /* 0x3f */
+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x1e, 0xf1,
+ 0xae, 0x85, 0x57, 0x57, 0x1f, 0x30, 0x00, 0x02,
+ 0x01}}, /* 0x40 */
+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}, /* 0x41 */
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x20, 0xf5,
+ 0x03, 0x88, 0xff, 0xff, 0x21, 0x10, 0x00, 0x07,
+ 0x01}}, /* 0x42 */
+ {{0xe6, 0xae, 0xae, 0x8a, 0xbd, 0x90, 0x3d, 0x10,
+ 0x1a, 0x8d, 0x19, 0x19, 0x3e, 0x2f, 0x00, 0x03,
+ 0x00}}, /* 0x43 */
+ {{0xc3, 0x8f, 0x8f, 0x87, 0x9b, 0x0b, 0x82, 0xef,
+ 0x60, 0x83, 0x5f, 0x5f, 0x83, 0x10, 0x00, 0x07,
+ 0x01}}, /* 0x44 */
+ {{0x86, 0x69, 0x69, 0x8A, 0x74, 0x06, 0x8C, 0x15,
+ 0x4F, 0x83, 0xEF, 0xEF, 0x8D, 0x30, 0x00, 0x02,
+ 0x00}}, /* 0x45 */
+ {{0x83, 0x69, 0x69, 0x87, 0x6f, 0x1d, 0x03, 0x3E,
+ 0xE5, 0x8d, 0xDF, 0xe4, 0x04, 0x00, 0x00, 0x06,
+ 0x00}}, /* 0x46 */
+ {{0x86, 0x6A, 0x6A, 0x8A, 0x74, 0x06, 0x8C, 0x15,
+ 0x4F, 0x83, 0xEF, 0xEF, 0x8D, 0x30, 0x00, 0x02,
+ 0x00}}, /* 0x47 */
+ {{0x81, 0x6A, 0x6A, 0x85, 0x70, 0x00, 0x0F, 0x3E,
+ 0xEB, 0x8E, 0xDF, 0xDF, 0x10, 0x00, 0x00, 0x02,
+ 0x00}}, /* 0x48 */
+ {{0xdd, 0xa9, 0xa9, 0x81, 0xb4, 0x97, 0x26, 0xfd,
+ 0x01, 0x8d, 0xff, 0x00, 0x27, 0x10, 0x00, 0x03,
+ 0x01}}, /* 0x49 */
+ {{0xd9, 0x8f, 0x8f, 0x9d, 0xba, 0x0a, 0x8a, 0xff,
+ 0x60, 0x8b, 0x5f, 0x5f, 0x8b, 0x10, 0x00, 0x03,
+ 0x01}}, /* 0x4a */
+ {{0xea, 0xae, 0xae, 0x8e, 0xba, 0x82, 0x40, 0x10,
+ 0x1b, 0x87, 0x19, 0x1a, 0x41, 0x0f, 0x00, 0x03,
+ 0x00}}, /* 0x4b */
+ {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0xf1, 0xff,
+ 0xc0, 0x83, 0xbf, 0xbf, 0xf2, 0x10, 0x00, 0x07,
+ 0x01}}, /* 0x4c */
+ {{0x75, 0x5f, 0x5f, 0x99, 0x66, 0x90, 0x53, 0xf0,
+ 0x41, 0x84, 0x3f, 0x3f, 0x54, 0x00, 0x00, 0x05,
+ 0x41}},
+ {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x00,
+ 0x00}}, /* 0x4e */
+ {{0xcd, 0x9f, 0x9f, 0x91, 0xab, 0x1c, 0x3a, 0xff,
+ 0x20, 0x83, 0x1f, 0x1f, 0x3b, 0x10, 0x00, 0x07,
+ 0x21}}, /* 0x4f */
+ {{0x15, 0xd1, 0xd1, 0x99, 0xe2, 0x19, 0x3d, 0x10,
+ 0x1a, 0x8d, 0x19, 0x19, 0x3e, 0x2f, 0x01, 0x0c,
+ 0x20}}, /* 0x50 */
+ {{0x0e, 0xef, 0xef, 0x92, 0xfe, 0x03, 0x30, 0xf0,
+ 0x1e, 0x83, 0x1b, 0x1c, 0x31, 0x00, 0x01, 0x00,
+ 0x61}}, /* 0x51 */
+ {{0x85, 0x77, 0x77, 0x89, 0x7d, 0x01, 0x31, 0xf0,
+ 0x1e, 0x84, 0x1b, 0x1c, 0x32, 0x00, 0x00, 0x02,
+ 0x41}}, /* 0x52 */
+ {{0x87, 0x77, 0x77, 0x8b, 0x81, 0x0b, 0x68, 0xf0,
+ 0x5a, 0x80, 0x57, 0x57, 0x69, 0x00, 0x00, 0x02,
+ 0x01}}, /* 0x53 */
+ {{0xcd, 0x8f, 0x8f, 0x91, 0x9b, 0x1b, 0x7a, 0xff,
+ 0x64, 0x8c, 0x5f, 0x62, 0x7b, 0x10, 0x00, 0x07,
+ 0x41}} /* 0x54 */
+};
+
+static const struct SiS_VCLKData SiSUSB_VCLKData[] = {
+ {0x1b, 0xe1, 25}, /* 0x00 */
+ {0x4e, 0xe4, 28}, /* 0x01 */
+ {0x57, 0xe4, 31}, /* 0x02 */
+ {0xc3, 0xc8, 36}, /* 0x03 */
+ {0x42, 0xe2, 40}, /* 0x04 */
+ {0xfe, 0xcd, 43}, /* 0x05 */
+ {0x5d, 0xc4, 44}, /* 0x06 */
+ {0x52, 0xe2, 49}, /* 0x07 */
+ {0x53, 0xe2, 50}, /* 0x08 */
+ {0x74, 0x67, 52}, /* 0x09 */
+ {0x6d, 0x66, 56}, /* 0x0a */
+ {0x5a, 0x64, 65}, /* 0x0b */
+ {0x46, 0x44, 67}, /* 0x0c */
+ {0xb1, 0x46, 68}, /* 0x0d */
+ {0xd3, 0x4a, 72}, /* 0x0e */
+ {0x29, 0x61, 75}, /* 0x0f */
+ {0x6e, 0x46, 76}, /* 0x10 */
+ {0x2b, 0x61, 78}, /* 0x11 */
+ {0x31, 0x42, 79}, /* 0x12 */
+ {0xab, 0x44, 83}, /* 0x13 */
+ {0x46, 0x25, 84}, /* 0x14 */
+ {0x78, 0x29, 86}, /* 0x15 */
+ {0x62, 0x44, 94}, /* 0x16 */
+ {0x2b, 0x41, 104}, /* 0x17 */
+ {0x3a, 0x23, 105}, /* 0x18 */
+ {0x70, 0x44, 108}, /* 0x19 */
+ {0x3c, 0x23, 109}, /* 0x1a */
+ {0x5e, 0x43, 113}, /* 0x1b */
+ {0xbc, 0x44, 116}, /* 0x1c */
+ {0xe0, 0x46, 132}, /* 0x1d */
+ {0x54, 0x42, 135}, /* 0x1e */
+ {0xea, 0x2a, 139}, /* 0x1f */
+ {0x41, 0x22, 157}, /* 0x20 */
+ {0x70, 0x24, 162}, /* 0x21 */
+ {0x30, 0x21, 175}, /* 0x22 */
+ {0x4e, 0x22, 189}, /* 0x23 */
+ {0xde, 0x26, 194}, /* 0x24 */
+ {0x62, 0x06, 202}, /* 0x25 */
+ {0x3f, 0x03, 229}, /* 0x26 */
+ {0xb8, 0x06, 234}, /* 0x27 */
+ {0x34, 0x02, 253}, /* 0x28 */
+ {0x58, 0x04, 255}, /* 0x29 */
+ {0x24, 0x01, 265}, /* 0x2a */
+ {0x9b, 0x02, 267}, /* 0x2b */
+ {0x70, 0x05, 270}, /* 0x2c */
+ {0x25, 0x01, 272}, /* 0x2d */
+ {0x9c, 0x02, 277}, /* 0x2e */
+ {0x27, 0x01, 286}, /* 0x2f */
+ {0x3c, 0x02, 291}, /* 0x30 */
+ {0xef, 0x0a, 292}, /* 0x31 */
+ {0xf6, 0x0a, 310}, /* 0x32 */
+ {0x95, 0x01, 315}, /* 0x33 */
+ {0xf0, 0x09, 324}, /* 0x34 */
+ {0xfe, 0x0a, 331}, /* 0x35 */
+ {0xf3, 0x09, 332}, /* 0x36 */
+ {0xea, 0x08, 340}, /* 0x37 */
+ {0xe8, 0x07, 376}, /* 0x38 */
+ {0xde, 0x06, 389}, /* 0x39 */
+ {0x52, 0x2a, 54}, /* 0x3a 301 TV */
+ {0x52, 0x6a, 27}, /* 0x3b 301 TV */
+ {0x62, 0x24, 70}, /* 0x3c 301 TV */
+ {0x62, 0x64, 70}, /* 0x3d 301 TV */
+ {0xa8, 0x4c, 30}, /* 0x3e 301 TV */
+ {0x20, 0x26, 33}, /* 0x3f 301 TV */
+ {0x31, 0xc2, 39}, /* 0x40 */
+ {0x60, 0x36, 30}, /* 0x41 Chrontel */
+ {0x40, 0x4a, 28}, /* 0x42 Chrontel */
+ {0x9f, 0x46, 44}, /* 0x43 Chrontel */
+ {0x97, 0x2c, 26}, /* 0x44 */
+ {0x44, 0xe4, 25}, /* 0x45 Chrontel */
+ {0x7e, 0x32, 47}, /* 0x46 Chrontel */
+ {0x8a, 0x24, 31}, /* 0x47 Chrontel */
+ {0x97, 0x2c, 26}, /* 0x48 Chrontel */
+ {0xce, 0x3c, 39}, /* 0x49 */
+ {0x52, 0x4a, 36}, /* 0x4a Chrontel */
+ {0x34, 0x61, 95}, /* 0x4b */
+ {0x78, 0x27, 108}, /* 0x4c - was 102 */
+ {0x66, 0x43, 123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
+ {0x41, 0x4e, 21}, /* 0x4e */
+ {0xa1, 0x4a, 29}, /* 0x4f Chrontel */
+ {0x19, 0x42, 42}, /* 0x50 */
+ {0x54, 0x46, 58}, /* 0x51 Chrontel */
+ {0x25, 0x42, 61}, /* 0x52 */
+ {0x44, 0x44, 66}, /* 0x53 Chrontel */
+ {0x3a, 0x62, 70}, /* 0x54 Chrontel */
+ {0x62, 0xc6, 34}, /* 0x55 848x480-60 */
+ {0x6a, 0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+ {0xbf, 0xc8, 35}, /* 0x57 856x480-38i,60 */
+ {0x30, 0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+ {0x52, 0x07, 149}, /* 0x59 1280x960-85 */
+ {0x56, 0x07, 156}, /* 0x5a 1400x1050-75 */
+ {0x70, 0x29, 81}, /* 0x5b 1280x768 LCD */
+ {0x45, 0x25, 83}, /* 0x5c 1280x800 */
+ {0x70, 0x0a, 147}, /* 0x5d 1680x1050 */
+ {0x70, 0x24, 162}, /* 0x5e 1600x1200 */
+ {0x5a, 0x64, 65}, /* 0x5f 1280x720 - temp */
+ {0x63, 0x46, 68}, /* 0x60 1280x768_2 */
+ {0x31, 0x42, 79}, /* 0x61 1280x768_3 - temp */
+ {0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */
+ {0x5a, 0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+ {0x70, 0x28, 90}, /* 0x64 1152x864@60 */
+ {0x41, 0xc4, 32}, /* 0x65 848x480@60 */
+ {0x5c, 0xc6, 32}, /* 0x66 856x480@60 */
+ {0x76, 0xe7, 27}, /* 0x67 720x480@60 */
+ {0x5f, 0xc6, 33}, /* 0x68 720/768x576@60 */
+ {0x52, 0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
+ {0x7c, 0x6b, 38}, /* 0x6a 960x540@60 */
+ {0xe3, 0x56, 41}, /* 0x6b 960x600@60 */
+ {0x45, 0x25, 83}, /* 0x6c 1280x800 */
+ {0x70, 0x28, 90}, /* 0x6d 1152x864@60 */
+ {0x15, 0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+ {0x5f, 0xc6, 33}, /* 0x6f 720x576@60 */
+ {0x37, 0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+ {0x2b, 0xc2, 35} /* 0x71 768@576@60 */
+};
+
+int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 * data);
+extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 data);
+extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 * data);
+extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
+ u8 idx, u8 myand, u8 myor);
+extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 myor);
+extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
+ u8 idx, u8 myand);
+
+void sisusb_delete(struct kref *kref);
+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_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);
+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);
+void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
+int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
+void sisusb_console_exit(struct sisusb_usb_data *sisusb);
+void sisusb_init_concode(void);
+
+#endif
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
new file mode 100644
index 00000000000..1c4240e802c
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h
@@ -0,0 +1,161 @@
+/*
+ * General structure definitions for universal mode switching modules
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * * notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * * notice, this list of conditions and the following disclaimer in the
+ * * documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_STRUCT_H_
+#define _SISUSB_STRUCT_H_
+
+struct SiS_St {
+ unsigned char St_ModeID;
+ unsigned short St_ModeFlag;
+ unsigned char St_StTableIndex;
+ unsigned char St_CRT2CRTC;
+ unsigned char St_ResInfo;
+ unsigned char VB_StTVFlickerIndex;
+ unsigned char VB_StTVEdgeIndex;
+ unsigned char VB_StTVYFilterIndex;
+ unsigned char St_PDC;
+};
+
+struct SiS_StandTable {
+ unsigned char CRT_COLS;
+ unsigned char ROWS;
+ unsigned char CHAR_HEIGHT;
+ unsigned short CRT_LEN;
+ unsigned char SR[4];
+ unsigned char MISC;
+ unsigned char CRTC[0x19];
+ unsigned char ATTR[0x14];
+ unsigned char GRC[9];
+};
+
+struct SiS_StResInfo_S {
+ unsigned short HTotal;
+ unsigned short VTotal;
+};
+
+struct SiS_Ext {
+ unsigned char Ext_ModeID;
+ unsigned short Ext_ModeFlag;
+ unsigned short Ext_VESAID;
+ unsigned char Ext_RESINFO;
+ unsigned char VB_ExtTVFlickerIndex;
+ unsigned char VB_ExtTVEdgeIndex;
+ unsigned char VB_ExtTVYFilterIndex;
+ unsigned char VB_ExtTVYFilterIndexROM661;
+ unsigned char REFindex;
+ char ROMMODEIDX661;
+};
+
+struct SiS_Ext2 {
+ unsigned short Ext_InfoFlag;
+ unsigned char Ext_CRT1CRTC;
+ unsigned char Ext_CRTVCLK;
+ unsigned char Ext_CRT2CRTC;
+ unsigned char Ext_CRT2CRTC_NS;
+ unsigned char ModeID;
+ unsigned short XRes;
+ unsigned short YRes;
+ unsigned char Ext_PDC;
+ unsigned char Ext_FakeCRT2CRTC;
+ unsigned char Ext_FakeCRT2Clk;
+};
+
+struct SiS_CRT1Table {
+ unsigned char CR[17];
+};
+
+struct SiS_VCLKData {
+ unsigned char SR2B, SR2C;
+ unsigned short CLOCK;
+};
+
+struct SiS_ModeResInfo {
+ unsigned short HTotal;
+ unsigned short VTotal;
+ unsigned char XChar;
+ unsigned char YChar;
+};
+
+struct SiS_Private {
+ void *sisusb;
+
+ unsigned long IOAddress;
+
+ unsigned long SiS_P3c4;
+ unsigned long SiS_P3d4;
+ unsigned long SiS_P3c0;
+ unsigned long SiS_P3ce;
+ unsigned long SiS_P3c2;
+ unsigned long SiS_P3ca;
+ unsigned long SiS_P3c6;
+ unsigned long SiS_P3c7;
+ unsigned long SiS_P3c8;
+ unsigned long SiS_P3c9;
+ unsigned long SiS_P3cb;
+ unsigned long SiS_P3cc;
+ unsigned long SiS_P3cd;
+ unsigned long SiS_P3da;
+ unsigned long SiS_Part1Port;
+
+ unsigned char SiS_MyCR63;
+ unsigned short SiS_CRT1Mode;
+ unsigned short SiS_ModeType;
+ unsigned short SiS_SetFlag;
+
+ const struct SiS_StandTable *SiS_StandTable;
+ const struct SiS_St *SiS_SModeIDTable;
+ const struct SiS_Ext *SiS_EModeIDTable;
+ const struct SiS_Ext2 *SiS_RefIndex;
+ const struct SiS_CRT1Table *SiS_CRT1Table;
+ const struct SiS_VCLKData *SiS_VCLKData;
+ const struct SiS_ModeResInfo *SiS_ModeResInfo;
+};
+
+#endif