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 timeout */
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));
1006 dev_err(&sisusb->sisusb_dev->dev, "Wrote %zd of %d bytes, error %d\n",
1007 *bytes_written, length, ret);
1008 else if (msgcount == 500)
1009 dev_err(&sisusb->sisusb_dev->dev, "Too many errors, logging stopped\n");
1011 addr += (*bytes_written);
1012 length -= (*bytes_written);
1020 return ret ? -EIO : 0;
1023 /* Remember: Read data in packet is in machine-endianess! So for
1024 * byte, word, 24bit, long no endian correction is necessary.
1027 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1030 struct sisusb_packet packet;
1033 CLEARPACKET(&packet);
1034 packet.header = (1 << (addr & 3)) | (type << 6);
1035 packet.address = addr & ~3;
1036 ret = sisusb_send_packet(sisusb, 6, &packet);
1037 *data = (u8)(packet.data >> ((addr & 3) << 3));
1041 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
1042 u32 addr, u16 *data)
1044 struct sisusb_packet packet;
1047 CLEARPACKET(&packet);
1049 packet.address = addr & ~3;
1053 packet.header = (type << 6) | 0x0003;
1054 ret = sisusb_send_packet(sisusb, 6, &packet);
1055 *data = (u16)(packet.data);
1058 packet.header = (type << 6) | 0x0006;
1059 ret = sisusb_send_packet(sisusb, 6, &packet);
1060 *data = (u16)(packet.data >> 8);
1063 packet.header = (type << 6) | 0x000c;
1064 ret = sisusb_send_packet(sisusb, 6, &packet);
1065 *data = (u16)(packet.data >> 16);
1068 packet.header = (type << 6) | 0x0008;
1069 ret = sisusb_send_packet(sisusb, 6, &packet);
1070 *data = (u16)(packet.data >> 24);
1071 packet.header = (type << 6) | 0x0001;
1072 packet.address = (addr & ~3) + 4;
1073 ret |= sisusb_send_packet(sisusb, 6, &packet);
1074 *data |= (u16)(packet.data << 8);
1080 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1081 u32 addr, u32 *data)
1083 struct sisusb_packet packet;
1086 packet.address = addr & ~3;
1090 packet.header = (type << 6) | 0x0007;
1091 ret = sisusb_send_packet(sisusb, 6, &packet);
1092 *data = packet.data & 0x00ffffff;
1095 packet.header = (type << 6) | 0x000e;
1096 ret = sisusb_send_packet(sisusb, 6, &packet);
1097 *data = packet.data >> 8;
1100 packet.header = (type << 6) | 0x000c;
1101 ret = sisusb_send_packet(sisusb, 6, &packet);
1102 *data = packet.data >> 16;
1103 packet.header = (type << 6) | 0x0001;
1104 packet.address = (addr & ~3) + 4;
1105 ret |= sisusb_send_packet(sisusb, 6, &packet);
1106 *data |= ((packet.data & 0xff) << 16);
1109 packet.header = (type << 6) | 0x0008;
1110 ret = sisusb_send_packet(sisusb, 6, &packet);
1111 *data = packet.data >> 24;
1112 packet.header = (type << 6) | 0x0003;
1113 packet.address = (addr & ~3) + 4;
1114 ret |= sisusb_send_packet(sisusb, 6, &packet);
1115 *data |= ((packet.data & 0xffff) << 8);
1121 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1122 u32 addr, u32 *data)
1124 struct sisusb_packet packet;
1127 packet.address = addr & ~3;
1131 packet.header = (type << 6) | 0x000f;
1132 ret = sisusb_send_packet(sisusb, 6, &packet);
1133 *data = packet.data;
1136 packet.header = (type << 6) | 0x000e;
1137 ret = sisusb_send_packet(sisusb, 6, &packet);
1138 *data = packet.data >> 8;
1139 packet.header = (type << 6) | 0x0001;
1140 packet.address = (addr & ~3) + 4;
1141 ret |= sisusb_send_packet(sisusb, 6, &packet);
1142 *data |= (packet.data << 24);
1145 packet.header = (type << 6) | 0x000c;
1146 ret = sisusb_send_packet(sisusb, 6, &packet);
1147 *data = packet.data >> 16;
1148 packet.header = (type << 6) | 0x0003;
1149 packet.address = (addr & ~3) + 4;
1150 ret |= sisusb_send_packet(sisusb, 6, &packet);
1151 *data |= (packet.data << 16);
1154 packet.header = (type << 6) | 0x0008;
1155 ret = sisusb_send_packet(sisusb, 6, &packet);
1156 *data = packet.data >> 24;
1157 packet.header = (type << 6) | 0x0007;
1158 packet.address = (addr & ~3) + 4;
1159 ret |= sisusb_send_packet(sisusb, 6, &packet);
1160 *data |= (packet.data << 8);
1166 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1167 char *kernbuffer, int length,
1168 char __user *userbuffer, ssize_t *bytes_read)
1177 length &= 0x00ffffff;
1185 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1190 if (put_user(buf[0],
1191 (u8 __user *)userbuffer)) {
1195 kernbuffer[0] = buf[0];
1201 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1206 if (put_user(swap16,
1207 (u16 __user *)userbuffer))
1210 *((u16 *)kernbuffer) = swap16;
1216 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1221 buf[0] = (swap32 >> 16) & 0xff;
1222 buf[1] = (swap32 >> 8) & 0xff;
1223 buf[2] = swap32 & 0xff;
1225 buf[2] = (swap32 >> 16) & 0xff;
1226 buf[1] = (swap32 >> 8) & 0xff;
1227 buf[0] = swap32 & 0xff;
1230 if (copy_to_user(userbuffer, &buf[0], 3))
1233 kernbuffer[0] = buf[0];
1234 kernbuffer[1] = buf[1];
1235 kernbuffer[2] = buf[2];
1241 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1246 if (put_user(swap32,
1247 (u32 __user *)userbuffer))
1252 *((u32 *)kernbuffer) = swap32;
1267 /* High level: Gfx (indexed) register access */
1269 #ifdef INCL_SISUSB_CON
1271 sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1273 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1277 sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1279 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1284 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1287 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1288 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1293 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1296 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1297 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1302 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1308 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1309 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1312 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1317 sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1322 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1323 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1325 tmp |= (data & mask);
1326 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1331 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1333 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1337 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1339 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1342 /* Write/read video ram */
1344 #ifdef INCL_SISUSB_CON
1346 sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1348 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1352 sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1354 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1358 sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1359 u32 dest, int length, size_t *bytes_written)
1361 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1364 #ifdef SISUSBENDIANTEST
1366 sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1367 u32 src, int length, size_t *bytes_written)
1369 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1374 #ifdef SISUSBENDIANTEST
1376 sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1378 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1379 char destbuffer[10];
1383 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1385 for(i = 1; i <= 7; i++) {
1386 dev_dbg(&sisusb->sisusb_dev->dev, "sisusb: rwtest %d bytes\n", i);
1387 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1388 for(j = 0; j < i; j++) {
1389 dev_dbg(&sisusb->sisusb_dev->dev, "rwtest read[%d] = %x\n", j, destbuffer[j]);
1395 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1398 sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
1400 struct sisusb_packet packet;
1403 packet.header = 0x008f;
1404 packet.address = regnum | 0x10000;
1406 ret = sisusb_send_packet(sisusb, 10, &packet);
1411 sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
1413 struct sisusb_packet packet;
1416 packet.header = 0x008f;
1417 packet.address = (u32)regnum | 0x10000;
1418 ret = sisusb_send_packet(sisusb, 6, &packet);
1419 *data = packet.data;
1423 /* Clear video RAM */
1426 sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
1431 if (address < sisusb->vrambase)
1434 if (address >= sisusb->vrambase + sisusb->vramsize)
1437 if (address + length > sisusb->vrambase + sisusb->vramsize)
1438 length = sisusb->vrambase + sisusb->vramsize - address;
1443 /* allocate free buffer/urb and clear the buffer */
1444 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1447 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1449 /* We can write a length > buffer size here. The buffer
1450 * data will simply be re-used (like a ring-buffer).
1452 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1454 /* Free the buffer/urb */
1455 sisusb_free_outbuf(sisusb, i);
1460 /* Initialize the graphics core (return 0 on success)
1461 * This resets the graphics hardware and puts it into
1462 * a defined mode (640x480@60Hz)
1465 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1466 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1467 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1468 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1469 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1470 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1471 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1472 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1473 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1474 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1475 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1478 sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1483 ret = GETIREG(SISSR, 0x16, &tmp8);
1486 ret |= SETIREG(SISSR, 0x16, tmp8);
1488 ret |= SETIREG(SISSR, 0x16, tmp8);
1491 ret |= SETIREG(SISSR, 0x16, tmp8);
1493 ret |= SETIREG(SISSR, 0x16, tmp8);
1495 ret |= SETIREG(SISSR, 0x16, tmp8);
1497 ret |= SETIREG(SISSR, 0x16, tmp8);
1499 ret |= SETIREG(SISSR, 0x16, tmp8);
1501 ret |= SETIREG(SISSR, 0x16, tmp8);
1503 ret |= SETIREG(SISSR, 0x16, tmp8);
1509 sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
1512 u8 ramtype, done = 0;
1514 u32 ramptr = SISUSB_PCI_MEMBASE;
1516 ret = GETIREG(SISSR, 0x3a, &ramtype);
1519 ret |= SETIREG(SISSR, 0x13, 0x00);
1522 ret |= SETIREG(SISSR, 0x14, 0x12);
1523 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1525 ret |= SETIREG(SISSR, 0x14, 0x02);
1528 ret |= sisusb_triggersr16(sisusb, ramtype);
1529 ret |= WRITEL(ramptr + 0, 0x01234567);
1530 ret |= WRITEL(ramptr + 4, 0x456789ab);
1531 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1532 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1533 ret |= WRITEL(ramptr + 16, 0x55555555);
1534 ret |= WRITEL(ramptr + 20, 0x55555555);
1535 ret |= WRITEL(ramptr + 24, 0xffffffff);
1536 ret |= WRITEL(ramptr + 28, 0xffffffff);
1537 ret |= READL(ramptr + 0, &t0);
1538 ret |= READL(ramptr + 4, &t1);
1539 ret |= READL(ramptr + 8, &t2);
1540 ret |= READL(ramptr + 12, &t3);
1544 *chab = 0; *bw = 64;
1546 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1547 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1548 *chab = 0; *bw = 64;
1549 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1552 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1553 *chab = 1; *bw = 64;
1554 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
1556 ret |= sisusb_triggersr16(sisusb, ramtype);
1557 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1558 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1559 ret |= WRITEL(ramptr + 8, 0x55555555);
1560 ret |= WRITEL(ramptr + 12, 0x55555555);
1561 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1562 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1563 ret |= READL(ramptr + 4, &t1);
1565 if (t1 != 0xcdef0123) {
1567 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1573 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1577 if (t1 == 0x456789ab) {
1578 if (t0 == 0x01234567) {
1579 *chab = 0; *bw = 64;
1583 if (t0 == 0x01234567) {
1584 *chab = 0; *bw = 32;
1585 ret |= SETIREG(SISSR, 0x14, 0x00);
1591 ret |= SETIREG(SISSR, 0x14, 0x03);
1592 ret |= sisusb_triggersr16(sisusb, ramtype);
1594 ret |= WRITEL(ramptr + 0, 0x01234567);
1595 ret |= WRITEL(ramptr + 4, 0x456789ab);
1596 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1597 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1598 ret |= WRITEL(ramptr + 16, 0x55555555);
1599 ret |= WRITEL(ramptr + 20, 0x55555555);
1600 ret |= WRITEL(ramptr + 24, 0xffffffff);
1601 ret |= WRITEL(ramptr + 28, 0xffffffff);
1602 ret |= READL(ramptr + 0, &t0);
1603 ret |= READL(ramptr + 4, &t1);
1605 if (t1 == 0x456789ab) {
1606 if (t0 == 0x01234567) {
1607 *chab = 1; *bw = 64;
1611 if (t0 == 0x01234567) {
1612 *chab = 1; *bw = 32;
1613 ret |= SETIREG(SISSR, 0x14, 0x01);
1622 sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1625 u32 ramptr = SISUSB_PCI_MEMBASE;
1626 u8 tmp1, tmp2, i, j;
1628 ret |= WRITEB(ramptr, 0xaa);
1629 ret |= WRITEB(ramptr + 16, 0x55);
1630 ret |= READB(ramptr, &tmp1);
1631 ret |= READB(ramptr + 16, &tmp2);
1632 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1633 for (i = 0, j = 16; i < 2; i++, j += 16) {
1634 ret |= GETIREG(SISSR, 0x21, &tmp1);
1635 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1636 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1637 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1638 ret |= SETIREG(SISSR, 0x21, tmp1);
1639 ret |= WRITEB(ramptr + 16 + j, j);
1640 ret |= READB(ramptr + 16 + j, &tmp1);
1642 ret |= WRITEB(ramptr + j, j);
1651 sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
1652 u8 rankno, u8 chab, const u8 dramtype[][5],
1655 int ret = 0, ranksize;
1660 if ((rankno == 2) && (dramtype[index][0] == 2))
1663 ranksize = dramtype[index][3] / 2 * bw / 32;
1665 if ((ranksize * rankno) > 128)
1669 while ((ranksize >>= 1) > 0) tmp += 0x10;
1670 tmp |= ((rankno - 1) << 2);
1671 tmp |= ((bw / 64) & 0x02);
1672 tmp |= (chab & 0x01);
1674 ret = SETIREG(SISSR, 0x14, tmp);
1675 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1683 sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
1690 for (i = 0, j = 0; i < testn; i++) {
1691 ret |= WRITEL(sisusb->vrambase + j, j);
1695 for (i = 0, j = 0; i < testn; i++) {
1696 ret |= READL(sisusb->vrambase + j, &tmp);
1697 if (tmp != j) return ret;
1706 sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
1707 int idx, int bw, const u8 rtype[][5])
1709 int ret = 0, i, i2ret;
1714 for (i = rankno; i >= 1; i--) {
1715 inc = 1 << (rtype[idx][2] +
1719 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1724 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1725 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1729 inc = 1 << (10 + bw / 64);
1730 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1739 sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
1742 int ret = 0, i2ret = 0, i, j;
1743 static const u8 sdramtype[13][5] = {
1744 { 2, 12, 9, 64, 0x35 },
1745 { 1, 13, 9, 64, 0x44 },
1746 { 2, 12, 8, 32, 0x31 },
1747 { 2, 11, 9, 32, 0x25 },
1748 { 1, 12, 9, 32, 0x34 },
1749 { 1, 13, 8, 32, 0x40 },
1750 { 2, 11, 8, 16, 0x21 },
1751 { 1, 12, 8, 16, 0x30 },
1752 { 1, 11, 9, 16, 0x24 },
1753 { 1, 11, 8, 8, 0x20 },
1754 { 2, 9, 8, 4, 0x01 },
1755 { 1, 10, 8, 4, 0x10 },
1756 { 1, 9, 8, 2, 0x00 }
1759 *iret = 1; /* error */
1761 for (i = 0; i < 13; i++) {
1762 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1763 for (j = 2; j > 0; j--) {
1764 ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
1765 chab, sdramtype, bw);
1769 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
1772 *iret = 0; /* ram size found */
1782 sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
1786 int i, length, modex, modey, bpp;
1788 modex = 640; modey = 480; bpp = 2;
1790 address = sisusb->vrambase; /* Clear video ram */
1793 length = sisusb->vramsize;
1795 length = modex * bpp * modey;
1797 ret = sisusb_clear_vram(sisusb, address, length);
1799 if (!ret && drwfr) {
1800 for (i = 0; i < modex; i++) {
1801 address = sisusb->vrambase + (i * bpp);
1802 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1804 address += (modex * (modey-1) * bpp);
1805 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1808 for (i = 0; i < modey; i++) {
1809 address = sisusb->vrambase + ((i * modex) * bpp);
1810 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1812 address += ((modex - 1) * bpp);
1813 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1822 sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
1824 int ret = 0, i, j, modex, modey, bpp, du;
1825 u8 sr31, cr63, tmp8;
1826 static const char attrdata[] = {
1827 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1828 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1831 static const char crtcrdata[] = {
1832 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1833 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1834 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1837 static const char grcdata[] = {
1838 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1841 static const char crtcdata[] = {
1842 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1843 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1847 modex = 640; modey = 480; bpp = 2;
1849 GETIREG(SISSR, 0x31, &sr31);
1850 GETIREG(SISCR, 0x63, &cr63);
1851 SETIREGOR(SISSR, 0x01, 0x20);
1852 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1853 SETIREGOR(SISCR, 0x17, 0x80);
1854 SETIREGOR(SISSR, 0x1f, 0x04);
1855 SETIREGAND(SISSR, 0x07, 0xfb);
1856 SETIREG(SISSR, 0x00, 0x03); /* seq */
1857 SETIREG(SISSR, 0x01, 0x21);
1858 SETIREG(SISSR, 0x02, 0x0f);
1859 SETIREG(SISSR, 0x03, 0x00);
1860 SETIREG(SISSR, 0x04, 0x0e);
1861 SETREG(SISMISCW, 0x23); /* misc */
1862 for (i = 0; i <= 0x18; i++) { /* crtc */
1863 SETIREG(SISCR, i, crtcrdata[i]);
1865 for (i = 0; i <= 0x13; i++) { /* att */
1866 GETREG(SISINPSTAT, &tmp8);
1868 SETREG(SISAR, attrdata[i]);
1870 GETREG(SISINPSTAT, &tmp8);
1871 SETREG(SISAR, 0x14);
1872 SETREG(SISAR, 0x00);
1873 GETREG(SISINPSTAT, &tmp8);
1874 SETREG(SISAR, 0x20);
1875 GETREG(SISINPSTAT, &tmp8);
1876 for (i = 0; i <= 0x08; i++) { /* grc */
1877 SETIREG(SISGR, i, grcdata[i]);
1879 SETIREGAND(SISGR, 0x05, 0xbf);
1880 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1881 SETIREG(SISSR, i, 0x00);
1883 SETIREGAND(SISSR, 0x37, 0xfe);
1884 SETREG(SISMISCW, 0xef); /* sync */
1885 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1886 for (j = 0x00, i = 0; i <= 7; i++, j++) {
1887 SETIREG(SISCR, j, crtcdata[i]);
1889 for (j = 0x10; i <= 10; i++, j++) {
1890 SETIREG(SISCR, j, crtcdata[i]);
1892 for (j = 0x15; i <= 12; i++, j++) {
1893 SETIREG(SISCR, j, crtcdata[i]);
1895 for (j = 0x0A; i <= 15; i++, j++) {
1896 SETIREG(SISSR, j, crtcdata[i]);
1898 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1899 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1900 SETIREG(SISCR, 0x14, 0x4f);
1901 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1902 if (modex % 16) du += bpp;
1903 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1904 SETIREG(SISCR, 0x13, (du & 0xff));
1907 if (du & 0xff) tmp8++;
1908 SETIREG(SISSR, 0x10, tmp8);
1909 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1910 SETIREG(SISSR, 0x2b, 0x1b);
1911 SETIREG(SISSR, 0x2c, 0xe1);
1912 SETIREG(SISSR, 0x2d, 0x01);
1913 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1914 SETIREG(SISSR, 0x08, 0xae);
1915 SETIREGAND(SISSR, 0x09, 0xf0);
1916 SETIREG(SISSR, 0x08, 0x34);
1917 SETIREGOR(SISSR, 0x3d, 0x01);
1918 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1919 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1920 SETIREG(SISCR, 0x19, 0x00);
1921 SETIREGAND(SISCR, 0x1a, 0xfc);
1922 SETIREGAND(SISSR, 0x0f, 0xb7);
1923 SETIREGAND(SISSR, 0x31, 0xfb);
1924 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1925 SETIREGAND(SISSR, 0x32, 0xf3);
1926 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1927 SETIREG(SISCR, 0x52, 0x6c);
1929 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1930 SETIREG(SISCR, 0x0c, 0x00);
1931 SETIREG(SISSR, 0x0d, 0x00);
1932 SETIREGAND(SISSR, 0x37, 0xfe);
1934 SETIREG(SISCR, 0x32, 0x20);
1935 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1936 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1937 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1940 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1941 SETIREGOR(SISSR, 0x1e, 0x5a);
1943 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1944 SETIREG(SISSR, 0x27, 0x1f);
1945 SETIREG(SISSR, 0x26, 0x00);
1948 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1954 sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1956 int ret = 0, i, j, bw, chab, iret, retry = 3;
1959 static const char mclktable[] = {
1960 0x3b, 0x22, 0x01, 143,
1961 0x3b, 0x22, 0x01, 143,
1962 0x3b, 0x22, 0x01, 143,
1963 0x3b, 0x22, 0x01, 143
1965 static const char eclktable[] = {
1966 0x3b, 0x22, 0x01, 143,
1967 0x3b, 0x22, 0x01, 143,
1968 0x3b, 0x22, 0x01, 143,
1969 0x3b, 0x22, 0x01, 143
1971 static const char ramtypetable1[] = {
1972 0x00, 0x04, 0x60, 0x60,
1973 0x0f, 0x0f, 0x1f, 0x1f,
1974 0xba, 0xba, 0xba, 0xba,
1975 0xa9, 0xa9, 0xac, 0xac,
1976 0xa0, 0xa0, 0xa0, 0xa8,
1977 0x00, 0x00, 0x02, 0x02,
1978 0x30, 0x30, 0x40, 0x40
1980 static const char ramtypetable2[] = {
1981 0x77, 0x77, 0x44, 0x44,
1982 0x77, 0x77, 0x44, 0x44,
1983 0x00, 0x00, 0x00, 0x00,
1984 0x5b, 0x5b, 0xab, 0xab,
1985 0x00, 0x00, 0xf0, 0xf8
1991 ret = GETREG(SISVGAEN, &tmp8);
1992 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1994 /* Enable GPU access to VRAM */
1995 ret |= GETREG(SISMISCR, &tmp8);
1996 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
2000 /* Reset registers */
2001 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
2002 ret |= SETIREG(SISSR, 0x05, 0x86);
2003 ret |= SETIREGOR(SISSR, 0x20, 0x01);
2005 ret |= SETREG(SISMISCW, 0x67);
2007 for (i = 0x06; i <= 0x1f; i++) {
2008 ret |= SETIREG(SISSR, i, 0x00);
2010 for (i = 0x21; i <= 0x27; i++) {
2011 ret |= SETIREG(SISSR, i, 0x00);
2013 for (i = 0x31; i <= 0x3d; i++) {
2014 ret |= SETIREG(SISSR, i, 0x00);
2016 for (i = 0x12; i <= 0x1b; i++) {
2017 ret |= SETIREG(SISSR, i, 0x00);
2019 for (i = 0x79; i <= 0x7c; i++) {
2020 ret |= SETIREG(SISCR, i, 0x00);
2025 ret |= SETIREG(SISCR, 0x63, 0x80);
2027 ret |= GETIREG(SISSR, 0x3a, &ramtype);
2030 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
2031 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
2032 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
2034 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
2035 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
2036 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
2038 ret |= SETIREG(SISSR, 0x07, 0x18);
2039 ret |= SETIREG(SISSR, 0x11, 0x0f);
2043 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
2044 ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
2046 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
2047 ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
2050 ret |= SETIREG(SISCR, 0x49, 0xaa);
2052 ret |= SETIREG(SISSR, 0x1f, 0x00);
2053 ret |= SETIREG(SISSR, 0x20, 0xa0);
2054 ret |= SETIREG(SISSR, 0x23, 0xf6);
2055 ret |= SETIREG(SISSR, 0x24, 0x0d);
2056 ret |= SETIREG(SISSR, 0x25, 0x33);
2058 ret |= SETIREG(SISSR, 0x11, 0x0f);
2060 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
2062 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2066 ret |= SETIREG(SISPART1, 0x00, 0x00);
2068 ret |= GETIREG(SISSR, 0x13, &tmp8);
2071 ret |= SETIREG(SISPART1, 0x02, 0x00);
2072 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2074 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2075 tmp32 &= 0x00f00000;
2076 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2077 ret |= SETIREG(SISSR, 0x25, tmp8);
2078 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2079 ret |= SETIREG(SISCR, 0x49, tmp8);
2081 ret |= SETIREG(SISSR, 0x27, 0x1f);
2082 ret |= SETIREG(SISSR, 0x31, 0x00);
2083 ret |= SETIREG(SISSR, 0x32, 0x11);
2084 ret |= SETIREG(SISSR, 0x33, 0x00);
2088 ret |= SETIREG(SISCR, 0x83, 0x00);
2090 ret |= sisusb_set_default_mode(sisusb, 0);
2092 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2093 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2094 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2096 ret |= sisusb_triggersr16(sisusb, ramtype);
2098 /* Disable refresh */
2099 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2100 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2102 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2103 ret |= sisusb_verify_mclk(sisusb);
2106 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2108 dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n");
2109 ret |= SETIREG(SISSR,0x14,0x31);
2113 dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n");
2114 ret |= SETIREG(SISSR,0x14,0x31);
2118 /* Enable refresh */
2119 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2120 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2121 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2123 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2125 ret |= SETIREG(SISSR, 0x22, 0xfb);
2126 ret |= SETIREG(SISSR, 0x21, 0xa5);
2146 sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2148 u8 tmp8, tmp82, ramtype;
2150 char *ramtypetext1 = NULL;
2151 const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
2152 "DDR SDRAM", "DDR SGRAM" };
2153 static const int busSDR[4] = {64, 64, 128, 128};
2154 static const int busDDR[4] = {32, 32, 64, 64};
2155 static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2157 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2158 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2159 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2160 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2162 switch ((tmp8 >> 2) & 0x03) {
2163 case 0: ramtypetext1 = "1 ch/1 r";
2167 bw = busSDR[(tmp8 & 0x03)];
2170 case 1: ramtypetext1 = "1 ch/2 r";
2171 sisusb->vramsize <<= 1;
2172 bw = busSDR[(tmp8 & 0x03)];
2174 case 2: ramtypetext1 = "asymmeric";
2175 sisusb->vramsize += sisusb->vramsize/2;
2176 bw = busDDRA[(tmp8 & 0x03)];
2178 case 3: ramtypetext1 = "2 channel";
2179 sisusb->vramsize <<= 1;
2180 bw = busDDR[(tmp8 & 0x03)];
2184 dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %s, bus width %d\n", (sisusb->vramsize >> 20), ramtypetext1,
2185 ramtypetext2[ramtype], bw);
2189 sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2191 struct sisusb_packet packet;
2196 packet.header = 0x001f;
2197 packet.address = 0x00000324;
2198 packet.data = 0x00000004;
2199 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2201 packet.header = 0x001f;
2202 packet.address = 0x00000364;
2203 packet.data = 0x00000004;
2204 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2206 packet.header = 0x001f;
2207 packet.address = 0x00000384;
2208 packet.data = 0x00000004;
2209 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2211 packet.header = 0x001f;
2212 packet.address = 0x00000100;
2213 packet.data = 0x00000700;
2214 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2216 packet.header = 0x000f;
2217 packet.address = 0x00000004;
2218 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2219 packet.data |= 0x17;
2220 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2222 /* Init BAR 0 (VRAM) */
2223 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2224 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2225 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2227 tmp32 |= SISUSB_PCI_MEMBASE;
2228 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2230 /* Init BAR 1 (MMIO) */
2231 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2232 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2233 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2235 tmp32 |= SISUSB_PCI_MMIOBASE;
2236 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2238 /* Init BAR 2 (i/o ports) */
2239 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2240 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2241 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2243 tmp32 |= SISUSB_PCI_IOPORTBASE;
2244 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2246 /* Enable memory and i/o access */
2247 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2249 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2252 /* Some further magic */
2253 packet.header = 0x001f;
2254 packet.address = 0x00000050;
2255 packet.data = 0x000000ff;
2256 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2262 /* Initialize the graphics device (return 0 on success)
2263 * This initializes the net2280 as well as the PCI registers
2264 * of the graphics board.
2268 sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2270 int ret = 0, test = 0;
2273 if (sisusb->devinit == 1) {
2274 /* Read PCI BARs and see if they have been set up */
2275 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2276 if (ret) return ret;
2277 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2279 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2280 if (ret) return ret;
2281 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2283 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2284 if (ret) return ret;
2285 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2288 /* No? So reset the device */
2289 if ((sisusb->devinit == 0) || (test != 3)) {
2291 ret |= sisusb_do_init_gfxdevice(sisusb);
2294 sisusb->devinit = 1;
2298 if (sisusb->devinit) {
2299 /* Initialize the graphics core */
2300 if (sisusb_init_gfxcore(sisusb) == 0) {
2301 sisusb->gfxinit = 1;
2302 sisusb_get_ramconfig(sisusb);
2303 ret |= sisusb_set_default_mode(sisusb, 1);
2304 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2312 #ifdef INCL_SISUSB_CON
2314 /* Set up default text mode:
2315 - Set text mode (0x03)
2316 - Upload default font
2317 - Upload user font (if available)
2321 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2323 int ret = 0, slot = sisusb->font_slot, i;
2324 const struct font_desc *myfont;
2328 static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2329 static const char bootlogo[] = "(o_ //\\ V_/_";
2331 /* sisusb->lock is down */
2333 if (!sisusb->SiS_Pr)
2336 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2337 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2340 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2342 if (!(myfont = find_font("VGA8x16")))
2345 if (!(tempbuf = vmalloc(8192)))
2348 for (i = 0; i < 256; i++)
2349 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2351 /* Upload default font */
2352 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2356 /* Upload user font (and reset current slot) */
2357 if (sisusb->font_backup) {
2358 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2359 8192, sisusb->font_backup_512, 1, NULL,
2360 sisusb->font_backup_height, 0);
2362 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2366 if (init && !sisusb->scrbuf) {
2368 if ((tempbuf = vmalloc(8192))) {
2371 tempbufb = (u16 *)tempbuf;
2373 *(tempbufb++) = 0x0720;
2376 tempbufb = (u16 *)tempbuf;
2377 while (bootlogo[i]) {
2378 *(tempbufb++) = 0x0700 | bootlogo[i++];
2384 tempbufb = (u16 *)tempbuf + 6;
2385 while (bootstring[i])
2386 *(tempbufb++) = 0x0700 | bootstring[i++];
2388 ret |= sisusb_copy_memory(sisusb, tempbuf,
2389 sisusb->vrambase, 8192, &written);
2395 } else if (sisusb->scrbuf) {
2397 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2398 sisusb->vrambase, sisusb->scrbuf_size, &written);
2402 if (sisusb->sisusb_cursor_size_from >= 0 &&
2403 sisusb->sisusb_cursor_size_to >= 0) {
2404 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2405 sisusb->sisusb_cursor_size_from);
2406 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2407 sisusb->sisusb_cursor_size_to);
2409 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2410 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2411 sisusb->sisusb_cursor_size_to = -1;
2414 slot = sisusb->sisusb_cursor_loc;
2415 if(slot < 0) slot = 0;
2417 sisusb->sisusb_cursor_loc = -1;
2418 sisusb->bad_cursor_pos = 1;
2420 sisusb_set_cursor(sisusb, slot);
2422 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2423 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2425 sisusb->textmodedestroyed = 0;
2427 /* sisusb->lock is down */
2437 sisusb_open(struct inode *inode, struct file *file)
2439 struct sisusb_usb_data *sisusb;
2440 struct usb_interface *interface;
2441 int subminor = iminor(inode);
2443 if (!(interface = usb_find_interface(&sisusb_driver, subminor)))
2446 if (!(sisusb = usb_get_intfdata(interface)))
2449 mutex_lock(&sisusb->lock);
2451 if (!sisusb->present || !sisusb->ready) {
2452 mutex_unlock(&sisusb->lock);
2456 if (sisusb->isopen) {
2457 mutex_unlock(&sisusb->lock);
2461 if (!sisusb->devinit) {
2462 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2463 if (sisusb_init_gfxdevice(sisusb, 0)) {
2464 mutex_unlock(&sisusb->lock);
2465 dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
2469 mutex_unlock(&sisusb->lock);
2470 dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n");
2475 /* Increment usage count for our sisusb */
2476 kref_get(&sisusb->kref);
2480 file->private_data = sisusb;
2482 mutex_unlock(&sisusb->lock);
2488 sisusb_delete(struct kref *kref)
2490 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2495 if (sisusb->sisusb_dev)
2496 usb_put_dev(sisusb->sisusb_dev);
2498 sisusb->sisusb_dev = NULL;
2499 sisusb_free_buffers(sisusb);
2500 sisusb_free_urbs(sisusb);
2501 #ifdef INCL_SISUSB_CON
2502 kfree(sisusb->SiS_Pr);
2508 sisusb_release(struct inode *inode, struct file *file)
2510 struct sisusb_usb_data *sisusb;
2512 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2515 mutex_lock(&sisusb->lock);
2517 if (sisusb->present) {
2518 /* Wait for all URBs to finish if device still present */
2519 if (!sisusb_wait_all_out_complete(sisusb))
2520 sisusb_kill_all_busy(sisusb);
2524 file->private_data = NULL;
2526 mutex_unlock(&sisusb->lock);
2528 /* decrement the usage count on our device */
2529 kref_put(&sisusb->kref, sisusb_delete);
2535 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2537 struct sisusb_usb_data *sisusb;
2538 ssize_t bytes_read = 0;
2544 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2547 mutex_lock(&sisusb->lock);
2550 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2551 mutex_unlock(&sisusb->lock);
2555 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2556 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2559 SISUSB_PCI_PSEUDO_IOPORTBASE +
2560 SISUSB_PCI_IOPORTBASE;
2563 * Byte, word and long(32) can be read. As this
2564 * emulates inX instructions, the data returned is
2565 * in machine-endianness.
2570 if (sisusb_read_memio_byte(sisusb,
2574 else if (put_user(buf8, (u8 __user *)buffer))
2582 if (sisusb_read_memio_word(sisusb,
2586 else if (put_user(buf16, (u16 __user *)buffer))
2594 if (sisusb_read_memio_long(sisusb,
2598 else if (put_user(buf32, (u32 __user *)buffer))
2610 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2611 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2614 SISUSB_PCI_PSEUDO_MEMBASE +
2618 * Remember: Data delivered is never endian-corrected
2620 errno = sisusb_read_mem_bulk(sisusb, address,
2621 NULL, count, buffer, &bytes_read);
2626 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2627 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2630 SISUSB_PCI_PSEUDO_MMIOBASE +
2631 SISUSB_PCI_MMIOBASE;
2634 * Remember: Data delivered is never endian-corrected
2636 errno = sisusb_read_mem_bulk(sisusb, address,
2637 NULL, count, buffer, &bytes_read);
2642 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2643 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2646 mutex_unlock(&sisusb->lock);
2650 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2652 /* Read PCI config register
2653 * Return value delivered in machine endianness.
2655 if (sisusb_read_pci_config(sisusb, address, &buf32))
2657 else if (put_user(buf32, (u32 __user *)buffer))
2668 (*ppos) += bytes_read;
2670 mutex_unlock(&sisusb->lock);
2672 return errno ? errno : bytes_read;
2676 sisusb_write(struct file *file, const char __user *buffer, size_t count,
2679 struct sisusb_usb_data *sisusb;
2681 ssize_t bytes_written = 0;
2686 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2689 mutex_lock(&sisusb->lock);
2692 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2693 mutex_unlock(&sisusb->lock);
2697 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2698 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2701 SISUSB_PCI_PSEUDO_IOPORTBASE +
2702 SISUSB_PCI_IOPORTBASE;
2705 * Byte, word and long(32) can be written. As this
2706 * emulates outX instructions, the data is expected
2707 * in machine-endianness.
2712 if (get_user(buf8, (u8 __user *)buffer))
2714 else if (sisusb_write_memio_byte(sisusb,
2724 if (get_user(buf16, (u16 __user *)buffer))
2726 else if (sisusb_write_memio_word(sisusb,
2736 if (get_user(buf32, (u32 __user *)buffer))
2738 else if (sisusb_write_memio_long(sisusb,
2751 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2752 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2755 SISUSB_PCI_PSEUDO_MEMBASE +
2759 * Buffer is copied 1:1, therefore, on big-endian
2760 * machines, the data must be swapped by userland
2761 * in advance (if applicable; no swapping in 8bpp
2762 * mode or if YUV data is being transferred).
2764 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2765 count, buffer, 0, &bytes_written);
2768 errno = bytes_written;
2770 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2771 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2774 SISUSB_PCI_PSEUDO_MMIOBASE +
2775 SISUSB_PCI_MMIOBASE;
2778 * Buffer is copied 1:1, therefore, on big-endian
2779 * machines, the data must be swapped by userland
2782 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2783 count, buffer, 0, &bytes_written);
2786 errno = bytes_written;
2788 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2789 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2792 mutex_unlock(&sisusb->lock);
2796 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2798 /* Write PCI config register.
2799 * Given value expected in machine endianness.
2801 if (get_user(buf32, (u32 __user *)buffer))
2803 else if (sisusb_write_pci_config(sisusb, address, buf32))
2816 (*ppos) += bytes_written;
2818 mutex_unlock(&sisusb->lock);
2820 return errno ? errno : bytes_written;
2824 sisusb_lseek(struct file *file, loff_t offset, int orig)
2826 struct sisusb_usb_data *sisusb;
2829 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2832 mutex_lock(&sisusb->lock);
2835 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2836 mutex_unlock(&sisusb->lock);
2842 file->f_pos = offset;
2844 /* never negative, no force_successful_syscall needed */
2847 file->f_pos += offset;
2849 /* never negative, no force_successful_syscall needed */
2852 /* seeking relative to "end of file" is not supported */
2856 mutex_unlock(&sisusb->lock);
2861 sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2864 int retval, port, length;
2867 /* All our commands require the device
2868 * to be initialized.
2870 if (!sisusb->devinit)
2874 SISUSB_PCI_PSEUDO_IOPORTBASE +
2875 SISUSB_PCI_IOPORTBASE;
2877 switch (y->operation) {
2879 retval = sisusb_getidxreg(sisusb, port,
2880 y->data0, &y->data1);
2882 if (copy_to_user((void __user *)arg, y,
2889 retval = sisusb_setidxreg(sisusb, port,
2890 y->data0, y->data1);
2894 retval = sisusb_setidxregor(sisusb, port,
2895 y->data0, y->data1);
2899 retval = sisusb_setidxregand(sisusb, port,
2900 y->data0, y->data1);
2903 case SUCMD_SETANDOR:
2904 retval = sisusb_setidxregandor(sisusb, port,
2905 y->data0, y->data1, y->data2);
2909 retval = sisusb_setidxregmask(sisusb, port,
2910 y->data0, y->data1, y->data2);
2914 /* Gfx core must be initialized */
2915 if (!sisusb->gfxinit)
2918 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2919 address = y->data3 -
2920 SISUSB_PCI_PSEUDO_MEMBASE +
2922 retval = sisusb_clear_vram(sisusb, address, length);
2925 case SUCMD_HANDLETEXTMODE:
2927 #ifdef INCL_SISUSB_CON
2928 /* Gfx core must be initialized, SiS_Pr must exist */
2929 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2934 retval = sisusb_reset_text_mode(sisusb, 0);
2937 sisusb->textmodedestroyed = 1;
2943 #ifdef INCL_SISUSB_CON
2945 /* Gfx core must be initialized, SiS_Pr must exist */
2946 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2951 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2952 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2954 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2959 case SUCMD_SETVESAMODE:
2960 /* Gfx core must be initialized, SiS_Pr must exist */
2961 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2966 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2967 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2969 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2986 sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2988 struct sisusb_usb_data *sisusb;
2989 struct sisusb_info x;
2990 struct sisusb_command y;
2992 u32 __user *argp = (u32 __user *)arg;
2994 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2998 mutex_lock(&sisusb->lock);
3001 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
3008 case SISUSB_GET_CONFIG_SIZE:
3010 if (put_user(sizeof(x), argp))
3015 case SISUSB_GET_CONFIG:
3017 x.sisusb_id = SISUSB_ID;
3018 x.sisusb_version = SISUSB_VERSION;
3019 x.sisusb_revision = SISUSB_REVISION;
3020 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3021 x.sisusb_gfxinit = sisusb->gfxinit;
3022 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
3023 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
3024 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
3025 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
3026 x.sisusb_vramsize = sisusb->vramsize;
3027 x.sisusb_minor = sisusb->minor;
3028 x.sisusb_fbdevactive= 0;
3029 #ifdef INCL_SISUSB_CON
3030 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3032 x.sisusb_conactive = 0;
3035 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3040 case SISUSB_COMMAND:
3042 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3045 retval = sisusb_handle_command(sisusb, &y, arg);
3055 mutex_unlock(&sisusb->lock);
3060 #ifdef SISUSB_NEW_CONFIG_COMPAT
3062 sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3067 case SISUSB_GET_CONFIG_SIZE:
3068 case SISUSB_GET_CONFIG:
3069 case SISUSB_COMMAND:
3070 retval = sisusb_ioctl(f, cmd, arg);
3074 return -ENOIOCTLCMD;
3079 static const struct file_operations usb_sisusb_fops = {
3080 .owner = THIS_MODULE,
3081 .open = sisusb_open,
3082 .release = sisusb_release,
3083 .read = sisusb_read,
3084 .write = sisusb_write,
3085 .llseek = sisusb_lseek,
3086 #ifdef SISUSB_NEW_CONFIG_COMPAT
3087 .compat_ioctl = sisusb_compat_ioctl,
3089 .unlocked_ioctl = sisusb_ioctl
3092 static struct usb_class_driver usb_sisusb_class = {
3093 .name = "sisusbvga%d",
3094 .fops = &usb_sisusb_fops,
3095 .minor_base = SISUSB_MINOR
3098 static int sisusb_probe(struct usb_interface *intf,
3099 const struct usb_device_id *id)
3101 struct usb_device *dev = interface_to_usbdev(intf);
3102 struct sisusb_usb_data *sisusb;
3105 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3108 /* Allocate memory for our private */
3109 if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3110 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n");
3113 kref_init(&sisusb->kref);
3115 mutex_init(&(sisusb->lock));
3117 /* Register device */
3118 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3119 dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n",
3125 sisusb->sisusb_dev = dev;
3126 sisusb->minor = intf->minor;
3127 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3128 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3129 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3130 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3131 /* Everything else is zero */
3133 /* Allocate buffers */
3134 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3135 if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3136 GFP_KERNEL, &sisusb->transfer_dma_in))) {
3137 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer");
3142 sisusb->numobufs = 0;
3143 sisusb->obufsize = SISUSB_OBUF_SIZE;
3144 for (i = 0; i < NUMOBUFS; i++) {
3145 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3147 &sisusb->transfer_dma_out[i]))) {
3149 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n");
3160 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3161 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3165 sisusb->completein = 1;
3167 for (i = 0; i < sisusb->numobufs; i++) {
3168 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3169 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3173 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3174 sisusb->urbout_context[i].urbindex = i;
3175 sisusb->urbstatus[i] = 0;
3178 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs);
3180 #ifdef INCL_SISUSB_CON
3181 /* Allocate our SiS_Pr */
3182 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3183 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n");
3187 /* Do remaining init stuff */
3189 init_waitqueue_head(&sisusb->wait_q);
3191 usb_set_intfdata(intf, sisusb);
3193 usb_get_dev(sisusb->sisusb_dev);
3195 sisusb->present = 1;
3197 if (dev->speed == USB_SPEED_HIGH) {
3199 #ifdef INCL_SISUSB_CON
3200 if (sisusb_first_vc > 0 &&
3201 sisusb_last_vc > 0 &&
3202 sisusb_first_vc <= sisusb_last_vc &&
3203 sisusb_last_vc <= MAX_NR_CONSOLES)
3206 if (sisusb_init_gfxdevice(sisusb, initscreen))
3207 dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n");
3210 dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n");
3214 #ifdef SISUSBENDIANTEST
3215 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3216 sisusb_testreadwrite(sisusb);
3217 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3220 #ifdef INCL_SISUSB_CON
3221 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3227 sisusb_free_urbs(sisusb);
3229 sisusb_free_buffers(sisusb);
3231 usb_deregister_dev(intf, &usb_sisusb_class);
3237 static void sisusb_disconnect(struct usb_interface *intf)
3239 struct sisusb_usb_data *sisusb;
3241 /* This should *not* happen */
3242 if (!(sisusb = usb_get_intfdata(intf)))
3245 #ifdef INCL_SISUSB_CON
3246 sisusb_console_exit(sisusb);
3249 usb_deregister_dev(intf, &usb_sisusb_class);
3251 mutex_lock(&sisusb->lock);
3253 /* Wait for all URBs to complete and kill them in case (MUST do) */
3254 if (!sisusb_wait_all_out_complete(sisusb))
3255 sisusb_kill_all_busy(sisusb);
3257 usb_set_intfdata(intf, NULL);
3259 sisusb->present = 0;
3262 mutex_unlock(&sisusb->lock);
3264 /* decrement our usage count */
3265 kref_put(&sisusb->kref, sisusb_delete);
3268 static struct usb_device_id sisusb_table [] = {
3269 { USB_DEVICE(0x0711, 0x0550) },
3270 { USB_DEVICE(0x0711, 0x0900) },
3271 { USB_DEVICE(0x0711, 0x0901) },
3272 { USB_DEVICE(0x0711, 0x0902) },
3273 { USB_DEVICE(0x0711, 0x0918) },
3274 { USB_DEVICE(0x182d, 0x021c) },
3275 { USB_DEVICE(0x182d, 0x0269) },
3279 MODULE_DEVICE_TABLE (usb, sisusb_table);
3281 static struct usb_driver sisusb_driver = {
3283 .probe = sisusb_probe,
3284 .disconnect = sisusb_disconnect,
3285 .id_table = sisusb_table,
3288 static int __init usb_sisusb_init(void)
3291 #ifdef INCL_SISUSB_CON
3292 sisusb_init_concode();
3295 return usb_register(&sisusb_driver);
3298 static void __exit usb_sisusb_exit(void)
3300 usb_deregister(&sisusb_driver);
3303 module_init(usb_sisusb_init);
3304 module_exit(usb_sisusb_exit);
3306 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3307 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3308 MODULE_LICENSE("GPL");