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/config.h>
40 #include <linux/mutex.h>
41 #include <linux/module.h>
42 #include <linux/kernel.h>
43 #include <linux/signal.h>
44 #include <linux/sched.h>
45 #include <linux/errno.h>
46 #include <linux/poll.h>
47 #include <linux/init.h>
48 #include <linux/slab.h>
49 #include <linux/spinlock.h>
50 #include <linux/kref.h>
51 #include <linux/usb.h>
52 #include <linux/smp_lock.h>
53 #include <linux/vmalloc.h>
57 #ifdef INCL_SISUSB_CON
58 #include <linux/font.h>
61 #define SISUSB_DONTSYNC
63 /* Forward declarations / clean-up routines */
65 #ifdef INCL_SISUSB_CON
66 int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
67 int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
68 int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
69 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
70 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
71 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
72 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
74 int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
75 int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
76 int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
77 int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
78 int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
79 u32 dest, int length, size_t *bytes_written);
81 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
83 extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
84 extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
86 extern void sisusb_init_concode(void);
87 extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
88 extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
90 extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
92 extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
93 u8 *arg, int cmapsz, int ch512, int dorecalc,
94 struct vc_data *c, int fh, int uplock);
96 static int sisusb_first_vc = 0;
97 static int sisusb_last_vc = 0;
98 module_param_named(first, sisusb_first_vc, int, 0);
99 module_param_named(last, sisusb_last_vc, int, 0);
100 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
101 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
104 static struct usb_driver sisusb_driver;
106 DEFINE_MUTEX(disconnect_mutex);
109 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
113 for (i = 0; i < NUMOBUFS; i++) {
114 if (sisusb->obuf[i]) {
115 usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
116 sisusb->obuf[i], sisusb->transfer_dma_out[i]);
117 sisusb->obuf[i] = NULL;
121 usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
122 sisusb->ibuf, sisusb->transfer_dma_in);
128 sisusb_free_urbs(struct sisusb_usb_data *sisusb)
132 for (i = 0; i < NUMOBUFS; i++) {
133 usb_free_urb(sisusb->sisurbout[i]);
134 sisusb->sisurbout[i] = NULL;
136 usb_free_urb(sisusb->sisurbin);
137 sisusb->sisurbin = NULL;
140 /* Level 0: USB transport layer */
144 /* out-urb management */
146 /* Return 1 if all free, 0 otherwise */
148 sisusb_all_free(struct sisusb_usb_data *sisusb)
152 for (i = 0; i < sisusb->numobufs; i++) {
154 if (sisusb->urbstatus[i] & SU_URB_BUSY)
162 /* Kill all busy URBs */
164 sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
168 if (sisusb_all_free(sisusb))
171 for (i = 0; i < sisusb->numobufs; i++) {
173 if (sisusb->urbstatus[i] & SU_URB_BUSY)
174 usb_kill_urb(sisusb->sisurbout[i]);
179 /* Return 1 if ok, 0 if error (not all complete within timeout) */
181 sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
183 int timeout = 5 * HZ, i = 1;
185 wait_event_timeout(sisusb->wait_q,
186 (i = sisusb_all_free(sisusb)),
193 sisusb_outurb_available(struct sisusb_usb_data *sisusb)
197 for (i = 0; i < sisusb->numobufs; i++) {
199 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
208 sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
210 int i, timeout = 5 * HZ;
212 wait_event_timeout(sisusb->wait_q,
213 ((i = sisusb_outurb_available(sisusb)) >= 0),
220 sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
224 i = sisusb_outurb_available(sisusb);
227 sisusb->urbstatus[i] |= SU_URB_ALLOC;
233 sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
235 if ((index >= 0) && (index < sisusb->numobufs))
236 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
239 /* completion callback */
242 sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
244 struct sisusb_urb_context *context = urb->context;
245 struct sisusb_usb_data *sisusb;
250 sisusb = context->sisusb;
252 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
255 #ifndef SISUSB_DONTSYNC
256 if (context->actual_length)
257 *(context->actual_length) += urb->actual_length;
260 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
261 wake_up(&sisusb->wait_q);
265 sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
266 int len, int *actual_length, int timeout, unsigned int tflags,
267 dma_addr_t transfer_dma)
269 struct urb *urb = sisusb->sisurbout[index];
270 int retval, byteswritten = 0;
273 urb->transfer_flags = 0;
275 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
276 sisusb_bulk_completeout, &sisusb->urbout_context[index]);
278 urb->transfer_flags |= tflags;
279 urb->actual_length = 0;
281 if ((urb->transfer_dma = transfer_dma))
282 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
285 sisusb->urbout_context[index].actual_length = (timeout) ?
286 NULL : actual_length;
288 /* Declare this urb/buffer in use */
289 sisusb->urbstatus[index] |= SU_URB_BUSY;
292 retval = usb_submit_urb(urb, GFP_ATOMIC);
294 /* If OK, and if timeout > 0, wait for completion */
295 if ((retval == 0) && timeout) {
296 wait_event_timeout(sisusb->wait_q,
297 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
299 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
300 /* URB timed out... kill it and report error */
304 /* Otherwise, report urb status */
305 retval = urb->status;
306 byteswritten = urb->actual_length;
311 *actual_length = byteswritten;
318 /* completion callback */
321 sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
323 struct sisusb_usb_data *sisusb = urb->context;
325 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
328 sisusb->completein = 1;
329 wake_up(&sisusb->wait_q);
333 sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
334 int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
336 struct urb *urb = sisusb->sisurbin;
337 int retval, readbytes = 0;
339 urb->transfer_flags = 0;
341 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
342 sisusb_bulk_completein, sisusb);
344 urb->transfer_flags |= tflags;
345 urb->actual_length = 0;
347 if ((urb->transfer_dma = transfer_dma))
348 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
350 sisusb->completein = 0;
351 retval = usb_submit_urb(urb, GFP_ATOMIC);
353 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
354 if (!sisusb->completein) {
355 /* URB timed out... kill it and report error */
359 /* URB completed within timout */
360 retval = urb->status;
361 readbytes = urb->actual_length;
366 *actual_length = readbytes;
374 /* Send a bulk message of variable size
376 * To copy the data from userspace, give pointer to "userbuffer",
377 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
378 * both of these are NULL, it is assumed, that the transfer
379 * buffer "sisusb->obuf[index]" is set up with the data to send.
380 * Index is ignored if either kernbuffer or userbuffer is set.
381 * If async is nonzero, URBs will be sent without waiting for
382 * completion of the previous URB.
384 * (return 0 on success)
387 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
388 char *kernbuffer, const char __user *userbuffer, int index,
389 ssize_t *bytes_written, unsigned int tflags, int async)
391 int result = 0, retry, count = len;
392 int passsize, thispass, transferred_len = 0;
393 int fromuser = (userbuffer != NULL) ? 1 : 0;
394 int fromkern = (kernbuffer != NULL) ? 1 : 0;
398 (*bytes_written) = 0;
401 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
404 /* If we copy data from kernel or userspace, force the
405 * allocation of a buffer/urb. If we have the data in
406 * the transfer buffer[index] already, reuse the buffer/URB
407 * if the length is > buffer size. (So, transmitting
408 * large data amounts directly from the transfer buffer
409 * treats the buffer as a ring buffer. However, we need
410 * to sync in this case.)
412 if (fromuser || fromkern)
414 else if (len > sisusb->obufsize)
417 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
420 passsize = thispass = (sisusb->obufsize < count) ?
421 sisusb->obufsize : count;
424 index = sisusb_get_free_outbuf(sisusb);
429 buffer = sisusb->obuf[index];
433 if (copy_from_user(buffer, userbuffer, passsize))
436 userbuffer += passsize;
438 } else if (fromkern) {
440 memcpy(buffer, kernbuffer, passsize);
441 kernbuffer += passsize;
448 if (!sisusb->sisusb_dev)
451 result = sisusb_bulkout_msg(sisusb,
459 sisusb->transfer_dma_out[index]);
461 if (result == -ETIMEDOUT) {
463 /* Will not happen if async */
469 } else if ((result == 0) && !async && transferred_len) {
471 thispass -= transferred_len;
473 if (sisusb->transfer_dma_out) {
474 /* If DMA, copy remaining
475 * to beginning of buffer
478 buffer + transferred_len,
481 /* If not DMA, simply increase
484 buffer += transferred_len;
495 (*bytes_written) += passsize;
498 /* Force new allocation in next iteration */
499 if (fromuser || fromkern)
505 #ifdef SISUSB_DONTSYNC
506 (*bytes_written) = len;
507 /* Some URBs/buffers might be busy */
509 sisusb_wait_all_out_complete(sisusb);
510 (*bytes_written) = transferred_len;
511 /* All URBs and all buffers are available */
515 return ((*bytes_written) == len) ? 0 : -EIO;
518 /* Receive a bulk message of variable size
520 * To copy the data to userspace, give pointer to "userbuffer",
521 * to copy to kernel memory, give "kernbuffer". One of them
522 * MUST be set. (There is no technique for letting the caller
523 * read directly from the ibuf.)
527 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
528 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
531 int result = 0, retry, count = len;
532 int bufsize, thispass, transferred_len;
539 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
542 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
543 buffer = sisusb->ibuf;
544 bufsize = sisusb->ibufsize;
548 #ifdef SISUSB_DONTSYNC
549 if (!(sisusb_wait_all_out_complete(sisusb)))
555 if (!sisusb->sisusb_dev)
558 thispass = (bufsize < count) ? bufsize : count;
560 result = sisusb_bulkin_msg(sisusb,
567 sisusb->transfer_dma_in);
570 thispass = transferred_len;
572 else if (result == -ETIMEDOUT) {
585 (*bytes_read) += thispass;
590 if (copy_to_user(userbuffer, buffer, thispass))
593 userbuffer += thispass;
597 memcpy(kernbuffer, buffer, thispass);
598 kernbuffer += thispass;
606 return ((*bytes_read) == len) ? 0 : -EIO;
609 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
610 struct sisusb_packet *packet)
613 ssize_t bytes_transferred = 0;
619 #ifdef SISUSB_DONTSYNC
620 if (!(sisusb_wait_all_out_complete(sisusb)))
624 /* Eventually correct endianness */
625 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
627 /* 1. send the packet */
628 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
629 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
631 if ((ret == 0) && (len == 6)) {
633 /* 2. if packet len == 6, it means we read, so wait for 32bit
634 * return value and write it to packet->data
636 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
637 (char *)&tmp, NULL, &bytes_transferred, 0);
639 packet->data = le32_to_cpu(tmp);
645 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
646 struct sisusb_packet *packet,
650 ssize_t bytes_transferred = 0;
656 #ifdef SISUSB_DONTSYNC
657 if (!(sisusb_wait_all_out_complete(sisusb)))
661 /* Eventually correct endianness */
662 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
664 /* 1. send the packet */
665 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
666 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
668 if ((ret == 0) && (len == 6)) {
670 /* 2. if packet len == 6, it means we read, so wait for 32bit
671 * return value and write it to packet->data
673 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
674 (char *)&tmp, NULL, &bytes_transferred, 0);
676 packet->data = le32_to_cpu(tmp);
682 /* access video memory and mmio (return 0 on success) */
686 /* The following routines assume being used to transfer byte, word,
689 * - the write routines expect "data" in machine endianness format.
690 * The data will be converted to leXX in sisusb_xxx_packet.
691 * - the read routines can expect read data in machine-endianess.
694 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
697 struct sisusb_packet packet;
700 packet.header = (1 << (addr & 3)) | (type << 6);
701 packet.address = addr & ~3;
702 packet.data = data << ((addr & 3) << 3);
703 ret = sisusb_send_packet(sisusb, 10, &packet);
707 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
710 struct sisusb_packet packet;
713 packet.address = addr & ~3;
717 packet.header = (type << 6) | 0x0003;
718 packet.data = (u32)data;
719 ret = sisusb_send_packet(sisusb, 10, &packet);
722 packet.header = (type << 6) | 0x0006;
723 packet.data = (u32)data << 8;
724 ret = sisusb_send_packet(sisusb, 10, &packet);
727 packet.header = (type << 6) | 0x000c;
728 packet.data = (u32)data << 16;
729 ret = sisusb_send_packet(sisusb, 10, &packet);
732 packet.header = (type << 6) | 0x0008;
733 packet.data = (u32)data << 24;
734 ret = sisusb_send_packet(sisusb, 10, &packet);
735 packet.header = (type << 6) | 0x0001;
736 packet.address = (addr & ~3) + 4;
737 packet.data = (u32)data >> 8;
738 ret |= sisusb_send_packet(sisusb, 10, &packet);
744 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
747 struct sisusb_packet packet;
750 packet.address = addr & ~3;
754 packet.header = (type << 6) | 0x0007;
755 packet.data = data & 0x00ffffff;
756 ret = sisusb_send_packet(sisusb, 10, &packet);
759 packet.header = (type << 6) | 0x000e;
760 packet.data = data << 8;
761 ret = sisusb_send_packet(sisusb, 10, &packet);
764 packet.header = (type << 6) | 0x000c;
765 packet.data = data << 16;
766 ret = sisusb_send_packet(sisusb, 10, &packet);
767 packet.header = (type << 6) | 0x0001;
768 packet.address = (addr & ~3) + 4;
769 packet.data = (data >> 16) & 0x00ff;
770 ret |= sisusb_send_packet(sisusb, 10, &packet);
773 packet.header = (type << 6) | 0x0008;
774 packet.data = data << 24;
775 ret = sisusb_send_packet(sisusb, 10, &packet);
776 packet.header = (type << 6) | 0x0003;
777 packet.address = (addr & ~3) + 4;
778 packet.data = (data >> 8) & 0xffff;
779 ret |= sisusb_send_packet(sisusb, 10, &packet);
785 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
788 struct sisusb_packet packet;
791 packet.address = addr & ~3;
795 packet.header = (type << 6) | 0x000f;
797 ret = sisusb_send_packet(sisusb, 10, &packet);
800 packet.header = (type << 6) | 0x000e;
801 packet.data = data << 8;
802 ret = sisusb_send_packet(sisusb, 10, &packet);
803 packet.header = (type << 6) | 0x0001;
804 packet.address = (addr & ~3) + 4;
805 packet.data = data >> 24;
806 ret |= sisusb_send_packet(sisusb, 10, &packet);
809 packet.header = (type << 6) | 0x000c;
810 packet.data = data << 16;
811 ret = sisusb_send_packet(sisusb, 10, &packet);
812 packet.header = (type << 6) | 0x0003;
813 packet.address = (addr & ~3) + 4;
814 packet.data = data >> 16;
815 ret |= sisusb_send_packet(sisusb, 10, &packet);
818 packet.header = (type << 6) | 0x0008;
819 packet.data = data << 24;
820 ret = sisusb_send_packet(sisusb, 10, &packet);
821 packet.header = (type << 6) | 0x0007;
822 packet.address = (addr & ~3) + 4;
823 packet.data = data >> 8;
824 ret |= sisusb_send_packet(sisusb, 10, &packet);
830 /* The xxx_bulk routines copy a buffer of variable size. They treat the
831 * buffer as chars, therefore lsb/msb has to be corrected if using the
832 * byte/word/long/etc routines for speed-up
834 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
835 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
836 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
837 * that the data already is in the transfer buffer "sisusb->obuf[index]".
840 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
841 char *kernbuffer, int length,
842 const char __user *userbuffer, int index,
843 ssize_t *bytes_written)
845 struct sisusb_packet packet;
847 static int msgcount = 0;
848 u8 swap8, fromkern = kernbuffer ? 1 : 0;
850 u32 swap32, flag = (length >> 28) & 1;
853 /* if neither kernbuffer not userbuffer are given, assume
856 if (!fromkern && !userbuffer)
857 kernbuffer = sisusb->obuf[index];
859 (*bytes_written = 0);
861 length &= 0x00ffffff;
869 if (get_user(swap8, (u8 __user *)userbuffer))
872 swap8 = kernbuffer[0];
874 ret = sisusb_write_memio_byte(sisusb,
885 if (get_user(swap16, (u16 __user *)userbuffer))
888 swap16 = *((u16 *)kernbuffer);
890 ret = sisusb_write_memio_word(sisusb,
896 (*bytes_written) += 2;
902 if (copy_from_user(&buf, userbuffer, 3))
905 swap32 = (buf[0] << 16) |
909 swap32 = (buf[2] << 16) |
915 swap32 = (kernbuffer[0] << 16) |
916 (kernbuffer[1] << 8) |
919 swap32 = (kernbuffer[2] << 16) |
920 (kernbuffer[1] << 8) |
924 ret = sisusb_write_memio_24bit(sisusb,
930 (*bytes_written) += 3;
936 if (get_user(swap32, (u32 __user *)userbuffer))
939 swap32 = *((u32 *)kernbuffer);
941 ret = sisusb_write_memio_long(sisusb,
946 (*bytes_written) += 4;
951 if ((length & ~3) > 0x10000) {
953 packet.header = 0x001f;
954 packet.address = 0x000001d4;
956 ret = sisusb_send_bridge_packet(sisusb, 10,
958 packet.header = 0x001f;
959 packet.address = 0x000001d0;
960 packet.data = (length & ~3);
961 ret |= sisusb_send_bridge_packet(sisusb, 10,
963 packet.header = 0x001f;
964 packet.address = 0x000001c0;
965 packet.data = flag | 0x16;
966 ret |= sisusb_send_bridge_packet(sisusb, 10,
969 ret |= sisusb_send_bulk_msg(sisusb,
970 SISUSB_EP_GFX_LBULK_OUT,
973 bytes_written, 0, 1);
974 userbuffer += (*bytes_written);
975 } else if (fromkern) {
976 ret |= sisusb_send_bulk_msg(sisusb,
977 SISUSB_EP_GFX_LBULK_OUT,
980 bytes_written, 0, 1);
981 kernbuffer += (*bytes_written);
983 ret |= sisusb_send_bulk_msg(sisusb,
984 SISUSB_EP_GFX_LBULK_OUT,
987 bytes_written, 0, 1);
988 kernbuffer += ((*bytes_written) &
989 (sisusb->obufsize-1));
994 packet.header = 0x001f;
995 packet.address = 0x00000194;
997 ret = sisusb_send_bridge_packet(sisusb, 10,
999 packet.header = 0x001f;
1000 packet.address = 0x00000190;
1001 packet.data = (length & ~3);
1002 ret |= sisusb_send_bridge_packet(sisusb, 10,
1004 if (sisusb->flagb0 != 0x16) {
1005 packet.header = 0x001f;
1006 packet.address = 0x00000180;
1007 packet.data = flag | 0x16;
1008 ret |= sisusb_send_bridge_packet(sisusb, 10,
1010 sisusb->flagb0 = 0x16;
1013 ret |= sisusb_send_bulk_msg(sisusb,
1014 SISUSB_EP_GFX_BULK_OUT,
1016 NULL, userbuffer, 0,
1017 bytes_written, 0, 1);
1018 userbuffer += (*bytes_written);
1019 } else if (fromkern) {
1020 ret |= sisusb_send_bulk_msg(sisusb,
1021 SISUSB_EP_GFX_BULK_OUT,
1023 kernbuffer, NULL, 0,
1024 bytes_written, 0, 1);
1025 kernbuffer += (*bytes_written);
1027 ret |= sisusb_send_bulk_msg(sisusb,
1028 SISUSB_EP_GFX_BULK_OUT,
1031 bytes_written, 0, 1);
1032 kernbuffer += ((*bytes_written) &
1033 (sisusb->obufsize-1));
1040 "sisusbvga[%d]: Wrote %zd of "
1041 "%d bytes, error %d\n",
1042 sisusb->minor, *bytes_written,
1044 else if (msgcount == 500)
1046 "sisusbvga[%d]: Too many errors"
1047 ", logging stopped\n",
1050 addr += (*bytes_written);
1051 length -= (*bytes_written);
1059 return ret ? -EIO : 0;
1062 /* Remember: Read data in packet is in machine-endianess! So for
1063 * byte, word, 24bit, long no endian correction is necessary.
1066 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1069 struct sisusb_packet packet;
1072 CLEARPACKET(&packet);
1073 packet.header = (1 << (addr & 3)) | (type << 6);
1074 packet.address = addr & ~3;
1075 ret = sisusb_send_packet(sisusb, 6, &packet);
1076 *data = (u8)(packet.data >> ((addr & 3) << 3));
1080 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
1081 u32 addr, u16 *data)
1083 struct sisusb_packet packet;
1086 CLEARPACKET(&packet);
1088 packet.address = addr & ~3;
1092 packet.header = (type << 6) | 0x0003;
1093 ret = sisusb_send_packet(sisusb, 6, &packet);
1094 *data = (u16)(packet.data);
1097 packet.header = (type << 6) | 0x0006;
1098 ret = sisusb_send_packet(sisusb, 6, &packet);
1099 *data = (u16)(packet.data >> 8);
1102 packet.header = (type << 6) | 0x000c;
1103 ret = sisusb_send_packet(sisusb, 6, &packet);
1104 *data = (u16)(packet.data >> 16);
1107 packet.header = (type << 6) | 0x0008;
1108 ret = sisusb_send_packet(sisusb, 6, &packet);
1109 *data = (u16)(packet.data >> 24);
1110 packet.header = (type << 6) | 0x0001;
1111 packet.address = (addr & ~3) + 4;
1112 ret |= sisusb_send_packet(sisusb, 6, &packet);
1113 *data |= (u16)(packet.data << 8);
1119 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1120 u32 addr, u32 *data)
1122 struct sisusb_packet packet;
1125 packet.address = addr & ~3;
1129 packet.header = (type << 6) | 0x0007;
1130 ret = sisusb_send_packet(sisusb, 6, &packet);
1131 *data = packet.data & 0x00ffffff;
1134 packet.header = (type << 6) | 0x000e;
1135 ret = sisusb_send_packet(sisusb, 6, &packet);
1136 *data = packet.data >> 8;
1139 packet.header = (type << 6) | 0x000c;
1140 ret = sisusb_send_packet(sisusb, 6, &packet);
1141 *data = packet.data >> 16;
1142 packet.header = (type << 6) | 0x0001;
1143 packet.address = (addr & ~3) + 4;
1144 ret |= sisusb_send_packet(sisusb, 6, &packet);
1145 *data |= ((packet.data & 0xff) << 16);
1148 packet.header = (type << 6) | 0x0008;
1149 ret = sisusb_send_packet(sisusb, 6, &packet);
1150 *data = packet.data >> 24;
1151 packet.header = (type << 6) | 0x0003;
1152 packet.address = (addr & ~3) + 4;
1153 ret |= sisusb_send_packet(sisusb, 6, &packet);
1154 *data |= ((packet.data & 0xffff) << 8);
1160 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1161 u32 addr, u32 *data)
1163 struct sisusb_packet packet;
1166 packet.address = addr & ~3;
1170 packet.header = (type << 6) | 0x000f;
1171 ret = sisusb_send_packet(sisusb, 6, &packet);
1172 *data = packet.data;
1175 packet.header = (type << 6) | 0x000e;
1176 ret = sisusb_send_packet(sisusb, 6, &packet);
1177 *data = packet.data >> 8;
1178 packet.header = (type << 6) | 0x0001;
1179 packet.address = (addr & ~3) + 4;
1180 ret |= sisusb_send_packet(sisusb, 6, &packet);
1181 *data |= (packet.data << 24);
1184 packet.header = (type << 6) | 0x000c;
1185 ret = sisusb_send_packet(sisusb, 6, &packet);
1186 *data = packet.data >> 16;
1187 packet.header = (type << 6) | 0x0003;
1188 packet.address = (addr & ~3) + 4;
1189 ret |= sisusb_send_packet(sisusb, 6, &packet);
1190 *data |= (packet.data << 16);
1193 packet.header = (type << 6) | 0x0008;
1194 ret = sisusb_send_packet(sisusb, 6, &packet);
1195 *data = packet.data >> 24;
1196 packet.header = (type << 6) | 0x0007;
1197 packet.address = (addr & ~3) + 4;
1198 ret |= sisusb_send_packet(sisusb, 6, &packet);
1199 *data |= (packet.data << 8);
1205 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1206 char *kernbuffer, int length,
1207 char __user *userbuffer, ssize_t *bytes_read)
1216 length &= 0x00ffffff;
1224 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1229 if (put_user(buf[0],
1230 (u8 __user *)userbuffer)) {
1234 kernbuffer[0] = buf[0];
1240 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1245 if (put_user(swap16,
1246 (u16 __user *)userbuffer))
1249 *((u16 *)kernbuffer) = swap16;
1255 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1260 buf[0] = (swap32 >> 16) & 0xff;
1261 buf[1] = (swap32 >> 8) & 0xff;
1262 buf[2] = swap32 & 0xff;
1264 buf[2] = (swap32 >> 16) & 0xff;
1265 buf[1] = (swap32 >> 8) & 0xff;
1266 buf[0] = swap32 & 0xff;
1269 if (copy_to_user(userbuffer, &buf[0], 3))
1272 kernbuffer[0] = buf[0];
1273 kernbuffer[1] = buf[1];
1274 kernbuffer[2] = buf[2];
1280 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1285 if (put_user(swap32,
1286 (u32 __user *)userbuffer))
1291 *((u32 *)kernbuffer) = swap32;
1297 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1299 CLEARPACKET(&packet);
1300 packet.header = 0x001f;
1301 packet.address = 0x000001a0;
1302 packet.data = 0x00000006;
1303 ret |= sisusb_send_bridge_packet(sisusb, 10,
1305 packet.header = 0x001f;
1306 packet.address = 0x000001b0;
1307 packet.data = (length & ~3) | 0x40000000;
1308 ret |= sisusb_send_bridge_packet(sisusb, 10,
1310 packet.header = 0x001f;
1311 packet.address = 0x000001b4;
1313 ret |= sisusb_send_bridge_packet(sisusb, 10,
1315 packet.header = 0x001f;
1316 packet.address = 0x000001a4;
1317 packet.data = 0x00000001;
1318 ret |= sisusb_send_bridge_packet(sisusb, 10,
1321 ret |= sisusb_recv_bulk_msg(sisusb,
1322 SISUSB_EP_GFX_BULK_IN,
1326 if (!ret) userbuffer += (*bytes_read);
1328 ret |= sisusb_recv_bulk_msg(sisusb,
1329 SISUSB_EP_GFX_BULK_IN,
1333 if (!ret) kernbuffer += (*bytes_read);
1335 addr += (*bytes_read);
1336 length -= (*bytes_read);
1347 /* High level: Gfx (indexed) register access */
1349 #ifdef INCL_SISUSB_CON
1351 sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1353 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1357 sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1359 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1363 #ifndef INCL_SISUSB_CON
1367 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1370 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1371 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1375 #ifndef INCL_SISUSB_CON
1379 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1382 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1383 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1387 #ifndef INCL_SISUSB_CON
1391 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1397 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1398 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1401 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1406 sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1411 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1412 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1414 tmp |= (data & mask);
1415 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1419 #ifndef INCL_SISUSB_CON
1423 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1425 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1428 #ifndef INCL_SISUSB_CON
1432 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1434 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1437 /* Write/read video ram */
1439 #ifdef INCL_SISUSB_CON
1441 sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1443 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1447 sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1449 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1453 sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
1455 return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1459 sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
1461 return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1465 sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1466 u32 dest, int length, size_t *bytes_written)
1468 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1471 #ifdef SISUSBENDIANTEST
1473 sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1474 u32 src, int length, size_t *bytes_written)
1476 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1481 #ifdef SISUSBENDIANTEST
1483 sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1485 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1486 char destbuffer[10];
1490 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1492 for(i = 1; i <= 7; i++) {
1493 printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
1494 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1495 for(j = 0; j < i; j++) {
1496 printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
1502 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1505 sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
1507 struct sisusb_packet packet;
1510 packet.header = 0x008f;
1511 packet.address = regnum | 0x10000;
1513 ret = sisusb_send_packet(sisusb, 10, &packet);
1518 sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
1520 struct sisusb_packet packet;
1523 packet.header = 0x008f;
1524 packet.address = (u32)regnum | 0x10000;
1525 ret = sisusb_send_packet(sisusb, 6, &packet);
1526 *data = packet.data;
1530 /* Clear video RAM */
1533 sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
1538 if (address < sisusb->vrambase)
1541 if (address >= sisusb->vrambase + sisusb->vramsize)
1544 if (address + length > sisusb->vrambase + sisusb->vramsize)
1545 length = sisusb->vrambase + sisusb->vramsize - address;
1550 /* allocate free buffer/urb and clear the buffer */
1551 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1554 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1556 /* We can write a length > buffer size here. The buffer
1557 * data will simply be re-used (like a ring-buffer).
1559 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1561 /* Free the buffer/urb */
1562 sisusb_free_outbuf(sisusb, i);
1567 /* Initialize the graphics core (return 0 on success)
1568 * This resets the graphics hardware and puts it into
1569 * a defined mode (640x480@60Hz)
1572 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1573 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1574 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1575 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1576 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1577 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1578 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1579 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1580 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1581 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1582 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1585 sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1590 ret = GETIREG(SISSR, 0x16, &tmp8);
1593 ret |= SETIREG(SISSR, 0x16, tmp8);
1595 ret |= SETIREG(SISSR, 0x16, tmp8);
1598 ret |= SETIREG(SISSR, 0x16, tmp8);
1600 ret |= SETIREG(SISSR, 0x16, tmp8);
1602 ret |= SETIREG(SISSR, 0x16, tmp8);
1604 ret |= SETIREG(SISSR, 0x16, tmp8);
1606 ret |= SETIREG(SISSR, 0x16, tmp8);
1608 ret |= SETIREG(SISSR, 0x16, tmp8);
1610 ret |= SETIREG(SISSR, 0x16, tmp8);
1616 sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
1619 u8 ramtype, done = 0;
1621 u32 ramptr = SISUSB_PCI_MEMBASE;
1623 ret = GETIREG(SISSR, 0x3a, &ramtype);
1626 ret |= SETIREG(SISSR, 0x13, 0x00);
1629 ret |= SETIREG(SISSR, 0x14, 0x12);
1630 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1632 ret |= SETIREG(SISSR, 0x14, 0x02);
1635 ret |= sisusb_triggersr16(sisusb, ramtype);
1636 ret |= WRITEL(ramptr + 0, 0x01234567);
1637 ret |= WRITEL(ramptr + 4, 0x456789ab);
1638 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1639 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1640 ret |= WRITEL(ramptr + 16, 0x55555555);
1641 ret |= WRITEL(ramptr + 20, 0x55555555);
1642 ret |= WRITEL(ramptr + 24, 0xffffffff);
1643 ret |= WRITEL(ramptr + 28, 0xffffffff);
1644 ret |= READL(ramptr + 0, &t0);
1645 ret |= READL(ramptr + 4, &t1);
1646 ret |= READL(ramptr + 8, &t2);
1647 ret |= READL(ramptr + 12, &t3);
1651 *chab = 0; *bw = 64;
1653 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1654 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1655 *chab = 0; *bw = 64;
1656 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1659 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1660 *chab = 1; *bw = 64;
1661 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
1663 ret |= sisusb_triggersr16(sisusb, ramtype);
1664 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1665 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1666 ret |= WRITEL(ramptr + 8, 0x55555555);
1667 ret |= WRITEL(ramptr + 12, 0x55555555);
1668 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1669 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1670 ret |= READL(ramptr + 4, &t1);
1672 if (t1 != 0xcdef0123) {
1674 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1680 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1684 if (t1 == 0x456789ab) {
1685 if (t0 == 0x01234567) {
1686 *chab = 0; *bw = 64;
1690 if (t0 == 0x01234567) {
1691 *chab = 0; *bw = 32;
1692 ret |= SETIREG(SISSR, 0x14, 0x00);
1698 ret |= SETIREG(SISSR, 0x14, 0x03);
1699 ret |= sisusb_triggersr16(sisusb, ramtype);
1701 ret |= WRITEL(ramptr + 0, 0x01234567);
1702 ret |= WRITEL(ramptr + 4, 0x456789ab);
1703 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1704 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1705 ret |= WRITEL(ramptr + 16, 0x55555555);
1706 ret |= WRITEL(ramptr + 20, 0x55555555);
1707 ret |= WRITEL(ramptr + 24, 0xffffffff);
1708 ret |= WRITEL(ramptr + 28, 0xffffffff);
1709 ret |= READL(ramptr + 0, &t0);
1710 ret |= READL(ramptr + 4, &t1);
1712 if (t1 == 0x456789ab) {
1713 if (t0 == 0x01234567) {
1714 *chab = 1; *bw = 64;
1718 if (t0 == 0x01234567) {
1719 *chab = 1; *bw = 32;
1720 ret |= SETIREG(SISSR, 0x14, 0x01);
1729 sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1732 u32 ramptr = SISUSB_PCI_MEMBASE;
1733 u8 tmp1, tmp2, i, j;
1735 ret |= WRITEB(ramptr, 0xaa);
1736 ret |= WRITEB(ramptr + 16, 0x55);
1737 ret |= READB(ramptr, &tmp1);
1738 ret |= READB(ramptr + 16, &tmp2);
1739 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1740 for (i = 0, j = 16; i < 2; i++, j += 16) {
1741 ret |= GETIREG(SISSR, 0x21, &tmp1);
1742 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1743 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1744 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1745 ret |= SETIREG(SISSR, 0x21, tmp1);
1746 ret |= WRITEB(ramptr + 16 + j, j);
1747 ret |= READB(ramptr + 16 + j, &tmp1);
1749 ret |= WRITEB(ramptr + j, j);
1758 sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
1759 u8 rankno, u8 chab, const u8 dramtype[][5],
1762 int ret = 0, ranksize;
1767 if ((rankno == 2) && (dramtype[index][0] == 2))
1770 ranksize = dramtype[index][3] / 2 * bw / 32;
1772 if ((ranksize * rankno) > 128)
1776 while ((ranksize >>= 1) > 0) tmp += 0x10;
1777 tmp |= ((rankno - 1) << 2);
1778 tmp |= ((bw / 64) & 0x02);
1779 tmp |= (chab & 0x01);
1781 ret = SETIREG(SISSR, 0x14, tmp);
1782 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1790 sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
1797 for (i = 0, j = 0; i < testn; i++) {
1798 ret |= WRITEL(sisusb->vrambase + j, j);
1802 for (i = 0, j = 0; i < testn; i++) {
1803 ret |= READL(sisusb->vrambase + j, &tmp);
1804 if (tmp != j) return ret;
1813 sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
1814 int idx, int bw, const u8 rtype[][5])
1816 int ret = 0, i, i2ret;
1821 for (i = rankno; i >= 1; i--) {
1822 inc = 1 << (rtype[idx][2] +
1826 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1831 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1832 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1836 inc = 1 << (10 + bw / 64);
1837 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1846 sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
1849 int ret = 0, i2ret = 0, i, j;
1850 static const u8 sdramtype[13][5] = {
1851 { 2, 12, 9, 64, 0x35 },
1852 { 1, 13, 9, 64, 0x44 },
1853 { 2, 12, 8, 32, 0x31 },
1854 { 2, 11, 9, 32, 0x25 },
1855 { 1, 12, 9, 32, 0x34 },
1856 { 1, 13, 8, 32, 0x40 },
1857 { 2, 11, 8, 16, 0x21 },
1858 { 1, 12, 8, 16, 0x30 },
1859 { 1, 11, 9, 16, 0x24 },
1860 { 1, 11, 8, 8, 0x20 },
1861 { 2, 9, 8, 4, 0x01 },
1862 { 1, 10, 8, 4, 0x10 },
1863 { 1, 9, 8, 2, 0x00 }
1866 *iret = 1; /* error */
1868 for (i = 0; i < 13; i++) {
1869 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1870 for (j = 2; j > 0; j--) {
1871 ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
1872 chab, sdramtype, bw);
1876 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
1879 *iret = 0; /* ram size found */
1889 sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
1893 int i, length, modex, modey, bpp;
1895 modex = 640; modey = 480; bpp = 2;
1897 address = sisusb->vrambase; /* Clear video ram */
1900 length = sisusb->vramsize;
1902 length = modex * bpp * modey;
1904 ret = sisusb_clear_vram(sisusb, address, length);
1906 if (!ret && drwfr) {
1907 for (i = 0; i < modex; i++) {
1908 address = sisusb->vrambase + (i * bpp);
1909 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1911 address += (modex * (modey-1) * bpp);
1912 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1915 for (i = 0; i < modey; i++) {
1916 address = sisusb->vrambase + ((i * modex) * bpp);
1917 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1919 address += ((modex - 1) * bpp);
1920 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1929 sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
1931 int ret = 0, i, j, modex, modey, bpp, du;
1932 u8 sr31, cr63, tmp8;
1933 static const char attrdata[] = {
1934 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1935 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1938 static const char crtcrdata[] = {
1939 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1940 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1941 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1944 static const char grcdata[] = {
1945 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1948 static const char crtcdata[] = {
1949 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1950 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1954 modex = 640; modey = 480; bpp = 2;
1956 GETIREG(SISSR, 0x31, &sr31);
1957 GETIREG(SISCR, 0x63, &cr63);
1958 SETIREGOR(SISSR, 0x01, 0x20);
1959 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1960 SETIREGOR(SISCR, 0x17, 0x80);
1961 SETIREGOR(SISSR, 0x1f, 0x04);
1962 SETIREGAND(SISSR, 0x07, 0xfb);
1963 SETIREG(SISSR, 0x00, 0x03); /* seq */
1964 SETIREG(SISSR, 0x01, 0x21);
1965 SETIREG(SISSR, 0x02, 0x0f);
1966 SETIREG(SISSR, 0x03, 0x00);
1967 SETIREG(SISSR, 0x04, 0x0e);
1968 SETREG(SISMISCW, 0x23); /* misc */
1969 for (i = 0; i <= 0x18; i++) { /* crtc */
1970 SETIREG(SISCR, i, crtcrdata[i]);
1972 for (i = 0; i <= 0x13; i++) { /* att */
1973 GETREG(SISINPSTAT, &tmp8);
1975 SETREG(SISAR, attrdata[i]);
1977 GETREG(SISINPSTAT, &tmp8);
1978 SETREG(SISAR, 0x14);
1979 SETREG(SISAR, 0x00);
1980 GETREG(SISINPSTAT, &tmp8);
1981 SETREG(SISAR, 0x20);
1982 GETREG(SISINPSTAT, &tmp8);
1983 for (i = 0; i <= 0x08; i++) { /* grc */
1984 SETIREG(SISGR, i, grcdata[i]);
1986 SETIREGAND(SISGR, 0x05, 0xbf);
1987 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1988 SETIREG(SISSR, i, 0x00);
1990 SETIREGAND(SISSR, 0x37, 0xfe);
1991 SETREG(SISMISCW, 0xef); /* sync */
1992 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1993 for (j = 0x00, i = 0; i <= 7; i++, j++) {
1994 SETIREG(SISCR, j, crtcdata[i]);
1996 for (j = 0x10; i <= 10; i++, j++) {
1997 SETIREG(SISCR, j, crtcdata[i]);
1999 for (j = 0x15; i <= 12; i++, j++) {
2000 SETIREG(SISCR, j, crtcdata[i]);
2002 for (j = 0x0A; i <= 15; i++, j++) {
2003 SETIREG(SISSR, j, crtcdata[i]);
2005 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
2006 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
2007 SETIREG(SISCR, 0x14, 0x4f);
2008 du = (modex / 16) * (bpp * 2); /* offset/pitch */
2009 if (modex % 16) du += bpp;
2010 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
2011 SETIREG(SISCR, 0x13, (du & 0xff));
2014 if (du & 0xff) tmp8++;
2015 SETIREG(SISSR, 0x10, tmp8);
2016 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
2017 SETIREG(SISSR, 0x2b, 0x1b);
2018 SETIREG(SISSR, 0x2c, 0xe1);
2019 SETIREG(SISSR, 0x2d, 0x01);
2020 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
2021 SETIREG(SISSR, 0x08, 0xae);
2022 SETIREGAND(SISSR, 0x09, 0xf0);
2023 SETIREG(SISSR, 0x08, 0x34);
2024 SETIREGOR(SISSR, 0x3d, 0x01);
2025 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
2026 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
2027 SETIREG(SISCR, 0x19, 0x00);
2028 SETIREGAND(SISCR, 0x1a, 0xfc);
2029 SETIREGAND(SISSR, 0x0f, 0xb7);
2030 SETIREGAND(SISSR, 0x31, 0xfb);
2031 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
2032 SETIREGAND(SISSR, 0x32, 0xf3);
2033 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
2034 SETIREG(SISCR, 0x52, 0x6c);
2036 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
2037 SETIREG(SISCR, 0x0c, 0x00);
2038 SETIREG(SISSR, 0x0d, 0x00);
2039 SETIREGAND(SISSR, 0x37, 0xfe);
2041 SETIREG(SISCR, 0x32, 0x20);
2042 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
2043 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
2044 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
2047 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
2048 SETIREGOR(SISSR, 0x1e, 0x5a);
2050 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
2051 SETIREG(SISSR, 0x27, 0x1f);
2052 SETIREG(SISSR, 0x26, 0x00);
2055 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
2061 sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
2063 int ret = 0, i, j, bw, chab, iret, retry = 3;
2066 static const char mclktable[] = {
2067 0x3b, 0x22, 0x01, 143,
2068 0x3b, 0x22, 0x01, 143,
2069 0x3b, 0x22, 0x01, 143,
2070 0x3b, 0x22, 0x01, 143
2072 static const char eclktable[] = {
2073 0x3b, 0x22, 0x01, 143,
2074 0x3b, 0x22, 0x01, 143,
2075 0x3b, 0x22, 0x01, 143,
2076 0x3b, 0x22, 0x01, 143
2078 static const char ramtypetable1[] = {
2079 0x00, 0x04, 0x60, 0x60,
2080 0x0f, 0x0f, 0x1f, 0x1f,
2081 0xba, 0xba, 0xba, 0xba,
2082 0xa9, 0xa9, 0xac, 0xac,
2083 0xa0, 0xa0, 0xa0, 0xa8,
2084 0x00, 0x00, 0x02, 0x02,
2085 0x30, 0x30, 0x40, 0x40
2087 static const char ramtypetable2[] = {
2088 0x77, 0x77, 0x44, 0x44,
2089 0x77, 0x77, 0x44, 0x44,
2090 0x00, 0x00, 0x00, 0x00,
2091 0x5b, 0x5b, 0xab, 0xab,
2092 0x00, 0x00, 0xf0, 0xf8
2098 ret = GETREG(SISVGAEN, &tmp8);
2099 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
2101 /* Enable GPU access to VRAM */
2102 ret |= GETREG(SISMISCR, &tmp8);
2103 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
2107 /* Reset registers */
2108 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
2109 ret |= SETIREG(SISSR, 0x05, 0x86);
2110 ret |= SETIREGOR(SISSR, 0x20, 0x01);
2112 ret |= SETREG(SISMISCW, 0x67);
2114 for (i = 0x06; i <= 0x1f; i++) {
2115 ret |= SETIREG(SISSR, i, 0x00);
2117 for (i = 0x21; i <= 0x27; i++) {
2118 ret |= SETIREG(SISSR, i, 0x00);
2120 for (i = 0x31; i <= 0x3d; i++) {
2121 ret |= SETIREG(SISSR, i, 0x00);
2123 for (i = 0x12; i <= 0x1b; i++) {
2124 ret |= SETIREG(SISSR, i, 0x00);
2126 for (i = 0x79; i <= 0x7c; i++) {
2127 ret |= SETIREG(SISCR, i, 0x00);
2132 ret |= SETIREG(SISCR, 0x63, 0x80);
2134 ret |= GETIREG(SISSR, 0x3a, &ramtype);
2137 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
2138 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
2139 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
2141 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
2142 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
2143 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
2145 ret |= SETIREG(SISSR, 0x07, 0x18);
2146 ret |= SETIREG(SISSR, 0x11, 0x0f);
2150 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
2151 ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
2153 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
2154 ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
2157 ret |= SETIREG(SISCR, 0x49, 0xaa);
2159 ret |= SETIREG(SISSR, 0x1f, 0x00);
2160 ret |= SETIREG(SISSR, 0x20, 0xa0);
2161 ret |= SETIREG(SISSR, 0x23, 0xf6);
2162 ret |= SETIREG(SISSR, 0x24, 0x0d);
2163 ret |= SETIREG(SISSR, 0x25, 0x33);
2165 ret |= SETIREG(SISSR, 0x11, 0x0f);
2167 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
2169 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2173 ret |= SETIREG(SISPART1, 0x00, 0x00);
2175 ret |= GETIREG(SISSR, 0x13, &tmp8);
2178 ret |= SETIREG(SISPART1, 0x02, 0x00);
2179 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2181 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2182 tmp32 &= 0x00f00000;
2183 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2184 ret |= SETIREG(SISSR, 0x25, tmp8);
2185 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2186 ret |= SETIREG(SISCR, 0x49, tmp8);
2188 ret |= SETIREG(SISSR, 0x27, 0x1f);
2189 ret |= SETIREG(SISSR, 0x31, 0x00);
2190 ret |= SETIREG(SISSR, 0x32, 0x11);
2191 ret |= SETIREG(SISSR, 0x33, 0x00);
2195 ret |= SETIREG(SISCR, 0x83, 0x00);
2197 ret |= sisusb_set_default_mode(sisusb, 0);
2199 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2200 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2201 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2203 ret |= sisusb_triggersr16(sisusb, ramtype);
2205 /* Disable refresh */
2206 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2207 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2209 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2210 ret |= sisusb_verify_mclk(sisusb);
2213 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2215 printk(KERN_ERR "sisusbvga[%d]: RAM size "
2216 "detection failed, "
2217 "assuming 8MB video RAM\n",
2219 ret |= SETIREG(SISSR,0x14,0x31);
2223 printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
2224 "assuming 8MB video RAM\n",
2226 ret |= SETIREG(SISSR,0x14,0x31);
2230 /* Enable refresh */
2231 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2232 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2233 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2235 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2237 ret |= SETIREG(SISSR, 0x22, 0xfb);
2238 ret |= SETIREG(SISSR, 0x21, 0xa5);
2258 sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2260 u8 tmp8, tmp82, ramtype;
2262 char *ramtypetext1 = NULL;
2263 const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
2264 "DDR SDRAM", "DDR SGRAM" };
2265 static const int busSDR[4] = {64, 64, 128, 128};
2266 static const int busDDR[4] = {32, 32, 64, 64};
2267 static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2269 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2270 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2271 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2272 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2274 switch ((tmp8 >> 2) & 0x03) {
2275 case 0: ramtypetext1 = "1 ch/1 r";
2279 bw = busSDR[(tmp8 & 0x03)];
2282 case 1: ramtypetext1 = "1 ch/2 r";
2283 sisusb->vramsize <<= 1;
2284 bw = busSDR[(tmp8 & 0x03)];
2286 case 2: ramtypetext1 = "asymmeric";
2287 sisusb->vramsize += sisusb->vramsize/2;
2288 bw = busDDRA[(tmp8 & 0x03)];
2290 case 3: ramtypetext1 = "2 channel";
2291 sisusb->vramsize <<= 1;
2292 bw = busDDR[(tmp8 & 0x03)];
2296 printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2297 sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
2298 ramtypetext2[ramtype], bw);
2302 sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2304 struct sisusb_packet packet;
2309 packet.header = 0x001f;
2310 packet.address = 0x00000324;
2311 packet.data = 0x00000004;
2312 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2314 packet.header = 0x001f;
2315 packet.address = 0x00000364;
2316 packet.data = 0x00000004;
2317 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2319 packet.header = 0x001f;
2320 packet.address = 0x00000384;
2321 packet.data = 0x00000004;
2322 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2324 packet.header = 0x001f;
2325 packet.address = 0x00000100;
2326 packet.data = 0x00000700;
2327 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2329 packet.header = 0x000f;
2330 packet.address = 0x00000004;
2331 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2332 packet.data |= 0x17;
2333 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2335 /* Init BAR 0 (VRAM) */
2336 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2337 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2338 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2340 tmp32 |= SISUSB_PCI_MEMBASE;
2341 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2343 /* Init BAR 1 (MMIO) */
2344 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2345 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2346 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2348 tmp32 |= SISUSB_PCI_MMIOBASE;
2349 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2351 /* Init BAR 2 (i/o ports) */
2352 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2353 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2354 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2356 tmp32 |= SISUSB_PCI_IOPORTBASE;
2357 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2359 /* Enable memory and i/o access */
2360 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2362 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2365 /* Some further magic */
2366 packet.header = 0x001f;
2367 packet.address = 0x00000050;
2368 packet.data = 0x000000ff;
2369 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2375 /* Initialize the graphics device (return 0 on success)
2376 * This initializes the net2280 as well as the PCI registers
2377 * of the graphics board.
2381 sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2383 int ret = 0, test = 0;
2386 if (sisusb->devinit == 1) {
2387 /* Read PCI BARs and see if they have been set up */
2388 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2389 if (ret) return ret;
2390 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2392 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2393 if (ret) return ret;
2394 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2396 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2397 if (ret) return ret;
2398 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2401 /* No? So reset the device */
2402 if ((sisusb->devinit == 0) || (test != 3)) {
2404 ret |= sisusb_do_init_gfxdevice(sisusb);
2407 sisusb->devinit = 1;
2411 if (sisusb->devinit) {
2412 /* Initialize the graphics core */
2413 if (sisusb_init_gfxcore(sisusb) == 0) {
2414 sisusb->gfxinit = 1;
2415 sisusb_get_ramconfig(sisusb);
2416 ret |= sisusb_set_default_mode(sisusb, 1);
2417 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2425 #ifdef INCL_SISUSB_CON
2427 /* Set up default text mode:
2428 - Set text mode (0x03)
2429 - Upload default font
2430 - Upload user font (if available)
2434 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2436 int ret = 0, slot = sisusb->font_slot, i;
2437 const struct font_desc *myfont;
2441 static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2442 static const char bootlogo[] = "(o_ //\\ V_/_";
2444 /* sisusb->lock is down */
2446 if (!sisusb->SiS_Pr)
2449 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2450 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2453 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2455 if (!(myfont = find_font("VGA8x16")))
2458 if (!(tempbuf = vmalloc(8192)))
2461 for (i = 0; i < 256; i++)
2462 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2464 /* Upload default font */
2465 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2469 /* Upload user font (and reset current slot) */
2470 if (sisusb->font_backup) {
2471 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2472 8192, sisusb->font_backup_512, 1, NULL,
2473 sisusb->font_backup_height, 0);
2475 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2479 if (init && !sisusb->scrbuf) {
2481 if ((tempbuf = vmalloc(8192))) {
2484 tempbufb = (u16 *)tempbuf;
2486 *(tempbufb++) = 0x0720;
2489 tempbufb = (u16 *)tempbuf;
2490 while (bootlogo[i]) {
2491 *(tempbufb++) = 0x0700 | bootlogo[i++];
2497 tempbufb = (u16 *)tempbuf + 6;
2498 while (bootstring[i])
2499 *(tempbufb++) = 0x0700 | bootstring[i++];
2501 ret |= sisusb_copy_memory(sisusb, tempbuf,
2502 sisusb->vrambase, 8192, &written);
2508 } else if (sisusb->scrbuf) {
2510 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2511 sisusb->vrambase, sisusb->scrbuf_size, &written);
2515 if (sisusb->sisusb_cursor_size_from >= 0 &&
2516 sisusb->sisusb_cursor_size_to >= 0) {
2517 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2518 sisusb->sisusb_cursor_size_from);
2519 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2520 sisusb->sisusb_cursor_size_to);
2522 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2523 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2524 sisusb->sisusb_cursor_size_to = -1;
2527 slot = sisusb->sisusb_cursor_loc;
2528 if(slot < 0) slot = 0;
2530 sisusb->sisusb_cursor_loc = -1;
2531 sisusb->bad_cursor_pos = 1;
2533 sisusb_set_cursor(sisusb, slot);
2535 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2536 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2538 sisusb->textmodedestroyed = 0;
2540 /* sisusb->lock is down */
2550 sisusb_open(struct inode *inode, struct file *file)
2552 struct sisusb_usb_data *sisusb;
2553 struct usb_interface *interface;
2554 int subminor = iminor(inode);
2556 mutex_lock(&disconnect_mutex);
2558 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2559 printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
2561 mutex_unlock(&disconnect_mutex);
2565 if (!(sisusb = usb_get_intfdata(interface))) {
2566 mutex_unlock(&disconnect_mutex);
2570 mutex_lock(&sisusb->lock);
2572 if (!sisusb->present || !sisusb->ready) {
2573 mutex_unlock(&sisusb->lock);
2574 mutex_unlock(&disconnect_mutex);
2578 if (sisusb->isopen) {
2579 mutex_unlock(&sisusb->lock);
2580 mutex_unlock(&disconnect_mutex);
2584 if (!sisusb->devinit) {
2585 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2586 if (sisusb_init_gfxdevice(sisusb, 0)) {
2587 mutex_unlock(&sisusb->lock);
2588 mutex_unlock(&disconnect_mutex);
2590 "sisusbvga[%d]: Failed to initialize "
2596 mutex_unlock(&sisusb->lock);
2597 mutex_unlock(&disconnect_mutex);
2599 "sisusbvga[%d]: Device not attached to "
2606 /* Increment usage count for our sisusb */
2607 kref_get(&sisusb->kref);
2611 file->private_data = sisusb;
2613 mutex_unlock(&sisusb->lock);
2615 mutex_unlock(&disconnect_mutex);
2621 sisusb_delete(struct kref *kref)
2623 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2628 if (sisusb->sisusb_dev)
2629 usb_put_dev(sisusb->sisusb_dev);
2631 sisusb->sisusb_dev = NULL;
2632 sisusb_free_buffers(sisusb);
2633 sisusb_free_urbs(sisusb);
2634 #ifdef INCL_SISUSB_CON
2635 kfree(sisusb->SiS_Pr);
2641 sisusb_release(struct inode *inode, struct file *file)
2643 struct sisusb_usb_data *sisusb;
2646 mutex_lock(&disconnect_mutex);
2648 if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
2649 mutex_unlock(&disconnect_mutex);
2653 mutex_lock(&sisusb->lock);
2655 if (sisusb->present) {
2656 /* Wait for all URBs to finish if device still present */
2657 if (!sisusb_wait_all_out_complete(sisusb))
2658 sisusb_kill_all_busy(sisusb);
2661 myminor = sisusb->minor;
2664 file->private_data = NULL;
2666 mutex_unlock(&sisusb->lock);
2668 /* decrement the usage count on our device */
2669 kref_put(&sisusb->kref, sisusb_delete);
2671 mutex_unlock(&disconnect_mutex);
2677 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2679 struct sisusb_usb_data *sisusb;
2680 ssize_t bytes_read = 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 read. As this
2706 * emulates inX instructions, the data returned is
2707 * in machine-endianness.
2712 if (sisusb_read_memio_byte(sisusb,
2716 else if (put_user(buf8, (u8 __user *)buffer))
2724 if (sisusb_read_memio_word(sisusb,
2728 else if (put_user(buf16, (u16 __user *)buffer))
2736 if (sisusb_read_memio_long(sisusb,
2740 else if (put_user(buf32, (u32 __user *)buffer))
2752 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2753 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2756 SISUSB_PCI_PSEUDO_MEMBASE +
2760 * Remember: Data delivered is never endian-corrected
2762 errno = sisusb_read_mem_bulk(sisusb, address,
2763 NULL, count, buffer, &bytes_read);
2768 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2769 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2772 SISUSB_PCI_PSEUDO_MMIOBASE +
2773 SISUSB_PCI_MMIOBASE;
2776 * Remember: Data delivered is never endian-corrected
2778 errno = sisusb_read_mem_bulk(sisusb, address,
2779 NULL, count, buffer, &bytes_read);
2784 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2785 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2788 mutex_unlock(&sisusb->lock);
2792 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2794 /* Read PCI config register
2795 * Return value delivered in machine endianness.
2797 if (sisusb_read_pci_config(sisusb, address, &buf32))
2799 else if (put_user(buf32, (u32 __user *)buffer))
2810 (*ppos) += bytes_read;
2812 mutex_unlock(&sisusb->lock);
2814 return errno ? errno : bytes_read;
2818 sisusb_write(struct file *file, const char __user *buffer, size_t count,
2821 struct sisusb_usb_data *sisusb;
2823 ssize_t bytes_written = 0;
2828 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2831 mutex_lock(&sisusb->lock);
2834 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2835 mutex_unlock(&sisusb->lock);
2839 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2840 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2843 SISUSB_PCI_PSEUDO_IOPORTBASE +
2844 SISUSB_PCI_IOPORTBASE;
2847 * Byte, word and long(32) can be written. As this
2848 * emulates outX instructions, the data is expected
2849 * in machine-endianness.
2854 if (get_user(buf8, (u8 __user *)buffer))
2856 else if (sisusb_write_memio_byte(sisusb,
2866 if (get_user(buf16, (u16 __user *)buffer))
2868 else if (sisusb_write_memio_word(sisusb,
2878 if (get_user(buf32, (u32 __user *)buffer))
2880 else if (sisusb_write_memio_long(sisusb,
2893 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2894 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2897 SISUSB_PCI_PSEUDO_MEMBASE +
2901 * Buffer is copied 1:1, therefore, on big-endian
2902 * machines, the data must be swapped by userland
2903 * in advance (if applicable; no swapping in 8bpp
2904 * mode or if YUV data is being transferred).
2906 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2907 count, buffer, 0, &bytes_written);
2910 errno = bytes_written;
2912 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2913 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2916 SISUSB_PCI_PSEUDO_MMIOBASE +
2917 SISUSB_PCI_MMIOBASE;
2920 * Buffer is copied 1:1, therefore, on big-endian
2921 * machines, the data must be swapped by userland
2924 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2925 count, buffer, 0, &bytes_written);
2928 errno = bytes_written;
2930 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2931 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2934 mutex_unlock(&sisusb->lock);
2938 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2940 /* Write PCI config register.
2941 * Given value expected in machine endianness.
2943 if (get_user(buf32, (u32 __user *)buffer))
2945 else if (sisusb_write_pci_config(sisusb, address, buf32))
2958 (*ppos) += bytes_written;
2960 mutex_unlock(&sisusb->lock);
2962 return errno ? errno : bytes_written;
2966 sisusb_lseek(struct file *file, loff_t offset, int orig)
2968 struct sisusb_usb_data *sisusb;
2971 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2974 mutex_lock(&sisusb->lock);
2977 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2978 mutex_unlock(&sisusb->lock);
2984 file->f_pos = offset;
2986 /* never negative, no force_successful_syscall needed */
2989 file->f_pos += offset;
2991 /* never negative, no force_successful_syscall needed */
2994 /* seeking relative to "end of file" is not supported */
2998 mutex_unlock(&sisusb->lock);
3003 sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
3006 int retval, port, length;
3009 /* All our commands require the device
3010 * to be initialized.
3012 if (!sisusb->devinit)
3016 SISUSB_PCI_PSEUDO_IOPORTBASE +
3017 SISUSB_PCI_IOPORTBASE;
3019 switch (y->operation) {
3021 retval = sisusb_getidxreg(sisusb, port,
3022 y->data0, &y->data1);
3024 if (copy_to_user((void __user *)arg, y,
3031 retval = sisusb_setidxreg(sisusb, port,
3032 y->data0, y->data1);
3036 retval = sisusb_setidxregor(sisusb, port,
3037 y->data0, y->data1);
3041 retval = sisusb_setidxregand(sisusb, port,
3042 y->data0, y->data1);
3045 case SUCMD_SETANDOR:
3046 retval = sisusb_setidxregandor(sisusb, port,
3047 y->data0, y->data1, y->data2);
3051 retval = sisusb_setidxregmask(sisusb, port,
3052 y->data0, y->data1, y->data2);
3056 /* Gfx core must be initialized */
3057 if (!sisusb->gfxinit)
3060 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
3061 address = y->data3 -
3062 SISUSB_PCI_PSEUDO_MEMBASE +
3064 retval = sisusb_clear_vram(sisusb, address, length);
3067 case SUCMD_HANDLETEXTMODE:
3069 #ifdef INCL_SISUSB_CON
3070 /* Gfx core must be initialized, SiS_Pr must exist */
3071 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3076 retval = sisusb_reset_text_mode(sisusb, 0);
3079 sisusb->textmodedestroyed = 1;
3085 #ifdef INCL_SISUSB_CON
3087 /* Gfx core must be initialized, SiS_Pr must exist */
3088 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3093 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3094 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3096 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
3101 case SUCMD_SETVESAMODE:
3102 /* Gfx core must be initialized, SiS_Pr must exist */
3103 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3108 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3109 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3111 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
3128 sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
3131 struct sisusb_usb_data *sisusb;
3132 struct sisusb_info x;
3133 struct sisusb_command y;
3135 u32 __user *argp = (u32 __user *)arg;
3137 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
3140 mutex_lock(&sisusb->lock);
3143 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
3150 case SISUSB_GET_CONFIG_SIZE:
3152 if (put_user(sizeof(x), argp))
3157 case SISUSB_GET_CONFIG:
3159 x.sisusb_id = SISUSB_ID;
3160 x.sisusb_version = SISUSB_VERSION;
3161 x.sisusb_revision = SISUSB_REVISION;
3162 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3163 x.sisusb_gfxinit = sisusb->gfxinit;
3164 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
3165 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
3166 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
3167 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
3168 x.sisusb_vramsize = sisusb->vramsize;
3169 x.sisusb_minor = sisusb->minor;
3170 x.sisusb_fbdevactive= 0;
3171 #ifdef INCL_SISUSB_CON
3172 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3174 x.sisusb_conactive = 0;
3177 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3182 case SISUSB_COMMAND:
3184 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3187 retval = sisusb_handle_command(sisusb, &y, arg);
3197 mutex_unlock(&sisusb->lock);
3201 #ifdef SISUSB_NEW_CONFIG_COMPAT
3203 sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3208 case SISUSB_GET_CONFIG_SIZE:
3209 case SISUSB_GET_CONFIG:
3210 case SISUSB_COMMAND:
3212 retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
3217 return -ENOIOCTLCMD;
3222 static struct file_operations usb_sisusb_fops = {
3223 .owner = THIS_MODULE,
3224 .open = sisusb_open,
3225 .release = sisusb_release,
3226 .read = sisusb_read,
3227 .write = sisusb_write,
3228 .llseek = sisusb_lseek,
3229 #ifdef SISUSB_NEW_CONFIG_COMPAT
3230 .compat_ioctl = sisusb_compat_ioctl,
3232 .ioctl = sisusb_ioctl
3235 static struct usb_class_driver usb_sisusb_class = {
3236 .name = "sisusbvga%d",
3237 .fops = &usb_sisusb_fops,
3238 .minor_base = SISUSB_MINOR
3241 static int sisusb_probe(struct usb_interface *intf,
3242 const struct usb_device_id *id)
3244 struct usb_device *dev = interface_to_usbdev(intf);
3245 struct sisusb_usb_data *sisusb;
3247 const char *memfail =
3249 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3251 printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
3254 /* Allocate memory for our private */
3255 if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3257 "sisusb: Failed to allocate memory for private data\n");
3260 kref_init(&sisusb->kref);
3262 mutex_init(&(sisusb->lock));
3264 /* Register device */
3265 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3267 "sisusb: Failed to get a minor for device %d\n",
3273 sisusb->sisusb_dev = dev;
3274 sisusb->minor = intf->minor;
3275 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3276 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3277 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3278 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3279 /* Everything else is zero */
3281 /* Allocate buffers */
3282 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3283 if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3284 GFP_KERNEL, &sisusb->transfer_dma_in))) {
3285 printk(memfail, "input", sisusb->minor);
3290 sisusb->numobufs = 0;
3291 sisusb->obufsize = SISUSB_OBUF_SIZE;
3292 for (i = 0; i < NUMOBUFS; i++) {
3293 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3295 &sisusb->transfer_dma_out[i]))) {
3297 printk(memfail, "output", sisusb->minor);
3308 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3310 "sisusbvga[%d]: Failed to allocate URBs\n",
3315 sisusb->completein = 1;
3317 for (i = 0; i < sisusb->numobufs; i++) {
3318 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3320 "sisusbvga[%d]: Failed to allocate URBs\n",
3325 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3326 sisusb->urbout_context[i].urbindex = i;
3327 sisusb->urbstatus[i] = 0;
3330 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
3331 sisusb->minor, sisusb->numobufs);
3333 #ifdef INCL_SISUSB_CON
3334 /* Allocate our SiS_Pr */
3335 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3337 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3342 /* Do remaining init stuff */
3344 init_waitqueue_head(&sisusb->wait_q);
3346 usb_set_intfdata(intf, sisusb);
3348 usb_get_dev(sisusb->sisusb_dev);
3350 sisusb->present = 1;
3352 #ifdef SISUSB_OLD_CONFIG_COMPAT
3355 /* Our ioctls are all "32/64bit compatible" */
3356 ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
3357 ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
3358 ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
3361 "sisusbvga[%d]: Error registering ioctl32 "
3365 sisusb->ioctl32registered = 1;
3369 if (dev->speed == USB_SPEED_HIGH) {
3371 #ifdef INCL_SISUSB_CON
3372 if (sisusb_first_vc > 0 &&
3373 sisusb_last_vc > 0 &&
3374 sisusb_first_vc <= sisusb_last_vc &&
3375 sisusb_last_vc <= MAX_NR_CONSOLES)
3378 if (sisusb_init_gfxdevice(sisusb, initscreen))
3380 "sisusbvga[%d]: Failed to early "
3381 "initialize device\n",
3386 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3392 #ifdef SISUSBENDIANTEST
3393 printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
3394 sisusb_testreadwrite(sisusb);
3395 printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
3398 #ifdef INCL_SISUSB_CON
3399 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3405 sisusb_free_urbs(sisusb);
3407 sisusb_free_buffers(sisusb);
3409 usb_deregister_dev(intf, &usb_sisusb_class);
3415 static void sisusb_disconnect(struct usb_interface *intf)
3417 struct sisusb_usb_data *sisusb;
3420 /* This should *not* happen */
3421 if (!(sisusb = usb_get_intfdata(intf)))
3424 #ifdef INCL_SISUSB_CON
3425 sisusb_console_exit(sisusb);
3428 /* The above code doesn't need the disconnect
3429 * semaphore to be down; its meaning is to
3430 * protect all other routines from the disconnect
3431 * case, not the other way round.
3433 mutex_lock(&disconnect_mutex);
3435 mutex_lock(&sisusb->lock);
3437 /* Wait for all URBs to complete and kill them in case (MUST do) */
3438 if (!sisusb_wait_all_out_complete(sisusb))
3439 sisusb_kill_all_busy(sisusb);
3441 minor = sisusb->minor;
3443 usb_set_intfdata(intf, NULL);
3445 usb_deregister_dev(intf, &usb_sisusb_class);
3447 #ifdef SISUSB_OLD_CONFIG_COMPAT
3448 if (sisusb->ioctl32registered) {
3450 sisusb->ioctl32registered = 0;
3451 ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
3452 ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
3453 ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
3456 "sisusbvga[%d]: Error unregistering "
3457 "ioctl32 translations\n",
3463 sisusb->present = 0;
3466 mutex_unlock(&sisusb->lock);
3468 /* decrement our usage count */
3469 kref_put(&sisusb->kref, sisusb_delete);
3471 mutex_unlock(&disconnect_mutex);
3473 printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
3476 static struct usb_device_id sisusb_table [] = {
3477 { USB_DEVICE(0x0711, 0x0900) },
3478 { USB_DEVICE(0x182d, 0x021c) },
3479 { USB_DEVICE(0x182d, 0x0269) },
3483 MODULE_DEVICE_TABLE (usb, sisusb_table);
3485 static struct usb_driver sisusb_driver = {
3487 .probe = sisusb_probe,
3488 .disconnect = sisusb_disconnect,
3489 .id_table = sisusb_table,
3492 static int __init usb_sisusb_init(void)
3496 #ifdef INCL_SISUSB_CON
3497 sisusb_init_concode();
3500 if (!(retval = usb_register(&sisusb_driver))) {
3502 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
3503 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
3505 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3512 static void __exit usb_sisusb_exit(void)
3514 usb_deregister(&sisusb_driver);
3517 module_init(usb_sisusb_init);
3518 module_exit(usb_sisusb_exit);
3520 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3521 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3522 MODULE_LICENSE("GPL");