2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
8 * If distributed as part of the Linux kernel, this code is licensed under the
11 * Otherwise, the following license terms apply:
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
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.
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.
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
39 #include <linux/mutex.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.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 #include <linux/usb.h>
50 #include <linux/smp_lock.h>
51 #include <linux/vmalloc.h>
54 #include "sisusb_init.h"
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
60 #define SISUSB_DONTSYNC
62 /* Forward declarations / clean-up routines */
64 #ifdef INCL_SISUSB_CON
65 static int sisusb_first_vc = 0;
66 static int sisusb_last_vc = 0;
67 module_param_named(first, sisusb_first_vc, int, 0);
68 module_param_named(last, sisusb_last_vc, int, 0);
69 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
70 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
73 static struct usb_driver sisusb_driver;
76 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
80 for (i = 0; i < NUMOBUFS; i++) {
81 if (sisusb->obuf[i]) {
82 usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
83 sisusb->obuf[i], sisusb->transfer_dma_out[i]);
84 sisusb->obuf[i] = NULL;
88 usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
89 sisusb->ibuf, sisusb->transfer_dma_in);
95 sisusb_free_urbs(struct sisusb_usb_data *sisusb)
99 for (i = 0; i < NUMOBUFS; i++) {
100 usb_free_urb(sisusb->sisurbout[i]);
101 sisusb->sisurbout[i] = NULL;
103 usb_free_urb(sisusb->sisurbin);
104 sisusb->sisurbin = NULL;
107 /* Level 0: USB transport layer */
111 /* out-urb management */
113 /* Return 1 if all free, 0 otherwise */
115 sisusb_all_free(struct sisusb_usb_data *sisusb)
119 for (i = 0; i < sisusb->numobufs; i++) {
121 if (sisusb->urbstatus[i] & SU_URB_BUSY)
129 /* Kill all busy URBs */
131 sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
135 if (sisusb_all_free(sisusb))
138 for (i = 0; i < sisusb->numobufs; i++) {
140 if (sisusb->urbstatus[i] & SU_URB_BUSY)
141 usb_kill_urb(sisusb->sisurbout[i]);
146 /* Return 1 if ok, 0 if error (not all complete within timeout) */
148 sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
150 int timeout = 5 * HZ, i = 1;
152 wait_event_timeout(sisusb->wait_q,
153 (i = sisusb_all_free(sisusb)),
160 sisusb_outurb_available(struct sisusb_usb_data *sisusb)
164 for (i = 0; i < sisusb->numobufs; i++) {
166 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
175 sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
177 int i, timeout = 5 * HZ;
179 wait_event_timeout(sisusb->wait_q,
180 ((i = sisusb_outurb_available(sisusb)) >= 0),
187 sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
191 i = sisusb_outurb_available(sisusb);
194 sisusb->urbstatus[i] |= SU_URB_ALLOC;
200 sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
202 if ((index >= 0) && (index < sisusb->numobufs))
203 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
206 /* completion callback */
209 sisusb_bulk_completeout(struct urb *urb)
211 struct sisusb_urb_context *context = urb->context;
212 struct sisusb_usb_data *sisusb;
217 sisusb = context->sisusb;
219 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
222 #ifndef SISUSB_DONTSYNC
223 if (context->actual_length)
224 *(context->actual_length) += urb->actual_length;
227 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
228 wake_up(&sisusb->wait_q);
232 sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
233 int len, int *actual_length, int timeout, unsigned int tflags,
234 dma_addr_t transfer_dma)
236 struct urb *urb = sisusb->sisurbout[index];
237 int retval, byteswritten = 0;
240 urb->transfer_flags = 0;
242 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
243 sisusb_bulk_completeout, &sisusb->urbout_context[index]);
245 urb->transfer_flags |= tflags;
246 urb->actual_length = 0;
248 if ((urb->transfer_dma = transfer_dma))
249 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
252 sisusb->urbout_context[index].actual_length = (timeout) ?
253 NULL : actual_length;
255 /* Declare this urb/buffer in use */
256 sisusb->urbstatus[index] |= SU_URB_BUSY;
259 retval = usb_submit_urb(urb, GFP_ATOMIC);
261 /* If OK, and if timeout > 0, wait for completion */
262 if ((retval == 0) && timeout) {
263 wait_event_timeout(sisusb->wait_q,
264 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
266 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
267 /* URB timed out... kill it and report error */
271 /* Otherwise, report urb status */
272 retval = urb->status;
273 byteswritten = urb->actual_length;
278 *actual_length = byteswritten;
285 /* completion callback */
288 sisusb_bulk_completein(struct urb *urb)
290 struct sisusb_usb_data *sisusb = urb->context;
292 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
295 sisusb->completein = 1;
296 wake_up(&sisusb->wait_q);
300 sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
301 int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
303 struct urb *urb = sisusb->sisurbin;
304 int retval, readbytes = 0;
306 urb->transfer_flags = 0;
308 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
309 sisusb_bulk_completein, sisusb);
311 urb->transfer_flags |= tflags;
312 urb->actual_length = 0;
314 if ((urb->transfer_dma = transfer_dma))
315 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
317 sisusb->completein = 0;
318 retval = usb_submit_urb(urb, GFP_ATOMIC);
320 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
321 if (!sisusb->completein) {
322 /* URB timed out... kill it and report error */
326 /* URB completed within timout */
327 retval = urb->status;
328 readbytes = urb->actual_length;
333 *actual_length = readbytes;
341 /* Send a bulk message of variable size
343 * To copy the data from userspace, give pointer to "userbuffer",
344 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
345 * both of these are NULL, it is assumed, that the transfer
346 * buffer "sisusb->obuf[index]" is set up with the data to send.
347 * Index is ignored if either kernbuffer or userbuffer is set.
348 * If async is nonzero, URBs will be sent without waiting for
349 * completion of the previous URB.
351 * (return 0 on success)
354 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
355 char *kernbuffer, const char __user *userbuffer, int index,
356 ssize_t *bytes_written, unsigned int tflags, int async)
358 int result = 0, retry, count = len;
359 int passsize, thispass, transferred_len = 0;
360 int fromuser = (userbuffer != NULL) ? 1 : 0;
361 int fromkern = (kernbuffer != NULL) ? 1 : 0;
365 (*bytes_written) = 0;
368 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
371 /* If we copy data from kernel or userspace, force the
372 * allocation of a buffer/urb. If we have the data in
373 * the transfer buffer[index] already, reuse the buffer/URB
374 * if the length is > buffer size. (So, transmitting
375 * large data amounts directly from the transfer buffer
376 * treats the buffer as a ring buffer. However, we need
377 * to sync in this case.)
379 if (fromuser || fromkern)
381 else if (len > sisusb->obufsize)
384 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
387 passsize = thispass = (sisusb->obufsize < count) ?
388 sisusb->obufsize : count;
391 index = sisusb_get_free_outbuf(sisusb);
396 buffer = sisusb->obuf[index];
400 if (copy_from_user(buffer, userbuffer, passsize))
403 userbuffer += passsize;
405 } else if (fromkern) {
407 memcpy(buffer, kernbuffer, passsize);
408 kernbuffer += passsize;
415 if (!sisusb->sisusb_dev)
418 result = sisusb_bulkout_msg(sisusb,
426 sisusb->transfer_dma_out[index]);
428 if (result == -ETIMEDOUT) {
430 /* Will not happen if async */
436 } else if ((result == 0) && !async && transferred_len) {
438 thispass -= transferred_len;
440 if (sisusb->transfer_dma_out) {
441 /* If DMA, copy remaining
442 * to beginning of buffer
445 buffer + transferred_len,
448 /* If not DMA, simply increase
451 buffer += transferred_len;
462 (*bytes_written) += passsize;
465 /* Force new allocation in next iteration */
466 if (fromuser || fromkern)
472 #ifdef SISUSB_DONTSYNC
473 (*bytes_written) = len;
474 /* Some URBs/buffers might be busy */
476 sisusb_wait_all_out_complete(sisusb);
477 (*bytes_written) = transferred_len;
478 /* All URBs and all buffers are available */
482 return ((*bytes_written) == len) ? 0 : -EIO;
485 /* Receive a bulk message of variable size
487 * To copy the data to userspace, give pointer to "userbuffer",
488 * to copy to kernel memory, give "kernbuffer". One of them
489 * MUST be set. (There is no technique for letting the caller
490 * read directly from the ibuf.)
494 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
495 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
498 int result = 0, retry, count = len;
499 int bufsize, thispass, transferred_len;
506 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
509 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
510 buffer = sisusb->ibuf;
511 bufsize = sisusb->ibufsize;
515 #ifdef SISUSB_DONTSYNC
516 if (!(sisusb_wait_all_out_complete(sisusb)))
522 if (!sisusb->sisusb_dev)
525 thispass = (bufsize < count) ? bufsize : count;
527 result = sisusb_bulkin_msg(sisusb,
534 sisusb->transfer_dma_in);
537 thispass = transferred_len;
539 else if (result == -ETIMEDOUT) {
552 (*bytes_read) += thispass;
557 if (copy_to_user(userbuffer, buffer, thispass))
560 userbuffer += thispass;
564 memcpy(kernbuffer, buffer, thispass);
565 kernbuffer += thispass;
573 return ((*bytes_read) == len) ? 0 : -EIO;
576 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
577 struct sisusb_packet *packet)
580 ssize_t bytes_transferred = 0;
586 #ifdef SISUSB_DONTSYNC
587 if (!(sisusb_wait_all_out_complete(sisusb)))
591 /* Eventually correct endianness */
592 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
594 /* 1. send the packet */
595 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
596 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
598 if ((ret == 0) && (len == 6)) {
600 /* 2. if packet len == 6, it means we read, so wait for 32bit
601 * return value and write it to packet->data
603 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
604 (char *)&tmp, NULL, &bytes_transferred, 0);
606 packet->data = le32_to_cpu(tmp);
612 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
613 struct sisusb_packet *packet,
617 ssize_t bytes_transferred = 0;
623 #ifdef SISUSB_DONTSYNC
624 if (!(sisusb_wait_all_out_complete(sisusb)))
628 /* Eventually correct endianness */
629 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
631 /* 1. send the packet */
632 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
633 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
635 if ((ret == 0) && (len == 6)) {
637 /* 2. if packet len == 6, it means we read, so wait for 32bit
638 * return value and write it to packet->data
640 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
641 (char *)&tmp, NULL, &bytes_transferred, 0);
643 packet->data = le32_to_cpu(tmp);
649 /* access video memory and mmio (return 0 on success) */
653 /* The following routines assume being used to transfer byte, word,
656 * - the write routines expect "data" in machine endianness format.
657 * The data will be converted to leXX in sisusb_xxx_packet.
658 * - the read routines can expect read data in machine-endianess.
661 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
664 struct sisusb_packet packet;
667 packet.header = (1 << (addr & 3)) | (type << 6);
668 packet.address = addr & ~3;
669 packet.data = data << ((addr & 3) << 3);
670 ret = sisusb_send_packet(sisusb, 10, &packet);
674 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
677 struct sisusb_packet packet;
680 packet.address = addr & ~3;
684 packet.header = (type << 6) | 0x0003;
685 packet.data = (u32)data;
686 ret = sisusb_send_packet(sisusb, 10, &packet);
689 packet.header = (type << 6) | 0x0006;
690 packet.data = (u32)data << 8;
691 ret = sisusb_send_packet(sisusb, 10, &packet);
694 packet.header = (type << 6) | 0x000c;
695 packet.data = (u32)data << 16;
696 ret = sisusb_send_packet(sisusb, 10, &packet);
699 packet.header = (type << 6) | 0x0008;
700 packet.data = (u32)data << 24;
701 ret = sisusb_send_packet(sisusb, 10, &packet);
702 packet.header = (type << 6) | 0x0001;
703 packet.address = (addr & ~3) + 4;
704 packet.data = (u32)data >> 8;
705 ret |= sisusb_send_packet(sisusb, 10, &packet);
711 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
714 struct sisusb_packet packet;
717 packet.address = addr & ~3;
721 packet.header = (type << 6) | 0x0007;
722 packet.data = data & 0x00ffffff;
723 ret = sisusb_send_packet(sisusb, 10, &packet);
726 packet.header = (type << 6) | 0x000e;
727 packet.data = data << 8;
728 ret = sisusb_send_packet(sisusb, 10, &packet);
731 packet.header = (type << 6) | 0x000c;
732 packet.data = data << 16;
733 ret = sisusb_send_packet(sisusb, 10, &packet);
734 packet.header = (type << 6) | 0x0001;
735 packet.address = (addr & ~3) + 4;
736 packet.data = (data >> 16) & 0x00ff;
737 ret |= sisusb_send_packet(sisusb, 10, &packet);
740 packet.header = (type << 6) | 0x0008;
741 packet.data = data << 24;
742 ret = sisusb_send_packet(sisusb, 10, &packet);
743 packet.header = (type << 6) | 0x0003;
744 packet.address = (addr & ~3) + 4;
745 packet.data = (data >> 8) & 0xffff;
746 ret |= sisusb_send_packet(sisusb, 10, &packet);
752 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
755 struct sisusb_packet packet;
758 packet.address = addr & ~3;
762 packet.header = (type << 6) | 0x000f;
764 ret = sisusb_send_packet(sisusb, 10, &packet);
767 packet.header = (type << 6) | 0x000e;
768 packet.data = data << 8;
769 ret = sisusb_send_packet(sisusb, 10, &packet);
770 packet.header = (type << 6) | 0x0001;
771 packet.address = (addr & ~3) + 4;
772 packet.data = data >> 24;
773 ret |= sisusb_send_packet(sisusb, 10, &packet);
776 packet.header = (type << 6) | 0x000c;
777 packet.data = data << 16;
778 ret = sisusb_send_packet(sisusb, 10, &packet);
779 packet.header = (type << 6) | 0x0003;
780 packet.address = (addr & ~3) + 4;
781 packet.data = data >> 16;
782 ret |= sisusb_send_packet(sisusb, 10, &packet);
785 packet.header = (type << 6) | 0x0008;
786 packet.data = data << 24;
787 ret = sisusb_send_packet(sisusb, 10, &packet);
788 packet.header = (type << 6) | 0x0007;
789 packet.address = (addr & ~3) + 4;
790 packet.data = data >> 8;
791 ret |= sisusb_send_packet(sisusb, 10, &packet);
797 /* The xxx_bulk routines copy a buffer of variable size. They treat the
798 * buffer as chars, therefore lsb/msb has to be corrected if using the
799 * byte/word/long/etc routines for speed-up
801 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
802 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
803 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
804 * that the data already is in the transfer buffer "sisusb->obuf[index]".
807 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
808 char *kernbuffer, int length,
809 const char __user *userbuffer, int index,
810 ssize_t *bytes_written)
812 struct sisusb_packet packet;
814 static int msgcount = 0;
815 u8 swap8, fromkern = kernbuffer ? 1 : 0;
817 u32 swap32, flag = (length >> 28) & 1;
820 /* if neither kernbuffer not userbuffer are given, assume
823 if (!fromkern && !userbuffer)
824 kernbuffer = sisusb->obuf[index];
826 (*bytes_written = 0);
828 length &= 0x00ffffff;
836 if (get_user(swap8, (u8 __user *)userbuffer))
839 swap8 = kernbuffer[0];
841 ret = sisusb_write_memio_byte(sisusb,
852 if (get_user(swap16, (u16 __user *)userbuffer))
855 swap16 = *((u16 *)kernbuffer);
857 ret = sisusb_write_memio_word(sisusb,
863 (*bytes_written) += 2;
869 if (copy_from_user(&buf, userbuffer, 3))
872 swap32 = (buf[0] << 16) |
876 swap32 = (buf[2] << 16) |
882 swap32 = (kernbuffer[0] << 16) |
883 (kernbuffer[1] << 8) |
886 swap32 = (kernbuffer[2] << 16) |
887 (kernbuffer[1] << 8) |
891 ret = sisusb_write_memio_24bit(sisusb,
897 (*bytes_written) += 3;
903 if (get_user(swap32, (u32 __user *)userbuffer))
906 swap32 = *((u32 *)kernbuffer);
908 ret = sisusb_write_memio_long(sisusb,
913 (*bytes_written) += 4;
918 if ((length & ~3) > 0x10000) {
920 packet.header = 0x001f;
921 packet.address = 0x000001d4;
923 ret = sisusb_send_bridge_packet(sisusb, 10,
925 packet.header = 0x001f;
926 packet.address = 0x000001d0;
927 packet.data = (length & ~3);
928 ret |= sisusb_send_bridge_packet(sisusb, 10,
930 packet.header = 0x001f;
931 packet.address = 0x000001c0;
932 packet.data = flag | 0x16;
933 ret |= sisusb_send_bridge_packet(sisusb, 10,
936 ret |= sisusb_send_bulk_msg(sisusb,
937 SISUSB_EP_GFX_LBULK_OUT,
940 bytes_written, 0, 1);
941 userbuffer += (*bytes_written);
942 } else if (fromkern) {
943 ret |= sisusb_send_bulk_msg(sisusb,
944 SISUSB_EP_GFX_LBULK_OUT,
947 bytes_written, 0, 1);
948 kernbuffer += (*bytes_written);
950 ret |= sisusb_send_bulk_msg(sisusb,
951 SISUSB_EP_GFX_LBULK_OUT,
954 bytes_written, 0, 1);
955 kernbuffer += ((*bytes_written) &
956 (sisusb->obufsize-1));
961 packet.header = 0x001f;
962 packet.address = 0x00000194;
964 ret = sisusb_send_bridge_packet(sisusb, 10,
966 packet.header = 0x001f;
967 packet.address = 0x00000190;
968 packet.data = (length & ~3);
969 ret |= sisusb_send_bridge_packet(sisusb, 10,
971 if (sisusb->flagb0 != 0x16) {
972 packet.header = 0x001f;
973 packet.address = 0x00000180;
974 packet.data = flag | 0x16;
975 ret |= sisusb_send_bridge_packet(sisusb, 10,
977 sisusb->flagb0 = 0x16;
980 ret |= sisusb_send_bulk_msg(sisusb,
981 SISUSB_EP_GFX_BULK_OUT,
984 bytes_written, 0, 1);
985 userbuffer += (*bytes_written);
986 } else if (fromkern) {
987 ret |= sisusb_send_bulk_msg(sisusb,
988 SISUSB_EP_GFX_BULK_OUT,
991 bytes_written, 0, 1);
992 kernbuffer += (*bytes_written);
994 ret |= sisusb_send_bulk_msg(sisusb,
995 SISUSB_EP_GFX_BULK_OUT,
998 bytes_written, 0, 1);
999 kernbuffer += ((*bytes_written) &
1000 (sisusb->obufsize-1));
1007 "sisusbvga[%d]: Wrote %zd of "
1008 "%d bytes, error %d\n",
1009 sisusb->minor, *bytes_written,
1011 else if (msgcount == 500)
1013 "sisusbvga[%d]: Too many errors"
1014 ", logging stopped\n",
1017 addr += (*bytes_written);
1018 length -= (*bytes_written);
1026 return ret ? -EIO : 0;
1029 /* Remember: Read data in packet is in machine-endianess! So for
1030 * byte, word, 24bit, long no endian correction is necessary.
1033 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1036 struct sisusb_packet packet;
1039 CLEARPACKET(&packet);
1040 packet.header = (1 << (addr & 3)) | (type << 6);
1041 packet.address = addr & ~3;
1042 ret = sisusb_send_packet(sisusb, 6, &packet);
1043 *data = (u8)(packet.data >> ((addr & 3) << 3));
1047 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
1048 u32 addr, u16 *data)
1050 struct sisusb_packet packet;
1053 CLEARPACKET(&packet);
1055 packet.address = addr & ~3;
1059 packet.header = (type << 6) | 0x0003;
1060 ret = sisusb_send_packet(sisusb, 6, &packet);
1061 *data = (u16)(packet.data);
1064 packet.header = (type << 6) | 0x0006;
1065 ret = sisusb_send_packet(sisusb, 6, &packet);
1066 *data = (u16)(packet.data >> 8);
1069 packet.header = (type << 6) | 0x000c;
1070 ret = sisusb_send_packet(sisusb, 6, &packet);
1071 *data = (u16)(packet.data >> 16);
1074 packet.header = (type << 6) | 0x0008;
1075 ret = sisusb_send_packet(sisusb, 6, &packet);
1076 *data = (u16)(packet.data >> 24);
1077 packet.header = (type << 6) | 0x0001;
1078 packet.address = (addr & ~3) + 4;
1079 ret |= sisusb_send_packet(sisusb, 6, &packet);
1080 *data |= (u16)(packet.data << 8);
1086 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1087 u32 addr, u32 *data)
1089 struct sisusb_packet packet;
1092 packet.address = addr & ~3;
1096 packet.header = (type << 6) | 0x0007;
1097 ret = sisusb_send_packet(sisusb, 6, &packet);
1098 *data = packet.data & 0x00ffffff;
1101 packet.header = (type << 6) | 0x000e;
1102 ret = sisusb_send_packet(sisusb, 6, &packet);
1103 *data = packet.data >> 8;
1106 packet.header = (type << 6) | 0x000c;
1107 ret = sisusb_send_packet(sisusb, 6, &packet);
1108 *data = packet.data >> 16;
1109 packet.header = (type << 6) | 0x0001;
1110 packet.address = (addr & ~3) + 4;
1111 ret |= sisusb_send_packet(sisusb, 6, &packet);
1112 *data |= ((packet.data & 0xff) << 16);
1115 packet.header = (type << 6) | 0x0008;
1116 ret = sisusb_send_packet(sisusb, 6, &packet);
1117 *data = packet.data >> 24;
1118 packet.header = (type << 6) | 0x0003;
1119 packet.address = (addr & ~3) + 4;
1120 ret |= sisusb_send_packet(sisusb, 6, &packet);
1121 *data |= ((packet.data & 0xffff) << 8);
1127 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1128 u32 addr, u32 *data)
1130 struct sisusb_packet packet;
1133 packet.address = addr & ~3;
1137 packet.header = (type << 6) | 0x000f;
1138 ret = sisusb_send_packet(sisusb, 6, &packet);
1139 *data = packet.data;
1142 packet.header = (type << 6) | 0x000e;
1143 ret = sisusb_send_packet(sisusb, 6, &packet);
1144 *data = packet.data >> 8;
1145 packet.header = (type << 6) | 0x0001;
1146 packet.address = (addr & ~3) + 4;
1147 ret |= sisusb_send_packet(sisusb, 6, &packet);
1148 *data |= (packet.data << 24);
1151 packet.header = (type << 6) | 0x000c;
1152 ret = sisusb_send_packet(sisusb, 6, &packet);
1153 *data = packet.data >> 16;
1154 packet.header = (type << 6) | 0x0003;
1155 packet.address = (addr & ~3) + 4;
1156 ret |= sisusb_send_packet(sisusb, 6, &packet);
1157 *data |= (packet.data << 16);
1160 packet.header = (type << 6) | 0x0008;
1161 ret = sisusb_send_packet(sisusb, 6, &packet);
1162 *data = packet.data >> 24;
1163 packet.header = (type << 6) | 0x0007;
1164 packet.address = (addr & ~3) + 4;
1165 ret |= sisusb_send_packet(sisusb, 6, &packet);
1166 *data |= (packet.data << 8);
1172 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1173 char *kernbuffer, int length,
1174 char __user *userbuffer, ssize_t *bytes_read)
1183 length &= 0x00ffffff;
1191 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1196 if (put_user(buf[0],
1197 (u8 __user *)userbuffer)) {
1201 kernbuffer[0] = buf[0];
1207 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1212 if (put_user(swap16,
1213 (u16 __user *)userbuffer))
1216 *((u16 *)kernbuffer) = swap16;
1222 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1227 buf[0] = (swap32 >> 16) & 0xff;
1228 buf[1] = (swap32 >> 8) & 0xff;
1229 buf[2] = swap32 & 0xff;
1231 buf[2] = (swap32 >> 16) & 0xff;
1232 buf[1] = (swap32 >> 8) & 0xff;
1233 buf[0] = swap32 & 0xff;
1236 if (copy_to_user(userbuffer, &buf[0], 3))
1239 kernbuffer[0] = buf[0];
1240 kernbuffer[1] = buf[1];
1241 kernbuffer[2] = buf[2];
1247 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1252 if (put_user(swap32,
1253 (u32 __user *)userbuffer))
1258 *((u32 *)kernbuffer) = swap32;
1264 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1266 CLEARPACKET(&packet);
1267 packet.header = 0x001f;
1268 packet.address = 0x000001a0;
1269 packet.data = 0x00000006;
1270 ret |= sisusb_send_bridge_packet(sisusb, 10,
1272 packet.header = 0x001f;
1273 packet.address = 0x000001b0;
1274 packet.data = (length & ~3) | 0x40000000;
1275 ret |= sisusb_send_bridge_packet(sisusb, 10,
1277 packet.header = 0x001f;
1278 packet.address = 0x000001b4;
1280 ret |= sisusb_send_bridge_packet(sisusb, 10,
1282 packet.header = 0x001f;
1283 packet.address = 0x000001a4;
1284 packet.data = 0x00000001;
1285 ret |= sisusb_send_bridge_packet(sisusb, 10,
1288 ret |= sisusb_recv_bulk_msg(sisusb,
1289 SISUSB_EP_GFX_BULK_IN,
1293 if (!ret) userbuffer += (*bytes_read);
1295 ret |= sisusb_recv_bulk_msg(sisusb,
1296 SISUSB_EP_GFX_BULK_IN,
1300 if (!ret) kernbuffer += (*bytes_read);
1302 addr += (*bytes_read);
1303 length -= (*bytes_read);
1314 /* High level: Gfx (indexed) register access */
1316 #ifdef INCL_SISUSB_CON
1318 sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1320 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1324 sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1326 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1331 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1334 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1335 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1340 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1343 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1344 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1349 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1355 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1356 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1359 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1364 sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1369 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1370 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1372 tmp |= (data & mask);
1373 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1378 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1380 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1384 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1386 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1389 /* Write/read video ram */
1391 #ifdef INCL_SISUSB_CON
1393 sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1395 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1399 sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1401 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1407 sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
1409 return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1413 sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
1415 return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1421 sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1422 u32 dest, int length, size_t *bytes_written)
1424 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1427 #ifdef SISUSBENDIANTEST
1429 sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1430 u32 src, int length, size_t *bytes_written)
1432 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1437 #ifdef SISUSBENDIANTEST
1439 sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1441 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1442 char destbuffer[10];
1446 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1448 for(i = 1; i <= 7; i++) {
1449 printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
1450 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1451 for(j = 0; j < i; j++) {
1452 printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
1458 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1461 sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
1463 struct sisusb_packet packet;
1466 packet.header = 0x008f;
1467 packet.address = regnum | 0x10000;
1469 ret = sisusb_send_packet(sisusb, 10, &packet);
1474 sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
1476 struct sisusb_packet packet;
1479 packet.header = 0x008f;
1480 packet.address = (u32)regnum | 0x10000;
1481 ret = sisusb_send_packet(sisusb, 6, &packet);
1482 *data = packet.data;
1486 /* Clear video RAM */
1489 sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
1494 if (address < sisusb->vrambase)
1497 if (address >= sisusb->vrambase + sisusb->vramsize)
1500 if (address + length > sisusb->vrambase + sisusb->vramsize)
1501 length = sisusb->vrambase + sisusb->vramsize - address;
1506 /* allocate free buffer/urb and clear the buffer */
1507 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1510 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1512 /* We can write a length > buffer size here. The buffer
1513 * data will simply be re-used (like a ring-buffer).
1515 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1517 /* Free the buffer/urb */
1518 sisusb_free_outbuf(sisusb, i);
1523 /* Initialize the graphics core (return 0 on success)
1524 * This resets the graphics hardware and puts it into
1525 * a defined mode (640x480@60Hz)
1528 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1529 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1530 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1531 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1532 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1533 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1534 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1535 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1536 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1537 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1538 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1541 sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1546 ret = GETIREG(SISSR, 0x16, &tmp8);
1549 ret |= SETIREG(SISSR, 0x16, tmp8);
1551 ret |= SETIREG(SISSR, 0x16, tmp8);
1554 ret |= SETIREG(SISSR, 0x16, tmp8);
1556 ret |= SETIREG(SISSR, 0x16, tmp8);
1558 ret |= SETIREG(SISSR, 0x16, tmp8);
1560 ret |= SETIREG(SISSR, 0x16, tmp8);
1562 ret |= SETIREG(SISSR, 0x16, tmp8);
1564 ret |= SETIREG(SISSR, 0x16, tmp8);
1566 ret |= SETIREG(SISSR, 0x16, tmp8);
1572 sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
1575 u8 ramtype, done = 0;
1577 u32 ramptr = SISUSB_PCI_MEMBASE;
1579 ret = GETIREG(SISSR, 0x3a, &ramtype);
1582 ret |= SETIREG(SISSR, 0x13, 0x00);
1585 ret |= SETIREG(SISSR, 0x14, 0x12);
1586 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1588 ret |= SETIREG(SISSR, 0x14, 0x02);
1591 ret |= sisusb_triggersr16(sisusb, ramtype);
1592 ret |= WRITEL(ramptr + 0, 0x01234567);
1593 ret |= WRITEL(ramptr + 4, 0x456789ab);
1594 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1595 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1596 ret |= WRITEL(ramptr + 16, 0x55555555);
1597 ret |= WRITEL(ramptr + 20, 0x55555555);
1598 ret |= WRITEL(ramptr + 24, 0xffffffff);
1599 ret |= WRITEL(ramptr + 28, 0xffffffff);
1600 ret |= READL(ramptr + 0, &t0);
1601 ret |= READL(ramptr + 4, &t1);
1602 ret |= READL(ramptr + 8, &t2);
1603 ret |= READL(ramptr + 12, &t3);
1607 *chab = 0; *bw = 64;
1609 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1610 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1611 *chab = 0; *bw = 64;
1612 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1615 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1616 *chab = 1; *bw = 64;
1617 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
1619 ret |= sisusb_triggersr16(sisusb, ramtype);
1620 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1621 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1622 ret |= WRITEL(ramptr + 8, 0x55555555);
1623 ret |= WRITEL(ramptr + 12, 0x55555555);
1624 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1625 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1626 ret |= READL(ramptr + 4, &t1);
1628 if (t1 != 0xcdef0123) {
1630 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1636 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1640 if (t1 == 0x456789ab) {
1641 if (t0 == 0x01234567) {
1642 *chab = 0; *bw = 64;
1646 if (t0 == 0x01234567) {
1647 *chab = 0; *bw = 32;
1648 ret |= SETIREG(SISSR, 0x14, 0x00);
1654 ret |= SETIREG(SISSR, 0x14, 0x03);
1655 ret |= sisusb_triggersr16(sisusb, ramtype);
1657 ret |= WRITEL(ramptr + 0, 0x01234567);
1658 ret |= WRITEL(ramptr + 4, 0x456789ab);
1659 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1660 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1661 ret |= WRITEL(ramptr + 16, 0x55555555);
1662 ret |= WRITEL(ramptr + 20, 0x55555555);
1663 ret |= WRITEL(ramptr + 24, 0xffffffff);
1664 ret |= WRITEL(ramptr + 28, 0xffffffff);
1665 ret |= READL(ramptr + 0, &t0);
1666 ret |= READL(ramptr + 4, &t1);
1668 if (t1 == 0x456789ab) {
1669 if (t0 == 0x01234567) {
1670 *chab = 1; *bw = 64;
1674 if (t0 == 0x01234567) {
1675 *chab = 1; *bw = 32;
1676 ret |= SETIREG(SISSR, 0x14, 0x01);
1685 sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1688 u32 ramptr = SISUSB_PCI_MEMBASE;
1689 u8 tmp1, tmp2, i, j;
1691 ret |= WRITEB(ramptr, 0xaa);
1692 ret |= WRITEB(ramptr + 16, 0x55);
1693 ret |= READB(ramptr, &tmp1);
1694 ret |= READB(ramptr + 16, &tmp2);
1695 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1696 for (i = 0, j = 16; i < 2; i++, j += 16) {
1697 ret |= GETIREG(SISSR, 0x21, &tmp1);
1698 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1699 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1700 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1701 ret |= SETIREG(SISSR, 0x21, tmp1);
1702 ret |= WRITEB(ramptr + 16 + j, j);
1703 ret |= READB(ramptr + 16 + j, &tmp1);
1705 ret |= WRITEB(ramptr + j, j);
1714 sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
1715 u8 rankno, u8 chab, const u8 dramtype[][5],
1718 int ret = 0, ranksize;
1723 if ((rankno == 2) && (dramtype[index][0] == 2))
1726 ranksize = dramtype[index][3] / 2 * bw / 32;
1728 if ((ranksize * rankno) > 128)
1732 while ((ranksize >>= 1) > 0) tmp += 0x10;
1733 tmp |= ((rankno - 1) << 2);
1734 tmp |= ((bw / 64) & 0x02);
1735 tmp |= (chab & 0x01);
1737 ret = SETIREG(SISSR, 0x14, tmp);
1738 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1746 sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
1753 for (i = 0, j = 0; i < testn; i++) {
1754 ret |= WRITEL(sisusb->vrambase + j, j);
1758 for (i = 0, j = 0; i < testn; i++) {
1759 ret |= READL(sisusb->vrambase + j, &tmp);
1760 if (tmp != j) return ret;
1769 sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
1770 int idx, int bw, const u8 rtype[][5])
1772 int ret = 0, i, i2ret;
1777 for (i = rankno; i >= 1; i--) {
1778 inc = 1 << (rtype[idx][2] +
1782 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1787 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1788 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1792 inc = 1 << (10 + bw / 64);
1793 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1802 sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
1805 int ret = 0, i2ret = 0, i, j;
1806 static const u8 sdramtype[13][5] = {
1807 { 2, 12, 9, 64, 0x35 },
1808 { 1, 13, 9, 64, 0x44 },
1809 { 2, 12, 8, 32, 0x31 },
1810 { 2, 11, 9, 32, 0x25 },
1811 { 1, 12, 9, 32, 0x34 },
1812 { 1, 13, 8, 32, 0x40 },
1813 { 2, 11, 8, 16, 0x21 },
1814 { 1, 12, 8, 16, 0x30 },
1815 { 1, 11, 9, 16, 0x24 },
1816 { 1, 11, 8, 8, 0x20 },
1817 { 2, 9, 8, 4, 0x01 },
1818 { 1, 10, 8, 4, 0x10 },
1819 { 1, 9, 8, 2, 0x00 }
1822 *iret = 1; /* error */
1824 for (i = 0; i < 13; i++) {
1825 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1826 for (j = 2; j > 0; j--) {
1827 ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
1828 chab, sdramtype, bw);
1832 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
1835 *iret = 0; /* ram size found */
1845 sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
1849 int i, length, modex, modey, bpp;
1851 modex = 640; modey = 480; bpp = 2;
1853 address = sisusb->vrambase; /* Clear video ram */
1856 length = sisusb->vramsize;
1858 length = modex * bpp * modey;
1860 ret = sisusb_clear_vram(sisusb, address, length);
1862 if (!ret && drwfr) {
1863 for (i = 0; i < modex; i++) {
1864 address = sisusb->vrambase + (i * bpp);
1865 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1867 address += (modex * (modey-1) * bpp);
1868 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1871 for (i = 0; i < modey; i++) {
1872 address = sisusb->vrambase + ((i * modex) * bpp);
1873 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1875 address += ((modex - 1) * bpp);
1876 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1885 sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
1887 int ret = 0, i, j, modex, modey, bpp, du;
1888 u8 sr31, cr63, tmp8;
1889 static const char attrdata[] = {
1890 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1891 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1894 static const char crtcrdata[] = {
1895 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1896 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1897 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1900 static const char grcdata[] = {
1901 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1904 static const char crtcdata[] = {
1905 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1906 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1910 modex = 640; modey = 480; bpp = 2;
1912 GETIREG(SISSR, 0x31, &sr31);
1913 GETIREG(SISCR, 0x63, &cr63);
1914 SETIREGOR(SISSR, 0x01, 0x20);
1915 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1916 SETIREGOR(SISCR, 0x17, 0x80);
1917 SETIREGOR(SISSR, 0x1f, 0x04);
1918 SETIREGAND(SISSR, 0x07, 0xfb);
1919 SETIREG(SISSR, 0x00, 0x03); /* seq */
1920 SETIREG(SISSR, 0x01, 0x21);
1921 SETIREG(SISSR, 0x02, 0x0f);
1922 SETIREG(SISSR, 0x03, 0x00);
1923 SETIREG(SISSR, 0x04, 0x0e);
1924 SETREG(SISMISCW, 0x23); /* misc */
1925 for (i = 0; i <= 0x18; i++) { /* crtc */
1926 SETIREG(SISCR, i, crtcrdata[i]);
1928 for (i = 0; i <= 0x13; i++) { /* att */
1929 GETREG(SISINPSTAT, &tmp8);
1931 SETREG(SISAR, attrdata[i]);
1933 GETREG(SISINPSTAT, &tmp8);
1934 SETREG(SISAR, 0x14);
1935 SETREG(SISAR, 0x00);
1936 GETREG(SISINPSTAT, &tmp8);
1937 SETREG(SISAR, 0x20);
1938 GETREG(SISINPSTAT, &tmp8);
1939 for (i = 0; i <= 0x08; i++) { /* grc */
1940 SETIREG(SISGR, i, grcdata[i]);
1942 SETIREGAND(SISGR, 0x05, 0xbf);
1943 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1944 SETIREG(SISSR, i, 0x00);
1946 SETIREGAND(SISSR, 0x37, 0xfe);
1947 SETREG(SISMISCW, 0xef); /* sync */
1948 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1949 for (j = 0x00, i = 0; i <= 7; i++, j++) {
1950 SETIREG(SISCR, j, crtcdata[i]);
1952 for (j = 0x10; i <= 10; i++, j++) {
1953 SETIREG(SISCR, j, crtcdata[i]);
1955 for (j = 0x15; i <= 12; i++, j++) {
1956 SETIREG(SISCR, j, crtcdata[i]);
1958 for (j = 0x0A; i <= 15; i++, j++) {
1959 SETIREG(SISSR, j, crtcdata[i]);
1961 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1962 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1963 SETIREG(SISCR, 0x14, 0x4f);
1964 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1965 if (modex % 16) du += bpp;
1966 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1967 SETIREG(SISCR, 0x13, (du & 0xff));
1970 if (du & 0xff) tmp8++;
1971 SETIREG(SISSR, 0x10, tmp8);
1972 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1973 SETIREG(SISSR, 0x2b, 0x1b);
1974 SETIREG(SISSR, 0x2c, 0xe1);
1975 SETIREG(SISSR, 0x2d, 0x01);
1976 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1977 SETIREG(SISSR, 0x08, 0xae);
1978 SETIREGAND(SISSR, 0x09, 0xf0);
1979 SETIREG(SISSR, 0x08, 0x34);
1980 SETIREGOR(SISSR, 0x3d, 0x01);
1981 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1982 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1983 SETIREG(SISCR, 0x19, 0x00);
1984 SETIREGAND(SISCR, 0x1a, 0xfc);
1985 SETIREGAND(SISSR, 0x0f, 0xb7);
1986 SETIREGAND(SISSR, 0x31, 0xfb);
1987 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1988 SETIREGAND(SISSR, 0x32, 0xf3);
1989 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1990 SETIREG(SISCR, 0x52, 0x6c);
1992 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1993 SETIREG(SISCR, 0x0c, 0x00);
1994 SETIREG(SISSR, 0x0d, 0x00);
1995 SETIREGAND(SISSR, 0x37, 0xfe);
1997 SETIREG(SISCR, 0x32, 0x20);
1998 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1999 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
2000 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
2003 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
2004 SETIREGOR(SISSR, 0x1e, 0x5a);
2006 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
2007 SETIREG(SISSR, 0x27, 0x1f);
2008 SETIREG(SISSR, 0x26, 0x00);
2011 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
2017 sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
2019 int ret = 0, i, j, bw, chab, iret, retry = 3;
2022 static const char mclktable[] = {
2023 0x3b, 0x22, 0x01, 143,
2024 0x3b, 0x22, 0x01, 143,
2025 0x3b, 0x22, 0x01, 143,
2026 0x3b, 0x22, 0x01, 143
2028 static const char eclktable[] = {
2029 0x3b, 0x22, 0x01, 143,
2030 0x3b, 0x22, 0x01, 143,
2031 0x3b, 0x22, 0x01, 143,
2032 0x3b, 0x22, 0x01, 143
2034 static const char ramtypetable1[] = {
2035 0x00, 0x04, 0x60, 0x60,
2036 0x0f, 0x0f, 0x1f, 0x1f,
2037 0xba, 0xba, 0xba, 0xba,
2038 0xa9, 0xa9, 0xac, 0xac,
2039 0xa0, 0xa0, 0xa0, 0xa8,
2040 0x00, 0x00, 0x02, 0x02,
2041 0x30, 0x30, 0x40, 0x40
2043 static const char ramtypetable2[] = {
2044 0x77, 0x77, 0x44, 0x44,
2045 0x77, 0x77, 0x44, 0x44,
2046 0x00, 0x00, 0x00, 0x00,
2047 0x5b, 0x5b, 0xab, 0xab,
2048 0x00, 0x00, 0xf0, 0xf8
2054 ret = GETREG(SISVGAEN, &tmp8);
2055 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
2057 /* Enable GPU access to VRAM */
2058 ret |= GETREG(SISMISCR, &tmp8);
2059 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
2063 /* Reset registers */
2064 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
2065 ret |= SETIREG(SISSR, 0x05, 0x86);
2066 ret |= SETIREGOR(SISSR, 0x20, 0x01);
2068 ret |= SETREG(SISMISCW, 0x67);
2070 for (i = 0x06; i <= 0x1f; i++) {
2071 ret |= SETIREG(SISSR, i, 0x00);
2073 for (i = 0x21; i <= 0x27; i++) {
2074 ret |= SETIREG(SISSR, i, 0x00);
2076 for (i = 0x31; i <= 0x3d; i++) {
2077 ret |= SETIREG(SISSR, i, 0x00);
2079 for (i = 0x12; i <= 0x1b; i++) {
2080 ret |= SETIREG(SISSR, i, 0x00);
2082 for (i = 0x79; i <= 0x7c; i++) {
2083 ret |= SETIREG(SISCR, i, 0x00);
2088 ret |= SETIREG(SISCR, 0x63, 0x80);
2090 ret |= GETIREG(SISSR, 0x3a, &ramtype);
2093 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
2094 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
2095 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
2097 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
2098 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
2099 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
2101 ret |= SETIREG(SISSR, 0x07, 0x18);
2102 ret |= SETIREG(SISSR, 0x11, 0x0f);
2106 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
2107 ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
2109 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
2110 ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
2113 ret |= SETIREG(SISCR, 0x49, 0xaa);
2115 ret |= SETIREG(SISSR, 0x1f, 0x00);
2116 ret |= SETIREG(SISSR, 0x20, 0xa0);
2117 ret |= SETIREG(SISSR, 0x23, 0xf6);
2118 ret |= SETIREG(SISSR, 0x24, 0x0d);
2119 ret |= SETIREG(SISSR, 0x25, 0x33);
2121 ret |= SETIREG(SISSR, 0x11, 0x0f);
2123 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
2125 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2129 ret |= SETIREG(SISPART1, 0x00, 0x00);
2131 ret |= GETIREG(SISSR, 0x13, &tmp8);
2134 ret |= SETIREG(SISPART1, 0x02, 0x00);
2135 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2137 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2138 tmp32 &= 0x00f00000;
2139 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2140 ret |= SETIREG(SISSR, 0x25, tmp8);
2141 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2142 ret |= SETIREG(SISCR, 0x49, tmp8);
2144 ret |= SETIREG(SISSR, 0x27, 0x1f);
2145 ret |= SETIREG(SISSR, 0x31, 0x00);
2146 ret |= SETIREG(SISSR, 0x32, 0x11);
2147 ret |= SETIREG(SISSR, 0x33, 0x00);
2151 ret |= SETIREG(SISCR, 0x83, 0x00);
2153 ret |= sisusb_set_default_mode(sisusb, 0);
2155 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2156 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2157 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2159 ret |= sisusb_triggersr16(sisusb, ramtype);
2161 /* Disable refresh */
2162 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2163 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2165 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2166 ret |= sisusb_verify_mclk(sisusb);
2169 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2171 printk(KERN_ERR "sisusbvga[%d]: RAM size "
2172 "detection failed, "
2173 "assuming 8MB video RAM\n",
2175 ret |= SETIREG(SISSR,0x14,0x31);
2179 printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
2180 "assuming 8MB video RAM\n",
2182 ret |= SETIREG(SISSR,0x14,0x31);
2186 /* Enable refresh */
2187 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2188 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2189 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2191 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2193 ret |= SETIREG(SISSR, 0x22, 0xfb);
2194 ret |= SETIREG(SISSR, 0x21, 0xa5);
2214 sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2216 u8 tmp8, tmp82, ramtype;
2218 char *ramtypetext1 = NULL;
2219 const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
2220 "DDR SDRAM", "DDR SGRAM" };
2221 static const int busSDR[4] = {64, 64, 128, 128};
2222 static const int busDDR[4] = {32, 32, 64, 64};
2223 static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2225 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2226 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2227 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2228 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2230 switch ((tmp8 >> 2) & 0x03) {
2231 case 0: ramtypetext1 = "1 ch/1 r";
2235 bw = busSDR[(tmp8 & 0x03)];
2238 case 1: ramtypetext1 = "1 ch/2 r";
2239 sisusb->vramsize <<= 1;
2240 bw = busSDR[(tmp8 & 0x03)];
2242 case 2: ramtypetext1 = "asymmeric";
2243 sisusb->vramsize += sisusb->vramsize/2;
2244 bw = busDDRA[(tmp8 & 0x03)];
2246 case 3: ramtypetext1 = "2 channel";
2247 sisusb->vramsize <<= 1;
2248 bw = busDDR[(tmp8 & 0x03)];
2252 printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2253 sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
2254 ramtypetext2[ramtype], bw);
2258 sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2260 struct sisusb_packet packet;
2265 packet.header = 0x001f;
2266 packet.address = 0x00000324;
2267 packet.data = 0x00000004;
2268 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2270 packet.header = 0x001f;
2271 packet.address = 0x00000364;
2272 packet.data = 0x00000004;
2273 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2275 packet.header = 0x001f;
2276 packet.address = 0x00000384;
2277 packet.data = 0x00000004;
2278 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2280 packet.header = 0x001f;
2281 packet.address = 0x00000100;
2282 packet.data = 0x00000700;
2283 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2285 packet.header = 0x000f;
2286 packet.address = 0x00000004;
2287 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2288 packet.data |= 0x17;
2289 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2291 /* Init BAR 0 (VRAM) */
2292 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2293 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2294 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2296 tmp32 |= SISUSB_PCI_MEMBASE;
2297 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2299 /* Init BAR 1 (MMIO) */
2300 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2301 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2302 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2304 tmp32 |= SISUSB_PCI_MMIOBASE;
2305 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2307 /* Init BAR 2 (i/o ports) */
2308 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2309 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2310 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2312 tmp32 |= SISUSB_PCI_IOPORTBASE;
2313 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2315 /* Enable memory and i/o access */
2316 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2318 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2321 /* Some further magic */
2322 packet.header = 0x001f;
2323 packet.address = 0x00000050;
2324 packet.data = 0x000000ff;
2325 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2331 /* Initialize the graphics device (return 0 on success)
2332 * This initializes the net2280 as well as the PCI registers
2333 * of the graphics board.
2337 sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2339 int ret = 0, test = 0;
2342 if (sisusb->devinit == 1) {
2343 /* Read PCI BARs and see if they have been set up */
2344 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2345 if (ret) return ret;
2346 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2348 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2349 if (ret) return ret;
2350 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2352 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2353 if (ret) return ret;
2354 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2357 /* No? So reset the device */
2358 if ((sisusb->devinit == 0) || (test != 3)) {
2360 ret |= sisusb_do_init_gfxdevice(sisusb);
2363 sisusb->devinit = 1;
2367 if (sisusb->devinit) {
2368 /* Initialize the graphics core */
2369 if (sisusb_init_gfxcore(sisusb) == 0) {
2370 sisusb->gfxinit = 1;
2371 sisusb_get_ramconfig(sisusb);
2372 ret |= sisusb_set_default_mode(sisusb, 1);
2373 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2381 #ifdef INCL_SISUSB_CON
2383 /* Set up default text mode:
2384 - Set text mode (0x03)
2385 - Upload default font
2386 - Upload user font (if available)
2390 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2392 int ret = 0, slot = sisusb->font_slot, i;
2393 const struct font_desc *myfont;
2397 static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2398 static const char bootlogo[] = "(o_ //\\ V_/_";
2400 /* sisusb->lock is down */
2402 if (!sisusb->SiS_Pr)
2405 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2406 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2409 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2411 if (!(myfont = find_font("VGA8x16")))
2414 if (!(tempbuf = vmalloc(8192)))
2417 for (i = 0; i < 256; i++)
2418 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2420 /* Upload default font */
2421 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2425 /* Upload user font (and reset current slot) */
2426 if (sisusb->font_backup) {
2427 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2428 8192, sisusb->font_backup_512, 1, NULL,
2429 sisusb->font_backup_height, 0);
2431 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2435 if (init && !sisusb->scrbuf) {
2437 if ((tempbuf = vmalloc(8192))) {
2440 tempbufb = (u16 *)tempbuf;
2442 *(tempbufb++) = 0x0720;
2445 tempbufb = (u16 *)tempbuf;
2446 while (bootlogo[i]) {
2447 *(tempbufb++) = 0x0700 | bootlogo[i++];
2453 tempbufb = (u16 *)tempbuf + 6;
2454 while (bootstring[i])
2455 *(tempbufb++) = 0x0700 | bootstring[i++];
2457 ret |= sisusb_copy_memory(sisusb, tempbuf,
2458 sisusb->vrambase, 8192, &written);
2464 } else if (sisusb->scrbuf) {
2466 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2467 sisusb->vrambase, sisusb->scrbuf_size, &written);
2471 if (sisusb->sisusb_cursor_size_from >= 0 &&
2472 sisusb->sisusb_cursor_size_to >= 0) {
2473 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2474 sisusb->sisusb_cursor_size_from);
2475 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2476 sisusb->sisusb_cursor_size_to);
2478 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2479 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2480 sisusb->sisusb_cursor_size_to = -1;
2483 slot = sisusb->sisusb_cursor_loc;
2484 if(slot < 0) slot = 0;
2486 sisusb->sisusb_cursor_loc = -1;
2487 sisusb->bad_cursor_pos = 1;
2489 sisusb_set_cursor(sisusb, slot);
2491 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2492 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2494 sisusb->textmodedestroyed = 0;
2496 /* sisusb->lock is down */
2506 sisusb_open(struct inode *inode, struct file *file)
2508 struct sisusb_usb_data *sisusb;
2509 struct usb_interface *interface;
2510 int subminor = iminor(inode);
2512 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2513 printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
2518 if (!(sisusb = usb_get_intfdata(interface)))
2521 mutex_lock(&sisusb->lock);
2523 if (!sisusb->present || !sisusb->ready) {
2524 mutex_unlock(&sisusb->lock);
2528 if (sisusb->isopen) {
2529 mutex_unlock(&sisusb->lock);
2533 if (!sisusb->devinit) {
2534 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2535 if (sisusb_init_gfxdevice(sisusb, 0)) {
2536 mutex_unlock(&sisusb->lock);
2538 "sisusbvga[%d]: Failed to initialize "
2544 mutex_unlock(&sisusb->lock);
2546 "sisusbvga[%d]: Device not attached to "
2553 /* Increment usage count for our sisusb */
2554 kref_get(&sisusb->kref);
2558 file->private_data = sisusb;
2560 mutex_unlock(&sisusb->lock);
2566 sisusb_delete(struct kref *kref)
2568 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2573 if (sisusb->sisusb_dev)
2574 usb_put_dev(sisusb->sisusb_dev);
2576 sisusb->sisusb_dev = NULL;
2577 sisusb_free_buffers(sisusb);
2578 sisusb_free_urbs(sisusb);
2579 #ifdef INCL_SISUSB_CON
2580 kfree(sisusb->SiS_Pr);
2586 sisusb_release(struct inode *inode, struct file *file)
2588 struct sisusb_usb_data *sisusb;
2591 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2594 mutex_lock(&sisusb->lock);
2596 if (sisusb->present) {
2597 /* Wait for all URBs to finish if device still present */
2598 if (!sisusb_wait_all_out_complete(sisusb))
2599 sisusb_kill_all_busy(sisusb);
2602 myminor = sisusb->minor;
2605 file->private_data = NULL;
2607 mutex_unlock(&sisusb->lock);
2609 /* decrement the usage count on our device */
2610 kref_put(&sisusb->kref, sisusb_delete);
2616 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2618 struct sisusb_usb_data *sisusb;
2619 ssize_t bytes_read = 0;
2625 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2628 mutex_lock(&sisusb->lock);
2631 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2632 mutex_unlock(&sisusb->lock);
2636 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2637 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2640 SISUSB_PCI_PSEUDO_IOPORTBASE +
2641 SISUSB_PCI_IOPORTBASE;
2644 * Byte, word and long(32) can be read. As this
2645 * emulates inX instructions, the data returned is
2646 * in machine-endianness.
2651 if (sisusb_read_memio_byte(sisusb,
2655 else if (put_user(buf8, (u8 __user *)buffer))
2663 if (sisusb_read_memio_word(sisusb,
2667 else if (put_user(buf16, (u16 __user *)buffer))
2675 if (sisusb_read_memio_long(sisusb,
2679 else if (put_user(buf32, (u32 __user *)buffer))
2691 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2692 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2695 SISUSB_PCI_PSEUDO_MEMBASE +
2699 * Remember: Data delivered is never endian-corrected
2701 errno = sisusb_read_mem_bulk(sisusb, address,
2702 NULL, count, buffer, &bytes_read);
2707 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2708 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2711 SISUSB_PCI_PSEUDO_MMIOBASE +
2712 SISUSB_PCI_MMIOBASE;
2715 * Remember: Data delivered is never endian-corrected
2717 errno = sisusb_read_mem_bulk(sisusb, address,
2718 NULL, count, buffer, &bytes_read);
2723 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2724 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2727 mutex_unlock(&sisusb->lock);
2731 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2733 /* Read PCI config register
2734 * Return value delivered in machine endianness.
2736 if (sisusb_read_pci_config(sisusb, address, &buf32))
2738 else if (put_user(buf32, (u32 __user *)buffer))
2749 (*ppos) += bytes_read;
2751 mutex_unlock(&sisusb->lock);
2753 return errno ? errno : bytes_read;
2757 sisusb_write(struct file *file, const char __user *buffer, size_t count,
2760 struct sisusb_usb_data *sisusb;
2762 ssize_t bytes_written = 0;
2767 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2770 mutex_lock(&sisusb->lock);
2773 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2774 mutex_unlock(&sisusb->lock);
2778 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2779 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2782 SISUSB_PCI_PSEUDO_IOPORTBASE +
2783 SISUSB_PCI_IOPORTBASE;
2786 * Byte, word and long(32) can be written. As this
2787 * emulates outX instructions, the data is expected
2788 * in machine-endianness.
2793 if (get_user(buf8, (u8 __user *)buffer))
2795 else if (sisusb_write_memio_byte(sisusb,
2805 if (get_user(buf16, (u16 __user *)buffer))
2807 else if (sisusb_write_memio_word(sisusb,
2817 if (get_user(buf32, (u32 __user *)buffer))
2819 else if (sisusb_write_memio_long(sisusb,
2832 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2833 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2836 SISUSB_PCI_PSEUDO_MEMBASE +
2840 * Buffer is copied 1:1, therefore, on big-endian
2841 * machines, the data must be swapped by userland
2842 * in advance (if applicable; no swapping in 8bpp
2843 * mode or if YUV data is being transferred).
2845 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2846 count, buffer, 0, &bytes_written);
2849 errno = bytes_written;
2851 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2852 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2855 SISUSB_PCI_PSEUDO_MMIOBASE +
2856 SISUSB_PCI_MMIOBASE;
2859 * Buffer is copied 1:1, therefore, on big-endian
2860 * machines, the data must be swapped by userland
2863 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2864 count, buffer, 0, &bytes_written);
2867 errno = bytes_written;
2869 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2870 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2873 mutex_unlock(&sisusb->lock);
2877 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2879 /* Write PCI config register.
2880 * Given value expected in machine endianness.
2882 if (get_user(buf32, (u32 __user *)buffer))
2884 else if (sisusb_write_pci_config(sisusb, address, buf32))
2897 (*ppos) += bytes_written;
2899 mutex_unlock(&sisusb->lock);
2901 return errno ? errno : bytes_written;
2905 sisusb_lseek(struct file *file, loff_t offset, int orig)
2907 struct sisusb_usb_data *sisusb;
2910 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2913 mutex_lock(&sisusb->lock);
2916 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2917 mutex_unlock(&sisusb->lock);
2923 file->f_pos = offset;
2925 /* never negative, no force_successful_syscall needed */
2928 file->f_pos += offset;
2930 /* never negative, no force_successful_syscall needed */
2933 /* seeking relative to "end of file" is not supported */
2937 mutex_unlock(&sisusb->lock);
2942 sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2945 int retval, port, length;
2948 /* All our commands require the device
2949 * to be initialized.
2951 if (!sisusb->devinit)
2955 SISUSB_PCI_PSEUDO_IOPORTBASE +
2956 SISUSB_PCI_IOPORTBASE;
2958 switch (y->operation) {
2960 retval = sisusb_getidxreg(sisusb, port,
2961 y->data0, &y->data1);
2963 if (copy_to_user((void __user *)arg, y,
2970 retval = sisusb_setidxreg(sisusb, port,
2971 y->data0, y->data1);
2975 retval = sisusb_setidxregor(sisusb, port,
2976 y->data0, y->data1);
2980 retval = sisusb_setidxregand(sisusb, port,
2981 y->data0, y->data1);
2984 case SUCMD_SETANDOR:
2985 retval = sisusb_setidxregandor(sisusb, port,
2986 y->data0, y->data1, y->data2);
2990 retval = sisusb_setidxregmask(sisusb, port,
2991 y->data0, y->data1, y->data2);
2995 /* Gfx core must be initialized */
2996 if (!sisusb->gfxinit)
2999 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
3000 address = y->data3 -
3001 SISUSB_PCI_PSEUDO_MEMBASE +
3003 retval = sisusb_clear_vram(sisusb, address, length);
3006 case SUCMD_HANDLETEXTMODE:
3008 #ifdef INCL_SISUSB_CON
3009 /* Gfx core must be initialized, SiS_Pr must exist */
3010 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3015 retval = sisusb_reset_text_mode(sisusb, 0);
3018 sisusb->textmodedestroyed = 1;
3024 #ifdef INCL_SISUSB_CON
3026 /* Gfx core must be initialized, SiS_Pr must exist */
3027 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3032 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3033 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3035 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
3040 case SUCMD_SETVESAMODE:
3041 /* Gfx core must be initialized, SiS_Pr must exist */
3042 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3047 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3048 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3050 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
3067 sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
3070 struct sisusb_usb_data *sisusb;
3071 struct sisusb_info x;
3072 struct sisusb_command y;
3074 u32 __user *argp = (u32 __user *)arg;
3076 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
3079 mutex_lock(&sisusb->lock);
3082 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
3089 case SISUSB_GET_CONFIG_SIZE:
3091 if (put_user(sizeof(x), argp))
3096 case SISUSB_GET_CONFIG:
3098 x.sisusb_id = SISUSB_ID;
3099 x.sisusb_version = SISUSB_VERSION;
3100 x.sisusb_revision = SISUSB_REVISION;
3101 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3102 x.sisusb_gfxinit = sisusb->gfxinit;
3103 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
3104 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
3105 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
3106 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
3107 x.sisusb_vramsize = sisusb->vramsize;
3108 x.sisusb_minor = sisusb->minor;
3109 x.sisusb_fbdevactive= 0;
3110 #ifdef INCL_SISUSB_CON
3111 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3113 x.sisusb_conactive = 0;
3116 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3121 case SISUSB_COMMAND:
3123 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3126 retval = sisusb_handle_command(sisusb, &y, arg);
3136 mutex_unlock(&sisusb->lock);
3140 #ifdef SISUSB_NEW_CONFIG_COMPAT
3142 sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3147 case SISUSB_GET_CONFIG_SIZE:
3148 case SISUSB_GET_CONFIG:
3149 case SISUSB_COMMAND:
3151 retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
3156 return -ENOIOCTLCMD;
3161 static const struct file_operations usb_sisusb_fops = {
3162 .owner = THIS_MODULE,
3163 .open = sisusb_open,
3164 .release = sisusb_release,
3165 .read = sisusb_read,
3166 .write = sisusb_write,
3167 .llseek = sisusb_lseek,
3168 #ifdef SISUSB_NEW_CONFIG_COMPAT
3169 .compat_ioctl = sisusb_compat_ioctl,
3171 .ioctl = sisusb_ioctl
3174 static struct usb_class_driver usb_sisusb_class = {
3175 .name = "sisusbvga%d",
3176 .fops = &usb_sisusb_fops,
3177 .minor_base = SISUSB_MINOR
3180 static int sisusb_probe(struct usb_interface *intf,
3181 const struct usb_device_id *id)
3183 struct usb_device *dev = interface_to_usbdev(intf);
3184 struct sisusb_usb_data *sisusb;
3186 const char *memfail =
3188 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3190 printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
3193 /* Allocate memory for our private */
3194 if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3196 "sisusb: Failed to allocate memory for private data\n");
3199 kref_init(&sisusb->kref);
3201 mutex_init(&(sisusb->lock));
3203 /* Register device */
3204 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3206 "sisusb: Failed to get a minor for device %d\n",
3212 sisusb->sisusb_dev = dev;
3213 sisusb->minor = intf->minor;
3214 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3215 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3216 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3217 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3218 /* Everything else is zero */
3220 /* Allocate buffers */
3221 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3222 if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3223 GFP_KERNEL, &sisusb->transfer_dma_in))) {
3224 printk(memfail, "input", sisusb->minor);
3229 sisusb->numobufs = 0;
3230 sisusb->obufsize = SISUSB_OBUF_SIZE;
3231 for (i = 0; i < NUMOBUFS; i++) {
3232 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3234 &sisusb->transfer_dma_out[i]))) {
3236 printk(memfail, "output", sisusb->minor);
3247 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3249 "sisusbvga[%d]: Failed to allocate URBs\n",
3254 sisusb->completein = 1;
3256 for (i = 0; i < sisusb->numobufs; i++) {
3257 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3259 "sisusbvga[%d]: Failed to allocate URBs\n",
3264 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3265 sisusb->urbout_context[i].urbindex = i;
3266 sisusb->urbstatus[i] = 0;
3269 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
3270 sisusb->minor, sisusb->numobufs);
3272 #ifdef INCL_SISUSB_CON
3273 /* Allocate our SiS_Pr */
3274 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3276 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3281 /* Do remaining init stuff */
3283 init_waitqueue_head(&sisusb->wait_q);
3285 usb_set_intfdata(intf, sisusb);
3287 usb_get_dev(sisusb->sisusb_dev);
3289 sisusb->present = 1;
3291 #ifdef SISUSB_OLD_CONFIG_COMPAT
3294 /* Our ioctls are all "32/64bit compatible" */
3295 ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
3296 ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
3297 ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
3300 "sisusbvga[%d]: Error registering ioctl32 "
3304 sisusb->ioctl32registered = 1;
3308 if (dev->speed == USB_SPEED_HIGH) {
3310 #ifdef INCL_SISUSB_CON
3311 if (sisusb_first_vc > 0 &&
3312 sisusb_last_vc > 0 &&
3313 sisusb_first_vc <= sisusb_last_vc &&
3314 sisusb_last_vc <= MAX_NR_CONSOLES)
3317 if (sisusb_init_gfxdevice(sisusb, initscreen))
3319 "sisusbvga[%d]: Failed to early "
3320 "initialize device\n",
3325 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3331 #ifdef SISUSBENDIANTEST
3332 printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
3333 sisusb_testreadwrite(sisusb);
3334 printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
3337 #ifdef INCL_SISUSB_CON
3338 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3344 sisusb_free_urbs(sisusb);
3346 sisusb_free_buffers(sisusb);
3348 usb_deregister_dev(intf, &usb_sisusb_class);
3354 static void sisusb_disconnect(struct usb_interface *intf)
3356 struct sisusb_usb_data *sisusb;
3359 /* This should *not* happen */
3360 if (!(sisusb = usb_get_intfdata(intf)))
3363 #ifdef INCL_SISUSB_CON
3364 sisusb_console_exit(sisusb);
3367 minor = sisusb->minor;
3369 usb_deregister_dev(intf, &usb_sisusb_class);
3371 mutex_lock(&sisusb->lock);
3373 /* Wait for all URBs to complete and kill them in case (MUST do) */
3374 if (!sisusb_wait_all_out_complete(sisusb))
3375 sisusb_kill_all_busy(sisusb);
3377 usb_set_intfdata(intf, NULL);
3379 #ifdef SISUSB_OLD_CONFIG_COMPAT
3380 if (sisusb->ioctl32registered) {
3382 sisusb->ioctl32registered = 0;
3383 ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
3384 ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
3385 ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
3388 "sisusbvga[%d]: Error unregistering "
3389 "ioctl32 translations\n",
3395 sisusb->present = 0;
3398 mutex_unlock(&sisusb->lock);
3400 /* decrement our usage count */
3401 kref_put(&sisusb->kref, sisusb_delete);
3403 printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
3406 static struct usb_device_id sisusb_table [] = {
3407 { USB_DEVICE(0x0711, 0x0900) },
3408 { USB_DEVICE(0x0711, 0x0901) },
3409 { USB_DEVICE(0x0711, 0x0902) },
3410 { USB_DEVICE(0x182d, 0x021c) },
3411 { USB_DEVICE(0x182d, 0x0269) },
3415 MODULE_DEVICE_TABLE (usb, sisusb_table);
3417 static struct usb_driver sisusb_driver = {
3419 .probe = sisusb_probe,
3420 .disconnect = sisusb_disconnect,
3421 .id_table = sisusb_table,
3424 static int __init usb_sisusb_init(void)
3428 #ifdef INCL_SISUSB_CON
3429 sisusb_init_concode();
3432 if (!(retval = usb_register(&sisusb_driver))) {
3434 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
3435 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
3437 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3444 static void __exit usb_sisusb_exit(void)
3446 usb_deregister(&sisusb_driver);
3449 module_init(usb_sisusb_init);
3450 module_exit(usb_sisusb_exit);
3452 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3453 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3454 MODULE_LICENSE("GPL");