2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
8 * If distributed as part of the Linux kernel, this code is licensed under the
11 * Otherwise, the following license terms apply:
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific psisusbr written permission.
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
39 #include <linux/mutex.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/errno.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/slab.h>
47 #include <linux/spinlock.h>
48 #include <linux/kref.h>
49 #include <linux/usb.h>
50 #include <linux/vmalloc.h>
53 #include "sisusb_init.h"
55 #ifdef INCL_SISUSB_CON
56 #include <linux/font.h>
59 #define SISUSB_DONTSYNC
61 /* Forward declarations / clean-up routines */
63 #ifdef INCL_SISUSB_CON
64 static int sisusb_first_vc
= 0;
65 static int sisusb_last_vc
= 0;
66 module_param_named(first
, sisusb_first_vc
, int, 0);
67 module_param_named(last
, sisusb_last_vc
, int, 0);
68 MODULE_PARM_DESC(first
, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
69 MODULE_PARM_DESC(last
, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
72 static struct usb_driver sisusb_driver
;
75 sisusb_free_buffers(struct sisusb_usb_data
*sisusb
)
79 for (i
= 0; i
< NUMOBUFS
; i
++) {
80 if (sisusb
->obuf
[i
]) {
81 kfree(sisusb
->obuf
[i
]);
82 sisusb
->obuf
[i
] = NULL
;
92 sisusb_free_urbs(struct sisusb_usb_data
*sisusb
)
96 for (i
= 0; i
< NUMOBUFS
; i
++) {
97 usb_free_urb(sisusb
->sisurbout
[i
]);
98 sisusb
->sisurbout
[i
] = NULL
;
100 usb_free_urb(sisusb
->sisurbin
);
101 sisusb
->sisurbin
= NULL
;
104 /* Level 0: USB transport layer */
108 /* out-urb management */
110 /* Return 1 if all free, 0 otherwise */
112 sisusb_all_free(struct sisusb_usb_data
*sisusb
)
116 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
118 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
126 /* Kill all busy URBs */
128 sisusb_kill_all_busy(struct sisusb_usb_data
*sisusb
)
132 if (sisusb_all_free(sisusb
))
135 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
137 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
138 usb_kill_urb(sisusb
->sisurbout
[i
]);
143 /* Return 1 if ok, 0 if error (not all complete within timeout) */
145 sisusb_wait_all_out_complete(struct sisusb_usb_data
*sisusb
)
147 int timeout
= 5 * HZ
, i
= 1;
149 wait_event_timeout(sisusb
->wait_q
,
150 (i
= sisusb_all_free(sisusb
)),
157 sisusb_outurb_available(struct sisusb_usb_data
*sisusb
)
161 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
163 if ((sisusb
->urbstatus
[i
] & (SU_URB_BUSY
|SU_URB_ALLOC
)) == 0)
172 sisusb_get_free_outbuf(struct sisusb_usb_data
*sisusb
)
174 int i
, timeout
= 5 * HZ
;
176 wait_event_timeout(sisusb
->wait_q
,
177 ((i
= sisusb_outurb_available(sisusb
)) >= 0),
184 sisusb_alloc_outbuf(struct sisusb_usb_data
*sisusb
)
188 i
= sisusb_outurb_available(sisusb
);
191 sisusb
->urbstatus
[i
] |= SU_URB_ALLOC
;
197 sisusb_free_outbuf(struct sisusb_usb_data
*sisusb
, int index
)
199 if ((index
>= 0) && (index
< sisusb
->numobufs
))
200 sisusb
->urbstatus
[index
] &= ~SU_URB_ALLOC
;
203 /* completion callback */
206 sisusb_bulk_completeout(struct urb
*urb
)
208 struct sisusb_urb_context
*context
= urb
->context
;
209 struct sisusb_usb_data
*sisusb
;
214 sisusb
= context
->sisusb
;
216 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
219 #ifndef SISUSB_DONTSYNC
220 if (context
->actual_length
)
221 *(context
->actual_length
) += urb
->actual_length
;
224 sisusb
->urbstatus
[context
->urbindex
] &= ~SU_URB_BUSY
;
225 wake_up(&sisusb
->wait_q
);
229 sisusb_bulkout_msg(struct sisusb_usb_data
*sisusb
, int index
, unsigned int pipe
, void *data
,
230 int len
, int *actual_length
, int timeout
, unsigned int tflags
)
232 struct urb
*urb
= sisusb
->sisurbout
[index
];
233 int retval
, byteswritten
= 0;
236 urb
->transfer_flags
= 0;
238 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
239 sisusb_bulk_completeout
, &sisusb
->urbout_context
[index
]);
241 urb
->transfer_flags
|= tflags
;
242 urb
->actual_length
= 0;
245 sisusb
->urbout_context
[index
].actual_length
= (timeout
) ?
246 NULL
: actual_length
;
248 /* Declare this urb/buffer in use */
249 sisusb
->urbstatus
[index
] |= SU_URB_BUSY
;
252 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
254 /* If OK, and if timeout > 0, wait for completion */
255 if ((retval
== 0) && timeout
) {
256 wait_event_timeout(sisusb
->wait_q
,
257 (!(sisusb
->urbstatus
[index
] & SU_URB_BUSY
)),
259 if (sisusb
->urbstatus
[index
] & SU_URB_BUSY
) {
260 /* URB timed out... kill it and report error */
264 /* Otherwise, report urb status */
265 retval
= urb
->status
;
266 byteswritten
= urb
->actual_length
;
271 *actual_length
= byteswritten
;
278 /* completion callback */
281 sisusb_bulk_completein(struct urb
*urb
)
283 struct sisusb_usb_data
*sisusb
= urb
->context
;
285 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
288 sisusb
->completein
= 1;
289 wake_up(&sisusb
->wait_q
);
293 sisusb_bulkin_msg(struct sisusb_usb_data
*sisusb
, unsigned int pipe
, void *data
,
294 int len
, int *actual_length
, int timeout
, unsigned int tflags
)
296 struct urb
*urb
= sisusb
->sisurbin
;
297 int retval
, readbytes
= 0;
299 urb
->transfer_flags
= 0;
301 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
302 sisusb_bulk_completein
, sisusb
);
304 urb
->transfer_flags
|= tflags
;
305 urb
->actual_length
= 0;
307 sisusb
->completein
= 0;
308 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
310 wait_event_timeout(sisusb
->wait_q
, sisusb
->completein
, timeout
);
311 if (!sisusb
->completein
) {
312 /* URB timed out... kill it and report error */
316 /* URB completed within timeout */
317 retval
= urb
->status
;
318 readbytes
= urb
->actual_length
;
323 *actual_length
= readbytes
;
331 /* Send a bulk message of variable size
333 * To copy the data from userspace, give pointer to "userbuffer",
334 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
335 * both of these are NULL, it is assumed, that the transfer
336 * buffer "sisusb->obuf[index]" is set up with the data to send.
337 * Index is ignored if either kernbuffer or userbuffer is set.
338 * If async is nonzero, URBs will be sent without waiting for
339 * completion of the previous URB.
341 * (return 0 on success)
344 static int sisusb_send_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
345 char *kernbuffer
, const char __user
*userbuffer
, int index
,
346 ssize_t
*bytes_written
, unsigned int tflags
, int async
)
348 int result
= 0, retry
, count
= len
;
349 int passsize
, thispass
, transferred_len
= 0;
350 int fromuser
= (userbuffer
!= NULL
) ? 1 : 0;
351 int fromkern
= (kernbuffer
!= NULL
) ? 1 : 0;
355 (*bytes_written
) = 0;
358 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
361 /* If we copy data from kernel or userspace, force the
362 * allocation of a buffer/urb. If we have the data in
363 * the transfer buffer[index] already, reuse the buffer/URB
364 * if the length is > buffer size. (So, transmitting
365 * large data amounts directly from the transfer buffer
366 * treats the buffer as a ring buffer. However, we need
367 * to sync in this case.)
369 if (fromuser
|| fromkern
)
371 else if (len
> sisusb
->obufsize
)
374 pipe
= usb_sndbulkpipe(sisusb
->sisusb_dev
, ep
);
377 passsize
= thispass
= (sisusb
->obufsize
< count
) ?
378 sisusb
->obufsize
: count
;
381 index
= sisusb_get_free_outbuf(sisusb
);
386 buffer
= sisusb
->obuf
[index
];
390 if (copy_from_user(buffer
, userbuffer
, passsize
))
393 userbuffer
+= passsize
;
395 } else if (fromkern
) {
397 memcpy(buffer
, kernbuffer
, passsize
);
398 kernbuffer
+= passsize
;
405 if (!sisusb
->sisusb_dev
)
408 result
= sisusb_bulkout_msg(sisusb
,
417 if (result
== -ETIMEDOUT
) {
419 /* Will not happen if async */
426 if ((result
== 0) && !async
&& transferred_len
) {
428 thispass
-= transferred_len
;
429 buffer
+= transferred_len
;
438 (*bytes_written
) += passsize
;
441 /* Force new allocation in next iteration */
442 if (fromuser
|| fromkern
)
448 #ifdef SISUSB_DONTSYNC
449 (*bytes_written
) = len
;
450 /* Some URBs/buffers might be busy */
452 sisusb_wait_all_out_complete(sisusb
);
453 (*bytes_written
) = transferred_len
;
454 /* All URBs and all buffers are available */
458 return ((*bytes_written
) == len
) ? 0 : -EIO
;
461 /* Receive a bulk message of variable size
463 * To copy the data to userspace, give pointer to "userbuffer",
464 * to copy to kernel memory, give "kernbuffer". One of them
465 * MUST be set. (There is no technique for letting the caller
466 * read directly from the ibuf.)
470 static int sisusb_recv_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
471 void *kernbuffer
, char __user
*userbuffer
, ssize_t
*bytes_read
,
474 int result
= 0, retry
, count
= len
;
475 int bufsize
, thispass
, transferred_len
;
482 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
485 pipe
= usb_rcvbulkpipe(sisusb
->sisusb_dev
, ep
);
486 buffer
= sisusb
->ibuf
;
487 bufsize
= sisusb
->ibufsize
;
491 #ifdef SISUSB_DONTSYNC
492 if (!(sisusb_wait_all_out_complete(sisusb
)))
498 if (!sisusb
->sisusb_dev
)
501 thispass
= (bufsize
< count
) ? bufsize
: count
;
503 result
= sisusb_bulkin_msg(sisusb
,
512 thispass
= transferred_len
;
514 else if (result
== -ETIMEDOUT
) {
527 (*bytes_read
) += thispass
;
532 if (copy_to_user(userbuffer
, buffer
, thispass
))
535 userbuffer
+= thispass
;
539 memcpy(kernbuffer
, buffer
, thispass
);
540 kernbuffer
+= thispass
;
548 return ((*bytes_read
) == len
) ? 0 : -EIO
;
551 static int sisusb_send_packet(struct sisusb_usb_data
*sisusb
, int len
,
552 struct sisusb_packet
*packet
)
555 ssize_t bytes_transferred
= 0;
561 #ifdef SISUSB_DONTSYNC
562 if (!(sisusb_wait_all_out_complete(sisusb
)))
566 /* Eventually correct endianness */
567 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
569 /* 1. send the packet */
570 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_GFX_OUT
, len
,
571 (char *)packet
, NULL
, 0, &bytes_transferred
, 0, 0);
573 if ((ret
== 0) && (len
== 6)) {
575 /* 2. if packet len == 6, it means we read, so wait for 32bit
576 * return value and write it to packet->data
578 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_GFX_IN
, 4,
579 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
581 packet
->data
= le32_to_cpu(tmp
);
587 static int sisusb_send_bridge_packet(struct sisusb_usb_data
*sisusb
, int len
,
588 struct sisusb_packet
*packet
,
592 ssize_t bytes_transferred
= 0;
598 #ifdef SISUSB_DONTSYNC
599 if (!(sisusb_wait_all_out_complete(sisusb
)))
603 /* Eventually correct endianness */
604 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
606 /* 1. send the packet */
607 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_OUT
, len
,
608 (char *)packet
, NULL
, 0, &bytes_transferred
, tflags
, 0);
610 if ((ret
== 0) && (len
== 6)) {
612 /* 2. if packet len == 6, it means we read, so wait for 32bit
613 * return value and write it to packet->data
615 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_IN
, 4,
616 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
618 packet
->data
= le32_to_cpu(tmp
);
624 /* access video memory and mmio (return 0 on success) */
628 /* The following routines assume being used to transfer byte, word,
631 * - the write routines expect "data" in machine endianness format.
632 * The data will be converted to leXX in sisusb_xxx_packet.
633 * - the read routines can expect read data in machine-endianess.
636 static int sisusb_write_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
639 struct sisusb_packet packet
;
642 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
643 packet
.address
= addr
& ~3;
644 packet
.data
= data
<< ((addr
& 3) << 3);
645 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
649 static int sisusb_write_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
652 struct sisusb_packet packet
;
655 packet
.address
= addr
& ~3;
659 packet
.header
= (type
<< 6) | 0x0003;
660 packet
.data
= (u32
)data
;
661 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
664 packet
.header
= (type
<< 6) | 0x0006;
665 packet
.data
= (u32
)data
<< 8;
666 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
669 packet
.header
= (type
<< 6) | 0x000c;
670 packet
.data
= (u32
)data
<< 16;
671 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
674 packet
.header
= (type
<< 6) | 0x0008;
675 packet
.data
= (u32
)data
<< 24;
676 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
677 packet
.header
= (type
<< 6) | 0x0001;
678 packet
.address
= (addr
& ~3) + 4;
679 packet
.data
= (u32
)data
>> 8;
680 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
686 static int sisusb_write_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
689 struct sisusb_packet packet
;
692 packet
.address
= addr
& ~3;
696 packet
.header
= (type
<< 6) | 0x0007;
697 packet
.data
= data
& 0x00ffffff;
698 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
701 packet
.header
= (type
<< 6) | 0x000e;
702 packet
.data
= data
<< 8;
703 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
706 packet
.header
= (type
<< 6) | 0x000c;
707 packet
.data
= data
<< 16;
708 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
709 packet
.header
= (type
<< 6) | 0x0001;
710 packet
.address
= (addr
& ~3) + 4;
711 packet
.data
= (data
>> 16) & 0x00ff;
712 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
715 packet
.header
= (type
<< 6) | 0x0008;
716 packet
.data
= data
<< 24;
717 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
718 packet
.header
= (type
<< 6) | 0x0003;
719 packet
.address
= (addr
& ~3) + 4;
720 packet
.data
= (data
>> 8) & 0xffff;
721 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
727 static int sisusb_write_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
730 struct sisusb_packet packet
;
733 packet
.address
= addr
& ~3;
737 packet
.header
= (type
<< 6) | 0x000f;
739 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
742 packet
.header
= (type
<< 6) | 0x000e;
743 packet
.data
= data
<< 8;
744 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
745 packet
.header
= (type
<< 6) | 0x0001;
746 packet
.address
= (addr
& ~3) + 4;
747 packet
.data
= data
>> 24;
748 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
751 packet
.header
= (type
<< 6) | 0x000c;
752 packet
.data
= data
<< 16;
753 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
754 packet
.header
= (type
<< 6) | 0x0003;
755 packet
.address
= (addr
& ~3) + 4;
756 packet
.data
= data
>> 16;
757 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
760 packet
.header
= (type
<< 6) | 0x0008;
761 packet
.data
= data
<< 24;
762 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
763 packet
.header
= (type
<< 6) | 0x0007;
764 packet
.address
= (addr
& ~3) + 4;
765 packet
.data
= data
>> 8;
766 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
772 /* The xxx_bulk routines copy a buffer of variable size. They treat the
773 * buffer as chars, therefore lsb/msb has to be corrected if using the
774 * byte/word/long/etc routines for speed-up
776 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
777 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
778 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
779 * that the data already is in the transfer buffer "sisusb->obuf[index]".
782 static int sisusb_write_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
783 char *kernbuffer
, int length
,
784 const char __user
*userbuffer
, int index
,
785 ssize_t
*bytes_written
)
787 struct sisusb_packet packet
;
789 static int msgcount
= 0;
790 u8 swap8
, fromkern
= kernbuffer
? 1 : 0;
792 u32 swap32
, flag
= (length
>> 28) & 1;
795 /* if neither kernbuffer not userbuffer are given, assume
798 if (!fromkern
&& !userbuffer
)
799 kernbuffer
= sisusb
->obuf
[index
];
801 (*bytes_written
= 0);
803 length
&= 0x00ffffff;
811 if (get_user(swap8
, (u8 __user
*)userbuffer
))
814 swap8
= kernbuffer
[0];
816 ret
= sisusb_write_memio_byte(sisusb
,
827 if (get_user(swap16
, (u16 __user
*)userbuffer
))
830 swap16
= *((u16
*)kernbuffer
);
832 ret
= sisusb_write_memio_word(sisusb
,
838 (*bytes_written
) += 2;
844 if (copy_from_user(&buf
, userbuffer
, 3))
847 swap32
= (buf
[0] << 16) |
851 swap32
= (buf
[2] << 16) |
857 swap32
= (kernbuffer
[0] << 16) |
858 (kernbuffer
[1] << 8) |
861 swap32
= (kernbuffer
[2] << 16) |
862 (kernbuffer
[1] << 8) |
866 ret
= sisusb_write_memio_24bit(sisusb
,
872 (*bytes_written
) += 3;
878 if (get_user(swap32
, (u32 __user
*)userbuffer
))
881 swap32
= *((u32
*)kernbuffer
);
883 ret
= sisusb_write_memio_long(sisusb
,
888 (*bytes_written
) += 4;
893 if ((length
& ~3) > 0x10000) {
895 packet
.header
= 0x001f;
896 packet
.address
= 0x000001d4;
898 ret
= sisusb_send_bridge_packet(sisusb
, 10,
900 packet
.header
= 0x001f;
901 packet
.address
= 0x000001d0;
902 packet
.data
= (length
& ~3);
903 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
905 packet
.header
= 0x001f;
906 packet
.address
= 0x000001c0;
907 packet
.data
= flag
| 0x16;
908 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
911 ret
|= sisusb_send_bulk_msg(sisusb
,
912 SISUSB_EP_GFX_LBULK_OUT
,
915 bytes_written
, 0, 1);
916 userbuffer
+= (*bytes_written
);
917 } else if (fromkern
) {
918 ret
|= sisusb_send_bulk_msg(sisusb
,
919 SISUSB_EP_GFX_LBULK_OUT
,
922 bytes_written
, 0, 1);
923 kernbuffer
+= (*bytes_written
);
925 ret
|= sisusb_send_bulk_msg(sisusb
,
926 SISUSB_EP_GFX_LBULK_OUT
,
929 bytes_written
, 0, 1);
930 kernbuffer
+= ((*bytes_written
) &
931 (sisusb
->obufsize
-1));
936 packet
.header
= 0x001f;
937 packet
.address
= 0x00000194;
939 ret
= sisusb_send_bridge_packet(sisusb
, 10,
941 packet
.header
= 0x001f;
942 packet
.address
= 0x00000190;
943 packet
.data
= (length
& ~3);
944 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
946 if (sisusb
->flagb0
!= 0x16) {
947 packet
.header
= 0x001f;
948 packet
.address
= 0x00000180;
949 packet
.data
= flag
| 0x16;
950 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
952 sisusb
->flagb0
= 0x16;
955 ret
|= sisusb_send_bulk_msg(sisusb
,
956 SISUSB_EP_GFX_BULK_OUT
,
959 bytes_written
, 0, 1);
960 userbuffer
+= (*bytes_written
);
961 } else if (fromkern
) {
962 ret
|= sisusb_send_bulk_msg(sisusb
,
963 SISUSB_EP_GFX_BULK_OUT
,
966 bytes_written
, 0, 1);
967 kernbuffer
+= (*bytes_written
);
969 ret
|= sisusb_send_bulk_msg(sisusb
,
970 SISUSB_EP_GFX_BULK_OUT
,
973 bytes_written
, 0, 1);
974 kernbuffer
+= ((*bytes_written
) &
975 (sisusb
->obufsize
-1));
981 dev_err(&sisusb
->sisusb_dev
->dev
, "Wrote %zd of %d bytes, error %d\n",
982 *bytes_written
, length
, ret
);
983 else if (msgcount
== 500)
984 dev_err(&sisusb
->sisusb_dev
->dev
, "Too many errors, logging stopped\n");
986 addr
+= (*bytes_written
);
987 length
-= (*bytes_written
);
995 return ret
? -EIO
: 0;
998 /* Remember: Read data in packet is in machine-endianess! So for
999 * byte, word, 24bit, long no endian correction is necessary.
1002 static int sisusb_read_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
1005 struct sisusb_packet packet
;
1008 CLEARPACKET(&packet
);
1009 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
1010 packet
.address
= addr
& ~3;
1011 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1012 *data
= (u8
)(packet
.data
>> ((addr
& 3) << 3));
1016 static int sisusb_read_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
1017 u32 addr
, u16
*data
)
1019 struct sisusb_packet packet
;
1022 CLEARPACKET(&packet
);
1024 packet
.address
= addr
& ~3;
1028 packet
.header
= (type
<< 6) | 0x0003;
1029 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1030 *data
= (u16
)(packet
.data
);
1033 packet
.header
= (type
<< 6) | 0x0006;
1034 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1035 *data
= (u16
)(packet
.data
>> 8);
1038 packet
.header
= (type
<< 6) | 0x000c;
1039 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1040 *data
= (u16
)(packet
.data
>> 16);
1043 packet
.header
= (type
<< 6) | 0x0008;
1044 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1045 *data
= (u16
)(packet
.data
>> 24);
1046 packet
.header
= (type
<< 6) | 0x0001;
1047 packet
.address
= (addr
& ~3) + 4;
1048 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1049 *data
|= (u16
)(packet
.data
<< 8);
1055 static int sisusb_read_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
1056 u32 addr
, u32
*data
)
1058 struct sisusb_packet packet
;
1061 packet
.address
= addr
& ~3;
1065 packet
.header
= (type
<< 6) | 0x0007;
1066 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1067 *data
= packet
.data
& 0x00ffffff;
1070 packet
.header
= (type
<< 6) | 0x000e;
1071 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1072 *data
= packet
.data
>> 8;
1075 packet
.header
= (type
<< 6) | 0x000c;
1076 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1077 *data
= packet
.data
>> 16;
1078 packet
.header
= (type
<< 6) | 0x0001;
1079 packet
.address
= (addr
& ~3) + 4;
1080 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1081 *data
|= ((packet
.data
& 0xff) << 16);
1084 packet
.header
= (type
<< 6) | 0x0008;
1085 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1086 *data
= packet
.data
>> 24;
1087 packet
.header
= (type
<< 6) | 0x0003;
1088 packet
.address
= (addr
& ~3) + 4;
1089 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1090 *data
|= ((packet
.data
& 0xffff) << 8);
1096 static int sisusb_read_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
1097 u32 addr
, u32
*data
)
1099 struct sisusb_packet packet
;
1102 packet
.address
= addr
& ~3;
1106 packet
.header
= (type
<< 6) | 0x000f;
1107 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1108 *data
= packet
.data
;
1111 packet
.header
= (type
<< 6) | 0x000e;
1112 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1113 *data
= packet
.data
>> 8;
1114 packet
.header
= (type
<< 6) | 0x0001;
1115 packet
.address
= (addr
& ~3) + 4;
1116 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1117 *data
|= (packet
.data
<< 24);
1120 packet
.header
= (type
<< 6) | 0x000c;
1121 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1122 *data
= packet
.data
>> 16;
1123 packet
.header
= (type
<< 6) | 0x0003;
1124 packet
.address
= (addr
& ~3) + 4;
1125 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1126 *data
|= (packet
.data
<< 16);
1129 packet
.header
= (type
<< 6) | 0x0008;
1130 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1131 *data
= packet
.data
>> 24;
1132 packet
.header
= (type
<< 6) | 0x0007;
1133 packet
.address
= (addr
& ~3) + 4;
1134 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1135 *data
|= (packet
.data
<< 8);
1141 static int sisusb_read_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
1142 char *kernbuffer
, int length
,
1143 char __user
*userbuffer
, ssize_t
*bytes_read
)
1152 length
&= 0x00ffffff;
1160 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
1165 if (put_user(buf
[0],
1166 (u8 __user
*)userbuffer
)) {
1170 kernbuffer
[0] = buf
[0];
1176 ret
|= sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1181 if (put_user(swap16
,
1182 (u16 __user
*)userbuffer
))
1185 *((u16
*)kernbuffer
) = swap16
;
1191 ret
|= sisusb_read_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
1196 buf
[0] = (swap32
>> 16) & 0xff;
1197 buf
[1] = (swap32
>> 8) & 0xff;
1198 buf
[2] = swap32
& 0xff;
1200 buf
[2] = (swap32
>> 16) & 0xff;
1201 buf
[1] = (swap32
>> 8) & 0xff;
1202 buf
[0] = swap32
& 0xff;
1205 if (copy_to_user(userbuffer
, &buf
[0], 3))
1208 kernbuffer
[0] = buf
[0];
1209 kernbuffer
[1] = buf
[1];
1210 kernbuffer
[2] = buf
[2];
1216 ret
|= sisusb_read_memio_long(sisusb
, SISUSB_TYPE_MEM
,
1221 if (put_user(swap32
,
1222 (u32 __user
*)userbuffer
))
1227 *((u32
*)kernbuffer
) = swap32
;
1242 /* High level: Gfx (indexed) register access */
1244 #ifdef INCL_SISUSB_CON
1246 sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
)
1248 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1252 sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
)
1254 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1259 sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 data
)
1262 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1263 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1268 sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8
*data
)
1271 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1272 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1277 sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1283 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1284 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1287 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1292 sisusb_setidxregmask(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1297 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1298 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1300 tmp
|= (data
& mask
);
1301 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1306 sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 myor
)
1308 return(sisusb_setidxregandor(sisusb
, port
, index
, 0xff, myor
));
1312 sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
)
1314 return(sisusb_setidxregandor(sisusb
, port
, idx
, myand
, 0x00));
1317 /* Write/read video ram */
1319 #ifdef INCL_SISUSB_CON
1321 sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
)
1323 return(sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1327 sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
)
1329 return(sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1333 sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
1334 u32 dest
, int length
, size_t *bytes_written
)
1336 return(sisusb_write_mem_bulk(sisusb
, dest
, src
, length
, NULL
, 0, bytes_written
));
1339 #ifdef SISUSBENDIANTEST
1341 sisusb_read_memory(struct sisusb_usb_data
*sisusb
, char *dest
,
1342 u32 src
, int length
, size_t *bytes_written
)
1344 return(sisusb_read_mem_bulk(sisusb
, src
, dest
, length
, NULL
, bytes_written
));
1349 #ifdef SISUSBENDIANTEST
1351 sisusb_testreadwrite(struct sisusb_usb_data
*sisusb
)
1353 static char srcbuffer
[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1354 char destbuffer
[10];
1358 sisusb_copy_memory(sisusb
, srcbuffer
, sisusb
->vrambase
, 7, &dummy
);
1360 for(i
= 1; i
<= 7; i
++) {
1361 dev_dbg(&sisusb
->sisusb_dev
->dev
, "sisusb: rwtest %d bytes\n", i
);
1362 sisusb_read_memory(sisusb
, destbuffer
, sisusb
->vrambase
, i
, &dummy
);
1363 for(j
= 0; j
< i
; j
++) {
1364 dev_dbg(&sisusb
->sisusb_dev
->dev
, "rwtest read[%d] = %x\n", j
, destbuffer
[j
]);
1370 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1373 sisusb_write_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32 data
)
1375 struct sisusb_packet packet
;
1378 packet
.header
= 0x008f;
1379 packet
.address
= regnum
| 0x10000;
1381 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
1386 sisusb_read_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32
*data
)
1388 struct sisusb_packet packet
;
1391 packet
.header
= 0x008f;
1392 packet
.address
= (u32
)regnum
| 0x10000;
1393 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1394 *data
= packet
.data
;
1398 /* Clear video RAM */
1401 sisusb_clear_vram(struct sisusb_usb_data
*sisusb
, u32 address
, int length
)
1406 if (address
< sisusb
->vrambase
)
1409 if (address
>= sisusb
->vrambase
+ sisusb
->vramsize
)
1412 if (address
+ length
> sisusb
->vrambase
+ sisusb
->vramsize
)
1413 length
= sisusb
->vrambase
+ sisusb
->vramsize
- address
;
1418 /* allocate free buffer/urb and clear the buffer */
1419 if ((i
= sisusb_alloc_outbuf(sisusb
)) < 0)
1422 memset(sisusb
->obuf
[i
], 0, sisusb
->obufsize
);
1424 /* We can write a length > buffer size here. The buffer
1425 * data will simply be re-used (like a ring-buffer).
1427 ret
= sisusb_write_mem_bulk(sisusb
, address
, NULL
, length
, NULL
, i
, &j
);
1429 /* Free the buffer/urb */
1430 sisusb_free_outbuf(sisusb
, i
);
1435 /* Initialize the graphics core (return 0 on success)
1436 * This resets the graphics hardware and puts it into
1437 * a defined mode (640x480@60Hz)
1440 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1441 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1442 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1443 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1444 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1445 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1446 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1447 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1448 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1449 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1450 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1453 sisusb_triggersr16(struct sisusb_usb_data
*sisusb
, u8 ramtype
)
1458 ret
= GETIREG(SISSR
, 0x16, &tmp8
);
1461 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1463 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1466 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1468 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1470 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1472 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1474 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1476 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1478 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1484 sisusb_getbuswidth(struct sisusb_usb_data
*sisusb
, int *bw
, int *chab
)
1487 u8 ramtype
, done
= 0;
1489 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1491 ret
= GETIREG(SISSR
, 0x3a, &ramtype
);
1494 ret
|= SETIREG(SISSR
, 0x13, 0x00);
1497 ret
|= SETIREG(SISSR
, 0x14, 0x12);
1498 ret
|= SETIREGAND(SISSR
, 0x15, 0xef);
1500 ret
|= SETIREG(SISSR
, 0x14, 0x02);
1503 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1504 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1505 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1506 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1507 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1508 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1509 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1510 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1511 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1512 ret
|= READL(ramptr
+ 0, &t0
);
1513 ret
|= READL(ramptr
+ 4, &t1
);
1514 ret
|= READL(ramptr
+ 8, &t2
);
1515 ret
|= READL(ramptr
+ 12, &t3
);
1519 *chab
= 0; *bw
= 64;
1521 if ((t3
!= 0xcdef0123) || (t2
!= 0x89abcdef)) {
1522 if ((t1
== 0x456789ab) && (t0
== 0x01234567)) {
1523 *chab
= 0; *bw
= 64;
1524 ret
|= SETIREGAND(SISSR
, 0x14, 0xfd);
1527 if ((t1
!= 0x456789ab) || (t0
!= 0x01234567)) {
1528 *chab
= 1; *bw
= 64;
1529 ret
|= SETIREGANDOR(SISSR
, 0x14, 0xfc,0x01);
1531 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1532 ret
|= WRITEL(ramptr
+ 0, 0x89abcdef);
1533 ret
|= WRITEL(ramptr
+ 4, 0xcdef0123);
1534 ret
|= WRITEL(ramptr
+ 8, 0x55555555);
1535 ret
|= WRITEL(ramptr
+ 12, 0x55555555);
1536 ret
|= WRITEL(ramptr
+ 16, 0xaaaaaaaa);
1537 ret
|= WRITEL(ramptr
+ 20, 0xaaaaaaaa);
1538 ret
|= READL(ramptr
+ 4, &t1
);
1540 if (t1
!= 0xcdef0123) {
1542 ret
|= SETIREGOR(SISSR
, 0x15, 0x10);
1548 *chab
= 0; *bw
= 64; /* default: cha, bw = 64 */
1552 if (t1
== 0x456789ab) {
1553 if (t0
== 0x01234567) {
1554 *chab
= 0; *bw
= 64;
1558 if (t0
== 0x01234567) {
1559 *chab
= 0; *bw
= 32;
1560 ret
|= SETIREG(SISSR
, 0x14, 0x00);
1566 ret
|= SETIREG(SISSR
, 0x14, 0x03);
1567 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1569 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1570 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1571 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1572 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1573 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1574 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1575 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1576 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1577 ret
|= READL(ramptr
+ 0, &t0
);
1578 ret
|= READL(ramptr
+ 4, &t1
);
1580 if (t1
== 0x456789ab) {
1581 if (t0
== 0x01234567) {
1582 *chab
= 1; *bw
= 64;
1586 if (t0
== 0x01234567) {
1587 *chab
= 1; *bw
= 32;
1588 ret
|= SETIREG(SISSR
, 0x14, 0x01);
1597 sisusb_verify_mclk(struct sisusb_usb_data
*sisusb
)
1600 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1601 u8 tmp1
, tmp2
, i
, j
;
1603 ret
|= WRITEB(ramptr
, 0xaa);
1604 ret
|= WRITEB(ramptr
+ 16, 0x55);
1605 ret
|= READB(ramptr
, &tmp1
);
1606 ret
|= READB(ramptr
+ 16, &tmp2
);
1607 if ((tmp1
!= 0xaa) || (tmp2
!= 0x55)) {
1608 for (i
= 0, j
= 16; i
< 2; i
++, j
+= 16) {
1609 ret
|= GETIREG(SISSR
, 0x21, &tmp1
);
1610 ret
|= SETIREGAND(SISSR
, 0x21, (tmp1
& 0xfb));
1611 ret
|= SETIREGOR(SISSR
, 0x3c, 0x01); /* not on 330 */
1612 ret
|= SETIREGAND(SISSR
, 0x3c, 0xfe); /* not on 330 */
1613 ret
|= SETIREG(SISSR
, 0x21, tmp1
);
1614 ret
|= WRITEB(ramptr
+ 16 + j
, j
);
1615 ret
|= READB(ramptr
+ 16 + j
, &tmp1
);
1617 ret
|= WRITEB(ramptr
+ j
, j
);
1626 sisusb_set_rank(struct sisusb_usb_data
*sisusb
, int *iret
, int index
,
1627 u8 rankno
, u8 chab
, const u8 dramtype
[][5],
1630 int ret
= 0, ranksize
;
1635 if ((rankno
== 2) && (dramtype
[index
][0] == 2))
1638 ranksize
= dramtype
[index
][3] / 2 * bw
/ 32;
1640 if ((ranksize
* rankno
) > 128)
1644 while ((ranksize
>>= 1) > 0) tmp
+= 0x10;
1645 tmp
|= ((rankno
- 1) << 2);
1646 tmp
|= ((bw
/ 64) & 0x02);
1647 tmp
|= (chab
& 0x01);
1649 ret
= SETIREG(SISSR
, 0x14, tmp
);
1650 ret
|= sisusb_triggersr16(sisusb
, 0); /* sic! */
1658 sisusb_check_rbc(struct sisusb_usb_data
*sisusb
, int *iret
, u32 inc
, int testn
)
1665 for (i
= 0, j
= 0; i
< testn
; i
++) {
1666 ret
|= WRITEL(sisusb
->vrambase
+ j
, j
);
1670 for (i
= 0, j
= 0; i
< testn
; i
++) {
1671 ret
|= READL(sisusb
->vrambase
+ j
, &tmp
);
1672 if (tmp
!= j
) return ret
;
1681 sisusb_check_ranks(struct sisusb_usb_data
*sisusb
, int *iret
, int rankno
,
1682 int idx
, int bw
, const u8 rtype
[][5])
1684 int ret
= 0, i
, i2ret
;
1689 for (i
= rankno
; i
>= 1; i
--) {
1690 inc
= 1 << (rtype
[idx
][2] +
1694 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1699 inc
= 1 << (rtype
[idx
][2] + bw
/ 64 + 2);
1700 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 4);
1704 inc
= 1 << (10 + bw
/ 64);
1705 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1714 sisusb_get_sdram_size(struct sisusb_usb_data
*sisusb
, int *iret
, int bw
,
1717 int ret
= 0, i2ret
= 0, i
, j
;
1718 static const u8 sdramtype
[13][5] = {
1719 { 2, 12, 9, 64, 0x35 },
1720 { 1, 13, 9, 64, 0x44 },
1721 { 2, 12, 8, 32, 0x31 },
1722 { 2, 11, 9, 32, 0x25 },
1723 { 1, 12, 9, 32, 0x34 },
1724 { 1, 13, 8, 32, 0x40 },
1725 { 2, 11, 8, 16, 0x21 },
1726 { 1, 12, 8, 16, 0x30 },
1727 { 1, 11, 9, 16, 0x24 },
1728 { 1, 11, 8, 8, 0x20 },
1729 { 2, 9, 8, 4, 0x01 },
1730 { 1, 10, 8, 4, 0x10 },
1731 { 1, 9, 8, 2, 0x00 }
1734 *iret
= 1; /* error */
1736 for (i
= 0; i
< 13; i
++) {
1737 ret
|= SETIREGANDOR(SISSR
, 0x13, 0x80, sdramtype
[i
][4]);
1738 for (j
= 2; j
> 0; j
--) {
1739 ret
|= sisusb_set_rank(sisusb
, &i2ret
, i
, j
,
1740 chab
, sdramtype
, bw
);
1744 ret
|= sisusb_check_ranks(sisusb
, &i2ret
, j
, i
,
1747 *iret
= 0; /* ram size found */
1757 sisusb_setup_screen(struct sisusb_usb_data
*sisusb
, int clrall
, int drwfr
)
1761 int i
, length
, modex
, modey
, bpp
;
1763 modex
= 640; modey
= 480; bpp
= 2;
1765 address
= sisusb
->vrambase
; /* Clear video ram */
1768 length
= sisusb
->vramsize
;
1770 length
= modex
* bpp
* modey
;
1772 ret
= sisusb_clear_vram(sisusb
, address
, length
);
1774 if (!ret
&& drwfr
) {
1775 for (i
= 0; i
< modex
; i
++) {
1776 address
= sisusb
->vrambase
+ (i
* bpp
);
1777 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1779 address
+= (modex
* (modey
-1) * bpp
);
1780 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1783 for (i
= 0; i
< modey
; i
++) {
1784 address
= sisusb
->vrambase
+ ((i
* modex
) * bpp
);
1785 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1787 address
+= ((modex
- 1) * bpp
);
1788 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1797 sisusb_set_default_mode(struct sisusb_usb_data
*sisusb
, int touchengines
)
1799 int ret
= 0, i
, j
, modex
, modey
, bpp
, du
;
1800 u8 sr31
, cr63
, tmp8
;
1801 static const char attrdata
[] = {
1802 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1803 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1806 static const char crtcrdata
[] = {
1807 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1808 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1809 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1812 static const char grcdata
[] = {
1813 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1816 static const char crtcdata
[] = {
1817 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1818 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1822 modex
= 640; modey
= 480; bpp
= 2;
1824 GETIREG(SISSR
, 0x31, &sr31
);
1825 GETIREG(SISCR
, 0x63, &cr63
);
1826 SETIREGOR(SISSR
, 0x01, 0x20);
1827 SETIREG(SISCR
, 0x63, cr63
& 0xbf);
1828 SETIREGOR(SISCR
, 0x17, 0x80);
1829 SETIREGOR(SISSR
, 0x1f, 0x04);
1830 SETIREGAND(SISSR
, 0x07, 0xfb);
1831 SETIREG(SISSR
, 0x00, 0x03); /* seq */
1832 SETIREG(SISSR
, 0x01, 0x21);
1833 SETIREG(SISSR
, 0x02, 0x0f);
1834 SETIREG(SISSR
, 0x03, 0x00);
1835 SETIREG(SISSR
, 0x04, 0x0e);
1836 SETREG(SISMISCW
, 0x23); /* misc */
1837 for (i
= 0; i
<= 0x18; i
++) { /* crtc */
1838 SETIREG(SISCR
, i
, crtcrdata
[i
]);
1840 for (i
= 0; i
<= 0x13; i
++) { /* att */
1841 GETREG(SISINPSTAT
, &tmp8
);
1843 SETREG(SISAR
, attrdata
[i
]);
1845 GETREG(SISINPSTAT
, &tmp8
);
1846 SETREG(SISAR
, 0x14);
1847 SETREG(SISAR
, 0x00);
1848 GETREG(SISINPSTAT
, &tmp8
);
1849 SETREG(SISAR
, 0x20);
1850 GETREG(SISINPSTAT
, &tmp8
);
1851 for (i
= 0; i
<= 0x08; i
++) { /* grc */
1852 SETIREG(SISGR
, i
, grcdata
[i
]);
1854 SETIREGAND(SISGR
, 0x05, 0xbf);
1855 for (i
= 0x0A; i
<= 0x0E; i
++) { /* clr ext */
1856 SETIREG(SISSR
, i
, 0x00);
1858 SETIREGAND(SISSR
, 0x37, 0xfe);
1859 SETREG(SISMISCW
, 0xef); /* sync */
1860 SETIREG(SISCR
, 0x11, 0x00); /* crtc */
1861 for (j
= 0x00, i
= 0; i
<= 7; i
++, j
++) {
1862 SETIREG(SISCR
, j
, crtcdata
[i
]);
1864 for (j
= 0x10; i
<= 10; i
++, j
++) {
1865 SETIREG(SISCR
, j
, crtcdata
[i
]);
1867 for (j
= 0x15; i
<= 12; i
++, j
++) {
1868 SETIREG(SISCR
, j
, crtcdata
[i
]);
1870 for (j
= 0x0A; i
<= 15; i
++, j
++) {
1871 SETIREG(SISSR
, j
, crtcdata
[i
]);
1873 SETIREG(SISSR
, 0x0E, (crtcdata
[16] & 0xE0));
1874 SETIREGANDOR(SISCR
, 0x09, 0x5f, ((crtcdata
[16] & 0x01) << 5));
1875 SETIREG(SISCR
, 0x14, 0x4f);
1876 du
= (modex
/ 16) * (bpp
* 2); /* offset/pitch */
1877 if (modex
% 16) du
+= bpp
;
1878 SETIREGANDOR(SISSR
, 0x0e, 0xf0, ((du
>> 8) & 0x0f));
1879 SETIREG(SISCR
, 0x13, (du
& 0xff));
1882 if (du
& 0xff) tmp8
++;
1883 SETIREG(SISSR
, 0x10, tmp8
);
1884 SETIREG(SISSR
, 0x31, 0x00); /* VCLK */
1885 SETIREG(SISSR
, 0x2b, 0x1b);
1886 SETIREG(SISSR
, 0x2c, 0xe1);
1887 SETIREG(SISSR
, 0x2d, 0x01);
1888 SETIREGAND(SISSR
, 0x3d, 0xfe); /* FIFO */
1889 SETIREG(SISSR
, 0x08, 0xae);
1890 SETIREGAND(SISSR
, 0x09, 0xf0);
1891 SETIREG(SISSR
, 0x08, 0x34);
1892 SETIREGOR(SISSR
, 0x3d, 0x01);
1893 SETIREGAND(SISSR
, 0x1f, 0x3f); /* mode regs */
1894 SETIREGANDOR(SISSR
, 0x06, 0xc0, 0x0a);
1895 SETIREG(SISCR
, 0x19, 0x00);
1896 SETIREGAND(SISCR
, 0x1a, 0xfc);
1897 SETIREGAND(SISSR
, 0x0f, 0xb7);
1898 SETIREGAND(SISSR
, 0x31, 0xfb);
1899 SETIREGANDOR(SISSR
, 0x21, 0x1f, 0xa0);
1900 SETIREGAND(SISSR
, 0x32, 0xf3);
1901 SETIREGANDOR(SISSR
, 0x07, 0xf8, 0x03);
1902 SETIREG(SISCR
, 0x52, 0x6c);
1904 SETIREG(SISCR
, 0x0d, 0x00); /* adjust frame */
1905 SETIREG(SISCR
, 0x0c, 0x00);
1906 SETIREG(SISSR
, 0x0d, 0x00);
1907 SETIREGAND(SISSR
, 0x37, 0xfe);
1909 SETIREG(SISCR
, 0x32, 0x20);
1910 SETIREGAND(SISSR
, 0x01, 0xdf); /* enable display */
1911 SETIREG(SISCR
, 0x63, (cr63
& 0xbf));
1912 SETIREG(SISSR
, 0x31, (sr31
& 0xfb));
1915 SETIREG(SISSR
, 0x20, 0xa1); /* enable engines */
1916 SETIREGOR(SISSR
, 0x1e, 0x5a);
1918 SETIREG(SISSR
, 0x26, 0x01); /* disable cmdqueue */
1919 SETIREG(SISSR
, 0x27, 0x1f);
1920 SETIREG(SISSR
, 0x26, 0x00);
1923 SETIREG(SISCR
, 0x34, 0x44); /* we just set std mode #44 */
1929 sisusb_init_gfxcore(struct sisusb_usb_data
*sisusb
)
1931 int ret
= 0, i
, j
, bw
, chab
, iret
, retry
= 3;
1934 static const char mclktable
[] = {
1935 0x3b, 0x22, 0x01, 143,
1936 0x3b, 0x22, 0x01, 143,
1937 0x3b, 0x22, 0x01, 143,
1938 0x3b, 0x22, 0x01, 143
1940 static const char eclktable
[] = {
1941 0x3b, 0x22, 0x01, 143,
1942 0x3b, 0x22, 0x01, 143,
1943 0x3b, 0x22, 0x01, 143,
1944 0x3b, 0x22, 0x01, 143
1946 static const char ramtypetable1
[] = {
1947 0x00, 0x04, 0x60, 0x60,
1948 0x0f, 0x0f, 0x1f, 0x1f,
1949 0xba, 0xba, 0xba, 0xba,
1950 0xa9, 0xa9, 0xac, 0xac,
1951 0xa0, 0xa0, 0xa0, 0xa8,
1952 0x00, 0x00, 0x02, 0x02,
1953 0x30, 0x30, 0x40, 0x40
1955 static const char ramtypetable2
[] = {
1956 0x77, 0x77, 0x44, 0x44,
1957 0x77, 0x77, 0x44, 0x44,
1958 0x00, 0x00, 0x00, 0x00,
1959 0x5b, 0x5b, 0xab, 0xab,
1960 0x00, 0x00, 0xf0, 0xf8
1966 ret
= GETREG(SISVGAEN
, &tmp8
);
1967 ret
|= SETREG(SISVGAEN
, (tmp8
| 0x01));
1969 /* Enable GPU access to VRAM */
1970 ret
|= GETREG(SISMISCR
, &tmp8
);
1971 ret
|= SETREG(SISMISCW
, (tmp8
| 0x01));
1975 /* Reset registers */
1976 ret
|= SETIREGAND(SISCR
, 0x5b, 0xdf);
1977 ret
|= SETIREG(SISSR
, 0x05, 0x86);
1978 ret
|= SETIREGOR(SISSR
, 0x20, 0x01);
1980 ret
|= SETREG(SISMISCW
, 0x67);
1982 for (i
= 0x06; i
<= 0x1f; i
++) {
1983 ret
|= SETIREG(SISSR
, i
, 0x00);
1985 for (i
= 0x21; i
<= 0x27; i
++) {
1986 ret
|= SETIREG(SISSR
, i
, 0x00);
1988 for (i
= 0x31; i
<= 0x3d; i
++) {
1989 ret
|= SETIREG(SISSR
, i
, 0x00);
1991 for (i
= 0x12; i
<= 0x1b; i
++) {
1992 ret
|= SETIREG(SISSR
, i
, 0x00);
1994 for (i
= 0x79; i
<= 0x7c; i
++) {
1995 ret
|= SETIREG(SISCR
, i
, 0x00);
2000 ret
|= SETIREG(SISCR
, 0x63, 0x80);
2002 ret
|= GETIREG(SISSR
, 0x3a, &ramtype
);
2005 ret
|= SETIREG(SISSR
, 0x28, mclktable
[ramtype
* 4]);
2006 ret
|= SETIREG(SISSR
, 0x29, mclktable
[(ramtype
* 4) + 1]);
2007 ret
|= SETIREG(SISSR
, 0x2a, mclktable
[(ramtype
* 4) + 2]);
2009 ret
|= SETIREG(SISSR
, 0x2e, eclktable
[ramtype
* 4]);
2010 ret
|= SETIREG(SISSR
, 0x2f, eclktable
[(ramtype
* 4) + 1]);
2011 ret
|= SETIREG(SISSR
, 0x30, eclktable
[(ramtype
* 4) + 2]);
2013 ret
|= SETIREG(SISSR
, 0x07, 0x18);
2014 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2018 for (i
= 0x15, j
= 0; i
<= 0x1b; i
++, j
++) {
2019 ret
|= SETIREG(SISSR
, i
, ramtypetable1
[(j
*4) + ramtype
]);
2021 for (i
= 0x40, j
= 0; i
<= 0x44; i
++, j
++) {
2022 ret
|= SETIREG(SISCR
, i
, ramtypetable2
[(j
*4) + ramtype
]);
2025 ret
|= SETIREG(SISCR
, 0x49, 0xaa);
2027 ret
|= SETIREG(SISSR
, 0x1f, 0x00);
2028 ret
|= SETIREG(SISSR
, 0x20, 0xa0);
2029 ret
|= SETIREG(SISSR
, 0x23, 0xf6);
2030 ret
|= SETIREG(SISSR
, 0x24, 0x0d);
2031 ret
|= SETIREG(SISSR
, 0x25, 0x33);
2033 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2035 ret
|= SETIREGOR(SISPART1
, 0x2f, 0x01);
2037 ret
|= SETIREGAND(SISCAP
, 0x3f, 0xef);
2041 ret
|= SETIREG(SISPART1
, 0x00, 0x00);
2043 ret
|= GETIREG(SISSR
, 0x13, &tmp8
);
2046 ret
|= SETIREG(SISPART1
, 0x02, 0x00);
2047 ret
|= SETIREG(SISPART1
, 0x2e, 0x08);
2049 ret
|= sisusb_read_pci_config(sisusb
, 0x50, &tmp32
);
2050 tmp32
&= 0x00f00000;
2051 tmp8
= (tmp32
== 0x100000) ? 0x33 : 0x03;
2052 ret
|= SETIREG(SISSR
, 0x25, tmp8
);
2053 tmp8
= (tmp32
== 0x100000) ? 0xaa : 0x88;
2054 ret
|= SETIREG(SISCR
, 0x49, tmp8
);
2056 ret
|= SETIREG(SISSR
, 0x27, 0x1f);
2057 ret
|= SETIREG(SISSR
, 0x31, 0x00);
2058 ret
|= SETIREG(SISSR
, 0x32, 0x11);
2059 ret
|= SETIREG(SISSR
, 0x33, 0x00);
2063 ret
|= SETIREG(SISCR
, 0x83, 0x00);
2065 ret
|= sisusb_set_default_mode(sisusb
, 0);
2067 ret
|= SETIREGAND(SISSR
, 0x21, 0xdf);
2068 ret
|= SETIREGOR(SISSR
, 0x01, 0x20);
2069 ret
|= SETIREGOR(SISSR
, 0x16, 0x0f);
2071 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
2073 /* Disable refresh */
2074 ret
|= SETIREGAND(SISSR
, 0x17, 0xf8);
2075 ret
|= SETIREGOR(SISSR
, 0x19, 0x03);
2077 ret
|= sisusb_getbuswidth(sisusb
, &bw
, &chab
);
2078 ret
|= sisusb_verify_mclk(sisusb
);
2081 ret
|= sisusb_get_sdram_size(sisusb
, &iret
, bw
, chab
);
2083 dev_err(&sisusb
->sisusb_dev
->dev
,"RAM size detection failed, assuming 8MB video RAM\n");
2084 ret
|= SETIREG(SISSR
,0x14,0x31);
2088 dev_err(&sisusb
->sisusb_dev
->dev
, "DDR RAM device found, assuming 8MB video RAM\n");
2089 ret
|= SETIREG(SISSR
,0x14,0x31);
2093 /* Enable refresh */
2094 ret
|= SETIREG(SISSR
, 0x16, ramtypetable1
[4 + ramtype
]);
2095 ret
|= SETIREG(SISSR
, 0x17, ramtypetable1
[8 + ramtype
]);
2096 ret
|= SETIREG(SISSR
, 0x19, ramtypetable1
[16 + ramtype
]);
2098 ret
|= SETIREGOR(SISSR
, 0x21, 0x20);
2100 ret
|= SETIREG(SISSR
, 0x22, 0xfb);
2101 ret
|= SETIREG(SISSR
, 0x21, 0xa5);
2121 sisusb_get_ramconfig(struct sisusb_usb_data
*sisusb
)
2123 u8 tmp8
, tmp82
, ramtype
;
2125 char *ramtypetext1
= NULL
;
2126 const char *ramtypetext2
[] = { "SDR SDRAM", "SDR SGRAM",
2127 "DDR SDRAM", "DDR SGRAM" };
2128 static const int busSDR
[4] = {64, 64, 128, 128};
2129 static const int busDDR
[4] = {32, 32, 64, 64};
2130 static const int busDDRA
[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2132 sisusb_getidxreg(sisusb
, SISSR
, 0x14, &tmp8
);
2133 sisusb_getidxreg(sisusb
, SISSR
, 0x15, &tmp82
);
2134 sisusb_getidxreg(sisusb
, SISSR
, 0x3a, &ramtype
);
2135 sisusb
->vramsize
= (1 << ((tmp8
& 0xf0) >> 4)) * 1024 * 1024;
2137 switch ((tmp8
>> 2) & 0x03) {
2138 case 0: ramtypetext1
= "1 ch/1 r";
2142 bw
= busSDR
[(tmp8
& 0x03)];
2145 case 1: ramtypetext1
= "1 ch/2 r";
2146 sisusb
->vramsize
<<= 1;
2147 bw
= busSDR
[(tmp8
& 0x03)];
2149 case 2: ramtypetext1
= "asymmeric";
2150 sisusb
->vramsize
+= sisusb
->vramsize
/2;
2151 bw
= busDDRA
[(tmp8
& 0x03)];
2153 case 3: ramtypetext1
= "2 channel";
2154 sisusb
->vramsize
<<= 1;
2155 bw
= busDDR
[(tmp8
& 0x03)];
2159 dev_info(&sisusb
->sisusb_dev
->dev
, "%dMB %s %s, bus width %d\n", (sisusb
->vramsize
>> 20), ramtypetext1
,
2160 ramtypetext2
[ramtype
], bw
);
2164 sisusb_do_init_gfxdevice(struct sisusb_usb_data
*sisusb
)
2166 struct sisusb_packet packet
;
2171 packet
.header
= 0x001f;
2172 packet
.address
= 0x00000324;
2173 packet
.data
= 0x00000004;
2174 ret
= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2176 packet
.header
= 0x001f;
2177 packet
.address
= 0x00000364;
2178 packet
.data
= 0x00000004;
2179 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2181 packet
.header
= 0x001f;
2182 packet
.address
= 0x00000384;
2183 packet
.data
= 0x00000004;
2184 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2186 packet
.header
= 0x001f;
2187 packet
.address
= 0x00000100;
2188 packet
.data
= 0x00000700;
2189 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2191 packet
.header
= 0x000f;
2192 packet
.address
= 0x00000004;
2193 ret
|= sisusb_send_bridge_packet(sisusb
, 6, &packet
, 0);
2194 packet
.data
|= 0x17;
2195 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2197 /* Init BAR 0 (VRAM) */
2198 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2199 ret
|= sisusb_write_pci_config(sisusb
, 0x10, 0xfffffff0);
2200 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2202 tmp32
|= SISUSB_PCI_MEMBASE
;
2203 ret
|= sisusb_write_pci_config(sisusb
, 0x10, tmp32
);
2205 /* Init BAR 1 (MMIO) */
2206 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2207 ret
|= sisusb_write_pci_config(sisusb
, 0x14, 0xfffffff0);
2208 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2210 tmp32
|= SISUSB_PCI_MMIOBASE
;
2211 ret
|= sisusb_write_pci_config(sisusb
, 0x14, tmp32
);
2213 /* Init BAR 2 (i/o ports) */
2214 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2215 ret
|= sisusb_write_pci_config(sisusb
, 0x18, 0xfffffff0);
2216 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2218 tmp32
|= SISUSB_PCI_IOPORTBASE
;
2219 ret
|= sisusb_write_pci_config(sisusb
, 0x18, tmp32
);
2221 /* Enable memory and i/o access */
2222 ret
|= sisusb_read_pci_config(sisusb
, 0x04, &tmp32
);
2224 ret
|= sisusb_write_pci_config(sisusb
, 0x04, tmp32
);
2227 /* Some further magic */
2228 packet
.header
= 0x001f;
2229 packet
.address
= 0x00000050;
2230 packet
.data
= 0x000000ff;
2231 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2237 /* Initialize the graphics device (return 0 on success)
2238 * This initializes the net2280 as well as the PCI registers
2239 * of the graphics board.
2243 sisusb_init_gfxdevice(struct sisusb_usb_data
*sisusb
, int initscreen
)
2245 int ret
= 0, test
= 0;
2248 if (sisusb
->devinit
== 1) {
2249 /* Read PCI BARs and see if they have been set up */
2250 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2251 if (ret
) return ret
;
2252 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MEMBASE
) test
++;
2254 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2255 if (ret
) return ret
;
2256 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MMIOBASE
) test
++;
2258 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2259 if (ret
) return ret
;
2260 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_IOPORTBASE
) test
++;
2263 /* No? So reset the device */
2264 if ((sisusb
->devinit
== 0) || (test
!= 3)) {
2266 ret
|= sisusb_do_init_gfxdevice(sisusb
);
2269 sisusb
->devinit
= 1;
2273 if (sisusb
->devinit
) {
2274 /* Initialize the graphics core */
2275 if (sisusb_init_gfxcore(sisusb
) == 0) {
2276 sisusb
->gfxinit
= 1;
2277 sisusb_get_ramconfig(sisusb
);
2278 ret
|= sisusb_set_default_mode(sisusb
, 1);
2279 ret
|= sisusb_setup_screen(sisusb
, 1, initscreen
);
2287 #ifdef INCL_SISUSB_CON
2289 /* Set up default text mode:
2290 - Set text mode (0x03)
2291 - Upload default font
2292 - Upload user font (if available)
2296 sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
)
2298 int ret
= 0, slot
= sisusb
->font_slot
, i
;
2299 const struct font_desc
*myfont
;
2303 static const char bootstring
[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2304 static const char bootlogo
[] = "(o_ //\\ V_/_";
2306 /* sisusb->lock is down */
2308 if (!sisusb
->SiS_Pr
)
2311 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2312 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2315 SiSUSBSetMode(sisusb
->SiS_Pr
, 0x03);
2317 if (!(myfont
= find_font("VGA8x16")))
2320 if (!(tempbuf
= vmalloc(8192)))
2323 for (i
= 0; i
< 256; i
++)
2324 memcpy(tempbuf
+ (i
* 32), myfont
->data
+ (i
* 16), 16);
2326 /* Upload default font */
2327 ret
= sisusbcon_do_font_op(sisusb
, 1, 0, tempbuf
, 8192, 0, 1, NULL
, 16, 0);
2331 /* Upload user font (and reset current slot) */
2332 if (sisusb
->font_backup
) {
2333 ret
|= sisusbcon_do_font_op(sisusb
, 1, 2, sisusb
->font_backup
,
2334 8192, sisusb
->font_backup_512
, 1, NULL
,
2335 sisusb
->font_backup_height
, 0);
2337 sisusbcon_do_font_op(sisusb
, 1, 0, NULL
, 0, 0, 1,
2341 if (init
&& !sisusb
->scrbuf
) {
2343 if ((tempbuf
= vmalloc(8192))) {
2346 tempbufb
= (u16
*)tempbuf
;
2348 *(tempbufb
++) = 0x0720;
2351 tempbufb
= (u16
*)tempbuf
;
2352 while (bootlogo
[i
]) {
2353 *(tempbufb
++) = 0x0700 | bootlogo
[i
++];
2359 tempbufb
= (u16
*)tempbuf
+ 6;
2360 while (bootstring
[i
])
2361 *(tempbufb
++) = 0x0700 | bootstring
[i
++];
2363 ret
|= sisusb_copy_memory(sisusb
, tempbuf
,
2364 sisusb
->vrambase
, 8192, &written
);
2370 } else if (sisusb
->scrbuf
) {
2372 ret
|= sisusb_copy_memory(sisusb
, (char *)sisusb
->scrbuf
,
2373 sisusb
->vrambase
, sisusb
->scrbuf_size
, &written
);
2377 if (sisusb
->sisusb_cursor_size_from
>= 0 &&
2378 sisusb
->sisusb_cursor_size_to
>= 0) {
2379 sisusb_setidxreg(sisusb
, SISCR
, 0x0a,
2380 sisusb
->sisusb_cursor_size_from
);
2381 sisusb_setidxregandor(sisusb
, SISCR
, 0x0b, 0xe0,
2382 sisusb
->sisusb_cursor_size_to
);
2384 sisusb_setidxreg(sisusb
, SISCR
, 0x0a, 0x2d);
2385 sisusb_setidxreg(sisusb
, SISCR
, 0x0b, 0x0e);
2386 sisusb
->sisusb_cursor_size_to
= -1;
2389 slot
= sisusb
->sisusb_cursor_loc
;
2390 if(slot
< 0) slot
= 0;
2392 sisusb
->sisusb_cursor_loc
= -1;
2393 sisusb
->bad_cursor_pos
= 1;
2395 sisusb_set_cursor(sisusb
, slot
);
2397 sisusb_setidxreg(sisusb
, SISCR
, 0x0c, (sisusb
->cur_start_addr
>> 8));
2398 sisusb_setidxreg(sisusb
, SISCR
, 0x0d, (sisusb
->cur_start_addr
& 0xff));
2400 sisusb
->textmodedestroyed
= 0;
2402 /* sisusb->lock is down */
2412 sisusb_open(struct inode
*inode
, struct file
*file
)
2414 struct sisusb_usb_data
*sisusb
;
2415 struct usb_interface
*interface
;
2416 int subminor
= iminor(inode
);
2418 if (!(interface
= usb_find_interface(&sisusb_driver
, subminor
))) {
2422 if (!(sisusb
= usb_get_intfdata(interface
))) {
2426 mutex_lock(&sisusb
->lock
);
2428 if (!sisusb
->present
|| !sisusb
->ready
) {
2429 mutex_unlock(&sisusb
->lock
);
2433 if (sisusb
->isopen
) {
2434 mutex_unlock(&sisusb
->lock
);
2438 if (!sisusb
->devinit
) {
2439 if (sisusb
->sisusb_dev
->speed
== USB_SPEED_HIGH
||
2440 sisusb
->sisusb_dev
->speed
== USB_SPEED_SUPER
) {
2441 if (sisusb_init_gfxdevice(sisusb
, 0)) {
2442 mutex_unlock(&sisusb
->lock
);
2443 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to initialize device\n");
2447 mutex_unlock(&sisusb
->lock
);
2448 dev_err(&sisusb
->sisusb_dev
->dev
, "Device not attached to USB 2.0 hub\n");
2453 /* Increment usage count for our sisusb */
2454 kref_get(&sisusb
->kref
);
2458 file
->private_data
= sisusb
;
2460 mutex_unlock(&sisusb
->lock
);
2466 sisusb_delete(struct kref
*kref
)
2468 struct sisusb_usb_data
*sisusb
= to_sisusb_dev(kref
);
2473 if (sisusb
->sisusb_dev
)
2474 usb_put_dev(sisusb
->sisusb_dev
);
2476 sisusb
->sisusb_dev
= NULL
;
2477 sisusb_free_buffers(sisusb
);
2478 sisusb_free_urbs(sisusb
);
2479 #ifdef INCL_SISUSB_CON
2480 kfree(sisusb
->SiS_Pr
);
2486 sisusb_release(struct inode
*inode
, struct file
*file
)
2488 struct sisusb_usb_data
*sisusb
;
2490 if (!(sisusb
= file
->private_data
))
2493 mutex_lock(&sisusb
->lock
);
2495 if (sisusb
->present
) {
2496 /* Wait for all URBs to finish if device still present */
2497 if (!sisusb_wait_all_out_complete(sisusb
))
2498 sisusb_kill_all_busy(sisusb
);
2502 file
->private_data
= NULL
;
2504 mutex_unlock(&sisusb
->lock
);
2506 /* decrement the usage count on our device */
2507 kref_put(&sisusb
->kref
, sisusb_delete
);
2513 sisusb_read(struct file
*file
, char __user
*buffer
, size_t count
, loff_t
*ppos
)
2515 struct sisusb_usb_data
*sisusb
;
2516 ssize_t bytes_read
= 0;
2522 if (!(sisusb
= file
->private_data
))
2525 mutex_lock(&sisusb
->lock
);
2528 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2529 mutex_unlock(&sisusb
->lock
);
2533 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2534 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2537 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2538 SISUSB_PCI_IOPORTBASE
;
2541 * Byte, word and long(32) can be read. As this
2542 * emulates inX instructions, the data returned is
2543 * in machine-endianness.
2548 if (sisusb_read_memio_byte(sisusb
,
2552 else if (put_user(buf8
, (u8 __user
*)buffer
))
2560 if (sisusb_read_memio_word(sisusb
,
2564 else if (put_user(buf16
, (u16 __user
*)buffer
))
2572 if (sisusb_read_memio_long(sisusb
,
2576 else if (put_user(buf32
, (u32 __user
*)buffer
))
2588 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2589 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2592 SISUSB_PCI_PSEUDO_MEMBASE
+
2596 * Remember: Data delivered is never endian-corrected
2598 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2599 NULL
, count
, buffer
, &bytes_read
);
2604 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2605 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2608 SISUSB_PCI_PSEUDO_MMIOBASE
+
2609 SISUSB_PCI_MMIOBASE
;
2612 * Remember: Data delivered is never endian-corrected
2614 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2615 NULL
, count
, buffer
, &bytes_read
);
2620 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2621 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ 0x5c) {
2624 mutex_unlock(&sisusb
->lock
);
2628 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2630 /* Read PCI config register
2631 * Return value delivered in machine endianness.
2633 if (sisusb_read_pci_config(sisusb
, address
, &buf32
))
2635 else if (put_user(buf32
, (u32 __user
*)buffer
))
2646 (*ppos
) += bytes_read
;
2648 mutex_unlock(&sisusb
->lock
);
2650 return errno
? errno
: bytes_read
;
2654 sisusb_write(struct file
*file
, const char __user
*buffer
, size_t count
,
2657 struct sisusb_usb_data
*sisusb
;
2659 ssize_t bytes_written
= 0;
2664 if (!(sisusb
= file
->private_data
))
2667 mutex_lock(&sisusb
->lock
);
2670 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2671 mutex_unlock(&sisusb
->lock
);
2675 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2676 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2679 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2680 SISUSB_PCI_IOPORTBASE
;
2683 * Byte, word and long(32) can be written. As this
2684 * emulates outX instructions, the data is expected
2685 * in machine-endianness.
2690 if (get_user(buf8
, (u8 __user
*)buffer
))
2692 else if (sisusb_write_memio_byte(sisusb
,
2702 if (get_user(buf16
, (u16 __user
*)buffer
))
2704 else if (sisusb_write_memio_word(sisusb
,
2714 if (get_user(buf32
, (u32 __user
*)buffer
))
2716 else if (sisusb_write_memio_long(sisusb
,
2729 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2730 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2733 SISUSB_PCI_PSEUDO_MEMBASE
+
2737 * Buffer is copied 1:1, therefore, on big-endian
2738 * machines, the data must be swapped by userland
2739 * in advance (if applicable; no swapping in 8bpp
2740 * mode or if YUV data is being transferred).
2742 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2743 count
, buffer
, 0, &bytes_written
);
2746 errno
= bytes_written
;
2748 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2749 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2752 SISUSB_PCI_PSEUDO_MMIOBASE
+
2753 SISUSB_PCI_MMIOBASE
;
2756 * Buffer is copied 1:1, therefore, on big-endian
2757 * machines, the data must be swapped by userland
2760 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2761 count
, buffer
, 0, &bytes_written
);
2764 errno
= bytes_written
;
2766 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2767 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ SISUSB_PCI_PCONFSIZE
) {
2770 mutex_unlock(&sisusb
->lock
);
2774 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2776 /* Write PCI config register.
2777 * Given value expected in machine endianness.
2779 if (get_user(buf32
, (u32 __user
*)buffer
))
2781 else if (sisusb_write_pci_config(sisusb
, address
, buf32
))
2794 (*ppos
) += bytes_written
;
2796 mutex_unlock(&sisusb
->lock
);
2798 return errno
? errno
: bytes_written
;
2802 sisusb_lseek(struct file
*file
, loff_t offset
, int orig
)
2804 struct sisusb_usb_data
*sisusb
;
2807 if (!(sisusb
= file
->private_data
))
2810 mutex_lock(&sisusb
->lock
);
2813 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2814 mutex_unlock(&sisusb
->lock
);
2820 file
->f_pos
= offset
;
2822 /* never negative, no force_successful_syscall needed */
2825 file
->f_pos
+= offset
;
2827 /* never negative, no force_successful_syscall needed */
2830 /* seeking relative to "end of file" is not supported */
2834 mutex_unlock(&sisusb
->lock
);
2839 sisusb_handle_command(struct sisusb_usb_data
*sisusb
, struct sisusb_command
*y
,
2842 int retval
, port
, length
;
2845 /* All our commands require the device
2846 * to be initialized.
2848 if (!sisusb
->devinit
)
2852 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2853 SISUSB_PCI_IOPORTBASE
;
2855 switch (y
->operation
) {
2857 retval
= sisusb_getidxreg(sisusb
, port
,
2858 y
->data0
, &y
->data1
);
2860 if (copy_to_user((void __user
*)arg
, y
,
2867 retval
= sisusb_setidxreg(sisusb
, port
,
2868 y
->data0
, y
->data1
);
2872 retval
= sisusb_setidxregor(sisusb
, port
,
2873 y
->data0
, y
->data1
);
2877 retval
= sisusb_setidxregand(sisusb
, port
,
2878 y
->data0
, y
->data1
);
2881 case SUCMD_SETANDOR
:
2882 retval
= sisusb_setidxregandor(sisusb
, port
,
2883 y
->data0
, y
->data1
, y
->data2
);
2887 retval
= sisusb_setidxregmask(sisusb
, port
,
2888 y
->data0
, y
->data1
, y
->data2
);
2892 /* Gfx core must be initialized */
2893 if (!sisusb
->gfxinit
)
2896 length
= (y
->data0
<< 16) | (y
->data1
<< 8) | y
->data2
;
2897 address
= y
->data3
-
2898 SISUSB_PCI_PSEUDO_MEMBASE
+
2900 retval
= sisusb_clear_vram(sisusb
, address
, length
);
2903 case SUCMD_HANDLETEXTMODE
:
2905 #ifdef INCL_SISUSB_CON
2906 /* Gfx core must be initialized, SiS_Pr must exist */
2907 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2912 retval
= sisusb_reset_text_mode(sisusb
, 0);
2915 sisusb
->textmodedestroyed
= 1;
2921 #ifdef INCL_SISUSB_CON
2923 /* Gfx core must be initialized, SiS_Pr must exist */
2924 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2929 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2930 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2932 if (SiSUSBSetMode(sisusb
->SiS_Pr
, y
->data3
))
2937 case SUCMD_SETVESAMODE
:
2938 /* Gfx core must be initialized, SiS_Pr must exist */
2939 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2944 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2945 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2947 if (SiSUSBSetVESAMode(sisusb
->SiS_Pr
, y
->data3
))
2964 sisusb_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
2966 struct sisusb_usb_data
*sisusb
;
2967 struct sisusb_info x
;
2968 struct sisusb_command y
;
2970 u32 __user
*argp
= (u32 __user
*)arg
;
2972 if (!(sisusb
= file
->private_data
))
2975 mutex_lock(&sisusb
->lock
);
2978 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2985 case SISUSB_GET_CONFIG_SIZE
:
2987 if (put_user(sizeof(x
), argp
))
2992 case SISUSB_GET_CONFIG
:
2994 x
.sisusb_id
= SISUSB_ID
;
2995 x
.sisusb_version
= SISUSB_VERSION
;
2996 x
.sisusb_revision
= SISUSB_REVISION
;
2997 x
.sisusb_patchlevel
= SISUSB_PATCHLEVEL
;
2998 x
.sisusb_gfxinit
= sisusb
->gfxinit
;
2999 x
.sisusb_vrambase
= SISUSB_PCI_PSEUDO_MEMBASE
;
3000 x
.sisusb_mmiobase
= SISUSB_PCI_PSEUDO_MMIOBASE
;
3001 x
.sisusb_iobase
= SISUSB_PCI_PSEUDO_IOPORTBASE
;
3002 x
.sisusb_pcibase
= SISUSB_PCI_PSEUDO_PCIBASE
;
3003 x
.sisusb_vramsize
= sisusb
->vramsize
;
3004 x
.sisusb_minor
= sisusb
->minor
;
3005 x
.sisusb_fbdevactive
= 0;
3006 #ifdef INCL_SISUSB_CON
3007 x
.sisusb_conactive
= sisusb
->haveconsole
? 1 : 0;
3009 x
.sisusb_conactive
= 0;
3011 memset(x
.sisusb_reserved
, 0, sizeof(x
.sisusb_reserved
));
3013 if (copy_to_user((void __user
*)arg
, &x
, sizeof(x
)))
3018 case SISUSB_COMMAND
:
3020 if (copy_from_user(&y
, (void __user
*)arg
, sizeof(y
)))
3023 retval
= sisusb_handle_command(sisusb
, &y
, arg
);
3033 mutex_unlock(&sisusb
->lock
);
3037 #ifdef SISUSB_NEW_CONFIG_COMPAT
3039 sisusb_compat_ioctl(struct file
*f
, unsigned int cmd
, unsigned long arg
)
3044 case SISUSB_GET_CONFIG_SIZE
:
3045 case SISUSB_GET_CONFIG
:
3046 case SISUSB_COMMAND
:
3047 retval
= sisusb_ioctl(f
, cmd
, arg
);
3051 return -ENOIOCTLCMD
;
3056 static const struct file_operations usb_sisusb_fops
= {
3057 .owner
= THIS_MODULE
,
3058 .open
= sisusb_open
,
3059 .release
= sisusb_release
,
3060 .read
= sisusb_read
,
3061 .write
= sisusb_write
,
3062 .llseek
= sisusb_lseek
,
3063 #ifdef SISUSB_NEW_CONFIG_COMPAT
3064 .compat_ioctl
= sisusb_compat_ioctl
,
3066 .unlocked_ioctl
= sisusb_ioctl
3069 static struct usb_class_driver usb_sisusb_class
= {
3070 .name
= "sisusbvga%d",
3071 .fops
= &usb_sisusb_fops
,
3072 .minor_base
= SISUSB_MINOR
3075 static int sisusb_probe(struct usb_interface
*intf
,
3076 const struct usb_device_id
*id
)
3078 struct usb_device
*dev
= interface_to_usbdev(intf
);
3079 struct sisusb_usb_data
*sisusb
;
3082 dev_info(&dev
->dev
, "USB2VGA dongle found at address %d\n",
3085 /* Allocate memory for our private */
3086 if (!(sisusb
= kzalloc(sizeof(*sisusb
), GFP_KERNEL
))) {
3087 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate memory for private data\n");
3090 kref_init(&sisusb
->kref
);
3092 mutex_init(&(sisusb
->lock
));
3094 /* Register device */
3095 if ((retval
= usb_register_dev(intf
, &usb_sisusb_class
))) {
3096 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to get a minor for device %d\n",
3102 sisusb
->sisusb_dev
= dev
;
3103 sisusb
->minor
= intf
->minor
;
3104 sisusb
->vrambase
= SISUSB_PCI_MEMBASE
;
3105 sisusb
->mmiobase
= SISUSB_PCI_MMIOBASE
;
3106 sisusb
->mmiosize
= SISUSB_PCI_MMIOSIZE
;
3107 sisusb
->ioportbase
= SISUSB_PCI_IOPORTBASE
;
3108 /* Everything else is zero */
3110 /* Allocate buffers */
3111 sisusb
->ibufsize
= SISUSB_IBUF_SIZE
;
3112 if (!(sisusb
->ibuf
= kmalloc(SISUSB_IBUF_SIZE
, GFP_KERNEL
))) {
3113 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate memory for input buffer");
3118 sisusb
->numobufs
= 0;
3119 sisusb
->obufsize
= SISUSB_OBUF_SIZE
;
3120 for (i
= 0; i
< NUMOBUFS
; i
++) {
3121 if (!(sisusb
->obuf
[i
] = kmalloc(SISUSB_OBUF_SIZE
, GFP_KERNEL
))) {
3123 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate memory for output buffer\n");
3134 if (!(sisusb
->sisurbin
= usb_alloc_urb(0, GFP_KERNEL
))) {
3135 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate URBs\n");
3139 sisusb
->completein
= 1;
3141 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
3142 if (!(sisusb
->sisurbout
[i
] = usb_alloc_urb(0, GFP_KERNEL
))) {
3143 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate URBs\n");
3147 sisusb
->urbout_context
[i
].sisusb
= (void *)sisusb
;
3148 sisusb
->urbout_context
[i
].urbindex
= i
;
3149 sisusb
->urbstatus
[i
] = 0;
3152 dev_info(&sisusb
->sisusb_dev
->dev
, "Allocated %d output buffers\n", sisusb
->numobufs
);
3154 #ifdef INCL_SISUSB_CON
3155 /* Allocate our SiS_Pr */
3156 if (!(sisusb
->SiS_Pr
= kmalloc(sizeof(struct SiS_Private
), GFP_KERNEL
))) {
3157 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate SiS_Pr\n");
3161 /* Do remaining init stuff */
3163 init_waitqueue_head(&sisusb
->wait_q
);
3165 usb_set_intfdata(intf
, sisusb
);
3167 usb_get_dev(sisusb
->sisusb_dev
);
3169 sisusb
->present
= 1;
3171 if (dev
->speed
== USB_SPEED_HIGH
|| dev
->speed
== USB_SPEED_SUPER
) {
3173 #ifdef INCL_SISUSB_CON
3174 if (sisusb_first_vc
> 0 &&
3175 sisusb_last_vc
> 0 &&
3176 sisusb_first_vc
<= sisusb_last_vc
&&
3177 sisusb_last_vc
<= MAX_NR_CONSOLES
)
3180 if (sisusb_init_gfxdevice(sisusb
, initscreen
))
3181 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to early initialize device\n");
3184 dev_info(&sisusb
->sisusb_dev
->dev
, "Not attached to USB 2.0 hub, deferring init\n");
3188 #ifdef SISUSBENDIANTEST
3189 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST ***\n");
3190 sisusb_testreadwrite(sisusb
);
3191 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST END ***\n");
3194 #ifdef INCL_SISUSB_CON
3195 sisusb_console_init(sisusb
, sisusb_first_vc
, sisusb_last_vc
);
3201 sisusb_free_urbs(sisusb
);
3203 sisusb_free_buffers(sisusb
);
3205 usb_deregister_dev(intf
, &usb_sisusb_class
);
3211 static void sisusb_disconnect(struct usb_interface
*intf
)
3213 struct sisusb_usb_data
*sisusb
;
3215 /* This should *not* happen */
3216 if (!(sisusb
= usb_get_intfdata(intf
)))
3219 #ifdef INCL_SISUSB_CON
3220 sisusb_console_exit(sisusb
);
3223 usb_deregister_dev(intf
, &usb_sisusb_class
);
3225 mutex_lock(&sisusb
->lock
);
3227 /* Wait for all URBs to complete and kill them in case (MUST do) */
3228 if (!sisusb_wait_all_out_complete(sisusb
))
3229 sisusb_kill_all_busy(sisusb
);
3231 usb_set_intfdata(intf
, NULL
);
3233 sisusb
->present
= 0;
3236 mutex_unlock(&sisusb
->lock
);
3238 /* decrement our usage count */
3239 kref_put(&sisusb
->kref
, sisusb_delete
);
3242 static const struct usb_device_id sisusb_table
[] = {
3243 { USB_DEVICE(0x0711, 0x0550) },
3244 { USB_DEVICE(0x0711, 0x0900) },
3245 { USB_DEVICE(0x0711, 0x0901) },
3246 { USB_DEVICE(0x0711, 0x0902) },
3247 { USB_DEVICE(0x0711, 0x0903) },
3248 { USB_DEVICE(0x0711, 0x0918) },
3249 { USB_DEVICE(0x0711, 0x0920) },
3250 { USB_DEVICE(0x182d, 0x021c) },
3251 { USB_DEVICE(0x182d, 0x0269) },
3255 MODULE_DEVICE_TABLE (usb
, sisusb_table
);
3257 static struct usb_driver sisusb_driver
= {
3259 .probe
= sisusb_probe
,
3260 .disconnect
= sisusb_disconnect
,
3261 .id_table
= sisusb_table
,
3264 static int __init
usb_sisusb_init(void)
3267 #ifdef INCL_SISUSB_CON
3268 sisusb_init_concode();
3271 return usb_register(&sisusb_driver
);
3274 static void __exit
usb_sisusb_exit(void)
3276 usb_deregister(&sisusb_driver
);
3279 module_init(usb_sisusb_init
);
3280 module_exit(usb_sisusb_exit
);
3282 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3283 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3284 MODULE_LICENSE("GPL");