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/vmalloc.h>
53 #include "sisusb_init.h"
55 #ifdef INCL_SISUSB_CON
56 #include <linux/font.h>
59 #define SISUSB_DONTSYNC
61 /* Forward declarations / clean-up routines */
63 #ifdef INCL_SISUSB_CON
64 static int sisusb_first_vc;
65 static int sisusb_last_vc;
66 module_param_named(first, sisusb_first_vc, int, 0);
67 module_param_named(last, sisusb_last_vc, int, 0);
68 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
69 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
72 static struct usb_driver sisusb_driver;
74 static void sisusb_free_buffers(struct sisusb_usb_data *sisusb)
78 for (i = 0; i < NUMOBUFS; i++) {
79 kfree(sisusb->obuf[i]);
80 sisusb->obuf[i] = NULL;
86 static void sisusb_free_urbs(struct sisusb_usb_data *sisusb)
90 for (i = 0; i < NUMOBUFS; i++) {
91 usb_free_urb(sisusb->sisurbout[i]);
92 sisusb->sisurbout[i] = NULL;
94 usb_free_urb(sisusb->sisurbin);
95 sisusb->sisurbin = NULL;
98 /* Level 0: USB transport layer */
102 /* out-urb management */
104 /* Return 1 if all free, 0 otherwise */
105 static int sisusb_all_free(struct sisusb_usb_data *sisusb)
109 for (i = 0; i < sisusb->numobufs; i++) {
111 if (sisusb->urbstatus[i] & SU_URB_BUSY)
119 /* Kill all busy URBs */
120 static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
124 if (sisusb_all_free(sisusb))
127 for (i = 0; i < sisusb->numobufs; i++) {
129 if (sisusb->urbstatus[i] & SU_URB_BUSY)
130 usb_kill_urb(sisusb->sisurbout[i]);
135 /* Return 1 if ok, 0 if error (not all complete within timeout) */
136 static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
138 int timeout = 5 * HZ, i = 1;
140 wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)),
146 static int sisusb_outurb_available(struct sisusb_usb_data *sisusb)
150 for (i = 0; i < sisusb->numobufs; i++) {
152 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
160 static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
162 int i, timeout = 5 * HZ;
164 wait_event_timeout(sisusb->wait_q,
165 ((i = sisusb_outurb_available(sisusb)) >= 0), timeout);
170 static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
174 i = sisusb_outurb_available(sisusb);
177 sisusb->urbstatus[i] |= SU_URB_ALLOC;
182 static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
184 if ((index >= 0) && (index < sisusb->numobufs))
185 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
188 /* completion callback */
190 static void sisusb_bulk_completeout(struct urb *urb)
192 struct sisusb_urb_context *context = urb->context;
193 struct sisusb_usb_data *sisusb;
198 sisusb = context->sisusb;
200 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
203 #ifndef SISUSB_DONTSYNC
204 if (context->actual_length)
205 *(context->actual_length) += urb->actual_length;
208 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
209 wake_up(&sisusb->wait_q);
212 static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index,
213 unsigned int pipe, void *data, int len, int *actual_length,
214 int timeout, unsigned int tflags)
216 struct urb *urb = sisusb->sisurbout[index];
217 int retval, byteswritten = 0;
220 urb->transfer_flags = 0;
222 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
223 sisusb_bulk_completeout,
224 &sisusb->urbout_context[index]);
226 urb->transfer_flags |= tflags;
227 urb->actual_length = 0;
230 sisusb->urbout_context[index].actual_length = (timeout) ?
231 NULL : actual_length;
233 /* Declare this urb/buffer in use */
234 sisusb->urbstatus[index] |= SU_URB_BUSY;
237 retval = usb_submit_urb(urb, GFP_KERNEL);
239 /* If OK, and if timeout > 0, wait for completion */
240 if ((retval == 0) && timeout) {
241 wait_event_timeout(sisusb->wait_q,
242 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
244 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
245 /* URB timed out... kill it and report error */
249 /* Otherwise, report urb status */
250 retval = urb->status;
251 byteswritten = urb->actual_length;
256 *actual_length = byteswritten;
263 /* completion callback */
265 static void sisusb_bulk_completein(struct urb *urb)
267 struct sisusb_usb_data *sisusb = urb->context;
269 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
272 sisusb->completein = 1;
273 wake_up(&sisusb->wait_q);
276 static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb,
277 unsigned int pipe, void *data, int len,
278 int *actual_length, int timeout, unsigned int tflags)
280 struct urb *urb = sisusb->sisurbin;
281 int retval, readbytes = 0;
283 urb->transfer_flags = 0;
285 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
286 sisusb_bulk_completein, sisusb);
288 urb->transfer_flags |= tflags;
289 urb->actual_length = 0;
291 sisusb->completein = 0;
292 retval = usb_submit_urb(urb, GFP_KERNEL);
294 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
295 if (!sisusb->completein) {
296 /* URB timed out... kill it and report error */
300 /* URB completed within timeout */
301 retval = urb->status;
302 readbytes = urb->actual_length;
307 *actual_length = readbytes;
315 /* Send a bulk message of variable size
317 * To copy the data from userspace, give pointer to "userbuffer",
318 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
319 * both of these are NULL, it is assumed, that the transfer
320 * buffer "sisusb->obuf[index]" is set up with the data to send.
321 * Index is ignored if either kernbuffer or userbuffer is set.
322 * If async is nonzero, URBs will be sent without waiting for
323 * completion of the previous URB.
325 * (return 0 on success)
328 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
329 char *kernbuffer, const char __user *userbuffer, int index,
330 ssize_t *bytes_written, unsigned int tflags, int async)
332 int result = 0, retry, count = len;
333 int passsize, thispass, transferred_len = 0;
334 int fromuser = (userbuffer != NULL) ? 1 : 0;
335 int fromkern = (kernbuffer != NULL) ? 1 : 0;
339 (*bytes_written) = 0;
342 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
345 /* If we copy data from kernel or userspace, force the
346 * allocation of a buffer/urb. If we have the data in
347 * the transfer buffer[index] already, reuse the buffer/URB
348 * if the length is > buffer size. (So, transmitting
349 * large data amounts directly from the transfer buffer
350 * treats the buffer as a ring buffer. However, we need
351 * to sync in this case.)
353 if (fromuser || fromkern)
355 else if (len > sisusb->obufsize)
358 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
361 passsize = thispass = (sisusb->obufsize < count) ?
362 sisusb->obufsize : count;
365 index = sisusb_get_free_outbuf(sisusb);
370 buffer = sisusb->obuf[index];
374 if (copy_from_user(buffer, userbuffer, passsize))
377 userbuffer += passsize;
379 } else if (fromkern) {
381 memcpy(buffer, kernbuffer, passsize);
382 kernbuffer += passsize;
389 if (!sisusb->sisusb_dev)
392 result = sisusb_bulkout_msg(sisusb, index, pipe,
393 buffer, thispass, &transferred_len,
394 async ? 0 : 5 * HZ, tflags);
396 if (result == -ETIMEDOUT) {
398 /* Will not happen if async */
405 if ((result == 0) && !async && transferred_len) {
407 thispass -= transferred_len;
408 buffer += transferred_len;
417 (*bytes_written) += passsize;
420 /* Force new allocation in next iteration */
421 if (fromuser || fromkern)
427 #ifdef SISUSB_DONTSYNC
428 (*bytes_written) = len;
429 /* Some URBs/buffers might be busy */
431 sisusb_wait_all_out_complete(sisusb);
432 (*bytes_written) = transferred_len;
433 /* All URBs and all buffers are available */
437 return ((*bytes_written) == len) ? 0 : -EIO;
440 /* Receive a bulk message of variable size
442 * To copy the data to userspace, give pointer to "userbuffer",
443 * to copy to kernel memory, give "kernbuffer". One of them
444 * MUST be set. (There is no technique for letting the caller
445 * read directly from the ibuf.)
449 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
450 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
453 int result = 0, retry, count = len;
454 int bufsize, thispass, transferred_len;
461 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
464 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
465 buffer = sisusb->ibuf;
466 bufsize = sisusb->ibufsize;
470 #ifdef SISUSB_DONTSYNC
471 if (!(sisusb_wait_all_out_complete(sisusb)))
477 if (!sisusb->sisusb_dev)
480 thispass = (bufsize < count) ? bufsize : count;
482 result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass,
483 &transferred_len, 5 * HZ, tflags);
486 thispass = transferred_len;
488 else if (result == -ETIMEDOUT) {
501 (*bytes_read) += thispass;
506 if (copy_to_user(userbuffer, buffer, thispass))
509 userbuffer += thispass;
513 memcpy(kernbuffer, buffer, thispass);
514 kernbuffer += thispass;
522 return ((*bytes_read) == len) ? 0 : -EIO;
525 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
526 struct sisusb_packet *packet)
529 ssize_t bytes_transferred = 0;
535 #ifdef SISUSB_DONTSYNC
536 if (!(sisusb_wait_all_out_complete(sisusb)))
540 /* Eventually correct endianness */
541 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
543 /* 1. send the packet */
544 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
545 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
547 if ((ret == 0) && (len == 6)) {
549 /* 2. if packet len == 6, it means we read, so wait for 32bit
550 * return value and write it to packet->data
552 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
553 (char *)&tmp, NULL, &bytes_transferred, 0);
555 packet->data = le32_to_cpu(tmp);
561 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
562 struct sisusb_packet *packet, unsigned int tflags)
565 ssize_t bytes_transferred = 0;
571 #ifdef SISUSB_DONTSYNC
572 if (!(sisusb_wait_all_out_complete(sisusb)))
576 /* Eventually correct endianness */
577 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
579 /* 1. send the packet */
580 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
581 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
583 if ((ret == 0) && (len == 6)) {
585 /* 2. if packet len == 6, it means we read, so wait for 32bit
586 * return value and write it to packet->data
588 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
589 (char *)&tmp, NULL, &bytes_transferred, 0);
591 packet->data = le32_to_cpu(tmp);
597 /* access video memory and mmio (return 0 on success) */
601 /* The following routines assume being used to transfer byte, word,
604 * - the write routines expect "data" in machine endianness format.
605 * The data will be converted to leXX in sisusb_xxx_packet.
606 * - the read routines can expect read data in machine-endianess.
609 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
612 struct sisusb_packet packet;
614 packet.header = (1 << (addr & 3)) | (type << 6);
615 packet.address = addr & ~3;
616 packet.data = data << ((addr & 3) << 3);
617 return sisusb_send_packet(sisusb, 10, &packet);
620 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
623 struct sisusb_packet packet;
626 packet.address = addr & ~3;
630 packet.header = (type << 6) | 0x0003;
631 packet.data = (u32)data;
632 ret = sisusb_send_packet(sisusb, 10, &packet);
635 packet.header = (type << 6) | 0x0006;
636 packet.data = (u32)data << 8;
637 ret = sisusb_send_packet(sisusb, 10, &packet);
640 packet.header = (type << 6) | 0x000c;
641 packet.data = (u32)data << 16;
642 ret = sisusb_send_packet(sisusb, 10, &packet);
645 packet.header = (type << 6) | 0x0008;
646 packet.data = (u32)data << 24;
647 ret = sisusb_send_packet(sisusb, 10, &packet);
648 packet.header = (type << 6) | 0x0001;
649 packet.address = (addr & ~3) + 4;
650 packet.data = (u32)data >> 8;
651 ret |= sisusb_send_packet(sisusb, 10, &packet);
657 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
660 struct sisusb_packet packet;
663 packet.address = addr & ~3;
667 packet.header = (type << 6) | 0x0007;
668 packet.data = data & 0x00ffffff;
669 ret = sisusb_send_packet(sisusb, 10, &packet);
672 packet.header = (type << 6) | 0x000e;
673 packet.data = data << 8;
674 ret = sisusb_send_packet(sisusb, 10, &packet);
677 packet.header = (type << 6) | 0x000c;
678 packet.data = data << 16;
679 ret = sisusb_send_packet(sisusb, 10, &packet);
680 packet.header = (type << 6) | 0x0001;
681 packet.address = (addr & ~3) + 4;
682 packet.data = (data >> 16) & 0x00ff;
683 ret |= sisusb_send_packet(sisusb, 10, &packet);
686 packet.header = (type << 6) | 0x0008;
687 packet.data = data << 24;
688 ret = sisusb_send_packet(sisusb, 10, &packet);
689 packet.header = (type << 6) | 0x0003;
690 packet.address = (addr & ~3) + 4;
691 packet.data = (data >> 8) & 0xffff;
692 ret |= sisusb_send_packet(sisusb, 10, &packet);
698 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
701 struct sisusb_packet packet;
704 packet.address = addr & ~3;
708 packet.header = (type << 6) | 0x000f;
710 ret = sisusb_send_packet(sisusb, 10, &packet);
713 packet.header = (type << 6) | 0x000e;
714 packet.data = data << 8;
715 ret = sisusb_send_packet(sisusb, 10, &packet);
716 packet.header = (type << 6) | 0x0001;
717 packet.address = (addr & ~3) + 4;
718 packet.data = data >> 24;
719 ret |= sisusb_send_packet(sisusb, 10, &packet);
722 packet.header = (type << 6) | 0x000c;
723 packet.data = data << 16;
724 ret = sisusb_send_packet(sisusb, 10, &packet);
725 packet.header = (type << 6) | 0x0003;
726 packet.address = (addr & ~3) + 4;
727 packet.data = data >> 16;
728 ret |= sisusb_send_packet(sisusb, 10, &packet);
731 packet.header = (type << 6) | 0x0008;
732 packet.data = data << 24;
733 ret = sisusb_send_packet(sisusb, 10, &packet);
734 packet.header = (type << 6) | 0x0007;
735 packet.address = (addr & ~3) + 4;
736 packet.data = data >> 8;
737 ret |= sisusb_send_packet(sisusb, 10, &packet);
743 /* The xxx_bulk routines copy a buffer of variable size. They treat the
744 * buffer as chars, therefore lsb/msb has to be corrected if using the
745 * byte/word/long/etc routines for speed-up
747 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
748 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
749 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
750 * that the data already is in the transfer buffer "sisusb->obuf[index]".
753 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
754 char *kernbuffer, int length, const char __user *userbuffer,
755 int index, ssize_t *bytes_written)
757 struct sisusb_packet packet;
760 u8 swap8, fromkern = kernbuffer ? 1 : 0;
762 u32 swap32, flag = (length >> 28) & 1;
765 /* if neither kernbuffer not userbuffer are given, assume
768 if (!fromkern && !userbuffer)
769 kernbuffer = sisusb->obuf[index];
771 (*bytes_written = 0);
773 length &= 0x00ffffff;
779 if (get_user(swap8, (u8 __user *)userbuffer))
782 swap8 = kernbuffer[0];
784 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
794 if (get_user(swap16, (u16 __user *)userbuffer))
797 swap16 = *((u16 *)kernbuffer);
799 ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
803 (*bytes_written) += 2;
809 if (copy_from_user(&buf, userbuffer, 3))
812 swap32 = (buf[0] << 16) |
816 swap32 = (buf[2] << 16) |
822 swap32 = (kernbuffer[0] << 16) |
823 (kernbuffer[1] << 8) |
826 swap32 = (kernbuffer[2] << 16) |
827 (kernbuffer[1] << 8) |
831 ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
835 (*bytes_written) += 3;
841 if (get_user(swap32, (u32 __user *)userbuffer))
844 swap32 = *((u32 *)kernbuffer);
846 ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
849 (*bytes_written) += 4;
854 if ((length & ~3) > 0x10000) {
856 packet.header = 0x001f;
857 packet.address = 0x000001d4;
859 ret = sisusb_send_bridge_packet(sisusb, 10,
861 packet.header = 0x001f;
862 packet.address = 0x000001d0;
863 packet.data = (length & ~3);
864 ret |= sisusb_send_bridge_packet(sisusb, 10,
866 packet.header = 0x001f;
867 packet.address = 0x000001c0;
868 packet.data = flag | 0x16;
869 ret |= sisusb_send_bridge_packet(sisusb, 10,
872 ret |= sisusb_send_bulk_msg(sisusb,
873 SISUSB_EP_GFX_LBULK_OUT,
876 bytes_written, 0, 1);
877 userbuffer += (*bytes_written);
878 } else if (fromkern) {
879 ret |= sisusb_send_bulk_msg(sisusb,
880 SISUSB_EP_GFX_LBULK_OUT,
883 bytes_written, 0, 1);
884 kernbuffer += (*bytes_written);
886 ret |= sisusb_send_bulk_msg(sisusb,
887 SISUSB_EP_GFX_LBULK_OUT,
890 bytes_written, 0, 1);
891 kernbuffer += ((*bytes_written) &
892 (sisusb->obufsize-1));
897 packet.header = 0x001f;
898 packet.address = 0x00000194;
900 ret = sisusb_send_bridge_packet(sisusb, 10,
902 packet.header = 0x001f;
903 packet.address = 0x00000190;
904 packet.data = (length & ~3);
905 ret |= sisusb_send_bridge_packet(sisusb, 10,
907 if (sisusb->flagb0 != 0x16) {
908 packet.header = 0x001f;
909 packet.address = 0x00000180;
910 packet.data = flag | 0x16;
911 ret |= sisusb_send_bridge_packet(sisusb,
913 sisusb->flagb0 = 0x16;
916 ret |= sisusb_send_bulk_msg(sisusb,
917 SISUSB_EP_GFX_BULK_OUT,
920 bytes_written, 0, 1);
921 userbuffer += (*bytes_written);
922 } else if (fromkern) {
923 ret |= sisusb_send_bulk_msg(sisusb,
924 SISUSB_EP_GFX_BULK_OUT,
927 bytes_written, 0, 1);
928 kernbuffer += (*bytes_written);
930 ret |= sisusb_send_bulk_msg(sisusb,
931 SISUSB_EP_GFX_BULK_OUT,
934 bytes_written, 0, 1);
935 kernbuffer += ((*bytes_written) &
936 (sisusb->obufsize-1));
942 dev_err(&sisusb->sisusb_dev->dev,
943 "Wrote %zd of %d bytes, error %d\n",
944 *bytes_written, length,
946 else if (msgcount == 500)
947 dev_err(&sisusb->sisusb_dev->dev,
948 "Too many errors, logging stopped\n");
950 addr += (*bytes_written);
951 length -= (*bytes_written);
959 return ret ? -EIO : 0;
962 /* Remember: Read data in packet is in machine-endianess! So for
963 * byte, word, 24bit, long no endian correction is necessary.
966 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
969 struct sisusb_packet packet;
972 CLEARPACKET(&packet);
973 packet.header = (1 << (addr & 3)) | (type << 6);
974 packet.address = addr & ~3;
975 ret = sisusb_send_packet(sisusb, 6, &packet);
976 *data = (u8)(packet.data >> ((addr & 3) << 3));
980 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
983 struct sisusb_packet packet;
986 CLEARPACKET(&packet);
988 packet.address = addr & ~3;
992 packet.header = (type << 6) | 0x0003;
993 ret = sisusb_send_packet(sisusb, 6, &packet);
994 *data = (u16)(packet.data);
997 packet.header = (type << 6) | 0x0006;
998 ret = sisusb_send_packet(sisusb, 6, &packet);
999 *data = (u16)(packet.data >> 8);
1002 packet.header = (type << 6) | 0x000c;
1003 ret = sisusb_send_packet(sisusb, 6, &packet);
1004 *data = (u16)(packet.data >> 16);
1007 packet.header = (type << 6) | 0x0008;
1008 ret = sisusb_send_packet(sisusb, 6, &packet);
1009 *data = (u16)(packet.data >> 24);
1010 packet.header = (type << 6) | 0x0001;
1011 packet.address = (addr & ~3) + 4;
1012 ret |= sisusb_send_packet(sisusb, 6, &packet);
1013 *data |= (u16)(packet.data << 8);
1019 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1020 u32 addr, u32 *data)
1022 struct sisusb_packet packet;
1025 packet.address = addr & ~3;
1029 packet.header = (type << 6) | 0x0007;
1030 ret = sisusb_send_packet(sisusb, 6, &packet);
1031 *data = packet.data & 0x00ffffff;
1034 packet.header = (type << 6) | 0x000e;
1035 ret = sisusb_send_packet(sisusb, 6, &packet);
1036 *data = packet.data >> 8;
1039 packet.header = (type << 6) | 0x000c;
1040 ret = sisusb_send_packet(sisusb, 6, &packet);
1041 *data = packet.data >> 16;
1042 packet.header = (type << 6) | 0x0001;
1043 packet.address = (addr & ~3) + 4;
1044 ret |= sisusb_send_packet(sisusb, 6, &packet);
1045 *data |= ((packet.data & 0xff) << 16);
1048 packet.header = (type << 6) | 0x0008;
1049 ret = sisusb_send_packet(sisusb, 6, &packet);
1050 *data = packet.data >> 24;
1051 packet.header = (type << 6) | 0x0003;
1052 packet.address = (addr & ~3) + 4;
1053 ret |= sisusb_send_packet(sisusb, 6, &packet);
1054 *data |= ((packet.data & 0xffff) << 8);
1060 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1061 u32 addr, u32 *data)
1063 struct sisusb_packet packet;
1066 packet.address = addr & ~3;
1070 packet.header = (type << 6) | 0x000f;
1071 ret = sisusb_send_packet(sisusb, 6, &packet);
1072 *data = packet.data;
1075 packet.header = (type << 6) | 0x000e;
1076 ret = sisusb_send_packet(sisusb, 6, &packet);
1077 *data = packet.data >> 8;
1078 packet.header = (type << 6) | 0x0001;
1079 packet.address = (addr & ~3) + 4;
1080 ret |= sisusb_send_packet(sisusb, 6, &packet);
1081 *data |= (packet.data << 24);
1084 packet.header = (type << 6) | 0x000c;
1085 ret = sisusb_send_packet(sisusb, 6, &packet);
1086 *data = packet.data >> 16;
1087 packet.header = (type << 6) | 0x0003;
1088 packet.address = (addr & ~3) + 4;
1089 ret |= sisusb_send_packet(sisusb, 6, &packet);
1090 *data |= (packet.data << 16);
1093 packet.header = (type << 6) | 0x0008;
1094 ret = sisusb_send_packet(sisusb, 6, &packet);
1095 *data = packet.data >> 24;
1096 packet.header = (type << 6) | 0x0007;
1097 packet.address = (addr & ~3) + 4;
1098 ret |= sisusb_send_packet(sisusb, 6, &packet);
1099 *data |= (packet.data << 8);
1105 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1106 char *kernbuffer, int length, char __user *userbuffer,
1107 ssize_t *bytes_read)
1116 length &= 0x00ffffff;
1121 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1126 if (put_user(buf[0], (u8 __user *)userbuffer))
1129 kernbuffer[0] = buf[0];
1134 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1139 if (put_user(swap16, (u16 __user *)userbuffer))
1142 *((u16 *)kernbuffer) = swap16;
1148 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1153 buf[0] = (swap32 >> 16) & 0xff;
1154 buf[1] = (swap32 >> 8) & 0xff;
1155 buf[2] = swap32 & 0xff;
1157 buf[2] = (swap32 >> 16) & 0xff;
1158 buf[1] = (swap32 >> 8) & 0xff;
1159 buf[0] = swap32 & 0xff;
1162 if (copy_to_user(userbuffer,
1166 kernbuffer[0] = buf[0];
1167 kernbuffer[1] = buf[1];
1168 kernbuffer[2] = buf[2];
1174 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1179 if (put_user(swap32, (u32 __user *)userbuffer))
1184 *((u32 *)kernbuffer) = swap32;
1198 /* High level: Gfx (indexed) register access */
1200 #ifdef INCL_SISUSB_CON
1201 int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1203 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1206 int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1208 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1212 int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
1217 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1218 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1222 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
1227 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1228 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1232 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1238 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1239 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1242 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1246 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1247 int port, u8 idx, u8 data, u8 mask)
1252 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1253 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1255 tmp |= (data & mask);
1256 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1260 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
1263 return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1266 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
1269 return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1272 /* Write/read video ram */
1274 #ifdef INCL_SISUSB_CON
1275 int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1277 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1280 int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1282 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1285 int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1286 u32 dest, int length)
1290 return sisusb_write_mem_bulk(sisusb, dest, src, length,
1294 #ifdef SISUSBENDIANTEST
1295 static int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1296 u32 src, int length)
1300 return sisusb_read_mem_bulk(sisusb, src, dest, length,
1306 #ifdef SISUSBENDIANTEST
1307 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1309 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1310 char destbuffer[10];
1313 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
1315 for (i = 1; i <= 7; i++) {
1316 dev_dbg(&sisusb->sisusb_dev->dev,
1317 "sisusb: rwtest %d bytes\n", i);
1318 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
1319 for (j = 0; j < i; j++) {
1320 dev_dbg(&sisusb->sisusb_dev->dev,
1321 "rwtest read[%d] = %x\n",
1328 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1330 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1331 int regnum, u32 data)
1333 struct sisusb_packet packet;
1335 packet.header = 0x008f;
1336 packet.address = regnum | 0x10000;
1338 return sisusb_send_packet(sisusb, 10, &packet);
1341 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1342 int regnum, u32 *data)
1344 struct sisusb_packet packet;
1347 packet.header = 0x008f;
1348 packet.address = (u32)regnum | 0x10000;
1349 ret = sisusb_send_packet(sisusb, 6, &packet);
1350 *data = packet.data;
1354 /* Clear video RAM */
1356 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1357 u32 address, int length)
1362 if (address < sisusb->vrambase)
1365 if (address >= sisusb->vrambase + sisusb->vramsize)
1368 if (address + length > sisusb->vrambase + sisusb->vramsize)
1369 length = sisusb->vrambase + sisusb->vramsize - address;
1374 /* allocate free buffer/urb and clear the buffer */
1375 i = sisusb_alloc_outbuf(sisusb);
1379 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1381 /* We can write a length > buffer size here. The buffer
1382 * data will simply be re-used (like a ring-buffer).
1384 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1386 /* Free the buffer/urb */
1387 sisusb_free_outbuf(sisusb, i);
1392 /* Initialize the graphics core (return 0 on success)
1393 * This resets the graphics hardware and puts it into
1394 * a defined mode (640x480@60Hz)
1397 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1398 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1399 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1400 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1401 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1402 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1403 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1404 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1405 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1406 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1409 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1414 ret = GETIREG(SISSR, 0x16, &tmp8);
1417 ret |= SETIREG(SISSR, 0x16, tmp8);
1419 ret |= SETIREG(SISSR, 0x16, tmp8);
1422 ret |= SETIREG(SISSR, 0x16, tmp8);
1424 ret |= SETIREG(SISSR, 0x16, tmp8);
1426 ret |= SETIREG(SISSR, 0x16, tmp8);
1428 ret |= SETIREG(SISSR, 0x16, tmp8);
1430 ret |= SETIREG(SISSR, 0x16, tmp8);
1432 ret |= SETIREG(SISSR, 0x16, tmp8);
1434 ret |= SETIREG(SISSR, 0x16, tmp8);
1439 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1443 u8 ramtype, done = 0;
1445 u32 ramptr = SISUSB_PCI_MEMBASE;
1447 ret = GETIREG(SISSR, 0x3a, &ramtype);
1450 ret |= SETIREG(SISSR, 0x13, 0x00);
1453 ret |= SETIREG(SISSR, 0x14, 0x12);
1454 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1456 ret |= SETIREG(SISSR, 0x14, 0x02);
1459 ret |= sisusb_triggersr16(sisusb, ramtype);
1460 ret |= WRITEL(ramptr + 0, 0x01234567);
1461 ret |= WRITEL(ramptr + 4, 0x456789ab);
1462 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1463 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1464 ret |= WRITEL(ramptr + 16, 0x55555555);
1465 ret |= WRITEL(ramptr + 20, 0x55555555);
1466 ret |= WRITEL(ramptr + 24, 0xffffffff);
1467 ret |= WRITEL(ramptr + 28, 0xffffffff);
1468 ret |= READL(ramptr + 0, &t0);
1469 ret |= READL(ramptr + 4, &t1);
1470 ret |= READL(ramptr + 8, &t2);
1471 ret |= READL(ramptr + 12, &t3);
1475 *chab = 0; *bw = 64;
1477 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1478 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1479 *chab = 0; *bw = 64;
1480 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1483 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1484 *chab = 1; *bw = 64;
1485 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1487 ret |= sisusb_triggersr16(sisusb, ramtype);
1488 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1489 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1490 ret |= WRITEL(ramptr + 8, 0x55555555);
1491 ret |= WRITEL(ramptr + 12, 0x55555555);
1492 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1493 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1494 ret |= READL(ramptr + 4, &t1);
1496 if (t1 != 0xcdef0123) {
1498 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1504 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1508 if (t1 == 0x456789ab) {
1509 if (t0 == 0x01234567) {
1510 *chab = 0; *bw = 64;
1514 if (t0 == 0x01234567) {
1515 *chab = 0; *bw = 32;
1516 ret |= SETIREG(SISSR, 0x14, 0x00);
1522 ret |= SETIREG(SISSR, 0x14, 0x03);
1523 ret |= sisusb_triggersr16(sisusb, ramtype);
1525 ret |= WRITEL(ramptr + 0, 0x01234567);
1526 ret |= WRITEL(ramptr + 4, 0x456789ab);
1527 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1528 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1529 ret |= WRITEL(ramptr + 16, 0x55555555);
1530 ret |= WRITEL(ramptr + 20, 0x55555555);
1531 ret |= WRITEL(ramptr + 24, 0xffffffff);
1532 ret |= WRITEL(ramptr + 28, 0xffffffff);
1533 ret |= READL(ramptr + 0, &t0);
1534 ret |= READL(ramptr + 4, &t1);
1536 if (t1 == 0x456789ab) {
1537 if (t0 == 0x01234567) {
1538 *chab = 1; *bw = 64;
1542 if (t0 == 0x01234567) {
1543 *chab = 1; *bw = 32;
1544 ret |= SETIREG(SISSR, 0x14, 0x01);
1552 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1555 u32 ramptr = SISUSB_PCI_MEMBASE;
1556 u8 tmp1, tmp2, i, j;
1558 ret |= WRITEB(ramptr, 0xaa);
1559 ret |= WRITEB(ramptr + 16, 0x55);
1560 ret |= READB(ramptr, &tmp1);
1561 ret |= READB(ramptr + 16, &tmp2);
1562 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1563 for (i = 0, j = 16; i < 2; i++, j += 16) {
1564 ret |= GETIREG(SISSR, 0x21, &tmp1);
1565 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1566 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1567 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1568 ret |= SETIREG(SISSR, 0x21, tmp1);
1569 ret |= WRITEB(ramptr + 16 + j, j);
1570 ret |= READB(ramptr + 16 + j, &tmp1);
1572 ret |= WRITEB(ramptr + j, j);
1580 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1581 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1583 int ret = 0, ranksize;
1588 if ((rankno == 2) && (dramtype[index][0] == 2))
1591 ranksize = dramtype[index][3] / 2 * bw / 32;
1593 if ((ranksize * rankno) > 128)
1597 while ((ranksize >>= 1) > 0)
1600 tmp |= ((rankno - 1) << 2);
1601 tmp |= ((bw / 64) & 0x02);
1602 tmp |= (chab & 0x01);
1604 ret = SETIREG(SISSR, 0x14, tmp);
1605 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1612 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1620 for (i = 0, j = 0; i < testn; i++) {
1621 ret |= WRITEL(sisusb->vrambase + j, j);
1625 for (i = 0, j = 0; i < testn; i++) {
1626 ret |= READL(sisusb->vrambase + j, &tmp);
1637 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1638 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1640 int ret = 0, i, i2ret;
1645 for (i = rankno; i >= 1; i--) {
1646 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1648 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1653 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1654 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1658 inc = 1 << (10 + bw / 64);
1659 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1667 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1670 int ret = 0, i2ret = 0, i, j;
1671 static const u8 sdramtype[13][5] = {
1672 { 2, 12, 9, 64, 0x35 },
1673 { 1, 13, 9, 64, 0x44 },
1674 { 2, 12, 8, 32, 0x31 },
1675 { 2, 11, 9, 32, 0x25 },
1676 { 1, 12, 9, 32, 0x34 },
1677 { 1, 13, 8, 32, 0x40 },
1678 { 2, 11, 8, 16, 0x21 },
1679 { 1, 12, 8, 16, 0x30 },
1680 { 1, 11, 9, 16, 0x24 },
1681 { 1, 11, 8, 8, 0x20 },
1682 { 2, 9, 8, 4, 0x01 },
1683 { 1, 10, 8, 4, 0x10 },
1684 { 1, 9, 8, 2, 0x00 }
1687 *iret = 1; /* error */
1689 for (i = 0; i < 13; i++) {
1690 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1691 for (j = 2; j > 0; j--) {
1692 ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1697 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1700 *iret = 0; /* ram size found */
1709 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1710 int clrall, int drwfr)
1714 int i, length, modex, modey, bpp;
1716 modex = 640; modey = 480; bpp = 2;
1718 address = sisusb->vrambase; /* Clear video ram */
1721 length = sisusb->vramsize;
1723 length = modex * bpp * modey;
1725 ret = sisusb_clear_vram(sisusb, address, length);
1727 if (!ret && drwfr) {
1728 for (i = 0; i < modex; i++) {
1729 address = sisusb->vrambase + (i * bpp);
1730 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1732 address += (modex * (modey-1) * bpp);
1733 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1736 for (i = 0; i < modey; i++) {
1737 address = sisusb->vrambase + ((i * modex) * bpp);
1738 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1740 address += ((modex - 1) * bpp);
1741 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1749 static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1752 int ret = 0, i, j, modex, modey, bpp, du;
1753 u8 sr31, cr63, tmp8;
1754 static const char attrdata[] = {
1755 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1756 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1757 0x01, 0x00, 0x00, 0x00
1759 static const char crtcrdata[] = {
1760 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1761 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1762 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1765 static const char grcdata[] = {
1766 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1769 static const char crtcdata[] = {
1770 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1771 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1775 modex = 640; modey = 480; bpp = 2;
1777 GETIREG(SISSR, 0x31, &sr31);
1778 GETIREG(SISCR, 0x63, &cr63);
1779 SETIREGOR(SISSR, 0x01, 0x20);
1780 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1781 SETIREGOR(SISCR, 0x17, 0x80);
1782 SETIREGOR(SISSR, 0x1f, 0x04);
1783 SETIREGAND(SISSR, 0x07, 0xfb);
1784 SETIREG(SISSR, 0x00, 0x03); /* seq */
1785 SETIREG(SISSR, 0x01, 0x21);
1786 SETIREG(SISSR, 0x02, 0x0f);
1787 SETIREG(SISSR, 0x03, 0x00);
1788 SETIREG(SISSR, 0x04, 0x0e);
1789 SETREG(SISMISCW, 0x23); /* misc */
1790 for (i = 0; i <= 0x18; i++) { /* crtc */
1791 SETIREG(SISCR, i, crtcrdata[i]);
1793 for (i = 0; i <= 0x13; i++) { /* att */
1794 GETREG(SISINPSTAT, &tmp8);
1796 SETREG(SISAR, attrdata[i]);
1798 GETREG(SISINPSTAT, &tmp8);
1799 SETREG(SISAR, 0x14);
1800 SETREG(SISAR, 0x00);
1801 GETREG(SISINPSTAT, &tmp8);
1802 SETREG(SISAR, 0x20);
1803 GETREG(SISINPSTAT, &tmp8);
1804 for (i = 0; i <= 0x08; i++) { /* grc */
1805 SETIREG(SISGR, i, grcdata[i]);
1807 SETIREGAND(SISGR, 0x05, 0xbf);
1808 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1809 SETIREG(SISSR, i, 0x00);
1811 SETIREGAND(SISSR, 0x37, 0xfe);
1812 SETREG(SISMISCW, 0xef); /* sync */
1813 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1814 for (j = 0x00, i = 0; i <= 7; i++, j++)
1815 SETIREG(SISCR, j, crtcdata[i]);
1817 for (j = 0x10; i <= 10; i++, j++)
1818 SETIREG(SISCR, j, crtcdata[i]);
1820 for (j = 0x15; i <= 12; i++, j++)
1821 SETIREG(SISCR, j, crtcdata[i]);
1823 for (j = 0x0A; i <= 15; i++, j++)
1824 SETIREG(SISSR, j, crtcdata[i]);
1826 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1827 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1828 SETIREG(SISCR, 0x14, 0x4f);
1829 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1830 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1831 SETIREG(SISCR, 0x13, (du & 0xff));
1834 SETIREG(SISSR, 0x10, tmp8);
1835 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1836 SETIREG(SISSR, 0x2b, 0x1b);
1837 SETIREG(SISSR, 0x2c, 0xe1);
1838 SETIREG(SISSR, 0x2d, 0x01);
1839 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1840 SETIREG(SISSR, 0x08, 0xae);
1841 SETIREGAND(SISSR, 0x09, 0xf0);
1842 SETIREG(SISSR, 0x08, 0x34);
1843 SETIREGOR(SISSR, 0x3d, 0x01);
1844 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1845 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1846 SETIREG(SISCR, 0x19, 0x00);
1847 SETIREGAND(SISCR, 0x1a, 0xfc);
1848 SETIREGAND(SISSR, 0x0f, 0xb7);
1849 SETIREGAND(SISSR, 0x31, 0xfb);
1850 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1851 SETIREGAND(SISSR, 0x32, 0xf3);
1852 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1853 SETIREG(SISCR, 0x52, 0x6c);
1855 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1856 SETIREG(SISCR, 0x0c, 0x00);
1857 SETIREG(SISSR, 0x0d, 0x00);
1858 SETIREGAND(SISSR, 0x37, 0xfe);
1860 SETIREG(SISCR, 0x32, 0x20);
1861 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1862 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1863 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1866 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1867 SETIREGOR(SISSR, 0x1e, 0x5a);
1869 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1870 SETIREG(SISSR, 0x27, 0x1f);
1871 SETIREG(SISSR, 0x26, 0x00);
1874 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1879 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1881 int ret = 0, i, j, bw, chab, iret, retry = 3;
1884 static const char mclktable[] = {
1885 0x3b, 0x22, 0x01, 143,
1886 0x3b, 0x22, 0x01, 143,
1887 0x3b, 0x22, 0x01, 143,
1888 0x3b, 0x22, 0x01, 143
1890 static const char eclktable[] = {
1891 0x3b, 0x22, 0x01, 143,
1892 0x3b, 0x22, 0x01, 143,
1893 0x3b, 0x22, 0x01, 143,
1894 0x3b, 0x22, 0x01, 143
1896 static const char ramtypetable1[] = {
1897 0x00, 0x04, 0x60, 0x60,
1898 0x0f, 0x0f, 0x1f, 0x1f,
1899 0xba, 0xba, 0xba, 0xba,
1900 0xa9, 0xa9, 0xac, 0xac,
1901 0xa0, 0xa0, 0xa0, 0xa8,
1902 0x00, 0x00, 0x02, 0x02,
1903 0x30, 0x30, 0x40, 0x40
1905 static const char ramtypetable2[] = {
1906 0x77, 0x77, 0x44, 0x44,
1907 0x77, 0x77, 0x44, 0x44,
1908 0x00, 0x00, 0x00, 0x00,
1909 0x5b, 0x5b, 0xab, 0xab,
1910 0x00, 0x00, 0xf0, 0xf8
1916 ret = GETREG(SISVGAEN, &tmp8);
1917 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1919 /* Enable GPU access to VRAM */
1920 ret |= GETREG(SISMISCR, &tmp8);
1921 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1926 /* Reset registers */
1927 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1928 ret |= SETIREG(SISSR, 0x05, 0x86);
1929 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1931 ret |= SETREG(SISMISCW, 0x67);
1933 for (i = 0x06; i <= 0x1f; i++)
1934 ret |= SETIREG(SISSR, i, 0x00);
1936 for (i = 0x21; i <= 0x27; i++)
1937 ret |= SETIREG(SISSR, i, 0x00);
1939 for (i = 0x31; i <= 0x3d; i++)
1940 ret |= SETIREG(SISSR, i, 0x00);
1942 for (i = 0x12; i <= 0x1b; i++)
1943 ret |= SETIREG(SISSR, i, 0x00);
1945 for (i = 0x79; i <= 0x7c; i++)
1946 ret |= SETIREG(SISCR, i, 0x00);
1951 ret |= SETIREG(SISCR, 0x63, 0x80);
1953 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1956 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1957 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1958 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1960 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1961 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1962 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1964 ret |= SETIREG(SISSR, 0x07, 0x18);
1965 ret |= SETIREG(SISSR, 0x11, 0x0f);
1970 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1971 ret |= SETIREG(SISSR, i,
1972 ramtypetable1[(j*4) + ramtype]);
1974 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1975 ret |= SETIREG(SISCR, i,
1976 ramtypetable2[(j*4) + ramtype]);
1979 ret |= SETIREG(SISCR, 0x49, 0xaa);
1981 ret |= SETIREG(SISSR, 0x1f, 0x00);
1982 ret |= SETIREG(SISSR, 0x20, 0xa0);
1983 ret |= SETIREG(SISSR, 0x23, 0xf6);
1984 ret |= SETIREG(SISSR, 0x24, 0x0d);
1985 ret |= SETIREG(SISSR, 0x25, 0x33);
1987 ret |= SETIREG(SISSR, 0x11, 0x0f);
1989 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1991 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
1996 ret |= SETIREG(SISPART1, 0x00, 0x00);
1998 ret |= GETIREG(SISSR, 0x13, &tmp8);
2001 ret |= SETIREG(SISPART1, 0x02, 0x00);
2002 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2004 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2005 tmp32 &= 0x00f00000;
2006 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2007 ret |= SETIREG(SISSR, 0x25, tmp8);
2008 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2009 ret |= SETIREG(SISCR, 0x49, tmp8);
2011 ret |= SETIREG(SISSR, 0x27, 0x1f);
2012 ret |= SETIREG(SISSR, 0x31, 0x00);
2013 ret |= SETIREG(SISSR, 0x32, 0x11);
2014 ret |= SETIREG(SISSR, 0x33, 0x00);
2019 ret |= SETIREG(SISCR, 0x83, 0x00);
2021 ret |= sisusb_set_default_mode(sisusb, 0);
2023 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2024 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2025 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2027 ret |= sisusb_triggersr16(sisusb, ramtype);
2029 /* Disable refresh */
2030 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2031 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2033 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2034 ret |= sisusb_verify_mclk(sisusb);
2037 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2039 dev_err(&sisusb->sisusb_dev->dev,
2040 "RAM size detection failed, assuming 8MB video RAM\n");
2041 ret |= SETIREG(SISSR, 0x14, 0x31);
2045 dev_err(&sisusb->sisusb_dev->dev,
2046 "DDR RAM device found, assuming 8MB video RAM\n");
2047 ret |= SETIREG(SISSR, 0x14, 0x31);
2051 /* Enable refresh */
2052 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2053 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2054 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2056 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2058 ret |= SETIREG(SISSR, 0x22, 0xfb);
2059 ret |= SETIREG(SISSR, 0x21, 0xa5);
2078 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2080 u8 tmp8, tmp82, ramtype;
2082 char *ramtypetext1 = NULL;
2083 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2084 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2085 static const int busSDR[4] = {64, 64, 128, 128};
2086 static const int busDDR[4] = {32, 32, 64, 64};
2087 static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2089 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2090 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2091 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2092 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2094 switch ((tmp8 >> 2) & 0x03) {
2096 ramtypetext1 = "1 ch/1 r";
2100 bw = busSDR[(tmp8 & 0x03)];
2104 ramtypetext1 = "1 ch/2 r";
2105 sisusb->vramsize <<= 1;
2106 bw = busSDR[(tmp8 & 0x03)];
2109 ramtypetext1 = "asymmeric";
2110 sisusb->vramsize += sisusb->vramsize/2;
2111 bw = busDDRA[(tmp8 & 0x03)];
2114 ramtypetext1 = "2 channel";
2115 sisusb->vramsize <<= 1;
2116 bw = busDDR[(tmp8 & 0x03)];
2120 dev_info(&sisusb->sisusb_dev->dev,
2121 "%dMB %s %cDR S%cRAM, bus width %d\n",
2122 sisusb->vramsize >> 20, ramtypetext1,
2123 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2126 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2128 struct sisusb_packet packet;
2133 packet.header = 0x001f;
2134 packet.address = 0x00000324;
2135 packet.data = 0x00000004;
2136 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2138 packet.header = 0x001f;
2139 packet.address = 0x00000364;
2140 packet.data = 0x00000004;
2141 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2143 packet.header = 0x001f;
2144 packet.address = 0x00000384;
2145 packet.data = 0x00000004;
2146 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2148 packet.header = 0x001f;
2149 packet.address = 0x00000100;
2150 packet.data = 0x00000700;
2151 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2153 packet.header = 0x000f;
2154 packet.address = 0x00000004;
2155 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2156 packet.data |= 0x17;
2157 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2159 /* Init BAR 0 (VRAM) */
2160 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2161 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2162 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2164 tmp32 |= SISUSB_PCI_MEMBASE;
2165 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2167 /* Init BAR 1 (MMIO) */
2168 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2169 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2170 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2172 tmp32 |= SISUSB_PCI_MMIOBASE;
2173 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2175 /* Init BAR 2 (i/o ports) */
2176 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2177 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2178 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2180 tmp32 |= SISUSB_PCI_IOPORTBASE;
2181 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2183 /* Enable memory and i/o access */
2184 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2186 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2189 /* Some further magic */
2190 packet.header = 0x001f;
2191 packet.address = 0x00000050;
2192 packet.data = 0x000000ff;
2193 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2199 /* Initialize the graphics device (return 0 on success)
2200 * This initializes the net2280 as well as the PCI registers
2201 * of the graphics board.
2204 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2206 int ret = 0, test = 0;
2209 if (sisusb->devinit == 1) {
2210 /* Read PCI BARs and see if they have been set up */
2211 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2215 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2218 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2222 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2225 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2229 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2233 /* No? So reset the device */
2234 if ((sisusb->devinit == 0) || (test != 3)) {
2236 ret |= sisusb_do_init_gfxdevice(sisusb);
2239 sisusb->devinit = 1;
2243 if (sisusb->devinit) {
2244 /* Initialize the graphics core */
2245 if (sisusb_init_gfxcore(sisusb) == 0) {
2246 sisusb->gfxinit = 1;
2247 sisusb_get_ramconfig(sisusb);
2248 ret |= sisusb_set_default_mode(sisusb, 1);
2249 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2257 #ifdef INCL_SISUSB_CON
2259 /* Set up default text mode:
2260 * - Set text mode (0x03)
2261 * - Upload default font
2262 * - Upload user font (if available)
2265 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2267 int ret = 0, slot = sisusb->font_slot, i;
2268 const struct font_desc *myfont;
2271 static const char bootstring[] =
2272 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2273 static const char bootlogo[] = "(o_ //\\ V_/_";
2275 /* sisusb->lock is down */
2277 if (!sisusb->SiS_Pr)
2280 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2281 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2284 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2286 myfont = find_font("VGA8x16");
2290 tempbuf = vmalloc(8192);
2294 for (i = 0; i < 256; i++)
2295 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2297 /* Upload default font */
2298 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2303 /* Upload user font (and reset current slot) */
2304 if (sisusb->font_backup) {
2305 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2306 8192, sisusb->font_backup_512, 1, NULL,
2307 sisusb->font_backup_height, 0);
2309 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2313 if (init && !sisusb->scrbuf) {
2315 tempbuf = vmalloc(8192);
2319 tempbufb = (u16 *)tempbuf;
2321 *(tempbufb++) = 0x0720;
2324 tempbufb = (u16 *)tempbuf;
2325 while (bootlogo[i]) {
2326 *(tempbufb++) = 0x0700 | bootlogo[i++];
2332 tempbufb = (u16 *)tempbuf + 6;
2333 while (bootstring[i])
2334 *(tempbufb++) = 0x0700 | bootstring[i++];
2336 ret |= sisusb_copy_memory(sisusb, tempbuf,
2337 sisusb->vrambase, 8192);
2343 } else if (sisusb->scrbuf) {
2344 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2345 sisusb->vrambase, sisusb->scrbuf_size);
2348 if (sisusb->sisusb_cursor_size_from >= 0 &&
2349 sisusb->sisusb_cursor_size_to >= 0) {
2350 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2351 sisusb->sisusb_cursor_size_from);
2352 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2353 sisusb->sisusb_cursor_size_to);
2355 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2356 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2357 sisusb->sisusb_cursor_size_to = -1;
2360 slot = sisusb->sisusb_cursor_loc;
2364 sisusb->sisusb_cursor_loc = -1;
2365 sisusb->bad_cursor_pos = 1;
2367 sisusb_set_cursor(sisusb, slot);
2369 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2370 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2372 sisusb->textmodedestroyed = 0;
2374 /* sisusb->lock is down */
2383 static int sisusb_open(struct inode *inode, struct file *file)
2385 struct sisusb_usb_data *sisusb;
2386 struct usb_interface *interface;
2387 int subminor = iminor(inode);
2389 interface = usb_find_interface(&sisusb_driver, subminor);
2393 sisusb = usb_get_intfdata(interface);
2397 mutex_lock(&sisusb->lock);
2399 if (!sisusb->present || !sisusb->ready) {
2400 mutex_unlock(&sisusb->lock);
2404 if (sisusb->isopen) {
2405 mutex_unlock(&sisusb->lock);
2409 if (!sisusb->devinit) {
2410 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2411 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2412 if (sisusb_init_gfxdevice(sisusb, 0)) {
2413 mutex_unlock(&sisusb->lock);
2414 dev_err(&sisusb->sisusb_dev->dev,
2415 "Failed to initialize device\n");
2419 mutex_unlock(&sisusb->lock);
2420 dev_err(&sisusb->sisusb_dev->dev,
2421 "Device not attached to USB 2.0 hub\n");
2426 /* Increment usage count for our sisusb */
2427 kref_get(&sisusb->kref);
2431 file->private_data = sisusb;
2433 mutex_unlock(&sisusb->lock);
2438 void sisusb_delete(struct kref *kref)
2440 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2445 usb_put_dev(sisusb->sisusb_dev);
2447 sisusb->sisusb_dev = NULL;
2448 sisusb_free_buffers(sisusb);
2449 sisusb_free_urbs(sisusb);
2450 #ifdef INCL_SISUSB_CON
2451 kfree(sisusb->SiS_Pr);
2456 static int sisusb_release(struct inode *inode, struct file *file)
2458 struct sisusb_usb_data *sisusb;
2460 sisusb = file->private_data;
2464 mutex_lock(&sisusb->lock);
2466 if (sisusb->present) {
2467 /* Wait for all URBs to finish if device still present */
2468 if (!sisusb_wait_all_out_complete(sisusb))
2469 sisusb_kill_all_busy(sisusb);
2473 file->private_data = NULL;
2475 mutex_unlock(&sisusb->lock);
2477 /* decrement the usage count on our device */
2478 kref_put(&sisusb->kref, sisusb_delete);
2483 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2484 size_t count, loff_t *ppos)
2486 struct sisusb_usb_data *sisusb;
2487 ssize_t bytes_read = 0;
2493 sisusb = file->private_data;
2497 mutex_lock(&sisusb->lock);
2500 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2501 mutex_unlock(&sisusb->lock);
2505 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2506 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2508 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2509 SISUSB_PCI_IOPORTBASE;
2512 * Byte, word and long(32) can be read. As this
2513 * emulates inX instructions, the data returned is
2514 * in machine-endianness.
2518 if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2521 else if (put_user(buf8, (u8 __user *)buffer))
2529 if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2532 else if (put_user(buf16, (u16 __user *)buffer))
2540 if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2543 else if (put_user(buf32, (u32 __user *)buffer))
2555 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2556 SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2558 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2562 * Remember: Data delivered is never endian-corrected
2564 errno = sisusb_read_mem_bulk(sisusb, address,
2565 NULL, count, buffer, &bytes_read);
2570 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2571 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2572 SISUSB_PCI_MMIOSIZE) {
2574 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2575 SISUSB_PCI_MMIOBASE;
2578 * Remember: Data delivered is never endian-corrected
2580 errno = sisusb_read_mem_bulk(sisusb, address,
2581 NULL, count, buffer, &bytes_read);
2586 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2587 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2590 mutex_unlock(&sisusb->lock);
2594 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2596 /* Read PCI config register
2597 * Return value delivered in machine endianness.
2599 if (sisusb_read_pci_config(sisusb, address, &buf32))
2601 else if (put_user(buf32, (u32 __user *)buffer))
2612 (*ppos) += bytes_read;
2614 mutex_unlock(&sisusb->lock);
2616 return errno ? errno : bytes_read;
2619 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2620 size_t count, loff_t *ppos)
2622 struct sisusb_usb_data *sisusb;
2624 ssize_t bytes_written = 0;
2629 sisusb = file->private_data;
2633 mutex_lock(&sisusb->lock);
2636 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2637 mutex_unlock(&sisusb->lock);
2641 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2642 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2644 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2645 SISUSB_PCI_IOPORTBASE;
2648 * Byte, word and long(32) can be written. As this
2649 * emulates outX instructions, the data is expected
2650 * in machine-endianness.
2654 if (get_user(buf8, (u8 __user *)buffer))
2656 else if (sisusb_write_memio_byte(sisusb,
2657 SISUSB_TYPE_IO, address, buf8))
2665 if (get_user(buf16, (u16 __user *)buffer))
2667 else if (sisusb_write_memio_word(sisusb,
2668 SISUSB_TYPE_IO, address, buf16))
2676 if (get_user(buf32, (u32 __user *)buffer))
2678 else if (sisusb_write_memio_long(sisusb,
2679 SISUSB_TYPE_IO, address, buf32))
2690 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2691 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE +
2694 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2698 * Buffer is copied 1:1, therefore, on big-endian
2699 * machines, the data must be swapped by userland
2700 * in advance (if applicable; no swapping in 8bpp
2701 * mode or if YUV data is being transferred).
2703 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2704 count, buffer, 0, &bytes_written);
2707 errno = bytes_written;
2709 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2710 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2711 SISUSB_PCI_MMIOSIZE) {
2713 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2714 SISUSB_PCI_MMIOBASE;
2717 * Buffer is copied 1:1, therefore, on big-endian
2718 * machines, the data must be swapped by userland
2721 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2722 count, buffer, 0, &bytes_written);
2725 errno = bytes_written;
2727 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2728 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2729 SISUSB_PCI_PCONFSIZE) {
2732 mutex_unlock(&sisusb->lock);
2736 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2738 /* Write PCI config register.
2739 * Given value expected in machine endianness.
2741 if (get_user(buf32, (u32 __user *)buffer))
2743 else if (sisusb_write_pci_config(sisusb, address, buf32))
2756 (*ppos) += bytes_written;
2758 mutex_unlock(&sisusb->lock);
2760 return errno ? errno : bytes_written;
2763 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2765 struct sisusb_usb_data *sisusb;
2768 sisusb = file->private_data;
2772 mutex_lock(&sisusb->lock);
2775 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2776 mutex_unlock(&sisusb->lock);
2780 ret = no_seek_end_llseek(file, offset, orig);
2782 mutex_unlock(&sisusb->lock);
2786 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2787 struct sisusb_command *y, unsigned long arg)
2789 int retval, port, length;
2792 /* All our commands require the device
2793 * to be initialized.
2795 if (!sisusb->devinit)
2799 SISUSB_PCI_PSEUDO_IOPORTBASE +
2800 SISUSB_PCI_IOPORTBASE;
2802 switch (y->operation) {
2804 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2806 if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2812 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2816 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2820 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2823 case SUCMD_SETANDOR:
2824 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2825 y->data1, y->data2);
2829 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2830 y->data1, y->data2);
2834 /* Gfx core must be initialized */
2835 if (!sisusb->gfxinit)
2838 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2839 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2841 retval = sisusb_clear_vram(sisusb, address, length);
2844 case SUCMD_HANDLETEXTMODE:
2846 #ifdef INCL_SISUSB_CON
2847 /* Gfx core must be initialized, SiS_Pr must exist */
2848 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2853 retval = sisusb_reset_text_mode(sisusb, 0);
2856 sisusb->textmodedestroyed = 1;
2862 #ifdef INCL_SISUSB_CON
2864 /* Gfx core must be initialized, SiS_Pr must exist */
2865 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2870 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2871 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2873 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2878 case SUCMD_SETVESAMODE:
2879 /* Gfx core must be initialized, SiS_Pr must exist */
2880 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2885 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2886 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2888 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2904 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2906 struct sisusb_usb_data *sisusb;
2907 struct sisusb_info x;
2908 struct sisusb_command y;
2910 u32 __user *argp = (u32 __user *)arg;
2912 sisusb = file->private_data;
2916 mutex_lock(&sisusb->lock);
2919 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2925 case SISUSB_GET_CONFIG_SIZE:
2927 if (put_user(sizeof(x), argp))
2932 case SISUSB_GET_CONFIG:
2934 x.sisusb_id = SISUSB_ID;
2935 x.sisusb_version = SISUSB_VERSION;
2936 x.sisusb_revision = SISUSB_REVISION;
2937 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2938 x.sisusb_gfxinit = sisusb->gfxinit;
2939 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2940 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2941 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2942 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2943 x.sisusb_vramsize = sisusb->vramsize;
2944 x.sisusb_minor = sisusb->minor;
2945 x.sisusb_fbdevactive = 0;
2946 #ifdef INCL_SISUSB_CON
2947 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
2949 x.sisusb_conactive = 0;
2951 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2953 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2958 case SISUSB_COMMAND:
2960 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2963 retval = sisusb_handle_command(sisusb, &y, arg);
2973 mutex_unlock(&sisusb->lock);
2977 #ifdef SISUSB_NEW_CONFIG_COMPAT
2978 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2982 case SISUSB_GET_CONFIG_SIZE:
2983 case SISUSB_GET_CONFIG:
2984 case SISUSB_COMMAND:
2985 return sisusb_ioctl(f, cmd, arg);
2988 return -ENOIOCTLCMD;
2993 static const struct file_operations usb_sisusb_fops = {
2994 .owner = THIS_MODULE,
2995 .open = sisusb_open,
2996 .release = sisusb_release,
2997 .read = sisusb_read,
2998 .write = sisusb_write,
2999 .llseek = sisusb_lseek,
3000 #ifdef SISUSB_NEW_CONFIG_COMPAT
3001 .compat_ioctl = sisusb_compat_ioctl,
3003 .unlocked_ioctl = sisusb_ioctl
3006 static struct usb_class_driver usb_sisusb_class = {
3007 .name = "sisusbvga%d",
3008 .fops = &usb_sisusb_fops,
3009 .minor_base = SISUSB_MINOR
3012 static int sisusb_probe(struct usb_interface *intf,
3013 const struct usb_device_id *id)
3015 struct usb_device *dev = interface_to_usbdev(intf);
3016 struct sisusb_usb_data *sisusb;
3019 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3022 /* Allocate memory for our private */
3023 sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3027 kref_init(&sisusb->kref);
3029 mutex_init(&(sisusb->lock));
3031 /* Register device */
3032 retval = usb_register_dev(intf, &usb_sisusb_class);
3034 dev_err(&sisusb->sisusb_dev->dev,
3035 "Failed to get a minor for device %d\n",
3041 sisusb->sisusb_dev = dev;
3042 sisusb->minor = intf->minor;
3043 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3044 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3045 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3046 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3047 /* Everything else is zero */
3049 /* Allocate buffers */
3050 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3051 sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3052 if (!sisusb->ibuf) {
3057 sisusb->numobufs = 0;
3058 sisusb->obufsize = SISUSB_OBUF_SIZE;
3059 for (i = 0; i < NUMOBUFS; i++) {
3060 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3061 if (!sisusb->obuf[i]) {
3072 sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3073 if (!sisusb->sisurbin) {
3077 sisusb->completein = 1;
3079 for (i = 0; i < sisusb->numobufs; i++) {
3080 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3081 if (!sisusb->sisurbout[i]) {
3085 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3086 sisusb->urbout_context[i].urbindex = i;
3087 sisusb->urbstatus[i] = 0;
3090 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3093 #ifdef INCL_SISUSB_CON
3094 /* Allocate our SiS_Pr */
3095 sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3096 if (!sisusb->SiS_Pr) {
3102 /* Do remaining init stuff */
3104 init_waitqueue_head(&sisusb->wait_q);
3106 usb_set_intfdata(intf, sisusb);
3108 usb_get_dev(sisusb->sisusb_dev);
3110 sisusb->present = 1;
3112 if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
3114 #ifdef INCL_SISUSB_CON
3115 if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3116 sisusb_first_vc <= sisusb_last_vc &&
3117 sisusb_last_vc <= MAX_NR_CONSOLES)
3120 if (sisusb_init_gfxdevice(sisusb, initscreen))
3121 dev_err(&sisusb->sisusb_dev->dev,
3122 "Failed to early initialize device\n");
3125 dev_info(&sisusb->sisusb_dev->dev,
3126 "Not attached to USB 2.0 hub, deferring init\n");
3130 #ifdef SISUSBENDIANTEST
3131 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3132 sisusb_testreadwrite(sisusb);
3133 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3136 #ifdef INCL_SISUSB_CON
3137 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3143 sisusb_free_urbs(sisusb);
3145 sisusb_free_buffers(sisusb);
3147 usb_deregister_dev(intf, &usb_sisusb_class);
3153 static void sisusb_disconnect(struct usb_interface *intf)
3155 struct sisusb_usb_data *sisusb;
3157 /* This should *not* happen */
3158 sisusb = usb_get_intfdata(intf);
3162 #ifdef INCL_SISUSB_CON
3163 sisusb_console_exit(sisusb);
3166 usb_deregister_dev(intf, &usb_sisusb_class);
3168 mutex_lock(&sisusb->lock);
3170 /* Wait for all URBs to complete and kill them in case (MUST do) */
3171 if (!sisusb_wait_all_out_complete(sisusb))
3172 sisusb_kill_all_busy(sisusb);
3174 usb_set_intfdata(intf, NULL);
3176 sisusb->present = 0;
3179 mutex_unlock(&sisusb->lock);
3181 /* decrement our usage count */
3182 kref_put(&sisusb->kref, sisusb_delete);
3185 static const struct usb_device_id sisusb_table[] = {
3186 { USB_DEVICE(0x0711, 0x0550) },
3187 { USB_DEVICE(0x0711, 0x0900) },
3188 { USB_DEVICE(0x0711, 0x0901) },
3189 { USB_DEVICE(0x0711, 0x0902) },
3190 { USB_DEVICE(0x0711, 0x0903) },
3191 { USB_DEVICE(0x0711, 0x0918) },
3192 { USB_DEVICE(0x0711, 0x0920) },
3193 { USB_DEVICE(0x0711, 0x0950) },
3194 { USB_DEVICE(0x0711, 0x5200) },
3195 { USB_DEVICE(0x182d, 0x021c) },
3196 { USB_DEVICE(0x182d, 0x0269) },
3200 MODULE_DEVICE_TABLE(usb, sisusb_table);
3202 static struct usb_driver sisusb_driver = {
3204 .probe = sisusb_probe,
3205 .disconnect = sisusb_disconnect,
3206 .id_table = sisusb_table,
3209 static int __init usb_sisusb_init(void)
3212 #ifdef INCL_SISUSB_CON
3213 sisusb_init_concode();
3216 return usb_register(&sisusb_driver);
3219 static void __exit usb_sisusb_exit(void)
3221 usb_deregister(&sisusb_driver);
3224 module_init(usb_sisusb_init);
3225 module_exit(usb_sisusb_exit);
3227 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3228 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3229 MODULE_LICENSE("GPL");