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/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/sched.h>
44 #include <linux/errno.h>
45 #include <linux/poll.h>
46 #include <linux/init.h>
47 #include <linux/slab.h>
48 #include <linux/spinlock.h>
49 #include <linux/kref.h>
50 #include <linux/usb.h>
51 #include <linux/smp_lock.h>
52 #include <linux/vmalloc.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 int sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
);
66 int sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
);
67 int sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 data
);
68 int sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8
*data
);
69 int sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
, u8 myor
);
70 int sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 myor
);
71 int sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
);
73 int sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
);
74 int sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
);
75 int sisusb_writew(struct sisusb_usb_data
*sisusb
, u32 adr
, u16 data
);
76 int sisusb_readw(struct sisusb_usb_data
*sisusb
, u32 adr
, u16
*data
);
77 int sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
78 u32 dest
, int length
, size_t *bytes_written
);
80 int sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
);
82 extern int SiSUSBSetMode(struct SiS_Private
*SiS_Pr
, unsigned short ModeNo
);
83 extern int SiSUSBSetVESAMode(struct SiS_Private
*SiS_Pr
, unsigned short VModeNo
);
85 extern void sisusb_init_concode(void);
86 extern int sisusb_console_init(struct sisusb_usb_data
*sisusb
, int first
, int last
);
87 extern void sisusb_console_exit(struct sisusb_usb_data
*sisusb
);
89 extern void sisusb_set_cursor(struct sisusb_usb_data
*sisusb
, unsigned int location
);
91 extern int sisusbcon_do_font_op(struct sisusb_usb_data
*sisusb
, int set
, int slot
,
92 u8
*arg
, int cmapsz
, int ch512
, int dorecalc
,
93 struct vc_data
*c
, int fh
, int uplock
);
95 static int sisusb_first_vc
= 0;
96 static int sisusb_last_vc
= 0;
97 module_param_named(first
, sisusb_first_vc
, int, 0);
98 module_param_named(last
, sisusb_last_vc
, int, 0);
99 MODULE_PARM_DESC(first
, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
100 MODULE_PARM_DESC(last
, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
103 static struct usb_driver sisusb_driver
;
105 DECLARE_MUTEX(disconnect_sem
);
108 sisusb_free_buffers(struct sisusb_usb_data
*sisusb
)
112 for (i
= 0; i
< NUMOBUFS
; i
++) {
113 if (sisusb
->obuf
[i
]) {
114 usb_buffer_free(sisusb
->sisusb_dev
, sisusb
->obufsize
,
115 sisusb
->obuf
[i
], sisusb
->transfer_dma_out
[i
]);
116 sisusb
->obuf
[i
] = NULL
;
120 usb_buffer_free(sisusb
->sisusb_dev
, sisusb
->ibufsize
,
121 sisusb
->ibuf
, sisusb
->transfer_dma_in
);
127 sisusb_free_urbs(struct sisusb_usb_data
*sisusb
)
131 for (i
= 0; i
< NUMOBUFS
; i
++) {
132 usb_free_urb(sisusb
->sisurbout
[i
]);
133 sisusb
->sisurbout
[i
] = NULL
;
135 usb_free_urb(sisusb
->sisurbin
);
136 sisusb
->sisurbin
= NULL
;
139 /* Level 0: USB transport layer */
143 /* out-urb management */
145 /* Return 1 if all free, 0 otherwise */
147 sisusb_all_free(struct sisusb_usb_data
*sisusb
)
151 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
153 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
161 /* Kill all busy URBs */
163 sisusb_kill_all_busy(struct sisusb_usb_data
*sisusb
)
167 if (sisusb_all_free(sisusb
))
170 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
172 if (sisusb
->urbstatus
[i
] & SU_URB_BUSY
)
173 usb_kill_urb(sisusb
->sisurbout
[i
]);
178 /* Return 1 if ok, 0 if error (not all complete within timeout) */
180 sisusb_wait_all_out_complete(struct sisusb_usb_data
*sisusb
)
182 int timeout
= 5 * HZ
, i
= 1;
184 wait_event_timeout(sisusb
->wait_q
,
185 (i
= sisusb_all_free(sisusb
)),
192 sisusb_outurb_available(struct sisusb_usb_data
*sisusb
)
196 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
198 if ((sisusb
->urbstatus
[i
] & (SU_URB_BUSY
|SU_URB_ALLOC
)) == 0)
207 sisusb_get_free_outbuf(struct sisusb_usb_data
*sisusb
)
209 int i
, timeout
= 5 * HZ
;
211 wait_event_timeout(sisusb
->wait_q
,
212 ((i
= sisusb_outurb_available(sisusb
)) >= 0),
219 sisusb_alloc_outbuf(struct sisusb_usb_data
*sisusb
)
223 i
= sisusb_outurb_available(sisusb
);
226 sisusb
->urbstatus
[i
] |= SU_URB_ALLOC
;
232 sisusb_free_outbuf(struct sisusb_usb_data
*sisusb
, int index
)
234 if ((index
>= 0) && (index
< sisusb
->numobufs
))
235 sisusb
->urbstatus
[index
] &= ~SU_URB_ALLOC
;
238 /* completion callback */
241 sisusb_bulk_completeout(struct urb
*urb
, struct pt_regs
*regs
)
243 struct sisusb_urb_context
*context
= urb
->context
;
244 struct sisusb_usb_data
*sisusb
;
249 sisusb
= context
->sisusb
;
251 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
254 #ifndef SISUSB_DONTSYNC
255 if (context
->actual_length
)
256 *(context
->actual_length
) += urb
->actual_length
;
259 sisusb
->urbstatus
[context
->urbindex
] &= ~SU_URB_BUSY
;
260 wake_up(&sisusb
->wait_q
);
264 sisusb_bulkout_msg(struct sisusb_usb_data
*sisusb
, int index
, unsigned int pipe
, void *data
,
265 int len
, int *actual_length
, int timeout
, unsigned int tflags
,
266 dma_addr_t transfer_dma
)
268 struct urb
*urb
= sisusb
->sisurbout
[index
];
269 int retval
, byteswritten
= 0;
272 urb
->transfer_flags
= 0;
274 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
275 sisusb_bulk_completeout
, &sisusb
->urbout_context
[index
]);
277 urb
->transfer_flags
|= tflags
;
278 urb
->actual_length
= 0;
280 if ((urb
->transfer_dma
= transfer_dma
))
281 urb
->transfer_flags
|= URB_NO_TRANSFER_DMA_MAP
;
284 sisusb
->urbout_context
[index
].actual_length
= (timeout
) ?
285 NULL
: actual_length
;
287 /* Declare this urb/buffer in use */
288 sisusb
->urbstatus
[index
] |= SU_URB_BUSY
;
291 retval
= usb_submit_urb(urb
, GFP_ATOMIC
);
293 /* If OK, and if timeout > 0, wait for completion */
294 if ((retval
== 0) && timeout
) {
295 wait_event_timeout(sisusb
->wait_q
,
296 (!(sisusb
->urbstatus
[index
] & SU_URB_BUSY
)),
298 if (sisusb
->urbstatus
[index
] & SU_URB_BUSY
) {
299 /* URB timed out... kill it and report error */
303 /* Otherwise, report urb status */
304 retval
= urb
->status
;
305 byteswritten
= urb
->actual_length
;
310 *actual_length
= byteswritten
;
317 /* completion callback */
320 sisusb_bulk_completein(struct urb
*urb
, struct pt_regs
*regs
)
322 struct sisusb_usb_data
*sisusb
= urb
->context
;
324 if (!sisusb
|| !sisusb
->sisusb_dev
|| !sisusb
->present
)
327 sisusb
->completein
= 1;
328 wake_up(&sisusb
->wait_q
);
332 sisusb_bulkin_msg(struct sisusb_usb_data
*sisusb
, unsigned int pipe
, void *data
, int len
,
333 int *actual_length
, int timeout
, unsigned int tflags
, dma_addr_t transfer_dma
)
335 struct urb
*urb
= sisusb
->sisurbin
;
336 int retval
, readbytes
= 0;
338 urb
->transfer_flags
= 0;
340 usb_fill_bulk_urb(urb
, sisusb
->sisusb_dev
, pipe
, data
, len
,
341 sisusb_bulk_completein
, sisusb
);
343 urb
->transfer_flags
|= tflags
;
344 urb
->actual_length
= 0;
346 if ((urb
->transfer_dma
= transfer_dma
))
347 urb
->transfer_flags
|= URB_NO_TRANSFER_DMA_MAP
;
349 sisusb
->completein
= 0;
350 retval
= usb_submit_urb(urb
, GFP_ATOMIC
);
352 wait_event_timeout(sisusb
->wait_q
, sisusb
->completein
, timeout
);
353 if (!sisusb
->completein
) {
354 /* URB timed out... kill it and report error */
358 /* URB completed within timout */
359 retval
= urb
->status
;
360 readbytes
= urb
->actual_length
;
365 *actual_length
= readbytes
;
373 /* Send a bulk message of variable size
375 * To copy the data from userspace, give pointer to "userbuffer",
376 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
377 * both of these are NULL, it is assumed, that the transfer
378 * buffer "sisusb->obuf[index]" is set up with the data to send.
379 * Index is ignored if either kernbuffer or userbuffer is set.
380 * If async is nonzero, URBs will be sent without waiting for
381 * completion of the previous URB.
383 * (return 0 on success)
386 static int sisusb_send_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
387 char *kernbuffer
, const char __user
*userbuffer
, int index
,
388 ssize_t
*bytes_written
, unsigned int tflags
, int async
)
390 int result
= 0, retry
, count
= len
;
391 int passsize
, thispass
, transferred_len
= 0;
392 int fromuser
= (userbuffer
!= NULL
) ? 1 : 0;
393 int fromkern
= (kernbuffer
!= NULL
) ? 1 : 0;
397 (*bytes_written
) = 0;
400 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
403 /* If we copy data from kernel or userspace, force the
404 * allocation of a buffer/urb. If we have the data in
405 * the transfer buffer[index] already, reuse the buffer/URB
406 * if the length is > buffer size. (So, transmitting
407 * large data amounts directly from the transfer buffer
408 * treats the buffer as a ring buffer. However, we need
409 * to sync in this case.)
411 if (fromuser
|| fromkern
)
413 else if (len
> sisusb
->obufsize
)
416 pipe
= usb_sndbulkpipe(sisusb
->sisusb_dev
, ep
);
419 passsize
= thispass
= (sisusb
->obufsize
< count
) ?
420 sisusb
->obufsize
: count
;
423 index
= sisusb_get_free_outbuf(sisusb
);
428 buffer
= sisusb
->obuf
[index
];
432 if (copy_from_user(buffer
, userbuffer
, passsize
))
435 userbuffer
+= passsize
;
437 } else if (fromkern
) {
439 memcpy(buffer
, kernbuffer
, passsize
);
440 kernbuffer
+= passsize
;
447 if (!sisusb
->sisusb_dev
)
450 result
= sisusb_bulkout_msg(sisusb
,
458 sisusb
->transfer_dma_out
[index
]);
460 if (result
== -ETIMEDOUT
) {
462 /* Will not happen if async */
468 } else if ((result
== 0) && !async
&& transferred_len
) {
470 thispass
-= transferred_len
;
472 if (sisusb
->transfer_dma_out
) {
473 /* If DMA, copy remaining
474 * to beginning of buffer
477 buffer
+ transferred_len
,
480 /* If not DMA, simply increase
483 buffer
+= transferred_len
;
494 (*bytes_written
) += passsize
;
497 /* Force new allocation in next iteration */
498 if (fromuser
|| fromkern
)
504 #ifdef SISUSB_DONTSYNC
505 (*bytes_written
) = len
;
506 /* Some URBs/buffers might be busy */
508 sisusb_wait_all_out_complete(sisusb
);
509 (*bytes_written
) = transferred_len
;
510 /* All URBs and all buffers are available */
514 return ((*bytes_written
) == len
) ? 0 : -EIO
;
517 /* Receive a bulk message of variable size
519 * To copy the data to userspace, give pointer to "userbuffer",
520 * to copy to kernel memory, give "kernbuffer". One of them
521 * MUST be set. (There is no technique for letting the caller
522 * read directly from the ibuf.)
526 static int sisusb_recv_bulk_msg(struct sisusb_usb_data
*sisusb
, int ep
, int len
,
527 void *kernbuffer
, char __user
*userbuffer
, ssize_t
*bytes_read
,
530 int result
= 0, retry
, count
= len
;
531 int bufsize
, thispass
, transferred_len
;
538 if (!sisusb
|| !sisusb
->present
|| !sisusb
->sisusb_dev
)
541 pipe
= usb_rcvbulkpipe(sisusb
->sisusb_dev
, ep
);
542 buffer
= sisusb
->ibuf
;
543 bufsize
= sisusb
->ibufsize
;
547 #ifdef SISUSB_DONTSYNC
548 if (!(sisusb_wait_all_out_complete(sisusb
)))
554 if (!sisusb
->sisusb_dev
)
557 thispass
= (bufsize
< count
) ? bufsize
: count
;
559 result
= sisusb_bulkin_msg(sisusb
,
566 sisusb
->transfer_dma_in
);
569 thispass
= transferred_len
;
571 else if (result
== -ETIMEDOUT
) {
584 (*bytes_read
) += thispass
;
589 if (copy_to_user(userbuffer
, buffer
, thispass
))
592 userbuffer
+= thispass
;
596 memcpy(kernbuffer
, buffer
, thispass
);
597 kernbuffer
+= thispass
;
605 return ((*bytes_read
) == len
) ? 0 : -EIO
;
608 static int sisusb_send_packet(struct sisusb_usb_data
*sisusb
, int len
,
609 struct sisusb_packet
*packet
)
612 ssize_t bytes_transferred
= 0;
618 #ifdef SISUSB_DONTSYNC
619 if (!(sisusb_wait_all_out_complete(sisusb
)))
623 /* Eventually correct endianness */
624 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
626 /* 1. send the packet */
627 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_GFX_OUT
, len
,
628 (char *)packet
, NULL
, 0, &bytes_transferred
, 0, 0);
630 if ((ret
== 0) && (len
== 6)) {
632 /* 2. if packet len == 6, it means we read, so wait for 32bit
633 * return value and write it to packet->data
635 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_GFX_IN
, 4,
636 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
638 packet
->data
= le32_to_cpu(tmp
);
644 static int sisusb_send_bridge_packet(struct sisusb_usb_data
*sisusb
, int len
,
645 struct sisusb_packet
*packet
,
649 ssize_t bytes_transferred
= 0;
655 #ifdef SISUSB_DONTSYNC
656 if (!(sisusb_wait_all_out_complete(sisusb
)))
660 /* Eventually correct endianness */
661 SISUSB_CORRECT_ENDIANNESS_PACKET(packet
);
663 /* 1. send the packet */
664 ret
= sisusb_send_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_OUT
, len
,
665 (char *)packet
, NULL
, 0, &bytes_transferred
, tflags
, 0);
667 if ((ret
== 0) && (len
== 6)) {
669 /* 2. if packet len == 6, it means we read, so wait for 32bit
670 * return value and write it to packet->data
672 ret
= sisusb_recv_bulk_msg(sisusb
, SISUSB_EP_BRIDGE_IN
, 4,
673 (char *)&tmp
, NULL
, &bytes_transferred
, 0);
675 packet
->data
= le32_to_cpu(tmp
);
681 /* access video memory and mmio (return 0 on success) */
685 /* The following routines assume being used to transfer byte, word,
688 * - the write routines expect "data" in machine endianness format.
689 * The data will be converted to leXX in sisusb_xxx_packet.
690 * - the read routines can expect read data in machine-endianess.
693 static int sisusb_write_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
696 struct sisusb_packet packet
;
699 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
700 packet
.address
= addr
& ~3;
701 packet
.data
= data
<< ((addr
& 3) << 3);
702 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
706 static int sisusb_write_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
709 struct sisusb_packet packet
;
712 packet
.address
= addr
& ~3;
716 packet
.header
= (type
<< 6) | 0x0003;
717 packet
.data
= (u32
)data
;
718 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
721 packet
.header
= (type
<< 6) | 0x0006;
722 packet
.data
= (u32
)data
<< 8;
723 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
726 packet
.header
= (type
<< 6) | 0x000c;
727 packet
.data
= (u32
)data
<< 16;
728 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
731 packet
.header
= (type
<< 6) | 0x0008;
732 packet
.data
= (u32
)data
<< 24;
733 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
734 packet
.header
= (type
<< 6) | 0x0001;
735 packet
.address
= (addr
& ~3) + 4;
736 packet
.data
= (u32
)data
>> 8;
737 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
743 static int sisusb_write_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
746 struct sisusb_packet packet
;
749 packet
.address
= addr
& ~3;
753 packet
.header
= (type
<< 6) | 0x0007;
754 packet
.data
= data
& 0x00ffffff;
755 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
758 packet
.header
= (type
<< 6) | 0x000e;
759 packet
.data
= data
<< 8;
760 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
763 packet
.header
= (type
<< 6) | 0x000c;
764 packet
.data
= data
<< 16;
765 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
766 packet
.header
= (type
<< 6) | 0x0001;
767 packet
.address
= (addr
& ~3) + 4;
768 packet
.data
= (data
>> 16) & 0x00ff;
769 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
772 packet
.header
= (type
<< 6) | 0x0008;
773 packet
.data
= data
<< 24;
774 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
775 packet
.header
= (type
<< 6) | 0x0003;
776 packet
.address
= (addr
& ~3) + 4;
777 packet
.data
= (data
>> 8) & 0xffff;
778 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
784 static int sisusb_write_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
787 struct sisusb_packet packet
;
790 packet
.address
= addr
& ~3;
794 packet
.header
= (type
<< 6) | 0x000f;
796 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
799 packet
.header
= (type
<< 6) | 0x000e;
800 packet
.data
= data
<< 8;
801 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
802 packet
.header
= (type
<< 6) | 0x0001;
803 packet
.address
= (addr
& ~3) + 4;
804 packet
.data
= data
>> 24;
805 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
808 packet
.header
= (type
<< 6) | 0x000c;
809 packet
.data
= data
<< 16;
810 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
811 packet
.header
= (type
<< 6) | 0x0003;
812 packet
.address
= (addr
& ~3) + 4;
813 packet
.data
= data
>> 16;
814 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
817 packet
.header
= (type
<< 6) | 0x0008;
818 packet
.data
= data
<< 24;
819 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
820 packet
.header
= (type
<< 6) | 0x0007;
821 packet
.address
= (addr
& ~3) + 4;
822 packet
.data
= data
>> 8;
823 ret
|= sisusb_send_packet(sisusb
, 10, &packet
);
829 /* The xxx_bulk routines copy a buffer of variable size. They treat the
830 * buffer as chars, therefore lsb/msb has to be corrected if using the
831 * byte/word/long/etc routines for speed-up
833 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
834 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
835 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
836 * that the data already is in the transfer buffer "sisusb->obuf[index]".
839 static int sisusb_write_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
840 char *kernbuffer
, int length
,
841 const char __user
*userbuffer
, int index
,
842 ssize_t
*bytes_written
)
844 struct sisusb_packet packet
;
846 static int msgcount
= 0;
847 u8 swap8
, fromkern
= kernbuffer
? 1 : 0;
849 u32 swap32
, flag
= (length
>> 28) & 1;
852 /* if neither kernbuffer not userbuffer are given, assume
855 if (!fromkern
&& !userbuffer
)
856 kernbuffer
= sisusb
->obuf
[index
];
858 (*bytes_written
= 0);
860 length
&= 0x00ffffff;
868 if (get_user(swap8
, (u8 __user
*)userbuffer
))
871 swap8
= kernbuffer
[0];
873 ret
= sisusb_write_memio_byte(sisusb
,
884 if (get_user(swap16
, (u16 __user
*)userbuffer
))
887 swap16
= *((u16
*)kernbuffer
);
889 ret
= sisusb_write_memio_word(sisusb
,
895 (*bytes_written
) += 2;
901 if (copy_from_user(&buf
, userbuffer
, 3))
904 swap32
= (buf
[0] << 16) |
908 swap32
= (buf
[2] << 16) |
914 swap32
= (kernbuffer
[0] << 16) |
915 (kernbuffer
[1] << 8) |
918 swap32
= (kernbuffer
[2] << 16) |
919 (kernbuffer
[1] << 8) |
923 ret
= sisusb_write_memio_24bit(sisusb
,
929 (*bytes_written
) += 3;
935 if (get_user(swap32
, (u32 __user
*)userbuffer
))
938 swap32
= *((u32
*)kernbuffer
);
940 ret
= sisusb_write_memio_long(sisusb
,
945 (*bytes_written
) += 4;
950 if ((length
& ~3) > 0x10000) {
952 packet
.header
= 0x001f;
953 packet
.address
= 0x000001d4;
955 ret
= sisusb_send_bridge_packet(sisusb
, 10,
957 packet
.header
= 0x001f;
958 packet
.address
= 0x000001d0;
959 packet
.data
= (length
& ~3);
960 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
962 packet
.header
= 0x001f;
963 packet
.address
= 0x000001c0;
964 packet
.data
= flag
| 0x16;
965 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
968 ret
|= sisusb_send_bulk_msg(sisusb
,
969 SISUSB_EP_GFX_LBULK_OUT
,
972 bytes_written
, 0, 1);
973 userbuffer
+= (*bytes_written
);
974 } else if (fromkern
) {
975 ret
|= sisusb_send_bulk_msg(sisusb
,
976 SISUSB_EP_GFX_LBULK_OUT
,
979 bytes_written
, 0, 1);
980 kernbuffer
+= (*bytes_written
);
982 ret
|= sisusb_send_bulk_msg(sisusb
,
983 SISUSB_EP_GFX_LBULK_OUT
,
986 bytes_written
, 0, 1);
987 kernbuffer
+= ((*bytes_written
) &
988 (sisusb
->obufsize
-1));
993 packet
.header
= 0x001f;
994 packet
.address
= 0x00000194;
996 ret
= sisusb_send_bridge_packet(sisusb
, 10,
998 packet
.header
= 0x001f;
999 packet
.address
= 0x00000190;
1000 packet
.data
= (length
& ~3);
1001 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1003 if (sisusb
->flagb0
!= 0x16) {
1004 packet
.header
= 0x001f;
1005 packet
.address
= 0x00000180;
1006 packet
.data
= flag
| 0x16;
1007 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1009 sisusb
->flagb0
= 0x16;
1012 ret
|= sisusb_send_bulk_msg(sisusb
,
1013 SISUSB_EP_GFX_BULK_OUT
,
1015 NULL
, userbuffer
, 0,
1016 bytes_written
, 0, 1);
1017 userbuffer
+= (*bytes_written
);
1018 } else if (fromkern
) {
1019 ret
|= sisusb_send_bulk_msg(sisusb
,
1020 SISUSB_EP_GFX_BULK_OUT
,
1022 kernbuffer
, NULL
, 0,
1023 bytes_written
, 0, 1);
1024 kernbuffer
+= (*bytes_written
);
1026 ret
|= sisusb_send_bulk_msg(sisusb
,
1027 SISUSB_EP_GFX_BULK_OUT
,
1030 bytes_written
, 0, 1);
1031 kernbuffer
+= ((*bytes_written
) &
1032 (sisusb
->obufsize
-1));
1039 "sisusbvga[%d]: Wrote %zd of "
1040 "%d bytes, error %d\n",
1041 sisusb
->minor
, *bytes_written
,
1043 else if (msgcount
== 500)
1045 "sisusbvga[%d]: Too many errors"
1046 ", logging stopped\n",
1049 addr
+= (*bytes_written
);
1050 length
-= (*bytes_written
);
1058 return ret
? -EIO
: 0;
1061 /* Remember: Read data in packet is in machine-endianess! So for
1062 * byte, word, 24bit, long no endian correction is necessary.
1065 static int sisusb_read_memio_byte(struct sisusb_usb_data
*sisusb
, int type
,
1068 struct sisusb_packet packet
;
1071 CLEARPACKET(&packet
);
1072 packet
.header
= (1 << (addr
& 3)) | (type
<< 6);
1073 packet
.address
= addr
& ~3;
1074 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1075 *data
= (u8
)(packet
.data
>> ((addr
& 3) << 3));
1079 static int sisusb_read_memio_word(struct sisusb_usb_data
*sisusb
, int type
,
1080 u32 addr
, u16
*data
)
1082 struct sisusb_packet packet
;
1085 CLEARPACKET(&packet
);
1087 packet
.address
= addr
& ~3;
1091 packet
.header
= (type
<< 6) | 0x0003;
1092 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1093 *data
= (u16
)(packet
.data
);
1096 packet
.header
= (type
<< 6) | 0x0006;
1097 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1098 *data
= (u16
)(packet
.data
>> 8);
1101 packet
.header
= (type
<< 6) | 0x000c;
1102 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1103 *data
= (u16
)(packet
.data
>> 16);
1106 packet
.header
= (type
<< 6) | 0x0008;
1107 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1108 *data
= (u16
)(packet
.data
>> 24);
1109 packet
.header
= (type
<< 6) | 0x0001;
1110 packet
.address
= (addr
& ~3) + 4;
1111 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1112 *data
|= (u16
)(packet
.data
<< 8);
1118 static int sisusb_read_memio_24bit(struct sisusb_usb_data
*sisusb
, int type
,
1119 u32 addr
, u32
*data
)
1121 struct sisusb_packet packet
;
1124 packet
.address
= addr
& ~3;
1128 packet
.header
= (type
<< 6) | 0x0007;
1129 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1130 *data
= packet
.data
& 0x00ffffff;
1133 packet
.header
= (type
<< 6) | 0x000e;
1134 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1135 *data
= packet
.data
>> 8;
1138 packet
.header
= (type
<< 6) | 0x000c;
1139 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1140 *data
= packet
.data
>> 16;
1141 packet
.header
= (type
<< 6) | 0x0001;
1142 packet
.address
= (addr
& ~3) + 4;
1143 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1144 *data
|= ((packet
.data
& 0xff) << 16);
1147 packet
.header
= (type
<< 6) | 0x0008;
1148 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1149 *data
= packet
.data
>> 24;
1150 packet
.header
= (type
<< 6) | 0x0003;
1151 packet
.address
= (addr
& ~3) + 4;
1152 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1153 *data
|= ((packet
.data
& 0xffff) << 8);
1159 static int sisusb_read_memio_long(struct sisusb_usb_data
*sisusb
, int type
,
1160 u32 addr
, u32
*data
)
1162 struct sisusb_packet packet
;
1165 packet
.address
= addr
& ~3;
1169 packet
.header
= (type
<< 6) | 0x000f;
1170 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1171 *data
= packet
.data
;
1174 packet
.header
= (type
<< 6) | 0x000e;
1175 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1176 *data
= packet
.data
>> 8;
1177 packet
.header
= (type
<< 6) | 0x0001;
1178 packet
.address
= (addr
& ~3) + 4;
1179 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1180 *data
|= (packet
.data
<< 24);
1183 packet
.header
= (type
<< 6) | 0x000c;
1184 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1185 *data
= packet
.data
>> 16;
1186 packet
.header
= (type
<< 6) | 0x0003;
1187 packet
.address
= (addr
& ~3) + 4;
1188 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1189 *data
|= (packet
.data
<< 16);
1192 packet
.header
= (type
<< 6) | 0x0008;
1193 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1194 *data
= packet
.data
>> 24;
1195 packet
.header
= (type
<< 6) | 0x0007;
1196 packet
.address
= (addr
& ~3) + 4;
1197 ret
|= sisusb_send_packet(sisusb
, 6, &packet
);
1198 *data
|= (packet
.data
<< 8);
1204 static int sisusb_read_mem_bulk(struct sisusb_usb_data
*sisusb
, u32 addr
,
1205 char *kernbuffer
, int length
,
1206 char __user
*userbuffer
, ssize_t
*bytes_read
)
1215 length
&= 0x00ffffff;
1223 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
,
1228 if (put_user(buf
[0],
1229 (u8 __user
*)userbuffer
)) {
1233 kernbuffer
[0] = buf
[0];
1239 ret
|= sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1244 if (put_user(swap16
,
1245 (u16 __user
*)userbuffer
))
1248 *((u16
*)kernbuffer
) = swap16
;
1254 ret
|= sisusb_read_memio_24bit(sisusb
, SISUSB_TYPE_MEM
,
1259 buf
[0] = (swap32
>> 16) & 0xff;
1260 buf
[1] = (swap32
>> 8) & 0xff;
1261 buf
[2] = swap32
& 0xff;
1263 buf
[2] = (swap32
>> 16) & 0xff;
1264 buf
[1] = (swap32
>> 8) & 0xff;
1265 buf
[0] = swap32
& 0xff;
1268 if (copy_to_user(userbuffer
, &buf
[0], 3))
1271 kernbuffer
[0] = buf
[0];
1272 kernbuffer
[1] = buf
[1];
1273 kernbuffer
[2] = buf
[2];
1279 ret
|= sisusb_read_memio_long(sisusb
, SISUSB_TYPE_MEM
,
1284 if (put_user(swap32
,
1285 (u32 __user
*)userbuffer
))
1290 *((u32
*)kernbuffer
) = swap32
;
1296 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1298 CLEARPACKET(&packet
);
1299 packet
.header
= 0x001f;
1300 packet
.address
= 0x000001a0;
1301 packet
.data
= 0x00000006;
1302 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1304 packet
.header
= 0x001f;
1305 packet
.address
= 0x000001b0;
1306 packet
.data
= (length
& ~3) | 0x40000000;
1307 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1309 packet
.header
= 0x001f;
1310 packet
.address
= 0x000001b4;
1312 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1314 packet
.header
= 0x001f;
1315 packet
.address
= 0x000001a4;
1316 packet
.data
= 0x00000001;
1317 ret
|= sisusb_send_bridge_packet(sisusb
, 10,
1320 ret
|= sisusb_recv_bulk_msg(sisusb
,
1321 SISUSB_EP_GFX_BULK_IN
,
1325 if (!ret
) userbuffer
+= (*bytes_read
);
1327 ret
|= sisusb_recv_bulk_msg(sisusb
,
1328 SISUSB_EP_GFX_BULK_IN
,
1332 if (!ret
) kernbuffer
+= (*bytes_read
);
1334 addr
+= (*bytes_read
);
1335 length
-= (*bytes_read
);
1346 /* High level: Gfx (indexed) register access */
1348 #ifdef INCL_SISUSB_CON
1350 sisusb_setreg(struct sisusb_usb_data
*sisusb
, int port
, u8 data
)
1352 return sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1356 sisusb_getreg(struct sisusb_usb_data
*sisusb
, int port
, u8
*data
)
1358 return sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, data
);
1362 #ifndef INCL_SISUSB_CON
1366 sisusb_setidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 data
)
1369 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1370 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1374 #ifndef INCL_SISUSB_CON
1378 sisusb_getidxreg(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8
*data
)
1381 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, index
);
1382 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, data
);
1386 #ifndef INCL_SISUSB_CON
1390 sisusb_setidxregandor(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1396 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1397 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1400 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1405 sisusb_setidxregmask(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
,
1410 ret
= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
, idx
);
1411 ret
|= sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, &tmp
);
1413 tmp
|= (data
& mask
);
1414 ret
|= sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_IO
, port
+ 1, tmp
);
1418 #ifndef INCL_SISUSB_CON
1422 sisusb_setidxregor(struct sisusb_usb_data
*sisusb
, int port
, u8 index
, u8 myor
)
1424 return(sisusb_setidxregandor(sisusb
, port
, index
, 0xff, myor
));
1427 #ifndef INCL_SISUSB_CON
1431 sisusb_setidxregand(struct sisusb_usb_data
*sisusb
, int port
, u8 idx
, u8 myand
)
1433 return(sisusb_setidxregandor(sisusb
, port
, idx
, myand
, 0x00));
1436 /* Write/read video ram */
1438 #ifdef INCL_SISUSB_CON
1440 sisusb_writeb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8 data
)
1442 return(sisusb_write_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1446 sisusb_readb(struct sisusb_usb_data
*sisusb
, u32 adr
, u8
*data
)
1448 return(sisusb_read_memio_byte(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1452 sisusb_writew(struct sisusb_usb_data
*sisusb
, u32 adr
, u16 data
)
1454 return(sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1458 sisusb_readw(struct sisusb_usb_data
*sisusb
, u32 adr
, u16
*data
)
1460 return(sisusb_read_memio_word(sisusb
, SISUSB_TYPE_MEM
, adr
, data
));
1464 sisusb_copy_memory(struct sisusb_usb_data
*sisusb
, char *src
,
1465 u32 dest
, int length
, size_t *bytes_written
)
1467 return(sisusb_write_mem_bulk(sisusb
, dest
, src
, length
, NULL
, 0, bytes_written
));
1470 #ifdef SISUSBENDIANTEST
1472 sisusb_read_memory(struct sisusb_usb_data
*sisusb
, char *dest
,
1473 u32 src
, int length
, size_t *bytes_written
)
1475 return(sisusb_read_mem_bulk(sisusb
, src
, dest
, length
, NULL
, bytes_written
));
1480 #ifdef SISUSBENDIANTEST
1482 sisusb_testreadwrite(struct sisusb_usb_data
*sisusb
)
1484 static char srcbuffer
[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1485 char destbuffer
[10];
1489 sisusb_copy_memory(sisusb
, srcbuffer
, sisusb
->vrambase
, 7, &dummy
);
1491 for(i
= 1; i
<= 7; i
++) {
1492 printk(KERN_DEBUG
"sisusb: rwtest %d bytes\n", i
);
1493 sisusb_read_memory(sisusb
, destbuffer
, sisusb
->vrambase
, i
, &dummy
);
1494 for(j
= 0; j
< i
; j
++) {
1495 printk(KERN_DEBUG
"sisusb: rwtest read[%d] = %x\n", j
, destbuffer
[j
]);
1501 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1504 sisusb_write_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32 data
)
1506 struct sisusb_packet packet
;
1509 packet
.header
= 0x008f;
1510 packet
.address
= regnum
| 0x10000;
1512 ret
= sisusb_send_packet(sisusb
, 10, &packet
);
1517 sisusb_read_pci_config(struct sisusb_usb_data
*sisusb
, int regnum
, u32
*data
)
1519 struct sisusb_packet packet
;
1522 packet
.header
= 0x008f;
1523 packet
.address
= (u32
)regnum
| 0x10000;
1524 ret
= sisusb_send_packet(sisusb
, 6, &packet
);
1525 *data
= packet
.data
;
1529 /* Clear video RAM */
1532 sisusb_clear_vram(struct sisusb_usb_data
*sisusb
, u32 address
, int length
)
1537 if (address
< sisusb
->vrambase
)
1540 if (address
>= sisusb
->vrambase
+ sisusb
->vramsize
)
1543 if (address
+ length
> sisusb
->vrambase
+ sisusb
->vramsize
)
1544 length
= sisusb
->vrambase
+ sisusb
->vramsize
- address
;
1549 /* allocate free buffer/urb and clear the buffer */
1550 if ((i
= sisusb_alloc_outbuf(sisusb
)) < 0)
1553 memset(sisusb
->obuf
[i
], 0, sisusb
->obufsize
);
1555 /* We can write a length > buffer size here. The buffer
1556 * data will simply be re-used (like a ring-buffer).
1558 ret
= sisusb_write_mem_bulk(sisusb
, address
, NULL
, length
, NULL
, i
, &j
);
1560 /* Free the buffer/urb */
1561 sisusb_free_outbuf(sisusb
, i
);
1566 /* Initialize the graphics core (return 0 on success)
1567 * This resets the graphics hardware and puts it into
1568 * a defined mode (640x480@60Hz)
1571 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1572 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1573 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1574 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1575 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1576 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1577 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1578 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1579 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1580 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1581 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1584 sisusb_triggersr16(struct sisusb_usb_data
*sisusb
, u8 ramtype
)
1589 ret
= GETIREG(SISSR
, 0x16, &tmp8
);
1592 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1594 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1597 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1599 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1601 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1603 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1605 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1607 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1609 ret
|= SETIREG(SISSR
, 0x16, tmp8
);
1615 sisusb_getbuswidth(struct sisusb_usb_data
*sisusb
, int *bw
, int *chab
)
1618 u8 ramtype
, done
= 0;
1620 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1622 ret
= GETIREG(SISSR
, 0x3a, &ramtype
);
1625 ret
|= SETIREG(SISSR
, 0x13, 0x00);
1628 ret
|= SETIREG(SISSR
, 0x14, 0x12);
1629 ret
|= SETIREGAND(SISSR
, 0x15, 0xef);
1631 ret
|= SETIREG(SISSR
, 0x14, 0x02);
1634 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1635 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1636 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1637 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1638 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1639 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1640 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1641 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1642 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1643 ret
|= READL(ramptr
+ 0, &t0
);
1644 ret
|= READL(ramptr
+ 4, &t1
);
1645 ret
|= READL(ramptr
+ 8, &t2
);
1646 ret
|= READL(ramptr
+ 12, &t3
);
1650 *chab
= 0; *bw
= 64;
1652 if ((t3
!= 0xcdef0123) || (t2
!= 0x89abcdef)) {
1653 if ((t1
== 0x456789ab) && (t0
== 0x01234567)) {
1654 *chab
= 0; *bw
= 64;
1655 ret
|= SETIREGAND(SISSR
, 0x14, 0xfd);
1658 if ((t1
!= 0x456789ab) || (t0
!= 0x01234567)) {
1659 *chab
= 1; *bw
= 64;
1660 ret
|= SETIREGANDOR(SISSR
, 0x14, 0xfc,0x01);
1662 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1663 ret
|= WRITEL(ramptr
+ 0, 0x89abcdef);
1664 ret
|= WRITEL(ramptr
+ 4, 0xcdef0123);
1665 ret
|= WRITEL(ramptr
+ 8, 0x55555555);
1666 ret
|= WRITEL(ramptr
+ 12, 0x55555555);
1667 ret
|= WRITEL(ramptr
+ 16, 0xaaaaaaaa);
1668 ret
|= WRITEL(ramptr
+ 20, 0xaaaaaaaa);
1669 ret
|= READL(ramptr
+ 4, &t1
);
1671 if (t1
!= 0xcdef0123) {
1673 ret
|= SETIREGOR(SISSR
, 0x15, 0x10);
1679 *chab
= 0; *bw
= 64; /* default: cha, bw = 64 */
1683 if (t1
== 0x456789ab) {
1684 if (t0
== 0x01234567) {
1685 *chab
= 0; *bw
= 64;
1689 if (t0
== 0x01234567) {
1690 *chab
= 0; *bw
= 32;
1691 ret
|= SETIREG(SISSR
, 0x14, 0x00);
1697 ret
|= SETIREG(SISSR
, 0x14, 0x03);
1698 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
1700 ret
|= WRITEL(ramptr
+ 0, 0x01234567);
1701 ret
|= WRITEL(ramptr
+ 4, 0x456789ab);
1702 ret
|= WRITEL(ramptr
+ 8, 0x89abcdef);
1703 ret
|= WRITEL(ramptr
+ 12, 0xcdef0123);
1704 ret
|= WRITEL(ramptr
+ 16, 0x55555555);
1705 ret
|= WRITEL(ramptr
+ 20, 0x55555555);
1706 ret
|= WRITEL(ramptr
+ 24, 0xffffffff);
1707 ret
|= WRITEL(ramptr
+ 28, 0xffffffff);
1708 ret
|= READL(ramptr
+ 0, &t0
);
1709 ret
|= READL(ramptr
+ 4, &t1
);
1711 if (t1
== 0x456789ab) {
1712 if (t0
== 0x01234567) {
1713 *chab
= 1; *bw
= 64;
1717 if (t0
== 0x01234567) {
1718 *chab
= 1; *bw
= 32;
1719 ret
|= SETIREG(SISSR
, 0x14, 0x01);
1728 sisusb_verify_mclk(struct sisusb_usb_data
*sisusb
)
1731 u32 ramptr
= SISUSB_PCI_MEMBASE
;
1732 u8 tmp1
, tmp2
, i
, j
;
1734 ret
|= WRITEB(ramptr
, 0xaa);
1735 ret
|= WRITEB(ramptr
+ 16, 0x55);
1736 ret
|= READB(ramptr
, &tmp1
);
1737 ret
|= READB(ramptr
+ 16, &tmp2
);
1738 if ((tmp1
!= 0xaa) || (tmp2
!= 0x55)) {
1739 for (i
= 0, j
= 16; i
< 2; i
++, j
+= 16) {
1740 ret
|= GETIREG(SISSR
, 0x21, &tmp1
);
1741 ret
|= SETIREGAND(SISSR
, 0x21, (tmp1
& 0xfb));
1742 ret
|= SETIREGOR(SISSR
, 0x3c, 0x01); /* not on 330 */
1743 ret
|= SETIREGAND(SISSR
, 0x3c, 0xfe); /* not on 330 */
1744 ret
|= SETIREG(SISSR
, 0x21, tmp1
);
1745 ret
|= WRITEB(ramptr
+ 16 + j
, j
);
1746 ret
|= READB(ramptr
+ 16 + j
, &tmp1
);
1748 ret
|= WRITEB(ramptr
+ j
, j
);
1757 sisusb_set_rank(struct sisusb_usb_data
*sisusb
, int *iret
, int index
,
1758 u8 rankno
, u8 chab
, const u8 dramtype
[][5],
1761 int ret
= 0, ranksize
;
1766 if ((rankno
== 2) && (dramtype
[index
][0] == 2))
1769 ranksize
= dramtype
[index
][3] / 2 * bw
/ 32;
1771 if ((ranksize
* rankno
) > 128)
1775 while ((ranksize
>>= 1) > 0) tmp
+= 0x10;
1776 tmp
|= ((rankno
- 1) << 2);
1777 tmp
|= ((bw
/ 64) & 0x02);
1778 tmp
|= (chab
& 0x01);
1780 ret
= SETIREG(SISSR
, 0x14, tmp
);
1781 ret
|= sisusb_triggersr16(sisusb
, 0); /* sic! */
1789 sisusb_check_rbc(struct sisusb_usb_data
*sisusb
, int *iret
, u32 inc
, int testn
)
1796 for (i
= 0, j
= 0; i
< testn
; i
++) {
1797 ret
|= WRITEL(sisusb
->vrambase
+ j
, j
);
1801 for (i
= 0, j
= 0; i
< testn
; i
++) {
1802 ret
|= READL(sisusb
->vrambase
+ j
, &tmp
);
1803 if (tmp
!= j
) return ret
;
1812 sisusb_check_ranks(struct sisusb_usb_data
*sisusb
, int *iret
, int rankno
,
1813 int idx
, int bw
, const u8 rtype
[][5])
1815 int ret
= 0, i
, i2ret
;
1820 for (i
= rankno
; i
>= 1; i
--) {
1821 inc
= 1 << (rtype
[idx
][2] +
1825 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1830 inc
= 1 << (rtype
[idx
][2] + bw
/ 64 + 2);
1831 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 4);
1835 inc
= 1 << (10 + bw
/ 64);
1836 ret
|= sisusb_check_rbc(sisusb
, &i2ret
, inc
, 2);
1845 sisusb_get_sdram_size(struct sisusb_usb_data
*sisusb
, int *iret
, int bw
,
1848 int ret
= 0, i2ret
= 0, i
, j
;
1849 static const u8 sdramtype
[13][5] = {
1850 { 2, 12, 9, 64, 0x35 },
1851 { 1, 13, 9, 64, 0x44 },
1852 { 2, 12, 8, 32, 0x31 },
1853 { 2, 11, 9, 32, 0x25 },
1854 { 1, 12, 9, 32, 0x34 },
1855 { 1, 13, 8, 32, 0x40 },
1856 { 2, 11, 8, 16, 0x21 },
1857 { 1, 12, 8, 16, 0x30 },
1858 { 1, 11, 9, 16, 0x24 },
1859 { 1, 11, 8, 8, 0x20 },
1860 { 2, 9, 8, 4, 0x01 },
1861 { 1, 10, 8, 4, 0x10 },
1862 { 1, 9, 8, 2, 0x00 }
1865 *iret
= 1; /* error */
1867 for (i
= 0; i
< 13; i
++) {
1868 ret
|= SETIREGANDOR(SISSR
, 0x13, 0x80, sdramtype
[i
][4]);
1869 for (j
= 2; j
> 0; j
--) {
1870 ret
|= sisusb_set_rank(sisusb
, &i2ret
, i
, j
,
1871 chab
, sdramtype
, bw
);
1875 ret
|= sisusb_check_ranks(sisusb
, &i2ret
, j
, i
,
1878 *iret
= 0; /* ram size found */
1888 sisusb_setup_screen(struct sisusb_usb_data
*sisusb
, int clrall
, int drwfr
)
1892 int i
, length
, modex
, modey
, bpp
;
1894 modex
= 640; modey
= 480; bpp
= 2;
1896 address
= sisusb
->vrambase
; /* Clear video ram */
1899 length
= sisusb
->vramsize
;
1901 length
= modex
* bpp
* modey
;
1903 ret
= sisusb_clear_vram(sisusb
, address
, length
);
1905 if (!ret
&& drwfr
) {
1906 for (i
= 0; i
< modex
; i
++) {
1907 address
= sisusb
->vrambase
+ (i
* bpp
);
1908 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1910 address
+= (modex
* (modey
-1) * bpp
);
1911 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1914 for (i
= 0; i
< modey
; i
++) {
1915 address
= sisusb
->vrambase
+ ((i
* modex
) * bpp
);
1916 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1918 address
+= ((modex
- 1) * bpp
);
1919 ret
|= sisusb_write_memio_word(sisusb
, SISUSB_TYPE_MEM
,
1928 sisusb_set_default_mode(struct sisusb_usb_data
*sisusb
, int touchengines
)
1930 int ret
= 0, i
, j
, modex
, modey
, bpp
, du
;
1931 u8 sr31
, cr63
, tmp8
;
1932 static const char attrdata
[] = {
1933 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1934 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1937 static const char crtcrdata
[] = {
1938 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1939 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1940 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1943 static const char grcdata
[] = {
1944 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1947 static const char crtcdata
[] = {
1948 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1949 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1953 modex
= 640; modey
= 480; bpp
= 2;
1955 GETIREG(SISSR
, 0x31, &sr31
);
1956 GETIREG(SISCR
, 0x63, &cr63
);
1957 SETIREGOR(SISSR
, 0x01, 0x20);
1958 SETIREG(SISCR
, 0x63, cr63
& 0xbf);
1959 SETIREGOR(SISCR
, 0x17, 0x80);
1960 SETIREGOR(SISSR
, 0x1f, 0x04);
1961 SETIREGAND(SISSR
, 0x07, 0xfb);
1962 SETIREG(SISSR
, 0x00, 0x03); /* seq */
1963 SETIREG(SISSR
, 0x01, 0x21);
1964 SETIREG(SISSR
, 0x02, 0x0f);
1965 SETIREG(SISSR
, 0x03, 0x00);
1966 SETIREG(SISSR
, 0x04, 0x0e);
1967 SETREG(SISMISCW
, 0x23); /* misc */
1968 for (i
= 0; i
<= 0x18; i
++) { /* crtc */
1969 SETIREG(SISCR
, i
, crtcrdata
[i
]);
1971 for (i
= 0; i
<= 0x13; i
++) { /* att */
1972 GETREG(SISINPSTAT
, &tmp8
);
1974 SETREG(SISAR
, attrdata
[i
]);
1976 GETREG(SISINPSTAT
, &tmp8
);
1977 SETREG(SISAR
, 0x14);
1978 SETREG(SISAR
, 0x00);
1979 GETREG(SISINPSTAT
, &tmp8
);
1980 SETREG(SISAR
, 0x20);
1981 GETREG(SISINPSTAT
, &tmp8
);
1982 for (i
= 0; i
<= 0x08; i
++) { /* grc */
1983 SETIREG(SISGR
, i
, grcdata
[i
]);
1985 SETIREGAND(SISGR
, 0x05, 0xbf);
1986 for (i
= 0x0A; i
<= 0x0E; i
++) { /* clr ext */
1987 SETIREG(SISSR
, i
, 0x00);
1989 SETIREGAND(SISSR
, 0x37, 0xfe);
1990 SETREG(SISMISCW
, 0xef); /* sync */
1991 SETIREG(SISCR
, 0x11, 0x00); /* crtc */
1992 for (j
= 0x00, i
= 0; i
<= 7; i
++, j
++) {
1993 SETIREG(SISCR
, j
, crtcdata
[i
]);
1995 for (j
= 0x10; i
<= 10; i
++, j
++) {
1996 SETIREG(SISCR
, j
, crtcdata
[i
]);
1998 for (j
= 0x15; i
<= 12; i
++, j
++) {
1999 SETIREG(SISCR
, j
, crtcdata
[i
]);
2001 for (j
= 0x0A; i
<= 15; i
++, j
++) {
2002 SETIREG(SISSR
, j
, crtcdata
[i
]);
2004 SETIREG(SISSR
, 0x0E, (crtcdata
[16] & 0xE0));
2005 SETIREGANDOR(SISCR
, 0x09, 0x5f, ((crtcdata
[16] & 0x01) << 5));
2006 SETIREG(SISCR
, 0x14, 0x4f);
2007 du
= (modex
/ 16) * (bpp
* 2); /* offset/pitch */
2008 if (modex
% 16) du
+= bpp
;
2009 SETIREGANDOR(SISSR
, 0x0e, 0xf0, ((du
>> 8) & 0x0f));
2010 SETIREG(SISCR
, 0x13, (du
& 0xff));
2013 if (du
& 0xff) tmp8
++;
2014 SETIREG(SISSR
, 0x10, tmp8
);
2015 SETIREG(SISSR
, 0x31, 0x00); /* VCLK */
2016 SETIREG(SISSR
, 0x2b, 0x1b);
2017 SETIREG(SISSR
, 0x2c, 0xe1);
2018 SETIREG(SISSR
, 0x2d, 0x01);
2019 SETIREGAND(SISSR
, 0x3d, 0xfe); /* FIFO */
2020 SETIREG(SISSR
, 0x08, 0xae);
2021 SETIREGAND(SISSR
, 0x09, 0xf0);
2022 SETIREG(SISSR
, 0x08, 0x34);
2023 SETIREGOR(SISSR
, 0x3d, 0x01);
2024 SETIREGAND(SISSR
, 0x1f, 0x3f); /* mode regs */
2025 SETIREGANDOR(SISSR
, 0x06, 0xc0, 0x0a);
2026 SETIREG(SISCR
, 0x19, 0x00);
2027 SETIREGAND(SISCR
, 0x1a, 0xfc);
2028 SETIREGAND(SISSR
, 0x0f, 0xb7);
2029 SETIREGAND(SISSR
, 0x31, 0xfb);
2030 SETIREGANDOR(SISSR
, 0x21, 0x1f, 0xa0);
2031 SETIREGAND(SISSR
, 0x32, 0xf3);
2032 SETIREGANDOR(SISSR
, 0x07, 0xf8, 0x03);
2033 SETIREG(SISCR
, 0x52, 0x6c);
2035 SETIREG(SISCR
, 0x0d, 0x00); /* adjust frame */
2036 SETIREG(SISCR
, 0x0c, 0x00);
2037 SETIREG(SISSR
, 0x0d, 0x00);
2038 SETIREGAND(SISSR
, 0x37, 0xfe);
2040 SETIREG(SISCR
, 0x32, 0x20);
2041 SETIREGAND(SISSR
, 0x01, 0xdf); /* enable display */
2042 SETIREG(SISCR
, 0x63, (cr63
& 0xbf));
2043 SETIREG(SISSR
, 0x31, (sr31
& 0xfb));
2046 SETIREG(SISSR
, 0x20, 0xa1); /* enable engines */
2047 SETIREGOR(SISSR
, 0x1e, 0x5a);
2049 SETIREG(SISSR
, 0x26, 0x01); /* disable cmdqueue */
2050 SETIREG(SISSR
, 0x27, 0x1f);
2051 SETIREG(SISSR
, 0x26, 0x00);
2054 SETIREG(SISCR
, 0x34, 0x44); /* we just set std mode #44 */
2060 sisusb_init_gfxcore(struct sisusb_usb_data
*sisusb
)
2062 int ret
= 0, i
, j
, bw
, chab
, iret
, retry
= 3;
2065 static const char mclktable
[] = {
2066 0x3b, 0x22, 0x01, 143,
2067 0x3b, 0x22, 0x01, 143,
2068 0x3b, 0x22, 0x01, 143,
2069 0x3b, 0x22, 0x01, 143
2071 static const char eclktable
[] = {
2072 0x3b, 0x22, 0x01, 143,
2073 0x3b, 0x22, 0x01, 143,
2074 0x3b, 0x22, 0x01, 143,
2075 0x3b, 0x22, 0x01, 143
2077 static const char ramtypetable1
[] = {
2078 0x00, 0x04, 0x60, 0x60,
2079 0x0f, 0x0f, 0x1f, 0x1f,
2080 0xba, 0xba, 0xba, 0xba,
2081 0xa9, 0xa9, 0xac, 0xac,
2082 0xa0, 0xa0, 0xa0, 0xa8,
2083 0x00, 0x00, 0x02, 0x02,
2084 0x30, 0x30, 0x40, 0x40
2086 static const char ramtypetable2
[] = {
2087 0x77, 0x77, 0x44, 0x44,
2088 0x77, 0x77, 0x44, 0x44,
2089 0x00, 0x00, 0x00, 0x00,
2090 0x5b, 0x5b, 0xab, 0xab,
2091 0x00, 0x00, 0xf0, 0xf8
2097 ret
= GETREG(SISVGAEN
, &tmp8
);
2098 ret
|= SETREG(SISVGAEN
, (tmp8
| 0x01));
2100 /* Enable GPU access to VRAM */
2101 ret
|= GETREG(SISMISCR
, &tmp8
);
2102 ret
|= SETREG(SISMISCW
, (tmp8
| 0x01));
2106 /* Reset registers */
2107 ret
|= SETIREGAND(SISCR
, 0x5b, 0xdf);
2108 ret
|= SETIREG(SISSR
, 0x05, 0x86);
2109 ret
|= SETIREGOR(SISSR
, 0x20, 0x01);
2111 ret
|= SETREG(SISMISCW
, 0x67);
2113 for (i
= 0x06; i
<= 0x1f; i
++) {
2114 ret
|= SETIREG(SISSR
, i
, 0x00);
2116 for (i
= 0x21; i
<= 0x27; i
++) {
2117 ret
|= SETIREG(SISSR
, i
, 0x00);
2119 for (i
= 0x31; i
<= 0x3d; i
++) {
2120 ret
|= SETIREG(SISSR
, i
, 0x00);
2122 for (i
= 0x12; i
<= 0x1b; i
++) {
2123 ret
|= SETIREG(SISSR
, i
, 0x00);
2125 for (i
= 0x79; i
<= 0x7c; i
++) {
2126 ret
|= SETIREG(SISCR
, i
, 0x00);
2131 ret
|= SETIREG(SISCR
, 0x63, 0x80);
2133 ret
|= GETIREG(SISSR
, 0x3a, &ramtype
);
2136 ret
|= SETIREG(SISSR
, 0x28, mclktable
[ramtype
* 4]);
2137 ret
|= SETIREG(SISSR
, 0x29, mclktable
[(ramtype
* 4) + 1]);
2138 ret
|= SETIREG(SISSR
, 0x2a, mclktable
[(ramtype
* 4) + 2]);
2140 ret
|= SETIREG(SISSR
, 0x2e, eclktable
[ramtype
* 4]);
2141 ret
|= SETIREG(SISSR
, 0x2f, eclktable
[(ramtype
* 4) + 1]);
2142 ret
|= SETIREG(SISSR
, 0x30, eclktable
[(ramtype
* 4) + 2]);
2144 ret
|= SETIREG(SISSR
, 0x07, 0x18);
2145 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2149 for (i
= 0x15, j
= 0; i
<= 0x1b; i
++, j
++) {
2150 ret
|= SETIREG(SISSR
, i
, ramtypetable1
[(j
*4) + ramtype
]);
2152 for (i
= 0x40, j
= 0; i
<= 0x44; i
++, j
++) {
2153 ret
|= SETIREG(SISCR
, i
, ramtypetable2
[(j
*4) + ramtype
]);
2156 ret
|= SETIREG(SISCR
, 0x49, 0xaa);
2158 ret
|= SETIREG(SISSR
, 0x1f, 0x00);
2159 ret
|= SETIREG(SISSR
, 0x20, 0xa0);
2160 ret
|= SETIREG(SISSR
, 0x23, 0xf6);
2161 ret
|= SETIREG(SISSR
, 0x24, 0x0d);
2162 ret
|= SETIREG(SISSR
, 0x25, 0x33);
2164 ret
|= SETIREG(SISSR
, 0x11, 0x0f);
2166 ret
|= SETIREGOR(SISPART1
, 0x2f, 0x01);
2168 ret
|= SETIREGAND(SISCAP
, 0x3f, 0xef);
2172 ret
|= SETIREG(SISPART1
, 0x00, 0x00);
2174 ret
|= GETIREG(SISSR
, 0x13, &tmp8
);
2177 ret
|= SETIREG(SISPART1
, 0x02, 0x00);
2178 ret
|= SETIREG(SISPART1
, 0x2e, 0x08);
2180 ret
|= sisusb_read_pci_config(sisusb
, 0x50, &tmp32
);
2181 tmp32
&= 0x00f00000;
2182 tmp8
= (tmp32
== 0x100000) ? 0x33 : 0x03;
2183 ret
|= SETIREG(SISSR
, 0x25, tmp8
);
2184 tmp8
= (tmp32
== 0x100000) ? 0xaa : 0x88;
2185 ret
|= SETIREG(SISCR
, 0x49, tmp8
);
2187 ret
|= SETIREG(SISSR
, 0x27, 0x1f);
2188 ret
|= SETIREG(SISSR
, 0x31, 0x00);
2189 ret
|= SETIREG(SISSR
, 0x32, 0x11);
2190 ret
|= SETIREG(SISSR
, 0x33, 0x00);
2194 ret
|= SETIREG(SISCR
, 0x83, 0x00);
2196 ret
|= sisusb_set_default_mode(sisusb
, 0);
2198 ret
|= SETIREGAND(SISSR
, 0x21, 0xdf);
2199 ret
|= SETIREGOR(SISSR
, 0x01, 0x20);
2200 ret
|= SETIREGOR(SISSR
, 0x16, 0x0f);
2202 ret
|= sisusb_triggersr16(sisusb
, ramtype
);
2204 /* Disable refresh */
2205 ret
|= SETIREGAND(SISSR
, 0x17, 0xf8);
2206 ret
|= SETIREGOR(SISSR
, 0x19, 0x03);
2208 ret
|= sisusb_getbuswidth(sisusb
, &bw
, &chab
);
2209 ret
|= sisusb_verify_mclk(sisusb
);
2212 ret
|= sisusb_get_sdram_size(sisusb
, &iret
, bw
, chab
);
2214 printk(KERN_ERR
"sisusbvga[%d]: RAM size "
2215 "detection failed, "
2216 "assuming 8MB video RAM\n",
2218 ret
|= SETIREG(SISSR
,0x14,0x31);
2222 printk(KERN_ERR
"sisusbvga[%d]: DDR RAM device found, "
2223 "assuming 8MB video RAM\n",
2225 ret
|= SETIREG(SISSR
,0x14,0x31);
2229 /* Enable refresh */
2230 ret
|= SETIREG(SISSR
, 0x16, ramtypetable1
[4 + ramtype
]);
2231 ret
|= SETIREG(SISSR
, 0x17, ramtypetable1
[8 + ramtype
]);
2232 ret
|= SETIREG(SISSR
, 0x19, ramtypetable1
[16 + ramtype
]);
2234 ret
|= SETIREGOR(SISSR
, 0x21, 0x20);
2236 ret
|= SETIREG(SISSR
, 0x22, 0xfb);
2237 ret
|= SETIREG(SISSR
, 0x21, 0xa5);
2257 sisusb_get_ramconfig(struct sisusb_usb_data
*sisusb
)
2259 u8 tmp8
, tmp82
, ramtype
;
2261 char *ramtypetext1
= NULL
;
2262 const char *ramtypetext2
[] = { "SDR SDRAM", "SDR SGRAM",
2263 "DDR SDRAM", "DDR SGRAM" };
2264 static const int busSDR
[4] = {64, 64, 128, 128};
2265 static const int busDDR
[4] = {32, 32, 64, 64};
2266 static const int busDDRA
[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2268 sisusb_getidxreg(sisusb
, SISSR
, 0x14, &tmp8
);
2269 sisusb_getidxreg(sisusb
, SISSR
, 0x15, &tmp82
);
2270 sisusb_getidxreg(sisusb
, SISSR
, 0x3a, &ramtype
);
2271 sisusb
->vramsize
= (1 << ((tmp8
& 0xf0) >> 4)) * 1024 * 1024;
2273 switch ((tmp8
>> 2) & 0x03) {
2274 case 0: ramtypetext1
= "1 ch/1 r";
2278 bw
= busSDR
[(tmp8
& 0x03)];
2281 case 1: ramtypetext1
= "1 ch/2 r";
2282 sisusb
->vramsize
<<= 1;
2283 bw
= busSDR
[(tmp8
& 0x03)];
2285 case 2: ramtypetext1
= "asymmeric";
2286 sisusb
->vramsize
+= sisusb
->vramsize
/2;
2287 bw
= busDDRA
[(tmp8
& 0x03)];
2289 case 3: ramtypetext1
= "2 channel";
2290 sisusb
->vramsize
<<= 1;
2291 bw
= busDDR
[(tmp8
& 0x03)];
2295 printk(KERN_INFO
"sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2296 sisusb
->minor
, (sisusb
->vramsize
>> 20), ramtypetext1
,
2297 ramtypetext2
[ramtype
], bw
);
2301 sisusb_do_init_gfxdevice(struct sisusb_usb_data
*sisusb
)
2303 struct sisusb_packet packet
;
2308 packet
.header
= 0x001f;
2309 packet
.address
= 0x00000324;
2310 packet
.data
= 0x00000004;
2311 ret
= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2313 packet
.header
= 0x001f;
2314 packet
.address
= 0x00000364;
2315 packet
.data
= 0x00000004;
2316 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2318 packet
.header
= 0x001f;
2319 packet
.address
= 0x00000384;
2320 packet
.data
= 0x00000004;
2321 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2323 packet
.header
= 0x001f;
2324 packet
.address
= 0x00000100;
2325 packet
.data
= 0x00000700;
2326 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2328 packet
.header
= 0x000f;
2329 packet
.address
= 0x00000004;
2330 ret
|= sisusb_send_bridge_packet(sisusb
, 6, &packet
, 0);
2331 packet
.data
|= 0x17;
2332 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2334 /* Init BAR 0 (VRAM) */
2335 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2336 ret
|= sisusb_write_pci_config(sisusb
, 0x10, 0xfffffff0);
2337 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2339 tmp32
|= SISUSB_PCI_MEMBASE
;
2340 ret
|= sisusb_write_pci_config(sisusb
, 0x10, tmp32
);
2342 /* Init BAR 1 (MMIO) */
2343 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2344 ret
|= sisusb_write_pci_config(sisusb
, 0x14, 0xfffffff0);
2345 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2347 tmp32
|= SISUSB_PCI_MMIOBASE
;
2348 ret
|= sisusb_write_pci_config(sisusb
, 0x14, tmp32
);
2350 /* Init BAR 2 (i/o ports) */
2351 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2352 ret
|= sisusb_write_pci_config(sisusb
, 0x18, 0xfffffff0);
2353 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2355 tmp32
|= SISUSB_PCI_IOPORTBASE
;
2356 ret
|= sisusb_write_pci_config(sisusb
, 0x18, tmp32
);
2358 /* Enable memory and i/o access */
2359 ret
|= sisusb_read_pci_config(sisusb
, 0x04, &tmp32
);
2361 ret
|= sisusb_write_pci_config(sisusb
, 0x04, tmp32
);
2364 /* Some further magic */
2365 packet
.header
= 0x001f;
2366 packet
.address
= 0x00000050;
2367 packet
.data
= 0x000000ff;
2368 ret
|= sisusb_send_bridge_packet(sisusb
, 10, &packet
, 0);
2374 /* Initialize the graphics device (return 0 on success)
2375 * This initializes the net2280 as well as the PCI registers
2376 * of the graphics board.
2380 sisusb_init_gfxdevice(struct sisusb_usb_data
*sisusb
, int initscreen
)
2382 int ret
= 0, test
= 0;
2385 if (sisusb
->devinit
== 1) {
2386 /* Read PCI BARs and see if they have been set up */
2387 ret
|= sisusb_read_pci_config(sisusb
, 0x10, &tmp32
);
2388 if (ret
) return ret
;
2389 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MEMBASE
) test
++;
2391 ret
|= sisusb_read_pci_config(sisusb
, 0x14, &tmp32
);
2392 if (ret
) return ret
;
2393 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_MMIOBASE
) test
++;
2395 ret
|= sisusb_read_pci_config(sisusb
, 0x18, &tmp32
);
2396 if (ret
) return ret
;
2397 if ((tmp32
& 0xfffffff0) == SISUSB_PCI_IOPORTBASE
) test
++;
2400 /* No? So reset the device */
2401 if ((sisusb
->devinit
== 0) || (test
!= 3)) {
2403 ret
|= sisusb_do_init_gfxdevice(sisusb
);
2406 sisusb
->devinit
= 1;
2410 if (sisusb
->devinit
) {
2411 /* Initialize the graphics core */
2412 if (sisusb_init_gfxcore(sisusb
) == 0) {
2413 sisusb
->gfxinit
= 1;
2414 sisusb_get_ramconfig(sisusb
);
2415 ret
|= sisusb_set_default_mode(sisusb
, 1);
2416 ret
|= sisusb_setup_screen(sisusb
, 1, initscreen
);
2424 #ifdef INCL_SISUSB_CON
2426 /* Set up default text mode:
2427 - Set text mode (0x03)
2428 - Upload default font
2429 - Upload user font (if available)
2433 sisusb_reset_text_mode(struct sisusb_usb_data
*sisusb
, int init
)
2435 int ret
= 0, slot
= sisusb
->font_slot
, i
;
2436 const struct font_desc
*myfont
;
2440 static const char bootstring
[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2441 static const char bootlogo
[] = "(o_ //\\ V_/_";
2443 /* sisusb->lock is down */
2445 if (!sisusb
->SiS_Pr
)
2448 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
2449 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
2452 SiSUSBSetMode(sisusb
->SiS_Pr
, 0x03);
2454 if (!(myfont
= find_font("VGA8x16")))
2457 if (!(tempbuf
= vmalloc(8192)))
2460 for (i
= 0; i
< 256; i
++)
2461 memcpy(tempbuf
+ (i
* 32), myfont
->data
+ (i
* 16), 16);
2463 /* Upload default font */
2464 ret
= sisusbcon_do_font_op(sisusb
, 1, 0, tempbuf
, 8192, 0, 1, NULL
, 16, 0);
2468 /* Upload user font (and reset current slot) */
2469 if (sisusb
->font_backup
) {
2470 ret
|= sisusbcon_do_font_op(sisusb
, 1, 2, sisusb
->font_backup
,
2471 8192, sisusb
->font_backup_512
, 1, NULL
,
2472 sisusb
->font_backup_height
, 0);
2474 sisusbcon_do_font_op(sisusb
, 1, 0, NULL
, 0, 0, 1,
2478 if (init
&& !sisusb
->scrbuf
) {
2480 if ((tempbuf
= vmalloc(8192))) {
2483 tempbufb
= (u16
*)tempbuf
;
2485 *(tempbufb
++) = 0x0720;
2488 tempbufb
= (u16
*)tempbuf
;
2489 while (bootlogo
[i
]) {
2490 *(tempbufb
++) = 0x0700 | bootlogo
[i
++];
2496 tempbufb
= (u16
*)tempbuf
+ 6;
2497 while (bootstring
[i
])
2498 *(tempbufb
++) = 0x0700 | bootstring
[i
++];
2500 ret
|= sisusb_copy_memory(sisusb
, tempbuf
,
2501 sisusb
->vrambase
, 8192, &written
);
2507 } else if (sisusb
->scrbuf
) {
2509 ret
|= sisusb_copy_memory(sisusb
, (char *)sisusb
->scrbuf
,
2510 sisusb
->vrambase
, sisusb
->scrbuf_size
, &written
);
2514 if (sisusb
->sisusb_cursor_size_from
>= 0 &&
2515 sisusb
->sisusb_cursor_size_to
>= 0) {
2516 sisusb_setidxreg(sisusb
, SISCR
, 0x0a,
2517 sisusb
->sisusb_cursor_size_from
);
2518 sisusb_setidxregandor(sisusb
, SISCR
, 0x0b, 0xe0,
2519 sisusb
->sisusb_cursor_size_to
);
2521 sisusb_setidxreg(sisusb
, SISCR
, 0x0a, 0x2d);
2522 sisusb_setidxreg(sisusb
, SISCR
, 0x0b, 0x0e);
2523 sisusb
->sisusb_cursor_size_to
= -1;
2526 slot
= sisusb
->sisusb_cursor_loc
;
2527 if(slot
< 0) slot
= 0;
2529 sisusb
->sisusb_cursor_loc
= -1;
2530 sisusb
->bad_cursor_pos
= 1;
2532 sisusb_set_cursor(sisusb
, slot
);
2534 sisusb_setidxreg(sisusb
, SISCR
, 0x0c, (sisusb
->cur_start_addr
>> 8));
2535 sisusb_setidxreg(sisusb
, SISCR
, 0x0d, (sisusb
->cur_start_addr
& 0xff));
2537 sisusb
->textmodedestroyed
= 0;
2539 /* sisusb->lock is down */
2549 sisusb_open(struct inode
*inode
, struct file
*file
)
2551 struct sisusb_usb_data
*sisusb
;
2552 struct usb_interface
*interface
;
2553 int subminor
= iminor(inode
);
2555 down(&disconnect_sem
);
2557 if (!(interface
= usb_find_interface(&sisusb_driver
, subminor
))) {
2558 printk(KERN_ERR
"sisusb[%d]: Failed to find interface\n",
2560 up(&disconnect_sem
);
2564 if (!(sisusb
= usb_get_intfdata(interface
))) {
2565 up(&disconnect_sem
);
2569 down(&sisusb
->lock
);
2571 if (!sisusb
->present
|| !sisusb
->ready
) {
2573 up(&disconnect_sem
);
2577 if (sisusb
->isopen
) {
2579 up(&disconnect_sem
);
2583 if (!sisusb
->devinit
) {
2584 if (sisusb
->sisusb_dev
->speed
== USB_SPEED_HIGH
) {
2585 if (sisusb_init_gfxdevice(sisusb
, 0)) {
2587 up(&disconnect_sem
);
2589 "sisusbvga[%d]: Failed to initialize "
2596 up(&disconnect_sem
);
2598 "sisusbvga[%d]: Device not attached to "
2605 /* Increment usage count for our sisusb */
2606 kref_get(&sisusb
->kref
);
2610 file
->private_data
= sisusb
;
2614 up(&disconnect_sem
);
2620 sisusb_delete(struct kref
*kref
)
2622 struct sisusb_usb_data
*sisusb
= to_sisusb_dev(kref
);
2627 if (sisusb
->sisusb_dev
)
2628 usb_put_dev(sisusb
->sisusb_dev
);
2630 sisusb
->sisusb_dev
= NULL
;
2631 sisusb_free_buffers(sisusb
);
2632 sisusb_free_urbs(sisusb
);
2633 #ifdef INCL_SISUSB_CON
2634 kfree(sisusb
->SiS_Pr
);
2640 sisusb_release(struct inode
*inode
, struct file
*file
)
2642 struct sisusb_usb_data
*sisusb
;
2645 down(&disconnect_sem
);
2647 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
)) {
2648 up(&disconnect_sem
);
2652 down(&sisusb
->lock
);
2654 if (sisusb
->present
) {
2655 /* Wait for all URBs to finish if device still present */
2656 if (!sisusb_wait_all_out_complete(sisusb
))
2657 sisusb_kill_all_busy(sisusb
);
2660 myminor
= sisusb
->minor
;
2663 file
->private_data
= NULL
;
2667 /* decrement the usage count on our device */
2668 kref_put(&sisusb
->kref
, sisusb_delete
);
2670 up(&disconnect_sem
);
2676 sisusb_read(struct file
*file
, char __user
*buffer
, size_t count
, loff_t
*ppos
)
2678 struct sisusb_usb_data
*sisusb
;
2679 ssize_t bytes_read
= 0;
2685 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2688 down(&sisusb
->lock
);
2691 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2696 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2697 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2700 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2701 SISUSB_PCI_IOPORTBASE
;
2704 * Byte, word and long(32) can be read. As this
2705 * emulates inX instructions, the data returned is
2706 * in machine-endianness.
2711 if (sisusb_read_memio_byte(sisusb
,
2715 else if (put_user(buf8
, (u8 __user
*)buffer
))
2723 if (sisusb_read_memio_word(sisusb
,
2727 else if (put_user(buf16
, (u16 __user
*)buffer
))
2735 if (sisusb_read_memio_long(sisusb
,
2739 else if (put_user(buf32
, (u32 __user
*)buffer
))
2751 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2752 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2755 SISUSB_PCI_PSEUDO_MEMBASE
+
2759 * Remember: Data delivered is never endian-corrected
2761 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2762 NULL
, count
, buffer
, &bytes_read
);
2767 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2768 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2771 SISUSB_PCI_PSEUDO_MMIOBASE
+
2772 SISUSB_PCI_MMIOBASE
;
2775 * Remember: Data delivered is never endian-corrected
2777 errno
= sisusb_read_mem_bulk(sisusb
, address
,
2778 NULL
, count
, buffer
, &bytes_read
);
2783 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2784 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ 0x5c) {
2791 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2793 /* Read PCI config register
2794 * Return value delivered in machine endianness.
2796 if (sisusb_read_pci_config(sisusb
, address
, &buf32
))
2798 else if (put_user(buf32
, (u32 __user
*)buffer
))
2809 (*ppos
) += bytes_read
;
2813 return errno
? errno
: bytes_read
;
2817 sisusb_write(struct file
*file
, const char __user
*buffer
, size_t count
,
2820 struct sisusb_usb_data
*sisusb
;
2822 ssize_t bytes_written
= 0;
2827 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2830 down(&sisusb
->lock
);
2833 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2838 if ((*ppos
) >= SISUSB_PCI_PSEUDO_IOPORTBASE
&&
2839 (*ppos
) < SISUSB_PCI_PSEUDO_IOPORTBASE
+ 128) {
2842 SISUSB_PCI_PSEUDO_IOPORTBASE
+
2843 SISUSB_PCI_IOPORTBASE
;
2846 * Byte, word and long(32) can be written. As this
2847 * emulates outX instructions, the data is expected
2848 * in machine-endianness.
2853 if (get_user(buf8
, (u8 __user
*)buffer
))
2855 else if (sisusb_write_memio_byte(sisusb
,
2865 if (get_user(buf16
, (u16 __user
*)buffer
))
2867 else if (sisusb_write_memio_word(sisusb
,
2877 if (get_user(buf32
, (u32 __user
*)buffer
))
2879 else if (sisusb_write_memio_long(sisusb
,
2892 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MEMBASE
&&
2893 (*ppos
) < SISUSB_PCI_PSEUDO_MEMBASE
+ sisusb
->vramsize
) {
2896 SISUSB_PCI_PSEUDO_MEMBASE
+
2900 * Buffer is copied 1:1, therefore, on big-endian
2901 * machines, the data must be swapped by userland
2902 * in advance (if applicable; no swapping in 8bpp
2903 * mode or if YUV data is being transferred).
2905 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2906 count
, buffer
, 0, &bytes_written
);
2909 errno
= bytes_written
;
2911 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_MMIOBASE
&&
2912 (*ppos
) < SISUSB_PCI_PSEUDO_MMIOBASE
+ SISUSB_PCI_MMIOSIZE
) {
2915 SISUSB_PCI_PSEUDO_MMIOBASE
+
2916 SISUSB_PCI_MMIOBASE
;
2919 * Buffer is copied 1:1, therefore, on big-endian
2920 * machines, the data must be swapped by userland
2923 errno
= sisusb_write_mem_bulk(sisusb
, address
, NULL
,
2924 count
, buffer
, 0, &bytes_written
);
2927 errno
= bytes_written
;
2929 } else if ((*ppos
) >= SISUSB_PCI_PSEUDO_PCIBASE
&&
2930 (*ppos
) <= SISUSB_PCI_PSEUDO_PCIBASE
+ SISUSB_PCI_PCONFSIZE
) {
2937 address
= (*ppos
) - SISUSB_PCI_PSEUDO_PCIBASE
;
2939 /* Write PCI config register.
2940 * Given value expected in machine endianness.
2942 if (get_user(buf32
, (u32 __user
*)buffer
))
2944 else if (sisusb_write_pci_config(sisusb
, address
, buf32
))
2957 (*ppos
) += bytes_written
;
2961 return errno
? errno
: bytes_written
;
2965 sisusb_lseek(struct file
*file
, loff_t offset
, int orig
)
2967 struct sisusb_usb_data
*sisusb
;
2970 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
2973 down(&sisusb
->lock
);
2976 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
2983 file
->f_pos
= offset
;
2985 /* never negative, no force_successful_syscall needed */
2988 file
->f_pos
+= offset
;
2990 /* never negative, no force_successful_syscall needed */
2993 /* seeking relative to "end of file" is not supported */
3002 sisusb_handle_command(struct sisusb_usb_data
*sisusb
, struct sisusb_command
*y
,
3005 int retval
, port
, length
;
3008 /* All our commands require the device
3009 * to be initialized.
3011 if (!sisusb
->devinit
)
3015 SISUSB_PCI_PSEUDO_IOPORTBASE
+
3016 SISUSB_PCI_IOPORTBASE
;
3018 switch (y
->operation
) {
3020 retval
= sisusb_getidxreg(sisusb
, port
,
3021 y
->data0
, &y
->data1
);
3023 if (copy_to_user((void __user
*)arg
, y
,
3030 retval
= sisusb_setidxreg(sisusb
, port
,
3031 y
->data0
, y
->data1
);
3035 retval
= sisusb_setidxregor(sisusb
, port
,
3036 y
->data0
, y
->data1
);
3040 retval
= sisusb_setidxregand(sisusb
, port
,
3041 y
->data0
, y
->data1
);
3044 case SUCMD_SETANDOR
:
3045 retval
= sisusb_setidxregandor(sisusb
, port
,
3046 y
->data0
, y
->data1
, y
->data2
);
3050 retval
= sisusb_setidxregmask(sisusb
, port
,
3051 y
->data0
, y
->data1
, y
->data2
);
3055 /* Gfx core must be initialized */
3056 if (!sisusb
->gfxinit
)
3059 length
= (y
->data0
<< 16) | (y
->data1
<< 8) | y
->data2
;
3060 address
= y
->data3
-
3061 SISUSB_PCI_PSEUDO_MEMBASE
+
3063 retval
= sisusb_clear_vram(sisusb
, address
, length
);
3066 case SUCMD_HANDLETEXTMODE
:
3068 #ifdef INCL_SISUSB_CON
3069 /* Gfx core must be initialized, SiS_Pr must exist */
3070 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3075 retval
= sisusb_reset_text_mode(sisusb
, 0);
3078 sisusb
->textmodedestroyed
= 1;
3084 #ifdef INCL_SISUSB_CON
3086 /* Gfx core must be initialized, SiS_Pr must exist */
3087 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3092 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
3093 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
3095 if (SiSUSBSetMode(sisusb
->SiS_Pr
, y
->data3
))
3100 case SUCMD_SETVESAMODE
:
3101 /* Gfx core must be initialized, SiS_Pr must exist */
3102 if (!sisusb
->gfxinit
|| !sisusb
->SiS_Pr
)
3107 sisusb
->SiS_Pr
->IOAddress
= SISUSB_PCI_IOPORTBASE
+ 0x30;
3108 sisusb
->SiS_Pr
->sisusb
= (void *)sisusb
;
3110 if (SiSUSBSetVESAMode(sisusb
->SiS_Pr
, y
->data3
))
3127 sisusb_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
3130 struct sisusb_usb_data
*sisusb
;
3131 struct sisusb_info x
;
3132 struct sisusb_command y
;
3134 u32 __user
*argp
= (u32 __user
*)arg
;
3136 if (!(sisusb
= (struct sisusb_usb_data
*)file
->private_data
))
3139 down(&sisusb
->lock
);
3142 if (!sisusb
->present
|| !sisusb
->ready
|| !sisusb
->sisusb_dev
) {
3149 case SISUSB_GET_CONFIG_SIZE
:
3151 if (put_user(sizeof(x
), argp
))
3156 case SISUSB_GET_CONFIG
:
3158 x
.sisusb_id
= SISUSB_ID
;
3159 x
.sisusb_version
= SISUSB_VERSION
;
3160 x
.sisusb_revision
= SISUSB_REVISION
;
3161 x
.sisusb_patchlevel
= SISUSB_PATCHLEVEL
;
3162 x
.sisusb_gfxinit
= sisusb
->gfxinit
;
3163 x
.sisusb_vrambase
= SISUSB_PCI_PSEUDO_MEMBASE
;
3164 x
.sisusb_mmiobase
= SISUSB_PCI_PSEUDO_MMIOBASE
;
3165 x
.sisusb_iobase
= SISUSB_PCI_PSEUDO_IOPORTBASE
;
3166 x
.sisusb_pcibase
= SISUSB_PCI_PSEUDO_PCIBASE
;
3167 x
.sisusb_vramsize
= sisusb
->vramsize
;
3168 x
.sisusb_minor
= sisusb
->minor
;
3169 x
.sisusb_fbdevactive
= 0;
3170 #ifdef INCL_SISUSB_CON
3171 x
.sisusb_conactive
= sisusb
->haveconsole
? 1 : 0;
3173 x
.sisusb_conactive
= 0;
3176 if (copy_to_user((void __user
*)arg
, &x
, sizeof(x
)))
3181 case SISUSB_COMMAND
:
3183 if (copy_from_user(&y
, (void __user
*)arg
, sizeof(y
)))
3186 retval
= sisusb_handle_command(sisusb
, &y
, arg
);
3200 #ifdef SISUSB_NEW_CONFIG_COMPAT
3202 sisusb_compat_ioctl(struct file
*f
, unsigned int cmd
, unsigned long arg
)
3207 case SISUSB_GET_CONFIG_SIZE
:
3208 case SISUSB_GET_CONFIG
:
3209 case SISUSB_COMMAND
:
3211 retval
= sisusb_ioctl(f
->f_dentry
->d_inode
, f
, cmd
, arg
);
3216 return -ENOIOCTLCMD
;
3221 static struct file_operations usb_sisusb_fops
= {
3222 .owner
= THIS_MODULE
,
3223 .open
= sisusb_open
,
3224 .release
= sisusb_release
,
3225 .read
= sisusb_read
,
3226 .write
= sisusb_write
,
3227 .llseek
= sisusb_lseek
,
3228 #ifdef SISUSB_NEW_CONFIG_COMPAT
3229 .compat_ioctl
= sisusb_compat_ioctl
,
3231 .ioctl
= sisusb_ioctl
3234 static struct usb_class_driver usb_sisusb_class
= {
3235 .name
= "sisusbvga%d",
3236 .fops
= &usb_sisusb_fops
,
3237 .minor_base
= SISUSB_MINOR
3240 static int sisusb_probe(struct usb_interface
*intf
,
3241 const struct usb_device_id
*id
)
3243 struct usb_device
*dev
= interface_to_usbdev(intf
);
3244 struct sisusb_usb_data
*sisusb
;
3246 const char *memfail
=
3248 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3250 printk(KERN_INFO
"sisusb: USB2VGA dongle found at address %d\n",
3253 /* Allocate memory for our private */
3254 if (!(sisusb
= kzalloc(sizeof(*sisusb
), GFP_KERNEL
))) {
3256 "sisusb: Failed to allocate memory for private data\n");
3259 kref_init(&sisusb
->kref
);
3261 init_MUTEX(&(sisusb
->lock
));
3263 /* Register device */
3264 if ((retval
= usb_register_dev(intf
, &usb_sisusb_class
))) {
3266 "sisusb: Failed to get a minor for device %d\n",
3272 sisusb
->sisusb_dev
= dev
;
3273 sisusb
->minor
= intf
->minor
;
3274 sisusb
->vrambase
= SISUSB_PCI_MEMBASE
;
3275 sisusb
->mmiobase
= SISUSB_PCI_MMIOBASE
;
3276 sisusb
->mmiosize
= SISUSB_PCI_MMIOSIZE
;
3277 sisusb
->ioportbase
= SISUSB_PCI_IOPORTBASE
;
3278 /* Everything else is zero */
3280 /* Allocate buffers */
3281 sisusb
->ibufsize
= SISUSB_IBUF_SIZE
;
3282 if (!(sisusb
->ibuf
= usb_buffer_alloc(dev
, SISUSB_IBUF_SIZE
,
3283 GFP_KERNEL
, &sisusb
->transfer_dma_in
))) {
3284 printk(memfail
, "input", sisusb
->minor
);
3289 sisusb
->numobufs
= 0;
3290 sisusb
->obufsize
= SISUSB_OBUF_SIZE
;
3291 for (i
= 0; i
< NUMOBUFS
; i
++) {
3292 if (!(sisusb
->obuf
[i
] = usb_buffer_alloc(dev
, SISUSB_OBUF_SIZE
,
3294 &sisusb
->transfer_dma_out
[i
]))) {
3296 printk(memfail
, "output", sisusb
->minor
);
3307 if (!(sisusb
->sisurbin
= usb_alloc_urb(0, GFP_KERNEL
))) {
3309 "sisusbvga[%d]: Failed to allocate URBs\n",
3314 sisusb
->completein
= 1;
3316 for (i
= 0; i
< sisusb
->numobufs
; i
++) {
3317 if (!(sisusb
->sisurbout
[i
] = usb_alloc_urb(0, GFP_KERNEL
))) {
3319 "sisusbvga[%d]: Failed to allocate URBs\n",
3324 sisusb
->urbout_context
[i
].sisusb
= (void *)sisusb
;
3325 sisusb
->urbout_context
[i
].urbindex
= i
;
3326 sisusb
->urbstatus
[i
] = 0;
3329 printk(KERN_INFO
"sisusbvga[%d]: Allocated %d output buffers\n",
3330 sisusb
->minor
, sisusb
->numobufs
);
3332 #ifdef INCL_SISUSB_CON
3333 /* Allocate our SiS_Pr */
3334 if (!(sisusb
->SiS_Pr
= kmalloc(sizeof(struct SiS_Private
), GFP_KERNEL
))) {
3336 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3341 /* Do remaining init stuff */
3343 init_waitqueue_head(&sisusb
->wait_q
);
3345 usb_set_intfdata(intf
, sisusb
);
3347 usb_get_dev(sisusb
->sisusb_dev
);
3349 sisusb
->present
= 1;
3351 #ifdef SISUSB_OLD_CONFIG_COMPAT
3354 /* Our ioctls are all "32/64bit compatible" */
3355 ret
= register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE
, NULL
);
3356 ret
|= register_ioctl32_conversion(SISUSB_GET_CONFIG
, NULL
);
3357 ret
|= register_ioctl32_conversion(SISUSB_COMMAND
, NULL
);
3360 "sisusbvga[%d]: Error registering ioctl32 "
3364 sisusb
->ioctl32registered
= 1;
3368 if (dev
->speed
== USB_SPEED_HIGH
) {
3370 #ifdef INCL_SISUSB_CON
3371 if (sisusb_first_vc
> 0 &&
3372 sisusb_last_vc
> 0 &&
3373 sisusb_first_vc
<= sisusb_last_vc
&&
3374 sisusb_last_vc
<= MAX_NR_CONSOLES
)
3377 if (sisusb_init_gfxdevice(sisusb
, initscreen
))
3379 "sisusbvga[%d]: Failed to early "
3380 "initialize device\n",
3385 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3391 #ifdef SISUSBENDIANTEST
3392 printk(KERN_DEBUG
"sisusb: *** RWTEST ***\n");
3393 sisusb_testreadwrite(sisusb
);
3394 printk(KERN_DEBUG
"sisusb: *** RWTEST END ***\n");
3397 #ifdef INCL_SISUSB_CON
3398 sisusb_console_init(sisusb
, sisusb_first_vc
, sisusb_last_vc
);
3404 sisusb_free_urbs(sisusb
);
3406 sisusb_free_buffers(sisusb
);
3408 usb_deregister_dev(intf
, &usb_sisusb_class
);
3414 static void sisusb_disconnect(struct usb_interface
*intf
)
3416 struct sisusb_usb_data
*sisusb
;
3419 /* This should *not* happen */
3420 if (!(sisusb
= usb_get_intfdata(intf
)))
3423 #ifdef INCL_SISUSB_CON
3424 sisusb_console_exit(sisusb
);
3427 /* The above code doesn't need the disconnect
3428 * semaphore to be down; its meaning is to
3429 * protect all other routines from the disconnect
3430 * case, not the other way round.
3432 down(&disconnect_sem
);
3434 down(&sisusb
->lock
);
3436 /* Wait for all URBs to complete and kill them in case (MUST do) */
3437 if (!sisusb_wait_all_out_complete(sisusb
))
3438 sisusb_kill_all_busy(sisusb
);
3440 minor
= sisusb
->minor
;
3442 usb_set_intfdata(intf
, NULL
);
3444 usb_deregister_dev(intf
, &usb_sisusb_class
);
3446 #ifdef SISUSB_OLD_CONFIG_COMPAT
3447 if (sisusb
->ioctl32registered
) {
3449 sisusb
->ioctl32registered
= 0;
3450 ret
= unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE
);
3451 ret
|= unregister_ioctl32_conversion(SISUSB_GET_CONFIG
);
3452 ret
|= unregister_ioctl32_conversion(SISUSB_COMMAND
);
3455 "sisusbvga[%d]: Error unregistering "
3456 "ioctl32 translations\n",
3462 sisusb
->present
= 0;
3467 /* decrement our usage count */
3468 kref_put(&sisusb
->kref
, sisusb_delete
);
3470 up(&disconnect_sem
);
3472 printk(KERN_INFO
"sisusbvga[%d]: Disconnected\n", minor
);
3475 static struct usb_device_id sisusb_table
[] = {
3476 { USB_DEVICE(0x0711, 0x0900) },
3477 { USB_DEVICE(0x182d, 0x021c) },
3478 { USB_DEVICE(0x182d, 0x0269) },
3482 MODULE_DEVICE_TABLE (usb
, sisusb_table
);
3484 static struct usb_driver sisusb_driver
= {
3486 .probe
= sisusb_probe
,
3487 .disconnect
= sisusb_disconnect
,
3488 .id_table
= sisusb_table
,
3491 static int __init
usb_sisusb_init(void)
3495 #ifdef INCL_SISUSB_CON
3496 sisusb_init_concode();
3499 if (!(retval
= usb_register(&sisusb_driver
))) {
3501 printk(KERN_INFO
"sisusb: Driver version %d.%d.%d\n",
3502 SISUSB_VERSION
, SISUSB_REVISION
, SISUSB_PATCHLEVEL
);
3504 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3511 static void __exit
usb_sisusb_exit(void)
3513 usb_deregister(&sisusb_driver
);
3516 module_init(usb_sisusb_init
);
3517 module_exit(usb_sisusb_exit
);
3519 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3520 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3521 MODULE_LICENSE("GPL");