2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
8 * If distributed as part of the Linux kernel, this code is licensed under the
11 * Otherwise, the following license terms apply:
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific psisusbr written permission.
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
39 #include <linux/mutex.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/errno.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/slab.h>
47 #include <linux/spinlock.h>
48 #include <linux/kref.h>
49 #include <linux/usb.h>
50 #include <linux/vmalloc.h>
53 #include "sisusb_init.h"
55 #ifdef INCL_SISUSB_CON
56 #include <linux/font.h>
59 #define SISUSB_DONTSYNC
61 /* Forward declarations / clean-up routines */
63 #ifdef INCL_SISUSB_CON
64 static int sisusb_first_vc
;
65 static int sisusb_last_vc
;
66 module_param_named(first
, sisusb_first_vc
, int, 0);
67 module_param_named(last
, sisusb_last_vc
, int, 0);
68 MODULE_PARM_DESC(first
, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
69 MODULE_PARM_DESC(last
, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
72 static struct usb_driver sisusb_driver
;
74 static void sisusb_free_buffers(struct sisusb_usb_data
*sisusb
)
78 for (i
= 0; i
< NUMOBUFS
; i
++) {
79 kfree(sisusb
->obuf
[i
]);
80 sisusb
->obuf
[i
] = NULL
;
86 static void sisusb_free_urbs(struct sisusb_usb_data
*sisusb
)
90 for (i
= 0; i
< NUMOBUFS
; i
++) {
91 usb_free_urb(sisusb
->sisurbout
[i
]);
92 sisusb
->sisurbout
[i
] = NULL
;
94 usb_free_urb(sisusb
->sisurbin
);
95 sisusb
->sisurbin
= NULL
;
98 /* Level 0: USB transport layer */
102 /* out-urb management */
104 /* Return 1 if all free, 0 otherwise */
105 static int sisusb_all_free(struct sisusb_usb_data
*sisusb
)
109 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
111 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
119 /* Kill all busy URBs */
120 static void sisusb_kill_all_busy(struct sisusb_usb_data
*sisusb
)
124 if (sisusb_all_free(sisusb
))
127 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
129 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
130 usb_kill_urb(sisusb
->sisurbout
[i
]);
135 /* Return 1 if ok, 0 if error (not all complete within timeout) */
136 static int sisusb_wait_all_out_complete(struct sisusb_usb_data
*sisusb
)
138 int timeout
= 5 * HZ
, i
= 1;
140 wait_event_timeout(sisusb
->wait_q
, (i
= sisusb_all_free(sisusb
)),
146 static int sisusb_outurb_available(struct sisusb_usb_data
*sisusb
)
150 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
152 if ((sisusb
->urbstatus
[i
] & (SU_URB_BUSY
|SU_URB_ALLOC
)) == 0)
160 static int sisusb_get_free_outbuf(struct sisusb_usb_data
*sisusb
)
162 int i
, timeout
= 5 * HZ
;
164 wait_event_timeout(sisusb
->wait_q
,
165 ((i
= sisusb_outurb_available(sisusb
)) >= 0), timeout
);
170 static int sisusb_alloc_outbuf(struct sisusb_usb_data
*sisusb
)
174 i
= sisusb_outurb_available(sisusb
);
177 sisusb
->urbstatus
[i
] |= SU_URB_ALLOC
;
182 static void sisusb_free_outbuf(struct sisusb_usb_data
*sisusb
, int index
)
184 if ((index
>= 0) && (index
< sisusb
->numobufs
))
185 sisusb
->urbstatus
[index
] &= ~SU_URB_ALLOC
;
188 /* completion callback */
190 static void sisusb_bulk_completeout(struct urb
*urb
)
192 struct sisusb_urb_context
*context
= urb
->context
;
193 struct sisusb_usb_data
*sisusb
;
198 sisusb
= context
->sisusb
;
200 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
203 #ifndef SISUSB_DONTSYNC
204 if (context
->actual_length
)
205 *(context
->actual_length
) += urb
->actual_length
;
208 sisusb
->urbstatus
[context
->urbindex
] &= ~SU_URB_BUSY
;
209 wake_up(&sisusb
->wait_q
);
212 static int sisusb_bulkout_msg(struct sisusb_usb_data
*sisusb
, int index
,
213 unsigned int pipe
, void *data
, int len
, int *actual_length
,
214 int timeout
, unsigned int tflags
)
216 struct urb
*urb
= sisusb
->sisurbout
[index
];
217 int retval
, byteswritten
= 0;
220 urb
->transfer_flags
= 0;
222 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
223 sisusb_bulk_completeout
,
224 &sisusb
->urbout_context
[index
]);
226 urb
->transfer_flags
|= tflags
;
227 urb
->actual_length
= 0;
230 sisusb
->urbout_context
[index
].actual_length
= (timeout
) ?
231 NULL
: actual_length
;
233 /* Declare this urb/buffer in use */
234 sisusb
->urbstatus
[index
] |= SU_URB_BUSY
;
237 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
239 /* If OK, and if timeout > 0, wait for completion */
240 if ((retval
== 0) && timeout
) {
241 wait_event_timeout(sisusb
->wait_q
,
242 (!(sisusb
->urbstatus
[index
] & SU_URB_BUSY
)),
244 if (sisusb
->urbstatus
[index
] & SU_URB_BUSY
) {
245 /* URB timed out... kill it and report error */
249 /* Otherwise, report urb status */
250 retval
= urb
->status
;
251 byteswritten
= urb
->actual_length
;
256 *actual_length
= byteswritten
;
263 /* completion callback */
265 static void sisusb_bulk_completein(struct urb
*urb
)
267 struct sisusb_usb_data
*sisusb
= urb
->context
;
269 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
272 sisusb
->completein
= 1;
273 wake_up(&sisusb
->wait_q
);
276 static int sisusb_bulkin_msg(struct sisusb_usb_data
*sisusb
,
277 unsigned int pipe
, void *data
, int len
,
278 int *actual_length
, int timeout
, unsigned int tflags
)
280 struct urb
*urb
= sisusb
->sisurbin
;
281 int retval
, readbytes
= 0;
283 urb
->transfer_flags
= 0;
285 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
286 sisusb_bulk_completein
, sisusb
);
288 urb
->transfer_flags
|= tflags
;
289 urb
->actual_length
= 0;
291 sisusb
->completein
= 0;
292 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
294 wait_event_timeout(sisusb
->wait_q
, sisusb
->completein
, timeout
);
295 if (!sisusb
->completein
) {
296 /* URB timed out... kill it and report error */
300 /* URB completed within timeout */
301 retval
= urb
->status
;
302 readbytes
= urb
->actual_length
;
307 *actual_length
= readbytes
;
315 /* Send a bulk message of variable size
317 * To copy the data from userspace, give pointer to "userbuffer",
318 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
319 * both of these are NULL, it is assumed, that the transfer
320 * buffer "sisusb->obuf[index]" is set up with the data to send.
321 * Index is ignored if either kernbuffer or userbuffer is set.
322 * If async is nonzero, URBs will be sent without waiting for
323 * completion of the previous URB.
325 * (return 0 on success)
328 static int sisusb_send_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
329 char *kernbuffer
, const char __user
*userbuffer
, int index
,
330 ssize_t
*bytes_written
, unsigned int tflags
, int async
)
332 int result
= 0, retry
, count
= len
;
333 int passsize
, thispass
, transferred_len
= 0;
334 int fromuser
= (userbuffer
!= NULL
) ? 1 : 0;
335 int fromkern
= (kernbuffer
!= NULL
) ? 1 : 0;
339 (*bytes_written
) = 0;
342 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
345 /* If we copy data from kernel or userspace, force the
346 * allocation of a buffer/urb. If we have the data in
347 * the transfer buffer[index] already, reuse the buffer/URB
348 * if the length is > buffer size. (So, transmitting
349 * large data amounts directly from the transfer buffer
350 * treats the buffer as a ring buffer. However, we need
351 * to sync in this case.)
353 if (fromuser
|| fromkern
)
355 else if (len
> sisusb
->obufsize
)
358 pipe
= usb_sndbulkpipe(sisusb
->sisusb_dev
, ep
);
361 passsize
= thispass
= (sisusb
->obufsize
< count
) ?
362 sisusb
->obufsize
: count
;
365 index
= sisusb_get_free_outbuf(sisusb
);
370 buffer
= sisusb
->obuf
[index
];
374 if (copy_from_user(buffer
, userbuffer
, passsize
))
377 userbuffer
+= passsize
;
379 } else if (fromkern
) {
381 memcpy(buffer
, kernbuffer
, passsize
);
382 kernbuffer
+= passsize
;
389 if (!sisusb
->sisusb_dev
)
392 result
= sisusb_bulkout_msg(sisusb
, index
, pipe
,
393 buffer
, thispass
, &transferred_len
,
394 async
? 0 : 5 * HZ
, tflags
);
396 if (result
== -ETIMEDOUT
) {
398 /* Will not happen if async */
405 if ((result
== 0) && !async
&& transferred_len
) {
407 thispass
-= transferred_len
;
408 buffer
+= transferred_len
;
417 (*bytes_written
) += passsize
;
420 /* Force new allocation in next iteration */
421 if (fromuser
|| fromkern
)
427 #ifdef SISUSB_DONTSYNC
428 (*bytes_written
) = len
;
429 /* Some URBs/buffers might be busy */
431 sisusb_wait_all_out_complete(sisusb
);
432 (*bytes_written
) = transferred_len
;
433 /* All URBs and all buffers are available */
437 return ((*bytes_written
) == len
) ? 0 : -EIO
;
440 /* Receive a bulk message of variable size
442 * To copy the data to userspace, give pointer to "userbuffer",
443 * to copy to kernel memory, give "kernbuffer". One of them
444 * MUST be set. (There is no technique for letting the caller
445 * read directly from the ibuf.)
449 static int sisusb_recv_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
450 void *kernbuffer
, char __user
*userbuffer
, ssize_t
*bytes_read
,
453 int result
= 0, retry
, count
= len
;
454 int bufsize
, thispass
, transferred_len
;
461 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
464 pipe
= usb_rcvbulkpipe(sisusb
->sisusb_dev
, ep
);
465 buffer
= sisusb
->ibuf
;
466 bufsize
= sisusb
->ibufsize
;
470 #ifdef SISUSB_DONTSYNC
471 if (!(sisusb_wait_all_out_complete(sisusb
)))
477 if (!sisusb
->sisusb_dev
)
480 thispass
= (bufsize
< count
) ? bufsize
: count
;
482 result
= sisusb_bulkin_msg(sisusb
, pipe
, buffer
, thispass
,
483 &transferred_len
, 5 * HZ
, tflags
);
486 thispass
= transferred_len
;
488 else if (result
== -ETIMEDOUT
) {
501 (*bytes_read
) += thispass
;
506 if (copy_to_user(userbuffer
, buffer
, thispass
))
509 userbuffer
+= thispass
;
513 memcpy(kernbuffer
, buffer
, thispass
);
514 kernbuffer
+= thispass
;
522 return ((*bytes_read
) == len
) ? 0 : -EIO
;
525 static int sisusb_send_packet(struct sisusb_usb_data
*sisusb
, int len
,
526 struct sisusb_packet
*packet
)
529 ssize_t bytes_transferred
= 0;
535 #ifdef SISUSB_DONTSYNC
536 if (!(sisusb_wait_all_out_complete(sisusb
)))
540 /* Eventually correct endianness */
541 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
543 /* 1. send the packet */
544 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_GFX_OUT
, len
,
545 (char *)packet
, NULL
, 0, &bytes_transferred
, 0, 0);
547 if ((ret
== 0) && (len
== 6)) {
549 /* 2. if packet len == 6, it means we read, so wait for 32bit
550 * return value and write it to packet->data
552 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_GFX_IN
, 4,
553 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
555 packet
->data
= le32_to_cpu(tmp
);
561 static int sisusb_send_bridge_packet(struct sisusb_usb_data
*sisusb
, int len
,
562 struct sisusb_packet
*packet
, unsigned int tflags
)
565 ssize_t bytes_transferred
= 0;
571 #ifdef SISUSB_DONTSYNC
572 if (!(sisusb_wait_all_out_complete(sisusb
)))
576 /* Eventually correct endianness */
577 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
579 /* 1. send the packet */
580 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_OUT
, len
,
581 (char *)packet
, NULL
, 0, &bytes_transferred
, tflags
, 0);
583 if ((ret
== 0) && (len
== 6)) {
585 /* 2. if packet len == 6, it means we read, so wait for 32bit
586 * return value and write it to packet->data
588 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_IN
, 4,
589 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
591 packet
->data
= le32_to_cpu(tmp
);
597 /* access video memory and mmio (return 0 on success) */
601 /* The following routines assume being used to transfer byte, word,
604 * - the write routines expect "data" in machine endianness format.
605 * The data will be converted to leXX in sisusb_xxx_packet.
606 * - the read routines can expect read data in machine-endianess.
609 static int sisusb_write_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
612 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 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
622 static int sisusb_write_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
625 struct sisusb_packet packet
;
628 packet
.address
= addr
& ~3;
632 packet
.header
= (type
<< 6) | 0x0003;
633 packet
.data
= (u32
)data
;
634 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
637 packet
.header
= (type
<< 6) | 0x0006;
638 packet
.data
= (u32
)data
<< 8;
639 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
642 packet
.header
= (type
<< 6) | 0x000c;
643 packet
.data
= (u32
)data
<< 16;
644 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
647 packet
.header
= (type
<< 6) | 0x0008;
648 packet
.data
= (u32
)data
<< 24;
649 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
650 packet
.header
= (type
<< 6) | 0x0001;
651 packet
.address
= (addr
& ~3) + 4;
652 packet
.data
= (u32
)data
>> 8;
653 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
659 static int sisusb_write_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
662 struct sisusb_packet packet
;
665 packet
.address
= addr
& ~3;
669 packet
.header
= (type
<< 6) | 0x0007;
670 packet
.data
= data
& 0x00ffffff;
671 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
674 packet
.header
= (type
<< 6) | 0x000e;
675 packet
.data
= data
<< 8;
676 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
679 packet
.header
= (type
<< 6) | 0x000c;
680 packet
.data
= data
<< 16;
681 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
682 packet
.header
= (type
<< 6) | 0x0001;
683 packet
.address
= (addr
& ~3) + 4;
684 packet
.data
= (data
>> 16) & 0x00ff;
685 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
688 packet
.header
= (type
<< 6) | 0x0008;
689 packet
.data
= data
<< 24;
690 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
691 packet
.header
= (type
<< 6) | 0x0003;
692 packet
.address
= (addr
& ~3) + 4;
693 packet
.data
= (data
>> 8) & 0xffff;
694 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
700 static int sisusb_write_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
703 struct sisusb_packet packet
;
706 packet
.address
= addr
& ~3;
710 packet
.header
= (type
<< 6) | 0x000f;
712 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
715 packet
.header
= (type
<< 6) | 0x000e;
716 packet
.data
= data
<< 8;
717 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
718 packet
.header
= (type
<< 6) | 0x0001;
719 packet
.address
= (addr
& ~3) + 4;
720 packet
.data
= data
>> 24;
721 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
724 packet
.header
= (type
<< 6) | 0x000c;
725 packet
.data
= data
<< 16;
726 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
727 packet
.header
= (type
<< 6) | 0x0003;
728 packet
.address
= (addr
& ~3) + 4;
729 packet
.data
= data
>> 16;
730 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
733 packet
.header
= (type
<< 6) | 0x0008;
734 packet
.data
= data
<< 24;
735 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
736 packet
.header
= (type
<< 6) | 0x0007;
737 packet
.address
= (addr
& ~3) + 4;
738 packet
.data
= data
>> 8;
739 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
745 /* The xxx_bulk routines copy a buffer of variable size. They treat the
746 * buffer as chars, therefore lsb/msb has to be corrected if using the
747 * byte/word/long/etc routines for speed-up
749 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
750 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
751 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
752 * that the data already is in the transfer buffer "sisusb->obuf[index]".
755 static int sisusb_write_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
756 char *kernbuffer
, int length
, const char __user
*userbuffer
,
757 int index
, ssize_t
*bytes_written
)
759 struct sisusb_packet packet
;
762 u8 swap8
, fromkern
= kernbuffer
? 1 : 0;
764 u32 swap32
, flag
= (length
>> 28) & 1;
767 /* if neither kernbuffer not userbuffer are given, assume
770 if (!fromkern
&& !userbuffer
)
771 kernbuffer
= sisusb
->obuf
[index
];
773 (*bytes_written
= 0);
775 length
&= 0x00ffffff;
781 if (get_user(swap8
, (u8 __user
*)userbuffer
))
784 swap8
= kernbuffer
[0];
786 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
796 if (get_user(swap16
, (u16 __user
*)userbuffer
))
799 swap16
= *((u16
*)kernbuffer
);
801 ret
= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
805 (*bytes_written
) += 2;
811 if (copy_from_user(&buf
, userbuffer
, 3))
814 swap32
= (buf
[0] << 16) |
818 swap32
= (buf
[2] << 16) |
824 swap32
= (kernbuffer
[0] << 16) |
825 (kernbuffer
[1] << 8) |
828 swap32
= (kernbuffer
[2] << 16) |
829 (kernbuffer
[1] << 8) |
833 ret
= sisusb_write_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
837 (*bytes_written
) += 3;
843 if (get_user(swap32
, (u32 __user
*)userbuffer
))
846 swap32
= *((u32
*)kernbuffer
);
848 ret
= sisusb_write_memio_long(sisusb
, SISUSB_TYPE_MEM
,
851 (*bytes_written
) += 4;
856 if ((length
& ~3) > 0x10000) {
858 packet
.header
= 0x001f;
859 packet
.address
= 0x000001d4;
861 ret
= sisusb_send_bridge_packet(sisusb
, 10,
863 packet
.header
= 0x001f;
864 packet
.address
= 0x000001d0;
865 packet
.data
= (length
& ~3);
866 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
868 packet
.header
= 0x001f;
869 packet
.address
= 0x000001c0;
870 packet
.data
= flag
| 0x16;
871 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
874 ret
|= sisusb_send_bulk_msg(sisusb
,
875 SISUSB_EP_GFX_LBULK_OUT
,
878 bytes_written
, 0, 1);
879 userbuffer
+= (*bytes_written
);
880 } else if (fromkern
) {
881 ret
|= sisusb_send_bulk_msg(sisusb
,
882 SISUSB_EP_GFX_LBULK_OUT
,
885 bytes_written
, 0, 1);
886 kernbuffer
+= (*bytes_written
);
888 ret
|= sisusb_send_bulk_msg(sisusb
,
889 SISUSB_EP_GFX_LBULK_OUT
,
892 bytes_written
, 0, 1);
893 kernbuffer
+= ((*bytes_written
) &
894 (sisusb
->obufsize
-1));
899 packet
.header
= 0x001f;
900 packet
.address
= 0x00000194;
902 ret
= sisusb_send_bridge_packet(sisusb
, 10,
904 packet
.header
= 0x001f;
905 packet
.address
= 0x00000190;
906 packet
.data
= (length
& ~3);
907 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
909 if (sisusb
->flagb0
!= 0x16) {
910 packet
.header
= 0x001f;
911 packet
.address
= 0x00000180;
912 packet
.data
= flag
| 0x16;
913 ret
|= sisusb_send_bridge_packet(sisusb
,
915 sisusb
->flagb0
= 0x16;
918 ret
|= sisusb_send_bulk_msg(sisusb
,
919 SISUSB_EP_GFX_BULK_OUT
,
922 bytes_written
, 0, 1);
923 userbuffer
+= (*bytes_written
);
924 } else if (fromkern
) {
925 ret
|= sisusb_send_bulk_msg(sisusb
,
926 SISUSB_EP_GFX_BULK_OUT
,
929 bytes_written
, 0, 1);
930 kernbuffer
+= (*bytes_written
);
932 ret
|= sisusb_send_bulk_msg(sisusb
,
933 SISUSB_EP_GFX_BULK_OUT
,
936 bytes_written
, 0, 1);
937 kernbuffer
+= ((*bytes_written
) &
938 (sisusb
->obufsize
-1));
944 dev_err(&sisusb
->sisusb_dev
->dev
,
945 "Wrote %zd of %d bytes, error %d\n",
946 *bytes_written
, length
,
948 else if (msgcount
== 500)
949 dev_err(&sisusb
->sisusb_dev
->dev
,
950 "Too many errors, logging stopped\n");
952 addr
+= (*bytes_written
);
953 length
-= (*bytes_written
);
961 return ret
? -EIO
: 0;
964 /* Remember: Read data in packet is in machine-endianess! So for
965 * byte, word, 24bit, long no endian correction is necessary.
968 static int sisusb_read_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
971 struct sisusb_packet packet
;
974 CLEARPACKET(&packet
);
975 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
976 packet
.address
= addr
& ~3;
977 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
978 *data
= (u8
)(packet
.data
>> ((addr
& 3) << 3));
982 static int sisusb_read_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
985 struct sisusb_packet packet
;
988 CLEARPACKET(&packet
);
990 packet
.address
= addr
& ~3;
994 packet
.header
= (type
<< 6) | 0x0003;
995 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
996 *data
= (u16
)(packet
.data
);
999 packet
.header
= (type
<< 6) | 0x0006;
1000 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1001 *data
= (u16
)(packet
.data
>> 8);
1004 packet
.header
= (type
<< 6) | 0x000c;
1005 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1006 *data
= (u16
)(packet
.data
>> 16);
1009 packet
.header
= (type
<< 6) | 0x0008;
1010 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1011 *data
= (u16
)(packet
.data
>> 24);
1012 packet
.header
= (type
<< 6) | 0x0001;
1013 packet
.address
= (addr
& ~3) + 4;
1014 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1015 *data
|= (u16
)(packet
.data
<< 8);
1021 static int sisusb_read_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
1022 u32 addr
, u32
*data
)
1024 struct sisusb_packet packet
;
1027 packet
.address
= addr
& ~3;
1031 packet
.header
= (type
<< 6) | 0x0007;
1032 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1033 *data
= packet
.data
& 0x00ffffff;
1036 packet
.header
= (type
<< 6) | 0x000e;
1037 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1038 *data
= packet
.data
>> 8;
1041 packet
.header
= (type
<< 6) | 0x000c;
1042 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1043 *data
= packet
.data
>> 16;
1044 packet
.header
= (type
<< 6) | 0x0001;
1045 packet
.address
= (addr
& ~3) + 4;
1046 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1047 *data
|= ((packet
.data
& 0xff) << 16);
1050 packet
.header
= (type
<< 6) | 0x0008;
1051 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1052 *data
= packet
.data
>> 24;
1053 packet
.header
= (type
<< 6) | 0x0003;
1054 packet
.address
= (addr
& ~3) + 4;
1055 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1056 *data
|= ((packet
.data
& 0xffff) << 8);
1062 static int sisusb_read_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
1063 u32 addr
, u32
*data
)
1065 struct sisusb_packet packet
;
1068 packet
.address
= addr
& ~3;
1072 packet
.header
= (type
<< 6) | 0x000f;
1073 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1074 *data
= packet
.data
;
1077 packet
.header
= (type
<< 6) | 0x000e;
1078 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1079 *data
= packet
.data
>> 8;
1080 packet
.header
= (type
<< 6) | 0x0001;
1081 packet
.address
= (addr
& ~3) + 4;
1082 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1083 *data
|= (packet
.data
<< 24);
1086 packet
.header
= (type
<< 6) | 0x000c;
1087 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1088 *data
= packet
.data
>> 16;
1089 packet
.header
= (type
<< 6) | 0x0003;
1090 packet
.address
= (addr
& ~3) + 4;
1091 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1092 *data
|= (packet
.data
<< 16);
1095 packet
.header
= (type
<< 6) | 0x0008;
1096 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1097 *data
= packet
.data
>> 24;
1098 packet
.header
= (type
<< 6) | 0x0007;
1099 packet
.address
= (addr
& ~3) + 4;
1100 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1101 *data
|= (packet
.data
<< 8);
1107 static int sisusb_read_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
1108 char *kernbuffer
, int length
, char __user
*userbuffer
,
1109 ssize_t
*bytes_read
)
1118 length
&= 0x00ffffff;
1123 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
1128 if (put_user(buf
[0], (u8 __user
*)userbuffer
))
1131 kernbuffer
[0] = buf
[0];
1136 ret
|= sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1141 if (put_user(swap16
, (u16 __user
*)userbuffer
))
1144 *((u16
*)kernbuffer
) = swap16
;
1150 ret
|= sisusb_read_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
1155 buf
[0] = (swap32
>> 16) & 0xff;
1156 buf
[1] = (swap32
>> 8) & 0xff;
1157 buf
[2] = swap32
& 0xff;
1159 buf
[2] = (swap32
>> 16) & 0xff;
1160 buf
[1] = (swap32
>> 8) & 0xff;
1161 buf
[0] = swap32
& 0xff;
1164 if (copy_to_user(userbuffer
,
1168 kernbuffer
[0] = buf
[0];
1169 kernbuffer
[1] = buf
[1];
1170 kernbuffer
[2] = buf
[2];
1176 ret
|= sisusb_read_memio_long(sisusb
, SISUSB_TYPE_MEM
,
1181 if (put_user(swap32
, (u32 __user
*)userbuffer
))
1186 *((u32
*)kernbuffer
) = swap32
;
1200 /* High level: Gfx (indexed) register access */
1202 #ifdef INCL_SISUSB_CON
1203 int sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
)
1205 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1208 int sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
)
1210 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1214 int sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
,
1219 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1220 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1224 int sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
,
1229 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1230 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1234 int sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1240 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1241 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1244 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1248 static int sisusb_setidxregmask(struct sisusb_usb_data
*sisusb
,
1249 int port
, u8 idx
, u8 data
, u8 mask
)
1254 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1255 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1257 tmp
|= (data
& mask
);
1258 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1262 int sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
,
1265 return sisusb_setidxregandor(sisusb
, port
, index
, 0xff, myor
);
1268 int sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
,
1271 return sisusb_setidxregandor(sisusb
, port
, idx
, myand
, 0x00);
1274 /* Write/read video ram */
1276 #ifdef INCL_SISUSB_CON
1277 int sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
)
1279 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
);
1282 int sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
)
1284 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
);
1287 int sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
1288 u32 dest
, int length
)
1292 return sisusb_write_mem_bulk(sisusb
, dest
, src
, length
,
1296 #ifdef SISUSBENDIANTEST
1297 static int sisusb_read_memory(struct sisusb_usb_data
*sisusb
, char *dest
,
1298 u32 src
, int length
)
1302 return sisusb_read_mem_bulk(sisusb
, src
, dest
, length
,
1308 #ifdef SISUSBENDIANTEST
1309 static void sisusb_testreadwrite(struct sisusb_usb_data
*sisusb
)
1311 static char srcbuffer
[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1312 char destbuffer
[10];
1315 sisusb_copy_memory(sisusb
, srcbuffer
, sisusb
->vrambase
, 7);
1317 for (i
= 1; i
<= 7; i
++) {
1318 dev_dbg(&sisusb
->sisusb_dev
->dev
,
1319 "sisusb: rwtest %d bytes\n", i
);
1320 sisusb_read_memory(sisusb
, destbuffer
, sisusb
->vrambase
, i
);
1321 for (j
= 0; j
< i
; j
++) {
1322 dev_dbg(&sisusb
->sisusb_dev
->dev
,
1323 "rwtest read[%d] = %x\n",
1330 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1332 static int sisusb_write_pci_config(struct sisusb_usb_data
*sisusb
,
1333 int regnum
, u32 data
)
1335 struct sisusb_packet packet
;
1338 packet
.header
= 0x008f;
1339 packet
.address
= regnum
| 0x10000;
1341 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
1345 static int sisusb_read_pci_config(struct sisusb_usb_data
*sisusb
,
1346 int regnum
, u32
*data
)
1348 struct sisusb_packet packet
;
1351 packet
.header
= 0x008f;
1352 packet
.address
= (u32
)regnum
| 0x10000;
1353 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1354 *data
= packet
.data
;
1358 /* Clear video RAM */
1360 static int sisusb_clear_vram(struct sisusb_usb_data
*sisusb
,
1361 u32 address
, int length
)
1366 if (address
< sisusb
->vrambase
)
1369 if (address
>= sisusb
->vrambase
+ sisusb
->vramsize
)
1372 if (address
+ length
> sisusb
->vrambase
+ sisusb
->vramsize
)
1373 length
= sisusb
->vrambase
+ sisusb
->vramsize
- address
;
1378 /* allocate free buffer/urb and clear the buffer */
1379 i
= sisusb_alloc_outbuf(sisusb
);
1383 memset(sisusb
->obuf
[i
], 0, sisusb
->obufsize
);
1385 /* We can write a length > buffer size here. The buffer
1386 * data will simply be re-used (like a ring-buffer).
1388 ret
= sisusb_write_mem_bulk(sisusb
, address
, NULL
, length
, NULL
, i
, &j
);
1390 /* Free the buffer/urb */
1391 sisusb_free_outbuf(sisusb
, i
);
1396 /* Initialize the graphics core (return 0 on success)
1397 * This resets the graphics hardware and puts it into
1398 * a defined mode (640x480@60Hz)
1401 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1402 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1403 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1404 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1405 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1406 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1407 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1408 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1409 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1410 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1411 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1413 static int sisusb_triggersr16(struct sisusb_usb_data
*sisusb
, u8 ramtype
)
1418 ret
= GETIREG(SISSR
, 0x16, &tmp8
);
1421 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1423 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1426 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1428 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1430 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1432 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1434 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1436 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1438 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1443 static int sisusb_getbuswidth(struct sisusb_usb_data
*sisusb
,
1447 u8 ramtype
, done
= 0;
1449 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1451 ret
= GETIREG(SISSR
, 0x3a, &ramtype
);
1454 ret
|= SETIREG(SISSR
, 0x13, 0x00);
1457 ret
|= SETIREG(SISSR
, 0x14, 0x12);
1458 ret
|= SETIREGAND(SISSR
, 0x15, 0xef);
1460 ret
|= SETIREG(SISSR
, 0x14, 0x02);
1463 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1464 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1465 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1466 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1467 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1468 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1469 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1470 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1471 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1472 ret
|= READL(ramptr
+ 0, &t0
);
1473 ret
|= READL(ramptr
+ 4, &t1
);
1474 ret
|= READL(ramptr
+ 8, &t2
);
1475 ret
|= READL(ramptr
+ 12, &t3
);
1479 *chab
= 0; *bw
= 64;
1481 if ((t3
!= 0xcdef0123) || (t2
!= 0x89abcdef)) {
1482 if ((t1
== 0x456789ab) && (t0
== 0x01234567)) {
1483 *chab
= 0; *bw
= 64;
1484 ret
|= SETIREGAND(SISSR
, 0x14, 0xfd);
1487 if ((t1
!= 0x456789ab) || (t0
!= 0x01234567)) {
1488 *chab
= 1; *bw
= 64;
1489 ret
|= SETIREGANDOR(SISSR
, 0x14, 0xfc, 0x01);
1491 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1492 ret
|= WRITEL(ramptr
+ 0, 0x89abcdef);
1493 ret
|= WRITEL(ramptr
+ 4, 0xcdef0123);
1494 ret
|= WRITEL(ramptr
+ 8, 0x55555555);
1495 ret
|= WRITEL(ramptr
+ 12, 0x55555555);
1496 ret
|= WRITEL(ramptr
+ 16, 0xaaaaaaaa);
1497 ret
|= WRITEL(ramptr
+ 20, 0xaaaaaaaa);
1498 ret
|= READL(ramptr
+ 4, &t1
);
1500 if (t1
!= 0xcdef0123) {
1502 ret
|= SETIREGOR(SISSR
, 0x15, 0x10);
1508 *chab
= 0; *bw
= 64; /* default: cha, bw = 64 */
1512 if (t1
== 0x456789ab) {
1513 if (t0
== 0x01234567) {
1514 *chab
= 0; *bw
= 64;
1518 if (t0
== 0x01234567) {
1519 *chab
= 0; *bw
= 32;
1520 ret
|= SETIREG(SISSR
, 0x14, 0x00);
1526 ret
|= SETIREG(SISSR
, 0x14, 0x03);
1527 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1529 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1530 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1531 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1532 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1533 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1534 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1535 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1536 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1537 ret
|= READL(ramptr
+ 0, &t0
);
1538 ret
|= READL(ramptr
+ 4, &t1
);
1540 if (t1
== 0x456789ab) {
1541 if (t0
== 0x01234567) {
1542 *chab
= 1; *bw
= 64;
1546 if (t0
== 0x01234567) {
1547 *chab
= 1; *bw
= 32;
1548 ret
|= SETIREG(SISSR
, 0x14, 0x01);
1556 static int sisusb_verify_mclk(struct sisusb_usb_data
*sisusb
)
1559 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1560 u8 tmp1
, tmp2
, i
, j
;
1562 ret
|= WRITEB(ramptr
, 0xaa);
1563 ret
|= WRITEB(ramptr
+ 16, 0x55);
1564 ret
|= READB(ramptr
, &tmp1
);
1565 ret
|= READB(ramptr
+ 16, &tmp2
);
1566 if ((tmp1
!= 0xaa) || (tmp2
!= 0x55)) {
1567 for (i
= 0, j
= 16; i
< 2; i
++, j
+= 16) {
1568 ret
|= GETIREG(SISSR
, 0x21, &tmp1
);
1569 ret
|= SETIREGAND(SISSR
, 0x21, (tmp1
& 0xfb));
1570 ret
|= SETIREGOR(SISSR
, 0x3c, 0x01); /* not on 330 */
1571 ret
|= SETIREGAND(SISSR
, 0x3c, 0xfe); /* not on 330 */
1572 ret
|= SETIREG(SISSR
, 0x21, tmp1
);
1573 ret
|= WRITEB(ramptr
+ 16 + j
, j
);
1574 ret
|= READB(ramptr
+ 16 + j
, &tmp1
);
1576 ret
|= WRITEB(ramptr
+ j
, j
);
1584 static int sisusb_set_rank(struct sisusb_usb_data
*sisusb
, int *iret
,
1585 int index
, u8 rankno
, u8 chab
, const u8 dramtype
[][5], int bw
)
1587 int ret
= 0, ranksize
;
1592 if ((rankno
== 2) && (dramtype
[index
][0] == 2))
1595 ranksize
= dramtype
[index
][3] / 2 * bw
/ 32;
1597 if ((ranksize
* rankno
) > 128)
1601 while ((ranksize
>>= 1) > 0)
1604 tmp
|= ((rankno
- 1) << 2);
1605 tmp
|= ((bw
/ 64) & 0x02);
1606 tmp
|= (chab
& 0x01);
1608 ret
= SETIREG(SISSR
, 0x14, tmp
);
1609 ret
|= sisusb_triggersr16(sisusb
, 0); /* sic! */
1616 static int sisusb_check_rbc(struct sisusb_usb_data
*sisusb
, int *iret
,
1624 for (i
= 0, j
= 0; i
< testn
; i
++) {
1625 ret
|= WRITEL(sisusb
->vrambase
+ j
, j
);
1629 for (i
= 0, j
= 0; i
< testn
; i
++) {
1630 ret
|= READL(sisusb
->vrambase
+ j
, &tmp
);
1641 static int sisusb_check_ranks(struct sisusb_usb_data
*sisusb
,
1642 int *iret
, int rankno
, int idx
, int bw
, const u8 rtype
[][5])
1644 int ret
= 0, i
, i2ret
;
1649 for (i
= rankno
; i
>= 1; i
--) {
1650 inc
= 1 << (rtype
[idx
][2] + rtype
[idx
][1] + rtype
[idx
][0] +
1652 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1657 inc
= 1 << (rtype
[idx
][2] + bw
/ 64 + 2);
1658 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 4);
1662 inc
= 1 << (10 + bw
/ 64);
1663 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1671 static int sisusb_get_sdram_size(struct sisusb_usb_data
*sisusb
, int *iret
,
1674 int ret
= 0, i2ret
= 0, i
, j
;
1675 static const u8 sdramtype
[13][5] = {
1676 { 2, 12, 9, 64, 0x35 },
1677 { 1, 13, 9, 64, 0x44 },
1678 { 2, 12, 8, 32, 0x31 },
1679 { 2, 11, 9, 32, 0x25 },
1680 { 1, 12, 9, 32, 0x34 },
1681 { 1, 13, 8, 32, 0x40 },
1682 { 2, 11, 8, 16, 0x21 },
1683 { 1, 12, 8, 16, 0x30 },
1684 { 1, 11, 9, 16, 0x24 },
1685 { 1, 11, 8, 8, 0x20 },
1686 { 2, 9, 8, 4, 0x01 },
1687 { 1, 10, 8, 4, 0x10 },
1688 { 1, 9, 8, 2, 0x00 }
1691 *iret
= 1; /* error */
1693 for (i
= 0; i
< 13; i
++) {
1694 ret
|= SETIREGANDOR(SISSR
, 0x13, 0x80, sdramtype
[i
][4]);
1695 for (j
= 2; j
> 0; j
--) {
1696 ret
|= sisusb_set_rank(sisusb
, &i2ret
, i
, j
, chab
,
1701 ret
|= sisusb_check_ranks(sisusb
, &i2ret
, j
, i
, bw
,
1704 *iret
= 0; /* ram size found */
1713 static int sisusb_setup_screen(struct sisusb_usb_data
*sisusb
,
1714 int clrall
, int drwfr
)
1718 int i
, length
, modex
, modey
, bpp
;
1720 modex
= 640; modey
= 480; bpp
= 2;
1722 address
= sisusb
->vrambase
; /* Clear video ram */
1725 length
= sisusb
->vramsize
;
1727 length
= modex
* bpp
* modey
;
1729 ret
= sisusb_clear_vram(sisusb
, address
, length
);
1731 if (!ret
&& drwfr
) {
1732 for (i
= 0; i
< modex
; i
++) {
1733 address
= sisusb
->vrambase
+ (i
* bpp
);
1734 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1736 address
+= (modex
* (modey
-1) * bpp
);
1737 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1740 for (i
= 0; i
< modey
; i
++) {
1741 address
= sisusb
->vrambase
+ ((i
* modex
) * bpp
);
1742 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1744 address
+= ((modex
- 1) * bpp
);
1745 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1753 static int sisusb_set_default_mode(struct sisusb_usb_data
*sisusb
,
1756 int ret
= 0, i
, j
, modex
, modey
, bpp
, du
;
1757 u8 sr31
, cr63
, tmp8
;
1758 static const char attrdata
[] = {
1759 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1760 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1761 0x01, 0x00, 0x00, 0x00
1763 static const char crtcrdata
[] = {
1764 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1765 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1766 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1769 static const char grcdata
[] = {
1770 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1773 static const char crtcdata
[] = {
1774 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1775 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1779 modex
= 640; modey
= 480; bpp
= 2;
1781 GETIREG(SISSR
, 0x31, &sr31
);
1782 GETIREG(SISCR
, 0x63, &cr63
);
1783 SETIREGOR(SISSR
, 0x01, 0x20);
1784 SETIREG(SISCR
, 0x63, cr63
& 0xbf);
1785 SETIREGOR(SISCR
, 0x17, 0x80);
1786 SETIREGOR(SISSR
, 0x1f, 0x04);
1787 SETIREGAND(SISSR
, 0x07, 0xfb);
1788 SETIREG(SISSR
, 0x00, 0x03); /* seq */
1789 SETIREG(SISSR
, 0x01, 0x21);
1790 SETIREG(SISSR
, 0x02, 0x0f);
1791 SETIREG(SISSR
, 0x03, 0x00);
1792 SETIREG(SISSR
, 0x04, 0x0e);
1793 SETREG(SISMISCW
, 0x23); /* misc */
1794 for (i
= 0; i
<= 0x18; i
++) { /* crtc */
1795 SETIREG(SISCR
, i
, crtcrdata
[i
]);
1797 for (i
= 0; i
<= 0x13; i
++) { /* att */
1798 GETREG(SISINPSTAT
, &tmp8
);
1800 SETREG(SISAR
, attrdata
[i
]);
1802 GETREG(SISINPSTAT
, &tmp8
);
1803 SETREG(SISAR
, 0x14);
1804 SETREG(SISAR
, 0x00);
1805 GETREG(SISINPSTAT
, &tmp8
);
1806 SETREG(SISAR
, 0x20);
1807 GETREG(SISINPSTAT
, &tmp8
);
1808 for (i
= 0; i
<= 0x08; i
++) { /* grc */
1809 SETIREG(SISGR
, i
, grcdata
[i
]);
1811 SETIREGAND(SISGR
, 0x05, 0xbf);
1812 for (i
= 0x0A; i
<= 0x0E; i
++) { /* clr ext */
1813 SETIREG(SISSR
, i
, 0x00);
1815 SETIREGAND(SISSR
, 0x37, 0xfe);
1816 SETREG(SISMISCW
, 0xef); /* sync */
1817 SETIREG(SISCR
, 0x11, 0x00); /* crtc */
1818 for (j
= 0x00, i
= 0; i
<= 7; i
++, j
++)
1819 SETIREG(SISCR
, j
, crtcdata
[i
]);
1821 for (j
= 0x10; i
<= 10; i
++, j
++)
1822 SETIREG(SISCR
, j
, crtcdata
[i
]);
1824 for (j
= 0x15; i
<= 12; i
++, j
++)
1825 SETIREG(SISCR
, j
, crtcdata
[i
]);
1827 for (j
= 0x0A; i
<= 15; i
++, j
++)
1828 SETIREG(SISSR
, j
, crtcdata
[i
]);
1830 SETIREG(SISSR
, 0x0E, (crtcdata
[16] & 0xE0));
1831 SETIREGANDOR(SISCR
, 0x09, 0x5f, ((crtcdata
[16] & 0x01) << 5));
1832 SETIREG(SISCR
, 0x14, 0x4f);
1833 du
= (modex
/ 16) * (bpp
* 2); /* offset/pitch */
1837 SETIREGANDOR(SISSR
, 0x0e, 0xf0, ((du
>> 8) & 0x0f));
1838 SETIREG(SISCR
, 0x13, (du
& 0xff));
1844 SETIREG(SISSR
, 0x10, tmp8
);
1845 SETIREG(SISSR
, 0x31, 0x00); /* VCLK */
1846 SETIREG(SISSR
, 0x2b, 0x1b);
1847 SETIREG(SISSR
, 0x2c, 0xe1);
1848 SETIREG(SISSR
, 0x2d, 0x01);
1849 SETIREGAND(SISSR
, 0x3d, 0xfe); /* FIFO */
1850 SETIREG(SISSR
, 0x08, 0xae);
1851 SETIREGAND(SISSR
, 0x09, 0xf0);
1852 SETIREG(SISSR
, 0x08, 0x34);
1853 SETIREGOR(SISSR
, 0x3d, 0x01);
1854 SETIREGAND(SISSR
, 0x1f, 0x3f); /* mode regs */
1855 SETIREGANDOR(SISSR
, 0x06, 0xc0, 0x0a);
1856 SETIREG(SISCR
, 0x19, 0x00);
1857 SETIREGAND(SISCR
, 0x1a, 0xfc);
1858 SETIREGAND(SISSR
, 0x0f, 0xb7);
1859 SETIREGAND(SISSR
, 0x31, 0xfb);
1860 SETIREGANDOR(SISSR
, 0x21, 0x1f, 0xa0);
1861 SETIREGAND(SISSR
, 0x32, 0xf3);
1862 SETIREGANDOR(SISSR
, 0x07, 0xf8, 0x03);
1863 SETIREG(SISCR
, 0x52, 0x6c);
1865 SETIREG(SISCR
, 0x0d, 0x00); /* adjust frame */
1866 SETIREG(SISCR
, 0x0c, 0x00);
1867 SETIREG(SISSR
, 0x0d, 0x00);
1868 SETIREGAND(SISSR
, 0x37, 0xfe);
1870 SETIREG(SISCR
, 0x32, 0x20);
1871 SETIREGAND(SISSR
, 0x01, 0xdf); /* enable display */
1872 SETIREG(SISCR
, 0x63, (cr63
& 0xbf));
1873 SETIREG(SISSR
, 0x31, (sr31
& 0xfb));
1876 SETIREG(SISSR
, 0x20, 0xa1); /* enable engines */
1877 SETIREGOR(SISSR
, 0x1e, 0x5a);
1879 SETIREG(SISSR
, 0x26, 0x01); /* disable cmdqueue */
1880 SETIREG(SISSR
, 0x27, 0x1f);
1881 SETIREG(SISSR
, 0x26, 0x00);
1884 SETIREG(SISCR
, 0x34, 0x44); /* we just set std mode #44 */
1889 static int sisusb_init_gfxcore(struct sisusb_usb_data
*sisusb
)
1891 int ret
= 0, i
, j
, bw
, chab
, iret
, retry
= 3;
1894 static const char mclktable
[] = {
1895 0x3b, 0x22, 0x01, 143,
1896 0x3b, 0x22, 0x01, 143,
1897 0x3b, 0x22, 0x01, 143,
1898 0x3b, 0x22, 0x01, 143
1900 static const char eclktable
[] = {
1901 0x3b, 0x22, 0x01, 143,
1902 0x3b, 0x22, 0x01, 143,
1903 0x3b, 0x22, 0x01, 143,
1904 0x3b, 0x22, 0x01, 143
1906 static const char ramtypetable1
[] = {
1907 0x00, 0x04, 0x60, 0x60,
1908 0x0f, 0x0f, 0x1f, 0x1f,
1909 0xba, 0xba, 0xba, 0xba,
1910 0xa9, 0xa9, 0xac, 0xac,
1911 0xa0, 0xa0, 0xa0, 0xa8,
1912 0x00, 0x00, 0x02, 0x02,
1913 0x30, 0x30, 0x40, 0x40
1915 static const char ramtypetable2
[] = {
1916 0x77, 0x77, 0x44, 0x44,
1917 0x77, 0x77, 0x44, 0x44,
1918 0x00, 0x00, 0x00, 0x00,
1919 0x5b, 0x5b, 0xab, 0xab,
1920 0x00, 0x00, 0xf0, 0xf8
1926 ret
= GETREG(SISVGAEN
, &tmp8
);
1927 ret
|= SETREG(SISVGAEN
, (tmp8
| 0x01));
1929 /* Enable GPU access to VRAM */
1930 ret
|= GETREG(SISMISCR
, &tmp8
);
1931 ret
|= SETREG(SISMISCW
, (tmp8
| 0x01));
1936 /* Reset registers */
1937 ret
|= SETIREGAND(SISCR
, 0x5b, 0xdf);
1938 ret
|= SETIREG(SISSR
, 0x05, 0x86);
1939 ret
|= SETIREGOR(SISSR
, 0x20, 0x01);
1941 ret
|= SETREG(SISMISCW
, 0x67);
1943 for (i
= 0x06; i
<= 0x1f; i
++)
1944 ret
|= SETIREG(SISSR
, i
, 0x00);
1946 for (i
= 0x21; i
<= 0x27; i
++)
1947 ret
|= SETIREG(SISSR
, i
, 0x00);
1949 for (i
= 0x31; i
<= 0x3d; i
++)
1950 ret
|= SETIREG(SISSR
, i
, 0x00);
1952 for (i
= 0x12; i
<= 0x1b; i
++)
1953 ret
|= SETIREG(SISSR
, i
, 0x00);
1955 for (i
= 0x79; i
<= 0x7c; i
++)
1956 ret
|= SETIREG(SISCR
, i
, 0x00);
1961 ret
|= SETIREG(SISCR
, 0x63, 0x80);
1963 ret
|= GETIREG(SISSR
, 0x3a, &ramtype
);
1966 ret
|= SETIREG(SISSR
, 0x28, mclktable
[ramtype
* 4]);
1967 ret
|= SETIREG(SISSR
, 0x29, mclktable
[(ramtype
* 4) + 1]);
1968 ret
|= SETIREG(SISSR
, 0x2a, mclktable
[(ramtype
* 4) + 2]);
1970 ret
|= SETIREG(SISSR
, 0x2e, eclktable
[ramtype
* 4]);
1971 ret
|= SETIREG(SISSR
, 0x2f, eclktable
[(ramtype
* 4) + 1]);
1972 ret
|= SETIREG(SISSR
, 0x30, eclktable
[(ramtype
* 4) + 2]);
1974 ret
|= SETIREG(SISSR
, 0x07, 0x18);
1975 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
1980 for (i
= 0x15, j
= 0; i
<= 0x1b; i
++, j
++) {
1981 ret
|= SETIREG(SISSR
, i
,
1982 ramtypetable1
[(j
*4) + ramtype
]);
1984 for (i
= 0x40, j
= 0; i
<= 0x44; i
++, j
++) {
1985 ret
|= SETIREG(SISCR
, i
,
1986 ramtypetable2
[(j
*4) + ramtype
]);
1989 ret
|= SETIREG(SISCR
, 0x49, 0xaa);
1991 ret
|= SETIREG(SISSR
, 0x1f, 0x00);
1992 ret
|= SETIREG(SISSR
, 0x20, 0xa0);
1993 ret
|= SETIREG(SISSR
, 0x23, 0xf6);
1994 ret
|= SETIREG(SISSR
, 0x24, 0x0d);
1995 ret
|= SETIREG(SISSR
, 0x25, 0x33);
1997 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
1999 ret
|= SETIREGOR(SISPART1
, 0x2f, 0x01);
2001 ret
|= SETIREGAND(SISCAP
, 0x3f, 0xef);
2006 ret
|= SETIREG(SISPART1
, 0x00, 0x00);
2008 ret
|= GETIREG(SISSR
, 0x13, &tmp8
);
2011 ret
|= SETIREG(SISPART1
, 0x02, 0x00);
2012 ret
|= SETIREG(SISPART1
, 0x2e, 0x08);
2014 ret
|= sisusb_read_pci_config(sisusb
, 0x50, &tmp32
);
2015 tmp32
&= 0x00f00000;
2016 tmp8
= (tmp32
== 0x100000) ? 0x33 : 0x03;
2017 ret
|= SETIREG(SISSR
, 0x25, tmp8
);
2018 tmp8
= (tmp32
== 0x100000) ? 0xaa : 0x88;
2019 ret
|= SETIREG(SISCR
, 0x49, tmp8
);
2021 ret
|= SETIREG(SISSR
, 0x27, 0x1f);
2022 ret
|= SETIREG(SISSR
, 0x31, 0x00);
2023 ret
|= SETIREG(SISSR
, 0x32, 0x11);
2024 ret
|= SETIREG(SISSR
, 0x33, 0x00);
2029 ret
|= SETIREG(SISCR
, 0x83, 0x00);
2031 ret
|= sisusb_set_default_mode(sisusb
, 0);
2033 ret
|= SETIREGAND(SISSR
, 0x21, 0xdf);
2034 ret
|= SETIREGOR(SISSR
, 0x01, 0x20);
2035 ret
|= SETIREGOR(SISSR
, 0x16, 0x0f);
2037 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
2039 /* Disable refresh */
2040 ret
|= SETIREGAND(SISSR
, 0x17, 0xf8);
2041 ret
|= SETIREGOR(SISSR
, 0x19, 0x03);
2043 ret
|= sisusb_getbuswidth(sisusb
, &bw
, &chab
);
2044 ret
|= sisusb_verify_mclk(sisusb
);
2047 ret
|= sisusb_get_sdram_size(sisusb
, &iret
, bw
, chab
);
2049 dev_err(&sisusb
->sisusb_dev
->dev
,
2050 "RAM size detection failed, assuming 8MB video RAM\n");
2051 ret
|= SETIREG(SISSR
, 0x14, 0x31);
2055 dev_err(&sisusb
->sisusb_dev
->dev
,
2056 "DDR RAM device found, assuming 8MB video RAM\n");
2057 ret
|= SETIREG(SISSR
, 0x14, 0x31);
2061 /* Enable refresh */
2062 ret
|= SETIREG(SISSR
, 0x16, ramtypetable1
[4 + ramtype
]);
2063 ret
|= SETIREG(SISSR
, 0x17, ramtypetable1
[8 + ramtype
]);
2064 ret
|= SETIREG(SISSR
, 0x19, ramtypetable1
[16 + ramtype
]);
2066 ret
|= SETIREGOR(SISSR
, 0x21, 0x20);
2068 ret
|= SETIREG(SISSR
, 0x22, 0xfb);
2069 ret
|= SETIREG(SISSR
, 0x21, 0xa5);
2088 static void sisusb_get_ramconfig(struct sisusb_usb_data
*sisusb
)
2090 u8 tmp8
, tmp82
, ramtype
;
2092 char *ramtypetext1
= NULL
;
2093 static const char ram_datarate
[4] = {'S', 'S', 'D', 'D'};
2094 static const char ram_dynamictype
[4] = {'D', 'G', 'D', 'G'};
2095 static const int busSDR
[4] = {64, 64, 128, 128};
2096 static const int busDDR
[4] = {32, 32, 64, 64};
2097 static const int busDDRA
[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2099 sisusb_getidxreg(sisusb
, SISSR
, 0x14, &tmp8
);
2100 sisusb_getidxreg(sisusb
, SISSR
, 0x15, &tmp82
);
2101 sisusb_getidxreg(sisusb
, SISSR
, 0x3a, &ramtype
);
2102 sisusb
->vramsize
= (1 << ((tmp8
& 0xf0) >> 4)) * 1024 * 1024;
2104 switch ((tmp8
>> 2) & 0x03) {
2106 ramtypetext1
= "1 ch/1 r";
2110 bw
= busSDR
[(tmp8
& 0x03)];
2114 ramtypetext1
= "1 ch/2 r";
2115 sisusb
->vramsize
<<= 1;
2116 bw
= busSDR
[(tmp8
& 0x03)];
2119 ramtypetext1
= "asymmeric";
2120 sisusb
->vramsize
+= sisusb
->vramsize
/2;
2121 bw
= busDDRA
[(tmp8
& 0x03)];
2124 ramtypetext1
= "2 channel";
2125 sisusb
->vramsize
<<= 1;
2126 bw
= busDDR
[(tmp8
& 0x03)];
2130 dev_info(&sisusb
->sisusb_dev
->dev
,
2131 "%dMB %s %cDR S%cRAM, bus width %d\n",
2132 sisusb
->vramsize
>> 20, ramtypetext1
,
2133 ram_datarate
[ramtype
], ram_dynamictype
[ramtype
], bw
);
2136 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data
*sisusb
)
2138 struct sisusb_packet packet
;
2143 packet
.header
= 0x001f;
2144 packet
.address
= 0x00000324;
2145 packet
.data
= 0x00000004;
2146 ret
= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2148 packet
.header
= 0x001f;
2149 packet
.address
= 0x00000364;
2150 packet
.data
= 0x00000004;
2151 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2153 packet
.header
= 0x001f;
2154 packet
.address
= 0x00000384;
2155 packet
.data
= 0x00000004;
2156 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2158 packet
.header
= 0x001f;
2159 packet
.address
= 0x00000100;
2160 packet
.data
= 0x00000700;
2161 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2163 packet
.header
= 0x000f;
2164 packet
.address
= 0x00000004;
2165 ret
|= sisusb_send_bridge_packet(sisusb
, 6, &packet
, 0);
2166 packet
.data
|= 0x17;
2167 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2169 /* Init BAR 0 (VRAM) */
2170 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2171 ret
|= sisusb_write_pci_config(sisusb
, 0x10, 0xfffffff0);
2172 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2174 tmp32
|= SISUSB_PCI_MEMBASE
;
2175 ret
|= sisusb_write_pci_config(sisusb
, 0x10, tmp32
);
2177 /* Init BAR 1 (MMIO) */
2178 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2179 ret
|= sisusb_write_pci_config(sisusb
, 0x14, 0xfffffff0);
2180 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2182 tmp32
|= SISUSB_PCI_MMIOBASE
;
2183 ret
|= sisusb_write_pci_config(sisusb
, 0x14, tmp32
);
2185 /* Init BAR 2 (i/o ports) */
2186 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2187 ret
|= sisusb_write_pci_config(sisusb
, 0x18, 0xfffffff0);
2188 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2190 tmp32
|= SISUSB_PCI_IOPORTBASE
;
2191 ret
|= sisusb_write_pci_config(sisusb
, 0x18, tmp32
);
2193 /* Enable memory and i/o access */
2194 ret
|= sisusb_read_pci_config(sisusb
, 0x04, &tmp32
);
2196 ret
|= sisusb_write_pci_config(sisusb
, 0x04, tmp32
);
2199 /* Some further magic */
2200 packet
.header
= 0x001f;
2201 packet
.address
= 0x00000050;
2202 packet
.data
= 0x000000ff;
2203 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2209 /* Initialize the graphics device (return 0 on success)
2210 * This initializes the net2280 as well as the PCI registers
2211 * of the graphics board.
2214 static int sisusb_init_gfxdevice(struct sisusb_usb_data
*sisusb
, int initscreen
)
2216 int ret
= 0, test
= 0;
2219 if (sisusb
->devinit
== 1) {
2220 /* Read PCI BARs and see if they have been set up */
2221 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2225 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MEMBASE
)
2228 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2232 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MMIOBASE
)
2235 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2239 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_IOPORTBASE
)
2243 /* No? So reset the device */
2244 if ((sisusb
->devinit
== 0) || (test
!= 3)) {
2246 ret
|= sisusb_do_init_gfxdevice(sisusb
);
2249 sisusb
->devinit
= 1;
2253 if (sisusb
->devinit
) {
2254 /* Initialize the graphics core */
2255 if (sisusb_init_gfxcore(sisusb
) == 0) {
2256 sisusb
->gfxinit
= 1;
2257 sisusb_get_ramconfig(sisusb
);
2258 ret
|= sisusb_set_default_mode(sisusb
, 1);
2259 ret
|= sisusb_setup_screen(sisusb
, 1, initscreen
);
2267 #ifdef INCL_SISUSB_CON
2269 /* Set up default text mode:
2270 * - Set text mode (0x03)
2271 * - Upload default font
2272 * - Upload user font (if available)
2275 int sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
)
2277 int ret
= 0, slot
= sisusb
->font_slot
, i
;
2278 const struct font_desc
*myfont
;
2281 static const char bootstring
[] =
2282 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2283 static const char bootlogo
[] = "(o_ //\\ V_/_";
2285 /* sisusb->lock is down */
2287 if (!sisusb
->SiS_Pr
)
2290 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2291 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2294 SiSUSBSetMode(sisusb
->SiS_Pr
, 0x03);
2296 myfont
= find_font("VGA8x16");
2300 tempbuf
= vmalloc(8192);
2304 for (i
= 0; i
< 256; i
++)
2305 memcpy(tempbuf
+ (i
* 32), myfont
->data
+ (i
* 16), 16);
2307 /* Upload default font */
2308 ret
= sisusbcon_do_font_op(sisusb
, 1, 0, tempbuf
, 8192,
2313 /* Upload user font (and reset current slot) */
2314 if (sisusb
->font_backup
) {
2315 ret
|= sisusbcon_do_font_op(sisusb
, 1, 2, sisusb
->font_backup
,
2316 8192, sisusb
->font_backup_512
, 1, NULL
,
2317 sisusb
->font_backup_height
, 0);
2319 sisusbcon_do_font_op(sisusb
, 1, 0, NULL
, 0, 0, 1,
2323 if (init
&& !sisusb
->scrbuf
) {
2325 tempbuf
= vmalloc(8192);
2329 tempbufb
= (u16
*)tempbuf
;
2331 *(tempbufb
++) = 0x0720;
2334 tempbufb
= (u16
*)tempbuf
;
2335 while (bootlogo
[i
]) {
2336 *(tempbufb
++) = 0x0700 | bootlogo
[i
++];
2342 tempbufb
= (u16
*)tempbuf
+ 6;
2343 while (bootstring
[i
])
2344 *(tempbufb
++) = 0x0700 | bootstring
[i
++];
2346 ret
|= sisusb_copy_memory(sisusb
, tempbuf
,
2347 sisusb
->vrambase
, 8192);
2353 } else if (sisusb
->scrbuf
) {
2354 ret
|= sisusb_copy_memory(sisusb
, (char *)sisusb
->scrbuf
,
2355 sisusb
->vrambase
, sisusb
->scrbuf_size
);
2358 if (sisusb
->sisusb_cursor_size_from
>= 0 &&
2359 sisusb
->sisusb_cursor_size_to
>= 0) {
2360 sisusb_setidxreg(sisusb
, SISCR
, 0x0a,
2361 sisusb
->sisusb_cursor_size_from
);
2362 sisusb_setidxregandor(sisusb
, SISCR
, 0x0b, 0xe0,
2363 sisusb
->sisusb_cursor_size_to
);
2365 sisusb_setidxreg(sisusb
, SISCR
, 0x0a, 0x2d);
2366 sisusb_setidxreg(sisusb
, SISCR
, 0x0b, 0x0e);
2367 sisusb
->sisusb_cursor_size_to
= -1;
2370 slot
= sisusb
->sisusb_cursor_loc
;
2374 sisusb
->sisusb_cursor_loc
= -1;
2375 sisusb
->bad_cursor_pos
= 1;
2377 sisusb_set_cursor(sisusb
, slot
);
2379 sisusb_setidxreg(sisusb
, SISCR
, 0x0c, (sisusb
->cur_start_addr
>> 8));
2380 sisusb_setidxreg(sisusb
, SISCR
, 0x0d, (sisusb
->cur_start_addr
& 0xff));
2382 sisusb
->textmodedestroyed
= 0;
2384 /* sisusb->lock is down */
2393 static int sisusb_open(struct inode
*inode
, struct file
*file
)
2395 struct sisusb_usb_data
*sisusb
;
2396 struct usb_interface
*interface
;
2397 int subminor
= iminor(inode
);
2399 interface
= usb_find_interface(&sisusb_driver
, subminor
);
2403 sisusb
= usb_get_intfdata(interface
);
2407 mutex_lock(&sisusb
->lock
);
2409 if (!sisusb
->present
|| !sisusb
->ready
) {
2410 mutex_unlock(&sisusb
->lock
);
2414 if (sisusb
->isopen
) {
2415 mutex_unlock(&sisusb
->lock
);
2419 if (!sisusb
->devinit
) {
2420 if (sisusb
->sisusb_dev
->speed
== USB_SPEED_HIGH
||
2421 sisusb
->sisusb_dev
->speed
>= USB_SPEED_SUPER
) {
2422 if (sisusb_init_gfxdevice(sisusb
, 0)) {
2423 mutex_unlock(&sisusb
->lock
);
2424 dev_err(&sisusb
->sisusb_dev
->dev
,
2425 "Failed to initialize device\n");
2429 mutex_unlock(&sisusb
->lock
);
2430 dev_err(&sisusb
->sisusb_dev
->dev
,
2431 "Device not attached to USB 2.0 hub\n");
2436 /* Increment usage count for our sisusb */
2437 kref_get(&sisusb
->kref
);
2441 file
->private_data
= sisusb
;
2443 mutex_unlock(&sisusb
->lock
);
2448 void sisusb_delete(struct kref
*kref
)
2450 struct sisusb_usb_data
*sisusb
= to_sisusb_dev(kref
);
2455 usb_put_dev(sisusb
->sisusb_dev
);
2457 sisusb
->sisusb_dev
= NULL
;
2458 sisusb_free_buffers(sisusb
);
2459 sisusb_free_urbs(sisusb
);
2460 #ifdef INCL_SISUSB_CON
2461 kfree(sisusb
->SiS_Pr
);
2466 static int sisusb_release(struct inode
*inode
, struct file
*file
)
2468 struct sisusb_usb_data
*sisusb
;
2470 sisusb
= file
->private_data
;
2474 mutex_lock(&sisusb
->lock
);
2476 if (sisusb
->present
) {
2477 /* Wait for all URBs to finish if device still present */
2478 if (!sisusb_wait_all_out_complete(sisusb
))
2479 sisusb_kill_all_busy(sisusb
);
2483 file
->private_data
= NULL
;
2485 mutex_unlock(&sisusb
->lock
);
2487 /* decrement the usage count on our device */
2488 kref_put(&sisusb
->kref
, sisusb_delete
);
2493 static ssize_t
sisusb_read(struct file
*file
, char __user
*buffer
,
2494 size_t count
, loff_t
*ppos
)
2496 struct sisusb_usb_data
*sisusb
;
2497 ssize_t bytes_read
= 0;
2503 sisusb
= file
->private_data
;
2507 mutex_lock(&sisusb
->lock
);
2510 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2511 mutex_unlock(&sisusb
->lock
);
2515 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2516 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2518 address
= (*ppos
) - SISUSB_PCI_PSEUDO_IOPORTBASE
+
2519 SISUSB_PCI_IOPORTBASE
;
2522 * Byte, word and long(32) can be read. As this
2523 * emulates inX instructions, the data returned is
2524 * in machine-endianness.
2528 if (sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
,
2531 else if (put_user(buf8
, (u8 __user
*)buffer
))
2539 if (sisusb_read_memio_word(sisusb
, SISUSB_TYPE_IO
,
2542 else if (put_user(buf16
, (u16 __user
*)buffer
))
2550 if (sisusb_read_memio_long(sisusb
, SISUSB_TYPE_IO
,
2553 else if (put_user(buf32
, (u32 __user
*)buffer
))
2565 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&& (*ppos
) <
2566 SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2568 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MEMBASE
+
2572 * Remember: Data delivered is never endian-corrected
2574 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2575 NULL
, count
, buffer
, &bytes_read
);
2580 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2581 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+
2582 SISUSB_PCI_MMIOSIZE
) {
2584 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MMIOBASE
+
2585 SISUSB_PCI_MMIOBASE
;
2588 * Remember: Data delivered is never endian-corrected
2590 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2591 NULL
, count
, buffer
, &bytes_read
);
2596 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2597 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ 0x5c) {
2600 mutex_unlock(&sisusb
->lock
);
2604 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2606 /* Read PCI config register
2607 * Return value delivered in machine endianness.
2609 if (sisusb_read_pci_config(sisusb
, address
, &buf32
))
2611 else if (put_user(buf32
, (u32 __user
*)buffer
))
2622 (*ppos
) += bytes_read
;
2624 mutex_unlock(&sisusb
->lock
);
2626 return errno
? errno
: bytes_read
;
2629 static ssize_t
sisusb_write(struct file
*file
, const char __user
*buffer
,
2630 size_t count
, loff_t
*ppos
)
2632 struct sisusb_usb_data
*sisusb
;
2634 ssize_t bytes_written
= 0;
2639 sisusb
= file
->private_data
;
2643 mutex_lock(&sisusb
->lock
);
2646 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2647 mutex_unlock(&sisusb
->lock
);
2651 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2652 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2654 address
= (*ppos
) - SISUSB_PCI_PSEUDO_IOPORTBASE
+
2655 SISUSB_PCI_IOPORTBASE
;
2658 * Byte, word and long(32) can be written. As this
2659 * emulates outX instructions, the data is expected
2660 * in machine-endianness.
2664 if (get_user(buf8
, (u8 __user
*)buffer
))
2666 else if (sisusb_write_memio_byte(sisusb
,
2667 SISUSB_TYPE_IO
, address
, buf8
))
2675 if (get_user(buf16
, (u16 __user
*)buffer
))
2677 else if (sisusb_write_memio_word(sisusb
,
2678 SISUSB_TYPE_IO
, address
, buf16
))
2686 if (get_user(buf32
, (u32 __user
*)buffer
))
2688 else if (sisusb_write_memio_long(sisusb
,
2689 SISUSB_TYPE_IO
, address
, buf32
))
2700 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2701 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+
2704 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MEMBASE
+
2708 * Buffer is copied 1:1, therefore, on big-endian
2709 * machines, the data must be swapped by userland
2710 * in advance (if applicable; no swapping in 8bpp
2711 * mode or if YUV data is being transferred).
2713 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2714 count
, buffer
, 0, &bytes_written
);
2717 errno
= bytes_written
;
2719 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2720 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+
2721 SISUSB_PCI_MMIOSIZE
) {
2723 address
= (*ppos
) - SISUSB_PCI_PSEUDO_MMIOBASE
+
2724 SISUSB_PCI_MMIOBASE
;
2727 * Buffer is copied 1:1, therefore, on big-endian
2728 * machines, the data must be swapped by userland
2731 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2732 count
, buffer
, 0, &bytes_written
);
2735 errno
= bytes_written
;
2737 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2738 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+
2739 SISUSB_PCI_PCONFSIZE
) {
2742 mutex_unlock(&sisusb
->lock
);
2746 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2748 /* Write PCI config register.
2749 * Given value expected in machine endianness.
2751 if (get_user(buf32
, (u32 __user
*)buffer
))
2753 else if (sisusb_write_pci_config(sisusb
, address
, buf32
))
2766 (*ppos
) += bytes_written
;
2768 mutex_unlock(&sisusb
->lock
);
2770 return errno
? errno
: bytes_written
;
2773 static loff_t
sisusb_lseek(struct file
*file
, loff_t offset
, int orig
)
2775 struct sisusb_usb_data
*sisusb
;
2778 sisusb
= file
->private_data
;
2782 mutex_lock(&sisusb
->lock
);
2785 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2786 mutex_unlock(&sisusb
->lock
);
2790 ret
= no_seek_end_llseek(file
, offset
, orig
);
2792 mutex_unlock(&sisusb
->lock
);
2796 static int sisusb_handle_command(struct sisusb_usb_data
*sisusb
,
2797 struct sisusb_command
*y
, unsigned long arg
)
2799 int retval
, port
, length
;
2802 /* All our commands require the device
2803 * to be initialized.
2805 if (!sisusb
->devinit
)
2809 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2810 SISUSB_PCI_IOPORTBASE
;
2812 switch (y
->operation
) {
2814 retval
= sisusb_getidxreg(sisusb
, port
, y
->data0
, &y
->data1
);
2816 if (copy_to_user((void __user
*)arg
, y
, sizeof(*y
)))
2822 retval
= sisusb_setidxreg(sisusb
, port
, y
->data0
, y
->data1
);
2826 retval
= sisusb_setidxregor(sisusb
, port
, y
->data0
, y
->data1
);
2830 retval
= sisusb_setidxregand(sisusb
, port
, y
->data0
, y
->data1
);
2833 case SUCMD_SETANDOR
:
2834 retval
= sisusb_setidxregandor(sisusb
, port
, y
->data0
,
2835 y
->data1
, y
->data2
);
2839 retval
= sisusb_setidxregmask(sisusb
, port
, y
->data0
,
2840 y
->data1
, y
->data2
);
2844 /* Gfx core must be initialized */
2845 if (!sisusb
->gfxinit
)
2848 length
= (y
->data0
<< 16) | (y
->data1
<< 8) | y
->data2
;
2849 address
= y
->data3
- SISUSB_PCI_PSEUDO_MEMBASE
+
2851 retval
= sisusb_clear_vram(sisusb
, address
, length
);
2854 case SUCMD_HANDLETEXTMODE
:
2856 #ifdef INCL_SISUSB_CON
2857 /* Gfx core must be initialized, SiS_Pr must exist */
2858 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2863 retval
= sisusb_reset_text_mode(sisusb
, 0);
2866 sisusb
->textmodedestroyed
= 1;
2872 #ifdef INCL_SISUSB_CON
2874 /* Gfx core must be initialized, SiS_Pr must exist */
2875 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2880 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2881 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2883 if (SiSUSBSetMode(sisusb
->SiS_Pr
, y
->data3
))
2888 case SUCMD_SETVESAMODE
:
2889 /* Gfx core must be initialized, SiS_Pr must exist */
2890 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
2895 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2896 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2898 if (SiSUSBSetVESAMode(sisusb
->SiS_Pr
, y
->data3
))
2914 static long sisusb_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
2916 struct sisusb_usb_data
*sisusb
;
2917 struct sisusb_info x
;
2918 struct sisusb_command y
;
2920 u32 __user
*argp
= (u32 __user
*)arg
;
2922 sisusb
= file
->private_data
;
2926 mutex_lock(&sisusb
->lock
);
2929 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2935 case SISUSB_GET_CONFIG_SIZE
:
2937 if (put_user(sizeof(x
), argp
))
2942 case SISUSB_GET_CONFIG
:
2944 x
.sisusb_id
= SISUSB_ID
;
2945 x
.sisusb_version
= SISUSB_VERSION
;
2946 x
.sisusb_revision
= SISUSB_REVISION
;
2947 x
.sisusb_patchlevel
= SISUSB_PATCHLEVEL
;
2948 x
.sisusb_gfxinit
= sisusb
->gfxinit
;
2949 x
.sisusb_vrambase
= SISUSB_PCI_PSEUDO_MEMBASE
;
2950 x
.sisusb_mmiobase
= SISUSB_PCI_PSEUDO_MMIOBASE
;
2951 x
.sisusb_iobase
= SISUSB_PCI_PSEUDO_IOPORTBASE
;
2952 x
.sisusb_pcibase
= SISUSB_PCI_PSEUDO_PCIBASE
;
2953 x
.sisusb_vramsize
= sisusb
->vramsize
;
2954 x
.sisusb_minor
= sisusb
->minor
;
2955 x
.sisusb_fbdevactive
= 0;
2956 #ifdef INCL_SISUSB_CON
2957 x
.sisusb_conactive
= sisusb
->haveconsole
? 1 : 0;
2959 x
.sisusb_conactive
= 0;
2961 memset(x
.sisusb_reserved
, 0, sizeof(x
.sisusb_reserved
));
2963 if (copy_to_user((void __user
*)arg
, &x
, sizeof(x
)))
2968 case SISUSB_COMMAND
:
2970 if (copy_from_user(&y
, (void __user
*)arg
, sizeof(y
)))
2973 retval
= sisusb_handle_command(sisusb
, &y
, arg
);
2983 mutex_unlock(&sisusb
->lock
);
2987 #ifdef SISUSB_NEW_CONFIG_COMPAT
2988 static long sisusb_compat_ioctl(struct file
*f
, unsigned int cmd
,
2994 case SISUSB_GET_CONFIG_SIZE
:
2995 case SISUSB_GET_CONFIG
:
2996 case SISUSB_COMMAND
:
2997 retval
= sisusb_ioctl(f
, cmd
, arg
);
3001 return -ENOIOCTLCMD
;
3006 static const struct file_operations usb_sisusb_fops
= {
3007 .owner
= THIS_MODULE
,
3008 .open
= sisusb_open
,
3009 .release
= sisusb_release
,
3010 .read
= sisusb_read
,
3011 .write
= sisusb_write
,
3012 .llseek
= sisusb_lseek
,
3013 #ifdef SISUSB_NEW_CONFIG_COMPAT
3014 .compat_ioctl
= sisusb_compat_ioctl
,
3016 .unlocked_ioctl
= sisusb_ioctl
3019 static struct usb_class_driver usb_sisusb_class
= {
3020 .name
= "sisusbvga%d",
3021 .fops
= &usb_sisusb_fops
,
3022 .minor_base
= SISUSB_MINOR
3025 static int sisusb_probe(struct usb_interface
*intf
,
3026 const struct usb_device_id
*id
)
3028 struct usb_device
*dev
= interface_to_usbdev(intf
);
3029 struct sisusb_usb_data
*sisusb
;
3032 dev_info(&dev
->dev
, "USB2VGA dongle found at address %d\n",
3035 /* Allocate memory for our private */
3036 sisusb
= kzalloc(sizeof(*sisusb
), GFP_KERNEL
);
3040 kref_init(&sisusb
->kref
);
3042 mutex_init(&(sisusb
->lock
));
3044 /* Register device */
3045 retval
= usb_register_dev(intf
, &usb_sisusb_class
);
3047 dev_err(&sisusb
->sisusb_dev
->dev
,
3048 "Failed to get a minor for device %d\n",
3054 sisusb
->sisusb_dev
= dev
;
3055 sisusb
->minor
= intf
->minor
;
3056 sisusb
->vrambase
= SISUSB_PCI_MEMBASE
;
3057 sisusb
->mmiobase
= SISUSB_PCI_MMIOBASE
;
3058 sisusb
->mmiosize
= SISUSB_PCI_MMIOSIZE
;
3059 sisusb
->ioportbase
= SISUSB_PCI_IOPORTBASE
;
3060 /* Everything else is zero */
3062 /* Allocate buffers */
3063 sisusb
->ibufsize
= SISUSB_IBUF_SIZE
;
3064 sisusb
->ibuf
= kmalloc(SISUSB_IBUF_SIZE
, GFP_KERNEL
);
3065 if (!sisusb
->ibuf
) {
3070 sisusb
->numobufs
= 0;
3071 sisusb
->obufsize
= SISUSB_OBUF_SIZE
;
3072 for (i
= 0; i
< NUMOBUFS
; i
++) {
3073 sisusb
->obuf
[i
] = kmalloc(SISUSB_OBUF_SIZE
, GFP_KERNEL
);
3074 if (!sisusb
->obuf
[i
]) {
3085 sisusb
->sisurbin
= usb_alloc_urb(0, GFP_KERNEL
);
3086 if (!sisusb
->sisurbin
) {
3090 sisusb
->completein
= 1;
3092 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
3093 sisusb
->sisurbout
[i
] = usb_alloc_urb(0, GFP_KERNEL
);
3094 if (!sisusb
->sisurbout
[i
]) {
3098 sisusb
->urbout_context
[i
].sisusb
= (void *)sisusb
;
3099 sisusb
->urbout_context
[i
].urbindex
= i
;
3100 sisusb
->urbstatus
[i
] = 0;
3103 dev_info(&sisusb
->sisusb_dev
->dev
, "Allocated %d output buffers\n",
3106 #ifdef INCL_SISUSB_CON
3107 /* Allocate our SiS_Pr */
3108 sisusb
->SiS_Pr
= kmalloc(sizeof(struct SiS_Private
), GFP_KERNEL
);
3109 if (!sisusb
->SiS_Pr
) {
3115 /* Do remaining init stuff */
3117 init_waitqueue_head(&sisusb
->wait_q
);
3119 usb_set_intfdata(intf
, sisusb
);
3121 usb_get_dev(sisusb
->sisusb_dev
);
3123 sisusb
->present
= 1;
3125 if (dev
->speed
== USB_SPEED_HIGH
|| dev
->speed
>= USB_SPEED_SUPER
) {
3127 #ifdef INCL_SISUSB_CON
3128 if (sisusb_first_vc
> 0 && sisusb_last_vc
> 0 &&
3129 sisusb_first_vc
<= sisusb_last_vc
&&
3130 sisusb_last_vc
<= MAX_NR_CONSOLES
)
3133 if (sisusb_init_gfxdevice(sisusb
, initscreen
))
3134 dev_err(&sisusb
->sisusb_dev
->dev
,
3135 "Failed to early initialize device\n");
3138 dev_info(&sisusb
->sisusb_dev
->dev
,
3139 "Not attached to USB 2.0 hub, deferring init\n");
3143 #ifdef SISUSBENDIANTEST
3144 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST ***\n");
3145 sisusb_testreadwrite(sisusb
);
3146 dev_dbg(&sisusb
->sisusb_dev
->dev
, "*** RWTEST END ***\n");
3149 #ifdef INCL_SISUSB_CON
3150 sisusb_console_init(sisusb
, sisusb_first_vc
, sisusb_last_vc
);
3156 sisusb_free_urbs(sisusb
);
3158 sisusb_free_buffers(sisusb
);
3160 usb_deregister_dev(intf
, &usb_sisusb_class
);
3166 static void sisusb_disconnect(struct usb_interface
*intf
)
3168 struct sisusb_usb_data
*sisusb
;
3170 /* This should *not* happen */
3171 sisusb
= usb_get_intfdata(intf
);
3175 #ifdef INCL_SISUSB_CON
3176 sisusb_console_exit(sisusb
);
3179 usb_deregister_dev(intf
, &usb_sisusb_class
);
3181 mutex_lock(&sisusb
->lock
);
3183 /* Wait for all URBs to complete and kill them in case (MUST do) */
3184 if (!sisusb_wait_all_out_complete(sisusb
))
3185 sisusb_kill_all_busy(sisusb
);
3187 usb_set_intfdata(intf
, NULL
);
3189 sisusb
->present
= 0;
3192 mutex_unlock(&sisusb
->lock
);
3194 /* decrement our usage count */
3195 kref_put(&sisusb
->kref
, sisusb_delete
);
3198 static const struct usb_device_id sisusb_table
[] = {
3199 { USB_DEVICE(0x0711, 0x0550) },
3200 { USB_DEVICE(0x0711, 0x0900) },
3201 { USB_DEVICE(0x0711, 0x0901) },
3202 { USB_DEVICE(0x0711, 0x0902) },
3203 { USB_DEVICE(0x0711, 0x0903) },
3204 { USB_DEVICE(0x0711, 0x0918) },
3205 { USB_DEVICE(0x0711, 0x0920) },
3206 { USB_DEVICE(0x0711, 0x0950) },
3207 { USB_DEVICE(0x0711, 0x5200) },
3208 { USB_DEVICE(0x182d, 0x021c) },
3209 { USB_DEVICE(0x182d, 0x0269) },
3213 MODULE_DEVICE_TABLE(usb
, sisusb_table
);
3215 static struct usb_driver sisusb_driver
= {
3217 .probe
= sisusb_probe
,
3218 .disconnect
= sisusb_disconnect
,
3219 .id_table
= sisusb_table
,
3222 static int __init
usb_sisusb_init(void)
3225 #ifdef INCL_SISUSB_CON
3226 sisusb_init_concode();
3229 return usb_register(&sisusb_driver
);
3232 static void __exit
usb_sisusb_exit(void)
3234 usb_deregister(&sisusb_driver
);
3237 module_init(usb_sisusb_init
);
3238 module_exit(usb_sisusb_exit
);
3240 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3241 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3242 MODULE_LICENSE("GPL");