aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig42
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile4
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c463
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h73
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c1658
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.c1047
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h830
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_struct.h169
8 files changed, 4231 insertions, 55 deletions
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 3957e144caf7..7603cbe0865d 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -4,11 +4,43 @@ config USB_SISUSBVGA
4 depends on USB && USB_EHCI_HCD 4 depends on USB && USB_EHCI_HCD
5 ---help--- 5 ---help---
6 Say Y here if you intend to attach a USB2VGA dongle based on a 6 Say Y here if you intend to attach a USB2VGA dongle based on a
7 Net2280 and a SiS315 chip. 7 Net2280 and a SiS315 chip.
8 8
9 Note that this device requires a USB 2.0 host controller. It will not 9 Note that this device requires a USB 2.0 host controller. It will not
10 work with USB 1.x controllers. 10 work with USB 1.x controllers.
11 11
12 To compile this driver as a module, choose M here: the module will be 12 To compile this driver as a module, choose M here; the module will be
13 called sisusb. If unsure, say N. 13 called sisusbvga. If unsure, say N.
14
15config USB_SISUSBVGA_CON
16 bool "Text console and mode switching support" if USB_SISUSBVGA
17 depends on VT
18 select FONT_8x16
19 ---help---
20 Say Y here if you want a VGA text console via the USB dongle or
21 want to support userland applications that utilize the driver's
22 display mode switching capabilities.
23
24 Note that this console supports VGA/EGA text mode only.
25
26 By default, the console part of the driver will not kick in when
27 the driver is initialized. If you want the driver to take over
28 one or more of the consoles, you need to specify the number of
29 the first and last consoles (starting at 1) as driver parameters.
30
31 For example, if the driver is compiled as a module:
32
33 modprobe sisusbvga first=1 last=5
34
35 If you use hotplug, add this to your modutils config files with
36 the "options" keyword, such as eg.
37
38 options sisusbvga first=1 last=5
39
40 If the driver is compiled into the kernel image, the parameters
41 must be given in the kernel command like, such as
42
43 sisusbvga.first=1 sisusbvga.last=5
44
45
14 46
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 76f1643ceaf8..7f934cfc906c 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -2,5 +2,7 @@
2# Makefile for the sisusb driver (if driver is inside kernel tree). 2# Makefile for the sisusb driver (if driver is inside kernel tree).
3# 3#
4 4
5obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o 5obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
6
7sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
6 8
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index d63ce6c030f3..39db3155723a 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 * 3 *
4 * Main part
5 *
4 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria 6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
5 * 7 *
6 * If distributed as part of the Linux kernel, this code is licensed under the 8 * If distributed as part of the Linux kernel, this code is licensed under the
@@ -48,16 +50,60 @@
48#include <linux/kref.h> 50#include <linux/kref.h>
49#include <linux/usb.h> 51#include <linux/usb.h>
50#include <linux/smp_lock.h> 52#include <linux/smp_lock.h>
53#include <linux/vmalloc.h>
51 54
52#include "sisusb.h" 55#include "sisusb.h"
53 56
57#ifdef INCL_SISUSB_CON
58#include <linux/font.h>
59#endif
60
54#define SISUSB_DONTSYNC 61#define SISUSB_DONTSYNC
55 62
56/* Forward declarations / clean-up routines */ 63/* Forward declarations / clean-up routines */
57 64
65#ifdef INCL_SISUSB_CON
66int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
67int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
68int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
69int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
70int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
71int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
72int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
73
74int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
75int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
76int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
77int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
78int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
79 u32 dest, int length, size_t *bytes_written);
80
81int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
82
83extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
84extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
85
86extern void sisusb_init_concode(void);
87extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
88extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
89
90extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
91
92extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
93 u8 *arg, int cmapsz, int ch512, int dorecalc,
94 struct vc_data *c, int fh, int uplock);
95
96static int sisusb_first_vc = 0;
97static int sisusb_last_vc = 0;
98module_param_named(first, sisusb_first_vc, int, 0);
99module_param_named(last, sisusb_last_vc, int, 0);
100MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
101MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
102#endif
103
58static struct usb_driver sisusb_driver; 104static struct usb_driver sisusb_driver;
59 105
60static DECLARE_MUTEX(disconnect_sem); 106DECLARE_MUTEX(disconnect_sem);
61 107
62static void 108static void
63sisusb_free_buffers(struct sisusb_usb_data *sisusb) 109sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -639,7 +685,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
639 685
640/* The following routines assume being used to transfer byte, word, 686/* The following routines assume being used to transfer byte, word,
641 * long etc. 687 * long etc.
642 * This means that they assume "data" in machine endianness format. 688 * This means that
689 * - the write routines expect "data" in machine endianness format.
690 * The data will be converted to leXX in sisusb_xxx_packet.
691 * - the read routines can expect read data in machine-endianess.
643 */ 692 */
644 693
645static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, 694static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
@@ -839,7 +888,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
839 if (get_user(swap16, (u16 __user *)userbuffer)) 888 if (get_user(swap16, (u16 __user *)userbuffer))
840 return -EFAULT; 889 return -EFAULT;
841 } else 890 } else
842 swap16 = (kernbuffer[0] << 8) | kernbuffer[1]; 891 swap16 = *((u16 *)kernbuffer);
843 892
844 ret = sisusb_write_memio_word(sisusb, 893 ret = sisusb_write_memio_word(sisusb,
845 SISUSB_TYPE_MEM, 894 SISUSB_TYPE_MEM,
@@ -855,14 +904,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
855 if (userbuffer) { 904 if (userbuffer) {
856 if (copy_from_user(&buf, userbuffer, 3)) 905 if (copy_from_user(&buf, userbuffer, 3))
857 return -EFAULT; 906 return -EFAULT;
858 907#ifdef __BIG_ENDIAN
859 swap32 = (buf[0] << 16) | 908 swap32 = (buf[0] << 16) |
860 (buf[1] << 8) | 909 (buf[1] << 8) |
861 buf[2]; 910 buf[2];
911#else
912 swap32 = (buf[2] << 16) |
913 (buf[1] << 8) |
914 buf[0];
915#endif
862 } else 916 } else
917#ifdef __BIG_ENDIAN
863 swap32 = (kernbuffer[0] << 16) | 918 swap32 = (kernbuffer[0] << 16) |
864 (kernbuffer[1] << 8) | 919 (kernbuffer[1] << 8) |
865 kernbuffer[2]; 920 kernbuffer[2];
921#else
922 swap32 = (kernbuffer[2] << 16) |
923 (kernbuffer[1] << 8) |
924 kernbuffer[0];
925#endif
866 926
867 ret = sisusb_write_memio_24bit(sisusb, 927 ret = sisusb_write_memio_24bit(sisusb,
868 SISUSB_TYPE_MEM, 928 SISUSB_TYPE_MEM,
@@ -879,10 +939,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
879 if (get_user(swap32, (u32 __user *)userbuffer)) 939 if (get_user(swap32, (u32 __user *)userbuffer))
880 return -EFAULT; 940 return -EFAULT;
881 } else 941 } else
882 swap32 = (kernbuffer[0] << 24) | 942 swap32 = *((u32 *)kernbuffer);
883 (kernbuffer[1] << 16) |
884 (kernbuffer[2] << 8) |
885 kernbuffer[3];
886 943
887 ret = sisusb_write_memio_long(sisusb, 944 ret = sisusb_write_memio_long(sisusb,
888 SISUSB_TYPE_MEM, 945 SISUSB_TYPE_MEM,
@@ -1005,6 +1062,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1005 return ret ? -EIO : 0; 1062 return ret ? -EIO : 0;
1006} 1063}
1007 1064
1065/* Remember: Read data in packet is in machine-endianess! So for
1066 * byte, word, 24bit, long no endian correction is necessary.
1067 */
1068
1008static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, 1069static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1009 u32 addr, u8 *data) 1070 u32 addr, u8 *data)
1010{ 1071{
@@ -1191,8 +1252,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1191 (u16 __user *)userbuffer)) 1252 (u16 __user *)userbuffer))
1192 return -EFAULT; 1253 return -EFAULT;
1193 } else { 1254 } else {
1194 kernbuffer[0] = swap16 >> 8; 1255 *((u16 *)kernbuffer) = swap16;
1195 kernbuffer[1] = swap16 & 0xff;
1196 } 1256 }
1197 } 1257 }
1198 return ret; 1258 return ret;
@@ -1202,9 +1262,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1202 addr, &swap32); 1262 addr, &swap32);
1203 if (!ret) { 1263 if (!ret) {
1204 (*bytes_read) += 3; 1264 (*bytes_read) += 3;
1265#ifdef __BIG_ENDIAN
1205 buf[0] = (swap32 >> 16) & 0xff; 1266 buf[0] = (swap32 >> 16) & 0xff;
1206 buf[1] = (swap32 >> 8) & 0xff; 1267 buf[1] = (swap32 >> 8) & 0xff;
1207 buf[2] = swap32 & 0xff; 1268 buf[2] = swap32 & 0xff;
1269#else
1270 buf[2] = (swap32 >> 16) & 0xff;
1271 buf[1] = (swap32 >> 8) & 0xff;
1272 buf[0] = swap32 & 0xff;
1273#endif
1208 if (userbuffer) { 1274 if (userbuffer) {
1209 if (copy_to_user(userbuffer, &buf[0], 3)) 1275 if (copy_to_user(userbuffer, &buf[0], 3))
1210 return -EFAULT; 1276 return -EFAULT;
@@ -1228,10 +1294,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1228 1294
1229 userbuffer += 4; 1295 userbuffer += 4;
1230 } else { 1296 } else {
1231 kernbuffer[0] = (swap32 >> 24) & 0xff; 1297 *((u32 *)kernbuffer) = swap32;
1232 kernbuffer[1] = (swap32 >> 16) & 0xff;
1233 kernbuffer[2] = (swap32 >> 8) & 0xff;
1234 kernbuffer[3] = swap32 & 0xff;
1235 kernbuffer += 4; 1298 kernbuffer += 4;
1236 } 1299 }
1237 addr += 4; 1300 addr += 4;
@@ -1289,7 +1352,24 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1289 1352
1290/* High level: Gfx (indexed) register access */ 1353/* High level: Gfx (indexed) register access */
1291 1354
1292static int 1355#ifdef INCL_SISUSB_CON
1356int
1357sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1358{
1359 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1360}
1361
1362int
1363sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1364{
1365 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1366}
1367#endif
1368
1369#ifndef INCL_SISUSB_CON
1370static
1371#endif
1372int
1293sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) 1373sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1294{ 1374{
1295 int ret; 1375 int ret;
@@ -1298,7 +1378,10 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1298 return ret; 1378 return ret;
1299} 1379}
1300 1380
1301static int 1381#ifndef INCL_SISUSB_CON
1382static
1383#endif
1384int
1302sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) 1385sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1303{ 1386{
1304 int ret; 1387 int ret;
@@ -1307,7 +1390,10 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1307 return ret; 1390 return ret;
1308} 1391}
1309 1392
1310static int 1393#ifndef INCL_SISUSB_CON
1394static
1395#endif
1396int
1311sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, 1397sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1312 u8 myand, u8 myor) 1398 u8 myand, u8 myor)
1313{ 1399{
@@ -1336,18 +1422,89 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1336 return ret; 1422 return ret;
1337} 1423}
1338 1424
1339static int 1425#ifndef INCL_SISUSB_CON
1426static
1427#endif
1428int
1340sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) 1429sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1341{ 1430{
1342 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); 1431 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1343} 1432}
1344 1433
1345static int 1434#ifndef INCL_SISUSB_CON
1435static
1436#endif
1437int
1346sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) 1438sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1347{ 1439{
1348 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00)); 1440 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1349} 1441}
1350 1442
1443/* Write/read video ram */
1444
1445#ifdef INCL_SISUSB_CON
1446int
1447sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1448{
1449 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1450}
1451
1452int
1453sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1454{
1455 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1456}
1457
1458int
1459sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
1460{
1461 return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1462}
1463
1464int
1465sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
1466{
1467 return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1468}
1469
1470int
1471sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1472 u32 dest, int length, size_t *bytes_written)
1473{
1474 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1475}
1476
1477#ifdef SISUSBENDIANTEST
1478int
1479sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1480 u32 src, int length, size_t *bytes_written)
1481{
1482 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1483}
1484#endif
1485#endif
1486
1487#ifdef SISUSBENDIANTEST
1488static void
1489sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1490{
1491 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1492 char destbuffer[10];
1493 size_t dummy;
1494 int i,j;
1495
1496 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1497
1498 for(i = 1; i <= 7; i++) {
1499 printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
1500 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1501 for(j = 0; j < i; j++) {
1502 printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
1503 }
1504 }
1505}
1506#endif
1507
1351/* access pci config registers (reg numbers 0, 4, 8, etc) */ 1508/* access pci config registers (reg numbers 0, 4, 8, etc) */
1352 1509
1353static int 1510static int
@@ -2270,6 +2427,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2270 return ret; 2427 return ret;
2271} 2428}
2272 2429
2430
2431#ifdef INCL_SISUSB_CON
2432
2433/* Set up default text mode:
2434 - Set text mode (0x03)
2435 - Upload default font
2436 - Upload user font (if available)
2437*/
2438
2439int
2440sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2441{
2442 int ret = 0, slot = sisusb->font_slot, i;
2443 struct font_desc *myfont;
2444 u8 *tempbuf;
2445 u16 *tempbufb;
2446 size_t written;
2447 static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2448 static char bootlogo[] = "(o_ //\\ V_/_";
2449
2450 /* sisusb->lock is down */
2451
2452 if (!sisusb->SiS_Pr)
2453 return 1;
2454
2455 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2456 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2457
2458 /* Set mode 0x03 */
2459 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2460
2461 if (!(myfont = find_font("VGA8x16")))
2462 return 1;
2463
2464 if (!(tempbuf = vmalloc(8192)))
2465 return 1;
2466
2467 for (i = 0; i < 256; i++)
2468 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2469
2470 /* Upload default font */
2471 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2472
2473 vfree(tempbuf);
2474
2475 /* Upload user font (and reset current slot) */
2476 if (sisusb->font_backup) {
2477 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2478 8192, sisusb->font_backup_512, 1, NULL,
2479 sisusb->font_backup_height, 0);
2480 if (slot != 2)
2481 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2482 NULL, 16, 0);
2483 }
2484
2485 if (init && !sisusb->scrbuf) {
2486
2487 if ((tempbuf = vmalloc(8192))) {
2488
2489 i = 4096;
2490 tempbufb = (u16 *)tempbuf;
2491 while (i--)
2492 *(tempbufb++) = 0x0720;
2493
2494 i = 0;
2495 tempbufb = (u16 *)tempbuf;
2496 while (bootlogo[i]) {
2497 *(tempbufb++) = 0x0700 | bootlogo[i++];
2498 if (!(i % 4))
2499 tempbufb += 76;
2500 }
2501
2502 i = 0;
2503 tempbufb = (u16 *)tempbuf + 6;
2504 while (bootstring[i])
2505 *(tempbufb++) = 0x0700 | bootstring[i++];
2506
2507 ret |= sisusb_copy_memory(sisusb, tempbuf,
2508 sisusb->vrambase, 8192, &written);
2509
2510 vfree(tempbuf);
2511
2512 }
2513
2514 } else if (sisusb->scrbuf) {
2515
2516 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2517 sisusb->vrambase, sisusb->scrbuf_size, &written);
2518
2519 }
2520
2521 if (sisusb->sisusb_cursor_size_from >= 0 &&
2522 sisusb->sisusb_cursor_size_to >= 0) {
2523 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2524 sisusb->sisusb_cursor_size_from);
2525 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2526 sisusb->sisusb_cursor_size_to);
2527 } else {
2528 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2529 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2530 sisusb->sisusb_cursor_size_to = -1;
2531 }
2532
2533 slot = sisusb->sisusb_cursor_loc;
2534 if(slot < 0) slot = 0;
2535
2536 sisusb->sisusb_cursor_loc = -1;
2537 sisusb->bad_cursor_pos = 1;
2538
2539 sisusb_set_cursor(sisusb, slot);
2540
2541 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2542 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2543
2544 sisusb->textmodedestroyed = 0;
2545
2546 /* sisusb->lock is down */
2547
2548 return ret;
2549}
2550
2551#endif
2552
2273/* fops */ 2553/* fops */
2274 2554
2275static int 2555static int
@@ -2329,7 +2609,7 @@ sisusb_open(struct inode *inode, struct file *file)
2329 } 2609 }
2330 } 2610 }
2331 2611
2332 /* increment usage count for the device */ 2612 /* Increment usage count for our sisusb */
2333 kref_get(&sisusb->kref); 2613 kref_get(&sisusb->kref);
2334 2614
2335 sisusb->isopen = 1; 2615 sisusb->isopen = 1;
@@ -2340,12 +2620,10 @@ sisusb_open(struct inode *inode, struct file *file)
2340 2620
2341 up(&disconnect_sem); 2621 up(&disconnect_sem);
2342 2622
2343 printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
2344
2345 return 0; 2623 return 0;
2346} 2624}
2347 2625
2348static void 2626void
2349sisusb_delete(struct kref *kref) 2627sisusb_delete(struct kref *kref)
2350{ 2628{
2351 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); 2629 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2637,9 @@ sisusb_delete(struct kref *kref)
2359 sisusb->sisusb_dev = NULL; 2637 sisusb->sisusb_dev = NULL;
2360 sisusb_free_buffers(sisusb); 2638 sisusb_free_buffers(sisusb);
2361 sisusb_free_urbs(sisusb); 2639 sisusb_free_urbs(sisusb);
2640#ifdef INCL_SISUSB_CON
2641 kfree(sisusb->SiS_Pr);
2642#endif
2362 kfree(sisusb); 2643 kfree(sisusb);
2363} 2644}
2364 2645
@@ -2395,8 +2676,6 @@ sisusb_release(struct inode *inode, struct file *file)
2395 2676
2396 up(&disconnect_sem); 2677 up(&disconnect_sem);
2397 2678
2398 printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
2399
2400 return 0; 2679 return 0;
2401} 2680}
2402 2681
@@ -2733,6 +3012,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2733 int retval, port, length; 3012 int retval, port, length;
2734 u32 address; 3013 u32 address;
2735 3014
3015 /* All our commands require the device
3016 * to be initialized.
3017 */
3018 if (!sisusb->devinit)
3019 return -ENODEV;
3020
2736 port = y->data3 - 3021 port = y->data3 -
2737 SISUSB_PCI_PSEUDO_IOPORTBASE + 3022 SISUSB_PCI_PSEUDO_IOPORTBASE +
2738 SISUSB_PCI_IOPORTBASE; 3023 SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +3059,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2774 break; 3059 break;
2775 3060
2776 case SUCMD_CLRSCR: 3061 case SUCMD_CLRSCR:
3062 /* Gfx core must be initialized */
3063 if (!sisusb->gfxinit)
3064 return -ENODEV;
3065
2777 length = (y->data0 << 16) | (y->data1 << 8) | y->data2; 3066 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2778 address = y->data3 - 3067 address = y->data3 -
2779 SISUSB_PCI_PSEUDO_MEMBASE + 3068 SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,11 +3070,61 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2781 retval = sisusb_clear_vram(sisusb, address, length); 3070 retval = sisusb_clear_vram(sisusb, address, length);
2782 break; 3071 break;
2783 3072
3073 case SUCMD_HANDLETEXTMODE:
3074 retval = 0;
3075#ifdef INCL_SISUSB_CON
3076 /* Gfx core must be initialized, SiS_Pr must exist */
3077 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3078 return -ENODEV;
3079
3080 switch (y->data0) {
3081 case 0:
3082 retval = sisusb_reset_text_mode(sisusb, 0);
3083 break;
3084 case 1:
3085 sisusb->textmodedestroyed = 1;
3086 break;
3087 }
3088#endif
3089 break;
3090
3091#ifdef INCL_SISUSB_CON
3092 case SUCMD_SETMODE:
3093 /* Gfx core must be initialized, SiS_Pr must exist */
3094 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3095 return -ENODEV;
3096
3097 retval = 0;
3098
3099 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3100 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3101
3102 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
3103 retval = -EINVAL;
3104
3105 break;
3106
3107 case SUCMD_SETVESAMODE:
3108 /* Gfx core must be initialized, SiS_Pr must exist */
3109 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3110 return -ENODEV;
3111
3112 retval = 0;
3113
3114 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3115 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3116
3117 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
3118 retval = -EINVAL;
3119
3120 break;
3121#endif
3122
2784 default: 3123 default:
2785 retval = -EINVAL; 3124 retval = -EINVAL;
2786 } 3125 }
2787 3126
2788 if(retval > 0) 3127 if (retval > 0)
2789 retval = -EIO; 3128 retval = -EIO;
2790 3129
2791 return retval; 3130 return retval;
@@ -2835,6 +3174,11 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2835 x.sisusb_vramsize = sisusb->vramsize; 3174 x.sisusb_vramsize = sisusb->vramsize;
2836 x.sisusb_minor = sisusb->minor; 3175 x.sisusb_minor = sisusb->minor;
2837 x.sisusb_fbdevactive= 0; 3176 x.sisusb_fbdevactive= 0;
3177#ifdef INCL_SISUSB_CON
3178 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3179#else
3180 x.sisusb_conactive = 0;
3181#endif
2838 3182
2839 if (copy_to_user((void __user *)arg, &x, sizeof(x))) 3183 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2840 retval = -EFAULT; 3184 retval = -EFAULT;
@@ -2895,9 +3239,13 @@ static struct file_operations usb_sisusb_fops = {
2895}; 3239};
2896 3240
2897static struct usb_class_driver usb_sisusb_class = { 3241static struct usb_class_driver usb_sisusb_class = {
3242#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
2898 .name = "usb/sisusbvga%d", 3243 .name = "usb/sisusbvga%d",
2899 .fops = &usb_sisusb_fops,
2900 .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, 3244 .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
3245#else
3246 .name = "sisusbvga%d",
3247#endif
3248 .fops = &usb_sisusb_fops,
2901 .minor_base = SISUSB_MINOR 3249 .minor_base = SISUSB_MINOR
2902}; 3250};
2903 3251
@@ -2994,12 +3342,25 @@ static int sisusb_probe(struct usb_interface *intf,
2994 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n", 3342 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
2995 sisusb->minor, sisusb->numobufs); 3343 sisusb->minor, sisusb->numobufs);
2996 3344
3345#ifdef INCL_SISUSB_CON
3346 /* Allocate our SiS_Pr */
3347 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3348 printk(KERN_ERR
3349 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3350 sisusb->minor);
3351 }
3352#endif
3353
2997 /* Do remaining init stuff */ 3354 /* Do remaining init stuff */
2998 3355
2999 init_waitqueue_head(&sisusb->wait_q); 3356 init_waitqueue_head(&sisusb->wait_q);
3000 3357
3001 usb_set_intfdata(intf, sisusb); 3358 usb_set_intfdata(intf, sisusb);
3002 3359
3360 usb_get_dev(sisusb->sisusb_dev);
3361
3362 sisusb->present = 1;
3363
3003#ifdef SISUSB_OLD_CONFIG_COMPAT 3364#ifdef SISUSB_OLD_CONFIG_COMPAT
3004 { 3365 {
3005 int ret; 3366 int ret;
@@ -3014,14 +3375,19 @@ static int sisusb_probe(struct usb_interface *intf,
3014 sisusb->minor); 3375 sisusb->minor);
3015 else 3376 else
3016 sisusb->ioctl32registered = 1; 3377 sisusb->ioctl32registered = 1;
3017
3018 } 3378 }
3019#endif 3379#endif
3020 3380
3021 sisusb->present = 1;
3022
3023 if (dev->speed == USB_SPEED_HIGH) { 3381 if (dev->speed == USB_SPEED_HIGH) {
3024 if (sisusb_init_gfxdevice(sisusb, 1)) 3382 int initscreen = 1;
3383#ifdef INCL_SISUSB_CON
3384 if (sisusb_first_vc > 0 &&
3385 sisusb_last_vc > 0 &&
3386 sisusb_first_vc <= sisusb_last_vc &&
3387 sisusb_last_vc <= MAX_NR_CONSOLES)
3388 initscreen = 0;
3389#endif
3390 if (sisusb_init_gfxdevice(sisusb, initscreen))
3025 printk(KERN_ERR 3391 printk(KERN_ERR
3026 "sisusbvga[%d]: Failed to early " 3392 "sisusbvga[%d]: Failed to early "
3027 "initialize device\n", 3393 "initialize device\n",
@@ -3035,6 +3401,16 @@ static int sisusb_probe(struct usb_interface *intf,
3035 3401
3036 sisusb->ready = 1; 3402 sisusb->ready = 1;
3037 3403
3404#ifdef SISUSBENDIANTEST
3405 printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
3406 sisusb_testreadwrite(sisusb);
3407 printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
3408#endif
3409
3410#ifdef INCL_SISUSB_CON
3411 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3412#endif
3413
3038 return 0; 3414 return 0;
3039 3415
3040error_4: 3416error_4:
@@ -3053,13 +3429,20 @@ static void sisusb_disconnect(struct usb_interface *intf)
3053 struct sisusb_usb_data *sisusb; 3429 struct sisusb_usb_data *sisusb;
3054 int minor; 3430 int minor;
3055 3431
3056 down(&disconnect_sem);
3057
3058 /* This should *not* happen */ 3432 /* This should *not* happen */
3059 if (!(sisusb = usb_get_intfdata(intf))) { 3433 if (!(sisusb = usb_get_intfdata(intf)))
3060 up(&disconnect_sem);
3061 return; 3434 return;
3062 } 3435
3436#ifdef INCL_SISUSB_CON
3437 sisusb_console_exit(sisusb);
3438#endif
3439
3440 /* The above code doesn't need the disconnect
3441 * semaphore to be down; its meaning is to
3442 * protect all other routines from the disconnect
3443 * case, not the other way round.
3444 */
3445 down(&disconnect_sem);
3063 3446
3064 down(&sisusb->lock); 3447 down(&sisusb->lock);
3065 3448
@@ -3123,11 +3506,17 @@ static int __init usb_sisusb_init(void)
3123{ 3506{
3124 int retval; 3507 int retval;
3125 3508
3509#ifdef INCL_SISUSB_CON
3510 sisusb_init_concode();
3511#endif
3512
3126 if (!(retval = usb_register(&sisusb_driver))) { 3513 if (!(retval = usb_register(&sisusb_driver))) {
3514
3127 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n", 3515 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
3128 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL); 3516 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
3129 printk(KERN_INFO 3517 printk(KERN_INFO
3130 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n"); 3518 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3519
3131 } 3520 }
3132 3521
3133 return retval; 3522 return retval;
@@ -3142,6 +3531,6 @@ module_init(usb_sisusb_init);
3142module_exit(usb_sisusb_exit); 3531module_exit(usb_sisusb_exit);
3143 3532
3144MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>"); 3533MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3145MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles"); 3534MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3146MODULE_LICENSE("GPL"); 3535MODULE_LICENSE("GPL");
3147 3536
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index 1306d006a25a..401ff21d7881 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -46,15 +46,36 @@
46#endif 46#endif
47#endif 47#endif
48 48
49/* For older kernels, support for text consoles is by default
50 * off. To ensable text console support, change the following:
51 */
52#if 0
53#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
54#define CONFIG_USB_SISUSBVGA_CON
55#endif
56#endif
57
49/* Version Information */ 58/* Version Information */
50 59
51#define SISUSB_VERSION 0 60#define SISUSB_VERSION 0
52#define SISUSB_REVISION 0 61#define SISUSB_REVISION 0
53#define SISUSB_PATCHLEVEL 7 62#define SISUSB_PATCHLEVEL 8
63
64/* Include console and mode switching code? */
65
66#ifdef CONFIG_USB_SISUSBVGA_CON
67#define INCL_SISUSB_CON 1
68#endif
69
70#ifdef INCL_SISUSB_CON
71#include <linux/console.h>
72#include <linux/vt_kern.h>
73#include "sisusb_struct.h"
74#endif
54 75
55/* USB related */ 76/* USB related */
56 77
57#define SISUSB_MINOR 133 /* FIXME */ 78#define SISUSB_MINOR 133 /* official */
58 79
59/* Size of the sisusb input/output buffers */ 80/* Size of the sisusb input/output buffers */
60#define SISUSB_IBUF_SIZE 0x01000 81#define SISUSB_IBUF_SIZE 0x01000
@@ -131,6 +152,26 @@ struct sisusb_usb_data {
131 unsigned char gfxinit; /* graphics core initialized? */ 152 unsigned char gfxinit; /* graphics core initialized? */
132 unsigned short chipid, chipvendor; 153 unsigned short chipid, chipvendor;
133 unsigned short chiprevision; 154 unsigned short chiprevision;
155#ifdef INCL_SISUSB_CON
156 struct SiS_Private *SiS_Pr;
157 unsigned long scrbuf;
158 unsigned int scrbuf_size;
159 int haveconsole, con_first, con_last;
160 int havethisconsole[MAX_NR_CONSOLES];
161 int textmodedestroyed;
162 unsigned int sisusb_num_columns; /* real number, not vt's idea */
163 int cur_start_addr, con_rolled_over;
164 int sisusb_cursor_loc, bad_cursor_pos;
165 int sisusb_cursor_size_from;
166 int sisusb_cursor_size_to;
167 int current_font_height, current_font_512;
168 int font_backup_size, font_backup_height, font_backup_512;
169 char *font_backup;
170 int font_slot;
171 struct vc_data *sisusb_display_fg;
172 int is_gfx;
173 int con_blanked;
174#endif
134}; 175};
135 176
136#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref) 177#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
@@ -249,7 +290,9 @@ struct sisusb_info {
249 290
250 __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */ 291 __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */
251 292
252 __u8 sisusb_reserved[32]; /* for future use */ 293 __u32 sisusb_conactive; /* != 0 if console driver active */
294
295 __u8 sisusb_reserved[28]; /* for future use */
253}; 296};
254 297
255struct sisusb_command { 298struct sisusb_command {
@@ -261,18 +304,24 @@ struct sisusb_command {
261 __u32 data4; /* for future use */ 304 __u32 data4; /* for future use */
262}; 305};
263 306
264#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */ 307#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
265#define SUCMD_SET 0x02 /* data1 = value */ 308#define SUCMD_SET 0x02 /* data1 = value */
266#define SUCMD_SETOR 0x03 /* data1 = or */ 309#define SUCMD_SETOR 0x03 /* data1 = or */
267#define SUCMD_SETAND 0x04 /* data1 = and */ 310#define SUCMD_SETAND 0x04 /* data1 = and */
268#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */ 311#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
269#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */ 312#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
270 313
271#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */ 314#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
315
316#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */
317
318#define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */
319#define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */
272 320
273#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command) 321#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)
274#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32) 322#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
275#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info) 323#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
324
276 325
277#endif /* SISUSB_H */ 326#endif /* SISUSB_H */
278 327
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
new file mode 100644
index 000000000000..24584463553d
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -0,0 +1,1658 @@
1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 *
4 * VGA text mode console part
5 *
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, this code is licensed under the
9 * terms of the GPL v2.
10 *
11 * Otherwise, the following license terms apply:
12 *
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
15 * * are met:
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific psisusbr written permission.
23 * *
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
36 *
37 * Portions based on vgacon.c which are
38 * Created 28 Sep 1997 by Geert Uytterhoeven
39 * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
40 * based on code Copyright (C) 1991, 1992 Linus Torvalds
41 * 1995 Jay Estabrook
42 *
43 * A note on using in_atomic() in here: We can't handle console
44 * calls from non-schedulable context due to our USB-dependend
45 * nature. For now, this driver just ignores any calls if it
46 * detects this state.
47 *
48 */
49
50#include <linux/config.h>
51#include <linux/version.h>
52#include <linux/module.h>
53#include <linux/kernel.h>
54#include <linux/signal.h>
55#include <linux/sched.h>
56#include <linux/fs.h>
57#include <linux/tty.h>
58#include <linux/console.h>
59#include <linux/string.h>
60#include <linux/kd.h>
61#include <linux/init.h>
62#include <linux/slab.h>
63#include <linux/vt_kern.h>
64#include <linux/selection.h>
65#include <linux/spinlock.h>
66#include <linux/kref.h>
67#include <linux/smp_lock.h>
68#include <linux/ioport.h>
69#include <linux/interrupt.h>
70#include <linux/vmalloc.h>
71
72#include "sisusb.h"
73
74#ifdef INCL_SISUSB_CON
75extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);
76extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);
77extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);
78extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);
79extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);
80extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);
81extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);
82
83extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
84extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
85extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
86extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
87extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
88 u32 dest, int length, size_t *bytes_written);
89
90extern void sisusb_delete(struct kref *kref);
91extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
92
93extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
94
95#define sisusbcon_writew(val, addr) (*(addr) = (val))
96#define sisusbcon_readw(addr) (*(addr))
97#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)
98#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)
99
100/* vc_data -> sisusb conversion table */
101static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
102
103/* Forward declaration */
104static const struct consw sisusb_con;
105
106extern struct semaphore disconnect_sem;
107
108static inline void
109sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
110{
111 count /= 2;
112 while (count--)
113 sisusbcon_writew(c, s++);
114}
115
116static inline void
117sisusb_initialize(struct sisusb_usb_data *sisusb)
118{
119 /* Reset cursor and start address */
120 if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))
121 return;
122 if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))
123 return;
124 if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))
125 return;
126 sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);
127}
128
129static inline void
130sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)
131{
132 sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;
133
134 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
135 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
136}
137
138void
139sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)
140{
141 if (sisusb->sisusb_cursor_loc == location)
142 return;
143
144 sisusb->sisusb_cursor_loc = location;
145
146 /* Hardware bug: Text cursor appears twice or not at all
147 * at some positions. Work around it with the cursor skew
148 * bits.
149 */
150
151 if ((location & 0x0007) == 0x0007) {
152 sisusb->bad_cursor_pos = 1;
153 location--;
154 if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))
155 return;
156 } else if (sisusb->bad_cursor_pos) {
157 if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))
158 return;
159 sisusb->bad_cursor_pos = 0;
160 }
161
162 if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))
163 return;
164 sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));
165}
166
167static inline struct sisusb_usb_data *
168sisusb_get_sisusb(unsigned short console)
169{
170 return mysisusbs[console];
171}
172
173static inline int
174sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)
175{
176 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)
177 return 0;
178
179 return 1;
180}
181
182static struct sisusb_usb_data *
183sisusb_get_sisusb_lock_and_check(unsigned short console)
184{
185 struct sisusb_usb_data *sisusb;
186
187 /* We can't handle console calls in non-schedulable
188 * context due to our locks and the USB transport.
189 * So we simply ignore them. This should only affect
190 * some calls to printk.
191 */
192 if (in_atomic())
193 return NULL;
194
195 if (!(sisusb = sisusb_get_sisusb(console)))
196 return NULL;
197
198 down(&sisusb->lock);
199
200 if (!sisusb_sisusb_valid(sisusb) ||
201 !sisusb->havethisconsole[console]) {
202 up(&sisusb->lock);
203 return NULL;
204 }
205
206 return sisusb;
207}
208
209static int
210sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)
211{
212 if (sisusb->is_gfx ||
213 sisusb->textmodedestroyed ||
214 c->vc_mode != KD_TEXT)
215 return 1;
216
217 return 0;
218}
219
220/* con_startup console interface routine */
221static const char *
222sisusbcon_startup(void)
223{
224 return "SISUSBCON";
225}
226
227/* con_init console interface routine */
228static void
229sisusbcon_init(struct vc_data *c, int init)
230{
231 struct sisusb_usb_data *sisusb;
232 int cols, rows;
233
234 /* This is called by take_over_console(),
235 * ie by us/under our control. It is
236 * only called after text mode and fonts
237 * are set up/restored.
238 */
239
240 down(&disconnect_sem);
241
242 if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
243 up(&disconnect_sem);
244 return;
245 }
246
247 down(&sisusb->lock);
248
249 if (!sisusb_sisusb_valid(sisusb)) {
250 up(&sisusb->lock);
251 up(&disconnect_sem);
252 return;
253 }
254
255 c->vc_can_do_color = 1;
256
257 c->vc_complement_mask = 0x7700;
258
259 c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;
260
261 sisusb->haveconsole = 1;
262
263 sisusb->havethisconsole[c->vc_num] = 1;
264
265 /* We only support 640x400 */
266 c->vc_scan_lines = 400;
267
268 c->vc_font.height = sisusb->current_font_height;
269
270 /* We only support width = 8 */
271 cols = 80;
272 rows = c->vc_scan_lines / c->vc_font.height;
273
274 /* Increment usage count for our sisusb.
275 * Doing so saves us from upping/downing
276 * the disconnect semaphore; we can't
277 * lose our sisusb until this is undone
278 * in con_deinit. For all other console
279 * interface functions, it suffices to
280 * use sisusb->lock and do a quick check
281 * of sisusb for device disconnection.
282 */
283 kref_get(&sisusb->kref);
284
285 if (!*c->vc_uni_pagedir_loc)
286 con_set_default_unimap(c);
287
288 up(&sisusb->lock);
289
290 up(&disconnect_sem);
291
292 if (init) {
293 c->vc_cols = cols;
294 c->vc_rows = rows;
295 } else
296 vc_resize(c, cols, rows);
297}
298
299/* con_deinit console interface routine */
300static void
301sisusbcon_deinit(struct vc_data *c)
302{
303 struct sisusb_usb_data *sisusb;
304 int i;
305
306 /* This is called by take_over_console()
307 * and others, ie not under our control.
308 */
309
310 down(&disconnect_sem);
311
312 if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
313 up(&disconnect_sem);
314 return;
315 }
316
317 down(&sisusb->lock);
318
319 /* Clear ourselves in mysisusbs */
320 mysisusbs[c->vc_num] = NULL;
321
322 sisusb->havethisconsole[c->vc_num] = 0;
323
324 /* Free our font buffer if all consoles are gone */
325 if (sisusb->font_backup) {
326 for(i = 0; i < MAX_NR_CONSOLES; i++) {
327 if (sisusb->havethisconsole[c->vc_num])
328 break;
329 }
330 if (i == MAX_NR_CONSOLES) {
331 vfree(sisusb->font_backup);
332 sisusb->font_backup = NULL;
333 }
334 }
335
336 up(&sisusb->lock);
337
338 /* decrement the usage count on our sisusb */
339 kref_put(&sisusb->kref, sisusb_delete);
340
341 up(&disconnect_sem);
342}
343
344/* interface routine */
345static u8
346sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
347 u8 blink, u8 underline, u8 reverse)
348{
349 u8 attr = color;
350
351 if (underline)
352 attr = (attr & 0xf0) | c->vc_ulcolor;
353 else if (intensity == 0)
354 attr = (attr & 0xf0) | c->vc_halfcolor;
355
356 if (reverse)
357 attr = ((attr) & 0x88) |
358 ((((attr) >> 4) |
359 ((attr) << 4)) & 0x77);
360
361 if (blink)
362 attr ^= 0x80;
363
364 if (intensity == 2)
365 attr ^= 0x08;
366
367 return attr;
368}
369
370/* Interface routine */
371static void
372sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
373{
374 /* Invert a region. This is called with a pointer
375 * to the console's internal screen buffer. So we
376 * simply do the inversion there and rely on
377 * a call to putc(s) to update the real screen.
378 */
379
380 while (count--) {
381 u16 a = sisusbcon_readw(p);
382
383 a = ((a) & 0x88ff) |
384 (((a) & 0x7000) >> 4) |
385 (((a) & 0x0700) << 4);
386
387 sisusbcon_writew(a, p++);
388 }
389}
390
391#define SISUSB_VADDR(x,y) \
392 ((u16 *)c->vc_origin + \
393 (y) * sisusb->sisusb_num_columns + \
394 (x))
395
396#define SISUSB_HADDR(x,y) \
397 ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
398 (y) * sisusb->sisusb_num_columns + \
399 (x))
400
401/* Interface routine */
402static void
403sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
404{
405 struct sisusb_usb_data *sisusb;
406 ssize_t written;
407
408 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
409 return;
410
411 /* sisusb->lock is down */
412
413 /* Don't need to put the character into buffer ourselves,
414 * because the vt does this BEFORE calling us.
415 */
416#if 0
417 sisusbcon_writew(ch, SISUSB_VADDR(x, y));
418#endif
419
420 if (sisusb_is_inactive(c, sisusb)) {
421 up(&sisusb->lock);
422 return;
423 }
424
425
426 sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
427 (u32)SISUSB_HADDR(x, y), 2, &written);
428
429 up(&sisusb->lock);
430}
431
432/* Interface routine */
433static void
434sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
435 int count, int y, int x)
436{
437 struct sisusb_usb_data *sisusb;
438 ssize_t written;
439 u16 *dest;
440 int i;
441
442 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
443 return;
444
445 /* sisusb->lock is down */
446
447 /* Need to put the characters into the buffer ourselves,
448 * because the vt does this AFTER calling us.
449 */
450
451 dest = SISUSB_VADDR(x, y);
452
453 for (i = count; i > 0; i--)
454 sisusbcon_writew(sisusbcon_readw(s++), dest++);
455
456 if (sisusb_is_inactive(c, sisusb)) {
457 up(&sisusb->lock);
458 return;
459 }
460
461 sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
462 (u32)SISUSB_HADDR(x, y), count * 2, &written);
463
464 up(&sisusb->lock);
465}
466
467/* Interface routine */
468static void
469sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
470{
471 struct sisusb_usb_data *sisusb;
472 u16 eattr = c->vc_video_erase_char;
473 ssize_t written;
474 int i, length, cols;
475 u16 *dest;
476
477 if (width <= 0 || height <= 0)
478 return;
479
480 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
481 return;
482
483 /* sisusb->lock is down */
484
485 /* Need to clear buffer ourselves, because the vt does
486 * this AFTER calling us.
487 */
488
489 dest = SISUSB_VADDR(x, y);
490
491 cols = sisusb->sisusb_num_columns;
492
493 if (width > cols)
494 width = cols;
495
496 if (x == 0 && width >= c->vc_cols) {
497
498 sisusbcon_memsetw(dest, eattr, height * cols * 2);
499
500 } else {
501
502 for (i = height; i > 0; i--, dest += cols)
503 sisusbcon_memsetw(dest, eattr, width * 2);
504
505 }
506
507 if (sisusb_is_inactive(c, sisusb)) {
508 up(&sisusb->lock);
509 return;
510 }
511
512 length = ((height * cols) - x - (cols - width - x)) * 2;
513
514
515 sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
516 (u32)SISUSB_HADDR(x, y), length, &written);
517
518 up(&sisusb->lock);
519}
520
521/* Interface routine */
522static void
523sisusbcon_bmove(struct vc_data *c, int sy, int sx,
524 int dy, int dx, int height, int width)
525{
526 struct sisusb_usb_data *sisusb;
527 ssize_t written;
528 int cols, length;
529#if 0
530 u16 *src, *dest;
531 int i;
532#endif
533
534 if (width <= 0 || height <= 0)
535 return;
536
537 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
538 return;
539
540 /* sisusb->lock is down */
541
542 cols = sisusb->sisusb_num_columns;
543
544 /* Don't need to move data outselves, because
545 * vt does this BEFORE calling us.
546 * This is only used by vt's insert/deletechar.
547 */
548#if 0
549 if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {
550
551 sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),
552 height * width * 2);
553
554 } else if (dy < sy || (dy == sy && dx < sx)) {
555
556 src = SISUSB_VADDR(sx, sy);
557 dest = SISUSB_VADDR(dx, dy);
558
559 for (i = height; i > 0; i--) {
560 sisusbcon_memmovew(dest, src, width * 2);
561 src += cols;
562 dest += cols;
563 }
564
565 } else {
566
567 src = SISUSB_VADDR(sx, sy + height - 1);
568 dest = SISUSB_VADDR(dx, dy + height - 1);
569
570 for (i = height; i > 0; i--) {
571 sisusbcon_memmovew(dest, src, width * 2);
572 src -= cols;
573 dest -= cols;
574 }
575
576 }
577#endif
578
579 if (sisusb_is_inactive(c, sisusb)) {
580 up(&sisusb->lock);
581 return;
582 }
583
584 length = ((height * cols) - dx - (cols - width - dx)) * 2;
585
586
587 sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
588 (u32)SISUSB_HADDR(dx, dy), length, &written);
589
590 up(&sisusb->lock);
591}
592
593/* interface routine */
594static int
595sisusbcon_switch(struct vc_data *c)
596{
597 struct sisusb_usb_data *sisusb;
598 ssize_t written;
599 int length;
600
601 /* Returnvalue 0 means we have fully restored screen,
602 * and vt doesn't need to call do_update_region().
603 * Returnvalue != 0 naturally means the opposite.
604 */
605
606 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
607 return 0;
608
609 /* sisusb->lock is down */
610
611 /* Don't write to screen if in gfx mode */
612 if (sisusb_is_inactive(c, sisusb)) {
613 up(&sisusb->lock);
614 return 0;
615 }
616
617 /* That really should not happen. It would mean we are
618 * being called while the vc is using its private buffer
619 * as origin.
620 */
621 if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
622 up(&sisusb->lock);
623 printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");
624 return 0;
625 }
626
627 /* Check that we don't copy too much */
628 length = min((int)c->vc_screenbuf_size,
629 (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
630
631 /* Restore the screen contents */
632 sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
633 length);
634
635 sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
636 (u32)SISUSB_HADDR(0, 0),
637 length, &written);
638
639 up(&sisusb->lock);
640
641 return 0;
642}
643
644/* interface routine */
645static void
646sisusbcon_save_screen(struct vc_data *c)
647{
648 struct sisusb_usb_data *sisusb;
649 int length;
650
651 /* Save the current screen contents to vc's private
652 * buffer.
653 */
654
655 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
656 return;
657
658 /* sisusb->lock is down */
659
660 if (sisusb_is_inactive(c, sisusb)) {
661 up(&sisusb->lock);
662 return;
663 }
664
665 /* Check that we don't copy too much */
666 length = min((int)c->vc_screenbuf_size,
667 (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
668
669 /* Save the screen contents to vc's private buffer */
670 sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
671 length);
672
673 up(&sisusb->lock);
674}
675
676/* interface routine */
677static int
678sisusbcon_set_palette(struct vc_data *c, unsigned char *table)
679{
680 struct sisusb_usb_data *sisusb;
681 int i, j;
682
683 /* Return value not used by vt */
684
685 if (!CON_IS_VISIBLE(c))
686 return -EINVAL;
687
688 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
689 return -EINVAL;
690
691 /* sisusb->lock is down */
692
693 if (sisusb_is_inactive(c, sisusb)) {
694 up(&sisusb->lock);
695 return -EINVAL;
696 }
697
698 for (i = j = 0; i < 16; i++) {
699 if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))
700 break;
701 if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
702 break;
703 if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
704 break;
705 if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
706 break;
707 }
708
709 up(&sisusb->lock);
710
711 return 0;
712}
713
714/* interface routine */
715static int
716sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
717{
718 struct sisusb_usb_data *sisusb;
719 u8 sr1, cr17, pmreg, cr63;
720 ssize_t written;
721 int ret = 0;
722
723 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
724 return 0;
725
726 /* sisusb->lock is down */
727
728 if (mode_switch)
729 sisusb->is_gfx = blank ? 1 : 0;
730
731 if (sisusb_is_inactive(c, sisusb)) {
732 up(&sisusb->lock);
733 return 0;
734 }
735
736 switch (blank) {
737
738 case 1: /* Normal blanking: Clear screen */
739 case -1:
740 sisusbcon_memsetw((u16 *)c->vc_origin,
741 c->vc_video_erase_char,
742 c->vc_screenbuf_size);
743 sisusb_copy_memory(sisusb,
744 (unsigned char *)c->vc_origin,
745 (u32)(sisusb->vrambase +
746 (c->vc_origin - sisusb->scrbuf)),
747 c->vc_screenbuf_size, &written);
748 sisusb->con_blanked = 1;
749 ret = 1;
750 break;
751
752 default: /* VESA blanking */
753 switch (blank) {
754 case 0: /* Unblank */
755 sr1 = 0x00;
756 cr17 = 0x80;
757 pmreg = 0x00;
758 cr63 = 0x00;
759 ret = 1;
760 sisusb->con_blanked = 0;
761 break;
762 case VESA_VSYNC_SUSPEND + 1:
763 sr1 = 0x20;
764 cr17 = 0x80;
765 pmreg = 0x80;
766 cr63 = 0x40;
767 break;
768 case VESA_HSYNC_SUSPEND + 1:
769 sr1 = 0x20;
770 cr17 = 0x80;
771 pmreg = 0x40;
772 cr63 = 0x40;
773 break;
774 case VESA_POWERDOWN + 1:
775 sr1 = 0x20;
776 cr17 = 0x00;
777 pmreg = 0xc0;
778 cr63 = 0x40;
779 break;
780 default:
781 up(&sisusb->lock);
782 return -EINVAL;
783 }
784
785 sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);
786 sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);
787 sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);
788 sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);
789
790 }
791
792 up(&sisusb->lock);
793
794 return ret;
795}
796
797/* interface routine */
798static int
799sisusbcon_scrolldelta(struct vc_data *c, int lines)
800{
801 struct sisusb_usb_data *sisusb;
802 int margin = c->vc_size_row * 4;
803 int ul, we, p, st;
804
805 /* The return value does not seem to be used */
806
807 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
808 return 0;
809
810 /* sisusb->lock is down */
811
812 if (sisusb_is_inactive(c, sisusb)) {
813 up(&sisusb->lock);
814 return 0;
815 }
816
817 if (!lines) /* Turn scrollback off */
818 c->vc_visible_origin = c->vc_origin;
819 else {
820
821 if (sisusb->con_rolled_over >
822 (c->vc_scr_end - sisusb->scrbuf) + margin) {
823
824 ul = c->vc_scr_end - sisusb->scrbuf;
825 we = sisusb->con_rolled_over + c->vc_size_row;
826
827 } else {
828
829 ul = 0;
830 we = sisusb->scrbuf_size;
831
832 }
833
834 p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +
835 lines * c->vc_size_row;
836
837 st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;
838
839 if (st < 2 * margin)
840 margin = 0;
841
842 if (p < margin)
843 p = 0;
844
845 if (p > st - margin)
846 p = st;
847
848 c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;
849 }
850
851 sisusbcon_set_start_address(sisusb, c);
852
853 up(&sisusb->lock);
854
855 return 1;
856}
857
858/* Interface routine */
859static void
860sisusbcon_cursor(struct vc_data *c, int mode)
861{
862 struct sisusb_usb_data *sisusb;
863 int from, to, baseline;
864
865 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
866 return;
867
868 /* sisusb->lock is down */
869
870 if (sisusb_is_inactive(c, sisusb)) {
871 up(&sisusb->lock);
872 return;
873 }
874
875 if (c->vc_origin != c->vc_visible_origin) {
876 c->vc_visible_origin = c->vc_origin;
877 sisusbcon_set_start_address(sisusb, c);
878 }
879
880 if (mode == CM_ERASE) {
881 sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
882 sisusb->sisusb_cursor_size_to = -1;
883 up(&sisusb->lock);
884 return;
885 }
886
887 sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);
888
889 baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
890
891 switch (c->vc_cursor_type & 0x0f) {
892 case CUR_BLOCK: from = 1;
893 to = c->vc_font.height;
894 break;
895 case CUR_TWO_THIRDS: from = c->vc_font.height / 3;
896 to = baseline;
897 break;
898 case CUR_LOWER_HALF: from = c->vc_font.height / 2;
899 to = baseline;
900 break;
901 case CUR_LOWER_THIRD: from = (c->vc_font.height * 2) / 3;
902 to = baseline;
903 break;
904 case CUR_NONE: from = 31;
905 to = 30;
906 break;
907 default:
908 case CUR_UNDERLINE: from = baseline - 1;
909 to = baseline;
910 break;
911 }
912
913 if (sisusb->sisusb_cursor_size_from != from ||
914 sisusb->sisusb_cursor_size_to != to) {
915
916 sisusb_setidxreg(sisusb, SISCR, 0x0a, from);
917 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);
918
919 sisusb->sisusb_cursor_size_from = from;
920 sisusb->sisusb_cursor_size_to = to;
921 }
922
923 up(&sisusb->lock);
924}
925
926static int
927sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
928 int t, int b, int dir, int lines)
929{
930 int cols = sisusb->sisusb_num_columns;
931 int length = ((b - t) * cols) * 2;
932 u16 eattr = c->vc_video_erase_char;
933 ssize_t written;
934
935 /* sisusb->lock is down */
936
937 /* Scroll an area which does not match the
938 * visible screen's dimensions. This needs
939 * to be done separately, as it does not
940 * use hardware panning.
941 */
942
943 switch (dir) {
944
945 case SM_UP:
946 sisusbcon_memmovew(SISUSB_VADDR(0, t),
947 SISUSB_VADDR(0, t + lines),
948 (b - t - lines) * cols * 2);
949 sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
950 lines * cols * 2);
951 break;
952
953 case SM_DOWN:
954 sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
955 SISUSB_VADDR(0, t),
956 (b - t - lines) * cols * 2);
957 sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
958 lines * cols * 2);
959 break;
960 }
961
962 sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
963 (u32)SISUSB_HADDR(0, t), length, &written);
964
965 up(&sisusb->lock);
966
967 return 1;
968}
969
970/* Interface routine */
971static int
972sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
973{
974 struct sisusb_usb_data *sisusb;
975 u16 eattr = c->vc_video_erase_char;
976 ssize_t written;
977 int copyall = 0;
978 unsigned long oldorigin;
979 unsigned int delta = lines * c->vc_size_row;
980 u32 originoffset;
981
982 /* Returning != 0 means we have done the scrolling successfully.
983 * Returning 0 makes vt do the scrolling on its own.
984 * Note that con_scroll is only called if the console is
985 * visible. In that case, the origin should be our buffer,
986 * not the vt's private one.
987 */
988
989 if (!lines)
990 return 1;
991
992 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
993 return 0;
994
995 /* sisusb->lock is down */
996
997 if (sisusb_is_inactive(c, sisusb)) {
998 up(&sisusb->lock);
999 return 0;
1000 }
1001
1002 /* Special case */
1003 if (t || b != c->vc_rows)
1004 return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);
1005
1006 if (c->vc_origin != c->vc_visible_origin) {
1007 c->vc_visible_origin = c->vc_origin;
1008 sisusbcon_set_start_address(sisusb, c);
1009 }
1010
1011 /* limit amount to maximum realistic size */
1012 if (lines > c->vc_rows)
1013 lines = c->vc_rows;
1014
1015 oldorigin = c->vc_origin;
1016
1017 switch (dir) {
1018
1019 case SM_UP:
1020
1021 if (c->vc_scr_end + delta >=
1022 sisusb->scrbuf + sisusb->scrbuf_size) {
1023 sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
1024 (u16 *)(oldorigin + delta),
1025 c->vc_screenbuf_size - delta);
1026 c->vc_origin = sisusb->scrbuf;
1027 sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;
1028 copyall = 1;
1029 } else
1030 c->vc_origin += delta;
1031
1032 sisusbcon_memsetw(
1033 (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),
1034 eattr, delta);
1035
1036 break;
1037
1038 case SM_DOWN:
1039
1040 if (oldorigin - delta < sisusb->scrbuf) {
1041 sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
1042 sisusb->scrbuf_size -
1043 c->vc_screenbuf_size +
1044 delta),
1045 (u16 *)oldorigin,
1046 c->vc_screenbuf_size - delta);
1047 c->vc_origin = sisusb->scrbuf +
1048 sisusb->scrbuf_size -
1049 c->vc_screenbuf_size;
1050 sisusb->con_rolled_over = 0;
1051 copyall = 1;
1052 } else
1053 c->vc_origin -= delta;
1054
1055 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1056
1057 scr_memsetw((u16 *)(c->vc_origin), eattr, delta);
1058
1059 break;
1060 }
1061
1062 originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
1063
1064 if (copyall)
1065 sisusb_copy_memory(sisusb,
1066 (char *)c->vc_origin,
1067 (u32)(sisusb->vrambase + originoffset),
1068 c->vc_screenbuf_size, &written);
1069 else if (dir == SM_UP)
1070 sisusb_copy_memory(sisusb,
1071 (char *)c->vc_origin + c->vc_screenbuf_size - delta,
1072 (u32)sisusb->vrambase + originoffset +
1073 c->vc_screenbuf_size - delta,
1074 delta, &written);
1075 else
1076 sisusb_copy_memory(sisusb,
1077 (char *)c->vc_origin,
1078 (u32)(sisusb->vrambase + originoffset),
1079 delta, &written);
1080
1081 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1082 c->vc_visible_origin = c->vc_origin;
1083
1084 sisusbcon_set_start_address(sisusb, c);
1085
1086 c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
1087
1088 up(&sisusb->lock);
1089
1090 return 1;
1091}
1092
1093/* Interface routine */
1094static int
1095sisusbcon_set_origin(struct vc_data *c)
1096{
1097 struct sisusb_usb_data *sisusb;
1098
1099 /* Returning != 0 means we were successful.
1100 * Returning 0 will vt make to use its own
1101 * screenbuffer as the origin.
1102 */
1103
1104 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1105 return 0;
1106
1107 /* sisusb->lock is down */
1108
1109 if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
1110 up(&sisusb->lock);
1111 return 0;
1112 }
1113
1114 c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;
1115
1116 sisusbcon_set_start_address(sisusb, c);
1117
1118 sisusb->con_rolled_over = 0;
1119
1120 up(&sisusb->lock);
1121
1122 return 1;
1123}
1124
1125/* Interface routine */
1126static int
1127sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)
1128{
1129 struct sisusb_usb_data *sisusb;
1130 int fh;
1131
1132 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1133 return -ENODEV;
1134
1135 fh = sisusb->current_font_height;
1136
1137 up(&sisusb->lock);
1138
1139 /* We are quite unflexible as regards resizing. The vt code
1140 * handles sizes where the line length isn't equal the pitch
1141 * quite badly. As regards the rows, our panning tricks only
1142 * work well if the number of rows equals the visible number
1143 * of rows.
1144 */
1145
1146 if (newcols != 80 || c->vc_scan_lines / fh != newrows)
1147 return -EINVAL;
1148
1149 return 0;
1150}
1151
1152int
1153sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
1154 u8 *arg, int cmapsz, int ch512, int dorecalc,
1155 struct vc_data *c, int fh, int uplock)
1156{
1157 int font_select = 0x00, i, err = 0;
1158 u32 offset = 0;
1159 u8 dummy;
1160
1161 /* sisusb->lock is down */
1162
1163 /*
1164 * The default font is kept in slot 0.
1165 * A user font is loaded in slot 2 (256 ch)
1166 * or 2+3 (512 ch).
1167 */
1168
1169 if ((slot != 0 && slot != 2) || !fh) {
1170 if (uplock)
1171 up(&sisusb->lock);
1172 return -EINVAL;
1173 }
1174
1175 if (set)
1176 sisusb->font_slot = slot;
1177
1178 /* Default font is always 256 */
1179 if (slot == 0)
1180 ch512 = 0;
1181 else
1182 offset = 4 * cmapsz;
1183
1184 font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);
1185
1186 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
1187 err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */
1188 err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */
1189 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */
1190
1191 if (err)
1192 goto font_op_error;
1193
1194 err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */
1195 err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */
1196 err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */
1197
1198 if (err)
1199 goto font_op_error;
1200
1201 if (arg) {
1202 if (set)
1203 for (i = 0; i < cmapsz; i++) {
1204 err |= sisusb_writeb(sisusb,
1205 sisusb->vrambase + offset + i,
1206 arg[i]);
1207 if (err)
1208 break;
1209 }
1210 else
1211 for (i = 0; i < cmapsz; i++) {
1212 err |= sisusb_readb(sisusb,
1213 sisusb->vrambase + offset + i,
1214 &arg[i]);
1215 if (err)
1216 break;
1217 }
1218
1219 /*
1220 * In 512-character mode, the character map is not contiguous if
1221 * we want to remain EGA compatible -- which we do
1222 */
1223
1224 if (ch512) {
1225 if (set)
1226 for (i = 0; i < cmapsz; i++) {
1227 err |= sisusb_writeb(sisusb,
1228 sisusb->vrambase + offset +
1229 (2 * cmapsz) + i,
1230 arg[cmapsz + i]);
1231 if (err)
1232 break;
1233 }
1234 else
1235 for (i = 0; i < cmapsz; i++) {
1236 err |= sisusb_readb(sisusb,
1237 sisusb->vrambase + offset +
1238 (2 * cmapsz) + i,
1239 &arg[cmapsz + i]);
1240 if (err)
1241 break;
1242 }
1243 }
1244 }
1245
1246 if (err)
1247 goto font_op_error;
1248
1249 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
1250 err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */
1251 err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */
1252 if (set)
1253 sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);
1254 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */
1255
1256 if (err)
1257 goto font_op_error;
1258
1259 err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */
1260 err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */
1261 err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */
1262
1263 if (err)
1264 goto font_op_error;
1265
1266 if ((set) && (ch512 != sisusb->current_font_512)) {
1267
1268 /* Font is shared among all our consoles.
1269 * And so is the hi_font_mask.
1270 */
1271 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1272 struct vc_data *c = vc_cons[i].d;
1273 if (c && c->vc_sw == &sisusb_con)
1274 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1275 }
1276
1277 sisusb->current_font_512 = ch512;
1278
1279 /* color plane enable register:
1280 256-char: enable intensity bit
1281 512-char: disable intensity bit */
1282 sisusb_getreg(sisusb, SISINPSTAT, &dummy);
1283 sisusb_setreg(sisusb, SISAR, 0x12);
1284 sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);
1285
1286 sisusb_getreg(sisusb, SISINPSTAT, &dummy);
1287 sisusb_setreg(sisusb, SISAR, 0x20);
1288 sisusb_getreg(sisusb, SISINPSTAT, &dummy);
1289 }
1290
1291 if (dorecalc) {
1292
1293 /*
1294 * Adjust the screen to fit a font of a certain height
1295 */
1296
1297 unsigned char ovr, vde, fsr;
1298 int rows = 0, maxscan = 0;
1299
1300 if (c) {
1301
1302 /* Number of video rows */
1303 rows = c->vc_scan_lines / fh;
1304 /* Scan lines to actually display-1 */
1305 maxscan = rows * fh - 1;
1306
1307 /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
1308 rows, maxscan, fh, c->vc_scan_lines);*/
1309
1310 sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);
1311 vde = maxscan & 0xff;
1312 ovr = (ovr & 0xbd) |
1313 ((maxscan & 0x100) >> 7) |
1314 ((maxscan & 0x200) >> 3);
1315 sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);
1316 sisusb_setidxreg(sisusb, SISCR, 0x12, vde);
1317
1318 }
1319
1320 sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);
1321 fsr = (fsr & 0xe0) | (fh - 1);
1322 sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);
1323 sisusb->current_font_height = fh;
1324
1325 sisusb->sisusb_cursor_size_from = -1;
1326 sisusb->sisusb_cursor_size_to = -1;
1327
1328 }
1329
1330 if (uplock)
1331 up(&sisusb->lock);
1332
1333 if (dorecalc && c) {
1334 int i, rows = c->vc_scan_lines / fh;
1335
1336 /* Now adjust our consoles' size */
1337
1338 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1339 struct vc_data *vc = vc_cons[i].d;
1340
1341 if (vc && vc->vc_sw == &sisusb_con) {
1342 if (CON_IS_VISIBLE(vc)) {
1343 vc->vc_sw->con_cursor(vc, CM_DRAW);
1344 }
1345 vc->vc_font.height = fh;
1346 vc_resize(vc, 0, rows);
1347 }
1348 }
1349 }
1350
1351 return 0;
1352
1353font_op_error:
1354 if (uplock)
1355 up(&sisusb->lock);
1356
1357 return -EIO;
1358}
1359
1360/* Interface routine */
1361static int
1362sisusbcon_font_set(struct vc_data *c, struct console_font *font,
1363 unsigned flags)
1364{
1365 struct sisusb_usb_data *sisusb;
1366 unsigned charcount = font->charcount;
1367
1368 if (font->width != 8 || (charcount != 256 && charcount != 512))
1369 return -EINVAL;
1370
1371 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1372 return -ENODEV;
1373
1374 /* sisusb->lock is down */
1375
1376 /* Save the user-provided font into a buffer. This
1377 * is used for restoring text mode after quitting
1378 * from X and for the con_getfont routine.
1379 */
1380 if (sisusb->font_backup) {
1381 if (sisusb->font_backup_size < charcount) {
1382 vfree(sisusb->font_backup);
1383 sisusb->font_backup = NULL;
1384 }
1385 }
1386
1387 if (!sisusb->font_backup)
1388 sisusb->font_backup = vmalloc(charcount * 32);
1389
1390 if (sisusb->font_backup) {
1391 memcpy(sisusb->font_backup, font->data, charcount * 32);
1392 sisusb->font_backup_size = charcount;
1393 sisusb->font_backup_height = font->height;
1394 sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;
1395 }
1396
1397 /* do_font_op ups sisusb->lock */
1398
1399 return sisusbcon_do_font_op(sisusb, 1, 2, font->data,
1400 8192, (charcount == 512),
1401 (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,
1402 c, font->height, 1);
1403}
1404
1405/* Interface routine */
1406static int
1407sisusbcon_font_get(struct vc_data *c, struct console_font *font)
1408{
1409 struct sisusb_usb_data *sisusb;
1410
1411 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1412 return -ENODEV;
1413
1414 /* sisusb->lock is down */
1415
1416 font->width = 8;
1417 font->height = c->vc_font.height;
1418 font->charcount = 256;
1419
1420 if (!font->data) {
1421 up(&sisusb->lock);
1422 return 0;
1423 }
1424
1425 if (!sisusb->font_backup) {
1426 up(&sisusb->lock);
1427 return -ENODEV;
1428 }
1429
1430 /* Copy 256 chars only, like vgacon */
1431 memcpy(font->data, sisusb->font_backup, 256 * 32);
1432
1433 up(&sisusb->lock);
1434
1435 return 0;
1436}
1437
1438/*
1439 * The console `switch' structure for the sisusb console
1440 */
1441
1442static const struct consw sisusb_con = {
1443 .owner = THIS_MODULE,
1444 .con_startup = sisusbcon_startup,
1445 .con_init = sisusbcon_init,
1446 .con_deinit = sisusbcon_deinit,
1447 .con_clear = sisusbcon_clear,
1448 .con_putc = sisusbcon_putc,
1449 .con_putcs = sisusbcon_putcs,
1450 .con_cursor = sisusbcon_cursor,
1451 .con_scroll = sisusbcon_scroll,
1452 .con_bmove = sisusbcon_bmove,
1453 .con_switch = sisusbcon_switch,
1454 .con_blank = sisusbcon_blank,
1455 .con_font_set = sisusbcon_font_set,
1456 .con_font_get = sisusbcon_font_get,
1457 .con_set_palette = sisusbcon_set_palette,
1458 .con_scrolldelta = sisusbcon_scrolldelta,
1459 .con_build_attr = sisusbcon_build_attr,
1460 .con_invert_region = sisusbcon_invert_region,
1461 .con_set_origin = sisusbcon_set_origin,
1462 .con_save_screen = sisusbcon_save_screen,
1463 .con_resize = sisusbcon_resize,
1464};
1465
1466/* Our very own dummy console driver */
1467
1468static const char *sisusbdummycon_startup(void)
1469{
1470 return "SISUSBVGADUMMY";
1471}
1472
1473static void sisusbdummycon_init(struct vc_data *vc, int init)
1474{
1475 vc->vc_can_do_color = 1;
1476 if (init) {
1477 vc->vc_cols = 80;
1478 vc->vc_rows = 25;
1479 } else
1480 vc_resize(vc, 80, 25);
1481}
1482
1483static int sisusbdummycon_dummy(void)
1484{
1485 return 0;
1486}
1487
1488#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy
1489
1490const struct consw sisusb_dummy_con = {
1491 .owner = THIS_MODULE,
1492 .con_startup = sisusbdummycon_startup,
1493 .con_init = sisusbdummycon_init,
1494 .con_deinit = SISUSBCONDUMMY,
1495 .con_clear = SISUSBCONDUMMY,
1496 .con_putc = SISUSBCONDUMMY,
1497 .con_putcs = SISUSBCONDUMMY,
1498 .con_cursor = SISUSBCONDUMMY,
1499 .con_scroll = SISUSBCONDUMMY,
1500 .con_bmove = SISUSBCONDUMMY,
1501 .con_switch = SISUSBCONDUMMY,
1502 .con_blank = SISUSBCONDUMMY,
1503 .con_font_set = SISUSBCONDUMMY,
1504 .con_font_get = SISUSBCONDUMMY,
1505 .con_font_default = SISUSBCONDUMMY,
1506 .con_font_copy = SISUSBCONDUMMY,
1507 .con_set_palette = SISUSBCONDUMMY,
1508 .con_scrolldelta = SISUSBCONDUMMY,
1509};
1510
1511int
1512sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
1513{
1514 int i, ret, minor = sisusb->minor;
1515
1516 down(&disconnect_sem);
1517
1518 down(&sisusb->lock);
1519
1520 /* Erm.. that should not happen */
1521 if (sisusb->haveconsole || !sisusb->SiS_Pr) {
1522 up(&sisusb->lock);
1523 up(&disconnect_sem);
1524 return 1;
1525 }
1526
1527 sisusb->con_first = first;
1528 sisusb->con_last = last;
1529
1530 if (first > last ||
1531 first > MAX_NR_CONSOLES ||
1532 last > MAX_NR_CONSOLES) {
1533 up(&sisusb->lock);
1534 up(&disconnect_sem);
1535 return 1;
1536 }
1537
1538 /* If gfxcore not initialized or no consoles given, quit graciously */
1539 if (!sisusb->gfxinit || first < 1 || last < 1) {
1540 up(&sisusb->lock);
1541 up(&disconnect_sem);
1542 return 0;
1543 }
1544
1545 sisusb->sisusb_cursor_loc = -1;
1546 sisusb->sisusb_cursor_size_from = -1;
1547 sisusb->sisusb_cursor_size_to = -1;
1548
1549 /* Set up text mode (and upload default font) */
1550 if (sisusb_reset_text_mode(sisusb, 1)) {
1551 up(&sisusb->lock);
1552 up(&disconnect_sem);
1553 printk(KERN_ERR
1554 "sisusbvga[%d]: Failed to set up text mode\n",
1555 minor);
1556 return 1;
1557 }
1558
1559 /* Initialize some gfx registers */
1560 sisusb_initialize(sisusb);
1561
1562 for (i = first - 1; i <= last - 1; i++) {
1563 /* Save sisusb for our interface routines */
1564 mysisusbs[i] = sisusb;
1565 }
1566
1567 /* Initial console setup */
1568 sisusb->sisusb_num_columns = 80;
1569
1570 /* Use a 32K buffer (matches b8000-bffff area) */
1571 sisusb->scrbuf_size = 32 * 1024;
1572
1573 /* Allocate screen buffer */
1574 if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
1575 up(&sisusb->lock);
1576 up(&disconnect_sem);
1577 printk(KERN_ERR
1578 "sisusbvga[%d]: Failed to allocate screen buffer\n",
1579 minor);
1580 return 1;
1581 }
1582
1583 up(&sisusb->lock);
1584 up(&disconnect_sem);
1585
1586 /* Now grab the desired console(s) */
1587 ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
1588
1589 if (!ret)
1590 sisusb->haveconsole = 1;
1591 else {
1592 for (i = first - 1; i <= last - 1; i++)
1593 mysisusbs[i] = NULL;
1594 }
1595
1596 return ret;
1597}
1598
1599void
1600sisusb_console_exit(struct sisusb_usb_data *sisusb)
1601{
1602 int i;
1603
1604 /* This is called if the device is disconnected
1605 * and while disconnect and lock semaphores
1606 * are up. This should be save because we
1607 * can't lose our sisusb any other way but by
1608 * disconnection (and hence, the disconnect
1609 * sema is for protecting all other access
1610 * functions from disconnection, not the
1611 * other way round).
1612 */
1613
1614 /* Now what do we do in case of disconnection:
1615 * One alternative would be to simply call
1616 * give_up_console(). Nah, not a good idea.
1617 * give_up_console() is obviously buggy as it
1618 * only discards the consw pointer from the
1619 * driver_map, but doesn't adapt vc->vc_sw
1620 * of the affected consoles. Hence, the next
1621 * call to any of the console functions will
1622 * eventually take a trip to oops county.
1623 * Also, give_up_console for some reason
1624 * doesn't decrement our module refcount.
1625 * Instead, we switch our consoles to a private
1626 * dummy console. This, of course, keeps our
1627 * refcount up as well, but it works perfectly.
1628 */
1629
1630 if (sisusb->haveconsole) {
1631 for (i = 0; i < MAX_NR_CONSOLES; i++)
1632 if (sisusb->havethisconsole[i])
1633 take_over_console(&sisusb_dummy_con, i, i, 0);
1634 /* At this point, con_deinit for all our
1635 * consoles is executed by take_over_console().
1636 */
1637 sisusb->haveconsole = 0;
1638 }
1639
1640 vfree((void *)sisusb->scrbuf);
1641 sisusb->scrbuf = 0;
1642
1643 vfree(sisusb->font_backup);
1644 sisusb->font_backup = NULL;
1645}
1646
1647void __init sisusb_init_concode(void)
1648{
1649 int i;
1650
1651 for (i = 0; i < MAX_NR_CONSOLES; i++)
1652 mysisusbs[i] = NULL;
1653}
1654
1655#endif /* INCL_CON */
1656
1657
1658
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
new file mode 100644
index 000000000000..f28bc240f9b6
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -0,0 +1,1047 @@
1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 *
4 * Display mode initializing code
5 *
6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, this code is licensed under the
9 * terms of the GPL v2.
10 *
11 * Otherwise, the following license terms apply:
12 *
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
15 * * are met:
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific prior written permission.
23 * *
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
36 *
37 */
38
39#include <linux/config.h>
40#include <linux/version.h>
41#include <linux/module.h>
42#include <linux/kernel.h>
43#include <linux/errno.h>
44#include <linux/poll.h>
45#include <linux/init.h>
46#include <linux/slab.h>
47#include <linux/spinlock.h>
48#include <linux/kref.h>
49
50#include "sisusb.h"
51
52#ifdef INCL_SISUSB_CON
53
54#include "sisusb_init.h"
55
56/*********************************************/
57/* POINTER INITIALIZATION */
58/*********************************************/
59
60static void
61SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
62{
63 SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo;
64 SiS_Pr->SiS_StandTable = SiSUSB_StandTable;
65
66 SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable;
67 SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable;
68 SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex;
69 SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table;
70
71 SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;
72}
73
74/*********************************************/
75/* HELPER: Get ModeID */
76/*********************************************/
77
78unsigned short
79SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
80{
81 unsigned short ModeIndex = 0;
82
83 switch (HDisplay)
84 {
85 case 320:
86 if (VDisplay == 200)
87 ModeIndex = ModeIndex_320x200[Depth];
88 else if (VDisplay == 240)
89 ModeIndex = ModeIndex_320x240[Depth];
90 break;
91 case 400:
92 if (VDisplay == 300)
93 ModeIndex = ModeIndex_400x300[Depth];
94 break;
95 case 512:
96 if (VDisplay == 384)
97 ModeIndex = ModeIndex_512x384[Depth];
98 break;
99 case 640:
100 if (VDisplay == 480)
101 ModeIndex = ModeIndex_640x480[Depth];
102 else if (VDisplay == 400)
103 ModeIndex = ModeIndex_640x400[Depth];
104 break;
105 case 720:
106 if (VDisplay == 480)
107 ModeIndex = ModeIndex_720x480[Depth];
108 else if (VDisplay == 576)
109 ModeIndex = ModeIndex_720x576[Depth];
110 break;
111 case 768:
112 if (VDisplay == 576)
113 ModeIndex = ModeIndex_768x576[Depth];
114 break;
115 case 800:
116 if (VDisplay == 600)
117 ModeIndex = ModeIndex_800x600[Depth];
118 else if (VDisplay == 480)
119 ModeIndex = ModeIndex_800x480[Depth];
120 break;
121 case 848:
122 if (VDisplay == 480)
123 ModeIndex = ModeIndex_848x480[Depth];
124 break;
125 case 856:
126 if (VDisplay == 480)
127 ModeIndex = ModeIndex_856x480[Depth];
128 break;
129 case 960:
130 if (VDisplay == 540)
131 ModeIndex = ModeIndex_960x540[Depth];
132 else if (VDisplay == 600)
133 ModeIndex = ModeIndex_960x600[Depth];
134 break;
135 case 1024:
136 if (VDisplay == 576)
137 ModeIndex = ModeIndex_1024x576[Depth];
138 else if (VDisplay == 768)
139 ModeIndex = ModeIndex_1024x768[Depth];
140 break;
141 case 1152:
142 if (VDisplay == 864)
143 ModeIndex = ModeIndex_1152x864[Depth];
144 break;
145 case 1280:
146 switch (VDisplay) {
147 case 720:
148 ModeIndex = ModeIndex_1280x720[Depth];
149 break;
150 case 768:
151 ModeIndex = ModeIndex_1280x768[Depth];
152 break;
153 case 1024:
154 ModeIndex = ModeIndex_1280x1024[Depth];
155 break;
156 }
157 }
158
159 return ModeIndex;
160}
161
162/*********************************************/
163/* HELPER: SetReg, GetReg */
164/*********************************************/
165
166static void
167SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
168 unsigned short index, unsigned short data)
169{
170 sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
171}
172
173static void
174SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
175 unsigned short data)
176{
177 sisusb_setreg(SiS_Pr->sisusb, port, data);
178}
179
180static unsigned char
181SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,
182 unsigned short index)
183{
184 u8 data;
185
186 sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
187
188 return data;
189}
190
191static unsigned char
192SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
193{
194 u8 data;
195
196 sisusb_getreg(SiS_Pr->sisusb, port, &data);
197
198 return data;
199}
200
201static void
202SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
203 unsigned short index, unsigned short DataAND,
204 unsigned short DataOR)
205{
206 sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
207}
208
209static void
210SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
211 unsigned short index, unsigned short DataAND)
212{
213 sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
214}
215
216static void
217SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,
218 unsigned short index, unsigned short DataOR)
219{
220 sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
221}
222
223/*********************************************/
224/* HELPER: DisplayOn, DisplayOff */
225/*********************************************/
226
227static void
228SiS_DisplayOn(struct SiS_Private *SiS_Pr)
229{
230 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
231}
232
233/*********************************************/
234/* HELPER: Init Port Addresses */
235/*********************************************/
236
237void
238SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
239{
240 SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
241 SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
242 SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
243 SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
244 SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
245 SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
246 SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
247 SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
248 SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
249 SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
250 SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
251 SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
252 SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
253 SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
254 SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
255}
256
257/*********************************************/
258/* HELPER: GetSysFlags */
259/*********************************************/
260
261static void
262SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
263{
264 SiS_Pr->SiS_MyCR63 = 0x63;
265}
266
267/*********************************************/
268/* HELPER: Init PCI & Engines */
269/*********************************************/
270
271static void
272SiSInitPCIetc(struct SiS_Private *SiS_Pr)
273{
274 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
275 /* - Enable 2D (0x40)
276 * - Enable 3D (0x02)
277 * - Enable 3D vertex command fetch (0x10)
278 * - Enable 3D command parser (0x08)
279 * - Enable 3D G/L transformation engine (0x80)
280 */
281 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
282}
283
284/*********************************************/
285/* HELPER: SET SEGMENT REGISTERS */
286/*********************************************/
287
288static void
289SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
290{
291 unsigned short temp;
292
293 value &= 0x00ff;
294 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
295 temp |= (value >> 4);
296 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
297 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
298 temp |= (value & 0x0f);
299 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
300}
301
302static void
303SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
304{
305 unsigned short temp;
306
307 value &= 0x00ff;
308 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
309 temp |= (value & 0xf0);
310 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
311 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
312 temp |= (value << 4);
313 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
314}
315
316static void
317SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
318{
319 SiS_SetSegRegLower(SiS_Pr, value);
320 SiS_SetSegRegUpper(SiS_Pr, value);
321}
322
323static void
324SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
325{
326 SiS_SetSegmentReg(SiS_Pr, 0);
327}
328
329static void
330SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
331{
332 unsigned short temp = value >> 8;
333
334 temp &= 0x07;
335 temp |= (temp << 4);
336 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
337 SiS_SetSegmentReg(SiS_Pr, value);
338}
339
340static void
341SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
342{
343 SiS_SetSegmentRegOver(SiS_Pr, 0);
344}
345
346static void
347SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
348{
349 SiS_ResetSegmentReg(SiS_Pr);
350 SiS_ResetSegmentRegOver(SiS_Pr);
351}
352
353/*********************************************/
354/* HELPER: SearchModeID */
355/*********************************************/
356
357static int
358SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
359 unsigned short *ModeIdIndex)
360{
361 if ((*ModeNo) <= 0x13) {
362
363 if ((*ModeNo) != 0x03)
364 return 0;
365
366 (*ModeIdIndex) = 0;
367
368 } else {
369
370 for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
371
372 if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))
373 break;
374
375 if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
376 return 0;
377 }
378
379 }
380
381 return 1;
382}
383
384/*********************************************/
385/* HELPER: ENABLE CRT1 */
386/*********************************************/
387
388static void
389SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
390{
391 /* Enable CRT1 gating */
392 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
393}
394
395/*********************************************/
396/* HELPER: GetColorDepth */
397/*********************************************/
398
399static unsigned short
400SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
401 unsigned short ModeIdIndex)
402{
403 static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
404 unsigned short modeflag;
405 short index;
406
407 if (ModeNo <= 0x13) {
408 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
409 } else {
410 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
411 }
412
413 index = (modeflag & ModeTypeMask) - ModeEGA;
414 if (index < 0) index = 0;
415 return ColorDepth[index];
416}
417
418/*********************************************/
419/* HELPER: GetOffset */
420/*********************************************/
421
422static unsigned short
423SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
424 unsigned short ModeIdIndex, unsigned short rrti)
425{
426 unsigned short xres, temp, colordepth, infoflag;
427
428 infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
429 xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
430
431 colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
432
433 temp = xres / 16;
434
435 if (infoflag & InterlaceMode)
436 temp <<= 1;
437
438 temp *= colordepth;
439
440 if (xres % 16)
441 temp += (colordepth >> 1);
442
443 return temp;
444}
445
446/*********************************************/
447/* SEQ */
448/*********************************************/
449
450static void
451SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
452{
453 unsigned char SRdata;
454 int i;
455
456 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
457
458 SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
459 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
460
461 for(i = 2; i <= 4; i++) {
462 SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
463 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
464 }
465}
466
467/*********************************************/
468/* MISC */
469/*********************************************/
470
471static void
472SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
473{
474 unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
475
476 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
477}
478
479/*********************************************/
480/* CRTC */
481/*********************************************/
482
483static void
484SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
485{
486 unsigned char CRTCdata;
487 unsigned short i;
488
489 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
490
491 for(i = 0; i <= 0x18; i++) {
492 CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
493 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
494 }
495}
496
497/*********************************************/
498/* ATT */
499/*********************************************/
500
501static void
502SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
503{
504 unsigned char ARdata;
505 unsigned short i;
506
507 for(i = 0; i <= 0x13; i++) {
508 ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
509 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
510 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
511 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
512 }
513 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
514 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
515 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
516
517 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
518 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
519 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
520}
521
522/*********************************************/
523/* GRC */
524/*********************************************/
525
526static void
527SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
528{
529 unsigned char GRdata;
530 unsigned short i;
531
532 for(i = 0; i <= 0x08; i++) {
533 GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
534 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
535 }
536
537 if (SiS_Pr->SiS_ModeType > ModeVGA) {
538 /* 256 color disable */
539 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
540 }
541}
542
543/*********************************************/
544/* CLEAR EXTENDED REGISTERS */
545/*********************************************/
546
547static void
548SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
549{
550 int i;
551
552 for(i = 0x0A; i <= 0x0E; i++) {
553 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
554 }
555
556 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
557}
558
559/*********************************************/
560/* Get rate index */
561/*********************************************/
562
563static unsigned short
564SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
565 unsigned short ModeIdIndex)
566{
567 unsigned short rrti, i, index, temp;
568
569 if (ModeNo <= 0x13)
570 return 0xFFFF;
571
572 index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
573 if (index > 0) index--;
574
575 rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
576 ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
577
578 i = 0;
579 do {
580 if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
581 break;
582
583 temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
584 if (temp < SiS_Pr->SiS_ModeType)
585 break;
586
587 i++;
588 index--;
589 } while(index != 0xFFFF);
590
591 i--;
592
593 return (rrti + i);
594}
595
596/*********************************************/
597/* SYNC */
598/*********************************************/
599
600static void
601SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
602{
603 unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
604 sync &= 0xC0;
605 sync |= 0x2f;
606 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
607}
608
609/*********************************************/
610/* CRTC/2 */
611/*********************************************/
612
613static void
614SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
615 unsigned short ModeIdIndex, unsigned short rrti)
616{
617 unsigned char index;
618 unsigned short temp, i, j, modeflag;
619
620 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);
621
622 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
623
624 index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
625
626 for(i = 0,j = 0; i <= 7; i++, j++) {
627 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
628 SiS_Pr->SiS_CRT1Table[index].CR[i]);
629 }
630 for(j = 0x10; i <= 10; i++, j++) {
631 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
632 SiS_Pr->SiS_CRT1Table[index].CR[i]);
633 }
634 for(j = 0x15; i <= 12; i++, j++) {
635 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
636 SiS_Pr->SiS_CRT1Table[index].CR[i]);
637 }
638 for(j = 0x0A; i <= 15; i++, j++) {
639 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
640 SiS_Pr->SiS_CRT1Table[index].CR[i]);
641 }
642
643 temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
644 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);
645
646 temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
647 if (modeflag & DoubleScanMode) temp |= 0x80;
648 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
649
650 if (SiS_Pr->SiS_ModeType > ModeVGA)
651 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
652}
653
654/*********************************************/
655/* OFFSET & PITCH */
656/*********************************************/
657/* (partly overruled by SetPitch() in XF86) */
658/*********************************************/
659
660static void
661SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
662 unsigned short ModeIdIndex, unsigned short rrti)
663{
664 unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
665 unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
666 unsigned short temp;
667
668 temp = (du >> 8) & 0x0f;
669 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
670
671 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
672
673 if (infoflag & InterlaceMode) du >>= 1;
674
675 du <<= 5;
676 temp = (du >> 8) & 0xff;
677 if (du & 0xff) temp++;
678 temp++;
679 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
680}
681
682/*********************************************/
683/* VCLK */
684/*********************************************/
685
686static void
687SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
688 unsigned short rrti)
689{
690 unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
691 unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
692 unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
693
694 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);
695
696 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);
697 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);
698 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);
699}
700
701/*********************************************/
702/* FIFO */
703/*********************************************/
704
705static void
706SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
707 unsigned short mi)
708{
709 unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
710
711 /* disable auto-threshold */
712 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
713
714 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
715 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
716
717 if (ModeNo <= 0x13)
718 return;
719
720 if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
721 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
722 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
723 }
724}
725
726/*********************************************/
727/* MODE REGISTERS */
728/*********************************************/
729
730static void
731SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
732 unsigned short rrti)
733{
734 unsigned short data = 0, VCLK = 0, index = 0;
735
736 if (ModeNo > 0x13) {
737 index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
738 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
739 }
740
741 if (VCLK >= 166) data |= 0x0c;
742 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
743
744 if (VCLK >= 166)
745 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
746
747 /* DAC speed */
748 data = 0x03;
749 if (VCLK >= 260)
750 data = 0x00;
751 else if (VCLK >= 160)
752 data = 0x01;
753 else if (VCLK >= 135)
754 data = 0x02;
755
756 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
757}
758
759static void
760SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
761 unsigned short ModeIdIndex, unsigned short rrti)
762{
763 unsigned short data, infoflag = 0, modeflag;
764
765 if (ModeNo <= 0x13)
766 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
767 else {
768 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
769 infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
770 }
771
772 /* Disable DPMS */
773 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
774
775 data = 0;
776 if (ModeNo > 0x13) {
777 if (SiS_Pr->SiS_ModeType > ModeEGA) {
778 data |= 0x02;
779 data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
780 }
781 if (infoflag & InterlaceMode) data |= 0x20;
782 }
783 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
784
785 data = 0;
786 if (infoflag & InterlaceMode) {
787 /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
788 unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
789 ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;
790 unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
791 ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;
792 data = hrs - (hto >> 1) + 3;
793 }
794 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
795 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
796
797 if (modeflag & HalfDCLK)
798 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
799
800 data = 0;
801 if (modeflag & LineCompareOff)
802 data = 0x08;
803 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
804
805 if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
806 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
807
808 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
809
810 data = 0x60;
811 if (SiS_Pr->SiS_ModeType != ModeText) {
812 data ^= 0x60;
813 if (SiS_Pr->SiS_ModeType != ModeEGA)
814 data ^= 0xA0;
815 }
816 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
817
818 SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
819
820 if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
821 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
822 else
823 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
824}
825
826/*********************************************/
827/* LOAD DAC */
828/*********************************************/
829
830static void
831SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
832 unsigned short shiftflag, unsigned short dl, unsigned short ah,
833 unsigned short al, unsigned short dh)
834{
835 unsigned short d1, d2, d3;
836
837 switch (dl) {
838 case 0:
839 d1 = dh; d2 = ah; d3 = al;
840 break;
841 case 1:
842 d1 = ah; d2 = al; d3 = dh;
843 break;
844 default:
845 d1 = al; d2 = dh; d3 = ah;
846 }
847 SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
848 SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
849 SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
850}
851
852static void
853SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)
854{
855 unsigned short data, data2, time, i, j, k, m, n, o;
856 unsigned short si, di, bx, sf;
857 unsigned long DACAddr, DACData;
858 const unsigned char *table = NULL;
859
860 if (ModeNo < 0x13)
861 data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
862 else
863 data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
864
865 data &= DACInfoFlag;
866
867 j = time = 64;
868 if (data == 0x00)
869 table = SiS_MDA_DAC;
870 else if (data == 0x08)
871 table = SiS_CGA_DAC;
872 else if (data == 0x10)
873 table = SiS_EGA_DAC;
874 else {
875 j = 16;
876 time = 256;
877 table = SiS_VGA_DAC;
878 }
879
880 DACAddr = SiS_Pr->SiS_P3c8;
881 DACData = SiS_Pr->SiS_P3c9;
882 sf = 0;
883 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
884
885 SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
886
887 for(i = 0; i < j; i++) {
888 data = table[i];
889 for(k = 0; k < 3; k++) {
890 data2 = 0;
891 if (data & 0x01) data2 += 0x2A;
892 if (data & 0x02) data2 += 0x15;
893 SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
894 data >>= 2;
895 }
896 }
897
898 if (time == 256) {
899 for(i = 16; i < 32; i++) {
900 data = table[i] << sf;
901 for(k = 0; k < 3; k++)
902 SiS_SetRegByte(SiS_Pr, DACData, data);
903 }
904 si = 32;
905 for(m = 0; m < 9; m++) {
906 di = si;
907 bx = si + 4;
908 for(n = 0; n < 3; n++) {
909 for(o = 0; o < 5; o++) {
910 SiS_WriteDAC(SiS_Pr, DACData, sf, n,
911 table[di], table[bx], table[si]);
912 si++;
913 }
914 si -= 2;
915 for(o = 0; o < 3; o++) {
916 SiS_WriteDAC(SiS_Pr, DACData, sf, n,
917 table[di], table[si], table[bx]);
918 si--;
919 }
920 }
921 si += 5;
922 }
923 }
924}
925
926/*********************************************/
927/* SET CRT1 REGISTER GROUP */
928/*********************************************/
929
930static void
931SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
932 unsigned short ModeIdIndex)
933{
934 unsigned short StandTableIndex, rrti;
935
936 SiS_Pr->SiS_CRT1Mode = ModeNo;
937
938 if (ModeNo <= 0x13)
939 StandTableIndex = 0;
940 else
941 StandTableIndex = 1;
942
943 SiS_ResetSegmentRegisters(SiS_Pr);
944 SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
945 SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
946 SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
947 SiS_SetATTRegs(SiS_Pr, StandTableIndex);
948 SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
949 SiS_ClearExt1Regs(SiS_Pr, ModeNo);
950
951 rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
952
953 if (rrti != 0xFFFF) {
954 SiS_SetCRT1Sync(SiS_Pr, rrti);
955 SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
956 SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
957 SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
958 }
959
960 SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
961
962 SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
963
964 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
965
966 SiS_DisplayOn(SiS_Pr);
967}
968
969/*********************************************/
970/* SiSSetMode() */
971/*********************************************/
972
973int
974SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
975{
976 unsigned short ModeIdIndex;
977 unsigned long BaseAddr = SiS_Pr->IOAddress;
978
979 SiSUSB_InitPtr(SiS_Pr);
980 SiSUSBRegInit(SiS_Pr, BaseAddr);
981 SiS_GetSysFlags(SiS_Pr);
982
983 if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
984 return 0;
985
986 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
987
988 SiSInitPCIetc(SiS_Pr);
989
990 ModeNo &= 0x7f;
991
992 SiS_Pr->SiS_ModeType =
993 SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
994
995 SiS_Pr->SiS_SetFlag = LowModeTests;
996
997 /* Set mode on CRT1 */
998 SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
999
1000 SiS_HandleCRT1(SiS_Pr);
1001
1002 SiS_DisplayOn(SiS_Pr);
1003 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
1004
1005 /* Store mode number */
1006 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
1007
1008 return 1;
1009}
1010
1011int
1012SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
1013{
1014 unsigned short ModeNo = 0;
1015 int i;
1016
1017 SiSUSB_InitPtr(SiS_Pr);
1018
1019 if (VModeNo == 0x03) {
1020
1021 ModeNo = 0x03;
1022
1023 } else {
1024
1025 i = 0;
1026 do {
1027
1028 if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
1029 ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
1030 break;
1031 }
1032
1033 } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
1034
1035 }
1036
1037 if (!ModeNo)
1038 return 0;
1039
1040 return SiSUSBSetMode(SiS_Pr, ModeNo);
1041}
1042
1043#endif /* INCL_SISUSB_CON */
1044
1045
1046
1047
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
new file mode 100644
index 000000000000..5b11577835c8
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -0,0 +1,830 @@
1/* $XFree86$ */
2/* $XdotOrg$ */
3/*
4 * Data and prototypes for init.c
5 *
6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, the following license terms
9 * apply:
10 *
11 * * This program is free software; you can redistribute it and/or modify
12 * * it under the terms of the GNU General Public License as published by
13 * * the Free Software Foundation; either version 2 of the named License,
14 * * or any later version.
15 * *
16 * * This program is distributed in the hope that it will be useful,
17 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * * GNU General Public License for more details.
20 * *
21 * * You should have received a copy of the GNU General Public License
22 * * along with this program; if not, write to the Free Software
23 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
24 *
25 * Otherwise, the following license terms apply:
26 *
27 * * Redistribution and use in source and binary forms, with or without
28 * * modification, are permitted provided that the following conditions
29 * * are met:
30 * * 1) Redistributions of source code must retain the above copyright
31 * * notice, this list of conditions and the following disclaimer.
32 * * 2) Redistributions in binary form must reproduce the above copyright
33 * * notice, this list of conditions and the following disclaimer in the
34 * * documentation and/or other materials provided with the distribution.
35 * * 3) The name of the author may not be used to endorse or promote products
36 * * derived from this software without specific prior written permission.
37 * *
38 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
42 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
47 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 *
49 * Author: Thomas Winischhofer <thomas@winischhofer.net>
50 *
51 */
52
53#ifndef _SISUSB_INIT_H_
54#define _SISUSB_INIT_H_
55
56/* SiS_ModeType */
57#define ModeText 0x00
58#define ModeCGA 0x01
59#define ModeEGA 0x02
60#define ModeVGA 0x03
61#define Mode15Bpp 0x04
62#define Mode16Bpp 0x05
63#define Mode24Bpp 0x06
64#define Mode32Bpp 0x07
65
66#define ModeTypeMask 0x07
67#define IsTextMode 0x07
68
69#define DACInfoFlag 0x0018
70#define MemoryInfoFlag 0x01E0
71#define MemorySizeShift 5
72
73/* modeflag */
74#define Charx8Dot 0x0200
75#define LineCompareOff 0x0400
76#define CRT2Mode 0x0800
77#define HalfDCLK 0x1000
78#define NoSupportSimuTV 0x2000
79#define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
80#define DoubleScanMode 0x8000
81
82/* Infoflag */
83#define SupportTV 0x0008
84#define SupportTV1024 0x0800
85#define SupportCHTV 0x0800
86#define Support64048060Hz 0x0800 /* Special for 640x480 LCD */
87#define SupportHiVision 0x0010
88#define SupportYPbPr750p 0x1000
89#define SupportLCD 0x0020
90#define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */
91#define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */
92#define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */
93#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */
94#define InterlaceMode 0x0080
95#define SyncPP 0x0000
96#define SyncPN 0x4000
97#define SyncNP 0x8000
98#define SyncNN 0xc000
99
100/* SetFlag */
101#define ProgrammingCRT2 0x0001
102#define LowModeTests 0x0002
103#define LCDVESATiming 0x0008
104#define EnableLVDSDDA 0x0010
105#define SetDispDevSwitchFlag 0x0020
106#define CheckWinDos 0x0040
107#define SetDOSMode 0x0080
108
109/* Index in ModeResInfo table */
110#define SIS_RI_320x200 0
111#define SIS_RI_320x240 1
112#define SIS_RI_320x400 2
113#define SIS_RI_400x300 3
114#define SIS_RI_512x384 4
115#define SIS_RI_640x400 5
116#define SIS_RI_640x480 6
117#define SIS_RI_800x600 7
118#define SIS_RI_1024x768 8
119#define SIS_RI_1280x1024 9
120#define SIS_RI_1600x1200 10
121#define SIS_RI_1920x1440 11
122#define SIS_RI_2048x1536 12
123#define SIS_RI_720x480 13
124#define SIS_RI_720x576 14
125#define SIS_RI_1280x960 15
126#define SIS_RI_800x480 16
127#define SIS_RI_1024x576 17
128#define SIS_RI_1280x720 18
129#define SIS_RI_856x480 19
130#define SIS_RI_1280x768 20
131#define SIS_RI_1400x1050 21
132#define SIS_RI_1152x864 22 /* Up to here SiS conforming */
133#define SIS_RI_848x480 23
134#define SIS_RI_1360x768 24
135#define SIS_RI_1024x600 25
136#define SIS_RI_1152x768 26
137#define SIS_RI_768x576 27
138#define SIS_RI_1360x1024 28
139#define SIS_RI_1680x1050 29
140#define SIS_RI_1280x800 30
141#define SIS_RI_1920x1080 31
142#define SIS_RI_960x540 32
143#define SIS_RI_960x600 33
144
145#define SIS_VIDEO_CAPTURE 0x00 - 0x30
146#define SIS_VIDEO_PLAYBACK 0x02 - 0x30
147#define SIS_CRT2_PORT_04 0x04 - 0x30
148
149/* Mode numbers */
150static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
151static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
152static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
153static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
154static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
155static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
156static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
157static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
158static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
159static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
160static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
161static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
162static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
163static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f};
164static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22};
165static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
166static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
167static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
168static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
169static const unsigned short ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25};
170static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
171
172static const unsigned char SiS_MDA_DAC[] =
173{
174 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
175 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
176 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
177 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
178 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
179 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
180 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
181 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
182};
183
184static const unsigned char SiS_CGA_DAC[] =
185{
186 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
187 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
188 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
189 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
190 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
191 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
192 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
193 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
194};
195
196static const unsigned char SiS_EGA_DAC[] =
197{
198 0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
199 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
200 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
201 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
202 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
203 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
204 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
205 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
206};
207
208static const unsigned char SiS_VGA_DAC[] =
209{
210 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
211 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
212 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
213 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
214 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
215 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
216 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
217 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
218 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
219 0x0B,0x0C,0x0D,0x0F,0x10
220};
221
222static const struct SiS_St SiSUSB_SModeIDTable[] =
223{
224 {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
225 {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
226};
227
228static const struct SiS_StResInfo_S SiSUSB_StResInfo[] =
229{
230 { 640,400},
231 { 640,350},
232 { 720,400},
233 { 720,350},
234 { 640,480}
235};
236
237static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] =
238{
239 { 320, 200, 8, 8}, /* 0x00 */
240 { 320, 240, 8, 8}, /* 0x01 */
241 { 320, 400, 8, 8}, /* 0x02 */
242 { 400, 300, 8, 8}, /* 0x03 */
243 { 512, 384, 8, 8}, /* 0x04 */
244 { 640, 400, 8,16}, /* 0x05 */
245 { 640, 480, 8,16}, /* 0x06 */
246 { 800, 600, 8,16}, /* 0x07 */
247 { 1024, 768, 8,16}, /* 0x08 */
248 { 1280,1024, 8,16}, /* 0x09 */
249 { 1600,1200, 8,16}, /* 0x0a */
250 { 1920,1440, 8,16}, /* 0x0b */
251 { 2048,1536, 8,16}, /* 0x0c */
252 { 720, 480, 8,16}, /* 0x0d */
253 { 720, 576, 8,16}, /* 0x0e */
254 { 1280, 960, 8,16}, /* 0x0f */
255 { 800, 480, 8,16}, /* 0x10 */
256 { 1024, 576, 8,16}, /* 0x11 */
257 { 1280, 720, 8,16}, /* 0x12 */
258 { 856, 480, 8,16}, /* 0x13 */
259 { 1280, 768, 8,16}, /* 0x14 */
260 { 1400,1050, 8,16}, /* 0x15 */
261 { 1152, 864, 8,16}, /* 0x16 */
262 { 848, 480, 8,16}, /* 0x17 */
263 { 1360, 768, 8,16}, /* 0x18 */
264 { 1024, 600, 8,16}, /* 0x19 */
265 { 1152, 768, 8,16}, /* 0x1a */
266 { 768, 576, 8,16}, /* 0x1b */
267 { 1360,1024, 8,16}, /* 0x1c */
268 { 1680,1050, 8,16}, /* 0x1d */
269 { 1280, 800, 8,16}, /* 0x1e */
270 { 1920,1080, 8,16}, /* 0x1f */
271 { 960, 540, 8,16}, /* 0x20 */
272 { 960, 600, 8,16} /* 0x21 */
273};
274
275static const struct SiS_StandTable SiSUSB_StandTable[] =
276{
277 /* MD_3_400 - mode 0x03 - 400 */
278 {
279 0x50,0x18,0x10,0x1000,
280 { 0x00,0x03,0x00,0x02 },
281 0x67,
282 { 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
283 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
284 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
285 0xff },
286 { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
287 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
288 0x0c,0x00,0x0f,0x08 },
289 { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff }
290 },
291 /* Generic for VGA and higher */
292 {
293 0x00,0x00,0x00,0x0000,
294 { 0x01,0x0f,0x00,0x0e },
295 0x23,
296 { 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
297 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
298 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
299 0xff },
300 { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
301 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
302 0x01,0x00,0x00,0x00 },
303 { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff }
304 }
305};
306
307static const struct SiS_Ext SiSUSB_EModeIDTable[] =
308{
309 {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
310 {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
311 {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
312 {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
313 {0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
314 {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
315 {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
316 {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
317 {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
318 {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
319 {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */
320 {0x41,0x9a1d,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */
321 {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
322 {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
323 {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
324 {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */
325 {0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8 */
326 {0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8 */
327 {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8 */
328 {0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */
329 {0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */
330 {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */
331 {0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8 */
332 {0x5c,0xba1f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */
333 {0x5d,0x0a1d,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */
334 {0x5e,0x0a1f,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
335 {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
336 {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
337 {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
338 {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */
339 {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */
340 {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */
341 {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */
342 {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */
343 {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */
344 {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */
345 {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */
346 {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */
347 {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */
348 {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */
349 {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */
350 {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */
351 {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */
352 {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
353 {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
354 {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */
355 {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
356 {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
357 {0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */
358 {0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */
359 {0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */
360 {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */
361 {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
362 {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
363 {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */
364 {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
365 {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
366 {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */
367 {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
368 {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
369 {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */
370 {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
371 {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
372 {0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1}
373};
374
375static const struct SiS_Ext2 SiSUSB_RefIndex[] =
376{
377 {0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */
378 {0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */
379 {0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */
380 {0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */
381 {0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */
382 {0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */
383 {0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */
384 {0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */
385 {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */
386 {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */
387 {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */
388 {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */
389 {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */
390 {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */
391 {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */
392 {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */
393 {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */
394 {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */
395 {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */
396 {0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */
397 {0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */
398 {0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */
399 {0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */
400 {0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */
401 {0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */
402 {0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */
403 {0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */
404 {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */
405 {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */
406 {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */
407 {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */
408 {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */
409 {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */
410 {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */
411 {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */
412 {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */
413 {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */
414 {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */
415 {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */
416 {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */
417 {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */
418 {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */
419 {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */
420 {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */
421 {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */
422 {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */
423 {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */
424 {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */
425 {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */
426 {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */
427 {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */
428 {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */
429 {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */
430 {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */
431 {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00}
432};
433
434static const struct SiS_CRT1Table SiSUSB_CRT1Table[] =
435{
436 {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
437 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
438 0x00}}, /* 0x0 */
439 {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
440 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
441 0x00}}, /* 0x1 */
442 {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
443 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
444 0x01}}, /* 0x2 */
445 {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
446 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
447 0x01}}, /* 0x3 */
448 {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
449 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
450 0x00}}, /* 0x4 */
451 {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
452 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
453 0x00}}, /* 0x5 */
454 {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,
455 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
456 0x00}}, /* 0x6 */
457 {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
458 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
459 0x00}}, /* 0x7 */
460 {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
461 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
462 0x00}}, /* 0x8 */
463 {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
464 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
465 0x61}}, /* 0x9 */
466 {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
467 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
468 0x61}}, /* 0xa */
469 {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
470 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,
471 0x61}}, /* 0xb */
472 {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
473 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,
474 0x00}}, /* 0xc */
475 {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
476 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
477 0x01}}, /* 0xd */
478 {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
479 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
480 0x01}}, /* 0xe */
481 {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
482 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
483 0x01}}, /* 0xf */
484 {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
485 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
486 0x01}}, /* 0x10 */
487 {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
488 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
489 0x01}}, /* 0x11 */
490 {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
491 0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
492 0x61}}, /* 0x12 */
493 {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
494 0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
495 0x61}}, /* 0x13 */
496 {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
497 0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
498 0x61}}, /* 0x14 */
499 {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
500 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
501 0x00}}, /* 0x15 */
502 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
503 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
504 0x01}}, /* 0x16 */
505 {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
506 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
507 0x01}}, /* 0x17 */
508 {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
509 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
510 0x01}}, /* 0x18 */
511 {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
512 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
513 0x01}}, /* 0x19 */
514 {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
515 0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
516 0x62}}, /* 0x1a */
517 {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
518 0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
519 0x62}}, /* 0x1b */
520 {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
521 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
522 0x00}}, /* 0x1c */
523 {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
524 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
525 0x01}}, /* 0x1d */
526 {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
527 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
528 0x01}}, /* 0x1e */
529 {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
530 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
531 0x01}}, /* 0x1f */
532 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
533 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
534 0x00}}, /* 0x20 */
535 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
536 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
537 0x00}}, /* 0x21 */
538 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
539 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
540 0x00}}, /* 0x22 */
541 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
542 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
543 0x00}}, /* 0x23 */
544 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
545 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
546 0x00}}, /* 0x24 */
547 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
548 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
549 0x00}}, /* 0x25 */
550 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
551 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
552 0x00}}, /* 0x26 */
553 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
554 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
555 0x00}}, /* 0x27 */
556 {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
557 0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
558 0x63}}, /* 0x28 */
559 {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
560 0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
561 0x63}}, /* 0x29 */
562 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
563 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
564 0x00}}, /* 0x2a */
565 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
566 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
567 0x00}}, /* 0x2b */
568 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
569 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
570 0x00}}, /* 0x2c */
571 {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
572 0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
573 0x44}}, /* 0x2d */
574 {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
575 0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
576 0x44}}, /* 0x2e */
577 {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
578 0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
579 0x44}}, /* 0x2f */
580 {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
581 0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
582 0x44}}, /* 0x30 */
583 {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
584 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
585 0x00}}, /* 0x31 */
586 {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
587 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
588 0x01}}, /* 0x32 */
589 {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
590 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
591 0x01}}, /* 0x33 */
592 {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
593 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
594 0x01}}, /* 0x34 */
595 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
596 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
597 0x01}}, /* 0x35 */
598 {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
599 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
600 0x01}}, /* 0x36 */
601 {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,
602 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
603 0x01}}, /* 0x37 */
604 {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
605 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
606 0x01}}, /* 0x38 */
607 {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
608 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
609 0x01}}, /* 0x39 */
610 {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
611 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
612 0x01}}, /* 0x3a */
613 {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,
614 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
615 0x01}}, /* 0x3b */
616 {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
617 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
618 0x00}}, /* 0x3c */
619 {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,
620 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
621 0x41}}, /* 0x3d */
622 {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
623 0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
624 0x00}}, /* 0x3e */
625 {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
626 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
627 0x00}}, /* 0x3f */
628 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
629 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
630 0x01}}, /* 0x40 */
631 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
632 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
633 0x01}}, /* 0x41 */
634 {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
635 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
636 0x01}}, /* 0x42 */
637 {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
638 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
639 0x00}}, /* 0x43 */
640 {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,
641 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
642 0x01}}, /* 0x44 */
643 {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,
644 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
645 0x00}}, /* 0x45 */
646 {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,
647 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
648 0x00}}, /* 0x46 */
649 {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,
650 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
651 0x00}}, /* 0x47 */
652 {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,
653 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
654 0x00}}, /* 0x48 */
655 {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,
656 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
657 0x01}}, /* 0x49 */
658 {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,
659 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
660 0x01}}, /* 0x4a */
661 {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10,
662 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
663 0x00}}, /* 0x4b */
664 {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,
665 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
666 0x01}}, /* 0x4c */
667 {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,
668 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
669 0x41}},
670 {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
671 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
672 0x00}}, /* 0x4e */
673 {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff,
674 0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
675 0x21}}, /* 0x4f */
676 {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10,
677 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
678 0x20}}, /* 0x50 */
679 {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0,
680 0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
681 0x61}}, /* 0x51 */
682 {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0,
683 0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
684 0x41}}, /* 0x52 */
685 {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0,
686 0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
687 0x01}}, /* 0x53 */
688 {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,
689 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
690 0x41}} /* 0x54 */
691};
692
693static struct SiS_VCLKData SiSUSB_VCLKData[] =
694{
695 { 0x1b,0xe1, 25}, /* 0x00 */
696 { 0x4e,0xe4, 28}, /* 0x01 */
697 { 0x57,0xe4, 31}, /* 0x02 */
698 { 0xc3,0xc8, 36}, /* 0x03 */
699 { 0x42,0xe2, 40}, /* 0x04 */
700 { 0xfe,0xcd, 43}, /* 0x05 */
701 { 0x5d,0xc4, 44}, /* 0x06 */
702 { 0x52,0xe2, 49}, /* 0x07 */
703 { 0x53,0xe2, 50}, /* 0x08 */
704 { 0x74,0x67, 52}, /* 0x09 */
705 { 0x6d,0x66, 56}, /* 0x0a */
706 { 0x5a,0x64, 65}, /* 0x0b */
707 { 0x46,0x44, 67}, /* 0x0c */
708 { 0xb1,0x46, 68}, /* 0x0d */
709 { 0xd3,0x4a, 72}, /* 0x0e */
710 { 0x29,0x61, 75}, /* 0x0f */
711 { 0x6e,0x46, 76}, /* 0x10 */
712 { 0x2b,0x61, 78}, /* 0x11 */
713 { 0x31,0x42, 79}, /* 0x12 */
714 { 0xab,0x44, 83}, /* 0x13 */
715 { 0x46,0x25, 84}, /* 0x14 */
716 { 0x78,0x29, 86}, /* 0x15 */
717 { 0x62,0x44, 94}, /* 0x16 */
718 { 0x2b,0x41,104}, /* 0x17 */
719 { 0x3a,0x23,105}, /* 0x18 */
720 { 0x70,0x44,108}, /* 0x19 */
721 { 0x3c,0x23,109}, /* 0x1a */
722 { 0x5e,0x43,113}, /* 0x1b */
723 { 0xbc,0x44,116}, /* 0x1c */
724 { 0xe0,0x46,132}, /* 0x1d */
725 { 0x54,0x42,135}, /* 0x1e */
726 { 0xea,0x2a,139}, /* 0x1f */
727 { 0x41,0x22,157}, /* 0x20 */
728 { 0x70,0x24,162}, /* 0x21 */
729 { 0x30,0x21,175}, /* 0x22 */
730 { 0x4e,0x22,189}, /* 0x23 */
731 { 0xde,0x26,194}, /* 0x24 */
732 { 0x62,0x06,202}, /* 0x25 */
733 { 0x3f,0x03,229}, /* 0x26 */
734 { 0xb8,0x06,234}, /* 0x27 */
735 { 0x34,0x02,253}, /* 0x28 */
736 { 0x58,0x04,255}, /* 0x29 */
737 { 0x24,0x01,265}, /* 0x2a */
738 { 0x9b,0x02,267}, /* 0x2b */
739 { 0x70,0x05,270}, /* 0x2c */
740 { 0x25,0x01,272}, /* 0x2d */
741 { 0x9c,0x02,277}, /* 0x2e */
742 { 0x27,0x01,286}, /* 0x2f */
743 { 0x3c,0x02,291}, /* 0x30 */
744 { 0xef,0x0a,292}, /* 0x31 */
745 { 0xf6,0x0a,310}, /* 0x32 */
746 { 0x95,0x01,315}, /* 0x33 */
747 { 0xf0,0x09,324}, /* 0x34 */
748 { 0xfe,0x0a,331}, /* 0x35 */
749 { 0xf3,0x09,332}, /* 0x36 */
750 { 0xea,0x08,340}, /* 0x37 */
751 { 0xe8,0x07,376}, /* 0x38 */
752 { 0xde,0x06,389}, /* 0x39 */
753 { 0x52,0x2a, 54}, /* 0x3a 301 TV */
754 { 0x52,0x6a, 27}, /* 0x3b 301 TV */
755 { 0x62,0x24, 70}, /* 0x3c 301 TV */
756 { 0x62,0x64, 70}, /* 0x3d 301 TV */
757 { 0xa8,0x4c, 30}, /* 0x3e 301 TV */
758 { 0x20,0x26, 33}, /* 0x3f 301 TV */
759 { 0x31,0xc2, 39}, /* 0x40 */
760 { 0x60,0x36, 30}, /* 0x41 Chrontel */
761 { 0x40,0x4a, 28}, /* 0x42 Chrontel */
762 { 0x9f,0x46, 44}, /* 0x43 Chrontel */
763 { 0x97,0x2c, 26}, /* 0x44 */
764 { 0x44,0xe4, 25}, /* 0x45 Chrontel */
765 { 0x7e,0x32, 47}, /* 0x46 Chrontel */
766 { 0x8a,0x24, 31}, /* 0x47 Chrontel */
767 { 0x97,0x2c, 26}, /* 0x48 Chrontel */
768 { 0xce,0x3c, 39}, /* 0x49 */
769 { 0x52,0x4a, 36}, /* 0x4a Chrontel */
770 { 0x34,0x61, 95}, /* 0x4b */
771 { 0x78,0x27,108}, /* 0x4c - was 102 */
772 { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
773 { 0x41,0x4e, 21}, /* 0x4e */
774 { 0xa1,0x4a, 29}, /* 0x4f Chrontel */
775 { 0x19,0x42, 42}, /* 0x50 */
776 { 0x54,0x46, 58}, /* 0x51 Chrontel */
777 { 0x25,0x42, 61}, /* 0x52 */
778 { 0x44,0x44, 66}, /* 0x53 Chrontel */
779 { 0x3a,0x62, 70}, /* 0x54 Chrontel */
780 { 0x62,0xc6, 34}, /* 0x55 848x480-60 */
781 { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
782 { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
783 { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
784 { 0x52,0x07,149}, /* 0x59 1280x960-85 */
785 { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
786 { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
787 { 0x45,0x25, 83}, /* 0x5c 1280x800 */
788 { 0x70,0x0a,147}, /* 0x5d 1680x1050 */
789 { 0x70,0x24,162}, /* 0x5e 1600x1200 */
790 { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
791 { 0x63,0x46, 68}, /* 0x60 1280x768_2 */
792 { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
793 { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */
794 { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
795 { 0x70,0x28, 90}, /* 0x64 1152x864@60 */
796 { 0x41,0xc4, 32}, /* 0x65 848x480@60 */
797 { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
798 { 0x76,0xe7, 27}, /* 0x67 720x480@60 */
799 { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
800 { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
801 { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
802 { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
803 { 0x45,0x25, 83}, /* 0x6c 1280x800 */
804 { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
805 { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
806 { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
807 { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
808 { 0x2b,0xc2, 35} /* 0x71 768@576@60 */
809};
810
811void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr);
812unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth);
813int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
814int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
815
816extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
817extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
818extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
819 u8 index, u8 data);
820extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
821 u8 index, u8 *data);
822extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
823 u8 idx, u8 myand, u8 myor);
824extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
825 u8 index, u8 myor);
826extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
827 u8 idx, u8 myand);
828
829#endif
830
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
new file mode 100644
index 000000000000..94edd4726c42
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h
@@ -0,0 +1,169 @@
1/*
2 * General structure definitions for universal mode switching modules
3 *
4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
5 *
6 * If distributed as part of the Linux kernel, the following license terms
7 * apply:
8 *
9 * * This program is free software; you can redistribute it and/or modify
10 * * it under the terms of the GNU General Public License as published by
11 * * the Free Software Foundation; either version 2 of the named License,
12 * * or any later version.
13 * *
14 * * This program is distributed in the hope that it will be useful,
15 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * * GNU General Public License for more details.
18 * *
19 * * You should have received a copy of the GNU General Public License
20 * * along with this program; if not, write to the Free Software
21 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
22 *
23 * Otherwise, the following license terms apply:
24 *
25 * * Redistribution and use in source and binary forms, with or without
26 * * modification, are permitted provided that the following conditions
27 * * are met:
28 * * 1) Redistributions of source code must retain the above copyright
29 * * notice, this list of conditions and the following disclaimer.
30 * * 2) Redistributions in binary form must reproduce the above copyright
31 * * notice, this list of conditions and the following disclaimer in the
32 * * documentation and/or other materials provided with the distribution.
33 * * 3) The name of the author may not be used to endorse or promote products
34 * * derived from this software without specific prior written permission.
35 * *
36 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
37 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
40 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
45 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 *
47 * Author: Thomas Winischhofer <thomas@winischhofer.net>
48 *
49 */
50
51#ifndef _SISUSB_STRUCT_H_
52#define _SISUSB_STRUCT_H_
53
54struct SiS_St {
55 unsigned char St_ModeID;
56 unsigned short St_ModeFlag;
57 unsigned char St_StTableIndex;
58 unsigned char St_CRT2CRTC;
59 unsigned char St_ResInfo;
60 unsigned char VB_StTVFlickerIndex;
61 unsigned char VB_StTVEdgeIndex;
62 unsigned char VB_StTVYFilterIndex;
63 unsigned char St_PDC;
64};
65
66struct SiS_StandTable
67{
68 unsigned char CRT_COLS;
69 unsigned char ROWS;
70 unsigned char CHAR_HEIGHT;
71 unsigned short CRT_LEN;
72 unsigned char SR[4];
73 unsigned char MISC;
74 unsigned char CRTC[0x19];
75 unsigned char ATTR[0x14];
76 unsigned char GRC[9];
77};
78
79struct SiS_StResInfo_S {
80 unsigned short HTotal;
81 unsigned short VTotal;
82};
83
84struct SiS_Ext
85{
86 unsigned char Ext_ModeID;
87 unsigned short Ext_ModeFlag;
88 unsigned short Ext_VESAID;
89 unsigned char Ext_RESINFO;
90 unsigned char VB_ExtTVFlickerIndex;
91 unsigned char VB_ExtTVEdgeIndex;
92 unsigned char VB_ExtTVYFilterIndex;
93 unsigned char VB_ExtTVYFilterIndexROM661;
94 unsigned char REFindex;
95 char ROMMODEIDX661;
96};
97
98struct SiS_Ext2
99{
100 unsigned short Ext_InfoFlag;
101 unsigned char Ext_CRT1CRTC;
102 unsigned char Ext_CRTVCLK;
103 unsigned char Ext_CRT2CRTC;
104 unsigned char Ext_CRT2CRTC_NS;
105 unsigned char ModeID;
106 unsigned short XRes;
107 unsigned short YRes;
108 unsigned char Ext_PDC;
109 unsigned char Ext_FakeCRT2CRTC;
110 unsigned char Ext_FakeCRT2Clk;
111};
112
113struct SiS_CRT1Table
114{
115 unsigned char CR[17];
116};
117
118struct SiS_VCLKData
119{
120 unsigned char SR2B,SR2C;
121 unsigned short CLOCK;
122};
123
124struct SiS_ModeResInfo
125{
126 unsigned short HTotal;
127 unsigned short VTotal;
128 unsigned char XChar;
129 unsigned char YChar;
130};
131
132struct SiS_Private
133{
134 void *sisusb;
135
136 unsigned long IOAddress;
137
138 unsigned long SiS_P3c4;
139 unsigned long SiS_P3d4;
140 unsigned long SiS_P3c0;
141 unsigned long SiS_P3ce;
142 unsigned long SiS_P3c2;
143 unsigned long SiS_P3ca;
144 unsigned long SiS_P3c6;
145 unsigned long SiS_P3c7;
146 unsigned long SiS_P3c8;
147 unsigned long SiS_P3c9;
148 unsigned long SiS_P3cb;
149 unsigned long SiS_P3cc;
150 unsigned long SiS_P3cd;
151 unsigned long SiS_P3da;
152 unsigned long SiS_Part1Port;
153
154 unsigned char SiS_MyCR63;
155 unsigned short SiS_CRT1Mode;
156 unsigned short SiS_ModeType;
157 unsigned short SiS_SetFlag;
158
159 const struct SiS_StandTable *SiS_StandTable;
160 const struct SiS_St *SiS_SModeIDTable;
161 const struct SiS_Ext *SiS_EModeIDTable;
162 const struct SiS_Ext2 *SiS_RefIndex;
163 const struct SiS_CRT1Table *SiS_CRT1Table;
164 struct SiS_VCLKData *SiS_VCLKData;
165 const struct SiS_ModeResInfo *SiS_ModeResInfo;
166};
167
168#endif
169