2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
8 * If distributed as part of the Linux kernel, this code is licensed under the
11 * Otherwise, the following license terms apply:
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific psisusbr written permission.
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
39 #include <linux/mutex.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/errno.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/slab.h>
47 #include <linux/spinlock.h>
48 #include <linux/kref.h>
49 #include <linux/usb.h>
50 #include <linux/smp_lock.h>
51 #include <linux/vmalloc.h>
54 #include "sisusb_init.h"
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
60 #define SISUSB_DONTSYNC
62 /* Forward declarations / clean-up routines */
64 #ifdef INCL_SISUSB_CON
65 static int sisusb_first_vc
= 0;
66 static int sisusb_last_vc
= 0;
67 module_param_named(first
, sisusb_first_vc
, int, 0);
68 module_param_named(last
, sisusb_last_vc
, int, 0);
69 MODULE_PARM_DESC(first
, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
70 MODULE_PARM_DESC(last
, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
73 static struct usb_driver sisusb_driver
;
76 sisusb_free_buffers(struct sisusb_usb_data
*sisusb
)
80 for (i
= 0; i
< NUMOBUFS
; i
++) {
81 if (sisusb
->obuf
[i
]) {
82 kfree(sisusb
->obuf
[i
]);
83 sisusb
->obuf
[i
] = NULL
;
93 sisusb_free_urbs(struct sisusb_usb_data
*sisusb
)
97 for (i
= 0; i
< NUMOBUFS
; i
++) {
98 usb_free_urb(sisusb
->sisurbout
[i
]);
99 sisusb
->sisurbout
[i
] = NULL
;
101 usb_free_urb(sisusb
->sisurbin
);
102 sisusb
->sisurbin
= NULL
;
105 /* Level 0: USB transport layer */
109 /* out-urb management */
111 /* Return 1 if all free, 0 otherwise */
113 sisusb_all_free(struct sisusb_usb_data
*sisusb
)
117 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
119 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
127 /* Kill all busy URBs */
129 sisusb_kill_all_busy(struct sisusb_usb_data
*sisusb
)
133 if (sisusb_all_free(sisusb
))
136 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
138 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
139 usb_kill_urb(sisusb
->sisurbout
[i
]);
144 /* Return 1 if ok, 0 if error (not all complete within timeout) */
146 sisusb_wait_all_out_complete(struct sisusb_usb_data
*sisusb
)
148 int timeout
= 5 * HZ
, i
= 1;
150 wait_event_timeout(sisusb
->wait_q
,
151 (i
= sisusb_all_free(sisusb
)),
158 sisusb_outurb_available(struct sisusb_usb_data
*sisusb
)
162 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
164 if ((sisusb
->urbstatus
[i
] & (SU_URB_BUSY
|SU_URB_ALLOC
)) == 0)
173 sisusb_get_free_outbuf(struct sisusb_usb_data
*sisusb
)
175 int i
, timeout
= 5 * HZ
;
177 wait_event_timeout(sisusb
->wait_q
,
178 ((i
= sisusb_outurb_available(sisusb
)) >= 0),
185 sisusb_alloc_outbuf(struct sisusb_usb_data
*sisusb
)
189 i
= sisusb_outurb_available(sisusb
);
192 sisusb
->urbstatus
[i
] |= SU_URB_ALLOC
;
198 sisusb_free_outbuf(struct sisusb_usb_data
*sisusb
, int index
)
200 if ((index
>= 0) && (index
< sisusb
->numobufs
))
201 sisusb
->urbstatus
[index
] &= ~SU_URB_ALLOC
;
204 /* completion callback */
207 sisusb_bulk_completeout(struct urb
*urb
)
209 struct sisusb_urb_context
*context
= urb
->context
;
210 struct sisusb_usb_data
*sisusb
;
215 sisusb
= context
->sisusb
;
217 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
220 #ifndef SISUSB_DONTSYNC
221 if (context
->actual_length
)
222 *(context
->actual_length
) += urb
->actual_length
;
225 sisusb
->urbstatus
[context
->urbindex
] &= ~SU_URB_BUSY
;
226 wake_up(&sisusb
->wait_q
);
230 sisusb_bulkout_msg(struct sisusb_usb_data
*sisusb
, int index
, unsigned int pipe
, void *data
,
231 int len
, int *actual_length
, int timeout
, unsigned int tflags
)
233 struct urb
*urb
= sisusb
->sisurbout
[index
];
234 int retval
, byteswritten
= 0;
237 urb
->transfer_flags
= 0;
239 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
240 sisusb_bulk_completeout
, &sisusb
->urbout_context
[index
]);
242 urb
->transfer_flags
|= tflags
;
243 urb
->actual_length
= 0;
246 sisusb
->urbout_context
[index
].actual_length
= (timeout
) ?
247 NULL
: actual_length
;
249 /* Declare this urb/buffer in use */
250 sisusb
->urbstatus
[index
] |= SU_URB_BUSY
;
253 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
255 /* If OK, and if timeout > 0, wait for completion */
256 if ((retval
== 0) && timeout
) {
257 wait_event_timeout(sisusb
->wait_q
,
258 (!(sisusb
->urbstatus
[index
] & SU_URB_BUSY
)),
260 if (sisusb
->urbstatus
[index
] & SU_URB_BUSY
) {
261 /* URB timed out... kill it and report error */
265 /* Otherwise, report urb status */
266 retval
= urb
->status
;
267 byteswritten
= urb
->actual_length
;
272 *actual_length
= byteswritten
;
279 /* completion callback */
282 sisusb_bulk_completein(struct urb
*urb
)
284 struct sisusb_usb_data
*sisusb
= urb
->context
;
286 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
289 sisusb
->completein
= 1;
290 wake_up(&sisusb
->wait_q
);
294 sisusb_bulkin_msg(struct sisusb_usb_data
*sisusb
, unsigned int pipe
, void *data
,
295 int len
, int *actual_length
, int timeout
, unsigned int tflags
)
297 struct urb
*urb
= sisusb
->sisurbin
;
298 int retval
, readbytes
= 0;
300 urb
->transfer_flags
= 0;
302 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
303 sisusb_bulk_completein
, sisusb
);
305 urb
->transfer_flags
|= tflags
;
306 urb
->actual_length
= 0;
308 sisusb
->completein
= 0;
309 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
311 wait_event_timeout(sisusb
->wait_q
, sisusb
->completein
, timeout
);
312 if (!sisusb
->completein
) {
313 /* URB timed out... kill it and report error */
317 /* URB completed within timeout */
318 retval
= urb
->status
;
319 readbytes
= urb
->actual_length
;
324 *actual_length
= readbytes
;
332 /* Send a bulk message of variable size
334 * To copy the data from userspace, give pointer to "userbuffer",
335 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
336 * both of these are NULL, it is assumed, that the transfer
337 * buffer "sisusb->obuf[index]" is set up with the data to send.
338 * Index is ignored if either kernbuffer or userbuffer is set.
339 * If async is nonzero, URBs will be sent without waiting for
340 * completion of the previous URB.
342 * (return 0 on success)
345 static int sisusb_send_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
346 char *kernbuffer
, const char __user
*userbuffer
, int index
,
347 ssize_t
*bytes_written
, unsigned int tflags
, int async
)
349 int result
= 0, retry
, count
= len
;
350 int passsize
, thispass
, transferred_len
= 0;
351 int fromuser
= (userbuffer
!= NULL
) ? 1 : 0;
352 int fromkern
= (kernbuffer
!= NULL
) ? 1 : 0;
356 (*bytes_written
) = 0;
359 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
362 /* If we copy data from kernel or userspace, force the
363 * allocation of a buffer/urb. If we have the data in
364 * the transfer buffer[index] already, reuse the buffer/URB
365 * if the length is > buffer size. (So, transmitting
366 * large data amounts directly from the transfer buffer
367 * treats the buffer as a ring buffer. However, we need
368 * to sync in this case.)
370 if (fromuser
|| fromkern
)
372 else if (len
> sisusb
->obufsize
)
375 pipe
= usb_sndbulkpipe(sisusb
->sisusb_dev
, ep
);
378 passsize
= thispass
= (sisusb
->obufsize
< count
) ?
379 sisusb
->obufsize
: count
;
382 index
= sisusb_get_free_outbuf(sisusb
);
387 buffer
= sisusb
->obuf
[index
];
391 if (copy_from_user(buffer
, userbuffer
, passsize
))
394 userbuffer
+= passsize
;
396 } else if (fromkern
) {
398 memcpy(buffer
, kernbuffer
, passsize
);
399 kernbuffer
+= passsize
;
406 if (!sisusb
->sisusb_dev
)
409 result
= sisusb_bulkout_msg(sisusb
,
418 if (result
== -ETIMEDOUT
) {
420 /* Will not happen if async */
427 if ((result
== 0) && !async
&& transferred_len
) {
429 thispass
-= transferred_len
;
430 buffer
+= transferred_len
;
439 (*bytes_written
) += passsize
;
442 /* Force new allocation in next iteration */
443 if (fromuser
|| fromkern
)
449 #ifdef SISUSB_DONTSYNC
450 (*bytes_written
) = len
;
451 /* Some URBs/buffers might be busy */
453 sisusb_wait_all_out_complete(sisusb
);
454 (*bytes_written
) = transferred_len
;
455 /* All URBs and all buffers are available */
459 return ((*bytes_written
) == len
) ? 0 : -EIO
;
462 /* Receive a bulk message of variable size
464 * To copy the data to userspace, give pointer to "userbuffer",
465 * to copy to kernel memory, give "kernbuffer". One of them
466 * MUST be set. (There is no technique for letting the caller
467 * read directly from the ibuf.)
471 static int sisusb_recv_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
472 void *kernbuffer
, char __user
*userbuffer
, ssize_t
*bytes_read
,
475 int result
= 0, retry
, count
= len
;
476 int bufsize
, thispass
, transferred_len
;
483 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
486 pipe
= usb_rcvbulkpipe(sisusb
->sisusb_dev
, ep
);
487 buffer
= sisusb
->ibuf
;
488 bufsize
= sisusb
->ibufsize
;
492 #ifdef SISUSB_DONTSYNC
493 if (!(sisusb_wait_all_out_complete(sisusb
)))
499 if (!sisusb
->sisusb_dev
)
502 thispass
= (bufsize
< count
) ? bufsize
: count
;
504 result
= sisusb_bulkin_msg(sisusb
,
513 thispass
= transferred_len
;
515 else if (result
== -ETIMEDOUT
) {
528 (*bytes_read
) += thispass
;
533 if (copy_to_user(userbuffer
, buffer
, thispass
))
536 userbuffer
+= thispass
;
540 memcpy(kernbuffer
, buffer
, thispass
);
541 kernbuffer
+= thispass
;
549 return ((*bytes_read
) == len
) ? 0 : -EIO
;
552 static int sisusb_send_packet(struct sisusb_usb_data
*sisusb
, int len
,
553 struct sisusb_packet
*packet
)
556 ssize_t bytes_transferred
= 0;
562 #ifdef SISUSB_DONTSYNC
563 if (!(sisusb_wait_all_out_complete(sisusb
)))
567 /* Eventually correct endianness */
568 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
570 /* 1. send the packet */
571 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_GFX_OUT
, len
,
572 (char *)packet
, NULL
, 0, &bytes_transferred
, 0, 0);
574 if ((ret
== 0) && (len
== 6)) {
576 /* 2. if packet len == 6, it means we read, so wait for 32bit
577 * return value and write it to packet->data
579 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_GFX_IN
, 4,
580 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
582 packet
->data
= le32_to_cpu(tmp
);
588 static int sisusb_send_bridge_packet(struct sisusb_usb_data
*sisusb
, int len
,
589 struct sisusb_packet
*packet
,
593 ssize_t bytes_transferred
= 0;
599 #ifdef SISUSB_DONTSYNC
600 if (!(sisusb_wait_all_out_complete(sisusb
)))
604 /* Eventually correct endianness */
605 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
607 /* 1. send the packet */
608 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_OUT
, len
,
609 (char *)packet
, NULL
, 0, &bytes_transferred
, tflags
, 0);
611 if ((ret
== 0) && (len
== 6)) {
613 /* 2. if packet len == 6, it means we read, so wait for 32bit
614 * return value and write it to packet->data
616 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_IN
, 4,
617 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
619 packet
->data
= le32_to_cpu(tmp
);
625 /* access video memory and mmio (return 0 on success) */
629 /* The following routines assume being used to transfer byte, word,
632 * - the write routines expect "data" in machine endianness format.
633 * The data will be converted to leXX in sisusb_xxx_packet.
634 * - the read routines can expect read data in machine-endianess.
637 static int sisusb_write_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
640 struct sisusb_packet packet
;
643 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
644 packet
.address
= addr
& ~3;
645 packet
.data
= data
<< ((addr
& 3) << 3);
646 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
650 static int sisusb_write_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
653 struct sisusb_packet packet
;
656 packet
.address
= addr
& ~3;
660 packet
.header
= (type
<< 6) | 0x0003;
661 packet
.data
= (u32
)data
;
662 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
665 packet
.header
= (type
<< 6) | 0x0006;
666 packet
.data
= (u32
)data
<< 8;
667 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
670 packet
.header
= (type
<< 6) | 0x000c;
671 packet
.data
= (u32
)data
<< 16;
672 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
675 packet
.header
= (type
<< 6) | 0x0008;
676 packet
.data
= (u32
)data
<< 24;
677 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
678 packet
.header
= (type
<< 6) | 0x0001;
679 packet
.address
= (addr
& ~3) + 4;
680 packet
.data
= (u32
)data
>> 8;
681 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
687 static int sisusb_write_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
690 struct sisusb_packet packet
;
693 packet
.address
= addr
& ~3;
697 packet
.header
= (type
<< 6) | 0x0007;
698 packet
.data
= data
& 0x00ffffff;
699 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
702 packet
.header
= (type
<< 6) | 0x000e;
703 packet
.data
= data
<< 8;
704 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
707 packet
.header
= (type
<< 6) | 0x000c;
708 packet
.data
= data
<< 16;
709 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
710 packet
.header
= (type
<< 6) | 0x0001;
711 packet
.address
= (addr
& ~3) + 4;
712 packet
.data
= (data
>> 16) & 0x00ff;
713 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
716 packet
.header
= (type
<< 6) | 0x0008;
717 packet
.data
= data
<< 24;
718 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
719 packet
.header
= (type
<< 6) | 0x0003;
720 packet
.address
= (addr
& ~3) + 4;
721 packet
.data
= (data
>> 8) & 0xffff;
722 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
728 static int sisusb_write_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
731 struct sisusb_packet packet
;
734 packet
.address
= addr
& ~3;
738 packet
.header
= (type
<< 6) | 0x000f;
740 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
743 packet
.header
= (type
<< 6) | 0x000e;
744 packet
.data
= data
<< 8;
745 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
746 packet
.header
= (type
<< 6) | 0x0001;
747 packet
.address
= (addr
& ~3) + 4;
748 packet
.data
= data
>> 24;
749 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
752 packet
.header
= (type
<< 6) | 0x000c;
753 packet
.data
= data
<< 16;
754 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
755 packet
.header
= (type
<< 6) | 0x0003;
756 packet
.address
= (addr
& ~3) + 4;
757 packet
.data
= data
>> 16;
758 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
761 packet
.header
= (type
<< 6) | 0x0008;
762 packet
.data
= data
<< 24;
763 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
764 packet
.header
= (type
<< 6) | 0x0007;
765 packet
.address
= (addr
& ~3) + 4;
766 packet
.data
= data
>> 8;
767 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
773 /* The xxx_bulk routines copy a buffer of variable size. They treat the
774 * buffer as chars, therefore lsb/msb has to be corrected if using the
775 * byte/word/long/etc routines for speed-up
777 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
778 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
779 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
780 * that the data already is in the transfer buffer "sisusb->obuf[index]".
783 static int sisusb_write_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
784 char *kernbuffer
, int length
,
785 const char __user
*userbuffer
, int index
,
786 ssize_t
*bytes_written
)
788 struct sisusb_packet packet
;
790 static int msgcount
= 0;
791 u8 swap8
, fromkern
= kernbuffer
? 1 : 0;
793 u32 swap32
, flag
= (length
>> 28) & 1;
796 /* if neither kernbuffer not userbuffer are given, assume
799 if (!fromkern
&& !userbuffer
)
800 kernbuffer
= sisusb
->obuf
[index
];
802 (*bytes_written
= 0);
804 length
&= 0x00ffffff;
812 if (get_user(swap8
, (u8 __user
*)userbuffer
))
815 swap8
= kernbuffer
[0];
817 ret
= sisusb_write_memio_byte(sisusb
,
828 if (get_user(swap16
, (u16 __user
*)userbuffer
))
831 swap16
= *((u16
*)kernbuffer
);
833 ret
= sisusb_write_memio_word(sisusb
,
839 (*bytes_written
) += 2;
845 if (copy_from_user(&buf
, userbuffer
, 3))
848 swap32
= (buf
[0] << 16) |
852 swap32
= (buf
[2] << 16) |
858 swap32
= (kernbuffer
[0] << 16) |
859 (kernbuffer
[1] << 8) |
862 swap32
= (kernbuffer
[2] << 16) |
863 (kernbuffer
[1] << 8) |
867 ret
= sisusb_write_memio_24bit(sisusb
,
873 (*bytes_written
) += 3;
879 if (get_user(swap32
, (u32 __user
*)userbuffer
))
882 swap32
= *((u32
*)kernbuffer
);
884 ret
= sisusb_write_memio_long(sisusb
,
889 (*bytes_written
) += 4;
894 if ((length
& ~3) > 0x10000) {
896 packet
.header
= 0x001f;
897 packet
.address
= 0x000001d4;
899 ret
= sisusb_send_bridge_packet(sisusb
, 10,
901 packet
.header
= 0x001f;
902 packet
.address
= 0x000001d0;
903 packet
.data
= (length
& ~3);
904 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
906 packet
.header
= 0x001f;
907 packet
.address
= 0x000001c0;
908 packet
.data
= flag
| 0x16;
909 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
912 ret
|= sisusb_send_bulk_msg(sisusb
,
913 SISUSB_EP_GFX_LBULK_OUT
,
916 bytes_written
, 0, 1);
917 userbuffer
+= (*bytes_written
);
918 } else if (fromkern
) {
919 ret
|= sisusb_send_bulk_msg(sisusb
,
920 SISUSB_EP_GFX_LBULK_OUT
,
923 bytes_written
, 0, 1);
924 kernbuffer
+= (*bytes_written
);
926 ret
|= sisusb_send_bulk_msg(sisusb
,
927 SISUSB_EP_GFX_LBULK_OUT
,
930 bytes_written
, 0, 1);
931 kernbuffer
+= ((*bytes_written
) &
932 (sisusb
->obufsize
-1));
937 packet
.header
= 0x001f;
938 packet
.address
= 0x00000194;
940 ret
= sisusb_send_bridge_packet(sisusb
, 10,
942 packet
.header
= 0x001f;
943 packet
.address
= 0x00000190;
944 packet
.data
= (length
& ~3);
945 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
947 if (sisusb
->flagb0
!= 0x16) {
948 packet
.header
= 0x001f;
949 packet
.address
= 0x00000180;
950 packet
.data
= flag
| 0x16;
951 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
953 sisusb
->flagb0
= 0x16;
956 ret
|= sisusb_send_bulk_msg(sisusb
,
957 SISUSB_EP_GFX_BULK_OUT
,
960 bytes_written
, 0, 1);
961 userbuffer
+= (*bytes_written
);
962 } else if (fromkern
) {
963 ret
|= sisusb_send_bulk_msg(sisusb
,
964 SISUSB_EP_GFX_BULK_OUT
,
967 bytes_written
, 0, 1);
968 kernbuffer
+= (*bytes_written
);
970 ret
|= sisusb_send_bulk_msg(sisusb
,
971 SISUSB_EP_GFX_BULK_OUT
,
974 bytes_written
, 0, 1);
975 kernbuffer
+= ((*bytes_written
) &
976 (sisusb
->obufsize
-1));
982 dev_err(&sisusb
->sisusb_dev
->dev
, "Wrote %zd of %d bytes, error %d\n",
983 *bytes_written
, length
, ret
);
984 else if (msgcount
== 500)
985 dev_err(&sisusb
->sisusb_dev
->dev
, "Too many errors, logging stopped\n");
987 addr
+= (*bytes_written
);
988 length
-= (*bytes_written
);
996 return ret
? -EIO
: 0;
999 /* Remember: Read data in packet is in machine-endianess! So for
1000 * byte, word, 24bit, long no endian correction is necessary.
1003 static int sisusb_read_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
1006 struct sisusb_packet packet
;
1009 CLEARPACKET(&packet
);
1010 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
1011 packet
.address
= addr
& ~3;
1012 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1013 *data
= (u8
)(packet
.data
>> ((addr
& 3) << 3));
1017 static int sisusb_read_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
1018 u32 addr
, u16
*data
)
1020 struct sisusb_packet packet
;
1023 CLEARPACKET(&packet
);
1025 packet
.address
= addr
& ~3;
1029 packet
.header
= (type
<< 6) | 0x0003;
1030 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1031 *data
= (u16
)(packet
.data
);
1034 packet
.header
= (type
<< 6) | 0x0006;
1035 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1036 *data
= (u16
)(packet
.data
>> 8);
1039 packet
.header
= (type
<< 6) | 0x000c;
1040 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1041 *data
= (u16
)(packet
.data
>> 16);
1044 packet
.header
= (type
<< 6) | 0x0008;
1045 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1046 *data
= (u16
)(packet
.data
>> 24);
1047 packet
.header
= (type
<< 6) | 0x0001;
1048 packet
.address
= (addr
& ~3) + 4;
1049 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1050 *data
|= (u16
)(packet
.data
<< 8);
1056 static int sisusb_read_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
1057 u32 addr
, u32
*data
)
1059 struct sisusb_packet packet
;
1062 packet
.address
= addr
& ~3;
1066 packet
.header
= (type
<< 6) | 0x0007;
1067 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1068 *data
= packet
.data
& 0x00ffffff;
1071 packet
.header
= (type
<< 6) | 0x000e;
1072 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1073 *data
= packet
.data
>> 8;
1076 packet
.header
= (type
<< 6) | 0x000c;
1077 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1078 *data
= packet
.data
>> 16;
1079 packet
.header
= (type
<< 6) | 0x0001;
1080 packet
.address
= (addr
& ~3) + 4;
1081 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1082 *data
|= ((packet
.data
& 0xff) << 16);
1085 packet
.header
= (type
<< 6) | 0x0008;
1086 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1087 *data
= packet
.data
>> 24;
1088 packet
.header
= (type
<< 6) | 0x0003;
1089 packet
.address
= (addr
& ~3) + 4;
1090 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1091 *data
|= ((packet
.data
& 0xffff) << 8);
1097 static int sisusb_read_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
1098 u32 addr
, u32
*data
)
1100 struct sisusb_packet packet
;
1103 packet
.address
= addr
& ~3;
1107 packet
.header
= (type
<< 6) | 0x000f;
1108 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1109 *data
= packet
.data
;
1112 packet
.header
= (type
<< 6) | 0x000e;
1113 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1114 *data
= packet
.data
>> 8;
1115 packet
.header
= (type
<< 6) | 0x0001;
1116 packet
.address
= (addr
& ~3) + 4;
1117 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1118 *data
|= (packet
.data
<< 24);
1121 packet
.header
= (type
<< 6) | 0x000c;
1122 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1123 *data
= packet
.data
>> 16;
1124 packet
.header
= (type
<< 6) | 0x0003;
1125 packet
.address
= (addr
& ~3) + 4;
1126 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1127 *data
|= (packet
.data
<< 16);
1130 packet
.header
= (type
<< 6) | 0x0008;
1131 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1132 *data
= packet
.data
>> 24;
1133 packet
.header
= (type
<< 6) | 0x0007;
1134 packet
.address
= (addr
& ~3) + 4;
1135 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1136 *data
|= (packet
.data
<< 8);
1142 static int sisusb_read_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
1143 char *kernbuffer
, int length
,
1144 char __user
*userbuffer
, ssize_t
*bytes_read
)
1153 length
&= 0x00ffffff;
1161 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
1166 if (put_user(buf
[0],
1167 (u8 __user
*)userbuffer
)) {
1171 kernbuffer
[0] = buf
[0];
1177 ret
|= sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1182 if (put_user(swap16
,
1183 (u16 __user
*)userbuffer
))
1186 *((u16
*)kernbuffer
) = swap16
;
1192 ret
|= sisusb_read_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
1197 buf
[0] = (swap32
>> 16) & 0xff;
1198 buf
[1] = (swap32
>> 8) & 0xff;
1199 buf
[2] = swap32
& 0xff;
1201 buf
[2] = (swap32
>> 16) & 0xff;
1202 buf
[1] = (swap32
>> 8) & 0xff;
1203 buf
[0] = swap32
& 0xff;
1206 if (copy_to_user(userbuffer
, &buf
[0], 3))
1209 kernbuffer
[0] = buf
[0];
1210 kernbuffer
[1] = buf
[1];
1211 kernbuffer
[2] = buf
[2];
1217 ret
|= sisusb_read_memio_long(sisusb
, SISUSB_TYPE_MEM
,
1222 if (put_user(swap32
,
1223 (u32 __user
*)userbuffer
))
1228 *((u32
*)kernbuffer
) = swap32
;
1243 /* High level: Gfx (indexed) register access */
1245 #ifdef INCL_SISUSB_CON
1247 sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
)
1249 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1253 sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
)
1255 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1260 sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 data
)
1263 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1264 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1269 sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8
*data
)
1272 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1273 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1278 sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1284 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1285 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1288 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1293 sisusb_setidxregmask(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1298 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1299 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1301 tmp
|= (data
& mask
);
1302 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1307 sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 myor
)
1309 return(sisusb_setidxregandor(sisusb
, port
, index
, 0xff, myor
));
1313 sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
)
1315 return(sisusb_setidxregandor(sisusb
, port
, idx
, myand
, 0x00));
1318 /* Write/read video ram */
1320 #ifdef INCL_SISUSB_CON
1322 sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
)
1324 return(sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1328 sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
)
1330 return(sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1334 sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
1335 u32 dest
, int length
, size_t *bytes_written
)
1337 return(sisusb_write_mem_bulk(sisusb
, dest
, src
, length
, NULL
, 0, bytes_written
));
1340 #ifdef SISUSBENDIANTEST
1342 sisusb_read_memory(struct sisusb_usb_data
*sisusb
, char *dest
,
1343 u32 src
, int length
, size_t *bytes_written
)
1345 return(sisusb_read_mem_bulk(sisusb
, src
, dest
, length
, NULL
, bytes_written
));
1350 #ifdef SISUSBENDIANTEST
1352 sisusb_testreadwrite(struct sisusb_usb_data
*sisusb
)
1354 static char srcbuffer
[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1355 char destbuffer
[10];
1359 sisusb_copy_memory(sisusb
, srcbuffer
, sisusb
->vrambase
, 7, &dummy
);
1361 for(i
= 1; i
<= 7; i
++) {
1362 dev_dbg(&sisusb
->sisusb_dev
->dev
, "sisusb: rwtest %d bytes\n", i
);
1363 sisusb_read_memory(sisusb
, destbuffer
, sisusb
->vrambase
, i
, &dummy
);
1364 for(j
= 0; j
< i
; j
++) {
1365 dev_dbg(&sisusb
->sisusb_dev
->dev
, "rwtest read[%d] = %x\n", j
, destbuffer
[j
]);
1371 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1374 sisusb_write_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32 data
)
1376 struct sisusb_packet packet
;
1379 packet
.header
= 0x008f;
1380 packet
.address
= regnum
| 0x10000;
1382 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
1387 sisusb_read_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32
*data
)
1389 struct sisusb_packet packet
;
1392 packet
.header
= 0x008f;
1393 packet
.address
= (u32
)regnum
| 0x10000;
1394 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1395 *data
= packet
.data
;
1399 /* Clear video RAM */
1402 sisusb_clear_vram(struct sisusb_usb_data
*sisusb
, u32 address
, int length
)
1407 if (address
< sisusb
->vrambase
)
1410 if (address
>= sisusb
->vrambase
+ sisusb
->vramsize
)
1413 if (address
+ length
> sisusb
->vrambase
+ sisusb
->vramsize
)
1414 length
= sisusb
->vrambase
+ sisusb
->vramsize
- address
;
1419 /* allocate free buffer/urb and clear the buffer */
1420 if ((i
= sisusb_alloc_outbuf(sisusb
)) < 0)
1423 memset(sisusb
->obuf
[i
], 0, sisusb
->obufsize
);
1425 /* We can write a length > buffer size here. The buffer
1426 * data will simply be re-used (like a ring-buffer).
1428 ret
= sisusb_write_mem_bulk(sisusb
, address
, NULL
, length
, NULL
, i
, &j
);
1430 /* Free the buffer/urb */
1431 sisusb_free_outbuf(sisusb
, i
);
1436 /* Initialize the graphics core (return 0 on success)
1437 * This resets the graphics hardware and puts it into
1438 * a defined mode (640x480@60Hz)
1441 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1442 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1443 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1444 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1445 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1446 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1447 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1448 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1449 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1450 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1451 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1454 sisusb_triggersr16(struct sisusb_usb_data
*sisusb
, u8 ramtype
)
1459 ret
= GETIREG(SISSR
, 0x16, &tmp8
);
1462 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1464 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1467 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1469 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1471 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1473 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1475 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1477 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1479 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1485 sisusb_getbuswidth(struct sisusb_usb_data
*sisusb
, int *bw
, int *chab
)
1488 u8 ramtype
, done
= 0;
1490 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1492 ret
= GETIREG(SISSR
, 0x3a, &ramtype
);
1495 ret
|= SETIREG(SISSR
, 0x13, 0x00);
1498 ret
|= SETIREG(SISSR
, 0x14, 0x12);
1499 ret
|= SETIREGAND(SISSR
, 0x15, 0xef);
1501 ret
|= SETIREG(SISSR
, 0x14, 0x02);
1504 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1505 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1506 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1507 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1508 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1509 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1510 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1511 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1512 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1513 ret
|= READL(ramptr
+ 0, &t0
);
1514 ret
|= READL(ramptr
+ 4, &t1
);
1515 ret
|= READL(ramptr
+ 8, &t2
);
1516 ret
|= READL(ramptr
+ 12, &t3
);
1520 *chab
= 0; *bw
= 64;
1522 if ((t3
!= 0xcdef0123) || (t2
!= 0x89abcdef)) {
1523 if ((t1
== 0x456789ab) && (t0
== 0x01234567)) {
1524 *chab
= 0; *bw
= 64;
1525 ret
|= SETIREGAND(SISSR
, 0x14, 0xfd);
1528 if ((t1
!= 0x456789ab) || (t0
!= 0x01234567)) {
1529 *chab
= 1; *bw
= 64;
1530 ret
|= SETIREGANDOR(SISSR
, 0x14, 0xfc,0x01);
1532 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1533 ret
|= WRITEL(ramptr
+ 0, 0x89abcdef);
1534 ret
|= WRITEL(ramptr
+ 4, 0xcdef0123);
1535 ret
|= WRITEL(ramptr
+ 8, 0x55555555);
1536 ret
|= WRITEL(ramptr
+ 12, 0x55555555);
1537 ret
|= WRITEL(ramptr
+ 16, 0xaaaaaaaa);
1538 ret
|= WRITEL(ramptr
+ 20, 0xaaaaaaaa);
1539 ret
|= READL(ramptr
+ 4, &t1
);
1541 if (t1
!= 0xcdef0123) {
1543 ret
|= SETIREGOR(SISSR
, 0x15, 0x10);
1549 *chab
= 0; *bw
= 64; /* default: cha, bw = 64 */
1553 if (t1
== 0x456789ab) {
1554 if (t0
== 0x01234567) {
1555 *chab
= 0; *bw
= 64;
1559 if (t0
== 0x01234567) {
1560 *chab
= 0; *bw
= 32;
1561 ret
|= SETIREG(SISSR
, 0x14, 0x00);
1567 ret
|= SETIREG(SISSR
, 0x14, 0x03);
1568 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1570 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1571 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1572 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1573 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1574 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1575 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1576 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1577 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1578 ret
|= READL(ramptr
+ 0, &t0
);
1579 ret
|= READL(ramptr
+ 4, &t1
);
1581 if (t1
== 0x456789ab) {
1582 if (t0
== 0x01234567) {
1583 *chab
= 1; *bw
= 64;
1587 if (t0
== 0x01234567) {
1588 *chab
= 1; *bw
= 32;
1589 ret
|= SETIREG(SISSR
, 0x14, 0x01);
1598 sisusb_verify_mclk(struct sisusb_usb_data
*sisusb
)
1601 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1602 u8 tmp1
, tmp2
, i
, j
;
1604 ret
|= WRITEB(ramptr
, 0xaa);
1605 ret
|= WRITEB(ramptr
+ 16, 0x55);
1606 ret
|= READB(ramptr
, &tmp1
);
1607 ret
|= READB(ramptr
+ 16, &tmp2
);
1608 if ((tmp1
!= 0xaa) || (tmp2
!= 0x55)) {
1609 for (i
= 0, j
= 16; i
< 2; i
++, j
+= 16) {
1610 ret
|= GETIREG(SISSR
, 0x21, &tmp1
);
1611 ret
|= SETIREGAND(SISSR
, 0x21, (tmp1
& 0xfb));
1612 ret
|= SETIREGOR(SISSR
, 0x3c, 0x01); /* not on 330 */
1613 ret
|= SETIREGAND(SISSR
, 0x3c, 0xfe); /* not on 330 */
1614 ret
|= SETIREG(SISSR
, 0x21, tmp1
);
1615 ret
|= WRITEB(ramptr
+ 16 + j
, j
);
1616 ret
|= READB(ramptr
+ 16 + j
, &tmp1
);
1618 ret
|= WRITEB(ramptr
+ j
, j
);
1627 sisusb_set_rank(struct sisusb_usb_data
*sisusb
, int *iret
, int index
,
1628 u8 rankno
, u8 chab
, const u8 dramtype
[][5],
1631 int ret
= 0, ranksize
;
1636 if ((rankno
== 2) && (dramtype
[index
][0] == 2))
1639 ranksize
= dramtype
[index
][3] / 2 * bw
/ 32;
1641 if ((ranksize
* rankno
) > 128)
1645 while ((ranksize
>>= 1) > 0) tmp
+= 0x10;
1646 tmp
|= ((rankno
- 1) << 2);
1647 tmp
|= ((bw
/ 64) & 0x02);
1648 tmp
|= (chab
& 0x01);
1650 ret
= SETIREG(SISSR
, 0x14, tmp
);
1651 ret
|= sisusb_triggersr16(sisusb
, 0); /* sic! */
1659 sisusb_check_rbc(struct sisusb_usb_data
*sisusb
, int *iret
, u32 inc
, int testn
)
1666 for (i
= 0, j
= 0; i
< testn
; i
++) {
1667 ret
|= WRITEL(sisusb
->vrambase
+ j
, j
);
1671 for (i
= 0, j
= 0; i
< testn
; i
++) {
1672 ret
|= READL(sisusb
->vrambase
+ j
, &tmp
);
1673 if (tmp
!= j
) return ret
;
1682 sisusb_check_ranks(struct sisusb_usb_data
*sisusb
, int *iret
, int rankno
,
1683 int idx
, int bw
, const u8 rtype
[][5])
1685 int ret
= 0, i
, i2ret
;
1690 for (i
= rankno
; i
>= 1; i
--) {
1691 inc
= 1 << (rtype
[idx
][2] +
1695 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1700 inc
= 1 << (rtype
[idx
][2] + bw
/ 64 + 2);
1701 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 4);
1705 inc
= 1 << (10 + bw
/ 64);
1706 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1715 sisusb_get_sdram_size(struct sisusb_usb_data
*sisusb
, int *iret
, int bw
,
1718 int ret
= 0, i2ret
= 0, i
, j
;
1719 static const u8 sdramtype
[13][5] = {
1720 { 2, 12, 9, 64, 0x35 },
1721 { 1, 13, 9, 64, 0x44 },
1722 { 2, 12, 8, 32, 0x31 },
1723 { 2, 11, 9, 32, 0x25 },
1724 { 1, 12, 9, 32, 0x34 },
1725 { 1, 13, 8, 32, 0x40 },
1726 { 2, 11, 8, 16, 0x21 },
1727 { 1, 12, 8, 16, 0x30 },
1728 { 1, 11, 9, 16, 0x24 },
1729 { 1, 11, 8, 8, 0x20 },
1730 { 2, 9, 8, 4, 0x01 },
1731 { 1, 10, 8, 4, 0x10 },
1732 { 1, 9, 8, 2, 0x00 }
1735 *iret
= 1; /* error */
1737 for (i
= 0; i
< 13; i
++) {
1738 ret
|= SETIREGANDOR(SISSR
, 0x13, 0x80, sdramtype
[i
][4]);
1739 for (j
= 2; j
> 0; j
--) {
1740 ret
|= sisusb_set_rank(sisusb
, &i2ret
, i
, j
,
1741 chab
, sdramtype
, bw
);
1745 ret
|= sisusb_check_ranks(sisusb
, &i2ret
, j
, i
,
1748 *iret
= 0; /* ram size found */
1758 sisusb_setup_screen(struct sisusb_usb_data
*sisusb
, int clrall
, int drwfr
)
1762 int i
, length
, modex
, modey
, bpp
;
1764 modex
= 640; modey
= 480; bpp
= 2;
1766 address
= sisusb
->vrambase
; /* Clear video ram */
1769 length
= sisusb
->vramsize
;
1771 length
= modex
* bpp
* modey
;
1773 ret
= sisusb_clear_vram(sisusb
, address
, length
);
1775 if (!ret
&& drwfr
) {
1776 for (i
= 0; i
< modex
; i
++) {
1777 address
= sisusb
->vrambase
+ (i
* bpp
);
1778 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1780 address
+= (modex
* (modey
-1) * bpp
);
1781 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1784 for (i
= 0; i
< modey
; i
++) {
1785 address
= sisusb
->vrambase
+ ((i
* modex
) * bpp
);
1786 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1788 address
+= ((modex
- 1) * bpp
);
1789 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1798 sisusb_set_default_mode(struct sisusb_usb_data
*sisusb
, int touchengines
)
1800 int ret
= 0, i
, j
, modex
, modey
, bpp
, du
;
1801 u8 sr31
, cr63
, tmp8
;
1802 static const char attrdata
[] = {
1803 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1804 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1807 static const char crtcrdata
[] = {
1808 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1809 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1810 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1813 static const char grcdata
[] = {
1814 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1817 static const char crtcdata
[] = {
1818 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1819 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1823 modex
= 640; modey
= 480; bpp
= 2;
1825 GETIREG(SISSR
, 0x31, &sr31
);
1826 GETIREG(SISCR
, 0x63, &cr63
);
1827 SETIREGOR(SISSR
, 0x01, 0x20);
1828 SETIREG(SISCR
, 0x63, cr63
& 0xbf);
1829 SETIREGOR(SISCR
, 0x17, 0x80);
1830 SETIREGOR(SISSR
, 0x1f, 0x04);
1831 SETIREGAND(SISSR
, 0x07, 0xfb);
1832 SETIREG(SISSR
, 0x00, 0x03); /* seq */
1833 SETIREG(SISSR
, 0x01, 0x21);
1834 SETIREG(SISSR
, 0x02, 0x0f);
1835 SETIREG(SISSR
, 0x03, 0x00);
1836 SETIREG(SISSR
, 0x04, 0x0e);
1837 SETREG(SISMISCW
, 0x23); /* misc */
1838 for (i
= 0; i
<= 0x18; i
++) { /* crtc */
1839 SETIREG(SISCR
, i
, crtcrdata
[i
]);
1841 for (i
= 0; i
<= 0x13; i
++) { /* att */
1842 GETREG(SISINPSTAT
, &tmp8
);
1844 SETREG(SISAR
, attrdata
[i
]);
1846 GETREG(SISINPSTAT
, &tmp8
);
1847 SETREG(SISAR
, 0x14);
1848 SETREG(SISAR
, 0x00);
1849 GETREG(SISINPSTAT
, &tmp8
);
1850 SETREG(SISAR
, 0x20);
1851 GETREG(SISINPSTAT
, &tmp8
);
1852 for (i
= 0; i
<= 0x08; i
++) { /* grc */
1853 SETIREG(SISGR
, i
, grcdata
[i
]);
1855 SETIREGAND(SISGR
, 0x05, 0xbf);
1856 for (i
= 0x0A; i
<= 0x0E; i
++) { /* clr ext */
1857 SETIREG(SISSR
, i
, 0x00);
1859 SETIREGAND(SISSR
, 0x37, 0xfe);
1860 SETREG(SISMISCW
, 0xef); /* sync */
1861 SETIREG(SISCR
, 0x11, 0x00); /* crtc */
1862 for (j
= 0x00, i
= 0; i
<= 7; i
++, j
++) {
1863 SETIREG(SISCR
, j
, crtcdata
[i
]);
1865 for (j
= 0x10; i
<= 10; i
++, j
++) {
1866 SETIREG(SISCR
, j
, crtcdata
[i
]);
1868 for (j
= 0x15; i
<= 12; i
++, j
++) {
1869 SETIREG(SISCR
, j
, crtcdata
[i
]);
1871 for (j
= 0x0A; i
<= 15; i
++, j
++) {
1872 SETIREG(SISSR
, j
, crtcdata
[i
]);
1874 SETIREG(SISSR
, 0x0E, (crtcdata
[16] & 0xE0));
1875 SETIREGANDOR(SISCR
, 0x09, 0x5f, ((crtcdata
[16] & 0x01) << 5));
1876 SETIREG(SISCR
, 0x14, 0x4f);
1877 du
= (modex
/ 16) * (bpp
* 2); /* offset/pitch */
1878 if (modex
% 16) du
+= bpp
;
1879 SETIREGANDOR(SISSR
, 0x0e, 0xf0, ((du
>> 8) & 0x0f));
1880 SETIREG(SISCR
, 0x13, (du
& 0xff));
1883 if (du
& 0xff) tmp8
++;
1884 SETIREG(SISSR
, 0x10, tmp8
);
1885 SETIREG(SISSR
, 0x31, 0x00); /* VCLK */
1886 SETIREG(SISSR
, 0x2b, 0x1b);
1887 SETIREG(SISSR
, 0x2c, 0xe1);
1888 SETIREG(SISSR
, 0x2d, 0x01);
1889 SETIREGAND(SISSR
, 0x3d, 0xfe); /* FIFO */
1890 SETIREG(SISSR
, 0x08, 0xae);
1891 SETIREGAND(SISSR
, 0x09, 0xf0);
1892 SETIREG(SISSR
, 0x08, 0x34);
1893 SETIREGOR(SISSR
, 0x3d, 0x01);
1894 SETIREGAND(SISSR
, 0x1f, 0x3f); /* mode regs */
1895 SETIREGANDOR(SISSR
, 0x06, 0xc0, 0x0a);
1896 SETIREG(SISCR
, 0x19, 0x00);
1897 SETIREGAND(SISCR
, 0x1a, 0xfc);
1898 SETIREGAND(SISSR
, 0x0f, 0xb7);
1899 SETIREGAND(SISSR
, 0x31, 0xfb);
1900 SETIREGANDOR(SISSR
, 0x21, 0x1f, 0xa0);
1901 SETIREGAND(SISSR
, 0x32, 0xf3);
1902 SETIREGANDOR(SISSR
, 0x07, 0xf8, 0x03);
1903 SETIREG(SISCR
, 0x52, 0x6c);
1905 SETIREG(SISCR
, 0x0d, 0x00); /* adjust frame */
1906 SETIREG(SISCR
, 0x0c, 0x00);
1907 SETIREG(SISSR
, 0x0d, 0x00);
1908 SETIREGAND(SISSR
, 0x37, 0xfe);
1910 SETIREG(SISCR
, 0x32, 0x20);
1911 SETIREGAND(SISSR
, 0x01, 0xdf); /* enable display */
1912 SETIREG(SISCR
, 0x63, (cr63
& 0xbf));
1913 SETIREG(SISSR
, 0x31, (sr31
& 0xfb));
1916 SETIREG(SISSR
, 0x20, 0xa1); /* enable engines */
1917 SETIREGOR(SISSR
, 0x1e, 0x5a);
1919 SETIREG(SISSR
, 0x26, 0x01); /* disable cmdqueue */
1920 SETIREG(SISSR
, 0x27, 0x1f);
1921 SETIREG(SISSR
, 0x26, 0x00);
1924 SETIREG(SISCR
, 0x34, 0x44); /* we just set std mode #44 */
1930 sisusb_init_gfxcore(struct sisusb_usb_data
*sisusb
)
1932 int ret
= 0, i
, j
, bw
, chab
, iret
, retry
= 3;
1935 static const char mclktable
[] = {
1936 0x3b, 0x22, 0x01, 143,
1937 0x3b, 0x22, 0x01, 143,
1938 0x3b, 0x22, 0x01, 143,
1939 0x3b, 0x22, 0x01, 143
1941 static const char eclktable
[] = {
1942 0x3b, 0x22, 0x01, 143,
1943 0x3b, 0x22, 0x01, 143,
1944 0x3b, 0x22, 0x01, 143,
1945 0x3b, 0x22, 0x01, 143
1947 static const char ramtypetable1
[] = {
1948 0x00, 0x04, 0x60, 0x60,
1949 0x0f, 0x0f, 0x1f, 0x1f,
1950 0xba, 0xba, 0xba, 0xba,
1951 0xa9, 0xa9, 0xac, 0xac,
1952 0xa0, 0xa0, 0xa0, 0xa8,
1953 0x00, 0x00, 0x02, 0x02,
1954 0x30, 0x30, 0x40, 0x40
1956 static const char ramtypetable2
[] = {
1957 0x77, 0x77, 0x44, 0x44,
1958 0x77, 0x77, 0x44, 0x44,
1959 0x00, 0x00, 0x00, 0x00,
1960 0x5b, 0x5b, 0xab, 0xab,
1961 0x00, 0x00, 0xf0, 0xf8
1967 ret
= GETREG(SISVGAEN
, &tmp8
);
1968 ret
|= SETREG(SISVGAEN
, (tmp8
| 0x01));
1970 /* Enable GPU access to VRAM */
1971 ret
|= GETREG(SISMISCR
, &tmp8
);
1972 ret
|= SETREG(SISMISCW
, (tmp8
| 0x01));
1976 /* Reset registers */
1977 ret
|= SETIREGAND(SISCR
, 0x5b, 0xdf);
1978 ret
|= SETIREG(SISSR
, 0x05, 0x86);
1979 ret
|= SETIREGOR(SISSR
, 0x20, 0x01);
1981 ret
|= SETREG(SISMISCW
, 0x67);
1983 for (i
= 0x06; i
<= 0x1f; i
++) {
1984 ret
|= SETIREG(SISSR
, i
, 0x00);
1986 for (i
= 0x21; i
<= 0x27; i
++) {
1987 ret
|= SETIREG(SISSR
, i
, 0x00);
1989 for (i
= 0x31; i
<= 0x3d; i
++) {
1990 ret
|= SETIREG(SISSR
, i
, 0x00);
1992 for (i
= 0x12; i
<= 0x1b; i
++) {
1993 ret
|= SETIREG(SISSR
, i
, 0x00);
1995 for (i
= 0x79; i
<= 0x7c; i
++) {
1996 ret
|= SETIREG(SISCR
, i
, 0x00);
2001 ret
|= SETIREG(SISCR
, 0x63, 0x80);
2003 ret
|= GETIREG(SISSR
, 0x3a, &ramtype
);
2006 ret
|= SETIREG(SISSR
, 0x28, mclktable
[ramtype
* 4]);
2007 ret
|= SETIREG(SISSR
, 0x29, mclktable
[(ramtype
* 4) + 1]);
2008 ret
|= SETIREG(SISSR
, 0x2a, mclktable
[(ramtype
* 4) + 2]);
2010 ret
|= SETIREG(SISSR
, 0x2e, eclktable
[ramtype
* 4]);
2011 ret
|= SETIREG(SISSR
, 0x2f, eclktable
[(ramtype
* 4) + 1]);
2012 ret
|= SETIREG(SISSR
, 0x30, eclktable
[(ramtype
* 4) + 2]);
2014 ret
|= SETIREG(SISSR
, 0x07, 0x18);
2015 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2019 for (i
= 0x15, j
= 0; i
<= 0x1b; i
++, j
++) {
2020 ret
|= SETIREG(SISSR
, i
, ramtypetable1
[(j
*4) + ramtype
]);
2022 for (i
= 0x40, j
= 0; i
<= 0x44; i
++, j
++) {
2023 ret
|= SETIREG(SISCR
, i
, ramtypetable2
[(j
*4) + ramtype
]);
2026 ret
|= SETIREG(SISCR
, 0x49, 0xaa);
2028 ret
|= SETIREG(SISSR
, 0x1f, 0x00);
2029 ret
|= SETIREG(SISSR
, 0x20, 0xa0);
2030 ret
|= SETIREG(SISSR
, 0x23, 0xf6);
2031 ret
|= SETIREG(SISSR
, 0x24, 0x0d);
2032 ret
|= SETIREG(SISSR
, 0x25, 0x33);
2034 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2036 ret
|= SETIREGOR(SISPART1
, 0x2f, 0x01);
2038 ret
|= SETIREGAND(SISCAP
, 0x3f, 0xef);
2042 ret
|= SETIREG(SISPART1
, 0x00, 0x00);
2044 ret
|= GETIREG(SISSR
, 0x13, &tmp8
);
2047 ret
|= SETIREG(SISPART1
, 0x02, 0x00);
2048 ret
|= SETIREG(SISPART1
, 0x2e, 0x08);
2050 ret
|= sisusb_read_pci_config(sisusb
, 0x50, &tmp32
);
2051 tmp32
&= 0x00f00000;
2052 tmp8
= (tmp32
== 0x100000) ? 0x33 : 0x03;
2053 ret
|= SETIREG(SISSR
, 0x25, tmp8
);
2054 tmp8
= (tmp32
== 0x100000) ? 0xaa : 0x88;
2055 ret
|= SETIREG(SISCR
, 0x49, tmp8
);
2057 ret
|= SETIREG(SISSR
, 0x27, 0x1f);
2058 ret
|= SETIREG(SISSR
, 0x31, 0x00);
2059 ret
|= SETIREG(SISSR
, 0x32, 0x11);
2060 ret
|= SETIREG(SISSR
, 0x33, 0x00);
2064 ret
|= SETIREG(SISCR
, 0x83, 0x00);
2066 ret
|= sisusb_set_default_mode(sisusb
, 0);
2068 ret
|= SETIREGAND(SISSR
, 0x21, 0xdf);
2069 ret
|= SETIREGOR(SISSR
, 0x01, 0x20);
2070 ret
|= SETIREGOR(SISSR
, 0x16, 0x0f);
2072 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
2074 /* Disable refresh */
2075 ret
|= SETIREGAND(SISSR
, 0x17, 0xf8);
2076 ret
|= SETIREGOR(SISSR
, 0x19, 0x03);
2078 ret
|= sisusb_getbuswidth(sisusb
, &bw
, &chab
);
2079 ret
|= sisusb_verify_mclk(sisusb
);
2082 ret
|= sisusb_get_sdram_size(sisusb
, &iret
, bw
, chab
);
2084 dev_err(&sisusb
->sisusb_dev
->dev
,"RAM size detection failed, assuming 8MB video RAM\n");
2085 ret
|= SETIREG(SISSR
,0x14,0x31);
2089 dev_err(&sisusb
->sisusb_dev
->dev
, "DDR RAM device found, assuming 8MB video RAM\n");
2090 ret
|= SETIREG(SISSR
,0x14,0x31);
2094 /* Enable refresh */
2095 ret
|= SETIREG(SISSR
, 0x16, ramtypetable1
[4 + ramtype
]);
2096 ret
|= SETIREG(SISSR
, 0x17, ramtypetable1
[8 + ramtype
]);
2097 ret
|= SETIREG(SISSR
, 0x19, ramtypetable1
[16 + ramtype
]);
2099 ret
|= SETIREGOR(SISSR
, 0x21, 0x20);
2101 ret
|= SETIREG(SISSR
, 0x22, 0xfb);
2102 ret
|= SETIREG(SISSR
, 0x21, 0xa5);
2122 sisusb_get_ramconfig(struct sisusb_usb_data
*sisusb
)
2124 u8 tmp8
, tmp82
, ramtype
;
2126 char *ramtypetext1
= NULL
;
2127 const char *ramtypetext2
[] = { "SDR SDRAM", "SDR SGRAM",
2128 "DDR SDRAM", "DDR SGRAM" };
2129 static const int busSDR
[4] = {64, 64, 128, 128};
2130 static const int busDDR
[4] = {32, 32, 64, 64};
2131 static const int busDDRA
[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2133 sisusb_getidxreg(sisusb
, SISSR
, 0x14, &tmp8
);
2134 sisusb_getidxreg(sisusb
, SISSR
, 0x15, &tmp82
);
2135 sisusb_getidxreg(sisusb
, SISSR
, 0x3a, &ramtype
);
2136 sisusb
->vramsize
= (1 << ((tmp8
& 0xf0) >> 4)) * 1024 * 1024;
2138 switch ((tmp8
>> 2) & 0x03) {
2139 case 0: ramtypetext1
= "1 ch/1 r";
2143 bw
= busSDR
[(tmp8
& 0x03)];
2146 case 1: ramtypetext1
= "1 ch/2 r";
2147 sisusb
->vramsize
<<= 1;
2148 bw
= busSDR
[(tmp8
& 0x03)];
2150 case 2: ramtypetext1
= "asymmeric";
2151 sisusb
->vramsize
+= sisusb
->vramsize
/2;
2152 bw
= busDDRA
[(tmp8
& 0x03)];
2154 case 3: ramtypetext1
= "2 channel";
2155 sisusb
->vramsize
<<= 1;
2156 bw
= busDDR
[(tmp8
& 0x03)];
2160 dev_info(&sisusb
->sisusb_dev
->dev
, "%dMB %s %s, bus width %d\n", (sisusb
->vramsize
>> 20), ramtypetext1
,
2161 ramtypetext2
[ramtype
], bw
);
2165 sisusb_do_init_gfxdevice(struct sisusb_usb_data
*sisusb
)
2167 struct sisusb_packet packet
;
2172 packet
.header
= 0x001f;
2173 packet
.address
= 0x00000324;
2174 packet
.data
= 0x00000004;
2175 ret
= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2177 packet
.header
= 0x001f;
2178 packet
.address
= 0x00000364;
2179 packet
.data
= 0x00000004;
2180 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2182 packet
.header
= 0x001f;
2183 packet
.address
= 0x00000384;
2184 packet
.data
= 0x00000004;
2185 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2187 packet
.header
= 0x001f;
2188 packet
.address
= 0x00000100;
2189 packet
.data
= 0x00000700;
2190 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2192 packet
.header
= 0x000f;
2193 packet
.address
= 0x00000004;
2194 ret
|= sisusb_send_bridge_packet(sisusb
, 6, &packet
, 0);
2195 packet
.data
|= 0x17;
2196 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2198 /* Init BAR 0 (VRAM) */
2199 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2200 ret
|= sisusb_write_pci_config(sisusb
, 0x10, 0xfffffff0);
2201 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2203 tmp32
|= SISUSB_PCI_MEMBASE
;
2204 ret
|= sisusb_write_pci_config(sisusb
, 0x10, tmp32
);
2206 /* Init BAR 1 (MMIO) */
2207 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2208 ret
|= sisusb_write_pci_config(sisusb
, 0x14, 0xfffffff0);
2209 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2211 tmp32
|= SISUSB_PCI_MMIOBASE
;
2212 ret
|= sisusb_write_pci_config(sisusb
, 0x14, tmp32
);
2214 /* Init BAR 2 (i/o ports) */
2215 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2216 ret
|= sisusb_write_pci_config(sisusb
, 0x18, 0xfffffff0);
2217 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2219 tmp32
|= SISUSB_PCI_IOPORTBASE
;
2220 ret
|= sisusb_write_pci_config(sisusb
, 0x18, tmp32
);
2222 /* Enable memory and i/o access */
2223 ret
|= sisusb_read_pci_config(sisusb
, 0x04, &tmp32
);
2225 ret
|= sisusb_write_pci_config(sisusb
, 0x04, tmp32
);
2228 /* Some further magic */
2229 packet
.header
= 0x001f;
2230 packet
.address
= 0x00000050;
2231 packet
.data
= 0x000000ff;
2232 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2238 /* Initialize the graphics device (return 0 on success)
2239 * This initializes the net2280 as well as the PCI registers
2240 * of the graphics board.
2244 sisusb_init_gfxdevice(struct sisusb_usb_data
*sisusb
, int initscreen
)
2246 int ret
= 0, test
= 0;
2249 if (sisusb
->devinit
== 1) {
2250 /* Read PCI BARs and see if they have been set up */
2251 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2252 if (ret
) return ret
;
2253 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MEMBASE
) test
++;
2255 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2256 if (ret
) return ret
;
2257 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MMIOBASE
) test
++;
2259 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2260 if (ret
) return ret
;
2261 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_IOPORTBASE
) test
++;
2264 /* No? So reset the device */
2265 if ((sisusb
->devinit
== 0) || (test
!= 3)) {
2267 ret
|= sisusb_do_init_gfxdevice(sisusb
);
2270 sisusb
->devinit
= 1;
2274 if (sisusb
->devinit
) {
2275 /* Initialize the graphics core */
2276 if (sisusb_init_gfxcore(sisusb
) == 0) {
2277 sisusb
->gfxinit
= 1;
2278 sisusb_get_ramconfig(sisusb
);
2279 ret
|= sisusb_set_default_mode(sisusb
, 1);
2280 ret
|= sisusb_setup_screen(sisusb
, 1, initscreen
);
2288 #ifdef INCL_SISUSB_CON
2290 /* Set up default text mode:
2291 - Set text mode (0x03)
2292 - Upload default font
2293 - Upload user font (if available)
2297 sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
)
2299 int ret
= 0, slot
= sisusb
->font_slot
, i
;
2300 const struct font_desc
*myfont
;
2304 static const char bootstring
[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2305 static const char bootlogo
[] = "(o_ //\\ V_/_";
2307 /* sisusb->lock is down */
2309 if (!sisusb
->SiS_Pr
)
2312 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2313 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2316 SiSUSBSetMode(sisusb
->SiS_Pr
, 0x03);
2318 if (!(myfont
= find_font("VGA8x16")))
2321 if (!(tempbuf
= vmalloc(8192)))
2324 for (i
= 0; i
< 256; i
++)
2325 memcpy(tempbuf
+ (i
* 32), myfont
->data
+ (i
* 16), 16);
2327 /* Upload default font */
2328 ret
= sisusbcon_do_font_op(sisusb
, 1, 0, tempbuf
, 8192, 0, 1, NULL
, 16, 0);
2332 /* Upload user font (and reset current slot) */
2333 if (sisusb
->font_backup
) {
2334 ret
|= sisusbcon_do_font_op(sisusb
, 1, 2, sisusb
->font_backup
,
2335 8192, sisusb
->font_backup_512
, 1, NULL
,
2336 sisusb
->font_backup_height
, 0);
2338 sisusbcon_do_font_op(sisusb
, 1, 0, NULL
, 0, 0, 1,
2342 if (init
&& !sisusb
->scrbuf
) {
2344 if ((tempbuf
= vmalloc(8192))) {
2347 tempbufb
= (u16
*)tempbuf
;
2349 *(tempbufb
++) = 0x0720;
2352 tempbufb
= (u16
*)tempbuf
;
2353 while (bootlogo
[i
]) {
2354 *(tempbufb
++) = 0x0700 | bootlogo
[i
++];
2360 tempbufb
= (u16
*)tempbuf
+ 6;
2361 while (bootstring
[i
])
2362 *(tempbufb
++) = 0x0700 | bootstring
[i
++];
2364 ret
|= sisusb_copy_memory(sisusb
, tempbuf
,
2365 sisusb
->vrambase
, 8192, &written
);
2371 } else if (sisusb
->scrbuf
) {
2373 ret
|= sisusb_copy_memory(sisusb
, (char *)sisusb
->scrbuf
,
2374 sisusb
->vrambase
, sisusb
->scrbuf_size
, &written
);
2378 if (sisusb
->sisusb_cursor_size_from
>= 0 &&
2379 sisusb
->sisusb_cursor_size_to
>= 0) {
2380 sisusb_setidxreg(sisusb
, SISCR
, 0x0a,
2381 sisusb
->sisusb_cursor_size_from
);
2382 sisusb_setidxregandor(sisusb
, SISCR
, 0x0b, 0xe0,
2383 sisusb
->sisusb_cursor_size_to
);
2385 sisusb_setidxreg(sisusb
, SISCR
, 0x0a, 0x2d);
2386 sisusb_setidxreg(sisusb
, SISCR
, 0x0b, 0x0e);
2387 sisusb
->sisusb_cursor_size_to
= -1;
2390 slot
= sisusb
->sisusb_cursor_loc
;
2391 if(slot
< 0) slot
= 0;
2393 sisusb
->sisusb_cursor_loc
= -1;
2394 sisusb
->bad_cursor_pos
= 1;
2396 sisusb_set_cursor(sisusb
, slot
);
2398 sisusb_setidxreg(sisusb
, SISCR
, 0x0c, (sisusb
->cur_start_addr
>> 8));
2399 sisusb_setidxreg(sisusb
, SISCR
, 0x0d, (sisusb
->cur_start_addr
& 0xff));
2401 sisusb
->textmodedestroyed
= 0;
2403 /* sisusb->lock is down */
2413 sisusb_open(struct inode
*inode
, struct file
*file
)
2415 struct sisusb_usb_data
*sisusb
;
2416 struct usb_interface
*interface
;
2417 int subminor
= iminor(inode
);
2420 if (!(interface
= usb_find_interface(&sisusb_driver
, subminor
))) {
2425 if (!(sisusb
= usb_get_intfdata(interface
))) {
2430 mutex_lock(&sisusb
->lock
);
2432 if (!sisusb
->present
|| !sisusb
->ready
) {
2433 mutex_unlock(&sisusb
->lock
);
2438 if (sisusb
->isopen
) {
2439 mutex_unlock(&sisusb
->lock
);
2444 if (!sisusb
->devinit
) {
2445 if (sisusb
->sisusb_dev
->speed
== USB_SPEED_HIGH
) {
2446 if (sisusb_init_gfxdevice(sisusb
, 0)) {
2447 mutex_unlock(&sisusb
->lock
);
2448 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to initialize device\n");
2453 mutex_unlock(&sisusb
->lock
);
2454 dev_err(&sisusb
->sisusb_dev
->dev
, "Device not attached to USB 2.0 hub\n");
2460 /* Increment usage count for our sisusb */
2461 kref_get(&sisusb
->kref
);
2465 file
->private_data
= sisusb
;
2467 mutex_unlock(&sisusb
->lock
);
2474 sisusb_delete(struct kref
*kref
)
2476 struct sisusb_usb_data
*sisusb
= to_sisusb_dev(kref
);
2481 if (sisusb
->sisusb_dev
)
2482 usb_put_dev(sisusb
->sisusb_dev
);
2484 sisusb
->sisusb_dev
= NULL
;
2485 sisusb_free_buffers(sisusb
);
2486 sisusb_free_urbs(sisusb
);
2487 #ifdef INCL_SISUSB_CON
2488 kfree(sisusb
->SiS_Pr
);
2494 sisusb_release(struct inode
*inode
, struct file
*file
)
2496 struct sisusb_usb_data
*sisusb
;
2498 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2501 mutex_lock(&sisusb
->lock
);
2503 if (sisusb
->present
) {
2504 /* Wait for all URBs to finish if device still present */
2505 if (!sisusb_wait_all_out_complete(sisusb
))
2506 sisusb_kill_all_busy(sisusb
);
2510 file
->private_data
= NULL
;
2512 mutex_unlock(&sisusb
->lock
);
2514 /* decrement the usage count on our device */
2515 kref_put(&sisusb
->kref
, sisusb_delete
);
2521 sisusb_read(struct file
*file
, char __user
*buffer
, size_t count
, loff_t
*ppos
)
2523 struct sisusb_usb_data
*sisusb
;
2524 ssize_t bytes_read
= 0;
2530 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2533 mutex_lock(&sisusb
->lock
);
2536 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2537 mutex_unlock(&sisusb
->lock
);
2541 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2542 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2545 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2546 SISUSB_PCI_IOPORTBASE
;
2549 * Byte, word and long(32) can be read. As this
2550 * emulates inX instructions, the data returned is
2551 * in machine-endianness.
2556 if (sisusb_read_memio_byte(sisusb
,
2560 else if (put_user(buf8
, (u8 __user
*)buffer
))
2568 if (sisusb_read_memio_word(sisusb
,
2572 else if (put_user(buf16
, (u16 __user
*)buffer
))
2580 if (sisusb_read_memio_long(sisusb
,
2584 else if (put_user(buf32
, (u32 __user
*)buffer
))
2596 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2597 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2600 SISUSB_PCI_PSEUDO_MEMBASE
+
2604 * Remember: Data delivered is never endian-corrected
2606 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2607 NULL
, count
, buffer
, &bytes_read
);
2612 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2613 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2616 SISUSB_PCI_PSEUDO_MMIOBASE
+
2617 SISUSB_PCI_MMIOBASE
;
2620 * Remember: Data delivered is never endian-corrected
2622 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2623 NULL
, count
, buffer
, &bytes_read
);
2628 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2629 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ 0x5c) {
2632 mutex_unlock(&sisusb
->lock
);
2636 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2638 /* Read PCI config register
2639 * Return value delivered in machine endianness.
2641 if (sisusb_read_pci_config(sisusb
, address
, &buf32
))
2643 else if (put_user(buf32
, (u32 __user
*)buffer
))
2654 (*ppos
) += bytes_read
;
2656 mutex_unlock(&sisusb
->lock
);
2658 return errno
? errno
: bytes_read
;
2662 sisusb_write(struct file
*file
, const char __user
*buffer
, size_t count
,
2665 struct sisusb_usb_data
*sisusb
;
2667 ssize_t bytes_written
= 0;
2672 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2675 mutex_lock(&sisusb
->lock
);
2678 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2679 mutex_unlock(&sisusb
->lock
);
2683 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2684 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2687 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2688 SISUSB_PCI_IOPORTBASE
;
2691 * Byte, word and long(32) can be written. As this
2692 * emulates outX instructions, the data is expected
2693 * in machine-endianness.
2698 if (get_user(buf8
, (u8 __user
*)buffer
))
2700 else if (sisusb_write_memio_byte(sisusb
,
2710 if (get_user(buf16
, (u16 __user
*)buffer
))
2712 else if (sisusb_write_memio_word(sisusb
,
2722 if (get_user(buf32
, (u32 __user
*)buffer
))
2724 else if (sisusb_write_memio_long(sisusb
,
2737 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2738 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2741 SISUSB_PCI_PSEUDO_MEMBASE
+
2745 * Buffer is copied 1:1, therefore, on big-endian
2746 * machines, the data must be swapped by userland
2747 * in advance (if applicable; no swapping in 8bpp
2748 * mode or if YUV data is being transferred).
2750 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2751 count
, buffer
, 0, &bytes_written
);
2754 errno
= bytes_written
;
2756 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2757 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2760 SISUSB_PCI_PSEUDO_MMIOBASE
+
2761 SISUSB_PCI_MMIOBASE
;
2764 * Buffer is copied 1:1, therefore, on big-endian
2765 * machines, the data must be swapped by userland
2768 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2769 count
, buffer
, 0, &bytes_written
);
2772 errno
= bytes_written
;
2774 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2775 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ SISUSB_PCI_PCONFSIZE
) {
2778 mutex_unlock(&sisusb
->lock
);
2782 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2784 /* Write PCI config register.
2785 * Given value expected in machine endianness.
2787 if (get_user(buf32
, (u32 __user
*)buffer
))
2789 else if (sisusb_write_pci_config(sisusb
, address
, buf32
))
2802 (*ppos
) += bytes_written
;
2804 mutex_unlock(&sisusb
->lock
);
2806 return errno
? errno
: bytes_written
;
2810 sisusb_lseek(struct file
*file
, loff_t offset
, int orig
)
2812 struct sisusb_usb_data
*sisusb
;
2815 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2818 mutex_lock(&sisusb
->lock
);
2821 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2822 mutex_unlock(&sisusb
->lock
);
2828 file
->f_pos
= offset
;
2830 /* never negative, no force_successful_syscall needed */
2833 file
->f_pos
+= offset
;
2835 /* never negative, no force_successful_syscall needed */
2838 /* seeking relative to "end of file" is not supported */
2842 mutex_unlock(&sisusb
->lock
);
2847 sisusb_handle_command(struct sisusb_usb_data
*sisusb
, struct sisusb_command
*y
,
2850 int retval
, port
, length
;
2853 /* All our commands require the device
2854 * to be initialized.
2856 if (!sisusb
->devinit
)
2860 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2861 SISUSB_PCI_IOPORTBASE
;
2863 switch (y
->operation
) {
2865 retval
= sisusb_getidxreg(sisusb
, port
,
2866 y
->data0
, &y
->data1
);
2868 if (copy_to_user((void __user
*)arg
, y
,
2875 retval
= sisusb_setidxreg(sisusb
, port
,
2876 y
->data0
, y
->data1
);
2880 retval
= sisusb_setidxregor(sisusb
, port
,
2881 y
->data0
, y
->data1
);
2885 retval
= sisusb_setidxregand(sisusb
, port
,
2886 y
->data0
, y
->data1
);
2889 case SUCMD_SETANDOR
:
2890 retval
= sisusb_setidxregandor(sisusb
, port
,
2891 y
->data0
, y
->data1
, y
->data2
);
2895 retval
= sisusb_setidxregmask(sisusb
, port
,
2896 y
->data0
, y
->data1
, y
->data2
);
2900 /* Gfx core must be initialized */
2901 if (!sisusb
->gfxinit
)
2904 length
= (y
->data0
<< 16) | (y
->data1
<< 8) | y
->data2
;
2905 address
= y
->data3
-
2906 SISUSB_PCI_PSEUDO_MEMBASE
+
2908 retval
= sisusb_clear_vram(sisusb
, address
, length
);
2911 case SUCMD_HANDLETEXTMODE
:
2913 #ifdef INCL_SISUSB_CON
2914 /* Gfx core must be initialized, SiS_Pr must exist */
2915 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2920 retval
= sisusb_reset_text_mode(sisusb
, 0);
2923 sisusb
->textmodedestroyed
= 1;
2929 #ifdef INCL_SISUSB_CON
2931 /* Gfx core must be initialized, SiS_Pr must exist */
2932 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2937 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2938 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2940 if (SiSUSBSetMode(sisusb
->SiS_Pr
, y
->data3
))
2945 case SUCMD_SETVESAMODE
:
2946 /* Gfx core must be initialized, SiS_Pr must exist */
2947 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2952 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2953 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2955 if (SiSUSBSetVESAMode(sisusb
->SiS_Pr
, y
->data3
))
2972 sisusb_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
2974 struct sisusb_usb_data
*sisusb
;
2975 struct sisusb_info x
;
2976 struct sisusb_command y
;
2978 u32 __user
*argp
= (u32 __user
*)arg
;
2980 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2984 mutex_lock(&sisusb
->lock
);
2987 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2994 case SISUSB_GET_CONFIG_SIZE
:
2996 if (put_user(sizeof(x
), argp
))
3001 case SISUSB_GET_CONFIG
:
3003 x
.sisusb_id
= SISUSB_ID
;
3004 x
.sisusb_version
= SISUSB_VERSION
;
3005 x
.sisusb_revision
= SISUSB_REVISION
;
3006 x
.sisusb_patchlevel
= SISUSB_PATCHLEVEL
;
3007 x
.sisusb_gfxinit
= sisusb
->gfxinit
;
3008 x
.sisusb_vrambase
= SISUSB_PCI_PSEUDO_MEMBASE
;
3009 x
.sisusb_mmiobase
= SISUSB_PCI_PSEUDO_MMIOBASE
;
3010 x
.sisusb_iobase
= SISUSB_PCI_PSEUDO_IOPORTBASE
;
3011 x
.sisusb_pcibase
= SISUSB_PCI_PSEUDO_PCIBASE
;
3012 x
.sisusb_vramsize
= sisusb
->vramsize
;
3013 x
.sisusb_minor
= sisusb
->minor
;
3014 x
.sisusb_fbdevactive
= 0;
3015 #ifdef INCL_SISUSB_CON
3016 x
.sisusb_conactive
= sisusb
->haveconsole
? 1 : 0;
3018 x
.sisusb_conactive
= 0;
3021 if (copy_to_user((void __user
*)arg
, &x
, sizeof(x
)))
3026 case SISUSB_COMMAND
:
3028 if (copy_from_user(&y
, (void __user
*)arg
, sizeof(y
)))
3031 retval
= sisusb_handle_command(sisusb
, &y
, arg
);
3041 mutex_unlock(&sisusb
->lock
);
3046 #ifdef SISUSB_NEW_CONFIG_COMPAT
3048 sisusb_compat_ioctl(struct file
*f
, unsigned int cmd
, unsigned long arg
)
3053 case SISUSB_GET_CONFIG_SIZE
:
3054 case SISUSB_GET_CONFIG
:
3055 case SISUSB_COMMAND
:
3056 retval
= sisusb_ioctl(f
, cmd
, arg
);
3060 return -ENOIOCTLCMD
;
3065 static const struct file_operations usb_sisusb_fops
= {
3066 .owner
= THIS_MODULE
,
3067 .open
= sisusb_open
,
3068 .release
= sisusb_release
,
3069 .read
= sisusb_read
,
3070 .write
= sisusb_write
,
3071 .llseek
= sisusb_lseek
,
3072 #ifdef SISUSB_NEW_CONFIG_COMPAT
3073 .compat_ioctl
= sisusb_compat_ioctl
,
3075 .unlocked_ioctl
= sisusb_ioctl
3078 static struct usb_class_driver usb_sisusb_class
= {
3079 .name
= "sisusbvga%d",
3080 .fops
= &usb_sisusb_fops
,
3081 .minor_base
= SISUSB_MINOR
3084 static int sisusb_probe(struct usb_interface
*intf
,
3085 const struct usb_device_id
*id
)
3087 struct usb_device
*dev
= interface_to_usbdev(intf
);
3088 struct sisusb_usb_data
*sisusb
;
3091 dev_info(&dev
->dev
, "USB2VGA dongle found at address %d\n",
3094 /* Allocate memory for our private */
3095 if (!(sisusb
= kzalloc(sizeof(*sisusb
), GFP_KERNEL
))) {
3096 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate memory for private data\n");
3099 kref_init(&sisusb
->kref
);
3101 mutex_init(&(sisusb
->lock
));
3103 /* Register device */
3104 if ((retval
= usb_register_dev(intf
, &usb_sisusb_class
))) {
3105 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to get a minor for device %d\n",
3111 sisusb
->sisusb_dev
= dev
;
3112 sisusb
->minor
= intf
->minor
;
3113 sisusb
->vrambase
= SISUSB_PCI_MEMBASE
;
3114 sisusb
->mmiobase
= SISUSB_PCI_MMIOBASE
;
3115 sisusb
->mmiosize
= SISUSB_PCI_MMIOSIZE
;
3116 sisusb
->ioportbase
= SISUSB_PCI_IOPORTBASE
;
3117 /* Everything else is zero */
3119 /* Allocate buffers */
3120 sisusb
->ibufsize
= SISUSB_IBUF_SIZE
;
3121 if (!(sisusb
->ibuf
= kmalloc(SISUSB_IBUF_SIZE
, GFP_KERNEL
))) {
3122 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate memory for input buffer");
3127 sisusb
->numobufs
= 0;
3128 sisusb
->obufsize
= SISUSB_OBUF_SIZE
;
3129 for (i
= 0; i
< NUMOBUFS
; i
++) {
3130 if (!(sisusb
->obuf
[i
] = kmalloc(SISUSB_OBUF_SIZE
, GFP_KERNEL
))) {
3132 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate memory for output buffer\n");
3143 if (!(sisusb
->sisurbin
= usb_alloc_urb(0, GFP_KERNEL
))) {
3144 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate URBs\n");
3148 sisusb
->completein
= 1;
3150 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
3151 if (!(sisusb
->sisurbout
[i
] = usb_alloc_urb(0, GFP_KERNEL
))) {
3152 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate URBs\n");
3156 sisusb
->urbout_context
[i
].sisusb
= (void *)sisusb
;
3157 sisusb
->urbout_context
[i
].urbindex
= i
;
3158 sisusb
->urbstatus
[i
] = 0;
3161 dev_info(&sisusb
->sisusb_dev
->dev
, "Allocated %d output buffers\n", sisusb
->numobufs
);
3163 #ifdef INCL_SISUSB_CON
3164 /* Allocate our SiS_Pr */
3165 if (!(sisusb
->SiS_Pr
= kmalloc(sizeof(struct SiS_Private
), GFP_KERNEL
))) {
3166 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to allocate SiS_Pr\n");
3170 /* Do remaining init stuff */
3172 init_waitqueue_head(&sisusb
->wait_q
);
3174 usb_set_intfdata(intf
, sisusb
);
3176 usb_get_dev(sisusb
->sisusb_dev
);
3178 sisusb
->present
= 1;
3180 if (dev
->speed
== USB_SPEED_HIGH
) {
3182 #ifdef INCL_SISUSB_CON
3183 if (sisusb_first_vc
> 0 &&
3184 sisusb_last_vc
> 0 &&
3185 sisusb_first_vc
<= sisusb_last_vc
&&
3186 sisusb_last_vc
<= MAX_NR_CONSOLES
)
3189 if (sisusb_init_gfxdevice(sisusb
, initscreen
))
3190 dev_err(&sisusb
->sisusb_dev
->dev
, "Failed to early initialize device\n");
3193 dev_info(&sisusb
->sisusb_dev
->dev
, "Not attached to USB 2.0 hub, deferring init\n");
3197 #ifdef SISUSBENDIANTEST
3198 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST ***\n");
3199 sisusb_testreadwrite(sisusb
);
3200 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST END ***\n");
3203 #ifdef INCL_SISUSB_CON
3204 sisusb_console_init(sisusb
, sisusb_first_vc
, sisusb_last_vc
);
3210 sisusb_free_urbs(sisusb
);
3212 sisusb_free_buffers(sisusb
);
3214 usb_deregister_dev(intf
, &usb_sisusb_class
);
3220 static void sisusb_disconnect(struct usb_interface
*intf
)
3222 struct sisusb_usb_data
*sisusb
;
3224 /* This should *not* happen */
3225 if (!(sisusb
= usb_get_intfdata(intf
)))
3228 #ifdef INCL_SISUSB_CON
3229 sisusb_console_exit(sisusb
);
3232 usb_deregister_dev(intf
, &usb_sisusb_class
);
3234 mutex_lock(&sisusb
->lock
);
3236 /* Wait for all URBs to complete and kill them in case (MUST do) */
3237 if (!sisusb_wait_all_out_complete(sisusb
))
3238 sisusb_kill_all_busy(sisusb
);
3240 usb_set_intfdata(intf
, NULL
);
3242 sisusb
->present
= 0;
3245 mutex_unlock(&sisusb
->lock
);
3247 /* decrement our usage count */
3248 kref_put(&sisusb
->kref
, sisusb_delete
);
3251 static const struct usb_device_id sisusb_table
[] = {
3252 { USB_DEVICE(0x0711, 0x0550) },
3253 { USB_DEVICE(0x0711, 0x0900) },
3254 { USB_DEVICE(0x0711, 0x0901) },
3255 { USB_DEVICE(0x0711, 0x0902) },
3256 { USB_DEVICE(0x0711, 0x0903) },
3257 { USB_DEVICE(0x0711, 0x0918) },
3258 { USB_DEVICE(0x0711, 0x0920) },
3259 { USB_DEVICE(0x182d, 0x021c) },
3260 { USB_DEVICE(0x182d, 0x0269) },
3264 MODULE_DEVICE_TABLE (usb
, sisusb_table
);
3266 static struct usb_driver sisusb_driver
= {
3268 .probe
= sisusb_probe
,
3269 .disconnect
= sisusb_disconnect
,
3270 .id_table
= sisusb_table
,
3273 static int __init
usb_sisusb_init(void)
3276 #ifdef INCL_SISUSB_CON
3277 sisusb_init_concode();
3280 return usb_register(&sisusb_driver
);
3283 static void __exit
usb_sisusb_exit(void)
3285 usb_deregister(&sisusb_driver
);
3288 module_init(usb_sisusb_init
);
3289 module_exit(usb_sisusb_exit
);
3291 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3292 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3293 MODULE_LICENSE("GPL");