1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
3 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
7 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
9 * If distributed as part of the Linux kernel, this code is licensed under the
10 * terms of the GPL v2.
12 * Otherwise, the following license terms apply:
14 * * Redistribution and use in source and binary forms, with or without
15 * * modification, are permitted provided that the following conditions
17 * * 1) Redistributions of source code must retain the above copyright
18 * * notice, this list of conditions and the following disclaimer.
19 * * 2) Redistributions in binary form must reproduce the above copyright
20 * * notice, this list of conditions and the following disclaimer in the
21 * * documentation and/or other materials provided with the distribution.
22 * * 3) The name of the author may not be used to endorse or promote products
23 * * derived from this software without specific psisusbr written permission.
25 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
26 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <linux/mutex.h>
41 #include <linux/module.h>
42 #include <linux/kernel.h>
43 #include <linux/signal.h>
44 #include <linux/errno.h>
45 #include <linux/poll.h>
46 #include <linux/init.h>
47 #include <linux/slab.h>
48 #include <linux/spinlock.h>
49 #include <linux/kref.h>
50 #include <linux/usb.h>
51 #include <linux/vmalloc.h>
55 #define SISUSB_DONTSYNC
57 /* Forward declarations / clean-up routines */
59 static struct usb_driver sisusb_driver;
61 static void sisusb_free_buffers(struct sisusb_usb_data *sisusb)
65 for (i = 0; i < NUMOBUFS; i++) {
66 kfree(sisusb->obuf[i]);
67 sisusb->obuf[i] = NULL;
73 static void sisusb_free_urbs(struct sisusb_usb_data *sisusb)
77 for (i = 0; i < NUMOBUFS; i++) {
78 usb_free_urb(sisusb->sisurbout[i]);
79 sisusb->sisurbout[i] = NULL;
81 usb_free_urb(sisusb->sisurbin);
82 sisusb->sisurbin = NULL;
85 /* Level 0: USB transport layer */
89 /* out-urb management */
91 /* Return 1 if all free, 0 otherwise */
92 static int sisusb_all_free(struct sisusb_usb_data *sisusb)
96 for (i = 0; i < sisusb->numobufs; i++) {
98 if (sisusb->urbstatus[i] & SU_URB_BUSY)
106 /* Kill all busy URBs */
107 static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
111 if (sisusb_all_free(sisusb))
114 for (i = 0; i < sisusb->numobufs; i++) {
116 if (sisusb->urbstatus[i] & SU_URB_BUSY)
117 usb_kill_urb(sisusb->sisurbout[i]);
122 /* Return 1 if ok, 0 if error (not all complete within timeout) */
123 static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
125 int timeout = 5 * HZ, i = 1;
127 wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)),
133 static int sisusb_outurb_available(struct sisusb_usb_data *sisusb)
137 for (i = 0; i < sisusb->numobufs; i++) {
139 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
147 static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
149 int i, timeout = 5 * HZ;
151 wait_event_timeout(sisusb->wait_q,
152 ((i = sisusb_outurb_available(sisusb)) >= 0), timeout);
157 static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
161 i = sisusb_outurb_available(sisusb);
164 sisusb->urbstatus[i] |= SU_URB_ALLOC;
169 static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
171 if ((index >= 0) && (index < sisusb->numobufs))
172 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
175 /* completion callback */
177 static void sisusb_bulk_completeout(struct urb *urb)
179 struct sisusb_urb_context *context = urb->context;
180 struct sisusb_usb_data *sisusb;
185 sisusb = context->sisusb;
187 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
190 #ifndef SISUSB_DONTSYNC
191 if (context->actual_length)
192 *(context->actual_length) += urb->actual_length;
195 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
196 wake_up(&sisusb->wait_q);
199 static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index,
200 unsigned int pipe, void *data, int len, int *actual_length,
201 int timeout, unsigned int tflags)
203 struct urb *urb = sisusb->sisurbout[index];
204 int retval, byteswritten = 0;
207 urb->transfer_flags = 0;
209 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
210 sisusb_bulk_completeout,
211 &sisusb->urbout_context[index]);
213 urb->transfer_flags |= tflags;
214 urb->actual_length = 0;
217 sisusb->urbout_context[index].actual_length = (timeout) ?
218 NULL : actual_length;
220 /* Declare this urb/buffer in use */
221 sisusb->urbstatus[index] |= SU_URB_BUSY;
224 retval = usb_submit_urb(urb, GFP_KERNEL);
226 /* If OK, and if timeout > 0, wait for completion */
227 if ((retval == 0) && timeout) {
228 wait_event_timeout(sisusb->wait_q,
229 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
231 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
232 /* URB timed out... kill it and report error */
236 /* Otherwise, report urb status */
237 retval = urb->status;
238 byteswritten = urb->actual_length;
243 *actual_length = byteswritten;
250 /* completion callback */
252 static void sisusb_bulk_completein(struct urb *urb)
254 struct sisusb_usb_data *sisusb = urb->context;
256 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
259 sisusb->completein = 1;
260 wake_up(&sisusb->wait_q);
263 static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb,
264 unsigned int pipe, void *data, int len,
265 int *actual_length, int timeout, unsigned int tflags)
267 struct urb *urb = sisusb->sisurbin;
268 int retval, readbytes = 0;
270 urb->transfer_flags = 0;
272 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
273 sisusb_bulk_completein, sisusb);
275 urb->transfer_flags |= tflags;
276 urb->actual_length = 0;
278 sisusb->completein = 0;
279 retval = usb_submit_urb(urb, GFP_KERNEL);
281 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
282 if (!sisusb->completein) {
283 /* URB timed out... kill it and report error */
287 /* URB completed within timeout */
288 retval = urb->status;
289 readbytes = urb->actual_length;
294 *actual_length = readbytes;
302 /* Send a bulk message of variable size
304 * To copy the data from userspace, give pointer to "userbuffer",
305 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
306 * both of these are NULL, it is assumed, that the transfer
307 * buffer "sisusb->obuf[index]" is set up with the data to send.
308 * Index is ignored if either kernbuffer or userbuffer is set.
309 * If async is nonzero, URBs will be sent without waiting for
310 * completion of the previous URB.
312 * (return 0 on success)
315 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
316 char *kernbuffer, const char __user *userbuffer, int index,
317 ssize_t *bytes_written, unsigned int tflags, int async)
319 int result = 0, retry, count = len;
320 int passsize, thispass, transferred_len = 0;
321 int fromuser = (userbuffer != NULL) ? 1 : 0;
322 int fromkern = (kernbuffer != NULL) ? 1 : 0;
326 (*bytes_written) = 0;
329 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
332 /* If we copy data from kernel or userspace, force the
333 * allocation of a buffer/urb. If we have the data in
334 * the transfer buffer[index] already, reuse the buffer/URB
335 * if the length is > buffer size. (So, transmitting
336 * large data amounts directly from the transfer buffer
337 * treats the buffer as a ring buffer. However, we need
338 * to sync in this case.)
340 if (fromuser || fromkern)
342 else if (len > sisusb->obufsize)
345 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
348 passsize = thispass = (sisusb->obufsize < count) ?
349 sisusb->obufsize : count;
352 index = sisusb_get_free_outbuf(sisusb);
357 buffer = sisusb->obuf[index];
361 if (copy_from_user(buffer, userbuffer, passsize))
364 userbuffer += passsize;
366 } else if (fromkern) {
368 memcpy(buffer, kernbuffer, passsize);
369 kernbuffer += passsize;
376 if (!sisusb->sisusb_dev)
379 result = sisusb_bulkout_msg(sisusb, index, pipe,
380 buffer, thispass, &transferred_len,
381 async ? 0 : 5 * HZ, tflags);
383 if (result == -ETIMEDOUT) {
385 /* Will not happen if async */
392 if ((result == 0) && !async && transferred_len) {
394 thispass -= transferred_len;
395 buffer += transferred_len;
404 (*bytes_written) += passsize;
407 /* Force new allocation in next iteration */
408 if (fromuser || fromkern)
414 #ifdef SISUSB_DONTSYNC
415 (*bytes_written) = len;
416 /* Some URBs/buffers might be busy */
418 sisusb_wait_all_out_complete(sisusb);
419 (*bytes_written) = transferred_len;
420 /* All URBs and all buffers are available */
424 return ((*bytes_written) == len) ? 0 : -EIO;
427 /* Receive a bulk message of variable size
429 * To copy the data to userspace, give pointer to "userbuffer",
430 * to copy to kernel memory, give "kernbuffer". One of them
431 * MUST be set. (There is no technique for letting the caller
432 * read directly from the ibuf.)
436 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
437 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
440 int result = 0, retry, count = len;
441 int bufsize, thispass, transferred_len;
448 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
451 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
452 buffer = sisusb->ibuf;
453 bufsize = sisusb->ibufsize;
457 #ifdef SISUSB_DONTSYNC
458 if (!(sisusb_wait_all_out_complete(sisusb)))
464 if (!sisusb->sisusb_dev)
467 thispass = (bufsize < count) ? bufsize : count;
469 result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass,
470 &transferred_len, 5 * HZ, tflags);
473 thispass = transferred_len;
475 else if (result == -ETIMEDOUT) {
488 (*bytes_read) += thispass;
493 if (copy_to_user(userbuffer, buffer, thispass))
496 userbuffer += thispass;
500 memcpy(kernbuffer, buffer, thispass);
501 kernbuffer += thispass;
509 return ((*bytes_read) == len) ? 0 : -EIO;
512 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
513 struct sisusb_packet *packet)
516 ssize_t bytes_transferred = 0;
522 #ifdef SISUSB_DONTSYNC
523 if (!(sisusb_wait_all_out_complete(sisusb)))
527 /* Eventually correct endianness */
528 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
530 /* 1. send the packet */
531 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
532 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
534 if ((ret == 0) && (len == 6)) {
536 /* 2. if packet len == 6, it means we read, so wait for 32bit
537 * return value and write it to packet->data
539 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
540 (char *)&tmp, NULL, &bytes_transferred, 0);
542 packet->data = le32_to_cpu(tmp);
548 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
549 struct sisusb_packet *packet, unsigned int tflags)
552 ssize_t bytes_transferred = 0;
558 #ifdef SISUSB_DONTSYNC
559 if (!(sisusb_wait_all_out_complete(sisusb)))
563 /* Eventually correct endianness */
564 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
566 /* 1. send the packet */
567 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
568 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
570 if ((ret == 0) && (len == 6)) {
572 /* 2. if packet len == 6, it means we read, so wait for 32bit
573 * return value and write it to packet->data
575 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
576 (char *)&tmp, NULL, &bytes_transferred, 0);
578 packet->data = le32_to_cpu(tmp);
584 /* access video memory and mmio (return 0 on success) */
588 /* The following routines assume being used to transfer byte, word,
591 * - the write routines expect "data" in machine endianness format.
592 * The data will be converted to leXX in sisusb_xxx_packet.
593 * - the read routines can expect read data in machine-endianess.
596 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
599 struct sisusb_packet packet;
601 packet.header = (1 << (addr & 3)) | (type << 6);
602 packet.address = addr & ~3;
603 packet.data = data << ((addr & 3) << 3);
604 return sisusb_send_packet(sisusb, 10, &packet);
607 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
610 struct sisusb_packet packet;
613 packet.address = addr & ~3;
617 packet.header = (type << 6) | 0x0003;
618 packet.data = (u32)data;
619 ret = sisusb_send_packet(sisusb, 10, &packet);
622 packet.header = (type << 6) | 0x0006;
623 packet.data = (u32)data << 8;
624 ret = sisusb_send_packet(sisusb, 10, &packet);
627 packet.header = (type << 6) | 0x000c;
628 packet.data = (u32)data << 16;
629 ret = sisusb_send_packet(sisusb, 10, &packet);
632 packet.header = (type << 6) | 0x0008;
633 packet.data = (u32)data << 24;
634 ret = sisusb_send_packet(sisusb, 10, &packet);
635 packet.header = (type << 6) | 0x0001;
636 packet.address = (addr & ~3) + 4;
637 packet.data = (u32)data >> 8;
638 ret |= sisusb_send_packet(sisusb, 10, &packet);
644 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
647 struct sisusb_packet packet;
650 packet.address = addr & ~3;
654 packet.header = (type << 6) | 0x0007;
655 packet.data = data & 0x00ffffff;
656 ret = sisusb_send_packet(sisusb, 10, &packet);
659 packet.header = (type << 6) | 0x000e;
660 packet.data = data << 8;
661 ret = sisusb_send_packet(sisusb, 10, &packet);
664 packet.header = (type << 6) | 0x000c;
665 packet.data = data << 16;
666 ret = sisusb_send_packet(sisusb, 10, &packet);
667 packet.header = (type << 6) | 0x0001;
668 packet.address = (addr & ~3) + 4;
669 packet.data = (data >> 16) & 0x00ff;
670 ret |= sisusb_send_packet(sisusb, 10, &packet);
673 packet.header = (type << 6) | 0x0008;
674 packet.data = data << 24;
675 ret = sisusb_send_packet(sisusb, 10, &packet);
676 packet.header = (type << 6) | 0x0003;
677 packet.address = (addr & ~3) + 4;
678 packet.data = (data >> 8) & 0xffff;
679 ret |= sisusb_send_packet(sisusb, 10, &packet);
685 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
688 struct sisusb_packet packet;
691 packet.address = addr & ~3;
695 packet.header = (type << 6) | 0x000f;
697 ret = sisusb_send_packet(sisusb, 10, &packet);
700 packet.header = (type << 6) | 0x000e;
701 packet.data = data << 8;
702 ret = sisusb_send_packet(sisusb, 10, &packet);
703 packet.header = (type << 6) | 0x0001;
704 packet.address = (addr & ~3) + 4;
705 packet.data = data >> 24;
706 ret |= sisusb_send_packet(sisusb, 10, &packet);
709 packet.header = (type << 6) | 0x000c;
710 packet.data = data << 16;
711 ret = sisusb_send_packet(sisusb, 10, &packet);
712 packet.header = (type << 6) | 0x0003;
713 packet.address = (addr & ~3) + 4;
714 packet.data = data >> 16;
715 ret |= sisusb_send_packet(sisusb, 10, &packet);
718 packet.header = (type << 6) | 0x0008;
719 packet.data = data << 24;
720 ret = sisusb_send_packet(sisusb, 10, &packet);
721 packet.header = (type << 6) | 0x0007;
722 packet.address = (addr & ~3) + 4;
723 packet.data = data >> 8;
724 ret |= sisusb_send_packet(sisusb, 10, &packet);
730 /* The xxx_bulk routines copy a buffer of variable size. They treat the
731 * buffer as chars, therefore lsb/msb has to be corrected if using the
732 * byte/word/long/etc routines for speed-up
734 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
735 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
736 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
737 * that the data already is in the transfer buffer "sisusb->obuf[index]".
740 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
741 char *kernbuffer, int length, const char __user *userbuffer,
742 int index, ssize_t *bytes_written)
744 struct sisusb_packet packet;
747 u8 swap8, fromkern = kernbuffer ? 1 : 0;
749 u32 swap32, flag = (length >> 28) & 1;
752 /* if neither kernbuffer not userbuffer are given, assume
755 if (!fromkern && !userbuffer)
756 kernbuffer = sisusb->obuf[index];
758 (*bytes_written = 0);
760 length &= 0x00ffffff;
766 if (get_user(swap8, (u8 __user *)userbuffer))
769 swap8 = kernbuffer[0];
771 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
781 if (get_user(swap16, (u16 __user *)userbuffer))
784 swap16 = *((u16 *)kernbuffer);
786 ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
790 (*bytes_written) += 2;
796 if (copy_from_user(&buf, userbuffer, 3))
799 swap32 = (buf[0] << 16) |
803 swap32 = (buf[2] << 16) |
809 swap32 = (kernbuffer[0] << 16) |
810 (kernbuffer[1] << 8) |
813 swap32 = (kernbuffer[2] << 16) |
814 (kernbuffer[1] << 8) |
818 ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
822 (*bytes_written) += 3;
828 if (get_user(swap32, (u32 __user *)userbuffer))
831 swap32 = *((u32 *)kernbuffer);
833 ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
836 (*bytes_written) += 4;
841 if ((length & ~3) > 0x10000) {
843 packet.header = 0x001f;
844 packet.address = 0x000001d4;
846 ret = sisusb_send_bridge_packet(sisusb, 10,
848 packet.header = 0x001f;
849 packet.address = 0x000001d0;
850 packet.data = (length & ~3);
851 ret |= sisusb_send_bridge_packet(sisusb, 10,
853 packet.header = 0x001f;
854 packet.address = 0x000001c0;
855 packet.data = flag | 0x16;
856 ret |= sisusb_send_bridge_packet(sisusb, 10,
859 ret |= sisusb_send_bulk_msg(sisusb,
860 SISUSB_EP_GFX_LBULK_OUT,
863 bytes_written, 0, 1);
864 userbuffer += (*bytes_written);
865 } else if (fromkern) {
866 ret |= sisusb_send_bulk_msg(sisusb,
867 SISUSB_EP_GFX_LBULK_OUT,
870 bytes_written, 0, 1);
871 kernbuffer += (*bytes_written);
873 ret |= sisusb_send_bulk_msg(sisusb,
874 SISUSB_EP_GFX_LBULK_OUT,
877 bytes_written, 0, 1);
878 kernbuffer += ((*bytes_written) &
879 (sisusb->obufsize-1));
884 packet.header = 0x001f;
885 packet.address = 0x00000194;
887 ret = sisusb_send_bridge_packet(sisusb, 10,
889 packet.header = 0x001f;
890 packet.address = 0x00000190;
891 packet.data = (length & ~3);
892 ret |= sisusb_send_bridge_packet(sisusb, 10,
894 if (sisusb->flagb0 != 0x16) {
895 packet.header = 0x001f;
896 packet.address = 0x00000180;
897 packet.data = flag | 0x16;
898 ret |= sisusb_send_bridge_packet(sisusb,
900 sisusb->flagb0 = 0x16;
903 ret |= sisusb_send_bulk_msg(sisusb,
904 SISUSB_EP_GFX_BULK_OUT,
907 bytes_written, 0, 1);
908 userbuffer += (*bytes_written);
909 } else if (fromkern) {
910 ret |= sisusb_send_bulk_msg(sisusb,
911 SISUSB_EP_GFX_BULK_OUT,
914 bytes_written, 0, 1);
915 kernbuffer += (*bytes_written);
917 ret |= sisusb_send_bulk_msg(sisusb,
918 SISUSB_EP_GFX_BULK_OUT,
921 bytes_written, 0, 1);
922 kernbuffer += ((*bytes_written) &
923 (sisusb->obufsize-1));
929 dev_err(&sisusb->sisusb_dev->dev,
930 "Wrote %zd of %d bytes, error %d\n",
931 *bytes_written, length,
933 else if (msgcount == 500)
934 dev_err(&sisusb->sisusb_dev->dev,
935 "Too many errors, logging stopped\n");
937 addr += (*bytes_written);
938 length -= (*bytes_written);
946 return ret ? -EIO : 0;
949 /* Remember: Read data in packet is in machine-endianess! So for
950 * byte, word, 24bit, long no endian correction is necessary.
953 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
956 struct sisusb_packet packet;
959 CLEARPACKET(&packet);
960 packet.header = (1 << (addr & 3)) | (type << 6);
961 packet.address = addr & ~3;
962 ret = sisusb_send_packet(sisusb, 6, &packet);
963 *data = (u8)(packet.data >> ((addr & 3) << 3));
967 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
970 struct sisusb_packet packet;
973 CLEARPACKET(&packet);
975 packet.address = addr & ~3;
979 packet.header = (type << 6) | 0x0003;
980 ret = sisusb_send_packet(sisusb, 6, &packet);
981 *data = (u16)(packet.data);
984 packet.header = (type << 6) | 0x0006;
985 ret = sisusb_send_packet(sisusb, 6, &packet);
986 *data = (u16)(packet.data >> 8);
989 packet.header = (type << 6) | 0x000c;
990 ret = sisusb_send_packet(sisusb, 6, &packet);
991 *data = (u16)(packet.data >> 16);
994 packet.header = (type << 6) | 0x0008;
995 ret = sisusb_send_packet(sisusb, 6, &packet);
996 *data = (u16)(packet.data >> 24);
997 packet.header = (type << 6) | 0x0001;
998 packet.address = (addr & ~3) + 4;
999 ret |= sisusb_send_packet(sisusb, 6, &packet);
1000 *data |= (u16)(packet.data << 8);
1006 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1007 u32 addr, u32 *data)
1009 struct sisusb_packet packet;
1012 packet.address = addr & ~3;
1016 packet.header = (type << 6) | 0x0007;
1017 ret = sisusb_send_packet(sisusb, 6, &packet);
1018 *data = packet.data & 0x00ffffff;
1021 packet.header = (type << 6) | 0x000e;
1022 ret = sisusb_send_packet(sisusb, 6, &packet);
1023 *data = packet.data >> 8;
1026 packet.header = (type << 6) | 0x000c;
1027 ret = sisusb_send_packet(sisusb, 6, &packet);
1028 *data = packet.data >> 16;
1029 packet.header = (type << 6) | 0x0001;
1030 packet.address = (addr & ~3) + 4;
1031 ret |= sisusb_send_packet(sisusb, 6, &packet);
1032 *data |= ((packet.data & 0xff) << 16);
1035 packet.header = (type << 6) | 0x0008;
1036 ret = sisusb_send_packet(sisusb, 6, &packet);
1037 *data = packet.data >> 24;
1038 packet.header = (type << 6) | 0x0003;
1039 packet.address = (addr & ~3) + 4;
1040 ret |= sisusb_send_packet(sisusb, 6, &packet);
1041 *data |= ((packet.data & 0xffff) << 8);
1047 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1048 u32 addr, u32 *data)
1050 struct sisusb_packet packet;
1053 packet.address = addr & ~3;
1057 packet.header = (type << 6) | 0x000f;
1058 ret = sisusb_send_packet(sisusb, 6, &packet);
1059 *data = packet.data;
1062 packet.header = (type << 6) | 0x000e;
1063 ret = sisusb_send_packet(sisusb, 6, &packet);
1064 *data = packet.data >> 8;
1065 packet.header = (type << 6) | 0x0001;
1066 packet.address = (addr & ~3) + 4;
1067 ret |= sisusb_send_packet(sisusb, 6, &packet);
1068 *data |= (packet.data << 24);
1071 packet.header = (type << 6) | 0x000c;
1072 ret = sisusb_send_packet(sisusb, 6, &packet);
1073 *data = packet.data >> 16;
1074 packet.header = (type << 6) | 0x0003;
1075 packet.address = (addr & ~3) + 4;
1076 ret |= sisusb_send_packet(sisusb, 6, &packet);
1077 *data |= (packet.data << 16);
1080 packet.header = (type << 6) | 0x0008;
1081 ret = sisusb_send_packet(sisusb, 6, &packet);
1082 *data = packet.data >> 24;
1083 packet.header = (type << 6) | 0x0007;
1084 packet.address = (addr & ~3) + 4;
1085 ret |= sisusb_send_packet(sisusb, 6, &packet);
1086 *data |= (packet.data << 8);
1092 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1093 char *kernbuffer, int length, char __user *userbuffer,
1094 ssize_t *bytes_read)
1103 length &= 0x00ffffff;
1108 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1113 if (put_user(buf[0], (u8 __user *)userbuffer))
1116 kernbuffer[0] = buf[0];
1121 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1126 if (put_user(swap16, (u16 __user *)userbuffer))
1129 *((u16 *)kernbuffer) = swap16;
1135 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1140 buf[0] = (swap32 >> 16) & 0xff;
1141 buf[1] = (swap32 >> 8) & 0xff;
1142 buf[2] = swap32 & 0xff;
1144 buf[2] = (swap32 >> 16) & 0xff;
1145 buf[1] = (swap32 >> 8) & 0xff;
1146 buf[0] = swap32 & 0xff;
1149 if (copy_to_user(userbuffer,
1153 kernbuffer[0] = buf[0];
1154 kernbuffer[1] = buf[1];
1155 kernbuffer[2] = buf[2];
1161 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1166 if (put_user(swap32, (u32 __user *)userbuffer))
1171 *((u32 *)kernbuffer) = swap32;
1185 /* High level: Gfx (indexed) register access */
1187 static int sisusb_setidxreg(struct sisusb_usb_data *sisusb, u32 port,
1192 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1193 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1197 static int sisusb_getidxreg(struct sisusb_usb_data *sisusb, u32 port,
1202 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1203 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1207 static int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, u32 port, u8 idx,
1213 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1214 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1217 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1221 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1222 u32 port, u8 idx, u8 data, u8 mask)
1227 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1228 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1230 tmp |= (data & mask);
1231 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1235 static int sisusb_setidxregor(struct sisusb_usb_data *sisusb, u32 port,
1238 return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1241 static int sisusb_setidxregand(struct sisusb_usb_data *sisusb, u32 port,
1244 return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1247 /* Write/read video ram */
1249 #ifdef SISUSBENDIANTEST
1250 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1252 static u8 srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1253 char destbuffer[10];
1256 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
1258 for (i = 1; i <= 7; i++) {
1259 dev_dbg(&sisusb->sisusb_dev->dev,
1260 "sisusb: rwtest %d bytes\n", i);
1261 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
1262 for (j = 0; j < i; j++) {
1263 dev_dbg(&sisusb->sisusb_dev->dev,
1264 "rwtest read[%d] = %x\n",
1271 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1273 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1274 int regnum, u32 data)
1276 struct sisusb_packet packet;
1278 packet.header = 0x008f;
1279 packet.address = regnum | 0x10000;
1281 return sisusb_send_packet(sisusb, 10, &packet);
1284 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1285 int regnum, u32 *data)
1287 struct sisusb_packet packet;
1290 packet.header = 0x008f;
1291 packet.address = (u32)regnum | 0x10000;
1292 ret = sisusb_send_packet(sisusb, 6, &packet);
1293 *data = packet.data;
1297 /* Clear video RAM */
1299 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1300 u32 address, int length)
1305 if (address < sisusb->vrambase)
1308 if (address >= sisusb->vrambase + sisusb->vramsize)
1311 if (address + length > sisusb->vrambase + sisusb->vramsize)
1312 length = sisusb->vrambase + sisusb->vramsize - address;
1317 /* allocate free buffer/urb and clear the buffer */
1318 i = sisusb_alloc_outbuf(sisusb);
1322 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1324 /* We can write a length > buffer size here. The buffer
1325 * data will simply be re-used (like a ring-buffer).
1327 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1329 /* Free the buffer/urb */
1330 sisusb_free_outbuf(sisusb, i);
1335 /* Initialize the graphics core (return 0 on success)
1336 * This resets the graphics hardware and puts it into
1337 * a defined mode (640x480@60Hz)
1340 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1341 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1342 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1343 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1344 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1345 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1346 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1347 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1348 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1349 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1350 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1352 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1357 ret = GETIREG(SISSR, 0x16, &tmp8);
1360 ret |= SETIREG(SISSR, 0x16, tmp8);
1362 ret |= SETIREG(SISSR, 0x16, tmp8);
1365 ret |= SETIREG(SISSR, 0x16, tmp8);
1367 ret |= SETIREG(SISSR, 0x16, tmp8);
1369 ret |= SETIREG(SISSR, 0x16, tmp8);
1371 ret |= SETIREG(SISSR, 0x16, tmp8);
1373 ret |= SETIREG(SISSR, 0x16, tmp8);
1375 ret |= SETIREG(SISSR, 0x16, tmp8);
1377 ret |= SETIREG(SISSR, 0x16, tmp8);
1382 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1386 u8 ramtype, done = 0;
1388 u32 ramptr = SISUSB_PCI_MEMBASE;
1390 ret = GETIREG(SISSR, 0x3a, &ramtype);
1393 ret |= SETIREG(SISSR, 0x13, 0x00);
1396 ret |= SETIREG(SISSR, 0x14, 0x12);
1397 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1399 ret |= SETIREG(SISSR, 0x14, 0x02);
1402 ret |= sisusb_triggersr16(sisusb, ramtype);
1403 ret |= WRITEL(ramptr + 0, 0x01234567);
1404 ret |= WRITEL(ramptr + 4, 0x456789ab);
1405 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1406 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1407 ret |= WRITEL(ramptr + 16, 0x55555555);
1408 ret |= WRITEL(ramptr + 20, 0x55555555);
1409 ret |= WRITEL(ramptr + 24, 0xffffffff);
1410 ret |= WRITEL(ramptr + 28, 0xffffffff);
1411 ret |= READL(ramptr + 0, &t0);
1412 ret |= READL(ramptr + 4, &t1);
1413 ret |= READL(ramptr + 8, &t2);
1414 ret |= READL(ramptr + 12, &t3);
1418 *chab = 0; *bw = 64;
1420 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1421 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1422 *chab = 0; *bw = 64;
1423 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1426 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1427 *chab = 1; *bw = 64;
1428 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1430 ret |= sisusb_triggersr16(sisusb, ramtype);
1431 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1432 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1433 ret |= WRITEL(ramptr + 8, 0x55555555);
1434 ret |= WRITEL(ramptr + 12, 0x55555555);
1435 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1436 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1437 ret |= READL(ramptr + 4, &t1);
1439 if (t1 != 0xcdef0123) {
1441 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1447 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1451 if (t1 == 0x456789ab) {
1452 if (t0 == 0x01234567) {
1453 *chab = 0; *bw = 64;
1457 if (t0 == 0x01234567) {
1458 *chab = 0; *bw = 32;
1459 ret |= SETIREG(SISSR, 0x14, 0x00);
1465 ret |= SETIREG(SISSR, 0x14, 0x03);
1466 ret |= sisusb_triggersr16(sisusb, ramtype);
1468 ret |= WRITEL(ramptr + 0, 0x01234567);
1469 ret |= WRITEL(ramptr + 4, 0x456789ab);
1470 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1471 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1472 ret |= WRITEL(ramptr + 16, 0x55555555);
1473 ret |= WRITEL(ramptr + 20, 0x55555555);
1474 ret |= WRITEL(ramptr + 24, 0xffffffff);
1475 ret |= WRITEL(ramptr + 28, 0xffffffff);
1476 ret |= READL(ramptr + 0, &t0);
1477 ret |= READL(ramptr + 4, &t1);
1479 if (t1 == 0x456789ab) {
1480 if (t0 == 0x01234567) {
1481 *chab = 1; *bw = 64;
1485 if (t0 == 0x01234567) {
1486 *chab = 1; *bw = 32;
1487 ret |= SETIREG(SISSR, 0x14, 0x01);
1495 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1498 u32 ramptr = SISUSB_PCI_MEMBASE;
1499 u8 tmp1, tmp2, i, j;
1501 ret |= WRITEB(ramptr, 0xaa);
1502 ret |= WRITEB(ramptr + 16, 0x55);
1503 ret |= READB(ramptr, &tmp1);
1504 ret |= READB(ramptr + 16, &tmp2);
1505 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1506 for (i = 0, j = 16; i < 2; i++, j += 16) {
1507 ret |= GETIREG(SISSR, 0x21, &tmp1);
1508 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1509 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1510 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1511 ret |= SETIREG(SISSR, 0x21, tmp1);
1512 ret |= WRITEB(ramptr + 16 + j, j);
1513 ret |= READB(ramptr + 16 + j, &tmp1);
1515 ret |= WRITEB(ramptr + j, j);
1523 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1524 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1526 int ret = 0, ranksize;
1531 if ((rankno == 2) && (dramtype[index][0] == 2))
1534 ranksize = dramtype[index][3] / 2 * bw / 32;
1536 if ((ranksize * rankno) > 128)
1540 while ((ranksize >>= 1) > 0)
1543 tmp |= ((rankno - 1) << 2);
1544 tmp |= ((bw / 64) & 0x02);
1545 tmp |= (chab & 0x01);
1547 ret = SETIREG(SISSR, 0x14, tmp);
1548 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1555 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1563 for (i = 0, j = 0; i < testn; i++) {
1564 ret |= WRITEL(sisusb->vrambase + j, j);
1568 for (i = 0, j = 0; i < testn; i++) {
1569 ret |= READL(sisusb->vrambase + j, &tmp);
1580 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1581 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1583 int ret = 0, i, i2ret;
1588 for (i = rankno; i >= 1; i--) {
1589 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1591 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1596 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1597 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1601 inc = 1 << (10 + bw / 64);
1602 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1610 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1613 int ret = 0, i2ret = 0, i, j;
1614 static const u8 sdramtype[13][5] = {
1615 { 2, 12, 9, 64, 0x35 },
1616 { 1, 13, 9, 64, 0x44 },
1617 { 2, 12, 8, 32, 0x31 },
1618 { 2, 11, 9, 32, 0x25 },
1619 { 1, 12, 9, 32, 0x34 },
1620 { 1, 13, 8, 32, 0x40 },
1621 { 2, 11, 8, 16, 0x21 },
1622 { 1, 12, 8, 16, 0x30 },
1623 { 1, 11, 9, 16, 0x24 },
1624 { 1, 11, 8, 8, 0x20 },
1625 { 2, 9, 8, 4, 0x01 },
1626 { 1, 10, 8, 4, 0x10 },
1627 { 1, 9, 8, 2, 0x00 }
1630 *iret = 1; /* error */
1632 for (i = 0; i < 13; i++) {
1633 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1634 for (j = 2; j > 0; j--) {
1635 ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1640 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1643 *iret = 0; /* ram size found */
1652 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1653 int clrall, int drwfr)
1657 int i, length, modex, modey, bpp;
1659 modex = 640; modey = 480; bpp = 2;
1661 address = sisusb->vrambase; /* Clear video ram */
1664 length = sisusb->vramsize;
1666 length = modex * bpp * modey;
1668 ret = sisusb_clear_vram(sisusb, address, length);
1670 if (!ret && drwfr) {
1671 for (i = 0; i < modex; i++) {
1672 address = sisusb->vrambase + (i * bpp);
1673 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1675 address += (modex * (modey-1) * bpp);
1676 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1679 for (i = 0; i < modey; i++) {
1680 address = sisusb->vrambase + ((i * modex) * bpp);
1681 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1683 address += ((modex - 1) * bpp);
1684 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1692 static void sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1695 int i, j, modex, bpp, du;
1696 u8 sr31, cr63, tmp8;
1697 static const char attrdata[] = {
1698 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1699 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1700 0x01, 0x00, 0x00, 0x00
1702 static const char crtcrdata[] = {
1703 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1704 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1705 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1708 static const char grcdata[] = {
1709 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1712 static const char crtcdata[] = {
1713 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1714 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1718 modex = 640; bpp = 2;
1720 GETIREG(SISSR, 0x31, &sr31);
1721 GETIREG(SISCR, 0x63, &cr63);
1722 SETIREGOR(SISSR, 0x01, 0x20);
1723 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1724 SETIREGOR(SISCR, 0x17, 0x80);
1725 SETIREGOR(SISSR, 0x1f, 0x04);
1726 SETIREGAND(SISSR, 0x07, 0xfb);
1727 SETIREG(SISSR, 0x00, 0x03); /* seq */
1728 SETIREG(SISSR, 0x01, 0x21);
1729 SETIREG(SISSR, 0x02, 0x0f);
1730 SETIREG(SISSR, 0x03, 0x00);
1731 SETIREG(SISSR, 0x04, 0x0e);
1732 SETREG(SISMISCW, 0x23); /* misc */
1733 for (i = 0; i <= 0x18; i++) { /* crtc */
1734 SETIREG(SISCR, i, crtcrdata[i]);
1736 for (i = 0; i <= 0x13; i++) { /* att */
1737 GETREG(SISINPSTAT, &tmp8);
1739 SETREG(SISAR, attrdata[i]);
1741 GETREG(SISINPSTAT, &tmp8);
1742 SETREG(SISAR, 0x14);
1743 SETREG(SISAR, 0x00);
1744 GETREG(SISINPSTAT, &tmp8);
1745 SETREG(SISAR, 0x20);
1746 GETREG(SISINPSTAT, &tmp8);
1747 for (i = 0; i <= 0x08; i++) { /* grc */
1748 SETIREG(SISGR, i, grcdata[i]);
1750 SETIREGAND(SISGR, 0x05, 0xbf);
1751 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1752 SETIREG(SISSR, i, 0x00);
1754 SETIREGAND(SISSR, 0x37, 0xfe);
1755 SETREG(SISMISCW, 0xef); /* sync */
1756 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1757 for (j = 0x00, i = 0; i <= 7; i++, j++)
1758 SETIREG(SISCR, j, crtcdata[i]);
1760 for (j = 0x10; i <= 10; i++, j++)
1761 SETIREG(SISCR, j, crtcdata[i]);
1763 for (j = 0x15; i <= 12; i++, j++)
1764 SETIREG(SISCR, j, crtcdata[i]);
1766 for (j = 0x0A; i <= 15; i++, j++)
1767 SETIREG(SISSR, j, crtcdata[i]);
1769 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1770 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1771 SETIREG(SISCR, 0x14, 0x4f);
1772 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1773 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1774 SETIREG(SISCR, 0x13, (du & 0xff));
1777 SETIREG(SISSR, 0x10, tmp8);
1778 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1779 SETIREG(SISSR, 0x2b, 0x1b);
1780 SETIREG(SISSR, 0x2c, 0xe1);
1781 SETIREG(SISSR, 0x2d, 0x01);
1782 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1783 SETIREG(SISSR, 0x08, 0xae);
1784 SETIREGAND(SISSR, 0x09, 0xf0);
1785 SETIREG(SISSR, 0x08, 0x34);
1786 SETIREGOR(SISSR, 0x3d, 0x01);
1787 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1788 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1789 SETIREG(SISCR, 0x19, 0x00);
1790 SETIREGAND(SISCR, 0x1a, 0xfc);
1791 SETIREGAND(SISSR, 0x0f, 0xb7);
1792 SETIREGAND(SISSR, 0x31, 0xfb);
1793 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1794 SETIREGAND(SISSR, 0x32, 0xf3);
1795 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1796 SETIREG(SISCR, 0x52, 0x6c);
1798 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1799 SETIREG(SISCR, 0x0c, 0x00);
1800 SETIREG(SISSR, 0x0d, 0x00);
1801 SETIREGAND(SISSR, 0x37, 0xfe);
1803 SETIREG(SISCR, 0x32, 0x20);
1804 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1805 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1806 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1809 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1810 SETIREGOR(SISSR, 0x1e, 0x5a);
1812 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1813 SETIREG(SISSR, 0x27, 0x1f);
1814 SETIREG(SISSR, 0x26, 0x00);
1817 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1820 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1822 int ret = 0, i, j, bw, chab, iret, retry = 3;
1825 static const char mclktable[] = {
1826 0x3b, 0x22, 0x01, 143,
1827 0x3b, 0x22, 0x01, 143,
1828 0x3b, 0x22, 0x01, 143,
1829 0x3b, 0x22, 0x01, 143
1831 static const char eclktable[] = {
1832 0x3b, 0x22, 0x01, 143,
1833 0x3b, 0x22, 0x01, 143,
1834 0x3b, 0x22, 0x01, 143,
1835 0x3b, 0x22, 0x01, 143
1837 static const char ramtypetable1[] = {
1838 0x00, 0x04, 0x60, 0x60,
1839 0x0f, 0x0f, 0x1f, 0x1f,
1840 0xba, 0xba, 0xba, 0xba,
1841 0xa9, 0xa9, 0xac, 0xac,
1842 0xa0, 0xa0, 0xa0, 0xa8,
1843 0x00, 0x00, 0x02, 0x02,
1844 0x30, 0x30, 0x40, 0x40
1846 static const char ramtypetable2[] = {
1847 0x77, 0x77, 0x44, 0x44,
1848 0x77, 0x77, 0x44, 0x44,
1849 0x00, 0x00, 0x00, 0x00,
1850 0x5b, 0x5b, 0xab, 0xab,
1851 0x00, 0x00, 0xf0, 0xf8
1857 ret = GETREG(SISVGAEN, &tmp8);
1858 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1860 /* Enable GPU access to VRAM */
1861 ret |= GETREG(SISMISCR, &tmp8);
1862 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1867 /* Reset registers */
1868 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1869 ret |= SETIREG(SISSR, 0x05, 0x86);
1870 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1872 ret |= SETREG(SISMISCW, 0x67);
1874 for (i = 0x06; i <= 0x1f; i++)
1875 ret |= SETIREG(SISSR, i, 0x00);
1877 for (i = 0x21; i <= 0x27; i++)
1878 ret |= SETIREG(SISSR, i, 0x00);
1880 for (i = 0x31; i <= 0x3d; i++)
1881 ret |= SETIREG(SISSR, i, 0x00);
1883 for (i = 0x12; i <= 0x1b; i++)
1884 ret |= SETIREG(SISSR, i, 0x00);
1886 for (i = 0x79; i <= 0x7c; i++)
1887 ret |= SETIREG(SISCR, i, 0x00);
1892 ret |= SETIREG(SISCR, 0x63, 0x80);
1894 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1897 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1898 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1899 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1901 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1902 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1903 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1905 ret |= SETIREG(SISSR, 0x07, 0x18);
1906 ret |= SETIREG(SISSR, 0x11, 0x0f);
1911 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1912 ret |= SETIREG(SISSR, i,
1913 ramtypetable1[(j*4) + ramtype]);
1915 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1916 ret |= SETIREG(SISCR, i,
1917 ramtypetable2[(j*4) + ramtype]);
1920 ret |= SETIREG(SISCR, 0x49, 0xaa);
1922 ret |= SETIREG(SISSR, 0x1f, 0x00);
1923 ret |= SETIREG(SISSR, 0x20, 0xa0);
1924 ret |= SETIREG(SISSR, 0x23, 0xf6);
1925 ret |= SETIREG(SISSR, 0x24, 0x0d);
1926 ret |= SETIREG(SISSR, 0x25, 0x33);
1928 ret |= SETIREG(SISSR, 0x11, 0x0f);
1930 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1932 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
1937 ret |= SETIREG(SISPART1, 0x00, 0x00);
1939 ret |= GETIREG(SISSR, 0x13, &tmp8);
1942 ret |= SETIREG(SISPART1, 0x02, 0x00);
1943 ret |= SETIREG(SISPART1, 0x2e, 0x08);
1945 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
1946 tmp32 &= 0x00f00000;
1947 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
1948 ret |= SETIREG(SISSR, 0x25, tmp8);
1949 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
1950 ret |= SETIREG(SISCR, 0x49, tmp8);
1952 ret |= SETIREG(SISSR, 0x27, 0x1f);
1953 ret |= SETIREG(SISSR, 0x31, 0x00);
1954 ret |= SETIREG(SISSR, 0x32, 0x11);
1955 ret |= SETIREG(SISSR, 0x33, 0x00);
1960 ret |= SETIREG(SISCR, 0x83, 0x00);
1962 sisusb_set_default_mode(sisusb, 0);
1964 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
1965 ret |= SETIREGOR(SISSR, 0x01, 0x20);
1966 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
1968 ret |= sisusb_triggersr16(sisusb, ramtype);
1970 /* Disable refresh */
1971 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
1972 ret |= SETIREGOR(SISSR, 0x19, 0x03);
1974 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
1975 ret |= sisusb_verify_mclk(sisusb);
1978 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
1980 dev_err(&sisusb->sisusb_dev->dev,
1981 "RAM size detection failed, assuming 8MB video RAM\n");
1982 ret |= SETIREG(SISSR, 0x14, 0x31);
1986 dev_err(&sisusb->sisusb_dev->dev,
1987 "DDR RAM device found, assuming 8MB video RAM\n");
1988 ret |= SETIREG(SISSR, 0x14, 0x31);
1992 /* Enable refresh */
1993 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
1994 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
1995 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
1997 ret |= SETIREGOR(SISSR, 0x21, 0x20);
1999 ret |= SETIREG(SISSR, 0x22, 0xfb);
2000 ret |= SETIREG(SISSR, 0x21, 0xa5);
2019 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2021 u8 tmp8, tmp82, ramtype;
2023 char *ramtypetext1 = NULL;
2024 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2025 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2026 static const int busSDR[4] = {64, 64, 128, 128};
2027 static const int busDDR[4] = {32, 32, 64, 64};
2028 static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2030 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2031 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2032 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2033 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2035 switch ((tmp8 >> 2) & 0x03) {
2037 ramtypetext1 = "1 ch/1 r";
2041 bw = busSDR[(tmp8 & 0x03)];
2045 ramtypetext1 = "1 ch/2 r";
2046 sisusb->vramsize <<= 1;
2047 bw = busSDR[(tmp8 & 0x03)];
2050 ramtypetext1 = "asymmetric";
2051 sisusb->vramsize += sisusb->vramsize/2;
2052 bw = busDDRA[(tmp8 & 0x03)];
2055 ramtypetext1 = "2 channel";
2056 sisusb->vramsize <<= 1;
2057 bw = busDDR[(tmp8 & 0x03)];
2061 dev_info(&sisusb->sisusb_dev->dev,
2062 "%dMB %s %cDR S%cRAM, bus width %d\n",
2063 sisusb->vramsize >> 20, ramtypetext1,
2064 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2067 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2069 struct sisusb_packet packet;
2074 packet.header = 0x001f;
2075 packet.address = 0x00000324;
2076 packet.data = 0x00000004;
2077 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2079 packet.header = 0x001f;
2080 packet.address = 0x00000364;
2081 packet.data = 0x00000004;
2082 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2084 packet.header = 0x001f;
2085 packet.address = 0x00000384;
2086 packet.data = 0x00000004;
2087 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2089 packet.header = 0x001f;
2090 packet.address = 0x00000100;
2091 packet.data = 0x00000700;
2092 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2094 packet.header = 0x000f;
2095 packet.address = 0x00000004;
2096 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2097 packet.data |= 0x17;
2098 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2100 /* Init BAR 0 (VRAM) */
2101 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2102 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2103 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2105 tmp32 |= SISUSB_PCI_MEMBASE;
2106 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2108 /* Init BAR 1 (MMIO) */
2109 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2110 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2111 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2113 tmp32 |= SISUSB_PCI_MMIOBASE;
2114 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2116 /* Init BAR 2 (i/o ports) */
2117 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2118 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2119 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2121 tmp32 |= SISUSB_PCI_IOPORTBASE;
2122 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2124 /* Enable memory and i/o access */
2125 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2127 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2130 /* Some further magic */
2131 packet.header = 0x001f;
2132 packet.address = 0x00000050;
2133 packet.data = 0x000000ff;
2134 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2140 /* Initialize the graphics device (return 0 on success)
2141 * This initializes the net2280 as well as the PCI registers
2142 * of the graphics board.
2145 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2147 int ret = 0, test = 0;
2150 if (sisusb->devinit == 1) {
2151 /* Read PCI BARs and see if they have been set up */
2152 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2156 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2159 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2163 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2166 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2170 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2174 /* No? So reset the device */
2175 if ((sisusb->devinit == 0) || (test != 3)) {
2177 ret |= sisusb_do_init_gfxdevice(sisusb);
2180 sisusb->devinit = 1;
2184 if (sisusb->devinit) {
2185 /* Initialize the graphics core */
2186 if (sisusb_init_gfxcore(sisusb) == 0) {
2187 sisusb->gfxinit = 1;
2188 sisusb_get_ramconfig(sisusb);
2189 sisusb_set_default_mode(sisusb, 1);
2190 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2199 static int sisusb_open(struct inode *inode, struct file *file)
2201 struct sisusb_usb_data *sisusb;
2202 struct usb_interface *interface;
2203 int subminor = iminor(inode);
2205 interface = usb_find_interface(&sisusb_driver, subminor);
2209 sisusb = usb_get_intfdata(interface);
2213 mutex_lock(&sisusb->lock);
2215 if (!sisusb->present || !sisusb->ready) {
2216 mutex_unlock(&sisusb->lock);
2220 if (sisusb->isopen) {
2221 mutex_unlock(&sisusb->lock);
2225 if (!sisusb->devinit) {
2226 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2227 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2228 if (sisusb_init_gfxdevice(sisusb, 0)) {
2229 mutex_unlock(&sisusb->lock);
2230 dev_err(&sisusb->sisusb_dev->dev,
2231 "Failed to initialize device\n");
2235 mutex_unlock(&sisusb->lock);
2236 dev_err(&sisusb->sisusb_dev->dev,
2237 "Device not attached to USB 2.0 hub\n");
2242 /* Increment usage count for our sisusb */
2243 kref_get(&sisusb->kref);
2247 file->private_data = sisusb;
2249 mutex_unlock(&sisusb->lock);
2254 static void sisusb_delete(struct kref *kref)
2256 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2261 usb_put_dev(sisusb->sisusb_dev);
2263 sisusb->sisusb_dev = NULL;
2264 sisusb_free_buffers(sisusb);
2265 sisusb_free_urbs(sisusb);
2269 static int sisusb_release(struct inode *inode, struct file *file)
2271 struct sisusb_usb_data *sisusb;
2273 sisusb = file->private_data;
2277 mutex_lock(&sisusb->lock);
2279 if (sisusb->present) {
2280 /* Wait for all URBs to finish if device still present */
2281 if (!sisusb_wait_all_out_complete(sisusb))
2282 sisusb_kill_all_busy(sisusb);
2286 file->private_data = NULL;
2288 mutex_unlock(&sisusb->lock);
2290 /* decrement the usage count on our device */
2291 kref_put(&sisusb->kref, sisusb_delete);
2296 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2297 size_t count, loff_t *ppos)
2299 struct sisusb_usb_data *sisusb;
2300 ssize_t bytes_read = 0;
2306 sisusb = file->private_data;
2310 mutex_lock(&sisusb->lock);
2313 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2314 mutex_unlock(&sisusb->lock);
2318 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2319 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2321 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2322 SISUSB_PCI_IOPORTBASE;
2325 * Byte, word and long(32) can be read. As this
2326 * emulates inX instructions, the data returned is
2327 * in machine-endianness.
2331 if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2334 else if (put_user(buf8, (u8 __user *)buffer))
2342 if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2345 else if (put_user(buf16, (u16 __user *)buffer))
2353 if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2356 else if (put_user(buf32, (u32 __user *)buffer))
2368 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2369 SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2371 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2375 * Remember: Data delivered is never endian-corrected
2377 errno = sisusb_read_mem_bulk(sisusb, address,
2378 NULL, count, buffer, &bytes_read);
2383 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2384 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2385 SISUSB_PCI_MMIOSIZE) {
2387 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2388 SISUSB_PCI_MMIOBASE;
2391 * Remember: Data delivered is never endian-corrected
2393 errno = sisusb_read_mem_bulk(sisusb, address,
2394 NULL, count, buffer, &bytes_read);
2399 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2400 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2403 mutex_unlock(&sisusb->lock);
2407 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2409 /* Read PCI config register
2410 * Return value delivered in machine endianness.
2412 if (sisusb_read_pci_config(sisusb, address, &buf32))
2414 else if (put_user(buf32, (u32 __user *)buffer))
2425 (*ppos) += bytes_read;
2427 mutex_unlock(&sisusb->lock);
2429 return errno ? errno : bytes_read;
2432 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2433 size_t count, loff_t *ppos)
2435 struct sisusb_usb_data *sisusb;
2437 ssize_t bytes_written = 0;
2442 sisusb = file->private_data;
2446 mutex_lock(&sisusb->lock);
2449 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2450 mutex_unlock(&sisusb->lock);
2454 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2455 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2457 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2458 SISUSB_PCI_IOPORTBASE;
2461 * Byte, word and long(32) can be written. As this
2462 * emulates outX instructions, the data is expected
2463 * in machine-endianness.
2467 if (get_user(buf8, (u8 __user *)buffer))
2469 else if (sisusb_write_memio_byte(sisusb,
2470 SISUSB_TYPE_IO, address, buf8))
2478 if (get_user(buf16, (u16 __user *)buffer))
2480 else if (sisusb_write_memio_word(sisusb,
2481 SISUSB_TYPE_IO, address, buf16))
2489 if (get_user(buf32, (u32 __user *)buffer))
2491 else if (sisusb_write_memio_long(sisusb,
2492 SISUSB_TYPE_IO, address, buf32))
2503 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2504 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE +
2507 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2511 * Buffer is copied 1:1, therefore, on big-endian
2512 * machines, the data must be swapped by userland
2513 * in advance (if applicable; no swapping in 8bpp
2514 * mode or if YUV data is being transferred).
2516 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2517 count, buffer, 0, &bytes_written);
2520 errno = bytes_written;
2522 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2523 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2524 SISUSB_PCI_MMIOSIZE) {
2526 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2527 SISUSB_PCI_MMIOBASE;
2530 * Buffer is copied 1:1, therefore, on big-endian
2531 * machines, the data must be swapped by userland
2534 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2535 count, buffer, 0, &bytes_written);
2538 errno = bytes_written;
2540 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2541 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2542 SISUSB_PCI_PCONFSIZE) {
2545 mutex_unlock(&sisusb->lock);
2549 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2551 /* Write PCI config register.
2552 * Given value expected in machine endianness.
2554 if (get_user(buf32, (u32 __user *)buffer))
2556 else if (sisusb_write_pci_config(sisusb, address, buf32))
2569 (*ppos) += bytes_written;
2571 mutex_unlock(&sisusb->lock);
2573 return errno ? errno : bytes_written;
2576 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2578 struct sisusb_usb_data *sisusb;
2581 sisusb = file->private_data;
2585 mutex_lock(&sisusb->lock);
2588 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2589 mutex_unlock(&sisusb->lock);
2593 ret = no_seek_end_llseek(file, offset, orig);
2595 mutex_unlock(&sisusb->lock);
2599 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2600 struct sisusb_command *y, unsigned long arg)
2605 /* All our commands require the device
2606 * to be initialized.
2608 if (!sisusb->devinit)
2612 SISUSB_PCI_PSEUDO_IOPORTBASE +
2613 SISUSB_PCI_IOPORTBASE;
2615 switch (y->operation) {
2617 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2619 if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2625 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2629 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2633 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2636 case SUCMD_SETANDOR:
2637 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2638 y->data1, y->data2);
2642 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2643 y->data1, y->data2);
2647 /* Gfx core must be initialized */
2648 if (!sisusb->gfxinit)
2651 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2652 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2654 retval = sisusb_clear_vram(sisusb, address, length);
2657 case SUCMD_HANDLETEXTMODE:
2671 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2673 struct sisusb_usb_data *sisusb;
2674 struct sisusb_info x;
2675 struct sisusb_command y;
2677 u32 __user *argp = (u32 __user *)arg;
2679 sisusb = file->private_data;
2683 mutex_lock(&sisusb->lock);
2686 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2692 case SISUSB_GET_CONFIG_SIZE:
2694 if (put_user(sizeof(x), argp))
2699 case SISUSB_GET_CONFIG:
2701 x.sisusb_id = SISUSB_ID;
2702 x.sisusb_version = SISUSB_VERSION;
2703 x.sisusb_revision = SISUSB_REVISION;
2704 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2705 x.sisusb_gfxinit = sisusb->gfxinit;
2706 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2707 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2708 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2709 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2710 x.sisusb_vramsize = sisusb->vramsize;
2711 x.sisusb_minor = sisusb->minor;
2712 x.sisusb_fbdevactive = 0;
2713 x.sisusb_conactive = 0;
2714 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2716 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2721 case SISUSB_COMMAND:
2723 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2726 retval = sisusb_handle_command(sisusb, &y, arg);
2736 mutex_unlock(&sisusb->lock);
2740 #ifdef CONFIG_COMPAT
2741 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2745 case SISUSB_GET_CONFIG_SIZE:
2746 case SISUSB_GET_CONFIG:
2747 case SISUSB_COMMAND:
2748 return sisusb_ioctl(f, cmd, arg);
2751 return -ENOIOCTLCMD;
2756 static const struct file_operations usb_sisusb_fops = {
2757 .owner = THIS_MODULE,
2758 .open = sisusb_open,
2759 .release = sisusb_release,
2760 .read = sisusb_read,
2761 .write = sisusb_write,
2762 .llseek = sisusb_lseek,
2763 #ifdef CONFIG_COMPAT
2764 .compat_ioctl = sisusb_compat_ioctl,
2766 .unlocked_ioctl = sisusb_ioctl
2769 static struct usb_class_driver usb_sisusb_class = {
2770 .name = "sisusbvga%d",
2771 .fops = &usb_sisusb_fops,
2772 .minor_base = SISUSB_MINOR
2775 static int sisusb_probe(struct usb_interface *intf,
2776 const struct usb_device_id *id)
2778 struct usb_device *dev = interface_to_usbdev(intf);
2779 struct sisusb_usb_data *sisusb;
2781 static const u8 ep_addresses[] = {
2782 SISUSB_EP_GFX_IN | USB_DIR_IN,
2783 SISUSB_EP_GFX_OUT | USB_DIR_OUT,
2784 SISUSB_EP_GFX_BULK_OUT | USB_DIR_OUT,
2785 SISUSB_EP_GFX_LBULK_OUT | USB_DIR_OUT,
2786 SISUSB_EP_BRIDGE_IN | USB_DIR_IN,
2787 SISUSB_EP_BRIDGE_OUT | USB_DIR_OUT,
2790 /* Are the expected endpoints present? */
2791 if (!usb_check_bulk_endpoints(intf, ep_addresses)) {
2792 dev_err(&intf->dev, "Invalid USB2VGA device\n");
2796 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
2799 /* Allocate memory for our private */
2800 sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
2804 kref_init(&sisusb->kref);
2806 mutex_init(&(sisusb->lock));
2808 sisusb->sisusb_dev = dev;
2809 sisusb->vrambase = SISUSB_PCI_MEMBASE;
2810 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
2811 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
2812 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
2813 /* Everything else is zero */
2815 /* Register device */
2816 retval = usb_register_dev(intf, &usb_sisusb_class);
2818 dev_err(&sisusb->sisusb_dev->dev,
2819 "Failed to get a minor for device %d\n",
2825 sisusb->minor = intf->minor;
2827 /* Allocate buffers */
2828 sisusb->ibufsize = SISUSB_IBUF_SIZE;
2829 sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
2830 if (!sisusb->ibuf) {
2835 sisusb->numobufs = 0;
2836 sisusb->obufsize = SISUSB_OBUF_SIZE;
2837 for (i = 0; i < NUMOBUFS; i++) {
2838 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
2839 if (!sisusb->obuf[i]) {
2850 sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
2851 if (!sisusb->sisurbin) {
2855 sisusb->completein = 1;
2857 for (i = 0; i < sisusb->numobufs; i++) {
2858 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
2859 if (!sisusb->sisurbout[i]) {
2863 sisusb->urbout_context[i].sisusb = (void *)sisusb;
2864 sisusb->urbout_context[i].urbindex = i;
2865 sisusb->urbstatus[i] = 0;
2868 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
2871 /* Do remaining init stuff */
2873 init_waitqueue_head(&sisusb->wait_q);
2875 usb_set_intfdata(intf, sisusb);
2877 usb_get_dev(sisusb->sisusb_dev);
2879 sisusb->present = 1;
2881 if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
2883 if (sisusb_init_gfxdevice(sisusb, initscreen))
2884 dev_err(&sisusb->sisusb_dev->dev,
2885 "Failed to early initialize device\n");
2888 dev_info(&sisusb->sisusb_dev->dev,
2889 "Not attached to USB 2.0 hub, deferring init\n");
2893 #ifdef SISUSBENDIANTEST
2894 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
2895 sisusb_testreadwrite(sisusb);
2896 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
2902 sisusb_free_urbs(sisusb);
2904 sisusb_free_buffers(sisusb);
2906 usb_deregister_dev(intf, &usb_sisusb_class);
2912 static void sisusb_disconnect(struct usb_interface *intf)
2914 struct sisusb_usb_data *sisusb;
2916 /* This should *not* happen */
2917 sisusb = usb_get_intfdata(intf);
2921 usb_deregister_dev(intf, &usb_sisusb_class);
2923 mutex_lock(&sisusb->lock);
2925 /* Wait for all URBs to complete and kill them in case (MUST do) */
2926 if (!sisusb_wait_all_out_complete(sisusb))
2927 sisusb_kill_all_busy(sisusb);
2929 usb_set_intfdata(intf, NULL);
2931 sisusb->present = 0;
2934 mutex_unlock(&sisusb->lock);
2936 /* decrement our usage count */
2937 kref_put(&sisusb->kref, sisusb_delete);
2940 static const struct usb_device_id sisusb_table[] = {
2941 { USB_DEVICE(0x0711, 0x0550) },
2942 { USB_DEVICE(0x0711, 0x0900) },
2943 { USB_DEVICE(0x0711, 0x0901) },
2944 { USB_DEVICE(0x0711, 0x0902) },
2945 { USB_DEVICE(0x0711, 0x0903) },
2946 { USB_DEVICE(0x0711, 0x0918) },
2947 { USB_DEVICE(0x0711, 0x0920) },
2948 { USB_DEVICE(0x0711, 0x0950) },
2949 { USB_DEVICE(0x0711, 0x5200) },
2950 { USB_DEVICE(0x182d, 0x021c) },
2951 { USB_DEVICE(0x182d, 0x0269) },
2955 MODULE_DEVICE_TABLE(usb, sisusb_table);
2957 static struct usb_driver sisusb_driver = {
2959 .probe = sisusb_probe,
2960 .disconnect = sisusb_disconnect,
2961 .id_table = sisusb_table,
2964 module_usb_driver(sisusb_driver);
2967 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
2968 MODULE_LICENSE("GPL");