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/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/sched.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/smp_lock.h>
52 #include <linux/vmalloc.h>
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
60 #define SISUSB_DONTSYNC
62 /* Forward declarations / clean-up routines */
64 #ifdef INCL_SISUSB_CON
65 int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
66 int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
67 int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
68 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
69 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
70 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
71 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
73 int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
74 int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
75 int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
76 int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
77 int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
78 u32 dest, int length, size_t *bytes_written);
80 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
82 extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
83 extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
85 extern void sisusb_init_concode(void);
86 extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
87 extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
89 extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
91 extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
92 u8 *arg, int cmapsz, int ch512, int dorecalc,
93 struct vc_data *c, int fh, int uplock);
95 static int sisusb_first_vc = 0;
96 static int sisusb_last_vc = 0;
97 module_param_named(first, sisusb_first_vc, int, 0);
98 module_param_named(last, sisusb_last_vc, int, 0);
99 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
100 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
103 static struct usb_driver sisusb_driver;
105 DECLARE_MUTEX(disconnect_sem);
108 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
112 for (i = 0; i < NUMOBUFS; i++) {
113 if (sisusb->obuf[i]) {
114 usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
115 sisusb->obuf[i], sisusb->transfer_dma_out[i]);
116 sisusb->obuf[i] = NULL;
120 usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
121 sisusb->ibuf, sisusb->transfer_dma_in);
127 sisusb_free_urbs(struct sisusb_usb_data *sisusb)
131 for (i = 0; i < NUMOBUFS; i++) {
132 usb_free_urb(sisusb->sisurbout[i]);
133 sisusb->sisurbout[i] = NULL;
135 usb_free_urb(sisusb->sisurbin);
136 sisusb->sisurbin = NULL;
139 /* Level 0: USB transport layer */
143 /* out-urb management */
145 /* Return 1 if all free, 0 otherwise */
147 sisusb_all_free(struct sisusb_usb_data *sisusb)
151 for (i = 0; i < sisusb->numobufs; i++) {
153 if (sisusb->urbstatus[i] & SU_URB_BUSY)
161 /* Kill all busy URBs */
163 sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
167 if (sisusb_all_free(sisusb))
170 for (i = 0; i < sisusb->numobufs; i++) {
172 if (sisusb->urbstatus[i] & SU_URB_BUSY)
173 usb_kill_urb(sisusb->sisurbout[i]);
178 /* Return 1 if ok, 0 if error (not all complete within timeout) */
180 sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
182 int timeout = 5 * HZ, i = 1;
184 wait_event_timeout(sisusb->wait_q,
185 (i = sisusb_all_free(sisusb)),
192 sisusb_outurb_available(struct sisusb_usb_data *sisusb)
196 for (i = 0; i < sisusb->numobufs; i++) {
198 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
207 sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
209 int i, timeout = 5 * HZ;
211 wait_event_timeout(sisusb->wait_q,
212 ((i = sisusb_outurb_available(sisusb)) >= 0),
219 sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
223 i = sisusb_outurb_available(sisusb);
226 sisusb->urbstatus[i] |= SU_URB_ALLOC;
232 sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
234 if ((index >= 0) && (index < sisusb->numobufs))
235 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
238 /* completion callback */
241 sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
243 struct sisusb_urb_context *context = urb->context;
244 struct sisusb_usb_data *sisusb;
249 sisusb = context->sisusb;
251 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
254 #ifndef SISUSB_DONTSYNC
255 if (context->actual_length)
256 *(context->actual_length) += urb->actual_length;
259 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
260 wake_up(&sisusb->wait_q);
264 sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
265 int len, int *actual_length, int timeout, unsigned int tflags,
266 dma_addr_t transfer_dma)
268 struct urb *urb = sisusb->sisurbout[index];
269 int retval, byteswritten = 0;
272 urb->transfer_flags = 0;
274 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
275 sisusb_bulk_completeout, &sisusb->urbout_context[index]);
277 urb->transfer_flags |= tflags;
278 urb->actual_length = 0;
280 if ((urb->transfer_dma = transfer_dma))
281 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
284 sisusb->urbout_context[index].actual_length = (timeout) ?
285 NULL : actual_length;
287 /* Declare this urb/buffer in use */
288 sisusb->urbstatus[index] |= SU_URB_BUSY;
291 retval = usb_submit_urb(urb, GFP_ATOMIC);
293 /* If OK, and if timeout > 0, wait for completion */
294 if ((retval == 0) && timeout) {
295 wait_event_timeout(sisusb->wait_q,
296 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
298 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
299 /* URB timed out... kill it and report error */
303 /* Otherwise, report urb status */
304 retval = urb->status;
305 byteswritten = urb->actual_length;
310 *actual_length = byteswritten;
317 /* completion callback */
320 sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
322 struct sisusb_usb_data *sisusb = urb->context;
324 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
327 sisusb->completein = 1;
328 wake_up(&sisusb->wait_q);
332 sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
333 int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
335 struct urb *urb = sisusb->sisurbin;
336 int retval, readbytes = 0;
338 urb->transfer_flags = 0;
340 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
341 sisusb_bulk_completein, sisusb);
343 urb->transfer_flags |= tflags;
344 urb->actual_length = 0;
346 if ((urb->transfer_dma = transfer_dma))
347 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
349 sisusb->completein = 0;
350 retval = usb_submit_urb(urb, GFP_ATOMIC);
352 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
353 if (!sisusb->completein) {
354 /* URB timed out... kill it and report error */
358 /* URB completed within timout */
359 retval = urb->status;
360 readbytes = urb->actual_length;
365 *actual_length = readbytes;
373 /* Send a bulk message of variable size
375 * To copy the data from userspace, give pointer to "userbuffer",
376 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
377 * both of these are NULL, it is assumed, that the transfer
378 * buffer "sisusb->obuf[index]" is set up with the data to send.
379 * Index is ignored if either kernbuffer or userbuffer is set.
380 * If async is nonzero, URBs will be sent without waiting for
381 * completion of the previous URB.
383 * (return 0 on success)
386 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
387 char *kernbuffer, const char __user *userbuffer, int index,
388 ssize_t *bytes_written, unsigned int tflags, int async)
390 int result = 0, retry, count = len;
391 int passsize, thispass, transferred_len = 0;
392 int fromuser = (userbuffer != NULL) ? 1 : 0;
393 int fromkern = (kernbuffer != NULL) ? 1 : 0;
397 (*bytes_written) = 0;
400 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
403 /* If we copy data from kernel or userspace, force the
404 * allocation of a buffer/urb. If we have the data in
405 * the transfer buffer[index] already, reuse the buffer/URB
406 * if the length is > buffer size. (So, transmitting
407 * large data amounts directly from the transfer buffer
408 * treats the buffer as a ring buffer. However, we need
409 * to sync in this case.)
411 if (fromuser || fromkern)
413 else if (len > sisusb->obufsize)
416 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
419 passsize = thispass = (sisusb->obufsize < count) ?
420 sisusb->obufsize : count;
423 index = sisusb_get_free_outbuf(sisusb);
428 buffer = sisusb->obuf[index];
432 if (copy_from_user(buffer, userbuffer, passsize))
435 userbuffer += passsize;
437 } else if (fromkern) {
439 memcpy(buffer, kernbuffer, passsize);
440 kernbuffer += passsize;
447 if (!sisusb->sisusb_dev)
450 result = sisusb_bulkout_msg(sisusb,
458 sisusb->transfer_dma_out[index]);
460 if (result == -ETIMEDOUT) {
462 /* Will not happen if async */
468 } else if ((result == 0) && !async && transferred_len) {
470 thispass -= transferred_len;
472 if (sisusb->transfer_dma_out) {
473 /* If DMA, copy remaining
474 * to beginning of buffer
477 buffer + transferred_len,
480 /* If not DMA, simply increase
483 buffer += transferred_len;
494 (*bytes_written) += passsize;
497 /* Force new allocation in next iteration */
498 if (fromuser || fromkern)
504 #ifdef SISUSB_DONTSYNC
505 (*bytes_written) = len;
506 /* Some URBs/buffers might be busy */
508 sisusb_wait_all_out_complete(sisusb);
509 (*bytes_written) = transferred_len;
510 /* All URBs and all buffers are available */
514 return ((*bytes_written) == len) ? 0 : -EIO;
517 /* Receive a bulk message of variable size
519 * To copy the data to userspace, give pointer to "userbuffer",
520 * to copy to kernel memory, give "kernbuffer". One of them
521 * MUST be set. (There is no technique for letting the caller
522 * read directly from the ibuf.)
526 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
527 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
530 int result = 0, retry, count = len;
531 int bufsize, thispass, transferred_len;
538 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
541 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
542 buffer = sisusb->ibuf;
543 bufsize = sisusb->ibufsize;
547 #ifdef SISUSB_DONTSYNC
548 if (!(sisusb_wait_all_out_complete(sisusb)))
554 if (!sisusb->sisusb_dev)
557 thispass = (bufsize < count) ? bufsize : count;
559 result = sisusb_bulkin_msg(sisusb,
566 sisusb->transfer_dma_in);
569 thispass = transferred_len;
571 else if (result == -ETIMEDOUT) {
584 (*bytes_read) += thispass;
589 if (copy_to_user(userbuffer, buffer, thispass))
592 userbuffer += thispass;
596 memcpy(kernbuffer, buffer, thispass);
597 kernbuffer += thispass;
605 return ((*bytes_read) == len) ? 0 : -EIO;
608 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
609 struct sisusb_packet *packet)
612 ssize_t bytes_transferred = 0;
618 #ifdef SISUSB_DONTSYNC
619 if (!(sisusb_wait_all_out_complete(sisusb)))
623 /* Eventually correct endianness */
624 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
626 /* 1. send the packet */
627 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
628 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
630 if ((ret == 0) && (len == 6)) {
632 /* 2. if packet len == 6, it means we read, so wait for 32bit
633 * return value and write it to packet->data
635 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
636 (char *)&tmp, NULL, &bytes_transferred, 0);
638 packet->data = le32_to_cpu(tmp);
644 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
645 struct sisusb_packet *packet,
649 ssize_t bytes_transferred = 0;
655 #ifdef SISUSB_DONTSYNC
656 if (!(sisusb_wait_all_out_complete(sisusb)))
660 /* Eventually correct endianness */
661 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
663 /* 1. send the packet */
664 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
665 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
667 if ((ret == 0) && (len == 6)) {
669 /* 2. if packet len == 6, it means we read, so wait for 32bit
670 * return value and write it to packet->data
672 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
673 (char *)&tmp, NULL, &bytes_transferred, 0);
675 packet->data = le32_to_cpu(tmp);
681 /* access video memory and mmio (return 0 on success) */
685 /* The following routines assume being used to transfer byte, word,
688 * - the write routines expect "data" in machine endianness format.
689 * The data will be converted to leXX in sisusb_xxx_packet.
690 * - the read routines can expect read data in machine-endianess.
693 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
696 struct sisusb_packet packet;
699 packet.header = (1 << (addr & 3)) | (type << 6);
700 packet.address = addr & ~3;
701 packet.data = data << ((addr & 3) << 3);
702 ret = sisusb_send_packet(sisusb, 10, &packet);
706 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
709 struct sisusb_packet packet;
712 packet.address = addr & ~3;
716 packet.header = (type << 6) | 0x0003;
717 packet.data = (u32)data;
718 ret = sisusb_send_packet(sisusb, 10, &packet);
721 packet.header = (type << 6) | 0x0006;
722 packet.data = (u32)data << 8;
723 ret = sisusb_send_packet(sisusb, 10, &packet);
726 packet.header = (type << 6) | 0x000c;
727 packet.data = (u32)data << 16;
728 ret = sisusb_send_packet(sisusb, 10, &packet);
731 packet.header = (type << 6) | 0x0008;
732 packet.data = (u32)data << 24;
733 ret = sisusb_send_packet(sisusb, 10, &packet);
734 packet.header = (type << 6) | 0x0001;
735 packet.address = (addr & ~3) + 4;
736 packet.data = (u32)data >> 8;
737 ret |= sisusb_send_packet(sisusb, 10, &packet);
743 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
746 struct sisusb_packet packet;
749 packet.address = addr & ~3;
753 packet.header = (type << 6) | 0x0007;
754 packet.data = data & 0x00ffffff;
755 ret = sisusb_send_packet(sisusb, 10, &packet);
758 packet.header = (type << 6) | 0x000e;
759 packet.data = data << 8;
760 ret = sisusb_send_packet(sisusb, 10, &packet);
763 packet.header = (type << 6) | 0x000c;
764 packet.data = data << 16;
765 ret = sisusb_send_packet(sisusb, 10, &packet);
766 packet.header = (type << 6) | 0x0001;
767 packet.address = (addr & ~3) + 4;
768 packet.data = (data >> 16) & 0x00ff;
769 ret |= sisusb_send_packet(sisusb, 10, &packet);
772 packet.header = (type << 6) | 0x0008;
773 packet.data = data << 24;
774 ret = sisusb_send_packet(sisusb, 10, &packet);
775 packet.header = (type << 6) | 0x0003;
776 packet.address = (addr & ~3) + 4;
777 packet.data = (data >> 8) & 0xffff;
778 ret |= sisusb_send_packet(sisusb, 10, &packet);
784 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
787 struct sisusb_packet packet;
790 packet.address = addr & ~3;
794 packet.header = (type << 6) | 0x000f;
796 ret = sisusb_send_packet(sisusb, 10, &packet);
799 packet.header = (type << 6) | 0x000e;
800 packet.data = data << 8;
801 ret = sisusb_send_packet(sisusb, 10, &packet);
802 packet.header = (type << 6) | 0x0001;
803 packet.address = (addr & ~3) + 4;
804 packet.data = data >> 24;
805 ret |= sisusb_send_packet(sisusb, 10, &packet);
808 packet.header = (type << 6) | 0x000c;
809 packet.data = data << 16;
810 ret = sisusb_send_packet(sisusb, 10, &packet);
811 packet.header = (type << 6) | 0x0003;
812 packet.address = (addr & ~3) + 4;
813 packet.data = data >> 16;
814 ret |= sisusb_send_packet(sisusb, 10, &packet);
817 packet.header = (type << 6) | 0x0008;
818 packet.data = data << 24;
819 ret = sisusb_send_packet(sisusb, 10, &packet);
820 packet.header = (type << 6) | 0x0007;
821 packet.address = (addr & ~3) + 4;
822 packet.data = data >> 8;
823 ret |= sisusb_send_packet(sisusb, 10, &packet);
829 /* The xxx_bulk routines copy a buffer of variable size. They treat the
830 * buffer as chars, therefore lsb/msb has to be corrected if using the
831 * byte/word/long/etc routines for speed-up
833 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
834 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
835 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
836 * that the data already is in the transfer buffer "sisusb->obuf[index]".
839 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
840 char *kernbuffer, int length,
841 const char __user *userbuffer, int index,
842 ssize_t *bytes_written)
844 struct sisusb_packet packet;
846 static int msgcount = 0;
847 u8 swap8, fromkern = kernbuffer ? 1 : 0;
849 u32 swap32, flag = (length >> 28) & 1;
852 /* if neither kernbuffer not userbuffer are given, assume
855 if (!fromkern && !userbuffer)
856 kernbuffer = sisusb->obuf[index];
858 (*bytes_written = 0);
860 length &= 0x00ffffff;
871 if (get_user(swap8, (u8 __user *)userbuffer))
874 swap8 = kernbuffer[0];
876 ret = sisusb_write_memio_byte(sisusb,
887 if (get_user(swap16, (u16 __user *)userbuffer))
890 swap16 = *((u16 *)kernbuffer);
892 ret = sisusb_write_memio_word(sisusb,
898 (*bytes_written) += 2;
904 if (copy_from_user(&buf, userbuffer, 3))
907 swap32 = (buf[0] << 16) |
911 swap32 = (buf[2] << 16) |
917 swap32 = (kernbuffer[0] << 16) |
918 (kernbuffer[1] << 8) |
921 swap32 = (kernbuffer[2] << 16) |
922 (kernbuffer[1] << 8) |
926 ret = sisusb_write_memio_24bit(sisusb,
932 (*bytes_written) += 3;
938 if (get_user(swap32, (u32 __user *)userbuffer))
941 swap32 = *((u32 *)kernbuffer);
943 ret = sisusb_write_memio_long(sisusb,
948 (*bytes_written) += 4;
953 if ((length & ~3) > 0x10000) {
955 packet.header = 0x001f;
956 packet.address = 0x000001d4;
958 ret = sisusb_send_bridge_packet(sisusb, 10,
960 packet.header = 0x001f;
961 packet.address = 0x000001d0;
962 packet.data = (length & ~3);
963 ret |= sisusb_send_bridge_packet(sisusb, 10,
965 packet.header = 0x001f;
966 packet.address = 0x000001c0;
967 packet.data = flag | 0x16;
968 ret |= sisusb_send_bridge_packet(sisusb, 10,
971 ret |= sisusb_send_bulk_msg(sisusb,
972 SISUSB_EP_GFX_LBULK_OUT,
975 bytes_written, 0, 1);
976 userbuffer += (*bytes_written);
977 } else if (fromkern) {
978 ret |= sisusb_send_bulk_msg(sisusb,
979 SISUSB_EP_GFX_LBULK_OUT,
982 bytes_written, 0, 1);
983 kernbuffer += (*bytes_written);
985 ret |= sisusb_send_bulk_msg(sisusb,
986 SISUSB_EP_GFX_LBULK_OUT,
989 bytes_written, 0, 1);
990 kernbuffer += ((*bytes_written) &
991 (sisusb->obufsize-1));
996 packet.header = 0x001f;
997 packet.address = 0x00000194;
999 ret = sisusb_send_bridge_packet(sisusb, 10,
1001 packet.header = 0x001f;
1002 packet.address = 0x00000190;
1003 packet.data = (length & ~3);
1004 ret |= sisusb_send_bridge_packet(sisusb, 10,
1006 if (sisusb->flagb0 != 0x16) {
1007 packet.header = 0x001f;
1008 packet.address = 0x00000180;
1009 packet.data = flag | 0x16;
1010 ret |= sisusb_send_bridge_packet(sisusb, 10,
1012 sisusb->flagb0 = 0x16;
1015 ret |= sisusb_send_bulk_msg(sisusb,
1016 SISUSB_EP_GFX_BULK_OUT,
1018 NULL, userbuffer, 0,
1019 bytes_written, 0, 1);
1020 userbuffer += (*bytes_written);
1021 } else if (fromkern) {
1022 ret |= sisusb_send_bulk_msg(sisusb,
1023 SISUSB_EP_GFX_BULK_OUT,
1025 kernbuffer, NULL, 0,
1026 bytes_written, 0, 1);
1027 kernbuffer += (*bytes_written);
1029 ret |= sisusb_send_bulk_msg(sisusb,
1030 SISUSB_EP_GFX_BULK_OUT,
1033 bytes_written, 0, 1);
1034 kernbuffer += ((*bytes_written) &
1035 (sisusb->obufsize-1));
1042 "sisusbvga[%d]: Wrote %zd of "
1043 "%d bytes, error %d\n",
1044 sisusb->minor, *bytes_written,
1046 else if (msgcount == 500)
1048 "sisusbvga[%d]: Too many errors"
1049 ", logging stopped\n",
1052 addr += (*bytes_written);
1053 length -= (*bytes_written);
1061 return ret ? -EIO : 0;
1064 /* Remember: Read data in packet is in machine-endianess! So for
1065 * byte, word, 24bit, long no endian correction is necessary.
1068 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1071 struct sisusb_packet packet;
1074 CLEARPACKET(&packet);
1075 packet.header = (1 << (addr & 3)) | (type << 6);
1076 packet.address = addr & ~3;
1077 ret = sisusb_send_packet(sisusb, 6, &packet);
1078 *data = (u8)(packet.data >> ((addr & 3) << 3));
1082 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
1083 u32 addr, u16 *data)
1085 struct sisusb_packet packet;
1088 CLEARPACKET(&packet);
1090 packet.address = addr & ~3;
1094 packet.header = (type << 6) | 0x0003;
1095 ret = sisusb_send_packet(sisusb, 6, &packet);
1096 *data = (u16)(packet.data);
1099 packet.header = (type << 6) | 0x0006;
1100 ret = sisusb_send_packet(sisusb, 6, &packet);
1101 *data = (u16)(packet.data >> 8);
1104 packet.header = (type << 6) | 0x000c;
1105 ret = sisusb_send_packet(sisusb, 6, &packet);
1106 *data = (u16)(packet.data >> 16);
1109 packet.header = (type << 6) | 0x0008;
1110 ret = sisusb_send_packet(sisusb, 6, &packet);
1111 *data = (u16)(packet.data >> 24);
1112 packet.header = (type << 6) | 0x0001;
1113 packet.address = (addr & ~3) + 4;
1114 ret |= sisusb_send_packet(sisusb, 6, &packet);
1115 *data |= (u16)(packet.data << 8);
1121 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1122 u32 addr, u32 *data)
1124 struct sisusb_packet packet;
1127 packet.address = addr & ~3;
1131 packet.header = (type << 6) | 0x0007;
1132 ret = sisusb_send_packet(sisusb, 6, &packet);
1133 *data = packet.data & 0x00ffffff;
1136 packet.header = (type << 6) | 0x000e;
1137 ret = sisusb_send_packet(sisusb, 6, &packet);
1138 *data = packet.data >> 8;
1141 packet.header = (type << 6) | 0x000c;
1142 ret = sisusb_send_packet(sisusb, 6, &packet);
1143 *data = packet.data >> 16;
1144 packet.header = (type << 6) | 0x0001;
1145 packet.address = (addr & ~3) + 4;
1146 ret |= sisusb_send_packet(sisusb, 6, &packet);
1147 *data |= ((packet.data & 0xff) << 16);
1150 packet.header = (type << 6) | 0x0008;
1151 ret = sisusb_send_packet(sisusb, 6, &packet);
1152 *data = packet.data >> 24;
1153 packet.header = (type << 6) | 0x0003;
1154 packet.address = (addr & ~3) + 4;
1155 ret |= sisusb_send_packet(sisusb, 6, &packet);
1156 *data |= ((packet.data & 0xffff) << 8);
1162 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1163 u32 addr, u32 *data)
1165 struct sisusb_packet packet;
1168 packet.address = addr & ~3;
1172 packet.header = (type << 6) | 0x000f;
1173 ret = sisusb_send_packet(sisusb, 6, &packet);
1174 *data = packet.data;
1177 packet.header = (type << 6) | 0x000e;
1178 ret = sisusb_send_packet(sisusb, 6, &packet);
1179 *data = packet.data >> 8;
1180 packet.header = (type << 6) | 0x0001;
1181 packet.address = (addr & ~3) + 4;
1182 ret |= sisusb_send_packet(sisusb, 6, &packet);
1183 *data |= (packet.data << 24);
1186 packet.header = (type << 6) | 0x000c;
1187 ret = sisusb_send_packet(sisusb, 6, &packet);
1188 *data = packet.data >> 16;
1189 packet.header = (type << 6) | 0x0003;
1190 packet.address = (addr & ~3) + 4;
1191 ret |= sisusb_send_packet(sisusb, 6, &packet);
1192 *data |= (packet.data << 16);
1195 packet.header = (type << 6) | 0x0008;
1196 ret = sisusb_send_packet(sisusb, 6, &packet);
1197 *data = packet.data >> 24;
1198 packet.header = (type << 6) | 0x0007;
1199 packet.address = (addr & ~3) + 4;
1200 ret |= sisusb_send_packet(sisusb, 6, &packet);
1201 *data |= (packet.data << 8);
1207 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1208 char *kernbuffer, int length,
1209 char __user *userbuffer, ssize_t *bytes_read)
1218 length &= 0x00ffffff;
1229 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1234 if (put_user(buf[0],
1235 (u8 __user *)userbuffer)) {
1239 kernbuffer[0] = buf[0];
1245 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1250 if (put_user(swap16,
1251 (u16 __user *)userbuffer))
1254 *((u16 *)kernbuffer) = swap16;
1260 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1265 buf[0] = (swap32 >> 16) & 0xff;
1266 buf[1] = (swap32 >> 8) & 0xff;
1267 buf[2] = swap32 & 0xff;
1269 buf[2] = (swap32 >> 16) & 0xff;
1270 buf[1] = (swap32 >> 8) & 0xff;
1271 buf[0] = swap32 & 0xff;
1274 if (copy_to_user(userbuffer, &buf[0], 3))
1277 kernbuffer[0] = buf[0];
1278 kernbuffer[1] = buf[1];
1279 kernbuffer[2] = buf[2];
1285 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1290 if (put_user(swap32,
1291 (u32 __user *)userbuffer))
1296 *((u32 *)kernbuffer) = swap32;
1302 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1304 CLEARPACKET(&packet);
1305 packet.header = 0x001f;
1306 packet.address = 0x000001a0;
1307 packet.data = 0x00000006;
1308 ret |= sisusb_send_bridge_packet(sisusb, 10,
1310 packet.header = 0x001f;
1311 packet.address = 0x000001b0;
1312 packet.data = (length & ~3) | 0x40000000;
1313 ret |= sisusb_send_bridge_packet(sisusb, 10,
1315 packet.header = 0x001f;
1316 packet.address = 0x000001b4;
1318 ret |= sisusb_send_bridge_packet(sisusb, 10,
1320 packet.header = 0x001f;
1321 packet.address = 0x000001a4;
1322 packet.data = 0x00000001;
1323 ret |= sisusb_send_bridge_packet(sisusb, 10,
1326 ret |= sisusb_recv_bulk_msg(sisusb,
1327 SISUSB_EP_GFX_BULK_IN,
1331 if (!ret) userbuffer += (*bytes_read);
1333 ret |= sisusb_recv_bulk_msg(sisusb,
1334 SISUSB_EP_GFX_BULK_IN,
1338 if (!ret) kernbuffer += (*bytes_read);
1340 addr += (*bytes_read);
1341 length -= (*bytes_read);
1352 /* High level: Gfx (indexed) register access */
1354 #ifdef INCL_SISUSB_CON
1356 sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1358 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1362 sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1364 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1368 #ifndef INCL_SISUSB_CON
1372 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1375 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1376 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1380 #ifndef INCL_SISUSB_CON
1384 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1387 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1388 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1392 #ifndef INCL_SISUSB_CON
1396 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1402 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1403 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1406 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1411 sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1416 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1417 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1419 tmp |= (data & mask);
1420 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1424 #ifndef INCL_SISUSB_CON
1428 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1430 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1433 #ifndef INCL_SISUSB_CON
1437 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1439 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1442 /* Write/read video ram */
1444 #ifdef INCL_SISUSB_CON
1446 sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1448 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1452 sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1454 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1458 sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
1460 return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1464 sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
1466 return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1470 sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1471 u32 dest, int length, size_t *bytes_written)
1473 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1476 #ifdef SISUSBENDIANTEST
1478 sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1479 u32 src, int length, size_t *bytes_written)
1481 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1486 #ifdef SISUSBENDIANTEST
1488 sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1490 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1491 char destbuffer[10];
1495 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1497 for(i = 1; i <= 7; i++) {
1498 printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
1499 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1500 for(j = 0; j < i; j++) {
1501 printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
1507 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1510 sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
1512 struct sisusb_packet packet;
1515 packet.header = 0x008f;
1516 packet.address = regnum | 0x10000;
1518 ret = sisusb_send_packet(sisusb, 10, &packet);
1523 sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
1525 struct sisusb_packet packet;
1528 packet.header = 0x008f;
1529 packet.address = (u32)regnum | 0x10000;
1530 ret = sisusb_send_packet(sisusb, 6, &packet);
1531 *data = packet.data;
1535 /* Clear video RAM */
1538 sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
1543 if (address < sisusb->vrambase)
1546 if (address >= sisusb->vrambase + sisusb->vramsize)
1549 if (address + length > sisusb->vrambase + sisusb->vramsize)
1550 length = sisusb->vrambase + sisusb->vramsize - address;
1555 /* allocate free buffer/urb and clear the buffer */
1556 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1559 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1561 /* We can write a length > buffer size here. The buffer
1562 * data will simply be re-used (like a ring-buffer).
1564 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1566 /* Free the buffer/urb */
1567 sisusb_free_outbuf(sisusb, i);
1572 /* Initialize the graphics core (return 0 on success)
1573 * This resets the graphics hardware and puts it into
1574 * a defined mode (640x480@60Hz)
1577 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1578 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1579 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1580 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1581 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1582 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1583 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1584 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1585 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1586 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1587 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1590 sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1595 ret = GETIREG(SISSR, 0x16, &tmp8);
1598 ret |= SETIREG(SISSR, 0x16, tmp8);
1600 ret |= SETIREG(SISSR, 0x16, tmp8);
1603 ret |= SETIREG(SISSR, 0x16, tmp8);
1605 ret |= SETIREG(SISSR, 0x16, tmp8);
1607 ret |= SETIREG(SISSR, 0x16, tmp8);
1609 ret |= SETIREG(SISSR, 0x16, tmp8);
1611 ret |= SETIREG(SISSR, 0x16, tmp8);
1613 ret |= SETIREG(SISSR, 0x16, tmp8);
1615 ret |= SETIREG(SISSR, 0x16, tmp8);
1621 sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
1624 u8 ramtype, done = 0;
1626 u32 ramptr = SISUSB_PCI_MEMBASE;
1628 ret = GETIREG(SISSR, 0x3a, &ramtype);
1631 ret |= SETIREG(SISSR, 0x13, 0x00);
1634 ret |= SETIREG(SISSR, 0x14, 0x12);
1635 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1637 ret |= SETIREG(SISSR, 0x14, 0x02);
1640 ret |= sisusb_triggersr16(sisusb, ramtype);
1641 ret |= WRITEL(ramptr + 0, 0x01234567);
1642 ret |= WRITEL(ramptr + 4, 0x456789ab);
1643 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1644 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1645 ret |= WRITEL(ramptr + 16, 0x55555555);
1646 ret |= WRITEL(ramptr + 20, 0x55555555);
1647 ret |= WRITEL(ramptr + 24, 0xffffffff);
1648 ret |= WRITEL(ramptr + 28, 0xffffffff);
1649 ret |= READL(ramptr + 0, &t0);
1650 ret |= READL(ramptr + 4, &t1);
1651 ret |= READL(ramptr + 8, &t2);
1652 ret |= READL(ramptr + 12, &t3);
1656 *chab = 0; *bw = 64;
1658 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1659 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1660 *chab = 0; *bw = 64;
1661 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1664 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1665 *chab = 1; *bw = 64;
1666 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
1668 ret |= sisusb_triggersr16(sisusb, ramtype);
1669 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1670 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1671 ret |= WRITEL(ramptr + 8, 0x55555555);
1672 ret |= WRITEL(ramptr + 12, 0x55555555);
1673 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1674 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1675 ret |= READL(ramptr + 4, &t1);
1677 if (t1 != 0xcdef0123) {
1679 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1685 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1689 if (t1 == 0x456789ab) {
1690 if (t0 == 0x01234567) {
1691 *chab = 0; *bw = 64;
1695 if (t0 == 0x01234567) {
1696 *chab = 0; *bw = 32;
1697 ret |= SETIREG(SISSR, 0x14, 0x00);
1703 ret |= SETIREG(SISSR, 0x14, 0x03);
1704 ret |= sisusb_triggersr16(sisusb, ramtype);
1706 ret |= WRITEL(ramptr + 0, 0x01234567);
1707 ret |= WRITEL(ramptr + 4, 0x456789ab);
1708 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1709 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1710 ret |= WRITEL(ramptr + 16, 0x55555555);
1711 ret |= WRITEL(ramptr + 20, 0x55555555);
1712 ret |= WRITEL(ramptr + 24, 0xffffffff);
1713 ret |= WRITEL(ramptr + 28, 0xffffffff);
1714 ret |= READL(ramptr + 0, &t0);
1715 ret |= READL(ramptr + 4, &t1);
1717 if (t1 == 0x456789ab) {
1718 if (t0 == 0x01234567) {
1719 *chab = 1; *bw = 64;
1723 if (t0 == 0x01234567) {
1724 *chab = 1; *bw = 32;
1725 ret |= SETIREG(SISSR, 0x14, 0x01);
1734 sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1737 u32 ramptr = SISUSB_PCI_MEMBASE;
1738 u8 tmp1, tmp2, i, j;
1740 ret |= WRITEB(ramptr, 0xaa);
1741 ret |= WRITEB(ramptr + 16, 0x55);
1742 ret |= READB(ramptr, &tmp1);
1743 ret |= READB(ramptr + 16, &tmp2);
1744 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1745 for (i = 0, j = 16; i < 2; i++, j += 16) {
1746 ret |= GETIREG(SISSR, 0x21, &tmp1);
1747 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1748 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1749 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1750 ret |= SETIREG(SISSR, 0x21, tmp1);
1751 ret |= WRITEB(ramptr + 16 + j, j);
1752 ret |= READB(ramptr + 16 + j, &tmp1);
1754 ret |= WRITEB(ramptr + j, j);
1763 sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
1764 u8 rankno, u8 chab, const u8 dramtype[][5],
1767 int ret = 0, ranksize;
1772 if ((rankno == 2) && (dramtype[index][0] == 2))
1775 ranksize = dramtype[index][3] / 2 * bw / 32;
1777 if ((ranksize * rankno) > 128)
1781 while ((ranksize >>= 1) > 0) tmp += 0x10;
1782 tmp |= ((rankno - 1) << 2);
1783 tmp |= ((bw / 64) & 0x02);
1784 tmp |= (chab & 0x01);
1786 ret = SETIREG(SISSR, 0x14, tmp);
1787 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1795 sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
1802 for (i = 0, j = 0; i < testn; i++) {
1803 ret |= WRITEL(sisusb->vrambase + j, j);
1807 for (i = 0, j = 0; i < testn; i++) {
1808 ret |= READL(sisusb->vrambase + j, &tmp);
1809 if (tmp != j) return ret;
1818 sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
1819 int idx, int bw, const u8 rtype[][5])
1821 int ret = 0, i, i2ret;
1826 for (i = rankno; i >= 1; i--) {
1827 inc = 1 << (rtype[idx][2] +
1831 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1836 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1837 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1841 inc = 1 << (10 + bw / 64);
1842 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1851 sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
1854 int ret = 0, i2ret = 0, i, j;
1855 static const u8 sdramtype[13][5] = {
1856 { 2, 12, 9, 64, 0x35 },
1857 { 1, 13, 9, 64, 0x44 },
1858 { 2, 12, 8, 32, 0x31 },
1859 { 2, 11, 9, 32, 0x25 },
1860 { 1, 12, 9, 32, 0x34 },
1861 { 1, 13, 8, 32, 0x40 },
1862 { 2, 11, 8, 16, 0x21 },
1863 { 1, 12, 8, 16, 0x30 },
1864 { 1, 11, 9, 16, 0x24 },
1865 { 1, 11, 8, 8, 0x20 },
1866 { 2, 9, 8, 4, 0x01 },
1867 { 1, 10, 8, 4, 0x10 },
1868 { 1, 9, 8, 2, 0x00 }
1871 *iret = 1; /* error */
1873 for (i = 0; i < 13; i++) {
1874 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1875 for (j = 2; j > 0; j--) {
1876 ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
1877 chab, sdramtype, bw);
1881 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
1884 *iret = 0; /* ram size found */
1894 sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
1898 int i, length, modex, modey, bpp;
1900 modex = 640; modey = 480; bpp = 2;
1902 address = sisusb->vrambase; /* Clear video ram */
1905 length = sisusb->vramsize;
1907 length = modex * bpp * modey;
1909 ret = sisusb_clear_vram(sisusb, address, length);
1911 if (!ret && drwfr) {
1912 for (i = 0; i < modex; i++) {
1913 address = sisusb->vrambase + (i * bpp);
1914 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1916 address += (modex * (modey-1) * bpp);
1917 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1920 for (i = 0; i < modey; i++) {
1921 address = sisusb->vrambase + ((i * modex) * bpp);
1922 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1924 address += ((modex - 1) * bpp);
1925 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1934 sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
1936 int ret = 0, i, j, modex, modey, bpp, du;
1937 u8 sr31, cr63, tmp8;
1938 static const char attrdata[] = {
1939 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1940 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1943 static const char crtcrdata[] = {
1944 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1945 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1946 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1949 static const char grcdata[] = {
1950 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1953 static const char crtcdata[] = {
1954 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1955 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1959 modex = 640; modey = 480; bpp = 2;
1961 GETIREG(SISSR, 0x31, &sr31);
1962 GETIREG(SISCR, 0x63, &cr63);
1963 SETIREGOR(SISSR, 0x01, 0x20);
1964 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1965 SETIREGOR(SISCR, 0x17, 0x80);
1966 SETIREGOR(SISSR, 0x1f, 0x04);
1967 SETIREGAND(SISSR, 0x07, 0xfb);
1968 SETIREG(SISSR, 0x00, 0x03); /* seq */
1969 SETIREG(SISSR, 0x01, 0x21);
1970 SETIREG(SISSR, 0x02, 0x0f);
1971 SETIREG(SISSR, 0x03, 0x00);
1972 SETIREG(SISSR, 0x04, 0x0e);
1973 SETREG(SISMISCW, 0x23); /* misc */
1974 for (i = 0; i <= 0x18; i++) { /* crtc */
1975 SETIREG(SISCR, i, crtcrdata[i]);
1977 for (i = 0; i <= 0x13; i++) { /* att */
1978 GETREG(SISINPSTAT, &tmp8);
1980 SETREG(SISAR, attrdata[i]);
1982 GETREG(SISINPSTAT, &tmp8);
1983 SETREG(SISAR, 0x14);
1984 SETREG(SISAR, 0x00);
1985 GETREG(SISINPSTAT, &tmp8);
1986 SETREG(SISAR, 0x20);
1987 GETREG(SISINPSTAT, &tmp8);
1988 for (i = 0; i <= 0x08; i++) { /* grc */
1989 SETIREG(SISGR, i, grcdata[i]);
1991 SETIREGAND(SISGR, 0x05, 0xbf);
1992 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1993 SETIREG(SISSR, i, 0x00);
1995 SETIREGAND(SISSR, 0x37, 0xfe);
1996 SETREG(SISMISCW, 0xef); /* sync */
1997 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1998 for (j = 0x00, i = 0; i <= 7; i++, j++) {
1999 SETIREG(SISCR, j, crtcdata[i]);
2001 for (j = 0x10; i <= 10; i++, j++) {
2002 SETIREG(SISCR, j, crtcdata[i]);
2004 for (j = 0x15; i <= 12; i++, j++) {
2005 SETIREG(SISCR, j, crtcdata[i]);
2007 for (j = 0x0A; i <= 15; i++, j++) {
2008 SETIREG(SISSR, j, crtcdata[i]);
2010 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
2011 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
2012 SETIREG(SISCR, 0x14, 0x4f);
2013 du = (modex / 16) * (bpp * 2); /* offset/pitch */
2014 if (modex % 16) du += bpp;
2015 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
2016 SETIREG(SISCR, 0x13, (du & 0xff));
2019 if (du & 0xff) tmp8++;
2020 SETIREG(SISSR, 0x10, tmp8);
2021 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
2022 SETIREG(SISSR, 0x2b, 0x1b);
2023 SETIREG(SISSR, 0x2c, 0xe1);
2024 SETIREG(SISSR, 0x2d, 0x01);
2025 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
2026 SETIREG(SISSR, 0x08, 0xae);
2027 SETIREGAND(SISSR, 0x09, 0xf0);
2028 SETIREG(SISSR, 0x08, 0x34);
2029 SETIREGOR(SISSR, 0x3d, 0x01);
2030 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
2031 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
2032 SETIREG(SISCR, 0x19, 0x00);
2033 SETIREGAND(SISCR, 0x1a, 0xfc);
2034 SETIREGAND(SISSR, 0x0f, 0xb7);
2035 SETIREGAND(SISSR, 0x31, 0xfb);
2036 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
2037 SETIREGAND(SISSR, 0x32, 0xf3);
2038 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
2039 SETIREG(SISCR, 0x52, 0x6c);
2041 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
2042 SETIREG(SISCR, 0x0c, 0x00);
2043 SETIREG(SISSR, 0x0d, 0x00);
2044 SETIREGAND(SISSR, 0x37, 0xfe);
2046 SETIREG(SISCR, 0x32, 0x20);
2047 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
2048 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
2049 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
2052 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
2053 SETIREGOR(SISSR, 0x1e, 0x5a);
2055 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
2056 SETIREG(SISSR, 0x27, 0x1f);
2057 SETIREG(SISSR, 0x26, 0x00);
2060 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
2066 sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
2068 int ret = 0, i, j, bw, chab, iret, retry = 3;
2071 static const char mclktable[] = {
2072 0x3b, 0x22, 0x01, 143,
2073 0x3b, 0x22, 0x01, 143,
2074 0x3b, 0x22, 0x01, 143,
2075 0x3b, 0x22, 0x01, 143
2077 static const char eclktable[] = {
2078 0x3b, 0x22, 0x01, 143,
2079 0x3b, 0x22, 0x01, 143,
2080 0x3b, 0x22, 0x01, 143,
2081 0x3b, 0x22, 0x01, 143
2083 static const char ramtypetable1[] = {
2084 0x00, 0x04, 0x60, 0x60,
2085 0x0f, 0x0f, 0x1f, 0x1f,
2086 0xba, 0xba, 0xba, 0xba,
2087 0xa9, 0xa9, 0xac, 0xac,
2088 0xa0, 0xa0, 0xa0, 0xa8,
2089 0x00, 0x00, 0x02, 0x02,
2090 0x30, 0x30, 0x40, 0x40
2092 static const char ramtypetable2[] = {
2093 0x77, 0x77, 0x44, 0x44,
2094 0x77, 0x77, 0x44, 0x44,
2095 0x00, 0x00, 0x00, 0x00,
2096 0x5b, 0x5b, 0xab, 0xab,
2097 0x00, 0x00, 0xf0, 0xf8
2103 ret = GETREG(SISVGAEN, &tmp8);
2104 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
2106 /* Enable GPU access to VRAM */
2107 ret |= GETREG(SISMISCR, &tmp8);
2108 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
2112 /* Reset registers */
2113 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
2114 ret |= SETIREG(SISSR, 0x05, 0x86);
2115 ret |= SETIREGOR(SISSR, 0x20, 0x01);
2117 ret |= SETREG(SISMISCW, 0x67);
2119 for (i = 0x06; i <= 0x1f; i++) {
2120 ret |= SETIREG(SISSR, i, 0x00);
2122 for (i = 0x21; i <= 0x27; i++) {
2123 ret |= SETIREG(SISSR, i, 0x00);
2125 for (i = 0x31; i <= 0x3d; i++) {
2126 ret |= SETIREG(SISSR, i, 0x00);
2128 for (i = 0x12; i <= 0x1b; i++) {
2129 ret |= SETIREG(SISSR, i, 0x00);
2131 for (i = 0x79; i <= 0x7c; i++) {
2132 ret |= SETIREG(SISCR, i, 0x00);
2137 ret |= SETIREG(SISCR, 0x63, 0x80);
2139 ret |= GETIREG(SISSR, 0x3a, &ramtype);
2142 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
2143 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
2144 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
2146 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
2147 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
2148 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
2150 ret |= SETIREG(SISSR, 0x07, 0x18);
2151 ret |= SETIREG(SISSR, 0x11, 0x0f);
2155 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
2156 ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
2158 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
2159 ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
2162 ret |= SETIREG(SISCR, 0x49, 0xaa);
2164 ret |= SETIREG(SISSR, 0x1f, 0x00);
2165 ret |= SETIREG(SISSR, 0x20, 0xa0);
2166 ret |= SETIREG(SISSR, 0x23, 0xf6);
2167 ret |= SETIREG(SISSR, 0x24, 0x0d);
2168 ret |= SETIREG(SISSR, 0x25, 0x33);
2170 ret |= SETIREG(SISSR, 0x11, 0x0f);
2172 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
2174 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2178 ret |= SETIREG(SISPART1, 0x00, 0x00);
2180 ret |= GETIREG(SISSR, 0x13, &tmp8);
2183 ret |= SETIREG(SISPART1, 0x02, 0x00);
2184 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2186 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2187 tmp32 &= 0x00f00000;
2188 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2189 ret |= SETIREG(SISSR, 0x25, tmp8);
2190 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2191 ret |= SETIREG(SISCR, 0x49, tmp8);
2193 ret |= SETIREG(SISSR, 0x27, 0x1f);
2194 ret |= SETIREG(SISSR, 0x31, 0x00);
2195 ret |= SETIREG(SISSR, 0x32, 0x11);
2196 ret |= SETIREG(SISSR, 0x33, 0x00);
2200 ret |= SETIREG(SISCR, 0x83, 0x00);
2202 ret |= sisusb_set_default_mode(sisusb, 0);
2204 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2205 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2206 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2208 ret |= sisusb_triggersr16(sisusb, ramtype);
2210 /* Disable refresh */
2211 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2212 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2214 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2215 ret |= sisusb_verify_mclk(sisusb);
2218 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2220 printk(KERN_ERR "sisusbvga[%d]: RAM size "
2221 "detection failed, "
2222 "assuming 8MB video RAM\n",
2224 ret |= SETIREG(SISSR,0x14,0x31);
2228 printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
2229 "assuming 8MB video RAM\n",
2231 ret |= SETIREG(SISSR,0x14,0x31);
2235 /* Enable refresh */
2236 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2237 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2238 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2240 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2242 ret |= SETIREG(SISSR, 0x22, 0xfb);
2243 ret |= SETIREG(SISSR, 0x21, 0xa5);
2263 sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2265 u8 tmp8, tmp82, ramtype;
2267 char *ramtypetext1 = NULL;
2268 const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
2269 "DDR SDRAM", "DDR SGRAM" };
2270 static const int busSDR[4] = {64, 64, 128, 128};
2271 static const int busDDR[4] = {32, 32, 64, 64};
2272 static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2274 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2275 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2276 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2277 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2279 switch ((tmp8 >> 2) & 0x03) {
2280 case 0: ramtypetext1 = "1 ch/1 r";
2284 bw = busSDR[(tmp8 & 0x03)];
2287 case 1: ramtypetext1 = "1 ch/2 r";
2288 sisusb->vramsize <<= 1;
2289 bw = busSDR[(tmp8 & 0x03)];
2291 case 2: ramtypetext1 = "asymmeric";
2292 sisusb->vramsize += sisusb->vramsize/2;
2293 bw = busDDRA[(tmp8 & 0x03)];
2295 case 3: ramtypetext1 = "2 channel";
2296 sisusb->vramsize <<= 1;
2297 bw = busDDR[(tmp8 & 0x03)];
2301 printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2302 sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
2303 ramtypetext2[ramtype], bw);
2307 sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2309 struct sisusb_packet packet;
2314 packet.header = 0x001f;
2315 packet.address = 0x00000324;
2316 packet.data = 0x00000004;
2317 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2319 packet.header = 0x001f;
2320 packet.address = 0x00000364;
2321 packet.data = 0x00000004;
2322 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2324 packet.header = 0x001f;
2325 packet.address = 0x00000384;
2326 packet.data = 0x00000004;
2327 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2329 packet.header = 0x001f;
2330 packet.address = 0x00000100;
2331 packet.data = 0x00000700;
2332 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2334 packet.header = 0x000f;
2335 packet.address = 0x00000004;
2336 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2337 packet.data |= 0x17;
2338 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2340 /* Init BAR 0 (VRAM) */
2341 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2342 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2343 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2345 tmp32 |= SISUSB_PCI_MEMBASE;
2346 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2348 /* Init BAR 1 (MMIO) */
2349 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2350 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2351 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2353 tmp32 |= SISUSB_PCI_MMIOBASE;
2354 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2356 /* Init BAR 2 (i/o ports) */
2357 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2358 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2359 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2361 tmp32 |= SISUSB_PCI_IOPORTBASE;
2362 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2364 /* Enable memory and i/o access */
2365 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2367 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2370 /* Some further magic */
2371 packet.header = 0x001f;
2372 packet.address = 0x00000050;
2373 packet.data = 0x000000ff;
2374 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2380 /* Initialize the graphics device (return 0 on success)
2381 * This initializes the net2280 as well as the PCI registers
2382 * of the graphics board.
2386 sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2388 int ret = 0, test = 0;
2391 if (sisusb->devinit == 1) {
2392 /* Read PCI BARs and see if they have been set up */
2393 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2394 if (ret) return ret;
2395 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2397 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2398 if (ret) return ret;
2399 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2401 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2402 if (ret) return ret;
2403 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2406 /* No? So reset the device */
2407 if ((sisusb->devinit == 0) || (test != 3)) {
2409 ret |= sisusb_do_init_gfxdevice(sisusb);
2412 sisusb->devinit = 1;
2416 if (sisusb->devinit) {
2417 /* Initialize the graphics core */
2418 if (sisusb_init_gfxcore(sisusb) == 0) {
2419 sisusb->gfxinit = 1;
2420 sisusb_get_ramconfig(sisusb);
2421 ret |= sisusb_set_default_mode(sisusb, 1);
2422 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2430 #ifdef INCL_SISUSB_CON
2432 /* Set up default text mode:
2433 - Set text mode (0x03)
2434 - Upload default font
2435 - Upload user font (if available)
2439 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2441 int ret = 0, slot = sisusb->font_slot, i;
2442 const struct font_desc *myfont;
2446 static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2447 static char bootlogo[] = "(o_ //\\ V_/_";
2449 /* sisusb->lock is down */
2451 if (!sisusb->SiS_Pr)
2454 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2455 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2458 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2460 if (!(myfont = find_font("VGA8x16")))
2463 if (!(tempbuf = vmalloc(8192)))
2466 for (i = 0; i < 256; i++)
2467 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2469 /* Upload default font */
2470 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2474 /* Upload user font (and reset current slot) */
2475 if (sisusb->font_backup) {
2476 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2477 8192, sisusb->font_backup_512, 1, NULL,
2478 sisusb->font_backup_height, 0);
2480 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2484 if (init && !sisusb->scrbuf) {
2486 if ((tempbuf = vmalloc(8192))) {
2489 tempbufb = (u16 *)tempbuf;
2491 *(tempbufb++) = 0x0720;
2494 tempbufb = (u16 *)tempbuf;
2495 while (bootlogo[i]) {
2496 *(tempbufb++) = 0x0700 | bootlogo[i++];
2502 tempbufb = (u16 *)tempbuf + 6;
2503 while (bootstring[i])
2504 *(tempbufb++) = 0x0700 | bootstring[i++];
2506 ret |= sisusb_copy_memory(sisusb, tempbuf,
2507 sisusb->vrambase, 8192, &written);
2513 } else if (sisusb->scrbuf) {
2515 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2516 sisusb->vrambase, sisusb->scrbuf_size, &written);
2520 if (sisusb->sisusb_cursor_size_from >= 0 &&
2521 sisusb->sisusb_cursor_size_to >= 0) {
2522 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2523 sisusb->sisusb_cursor_size_from);
2524 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2525 sisusb->sisusb_cursor_size_to);
2527 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2528 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2529 sisusb->sisusb_cursor_size_to = -1;
2532 slot = sisusb->sisusb_cursor_loc;
2533 if(slot < 0) slot = 0;
2535 sisusb->sisusb_cursor_loc = -1;
2536 sisusb->bad_cursor_pos = 1;
2538 sisusb_set_cursor(sisusb, slot);
2540 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2541 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2543 sisusb->textmodedestroyed = 0;
2545 /* sisusb->lock is down */
2555 sisusb_open(struct inode *inode, struct file *file)
2557 struct sisusb_usb_data *sisusb;
2558 struct usb_interface *interface;
2559 int subminor = iminor(inode);
2561 down(&disconnect_sem);
2563 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2564 printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
2566 up(&disconnect_sem);
2570 if (!(sisusb = usb_get_intfdata(interface))) {
2571 up(&disconnect_sem);
2575 down(&sisusb->lock);
2577 if (!sisusb->present || !sisusb->ready) {
2579 up(&disconnect_sem);
2583 if (sisusb->isopen) {
2585 up(&disconnect_sem);
2589 if (!sisusb->devinit) {
2590 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2591 if (sisusb_init_gfxdevice(sisusb, 0)) {
2593 up(&disconnect_sem);
2595 "sisusbvga[%d]: Failed to initialize "
2602 up(&disconnect_sem);
2604 "sisusbvga[%d]: Device not attached to "
2611 /* Increment usage count for our sisusb */
2612 kref_get(&sisusb->kref);
2616 file->private_data = sisusb;
2620 up(&disconnect_sem);
2626 sisusb_delete(struct kref *kref)
2628 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2633 if (sisusb->sisusb_dev)
2634 usb_put_dev(sisusb->sisusb_dev);
2636 sisusb->sisusb_dev = NULL;
2637 sisusb_free_buffers(sisusb);
2638 sisusb_free_urbs(sisusb);
2639 #ifdef INCL_SISUSB_CON
2640 kfree(sisusb->SiS_Pr);
2646 sisusb_release(struct inode *inode, struct file *file)
2648 struct sisusb_usb_data *sisusb;
2651 down(&disconnect_sem);
2653 if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
2654 up(&disconnect_sem);
2658 down(&sisusb->lock);
2660 if (sisusb->present) {
2661 /* Wait for all URBs to finish if device still present */
2662 if (!sisusb_wait_all_out_complete(sisusb))
2663 sisusb_kill_all_busy(sisusb);
2666 myminor = sisusb->minor;
2669 file->private_data = NULL;
2673 /* decrement the usage count on our device */
2674 kref_put(&sisusb->kref, sisusb_delete);
2676 up(&disconnect_sem);
2682 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2684 struct sisusb_usb_data *sisusb;
2685 ssize_t bytes_read = 0;
2691 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2694 down(&sisusb->lock);
2697 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2702 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2703 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2706 SISUSB_PCI_PSEUDO_IOPORTBASE +
2707 SISUSB_PCI_IOPORTBASE;
2710 * Byte, word and long(32) can be read. As this
2711 * emulates inX instructions, the data returned is
2712 * in machine-endianness.
2717 if (sisusb_read_memio_byte(sisusb,
2721 else if (put_user(buf8, (u8 __user *)buffer))
2729 if (sisusb_read_memio_word(sisusb,
2733 else if (put_user(buf16, (u16 __user *)buffer))
2741 if (sisusb_read_memio_long(sisusb,
2745 else if (put_user(buf32, (u32 __user *)buffer))
2757 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2758 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2761 SISUSB_PCI_PSEUDO_MEMBASE +
2765 * Remember: Data delivered is never endian-corrected
2767 errno = sisusb_read_mem_bulk(sisusb, address,
2768 NULL, count, buffer, &bytes_read);
2773 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2774 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2777 SISUSB_PCI_PSEUDO_MMIOBASE +
2778 SISUSB_PCI_MMIOBASE;
2781 * Remember: Data delivered is never endian-corrected
2783 errno = sisusb_read_mem_bulk(sisusb, address,
2784 NULL, count, buffer, &bytes_read);
2789 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2790 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2797 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2799 /* Read PCI config register
2800 * Return value delivered in machine endianness.
2802 if (sisusb_read_pci_config(sisusb, address, &buf32))
2804 else if (put_user(buf32, (u32 __user *)buffer))
2815 (*ppos) += bytes_read;
2819 return errno ? errno : bytes_read;
2823 sisusb_write(struct file *file, const char __user *buffer, size_t count,
2826 struct sisusb_usb_data *sisusb;
2828 ssize_t bytes_written = 0;
2833 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2836 down(&sisusb->lock);
2839 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2844 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2845 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2848 SISUSB_PCI_PSEUDO_IOPORTBASE +
2849 SISUSB_PCI_IOPORTBASE;
2852 * Byte, word and long(32) can be written. As this
2853 * emulates outX instructions, the data is expected
2854 * in machine-endianness.
2859 if (get_user(buf8, (u8 __user *)buffer))
2861 else if (sisusb_write_memio_byte(sisusb,
2871 if (get_user(buf16, (u16 __user *)buffer))
2873 else if (sisusb_write_memio_word(sisusb,
2883 if (get_user(buf32, (u32 __user *)buffer))
2885 else if (sisusb_write_memio_long(sisusb,
2898 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2899 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2902 SISUSB_PCI_PSEUDO_MEMBASE +
2906 * Buffer is copied 1:1, therefore, on big-endian
2907 * machines, the data must be swapped by userland
2908 * in advance (if applicable; no swapping in 8bpp
2909 * mode or if YUV data is being transferred).
2911 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2912 count, buffer, 0, &bytes_written);
2915 errno = bytes_written;
2917 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2918 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2921 SISUSB_PCI_PSEUDO_MMIOBASE +
2922 SISUSB_PCI_MMIOBASE;
2925 * Buffer is copied 1:1, therefore, on big-endian
2926 * machines, the data must be swapped by userland
2929 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2930 count, buffer, 0, &bytes_written);
2933 errno = bytes_written;
2935 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2936 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2943 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2945 /* Write PCI config register.
2946 * Given value expected in machine endianness.
2948 if (get_user(buf32, (u32 __user *)buffer))
2950 else if (sisusb_write_pci_config(sisusb, address, buf32))
2963 (*ppos) += bytes_written;
2967 return errno ? errno : bytes_written;
2971 sisusb_lseek(struct file *file, loff_t offset, int orig)
2973 struct sisusb_usb_data *sisusb;
2976 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2979 down(&sisusb->lock);
2982 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2989 file->f_pos = offset;
2991 /* never negative, no force_successful_syscall needed */
2994 file->f_pos += offset;
2996 /* never negative, no force_successful_syscall needed */
2999 /* seeking relative to "end of file" is not supported */
3008 sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
3011 int retval, port, length;
3014 /* All our commands require the device
3015 * to be initialized.
3017 if (!sisusb->devinit)
3021 SISUSB_PCI_PSEUDO_IOPORTBASE +
3022 SISUSB_PCI_IOPORTBASE;
3024 switch (y->operation) {
3026 retval = sisusb_getidxreg(sisusb, port,
3027 y->data0, &y->data1);
3029 if (copy_to_user((void __user *)arg, y,
3036 retval = sisusb_setidxreg(sisusb, port,
3037 y->data0, y->data1);
3041 retval = sisusb_setidxregor(sisusb, port,
3042 y->data0, y->data1);
3046 retval = sisusb_setidxregand(sisusb, port,
3047 y->data0, y->data1);
3050 case SUCMD_SETANDOR:
3051 retval = sisusb_setidxregandor(sisusb, port,
3052 y->data0, y->data1, y->data2);
3056 retval = sisusb_setidxregmask(sisusb, port,
3057 y->data0, y->data1, y->data2);
3061 /* Gfx core must be initialized */
3062 if (!sisusb->gfxinit)
3065 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
3066 address = y->data3 -
3067 SISUSB_PCI_PSEUDO_MEMBASE +
3069 retval = sisusb_clear_vram(sisusb, address, length);
3072 case SUCMD_HANDLETEXTMODE:
3074 #ifdef INCL_SISUSB_CON
3075 /* Gfx core must be initialized, SiS_Pr must exist */
3076 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3081 retval = sisusb_reset_text_mode(sisusb, 0);
3084 sisusb->textmodedestroyed = 1;
3090 #ifdef INCL_SISUSB_CON
3092 /* Gfx core must be initialized, SiS_Pr must exist */
3093 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3098 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3099 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3101 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
3106 case SUCMD_SETVESAMODE:
3107 /* Gfx core must be initialized, SiS_Pr must exist */
3108 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3113 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3114 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3116 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
3133 sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
3136 struct sisusb_usb_data *sisusb;
3137 struct sisusb_info x;
3138 struct sisusb_command y;
3140 u32 __user *argp = (u32 __user *)arg;
3142 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
3145 down(&sisusb->lock);
3148 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
3155 case SISUSB_GET_CONFIG_SIZE:
3157 if (put_user(sizeof(x), argp))
3162 case SISUSB_GET_CONFIG:
3164 x.sisusb_id = SISUSB_ID;
3165 x.sisusb_version = SISUSB_VERSION;
3166 x.sisusb_revision = SISUSB_REVISION;
3167 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3168 x.sisusb_gfxinit = sisusb->gfxinit;
3169 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
3170 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
3171 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
3172 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
3173 x.sisusb_vramsize = sisusb->vramsize;
3174 x.sisusb_minor = sisusb->minor;
3175 x.sisusb_fbdevactive= 0;
3176 #ifdef INCL_SISUSB_CON
3177 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3179 x.sisusb_conactive = 0;
3182 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3187 case SISUSB_COMMAND:
3189 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3192 retval = sisusb_handle_command(sisusb, &y, arg);
3206 #ifdef SISUSB_NEW_CONFIG_COMPAT
3208 sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3213 case SISUSB_GET_CONFIG_SIZE:
3214 case SISUSB_GET_CONFIG:
3215 case SISUSB_COMMAND:
3217 retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
3222 return -ENOIOCTLCMD;
3227 static struct file_operations usb_sisusb_fops = {
3228 .owner = THIS_MODULE,
3229 .open = sisusb_open,
3230 .release = sisusb_release,
3231 .read = sisusb_read,
3232 .write = sisusb_write,
3233 .llseek = sisusb_lseek,
3234 #ifdef SISUSB_NEW_CONFIG_COMPAT
3235 .compat_ioctl = sisusb_compat_ioctl,
3237 .ioctl = sisusb_ioctl
3240 static struct usb_class_driver usb_sisusb_class = {
3241 .name = "sisusbvga%d",
3242 .fops = &usb_sisusb_fops,
3243 .minor_base = SISUSB_MINOR
3246 static int sisusb_probe(struct usb_interface *intf,
3247 const struct usb_device_id *id)
3249 struct usb_device *dev = interface_to_usbdev(intf);
3250 struct sisusb_usb_data *sisusb;
3252 const char *memfail =
3254 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3256 printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
3259 /* Allocate memory for our private */
3260 if (!(sisusb = kmalloc(sizeof(*sisusb), GFP_KERNEL))) {
3262 "sisusb: Failed to allocate memory for private data\n");
3265 memset(sisusb, 0, sizeof(*sisusb));
3266 kref_init(&sisusb->kref);
3268 init_MUTEX(&(sisusb->lock));
3270 /* Register device */
3271 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3273 "sisusb: Failed to get a minor for device %d\n",
3279 sisusb->sisusb_dev = dev;
3280 sisusb->minor = intf->minor;
3281 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3282 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3283 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3284 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3285 /* Everything else is zero */
3287 /* Allocate buffers */
3288 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3289 if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3290 GFP_KERNEL, &sisusb->transfer_dma_in))) {
3291 printk(memfail, "input", sisusb->minor);
3296 sisusb->numobufs = 0;
3297 sisusb->obufsize = SISUSB_OBUF_SIZE;
3298 for (i = 0; i < NUMOBUFS; i++) {
3299 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3301 &sisusb->transfer_dma_out[i]))) {
3303 printk(memfail, "output", sisusb->minor);
3314 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3316 "sisusbvga[%d]: Failed to allocate URBs\n",
3321 sisusb->completein = 1;
3323 for (i = 0; i < sisusb->numobufs; i++) {
3324 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3326 "sisusbvga[%d]: Failed to allocate URBs\n",
3331 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3332 sisusb->urbout_context[i].urbindex = i;
3333 sisusb->urbstatus[i] = 0;
3336 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
3337 sisusb->minor, sisusb->numobufs);
3339 #ifdef INCL_SISUSB_CON
3340 /* Allocate our SiS_Pr */
3341 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3343 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3348 /* Do remaining init stuff */
3350 init_waitqueue_head(&sisusb->wait_q);
3352 usb_set_intfdata(intf, sisusb);
3354 usb_get_dev(sisusb->sisusb_dev);
3356 sisusb->present = 1;
3358 #ifdef SISUSB_OLD_CONFIG_COMPAT
3361 /* Our ioctls are all "32/64bit compatible" */
3362 ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
3363 ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
3364 ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
3367 "sisusbvga[%d]: Error registering ioctl32 "
3371 sisusb->ioctl32registered = 1;
3375 if (dev->speed == USB_SPEED_HIGH) {
3377 #ifdef INCL_SISUSB_CON
3378 if (sisusb_first_vc > 0 &&
3379 sisusb_last_vc > 0 &&
3380 sisusb_first_vc <= sisusb_last_vc &&
3381 sisusb_last_vc <= MAX_NR_CONSOLES)
3384 if (sisusb_init_gfxdevice(sisusb, initscreen))
3386 "sisusbvga[%d]: Failed to early "
3387 "initialize device\n",
3392 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3398 #ifdef SISUSBENDIANTEST
3399 printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
3400 sisusb_testreadwrite(sisusb);
3401 printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
3404 #ifdef INCL_SISUSB_CON
3405 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3411 sisusb_free_urbs(sisusb);
3413 sisusb_free_buffers(sisusb);
3415 usb_deregister_dev(intf, &usb_sisusb_class);
3421 static void sisusb_disconnect(struct usb_interface *intf)
3423 struct sisusb_usb_data *sisusb;
3426 /* This should *not* happen */
3427 if (!(sisusb = usb_get_intfdata(intf)))
3430 #ifdef INCL_SISUSB_CON
3431 sisusb_console_exit(sisusb);
3434 /* The above code doesn't need the disconnect
3435 * semaphore to be down; its meaning is to
3436 * protect all other routines from the disconnect
3437 * case, not the other way round.
3439 down(&disconnect_sem);
3441 down(&sisusb->lock);
3443 /* Wait for all URBs to complete and kill them in case (MUST do) */
3444 if (!sisusb_wait_all_out_complete(sisusb))
3445 sisusb_kill_all_busy(sisusb);
3447 minor = sisusb->minor;
3449 usb_set_intfdata(intf, NULL);
3451 usb_deregister_dev(intf, &usb_sisusb_class);
3453 #ifdef SISUSB_OLD_CONFIG_COMPAT
3454 if (sisusb->ioctl32registered) {
3456 sisusb->ioctl32registered = 0;
3457 ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
3458 ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
3459 ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
3462 "sisusbvga[%d]: Error unregistering "
3463 "ioctl32 translations\n",
3469 sisusb->present = 0;
3474 /* decrement our usage count */
3475 kref_put(&sisusb->kref, sisusb_delete);
3477 up(&disconnect_sem);
3479 printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
3482 static struct usb_device_id sisusb_table [] = {
3483 { USB_DEVICE(0x0711, 0x0900) },
3484 { USB_DEVICE(0x182d, 0x021c) },
3485 { USB_DEVICE(0x182d, 0x0269) },
3489 MODULE_DEVICE_TABLE (usb, sisusb_table);
3491 static struct usb_driver sisusb_driver = {
3492 .owner = THIS_MODULE,
3494 .probe = sisusb_probe,
3495 .disconnect = sisusb_disconnect,
3496 .id_table = sisusb_table,
3499 static int __init usb_sisusb_init(void)
3503 #ifdef INCL_SISUSB_CON
3504 sisusb_init_concode();
3507 if (!(retval = usb_register(&sisusb_driver))) {
3509 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
3510 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
3512 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3519 static void __exit usb_sisusb_exit(void)
3521 usb_deregister(&sisusb_driver);
3524 module_init(usb_sisusb_init);
3525 module_exit(usb_sisusb_exit);
3527 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3528 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3529 MODULE_LICENSE("GPL");