1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
3 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
7 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
9 * If distributed as part of the Linux kernel, this code is licensed under the
10 * terms of the GPL v2.
12 * Otherwise, the following license terms apply:
14 * * Redistribution and use in source and binary forms, with or without
15 * * modification, are permitted provided that the following conditions
17 * * 1) Redistributions of source code must retain the above copyright
18 * * notice, this list of conditions and the following disclaimer.
19 * * 2) Redistributions in binary form must reproduce the above copyright
20 * * notice, this list of conditions and the following disclaimer in the
21 * * documentation and/or other materials provided with the distribution.
22 * * 3) The name of the author may not be used to endorse or promote products
23 * * derived from this software without specific psisusbr written permission.
25 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
26 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Author: Thomas Winischhofer <thomas@winischhofer.net>
40 #include <linux/mutex.h>
41 #include <linux/module.h>
42 #include <linux/kernel.h>
43 #include <linux/signal.h>
44 #include <linux/errno.h>
45 #include <linux/poll.h>
46 #include <linux/init.h>
47 #include <linux/slab.h>
48 #include <linux/spinlock.h>
49 #include <linux/kref.h>
50 #include <linux/usb.h>
51 #include <linux/vmalloc.h>
54 #include "sisusb_init.h"
56 #ifdef CONFIG_USB_SISUSBVGA_CON
57 #include <linux/font.h>
60 #define SISUSB_DONTSYNC
62 /* Forward declarations / clean-up routines */
64 #ifdef CONFIG_USB_SISUSBVGA_CON
65 static int sisusb_first_vc
;
66 static int sisusb_last_vc
;
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
;
75 static void sisusb_free_buffers(struct sisusb_usb_data
*sisusb
)
79 for (i
= 0; i
< NUMOBUFS
; i
++) {
80 kfree(sisusb
->obuf
[i
]);
81 sisusb
->obuf
[i
] = NULL
;
87 static void sisusb_free_urbs(struct sisusb_usb_data
*sisusb
)
91 for (i
= 0; i
< NUMOBUFS
; i
++) {
92 usb_free_urb(sisusb
->sisurbout
[i
]);
93 sisusb
->sisurbout
[i
] = NULL
;
95 usb_free_urb(sisusb
->sisurbin
);
96 sisusb
->sisurbin
= NULL
;
99 /* Level 0: USB transport layer */
103 /* out-urb management */
105 /* Return 1 if all free, 0 otherwise */
106 static int sisusb_all_free(struct sisusb_usb_data
*sisusb
)
110 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
112 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
120 /* Kill all busy URBs */
121 static void sisusb_kill_all_busy(struct sisusb_usb_data
*sisusb
)
125 if (sisusb_all_free(sisusb
))
128 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
130 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
131 usb_kill_urb(sisusb
->sisurbout
[i
]);
136 /* Return 1 if ok, 0 if error (not all complete within timeout) */
137 static int sisusb_wait_all_out_complete(struct sisusb_usb_data
*sisusb
)
139 int timeout
= 5 * HZ
, i
= 1;
141 wait_event_timeout(sisusb
->wait_q
, (i
= sisusb_all_free(sisusb
)),
147 static int sisusb_outurb_available(struct sisusb_usb_data
*sisusb
)
151 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
153 if ((sisusb
->urbstatus
[i
] & (SU_URB_BUSY
|SU_URB_ALLOC
)) == 0)
161 static int sisusb_get_free_outbuf(struct sisusb_usb_data
*sisusb
)
163 int i
, timeout
= 5 * HZ
;
165 wait_event_timeout(sisusb
->wait_q
,
166 ((i
= sisusb_outurb_available(sisusb
)) >= 0), timeout
);
171 static int sisusb_alloc_outbuf(struct sisusb_usb_data
*sisusb
)
175 i
= sisusb_outurb_available(sisusb
);
178 sisusb
->urbstatus
[i
] |= SU_URB_ALLOC
;
183 static void sisusb_free_outbuf(struct sisusb_usb_data
*sisusb
, int index
)
185 if ((index
>= 0) && (index
< sisusb
->numobufs
))
186 sisusb
->urbstatus
[index
] &= ~SU_URB_ALLOC
;
189 /* completion callback */
191 static void sisusb_bulk_completeout(struct urb
*urb
)
193 struct sisusb_urb_context
*context
= urb
->context
;
194 struct sisusb_usb_data
*sisusb
;
199 sisusb
= context
->sisusb
;
201 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
204 #ifndef SISUSB_DONTSYNC
205 if (context
->actual_length
)
206 *(context
->actual_length
) += urb
->actual_length
;
209 sisusb
->urbstatus
[context
->urbindex
] &= ~SU_URB_BUSY
;
210 wake_up(&sisusb
->wait_q
);
213 static int sisusb_bulkout_msg(struct sisusb_usb_data
*sisusb
, int index
,
214 unsigned int pipe
, void *data
, int len
, int *actual_length
,
215 int timeout
, unsigned int tflags
)
217 struct urb
*urb
= sisusb
->sisurbout
[index
];
218 int retval
, byteswritten
= 0;
221 urb
->transfer_flags
= 0;
223 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
224 sisusb_bulk_completeout
,
225 &sisusb
->urbout_context
[index
]);
227 urb
->transfer_flags
|= tflags
;
228 urb
->actual_length
= 0;
231 sisusb
->urbout_context
[index
].actual_length
= (timeout
) ?
232 NULL
: actual_length
;
234 /* Declare this urb/buffer in use */
235 sisusb
->urbstatus
[index
] |= SU_URB_BUSY
;
238 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
240 /* If OK, and if timeout > 0, wait for completion */
241 if ((retval
== 0) && timeout
) {
242 wait_event_timeout(sisusb
->wait_q
,
243 (!(sisusb
->urbstatus
[index
] & SU_URB_BUSY
)),
245 if (sisusb
->urbstatus
[index
] & SU_URB_BUSY
) {
246 /* URB timed out... kill it and report error */
250 /* Otherwise, report urb status */
251 retval
= urb
->status
;
252 byteswritten
= urb
->actual_length
;
257 *actual_length
= byteswritten
;
264 /* completion callback */
266 static void sisusb_bulk_completein(struct urb
*urb
)
268 struct sisusb_usb_data
*sisusb
= urb
->context
;
270 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
273 sisusb
->completein
= 1;
274 wake_up(&sisusb
->wait_q
);
277 static int sisusb_bulkin_msg(struct sisusb_usb_data
*sisusb
,
278 unsigned int pipe
, void *data
, int len
,
279 int *actual_length
, int timeout
, unsigned int tflags
)
281 struct urb
*urb
= sisusb
->sisurbin
;
282 int retval
, readbytes
= 0;
284 urb
->transfer_flags
= 0;
286 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
287 sisusb_bulk_completein
, sisusb
);
289 urb
->transfer_flags
|= tflags
;
290 urb
->actual_length
= 0;
292 sisusb
->completein
= 0;
293 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
295 wait_event_timeout(sisusb
->wait_q
, sisusb
->completein
, timeout
);
296 if (!sisusb
->completein
) {
297 /* URB timed out... kill it and report error */
301 /* URB completed within timeout */
302 retval
= urb
->status
;
303 readbytes
= urb
->actual_length
;
308 *actual_length
= readbytes
;
316 /* Send a bulk message of variable size
318 * To copy the data from userspace, give pointer to "userbuffer",
319 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
320 * both of these are NULL, it is assumed, that the transfer
321 * buffer "sisusb->obuf[index]" is set up with the data to send.
322 * Index is ignored if either kernbuffer or userbuffer is set.
323 * If async is nonzero, URBs will be sent without waiting for
324 * completion of the previous URB.
326 * (return 0 on success)
329 static int sisusb_send_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
330 char *kernbuffer
, const char __user
*userbuffer
, int index
,
331 ssize_t
*bytes_written
, unsigned int tflags
, int async
)
333 int result
= 0, retry
, count
= len
;
334 int passsize
, thispass
, transferred_len
= 0;
335 int fromuser
= (userbuffer
!= NULL
) ? 1 : 0;
336 int fromkern
= (kernbuffer
!= NULL
) ? 1 : 0;
340 (*bytes_written
) = 0;
343 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
346 /* If we copy data from kernel or userspace, force the
347 * allocation of a buffer/urb. If we have the data in
348 * the transfer buffer[index] already, reuse the buffer/URB
349 * if the length is > buffer size. (So, transmitting
350 * large data amounts directly from the transfer buffer
351 * treats the buffer as a ring buffer. However, we need
352 * to sync in this case.)
354 if (fromuser
|| fromkern
)
356 else if (len
> sisusb
->obufsize
)
359 pipe
= usb_sndbulkpipe(sisusb
->sisusb_dev
, ep
);
362 passsize
= thispass
= (sisusb
->obufsize
< count
) ?
363 sisusb
->obufsize
: count
;
366 index
= sisusb_get_free_outbuf(sisusb
);
371 buffer
= sisusb
->obuf
[index
];
375 if (copy_from_user(buffer
, userbuffer
, passsize
))
378 userbuffer
+= passsize
;
380 } else if (fromkern
) {
382 memcpy(buffer
, kernbuffer
, passsize
);
383 kernbuffer
+= passsize
;
390 if (!sisusb
->sisusb_dev
)
393 result
= sisusb_bulkout_msg(sisusb
, index
, pipe
,
394 buffer
, thispass
, &transferred_len
,
395 async
? 0 : 5 * HZ
, tflags
);
397 if (result
== -ETIMEDOUT
) {
399 /* Will not happen if async */
406 if ((result
== 0) && !async
&& transferred_len
) {
408 thispass
-= transferred_len
;
409 buffer
+= transferred_len
;
418 (*bytes_written
) += passsize
;
421 /* Force new allocation in next iteration */
422 if (fromuser
|| fromkern
)
428 #ifdef SISUSB_DONTSYNC
429 (*bytes_written
) = len
;
430 /* Some URBs/buffers might be busy */
432 sisusb_wait_all_out_complete(sisusb
);
433 (*bytes_written
) = transferred_len
;
434 /* All URBs and all buffers are available */
438 return ((*bytes_written
) == len
) ? 0 : -EIO
;
441 /* Receive a bulk message of variable size
443 * To copy the data to userspace, give pointer to "userbuffer",
444 * to copy to kernel memory, give "kernbuffer". One of them
445 * MUST be set. (There is no technique for letting the caller
446 * read directly from the ibuf.)
450 static int sisusb_recv_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
451 void *kernbuffer
, char __user
*userbuffer
, ssize_t
*bytes_read
,
454 int result
= 0, retry
, count
= len
;
455 int bufsize
, thispass
, transferred_len
;
462 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
465 pipe
= usb_rcvbulkpipe(sisusb
->sisusb_dev
, ep
);
466 buffer
= sisusb
->ibuf
;
467 bufsize
= sisusb
->ibufsize
;
471 #ifdef SISUSB_DONTSYNC
472 if (!(sisusb_wait_all_out_complete(sisusb
)))
478 if (!sisusb
->sisusb_dev
)
481 thispass
= (bufsize
< count
) ? bufsize
: count
;
483 result
= sisusb_bulkin_msg(sisusb
, pipe
, buffer
, thispass
,
484 &transferred_len
, 5 * HZ
, tflags
);
487 thispass
= transferred_len
;
489 else if (result
== -ETIMEDOUT
) {
502 (*bytes_read
) += thispass
;
507 if (copy_to_user(userbuffer
, buffer
, thispass
))
510 userbuffer
+= thispass
;
514 memcpy(kernbuffer
, buffer
, thispass
);
515 kernbuffer
+= thispass
;
523 return ((*bytes_read
) == len
) ? 0 : -EIO
;
526 static int sisusb_send_packet(struct sisusb_usb_data
*sisusb
, int len
,
527 struct sisusb_packet
*packet
)
530 ssize_t bytes_transferred
= 0;
536 #ifdef SISUSB_DONTSYNC
537 if (!(sisusb_wait_all_out_complete(sisusb
)))
541 /* Eventually correct endianness */
542 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
544 /* 1. send the packet */
545 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_GFX_OUT
, len
,
546 (char *)packet
, NULL
, 0, &bytes_transferred
, 0, 0);
548 if ((ret
== 0) && (len
== 6)) {
550 /* 2. if packet len == 6, it means we read, so wait for 32bit
551 * return value and write it to packet->data
553 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_GFX_IN
, 4,
554 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
556 packet
->data
= le32_to_cpu(tmp
);
562 static int sisusb_send_bridge_packet(struct sisusb_usb_data
*sisusb
, int len
,
563 struct sisusb_packet
*packet
, unsigned int tflags
)
566 ssize_t bytes_transferred
= 0;
572 #ifdef SISUSB_DONTSYNC
573 if (!(sisusb_wait_all_out_complete(sisusb
)))
577 /* Eventually correct endianness */
578 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
580 /* 1. send the packet */
581 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_OUT
, len
,
582 (char *)packet
, NULL
, 0, &bytes_transferred
, tflags
, 0);
584 if ((ret
== 0) && (len
== 6)) {
586 /* 2. if packet len == 6, it means we read, so wait for 32bit
587 * return value and write it to packet->data
589 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_IN
, 4,
590 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
592 packet
->data
= le32_to_cpu(tmp
);
598 /* access video memory and mmio (return 0 on success) */
602 /* The following routines assume being used to transfer byte, word,
605 * - the write routines expect "data" in machine endianness format.
606 * The data will be converted to leXX in sisusb_xxx_packet.
607 * - the read routines can expect read data in machine-endianess.
610 static int sisusb_write_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
613 struct sisusb_packet packet
;
615 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
616 packet
.address
= addr
& ~3;
617 packet
.data
= data
<< ((addr
& 3) << 3);
618 return sisusb_send_packet(sisusb
, 10, &packet
);
621 static int sisusb_write_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
624 struct sisusb_packet packet
;
627 packet
.address
= addr
& ~3;
631 packet
.header
= (type
<< 6) | 0x0003;
632 packet
.data
= (u32
)data
;
633 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
636 packet
.header
= (type
<< 6) | 0x0006;
637 packet
.data
= (u32
)data
<< 8;
638 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
641 packet
.header
= (type
<< 6) | 0x000c;
642 packet
.data
= (u32
)data
<< 16;
643 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
646 packet
.header
= (type
<< 6) | 0x0008;
647 packet
.data
= (u32
)data
<< 24;
648 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
649 packet
.header
= (type
<< 6) | 0x0001;
650 packet
.address
= (addr
& ~3) + 4;
651 packet
.data
= (u32
)data
>> 8;
652 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
658 static int sisusb_write_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
661 struct sisusb_packet packet
;
664 packet
.address
= addr
& ~3;
668 packet
.header
= (type
<< 6) | 0x0007;
669 packet
.data
= data
& 0x00ffffff;
670 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
673 packet
.header
= (type
<< 6) | 0x000e;
674 packet
.data
= data
<< 8;
675 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
678 packet
.header
= (type
<< 6) | 0x000c;
679 packet
.data
= data
<< 16;
680 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
681 packet
.header
= (type
<< 6) | 0x0001;
682 packet
.address
= (addr
& ~3) + 4;
683 packet
.data
= (data
>> 16) & 0x00ff;
684 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
687 packet
.header
= (type
<< 6) | 0x0008;
688 packet
.data
= data
<< 24;
689 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
690 packet
.header
= (type
<< 6) | 0x0003;
691 packet
.address
= (addr
& ~3) + 4;
692 packet
.data
= (data
>> 8) & 0xffff;
693 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
699 static int sisusb_write_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
702 struct sisusb_packet packet
;
705 packet
.address
= addr
& ~3;
709 packet
.header
= (type
<< 6) | 0x000f;
711 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
714 packet
.header
= (type
<< 6) | 0x000e;
715 packet
.data
= data
<< 8;
716 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
717 packet
.header
= (type
<< 6) | 0x0001;
718 packet
.address
= (addr
& ~3) + 4;
719 packet
.data
= data
>> 24;
720 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
723 packet
.header
= (type
<< 6) | 0x000c;
724 packet
.data
= data
<< 16;
725 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
726 packet
.header
= (type
<< 6) | 0x0003;
727 packet
.address
= (addr
& ~3) + 4;
728 packet
.data
= data
>> 16;
729 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
732 packet
.header
= (type
<< 6) | 0x0008;
733 packet
.data
= data
<< 24;
734 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
735 packet
.header
= (type
<< 6) | 0x0007;
736 packet
.address
= (addr
& ~3) + 4;
737 packet
.data
= data
>> 8;
738 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
744 /* The xxx_bulk routines copy a buffer of variable size. They treat the
745 * buffer as chars, therefore lsb/msb has to be corrected if using the
746 * byte/word/long/etc routines for speed-up
748 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
749 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
750 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
751 * that the data already is in the transfer buffer "sisusb->obuf[index]".
754 static int sisusb_write_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
755 char *kernbuffer
, int length
, const char __user
*userbuffer
,
756 int index
, ssize_t
*bytes_written
)
758 struct sisusb_packet packet
;
761 u8 swap8
, fromkern
= kernbuffer
? 1 : 0;
763 u32 swap32
, flag
= (length
>> 28) & 1;
766 /* if neither kernbuffer not userbuffer are given, assume
769 if (!fromkern
&& !userbuffer
)
770 kernbuffer
= sisusb
->obuf
[index
];
772 (*bytes_written
= 0);
774 length
&= 0x00ffffff;
780 if (get_user(swap8
, (u8 __user
*)userbuffer
))
783 swap8
= kernbuffer
[0];
785 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
795 if (get_user(swap16
, (u16 __user
*)userbuffer
))
798 swap16
= *((u16
*)kernbuffer
);
800 ret
= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
804 (*bytes_written
) += 2;
810 if (copy_from_user(&buf
, userbuffer
, 3))
813 swap32
= (buf
[0] << 16) |
817 swap32
= (buf
[2] << 16) |
823 swap32
= (kernbuffer
[0] << 16) |
824 (kernbuffer
[1] << 8) |
827 swap32
= (kernbuffer
[2] << 16) |
828 (kernbuffer
[1] << 8) |
832 ret
= sisusb_write_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
836 (*bytes_written
) += 3;
842 if (get_user(swap32
, (u32 __user
*)userbuffer
))
845 swap32
= *((u32
*)kernbuffer
);
847 ret
= sisusb_write_memio_long(sisusb
, SISUSB_TYPE_MEM
,
850 (*bytes_written
) += 4;
855 if ((length
& ~3) > 0x10000) {
857 packet
.header
= 0x001f;
858 packet
.address
= 0x000001d4;
860 ret
= sisusb_send_bridge_packet(sisusb
, 10,
862 packet
.header
= 0x001f;
863 packet
.address
= 0x000001d0;
864 packet
.data
= (length
& ~3);
865 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
867 packet
.header
= 0x001f;
868 packet
.address
= 0x000001c0;
869 packet
.data
= flag
| 0x16;
870 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
873 ret
|= sisusb_send_bulk_msg(sisusb
,
874 SISUSB_EP_GFX_LBULK_OUT
,
877 bytes_written
, 0, 1);
878 userbuffer
+= (*bytes_written
);
879 } else if (fromkern
) {
880 ret
|= sisusb_send_bulk_msg(sisusb
,
881 SISUSB_EP_GFX_LBULK_OUT
,
884 bytes_written
, 0, 1);
885 kernbuffer
+= (*bytes_written
);
887 ret
|= sisusb_send_bulk_msg(sisusb
,
888 SISUSB_EP_GFX_LBULK_OUT
,
891 bytes_written
, 0, 1);
892 kernbuffer
+= ((*bytes_written
) &
893 (sisusb
->obufsize
-1));
898 packet
.header
= 0x001f;
899 packet
.address
= 0x00000194;
901 ret
= sisusb_send_bridge_packet(sisusb
, 10,
903 packet
.header
= 0x001f;
904 packet
.address
= 0x00000190;
905 packet
.data
= (length
& ~3);
906 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
908 if (sisusb
->flagb0
!= 0x16) {
909 packet
.header
= 0x001f;
910 packet
.address
= 0x00000180;
911 packet
.data
= flag
| 0x16;
912 ret
|= sisusb_send_bridge_packet(sisusb
,
914 sisusb
->flagb0
= 0x16;
917 ret
|= sisusb_send_bulk_msg(sisusb
,
918 SISUSB_EP_GFX_BULK_OUT
,
921 bytes_written
, 0, 1);
922 userbuffer
+= (*bytes_written
);
923 } else if (fromkern
) {
924 ret
|= sisusb_send_bulk_msg(sisusb
,
925 SISUSB_EP_GFX_BULK_OUT
,
928 bytes_written
, 0, 1);
929 kernbuffer
+= (*bytes_written
);
931 ret
|= sisusb_send_bulk_msg(sisusb
,
932 SISUSB_EP_GFX_BULK_OUT
,
935 bytes_written
, 0, 1);
936 kernbuffer
+= ((*bytes_written
) &
937 (sisusb
->obufsize
-1));
943 dev_err(&sisusb
->sisusb_dev
->dev
,
944 "Wrote %zd of %d bytes, error %d\n",
945 *bytes_written
, length
,
947 else if (msgcount
== 500)
948 dev_err(&sisusb
->sisusb_dev
->dev
,
949 "Too many errors, logging stopped\n");
951 addr
+= (*bytes_written
);
952 length
-= (*bytes_written
);
960 return ret
? -EIO
: 0;
963 /* Remember: Read data in packet is in machine-endianess! So for
964 * byte, word, 24bit, long no endian correction is necessary.
967 static int sisusb_read_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
970 struct sisusb_packet packet
;
973 CLEARPACKET(&packet
);
974 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
975 packet
.address
= addr
& ~3;
976 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
977 *data
= (u8
)(packet
.data
>> ((addr
& 3) << 3));
981 static int sisusb_read_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
984 struct sisusb_packet packet
;
987 CLEARPACKET(&packet
);
989 packet
.address
= addr
& ~3;
993 packet
.header
= (type
<< 6) | 0x0003;
994 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
995 *data
= (u16
)(packet
.data
);
998 packet
.header
= (type
<< 6) | 0x0006;
999 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1000 *data
= (u16
)(packet
.data
>> 8);
1003 packet
.header
= (type
<< 6) | 0x000c;
1004 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1005 *data
= (u16
)(packet
.data
>> 16);
1008 packet
.header
= (type
<< 6) | 0x0008;
1009 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1010 *data
= (u16
)(packet
.data
>> 24);
1011 packet
.header
= (type
<< 6) | 0x0001;
1012 packet
.address
= (addr
& ~3) + 4;
1013 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1014 *data
|= (u16
)(packet
.data
<< 8);
1020 static int sisusb_read_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
1021 u32 addr
, u32
*data
)
1023 struct sisusb_packet packet
;
1026 packet
.address
= addr
& ~3;
1030 packet
.header
= (type
<< 6) | 0x0007;
1031 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1032 *data
= packet
.data
& 0x00ffffff;
1035 packet
.header
= (type
<< 6) | 0x000e;
1036 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1037 *data
= packet
.data
>> 8;
1040 packet
.header
= (type
<< 6) | 0x000c;
1041 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1042 *data
= packet
.data
>> 16;
1043 packet
.header
= (type
<< 6) | 0x0001;
1044 packet
.address
= (addr
& ~3) + 4;
1045 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1046 *data
|= ((packet
.data
& 0xff) << 16);
1049 packet
.header
= (type
<< 6) | 0x0008;
1050 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1051 *data
= packet
.data
>> 24;
1052 packet
.header
= (type
<< 6) | 0x0003;
1053 packet
.address
= (addr
& ~3) + 4;
1054 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1055 *data
|= ((packet
.data
& 0xffff) << 8);
1061 static int sisusb_read_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
1062 u32 addr
, u32
*data
)
1064 struct sisusb_packet packet
;
1067 packet
.address
= addr
& ~3;
1071 packet
.header
= (type
<< 6) | 0x000f;
1072 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1073 *data
= packet
.data
;
1076 packet
.header
= (type
<< 6) | 0x000e;
1077 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1078 *data
= packet
.data
>> 8;
1079 packet
.header
= (type
<< 6) | 0x0001;
1080 packet
.address
= (addr
& ~3) + 4;
1081 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1082 *data
|= (packet
.data
<< 24);
1085 packet
.header
= (type
<< 6) | 0x000c;
1086 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1087 *data
= packet
.data
>> 16;
1088 packet
.header
= (type
<< 6) | 0x0003;
1089 packet
.address
= (addr
& ~3) + 4;
1090 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1091 *data
|= (packet
.data
<< 16);
1094 packet
.header
= (type
<< 6) | 0x0008;
1095 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1096 *data
= packet
.data
>> 24;
1097 packet
.header
= (type
<< 6) | 0x0007;
1098 packet
.address
= (addr
& ~3) + 4;
1099 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1100 *data
|= (packet
.data
<< 8);
1106 static int sisusb_read_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
1107 char *kernbuffer
, int length
, char __user
*userbuffer
,
1108 ssize_t
*bytes_read
)
1117 length
&= 0x00ffffff;
1122 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
1127 if (put_user(buf
[0], (u8 __user
*)userbuffer
))
1130 kernbuffer
[0] = buf
[0];
1135 ret
|= sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1140 if (put_user(swap16
, (u16 __user
*)userbuffer
))
1143 *((u16
*)kernbuffer
) = swap16
;
1149 ret
|= sisusb_read_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
1154 buf
[0] = (swap32
>> 16) & 0xff;
1155 buf
[1] = (swap32
>> 8) & 0xff;
1156 buf
[2] = swap32
& 0xff;
1158 buf
[2] = (swap32
>> 16) & 0xff;
1159 buf
[1] = (swap32
>> 8) & 0xff;
1160 buf
[0] = swap32
& 0xff;
1163 if (copy_to_user(userbuffer
,
1167 kernbuffer
[0] = buf
[0];
1168 kernbuffer
[1] = buf
[1];
1169 kernbuffer
[2] = buf
[2];
1175 ret
|= sisusb_read_memio_long(sisusb
, SISUSB_TYPE_MEM
,
1180 if (put_user(swap32
, (u32 __user
*)userbuffer
))
1185 *((u32
*)kernbuffer
) = swap32
;
1199 /* High level: Gfx (indexed) register access */
1201 #ifdef CONFIG_USB_SISUSBVGA_CON
1202 int sisusb_setreg(struct sisusb_usb_data
*sisusb
, u32 port
, u8 data
)
1204 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1207 int sisusb_getreg(struct sisusb_usb_data
*sisusb
, u32 port
, u8
*data
)
1209 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1213 int sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, u32 port
,
1218 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1219 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1223 int sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, u32 port
,
1228 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1229 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1233 int sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, u32 port
, u8 idx
,
1239 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1240 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1243 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1247 static int sisusb_setidxregmask(struct sisusb_usb_data
*sisusb
,
1248 u32 port
, u8 idx
, u8 data
, u8 mask
)
1253 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1254 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1256 tmp
|= (data
& mask
);
1257 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1261 int sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, u32 port
,
1264 return sisusb_setidxregandor(sisusb
, port
, index
, 0xff, myor
);
1267 int sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, u32 port
,
1270 return sisusb_setidxregandor(sisusb
, port
, idx
, myand
, 0x00);
1273 /* Write/read video ram */
1275 #ifdef CONFIG_USB_SISUSBVGA_CON
1276 int sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
)
1278 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
);
1281 int sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
)
1283 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
);
1286 int sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, u8
*src
,
1287 u32 dest
, int length
)
1291 return sisusb_write_mem_bulk(sisusb
, dest
, src
, length
,
1295 #ifdef SISUSBENDIANTEST
1296 static int sisusb_read_memory(struct sisusb_usb_data
*sisusb
, char *dest
,
1297 u32 src
, int length
)
1301 return sisusb_read_mem_bulk(sisusb
, src
, dest
, length
,
1307 #ifdef SISUSBENDIANTEST
1308 static void sisusb_testreadwrite(struct sisusb_usb_data
*sisusb
)
1310 static u8 srcbuffer
[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1311 char destbuffer
[10];
1314 sisusb_copy_memory(sisusb
, srcbuffer
, sisusb
->vrambase
, 7);
1316 for (i
= 1; i
<= 7; i
++) {
1317 dev_dbg(&sisusb
->sisusb_dev
->dev
,
1318 "sisusb: rwtest %d bytes\n", i
);
1319 sisusb_read_memory(sisusb
, destbuffer
, sisusb
->vrambase
, i
);
1320 for (j
= 0; j
< i
; j
++) {
1321 dev_dbg(&sisusb
->sisusb_dev
->dev
,
1322 "rwtest read[%d] = %x\n",
1329 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1331 static int sisusb_write_pci_config(struct sisusb_usb_data
*sisusb
,
1332 int regnum
, u32 data
)
1334 struct sisusb_packet packet
;
1336 packet
.header
= 0x008f;
1337 packet
.address
= regnum
| 0x10000;
1339 return sisusb_send_packet(sisusb
, 10, &packet
);
1342 static int sisusb_read_pci_config(struct sisusb_usb_data
*sisusb
,
1343 int regnum
, u32
*data
)
1345 struct sisusb_packet packet
;
1348 packet
.header
= 0x008f;
1349 packet
.address
= (u32
)regnum
| 0x10000;
1350 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1351 *data
= packet
.data
;
1355 /* Clear video RAM */
1357 static int sisusb_clear_vram(struct sisusb_usb_data
*sisusb
,
1358 u32 address
, int length
)
1363 if (address
< sisusb
->vrambase
)
1366 if (address
>= sisusb
->vrambase
+ sisusb
->vramsize
)
1369 if (address
+ length
> sisusb
->vrambase
+ sisusb
->vramsize
)
1370 length
= sisusb
->vrambase
+ sisusb
->vramsize
- address
;
1375 /* allocate free buffer/urb and clear the buffer */
1376 i
= sisusb_alloc_outbuf(sisusb
);
1380 memset(sisusb
->obuf
[i
], 0, sisusb
->obufsize
);
1382 /* We can write a length > buffer size here. The buffer
1383 * data will simply be re-used (like a ring-buffer).
1385 ret
= sisusb_write_mem_bulk(sisusb
, address
, NULL
, length
, NULL
, i
, &j
);
1387 /* Free the buffer/urb */
1388 sisusb_free_outbuf(sisusb
, i
);
1393 /* Initialize the graphics core (return 0 on success)
1394 * This resets the graphics hardware and puts it into
1395 * a defined mode (640x480@60Hz)
1398 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1399 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1400 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1401 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1402 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1403 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1404 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1405 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1406 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1408 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1410 static int sisusb_triggersr16(struct sisusb_usb_data
*sisusb
, u8 ramtype
)
1415 ret
= GETIREG(SISSR
, 0x16, &tmp8
);
1418 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1420 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1423 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1425 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1427 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1429 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1431 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1433 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1435 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1440 static int sisusb_getbuswidth(struct sisusb_usb_data
*sisusb
,
1444 u8 ramtype
, done
= 0;
1446 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1448 ret
= GETIREG(SISSR
, 0x3a, &ramtype
);
1451 ret
|= SETIREG(SISSR
, 0x13, 0x00);
1454 ret
|= SETIREG(SISSR
, 0x14, 0x12);
1455 ret
|= SETIREGAND(SISSR
, 0x15, 0xef);
1457 ret
|= SETIREG(SISSR
, 0x14, 0x02);
1460 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1461 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1462 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1463 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1464 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1465 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1466 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1467 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1468 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1469 ret
|= READL(ramptr
+ 0, &t0
);
1470 ret
|= READL(ramptr
+ 4, &t1
);
1471 ret
|= READL(ramptr
+ 8, &t2
);
1472 ret
|= READL(ramptr
+ 12, &t3
);
1476 *chab
= 0; *bw
= 64;
1478 if ((t3
!= 0xcdef0123) || (t2
!= 0x89abcdef)) {
1479 if ((t1
== 0x456789ab) && (t0
== 0x01234567)) {
1480 *chab
= 0; *bw
= 64;
1481 ret
|= SETIREGAND(SISSR
, 0x14, 0xfd);
1484 if ((t1
!= 0x456789ab) || (t0
!= 0x01234567)) {
1485 *chab
= 1; *bw
= 64;
1486 ret
|= SETIREGANDOR(SISSR
, 0x14, 0xfc, 0x01);
1488 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1489 ret
|= WRITEL(ramptr
+ 0, 0x89abcdef);
1490 ret
|= WRITEL(ramptr
+ 4, 0xcdef0123);
1491 ret
|= WRITEL(ramptr
+ 8, 0x55555555);
1492 ret
|= WRITEL(ramptr
+ 12, 0x55555555);
1493 ret
|= WRITEL(ramptr
+ 16, 0xaaaaaaaa);
1494 ret
|= WRITEL(ramptr
+ 20, 0xaaaaaaaa);
1495 ret
|= READL(ramptr
+ 4, &t1
);
1497 if (t1
!= 0xcdef0123) {
1499 ret
|= SETIREGOR(SISSR
, 0x15, 0x10);
1505 *chab
= 0; *bw
= 64; /* default: cha, bw = 64 */
1509 if (t1
== 0x456789ab) {
1510 if (t0
== 0x01234567) {
1511 *chab
= 0; *bw
= 64;
1515 if (t0
== 0x01234567) {
1516 *chab
= 0; *bw
= 32;
1517 ret
|= SETIREG(SISSR
, 0x14, 0x00);
1523 ret
|= SETIREG(SISSR
, 0x14, 0x03);
1524 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1526 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1527 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1528 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1529 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1530 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1531 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1532 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1533 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1534 ret
|= READL(ramptr
+ 0, &t0
);
1535 ret
|= READL(ramptr
+ 4, &t1
);
1537 if (t1
== 0x456789ab) {
1538 if (t0
== 0x01234567) {
1539 *chab
= 1; *bw
= 64;
1543 if (t0
== 0x01234567) {
1544 *chab
= 1; *bw
= 32;
1545 ret
|= SETIREG(SISSR
, 0x14, 0x01);
1553 static int sisusb_verify_mclk(struct sisusb_usb_data
*sisusb
)
1556 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1557 u8 tmp1
, tmp2
, i
, j
;
1559 ret
|= WRITEB(ramptr
, 0xaa);
1560 ret
|= WRITEB(ramptr
+ 16, 0x55);
1561 ret
|= READB(ramptr
, &tmp1
);
1562 ret
|= READB(ramptr
+ 16, &tmp2
);
1563 if ((tmp1
!= 0xaa) || (tmp2
!= 0x55)) {
1564 for (i
= 0, j
= 16; i
< 2; i
++, j
+= 16) {
1565 ret
|= GETIREG(SISSR
, 0x21, &tmp1
);
1566 ret
|= SETIREGAND(SISSR
, 0x21, (tmp1
& 0xfb));
1567 ret
|= SETIREGOR(SISSR
, 0x3c, 0x01); /* not on 330 */
1568 ret
|= SETIREGAND(SISSR
, 0x3c, 0xfe); /* not on 330 */
1569 ret
|= SETIREG(SISSR
, 0x21, tmp1
);
1570 ret
|= WRITEB(ramptr
+ 16 + j
, j
);
1571 ret
|= READB(ramptr
+ 16 + j
, &tmp1
);
1573 ret
|= WRITEB(ramptr
+ j
, j
);
1581 static int sisusb_set_rank(struct sisusb_usb_data
*sisusb
, int *iret
,
1582 int index
, u8 rankno
, u8 chab
, const u8 dramtype
[][5], int bw
)
1584 int ret
= 0, ranksize
;
1589 if ((rankno
== 2) && (dramtype
[index
][0] == 2))
1592 ranksize
= dramtype
[index
][3] / 2 * bw
/ 32;
1594 if ((ranksize
* rankno
) > 128)
1598 while ((ranksize
>>= 1) > 0)
1601 tmp
|= ((rankno
- 1) << 2);
1602 tmp
|= ((bw
/ 64) & 0x02);
1603 tmp
|= (chab
& 0x01);
1605 ret
= SETIREG(SISSR
, 0x14, tmp
);
1606 ret
|= sisusb_triggersr16(sisusb
, 0); /* sic! */
1613 static int sisusb_check_rbc(struct sisusb_usb_data
*sisusb
, int *iret
,
1621 for (i
= 0, j
= 0; i
< testn
; i
++) {
1622 ret
|= WRITEL(sisusb
->vrambase
+ j
, j
);
1626 for (i
= 0, j
= 0; i
< testn
; i
++) {
1627 ret
|= READL(sisusb
->vrambase
+ j
, &tmp
);
1638 static int sisusb_check_ranks(struct sisusb_usb_data
*sisusb
,
1639 int *iret
, int rankno
, int idx
, int bw
, const u8 rtype
[][5])
1641 int ret
= 0, i
, i2ret
;
1646 for (i
= rankno
; i
>= 1; i
--) {
1647 inc
= 1 << (rtype
[idx
][2] + rtype
[idx
][1] + rtype
[idx
][0] +
1649 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1654 inc
= 1 << (rtype
[idx
][2] + bw
/ 64 + 2);
1655 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 4);
1659 inc
= 1 << (10 + bw
/ 64);
1660 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1668 static int sisusb_get_sdram_size(struct sisusb_usb_data
*sisusb
, int *iret
,
1671 int ret
= 0, i2ret
= 0, i
, j
;
1672 static const u8 sdramtype
[13][5] = {
1673 { 2, 12, 9, 64, 0x35 },
1674 { 1, 13, 9, 64, 0x44 },
1675 { 2, 12, 8, 32, 0x31 },
1676 { 2, 11, 9, 32, 0x25 },
1677 { 1, 12, 9, 32, 0x34 },
1678 { 1, 13, 8, 32, 0x40 },
1679 { 2, 11, 8, 16, 0x21 },
1680 { 1, 12, 8, 16, 0x30 },
1681 { 1, 11, 9, 16, 0x24 },
1682 { 1, 11, 8, 8, 0x20 },
1683 { 2, 9, 8, 4, 0x01 },
1684 { 1, 10, 8, 4, 0x10 },
1685 { 1, 9, 8, 2, 0x00 }
1688 *iret
= 1; /* error */
1690 for (i
= 0; i
< 13; i
++) {
1691 ret
|= SETIREGANDOR(SISSR
, 0x13, 0x80, sdramtype
[i
][4]);
1692 for (j
= 2; j
> 0; j
--) {
1693 ret
|= sisusb_set_rank(sisusb
, &i2ret
, i
, j
, chab
,
1698 ret
|= sisusb_check_ranks(sisusb
, &i2ret
, j
, i
, bw
,
1701 *iret
= 0; /* ram size found */
1710 static int sisusb_setup_screen(struct sisusb_usb_data
*sisusb
,
1711 int clrall
, int drwfr
)
1715 int i
, length
, modex
, modey
, bpp
;
1717 modex
= 640; modey
= 480; bpp
= 2;
1719 address
= sisusb
->vrambase
; /* Clear video ram */
1722 length
= sisusb
->vramsize
;
1724 length
= modex
* bpp
* modey
;
1726 ret
= sisusb_clear_vram(sisusb
, address
, length
);
1728 if (!ret
&& drwfr
) {
1729 for (i
= 0; i
< modex
; i
++) {
1730 address
= sisusb
->vrambase
+ (i
* bpp
);
1731 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1733 address
+= (modex
* (modey
-1) * bpp
);
1734 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1737 for (i
= 0; i
< modey
; i
++) {
1738 address
= sisusb
->vrambase
+ ((i
* modex
) * bpp
);
1739 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1741 address
+= ((modex
- 1) * bpp
);
1742 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1750 static void sisusb_set_default_mode(struct sisusb_usb_data
*sisusb
,
1753 int i
, j
, modex
, bpp
, du
;
1754 u8 sr31
, cr63
, tmp8
;
1755 static const char attrdata
[] = {
1756 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1757 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1758 0x01, 0x00, 0x00, 0x00
1760 static const char crtcrdata
[] = {
1761 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1762 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1763 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1766 static const char grcdata
[] = {
1767 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1770 static const char crtcdata
[] = {
1771 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1772 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1776 modex
= 640; bpp
= 2;
1778 GETIREG(SISSR
, 0x31, &sr31
);
1779 GETIREG(SISCR
, 0x63, &cr63
);
1780 SETIREGOR(SISSR
, 0x01, 0x20);
1781 SETIREG(SISCR
, 0x63, cr63
& 0xbf);
1782 SETIREGOR(SISCR
, 0x17, 0x80);
1783 SETIREGOR(SISSR
, 0x1f, 0x04);
1784 SETIREGAND(SISSR
, 0x07, 0xfb);
1785 SETIREG(SISSR
, 0x00, 0x03); /* seq */
1786 SETIREG(SISSR
, 0x01, 0x21);
1787 SETIREG(SISSR
, 0x02, 0x0f);
1788 SETIREG(SISSR
, 0x03, 0x00);
1789 SETIREG(SISSR
, 0x04, 0x0e);
1790 SETREG(SISMISCW
, 0x23); /* misc */
1791 for (i
= 0; i
<= 0x18; i
++) { /* crtc */
1792 SETIREG(SISCR
, i
, crtcrdata
[i
]);
1794 for (i
= 0; i
<= 0x13; i
++) { /* att */
1795 GETREG(SISINPSTAT
, &tmp8
);
1797 SETREG(SISAR
, attrdata
[i
]);
1799 GETREG(SISINPSTAT
, &tmp8
);
1800 SETREG(SISAR
, 0x14);
1801 SETREG(SISAR
, 0x00);
1802 GETREG(SISINPSTAT
, &tmp8
);
1803 SETREG(SISAR
, 0x20);
1804 GETREG(SISINPSTAT
, &tmp8
);
1805 for (i
= 0; i
<= 0x08; i
++) { /* grc */
1806 SETIREG(SISGR
, i
, grcdata
[i
]);
1808 SETIREGAND(SISGR
, 0x05, 0xbf);
1809 for (i
= 0x0A; i
<= 0x0E; i
++) { /* clr ext */
1810 SETIREG(SISSR
, i
, 0x00);
1812 SETIREGAND(SISSR
, 0x37, 0xfe);
1813 SETREG(SISMISCW
, 0xef); /* sync */
1814 SETIREG(SISCR
, 0x11, 0x00); /* crtc */
1815 for (j
= 0x00, i
= 0; i
<= 7; i
++, j
++)
1816 SETIREG(SISCR
, j
, crtcdata
[i
]);
1818 for (j
= 0x10; i
<= 10; i
++, j
++)
1819 SETIREG(SISCR
, j
, crtcdata
[i
]);
1821 for (j
= 0x15; i
<= 12; i
++, j
++)
1822 SETIREG(SISCR
, j
, crtcdata
[i
]);
1824 for (j
= 0x0A; i
<= 15; i
++, j
++)
1825 SETIREG(SISSR
, j
, crtcdata
[i
]);
1827 SETIREG(SISSR
, 0x0E, (crtcdata
[16] & 0xE0));
1828 SETIREGANDOR(SISCR
, 0x09, 0x5f, ((crtcdata
[16] & 0x01) << 5));
1829 SETIREG(SISCR
, 0x14, 0x4f);
1830 du
= (modex
/ 16) * (bpp
* 2); /* offset/pitch */
1831 SETIREGANDOR(SISSR
, 0x0e, 0xf0, ((du
>> 8) & 0x0f));
1832 SETIREG(SISCR
, 0x13, (du
& 0xff));
1835 SETIREG(SISSR
, 0x10, tmp8
);
1836 SETIREG(SISSR
, 0x31, 0x00); /* VCLK */
1837 SETIREG(SISSR
, 0x2b, 0x1b);
1838 SETIREG(SISSR
, 0x2c, 0xe1);
1839 SETIREG(SISSR
, 0x2d, 0x01);
1840 SETIREGAND(SISSR
, 0x3d, 0xfe); /* FIFO */
1841 SETIREG(SISSR
, 0x08, 0xae);
1842 SETIREGAND(SISSR
, 0x09, 0xf0);
1843 SETIREG(SISSR
, 0x08, 0x34);
1844 SETIREGOR(SISSR
, 0x3d, 0x01);
1845 SETIREGAND(SISSR
, 0x1f, 0x3f); /* mode regs */
1846 SETIREGANDOR(SISSR
, 0x06, 0xc0, 0x0a);
1847 SETIREG(SISCR
, 0x19, 0x00);
1848 SETIREGAND(SISCR
, 0x1a, 0xfc);
1849 SETIREGAND(SISSR
, 0x0f, 0xb7);
1850 SETIREGAND(SISSR
, 0x31, 0xfb);
1851 SETIREGANDOR(SISSR
, 0x21, 0x1f, 0xa0);
1852 SETIREGAND(SISSR
, 0x32, 0xf3);
1853 SETIREGANDOR(SISSR
, 0x07, 0xf8, 0x03);
1854 SETIREG(SISCR
, 0x52, 0x6c);
1856 SETIREG(SISCR
, 0x0d, 0x00); /* adjust frame */
1857 SETIREG(SISCR
, 0x0c, 0x00);
1858 SETIREG(SISSR
, 0x0d, 0x00);
1859 SETIREGAND(SISSR
, 0x37, 0xfe);
1861 SETIREG(SISCR
, 0x32, 0x20);
1862 SETIREGAND(SISSR
, 0x01, 0xdf); /* enable display */
1863 SETIREG(SISCR
, 0x63, (cr63
& 0xbf));
1864 SETIREG(SISSR
, 0x31, (sr31
& 0xfb));
1867 SETIREG(SISSR
, 0x20, 0xa1); /* enable engines */
1868 SETIREGOR(SISSR
, 0x1e, 0x5a);
1870 SETIREG(SISSR
, 0x26, 0x01); /* disable cmdqueue */
1871 SETIREG(SISSR
, 0x27, 0x1f);
1872 SETIREG(SISSR
, 0x26, 0x00);
1875 SETIREG(SISCR
, 0x34, 0x44); /* we just set std mode #44 */
1878 static int sisusb_init_gfxcore(struct sisusb_usb_data
*sisusb
)
1880 int ret
= 0, i
, j
, bw
, chab
, iret
, retry
= 3;
1883 static const char mclktable
[] = {
1884 0x3b, 0x22, 0x01, 143,
1885 0x3b, 0x22, 0x01, 143,
1886 0x3b, 0x22, 0x01, 143,
1887 0x3b, 0x22, 0x01, 143
1889 static const char eclktable
[] = {
1890 0x3b, 0x22, 0x01, 143,
1891 0x3b, 0x22, 0x01, 143,
1892 0x3b, 0x22, 0x01, 143,
1893 0x3b, 0x22, 0x01, 143
1895 static const char ramtypetable1
[] = {
1896 0x00, 0x04, 0x60, 0x60,
1897 0x0f, 0x0f, 0x1f, 0x1f,
1898 0xba, 0xba, 0xba, 0xba,
1899 0xa9, 0xa9, 0xac, 0xac,
1900 0xa0, 0xa0, 0xa0, 0xa8,
1901 0x00, 0x00, 0x02, 0x02,
1902 0x30, 0x30, 0x40, 0x40
1904 static const char ramtypetable2
[] = {
1905 0x77, 0x77, 0x44, 0x44,
1906 0x77, 0x77, 0x44, 0x44,
1907 0x00, 0x00, 0x00, 0x00,
1908 0x5b, 0x5b, 0xab, 0xab,
1909 0x00, 0x00, 0xf0, 0xf8
1915 ret
= GETREG(SISVGAEN
, &tmp8
);
1916 ret
|= SETREG(SISVGAEN
, (tmp8
| 0x01));
1918 /* Enable GPU access to VRAM */
1919 ret
|= GETREG(SISMISCR
, &tmp8
);
1920 ret
|= SETREG(SISMISCW
, (tmp8
| 0x01));
1925 /* Reset registers */
1926 ret
|= SETIREGAND(SISCR
, 0x5b, 0xdf);
1927 ret
|= SETIREG(SISSR
, 0x05, 0x86);
1928 ret
|= SETIREGOR(SISSR
, 0x20, 0x01);
1930 ret
|= SETREG(SISMISCW
, 0x67);
1932 for (i
= 0x06; i
<= 0x1f; i
++)
1933 ret
|= SETIREG(SISSR
, i
, 0x00);
1935 for (i
= 0x21; i
<= 0x27; i
++)
1936 ret
|= SETIREG(SISSR
, i
, 0x00);
1938 for (i
= 0x31; i
<= 0x3d; i
++)
1939 ret
|= SETIREG(SISSR
, i
, 0x00);
1941 for (i
= 0x12; i
<= 0x1b; i
++)
1942 ret
|= SETIREG(SISSR
, i
, 0x00);
1944 for (i
= 0x79; i
<= 0x7c; i
++)
1945 ret
|= SETIREG(SISCR
, i
, 0x00);
1950 ret
|= SETIREG(SISCR
, 0x63, 0x80);
1952 ret
|= GETIREG(SISSR
, 0x3a, &ramtype
);
1955 ret
|= SETIREG(SISSR
, 0x28, mclktable
[ramtype
* 4]);
1956 ret
|= SETIREG(SISSR
, 0x29, mclktable
[(ramtype
* 4) + 1]);
1957 ret
|= SETIREG(SISSR
, 0x2a, mclktable
[(ramtype
* 4) + 2]);
1959 ret
|= SETIREG(SISSR
, 0x2e, eclktable
[ramtype
* 4]);
1960 ret
|= SETIREG(SISSR
, 0x2f, eclktable
[(ramtype
* 4) + 1]);
1961 ret
|= SETIREG(SISSR
, 0x30, eclktable
[(ramtype
* 4) + 2]);
1963 ret
|= SETIREG(SISSR
, 0x07, 0x18);
1964 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
1969 for (i
= 0x15, j
= 0; i
<= 0x1b; i
++, j
++) {
1970 ret
|= SETIREG(SISSR
, i
,
1971 ramtypetable1
[(j
*4) + ramtype
]);
1973 for (i
= 0x40, j
= 0; i
<= 0x44; i
++, j
++) {
1974 ret
|= SETIREG(SISCR
, i
,
1975 ramtypetable2
[(j
*4) + ramtype
]);
1978 ret
|= SETIREG(SISCR
, 0x49, 0xaa);
1980 ret
|= SETIREG(SISSR
, 0x1f, 0x00);
1981 ret
|= SETIREG(SISSR
, 0x20, 0xa0);
1982 ret
|= SETIREG(SISSR
, 0x23, 0xf6);
1983 ret
|= SETIREG(SISSR
, 0x24, 0x0d);
1984 ret
|= SETIREG(SISSR
, 0x25, 0x33);
1986 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
1988 ret
|= SETIREGOR(SISPART1
, 0x2f, 0x01);
1990 ret
|= SETIREGAND(SISCAP
, 0x3f, 0xef);
1995 ret
|= SETIREG(SISPART1
, 0x00, 0x00);
1997 ret
|= GETIREG(SISSR
, 0x13, &tmp8
);
2000 ret
|= SETIREG(SISPART1
, 0x02, 0x00);
2001 ret
|= SETIREG(SISPART1
, 0x2e, 0x08);
2003 ret
|= sisusb_read_pci_config(sisusb
, 0x50, &tmp32
);
2004 tmp32
&= 0x00f00000;
2005 tmp8
= (tmp32
== 0x100000) ? 0x33 : 0x03;
2006 ret
|= SETIREG(SISSR
, 0x25, tmp8
);
2007 tmp8
= (tmp32
== 0x100000) ? 0xaa : 0x88;
2008 ret
|= SETIREG(SISCR
, 0x49, tmp8
);
2010 ret
|= SETIREG(SISSR
, 0x27, 0x1f);
2011 ret
|= SETIREG(SISSR
, 0x31, 0x00);
2012 ret
|= SETIREG(SISSR
, 0x32, 0x11);
2013 ret
|= SETIREG(SISSR
, 0x33, 0x00);
2018 ret
|= SETIREG(SISCR
, 0x83, 0x00);
2020 sisusb_set_default_mode(sisusb
, 0);
2022 ret
|= SETIREGAND(SISSR
, 0x21, 0xdf);
2023 ret
|= SETIREGOR(SISSR
, 0x01, 0x20);
2024 ret
|= SETIREGOR(SISSR
, 0x16, 0x0f);
2026 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
2028 /* Disable refresh */
2029 ret
|= SETIREGAND(SISSR
, 0x17, 0xf8);
2030 ret
|= SETIREGOR(SISSR
, 0x19, 0x03);
2032 ret
|= sisusb_getbuswidth(sisusb
, &bw
, &chab
);
2033 ret
|= sisusb_verify_mclk(sisusb
);
2036 ret
|= sisusb_get_sdram_size(sisusb
, &iret
, bw
, chab
);
2038 dev_err(&sisusb
->sisusb_dev
->dev
,
2039 "RAM size detection failed, assuming 8MB video RAM\n");
2040 ret
|= SETIREG(SISSR
, 0x14, 0x31);
2044 dev_err(&sisusb
->sisusb_dev
->dev
,
2045 "DDR RAM device found, assuming 8MB video RAM\n");
2046 ret
|= SETIREG(SISSR
, 0x14, 0x31);
2050 /* Enable refresh */
2051 ret
|= SETIREG(SISSR
, 0x16, ramtypetable1
[4 + ramtype
]);
2052 ret
|= SETIREG(SISSR
, 0x17, ramtypetable1
[8 + ramtype
]);
2053 ret
|= SETIREG(SISSR
, 0x19, ramtypetable1
[16 + ramtype
]);
2055 ret
|= SETIREGOR(SISSR
, 0x21, 0x20);
2057 ret
|= SETIREG(SISSR
, 0x22, 0xfb);
2058 ret
|= SETIREG(SISSR
, 0x21, 0xa5);
2077 static void sisusb_get_ramconfig(struct sisusb_usb_data
*sisusb
)
2079 u8 tmp8
, tmp82
, ramtype
;
2081 char *ramtypetext1
= NULL
;
2082 static const char ram_datarate
[4] = {'S', 'S', 'D', 'D'};
2083 static const char ram_dynamictype
[4] = {'D', 'G', 'D', 'G'};
2084 static const int busSDR
[4] = {64, 64, 128, 128};
2085 static const int busDDR
[4] = {32, 32, 64, 64};
2086 static const int busDDRA
[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2088 sisusb_getidxreg(sisusb
, SISSR
, 0x14, &tmp8
);
2089 sisusb_getidxreg(sisusb
, SISSR
, 0x15, &tmp82
);
2090 sisusb_getidxreg(sisusb
, SISSR
, 0x3a, &ramtype
);
2091 sisusb
->vramsize
= (1 << ((tmp8
& 0xf0) >> 4)) * 1024 * 1024;
2093 switch ((tmp8
>> 2) & 0x03) {
2095 ramtypetext1
= "1 ch/1 r";
2099 bw
= busSDR
[(tmp8
& 0x03)];
2103 ramtypetext1
= "1 ch/2 r";
2104 sisusb
->vramsize
<<= 1;
2105 bw
= busSDR
[(tmp8
& 0x03)];
2108 ramtypetext1
= "asymmetric";
2109 sisusb
->vramsize
+= sisusb
->vramsize
/2;
2110 bw
= busDDRA
[(tmp8
& 0x03)];
2113 ramtypetext1
= "2 channel";
2114 sisusb
->vramsize
<<= 1;
2115 bw
= busDDR
[(tmp8
& 0x03)];
2119 dev_info(&sisusb
->sisusb_dev
->dev
,
2120 "%dMB %s %cDR S%cRAM, bus width %d\n",
2121 sisusb
->vramsize
>> 20, ramtypetext1
,
2122 ram_datarate
[ramtype
], ram_dynamictype
[ramtype
], bw
);
2125 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data
*sisusb
)
2127 struct sisusb_packet packet
;
2132 packet
.header
= 0x001f;
2133 packet
.address
= 0x00000324;
2134 packet
.data
= 0x00000004;
2135 ret
= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2137 packet
.header
= 0x001f;
2138 packet
.address
= 0x00000364;
2139 packet
.data
= 0x00000004;
2140 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2142 packet
.header
= 0x001f;
2143 packet
.address
= 0x00000384;
2144 packet
.data
= 0x00000004;
2145 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2147 packet
.header
= 0x001f;
2148 packet
.address
= 0x00000100;
2149 packet
.data
= 0x00000700;
2150 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2152 packet
.header
= 0x000f;
2153 packet
.address
= 0x00000004;
2154 ret
|= sisusb_send_bridge_packet(sisusb
, 6, &packet
, 0);
2155 packet
.data
|= 0x17;
2156 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2158 /* Init BAR 0 (VRAM) */
2159 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2160 ret
|= sisusb_write_pci_config(sisusb
, 0x10, 0xfffffff0);
2161 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2163 tmp32
|= SISUSB_PCI_MEMBASE
;
2164 ret
|= sisusb_write_pci_config(sisusb
, 0x10, tmp32
);
2166 /* Init BAR 1 (MMIO) */
2167 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2168 ret
|= sisusb_write_pci_config(sisusb
, 0x14, 0xfffffff0);
2169 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2171 tmp32
|= SISUSB_PCI_MMIOBASE
;
2172 ret
|= sisusb_write_pci_config(sisusb
, 0x14, tmp32
);
2174 /* Init BAR 2 (i/o ports) */
2175 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2176 ret
|= sisusb_write_pci_config(sisusb
, 0x18, 0xfffffff0);
2177 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2179 tmp32
|= SISUSB_PCI_IOPORTBASE
;
2180 ret
|= sisusb_write_pci_config(sisusb
, 0x18, tmp32
);
2182 /* Enable memory and i/o access */
2183 ret
|= sisusb_read_pci_config(sisusb
, 0x04, &tmp32
);
2185 ret
|= sisusb_write_pci_config(sisusb
, 0x04, tmp32
);
2188 /* Some further magic */
2189 packet
.header
= 0x001f;
2190 packet
.address
= 0x00000050;
2191 packet
.data
= 0x000000ff;
2192 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2198 /* Initialize the graphics device (return 0 on success)
2199 * This initializes the net2280 as well as the PCI registers
2200 * of the graphics board.
2203 static int sisusb_init_gfxdevice(struct sisusb_usb_data
*sisusb
, int initscreen
)
2205 int ret
= 0, test
= 0;
2208 if (sisusb
->devinit
== 1) {
2209 /* Read PCI BARs and see if they have been set up */
2210 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2214 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MEMBASE
)
2217 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2221 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MMIOBASE
)
2224 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2228 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_IOPORTBASE
)
2232 /* No? So reset the device */
2233 if ((sisusb
->devinit
== 0) || (test
!= 3)) {
2235 ret
|= sisusb_do_init_gfxdevice(sisusb
);
2238 sisusb
->devinit
= 1;
2242 if (sisusb
->devinit
) {
2243 /* Initialize the graphics core */
2244 if (sisusb_init_gfxcore(sisusb
) == 0) {
2245 sisusb
->gfxinit
= 1;
2246 sisusb_get_ramconfig(sisusb
);
2247 sisusb_set_default_mode(sisusb
, 1);
2248 ret
|= sisusb_setup_screen(sisusb
, 1, initscreen
);
2256 #ifdef CONFIG_USB_SISUSBVGA_CON
2258 /* Set up default text mode:
2259 * - Set text mode (0x03)
2260 * - Upload default font
2261 * - Upload user font (if available)
2264 int sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
)
2266 int ret
= 0, slot
= sisusb
->font_slot
, i
;
2267 const struct font_desc
*myfont
;
2270 static const char bootstring
[] =
2271 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2272 static const char bootlogo
[] = "(o_ //\\ V_/_";
2274 /* sisusb->lock is down */
2276 if (!sisusb
->SiS_Pr
)
2279 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2280 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2283 SiSUSBSetMode(sisusb
->SiS_Pr
, 0x03);
2285 myfont
= find_font("VGA8x16");
2289 tempbuf
= vmalloc(8192);
2293 for (i
= 0; i
< 256; i
++)
2294 memcpy(tempbuf
+ (i
* 32), myfont
->data
+ (i
* 16), 16);
2296 /* Upload default font */
2297 ret
= sisusbcon_do_font_op(sisusb
, 1, 0, tempbuf
, 8192,
2302 /* Upload user font (and reset current slot) */
2303 if (sisusb
->font_backup
) {
2304 ret
|= sisusbcon_do_font_op(sisusb
, 1, 2, sisusb
->font_backup
,
2305 8192, sisusb
->font_backup_512
, 1, NULL
,
2306 sisusb
->font_backup_height
, 0);
2308 sisusbcon_do_font_op(sisusb
, 1, 0, NULL
, 0, 0, 1,
2312 if (init
&& !sisusb
->scrbuf
) {
2314 tempbuf
= vmalloc(8192);
2318 tempbufb
= (u16
*)tempbuf
;
2320 *(tempbufb
++) = 0x0720;
2323 tempbufb
= (u16
*)tempbuf
;
2324 while (bootlogo
[i
]) {
2325 *(tempbufb
++) = 0x0700 | bootlogo
[i
++];
2331 tempbufb
= (u16
*)tempbuf
+ 6;
2332 while (bootstring
[i
])
2333 *(tempbufb
++) = 0x0700 | bootstring
[i
++];
2335 ret
|= sisusb_copy_memory(sisusb
, tempbuf
,
2336 sisusb
->vrambase
, 8192);
2342 } else if (sisusb
->scrbuf
) {
2343 ret
|= sisusb_copy_memory(sisusb
, (u8
*)sisusb
->scrbuf
,
2344 sisusb
->vrambase
, sisusb
->scrbuf_size
);
2347 if (sisusb
->sisusb_cursor_size_from
>= 0 &&
2348 sisusb
->sisusb_cursor_size_to
>= 0) {
2349 sisusb_setidxreg(sisusb
, SISCR
, 0x0a,
2350 sisusb
->sisusb_cursor_size_from
);
2351 sisusb_setidxregandor(sisusb
, SISCR
, 0x0b, 0xe0,
2352 sisusb
->sisusb_cursor_size_to
);
2354 sisusb_setidxreg(sisusb
, SISCR
, 0x0a, 0x2d);
2355 sisusb_setidxreg(sisusb
, SISCR
, 0x0b, 0x0e);
2356 sisusb
->sisusb_cursor_size_to
= -1;
2359 slot
= sisusb
->sisusb_cursor_loc
;
2363 sisusb
->sisusb_cursor_loc
= -1;
2364 sisusb
->bad_cursor_pos
= 1;
2366 sisusb_set_cursor(sisusb
, slot
);
2368 sisusb_setidxreg(sisusb
, SISCR
, 0x0c, (sisusb
->cur_start_addr
>> 8));
2369 sisusb_setidxreg(sisusb
, SISCR
, 0x0d, (sisusb
->cur_start_addr
& 0xff));
2371 sisusb
->textmodedestroyed
= 0;
2373 /* sisusb->lock is down */
2382 static int sisusb_open(struct inode
*inode
, struct file
*file
)
2384 struct sisusb_usb_data
*sisusb
;
2385 struct usb_interface
*interface
;
2386 int subminor
= iminor(inode
);
2388 interface
= usb_find_interface(&sisusb_driver
, subminor
);
2392 sisusb
= usb_get_intfdata(interface
);
2396 mutex_lock(&sisusb
->lock
);
2398 if (!sisusb
->present
|| !sisusb
->ready
) {
2399 mutex_unlock(&sisusb
->lock
);
2403 if (sisusb
->isopen
) {
2404 mutex_unlock(&sisusb
->lock
);
2408 if (!sisusb
->devinit
) {
2409 if (sisusb
->sisusb_dev
->speed
== USB_SPEED_HIGH
||
2410 sisusb
->sisusb_dev
->speed
>= USB_SPEED_SUPER
) {
2411 if (sisusb_init_gfxdevice(sisusb
, 0)) {
2412 mutex_unlock(&sisusb
->lock
);
2413 dev_err(&sisusb
->sisusb_dev
->dev
,
2414 "Failed to initialize device\n");
2418 mutex_unlock(&sisusb
->lock
);
2419 dev_err(&sisusb
->sisusb_dev
->dev
,
2420 "Device not attached to USB 2.0 hub\n");
2425 /* Increment usage count for our sisusb */
2426 kref_get(&sisusb
->kref
);
2430 file
->private_data
= sisusb
;
2432 mutex_unlock(&sisusb
->lock
);
2437 void sisusb_delete(struct kref
*kref
)
2439 struct sisusb_usb_data
*sisusb
= to_sisusb_dev(kref
);
2444 usb_put_dev(sisusb
->sisusb_dev
);
2446 sisusb
->sisusb_dev
= NULL
;
2447 sisusb_free_buffers(sisusb
);
2448 sisusb_free_urbs(sisusb
);
2449 #ifdef CONFIG_USB_SISUSBVGA_CON
2450 kfree(sisusb
->SiS_Pr
);
2455 static int sisusb_release(struct inode
*inode
, struct file
*file
)
2457 struct sisusb_usb_data
*sisusb
;
2459 sisusb
= file
->private_data
;
2463 mutex_lock(&sisusb
->lock
);
2465 if (sisusb
->present
) {
2466 /* Wait for all URBs to finish if device still present */
2467 if (!sisusb_wait_all_out_complete(sisusb
))
2468 sisusb_kill_all_busy(sisusb
);
2472 file
->private_data
= NULL
;
2474 mutex_unlock(&sisusb
->lock
);
2476 /* decrement the usage count on our device */
2477 kref_put(&sisusb
->kref
, sisusb_delete
);
2482 static ssize_t
sisusb_read(struct file
*file
, char __user
*buffer
,
2483 size_t count
, loff_t
*ppos
)
2485 struct sisusb_usb_data
*sisusb
;
2486 ssize_t bytes_read
= 0;
2492 sisusb
= file
->private_data
;
2496 mutex_lock(&sisusb
->lock
);
2499 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2500 mutex_unlock(&sisusb
->lock
);
2504 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2505 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2507 address
= (*ppos
) - SISUSB_PCI_PSEUDO_IOPORTBASE
+
2508 SISUSB_PCI_IOPORTBASE
;
2511 * Byte, word and long(32) can be read. As this
2512 * emulates inX instructions, the data returned is
2513 * in machine-endianness.
2517 if (sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
,
2520 else if (put_user(buf8
, (u8 __user
*)buffer
))
2528 if (sisusb_read_memio_word(sisusb
, SISUSB_TYPE_IO
,
2531 else if (put_user(buf16
, (u16 __user
*)buffer
))
2539 if (sisusb_read_memio_long(sisusb
, SISUSB_TYPE_IO
,
2542 else if (put_user(buf32
, (u32 __user
*)buffer
))
2554 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&& (*ppos
) <
2555 SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2557 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MEMBASE
+
2561 * Remember: Data delivered is never endian-corrected
2563 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2564 NULL
, count
, buffer
, &bytes_read
);
2569 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2570 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+
2571 SISUSB_PCI_MMIOSIZE
) {
2573 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MMIOBASE
+
2574 SISUSB_PCI_MMIOBASE
;
2577 * Remember: Data delivered is never endian-corrected
2579 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2580 NULL
, count
, buffer
, &bytes_read
);
2585 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2586 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ 0x5c) {
2589 mutex_unlock(&sisusb
->lock
);
2593 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2595 /* Read PCI config register
2596 * Return value delivered in machine endianness.
2598 if (sisusb_read_pci_config(sisusb
, address
, &buf32
))
2600 else if (put_user(buf32
, (u32 __user
*)buffer
))
2611 (*ppos
) += bytes_read
;
2613 mutex_unlock(&sisusb
->lock
);
2615 return errno
? errno
: bytes_read
;
2618 static ssize_t
sisusb_write(struct file
*file
, const char __user
*buffer
,
2619 size_t count
, loff_t
*ppos
)
2621 struct sisusb_usb_data
*sisusb
;
2623 ssize_t bytes_written
= 0;
2628 sisusb
= file
->private_data
;
2632 mutex_lock(&sisusb
->lock
);
2635 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2636 mutex_unlock(&sisusb
->lock
);
2640 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2641 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2643 address
= (*ppos
) - SISUSB_PCI_PSEUDO_IOPORTBASE
+
2644 SISUSB_PCI_IOPORTBASE
;
2647 * Byte, word and long(32) can be written. As this
2648 * emulates outX instructions, the data is expected
2649 * in machine-endianness.
2653 if (get_user(buf8
, (u8 __user
*)buffer
))
2655 else if (sisusb_write_memio_byte(sisusb
,
2656 SISUSB_TYPE_IO
, address
, buf8
))
2664 if (get_user(buf16
, (u16 __user
*)buffer
))
2666 else if (sisusb_write_memio_word(sisusb
,
2667 SISUSB_TYPE_IO
, address
, buf16
))
2675 if (get_user(buf32
, (u32 __user
*)buffer
))
2677 else if (sisusb_write_memio_long(sisusb
,
2678 SISUSB_TYPE_IO
, address
, buf32
))
2689 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2690 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+
2693 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MEMBASE
+
2697 * Buffer is copied 1:1, therefore, on big-endian
2698 * machines, the data must be swapped by userland
2699 * in advance (if applicable; no swapping in 8bpp
2700 * mode or if YUV data is being transferred).
2702 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2703 count
, buffer
, 0, &bytes_written
);
2706 errno
= bytes_written
;
2708 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2709 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+
2710 SISUSB_PCI_MMIOSIZE
) {
2712 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MMIOBASE
+
2713 SISUSB_PCI_MMIOBASE
;
2716 * Buffer is copied 1:1, therefore, on big-endian
2717 * machines, the data must be swapped by userland
2720 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2721 count
, buffer
, 0, &bytes_written
);
2724 errno
= bytes_written
;
2726 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2727 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+
2728 SISUSB_PCI_PCONFSIZE
) {
2731 mutex_unlock(&sisusb
->lock
);
2735 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2737 /* Write PCI config register.
2738 * Given value expected in machine endianness.
2740 if (get_user(buf32
, (u32 __user
*)buffer
))
2742 else if (sisusb_write_pci_config(sisusb
, address
, buf32
))
2755 (*ppos
) += bytes_written
;
2757 mutex_unlock(&sisusb
->lock
);
2759 return errno
? errno
: bytes_written
;
2762 static loff_t
sisusb_lseek(struct file
*file
, loff_t offset
, int orig
)
2764 struct sisusb_usb_data
*sisusb
;
2767 sisusb
= file
->private_data
;
2771 mutex_lock(&sisusb
->lock
);
2774 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2775 mutex_unlock(&sisusb
->lock
);
2779 ret
= no_seek_end_llseek(file
, offset
, orig
);
2781 mutex_unlock(&sisusb
->lock
);
2785 static int sisusb_handle_command(struct sisusb_usb_data
*sisusb
,
2786 struct sisusb_command
*y
, unsigned long arg
)
2791 /* All our commands require the device
2792 * to be initialized.
2794 if (!sisusb
->devinit
)
2798 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2799 SISUSB_PCI_IOPORTBASE
;
2801 switch (y
->operation
) {
2803 retval
= sisusb_getidxreg(sisusb
, port
, y
->data0
, &y
->data1
);
2805 if (copy_to_user((void __user
*)arg
, y
, sizeof(*y
)))
2811 retval
= sisusb_setidxreg(sisusb
, port
, y
->data0
, y
->data1
);
2815 retval
= sisusb_setidxregor(sisusb
, port
, y
->data0
, y
->data1
);
2819 retval
= sisusb_setidxregand(sisusb
, port
, y
->data0
, y
->data1
);
2822 case SUCMD_SETANDOR
:
2823 retval
= sisusb_setidxregandor(sisusb
, port
, y
->data0
,
2824 y
->data1
, y
->data2
);
2828 retval
= sisusb_setidxregmask(sisusb
, port
, y
->data0
,
2829 y
->data1
, y
->data2
);
2833 /* Gfx core must be initialized */
2834 if (!sisusb
->gfxinit
)
2837 length
= (y
->data0
<< 16) | (y
->data1
<< 8) | y
->data2
;
2838 address
= y
->data3
- SISUSB_PCI_PSEUDO_MEMBASE
+
2840 retval
= sisusb_clear_vram(sisusb
, address
, length
);
2843 case SUCMD_HANDLETEXTMODE
:
2845 #ifdef CONFIG_USB_SISUSBVGA_CON
2846 /* Gfx core must be initialized, SiS_Pr must exist */
2847 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2852 retval
= sisusb_reset_text_mode(sisusb
, 0);
2855 sisusb
->textmodedestroyed
= 1;
2861 #ifdef CONFIG_USB_SISUSBVGA_CON
2863 /* Gfx core must be initialized, SiS_Pr must exist */
2864 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2869 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2870 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2872 if (SiSUSBSetMode(sisusb
->SiS_Pr
, y
->data3
))
2877 case SUCMD_SETVESAMODE
:
2878 /* Gfx core must be initialized, SiS_Pr must exist */
2879 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2884 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2885 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2887 if (SiSUSBSetVESAMode(sisusb
->SiS_Pr
, y
->data3
))
2903 static long sisusb_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
2905 struct sisusb_usb_data
*sisusb
;
2906 struct sisusb_info x
;
2907 struct sisusb_command y
;
2909 u32 __user
*argp
= (u32 __user
*)arg
;
2911 sisusb
= file
->private_data
;
2915 mutex_lock(&sisusb
->lock
);
2918 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2924 case SISUSB_GET_CONFIG_SIZE
:
2926 if (put_user(sizeof(x
), argp
))
2931 case SISUSB_GET_CONFIG
:
2933 x
.sisusb_id
= SISUSB_ID
;
2934 x
.sisusb_version
= SISUSB_VERSION
;
2935 x
.sisusb_revision
= SISUSB_REVISION
;
2936 x
.sisusb_patchlevel
= SISUSB_PATCHLEVEL
;
2937 x
.sisusb_gfxinit
= sisusb
->gfxinit
;
2938 x
.sisusb_vrambase
= SISUSB_PCI_PSEUDO_MEMBASE
;
2939 x
.sisusb_mmiobase
= SISUSB_PCI_PSEUDO_MMIOBASE
;
2940 x
.sisusb_iobase
= SISUSB_PCI_PSEUDO_IOPORTBASE
;
2941 x
.sisusb_pcibase
= SISUSB_PCI_PSEUDO_PCIBASE
;
2942 x
.sisusb_vramsize
= sisusb
->vramsize
;
2943 x
.sisusb_minor
= sisusb
->minor
;
2944 x
.sisusb_fbdevactive
= 0;
2945 #ifdef CONFIG_USB_SISUSBVGA_CON
2946 x
.sisusb_conactive
= sisusb
->haveconsole
? 1 : 0;
2948 x
.sisusb_conactive
= 0;
2950 memset(x
.sisusb_reserved
, 0, sizeof(x
.sisusb_reserved
));
2952 if (copy_to_user((void __user
*)arg
, &x
, sizeof(x
)))
2957 case SISUSB_COMMAND
:
2959 if (copy_from_user(&y
, (void __user
*)arg
, sizeof(y
)))
2962 retval
= sisusb_handle_command(sisusb
, &y
, arg
);
2972 mutex_unlock(&sisusb
->lock
);
2976 #ifdef CONFIG_COMPAT
2977 static long sisusb_compat_ioctl(struct file
*f
, unsigned int cmd
,
2981 case SISUSB_GET_CONFIG_SIZE
:
2982 case SISUSB_GET_CONFIG
:
2983 case SISUSB_COMMAND
:
2984 return sisusb_ioctl(f
, cmd
, arg
);
2987 return -ENOIOCTLCMD
;
2992 static const struct file_operations usb_sisusb_fops
= {
2993 .owner
= THIS_MODULE
,
2994 .open
= sisusb_open
,
2995 .release
= sisusb_release
,
2996 .read
= sisusb_read
,
2997 .write
= sisusb_write
,
2998 .llseek
= sisusb_lseek
,
2999 #ifdef CONFIG_COMPAT
3000 .compat_ioctl
= sisusb_compat_ioctl
,
3002 .unlocked_ioctl
= sisusb_ioctl
3005 static struct usb_class_driver usb_sisusb_class
= {
3006 .name
= "sisusbvga%d",
3007 .fops
= &usb_sisusb_fops
,
3008 .minor_base
= SISUSB_MINOR
3011 static int sisusb_probe(struct usb_interface
*intf
,
3012 const struct usb_device_id
*id
)
3014 struct usb_device
*dev
= interface_to_usbdev(intf
);
3015 struct sisusb_usb_data
*sisusb
;
3018 dev_info(&dev
->dev
, "USB2VGA dongle found at address %d\n",
3021 /* Allocate memory for our private */
3022 sisusb
= kzalloc(sizeof(*sisusb
), GFP_KERNEL
);
3026 kref_init(&sisusb
->kref
);
3028 mutex_init(&(sisusb
->lock
));
3030 sisusb
->sisusb_dev
= dev
;
3031 sisusb
->vrambase
= SISUSB_PCI_MEMBASE
;
3032 sisusb
->mmiobase
= SISUSB_PCI_MMIOBASE
;
3033 sisusb
->mmiosize
= SISUSB_PCI_MMIOSIZE
;
3034 sisusb
->ioportbase
= SISUSB_PCI_IOPORTBASE
;
3035 /* Everything else is zero */
3037 /* Register device */
3038 retval
= usb_register_dev(intf
, &usb_sisusb_class
);
3040 dev_err(&sisusb
->sisusb_dev
->dev
,
3041 "Failed to get a minor for device %d\n",
3047 sisusb
->minor
= intf
->minor
;
3049 /* Allocate buffers */
3050 sisusb
->ibufsize
= SISUSB_IBUF_SIZE
;
3051 sisusb
->ibuf
= kmalloc(SISUSB_IBUF_SIZE
, GFP_KERNEL
);
3052 if (!sisusb
->ibuf
) {
3057 sisusb
->numobufs
= 0;
3058 sisusb
->obufsize
= SISUSB_OBUF_SIZE
;
3059 for (i
= 0; i
< NUMOBUFS
; i
++) {
3060 sisusb
->obuf
[i
] = kmalloc(SISUSB_OBUF_SIZE
, GFP_KERNEL
);
3061 if (!sisusb
->obuf
[i
]) {
3072 sisusb
->sisurbin
= usb_alloc_urb(0, GFP_KERNEL
);
3073 if (!sisusb
->sisurbin
) {
3077 sisusb
->completein
= 1;
3079 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
3080 sisusb
->sisurbout
[i
] = usb_alloc_urb(0, GFP_KERNEL
);
3081 if (!sisusb
->sisurbout
[i
]) {
3085 sisusb
->urbout_context
[i
].sisusb
= (void *)sisusb
;
3086 sisusb
->urbout_context
[i
].urbindex
= i
;
3087 sisusb
->urbstatus
[i
] = 0;
3090 dev_info(&sisusb
->sisusb_dev
->dev
, "Allocated %d output buffers\n",
3093 #ifdef CONFIG_USB_SISUSBVGA_CON
3094 /* Allocate our SiS_Pr */
3095 sisusb
->SiS_Pr
= kmalloc(sizeof(struct SiS_Private
), GFP_KERNEL
);
3096 if (!sisusb
->SiS_Pr
) {
3102 /* Do remaining init stuff */
3104 init_waitqueue_head(&sisusb
->wait_q
);
3106 usb_set_intfdata(intf
, sisusb
);
3108 usb_get_dev(sisusb
->sisusb_dev
);
3110 sisusb
->present
= 1;
3112 if (dev
->speed
== USB_SPEED_HIGH
|| dev
->speed
>= USB_SPEED_SUPER
) {
3114 #ifdef CONFIG_USB_SISUSBVGA_CON
3115 if (sisusb_first_vc
> 0 && sisusb_last_vc
> 0 &&
3116 sisusb_first_vc
<= sisusb_last_vc
&&
3117 sisusb_last_vc
<= MAX_NR_CONSOLES
)
3120 if (sisusb_init_gfxdevice(sisusb
, initscreen
))
3121 dev_err(&sisusb
->sisusb_dev
->dev
,
3122 "Failed to early initialize device\n");
3125 dev_info(&sisusb
->sisusb_dev
->dev
,
3126 "Not attached to USB 2.0 hub, deferring init\n");
3130 #ifdef SISUSBENDIANTEST
3131 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST ***\n");
3132 sisusb_testreadwrite(sisusb
);
3133 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST END ***\n");
3136 #ifdef CONFIG_USB_SISUSBVGA_CON
3137 sisusb_console_init(sisusb
, sisusb_first_vc
, sisusb_last_vc
);
3143 sisusb_free_urbs(sisusb
);
3145 sisusb_free_buffers(sisusb
);
3147 usb_deregister_dev(intf
, &usb_sisusb_class
);
3153 static void sisusb_disconnect(struct usb_interface
*intf
)
3155 struct sisusb_usb_data
*sisusb
;
3157 /* This should *not* happen */
3158 sisusb
= usb_get_intfdata(intf
);
3162 #ifdef CONFIG_USB_SISUSBVGA_CON
3163 sisusb_console_exit(sisusb
);
3166 usb_deregister_dev(intf
, &usb_sisusb_class
);
3168 mutex_lock(&sisusb
->lock
);
3170 /* Wait for all URBs to complete and kill them in case (MUST do) */
3171 if (!sisusb_wait_all_out_complete(sisusb
))
3172 sisusb_kill_all_busy(sisusb
);
3174 usb_set_intfdata(intf
, NULL
);
3176 sisusb
->present
= 0;
3179 mutex_unlock(&sisusb
->lock
);
3181 /* decrement our usage count */
3182 kref_put(&sisusb
->kref
, sisusb_delete
);
3185 static const struct usb_device_id sisusb_table
[] = {
3186 { USB_DEVICE(0x0711, 0x0550) },
3187 { USB_DEVICE(0x0711, 0x0900) },
3188 { USB_DEVICE(0x0711, 0x0901) },
3189 { USB_DEVICE(0x0711, 0x0902) },
3190 { USB_DEVICE(0x0711, 0x0903) },
3191 { USB_DEVICE(0x0711, 0x0918) },
3192 { USB_DEVICE(0x0711, 0x0920) },
3193 { USB_DEVICE(0x0711, 0x0950) },
3194 { USB_DEVICE(0x0711, 0x5200) },
3195 { USB_DEVICE(0x182d, 0x021c) },
3196 { USB_DEVICE(0x182d, 0x0269) },
3200 MODULE_DEVICE_TABLE(usb
, sisusb_table
);
3202 static struct usb_driver sisusb_driver
= {
3204 .probe
= sisusb_probe
,
3205 .disconnect
= sisusb_disconnect
,
3206 .id_table
= sisusb_table
,
3209 static int __init
usb_sisusb_init(void)
3212 #ifdef CONFIG_USB_SISUSBVGA_CON
3213 sisusb_init_concode();
3216 return usb_register(&sisusb_driver
);
3219 static void __exit
usb_sisusb_exit(void)
3221 usb_deregister(&sisusb_driver
);
3224 module_init(usb_sisusb_init
);
3225 module_exit(usb_sisusb_exit
);
3227 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3228 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3229 MODULE_LICENSE("GPL");