2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
8 * If distributed as part of the Linux kernel, this code is licensed under the
11 * Otherwise, the following license terms apply:
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific psisusbr written permission.
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
39 #include <linux/mutex.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/errno.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/slab.h>
47 #include <linux/spinlock.h>
48 #include <linux/kref.h>
49 #include <linux/usb.h>
50 #include <linux/smp_lock.h>
51 #include <linux/vmalloc.h>
54 #include "sisusb_init.h"
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
60 #define SISUSB_DONTSYNC
62 /* Forward declarations / clean-up routines */
64 #ifdef INCL_SISUSB_CON
65 static int sisusb_first_vc
= 0;
66 static int sisusb_last_vc
= 0;
67 module_param_named(first
, sisusb_first_vc
, int, 0);
68 module_param_named(last
, sisusb_last_vc
, int, 0);
69 MODULE_PARM_DESC(first
, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
70 MODULE_PARM_DESC(last
, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
73 static struct usb_driver sisusb_driver
;
75 DEFINE_MUTEX(disconnect_mutex
);
78 sisusb_free_buffers(struct sisusb_usb_data
*sisusb
)
82 for (i
= 0; i
< NUMOBUFS
; i
++) {
83 if (sisusb
->obuf
[i
]) {
84 usb_buffer_free(sisusb
->sisusb_dev
, sisusb
->obufsize
,
85 sisusb
->obuf
[i
], sisusb
->transfer_dma_out
[i
]);
86 sisusb
->obuf
[i
] = NULL
;
90 usb_buffer_free(sisusb
->sisusb_dev
, sisusb
->ibufsize
,
91 sisusb
->ibuf
, sisusb
->transfer_dma_in
);
97 sisusb_free_urbs(struct sisusb_usb_data
*sisusb
)
101 for (i
= 0; i
< NUMOBUFS
; i
++) {
102 usb_free_urb(sisusb
->sisurbout
[i
]);
103 sisusb
->sisurbout
[i
] = NULL
;
105 usb_free_urb(sisusb
->sisurbin
);
106 sisusb
->sisurbin
= NULL
;
109 /* Level 0: USB transport layer */
113 /* out-urb management */
115 /* Return 1 if all free, 0 otherwise */
117 sisusb_all_free(struct sisusb_usb_data
*sisusb
)
121 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
123 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
131 /* Kill all busy URBs */
133 sisusb_kill_all_busy(struct sisusb_usb_data
*sisusb
)
137 if (sisusb_all_free(sisusb
))
140 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
142 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
143 usb_kill_urb(sisusb
->sisurbout
[i
]);
148 /* Return 1 if ok, 0 if error (not all complete within timeout) */
150 sisusb_wait_all_out_complete(struct sisusb_usb_data
*sisusb
)
152 int timeout
= 5 * HZ
, i
= 1;
154 wait_event_timeout(sisusb
->wait_q
,
155 (i
= sisusb_all_free(sisusb
)),
162 sisusb_outurb_available(struct sisusb_usb_data
*sisusb
)
166 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
168 if ((sisusb
->urbstatus
[i
] & (SU_URB_BUSY
|SU_URB_ALLOC
)) == 0)
177 sisusb_get_free_outbuf(struct sisusb_usb_data
*sisusb
)
179 int i
, timeout
= 5 * HZ
;
181 wait_event_timeout(sisusb
->wait_q
,
182 ((i
= sisusb_outurb_available(sisusb
)) >= 0),
189 sisusb_alloc_outbuf(struct sisusb_usb_data
*sisusb
)
193 i
= sisusb_outurb_available(sisusb
);
196 sisusb
->urbstatus
[i
] |= SU_URB_ALLOC
;
202 sisusb_free_outbuf(struct sisusb_usb_data
*sisusb
, int index
)
204 if ((index
>= 0) && (index
< sisusb
->numobufs
))
205 sisusb
->urbstatus
[index
] &= ~SU_URB_ALLOC
;
208 /* completion callback */
211 sisusb_bulk_completeout(struct urb
*urb
)
213 struct sisusb_urb_context
*context
= urb
->context
;
214 struct sisusb_usb_data
*sisusb
;
219 sisusb
= context
->sisusb
;
221 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
224 #ifndef SISUSB_DONTSYNC
225 if (context
->actual_length
)
226 *(context
->actual_length
) += urb
->actual_length
;
229 sisusb
->urbstatus
[context
->urbindex
] &= ~SU_URB_BUSY
;
230 wake_up(&sisusb
->wait_q
);
234 sisusb_bulkout_msg(struct sisusb_usb_data
*sisusb
, int index
, unsigned int pipe
, void *data
,
235 int len
, int *actual_length
, int timeout
, unsigned int tflags
,
236 dma_addr_t transfer_dma
)
238 struct urb
*urb
= sisusb
->sisurbout
[index
];
239 int retval
, byteswritten
= 0;
242 urb
->transfer_flags
= 0;
244 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
245 sisusb_bulk_completeout
, &sisusb
->urbout_context
[index
]);
247 urb
->transfer_flags
|= tflags
;
248 urb
->actual_length
= 0;
250 if ((urb
->transfer_dma
= transfer_dma
))
251 urb
->transfer_flags
|= URB_NO_TRANSFER_DMA_MAP
;
254 sisusb
->urbout_context
[index
].actual_length
= (timeout
) ?
255 NULL
: actual_length
;
257 /* Declare this urb/buffer in use */
258 sisusb
->urbstatus
[index
] |= SU_URB_BUSY
;
261 retval
= usb_submit_urb(urb
, GFP_ATOMIC
);
263 /* If OK, and if timeout > 0, wait for completion */
264 if ((retval
== 0) && timeout
) {
265 wait_event_timeout(sisusb
->wait_q
,
266 (!(sisusb
->urbstatus
[index
] & SU_URB_BUSY
)),
268 if (sisusb
->urbstatus
[index
] & SU_URB_BUSY
) {
269 /* URB timed out... kill it and report error */
273 /* Otherwise, report urb status */
274 retval
= urb
->status
;
275 byteswritten
= urb
->actual_length
;
280 *actual_length
= byteswritten
;
287 /* completion callback */
290 sisusb_bulk_completein(struct urb
*urb
)
292 struct sisusb_usb_data
*sisusb
= urb
->context
;
294 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
297 sisusb
->completein
= 1;
298 wake_up(&sisusb
->wait_q
);
302 sisusb_bulkin_msg(struct sisusb_usb_data
*sisusb
, unsigned int pipe
, void *data
, int len
,
303 int *actual_length
, int timeout
, unsigned int tflags
, dma_addr_t transfer_dma
)
305 struct urb
*urb
= sisusb
->sisurbin
;
306 int retval
, readbytes
= 0;
308 urb
->transfer_flags
= 0;
310 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
311 sisusb_bulk_completein
, sisusb
);
313 urb
->transfer_flags
|= tflags
;
314 urb
->actual_length
= 0;
316 if ((urb
->transfer_dma
= transfer_dma
))
317 urb
->transfer_flags
|= URB_NO_TRANSFER_DMA_MAP
;
319 sisusb
->completein
= 0;
320 retval
= usb_submit_urb(urb
, GFP_ATOMIC
);
322 wait_event_timeout(sisusb
->wait_q
, sisusb
->completein
, timeout
);
323 if (!sisusb
->completein
) {
324 /* URB timed out... kill it and report error */
328 /* URB completed within timout */
329 retval
= urb
->status
;
330 readbytes
= urb
->actual_length
;
335 *actual_length
= readbytes
;
343 /* Send a bulk message of variable size
345 * To copy the data from userspace, give pointer to "userbuffer",
346 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
347 * both of these are NULL, it is assumed, that the transfer
348 * buffer "sisusb->obuf[index]" is set up with the data to send.
349 * Index is ignored if either kernbuffer or userbuffer is set.
350 * If async is nonzero, URBs will be sent without waiting for
351 * completion of the previous URB.
353 * (return 0 on success)
356 static int sisusb_send_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
357 char *kernbuffer
, const char __user
*userbuffer
, int index
,
358 ssize_t
*bytes_written
, unsigned int tflags
, int async
)
360 int result
= 0, retry
, count
= len
;
361 int passsize
, thispass
, transferred_len
= 0;
362 int fromuser
= (userbuffer
!= NULL
) ? 1 : 0;
363 int fromkern
= (kernbuffer
!= NULL
) ? 1 : 0;
367 (*bytes_written
) = 0;
370 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
373 /* If we copy data from kernel or userspace, force the
374 * allocation of a buffer/urb. If we have the data in
375 * the transfer buffer[index] already, reuse the buffer/URB
376 * if the length is > buffer size. (So, transmitting
377 * large data amounts directly from the transfer buffer
378 * treats the buffer as a ring buffer. However, we need
379 * to sync in this case.)
381 if (fromuser
|| fromkern
)
383 else if (len
> sisusb
->obufsize
)
386 pipe
= usb_sndbulkpipe(sisusb
->sisusb_dev
, ep
);
389 passsize
= thispass
= (sisusb
->obufsize
< count
) ?
390 sisusb
->obufsize
: count
;
393 index
= sisusb_get_free_outbuf(sisusb
);
398 buffer
= sisusb
->obuf
[index
];
402 if (copy_from_user(buffer
, userbuffer
, passsize
))
405 userbuffer
+= passsize
;
407 } else if (fromkern
) {
409 memcpy(buffer
, kernbuffer
, passsize
);
410 kernbuffer
+= passsize
;
417 if (!sisusb
->sisusb_dev
)
420 result
= sisusb_bulkout_msg(sisusb
,
428 sisusb
->transfer_dma_out
[index
]);
430 if (result
== -ETIMEDOUT
) {
432 /* Will not happen if async */
438 } else if ((result
== 0) && !async
&& transferred_len
) {
440 thispass
-= transferred_len
;
442 if (sisusb
->transfer_dma_out
) {
443 /* If DMA, copy remaining
444 * to beginning of buffer
447 buffer
+ transferred_len
,
450 /* If not DMA, simply increase
453 buffer
+= transferred_len
;
464 (*bytes_written
) += passsize
;
467 /* Force new allocation in next iteration */
468 if (fromuser
|| fromkern
)
474 #ifdef SISUSB_DONTSYNC
475 (*bytes_written
) = len
;
476 /* Some URBs/buffers might be busy */
478 sisusb_wait_all_out_complete(sisusb
);
479 (*bytes_written
) = transferred_len
;
480 /* All URBs and all buffers are available */
484 return ((*bytes_written
) == len
) ? 0 : -EIO
;
487 /* Receive a bulk message of variable size
489 * To copy the data to userspace, give pointer to "userbuffer",
490 * to copy to kernel memory, give "kernbuffer". One of them
491 * MUST be set. (There is no technique for letting the caller
492 * read directly from the ibuf.)
496 static int sisusb_recv_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
497 void *kernbuffer
, char __user
*userbuffer
, ssize_t
*bytes_read
,
500 int result
= 0, retry
, count
= len
;
501 int bufsize
, thispass
, transferred_len
;
508 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
511 pipe
= usb_rcvbulkpipe(sisusb
->sisusb_dev
, ep
);
512 buffer
= sisusb
->ibuf
;
513 bufsize
= sisusb
->ibufsize
;
517 #ifdef SISUSB_DONTSYNC
518 if (!(sisusb_wait_all_out_complete(sisusb
)))
524 if (!sisusb
->sisusb_dev
)
527 thispass
= (bufsize
< count
) ? bufsize
: count
;
529 result
= sisusb_bulkin_msg(sisusb
,
536 sisusb
->transfer_dma_in
);
539 thispass
= transferred_len
;
541 else if (result
== -ETIMEDOUT
) {
554 (*bytes_read
) += thispass
;
559 if (copy_to_user(userbuffer
, buffer
, thispass
))
562 userbuffer
+= thispass
;
566 memcpy(kernbuffer
, buffer
, thispass
);
567 kernbuffer
+= thispass
;
575 return ((*bytes_read
) == len
) ? 0 : -EIO
;
578 static int sisusb_send_packet(struct sisusb_usb_data
*sisusb
, int len
,
579 struct sisusb_packet
*packet
)
582 ssize_t bytes_transferred
= 0;
588 #ifdef SISUSB_DONTSYNC
589 if (!(sisusb_wait_all_out_complete(sisusb
)))
593 /* Eventually correct endianness */
594 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
596 /* 1. send the packet */
597 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_GFX_OUT
, len
,
598 (char *)packet
, NULL
, 0, &bytes_transferred
, 0, 0);
600 if ((ret
== 0) && (len
== 6)) {
602 /* 2. if packet len == 6, it means we read, so wait for 32bit
603 * return value and write it to packet->data
605 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_GFX_IN
, 4,
606 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
608 packet
->data
= le32_to_cpu(tmp
);
614 static int sisusb_send_bridge_packet(struct sisusb_usb_data
*sisusb
, int len
,
615 struct sisusb_packet
*packet
,
619 ssize_t bytes_transferred
= 0;
625 #ifdef SISUSB_DONTSYNC
626 if (!(sisusb_wait_all_out_complete(sisusb
)))
630 /* Eventually correct endianness */
631 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
633 /* 1. send the packet */
634 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_OUT
, len
,
635 (char *)packet
, NULL
, 0, &bytes_transferred
, tflags
, 0);
637 if ((ret
== 0) && (len
== 6)) {
639 /* 2. if packet len == 6, it means we read, so wait for 32bit
640 * return value and write it to packet->data
642 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_IN
, 4,
643 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
645 packet
->data
= le32_to_cpu(tmp
);
651 /* access video memory and mmio (return 0 on success) */
655 /* The following routines assume being used to transfer byte, word,
658 * - the write routines expect "data" in machine endianness format.
659 * The data will be converted to leXX in sisusb_xxx_packet.
660 * - the read routines can expect read data in machine-endianess.
663 static int sisusb_write_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
666 struct sisusb_packet packet
;
669 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
670 packet
.address
= addr
& ~3;
671 packet
.data
= data
<< ((addr
& 3) << 3);
672 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
676 static int sisusb_write_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
679 struct sisusb_packet packet
;
682 packet
.address
= addr
& ~3;
686 packet
.header
= (type
<< 6) | 0x0003;
687 packet
.data
= (u32
)data
;
688 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
691 packet
.header
= (type
<< 6) | 0x0006;
692 packet
.data
= (u32
)data
<< 8;
693 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
696 packet
.header
= (type
<< 6) | 0x000c;
697 packet
.data
= (u32
)data
<< 16;
698 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
701 packet
.header
= (type
<< 6) | 0x0008;
702 packet
.data
= (u32
)data
<< 24;
703 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
704 packet
.header
= (type
<< 6) | 0x0001;
705 packet
.address
= (addr
& ~3) + 4;
706 packet
.data
= (u32
)data
>> 8;
707 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
713 static int sisusb_write_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
716 struct sisusb_packet packet
;
719 packet
.address
= addr
& ~3;
723 packet
.header
= (type
<< 6) | 0x0007;
724 packet
.data
= data
& 0x00ffffff;
725 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
728 packet
.header
= (type
<< 6) | 0x000e;
729 packet
.data
= data
<< 8;
730 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
733 packet
.header
= (type
<< 6) | 0x000c;
734 packet
.data
= data
<< 16;
735 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
736 packet
.header
= (type
<< 6) | 0x0001;
737 packet
.address
= (addr
& ~3) + 4;
738 packet
.data
= (data
>> 16) & 0x00ff;
739 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
742 packet
.header
= (type
<< 6) | 0x0008;
743 packet
.data
= data
<< 24;
744 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
745 packet
.header
= (type
<< 6) | 0x0003;
746 packet
.address
= (addr
& ~3) + 4;
747 packet
.data
= (data
>> 8) & 0xffff;
748 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
754 static int sisusb_write_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
757 struct sisusb_packet packet
;
760 packet
.address
= addr
& ~3;
764 packet
.header
= (type
<< 6) | 0x000f;
766 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
769 packet
.header
= (type
<< 6) | 0x000e;
770 packet
.data
= data
<< 8;
771 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
772 packet
.header
= (type
<< 6) | 0x0001;
773 packet
.address
= (addr
& ~3) + 4;
774 packet
.data
= data
>> 24;
775 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
778 packet
.header
= (type
<< 6) | 0x000c;
779 packet
.data
= data
<< 16;
780 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
781 packet
.header
= (type
<< 6) | 0x0003;
782 packet
.address
= (addr
& ~3) + 4;
783 packet
.data
= data
>> 16;
784 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
787 packet
.header
= (type
<< 6) | 0x0008;
788 packet
.data
= data
<< 24;
789 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
790 packet
.header
= (type
<< 6) | 0x0007;
791 packet
.address
= (addr
& ~3) + 4;
792 packet
.data
= data
>> 8;
793 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
799 /* The xxx_bulk routines copy a buffer of variable size. They treat the
800 * buffer as chars, therefore lsb/msb has to be corrected if using the
801 * byte/word/long/etc routines for speed-up
803 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
804 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
805 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
806 * that the data already is in the transfer buffer "sisusb->obuf[index]".
809 static int sisusb_write_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
810 char *kernbuffer
, int length
,
811 const char __user
*userbuffer
, int index
,
812 ssize_t
*bytes_written
)
814 struct sisusb_packet packet
;
816 static int msgcount
= 0;
817 u8 swap8
, fromkern
= kernbuffer
? 1 : 0;
819 u32 swap32
, flag
= (length
>> 28) & 1;
822 /* if neither kernbuffer not userbuffer are given, assume
825 if (!fromkern
&& !userbuffer
)
826 kernbuffer
= sisusb
->obuf
[index
];
828 (*bytes_written
= 0);
830 length
&= 0x00ffffff;
838 if (get_user(swap8
, (u8 __user
*)userbuffer
))
841 swap8
= kernbuffer
[0];
843 ret
= sisusb_write_memio_byte(sisusb
,
854 if (get_user(swap16
, (u16 __user
*)userbuffer
))
857 swap16
= *((u16
*)kernbuffer
);
859 ret
= sisusb_write_memio_word(sisusb
,
865 (*bytes_written
) += 2;
871 if (copy_from_user(&buf
, userbuffer
, 3))
874 swap32
= (buf
[0] << 16) |
878 swap32
= (buf
[2] << 16) |
884 swap32
= (kernbuffer
[0] << 16) |
885 (kernbuffer
[1] << 8) |
888 swap32
= (kernbuffer
[2] << 16) |
889 (kernbuffer
[1] << 8) |
893 ret
= sisusb_write_memio_24bit(sisusb
,
899 (*bytes_written
) += 3;
905 if (get_user(swap32
, (u32 __user
*)userbuffer
))
908 swap32
= *((u32
*)kernbuffer
);
910 ret
= sisusb_write_memio_long(sisusb
,
915 (*bytes_written
) += 4;
920 if ((length
& ~3) > 0x10000) {
922 packet
.header
= 0x001f;
923 packet
.address
= 0x000001d4;
925 ret
= sisusb_send_bridge_packet(sisusb
, 10,
927 packet
.header
= 0x001f;
928 packet
.address
= 0x000001d0;
929 packet
.data
= (length
& ~3);
930 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
932 packet
.header
= 0x001f;
933 packet
.address
= 0x000001c0;
934 packet
.data
= flag
| 0x16;
935 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
938 ret
|= sisusb_send_bulk_msg(sisusb
,
939 SISUSB_EP_GFX_LBULK_OUT
,
942 bytes_written
, 0, 1);
943 userbuffer
+= (*bytes_written
);
944 } else if (fromkern
) {
945 ret
|= sisusb_send_bulk_msg(sisusb
,
946 SISUSB_EP_GFX_LBULK_OUT
,
949 bytes_written
, 0, 1);
950 kernbuffer
+= (*bytes_written
);
952 ret
|= sisusb_send_bulk_msg(sisusb
,
953 SISUSB_EP_GFX_LBULK_OUT
,
956 bytes_written
, 0, 1);
957 kernbuffer
+= ((*bytes_written
) &
958 (sisusb
->obufsize
-1));
963 packet
.header
= 0x001f;
964 packet
.address
= 0x00000194;
966 ret
= sisusb_send_bridge_packet(sisusb
, 10,
968 packet
.header
= 0x001f;
969 packet
.address
= 0x00000190;
970 packet
.data
= (length
& ~3);
971 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
973 if (sisusb
->flagb0
!= 0x16) {
974 packet
.header
= 0x001f;
975 packet
.address
= 0x00000180;
976 packet
.data
= flag
| 0x16;
977 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
979 sisusb
->flagb0
= 0x16;
982 ret
|= sisusb_send_bulk_msg(sisusb
,
983 SISUSB_EP_GFX_BULK_OUT
,
986 bytes_written
, 0, 1);
987 userbuffer
+= (*bytes_written
);
988 } else if (fromkern
) {
989 ret
|= sisusb_send_bulk_msg(sisusb
,
990 SISUSB_EP_GFX_BULK_OUT
,
993 bytes_written
, 0, 1);
994 kernbuffer
+= (*bytes_written
);
996 ret
|= sisusb_send_bulk_msg(sisusb
,
997 SISUSB_EP_GFX_BULK_OUT
,
1000 bytes_written
, 0, 1);
1001 kernbuffer
+= ((*bytes_written
) &
1002 (sisusb
->obufsize
-1));
1009 "sisusbvga[%d]: Wrote %zd of "
1010 "%d bytes, error %d\n",
1011 sisusb
->minor
, *bytes_written
,
1013 else if (msgcount
== 500)
1015 "sisusbvga[%d]: Too many errors"
1016 ", logging stopped\n",
1019 addr
+= (*bytes_written
);
1020 length
-= (*bytes_written
);
1028 return ret
? -EIO
: 0;
1031 /* Remember: Read data in packet is in machine-endianess! So for
1032 * byte, word, 24bit, long no endian correction is necessary.
1035 static int sisusb_read_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
1038 struct sisusb_packet packet
;
1041 CLEARPACKET(&packet
);
1042 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
1043 packet
.address
= addr
& ~3;
1044 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1045 *data
= (u8
)(packet
.data
>> ((addr
& 3) << 3));
1049 static int sisusb_read_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
1050 u32 addr
, u16
*data
)
1052 struct sisusb_packet packet
;
1055 CLEARPACKET(&packet
);
1057 packet
.address
= addr
& ~3;
1061 packet
.header
= (type
<< 6) | 0x0003;
1062 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1063 *data
= (u16
)(packet
.data
);
1066 packet
.header
= (type
<< 6) | 0x0006;
1067 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1068 *data
= (u16
)(packet
.data
>> 8);
1071 packet
.header
= (type
<< 6) | 0x000c;
1072 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1073 *data
= (u16
)(packet
.data
>> 16);
1076 packet
.header
= (type
<< 6) | 0x0008;
1077 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1078 *data
= (u16
)(packet
.data
>> 24);
1079 packet
.header
= (type
<< 6) | 0x0001;
1080 packet
.address
= (addr
& ~3) + 4;
1081 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1082 *data
|= (u16
)(packet
.data
<< 8);
1088 static int sisusb_read_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
1089 u32 addr
, u32
*data
)
1091 struct sisusb_packet packet
;
1094 packet
.address
= addr
& ~3;
1098 packet
.header
= (type
<< 6) | 0x0007;
1099 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1100 *data
= packet
.data
& 0x00ffffff;
1103 packet
.header
= (type
<< 6) | 0x000e;
1104 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1105 *data
= packet
.data
>> 8;
1108 packet
.header
= (type
<< 6) | 0x000c;
1109 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1110 *data
= packet
.data
>> 16;
1111 packet
.header
= (type
<< 6) | 0x0001;
1112 packet
.address
= (addr
& ~3) + 4;
1113 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1114 *data
|= ((packet
.data
& 0xff) << 16);
1117 packet
.header
= (type
<< 6) | 0x0008;
1118 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1119 *data
= packet
.data
>> 24;
1120 packet
.header
= (type
<< 6) | 0x0003;
1121 packet
.address
= (addr
& ~3) + 4;
1122 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1123 *data
|= ((packet
.data
& 0xffff) << 8);
1129 static int sisusb_read_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
1130 u32 addr
, u32
*data
)
1132 struct sisusb_packet packet
;
1135 packet
.address
= addr
& ~3;
1139 packet
.header
= (type
<< 6) | 0x000f;
1140 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1141 *data
= packet
.data
;
1144 packet
.header
= (type
<< 6) | 0x000e;
1145 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1146 *data
= packet
.data
>> 8;
1147 packet
.header
= (type
<< 6) | 0x0001;
1148 packet
.address
= (addr
& ~3) + 4;
1149 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1150 *data
|= (packet
.data
<< 24);
1153 packet
.header
= (type
<< 6) | 0x000c;
1154 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1155 *data
= packet
.data
>> 16;
1156 packet
.header
= (type
<< 6) | 0x0003;
1157 packet
.address
= (addr
& ~3) + 4;
1158 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1159 *data
|= (packet
.data
<< 16);
1162 packet
.header
= (type
<< 6) | 0x0008;
1163 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1164 *data
= packet
.data
>> 24;
1165 packet
.header
= (type
<< 6) | 0x0007;
1166 packet
.address
= (addr
& ~3) + 4;
1167 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1168 *data
|= (packet
.data
<< 8);
1174 static int sisusb_read_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
1175 char *kernbuffer
, int length
,
1176 char __user
*userbuffer
, ssize_t
*bytes_read
)
1185 length
&= 0x00ffffff;
1193 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
1198 if (put_user(buf
[0],
1199 (u8 __user
*)userbuffer
)) {
1203 kernbuffer
[0] = buf
[0];
1209 ret
|= sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1214 if (put_user(swap16
,
1215 (u16 __user
*)userbuffer
))
1218 *((u16
*)kernbuffer
) = swap16
;
1224 ret
|= sisusb_read_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
1229 buf
[0] = (swap32
>> 16) & 0xff;
1230 buf
[1] = (swap32
>> 8) & 0xff;
1231 buf
[2] = swap32
& 0xff;
1233 buf
[2] = (swap32
>> 16) & 0xff;
1234 buf
[1] = (swap32
>> 8) & 0xff;
1235 buf
[0] = swap32
& 0xff;
1238 if (copy_to_user(userbuffer
, &buf
[0], 3))
1241 kernbuffer
[0] = buf
[0];
1242 kernbuffer
[1] = buf
[1];
1243 kernbuffer
[2] = buf
[2];
1249 ret
|= sisusb_read_memio_long(sisusb
, SISUSB_TYPE_MEM
,
1254 if (put_user(swap32
,
1255 (u32 __user
*)userbuffer
))
1260 *((u32
*)kernbuffer
) = swap32
;
1266 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1268 CLEARPACKET(&packet
);
1269 packet
.header
= 0x001f;
1270 packet
.address
= 0x000001a0;
1271 packet
.data
= 0x00000006;
1272 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1274 packet
.header
= 0x001f;
1275 packet
.address
= 0x000001b0;
1276 packet
.data
= (length
& ~3) | 0x40000000;
1277 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1279 packet
.header
= 0x001f;
1280 packet
.address
= 0x000001b4;
1282 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1284 packet
.header
= 0x001f;
1285 packet
.address
= 0x000001a4;
1286 packet
.data
= 0x00000001;
1287 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1290 ret
|= sisusb_recv_bulk_msg(sisusb
,
1291 SISUSB_EP_GFX_BULK_IN
,
1295 if (!ret
) userbuffer
+= (*bytes_read
);
1297 ret
|= sisusb_recv_bulk_msg(sisusb
,
1298 SISUSB_EP_GFX_BULK_IN
,
1302 if (!ret
) kernbuffer
+= (*bytes_read
);
1304 addr
+= (*bytes_read
);
1305 length
-= (*bytes_read
);
1316 /* High level: Gfx (indexed) register access */
1318 #ifdef INCL_SISUSB_CON
1320 sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
)
1322 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1326 sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
)
1328 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1333 sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 data
)
1336 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1337 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1342 sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8
*data
)
1345 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1346 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1351 sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1357 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1358 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1361 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1366 sisusb_setidxregmask(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1371 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1372 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1374 tmp
|= (data
& mask
);
1375 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1380 sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 myor
)
1382 return(sisusb_setidxregandor(sisusb
, port
, index
, 0xff, myor
));
1386 sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
)
1388 return(sisusb_setidxregandor(sisusb
, port
, idx
, myand
, 0x00));
1391 /* Write/read video ram */
1393 #ifdef INCL_SISUSB_CON
1395 sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
)
1397 return(sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1401 sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
)
1403 return(sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1409 sisusb_writew(struct sisusb_usb_data
*sisusb
, u32 adr
, u16 data
)
1411 return(sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1415 sisusb_readw(struct sisusb_usb_data
*sisusb
, u32 adr
, u16
*data
)
1417 return(sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1423 sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
1424 u32 dest
, int length
, size_t *bytes_written
)
1426 return(sisusb_write_mem_bulk(sisusb
, dest
, src
, length
, NULL
, 0, bytes_written
));
1429 #ifdef SISUSBENDIANTEST
1431 sisusb_read_memory(struct sisusb_usb_data
*sisusb
, char *dest
,
1432 u32 src
, int length
, size_t *bytes_written
)
1434 return(sisusb_read_mem_bulk(sisusb
, src
, dest
, length
, NULL
, bytes_written
));
1439 #ifdef SISUSBENDIANTEST
1441 sisusb_testreadwrite(struct sisusb_usb_data
*sisusb
)
1443 static char srcbuffer
[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1444 char destbuffer
[10];
1448 sisusb_copy_memory(sisusb
, srcbuffer
, sisusb
->vrambase
, 7, &dummy
);
1450 for(i
= 1; i
<= 7; i
++) {
1451 printk(KERN_DEBUG
"sisusb: rwtest %d bytes\n", i
);
1452 sisusb_read_memory(sisusb
, destbuffer
, sisusb
->vrambase
, i
, &dummy
);
1453 for(j
= 0; j
< i
; j
++) {
1454 printk(KERN_DEBUG
"sisusb: rwtest read[%d] = %x\n", j
, destbuffer
[j
]);
1460 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1463 sisusb_write_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32 data
)
1465 struct sisusb_packet packet
;
1468 packet
.header
= 0x008f;
1469 packet
.address
= regnum
| 0x10000;
1471 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
1476 sisusb_read_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32
*data
)
1478 struct sisusb_packet packet
;
1481 packet
.header
= 0x008f;
1482 packet
.address
= (u32
)regnum
| 0x10000;
1483 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1484 *data
= packet
.data
;
1488 /* Clear video RAM */
1491 sisusb_clear_vram(struct sisusb_usb_data
*sisusb
, u32 address
, int length
)
1496 if (address
< sisusb
->vrambase
)
1499 if (address
>= sisusb
->vrambase
+ sisusb
->vramsize
)
1502 if (address
+ length
> sisusb
->vrambase
+ sisusb
->vramsize
)
1503 length
= sisusb
->vrambase
+ sisusb
->vramsize
- address
;
1508 /* allocate free buffer/urb and clear the buffer */
1509 if ((i
= sisusb_alloc_outbuf(sisusb
)) < 0)
1512 memset(sisusb
->obuf
[i
], 0, sisusb
->obufsize
);
1514 /* We can write a length > buffer size here. The buffer
1515 * data will simply be re-used (like a ring-buffer).
1517 ret
= sisusb_write_mem_bulk(sisusb
, address
, NULL
, length
, NULL
, i
, &j
);
1519 /* Free the buffer/urb */
1520 sisusb_free_outbuf(sisusb
, i
);
1525 /* Initialize the graphics core (return 0 on success)
1526 * This resets the graphics hardware and puts it into
1527 * a defined mode (640x480@60Hz)
1530 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1531 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1532 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1533 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1534 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1535 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1536 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1537 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1538 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1539 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1540 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1543 sisusb_triggersr16(struct sisusb_usb_data
*sisusb
, u8 ramtype
)
1548 ret
= GETIREG(SISSR
, 0x16, &tmp8
);
1551 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1553 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1556 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1558 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1560 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1562 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1564 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1566 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1568 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1574 sisusb_getbuswidth(struct sisusb_usb_data
*sisusb
, int *bw
, int *chab
)
1577 u8 ramtype
, done
= 0;
1579 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1581 ret
= GETIREG(SISSR
, 0x3a, &ramtype
);
1584 ret
|= SETIREG(SISSR
, 0x13, 0x00);
1587 ret
|= SETIREG(SISSR
, 0x14, 0x12);
1588 ret
|= SETIREGAND(SISSR
, 0x15, 0xef);
1590 ret
|= SETIREG(SISSR
, 0x14, 0x02);
1593 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1594 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1595 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1596 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1597 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1598 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1599 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1600 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1601 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1602 ret
|= READL(ramptr
+ 0, &t0
);
1603 ret
|= READL(ramptr
+ 4, &t1
);
1604 ret
|= READL(ramptr
+ 8, &t2
);
1605 ret
|= READL(ramptr
+ 12, &t3
);
1609 *chab
= 0; *bw
= 64;
1611 if ((t3
!= 0xcdef0123) || (t2
!= 0x89abcdef)) {
1612 if ((t1
== 0x456789ab) && (t0
== 0x01234567)) {
1613 *chab
= 0; *bw
= 64;
1614 ret
|= SETIREGAND(SISSR
, 0x14, 0xfd);
1617 if ((t1
!= 0x456789ab) || (t0
!= 0x01234567)) {
1618 *chab
= 1; *bw
= 64;
1619 ret
|= SETIREGANDOR(SISSR
, 0x14, 0xfc,0x01);
1621 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1622 ret
|= WRITEL(ramptr
+ 0, 0x89abcdef);
1623 ret
|= WRITEL(ramptr
+ 4, 0xcdef0123);
1624 ret
|= WRITEL(ramptr
+ 8, 0x55555555);
1625 ret
|= WRITEL(ramptr
+ 12, 0x55555555);
1626 ret
|= WRITEL(ramptr
+ 16, 0xaaaaaaaa);
1627 ret
|= WRITEL(ramptr
+ 20, 0xaaaaaaaa);
1628 ret
|= READL(ramptr
+ 4, &t1
);
1630 if (t1
!= 0xcdef0123) {
1632 ret
|= SETIREGOR(SISSR
, 0x15, 0x10);
1638 *chab
= 0; *bw
= 64; /* default: cha, bw = 64 */
1642 if (t1
== 0x456789ab) {
1643 if (t0
== 0x01234567) {
1644 *chab
= 0; *bw
= 64;
1648 if (t0
== 0x01234567) {
1649 *chab
= 0; *bw
= 32;
1650 ret
|= SETIREG(SISSR
, 0x14, 0x00);
1656 ret
|= SETIREG(SISSR
, 0x14, 0x03);
1657 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1659 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1660 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1661 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1662 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1663 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1664 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1665 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1666 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1667 ret
|= READL(ramptr
+ 0, &t0
);
1668 ret
|= READL(ramptr
+ 4, &t1
);
1670 if (t1
== 0x456789ab) {
1671 if (t0
== 0x01234567) {
1672 *chab
= 1; *bw
= 64;
1676 if (t0
== 0x01234567) {
1677 *chab
= 1; *bw
= 32;
1678 ret
|= SETIREG(SISSR
, 0x14, 0x01);
1687 sisusb_verify_mclk(struct sisusb_usb_data
*sisusb
)
1690 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1691 u8 tmp1
, tmp2
, i
, j
;
1693 ret
|= WRITEB(ramptr
, 0xaa);
1694 ret
|= WRITEB(ramptr
+ 16, 0x55);
1695 ret
|= READB(ramptr
, &tmp1
);
1696 ret
|= READB(ramptr
+ 16, &tmp2
);
1697 if ((tmp1
!= 0xaa) || (tmp2
!= 0x55)) {
1698 for (i
= 0, j
= 16; i
< 2; i
++, j
+= 16) {
1699 ret
|= GETIREG(SISSR
, 0x21, &tmp1
);
1700 ret
|= SETIREGAND(SISSR
, 0x21, (tmp1
& 0xfb));
1701 ret
|= SETIREGOR(SISSR
, 0x3c, 0x01); /* not on 330 */
1702 ret
|= SETIREGAND(SISSR
, 0x3c, 0xfe); /* not on 330 */
1703 ret
|= SETIREG(SISSR
, 0x21, tmp1
);
1704 ret
|= WRITEB(ramptr
+ 16 + j
, j
);
1705 ret
|= READB(ramptr
+ 16 + j
, &tmp1
);
1707 ret
|= WRITEB(ramptr
+ j
, j
);
1716 sisusb_set_rank(struct sisusb_usb_data
*sisusb
, int *iret
, int index
,
1717 u8 rankno
, u8 chab
, const u8 dramtype
[][5],
1720 int ret
= 0, ranksize
;
1725 if ((rankno
== 2) && (dramtype
[index
][0] == 2))
1728 ranksize
= dramtype
[index
][3] / 2 * bw
/ 32;
1730 if ((ranksize
* rankno
) > 128)
1734 while ((ranksize
>>= 1) > 0) tmp
+= 0x10;
1735 tmp
|= ((rankno
- 1) << 2);
1736 tmp
|= ((bw
/ 64) & 0x02);
1737 tmp
|= (chab
& 0x01);
1739 ret
= SETIREG(SISSR
, 0x14, tmp
);
1740 ret
|= sisusb_triggersr16(sisusb
, 0); /* sic! */
1748 sisusb_check_rbc(struct sisusb_usb_data
*sisusb
, int *iret
, u32 inc
, int testn
)
1755 for (i
= 0, j
= 0; i
< testn
; i
++) {
1756 ret
|= WRITEL(sisusb
->vrambase
+ j
, j
);
1760 for (i
= 0, j
= 0; i
< testn
; i
++) {
1761 ret
|= READL(sisusb
->vrambase
+ j
, &tmp
);
1762 if (tmp
!= j
) return ret
;
1771 sisusb_check_ranks(struct sisusb_usb_data
*sisusb
, int *iret
, int rankno
,
1772 int idx
, int bw
, const u8 rtype
[][5])
1774 int ret
= 0, i
, i2ret
;
1779 for (i
= rankno
; i
>= 1; i
--) {
1780 inc
= 1 << (rtype
[idx
][2] +
1784 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1789 inc
= 1 << (rtype
[idx
][2] + bw
/ 64 + 2);
1790 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 4);
1794 inc
= 1 << (10 + bw
/ 64);
1795 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1804 sisusb_get_sdram_size(struct sisusb_usb_data
*sisusb
, int *iret
, int bw
,
1807 int ret
= 0, i2ret
= 0, i
, j
;
1808 static const u8 sdramtype
[13][5] = {
1809 { 2, 12, 9, 64, 0x35 },
1810 { 1, 13, 9, 64, 0x44 },
1811 { 2, 12, 8, 32, 0x31 },
1812 { 2, 11, 9, 32, 0x25 },
1813 { 1, 12, 9, 32, 0x34 },
1814 { 1, 13, 8, 32, 0x40 },
1815 { 2, 11, 8, 16, 0x21 },
1816 { 1, 12, 8, 16, 0x30 },
1817 { 1, 11, 9, 16, 0x24 },
1818 { 1, 11, 8, 8, 0x20 },
1819 { 2, 9, 8, 4, 0x01 },
1820 { 1, 10, 8, 4, 0x10 },
1821 { 1, 9, 8, 2, 0x00 }
1824 *iret
= 1; /* error */
1826 for (i
= 0; i
< 13; i
++) {
1827 ret
|= SETIREGANDOR(SISSR
, 0x13, 0x80, sdramtype
[i
][4]);
1828 for (j
= 2; j
> 0; j
--) {
1829 ret
|= sisusb_set_rank(sisusb
, &i2ret
, i
, j
,
1830 chab
, sdramtype
, bw
);
1834 ret
|= sisusb_check_ranks(sisusb
, &i2ret
, j
, i
,
1837 *iret
= 0; /* ram size found */
1847 sisusb_setup_screen(struct sisusb_usb_data
*sisusb
, int clrall
, int drwfr
)
1851 int i
, length
, modex
, modey
, bpp
;
1853 modex
= 640; modey
= 480; bpp
= 2;
1855 address
= sisusb
->vrambase
; /* Clear video ram */
1858 length
= sisusb
->vramsize
;
1860 length
= modex
* bpp
* modey
;
1862 ret
= sisusb_clear_vram(sisusb
, address
, length
);
1864 if (!ret
&& drwfr
) {
1865 for (i
= 0; i
< modex
; i
++) {
1866 address
= sisusb
->vrambase
+ (i
* bpp
);
1867 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1869 address
+= (modex
* (modey
-1) * bpp
);
1870 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1873 for (i
= 0; i
< modey
; i
++) {
1874 address
= sisusb
->vrambase
+ ((i
* modex
) * bpp
);
1875 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1877 address
+= ((modex
- 1) * bpp
);
1878 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1887 sisusb_set_default_mode(struct sisusb_usb_data
*sisusb
, int touchengines
)
1889 int ret
= 0, i
, j
, modex
, modey
, bpp
, du
;
1890 u8 sr31
, cr63
, tmp8
;
1891 static const char attrdata
[] = {
1892 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1893 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1896 static const char crtcrdata
[] = {
1897 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1898 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1899 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1902 static const char grcdata
[] = {
1903 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1906 static const char crtcdata
[] = {
1907 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1908 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1912 modex
= 640; modey
= 480; bpp
= 2;
1914 GETIREG(SISSR
, 0x31, &sr31
);
1915 GETIREG(SISCR
, 0x63, &cr63
);
1916 SETIREGOR(SISSR
, 0x01, 0x20);
1917 SETIREG(SISCR
, 0x63, cr63
& 0xbf);
1918 SETIREGOR(SISCR
, 0x17, 0x80);
1919 SETIREGOR(SISSR
, 0x1f, 0x04);
1920 SETIREGAND(SISSR
, 0x07, 0xfb);
1921 SETIREG(SISSR
, 0x00, 0x03); /* seq */
1922 SETIREG(SISSR
, 0x01, 0x21);
1923 SETIREG(SISSR
, 0x02, 0x0f);
1924 SETIREG(SISSR
, 0x03, 0x00);
1925 SETIREG(SISSR
, 0x04, 0x0e);
1926 SETREG(SISMISCW
, 0x23); /* misc */
1927 for (i
= 0; i
<= 0x18; i
++) { /* crtc */
1928 SETIREG(SISCR
, i
, crtcrdata
[i
]);
1930 for (i
= 0; i
<= 0x13; i
++) { /* att */
1931 GETREG(SISINPSTAT
, &tmp8
);
1933 SETREG(SISAR
, attrdata
[i
]);
1935 GETREG(SISINPSTAT
, &tmp8
);
1936 SETREG(SISAR
, 0x14);
1937 SETREG(SISAR
, 0x00);
1938 GETREG(SISINPSTAT
, &tmp8
);
1939 SETREG(SISAR
, 0x20);
1940 GETREG(SISINPSTAT
, &tmp8
);
1941 for (i
= 0; i
<= 0x08; i
++) { /* grc */
1942 SETIREG(SISGR
, i
, grcdata
[i
]);
1944 SETIREGAND(SISGR
, 0x05, 0xbf);
1945 for (i
= 0x0A; i
<= 0x0E; i
++) { /* clr ext */
1946 SETIREG(SISSR
, i
, 0x00);
1948 SETIREGAND(SISSR
, 0x37, 0xfe);
1949 SETREG(SISMISCW
, 0xef); /* sync */
1950 SETIREG(SISCR
, 0x11, 0x00); /* crtc */
1951 for (j
= 0x00, i
= 0; i
<= 7; i
++, j
++) {
1952 SETIREG(SISCR
, j
, crtcdata
[i
]);
1954 for (j
= 0x10; i
<= 10; i
++, j
++) {
1955 SETIREG(SISCR
, j
, crtcdata
[i
]);
1957 for (j
= 0x15; i
<= 12; i
++, j
++) {
1958 SETIREG(SISCR
, j
, crtcdata
[i
]);
1960 for (j
= 0x0A; i
<= 15; i
++, j
++) {
1961 SETIREG(SISSR
, j
, crtcdata
[i
]);
1963 SETIREG(SISSR
, 0x0E, (crtcdata
[16] & 0xE0));
1964 SETIREGANDOR(SISCR
, 0x09, 0x5f, ((crtcdata
[16] & 0x01) << 5));
1965 SETIREG(SISCR
, 0x14, 0x4f);
1966 du
= (modex
/ 16) * (bpp
* 2); /* offset/pitch */
1967 if (modex
% 16) du
+= bpp
;
1968 SETIREGANDOR(SISSR
, 0x0e, 0xf0, ((du
>> 8) & 0x0f));
1969 SETIREG(SISCR
, 0x13, (du
& 0xff));
1972 if (du
& 0xff) tmp8
++;
1973 SETIREG(SISSR
, 0x10, tmp8
);
1974 SETIREG(SISSR
, 0x31, 0x00); /* VCLK */
1975 SETIREG(SISSR
, 0x2b, 0x1b);
1976 SETIREG(SISSR
, 0x2c, 0xe1);
1977 SETIREG(SISSR
, 0x2d, 0x01);
1978 SETIREGAND(SISSR
, 0x3d, 0xfe); /* FIFO */
1979 SETIREG(SISSR
, 0x08, 0xae);
1980 SETIREGAND(SISSR
, 0x09, 0xf0);
1981 SETIREG(SISSR
, 0x08, 0x34);
1982 SETIREGOR(SISSR
, 0x3d, 0x01);
1983 SETIREGAND(SISSR
, 0x1f, 0x3f); /* mode regs */
1984 SETIREGANDOR(SISSR
, 0x06, 0xc0, 0x0a);
1985 SETIREG(SISCR
, 0x19, 0x00);
1986 SETIREGAND(SISCR
, 0x1a, 0xfc);
1987 SETIREGAND(SISSR
, 0x0f, 0xb7);
1988 SETIREGAND(SISSR
, 0x31, 0xfb);
1989 SETIREGANDOR(SISSR
, 0x21, 0x1f, 0xa0);
1990 SETIREGAND(SISSR
, 0x32, 0xf3);
1991 SETIREGANDOR(SISSR
, 0x07, 0xf8, 0x03);
1992 SETIREG(SISCR
, 0x52, 0x6c);
1994 SETIREG(SISCR
, 0x0d, 0x00); /* adjust frame */
1995 SETIREG(SISCR
, 0x0c, 0x00);
1996 SETIREG(SISSR
, 0x0d, 0x00);
1997 SETIREGAND(SISSR
, 0x37, 0xfe);
1999 SETIREG(SISCR
, 0x32, 0x20);
2000 SETIREGAND(SISSR
, 0x01, 0xdf); /* enable display */
2001 SETIREG(SISCR
, 0x63, (cr63
& 0xbf));
2002 SETIREG(SISSR
, 0x31, (sr31
& 0xfb));
2005 SETIREG(SISSR
, 0x20, 0xa1); /* enable engines */
2006 SETIREGOR(SISSR
, 0x1e, 0x5a);
2008 SETIREG(SISSR
, 0x26, 0x01); /* disable cmdqueue */
2009 SETIREG(SISSR
, 0x27, 0x1f);
2010 SETIREG(SISSR
, 0x26, 0x00);
2013 SETIREG(SISCR
, 0x34, 0x44); /* we just set std mode #44 */
2019 sisusb_init_gfxcore(struct sisusb_usb_data
*sisusb
)
2021 int ret
= 0, i
, j
, bw
, chab
, iret
, retry
= 3;
2024 static const char mclktable
[] = {
2025 0x3b, 0x22, 0x01, 143,
2026 0x3b, 0x22, 0x01, 143,
2027 0x3b, 0x22, 0x01, 143,
2028 0x3b, 0x22, 0x01, 143
2030 static const char eclktable
[] = {
2031 0x3b, 0x22, 0x01, 143,
2032 0x3b, 0x22, 0x01, 143,
2033 0x3b, 0x22, 0x01, 143,
2034 0x3b, 0x22, 0x01, 143
2036 static const char ramtypetable1
[] = {
2037 0x00, 0x04, 0x60, 0x60,
2038 0x0f, 0x0f, 0x1f, 0x1f,
2039 0xba, 0xba, 0xba, 0xba,
2040 0xa9, 0xa9, 0xac, 0xac,
2041 0xa0, 0xa0, 0xa0, 0xa8,
2042 0x00, 0x00, 0x02, 0x02,
2043 0x30, 0x30, 0x40, 0x40
2045 static const char ramtypetable2
[] = {
2046 0x77, 0x77, 0x44, 0x44,
2047 0x77, 0x77, 0x44, 0x44,
2048 0x00, 0x00, 0x00, 0x00,
2049 0x5b, 0x5b, 0xab, 0xab,
2050 0x00, 0x00, 0xf0, 0xf8
2056 ret
= GETREG(SISVGAEN
, &tmp8
);
2057 ret
|= SETREG(SISVGAEN
, (tmp8
| 0x01));
2059 /* Enable GPU access to VRAM */
2060 ret
|= GETREG(SISMISCR
, &tmp8
);
2061 ret
|= SETREG(SISMISCW
, (tmp8
| 0x01));
2065 /* Reset registers */
2066 ret
|= SETIREGAND(SISCR
, 0x5b, 0xdf);
2067 ret
|= SETIREG(SISSR
, 0x05, 0x86);
2068 ret
|= SETIREGOR(SISSR
, 0x20, 0x01);
2070 ret
|= SETREG(SISMISCW
, 0x67);
2072 for (i
= 0x06; i
<= 0x1f; i
++) {
2073 ret
|= SETIREG(SISSR
, i
, 0x00);
2075 for (i
= 0x21; i
<= 0x27; i
++) {
2076 ret
|= SETIREG(SISSR
, i
, 0x00);
2078 for (i
= 0x31; i
<= 0x3d; i
++) {
2079 ret
|= SETIREG(SISSR
, i
, 0x00);
2081 for (i
= 0x12; i
<= 0x1b; i
++) {
2082 ret
|= SETIREG(SISSR
, i
, 0x00);
2084 for (i
= 0x79; i
<= 0x7c; i
++) {
2085 ret
|= SETIREG(SISCR
, i
, 0x00);
2090 ret
|= SETIREG(SISCR
, 0x63, 0x80);
2092 ret
|= GETIREG(SISSR
, 0x3a, &ramtype
);
2095 ret
|= SETIREG(SISSR
, 0x28, mclktable
[ramtype
* 4]);
2096 ret
|= SETIREG(SISSR
, 0x29, mclktable
[(ramtype
* 4) + 1]);
2097 ret
|= SETIREG(SISSR
, 0x2a, mclktable
[(ramtype
* 4) + 2]);
2099 ret
|= SETIREG(SISSR
, 0x2e, eclktable
[ramtype
* 4]);
2100 ret
|= SETIREG(SISSR
, 0x2f, eclktable
[(ramtype
* 4) + 1]);
2101 ret
|= SETIREG(SISSR
, 0x30, eclktable
[(ramtype
* 4) + 2]);
2103 ret
|= SETIREG(SISSR
, 0x07, 0x18);
2104 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2108 for (i
= 0x15, j
= 0; i
<= 0x1b; i
++, j
++) {
2109 ret
|= SETIREG(SISSR
, i
, ramtypetable1
[(j
*4) + ramtype
]);
2111 for (i
= 0x40, j
= 0; i
<= 0x44; i
++, j
++) {
2112 ret
|= SETIREG(SISCR
, i
, ramtypetable2
[(j
*4) + ramtype
]);
2115 ret
|= SETIREG(SISCR
, 0x49, 0xaa);
2117 ret
|= SETIREG(SISSR
, 0x1f, 0x00);
2118 ret
|= SETIREG(SISSR
, 0x20, 0xa0);
2119 ret
|= SETIREG(SISSR
, 0x23, 0xf6);
2120 ret
|= SETIREG(SISSR
, 0x24, 0x0d);
2121 ret
|= SETIREG(SISSR
, 0x25, 0x33);
2123 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2125 ret
|= SETIREGOR(SISPART1
, 0x2f, 0x01);
2127 ret
|= SETIREGAND(SISCAP
, 0x3f, 0xef);
2131 ret
|= SETIREG(SISPART1
, 0x00, 0x00);
2133 ret
|= GETIREG(SISSR
, 0x13, &tmp8
);
2136 ret
|= SETIREG(SISPART1
, 0x02, 0x00);
2137 ret
|= SETIREG(SISPART1
, 0x2e, 0x08);
2139 ret
|= sisusb_read_pci_config(sisusb
, 0x50, &tmp32
);
2140 tmp32
&= 0x00f00000;
2141 tmp8
= (tmp32
== 0x100000) ? 0x33 : 0x03;
2142 ret
|= SETIREG(SISSR
, 0x25, tmp8
);
2143 tmp8
= (tmp32
== 0x100000) ? 0xaa : 0x88;
2144 ret
|= SETIREG(SISCR
, 0x49, tmp8
);
2146 ret
|= SETIREG(SISSR
, 0x27, 0x1f);
2147 ret
|= SETIREG(SISSR
, 0x31, 0x00);
2148 ret
|= SETIREG(SISSR
, 0x32, 0x11);
2149 ret
|= SETIREG(SISSR
, 0x33, 0x00);
2153 ret
|= SETIREG(SISCR
, 0x83, 0x00);
2155 ret
|= sisusb_set_default_mode(sisusb
, 0);
2157 ret
|= SETIREGAND(SISSR
, 0x21, 0xdf);
2158 ret
|= SETIREGOR(SISSR
, 0x01, 0x20);
2159 ret
|= SETIREGOR(SISSR
, 0x16, 0x0f);
2161 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
2163 /* Disable refresh */
2164 ret
|= SETIREGAND(SISSR
, 0x17, 0xf8);
2165 ret
|= SETIREGOR(SISSR
, 0x19, 0x03);
2167 ret
|= sisusb_getbuswidth(sisusb
, &bw
, &chab
);
2168 ret
|= sisusb_verify_mclk(sisusb
);
2171 ret
|= sisusb_get_sdram_size(sisusb
, &iret
, bw
, chab
);
2173 printk(KERN_ERR
"sisusbvga[%d]: RAM size "
2174 "detection failed, "
2175 "assuming 8MB video RAM\n",
2177 ret
|= SETIREG(SISSR
,0x14,0x31);
2181 printk(KERN_ERR
"sisusbvga[%d]: DDR RAM device found, "
2182 "assuming 8MB video RAM\n",
2184 ret
|= SETIREG(SISSR
,0x14,0x31);
2188 /* Enable refresh */
2189 ret
|= SETIREG(SISSR
, 0x16, ramtypetable1
[4 + ramtype
]);
2190 ret
|= SETIREG(SISSR
, 0x17, ramtypetable1
[8 + ramtype
]);
2191 ret
|= SETIREG(SISSR
, 0x19, ramtypetable1
[16 + ramtype
]);
2193 ret
|= SETIREGOR(SISSR
, 0x21, 0x20);
2195 ret
|= SETIREG(SISSR
, 0x22, 0xfb);
2196 ret
|= SETIREG(SISSR
, 0x21, 0xa5);
2216 sisusb_get_ramconfig(struct sisusb_usb_data
*sisusb
)
2218 u8 tmp8
, tmp82
, ramtype
;
2220 char *ramtypetext1
= NULL
;
2221 const char *ramtypetext2
[] = { "SDR SDRAM", "SDR SGRAM",
2222 "DDR SDRAM", "DDR SGRAM" };
2223 static const int busSDR
[4] = {64, 64, 128, 128};
2224 static const int busDDR
[4] = {32, 32, 64, 64};
2225 static const int busDDRA
[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2227 sisusb_getidxreg(sisusb
, SISSR
, 0x14, &tmp8
);
2228 sisusb_getidxreg(sisusb
, SISSR
, 0x15, &tmp82
);
2229 sisusb_getidxreg(sisusb
, SISSR
, 0x3a, &ramtype
);
2230 sisusb
->vramsize
= (1 << ((tmp8
& 0xf0) >> 4)) * 1024 * 1024;
2232 switch ((tmp8
>> 2) & 0x03) {
2233 case 0: ramtypetext1
= "1 ch/1 r";
2237 bw
= busSDR
[(tmp8
& 0x03)];
2240 case 1: ramtypetext1
= "1 ch/2 r";
2241 sisusb
->vramsize
<<= 1;
2242 bw
= busSDR
[(tmp8
& 0x03)];
2244 case 2: ramtypetext1
= "asymmeric";
2245 sisusb
->vramsize
+= sisusb
->vramsize
/2;
2246 bw
= busDDRA
[(tmp8
& 0x03)];
2248 case 3: ramtypetext1
= "2 channel";
2249 sisusb
->vramsize
<<= 1;
2250 bw
= busDDR
[(tmp8
& 0x03)];
2254 printk(KERN_INFO
"sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2255 sisusb
->minor
, (sisusb
->vramsize
>> 20), ramtypetext1
,
2256 ramtypetext2
[ramtype
], bw
);
2260 sisusb_do_init_gfxdevice(struct sisusb_usb_data
*sisusb
)
2262 struct sisusb_packet packet
;
2267 packet
.header
= 0x001f;
2268 packet
.address
= 0x00000324;
2269 packet
.data
= 0x00000004;
2270 ret
= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2272 packet
.header
= 0x001f;
2273 packet
.address
= 0x00000364;
2274 packet
.data
= 0x00000004;
2275 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2277 packet
.header
= 0x001f;
2278 packet
.address
= 0x00000384;
2279 packet
.data
= 0x00000004;
2280 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2282 packet
.header
= 0x001f;
2283 packet
.address
= 0x00000100;
2284 packet
.data
= 0x00000700;
2285 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2287 packet
.header
= 0x000f;
2288 packet
.address
= 0x00000004;
2289 ret
|= sisusb_send_bridge_packet(sisusb
, 6, &packet
, 0);
2290 packet
.data
|= 0x17;
2291 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2293 /* Init BAR 0 (VRAM) */
2294 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2295 ret
|= sisusb_write_pci_config(sisusb
, 0x10, 0xfffffff0);
2296 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2298 tmp32
|= SISUSB_PCI_MEMBASE
;
2299 ret
|= sisusb_write_pci_config(sisusb
, 0x10, tmp32
);
2301 /* Init BAR 1 (MMIO) */
2302 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2303 ret
|= sisusb_write_pci_config(sisusb
, 0x14, 0xfffffff0);
2304 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2306 tmp32
|= SISUSB_PCI_MMIOBASE
;
2307 ret
|= sisusb_write_pci_config(sisusb
, 0x14, tmp32
);
2309 /* Init BAR 2 (i/o ports) */
2310 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2311 ret
|= sisusb_write_pci_config(sisusb
, 0x18, 0xfffffff0);
2312 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2314 tmp32
|= SISUSB_PCI_IOPORTBASE
;
2315 ret
|= sisusb_write_pci_config(sisusb
, 0x18, tmp32
);
2317 /* Enable memory and i/o access */
2318 ret
|= sisusb_read_pci_config(sisusb
, 0x04, &tmp32
);
2320 ret
|= sisusb_write_pci_config(sisusb
, 0x04, tmp32
);
2323 /* Some further magic */
2324 packet
.header
= 0x001f;
2325 packet
.address
= 0x00000050;
2326 packet
.data
= 0x000000ff;
2327 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2333 /* Initialize the graphics device (return 0 on success)
2334 * This initializes the net2280 as well as the PCI registers
2335 * of the graphics board.
2339 sisusb_init_gfxdevice(struct sisusb_usb_data
*sisusb
, int initscreen
)
2341 int ret
= 0, test
= 0;
2344 if (sisusb
->devinit
== 1) {
2345 /* Read PCI BARs and see if they have been set up */
2346 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2347 if (ret
) return ret
;
2348 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MEMBASE
) test
++;
2350 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2351 if (ret
) return ret
;
2352 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MMIOBASE
) test
++;
2354 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2355 if (ret
) return ret
;
2356 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_IOPORTBASE
) test
++;
2359 /* No? So reset the device */
2360 if ((sisusb
->devinit
== 0) || (test
!= 3)) {
2362 ret
|= sisusb_do_init_gfxdevice(sisusb
);
2365 sisusb
->devinit
= 1;
2369 if (sisusb
->devinit
) {
2370 /* Initialize the graphics core */
2371 if (sisusb_init_gfxcore(sisusb
) == 0) {
2372 sisusb
->gfxinit
= 1;
2373 sisusb_get_ramconfig(sisusb
);
2374 ret
|= sisusb_set_default_mode(sisusb
, 1);
2375 ret
|= sisusb_setup_screen(sisusb
, 1, initscreen
);
2383 #ifdef INCL_SISUSB_CON
2385 /* Set up default text mode:
2386 - Set text mode (0x03)
2387 - Upload default font
2388 - Upload user font (if available)
2392 sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
)
2394 int ret
= 0, slot
= sisusb
->font_slot
, i
;
2395 const struct font_desc
*myfont
;
2399 static const char bootstring
[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2400 static const char bootlogo
[] = "(o_ //\\ V_/_";
2402 /* sisusb->lock is down */
2404 if (!sisusb
->SiS_Pr
)
2407 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2408 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2411 SiSUSBSetMode(sisusb
->SiS_Pr
, 0x03);
2413 if (!(myfont
= find_font("VGA8x16")))
2416 if (!(tempbuf
= vmalloc(8192)))
2419 for (i
= 0; i
< 256; i
++)
2420 memcpy(tempbuf
+ (i
* 32), myfont
->data
+ (i
* 16), 16);
2422 /* Upload default font */
2423 ret
= sisusbcon_do_font_op(sisusb
, 1, 0, tempbuf
, 8192, 0, 1, NULL
, 16, 0);
2427 /* Upload user font (and reset current slot) */
2428 if (sisusb
->font_backup
) {
2429 ret
|= sisusbcon_do_font_op(sisusb
, 1, 2, sisusb
->font_backup
,
2430 8192, sisusb
->font_backup_512
, 1, NULL
,
2431 sisusb
->font_backup_height
, 0);
2433 sisusbcon_do_font_op(sisusb
, 1, 0, NULL
, 0, 0, 1,
2437 if (init
&& !sisusb
->scrbuf
) {
2439 if ((tempbuf
= vmalloc(8192))) {
2442 tempbufb
= (u16
*)tempbuf
;
2444 *(tempbufb
++) = 0x0720;
2447 tempbufb
= (u16
*)tempbuf
;
2448 while (bootlogo
[i
]) {
2449 *(tempbufb
++) = 0x0700 | bootlogo
[i
++];
2455 tempbufb
= (u16
*)tempbuf
+ 6;
2456 while (bootstring
[i
])
2457 *(tempbufb
++) = 0x0700 | bootstring
[i
++];
2459 ret
|= sisusb_copy_memory(sisusb
, tempbuf
,
2460 sisusb
->vrambase
, 8192, &written
);
2466 } else if (sisusb
->scrbuf
) {
2468 ret
|= sisusb_copy_memory(sisusb
, (char *)sisusb
->scrbuf
,
2469 sisusb
->vrambase
, sisusb
->scrbuf_size
, &written
);
2473 if (sisusb
->sisusb_cursor_size_from
>= 0 &&
2474 sisusb
->sisusb_cursor_size_to
>= 0) {
2475 sisusb_setidxreg(sisusb
, SISCR
, 0x0a,
2476 sisusb
->sisusb_cursor_size_from
);
2477 sisusb_setidxregandor(sisusb
, SISCR
, 0x0b, 0xe0,
2478 sisusb
->sisusb_cursor_size_to
);
2480 sisusb_setidxreg(sisusb
, SISCR
, 0x0a, 0x2d);
2481 sisusb_setidxreg(sisusb
, SISCR
, 0x0b, 0x0e);
2482 sisusb
->sisusb_cursor_size_to
= -1;
2485 slot
= sisusb
->sisusb_cursor_loc
;
2486 if(slot
< 0) slot
= 0;
2488 sisusb
->sisusb_cursor_loc
= -1;
2489 sisusb
->bad_cursor_pos
= 1;
2491 sisusb_set_cursor(sisusb
, slot
);
2493 sisusb_setidxreg(sisusb
, SISCR
, 0x0c, (sisusb
->cur_start_addr
>> 8));
2494 sisusb_setidxreg(sisusb
, SISCR
, 0x0d, (sisusb
->cur_start_addr
& 0xff));
2496 sisusb
->textmodedestroyed
= 0;
2498 /* sisusb->lock is down */
2508 sisusb_open(struct inode
*inode
, struct file
*file
)
2510 struct sisusb_usb_data
*sisusb
;
2511 struct usb_interface
*interface
;
2512 int subminor
= iminor(inode
);
2514 mutex_lock(&disconnect_mutex
);
2516 if (!(interface
= usb_find_interface(&sisusb_driver
, subminor
))) {
2517 printk(KERN_ERR
"sisusb[%d]: Failed to find interface\n",
2519 mutex_unlock(&disconnect_mutex
);
2523 if (!(sisusb
= usb_get_intfdata(interface
))) {
2524 mutex_unlock(&disconnect_mutex
);
2528 mutex_lock(&sisusb
->lock
);
2530 if (!sisusb
->present
|| !sisusb
->ready
) {
2531 mutex_unlock(&sisusb
->lock
);
2532 mutex_unlock(&disconnect_mutex
);
2536 if (sisusb
->isopen
) {
2537 mutex_unlock(&sisusb
->lock
);
2538 mutex_unlock(&disconnect_mutex
);
2542 if (!sisusb
->devinit
) {
2543 if (sisusb
->sisusb_dev
->speed
== USB_SPEED_HIGH
) {
2544 if (sisusb_init_gfxdevice(sisusb
, 0)) {
2545 mutex_unlock(&sisusb
->lock
);
2546 mutex_unlock(&disconnect_mutex
);
2548 "sisusbvga[%d]: Failed to initialize "
2554 mutex_unlock(&sisusb
->lock
);
2555 mutex_unlock(&disconnect_mutex
);
2557 "sisusbvga[%d]: Device not attached to "
2564 /* Increment usage count for our sisusb */
2565 kref_get(&sisusb
->kref
);
2569 file
->private_data
= sisusb
;
2571 mutex_unlock(&sisusb
->lock
);
2573 mutex_unlock(&disconnect_mutex
);
2579 sisusb_delete(struct kref
*kref
)
2581 struct sisusb_usb_data
*sisusb
= to_sisusb_dev(kref
);
2586 if (sisusb
->sisusb_dev
)
2587 usb_put_dev(sisusb
->sisusb_dev
);
2589 sisusb
->sisusb_dev
= NULL
;
2590 sisusb_free_buffers(sisusb
);
2591 sisusb_free_urbs(sisusb
);
2592 #ifdef INCL_SISUSB_CON
2593 kfree(sisusb
->SiS_Pr
);
2599 sisusb_release(struct inode
*inode
, struct file
*file
)
2601 struct sisusb_usb_data
*sisusb
;
2604 mutex_lock(&disconnect_mutex
);
2606 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
)) {
2607 mutex_unlock(&disconnect_mutex
);
2611 mutex_lock(&sisusb
->lock
);
2613 if (sisusb
->present
) {
2614 /* Wait for all URBs to finish if device still present */
2615 if (!sisusb_wait_all_out_complete(sisusb
))
2616 sisusb_kill_all_busy(sisusb
);
2619 myminor
= sisusb
->minor
;
2622 file
->private_data
= NULL
;
2624 mutex_unlock(&sisusb
->lock
);
2626 /* decrement the usage count on our device */
2627 kref_put(&sisusb
->kref
, sisusb_delete
);
2629 mutex_unlock(&disconnect_mutex
);
2635 sisusb_read(struct file
*file
, char __user
*buffer
, size_t count
, loff_t
*ppos
)
2637 struct sisusb_usb_data
*sisusb
;
2638 ssize_t bytes_read
= 0;
2644 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2647 mutex_lock(&sisusb
->lock
);
2650 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2651 mutex_unlock(&sisusb
->lock
);
2655 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2656 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2659 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2660 SISUSB_PCI_IOPORTBASE
;
2663 * Byte, word and long(32) can be read. As this
2664 * emulates inX instructions, the data returned is
2665 * in machine-endianness.
2670 if (sisusb_read_memio_byte(sisusb
,
2674 else if (put_user(buf8
, (u8 __user
*)buffer
))
2682 if (sisusb_read_memio_word(sisusb
,
2686 else if (put_user(buf16
, (u16 __user
*)buffer
))
2694 if (sisusb_read_memio_long(sisusb
,
2698 else if (put_user(buf32
, (u32 __user
*)buffer
))
2710 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2711 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2714 SISUSB_PCI_PSEUDO_MEMBASE
+
2718 * Remember: Data delivered is never endian-corrected
2720 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2721 NULL
, count
, buffer
, &bytes_read
);
2726 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2727 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2730 SISUSB_PCI_PSEUDO_MMIOBASE
+
2731 SISUSB_PCI_MMIOBASE
;
2734 * Remember: Data delivered is never endian-corrected
2736 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2737 NULL
, count
, buffer
, &bytes_read
);
2742 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2743 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ 0x5c) {
2746 mutex_unlock(&sisusb
->lock
);
2750 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2752 /* Read PCI config register
2753 * Return value delivered in machine endianness.
2755 if (sisusb_read_pci_config(sisusb
, address
, &buf32
))
2757 else if (put_user(buf32
, (u32 __user
*)buffer
))
2768 (*ppos
) += bytes_read
;
2770 mutex_unlock(&sisusb
->lock
);
2772 return errno
? errno
: bytes_read
;
2776 sisusb_write(struct file
*file
, const char __user
*buffer
, size_t count
,
2779 struct sisusb_usb_data
*sisusb
;
2781 ssize_t bytes_written
= 0;
2786 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2789 mutex_lock(&sisusb
->lock
);
2792 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2793 mutex_unlock(&sisusb
->lock
);
2797 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2798 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2801 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2802 SISUSB_PCI_IOPORTBASE
;
2805 * Byte, word and long(32) can be written. As this
2806 * emulates outX instructions, the data is expected
2807 * in machine-endianness.
2812 if (get_user(buf8
, (u8 __user
*)buffer
))
2814 else if (sisusb_write_memio_byte(sisusb
,
2824 if (get_user(buf16
, (u16 __user
*)buffer
))
2826 else if (sisusb_write_memio_word(sisusb
,
2836 if (get_user(buf32
, (u32 __user
*)buffer
))
2838 else if (sisusb_write_memio_long(sisusb
,
2851 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2852 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2855 SISUSB_PCI_PSEUDO_MEMBASE
+
2859 * Buffer is copied 1:1, therefore, on big-endian
2860 * machines, the data must be swapped by userland
2861 * in advance (if applicable; no swapping in 8bpp
2862 * mode or if YUV data is being transferred).
2864 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2865 count
, buffer
, 0, &bytes_written
);
2868 errno
= bytes_written
;
2870 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2871 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2874 SISUSB_PCI_PSEUDO_MMIOBASE
+
2875 SISUSB_PCI_MMIOBASE
;
2878 * Buffer is copied 1:1, therefore, on big-endian
2879 * machines, the data must be swapped by userland
2882 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2883 count
, buffer
, 0, &bytes_written
);
2886 errno
= bytes_written
;
2888 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2889 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ SISUSB_PCI_PCONFSIZE
) {
2892 mutex_unlock(&sisusb
->lock
);
2896 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2898 /* Write PCI config register.
2899 * Given value expected in machine endianness.
2901 if (get_user(buf32
, (u32 __user
*)buffer
))
2903 else if (sisusb_write_pci_config(sisusb
, address
, buf32
))
2916 (*ppos
) += bytes_written
;
2918 mutex_unlock(&sisusb
->lock
);
2920 return errno
? errno
: bytes_written
;
2924 sisusb_lseek(struct file
*file
, loff_t offset
, int orig
)
2926 struct sisusb_usb_data
*sisusb
;
2929 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2932 mutex_lock(&sisusb
->lock
);
2935 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2936 mutex_unlock(&sisusb
->lock
);
2942 file
->f_pos
= offset
;
2944 /* never negative, no force_successful_syscall needed */
2947 file
->f_pos
+= offset
;
2949 /* never negative, no force_successful_syscall needed */
2952 /* seeking relative to "end of file" is not supported */
2956 mutex_unlock(&sisusb
->lock
);
2961 sisusb_handle_command(struct sisusb_usb_data
*sisusb
, struct sisusb_command
*y
,
2964 int retval
, port
, length
;
2967 /* All our commands require the device
2968 * to be initialized.
2970 if (!sisusb
->devinit
)
2974 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2975 SISUSB_PCI_IOPORTBASE
;
2977 switch (y
->operation
) {
2979 retval
= sisusb_getidxreg(sisusb
, port
,
2980 y
->data0
, &y
->data1
);
2982 if (copy_to_user((void __user
*)arg
, y
,
2989 retval
= sisusb_setidxreg(sisusb
, port
,
2990 y
->data0
, y
->data1
);
2994 retval
= sisusb_setidxregor(sisusb
, port
,
2995 y
->data0
, y
->data1
);
2999 retval
= sisusb_setidxregand(sisusb
, port
,
3000 y
->data0
, y
->data1
);
3003 case SUCMD_SETANDOR
:
3004 retval
= sisusb_setidxregandor(sisusb
, port
,
3005 y
->data0
, y
->data1
, y
->data2
);
3009 retval
= sisusb_setidxregmask(sisusb
, port
,
3010 y
->data0
, y
->data1
, y
->data2
);
3014 /* Gfx core must be initialized */
3015 if (!sisusb
->gfxinit
)
3018 length
= (y
->data0
<< 16) | (y
->data1
<< 8) | y
->data2
;
3019 address
= y
->data3
-
3020 SISUSB_PCI_PSEUDO_MEMBASE
+
3022 retval
= sisusb_clear_vram(sisusb
, address
, length
);
3025 case SUCMD_HANDLETEXTMODE
:
3027 #ifdef INCL_SISUSB_CON
3028 /* Gfx core must be initialized, SiS_Pr must exist */
3029 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3034 retval
= sisusb_reset_text_mode(sisusb
, 0);
3037 sisusb
->textmodedestroyed
= 1;
3043 #ifdef INCL_SISUSB_CON
3045 /* Gfx core must be initialized, SiS_Pr must exist */
3046 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3051 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
3052 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
3054 if (SiSUSBSetMode(sisusb
->SiS_Pr
, y
->data3
))
3059 case SUCMD_SETVESAMODE
:
3060 /* Gfx core must be initialized, SiS_Pr must exist */
3061 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3066 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
3067 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
3069 if (SiSUSBSetVESAMode(sisusb
->SiS_Pr
, y
->data3
))
3086 sisusb_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
3089 struct sisusb_usb_data
*sisusb
;
3090 struct sisusb_info x
;
3091 struct sisusb_command y
;
3093 u32 __user
*argp
= (u32 __user
*)arg
;
3095 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
3098 mutex_lock(&sisusb
->lock
);
3101 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
3108 case SISUSB_GET_CONFIG_SIZE
:
3110 if (put_user(sizeof(x
), argp
))
3115 case SISUSB_GET_CONFIG
:
3117 x
.sisusb_id
= SISUSB_ID
;
3118 x
.sisusb_version
= SISUSB_VERSION
;
3119 x
.sisusb_revision
= SISUSB_REVISION
;
3120 x
.sisusb_patchlevel
= SISUSB_PATCHLEVEL
;
3121 x
.sisusb_gfxinit
= sisusb
->gfxinit
;
3122 x
.sisusb_vrambase
= SISUSB_PCI_PSEUDO_MEMBASE
;
3123 x
.sisusb_mmiobase
= SISUSB_PCI_PSEUDO_MMIOBASE
;
3124 x
.sisusb_iobase
= SISUSB_PCI_PSEUDO_IOPORTBASE
;
3125 x
.sisusb_pcibase
= SISUSB_PCI_PSEUDO_PCIBASE
;
3126 x
.sisusb_vramsize
= sisusb
->vramsize
;
3127 x
.sisusb_minor
= sisusb
->minor
;
3128 x
.sisusb_fbdevactive
= 0;
3129 #ifdef INCL_SISUSB_CON
3130 x
.sisusb_conactive
= sisusb
->haveconsole
? 1 : 0;
3132 x
.sisusb_conactive
= 0;
3135 if (copy_to_user((void __user
*)arg
, &x
, sizeof(x
)))
3140 case SISUSB_COMMAND
:
3142 if (copy_from_user(&y
, (void __user
*)arg
, sizeof(y
)))
3145 retval
= sisusb_handle_command(sisusb
, &y
, arg
);
3155 mutex_unlock(&sisusb
->lock
);
3159 #ifdef SISUSB_NEW_CONFIG_COMPAT
3161 sisusb_compat_ioctl(struct file
*f
, unsigned int cmd
, unsigned long arg
)
3166 case SISUSB_GET_CONFIG_SIZE
:
3167 case SISUSB_GET_CONFIG
:
3168 case SISUSB_COMMAND
:
3170 retval
= sisusb_ioctl(f
->f_path
.dentry
->d_inode
, f
, cmd
, arg
);
3175 return -ENOIOCTLCMD
;
3180 static const struct file_operations usb_sisusb_fops
= {
3181 .owner
= THIS_MODULE
,
3182 .open
= sisusb_open
,
3183 .release
= sisusb_release
,
3184 .read
= sisusb_read
,
3185 .write
= sisusb_write
,
3186 .llseek
= sisusb_lseek
,
3187 #ifdef SISUSB_NEW_CONFIG_COMPAT
3188 .compat_ioctl
= sisusb_compat_ioctl
,
3190 .ioctl
= sisusb_ioctl
3193 static struct usb_class_driver usb_sisusb_class
= {
3194 .name
= "sisusbvga%d",
3195 .fops
= &usb_sisusb_fops
,
3196 .minor_base
= SISUSB_MINOR
3199 static int sisusb_probe(struct usb_interface
*intf
,
3200 const struct usb_device_id
*id
)
3202 struct usb_device
*dev
= interface_to_usbdev(intf
);
3203 struct sisusb_usb_data
*sisusb
;
3205 const char *memfail
=
3207 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3209 printk(KERN_INFO
"sisusb: USB2VGA dongle found at address %d\n",
3212 /* Allocate memory for our private */
3213 if (!(sisusb
= kzalloc(sizeof(*sisusb
), GFP_KERNEL
))) {
3215 "sisusb: Failed to allocate memory for private data\n");
3218 kref_init(&sisusb
->kref
);
3220 mutex_init(&(sisusb
->lock
));
3222 /* Register device */
3223 if ((retval
= usb_register_dev(intf
, &usb_sisusb_class
))) {
3225 "sisusb: Failed to get a minor for device %d\n",
3231 sisusb
->sisusb_dev
= dev
;
3232 sisusb
->minor
= intf
->minor
;
3233 sisusb
->vrambase
= SISUSB_PCI_MEMBASE
;
3234 sisusb
->mmiobase
= SISUSB_PCI_MMIOBASE
;
3235 sisusb
->mmiosize
= SISUSB_PCI_MMIOSIZE
;
3236 sisusb
->ioportbase
= SISUSB_PCI_IOPORTBASE
;
3237 /* Everything else is zero */
3239 /* Allocate buffers */
3240 sisusb
->ibufsize
= SISUSB_IBUF_SIZE
;
3241 if (!(sisusb
->ibuf
= usb_buffer_alloc(dev
, SISUSB_IBUF_SIZE
,
3242 GFP_KERNEL
, &sisusb
->transfer_dma_in
))) {
3243 printk(memfail
, "input", sisusb
->minor
);
3248 sisusb
->numobufs
= 0;
3249 sisusb
->obufsize
= SISUSB_OBUF_SIZE
;
3250 for (i
= 0; i
< NUMOBUFS
; i
++) {
3251 if (!(sisusb
->obuf
[i
] = usb_buffer_alloc(dev
, SISUSB_OBUF_SIZE
,
3253 &sisusb
->transfer_dma_out
[i
]))) {
3255 printk(memfail
, "output", sisusb
->minor
);
3266 if (!(sisusb
->sisurbin
= usb_alloc_urb(0, GFP_KERNEL
))) {
3268 "sisusbvga[%d]: Failed to allocate URBs\n",
3273 sisusb
->completein
= 1;
3275 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
3276 if (!(sisusb
->sisurbout
[i
] = usb_alloc_urb(0, GFP_KERNEL
))) {
3278 "sisusbvga[%d]: Failed to allocate URBs\n",
3283 sisusb
->urbout_context
[i
].sisusb
= (void *)sisusb
;
3284 sisusb
->urbout_context
[i
].urbindex
= i
;
3285 sisusb
->urbstatus
[i
] = 0;
3288 printk(KERN_INFO
"sisusbvga[%d]: Allocated %d output buffers\n",
3289 sisusb
->minor
, sisusb
->numobufs
);
3291 #ifdef INCL_SISUSB_CON
3292 /* Allocate our SiS_Pr */
3293 if (!(sisusb
->SiS_Pr
= kmalloc(sizeof(struct SiS_Private
), GFP_KERNEL
))) {
3295 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3300 /* Do remaining init stuff */
3302 init_waitqueue_head(&sisusb
->wait_q
);
3304 usb_set_intfdata(intf
, sisusb
);
3306 usb_get_dev(sisusb
->sisusb_dev
);
3308 sisusb
->present
= 1;
3310 #ifdef SISUSB_OLD_CONFIG_COMPAT
3313 /* Our ioctls are all "32/64bit compatible" */
3314 ret
= register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE
, NULL
);
3315 ret
|= register_ioctl32_conversion(SISUSB_GET_CONFIG
, NULL
);
3316 ret
|= register_ioctl32_conversion(SISUSB_COMMAND
, NULL
);
3319 "sisusbvga[%d]: Error registering ioctl32 "
3323 sisusb
->ioctl32registered
= 1;
3327 if (dev
->speed
== USB_SPEED_HIGH
) {
3329 #ifdef INCL_SISUSB_CON
3330 if (sisusb_first_vc
> 0 &&
3331 sisusb_last_vc
> 0 &&
3332 sisusb_first_vc
<= sisusb_last_vc
&&
3333 sisusb_last_vc
<= MAX_NR_CONSOLES
)
3336 if (sisusb_init_gfxdevice(sisusb
, initscreen
))
3338 "sisusbvga[%d]: Failed to early "
3339 "initialize device\n",
3344 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3350 #ifdef SISUSBENDIANTEST
3351 printk(KERN_DEBUG
"sisusb: *** RWTEST ***\n");
3352 sisusb_testreadwrite(sisusb
);
3353 printk(KERN_DEBUG
"sisusb: *** RWTEST END ***\n");
3356 #ifdef INCL_SISUSB_CON
3357 sisusb_console_init(sisusb
, sisusb_first_vc
, sisusb_last_vc
);
3363 sisusb_free_urbs(sisusb
);
3365 sisusb_free_buffers(sisusb
);
3367 usb_deregister_dev(intf
, &usb_sisusb_class
);
3373 static void sisusb_disconnect(struct usb_interface
*intf
)
3375 struct sisusb_usb_data
*sisusb
;
3378 /* This should *not* happen */
3379 if (!(sisusb
= usb_get_intfdata(intf
)))
3382 #ifdef INCL_SISUSB_CON
3383 sisusb_console_exit(sisusb
);
3386 /* The above code doesn't need the disconnect
3387 * semaphore to be down; its meaning is to
3388 * protect all other routines from the disconnect
3389 * case, not the other way round.
3391 mutex_lock(&disconnect_mutex
);
3393 mutex_lock(&sisusb
->lock
);
3395 /* Wait for all URBs to complete and kill them in case (MUST do) */
3396 if (!sisusb_wait_all_out_complete(sisusb
))
3397 sisusb_kill_all_busy(sisusb
);
3399 minor
= sisusb
->minor
;
3401 usb_set_intfdata(intf
, NULL
);
3403 usb_deregister_dev(intf
, &usb_sisusb_class
);
3405 #ifdef SISUSB_OLD_CONFIG_COMPAT
3406 if (sisusb
->ioctl32registered
) {
3408 sisusb
->ioctl32registered
= 0;
3409 ret
= unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE
);
3410 ret
|= unregister_ioctl32_conversion(SISUSB_GET_CONFIG
);
3411 ret
|= unregister_ioctl32_conversion(SISUSB_COMMAND
);
3414 "sisusbvga[%d]: Error unregistering "
3415 "ioctl32 translations\n",
3421 sisusb
->present
= 0;
3424 mutex_unlock(&sisusb
->lock
);
3426 /* decrement our usage count */
3427 kref_put(&sisusb
->kref
, sisusb_delete
);
3429 mutex_unlock(&disconnect_mutex
);
3431 printk(KERN_INFO
"sisusbvga[%d]: Disconnected\n", minor
);
3434 static struct usb_device_id sisusb_table
[] = {
3435 { USB_DEVICE(0x0711, 0x0900) },
3436 { USB_DEVICE(0x0711, 0x0901) },
3437 { USB_DEVICE(0x0711, 0x0902) },
3438 { USB_DEVICE(0x182d, 0x021c) },
3439 { USB_DEVICE(0x182d, 0x0269) },
3443 MODULE_DEVICE_TABLE (usb
, sisusb_table
);
3445 static struct usb_driver sisusb_driver
= {
3447 .probe
= sisusb_probe
,
3448 .disconnect
= sisusb_disconnect
,
3449 .id_table
= sisusb_table
,
3452 static int __init
usb_sisusb_init(void)
3456 #ifdef INCL_SISUSB_CON
3457 sisusb_init_concode();
3460 if (!(retval
= usb_register(&sisusb_driver
))) {
3462 printk(KERN_INFO
"sisusb: Driver version %d.%d.%d\n",
3463 SISUSB_VERSION
, SISUSB_REVISION
, SISUSB_PATCHLEVEL
);
3465 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3472 static void __exit
usb_sisusb_exit(void)
3474 usb_deregister(&sisusb_driver
);
3477 module_init(usb_sisusb_init
);
3478 module_exit(usb_sisusb_exit
);
3480 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3481 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3482 MODULE_LICENSE("GPL");