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/config.h>
40 #include <linux/version.h>
41 #include <linux/module.h>
42 #include <linux/kernel.h>
43 #include <linux/signal.h>
44 #include <linux/sched.h>
45 #include <linux/errno.h>
46 #include <linux/poll.h>
47 #include <linux/init.h>
48 #include <linux/slab.h>
49 #include <linux/spinlock.h>
50 #include <linux/kref.h>
51 #include <linux/usb.h>
52 #include <linux/smp_lock.h>
53 #include <linux/vmalloc.h>
57 #ifdef INCL_SISUSB_CON
58 #include <linux/font.h>
61 #define SISUSB_DONTSYNC
63 /* Forward declarations / clean-up routines */
65 #ifdef INCL_SISUSB_CON
66 int sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
);
67 int sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
);
68 int sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 data
);
69 int sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8
*data
);
70 int sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
, u8 myor
);
71 int sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 myor
);
72 int sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
);
74 int sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
);
75 int sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
);
76 int sisusb_writew(struct sisusb_usb_data
*sisusb
, u32 adr
, u16 data
);
77 int sisusb_readw(struct sisusb_usb_data
*sisusb
, u32 adr
, u16
*data
);
78 int sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
79 u32 dest
, int length
, size_t *bytes_written
);
81 int sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
);
83 extern int SiSUSBSetMode(struct SiS_Private
*SiS_Pr
, unsigned short ModeNo
);
84 extern int SiSUSBSetVESAMode(struct SiS_Private
*SiS_Pr
, unsigned short VModeNo
);
86 extern void sisusb_init_concode(void);
87 extern int sisusb_console_init(struct sisusb_usb_data
*sisusb
, int first
, int last
);
88 extern void sisusb_console_exit(struct sisusb_usb_data
*sisusb
);
90 extern void sisusb_set_cursor(struct sisusb_usb_data
*sisusb
, unsigned int location
);
92 extern int sisusbcon_do_font_op(struct sisusb_usb_data
*sisusb
, int set
, int slot
,
93 u8
*arg
, int cmapsz
, int ch512
, int dorecalc
,
94 struct vc_data
*c
, int fh
, int uplock
);
96 static int sisusb_first_vc
= 0;
97 static int sisusb_last_vc
= 0;
98 module_param_named(first
, sisusb_first_vc
, int, 0);
99 module_param_named(last
, sisusb_last_vc
, int, 0);
100 MODULE_PARM_DESC(first
, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
101 MODULE_PARM_DESC(last
, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
104 static struct usb_driver sisusb_driver
;
106 DECLARE_MUTEX(disconnect_sem
);
109 sisusb_free_buffers(struct sisusb_usb_data
*sisusb
)
113 for (i
= 0; i
< NUMOBUFS
; i
++) {
114 if (sisusb
->obuf
[i
]) {
115 usb_buffer_free(sisusb
->sisusb_dev
, sisusb
->obufsize
,
116 sisusb
->obuf
[i
], sisusb
->transfer_dma_out
[i
]);
117 sisusb
->obuf
[i
] = NULL
;
121 usb_buffer_free(sisusb
->sisusb_dev
, sisusb
->ibufsize
,
122 sisusb
->ibuf
, sisusb
->transfer_dma_in
);
128 sisusb_free_urbs(struct sisusb_usb_data
*sisusb
)
132 for (i
= 0; i
< NUMOBUFS
; i
++) {
133 usb_free_urb(sisusb
->sisurbout
[i
]);
134 sisusb
->sisurbout
[i
] = NULL
;
136 usb_free_urb(sisusb
->sisurbin
);
137 sisusb
->sisurbin
= NULL
;
140 /* Level 0: USB transport layer */
144 /* out-urb management */
146 /* Return 1 if all free, 0 otherwise */
148 sisusb_all_free(struct sisusb_usb_data
*sisusb
)
152 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
154 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
162 /* Kill all busy URBs */
164 sisusb_kill_all_busy(struct sisusb_usb_data
*sisusb
)
168 if (sisusb_all_free(sisusb
))
171 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
173 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
174 usb_kill_urb(sisusb
->sisurbout
[i
]);
179 /* Return 1 if ok, 0 if error (not all complete within timeout) */
181 sisusb_wait_all_out_complete(struct sisusb_usb_data
*sisusb
)
183 int timeout
= 5 * HZ
, i
= 1;
185 wait_event_timeout(sisusb
->wait_q
,
186 (i
= sisusb_all_free(sisusb
)),
193 sisusb_outurb_available(struct sisusb_usb_data
*sisusb
)
197 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
199 if ((sisusb
->urbstatus
[i
] & (SU_URB_BUSY
|SU_URB_ALLOC
)) == 0)
208 sisusb_get_free_outbuf(struct sisusb_usb_data
*sisusb
)
210 int i
, timeout
= 5 * HZ
;
212 wait_event_timeout(sisusb
->wait_q
,
213 ((i
= sisusb_outurb_available(sisusb
)) >= 0),
220 sisusb_alloc_outbuf(struct sisusb_usb_data
*sisusb
)
224 i
= sisusb_outurb_available(sisusb
);
227 sisusb
->urbstatus
[i
] |= SU_URB_ALLOC
;
233 sisusb_free_outbuf(struct sisusb_usb_data
*sisusb
, int index
)
235 if ((index
>= 0) && (index
< sisusb
->numobufs
))
236 sisusb
->urbstatus
[index
] &= ~SU_URB_ALLOC
;
239 /* completion callback */
242 sisusb_bulk_completeout(struct urb
*urb
, struct pt_regs
*regs
)
244 struct sisusb_urb_context
*context
= urb
->context
;
245 struct sisusb_usb_data
*sisusb
;
250 sisusb
= context
->sisusb
;
252 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
255 #ifndef SISUSB_DONTSYNC
256 if (context
->actual_length
)
257 *(context
->actual_length
) += urb
->actual_length
;
260 sisusb
->urbstatus
[context
->urbindex
] &= ~SU_URB_BUSY
;
261 wake_up(&sisusb
->wait_q
);
265 sisusb_bulkout_msg(struct sisusb_usb_data
*sisusb
, int index
, unsigned int pipe
, void *data
,
266 int len
, int *actual_length
, int timeout
, unsigned int tflags
,
267 dma_addr_t transfer_dma
)
269 struct urb
*urb
= sisusb
->sisurbout
[index
];
270 int retval
, byteswritten
= 0;
273 urb
->transfer_flags
= 0;
275 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
276 sisusb_bulk_completeout
, &sisusb
->urbout_context
[index
]);
278 urb
->transfer_flags
|= tflags
;
279 urb
->actual_length
= 0;
281 if ((urb
->transfer_dma
= transfer_dma
))
282 urb
->transfer_flags
|= URB_NO_TRANSFER_DMA_MAP
;
285 sisusb
->urbout_context
[index
].actual_length
= (timeout
) ?
286 NULL
: actual_length
;
288 /* Declare this urb/buffer in use */
289 sisusb
->urbstatus
[index
] |= SU_URB_BUSY
;
292 retval
= usb_submit_urb(urb
, GFP_ATOMIC
);
294 /* If OK, and if timeout > 0, wait for completion */
295 if ((retval
== 0) && timeout
) {
296 wait_event_timeout(sisusb
->wait_q
,
297 (!(sisusb
->urbstatus
[index
] & SU_URB_BUSY
)),
299 if (sisusb
->urbstatus
[index
] & SU_URB_BUSY
) {
300 /* URB timed out... kill it and report error */
304 /* Otherwise, report urb status */
305 retval
= urb
->status
;
306 byteswritten
= urb
->actual_length
;
311 *actual_length
= byteswritten
;
318 /* completion callback */
321 sisusb_bulk_completein(struct urb
*urb
, struct pt_regs
*regs
)
323 struct sisusb_usb_data
*sisusb
= urb
->context
;
325 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
328 sisusb
->completein
= 1;
329 wake_up(&sisusb
->wait_q
);
333 sisusb_bulkin_msg(struct sisusb_usb_data
*sisusb
, unsigned int pipe
, void *data
, int len
,
334 int *actual_length
, int timeout
, unsigned int tflags
, dma_addr_t transfer_dma
)
336 struct urb
*urb
= sisusb
->sisurbin
;
337 int retval
, readbytes
= 0;
339 urb
->transfer_flags
= 0;
341 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
342 sisusb_bulk_completein
, sisusb
);
344 urb
->transfer_flags
|= tflags
;
345 urb
->actual_length
= 0;
347 if ((urb
->transfer_dma
= transfer_dma
))
348 urb
->transfer_flags
|= URB_NO_TRANSFER_DMA_MAP
;
350 sisusb
->completein
= 0;
351 retval
= usb_submit_urb(urb
, GFP_ATOMIC
);
353 wait_event_timeout(sisusb
->wait_q
, sisusb
->completein
, timeout
);
354 if (!sisusb
->completein
) {
355 /* URB timed out... kill it and report error */
359 /* URB completed within timout */
360 retval
= urb
->status
;
361 readbytes
= urb
->actual_length
;
366 *actual_length
= readbytes
;
374 /* Send a bulk message of variable size
376 * To copy the data from userspace, give pointer to "userbuffer",
377 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
378 * both of these are NULL, it is assumed, that the transfer
379 * buffer "sisusb->obuf[index]" is set up with the data to send.
380 * Index is ignored if either kernbuffer or userbuffer is set.
381 * If async is nonzero, URBs will be sent without waiting for
382 * completion of the previous URB.
384 * (return 0 on success)
387 static int sisusb_send_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
388 char *kernbuffer
, const char __user
*userbuffer
, int index
,
389 ssize_t
*bytes_written
, unsigned int tflags
, int async
)
391 int result
= 0, retry
, count
= len
;
392 int passsize
, thispass
, transferred_len
= 0;
393 int fromuser
= (userbuffer
!= NULL
) ? 1 : 0;
394 int fromkern
= (kernbuffer
!= NULL
) ? 1 : 0;
398 (*bytes_written
) = 0;
401 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
404 /* If we copy data from kernel or userspace, force the
405 * allocation of a buffer/urb. If we have the data in
406 * the transfer buffer[index] already, reuse the buffer/URB
407 * if the length is > buffer size. (So, transmitting
408 * large data amounts directly from the transfer buffer
409 * treats the buffer as a ring buffer. However, we need
410 * to sync in this case.)
412 if (fromuser
|| fromkern
)
414 else if (len
> sisusb
->obufsize
)
417 pipe
= usb_sndbulkpipe(sisusb
->sisusb_dev
, ep
);
420 passsize
= thispass
= (sisusb
->obufsize
< count
) ?
421 sisusb
->obufsize
: count
;
424 index
= sisusb_get_free_outbuf(sisusb
);
429 buffer
= sisusb
->obuf
[index
];
433 if (copy_from_user(buffer
, userbuffer
, passsize
))
436 userbuffer
+= passsize
;
438 } else if (fromkern
) {
440 memcpy(buffer
, kernbuffer
, passsize
);
441 kernbuffer
+= passsize
;
448 if (!sisusb
->sisusb_dev
)
451 result
= sisusb_bulkout_msg(sisusb
,
459 sisusb
->transfer_dma_out
[index
]);
461 if (result
== -ETIMEDOUT
) {
463 /* Will not happen if async */
469 } else if ((result
== 0) && !async
&& transferred_len
) {
471 thispass
-= transferred_len
;
473 if (sisusb
->transfer_dma_out
) {
474 /* If DMA, copy remaining
475 * to beginning of buffer
478 buffer
+ transferred_len
,
481 /* If not DMA, simply increase
484 buffer
+= transferred_len
;
495 (*bytes_written
) += passsize
;
498 /* Force new allocation in next iteration */
499 if (fromuser
|| fromkern
)
505 #ifdef SISUSB_DONTSYNC
506 (*bytes_written
) = len
;
507 /* Some URBs/buffers might be busy */
509 sisusb_wait_all_out_complete(sisusb
);
510 (*bytes_written
) = transferred_len
;
511 /* All URBs and all buffers are available */
515 return ((*bytes_written
) == len
) ? 0 : -EIO
;
518 /* Receive a bulk message of variable size
520 * To copy the data to userspace, give pointer to "userbuffer",
521 * to copy to kernel memory, give "kernbuffer". One of them
522 * MUST be set. (There is no technique for letting the caller
523 * read directly from the ibuf.)
527 static int sisusb_recv_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
528 void *kernbuffer
, char __user
*userbuffer
, ssize_t
*bytes_read
,
531 int result
= 0, retry
, count
= len
;
532 int bufsize
, thispass
, transferred_len
;
539 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
542 pipe
= usb_rcvbulkpipe(sisusb
->sisusb_dev
, ep
);
543 buffer
= sisusb
->ibuf
;
544 bufsize
= sisusb
->ibufsize
;
548 #ifdef SISUSB_DONTSYNC
549 if (!(sisusb_wait_all_out_complete(sisusb
)))
555 if (!sisusb
->sisusb_dev
)
558 thispass
= (bufsize
< count
) ? bufsize
: count
;
560 result
= sisusb_bulkin_msg(sisusb
,
567 sisusb
->transfer_dma_in
);
570 thispass
= transferred_len
;
572 else if (result
== -ETIMEDOUT
) {
585 (*bytes_read
) += thispass
;
590 if (copy_to_user(userbuffer
, buffer
, thispass
))
593 userbuffer
+= thispass
;
597 memcpy(kernbuffer
, buffer
, thispass
);
598 kernbuffer
+= thispass
;
606 return ((*bytes_read
) == len
) ? 0 : -EIO
;
609 static int sisusb_send_packet(struct sisusb_usb_data
*sisusb
, int len
,
610 struct sisusb_packet
*packet
)
613 ssize_t bytes_transferred
= 0;
619 #ifdef SISUSB_DONTSYNC
620 if (!(sisusb_wait_all_out_complete(sisusb
)))
624 /* Eventually correct endianness */
625 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
627 /* 1. send the packet */
628 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_GFX_OUT
, len
,
629 (char *)packet
, NULL
, 0, &bytes_transferred
, 0, 0);
631 if ((ret
== 0) && (len
== 6)) {
633 /* 2. if packet len == 6, it means we read, so wait for 32bit
634 * return value and write it to packet->data
636 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_GFX_IN
, 4,
637 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
639 packet
->data
= le32_to_cpu(tmp
);
645 static int sisusb_send_bridge_packet(struct sisusb_usb_data
*sisusb
, int len
,
646 struct sisusb_packet
*packet
,
650 ssize_t bytes_transferred
= 0;
656 #ifdef SISUSB_DONTSYNC
657 if (!(sisusb_wait_all_out_complete(sisusb
)))
661 /* Eventually correct endianness */
662 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
664 /* 1. send the packet */
665 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_OUT
, len
,
666 (char *)packet
, NULL
, 0, &bytes_transferred
, tflags
, 0);
668 if ((ret
== 0) && (len
== 6)) {
670 /* 2. if packet len == 6, it means we read, so wait for 32bit
671 * return value and write it to packet->data
673 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_IN
, 4,
674 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
676 packet
->data
= le32_to_cpu(tmp
);
682 /* access video memory and mmio (return 0 on success) */
686 /* The following routines assume being used to transfer byte, word,
689 * - the write routines expect "data" in machine endianness format.
690 * The data will be converted to leXX in sisusb_xxx_packet.
691 * - the read routines can expect read data in machine-endianess.
694 static int sisusb_write_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
697 struct sisusb_packet packet
;
700 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
701 packet
.address
= addr
& ~3;
702 packet
.data
= data
<< ((addr
& 3) << 3);
703 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
707 static int sisusb_write_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
710 struct sisusb_packet packet
;
713 packet
.address
= addr
& ~3;
717 packet
.header
= (type
<< 6) | 0x0003;
718 packet
.data
= (u32
)data
;
719 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
722 packet
.header
= (type
<< 6) | 0x0006;
723 packet
.data
= (u32
)data
<< 8;
724 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
727 packet
.header
= (type
<< 6) | 0x000c;
728 packet
.data
= (u32
)data
<< 16;
729 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
732 packet
.header
= (type
<< 6) | 0x0008;
733 packet
.data
= (u32
)data
<< 24;
734 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
735 packet
.header
= (type
<< 6) | 0x0001;
736 packet
.address
= (addr
& ~3) + 4;
737 packet
.data
= (u32
)data
>> 8;
738 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
744 static int sisusb_write_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
747 struct sisusb_packet packet
;
750 packet
.address
= addr
& ~3;
754 packet
.header
= (type
<< 6) | 0x0007;
755 packet
.data
= data
& 0x00ffffff;
756 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
759 packet
.header
= (type
<< 6) | 0x000e;
760 packet
.data
= data
<< 8;
761 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
764 packet
.header
= (type
<< 6) | 0x000c;
765 packet
.data
= data
<< 16;
766 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
767 packet
.header
= (type
<< 6) | 0x0001;
768 packet
.address
= (addr
& ~3) + 4;
769 packet
.data
= (data
>> 16) & 0x00ff;
770 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
773 packet
.header
= (type
<< 6) | 0x0008;
774 packet
.data
= data
<< 24;
775 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
776 packet
.header
= (type
<< 6) | 0x0003;
777 packet
.address
= (addr
& ~3) + 4;
778 packet
.data
= (data
>> 8) & 0xffff;
779 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
785 static int sisusb_write_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
788 struct sisusb_packet packet
;
791 packet
.address
= addr
& ~3;
795 packet
.header
= (type
<< 6) | 0x000f;
797 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
800 packet
.header
= (type
<< 6) | 0x000e;
801 packet
.data
= data
<< 8;
802 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
803 packet
.header
= (type
<< 6) | 0x0001;
804 packet
.address
= (addr
& ~3) + 4;
805 packet
.data
= data
>> 24;
806 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
809 packet
.header
= (type
<< 6) | 0x000c;
810 packet
.data
= data
<< 16;
811 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
812 packet
.header
= (type
<< 6) | 0x0003;
813 packet
.address
= (addr
& ~3) + 4;
814 packet
.data
= data
>> 16;
815 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
818 packet
.header
= (type
<< 6) | 0x0008;
819 packet
.data
= data
<< 24;
820 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
821 packet
.header
= (type
<< 6) | 0x0007;
822 packet
.address
= (addr
& ~3) + 4;
823 packet
.data
= data
>> 8;
824 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
830 /* The xxx_bulk routines copy a buffer of variable size. They treat the
831 * buffer as chars, therefore lsb/msb has to be corrected if using the
832 * byte/word/long/etc routines for speed-up
834 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
835 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
836 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
837 * that the data already is in the transfer buffer "sisusb->obuf[index]".
840 static int sisusb_write_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
841 char *kernbuffer
, int length
,
842 const char __user
*userbuffer
, int index
,
843 ssize_t
*bytes_written
)
845 struct sisusb_packet packet
;
847 static int msgcount
= 0;
848 u8 swap8
, fromkern
= kernbuffer
? 1 : 0;
850 u32 swap32
, flag
= (length
>> 28) & 1;
853 /* if neither kernbuffer not userbuffer are given, assume
856 if (!fromkern
&& !userbuffer
)
857 kernbuffer
= sisusb
->obuf
[index
];
859 (*bytes_written
= 0);
861 length
&= 0x00ffffff;
872 if (get_user(swap8
, (u8 __user
*)userbuffer
))
875 swap8
= kernbuffer
[0];
877 ret
= sisusb_write_memio_byte(sisusb
,
888 if (get_user(swap16
, (u16 __user
*)userbuffer
))
891 swap16
= *((u16
*)kernbuffer
);
893 ret
= sisusb_write_memio_word(sisusb
,
899 (*bytes_written
) += 2;
905 if (copy_from_user(&buf
, userbuffer
, 3))
908 swap32
= (buf
[0] << 16) |
912 swap32
= (buf
[2] << 16) |
918 swap32
= (kernbuffer
[0] << 16) |
919 (kernbuffer
[1] << 8) |
922 swap32
= (kernbuffer
[2] << 16) |
923 (kernbuffer
[1] << 8) |
927 ret
= sisusb_write_memio_24bit(sisusb
,
933 (*bytes_written
) += 3;
939 if (get_user(swap32
, (u32 __user
*)userbuffer
))
942 swap32
= *((u32
*)kernbuffer
);
944 ret
= sisusb_write_memio_long(sisusb
,
949 (*bytes_written
) += 4;
954 if ((length
& ~3) > 0x10000) {
956 packet
.header
= 0x001f;
957 packet
.address
= 0x000001d4;
959 ret
= sisusb_send_bridge_packet(sisusb
, 10,
961 packet
.header
= 0x001f;
962 packet
.address
= 0x000001d0;
963 packet
.data
= (length
& ~3);
964 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
966 packet
.header
= 0x001f;
967 packet
.address
= 0x000001c0;
968 packet
.data
= flag
| 0x16;
969 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
972 ret
|= sisusb_send_bulk_msg(sisusb
,
973 SISUSB_EP_GFX_LBULK_OUT
,
976 bytes_written
, 0, 1);
977 userbuffer
+= (*bytes_written
);
978 } else if (fromkern
) {
979 ret
|= sisusb_send_bulk_msg(sisusb
,
980 SISUSB_EP_GFX_LBULK_OUT
,
983 bytes_written
, 0, 1);
984 kernbuffer
+= (*bytes_written
);
986 ret
|= sisusb_send_bulk_msg(sisusb
,
987 SISUSB_EP_GFX_LBULK_OUT
,
990 bytes_written
, 0, 1);
991 kernbuffer
+= ((*bytes_written
) &
992 (sisusb
->obufsize
-1));
997 packet
.header
= 0x001f;
998 packet
.address
= 0x00000194;
1000 ret
= sisusb_send_bridge_packet(sisusb
, 10,
1002 packet
.header
= 0x001f;
1003 packet
.address
= 0x00000190;
1004 packet
.data
= (length
& ~3);
1005 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1007 if (sisusb
->flagb0
!= 0x16) {
1008 packet
.header
= 0x001f;
1009 packet
.address
= 0x00000180;
1010 packet
.data
= flag
| 0x16;
1011 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1013 sisusb
->flagb0
= 0x16;
1016 ret
|= sisusb_send_bulk_msg(sisusb
,
1017 SISUSB_EP_GFX_BULK_OUT
,
1019 NULL
, userbuffer
, 0,
1020 bytes_written
, 0, 1);
1021 userbuffer
+= (*bytes_written
);
1022 } else if (fromkern
) {
1023 ret
|= sisusb_send_bulk_msg(sisusb
,
1024 SISUSB_EP_GFX_BULK_OUT
,
1026 kernbuffer
, NULL
, 0,
1027 bytes_written
, 0, 1);
1028 kernbuffer
+= (*bytes_written
);
1030 ret
|= sisusb_send_bulk_msg(sisusb
,
1031 SISUSB_EP_GFX_BULK_OUT
,
1034 bytes_written
, 0, 1);
1035 kernbuffer
+= ((*bytes_written
) &
1036 (sisusb
->obufsize
-1));
1043 "sisusbvga[%d]: Wrote %zd of "
1044 "%d bytes, error %d\n",
1045 sisusb
->minor
, *bytes_written
,
1047 else if (msgcount
== 500)
1049 "sisusbvga[%d]: Too many errors"
1050 ", logging stopped\n",
1053 addr
+= (*bytes_written
);
1054 length
-= (*bytes_written
);
1062 return ret
? -EIO
: 0;
1065 /* Remember: Read data in packet is in machine-endianess! So for
1066 * byte, word, 24bit, long no endian correction is necessary.
1069 static int sisusb_read_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
1072 struct sisusb_packet packet
;
1075 CLEARPACKET(&packet
);
1076 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
1077 packet
.address
= addr
& ~3;
1078 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1079 *data
= (u8
)(packet
.data
>> ((addr
& 3) << 3));
1083 static int sisusb_read_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
1084 u32 addr
, u16
*data
)
1086 struct sisusb_packet packet
;
1089 CLEARPACKET(&packet
);
1091 packet
.address
= addr
& ~3;
1095 packet
.header
= (type
<< 6) | 0x0003;
1096 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1097 *data
= (u16
)(packet
.data
);
1100 packet
.header
= (type
<< 6) | 0x0006;
1101 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1102 *data
= (u16
)(packet
.data
>> 8);
1105 packet
.header
= (type
<< 6) | 0x000c;
1106 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1107 *data
= (u16
)(packet
.data
>> 16);
1110 packet
.header
= (type
<< 6) | 0x0008;
1111 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1112 *data
= (u16
)(packet
.data
>> 24);
1113 packet
.header
= (type
<< 6) | 0x0001;
1114 packet
.address
= (addr
& ~3) + 4;
1115 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1116 *data
|= (u16
)(packet
.data
<< 8);
1122 static int sisusb_read_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
1123 u32 addr
, u32
*data
)
1125 struct sisusb_packet packet
;
1128 packet
.address
= addr
& ~3;
1132 packet
.header
= (type
<< 6) | 0x0007;
1133 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1134 *data
= packet
.data
& 0x00ffffff;
1137 packet
.header
= (type
<< 6) | 0x000e;
1138 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1139 *data
= packet
.data
>> 8;
1142 packet
.header
= (type
<< 6) | 0x000c;
1143 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1144 *data
= packet
.data
>> 16;
1145 packet
.header
= (type
<< 6) | 0x0001;
1146 packet
.address
= (addr
& ~3) + 4;
1147 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1148 *data
|= ((packet
.data
& 0xff) << 16);
1151 packet
.header
= (type
<< 6) | 0x0008;
1152 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1153 *data
= packet
.data
>> 24;
1154 packet
.header
= (type
<< 6) | 0x0003;
1155 packet
.address
= (addr
& ~3) + 4;
1156 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1157 *data
|= ((packet
.data
& 0xffff) << 8);
1163 static int sisusb_read_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
1164 u32 addr
, u32
*data
)
1166 struct sisusb_packet packet
;
1169 packet
.address
= addr
& ~3;
1173 packet
.header
= (type
<< 6) | 0x000f;
1174 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1175 *data
= packet
.data
;
1178 packet
.header
= (type
<< 6) | 0x000e;
1179 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1180 *data
= packet
.data
>> 8;
1181 packet
.header
= (type
<< 6) | 0x0001;
1182 packet
.address
= (addr
& ~3) + 4;
1183 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1184 *data
|= (packet
.data
<< 24);
1187 packet
.header
= (type
<< 6) | 0x000c;
1188 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1189 *data
= packet
.data
>> 16;
1190 packet
.header
= (type
<< 6) | 0x0003;
1191 packet
.address
= (addr
& ~3) + 4;
1192 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1193 *data
|= (packet
.data
<< 16);
1196 packet
.header
= (type
<< 6) | 0x0008;
1197 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1198 *data
= packet
.data
>> 24;
1199 packet
.header
= (type
<< 6) | 0x0007;
1200 packet
.address
= (addr
& ~3) + 4;
1201 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1202 *data
|= (packet
.data
<< 8);
1208 static int sisusb_read_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
1209 char *kernbuffer
, int length
,
1210 char __user
*userbuffer
, ssize_t
*bytes_read
)
1219 length
&= 0x00ffffff;
1230 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
1235 if (put_user(buf
[0],
1236 (u8 __user
*)userbuffer
)) {
1240 kernbuffer
[0] = buf
[0];
1246 ret
|= sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1251 if (put_user(swap16
,
1252 (u16 __user
*)userbuffer
))
1255 *((u16
*)kernbuffer
) = swap16
;
1261 ret
|= sisusb_read_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
1266 buf
[0] = (swap32
>> 16) & 0xff;
1267 buf
[1] = (swap32
>> 8) & 0xff;
1268 buf
[2] = swap32
& 0xff;
1270 buf
[2] = (swap32
>> 16) & 0xff;
1271 buf
[1] = (swap32
>> 8) & 0xff;
1272 buf
[0] = swap32
& 0xff;
1275 if (copy_to_user(userbuffer
, &buf
[0], 3))
1278 kernbuffer
[0] = buf
[0];
1279 kernbuffer
[1] = buf
[1];
1280 kernbuffer
[2] = buf
[2];
1286 ret
|= sisusb_read_memio_long(sisusb
, SISUSB_TYPE_MEM
,
1291 if (put_user(swap32
,
1292 (u32 __user
*)userbuffer
))
1297 *((u32
*)kernbuffer
) = swap32
;
1303 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1305 CLEARPACKET(&packet
);
1306 packet
.header
= 0x001f;
1307 packet
.address
= 0x000001a0;
1308 packet
.data
= 0x00000006;
1309 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1311 packet
.header
= 0x001f;
1312 packet
.address
= 0x000001b0;
1313 packet
.data
= (length
& ~3) | 0x40000000;
1314 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1316 packet
.header
= 0x001f;
1317 packet
.address
= 0x000001b4;
1319 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1321 packet
.header
= 0x001f;
1322 packet
.address
= 0x000001a4;
1323 packet
.data
= 0x00000001;
1324 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1327 ret
|= sisusb_recv_bulk_msg(sisusb
,
1328 SISUSB_EP_GFX_BULK_IN
,
1332 if (!ret
) userbuffer
+= (*bytes_read
);
1334 ret
|= sisusb_recv_bulk_msg(sisusb
,
1335 SISUSB_EP_GFX_BULK_IN
,
1339 if (!ret
) kernbuffer
+= (*bytes_read
);
1341 addr
+= (*bytes_read
);
1342 length
-= (*bytes_read
);
1353 /* High level: Gfx (indexed) register access */
1355 #ifdef INCL_SISUSB_CON
1357 sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
)
1359 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1363 sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
)
1365 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1369 #ifndef INCL_SISUSB_CON
1373 sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 data
)
1376 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1377 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1381 #ifndef INCL_SISUSB_CON
1385 sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8
*data
)
1388 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1389 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1393 #ifndef INCL_SISUSB_CON
1397 sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1403 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1404 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1407 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1412 sisusb_setidxregmask(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1417 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1418 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1420 tmp
|= (data
& mask
);
1421 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1425 #ifndef INCL_SISUSB_CON
1429 sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 myor
)
1431 return(sisusb_setidxregandor(sisusb
, port
, index
, 0xff, myor
));
1434 #ifndef INCL_SISUSB_CON
1438 sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
)
1440 return(sisusb_setidxregandor(sisusb
, port
, idx
, myand
, 0x00));
1443 /* Write/read video ram */
1445 #ifdef INCL_SISUSB_CON
1447 sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
)
1449 return(sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1453 sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
)
1455 return(sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1459 sisusb_writew(struct sisusb_usb_data
*sisusb
, u32 adr
, u16 data
)
1461 return(sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1465 sisusb_readw(struct sisusb_usb_data
*sisusb
, u32 adr
, u16
*data
)
1467 return(sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1471 sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
1472 u32 dest
, int length
, size_t *bytes_written
)
1474 return(sisusb_write_mem_bulk(sisusb
, dest
, src
, length
, NULL
, 0, bytes_written
));
1477 #ifdef SISUSBENDIANTEST
1479 sisusb_read_memory(struct sisusb_usb_data
*sisusb
, char *dest
,
1480 u32 src
, int length
, size_t *bytes_written
)
1482 return(sisusb_read_mem_bulk(sisusb
, src
, dest
, length
, NULL
, bytes_written
));
1487 #ifdef SISUSBENDIANTEST
1489 sisusb_testreadwrite(struct sisusb_usb_data
*sisusb
)
1491 static char srcbuffer
[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1492 char destbuffer
[10];
1496 sisusb_copy_memory(sisusb
, srcbuffer
, sisusb
->vrambase
, 7, &dummy
);
1498 for(i
= 1; i
<= 7; i
++) {
1499 printk(KERN_DEBUG
"sisusb: rwtest %d bytes\n", i
);
1500 sisusb_read_memory(sisusb
, destbuffer
, sisusb
->vrambase
, i
, &dummy
);
1501 for(j
= 0; j
< i
; j
++) {
1502 printk(KERN_DEBUG
"sisusb: rwtest read[%d] = %x\n", j
, destbuffer
[j
]);
1508 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1511 sisusb_write_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32 data
)
1513 struct sisusb_packet packet
;
1516 packet
.header
= 0x008f;
1517 packet
.address
= regnum
| 0x10000;
1519 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
1524 sisusb_read_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32
*data
)
1526 struct sisusb_packet packet
;
1529 packet
.header
= 0x008f;
1530 packet
.address
= (u32
)regnum
| 0x10000;
1531 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1532 *data
= packet
.data
;
1536 /* Clear video RAM */
1539 sisusb_clear_vram(struct sisusb_usb_data
*sisusb
, u32 address
, int length
)
1544 if (address
< sisusb
->vrambase
)
1547 if (address
>= sisusb
->vrambase
+ sisusb
->vramsize
)
1550 if (address
+ length
> sisusb
->vrambase
+ sisusb
->vramsize
)
1551 length
= sisusb
->vrambase
+ sisusb
->vramsize
- address
;
1556 /* allocate free buffer/urb and clear the buffer */
1557 if ((i
= sisusb_alloc_outbuf(sisusb
)) < 0)
1560 memset(sisusb
->obuf
[i
], 0, sisusb
->obufsize
);
1562 /* We can write a length > buffer size here. The buffer
1563 * data will simply be re-used (like a ring-buffer).
1565 ret
= sisusb_write_mem_bulk(sisusb
, address
, NULL
, length
, NULL
, i
, &j
);
1567 /* Free the buffer/urb */
1568 sisusb_free_outbuf(sisusb
, i
);
1573 /* Initialize the graphics core (return 0 on success)
1574 * This resets the graphics hardware and puts it into
1575 * a defined mode (640x480@60Hz)
1578 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1579 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1580 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1581 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1582 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1583 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1584 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1585 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1586 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1587 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1588 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1591 sisusb_triggersr16(struct sisusb_usb_data
*sisusb
, u8 ramtype
)
1596 ret
= GETIREG(SISSR
, 0x16, &tmp8
);
1599 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1601 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1604 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1606 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1608 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1610 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1612 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1614 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1616 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1622 sisusb_getbuswidth(struct sisusb_usb_data
*sisusb
, int *bw
, int *chab
)
1625 u8 ramtype
, done
= 0;
1627 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1629 ret
= GETIREG(SISSR
, 0x3a, &ramtype
);
1632 ret
|= SETIREG(SISSR
, 0x13, 0x00);
1635 ret
|= SETIREG(SISSR
, 0x14, 0x12);
1636 ret
|= SETIREGAND(SISSR
, 0x15, 0xef);
1638 ret
|= SETIREG(SISSR
, 0x14, 0x02);
1641 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1642 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1643 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1644 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1645 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1646 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1647 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1648 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1649 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1650 ret
|= READL(ramptr
+ 0, &t0
);
1651 ret
|= READL(ramptr
+ 4, &t1
);
1652 ret
|= READL(ramptr
+ 8, &t2
);
1653 ret
|= READL(ramptr
+ 12, &t3
);
1657 *chab
= 0; *bw
= 64;
1659 if ((t3
!= 0xcdef0123) || (t2
!= 0x89abcdef)) {
1660 if ((t1
== 0x456789ab) && (t0
== 0x01234567)) {
1661 *chab
= 0; *bw
= 64;
1662 ret
|= SETIREGAND(SISSR
, 0x14, 0xfd);
1665 if ((t1
!= 0x456789ab) || (t0
!= 0x01234567)) {
1666 *chab
= 1; *bw
= 64;
1667 ret
|= SETIREGANDOR(SISSR
, 0x14, 0xfc,0x01);
1669 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1670 ret
|= WRITEL(ramptr
+ 0, 0x89abcdef);
1671 ret
|= WRITEL(ramptr
+ 4, 0xcdef0123);
1672 ret
|= WRITEL(ramptr
+ 8, 0x55555555);
1673 ret
|= WRITEL(ramptr
+ 12, 0x55555555);
1674 ret
|= WRITEL(ramptr
+ 16, 0xaaaaaaaa);
1675 ret
|= WRITEL(ramptr
+ 20, 0xaaaaaaaa);
1676 ret
|= READL(ramptr
+ 4, &t1
);
1678 if (t1
!= 0xcdef0123) {
1680 ret
|= SETIREGOR(SISSR
, 0x15, 0x10);
1686 *chab
= 0; *bw
= 64; /* default: cha, bw = 64 */
1690 if (t1
== 0x456789ab) {
1691 if (t0
== 0x01234567) {
1692 *chab
= 0; *bw
= 64;
1696 if (t0
== 0x01234567) {
1697 *chab
= 0; *bw
= 32;
1698 ret
|= SETIREG(SISSR
, 0x14, 0x00);
1704 ret
|= SETIREG(SISSR
, 0x14, 0x03);
1705 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1707 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1708 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1709 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1710 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1711 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1712 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1713 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1714 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1715 ret
|= READL(ramptr
+ 0, &t0
);
1716 ret
|= READL(ramptr
+ 4, &t1
);
1718 if (t1
== 0x456789ab) {
1719 if (t0
== 0x01234567) {
1720 *chab
= 1; *bw
= 64;
1724 if (t0
== 0x01234567) {
1725 *chab
= 1; *bw
= 32;
1726 ret
|= SETIREG(SISSR
, 0x14, 0x01);
1735 sisusb_verify_mclk(struct sisusb_usb_data
*sisusb
)
1738 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1739 u8 tmp1
, tmp2
, i
, j
;
1741 ret
|= WRITEB(ramptr
, 0xaa);
1742 ret
|= WRITEB(ramptr
+ 16, 0x55);
1743 ret
|= READB(ramptr
, &tmp1
);
1744 ret
|= READB(ramptr
+ 16, &tmp2
);
1745 if ((tmp1
!= 0xaa) || (tmp2
!= 0x55)) {
1746 for (i
= 0, j
= 16; i
< 2; i
++, j
+= 16) {
1747 ret
|= GETIREG(SISSR
, 0x21, &tmp1
);
1748 ret
|= SETIREGAND(SISSR
, 0x21, (tmp1
& 0xfb));
1749 ret
|= SETIREGOR(SISSR
, 0x3c, 0x01); /* not on 330 */
1750 ret
|= SETIREGAND(SISSR
, 0x3c, 0xfe); /* not on 330 */
1751 ret
|= SETIREG(SISSR
, 0x21, tmp1
);
1752 ret
|= WRITEB(ramptr
+ 16 + j
, j
);
1753 ret
|= READB(ramptr
+ 16 + j
, &tmp1
);
1755 ret
|= WRITEB(ramptr
+ j
, j
);
1764 sisusb_set_rank(struct sisusb_usb_data
*sisusb
, int *iret
, int index
,
1765 u8 rankno
, u8 chab
, const u8 dramtype
[][5],
1768 int ret
= 0, ranksize
;
1773 if ((rankno
== 2) && (dramtype
[index
][0] == 2))
1776 ranksize
= dramtype
[index
][3] / 2 * bw
/ 32;
1778 if ((ranksize
* rankno
) > 128)
1782 while ((ranksize
>>= 1) > 0) tmp
+= 0x10;
1783 tmp
|= ((rankno
- 1) << 2);
1784 tmp
|= ((bw
/ 64) & 0x02);
1785 tmp
|= (chab
& 0x01);
1787 ret
= SETIREG(SISSR
, 0x14, tmp
);
1788 ret
|= sisusb_triggersr16(sisusb
, 0); /* sic! */
1796 sisusb_check_rbc(struct sisusb_usb_data
*sisusb
, int *iret
, u32 inc
, int testn
)
1803 for (i
= 0, j
= 0; i
< testn
; i
++) {
1804 ret
|= WRITEL(sisusb
->vrambase
+ j
, j
);
1808 for (i
= 0, j
= 0; i
< testn
; i
++) {
1809 ret
|= READL(sisusb
->vrambase
+ j
, &tmp
);
1810 if (tmp
!= j
) return ret
;
1819 sisusb_check_ranks(struct sisusb_usb_data
*sisusb
, int *iret
, int rankno
,
1820 int idx
, int bw
, const u8 rtype
[][5])
1822 int ret
= 0, i
, i2ret
;
1827 for (i
= rankno
; i
>= 1; i
--) {
1828 inc
= 1 << (rtype
[idx
][2] +
1832 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1837 inc
= 1 << (rtype
[idx
][2] + bw
/ 64 + 2);
1838 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 4);
1842 inc
= 1 << (10 + bw
/ 64);
1843 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1852 sisusb_get_sdram_size(struct sisusb_usb_data
*sisusb
, int *iret
, int bw
,
1855 int ret
= 0, i2ret
= 0, i
, j
;
1856 static const u8 sdramtype
[13][5] = {
1857 { 2, 12, 9, 64, 0x35 },
1858 { 1, 13, 9, 64, 0x44 },
1859 { 2, 12, 8, 32, 0x31 },
1860 { 2, 11, 9, 32, 0x25 },
1861 { 1, 12, 9, 32, 0x34 },
1862 { 1, 13, 8, 32, 0x40 },
1863 { 2, 11, 8, 16, 0x21 },
1864 { 1, 12, 8, 16, 0x30 },
1865 { 1, 11, 9, 16, 0x24 },
1866 { 1, 11, 8, 8, 0x20 },
1867 { 2, 9, 8, 4, 0x01 },
1868 { 1, 10, 8, 4, 0x10 },
1869 { 1, 9, 8, 2, 0x00 }
1872 *iret
= 1; /* error */
1874 for (i
= 0; i
< 13; i
++) {
1875 ret
|= SETIREGANDOR(SISSR
, 0x13, 0x80, sdramtype
[i
][4]);
1876 for (j
= 2; j
> 0; j
--) {
1877 ret
|= sisusb_set_rank(sisusb
, &i2ret
, i
, j
,
1878 chab
, sdramtype
, bw
);
1882 ret
|= sisusb_check_ranks(sisusb
, &i2ret
, j
, i
,
1885 *iret
= 0; /* ram size found */
1895 sisusb_setup_screen(struct sisusb_usb_data
*sisusb
, int clrall
, int drwfr
)
1899 int i
, length
, modex
, modey
, bpp
;
1901 modex
= 640; modey
= 480; bpp
= 2;
1903 address
= sisusb
->vrambase
; /* Clear video ram */
1906 length
= sisusb
->vramsize
;
1908 length
= modex
* bpp
* modey
;
1910 ret
= sisusb_clear_vram(sisusb
, address
, length
);
1912 if (!ret
&& drwfr
) {
1913 for (i
= 0; i
< modex
; i
++) {
1914 address
= sisusb
->vrambase
+ (i
* bpp
);
1915 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1917 address
+= (modex
* (modey
-1) * bpp
);
1918 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1921 for (i
= 0; i
< modey
; i
++) {
1922 address
= sisusb
->vrambase
+ ((i
* modex
) * bpp
);
1923 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1925 address
+= ((modex
- 1) * bpp
);
1926 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1935 sisusb_set_default_mode(struct sisusb_usb_data
*sisusb
, int touchengines
)
1937 int ret
= 0, i
, j
, modex
, modey
, bpp
, du
;
1938 u8 sr31
, cr63
, tmp8
;
1939 static const char attrdata
[] = {
1940 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1941 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1944 static const char crtcrdata
[] = {
1945 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1946 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1947 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1950 static const char grcdata
[] = {
1951 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1954 static const char crtcdata
[] = {
1955 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1956 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1960 modex
= 640; modey
= 480; bpp
= 2;
1962 GETIREG(SISSR
, 0x31, &sr31
);
1963 GETIREG(SISCR
, 0x63, &cr63
);
1964 SETIREGOR(SISSR
, 0x01, 0x20);
1965 SETIREG(SISCR
, 0x63, cr63
& 0xbf);
1966 SETIREGOR(SISCR
, 0x17, 0x80);
1967 SETIREGOR(SISSR
, 0x1f, 0x04);
1968 SETIREGAND(SISSR
, 0x07, 0xfb);
1969 SETIREG(SISSR
, 0x00, 0x03); /* seq */
1970 SETIREG(SISSR
, 0x01, 0x21);
1971 SETIREG(SISSR
, 0x02, 0x0f);
1972 SETIREG(SISSR
, 0x03, 0x00);
1973 SETIREG(SISSR
, 0x04, 0x0e);
1974 SETREG(SISMISCW
, 0x23); /* misc */
1975 for (i
= 0; i
<= 0x18; i
++) { /* crtc */
1976 SETIREG(SISCR
, i
, crtcrdata
[i
]);
1978 for (i
= 0; i
<= 0x13; i
++) { /* att */
1979 GETREG(SISINPSTAT
, &tmp8
);
1981 SETREG(SISAR
, attrdata
[i
]);
1983 GETREG(SISINPSTAT
, &tmp8
);
1984 SETREG(SISAR
, 0x14);
1985 SETREG(SISAR
, 0x00);
1986 GETREG(SISINPSTAT
, &tmp8
);
1987 SETREG(SISAR
, 0x20);
1988 GETREG(SISINPSTAT
, &tmp8
);
1989 for (i
= 0; i
<= 0x08; i
++) { /* grc */
1990 SETIREG(SISGR
, i
, grcdata
[i
]);
1992 SETIREGAND(SISGR
, 0x05, 0xbf);
1993 for (i
= 0x0A; i
<= 0x0E; i
++) { /* clr ext */
1994 SETIREG(SISSR
, i
, 0x00);
1996 SETIREGAND(SISSR
, 0x37, 0xfe);
1997 SETREG(SISMISCW
, 0xef); /* sync */
1998 SETIREG(SISCR
, 0x11, 0x00); /* crtc */
1999 for (j
= 0x00, i
= 0; i
<= 7; i
++, j
++) {
2000 SETIREG(SISCR
, j
, crtcdata
[i
]);
2002 for (j
= 0x10; i
<= 10; i
++, j
++) {
2003 SETIREG(SISCR
, j
, crtcdata
[i
]);
2005 for (j
= 0x15; i
<= 12; i
++, j
++) {
2006 SETIREG(SISCR
, j
, crtcdata
[i
]);
2008 for (j
= 0x0A; i
<= 15; i
++, j
++) {
2009 SETIREG(SISSR
, j
, crtcdata
[i
]);
2011 SETIREG(SISSR
, 0x0E, (crtcdata
[16] & 0xE0));
2012 SETIREGANDOR(SISCR
, 0x09, 0x5f, ((crtcdata
[16] & 0x01) << 5));
2013 SETIREG(SISCR
, 0x14, 0x4f);
2014 du
= (modex
/ 16) * (bpp
* 2); /* offset/pitch */
2015 if (modex
% 16) du
+= bpp
;
2016 SETIREGANDOR(SISSR
, 0x0e, 0xf0, ((du
>> 8) & 0x0f));
2017 SETIREG(SISCR
, 0x13, (du
& 0xff));
2020 if (du
& 0xff) tmp8
++;
2021 SETIREG(SISSR
, 0x10, tmp8
);
2022 SETIREG(SISSR
, 0x31, 0x00); /* VCLK */
2023 SETIREG(SISSR
, 0x2b, 0x1b);
2024 SETIREG(SISSR
, 0x2c, 0xe1);
2025 SETIREG(SISSR
, 0x2d, 0x01);
2026 SETIREGAND(SISSR
, 0x3d, 0xfe); /* FIFO */
2027 SETIREG(SISSR
, 0x08, 0xae);
2028 SETIREGAND(SISSR
, 0x09, 0xf0);
2029 SETIREG(SISSR
, 0x08, 0x34);
2030 SETIREGOR(SISSR
, 0x3d, 0x01);
2031 SETIREGAND(SISSR
, 0x1f, 0x3f); /* mode regs */
2032 SETIREGANDOR(SISSR
, 0x06, 0xc0, 0x0a);
2033 SETIREG(SISCR
, 0x19, 0x00);
2034 SETIREGAND(SISCR
, 0x1a, 0xfc);
2035 SETIREGAND(SISSR
, 0x0f, 0xb7);
2036 SETIREGAND(SISSR
, 0x31, 0xfb);
2037 SETIREGANDOR(SISSR
, 0x21, 0x1f, 0xa0);
2038 SETIREGAND(SISSR
, 0x32, 0xf3);
2039 SETIREGANDOR(SISSR
, 0x07, 0xf8, 0x03);
2040 SETIREG(SISCR
, 0x52, 0x6c);
2042 SETIREG(SISCR
, 0x0d, 0x00); /* adjust frame */
2043 SETIREG(SISCR
, 0x0c, 0x00);
2044 SETIREG(SISSR
, 0x0d, 0x00);
2045 SETIREGAND(SISSR
, 0x37, 0xfe);
2047 SETIREG(SISCR
, 0x32, 0x20);
2048 SETIREGAND(SISSR
, 0x01, 0xdf); /* enable display */
2049 SETIREG(SISCR
, 0x63, (cr63
& 0xbf));
2050 SETIREG(SISSR
, 0x31, (sr31
& 0xfb));
2053 SETIREG(SISSR
, 0x20, 0xa1); /* enable engines */
2054 SETIREGOR(SISSR
, 0x1e, 0x5a);
2056 SETIREG(SISSR
, 0x26, 0x01); /* disable cmdqueue */
2057 SETIREG(SISSR
, 0x27, 0x1f);
2058 SETIREG(SISSR
, 0x26, 0x00);
2061 SETIREG(SISCR
, 0x34, 0x44); /* we just set std mode #44 */
2067 sisusb_init_gfxcore(struct sisusb_usb_data
*sisusb
)
2069 int ret
= 0, i
, j
, bw
, chab
, iret
, retry
= 3;
2072 static const char mclktable
[] = {
2073 0x3b, 0x22, 0x01, 143,
2074 0x3b, 0x22, 0x01, 143,
2075 0x3b, 0x22, 0x01, 143,
2076 0x3b, 0x22, 0x01, 143
2078 static const char eclktable
[] = {
2079 0x3b, 0x22, 0x01, 143,
2080 0x3b, 0x22, 0x01, 143,
2081 0x3b, 0x22, 0x01, 143,
2082 0x3b, 0x22, 0x01, 143
2084 static const char ramtypetable1
[] = {
2085 0x00, 0x04, 0x60, 0x60,
2086 0x0f, 0x0f, 0x1f, 0x1f,
2087 0xba, 0xba, 0xba, 0xba,
2088 0xa9, 0xa9, 0xac, 0xac,
2089 0xa0, 0xa0, 0xa0, 0xa8,
2090 0x00, 0x00, 0x02, 0x02,
2091 0x30, 0x30, 0x40, 0x40
2093 static const char ramtypetable2
[] = {
2094 0x77, 0x77, 0x44, 0x44,
2095 0x77, 0x77, 0x44, 0x44,
2096 0x00, 0x00, 0x00, 0x00,
2097 0x5b, 0x5b, 0xab, 0xab,
2098 0x00, 0x00, 0xf0, 0xf8
2104 ret
= GETREG(SISVGAEN
, &tmp8
);
2105 ret
|= SETREG(SISVGAEN
, (tmp8
| 0x01));
2107 /* Enable GPU access to VRAM */
2108 ret
|= GETREG(SISMISCR
, &tmp8
);
2109 ret
|= SETREG(SISMISCW
, (tmp8
| 0x01));
2113 /* Reset registers */
2114 ret
|= SETIREGAND(SISCR
, 0x5b, 0xdf);
2115 ret
|= SETIREG(SISSR
, 0x05, 0x86);
2116 ret
|= SETIREGOR(SISSR
, 0x20, 0x01);
2118 ret
|= SETREG(SISMISCW
, 0x67);
2120 for (i
= 0x06; i
<= 0x1f; i
++) {
2121 ret
|= SETIREG(SISSR
, i
, 0x00);
2123 for (i
= 0x21; i
<= 0x27; i
++) {
2124 ret
|= SETIREG(SISSR
, i
, 0x00);
2126 for (i
= 0x31; i
<= 0x3d; i
++) {
2127 ret
|= SETIREG(SISSR
, i
, 0x00);
2129 for (i
= 0x12; i
<= 0x1b; i
++) {
2130 ret
|= SETIREG(SISSR
, i
, 0x00);
2132 for (i
= 0x79; i
<= 0x7c; i
++) {
2133 ret
|= SETIREG(SISCR
, i
, 0x00);
2138 ret
|= SETIREG(SISCR
, 0x63, 0x80);
2140 ret
|= GETIREG(SISSR
, 0x3a, &ramtype
);
2143 ret
|= SETIREG(SISSR
, 0x28, mclktable
[ramtype
* 4]);
2144 ret
|= SETIREG(SISSR
, 0x29, mclktable
[(ramtype
* 4) + 1]);
2145 ret
|= SETIREG(SISSR
, 0x2a, mclktable
[(ramtype
* 4) + 2]);
2147 ret
|= SETIREG(SISSR
, 0x2e, eclktable
[ramtype
* 4]);
2148 ret
|= SETIREG(SISSR
, 0x2f, eclktable
[(ramtype
* 4) + 1]);
2149 ret
|= SETIREG(SISSR
, 0x30, eclktable
[(ramtype
* 4) + 2]);
2151 ret
|= SETIREG(SISSR
, 0x07, 0x18);
2152 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2156 for (i
= 0x15, j
= 0; i
<= 0x1b; i
++, j
++) {
2157 ret
|= SETIREG(SISSR
, i
, ramtypetable1
[(j
*4) + ramtype
]);
2159 for (i
= 0x40, j
= 0; i
<= 0x44; i
++, j
++) {
2160 ret
|= SETIREG(SISCR
, i
, ramtypetable2
[(j
*4) + ramtype
]);
2163 ret
|= SETIREG(SISCR
, 0x49, 0xaa);
2165 ret
|= SETIREG(SISSR
, 0x1f, 0x00);
2166 ret
|= SETIREG(SISSR
, 0x20, 0xa0);
2167 ret
|= SETIREG(SISSR
, 0x23, 0xf6);
2168 ret
|= SETIREG(SISSR
, 0x24, 0x0d);
2169 ret
|= SETIREG(SISSR
, 0x25, 0x33);
2171 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2173 ret
|= SETIREGOR(SISPART1
, 0x2f, 0x01);
2175 ret
|= SETIREGAND(SISCAP
, 0x3f, 0xef);
2179 ret
|= SETIREG(SISPART1
, 0x00, 0x00);
2181 ret
|= GETIREG(SISSR
, 0x13, &tmp8
);
2184 ret
|= SETIREG(SISPART1
, 0x02, 0x00);
2185 ret
|= SETIREG(SISPART1
, 0x2e, 0x08);
2187 ret
|= sisusb_read_pci_config(sisusb
, 0x50, &tmp32
);
2188 tmp32
&= 0x00f00000;
2189 tmp8
= (tmp32
== 0x100000) ? 0x33 : 0x03;
2190 ret
|= SETIREG(SISSR
, 0x25, tmp8
);
2191 tmp8
= (tmp32
== 0x100000) ? 0xaa : 0x88;
2192 ret
|= SETIREG(SISCR
, 0x49, tmp8
);
2194 ret
|= SETIREG(SISSR
, 0x27, 0x1f);
2195 ret
|= SETIREG(SISSR
, 0x31, 0x00);
2196 ret
|= SETIREG(SISSR
, 0x32, 0x11);
2197 ret
|= SETIREG(SISSR
, 0x33, 0x00);
2201 ret
|= SETIREG(SISCR
, 0x83, 0x00);
2203 ret
|= sisusb_set_default_mode(sisusb
, 0);
2205 ret
|= SETIREGAND(SISSR
, 0x21, 0xdf);
2206 ret
|= SETIREGOR(SISSR
, 0x01, 0x20);
2207 ret
|= SETIREGOR(SISSR
, 0x16, 0x0f);
2209 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
2211 /* Disable refresh */
2212 ret
|= SETIREGAND(SISSR
, 0x17, 0xf8);
2213 ret
|= SETIREGOR(SISSR
, 0x19, 0x03);
2215 ret
|= sisusb_getbuswidth(sisusb
, &bw
, &chab
);
2216 ret
|= sisusb_verify_mclk(sisusb
);
2219 ret
|= sisusb_get_sdram_size(sisusb
, &iret
, bw
, chab
);
2221 printk(KERN_ERR
"sisusbvga[%d]: RAM size "
2222 "detection failed, "
2223 "assuming 8MB video RAM\n",
2225 ret
|= SETIREG(SISSR
,0x14,0x31);
2229 printk(KERN_ERR
"sisusbvga[%d]: DDR RAM device found, "
2230 "assuming 8MB video RAM\n",
2232 ret
|= SETIREG(SISSR
,0x14,0x31);
2236 /* Enable refresh */
2237 ret
|= SETIREG(SISSR
, 0x16, ramtypetable1
[4 + ramtype
]);
2238 ret
|= SETIREG(SISSR
, 0x17, ramtypetable1
[8 + ramtype
]);
2239 ret
|= SETIREG(SISSR
, 0x19, ramtypetable1
[16 + ramtype
]);
2241 ret
|= SETIREGOR(SISSR
, 0x21, 0x20);
2243 ret
|= SETIREG(SISSR
, 0x22, 0xfb);
2244 ret
|= SETIREG(SISSR
, 0x21, 0xa5);
2264 sisusb_get_ramconfig(struct sisusb_usb_data
*sisusb
)
2266 u8 tmp8
, tmp82
, ramtype
;
2268 char *ramtypetext1
= NULL
;
2269 const char *ramtypetext2
[] = { "SDR SDRAM", "SDR SGRAM",
2270 "DDR SDRAM", "DDR SGRAM" };
2271 static const int busSDR
[4] = {64, 64, 128, 128};
2272 static const int busDDR
[4] = {32, 32, 64, 64};
2273 static const int busDDRA
[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2275 sisusb_getidxreg(sisusb
, SISSR
, 0x14, &tmp8
);
2276 sisusb_getidxreg(sisusb
, SISSR
, 0x15, &tmp82
);
2277 sisusb_getidxreg(sisusb
, SISSR
, 0x3a, &ramtype
);
2278 sisusb
->vramsize
= (1 << ((tmp8
& 0xf0) >> 4)) * 1024 * 1024;
2280 switch ((tmp8
>> 2) & 0x03) {
2281 case 0: ramtypetext1
= "1 ch/1 r";
2285 bw
= busSDR
[(tmp8
& 0x03)];
2288 case 1: ramtypetext1
= "1 ch/2 r";
2289 sisusb
->vramsize
<<= 1;
2290 bw
= busSDR
[(tmp8
& 0x03)];
2292 case 2: ramtypetext1
= "asymmeric";
2293 sisusb
->vramsize
+= sisusb
->vramsize
/2;
2294 bw
= busDDRA
[(tmp8
& 0x03)];
2296 case 3: ramtypetext1
= "2 channel";
2297 sisusb
->vramsize
<<= 1;
2298 bw
= busDDR
[(tmp8
& 0x03)];
2302 printk(KERN_INFO
"sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2303 sisusb
->minor
, (sisusb
->vramsize
>> 20), ramtypetext1
,
2304 ramtypetext2
[ramtype
], bw
);
2308 sisusb_do_init_gfxdevice(struct sisusb_usb_data
*sisusb
)
2310 struct sisusb_packet packet
;
2315 packet
.header
= 0x001f;
2316 packet
.address
= 0x00000324;
2317 packet
.data
= 0x00000004;
2318 ret
= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2320 packet
.header
= 0x001f;
2321 packet
.address
= 0x00000364;
2322 packet
.data
= 0x00000004;
2323 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2325 packet
.header
= 0x001f;
2326 packet
.address
= 0x00000384;
2327 packet
.data
= 0x00000004;
2328 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2330 packet
.header
= 0x001f;
2331 packet
.address
= 0x00000100;
2332 packet
.data
= 0x00000700;
2333 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2335 packet
.header
= 0x000f;
2336 packet
.address
= 0x00000004;
2337 ret
|= sisusb_send_bridge_packet(sisusb
, 6, &packet
, 0);
2338 packet
.data
|= 0x17;
2339 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2341 /* Init BAR 0 (VRAM) */
2342 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2343 ret
|= sisusb_write_pci_config(sisusb
, 0x10, 0xfffffff0);
2344 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2346 tmp32
|= SISUSB_PCI_MEMBASE
;
2347 ret
|= sisusb_write_pci_config(sisusb
, 0x10, tmp32
);
2349 /* Init BAR 1 (MMIO) */
2350 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2351 ret
|= sisusb_write_pci_config(sisusb
, 0x14, 0xfffffff0);
2352 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2354 tmp32
|= SISUSB_PCI_MMIOBASE
;
2355 ret
|= sisusb_write_pci_config(sisusb
, 0x14, tmp32
);
2357 /* Init BAR 2 (i/o ports) */
2358 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2359 ret
|= sisusb_write_pci_config(sisusb
, 0x18, 0xfffffff0);
2360 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2362 tmp32
|= SISUSB_PCI_IOPORTBASE
;
2363 ret
|= sisusb_write_pci_config(sisusb
, 0x18, tmp32
);
2365 /* Enable memory and i/o access */
2366 ret
|= sisusb_read_pci_config(sisusb
, 0x04, &tmp32
);
2368 ret
|= sisusb_write_pci_config(sisusb
, 0x04, tmp32
);
2371 /* Some further magic */
2372 packet
.header
= 0x001f;
2373 packet
.address
= 0x00000050;
2374 packet
.data
= 0x000000ff;
2375 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2381 /* Initialize the graphics device (return 0 on success)
2382 * This initializes the net2280 as well as the PCI registers
2383 * of the graphics board.
2387 sisusb_init_gfxdevice(struct sisusb_usb_data
*sisusb
, int initscreen
)
2389 int ret
= 0, test
= 0;
2392 if (sisusb
->devinit
== 1) {
2393 /* Read PCI BARs and see if they have been set up */
2394 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2395 if (ret
) return ret
;
2396 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MEMBASE
) test
++;
2398 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2399 if (ret
) return ret
;
2400 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MMIOBASE
) test
++;
2402 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2403 if (ret
) return ret
;
2404 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_IOPORTBASE
) test
++;
2407 /* No? So reset the device */
2408 if ((sisusb
->devinit
== 0) || (test
!= 3)) {
2410 ret
|= sisusb_do_init_gfxdevice(sisusb
);
2413 sisusb
->devinit
= 1;
2417 if (sisusb
->devinit
) {
2418 /* Initialize the graphics core */
2419 if (sisusb_init_gfxcore(sisusb
) == 0) {
2420 sisusb
->gfxinit
= 1;
2421 sisusb_get_ramconfig(sisusb
);
2422 ret
|= sisusb_set_default_mode(sisusb
, 1);
2423 ret
|= sisusb_setup_screen(sisusb
, 1, initscreen
);
2431 #ifdef INCL_SISUSB_CON
2433 /* Set up default text mode:
2434 - Set text mode (0x03)
2435 - Upload default font
2436 - Upload user font (if available)
2440 sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
)
2442 int ret
= 0, slot
= sisusb
->font_slot
, i
;
2443 struct font_desc
*myfont
;
2447 static char bootstring
[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2448 static char bootlogo
[] = "(o_ //\\ V_/_";
2450 /* sisusb->lock is down */
2452 if (!sisusb
->SiS_Pr
)
2455 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2456 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2459 SiSUSBSetMode(sisusb
->SiS_Pr
, 0x03);
2461 if (!(myfont
= find_font("VGA8x16")))
2464 if (!(tempbuf
= vmalloc(8192)))
2467 for (i
= 0; i
< 256; i
++)
2468 memcpy(tempbuf
+ (i
* 32), myfont
->data
+ (i
* 16), 16);
2470 /* Upload default font */
2471 ret
= sisusbcon_do_font_op(sisusb
, 1, 0, tempbuf
, 8192, 0, 1, NULL
, 16, 0);
2475 /* Upload user font (and reset current slot) */
2476 if (sisusb
->font_backup
) {
2477 ret
|= sisusbcon_do_font_op(sisusb
, 1, 2, sisusb
->font_backup
,
2478 8192, sisusb
->font_backup_512
, 1, NULL
,
2479 sisusb
->font_backup_height
, 0);
2481 sisusbcon_do_font_op(sisusb
, 1, 0, NULL
, 0, 0, 1,
2485 if (init
&& !sisusb
->scrbuf
) {
2487 if ((tempbuf
= vmalloc(8192))) {
2490 tempbufb
= (u16
*)tempbuf
;
2492 *(tempbufb
++) = 0x0720;
2495 tempbufb
= (u16
*)tempbuf
;
2496 while (bootlogo
[i
]) {
2497 *(tempbufb
++) = 0x0700 | bootlogo
[i
++];
2503 tempbufb
= (u16
*)tempbuf
+ 6;
2504 while (bootstring
[i
])
2505 *(tempbufb
++) = 0x0700 | bootstring
[i
++];
2507 ret
|= sisusb_copy_memory(sisusb
, tempbuf
,
2508 sisusb
->vrambase
, 8192, &written
);
2514 } else if (sisusb
->scrbuf
) {
2516 ret
|= sisusb_copy_memory(sisusb
, (char *)sisusb
->scrbuf
,
2517 sisusb
->vrambase
, sisusb
->scrbuf_size
, &written
);
2521 if (sisusb
->sisusb_cursor_size_from
>= 0 &&
2522 sisusb
->sisusb_cursor_size_to
>= 0) {
2523 sisusb_setidxreg(sisusb
, SISCR
, 0x0a,
2524 sisusb
->sisusb_cursor_size_from
);
2525 sisusb_setidxregandor(sisusb
, SISCR
, 0x0b, 0xe0,
2526 sisusb
->sisusb_cursor_size_to
);
2528 sisusb_setidxreg(sisusb
, SISCR
, 0x0a, 0x2d);
2529 sisusb_setidxreg(sisusb
, SISCR
, 0x0b, 0x0e);
2530 sisusb
->sisusb_cursor_size_to
= -1;
2533 slot
= sisusb
->sisusb_cursor_loc
;
2534 if(slot
< 0) slot
= 0;
2536 sisusb
->sisusb_cursor_loc
= -1;
2537 sisusb
->bad_cursor_pos
= 1;
2539 sisusb_set_cursor(sisusb
, slot
);
2541 sisusb_setidxreg(sisusb
, SISCR
, 0x0c, (sisusb
->cur_start_addr
>> 8));
2542 sisusb_setidxreg(sisusb
, SISCR
, 0x0d, (sisusb
->cur_start_addr
& 0xff));
2544 sisusb
->textmodedestroyed
= 0;
2546 /* sisusb->lock is down */
2556 sisusb_open(struct inode
*inode
, struct file
*file
)
2558 struct sisusb_usb_data
*sisusb
;
2559 struct usb_interface
*interface
;
2560 int subminor
= iminor(inode
);
2562 down(&disconnect_sem
);
2564 if (!(interface
= usb_find_interface(&sisusb_driver
, subminor
))) {
2565 printk(KERN_ERR
"sisusb[%d]: Failed to find interface\n",
2567 up(&disconnect_sem
);
2571 if (!(sisusb
= usb_get_intfdata(interface
))) {
2572 up(&disconnect_sem
);
2576 down(&sisusb
->lock
);
2578 if (!sisusb
->present
|| !sisusb
->ready
) {
2580 up(&disconnect_sem
);
2584 if (sisusb
->isopen
) {
2586 up(&disconnect_sem
);
2590 if (!sisusb
->devinit
) {
2591 if (sisusb
->sisusb_dev
->speed
== USB_SPEED_HIGH
) {
2592 if (sisusb_init_gfxdevice(sisusb
, 0)) {
2594 up(&disconnect_sem
);
2596 "sisusbvga[%d]: Failed to initialize "
2603 up(&disconnect_sem
);
2605 "sisusbvga[%d]: Device not attached to "
2612 /* Increment usage count for our sisusb */
2613 kref_get(&sisusb
->kref
);
2617 file
->private_data
= sisusb
;
2621 up(&disconnect_sem
);
2627 sisusb_delete(struct kref
*kref
)
2629 struct sisusb_usb_data
*sisusb
= to_sisusb_dev(kref
);
2634 if (sisusb
->sisusb_dev
)
2635 usb_put_dev(sisusb
->sisusb_dev
);
2637 sisusb
->sisusb_dev
= NULL
;
2638 sisusb_free_buffers(sisusb
);
2639 sisusb_free_urbs(sisusb
);
2640 #ifdef INCL_SISUSB_CON
2641 kfree(sisusb
->SiS_Pr
);
2647 sisusb_release(struct inode
*inode
, struct file
*file
)
2649 struct sisusb_usb_data
*sisusb
;
2652 down(&disconnect_sem
);
2654 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
)) {
2655 up(&disconnect_sem
);
2659 down(&sisusb
->lock
);
2661 if (sisusb
->present
) {
2662 /* Wait for all URBs to finish if device still present */
2663 if (!sisusb_wait_all_out_complete(sisusb
))
2664 sisusb_kill_all_busy(sisusb
);
2667 myminor
= sisusb
->minor
;
2670 file
->private_data
= NULL
;
2674 /* decrement the usage count on our device */
2675 kref_put(&sisusb
->kref
, sisusb_delete
);
2677 up(&disconnect_sem
);
2683 sisusb_read(struct file
*file
, char __user
*buffer
, size_t count
, loff_t
*ppos
)
2685 struct sisusb_usb_data
*sisusb
;
2686 ssize_t bytes_read
= 0;
2692 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2695 down(&sisusb
->lock
);
2698 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2703 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2704 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2707 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2708 SISUSB_PCI_IOPORTBASE
;
2711 * Byte, word and long(32) can be read. As this
2712 * emulates inX instructions, the data returned is
2713 * in machine-endianness.
2718 if (sisusb_read_memio_byte(sisusb
,
2722 else if (put_user(buf8
, (u8 __user
*)buffer
))
2730 if (sisusb_read_memio_word(sisusb
,
2734 else if (put_user(buf16
, (u16 __user
*)buffer
))
2742 if (sisusb_read_memio_long(sisusb
,
2746 else if (put_user(buf32
, (u32 __user
*)buffer
))
2758 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2759 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2762 SISUSB_PCI_PSEUDO_MEMBASE
+
2766 * Remember: Data delivered is never endian-corrected
2768 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2769 NULL
, count
, buffer
, &bytes_read
);
2774 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2775 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2778 SISUSB_PCI_PSEUDO_MMIOBASE
+
2779 SISUSB_PCI_MMIOBASE
;
2782 * Remember: Data delivered is never endian-corrected
2784 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2785 NULL
, count
, buffer
, &bytes_read
);
2790 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2791 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ 0x5c) {
2798 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2800 /* Read PCI config register
2801 * Return value delivered in machine endianness.
2803 if (sisusb_read_pci_config(sisusb
, address
, &buf32
))
2805 else if (put_user(buf32
, (u32 __user
*)buffer
))
2816 (*ppos
) += bytes_read
;
2820 return errno
? errno
: bytes_read
;
2824 sisusb_write(struct file
*file
, const char __user
*buffer
, size_t count
,
2827 struct sisusb_usb_data
*sisusb
;
2829 ssize_t bytes_written
= 0;
2834 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2837 down(&sisusb
->lock
);
2840 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2845 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2846 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2849 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2850 SISUSB_PCI_IOPORTBASE
;
2853 * Byte, word and long(32) can be written. As this
2854 * emulates outX instructions, the data is expected
2855 * in machine-endianness.
2860 if (get_user(buf8
, (u8 __user
*)buffer
))
2862 else if (sisusb_write_memio_byte(sisusb
,
2872 if (get_user(buf16
, (u16 __user
*)buffer
))
2874 else if (sisusb_write_memio_word(sisusb
,
2884 if (get_user(buf32
, (u32 __user
*)buffer
))
2886 else if (sisusb_write_memio_long(sisusb
,
2899 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2900 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2903 SISUSB_PCI_PSEUDO_MEMBASE
+
2907 * Buffer is copied 1:1, therefore, on big-endian
2908 * machines, the data must be swapped by userland
2909 * in advance (if applicable; no swapping in 8bpp
2910 * mode or if YUV data is being transferred).
2912 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2913 count
, buffer
, 0, &bytes_written
);
2916 errno
= bytes_written
;
2918 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2919 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2922 SISUSB_PCI_PSEUDO_MMIOBASE
+
2923 SISUSB_PCI_MMIOBASE
;
2926 * Buffer is copied 1:1, therefore, on big-endian
2927 * machines, the data must be swapped by userland
2930 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2931 count
, buffer
, 0, &bytes_written
);
2934 errno
= bytes_written
;
2936 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2937 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ SISUSB_PCI_PCONFSIZE
) {
2944 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2946 /* Write PCI config register.
2947 * Given value expected in machine endianness.
2949 if (get_user(buf32
, (u32 __user
*)buffer
))
2951 else if (sisusb_write_pci_config(sisusb
, address
, buf32
))
2964 (*ppos
) += bytes_written
;
2968 return errno
? errno
: bytes_written
;
2972 sisusb_lseek(struct file
*file
, loff_t offset
, int orig
)
2974 struct sisusb_usb_data
*sisusb
;
2977 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2980 down(&sisusb
->lock
);
2983 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2990 file
->f_pos
= offset
;
2992 /* never negative, no force_successful_syscall needed */
2995 file
->f_pos
+= offset
;
2997 /* never negative, no force_successful_syscall needed */
3000 /* seeking relative to "end of file" is not supported */
3009 sisusb_handle_command(struct sisusb_usb_data
*sisusb
, struct sisusb_command
*y
,
3012 int retval
, port
, length
;
3015 /* All our commands require the device
3016 * to be initialized.
3018 if (!sisusb
->devinit
)
3022 SISUSB_PCI_PSEUDO_IOPORTBASE
+
3023 SISUSB_PCI_IOPORTBASE
;
3025 switch (y
->operation
) {
3027 retval
= sisusb_getidxreg(sisusb
, port
,
3028 y
->data0
, &y
->data1
);
3030 if (copy_to_user((void __user
*)arg
, y
,
3037 retval
= sisusb_setidxreg(sisusb
, port
,
3038 y
->data0
, y
->data1
);
3042 retval
= sisusb_setidxregor(sisusb
, port
,
3043 y
->data0
, y
->data1
);
3047 retval
= sisusb_setidxregand(sisusb
, port
,
3048 y
->data0
, y
->data1
);
3051 case SUCMD_SETANDOR
:
3052 retval
= sisusb_setidxregandor(sisusb
, port
,
3053 y
->data0
, y
->data1
, y
->data2
);
3057 retval
= sisusb_setidxregmask(sisusb
, port
,
3058 y
->data0
, y
->data1
, y
->data2
);
3062 /* Gfx core must be initialized */
3063 if (!sisusb
->gfxinit
)
3066 length
= (y
->data0
<< 16) | (y
->data1
<< 8) | y
->data2
;
3067 address
= y
->data3
-
3068 SISUSB_PCI_PSEUDO_MEMBASE
+
3070 retval
= sisusb_clear_vram(sisusb
, address
, length
);
3073 case SUCMD_HANDLETEXTMODE
:
3075 #ifdef INCL_SISUSB_CON
3076 /* Gfx core must be initialized, SiS_Pr must exist */
3077 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3082 retval
= sisusb_reset_text_mode(sisusb
, 0);
3085 sisusb
->textmodedestroyed
= 1;
3091 #ifdef INCL_SISUSB_CON
3093 /* Gfx core must be initialized, SiS_Pr must exist */
3094 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3099 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
3100 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
3102 if (SiSUSBSetMode(sisusb
->SiS_Pr
, y
->data3
))
3107 case SUCMD_SETVESAMODE
:
3108 /* Gfx core must be initialized, SiS_Pr must exist */
3109 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3114 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
3115 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
3117 if (SiSUSBSetVESAMode(sisusb
->SiS_Pr
, y
->data3
))
3134 sisusb_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
3137 struct sisusb_usb_data
*sisusb
;
3138 struct sisusb_info x
;
3139 struct sisusb_command y
;
3141 u32 __user
*argp
= (u32 __user
*)arg
;
3143 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
3146 down(&sisusb
->lock
);
3149 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
3156 case SISUSB_GET_CONFIG_SIZE
:
3158 if (put_user(sizeof(x
), argp
))
3163 case SISUSB_GET_CONFIG
:
3165 x
.sisusb_id
= SISUSB_ID
;
3166 x
.sisusb_version
= SISUSB_VERSION
;
3167 x
.sisusb_revision
= SISUSB_REVISION
;
3168 x
.sisusb_patchlevel
= SISUSB_PATCHLEVEL
;
3169 x
.sisusb_gfxinit
= sisusb
->gfxinit
;
3170 x
.sisusb_vrambase
= SISUSB_PCI_PSEUDO_MEMBASE
;
3171 x
.sisusb_mmiobase
= SISUSB_PCI_PSEUDO_MMIOBASE
;
3172 x
.sisusb_iobase
= SISUSB_PCI_PSEUDO_IOPORTBASE
;
3173 x
.sisusb_pcibase
= SISUSB_PCI_PSEUDO_PCIBASE
;
3174 x
.sisusb_vramsize
= sisusb
->vramsize
;
3175 x
.sisusb_minor
= sisusb
->minor
;
3176 x
.sisusb_fbdevactive
= 0;
3177 #ifdef INCL_SISUSB_CON
3178 x
.sisusb_conactive
= sisusb
->haveconsole
? 1 : 0;
3180 x
.sisusb_conactive
= 0;
3183 if (copy_to_user((void __user
*)arg
, &x
, sizeof(x
)))
3188 case SISUSB_COMMAND
:
3190 if (copy_from_user(&y
, (void __user
*)arg
, sizeof(y
)))
3193 retval
= sisusb_handle_command(sisusb
, &y
, arg
);
3207 #ifdef SISUSB_NEW_CONFIG_COMPAT
3209 sisusb_compat_ioctl(struct file
*f
, unsigned int cmd
, unsigned long arg
)
3214 case SISUSB_GET_CONFIG_SIZE
:
3215 case SISUSB_GET_CONFIG
:
3216 case SISUSB_COMMAND
:
3218 retval
= sisusb_ioctl(f
->f_dentry
->d_inode
, f
, cmd
, arg
);
3223 return -ENOIOCTLCMD
;
3228 static struct file_operations usb_sisusb_fops
= {
3229 .owner
= THIS_MODULE
,
3230 .open
= sisusb_open
,
3231 .release
= sisusb_release
,
3232 .read
= sisusb_read
,
3233 .write
= sisusb_write
,
3234 .llseek
= sisusb_lseek
,
3235 #ifdef SISUSB_NEW_CONFIG_COMPAT
3236 .compat_ioctl
= sisusb_compat_ioctl
,
3238 .ioctl
= sisusb_ioctl
3241 static struct usb_class_driver usb_sisusb_class
= {
3242 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
3243 .name
= "usb/sisusbvga%d",
3244 .mode
= S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
,
3246 .name
= "sisusbvga%d",
3248 .fops
= &usb_sisusb_fops
,
3249 .minor_base
= SISUSB_MINOR
3252 static int sisusb_probe(struct usb_interface
*intf
,
3253 const struct usb_device_id
*id
)
3255 struct usb_device
*dev
= interface_to_usbdev(intf
);
3256 struct sisusb_usb_data
*sisusb
;
3258 const char *memfail
=
3260 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3262 printk(KERN_INFO
"sisusb: USB2VGA dongle found at address %d\n",
3265 /* Allocate memory for our private */
3266 if (!(sisusb
= kmalloc(sizeof(*sisusb
), GFP_KERNEL
))) {
3268 "sisusb: Failed to allocate memory for private data\n");
3271 memset(sisusb
, 0, sizeof(*sisusb
));
3272 kref_init(&sisusb
->kref
);
3274 init_MUTEX(&(sisusb
->lock
));
3276 /* Register device */
3277 if ((retval
= usb_register_dev(intf
, &usb_sisusb_class
))) {
3279 "sisusb: Failed to get a minor for device %d\n",
3285 sisusb
->sisusb_dev
= dev
;
3286 sisusb
->minor
= intf
->minor
;
3287 sisusb
->vrambase
= SISUSB_PCI_MEMBASE
;
3288 sisusb
->mmiobase
= SISUSB_PCI_MMIOBASE
;
3289 sisusb
->mmiosize
= SISUSB_PCI_MMIOSIZE
;
3290 sisusb
->ioportbase
= SISUSB_PCI_IOPORTBASE
;
3291 /* Everything else is zero */
3293 /* Allocate buffers */
3294 sisusb
->ibufsize
= SISUSB_IBUF_SIZE
;
3295 if (!(sisusb
->ibuf
= usb_buffer_alloc(dev
, SISUSB_IBUF_SIZE
,
3296 GFP_KERNEL
, &sisusb
->transfer_dma_in
))) {
3297 printk(memfail
, "input", sisusb
->minor
);
3302 sisusb
->numobufs
= 0;
3303 sisusb
->obufsize
= SISUSB_OBUF_SIZE
;
3304 for (i
= 0; i
< NUMOBUFS
; i
++) {
3305 if (!(sisusb
->obuf
[i
] = usb_buffer_alloc(dev
, SISUSB_OBUF_SIZE
,
3307 &sisusb
->transfer_dma_out
[i
]))) {
3309 printk(memfail
, "output", sisusb
->minor
);
3320 if (!(sisusb
->sisurbin
= usb_alloc_urb(0, GFP_KERNEL
))) {
3322 "sisusbvga[%d]: Failed to allocate URBs\n",
3327 sisusb
->completein
= 1;
3329 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
3330 if (!(sisusb
->sisurbout
[i
] = usb_alloc_urb(0, GFP_KERNEL
))) {
3332 "sisusbvga[%d]: Failed to allocate URBs\n",
3337 sisusb
->urbout_context
[i
].sisusb
= (void *)sisusb
;
3338 sisusb
->urbout_context
[i
].urbindex
= i
;
3339 sisusb
->urbstatus
[i
] = 0;
3342 printk(KERN_INFO
"sisusbvga[%d]: Allocated %d output buffers\n",
3343 sisusb
->minor
, sisusb
->numobufs
);
3345 #ifdef INCL_SISUSB_CON
3346 /* Allocate our SiS_Pr */
3347 if (!(sisusb
->SiS_Pr
= kmalloc(sizeof(struct SiS_Private
), GFP_KERNEL
))) {
3349 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3354 /* Do remaining init stuff */
3356 init_waitqueue_head(&sisusb
->wait_q
);
3358 usb_set_intfdata(intf
, sisusb
);
3360 usb_get_dev(sisusb
->sisusb_dev
);
3362 sisusb
->present
= 1;
3364 #ifdef SISUSB_OLD_CONFIG_COMPAT
3367 /* Our ioctls are all "32/64bit compatible" */
3368 ret
= register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE
, NULL
);
3369 ret
|= register_ioctl32_conversion(SISUSB_GET_CONFIG
, NULL
);
3370 ret
|= register_ioctl32_conversion(SISUSB_COMMAND
, NULL
);
3373 "sisusbvga[%d]: Error registering ioctl32 "
3377 sisusb
->ioctl32registered
= 1;
3381 if (dev
->speed
== USB_SPEED_HIGH
) {
3383 #ifdef INCL_SISUSB_CON
3384 if (sisusb_first_vc
> 0 &&
3385 sisusb_last_vc
> 0 &&
3386 sisusb_first_vc
<= sisusb_last_vc
&&
3387 sisusb_last_vc
<= MAX_NR_CONSOLES
)
3390 if (sisusb_init_gfxdevice(sisusb
, initscreen
))
3392 "sisusbvga[%d]: Failed to early "
3393 "initialize device\n",
3398 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3404 #ifdef SISUSBENDIANTEST
3405 printk(KERN_DEBUG
"sisusb: *** RWTEST ***\n");
3406 sisusb_testreadwrite(sisusb
);
3407 printk(KERN_DEBUG
"sisusb: *** RWTEST END ***\n");
3410 #ifdef INCL_SISUSB_CON
3411 sisusb_console_init(sisusb
, sisusb_first_vc
, sisusb_last_vc
);
3417 sisusb_free_urbs(sisusb
);
3419 sisusb_free_buffers(sisusb
);
3421 usb_deregister_dev(intf
, &usb_sisusb_class
);
3427 static void sisusb_disconnect(struct usb_interface
*intf
)
3429 struct sisusb_usb_data
*sisusb
;
3432 /* This should *not* happen */
3433 if (!(sisusb
= usb_get_intfdata(intf
)))
3436 #ifdef INCL_SISUSB_CON
3437 sisusb_console_exit(sisusb
);
3440 /* The above code doesn't need the disconnect
3441 * semaphore to be down; its meaning is to
3442 * protect all other routines from the disconnect
3443 * case, not the other way round.
3445 down(&disconnect_sem
);
3447 down(&sisusb
->lock
);
3449 /* Wait for all URBs to complete and kill them in case (MUST do) */
3450 if (!sisusb_wait_all_out_complete(sisusb
))
3451 sisusb_kill_all_busy(sisusb
);
3453 minor
= sisusb
->minor
;
3455 usb_set_intfdata(intf
, NULL
);
3457 usb_deregister_dev(intf
, &usb_sisusb_class
);
3459 #ifdef SISUSB_OLD_CONFIG_COMPAT
3460 if (sisusb
->ioctl32registered
) {
3462 sisusb
->ioctl32registered
= 0;
3463 ret
= unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE
);
3464 ret
|= unregister_ioctl32_conversion(SISUSB_GET_CONFIG
);
3465 ret
|= unregister_ioctl32_conversion(SISUSB_COMMAND
);
3468 "sisusbvga[%d]: Error unregistering "
3469 "ioctl32 translations\n",
3475 sisusb
->present
= 0;
3480 /* decrement our usage count */
3481 kref_put(&sisusb
->kref
, sisusb_delete
);
3483 up(&disconnect_sem
);
3485 printk(KERN_INFO
"sisusbvga[%d]: Disconnected\n", minor
);
3488 static struct usb_device_id sisusb_table
[] = {
3489 { USB_DEVICE(0x0711, 0x0900) },
3490 { USB_DEVICE(0x182d, 0x021c) },
3491 { USB_DEVICE(0x182d, 0x0269) },
3495 MODULE_DEVICE_TABLE (usb
, sisusb_table
);
3497 static struct usb_driver sisusb_driver
= {
3498 .owner
= THIS_MODULE
,
3500 .probe
= sisusb_probe
,
3501 .disconnect
= sisusb_disconnect
,
3502 .id_table
= sisusb_table
,
3505 static int __init
usb_sisusb_init(void)
3509 #ifdef INCL_SISUSB_CON
3510 sisusb_init_concode();
3513 if (!(retval
= usb_register(&sisusb_driver
))) {
3515 printk(KERN_INFO
"sisusb: Driver version %d.%d.%d\n",
3516 SISUSB_VERSION
, SISUSB_REVISION
, SISUSB_PATCHLEVEL
);
3518 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3525 static void __exit
usb_sisusb_exit(void)
3527 usb_deregister(&sisusb_driver
);
3530 module_init(usb_sisusb_init
);
3531 module_exit(usb_sisusb_exit
);
3533 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3534 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3535 MODULE_LICENSE("GPL");