[PATCH] USB: remove .owner field from struct usb_driver
[linux-2.6/verdex.git] / drivers / usb / misc / sisusbvga / sisusb.c
blob44350d49ad0a9d969ef21e499c8103d023689893
1 /*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
4 * Main part
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
8 * If distributed as part of the Linux kernel, this code is licensed under the
9 * terms of the GPL v2.
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
15 * * are met:
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.
23 * *
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>
54 #include "sisusb.h"
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
58 #endif
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)");
101 #endif
103 static struct usb_driver sisusb_driver;
105 DECLARE_MUTEX(disconnect_sem);
107 static void
108 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
110 int i;
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;
119 if (sisusb->ibuf) {
120 usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
121 sisusb->ibuf, sisusb->transfer_dma_in);
122 sisusb->ibuf = NULL;
126 static void
127 sisusb_free_urbs(struct sisusb_usb_data *sisusb)
129 int i;
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 */
141 /* 1. out-bulks */
143 /* out-urb management */
145 /* Return 1 if all free, 0 otherwise */
146 static int
147 sisusb_all_free(struct sisusb_usb_data *sisusb)
149 int i;
151 for (i = 0; i < sisusb->numobufs; i++) {
153 if (sisusb->urbstatus[i] & SU_URB_BUSY)
154 return 0;
158 return 1;
161 /* Kill all busy URBs */
162 static void
163 sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
165 int i;
167 if (sisusb_all_free(sisusb))
168 return;
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) */
179 static int
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)),
186 timeout);
188 return i;
191 static int
192 sisusb_outurb_available(struct sisusb_usb_data *sisusb)
194 int i;
196 for (i = 0; i < sisusb->numobufs; i++) {
198 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
199 return i;
203 return -1;
206 static int
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),
213 timeout);
215 return i;
218 static int
219 sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
221 int i;
223 i = sisusb_outurb_available(sisusb);
225 if (i >= 0)
226 sisusb->urbstatus[i] |= SU_URB_ALLOC;
228 return i;
231 static void
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 */
240 static void
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;
246 if (!context)
247 return;
249 sisusb = context->sisusb;
251 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
252 return;
254 #ifndef SISUSB_DONTSYNC
255 if (context->actual_length)
256 *(context->actual_length) += urb->actual_length;
257 #endif
259 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
260 wake_up(&sisusb->wait_q);
263 static int
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;
271 /* Set up URB */
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;
283 /* Set up context */
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;
290 /* Submit URB */
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)),
297 timeout);
298 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
299 /* URB timed out... kill it and report error */
300 usb_kill_urb(urb);
301 retval = -ETIMEDOUT;
302 } else {
303 /* Otherwise, report urb status */
304 retval = urb->status;
305 byteswritten = urb->actual_length;
309 if (actual_length)
310 *actual_length = byteswritten;
312 return retval;
315 /* 2. in-bulks */
317 /* completion callback */
319 static void
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)
325 return;
327 sisusb->completein = 1;
328 wake_up(&sisusb->wait_q);
331 static int
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);
351 if (retval == 0) {
352 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
353 if (!sisusb->completein) {
354 /* URB timed out... kill it and report error */
355 usb_kill_urb(urb);
356 retval = -ETIMEDOUT;
357 } else {
358 /* URB completed within timout */
359 retval = urb->status;
360 readbytes = urb->actual_length;
364 if (actual_length)
365 *actual_length = readbytes;
367 return retval;
371 /* Level 1: */
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;
394 unsigned int pipe;
395 char *buffer;
397 (*bytes_written) = 0;
399 /* Sanity check */
400 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
401 return -ENODEV;
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)
412 index = -1;
413 else if (len > sisusb->obufsize)
414 async = 0;
416 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
418 do {
419 passsize = thispass = (sisusb->obufsize < count) ?
420 sisusb->obufsize : count;
422 if (index < 0)
423 index = sisusb_get_free_outbuf(sisusb);
425 if (index < 0)
426 return -EIO;
428 buffer = sisusb->obuf[index];
430 if (fromuser) {
432 if (copy_from_user(buffer, userbuffer, passsize))
433 return -EFAULT;
435 userbuffer += passsize;
437 } else if (fromkern) {
439 memcpy(buffer, kernbuffer, passsize);
440 kernbuffer += passsize;
444 retry = 5;
445 while (thispass) {
447 if (!sisusb->sisusb_dev)
448 return -ENODEV;
450 result = sisusb_bulkout_msg(sisusb,
451 index,
452 pipe,
453 buffer,
454 thispass,
455 &transferred_len,
456 async ? 0 : 5 * HZ,
457 tflags,
458 sisusb->transfer_dma_out[index]);
460 if (result == -ETIMEDOUT) {
462 /* Will not happen if async */
463 if (!retry--)
464 return -ETIME;
466 continue;
468 } else if ((result == 0) && !async && transferred_len) {
470 thispass -= transferred_len;
471 if (thispass) {
472 if (sisusb->transfer_dma_out) {
473 /* If DMA, copy remaining
474 * to beginning of buffer
476 memcpy(buffer,
477 buffer + transferred_len,
478 thispass);
479 } else {
480 /* If not DMA, simply increase
481 * the pointer
483 buffer += transferred_len;
487 } else
488 break;
491 if (result)
492 return result;
494 (*bytes_written) += passsize;
495 count -= passsize;
497 /* Force new allocation in next iteration */
498 if (fromuser || fromkern)
499 index = -1;
501 } while (count > 0);
503 if (async) {
504 #ifdef SISUSB_DONTSYNC
505 (*bytes_written) = len;
506 /* Some URBs/buffers might be busy */
507 #else
508 sisusb_wait_all_out_complete(sisusb);
509 (*bytes_written) = transferred_len;
510 /* All URBs and all buffers are available */
511 #endif
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,
528 unsigned int tflags)
530 int result = 0, retry, count = len;
531 int bufsize, thispass, transferred_len;
532 unsigned int pipe;
533 char *buffer;
535 (*bytes_read) = 0;
537 /* Sanity check */
538 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
539 return -ENODEV;
541 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
542 buffer = sisusb->ibuf;
543 bufsize = sisusb->ibufsize;
545 retry = 5;
547 #ifdef SISUSB_DONTSYNC
548 if (!(sisusb_wait_all_out_complete(sisusb)))
549 return -EIO;
550 #endif
552 while (count > 0) {
554 if (!sisusb->sisusb_dev)
555 return -ENODEV;
557 thispass = (bufsize < count) ? bufsize : count;
559 result = sisusb_bulkin_msg(sisusb,
560 pipe,
561 buffer,
562 thispass,
563 &transferred_len,
564 5 * HZ,
565 tflags,
566 sisusb->transfer_dma_in);
568 if (transferred_len)
569 thispass = transferred_len;
571 else if (result == -ETIMEDOUT) {
573 if (!retry--)
574 return -ETIME;
576 continue;
578 } else
579 return -EIO;
582 if (thispass) {
584 (*bytes_read) += thispass;
585 count -= thispass;
587 if (userbuffer) {
589 if (copy_to_user(userbuffer, buffer, thispass))
590 return -EFAULT;
592 userbuffer += thispass;
594 } else {
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)
611 int ret;
612 ssize_t bytes_transferred = 0;
613 __le32 tmp;
615 if (len == 6)
616 packet->data = 0;
618 #ifdef SISUSB_DONTSYNC
619 if (!(sisusb_wait_all_out_complete(sisusb)))
620 return 1;
621 #endif
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);
641 return ret;
644 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
645 struct sisusb_packet *packet,
646 unsigned int tflags)
648 int ret;
649 ssize_t bytes_transferred = 0;
650 __le32 tmp;
652 if (len == 6)
653 packet->data = 0;
655 #ifdef SISUSB_DONTSYNC
656 if (!(sisusb_wait_all_out_complete(sisusb)))
657 return 1;
658 #endif
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);
678 return ret;
681 /* access video memory and mmio (return 0 on success) */
683 /* Low level */
685 /* The following routines assume being used to transfer byte, word,
686 * long etc.
687 * This means that
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,
694 u32 addr, u8 data)
696 struct sisusb_packet packet;
697 int ret;
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);
703 return ret;
706 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
707 u32 addr, u16 data)
709 struct sisusb_packet packet;
710 int ret = 0;
712 packet.address = addr & ~3;
714 switch (addr & 3) {
715 case 0:
716 packet.header = (type << 6) | 0x0003;
717 packet.data = (u32)data;
718 ret = sisusb_send_packet(sisusb, 10, &packet);
719 break;
720 case 1:
721 packet.header = (type << 6) | 0x0006;
722 packet.data = (u32)data << 8;
723 ret = sisusb_send_packet(sisusb, 10, &packet);
724 break;
725 case 2:
726 packet.header = (type << 6) | 0x000c;
727 packet.data = (u32)data << 16;
728 ret = sisusb_send_packet(sisusb, 10, &packet);
729 break;
730 case 3:
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);
740 return ret;
743 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
744 u32 addr, u32 data)
746 struct sisusb_packet packet;
747 int ret = 0;
749 packet.address = addr & ~3;
751 switch (addr & 3) {
752 case 0:
753 packet.header = (type << 6) | 0x0007;
754 packet.data = data & 0x00ffffff;
755 ret = sisusb_send_packet(sisusb, 10, &packet);
756 break;
757 case 1:
758 packet.header = (type << 6) | 0x000e;
759 packet.data = data << 8;
760 ret = sisusb_send_packet(sisusb, 10, &packet);
761 break;
762 case 2:
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);
770 break;
771 case 3:
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);
781 return ret;
784 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
785 u32 addr, u32 data)
787 struct sisusb_packet packet;
788 int ret = 0;
790 packet.address = addr & ~3;
792 switch (addr & 3) {
793 case 0:
794 packet.header = (type << 6) | 0x000f;
795 packet.data = data;
796 ret = sisusb_send_packet(sisusb, 10, &packet);
797 break;
798 case 1:
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);
806 break;
807 case 2:
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);
815 break;
816 case 3:
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);
826 return ret;
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;
845 int ret = 0;
846 static int msgcount = 0;
847 u8 swap8, fromkern = kernbuffer ? 1 : 0;
848 u16 swap16;
849 u32 swap32, flag = (length >> 28) & 1;
850 char buf[4];
852 /* if neither kernbuffer not userbuffer are given, assume
853 * data in obuf
855 if (!fromkern && !userbuffer)
856 kernbuffer = sisusb->obuf[index];
858 (*bytes_written = 0);
860 length &= 0x00ffffff;
862 while (length) {
864 switch (length) {
866 case 0:
867 return ret;
869 case 1:
870 if (userbuffer) {
871 if (get_user(swap8, (u8 __user *)userbuffer))
872 return -EFAULT;
873 } else
874 swap8 = kernbuffer[0];
876 ret = sisusb_write_memio_byte(sisusb,
877 SISUSB_TYPE_MEM,
878 addr, swap8);
880 if (!ret)
881 (*bytes_written)++;
883 return ret;
885 case 2:
886 if (userbuffer) {
887 if (get_user(swap16, (u16 __user *)userbuffer))
888 return -EFAULT;
889 } else
890 swap16 = *((u16 *)kernbuffer);
892 ret = sisusb_write_memio_word(sisusb,
893 SISUSB_TYPE_MEM,
894 addr,
895 swap16);
897 if (!ret)
898 (*bytes_written) += 2;
900 return ret;
902 case 3:
903 if (userbuffer) {
904 if (copy_from_user(&buf, userbuffer, 3))
905 return -EFAULT;
906 #ifdef __BIG_ENDIAN
907 swap32 = (buf[0] << 16) |
908 (buf[1] << 8) |
909 buf[2];
910 #else
911 swap32 = (buf[2] << 16) |
912 (buf[1] << 8) |
913 buf[0];
914 #endif
915 } else
916 #ifdef __BIG_ENDIAN
917 swap32 = (kernbuffer[0] << 16) |
918 (kernbuffer[1] << 8) |
919 kernbuffer[2];
920 #else
921 swap32 = (kernbuffer[2] << 16) |
922 (kernbuffer[1] << 8) |
923 kernbuffer[0];
924 #endif
926 ret = sisusb_write_memio_24bit(sisusb,
927 SISUSB_TYPE_MEM,
928 addr,
929 swap32);
931 if (!ret)
932 (*bytes_written) += 3;
934 return ret;
936 case 4:
937 if (userbuffer) {
938 if (get_user(swap32, (u32 __user *)userbuffer))
939 return -EFAULT;
940 } else
941 swap32 = *((u32 *)kernbuffer);
943 ret = sisusb_write_memio_long(sisusb,
944 SISUSB_TYPE_MEM,
945 addr,
946 swap32);
947 if (!ret)
948 (*bytes_written) += 4;
950 return ret;
952 default:
953 if ((length & ~3) > 0x10000) {
955 packet.header = 0x001f;
956 packet.address = 0x000001d4;
957 packet.data = addr;
958 ret = sisusb_send_bridge_packet(sisusb, 10,
959 &packet, 0);
960 packet.header = 0x001f;
961 packet.address = 0x000001d0;
962 packet.data = (length & ~3);
963 ret |= sisusb_send_bridge_packet(sisusb, 10,
964 &packet, 0);
965 packet.header = 0x001f;
966 packet.address = 0x000001c0;
967 packet.data = flag | 0x16;
968 ret |= sisusb_send_bridge_packet(sisusb, 10,
969 &packet, 0);
970 if (userbuffer) {
971 ret |= sisusb_send_bulk_msg(sisusb,
972 SISUSB_EP_GFX_LBULK_OUT,
973 (length & ~3),
974 NULL, userbuffer, 0,
975 bytes_written, 0, 1);
976 userbuffer += (*bytes_written);
977 } else if (fromkern) {
978 ret |= sisusb_send_bulk_msg(sisusb,
979 SISUSB_EP_GFX_LBULK_OUT,
980 (length & ~3),
981 kernbuffer, NULL, 0,
982 bytes_written, 0, 1);
983 kernbuffer += (*bytes_written);
984 } else {
985 ret |= sisusb_send_bulk_msg(sisusb,
986 SISUSB_EP_GFX_LBULK_OUT,
987 (length & ~3),
988 NULL, NULL, index,
989 bytes_written, 0, 1);
990 kernbuffer += ((*bytes_written) &
991 (sisusb->obufsize-1));
994 } else {
996 packet.header = 0x001f;
997 packet.address = 0x00000194;
998 packet.data = addr;
999 ret = sisusb_send_bridge_packet(sisusb, 10,
1000 &packet, 0);
1001 packet.header = 0x001f;
1002 packet.address = 0x00000190;
1003 packet.data = (length & ~3);
1004 ret |= sisusb_send_bridge_packet(sisusb, 10,
1005 &packet, 0);
1006 if (sisusb->flagb0 != 0x16) {
1007 packet.header = 0x001f;
1008 packet.address = 0x00000180;
1009 packet.data = flag | 0x16;
1010 ret |= sisusb_send_bridge_packet(sisusb, 10,
1011 &packet, 0);
1012 sisusb->flagb0 = 0x16;
1014 if (userbuffer) {
1015 ret |= sisusb_send_bulk_msg(sisusb,
1016 SISUSB_EP_GFX_BULK_OUT,
1017 (length & ~3),
1018 NULL, userbuffer, 0,
1019 bytes_written, 0, 1);
1020 userbuffer += (*bytes_written);
1021 } else if (fromkern) {
1022 ret |= sisusb_send_bulk_msg(sisusb,
1023 SISUSB_EP_GFX_BULK_OUT,
1024 (length & ~3),
1025 kernbuffer, NULL, 0,
1026 bytes_written, 0, 1);
1027 kernbuffer += (*bytes_written);
1028 } else {
1029 ret |= sisusb_send_bulk_msg(sisusb,
1030 SISUSB_EP_GFX_BULK_OUT,
1031 (length & ~3),
1032 NULL, NULL, index,
1033 bytes_written, 0, 1);
1034 kernbuffer += ((*bytes_written) &
1035 (sisusb->obufsize-1));
1038 if (ret) {
1039 msgcount++;
1040 if (msgcount < 500)
1041 printk(KERN_ERR
1042 "sisusbvga[%d]: Wrote %zd of "
1043 "%d bytes, error %d\n",
1044 sisusb->minor, *bytes_written,
1045 length, ret);
1046 else if (msgcount == 500)
1047 printk(KERN_ERR
1048 "sisusbvga[%d]: Too many errors"
1049 ", logging stopped\n",
1050 sisusb->minor);
1052 addr += (*bytes_written);
1053 length -= (*bytes_written);
1056 if (ret)
1057 break;
1061 return ret ? -EIO : 0;
1064 /* Remember: Read data in packet is in machine-endianess! So for
1065 * byte, word, 24bit, long no endian correction is necessary.
1068 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1069 u32 addr, u8 *data)
1071 struct sisusb_packet packet;
1072 int ret;
1074 CLEARPACKET(&packet);
1075 packet.header = (1 << (addr & 3)) | (type << 6);
1076 packet.address = addr & ~3;
1077 ret = sisusb_send_packet(sisusb, 6, &packet);
1078 *data = (u8)(packet.data >> ((addr & 3) << 3));
1079 return ret;
1082 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
1083 u32 addr, u16 *data)
1085 struct sisusb_packet packet;
1086 int ret = 0;
1088 CLEARPACKET(&packet);
1090 packet.address = addr & ~3;
1092 switch (addr & 3) {
1093 case 0:
1094 packet.header = (type << 6) | 0x0003;
1095 ret = sisusb_send_packet(sisusb, 6, &packet);
1096 *data = (u16)(packet.data);
1097 break;
1098 case 1:
1099 packet.header = (type << 6) | 0x0006;
1100 ret = sisusb_send_packet(sisusb, 6, &packet);
1101 *data = (u16)(packet.data >> 8);
1102 break;
1103 case 2:
1104 packet.header = (type << 6) | 0x000c;
1105 ret = sisusb_send_packet(sisusb, 6, &packet);
1106 *data = (u16)(packet.data >> 16);
1107 break;
1108 case 3:
1109 packet.header = (type << 6) | 0x0008;
1110 ret = sisusb_send_packet(sisusb, 6, &packet);
1111 *data = (u16)(packet.data >> 24);
1112 packet.header = (type << 6) | 0x0001;
1113 packet.address = (addr & ~3) + 4;
1114 ret |= sisusb_send_packet(sisusb, 6, &packet);
1115 *data |= (u16)(packet.data << 8);
1118 return ret;
1121 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1122 u32 addr, u32 *data)
1124 struct sisusb_packet packet;
1125 int ret = 0;
1127 packet.address = addr & ~3;
1129 switch (addr & 3) {
1130 case 0:
1131 packet.header = (type << 6) | 0x0007;
1132 ret = sisusb_send_packet(sisusb, 6, &packet);
1133 *data = packet.data & 0x00ffffff;
1134 break;
1135 case 1:
1136 packet.header = (type << 6) | 0x000e;
1137 ret = sisusb_send_packet(sisusb, 6, &packet);
1138 *data = packet.data >> 8;
1139 break;
1140 case 2:
1141 packet.header = (type << 6) | 0x000c;
1142 ret = sisusb_send_packet(sisusb, 6, &packet);
1143 *data = packet.data >> 16;
1144 packet.header = (type << 6) | 0x0001;
1145 packet.address = (addr & ~3) + 4;
1146 ret |= sisusb_send_packet(sisusb, 6, &packet);
1147 *data |= ((packet.data & 0xff) << 16);
1148 break;
1149 case 3:
1150 packet.header = (type << 6) | 0x0008;
1151 ret = sisusb_send_packet(sisusb, 6, &packet);
1152 *data = packet.data >> 24;
1153 packet.header = (type << 6) | 0x0003;
1154 packet.address = (addr & ~3) + 4;
1155 ret |= sisusb_send_packet(sisusb, 6, &packet);
1156 *data |= ((packet.data & 0xffff) << 8);
1159 return ret;
1162 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1163 u32 addr, u32 *data)
1165 struct sisusb_packet packet;
1166 int ret = 0;
1168 packet.address = addr & ~3;
1170 switch (addr & 3) {
1171 case 0:
1172 packet.header = (type << 6) | 0x000f;
1173 ret = sisusb_send_packet(sisusb, 6, &packet);
1174 *data = packet.data;
1175 break;
1176 case 1:
1177 packet.header = (type << 6) | 0x000e;
1178 ret = sisusb_send_packet(sisusb, 6, &packet);
1179 *data = packet.data >> 8;
1180 packet.header = (type << 6) | 0x0001;
1181 packet.address = (addr & ~3) + 4;
1182 ret |= sisusb_send_packet(sisusb, 6, &packet);
1183 *data |= (packet.data << 24);
1184 break;
1185 case 2:
1186 packet.header = (type << 6) | 0x000c;
1187 ret = sisusb_send_packet(sisusb, 6, &packet);
1188 *data = packet.data >> 16;
1189 packet.header = (type << 6) | 0x0003;
1190 packet.address = (addr & ~3) + 4;
1191 ret |= sisusb_send_packet(sisusb, 6, &packet);
1192 *data |= (packet.data << 16);
1193 break;
1194 case 3:
1195 packet.header = (type << 6) | 0x0008;
1196 ret = sisusb_send_packet(sisusb, 6, &packet);
1197 *data = packet.data >> 24;
1198 packet.header = (type << 6) | 0x0007;
1199 packet.address = (addr & ~3) + 4;
1200 ret |= sisusb_send_packet(sisusb, 6, &packet);
1201 *data |= (packet.data << 8);
1204 return ret;
1207 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1208 char *kernbuffer, int length,
1209 char __user *userbuffer, ssize_t *bytes_read)
1211 int ret = 0;
1212 char buf[4];
1213 u16 swap16;
1214 u32 swap32;
1216 (*bytes_read = 0);
1218 length &= 0x00ffffff;
1220 while (length) {
1222 switch (length) {
1224 case 0:
1225 return ret;
1227 case 1:
1229 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1230 addr, &buf[0]);
1231 if (!ret) {
1232 (*bytes_read)++;
1233 if (userbuffer) {
1234 if (put_user(buf[0],
1235 (u8 __user *)userbuffer)) {
1236 return -EFAULT;
1238 } else {
1239 kernbuffer[0] = buf[0];
1242 return ret;
1244 case 2:
1245 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1246 addr, &swap16);
1247 if (!ret) {
1248 (*bytes_read) += 2;
1249 if (userbuffer) {
1250 if (put_user(swap16,
1251 (u16 __user *)userbuffer))
1252 return -EFAULT;
1253 } else {
1254 *((u16 *)kernbuffer) = swap16;
1257 return ret;
1259 case 3:
1260 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1261 addr, &swap32);
1262 if (!ret) {
1263 (*bytes_read) += 3;
1264 #ifdef __BIG_ENDIAN
1265 buf[0] = (swap32 >> 16) & 0xff;
1266 buf[1] = (swap32 >> 8) & 0xff;
1267 buf[2] = swap32 & 0xff;
1268 #else
1269 buf[2] = (swap32 >> 16) & 0xff;
1270 buf[1] = (swap32 >> 8) & 0xff;
1271 buf[0] = swap32 & 0xff;
1272 #endif
1273 if (userbuffer) {
1274 if (copy_to_user(userbuffer, &buf[0], 3))
1275 return -EFAULT;
1276 } else {
1277 kernbuffer[0] = buf[0];
1278 kernbuffer[1] = buf[1];
1279 kernbuffer[2] = buf[2];
1282 return ret;
1284 default:
1285 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1286 addr, &swap32);
1287 if (!ret) {
1288 (*bytes_read) += 4;
1289 if (userbuffer) {
1290 if (put_user(swap32,
1291 (u32 __user *)userbuffer))
1292 return -EFAULT;
1294 userbuffer += 4;
1295 } else {
1296 *((u32 *)kernbuffer) = swap32;
1297 kernbuffer += 4;
1299 addr += 4;
1300 length -= 4;
1302 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1303 default:
1304 CLEARPACKET(&packet);
1305 packet.header = 0x001f;
1306 packet.address = 0x000001a0;
1307 packet.data = 0x00000006;
1308 ret |= sisusb_send_bridge_packet(sisusb, 10,
1309 &packet, 0);
1310 packet.header = 0x001f;
1311 packet.address = 0x000001b0;
1312 packet.data = (length & ~3) | 0x40000000;
1313 ret |= sisusb_send_bridge_packet(sisusb, 10,
1314 &packet, 0);
1315 packet.header = 0x001f;
1316 packet.address = 0x000001b4;
1317 packet.data = addr;
1318 ret |= sisusb_send_bridge_packet(sisusb, 10,
1319 &packet, 0);
1320 packet.header = 0x001f;
1321 packet.address = 0x000001a4;
1322 packet.data = 0x00000001;
1323 ret |= sisusb_send_bridge_packet(sisusb, 10,
1324 &packet, 0);
1325 if (userbuffer) {
1326 ret |= sisusb_recv_bulk_msg(sisusb,
1327 SISUSB_EP_GFX_BULK_IN,
1328 (length & ~3),
1329 NULL, userbuffer,
1330 bytes_read, 0);
1331 if (!ret) userbuffer += (*bytes_read);
1332 } else {
1333 ret |= sisusb_recv_bulk_msg(sisusb,
1334 SISUSB_EP_GFX_BULK_IN,
1335 (length & ~3),
1336 kernbuffer, NULL,
1337 bytes_read, 0);
1338 if (!ret) kernbuffer += (*bytes_read);
1340 addr += (*bytes_read);
1341 length -= (*bytes_read);
1342 #endif
1345 if (ret)
1346 break;
1349 return ret;
1352 /* High level: Gfx (indexed) register access */
1354 #ifdef INCL_SISUSB_CON
1356 sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1358 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1362 sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1364 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1366 #endif
1368 #ifndef INCL_SISUSB_CON
1369 static
1370 #endif
1372 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1374 int ret;
1375 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1376 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1377 return ret;
1380 #ifndef INCL_SISUSB_CON
1381 static
1382 #endif
1384 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1386 int ret;
1387 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1388 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1389 return ret;
1392 #ifndef INCL_SISUSB_CON
1393 static
1394 #endif
1396 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1397 u8 myand, u8 myor)
1399 int ret;
1400 u8 tmp;
1402 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1403 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1404 tmp &= myand;
1405 tmp |= myor;
1406 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1407 return ret;
1410 static int
1411 sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1412 u8 data, u8 mask)
1414 int ret;
1415 u8 tmp;
1416 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1417 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1418 tmp &= ~(mask);
1419 tmp |= (data & mask);
1420 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1421 return ret;
1424 #ifndef INCL_SISUSB_CON
1425 static
1426 #endif
1428 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1430 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1433 #ifndef INCL_SISUSB_CON
1434 static
1435 #endif
1437 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1439 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1442 /* Write/read video ram */
1444 #ifdef INCL_SISUSB_CON
1446 sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1448 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1452 sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1454 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1458 sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
1460 return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1464 sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
1466 return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1470 sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1471 u32 dest, int length, size_t *bytes_written)
1473 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1476 #ifdef SISUSBENDIANTEST
1478 sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1479 u32 src, int length, size_t *bytes_written)
1481 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1483 #endif
1484 #endif
1486 #ifdef SISUSBENDIANTEST
1487 static void
1488 sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1490 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1491 char destbuffer[10];
1492 size_t dummy;
1493 int i,j;
1495 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1497 for(i = 1; i <= 7; i++) {
1498 printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
1499 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1500 for(j = 0; j < i; j++) {
1501 printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
1505 #endif
1507 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1509 static int
1510 sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
1512 struct sisusb_packet packet;
1513 int ret;
1515 packet.header = 0x008f;
1516 packet.address = regnum | 0x10000;
1517 packet.data = data;
1518 ret = sisusb_send_packet(sisusb, 10, &packet);
1519 return ret;
1522 static int
1523 sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
1525 struct sisusb_packet packet;
1526 int ret;
1528 packet.header = 0x008f;
1529 packet.address = (u32)regnum | 0x10000;
1530 ret = sisusb_send_packet(sisusb, 6, &packet);
1531 *data = packet.data;
1532 return ret;
1535 /* Clear video RAM */
1537 static int
1538 sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
1540 int ret, i;
1541 ssize_t j;
1543 if (address < sisusb->vrambase)
1544 return 1;
1546 if (address >= sisusb->vrambase + sisusb->vramsize)
1547 return 1;
1549 if (address + length > sisusb->vrambase + sisusb->vramsize)
1550 length = sisusb->vrambase + sisusb->vramsize - address;
1552 if (length <= 0)
1553 return 0;
1555 /* allocate free buffer/urb and clear the buffer */
1556 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1557 return -EBUSY;
1559 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1561 /* We can write a length > buffer size here. The buffer
1562 * data will simply be re-used (like a ring-buffer).
1564 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1566 /* Free the buffer/urb */
1567 sisusb_free_outbuf(sisusb, i);
1569 return ret;
1572 /* Initialize the graphics core (return 0 on success)
1573 * This resets the graphics hardware and puts it into
1574 * a defined mode (640x480@60Hz)
1577 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1578 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1579 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1580 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1581 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1582 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1583 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1584 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1585 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1586 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1587 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1589 static int
1590 sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1592 int ret;
1593 u8 tmp8;
1595 ret = GETIREG(SISSR, 0x16, &tmp8);
1596 if (ramtype <= 1) {
1597 tmp8 &= 0x3f;
1598 ret |= SETIREG(SISSR, 0x16, tmp8);
1599 tmp8 |= 0x80;
1600 ret |= SETIREG(SISSR, 0x16, tmp8);
1601 } else {
1602 tmp8 |= 0xc0;
1603 ret |= SETIREG(SISSR, 0x16, tmp8);
1604 tmp8 &= 0x0f;
1605 ret |= SETIREG(SISSR, 0x16, tmp8);
1606 tmp8 |= 0x80;
1607 ret |= SETIREG(SISSR, 0x16, tmp8);
1608 tmp8 &= 0x0f;
1609 ret |= SETIREG(SISSR, 0x16, tmp8);
1610 tmp8 |= 0xd0;
1611 ret |= SETIREG(SISSR, 0x16, tmp8);
1612 tmp8 &= 0x0f;
1613 ret |= SETIREG(SISSR, 0x16, tmp8);
1614 tmp8 |= 0xa0;
1615 ret |= SETIREG(SISSR, 0x16, tmp8);
1617 return ret;
1620 static int
1621 sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
1623 int ret;
1624 u8 ramtype, done = 0;
1625 u32 t0, t1, t2, t3;
1626 u32 ramptr = SISUSB_PCI_MEMBASE;
1628 ret = GETIREG(SISSR, 0x3a, &ramtype);
1629 ramtype &= 3;
1631 ret |= SETIREG(SISSR, 0x13, 0x00);
1633 if (ramtype <= 1) {
1634 ret |= SETIREG(SISSR, 0x14, 0x12);
1635 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1636 } else {
1637 ret |= SETIREG(SISSR, 0x14, 0x02);
1640 ret |= sisusb_triggersr16(sisusb, ramtype);
1641 ret |= WRITEL(ramptr + 0, 0x01234567);
1642 ret |= WRITEL(ramptr + 4, 0x456789ab);
1643 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1644 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1645 ret |= WRITEL(ramptr + 16, 0x55555555);
1646 ret |= WRITEL(ramptr + 20, 0x55555555);
1647 ret |= WRITEL(ramptr + 24, 0xffffffff);
1648 ret |= WRITEL(ramptr + 28, 0xffffffff);
1649 ret |= READL(ramptr + 0, &t0);
1650 ret |= READL(ramptr + 4, &t1);
1651 ret |= READL(ramptr + 8, &t2);
1652 ret |= READL(ramptr + 12, &t3);
1654 if (ramtype <= 1) {
1656 *chab = 0; *bw = 64;
1658 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1659 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1660 *chab = 0; *bw = 64;
1661 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1664 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1665 *chab = 1; *bw = 64;
1666 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
1668 ret |= sisusb_triggersr16(sisusb, ramtype);
1669 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1670 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1671 ret |= WRITEL(ramptr + 8, 0x55555555);
1672 ret |= WRITEL(ramptr + 12, 0x55555555);
1673 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1674 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1675 ret |= READL(ramptr + 4, &t1);
1677 if (t1 != 0xcdef0123) {
1678 *bw = 32;
1679 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1683 } else {
1685 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1687 done = 0;
1689 if (t1 == 0x456789ab) {
1690 if (t0 == 0x01234567) {
1691 *chab = 0; *bw = 64;
1692 done = 1;
1694 } else {
1695 if (t0 == 0x01234567) {
1696 *chab = 0; *bw = 32;
1697 ret |= SETIREG(SISSR, 0x14, 0x00);
1698 done = 1;
1702 if (!done) {
1703 ret |= SETIREG(SISSR, 0x14, 0x03);
1704 ret |= sisusb_triggersr16(sisusb, ramtype);
1706 ret |= WRITEL(ramptr + 0, 0x01234567);
1707 ret |= WRITEL(ramptr + 4, 0x456789ab);
1708 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1709 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1710 ret |= WRITEL(ramptr + 16, 0x55555555);
1711 ret |= WRITEL(ramptr + 20, 0x55555555);
1712 ret |= WRITEL(ramptr + 24, 0xffffffff);
1713 ret |= WRITEL(ramptr + 28, 0xffffffff);
1714 ret |= READL(ramptr + 0, &t0);
1715 ret |= READL(ramptr + 4, &t1);
1717 if (t1 == 0x456789ab) {
1718 if (t0 == 0x01234567) {
1719 *chab = 1; *bw = 64;
1720 return ret;
1721 } /* else error */
1722 } else {
1723 if (t0 == 0x01234567) {
1724 *chab = 1; *bw = 32;
1725 ret |= SETIREG(SISSR, 0x14, 0x01);
1726 } /* else error */
1730 return ret;
1733 static int
1734 sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1736 int ret = 0;
1737 u32 ramptr = SISUSB_PCI_MEMBASE;
1738 u8 tmp1, tmp2, i, j;
1740 ret |= WRITEB(ramptr, 0xaa);
1741 ret |= WRITEB(ramptr + 16, 0x55);
1742 ret |= READB(ramptr, &tmp1);
1743 ret |= READB(ramptr + 16, &tmp2);
1744 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1745 for (i = 0, j = 16; i < 2; i++, j += 16) {
1746 ret |= GETIREG(SISSR, 0x21, &tmp1);
1747 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1748 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1749 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1750 ret |= SETIREG(SISSR, 0x21, tmp1);
1751 ret |= WRITEB(ramptr + 16 + j, j);
1752 ret |= READB(ramptr + 16 + j, &tmp1);
1753 if (tmp1 == j) {
1754 ret |= WRITEB(ramptr + j, j);
1755 break;
1759 return ret;
1762 static int
1763 sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
1764 u8 rankno, u8 chab, const u8 dramtype[][5],
1765 int bw)
1767 int ret = 0, ranksize;
1768 u8 tmp;
1770 *iret = 0;
1772 if ((rankno == 2) && (dramtype[index][0] == 2))
1773 return ret;
1775 ranksize = dramtype[index][3] / 2 * bw / 32;
1777 if ((ranksize * rankno) > 128)
1778 return ret;
1780 tmp = 0;
1781 while ((ranksize >>= 1) > 0) tmp += 0x10;
1782 tmp |= ((rankno - 1) << 2);
1783 tmp |= ((bw / 64) & 0x02);
1784 tmp |= (chab & 0x01);
1786 ret = SETIREG(SISSR, 0x14, tmp);
1787 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1789 *iret = 1;
1791 return ret;
1794 static int
1795 sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
1797 int ret = 0, i;
1798 u32 j, tmp;
1800 *iret = 0;
1802 for (i = 0, j = 0; i < testn; i++) {
1803 ret |= WRITEL(sisusb->vrambase + j, j);
1804 j += inc;
1807 for (i = 0, j = 0; i < testn; i++) {
1808 ret |= READL(sisusb->vrambase + j, &tmp);
1809 if (tmp != j) return ret;
1810 j += inc;
1813 *iret = 1;
1814 return ret;
1817 static int
1818 sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
1819 int idx, int bw, const u8 rtype[][5])
1821 int ret = 0, i, i2ret;
1822 u32 inc;
1824 *iret = 0;
1826 for (i = rankno; i >= 1; i--) {
1827 inc = 1 << (rtype[idx][2] +
1828 rtype[idx][1] +
1829 rtype[idx][0] +
1830 bw / 64 + i);
1831 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1832 if (!i2ret)
1833 return ret;
1836 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1837 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1838 if (!i2ret)
1839 return ret;
1841 inc = 1 << (10 + bw / 64);
1842 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1843 if (!i2ret)
1844 return ret;
1846 *iret = 1;
1847 return ret;
1850 static int
1851 sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
1852 int chab)
1854 int ret = 0, i2ret = 0, i, j;
1855 static const u8 sdramtype[13][5] = {
1856 { 2, 12, 9, 64, 0x35 },
1857 { 1, 13, 9, 64, 0x44 },
1858 { 2, 12, 8, 32, 0x31 },
1859 { 2, 11, 9, 32, 0x25 },
1860 { 1, 12, 9, 32, 0x34 },
1861 { 1, 13, 8, 32, 0x40 },
1862 { 2, 11, 8, 16, 0x21 },
1863 { 1, 12, 8, 16, 0x30 },
1864 { 1, 11, 9, 16, 0x24 },
1865 { 1, 11, 8, 8, 0x20 },
1866 { 2, 9, 8, 4, 0x01 },
1867 { 1, 10, 8, 4, 0x10 },
1868 { 1, 9, 8, 2, 0x00 }
1871 *iret = 1; /* error */
1873 for (i = 0; i < 13; i++) {
1874 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1875 for (j = 2; j > 0; j--) {
1876 ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
1877 chab, sdramtype, bw);
1878 if (!i2ret)
1879 continue;
1881 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
1882 bw, sdramtype);
1883 if (i2ret) {
1884 *iret = 0; /* ram size found */
1885 return ret;
1890 return ret;
1893 static int
1894 sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
1896 int ret = 0;
1897 u32 address;
1898 int i, length, modex, modey, bpp;
1900 modex = 640; modey = 480; bpp = 2;
1902 address = sisusb->vrambase; /* Clear video ram */
1904 if (clrall)
1905 length = sisusb->vramsize;
1906 else
1907 length = modex * bpp * modey;
1909 ret = sisusb_clear_vram(sisusb, address, length);
1911 if (!ret && drwfr) {
1912 for (i = 0; i < modex; i++) {
1913 address = sisusb->vrambase + (i * bpp);
1914 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1915 address, 0xf100);
1916 address += (modex * (modey-1) * bpp);
1917 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1918 address, 0xf100);
1920 for (i = 0; i < modey; i++) {
1921 address = sisusb->vrambase + ((i * modex) * bpp);
1922 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1923 address, 0xf100);
1924 address += ((modex - 1) * bpp);
1925 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1926 address, 0xf100);
1930 return ret;
1933 static int
1934 sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
1936 int ret = 0, i, j, modex, modey, bpp, du;
1937 u8 sr31, cr63, tmp8;
1938 static const char attrdata[] = {
1939 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1940 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1941 0x01,0x00,0x00,0x00
1943 static const char crtcrdata[] = {
1944 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1945 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1946 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1947 0xff
1949 static const char grcdata[] = {
1950 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1951 0xff
1953 static const char crtcdata[] = {
1954 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1955 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1956 0x00
1959 modex = 640; modey = 480; bpp = 2;
1961 GETIREG(SISSR, 0x31, &sr31);
1962 GETIREG(SISCR, 0x63, &cr63);
1963 SETIREGOR(SISSR, 0x01, 0x20);
1964 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1965 SETIREGOR(SISCR, 0x17, 0x80);
1966 SETIREGOR(SISSR, 0x1f, 0x04);
1967 SETIREGAND(SISSR, 0x07, 0xfb);
1968 SETIREG(SISSR, 0x00, 0x03); /* seq */
1969 SETIREG(SISSR, 0x01, 0x21);
1970 SETIREG(SISSR, 0x02, 0x0f);
1971 SETIREG(SISSR, 0x03, 0x00);
1972 SETIREG(SISSR, 0x04, 0x0e);
1973 SETREG(SISMISCW, 0x23); /* misc */
1974 for (i = 0; i <= 0x18; i++) { /* crtc */
1975 SETIREG(SISCR, i, crtcrdata[i]);
1977 for (i = 0; i <= 0x13; i++) { /* att */
1978 GETREG(SISINPSTAT, &tmp8);
1979 SETREG(SISAR, i);
1980 SETREG(SISAR, attrdata[i]);
1982 GETREG(SISINPSTAT, &tmp8);
1983 SETREG(SISAR, 0x14);
1984 SETREG(SISAR, 0x00);
1985 GETREG(SISINPSTAT, &tmp8);
1986 SETREG(SISAR, 0x20);
1987 GETREG(SISINPSTAT, &tmp8);
1988 for (i = 0; i <= 0x08; i++) { /* grc */
1989 SETIREG(SISGR, i, grcdata[i]);
1991 SETIREGAND(SISGR, 0x05, 0xbf);
1992 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1993 SETIREG(SISSR, i, 0x00);
1995 SETIREGAND(SISSR, 0x37, 0xfe);
1996 SETREG(SISMISCW, 0xef); /* sync */
1997 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1998 for (j = 0x00, i = 0; i <= 7; i++, j++) {
1999 SETIREG(SISCR, j, crtcdata[i]);
2001 for (j = 0x10; i <= 10; i++, j++) {
2002 SETIREG(SISCR, j, crtcdata[i]);
2004 for (j = 0x15; i <= 12; i++, j++) {
2005 SETIREG(SISCR, j, crtcdata[i]);
2007 for (j = 0x0A; i <= 15; i++, j++) {
2008 SETIREG(SISSR, j, crtcdata[i]);
2010 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
2011 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
2012 SETIREG(SISCR, 0x14, 0x4f);
2013 du = (modex / 16) * (bpp * 2); /* offset/pitch */
2014 if (modex % 16) du += bpp;
2015 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
2016 SETIREG(SISCR, 0x13, (du & 0xff));
2017 du <<= 5;
2018 tmp8 = du >> 8;
2019 if (du & 0xff) tmp8++;
2020 SETIREG(SISSR, 0x10, tmp8);
2021 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
2022 SETIREG(SISSR, 0x2b, 0x1b);
2023 SETIREG(SISSR, 0x2c, 0xe1);
2024 SETIREG(SISSR, 0x2d, 0x01);
2025 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
2026 SETIREG(SISSR, 0x08, 0xae);
2027 SETIREGAND(SISSR, 0x09, 0xf0);
2028 SETIREG(SISSR, 0x08, 0x34);
2029 SETIREGOR(SISSR, 0x3d, 0x01);
2030 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
2031 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
2032 SETIREG(SISCR, 0x19, 0x00);
2033 SETIREGAND(SISCR, 0x1a, 0xfc);
2034 SETIREGAND(SISSR, 0x0f, 0xb7);
2035 SETIREGAND(SISSR, 0x31, 0xfb);
2036 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
2037 SETIREGAND(SISSR, 0x32, 0xf3);
2038 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
2039 SETIREG(SISCR, 0x52, 0x6c);
2041 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
2042 SETIREG(SISCR, 0x0c, 0x00);
2043 SETIREG(SISSR, 0x0d, 0x00);
2044 SETIREGAND(SISSR, 0x37, 0xfe);
2046 SETIREG(SISCR, 0x32, 0x20);
2047 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
2048 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
2049 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
2051 if (touchengines) {
2052 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
2053 SETIREGOR(SISSR, 0x1e, 0x5a);
2055 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
2056 SETIREG(SISSR, 0x27, 0x1f);
2057 SETIREG(SISSR, 0x26, 0x00);
2060 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
2062 return ret;
2065 static int
2066 sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
2068 int ret = 0, i, j, bw, chab, iret, retry = 3;
2069 u8 tmp8, ramtype;
2070 u32 tmp32;
2071 static const char mclktable[] = {
2072 0x3b, 0x22, 0x01, 143,
2073 0x3b, 0x22, 0x01, 143,
2074 0x3b, 0x22, 0x01, 143,
2075 0x3b, 0x22, 0x01, 143
2077 static const char eclktable[] = {
2078 0x3b, 0x22, 0x01, 143,
2079 0x3b, 0x22, 0x01, 143,
2080 0x3b, 0x22, 0x01, 143,
2081 0x3b, 0x22, 0x01, 143
2083 static const char ramtypetable1[] = {
2084 0x00, 0x04, 0x60, 0x60,
2085 0x0f, 0x0f, 0x1f, 0x1f,
2086 0xba, 0xba, 0xba, 0xba,
2087 0xa9, 0xa9, 0xac, 0xac,
2088 0xa0, 0xa0, 0xa0, 0xa8,
2089 0x00, 0x00, 0x02, 0x02,
2090 0x30, 0x30, 0x40, 0x40
2092 static const char ramtypetable2[] = {
2093 0x77, 0x77, 0x44, 0x44,
2094 0x77, 0x77, 0x44, 0x44,
2095 0x00, 0x00, 0x00, 0x00,
2096 0x5b, 0x5b, 0xab, 0xab,
2097 0x00, 0x00, 0xf0, 0xf8
2100 while (retry--) {
2102 /* Enable VGA */
2103 ret = GETREG(SISVGAEN, &tmp8);
2104 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
2106 /* Enable GPU access to VRAM */
2107 ret |= GETREG(SISMISCR, &tmp8);
2108 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
2110 if (ret) continue;
2112 /* Reset registers */
2113 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
2114 ret |= SETIREG(SISSR, 0x05, 0x86);
2115 ret |= SETIREGOR(SISSR, 0x20, 0x01);
2117 ret |= SETREG(SISMISCW, 0x67);
2119 for (i = 0x06; i <= 0x1f; i++) {
2120 ret |= SETIREG(SISSR, i, 0x00);
2122 for (i = 0x21; i <= 0x27; i++) {
2123 ret |= SETIREG(SISSR, i, 0x00);
2125 for (i = 0x31; i <= 0x3d; i++) {
2126 ret |= SETIREG(SISSR, i, 0x00);
2128 for (i = 0x12; i <= 0x1b; i++) {
2129 ret |= SETIREG(SISSR, i, 0x00);
2131 for (i = 0x79; i <= 0x7c; i++) {
2132 ret |= SETIREG(SISCR, i, 0x00);
2135 if (ret) continue;
2137 ret |= SETIREG(SISCR, 0x63, 0x80);
2139 ret |= GETIREG(SISSR, 0x3a, &ramtype);
2140 ramtype &= 0x03;
2142 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
2143 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
2144 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
2146 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
2147 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
2148 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
2150 ret |= SETIREG(SISSR, 0x07, 0x18);
2151 ret |= SETIREG(SISSR, 0x11, 0x0f);
2153 if (ret) continue;
2155 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
2156 ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
2158 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
2159 ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
2162 ret |= SETIREG(SISCR, 0x49, 0xaa);
2164 ret |= SETIREG(SISSR, 0x1f, 0x00);
2165 ret |= SETIREG(SISSR, 0x20, 0xa0);
2166 ret |= SETIREG(SISSR, 0x23, 0xf6);
2167 ret |= SETIREG(SISSR, 0x24, 0x0d);
2168 ret |= SETIREG(SISSR, 0x25, 0x33);
2170 ret |= SETIREG(SISSR, 0x11, 0x0f);
2172 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
2174 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2176 if (ret) continue;
2178 ret |= SETIREG(SISPART1, 0x00, 0x00);
2180 ret |= GETIREG(SISSR, 0x13, &tmp8);
2181 tmp8 >>= 4;
2183 ret |= SETIREG(SISPART1, 0x02, 0x00);
2184 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2186 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2187 tmp32 &= 0x00f00000;
2188 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2189 ret |= SETIREG(SISSR, 0x25, tmp8);
2190 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2191 ret |= SETIREG(SISCR, 0x49, tmp8);
2193 ret |= SETIREG(SISSR, 0x27, 0x1f);
2194 ret |= SETIREG(SISSR, 0x31, 0x00);
2195 ret |= SETIREG(SISSR, 0x32, 0x11);
2196 ret |= SETIREG(SISSR, 0x33, 0x00);
2198 if (ret) continue;
2200 ret |= SETIREG(SISCR, 0x83, 0x00);
2202 ret |= sisusb_set_default_mode(sisusb, 0);
2204 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2205 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2206 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2208 ret |= sisusb_triggersr16(sisusb, ramtype);
2210 /* Disable refresh */
2211 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2212 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2214 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2215 ret |= sisusb_verify_mclk(sisusb);
2217 if (ramtype <= 1) {
2218 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2219 if (iret) {
2220 printk(KERN_ERR "sisusbvga[%d]: RAM size "
2221 "detection failed, "
2222 "assuming 8MB video RAM\n",
2223 sisusb->minor);
2224 ret |= SETIREG(SISSR,0x14,0x31);
2225 /* TODO */
2227 } else {
2228 printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
2229 "assuming 8MB video RAM\n",
2230 sisusb->minor);
2231 ret |= SETIREG(SISSR,0x14,0x31);
2232 /* *** TODO *** */
2235 /* Enable refresh */
2236 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2237 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2238 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2240 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2242 ret |= SETIREG(SISSR, 0x22, 0xfb);
2243 ret |= SETIREG(SISSR, 0x21, 0xa5);
2245 if (ret == 0)
2246 break;
2249 return ret;
2252 #undef SETREG
2253 #undef GETREG
2254 #undef SETIREG
2255 #undef GETIREG
2256 #undef SETIREGOR
2257 #undef SETIREGAND
2258 #undef SETIREGANDOR
2259 #undef READL
2260 #undef WRITEL
2262 static void
2263 sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2265 u8 tmp8, tmp82, ramtype;
2266 int bw = 0;
2267 char *ramtypetext1 = NULL;
2268 const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
2269 "DDR SDRAM", "DDR SGRAM" };
2270 static const int busSDR[4] = {64, 64, 128, 128};
2271 static const int busDDR[4] = {32, 32, 64, 64};
2272 static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2274 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2275 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2276 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2277 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2278 ramtype &= 0x03;
2279 switch ((tmp8 >> 2) & 0x03) {
2280 case 0: ramtypetext1 = "1 ch/1 r";
2281 if (tmp82 & 0x10) {
2282 bw = 32;
2283 } else {
2284 bw = busSDR[(tmp8 & 0x03)];
2286 break;
2287 case 1: ramtypetext1 = "1 ch/2 r";
2288 sisusb->vramsize <<= 1;
2289 bw = busSDR[(tmp8 & 0x03)];
2290 break;
2291 case 2: ramtypetext1 = "asymmeric";
2292 sisusb->vramsize += sisusb->vramsize/2;
2293 bw = busDDRA[(tmp8 & 0x03)];
2294 break;
2295 case 3: ramtypetext1 = "2 channel";
2296 sisusb->vramsize <<= 1;
2297 bw = busDDR[(tmp8 & 0x03)];
2298 break;
2301 printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2302 sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
2303 ramtypetext2[ramtype], bw);
2306 static int
2307 sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2309 struct sisusb_packet packet;
2310 int ret;
2311 u32 tmp32;
2313 /* Do some magic */
2314 packet.header = 0x001f;
2315 packet.address = 0x00000324;
2316 packet.data = 0x00000004;
2317 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2319 packet.header = 0x001f;
2320 packet.address = 0x00000364;
2321 packet.data = 0x00000004;
2322 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2324 packet.header = 0x001f;
2325 packet.address = 0x00000384;
2326 packet.data = 0x00000004;
2327 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2329 packet.header = 0x001f;
2330 packet.address = 0x00000100;
2331 packet.data = 0x00000700;
2332 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2334 packet.header = 0x000f;
2335 packet.address = 0x00000004;
2336 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2337 packet.data |= 0x17;
2338 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2340 /* Init BAR 0 (VRAM) */
2341 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2342 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2343 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2344 tmp32 &= 0x0f;
2345 tmp32 |= SISUSB_PCI_MEMBASE;
2346 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2348 /* Init BAR 1 (MMIO) */
2349 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2350 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2351 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2352 tmp32 &= 0x0f;
2353 tmp32 |= SISUSB_PCI_MMIOBASE;
2354 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2356 /* Init BAR 2 (i/o ports) */
2357 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2358 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2359 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2360 tmp32 &= 0x0f;
2361 tmp32 |= SISUSB_PCI_IOPORTBASE;
2362 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2364 /* Enable memory and i/o access */
2365 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2366 tmp32 |= 0x3;
2367 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2369 if (ret == 0) {
2370 /* Some further magic */
2371 packet.header = 0x001f;
2372 packet.address = 0x00000050;
2373 packet.data = 0x000000ff;
2374 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2377 return ret;
2380 /* Initialize the graphics device (return 0 on success)
2381 * This initializes the net2280 as well as the PCI registers
2382 * of the graphics board.
2385 static int
2386 sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2388 int ret = 0, test = 0;
2389 u32 tmp32;
2391 if (sisusb->devinit == 1) {
2392 /* Read PCI BARs and see if they have been set up */
2393 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2394 if (ret) return ret;
2395 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2397 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2398 if (ret) return ret;
2399 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2401 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2402 if (ret) return ret;
2403 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2406 /* No? So reset the device */
2407 if ((sisusb->devinit == 0) || (test != 3)) {
2409 ret |= sisusb_do_init_gfxdevice(sisusb);
2411 if (ret == 0)
2412 sisusb->devinit = 1;
2416 if (sisusb->devinit) {
2417 /* Initialize the graphics core */
2418 if (sisusb_init_gfxcore(sisusb) == 0) {
2419 sisusb->gfxinit = 1;
2420 sisusb_get_ramconfig(sisusb);
2421 ret |= sisusb_set_default_mode(sisusb, 1);
2422 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2426 return ret;
2430 #ifdef INCL_SISUSB_CON
2432 /* Set up default text mode:
2433 - Set text mode (0x03)
2434 - Upload default font
2435 - Upload user font (if available)
2439 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2441 int ret = 0, slot = sisusb->font_slot, i;
2442 const struct font_desc *myfont;
2443 u8 *tempbuf;
2444 u16 *tempbufb;
2445 size_t written;
2446 static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2447 static char bootlogo[] = "(o_ //\\ V_/_";
2449 /* sisusb->lock is down */
2451 if (!sisusb->SiS_Pr)
2452 return 1;
2454 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2455 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2457 /* Set mode 0x03 */
2458 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2460 if (!(myfont = find_font("VGA8x16")))
2461 return 1;
2463 if (!(tempbuf = vmalloc(8192)))
2464 return 1;
2466 for (i = 0; i < 256; i++)
2467 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2469 /* Upload default font */
2470 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2472 vfree(tempbuf);
2474 /* Upload user font (and reset current slot) */
2475 if (sisusb->font_backup) {
2476 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2477 8192, sisusb->font_backup_512, 1, NULL,
2478 sisusb->font_backup_height, 0);
2479 if (slot != 2)
2480 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2481 NULL, 16, 0);
2484 if (init && !sisusb->scrbuf) {
2486 if ((tempbuf = vmalloc(8192))) {
2488 i = 4096;
2489 tempbufb = (u16 *)tempbuf;
2490 while (i--)
2491 *(tempbufb++) = 0x0720;
2493 i = 0;
2494 tempbufb = (u16 *)tempbuf;
2495 while (bootlogo[i]) {
2496 *(tempbufb++) = 0x0700 | bootlogo[i++];
2497 if (!(i % 4))
2498 tempbufb += 76;
2501 i = 0;
2502 tempbufb = (u16 *)tempbuf + 6;
2503 while (bootstring[i])
2504 *(tempbufb++) = 0x0700 | bootstring[i++];
2506 ret |= sisusb_copy_memory(sisusb, tempbuf,
2507 sisusb->vrambase, 8192, &written);
2509 vfree(tempbuf);
2513 } else if (sisusb->scrbuf) {
2515 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2516 sisusb->vrambase, sisusb->scrbuf_size, &written);
2520 if (sisusb->sisusb_cursor_size_from >= 0 &&
2521 sisusb->sisusb_cursor_size_to >= 0) {
2522 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2523 sisusb->sisusb_cursor_size_from);
2524 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2525 sisusb->sisusb_cursor_size_to);
2526 } else {
2527 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2528 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2529 sisusb->sisusb_cursor_size_to = -1;
2532 slot = sisusb->sisusb_cursor_loc;
2533 if(slot < 0) slot = 0;
2535 sisusb->sisusb_cursor_loc = -1;
2536 sisusb->bad_cursor_pos = 1;
2538 sisusb_set_cursor(sisusb, slot);
2540 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2541 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2543 sisusb->textmodedestroyed = 0;
2545 /* sisusb->lock is down */
2547 return ret;
2550 #endif
2552 /* fops */
2554 static int
2555 sisusb_open(struct inode *inode, struct file *file)
2557 struct sisusb_usb_data *sisusb;
2558 struct usb_interface *interface;
2559 int subminor = iminor(inode);
2561 down(&disconnect_sem);
2563 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2564 printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
2565 subminor);
2566 up(&disconnect_sem);
2567 return -ENODEV;
2570 if (!(sisusb = usb_get_intfdata(interface))) {
2571 up(&disconnect_sem);
2572 return -ENODEV;
2575 down(&sisusb->lock);
2577 if (!sisusb->present || !sisusb->ready) {
2578 up(&sisusb->lock);
2579 up(&disconnect_sem);
2580 return -ENODEV;
2583 if (sisusb->isopen) {
2584 up(&sisusb->lock);
2585 up(&disconnect_sem);
2586 return -EBUSY;
2589 if (!sisusb->devinit) {
2590 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2591 if (sisusb_init_gfxdevice(sisusb, 0)) {
2592 up(&sisusb->lock);
2593 up(&disconnect_sem);
2594 printk(KERN_ERR
2595 "sisusbvga[%d]: Failed to initialize "
2596 "device\n",
2597 sisusb->minor);
2598 return -EIO;
2600 } else {
2601 up(&sisusb->lock);
2602 up(&disconnect_sem);
2603 printk(KERN_ERR
2604 "sisusbvga[%d]: Device not attached to "
2605 "USB 2.0 hub\n",
2606 sisusb->minor);
2607 return -EIO;
2611 /* Increment usage count for our sisusb */
2612 kref_get(&sisusb->kref);
2614 sisusb->isopen = 1;
2616 file->private_data = sisusb;
2618 up(&sisusb->lock);
2620 up(&disconnect_sem);
2622 return 0;
2625 void
2626 sisusb_delete(struct kref *kref)
2628 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2630 if (!sisusb)
2631 return;
2633 if (sisusb->sisusb_dev)
2634 usb_put_dev(sisusb->sisusb_dev);
2636 sisusb->sisusb_dev = NULL;
2637 sisusb_free_buffers(sisusb);
2638 sisusb_free_urbs(sisusb);
2639 #ifdef INCL_SISUSB_CON
2640 kfree(sisusb->SiS_Pr);
2641 #endif
2642 kfree(sisusb);
2645 static int
2646 sisusb_release(struct inode *inode, struct file *file)
2648 struct sisusb_usb_data *sisusb;
2649 int myminor;
2651 down(&disconnect_sem);
2653 if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
2654 up(&disconnect_sem);
2655 return -ENODEV;
2658 down(&sisusb->lock);
2660 if (sisusb->present) {
2661 /* Wait for all URBs to finish if device still present */
2662 if (!sisusb_wait_all_out_complete(sisusb))
2663 sisusb_kill_all_busy(sisusb);
2666 myminor = sisusb->minor;
2668 sisusb->isopen = 0;
2669 file->private_data = NULL;
2671 up(&sisusb->lock);
2673 /* decrement the usage count on our device */
2674 kref_put(&sisusb->kref, sisusb_delete);
2676 up(&disconnect_sem);
2678 return 0;
2681 static ssize_t
2682 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2684 struct sisusb_usb_data *sisusb;
2685 ssize_t bytes_read = 0;
2686 int errno = 0;
2687 u8 buf8;
2688 u16 buf16;
2689 u32 buf32, address;
2691 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2692 return -ENODEV;
2694 down(&sisusb->lock);
2696 /* Sanity check */
2697 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2698 up(&sisusb->lock);
2699 return -ENODEV;
2702 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2703 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2705 address = (*ppos) -
2706 SISUSB_PCI_PSEUDO_IOPORTBASE +
2707 SISUSB_PCI_IOPORTBASE;
2709 /* Read i/o ports
2710 * Byte, word and long(32) can be read. As this
2711 * emulates inX instructions, the data returned is
2712 * in machine-endianness.
2714 switch (count) {
2716 case 1:
2717 if (sisusb_read_memio_byte(sisusb,
2718 SISUSB_TYPE_IO,
2719 address, &buf8))
2720 errno = -EIO;
2721 else if (put_user(buf8, (u8 __user *)buffer))
2722 errno = -EFAULT;
2723 else
2724 bytes_read = 1;
2726 break;
2728 case 2:
2729 if (sisusb_read_memio_word(sisusb,
2730 SISUSB_TYPE_IO,
2731 address, &buf16))
2732 errno = -EIO;
2733 else if (put_user(buf16, (u16 __user *)buffer))
2734 errno = -EFAULT;
2735 else
2736 bytes_read = 2;
2738 break;
2740 case 4:
2741 if (sisusb_read_memio_long(sisusb,
2742 SISUSB_TYPE_IO,
2743 address, &buf32))
2744 errno = -EIO;
2745 else if (put_user(buf32, (u32 __user *)buffer))
2746 errno = -EFAULT;
2747 else
2748 bytes_read = 4;
2750 break;
2752 default:
2753 errno = -EIO;
2757 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2758 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2760 address = (*ppos) -
2761 SISUSB_PCI_PSEUDO_MEMBASE +
2762 SISUSB_PCI_MEMBASE;
2764 /* Read video ram
2765 * Remember: Data delivered is never endian-corrected
2767 errno = sisusb_read_mem_bulk(sisusb, address,
2768 NULL, count, buffer, &bytes_read);
2770 if (bytes_read)
2771 errno = bytes_read;
2773 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2774 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2776 address = (*ppos) -
2777 SISUSB_PCI_PSEUDO_MMIOBASE +
2778 SISUSB_PCI_MMIOBASE;
2780 /* Read MMIO
2781 * Remember: Data delivered is never endian-corrected
2783 errno = sisusb_read_mem_bulk(sisusb, address,
2784 NULL, count, buffer, &bytes_read);
2786 if (bytes_read)
2787 errno = bytes_read;
2789 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2790 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2792 if (count != 4) {
2793 up(&sisusb->lock);
2794 return -EINVAL;
2797 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2799 /* Read PCI config register
2800 * Return value delivered in machine endianness.
2802 if (sisusb_read_pci_config(sisusb, address, &buf32))
2803 errno = -EIO;
2804 else if (put_user(buf32, (u32 __user *)buffer))
2805 errno = -EFAULT;
2806 else
2807 bytes_read = 4;
2809 } else {
2811 errno = -EBADFD;
2815 (*ppos) += bytes_read;
2817 up(&sisusb->lock);
2819 return errno ? errno : bytes_read;
2822 static ssize_t
2823 sisusb_write(struct file *file, const char __user *buffer, size_t count,
2824 loff_t *ppos)
2826 struct sisusb_usb_data *sisusb;
2827 int errno = 0;
2828 ssize_t bytes_written = 0;
2829 u8 buf8;
2830 u16 buf16;
2831 u32 buf32, address;
2833 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2834 return -ENODEV;
2836 down(&sisusb->lock);
2838 /* Sanity check */
2839 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2840 up(&sisusb->lock);
2841 return -ENODEV;
2844 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2845 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2847 address = (*ppos) -
2848 SISUSB_PCI_PSEUDO_IOPORTBASE +
2849 SISUSB_PCI_IOPORTBASE;
2851 /* Write i/o ports
2852 * Byte, word and long(32) can be written. As this
2853 * emulates outX instructions, the data is expected
2854 * in machine-endianness.
2856 switch (count) {
2858 case 1:
2859 if (get_user(buf8, (u8 __user *)buffer))
2860 errno = -EFAULT;
2861 else if (sisusb_write_memio_byte(sisusb,
2862 SISUSB_TYPE_IO,
2863 address, buf8))
2864 errno = -EIO;
2865 else
2866 bytes_written = 1;
2868 break;
2870 case 2:
2871 if (get_user(buf16, (u16 __user *)buffer))
2872 errno = -EFAULT;
2873 else if (sisusb_write_memio_word(sisusb,
2874 SISUSB_TYPE_IO,
2875 address, buf16))
2876 errno = -EIO;
2877 else
2878 bytes_written = 2;
2880 break;
2882 case 4:
2883 if (get_user(buf32, (u32 __user *)buffer))
2884 errno = -EFAULT;
2885 else if (sisusb_write_memio_long(sisusb,
2886 SISUSB_TYPE_IO,
2887 address, buf32))
2888 errno = -EIO;
2889 else
2890 bytes_written = 4;
2892 break;
2894 default:
2895 errno = -EIO;
2898 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2899 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2901 address = (*ppos) -
2902 SISUSB_PCI_PSEUDO_MEMBASE +
2903 SISUSB_PCI_MEMBASE;
2905 /* Write video ram.
2906 * Buffer is copied 1:1, therefore, on big-endian
2907 * machines, the data must be swapped by userland
2908 * in advance (if applicable; no swapping in 8bpp
2909 * mode or if YUV data is being transferred).
2911 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2912 count, buffer, 0, &bytes_written);
2914 if (bytes_written)
2915 errno = bytes_written;
2917 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2918 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2920 address = (*ppos) -
2921 SISUSB_PCI_PSEUDO_MMIOBASE +
2922 SISUSB_PCI_MMIOBASE;
2924 /* Write MMIO.
2925 * Buffer is copied 1:1, therefore, on big-endian
2926 * machines, the data must be swapped by userland
2927 * in advance.
2929 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2930 count, buffer, 0, &bytes_written);
2932 if (bytes_written)
2933 errno = bytes_written;
2935 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2936 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2938 if (count != 4) {
2939 up(&sisusb->lock);
2940 return -EINVAL;
2943 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2945 /* Write PCI config register.
2946 * Given value expected in machine endianness.
2948 if (get_user(buf32, (u32 __user *)buffer))
2949 errno = -EFAULT;
2950 else if (sisusb_write_pci_config(sisusb, address, buf32))
2951 errno = -EIO;
2952 else
2953 bytes_written = 4;
2956 } else {
2958 /* Error */
2959 errno = -EBADFD;
2963 (*ppos) += bytes_written;
2965 up(&sisusb->lock);
2967 return errno ? errno : bytes_written;
2970 static loff_t
2971 sisusb_lseek(struct file *file, loff_t offset, int orig)
2973 struct sisusb_usb_data *sisusb;
2974 loff_t ret;
2976 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2977 return -ENODEV;
2979 down(&sisusb->lock);
2981 /* Sanity check */
2982 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2983 up(&sisusb->lock);
2984 return -ENODEV;
2987 switch (orig) {
2988 case 0:
2989 file->f_pos = offset;
2990 ret = file->f_pos;
2991 /* never negative, no force_successful_syscall needed */
2992 break;
2993 case 1:
2994 file->f_pos += offset;
2995 ret = file->f_pos;
2996 /* never negative, no force_successful_syscall needed */
2997 break;
2998 default:
2999 /* seeking relative to "end of file" is not supported */
3000 ret = -EINVAL;
3003 up(&sisusb->lock);
3004 return ret;
3007 static int
3008 sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
3009 unsigned long arg)
3011 int retval, port, length;
3012 u32 address;
3014 /* All our commands require the device
3015 * to be initialized.
3017 if (!sisusb->devinit)
3018 return -ENODEV;
3020 port = y->data3 -
3021 SISUSB_PCI_PSEUDO_IOPORTBASE +
3022 SISUSB_PCI_IOPORTBASE;
3024 switch (y->operation) {
3025 case SUCMD_GET:
3026 retval = sisusb_getidxreg(sisusb, port,
3027 y->data0, &y->data1);
3028 if (!retval) {
3029 if (copy_to_user((void __user *)arg, y,
3030 sizeof(*y)))
3031 retval = -EFAULT;
3033 break;
3035 case SUCMD_SET:
3036 retval = sisusb_setidxreg(sisusb, port,
3037 y->data0, y->data1);
3038 break;
3040 case SUCMD_SETOR:
3041 retval = sisusb_setidxregor(sisusb, port,
3042 y->data0, y->data1);
3043 break;
3045 case SUCMD_SETAND:
3046 retval = sisusb_setidxregand(sisusb, port,
3047 y->data0, y->data1);
3048 break;
3050 case SUCMD_SETANDOR:
3051 retval = sisusb_setidxregandor(sisusb, port,
3052 y->data0, y->data1, y->data2);
3053 break;
3055 case SUCMD_SETMASK:
3056 retval = sisusb_setidxregmask(sisusb, port,
3057 y->data0, y->data1, y->data2);
3058 break;
3060 case SUCMD_CLRSCR:
3061 /* Gfx core must be initialized */
3062 if (!sisusb->gfxinit)
3063 return -ENODEV;
3065 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
3066 address = y->data3 -
3067 SISUSB_PCI_PSEUDO_MEMBASE +
3068 SISUSB_PCI_MEMBASE;
3069 retval = sisusb_clear_vram(sisusb, address, length);
3070 break;
3072 case SUCMD_HANDLETEXTMODE:
3073 retval = 0;
3074 #ifdef INCL_SISUSB_CON
3075 /* Gfx core must be initialized, SiS_Pr must exist */
3076 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3077 return -ENODEV;
3079 switch (y->data0) {
3080 case 0:
3081 retval = sisusb_reset_text_mode(sisusb, 0);
3082 break;
3083 case 1:
3084 sisusb->textmodedestroyed = 1;
3085 break;
3087 #endif
3088 break;
3090 #ifdef INCL_SISUSB_CON
3091 case SUCMD_SETMODE:
3092 /* Gfx core must be initialized, SiS_Pr must exist */
3093 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3094 return -ENODEV;
3096 retval = 0;
3098 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3099 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3101 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
3102 retval = -EINVAL;
3104 break;
3106 case SUCMD_SETVESAMODE:
3107 /* Gfx core must be initialized, SiS_Pr must exist */
3108 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3109 return -ENODEV;
3111 retval = 0;
3113 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3114 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3116 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
3117 retval = -EINVAL;
3119 break;
3120 #endif
3122 default:
3123 retval = -EINVAL;
3126 if (retval > 0)
3127 retval = -EIO;
3129 return retval;
3132 static int
3133 sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
3134 unsigned long arg)
3136 struct sisusb_usb_data *sisusb;
3137 struct sisusb_info x;
3138 struct sisusb_command y;
3139 int retval = 0;
3140 u32 __user *argp = (u32 __user *)arg;
3142 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
3143 return -ENODEV;
3145 down(&sisusb->lock);
3147 /* Sanity check */
3148 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
3149 retval = -ENODEV;
3150 goto err_out;
3153 switch (cmd) {
3155 case SISUSB_GET_CONFIG_SIZE:
3157 if (put_user(sizeof(x), argp))
3158 retval = -EFAULT;
3160 break;
3162 case SISUSB_GET_CONFIG:
3164 x.sisusb_id = SISUSB_ID;
3165 x.sisusb_version = SISUSB_VERSION;
3166 x.sisusb_revision = SISUSB_REVISION;
3167 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3168 x.sisusb_gfxinit = sisusb->gfxinit;
3169 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
3170 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
3171 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
3172 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
3173 x.sisusb_vramsize = sisusb->vramsize;
3174 x.sisusb_minor = sisusb->minor;
3175 x.sisusb_fbdevactive= 0;
3176 #ifdef INCL_SISUSB_CON
3177 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3178 #else
3179 x.sisusb_conactive = 0;
3180 #endif
3182 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3183 retval = -EFAULT;
3185 break;
3187 case SISUSB_COMMAND:
3189 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3190 retval = -EFAULT;
3191 else
3192 retval = sisusb_handle_command(sisusb, &y, arg);
3194 break;
3196 default:
3197 retval = -EINVAL;
3198 break;
3201 err_out:
3202 up(&sisusb->lock);
3203 return retval;
3206 #ifdef SISUSB_NEW_CONFIG_COMPAT
3207 static long
3208 sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3210 long retval;
3212 switch (cmd) {
3213 case SISUSB_GET_CONFIG_SIZE:
3214 case SISUSB_GET_CONFIG:
3215 case SISUSB_COMMAND:
3216 lock_kernel();
3217 retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
3218 unlock_kernel();
3219 return retval;
3221 default:
3222 return -ENOIOCTLCMD;
3225 #endif
3227 static struct file_operations usb_sisusb_fops = {
3228 .owner = THIS_MODULE,
3229 .open = sisusb_open,
3230 .release = sisusb_release,
3231 .read = sisusb_read,
3232 .write = sisusb_write,
3233 .llseek = sisusb_lseek,
3234 #ifdef SISUSB_NEW_CONFIG_COMPAT
3235 .compat_ioctl = sisusb_compat_ioctl,
3236 #endif
3237 .ioctl = sisusb_ioctl
3240 static struct usb_class_driver usb_sisusb_class = {
3241 .name = "sisusbvga%d",
3242 .fops = &usb_sisusb_fops,
3243 .minor_base = SISUSB_MINOR
3246 static int sisusb_probe(struct usb_interface *intf,
3247 const struct usb_device_id *id)
3249 struct usb_device *dev = interface_to_usbdev(intf);
3250 struct sisusb_usb_data *sisusb;
3251 int retval = 0, i;
3252 const char *memfail =
3253 KERN_ERR
3254 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3256 printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
3257 dev->devnum);
3259 /* Allocate memory for our private */
3260 if (!(sisusb = kmalloc(sizeof(*sisusb), GFP_KERNEL))) {
3261 printk(KERN_ERR
3262 "sisusb: Failed to allocate memory for private data\n");
3263 return -ENOMEM;
3265 memset(sisusb, 0, sizeof(*sisusb));
3266 kref_init(&sisusb->kref);
3268 init_MUTEX(&(sisusb->lock));
3270 /* Register device */
3271 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3272 printk(KERN_ERR
3273 "sisusb: Failed to get a minor for device %d\n",
3274 dev->devnum);
3275 retval = -ENODEV;
3276 goto error_1;
3279 sisusb->sisusb_dev = dev;
3280 sisusb->minor = intf->minor;
3281 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3282 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3283 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3284 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3285 /* Everything else is zero */
3287 /* Allocate buffers */
3288 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3289 if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3290 GFP_KERNEL, &sisusb->transfer_dma_in))) {
3291 printk(memfail, "input", sisusb->minor);
3292 retval = -ENOMEM;
3293 goto error_2;
3296 sisusb->numobufs = 0;
3297 sisusb->obufsize = SISUSB_OBUF_SIZE;
3298 for (i = 0; i < NUMOBUFS; i++) {
3299 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3300 GFP_KERNEL,
3301 &sisusb->transfer_dma_out[i]))) {
3302 if (i == 0) {
3303 printk(memfail, "output", sisusb->minor);
3304 retval = -ENOMEM;
3305 goto error_3;
3307 break;
3308 } else
3309 sisusb->numobufs++;
3313 /* Allocate URBs */
3314 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3315 printk(KERN_ERR
3316 "sisusbvga[%d]: Failed to allocate URBs\n",
3317 sisusb->minor);
3318 retval = -ENOMEM;
3319 goto error_3;
3321 sisusb->completein = 1;
3323 for (i = 0; i < sisusb->numobufs; i++) {
3324 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3325 printk(KERN_ERR
3326 "sisusbvga[%d]: Failed to allocate URBs\n",
3327 sisusb->minor);
3328 retval = -ENOMEM;
3329 goto error_4;
3331 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3332 sisusb->urbout_context[i].urbindex = i;
3333 sisusb->urbstatus[i] = 0;
3336 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
3337 sisusb->minor, sisusb->numobufs);
3339 #ifdef INCL_SISUSB_CON
3340 /* Allocate our SiS_Pr */
3341 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3342 printk(KERN_ERR
3343 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3344 sisusb->minor);
3346 #endif
3348 /* Do remaining init stuff */
3350 init_waitqueue_head(&sisusb->wait_q);
3352 usb_set_intfdata(intf, sisusb);
3354 usb_get_dev(sisusb->sisusb_dev);
3356 sisusb->present = 1;
3358 #ifdef SISUSB_OLD_CONFIG_COMPAT
3360 int ret;
3361 /* Our ioctls are all "32/64bit compatible" */
3362 ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
3363 ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
3364 ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
3365 if (ret)
3366 printk(KERN_ERR
3367 "sisusbvga[%d]: Error registering ioctl32 "
3368 "translations\n",
3369 sisusb->minor);
3370 else
3371 sisusb->ioctl32registered = 1;
3373 #endif
3375 if (dev->speed == USB_SPEED_HIGH) {
3376 int initscreen = 1;
3377 #ifdef INCL_SISUSB_CON
3378 if (sisusb_first_vc > 0 &&
3379 sisusb_last_vc > 0 &&
3380 sisusb_first_vc <= sisusb_last_vc &&
3381 sisusb_last_vc <= MAX_NR_CONSOLES)
3382 initscreen = 0;
3383 #endif
3384 if (sisusb_init_gfxdevice(sisusb, initscreen))
3385 printk(KERN_ERR
3386 "sisusbvga[%d]: Failed to early "
3387 "initialize device\n",
3388 sisusb->minor);
3390 } else
3391 printk(KERN_INFO
3392 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3393 "deferring init\n",
3394 sisusb->minor);
3396 sisusb->ready = 1;
3398 #ifdef SISUSBENDIANTEST
3399 printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
3400 sisusb_testreadwrite(sisusb);
3401 printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
3402 #endif
3404 #ifdef INCL_SISUSB_CON
3405 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3406 #endif
3408 return 0;
3410 error_4:
3411 sisusb_free_urbs(sisusb);
3412 error_3:
3413 sisusb_free_buffers(sisusb);
3414 error_2:
3415 usb_deregister_dev(intf, &usb_sisusb_class);
3416 error_1:
3417 kfree(sisusb);
3418 return retval;
3421 static void sisusb_disconnect(struct usb_interface *intf)
3423 struct sisusb_usb_data *sisusb;
3424 int minor;
3426 /* This should *not* happen */
3427 if (!(sisusb = usb_get_intfdata(intf)))
3428 return;
3430 #ifdef INCL_SISUSB_CON
3431 sisusb_console_exit(sisusb);
3432 #endif
3434 /* The above code doesn't need the disconnect
3435 * semaphore to be down; its meaning is to
3436 * protect all other routines from the disconnect
3437 * case, not the other way round.
3439 down(&disconnect_sem);
3441 down(&sisusb->lock);
3443 /* Wait for all URBs to complete and kill them in case (MUST do) */
3444 if (!sisusb_wait_all_out_complete(sisusb))
3445 sisusb_kill_all_busy(sisusb);
3447 minor = sisusb->minor;
3449 usb_set_intfdata(intf, NULL);
3451 usb_deregister_dev(intf, &usb_sisusb_class);
3453 #ifdef SISUSB_OLD_CONFIG_COMPAT
3454 if (sisusb->ioctl32registered) {
3455 int ret;
3456 sisusb->ioctl32registered = 0;
3457 ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
3458 ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
3459 ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
3460 if (ret) {
3461 printk(KERN_ERR
3462 "sisusbvga[%d]: Error unregistering "
3463 "ioctl32 translations\n",
3464 minor);
3467 #endif
3469 sisusb->present = 0;
3470 sisusb->ready = 0;
3472 up(&sisusb->lock);
3474 /* decrement our usage count */
3475 kref_put(&sisusb->kref, sisusb_delete);
3477 up(&disconnect_sem);
3479 printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
3482 static struct usb_device_id sisusb_table [] = {
3483 { USB_DEVICE(0x0711, 0x0900) },
3484 { USB_DEVICE(0x182d, 0x021c) },
3485 { USB_DEVICE(0x182d, 0x0269) },
3489 MODULE_DEVICE_TABLE (usb, sisusb_table);
3491 static struct usb_driver sisusb_driver = {
3492 .name = "sisusb",
3493 .probe = sisusb_probe,
3494 .disconnect = sisusb_disconnect,
3495 .id_table = sisusb_table,
3498 static int __init usb_sisusb_init(void)
3500 int retval;
3502 #ifdef INCL_SISUSB_CON
3503 sisusb_init_concode();
3504 #endif
3506 if (!(retval = usb_register(&sisusb_driver))) {
3508 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
3509 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
3510 printk(KERN_INFO
3511 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3515 return retval;
3518 static void __exit usb_sisusb_exit(void)
3520 usb_deregister(&sisusb_driver);
3523 module_init(usb_sisusb_init);
3524 module_exit(usb_sisusb_exit);
3526 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3527 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3528 MODULE_LICENSE("GPL");