Merge tag 'ceph-for-4.13-rc8' of git://github.com/ceph/ceph-client
[linux/fpc-iii.git] / drivers / usb / misc / sisusbvga / sisusb.c
blob440d7fef58cc6d18f1b7e55f96ddba63b0a97043
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/mutex.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/errno.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/slab.h>
47 #include <linux/spinlock.h>
48 #include <linux/kref.h>
49 #include <linux/usb.h>
50 #include <linux/vmalloc.h>
52 #include "sisusb.h"
53 #include "sisusb_init.h"
55 #ifdef INCL_SISUSB_CON
56 #include <linux/font.h>
57 #endif
59 #define SISUSB_DONTSYNC
61 /* Forward declarations / clean-up routines */
63 #ifdef INCL_SISUSB_CON
64 static int sisusb_first_vc;
65 static int sisusb_last_vc;
66 module_param_named(first, sisusb_first_vc, int, 0);
67 module_param_named(last, sisusb_last_vc, int, 0);
68 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
69 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
70 #endif
72 static struct usb_driver sisusb_driver;
74 static void sisusb_free_buffers(struct sisusb_usb_data *sisusb)
76 int i;
78 for (i = 0; i < NUMOBUFS; i++) {
79 kfree(sisusb->obuf[i]);
80 sisusb->obuf[i] = NULL;
82 kfree(sisusb->ibuf);
83 sisusb->ibuf = NULL;
86 static void sisusb_free_urbs(struct sisusb_usb_data *sisusb)
88 int i;
90 for (i = 0; i < NUMOBUFS; i++) {
91 usb_free_urb(sisusb->sisurbout[i]);
92 sisusb->sisurbout[i] = NULL;
94 usb_free_urb(sisusb->sisurbin);
95 sisusb->sisurbin = NULL;
98 /* Level 0: USB transport layer */
100 /* 1. out-bulks */
102 /* out-urb management */
104 /* Return 1 if all free, 0 otherwise */
105 static int sisusb_all_free(struct sisusb_usb_data *sisusb)
107 int i;
109 for (i = 0; i < sisusb->numobufs; i++) {
111 if (sisusb->urbstatus[i] & SU_URB_BUSY)
112 return 0;
116 return 1;
119 /* Kill all busy URBs */
120 static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
122 int i;
124 if (sisusb_all_free(sisusb))
125 return;
127 for (i = 0; i < sisusb->numobufs; i++) {
129 if (sisusb->urbstatus[i] & SU_URB_BUSY)
130 usb_kill_urb(sisusb->sisurbout[i]);
135 /* Return 1 if ok, 0 if error (not all complete within timeout) */
136 static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
138 int timeout = 5 * HZ, i = 1;
140 wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)),
141 timeout);
143 return i;
146 static int sisusb_outurb_available(struct sisusb_usb_data *sisusb)
148 int i;
150 for (i = 0; i < sisusb->numobufs; i++) {
152 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
153 return i;
157 return -1;
160 static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
162 int i, timeout = 5 * HZ;
164 wait_event_timeout(sisusb->wait_q,
165 ((i = sisusb_outurb_available(sisusb)) >= 0), timeout);
167 return i;
170 static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
172 int i;
174 i = sisusb_outurb_available(sisusb);
176 if (i >= 0)
177 sisusb->urbstatus[i] |= SU_URB_ALLOC;
179 return i;
182 static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
184 if ((index >= 0) && (index < sisusb->numobufs))
185 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
188 /* completion callback */
190 static void sisusb_bulk_completeout(struct urb *urb)
192 struct sisusb_urb_context *context = urb->context;
193 struct sisusb_usb_data *sisusb;
195 if (!context)
196 return;
198 sisusb = context->sisusb;
200 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
201 return;
203 #ifndef SISUSB_DONTSYNC
204 if (context->actual_length)
205 *(context->actual_length) += urb->actual_length;
206 #endif
208 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
209 wake_up(&sisusb->wait_q);
212 static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index,
213 unsigned int pipe, void *data, int len, int *actual_length,
214 int timeout, unsigned int tflags)
216 struct urb *urb = sisusb->sisurbout[index];
217 int retval, byteswritten = 0;
219 /* Set up URB */
220 urb->transfer_flags = 0;
222 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
223 sisusb_bulk_completeout,
224 &sisusb->urbout_context[index]);
226 urb->transfer_flags |= tflags;
227 urb->actual_length = 0;
229 /* Set up context */
230 sisusb->urbout_context[index].actual_length = (timeout) ?
231 NULL : actual_length;
233 /* Declare this urb/buffer in use */
234 sisusb->urbstatus[index] |= SU_URB_BUSY;
236 /* Submit URB */
237 retval = usb_submit_urb(urb, GFP_KERNEL);
239 /* If OK, and if timeout > 0, wait for completion */
240 if ((retval == 0) && timeout) {
241 wait_event_timeout(sisusb->wait_q,
242 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
243 timeout);
244 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
245 /* URB timed out... kill it and report error */
246 usb_kill_urb(urb);
247 retval = -ETIMEDOUT;
248 } else {
249 /* Otherwise, report urb status */
250 retval = urb->status;
251 byteswritten = urb->actual_length;
255 if (actual_length)
256 *actual_length = byteswritten;
258 return retval;
261 /* 2. in-bulks */
263 /* completion callback */
265 static void sisusb_bulk_completein(struct urb *urb)
267 struct sisusb_usb_data *sisusb = urb->context;
269 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
270 return;
272 sisusb->completein = 1;
273 wake_up(&sisusb->wait_q);
276 static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb,
277 unsigned int pipe, void *data, int len,
278 int *actual_length, int timeout, unsigned int tflags)
280 struct urb *urb = sisusb->sisurbin;
281 int retval, readbytes = 0;
283 urb->transfer_flags = 0;
285 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
286 sisusb_bulk_completein, sisusb);
288 urb->transfer_flags |= tflags;
289 urb->actual_length = 0;
291 sisusb->completein = 0;
292 retval = usb_submit_urb(urb, GFP_KERNEL);
293 if (retval == 0) {
294 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
295 if (!sisusb->completein) {
296 /* URB timed out... kill it and report error */
297 usb_kill_urb(urb);
298 retval = -ETIMEDOUT;
299 } else {
300 /* URB completed within timeout */
301 retval = urb->status;
302 readbytes = urb->actual_length;
306 if (actual_length)
307 *actual_length = readbytes;
309 return retval;
313 /* Level 1: */
315 /* Send a bulk message of variable size
317 * To copy the data from userspace, give pointer to "userbuffer",
318 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
319 * both of these are NULL, it is assumed, that the transfer
320 * buffer "sisusb->obuf[index]" is set up with the data to send.
321 * Index is ignored if either kernbuffer or userbuffer is set.
322 * If async is nonzero, URBs will be sent without waiting for
323 * completion of the previous URB.
325 * (return 0 on success)
328 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
329 char *kernbuffer, const char __user *userbuffer, int index,
330 ssize_t *bytes_written, unsigned int tflags, int async)
332 int result = 0, retry, count = len;
333 int passsize, thispass, transferred_len = 0;
334 int fromuser = (userbuffer != NULL) ? 1 : 0;
335 int fromkern = (kernbuffer != NULL) ? 1 : 0;
336 unsigned int pipe;
337 char *buffer;
339 (*bytes_written) = 0;
341 /* Sanity check */
342 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
343 return -ENODEV;
345 /* If we copy data from kernel or userspace, force the
346 * allocation of a buffer/urb. If we have the data in
347 * the transfer buffer[index] already, reuse the buffer/URB
348 * if the length is > buffer size. (So, transmitting
349 * large data amounts directly from the transfer buffer
350 * treats the buffer as a ring buffer. However, we need
351 * to sync in this case.)
353 if (fromuser || fromkern)
354 index = -1;
355 else if (len > sisusb->obufsize)
356 async = 0;
358 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
360 do {
361 passsize = thispass = (sisusb->obufsize < count) ?
362 sisusb->obufsize : count;
364 if (index < 0)
365 index = sisusb_get_free_outbuf(sisusb);
367 if (index < 0)
368 return -EIO;
370 buffer = sisusb->obuf[index];
372 if (fromuser) {
374 if (copy_from_user(buffer, userbuffer, passsize))
375 return -EFAULT;
377 userbuffer += passsize;
379 } else if (fromkern) {
381 memcpy(buffer, kernbuffer, passsize);
382 kernbuffer += passsize;
386 retry = 5;
387 while (thispass) {
389 if (!sisusb->sisusb_dev)
390 return -ENODEV;
392 result = sisusb_bulkout_msg(sisusb, index, pipe,
393 buffer, thispass, &transferred_len,
394 async ? 0 : 5 * HZ, tflags);
396 if (result == -ETIMEDOUT) {
398 /* Will not happen if async */
399 if (!retry--)
400 return -ETIME;
402 continue;
405 if ((result == 0) && !async && transferred_len) {
407 thispass -= transferred_len;
408 buffer += transferred_len;
410 } else
411 break;
414 if (result)
415 return result;
417 (*bytes_written) += passsize;
418 count -= passsize;
420 /* Force new allocation in next iteration */
421 if (fromuser || fromkern)
422 index = -1;
424 } while (count > 0);
426 if (async) {
427 #ifdef SISUSB_DONTSYNC
428 (*bytes_written) = len;
429 /* Some URBs/buffers might be busy */
430 #else
431 sisusb_wait_all_out_complete(sisusb);
432 (*bytes_written) = transferred_len;
433 /* All URBs and all buffers are available */
434 #endif
437 return ((*bytes_written) == len) ? 0 : -EIO;
440 /* Receive a bulk message of variable size
442 * To copy the data to userspace, give pointer to "userbuffer",
443 * to copy to kernel memory, give "kernbuffer". One of them
444 * MUST be set. (There is no technique for letting the caller
445 * read directly from the ibuf.)
449 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
450 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
451 unsigned int tflags)
453 int result = 0, retry, count = len;
454 int bufsize, thispass, transferred_len;
455 unsigned int pipe;
456 char *buffer;
458 (*bytes_read) = 0;
460 /* Sanity check */
461 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
462 return -ENODEV;
464 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
465 buffer = sisusb->ibuf;
466 bufsize = sisusb->ibufsize;
468 retry = 5;
470 #ifdef SISUSB_DONTSYNC
471 if (!(sisusb_wait_all_out_complete(sisusb)))
472 return -EIO;
473 #endif
475 while (count > 0) {
477 if (!sisusb->sisusb_dev)
478 return -ENODEV;
480 thispass = (bufsize < count) ? bufsize : count;
482 result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass,
483 &transferred_len, 5 * HZ, tflags);
485 if (transferred_len)
486 thispass = transferred_len;
488 else if (result == -ETIMEDOUT) {
490 if (!retry--)
491 return -ETIME;
493 continue;
495 } else
496 return -EIO;
499 if (thispass) {
501 (*bytes_read) += thispass;
502 count -= thispass;
504 if (userbuffer) {
506 if (copy_to_user(userbuffer, buffer, thispass))
507 return -EFAULT;
509 userbuffer += thispass;
511 } else {
513 memcpy(kernbuffer, buffer, thispass);
514 kernbuffer += thispass;
522 return ((*bytes_read) == len) ? 0 : -EIO;
525 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
526 struct sisusb_packet *packet)
528 int ret;
529 ssize_t bytes_transferred = 0;
530 __le32 tmp;
532 if (len == 6)
533 packet->data = 0;
535 #ifdef SISUSB_DONTSYNC
536 if (!(sisusb_wait_all_out_complete(sisusb)))
537 return 1;
538 #endif
540 /* Eventually correct endianness */
541 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
543 /* 1. send the packet */
544 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
545 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
547 if ((ret == 0) && (len == 6)) {
549 /* 2. if packet len == 6, it means we read, so wait for 32bit
550 * return value and write it to packet->data
552 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
553 (char *)&tmp, NULL, &bytes_transferred, 0);
555 packet->data = le32_to_cpu(tmp);
558 return ret;
561 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
562 struct sisusb_packet *packet, unsigned int tflags)
564 int ret;
565 ssize_t bytes_transferred = 0;
566 __le32 tmp;
568 if (len == 6)
569 packet->data = 0;
571 #ifdef SISUSB_DONTSYNC
572 if (!(sisusb_wait_all_out_complete(sisusb)))
573 return 1;
574 #endif
576 /* Eventually correct endianness */
577 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
579 /* 1. send the packet */
580 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
581 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
583 if ((ret == 0) && (len == 6)) {
585 /* 2. if packet len == 6, it means we read, so wait for 32bit
586 * return value and write it to packet->data
588 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
589 (char *)&tmp, NULL, &bytes_transferred, 0);
591 packet->data = le32_to_cpu(tmp);
594 return ret;
597 /* access video memory and mmio (return 0 on success) */
599 /* Low level */
601 /* The following routines assume being used to transfer byte, word,
602 * long etc.
603 * This means that
604 * - the write routines expect "data" in machine endianness format.
605 * The data will be converted to leXX in sisusb_xxx_packet.
606 * - the read routines can expect read data in machine-endianess.
609 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
610 u32 addr, u8 data)
612 struct sisusb_packet packet;
613 int ret;
615 packet.header = (1 << (addr & 3)) | (type << 6);
616 packet.address = addr & ~3;
617 packet.data = data << ((addr & 3) << 3);
618 ret = sisusb_send_packet(sisusb, 10, &packet);
619 return ret;
622 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
623 u32 addr, u16 data)
625 struct sisusb_packet packet;
626 int ret = 0;
628 packet.address = addr & ~3;
630 switch (addr & 3) {
631 case 0:
632 packet.header = (type << 6) | 0x0003;
633 packet.data = (u32)data;
634 ret = sisusb_send_packet(sisusb, 10, &packet);
635 break;
636 case 1:
637 packet.header = (type << 6) | 0x0006;
638 packet.data = (u32)data << 8;
639 ret = sisusb_send_packet(sisusb, 10, &packet);
640 break;
641 case 2:
642 packet.header = (type << 6) | 0x000c;
643 packet.data = (u32)data << 16;
644 ret = sisusb_send_packet(sisusb, 10, &packet);
645 break;
646 case 3:
647 packet.header = (type << 6) | 0x0008;
648 packet.data = (u32)data << 24;
649 ret = sisusb_send_packet(sisusb, 10, &packet);
650 packet.header = (type << 6) | 0x0001;
651 packet.address = (addr & ~3) + 4;
652 packet.data = (u32)data >> 8;
653 ret |= sisusb_send_packet(sisusb, 10, &packet);
656 return ret;
659 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
660 u32 addr, u32 data)
662 struct sisusb_packet packet;
663 int ret = 0;
665 packet.address = addr & ~3;
667 switch (addr & 3) {
668 case 0:
669 packet.header = (type << 6) | 0x0007;
670 packet.data = data & 0x00ffffff;
671 ret = sisusb_send_packet(sisusb, 10, &packet);
672 break;
673 case 1:
674 packet.header = (type << 6) | 0x000e;
675 packet.data = data << 8;
676 ret = sisusb_send_packet(sisusb, 10, &packet);
677 break;
678 case 2:
679 packet.header = (type << 6) | 0x000c;
680 packet.data = data << 16;
681 ret = sisusb_send_packet(sisusb, 10, &packet);
682 packet.header = (type << 6) | 0x0001;
683 packet.address = (addr & ~3) + 4;
684 packet.data = (data >> 16) & 0x00ff;
685 ret |= sisusb_send_packet(sisusb, 10, &packet);
686 break;
687 case 3:
688 packet.header = (type << 6) | 0x0008;
689 packet.data = data << 24;
690 ret = sisusb_send_packet(sisusb, 10, &packet);
691 packet.header = (type << 6) | 0x0003;
692 packet.address = (addr & ~3) + 4;
693 packet.data = (data >> 8) & 0xffff;
694 ret |= sisusb_send_packet(sisusb, 10, &packet);
697 return ret;
700 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
701 u32 addr, u32 data)
703 struct sisusb_packet packet;
704 int ret = 0;
706 packet.address = addr & ~3;
708 switch (addr & 3) {
709 case 0:
710 packet.header = (type << 6) | 0x000f;
711 packet.data = data;
712 ret = sisusb_send_packet(sisusb, 10, &packet);
713 break;
714 case 1:
715 packet.header = (type << 6) | 0x000e;
716 packet.data = data << 8;
717 ret = sisusb_send_packet(sisusb, 10, &packet);
718 packet.header = (type << 6) | 0x0001;
719 packet.address = (addr & ~3) + 4;
720 packet.data = data >> 24;
721 ret |= sisusb_send_packet(sisusb, 10, &packet);
722 break;
723 case 2:
724 packet.header = (type << 6) | 0x000c;
725 packet.data = data << 16;
726 ret = sisusb_send_packet(sisusb, 10, &packet);
727 packet.header = (type << 6) | 0x0003;
728 packet.address = (addr & ~3) + 4;
729 packet.data = data >> 16;
730 ret |= sisusb_send_packet(sisusb, 10, &packet);
731 break;
732 case 3:
733 packet.header = (type << 6) | 0x0008;
734 packet.data = data << 24;
735 ret = sisusb_send_packet(sisusb, 10, &packet);
736 packet.header = (type << 6) | 0x0007;
737 packet.address = (addr & ~3) + 4;
738 packet.data = data >> 8;
739 ret |= sisusb_send_packet(sisusb, 10, &packet);
742 return ret;
745 /* The xxx_bulk routines copy a buffer of variable size. They treat the
746 * buffer as chars, therefore lsb/msb has to be corrected if using the
747 * byte/word/long/etc routines for speed-up
749 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
750 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
751 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
752 * that the data already is in the transfer buffer "sisusb->obuf[index]".
755 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
756 char *kernbuffer, int length, const char __user *userbuffer,
757 int index, ssize_t *bytes_written)
759 struct sisusb_packet packet;
760 int ret = 0;
761 static int msgcount;
762 u8 swap8, fromkern = kernbuffer ? 1 : 0;
763 u16 swap16;
764 u32 swap32, flag = (length >> 28) & 1;
765 char buf[4];
767 /* if neither kernbuffer not userbuffer are given, assume
768 * data in obuf
770 if (!fromkern && !userbuffer)
771 kernbuffer = sisusb->obuf[index];
773 (*bytes_written = 0);
775 length &= 0x00ffffff;
777 while (length) {
778 switch (length) {
779 case 1:
780 if (userbuffer) {
781 if (get_user(swap8, (u8 __user *)userbuffer))
782 return -EFAULT;
783 } else
784 swap8 = kernbuffer[0];
786 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
787 addr, swap8);
789 if (!ret)
790 (*bytes_written)++;
792 return ret;
794 case 2:
795 if (userbuffer) {
796 if (get_user(swap16, (u16 __user *)userbuffer))
797 return -EFAULT;
798 } else
799 swap16 = *((u16 *)kernbuffer);
801 ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
802 addr, swap16);
804 if (!ret)
805 (*bytes_written) += 2;
807 return ret;
809 case 3:
810 if (userbuffer) {
811 if (copy_from_user(&buf, userbuffer, 3))
812 return -EFAULT;
813 #ifdef __BIG_ENDIAN
814 swap32 = (buf[0] << 16) |
815 (buf[1] << 8) |
816 buf[2];
817 #else
818 swap32 = (buf[2] << 16) |
819 (buf[1] << 8) |
820 buf[0];
821 #endif
822 } else
823 #ifdef __BIG_ENDIAN
824 swap32 = (kernbuffer[0] << 16) |
825 (kernbuffer[1] << 8) |
826 kernbuffer[2];
827 #else
828 swap32 = (kernbuffer[2] << 16) |
829 (kernbuffer[1] << 8) |
830 kernbuffer[0];
831 #endif
833 ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
834 addr, swap32);
836 if (!ret)
837 (*bytes_written) += 3;
839 return ret;
841 case 4:
842 if (userbuffer) {
843 if (get_user(swap32, (u32 __user *)userbuffer))
844 return -EFAULT;
845 } else
846 swap32 = *((u32 *)kernbuffer);
848 ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
849 addr, swap32);
850 if (!ret)
851 (*bytes_written) += 4;
853 return ret;
855 default:
856 if ((length & ~3) > 0x10000) {
858 packet.header = 0x001f;
859 packet.address = 0x000001d4;
860 packet.data = addr;
861 ret = sisusb_send_bridge_packet(sisusb, 10,
862 &packet, 0);
863 packet.header = 0x001f;
864 packet.address = 0x000001d0;
865 packet.data = (length & ~3);
866 ret |= sisusb_send_bridge_packet(sisusb, 10,
867 &packet, 0);
868 packet.header = 0x001f;
869 packet.address = 0x000001c0;
870 packet.data = flag | 0x16;
871 ret |= sisusb_send_bridge_packet(sisusb, 10,
872 &packet, 0);
873 if (userbuffer) {
874 ret |= sisusb_send_bulk_msg(sisusb,
875 SISUSB_EP_GFX_LBULK_OUT,
876 (length & ~3),
877 NULL, userbuffer, 0,
878 bytes_written, 0, 1);
879 userbuffer += (*bytes_written);
880 } else if (fromkern) {
881 ret |= sisusb_send_bulk_msg(sisusb,
882 SISUSB_EP_GFX_LBULK_OUT,
883 (length & ~3),
884 kernbuffer, NULL, 0,
885 bytes_written, 0, 1);
886 kernbuffer += (*bytes_written);
887 } else {
888 ret |= sisusb_send_bulk_msg(sisusb,
889 SISUSB_EP_GFX_LBULK_OUT,
890 (length & ~3),
891 NULL, NULL, index,
892 bytes_written, 0, 1);
893 kernbuffer += ((*bytes_written) &
894 (sisusb->obufsize-1));
897 } else {
899 packet.header = 0x001f;
900 packet.address = 0x00000194;
901 packet.data = addr;
902 ret = sisusb_send_bridge_packet(sisusb, 10,
903 &packet, 0);
904 packet.header = 0x001f;
905 packet.address = 0x00000190;
906 packet.data = (length & ~3);
907 ret |= sisusb_send_bridge_packet(sisusb, 10,
908 &packet, 0);
909 if (sisusb->flagb0 != 0x16) {
910 packet.header = 0x001f;
911 packet.address = 0x00000180;
912 packet.data = flag | 0x16;
913 ret |= sisusb_send_bridge_packet(sisusb,
914 10, &packet, 0);
915 sisusb->flagb0 = 0x16;
917 if (userbuffer) {
918 ret |= sisusb_send_bulk_msg(sisusb,
919 SISUSB_EP_GFX_BULK_OUT,
920 (length & ~3),
921 NULL, userbuffer, 0,
922 bytes_written, 0, 1);
923 userbuffer += (*bytes_written);
924 } else if (fromkern) {
925 ret |= sisusb_send_bulk_msg(sisusb,
926 SISUSB_EP_GFX_BULK_OUT,
927 (length & ~3),
928 kernbuffer, NULL, 0,
929 bytes_written, 0, 1);
930 kernbuffer += (*bytes_written);
931 } else {
932 ret |= sisusb_send_bulk_msg(sisusb,
933 SISUSB_EP_GFX_BULK_OUT,
934 (length & ~3),
935 NULL, NULL, index,
936 bytes_written, 0, 1);
937 kernbuffer += ((*bytes_written) &
938 (sisusb->obufsize-1));
941 if (ret) {
942 msgcount++;
943 if (msgcount < 500)
944 dev_err(&sisusb->sisusb_dev->dev,
945 "Wrote %zd of %d bytes, error %d\n",
946 *bytes_written, length,
947 ret);
948 else if (msgcount == 500)
949 dev_err(&sisusb->sisusb_dev->dev,
950 "Too many errors, logging stopped\n");
952 addr += (*bytes_written);
953 length -= (*bytes_written);
956 if (ret)
957 break;
961 return ret ? -EIO : 0;
964 /* Remember: Read data in packet is in machine-endianess! So for
965 * byte, word, 24bit, long no endian correction is necessary.
968 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
969 u32 addr, u8 *data)
971 struct sisusb_packet packet;
972 int ret;
974 CLEARPACKET(&packet);
975 packet.header = (1 << (addr & 3)) | (type << 6);
976 packet.address = addr & ~3;
977 ret = sisusb_send_packet(sisusb, 6, &packet);
978 *data = (u8)(packet.data >> ((addr & 3) << 3));
979 return ret;
982 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
983 u32 addr, u16 *data)
985 struct sisusb_packet packet;
986 int ret = 0;
988 CLEARPACKET(&packet);
990 packet.address = addr & ~3;
992 switch (addr & 3) {
993 case 0:
994 packet.header = (type << 6) | 0x0003;
995 ret = sisusb_send_packet(sisusb, 6, &packet);
996 *data = (u16)(packet.data);
997 break;
998 case 1:
999 packet.header = (type << 6) | 0x0006;
1000 ret = sisusb_send_packet(sisusb, 6, &packet);
1001 *data = (u16)(packet.data >> 8);
1002 break;
1003 case 2:
1004 packet.header = (type << 6) | 0x000c;
1005 ret = sisusb_send_packet(sisusb, 6, &packet);
1006 *data = (u16)(packet.data >> 16);
1007 break;
1008 case 3:
1009 packet.header = (type << 6) | 0x0008;
1010 ret = sisusb_send_packet(sisusb, 6, &packet);
1011 *data = (u16)(packet.data >> 24);
1012 packet.header = (type << 6) | 0x0001;
1013 packet.address = (addr & ~3) + 4;
1014 ret |= sisusb_send_packet(sisusb, 6, &packet);
1015 *data |= (u16)(packet.data << 8);
1018 return ret;
1021 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1022 u32 addr, u32 *data)
1024 struct sisusb_packet packet;
1025 int ret = 0;
1027 packet.address = addr & ~3;
1029 switch (addr & 3) {
1030 case 0:
1031 packet.header = (type << 6) | 0x0007;
1032 ret = sisusb_send_packet(sisusb, 6, &packet);
1033 *data = packet.data & 0x00ffffff;
1034 break;
1035 case 1:
1036 packet.header = (type << 6) | 0x000e;
1037 ret = sisusb_send_packet(sisusb, 6, &packet);
1038 *data = packet.data >> 8;
1039 break;
1040 case 2:
1041 packet.header = (type << 6) | 0x000c;
1042 ret = sisusb_send_packet(sisusb, 6, &packet);
1043 *data = packet.data >> 16;
1044 packet.header = (type << 6) | 0x0001;
1045 packet.address = (addr & ~3) + 4;
1046 ret |= sisusb_send_packet(sisusb, 6, &packet);
1047 *data |= ((packet.data & 0xff) << 16);
1048 break;
1049 case 3:
1050 packet.header = (type << 6) | 0x0008;
1051 ret = sisusb_send_packet(sisusb, 6, &packet);
1052 *data = packet.data >> 24;
1053 packet.header = (type << 6) | 0x0003;
1054 packet.address = (addr & ~3) + 4;
1055 ret |= sisusb_send_packet(sisusb, 6, &packet);
1056 *data |= ((packet.data & 0xffff) << 8);
1059 return ret;
1062 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1063 u32 addr, u32 *data)
1065 struct sisusb_packet packet;
1066 int ret = 0;
1068 packet.address = addr & ~3;
1070 switch (addr & 3) {
1071 case 0:
1072 packet.header = (type << 6) | 0x000f;
1073 ret = sisusb_send_packet(sisusb, 6, &packet);
1074 *data = packet.data;
1075 break;
1076 case 1:
1077 packet.header = (type << 6) | 0x000e;
1078 ret = sisusb_send_packet(sisusb, 6, &packet);
1079 *data = packet.data >> 8;
1080 packet.header = (type << 6) | 0x0001;
1081 packet.address = (addr & ~3) + 4;
1082 ret |= sisusb_send_packet(sisusb, 6, &packet);
1083 *data |= (packet.data << 24);
1084 break;
1085 case 2:
1086 packet.header = (type << 6) | 0x000c;
1087 ret = sisusb_send_packet(sisusb, 6, &packet);
1088 *data = packet.data >> 16;
1089 packet.header = (type << 6) | 0x0003;
1090 packet.address = (addr & ~3) + 4;
1091 ret |= sisusb_send_packet(sisusb, 6, &packet);
1092 *data |= (packet.data << 16);
1093 break;
1094 case 3:
1095 packet.header = (type << 6) | 0x0008;
1096 ret = sisusb_send_packet(sisusb, 6, &packet);
1097 *data = packet.data >> 24;
1098 packet.header = (type << 6) | 0x0007;
1099 packet.address = (addr & ~3) + 4;
1100 ret |= sisusb_send_packet(sisusb, 6, &packet);
1101 *data |= (packet.data << 8);
1104 return ret;
1107 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1108 char *kernbuffer, int length, char __user *userbuffer,
1109 ssize_t *bytes_read)
1111 int ret = 0;
1112 char buf[4];
1113 u16 swap16;
1114 u32 swap32;
1116 (*bytes_read = 0);
1118 length &= 0x00ffffff;
1120 while (length) {
1121 switch (length) {
1122 case 1:
1123 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1124 addr, &buf[0]);
1125 if (!ret) {
1126 (*bytes_read)++;
1127 if (userbuffer) {
1128 if (put_user(buf[0], (u8 __user *)userbuffer))
1129 return -EFAULT;
1130 } else
1131 kernbuffer[0] = buf[0];
1133 return ret;
1135 case 2:
1136 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1137 addr, &swap16);
1138 if (!ret) {
1139 (*bytes_read) += 2;
1140 if (userbuffer) {
1141 if (put_user(swap16, (u16 __user *)userbuffer))
1142 return -EFAULT;
1143 } else {
1144 *((u16 *)kernbuffer) = swap16;
1147 return ret;
1149 case 3:
1150 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1151 addr, &swap32);
1152 if (!ret) {
1153 (*bytes_read) += 3;
1154 #ifdef __BIG_ENDIAN
1155 buf[0] = (swap32 >> 16) & 0xff;
1156 buf[1] = (swap32 >> 8) & 0xff;
1157 buf[2] = swap32 & 0xff;
1158 #else
1159 buf[2] = (swap32 >> 16) & 0xff;
1160 buf[1] = (swap32 >> 8) & 0xff;
1161 buf[0] = swap32 & 0xff;
1162 #endif
1163 if (userbuffer) {
1164 if (copy_to_user(userbuffer,
1165 &buf[0], 3))
1166 return -EFAULT;
1167 } else {
1168 kernbuffer[0] = buf[0];
1169 kernbuffer[1] = buf[1];
1170 kernbuffer[2] = buf[2];
1173 return ret;
1175 default:
1176 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1177 addr, &swap32);
1178 if (!ret) {
1179 (*bytes_read) += 4;
1180 if (userbuffer) {
1181 if (put_user(swap32, (u32 __user *)userbuffer))
1182 return -EFAULT;
1184 userbuffer += 4;
1185 } else {
1186 *((u32 *)kernbuffer) = swap32;
1187 kernbuffer += 4;
1189 addr += 4;
1190 length -= 4;
1193 if (ret)
1194 break;
1197 return ret;
1200 /* High level: Gfx (indexed) register access */
1202 #ifdef INCL_SISUSB_CON
1203 int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1205 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1208 int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1210 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1212 #endif
1214 int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
1215 u8 index, u8 data)
1217 int ret;
1219 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1220 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1221 return ret;
1224 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
1225 u8 index, u8 *data)
1227 int ret;
1229 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1230 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1231 return ret;
1234 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1235 u8 myand, u8 myor)
1237 int ret;
1238 u8 tmp;
1240 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1241 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1242 tmp &= myand;
1243 tmp |= myor;
1244 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1245 return ret;
1248 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1249 int port, u8 idx, u8 data, u8 mask)
1251 int ret;
1252 u8 tmp;
1254 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1255 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1256 tmp &= ~(mask);
1257 tmp |= (data & mask);
1258 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1259 return ret;
1262 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
1263 u8 index, u8 myor)
1265 return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1268 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
1269 u8 idx, u8 myand)
1271 return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1274 /* Write/read video ram */
1276 #ifdef INCL_SISUSB_CON
1277 int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1279 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1282 int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1284 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1287 int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1288 u32 dest, int length)
1290 size_t dummy;
1292 return sisusb_write_mem_bulk(sisusb, dest, src, length,
1293 NULL, 0, &dummy);
1296 #ifdef SISUSBENDIANTEST
1297 static int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1298 u32 src, int length)
1300 size_t dummy;
1302 return sisusb_read_mem_bulk(sisusb, src, dest, length,
1303 NULL, &dummy);
1305 #endif
1306 #endif
1308 #ifdef SISUSBENDIANTEST
1309 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1311 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1312 char destbuffer[10];
1313 int i, j;
1315 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
1317 for (i = 1; i <= 7; i++) {
1318 dev_dbg(&sisusb->sisusb_dev->dev,
1319 "sisusb: rwtest %d bytes\n", i);
1320 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
1321 for (j = 0; j < i; j++) {
1322 dev_dbg(&sisusb->sisusb_dev->dev,
1323 "rwtest read[%d] = %x\n",
1324 j, destbuffer[j]);
1328 #endif
1330 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1332 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1333 int regnum, u32 data)
1335 struct sisusb_packet packet;
1336 int ret;
1338 packet.header = 0x008f;
1339 packet.address = regnum | 0x10000;
1340 packet.data = data;
1341 ret = sisusb_send_packet(sisusb, 10, &packet);
1342 return ret;
1345 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1346 int regnum, u32 *data)
1348 struct sisusb_packet packet;
1349 int ret;
1351 packet.header = 0x008f;
1352 packet.address = (u32)regnum | 0x10000;
1353 ret = sisusb_send_packet(sisusb, 6, &packet);
1354 *data = packet.data;
1355 return ret;
1358 /* Clear video RAM */
1360 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1361 u32 address, int length)
1363 int ret, i;
1364 ssize_t j;
1366 if (address < sisusb->vrambase)
1367 return 1;
1369 if (address >= sisusb->vrambase + sisusb->vramsize)
1370 return 1;
1372 if (address + length > sisusb->vrambase + sisusb->vramsize)
1373 length = sisusb->vrambase + sisusb->vramsize - address;
1375 if (length <= 0)
1376 return 0;
1378 /* allocate free buffer/urb and clear the buffer */
1379 i = sisusb_alloc_outbuf(sisusb);
1380 if (i < 0)
1381 return -EBUSY;
1383 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1385 /* We can write a length > buffer size here. The buffer
1386 * data will simply be re-used (like a ring-buffer).
1388 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1390 /* Free the buffer/urb */
1391 sisusb_free_outbuf(sisusb, i);
1393 return ret;
1396 /* Initialize the graphics core (return 0 on success)
1397 * This resets the graphics hardware and puts it into
1398 * a defined mode (640x480@60Hz)
1401 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1402 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1403 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1404 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1405 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1406 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1407 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1408 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1409 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1410 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1411 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1413 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1415 int ret;
1416 u8 tmp8;
1418 ret = GETIREG(SISSR, 0x16, &tmp8);
1419 if (ramtype <= 1) {
1420 tmp8 &= 0x3f;
1421 ret |= SETIREG(SISSR, 0x16, tmp8);
1422 tmp8 |= 0x80;
1423 ret |= SETIREG(SISSR, 0x16, tmp8);
1424 } else {
1425 tmp8 |= 0xc0;
1426 ret |= SETIREG(SISSR, 0x16, tmp8);
1427 tmp8 &= 0x0f;
1428 ret |= SETIREG(SISSR, 0x16, tmp8);
1429 tmp8 |= 0x80;
1430 ret |= SETIREG(SISSR, 0x16, tmp8);
1431 tmp8 &= 0x0f;
1432 ret |= SETIREG(SISSR, 0x16, tmp8);
1433 tmp8 |= 0xd0;
1434 ret |= SETIREG(SISSR, 0x16, tmp8);
1435 tmp8 &= 0x0f;
1436 ret |= SETIREG(SISSR, 0x16, tmp8);
1437 tmp8 |= 0xa0;
1438 ret |= SETIREG(SISSR, 0x16, tmp8);
1440 return ret;
1443 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1444 int *bw, int *chab)
1446 int ret;
1447 u8 ramtype, done = 0;
1448 u32 t0, t1, t2, t3;
1449 u32 ramptr = SISUSB_PCI_MEMBASE;
1451 ret = GETIREG(SISSR, 0x3a, &ramtype);
1452 ramtype &= 3;
1454 ret |= SETIREG(SISSR, 0x13, 0x00);
1456 if (ramtype <= 1) {
1457 ret |= SETIREG(SISSR, 0x14, 0x12);
1458 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1459 } else {
1460 ret |= SETIREG(SISSR, 0x14, 0x02);
1463 ret |= sisusb_triggersr16(sisusb, ramtype);
1464 ret |= WRITEL(ramptr + 0, 0x01234567);
1465 ret |= WRITEL(ramptr + 4, 0x456789ab);
1466 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1467 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1468 ret |= WRITEL(ramptr + 16, 0x55555555);
1469 ret |= WRITEL(ramptr + 20, 0x55555555);
1470 ret |= WRITEL(ramptr + 24, 0xffffffff);
1471 ret |= WRITEL(ramptr + 28, 0xffffffff);
1472 ret |= READL(ramptr + 0, &t0);
1473 ret |= READL(ramptr + 4, &t1);
1474 ret |= READL(ramptr + 8, &t2);
1475 ret |= READL(ramptr + 12, &t3);
1477 if (ramtype <= 1) {
1479 *chab = 0; *bw = 64;
1481 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1482 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1483 *chab = 0; *bw = 64;
1484 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1487 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1488 *chab = 1; *bw = 64;
1489 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1491 ret |= sisusb_triggersr16(sisusb, ramtype);
1492 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1493 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1494 ret |= WRITEL(ramptr + 8, 0x55555555);
1495 ret |= WRITEL(ramptr + 12, 0x55555555);
1496 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1497 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1498 ret |= READL(ramptr + 4, &t1);
1500 if (t1 != 0xcdef0123) {
1501 *bw = 32;
1502 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1506 } else {
1508 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1510 done = 0;
1512 if (t1 == 0x456789ab) {
1513 if (t0 == 0x01234567) {
1514 *chab = 0; *bw = 64;
1515 done = 1;
1517 } else {
1518 if (t0 == 0x01234567) {
1519 *chab = 0; *bw = 32;
1520 ret |= SETIREG(SISSR, 0x14, 0x00);
1521 done = 1;
1525 if (!done) {
1526 ret |= SETIREG(SISSR, 0x14, 0x03);
1527 ret |= sisusb_triggersr16(sisusb, ramtype);
1529 ret |= WRITEL(ramptr + 0, 0x01234567);
1530 ret |= WRITEL(ramptr + 4, 0x456789ab);
1531 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1532 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1533 ret |= WRITEL(ramptr + 16, 0x55555555);
1534 ret |= WRITEL(ramptr + 20, 0x55555555);
1535 ret |= WRITEL(ramptr + 24, 0xffffffff);
1536 ret |= WRITEL(ramptr + 28, 0xffffffff);
1537 ret |= READL(ramptr + 0, &t0);
1538 ret |= READL(ramptr + 4, &t1);
1540 if (t1 == 0x456789ab) {
1541 if (t0 == 0x01234567) {
1542 *chab = 1; *bw = 64;
1543 return ret;
1544 } /* else error */
1545 } else {
1546 if (t0 == 0x01234567) {
1547 *chab = 1; *bw = 32;
1548 ret |= SETIREG(SISSR, 0x14, 0x01);
1549 } /* else error */
1553 return ret;
1556 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1558 int ret = 0;
1559 u32 ramptr = SISUSB_PCI_MEMBASE;
1560 u8 tmp1, tmp2, i, j;
1562 ret |= WRITEB(ramptr, 0xaa);
1563 ret |= WRITEB(ramptr + 16, 0x55);
1564 ret |= READB(ramptr, &tmp1);
1565 ret |= READB(ramptr + 16, &tmp2);
1566 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1567 for (i = 0, j = 16; i < 2; i++, j += 16) {
1568 ret |= GETIREG(SISSR, 0x21, &tmp1);
1569 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1570 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1571 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1572 ret |= SETIREG(SISSR, 0x21, tmp1);
1573 ret |= WRITEB(ramptr + 16 + j, j);
1574 ret |= READB(ramptr + 16 + j, &tmp1);
1575 if (tmp1 == j) {
1576 ret |= WRITEB(ramptr + j, j);
1577 break;
1581 return ret;
1584 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1585 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1587 int ret = 0, ranksize;
1588 u8 tmp;
1590 *iret = 0;
1592 if ((rankno == 2) && (dramtype[index][0] == 2))
1593 return ret;
1595 ranksize = dramtype[index][3] / 2 * bw / 32;
1597 if ((ranksize * rankno) > 128)
1598 return ret;
1600 tmp = 0;
1601 while ((ranksize >>= 1) > 0)
1602 tmp += 0x10;
1604 tmp |= ((rankno - 1) << 2);
1605 tmp |= ((bw / 64) & 0x02);
1606 tmp |= (chab & 0x01);
1608 ret = SETIREG(SISSR, 0x14, tmp);
1609 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1611 *iret = 1;
1613 return ret;
1616 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1617 u32 inc, int testn)
1619 int ret = 0, i;
1620 u32 j, tmp;
1622 *iret = 0;
1624 for (i = 0, j = 0; i < testn; i++) {
1625 ret |= WRITEL(sisusb->vrambase + j, j);
1626 j += inc;
1629 for (i = 0, j = 0; i < testn; i++) {
1630 ret |= READL(sisusb->vrambase + j, &tmp);
1631 if (tmp != j)
1632 return ret;
1634 j += inc;
1637 *iret = 1;
1638 return ret;
1641 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1642 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1644 int ret = 0, i, i2ret;
1645 u32 inc;
1647 *iret = 0;
1649 for (i = rankno; i >= 1; i--) {
1650 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1651 bw / 64 + i);
1652 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1653 if (!i2ret)
1654 return ret;
1657 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1658 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1659 if (!i2ret)
1660 return ret;
1662 inc = 1 << (10 + bw / 64);
1663 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1664 if (!i2ret)
1665 return ret;
1667 *iret = 1;
1668 return ret;
1671 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1672 int bw, int chab)
1674 int ret = 0, i2ret = 0, i, j;
1675 static const u8 sdramtype[13][5] = {
1676 { 2, 12, 9, 64, 0x35 },
1677 { 1, 13, 9, 64, 0x44 },
1678 { 2, 12, 8, 32, 0x31 },
1679 { 2, 11, 9, 32, 0x25 },
1680 { 1, 12, 9, 32, 0x34 },
1681 { 1, 13, 8, 32, 0x40 },
1682 { 2, 11, 8, 16, 0x21 },
1683 { 1, 12, 8, 16, 0x30 },
1684 { 1, 11, 9, 16, 0x24 },
1685 { 1, 11, 8, 8, 0x20 },
1686 { 2, 9, 8, 4, 0x01 },
1687 { 1, 10, 8, 4, 0x10 },
1688 { 1, 9, 8, 2, 0x00 }
1691 *iret = 1; /* error */
1693 for (i = 0; i < 13; i++) {
1694 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1695 for (j = 2; j > 0; j--) {
1696 ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1697 sdramtype, bw);
1698 if (!i2ret)
1699 continue;
1701 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1702 sdramtype);
1703 if (i2ret) {
1704 *iret = 0; /* ram size found */
1705 return ret;
1710 return ret;
1713 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1714 int clrall, int drwfr)
1716 int ret = 0;
1717 u32 address;
1718 int i, length, modex, modey, bpp;
1720 modex = 640; modey = 480; bpp = 2;
1722 address = sisusb->vrambase; /* Clear video ram */
1724 if (clrall)
1725 length = sisusb->vramsize;
1726 else
1727 length = modex * bpp * modey;
1729 ret = sisusb_clear_vram(sisusb, address, length);
1731 if (!ret && drwfr) {
1732 for (i = 0; i < modex; i++) {
1733 address = sisusb->vrambase + (i * bpp);
1734 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1735 address, 0xf100);
1736 address += (modex * (modey-1) * bpp);
1737 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1738 address, 0xf100);
1740 for (i = 0; i < modey; i++) {
1741 address = sisusb->vrambase + ((i * modex) * bpp);
1742 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1743 address, 0xf100);
1744 address += ((modex - 1) * bpp);
1745 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1746 address, 0xf100);
1750 return ret;
1753 static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1754 int touchengines)
1756 int ret = 0, i, j, modex, modey, bpp, du;
1757 u8 sr31, cr63, tmp8;
1758 static const char attrdata[] = {
1759 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1760 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1761 0x01, 0x00, 0x00, 0x00
1763 static const char crtcrdata[] = {
1764 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1765 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1766 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1767 0xff
1769 static const char grcdata[] = {
1770 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1771 0xff
1773 static const char crtcdata[] = {
1774 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1775 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1776 0x00
1779 modex = 640; modey = 480; bpp = 2;
1781 GETIREG(SISSR, 0x31, &sr31);
1782 GETIREG(SISCR, 0x63, &cr63);
1783 SETIREGOR(SISSR, 0x01, 0x20);
1784 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1785 SETIREGOR(SISCR, 0x17, 0x80);
1786 SETIREGOR(SISSR, 0x1f, 0x04);
1787 SETIREGAND(SISSR, 0x07, 0xfb);
1788 SETIREG(SISSR, 0x00, 0x03); /* seq */
1789 SETIREG(SISSR, 0x01, 0x21);
1790 SETIREG(SISSR, 0x02, 0x0f);
1791 SETIREG(SISSR, 0x03, 0x00);
1792 SETIREG(SISSR, 0x04, 0x0e);
1793 SETREG(SISMISCW, 0x23); /* misc */
1794 for (i = 0; i <= 0x18; i++) { /* crtc */
1795 SETIREG(SISCR, i, crtcrdata[i]);
1797 for (i = 0; i <= 0x13; i++) { /* att */
1798 GETREG(SISINPSTAT, &tmp8);
1799 SETREG(SISAR, i);
1800 SETREG(SISAR, attrdata[i]);
1802 GETREG(SISINPSTAT, &tmp8);
1803 SETREG(SISAR, 0x14);
1804 SETREG(SISAR, 0x00);
1805 GETREG(SISINPSTAT, &tmp8);
1806 SETREG(SISAR, 0x20);
1807 GETREG(SISINPSTAT, &tmp8);
1808 for (i = 0; i <= 0x08; i++) { /* grc */
1809 SETIREG(SISGR, i, grcdata[i]);
1811 SETIREGAND(SISGR, 0x05, 0xbf);
1812 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1813 SETIREG(SISSR, i, 0x00);
1815 SETIREGAND(SISSR, 0x37, 0xfe);
1816 SETREG(SISMISCW, 0xef); /* sync */
1817 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1818 for (j = 0x00, i = 0; i <= 7; i++, j++)
1819 SETIREG(SISCR, j, crtcdata[i]);
1821 for (j = 0x10; i <= 10; i++, j++)
1822 SETIREG(SISCR, j, crtcdata[i]);
1824 for (j = 0x15; i <= 12; i++, j++)
1825 SETIREG(SISCR, j, crtcdata[i]);
1827 for (j = 0x0A; i <= 15; i++, j++)
1828 SETIREG(SISSR, j, crtcdata[i]);
1830 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1831 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1832 SETIREG(SISCR, 0x14, 0x4f);
1833 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1834 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1835 SETIREG(SISCR, 0x13, (du & 0xff));
1836 du <<= 5;
1837 tmp8 = du >> 8;
1838 SETIREG(SISSR, 0x10, tmp8);
1839 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1840 SETIREG(SISSR, 0x2b, 0x1b);
1841 SETIREG(SISSR, 0x2c, 0xe1);
1842 SETIREG(SISSR, 0x2d, 0x01);
1843 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1844 SETIREG(SISSR, 0x08, 0xae);
1845 SETIREGAND(SISSR, 0x09, 0xf0);
1846 SETIREG(SISSR, 0x08, 0x34);
1847 SETIREGOR(SISSR, 0x3d, 0x01);
1848 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1849 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1850 SETIREG(SISCR, 0x19, 0x00);
1851 SETIREGAND(SISCR, 0x1a, 0xfc);
1852 SETIREGAND(SISSR, 0x0f, 0xb7);
1853 SETIREGAND(SISSR, 0x31, 0xfb);
1854 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1855 SETIREGAND(SISSR, 0x32, 0xf3);
1856 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1857 SETIREG(SISCR, 0x52, 0x6c);
1859 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1860 SETIREG(SISCR, 0x0c, 0x00);
1861 SETIREG(SISSR, 0x0d, 0x00);
1862 SETIREGAND(SISSR, 0x37, 0xfe);
1864 SETIREG(SISCR, 0x32, 0x20);
1865 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1866 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1867 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1869 if (touchengines) {
1870 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1871 SETIREGOR(SISSR, 0x1e, 0x5a);
1873 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1874 SETIREG(SISSR, 0x27, 0x1f);
1875 SETIREG(SISSR, 0x26, 0x00);
1878 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1880 return ret;
1883 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1885 int ret = 0, i, j, bw, chab, iret, retry = 3;
1886 u8 tmp8, ramtype;
1887 u32 tmp32;
1888 static const char mclktable[] = {
1889 0x3b, 0x22, 0x01, 143,
1890 0x3b, 0x22, 0x01, 143,
1891 0x3b, 0x22, 0x01, 143,
1892 0x3b, 0x22, 0x01, 143
1894 static const char eclktable[] = {
1895 0x3b, 0x22, 0x01, 143,
1896 0x3b, 0x22, 0x01, 143,
1897 0x3b, 0x22, 0x01, 143,
1898 0x3b, 0x22, 0x01, 143
1900 static const char ramtypetable1[] = {
1901 0x00, 0x04, 0x60, 0x60,
1902 0x0f, 0x0f, 0x1f, 0x1f,
1903 0xba, 0xba, 0xba, 0xba,
1904 0xa9, 0xa9, 0xac, 0xac,
1905 0xa0, 0xa0, 0xa0, 0xa8,
1906 0x00, 0x00, 0x02, 0x02,
1907 0x30, 0x30, 0x40, 0x40
1909 static const char ramtypetable2[] = {
1910 0x77, 0x77, 0x44, 0x44,
1911 0x77, 0x77, 0x44, 0x44,
1912 0x00, 0x00, 0x00, 0x00,
1913 0x5b, 0x5b, 0xab, 0xab,
1914 0x00, 0x00, 0xf0, 0xf8
1917 while (retry--) {
1919 /* Enable VGA */
1920 ret = GETREG(SISVGAEN, &tmp8);
1921 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1923 /* Enable GPU access to VRAM */
1924 ret |= GETREG(SISMISCR, &tmp8);
1925 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1927 if (ret)
1928 continue;
1930 /* Reset registers */
1931 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1932 ret |= SETIREG(SISSR, 0x05, 0x86);
1933 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1935 ret |= SETREG(SISMISCW, 0x67);
1937 for (i = 0x06; i <= 0x1f; i++)
1938 ret |= SETIREG(SISSR, i, 0x00);
1940 for (i = 0x21; i <= 0x27; i++)
1941 ret |= SETIREG(SISSR, i, 0x00);
1943 for (i = 0x31; i <= 0x3d; i++)
1944 ret |= SETIREG(SISSR, i, 0x00);
1946 for (i = 0x12; i <= 0x1b; i++)
1947 ret |= SETIREG(SISSR, i, 0x00);
1949 for (i = 0x79; i <= 0x7c; i++)
1950 ret |= SETIREG(SISCR, i, 0x00);
1952 if (ret)
1953 continue;
1955 ret |= SETIREG(SISCR, 0x63, 0x80);
1957 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1958 ramtype &= 0x03;
1960 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1961 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1962 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1964 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1965 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1966 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1968 ret |= SETIREG(SISSR, 0x07, 0x18);
1969 ret |= SETIREG(SISSR, 0x11, 0x0f);
1971 if (ret)
1972 continue;
1974 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1975 ret |= SETIREG(SISSR, i,
1976 ramtypetable1[(j*4) + ramtype]);
1978 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1979 ret |= SETIREG(SISCR, i,
1980 ramtypetable2[(j*4) + ramtype]);
1983 ret |= SETIREG(SISCR, 0x49, 0xaa);
1985 ret |= SETIREG(SISSR, 0x1f, 0x00);
1986 ret |= SETIREG(SISSR, 0x20, 0xa0);
1987 ret |= SETIREG(SISSR, 0x23, 0xf6);
1988 ret |= SETIREG(SISSR, 0x24, 0x0d);
1989 ret |= SETIREG(SISSR, 0x25, 0x33);
1991 ret |= SETIREG(SISSR, 0x11, 0x0f);
1993 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1995 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
1997 if (ret)
1998 continue;
2000 ret |= SETIREG(SISPART1, 0x00, 0x00);
2002 ret |= GETIREG(SISSR, 0x13, &tmp8);
2003 tmp8 >>= 4;
2005 ret |= SETIREG(SISPART1, 0x02, 0x00);
2006 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2008 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2009 tmp32 &= 0x00f00000;
2010 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2011 ret |= SETIREG(SISSR, 0x25, tmp8);
2012 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2013 ret |= SETIREG(SISCR, 0x49, tmp8);
2015 ret |= SETIREG(SISSR, 0x27, 0x1f);
2016 ret |= SETIREG(SISSR, 0x31, 0x00);
2017 ret |= SETIREG(SISSR, 0x32, 0x11);
2018 ret |= SETIREG(SISSR, 0x33, 0x00);
2020 if (ret)
2021 continue;
2023 ret |= SETIREG(SISCR, 0x83, 0x00);
2025 ret |= sisusb_set_default_mode(sisusb, 0);
2027 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2028 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2029 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2031 ret |= sisusb_triggersr16(sisusb, ramtype);
2033 /* Disable refresh */
2034 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2035 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2037 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2038 ret |= sisusb_verify_mclk(sisusb);
2040 if (ramtype <= 1) {
2041 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2042 if (iret) {
2043 dev_err(&sisusb->sisusb_dev->dev,
2044 "RAM size detection failed, assuming 8MB video RAM\n");
2045 ret |= SETIREG(SISSR, 0x14, 0x31);
2046 /* TODO */
2048 } else {
2049 dev_err(&sisusb->sisusb_dev->dev,
2050 "DDR RAM device found, assuming 8MB video RAM\n");
2051 ret |= SETIREG(SISSR, 0x14, 0x31);
2052 /* *** TODO *** */
2055 /* Enable refresh */
2056 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2057 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2058 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2060 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2062 ret |= SETIREG(SISSR, 0x22, 0xfb);
2063 ret |= SETIREG(SISSR, 0x21, 0xa5);
2065 if (ret == 0)
2066 break;
2069 return ret;
2072 #undef SETREG
2073 #undef GETREG
2074 #undef SETIREG
2075 #undef GETIREG
2076 #undef SETIREGOR
2077 #undef SETIREGAND
2078 #undef SETIREGANDOR
2079 #undef READL
2080 #undef WRITEL
2082 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2084 u8 tmp8, tmp82, ramtype;
2085 int bw = 0;
2086 char *ramtypetext1 = NULL;
2087 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2088 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2089 static const int busSDR[4] = {64, 64, 128, 128};
2090 static const int busDDR[4] = {32, 32, 64, 64};
2091 static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2093 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2094 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2095 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2096 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2097 ramtype &= 0x03;
2098 switch ((tmp8 >> 2) & 0x03) {
2099 case 0:
2100 ramtypetext1 = "1 ch/1 r";
2101 if (tmp82 & 0x10)
2102 bw = 32;
2103 else
2104 bw = busSDR[(tmp8 & 0x03)];
2106 break;
2107 case 1:
2108 ramtypetext1 = "1 ch/2 r";
2109 sisusb->vramsize <<= 1;
2110 bw = busSDR[(tmp8 & 0x03)];
2111 break;
2112 case 2:
2113 ramtypetext1 = "asymmeric";
2114 sisusb->vramsize += sisusb->vramsize/2;
2115 bw = busDDRA[(tmp8 & 0x03)];
2116 break;
2117 case 3:
2118 ramtypetext1 = "2 channel";
2119 sisusb->vramsize <<= 1;
2120 bw = busDDR[(tmp8 & 0x03)];
2121 break;
2124 dev_info(&sisusb->sisusb_dev->dev,
2125 "%dMB %s %cDR S%cRAM, bus width %d\n",
2126 sisusb->vramsize >> 20, ramtypetext1,
2127 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2130 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2132 struct sisusb_packet packet;
2133 int ret;
2134 u32 tmp32;
2136 /* Do some magic */
2137 packet.header = 0x001f;
2138 packet.address = 0x00000324;
2139 packet.data = 0x00000004;
2140 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2142 packet.header = 0x001f;
2143 packet.address = 0x00000364;
2144 packet.data = 0x00000004;
2145 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2147 packet.header = 0x001f;
2148 packet.address = 0x00000384;
2149 packet.data = 0x00000004;
2150 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2152 packet.header = 0x001f;
2153 packet.address = 0x00000100;
2154 packet.data = 0x00000700;
2155 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2157 packet.header = 0x000f;
2158 packet.address = 0x00000004;
2159 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2160 packet.data |= 0x17;
2161 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2163 /* Init BAR 0 (VRAM) */
2164 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2165 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2166 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2167 tmp32 &= 0x0f;
2168 tmp32 |= SISUSB_PCI_MEMBASE;
2169 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2171 /* Init BAR 1 (MMIO) */
2172 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2173 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2174 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2175 tmp32 &= 0x0f;
2176 tmp32 |= SISUSB_PCI_MMIOBASE;
2177 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2179 /* Init BAR 2 (i/o ports) */
2180 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2181 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2182 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2183 tmp32 &= 0x0f;
2184 tmp32 |= SISUSB_PCI_IOPORTBASE;
2185 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2187 /* Enable memory and i/o access */
2188 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2189 tmp32 |= 0x3;
2190 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2192 if (ret == 0) {
2193 /* Some further magic */
2194 packet.header = 0x001f;
2195 packet.address = 0x00000050;
2196 packet.data = 0x000000ff;
2197 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2200 return ret;
2203 /* Initialize the graphics device (return 0 on success)
2204 * This initializes the net2280 as well as the PCI registers
2205 * of the graphics board.
2208 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2210 int ret = 0, test = 0;
2211 u32 tmp32;
2213 if (sisusb->devinit == 1) {
2214 /* Read PCI BARs and see if they have been set up */
2215 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2216 if (ret)
2217 return ret;
2219 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2220 test++;
2222 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2223 if (ret)
2224 return ret;
2226 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2227 test++;
2229 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2230 if (ret)
2231 return ret;
2233 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2234 test++;
2237 /* No? So reset the device */
2238 if ((sisusb->devinit == 0) || (test != 3)) {
2240 ret |= sisusb_do_init_gfxdevice(sisusb);
2242 if (ret == 0)
2243 sisusb->devinit = 1;
2247 if (sisusb->devinit) {
2248 /* Initialize the graphics core */
2249 if (sisusb_init_gfxcore(sisusb) == 0) {
2250 sisusb->gfxinit = 1;
2251 sisusb_get_ramconfig(sisusb);
2252 ret |= sisusb_set_default_mode(sisusb, 1);
2253 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2257 return ret;
2261 #ifdef INCL_SISUSB_CON
2263 /* Set up default text mode:
2264 * - Set text mode (0x03)
2265 * - Upload default font
2266 * - Upload user font (if available)
2269 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2271 int ret = 0, slot = sisusb->font_slot, i;
2272 const struct font_desc *myfont;
2273 u8 *tempbuf;
2274 u16 *tempbufb;
2275 static const char bootstring[] =
2276 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2277 static const char bootlogo[] = "(o_ //\\ V_/_";
2279 /* sisusb->lock is down */
2281 if (!sisusb->SiS_Pr)
2282 return 1;
2284 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2285 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2287 /* Set mode 0x03 */
2288 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2290 myfont = find_font("VGA8x16");
2291 if (!myfont)
2292 return 1;
2294 tempbuf = vmalloc(8192);
2295 if (!tempbuf)
2296 return 1;
2298 for (i = 0; i < 256; i++)
2299 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2301 /* Upload default font */
2302 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2303 0, 1, NULL, 16, 0);
2305 vfree(tempbuf);
2307 /* Upload user font (and reset current slot) */
2308 if (sisusb->font_backup) {
2309 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2310 8192, sisusb->font_backup_512, 1, NULL,
2311 sisusb->font_backup_height, 0);
2312 if (slot != 2)
2313 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2314 NULL, 16, 0);
2317 if (init && !sisusb->scrbuf) {
2319 tempbuf = vmalloc(8192);
2320 if (tempbuf) {
2322 i = 4096;
2323 tempbufb = (u16 *)tempbuf;
2324 while (i--)
2325 *(tempbufb++) = 0x0720;
2327 i = 0;
2328 tempbufb = (u16 *)tempbuf;
2329 while (bootlogo[i]) {
2330 *(tempbufb++) = 0x0700 | bootlogo[i++];
2331 if (!(i % 4))
2332 tempbufb += 76;
2335 i = 0;
2336 tempbufb = (u16 *)tempbuf + 6;
2337 while (bootstring[i])
2338 *(tempbufb++) = 0x0700 | bootstring[i++];
2340 ret |= sisusb_copy_memory(sisusb, tempbuf,
2341 sisusb->vrambase, 8192);
2343 vfree(tempbuf);
2347 } else if (sisusb->scrbuf) {
2348 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2349 sisusb->vrambase, sisusb->scrbuf_size);
2352 if (sisusb->sisusb_cursor_size_from >= 0 &&
2353 sisusb->sisusb_cursor_size_to >= 0) {
2354 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2355 sisusb->sisusb_cursor_size_from);
2356 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2357 sisusb->sisusb_cursor_size_to);
2358 } else {
2359 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2360 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2361 sisusb->sisusb_cursor_size_to = -1;
2364 slot = sisusb->sisusb_cursor_loc;
2365 if (slot < 0)
2366 slot = 0;
2368 sisusb->sisusb_cursor_loc = -1;
2369 sisusb->bad_cursor_pos = 1;
2371 sisusb_set_cursor(sisusb, slot);
2373 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2374 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2376 sisusb->textmodedestroyed = 0;
2378 /* sisusb->lock is down */
2380 return ret;
2383 #endif
2385 /* fops */
2387 static int sisusb_open(struct inode *inode, struct file *file)
2389 struct sisusb_usb_data *sisusb;
2390 struct usb_interface *interface;
2391 int subminor = iminor(inode);
2393 interface = usb_find_interface(&sisusb_driver, subminor);
2394 if (!interface)
2395 return -ENODEV;
2397 sisusb = usb_get_intfdata(interface);
2398 if (!sisusb)
2399 return -ENODEV;
2401 mutex_lock(&sisusb->lock);
2403 if (!sisusb->present || !sisusb->ready) {
2404 mutex_unlock(&sisusb->lock);
2405 return -ENODEV;
2408 if (sisusb->isopen) {
2409 mutex_unlock(&sisusb->lock);
2410 return -EBUSY;
2413 if (!sisusb->devinit) {
2414 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2415 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2416 if (sisusb_init_gfxdevice(sisusb, 0)) {
2417 mutex_unlock(&sisusb->lock);
2418 dev_err(&sisusb->sisusb_dev->dev,
2419 "Failed to initialize device\n");
2420 return -EIO;
2422 } else {
2423 mutex_unlock(&sisusb->lock);
2424 dev_err(&sisusb->sisusb_dev->dev,
2425 "Device not attached to USB 2.0 hub\n");
2426 return -EIO;
2430 /* Increment usage count for our sisusb */
2431 kref_get(&sisusb->kref);
2433 sisusb->isopen = 1;
2435 file->private_data = sisusb;
2437 mutex_unlock(&sisusb->lock);
2439 return 0;
2442 void sisusb_delete(struct kref *kref)
2444 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2446 if (!sisusb)
2447 return;
2449 usb_put_dev(sisusb->sisusb_dev);
2451 sisusb->sisusb_dev = NULL;
2452 sisusb_free_buffers(sisusb);
2453 sisusb_free_urbs(sisusb);
2454 #ifdef INCL_SISUSB_CON
2455 kfree(sisusb->SiS_Pr);
2456 #endif
2457 kfree(sisusb);
2460 static int sisusb_release(struct inode *inode, struct file *file)
2462 struct sisusb_usb_data *sisusb;
2464 sisusb = file->private_data;
2465 if (!sisusb)
2466 return -ENODEV;
2468 mutex_lock(&sisusb->lock);
2470 if (sisusb->present) {
2471 /* Wait for all URBs to finish if device still present */
2472 if (!sisusb_wait_all_out_complete(sisusb))
2473 sisusb_kill_all_busy(sisusb);
2476 sisusb->isopen = 0;
2477 file->private_data = NULL;
2479 mutex_unlock(&sisusb->lock);
2481 /* decrement the usage count on our device */
2482 kref_put(&sisusb->kref, sisusb_delete);
2484 return 0;
2487 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2488 size_t count, loff_t *ppos)
2490 struct sisusb_usb_data *sisusb;
2491 ssize_t bytes_read = 0;
2492 int errno = 0;
2493 u8 buf8;
2494 u16 buf16;
2495 u32 buf32, address;
2497 sisusb = file->private_data;
2498 if (!sisusb)
2499 return -ENODEV;
2501 mutex_lock(&sisusb->lock);
2503 /* Sanity check */
2504 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2505 mutex_unlock(&sisusb->lock);
2506 return -ENODEV;
2509 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2510 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2512 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2513 SISUSB_PCI_IOPORTBASE;
2515 /* Read i/o ports
2516 * Byte, word and long(32) can be read. As this
2517 * emulates inX instructions, the data returned is
2518 * in machine-endianness.
2520 switch (count) {
2521 case 1:
2522 if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2523 address, &buf8))
2524 errno = -EIO;
2525 else if (put_user(buf8, (u8 __user *)buffer))
2526 errno = -EFAULT;
2527 else
2528 bytes_read = 1;
2530 break;
2532 case 2:
2533 if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2534 address, &buf16))
2535 errno = -EIO;
2536 else if (put_user(buf16, (u16 __user *)buffer))
2537 errno = -EFAULT;
2538 else
2539 bytes_read = 2;
2541 break;
2543 case 4:
2544 if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2545 address, &buf32))
2546 errno = -EIO;
2547 else if (put_user(buf32, (u32 __user *)buffer))
2548 errno = -EFAULT;
2549 else
2550 bytes_read = 4;
2552 break;
2554 default:
2555 errno = -EIO;
2559 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2560 SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2562 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2563 SISUSB_PCI_MEMBASE;
2565 /* Read video ram
2566 * Remember: Data delivered is never endian-corrected
2568 errno = sisusb_read_mem_bulk(sisusb, address,
2569 NULL, count, buffer, &bytes_read);
2571 if (bytes_read)
2572 errno = bytes_read;
2574 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2575 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2576 SISUSB_PCI_MMIOSIZE) {
2578 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2579 SISUSB_PCI_MMIOBASE;
2581 /* Read MMIO
2582 * Remember: Data delivered is never endian-corrected
2584 errno = sisusb_read_mem_bulk(sisusb, address,
2585 NULL, count, buffer, &bytes_read);
2587 if (bytes_read)
2588 errno = bytes_read;
2590 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2591 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2593 if (count != 4) {
2594 mutex_unlock(&sisusb->lock);
2595 return -EINVAL;
2598 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2600 /* Read PCI config register
2601 * Return value delivered in machine endianness.
2603 if (sisusb_read_pci_config(sisusb, address, &buf32))
2604 errno = -EIO;
2605 else if (put_user(buf32, (u32 __user *)buffer))
2606 errno = -EFAULT;
2607 else
2608 bytes_read = 4;
2610 } else {
2612 errno = -EBADFD;
2616 (*ppos) += bytes_read;
2618 mutex_unlock(&sisusb->lock);
2620 return errno ? errno : bytes_read;
2623 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2624 size_t count, loff_t *ppos)
2626 struct sisusb_usb_data *sisusb;
2627 int errno = 0;
2628 ssize_t bytes_written = 0;
2629 u8 buf8;
2630 u16 buf16;
2631 u32 buf32, address;
2633 sisusb = file->private_data;
2634 if (!sisusb)
2635 return -ENODEV;
2637 mutex_lock(&sisusb->lock);
2639 /* Sanity check */
2640 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2641 mutex_unlock(&sisusb->lock);
2642 return -ENODEV;
2645 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2646 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2648 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2649 SISUSB_PCI_IOPORTBASE;
2651 /* Write i/o ports
2652 * Byte, word and long(32) can be written. As this
2653 * emulates outX instructions, the data is expected
2654 * in machine-endianness.
2656 switch (count) {
2657 case 1:
2658 if (get_user(buf8, (u8 __user *)buffer))
2659 errno = -EFAULT;
2660 else if (sisusb_write_memio_byte(sisusb,
2661 SISUSB_TYPE_IO, address, buf8))
2662 errno = -EIO;
2663 else
2664 bytes_written = 1;
2666 break;
2668 case 2:
2669 if (get_user(buf16, (u16 __user *)buffer))
2670 errno = -EFAULT;
2671 else if (sisusb_write_memio_word(sisusb,
2672 SISUSB_TYPE_IO, address, buf16))
2673 errno = -EIO;
2674 else
2675 bytes_written = 2;
2677 break;
2679 case 4:
2680 if (get_user(buf32, (u32 __user *)buffer))
2681 errno = -EFAULT;
2682 else if (sisusb_write_memio_long(sisusb,
2683 SISUSB_TYPE_IO, address, buf32))
2684 errno = -EIO;
2685 else
2686 bytes_written = 4;
2688 break;
2690 default:
2691 errno = -EIO;
2694 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2695 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE +
2696 sisusb->vramsize) {
2698 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2699 SISUSB_PCI_MEMBASE;
2701 /* Write video ram.
2702 * Buffer is copied 1:1, therefore, on big-endian
2703 * machines, the data must be swapped by userland
2704 * in advance (if applicable; no swapping in 8bpp
2705 * mode or if YUV data is being transferred).
2707 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2708 count, buffer, 0, &bytes_written);
2710 if (bytes_written)
2711 errno = bytes_written;
2713 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2714 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2715 SISUSB_PCI_MMIOSIZE) {
2717 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2718 SISUSB_PCI_MMIOBASE;
2720 /* Write MMIO.
2721 * Buffer is copied 1:1, therefore, on big-endian
2722 * machines, the data must be swapped by userland
2723 * in advance.
2725 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2726 count, buffer, 0, &bytes_written);
2728 if (bytes_written)
2729 errno = bytes_written;
2731 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2732 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2733 SISUSB_PCI_PCONFSIZE) {
2735 if (count != 4) {
2736 mutex_unlock(&sisusb->lock);
2737 return -EINVAL;
2740 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2742 /* Write PCI config register.
2743 * Given value expected in machine endianness.
2745 if (get_user(buf32, (u32 __user *)buffer))
2746 errno = -EFAULT;
2747 else if (sisusb_write_pci_config(sisusb, address, buf32))
2748 errno = -EIO;
2749 else
2750 bytes_written = 4;
2753 } else {
2755 /* Error */
2756 errno = -EBADFD;
2760 (*ppos) += bytes_written;
2762 mutex_unlock(&sisusb->lock);
2764 return errno ? errno : bytes_written;
2767 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2769 struct sisusb_usb_data *sisusb;
2770 loff_t ret;
2772 sisusb = file->private_data;
2773 if (!sisusb)
2774 return -ENODEV;
2776 mutex_lock(&sisusb->lock);
2778 /* Sanity check */
2779 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2780 mutex_unlock(&sisusb->lock);
2781 return -ENODEV;
2784 ret = no_seek_end_llseek(file, offset, orig);
2786 mutex_unlock(&sisusb->lock);
2787 return ret;
2790 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2791 struct sisusb_command *y, unsigned long arg)
2793 int retval, port, length;
2794 u32 address;
2796 /* All our commands require the device
2797 * to be initialized.
2799 if (!sisusb->devinit)
2800 return -ENODEV;
2802 port = y->data3 -
2803 SISUSB_PCI_PSEUDO_IOPORTBASE +
2804 SISUSB_PCI_IOPORTBASE;
2806 switch (y->operation) {
2807 case SUCMD_GET:
2808 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2809 if (!retval) {
2810 if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2811 retval = -EFAULT;
2813 break;
2815 case SUCMD_SET:
2816 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2817 break;
2819 case SUCMD_SETOR:
2820 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2821 break;
2823 case SUCMD_SETAND:
2824 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2825 break;
2827 case SUCMD_SETANDOR:
2828 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2829 y->data1, y->data2);
2830 break;
2832 case SUCMD_SETMASK:
2833 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2834 y->data1, y->data2);
2835 break;
2837 case SUCMD_CLRSCR:
2838 /* Gfx core must be initialized */
2839 if (!sisusb->gfxinit)
2840 return -ENODEV;
2842 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2843 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2844 SISUSB_PCI_MEMBASE;
2845 retval = sisusb_clear_vram(sisusb, address, length);
2846 break;
2848 case SUCMD_HANDLETEXTMODE:
2849 retval = 0;
2850 #ifdef INCL_SISUSB_CON
2851 /* Gfx core must be initialized, SiS_Pr must exist */
2852 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2853 return -ENODEV;
2855 switch (y->data0) {
2856 case 0:
2857 retval = sisusb_reset_text_mode(sisusb, 0);
2858 break;
2859 case 1:
2860 sisusb->textmodedestroyed = 1;
2861 break;
2863 #endif
2864 break;
2866 #ifdef INCL_SISUSB_CON
2867 case SUCMD_SETMODE:
2868 /* Gfx core must be initialized, SiS_Pr must exist */
2869 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2870 return -ENODEV;
2872 retval = 0;
2874 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2875 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2877 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2878 retval = -EINVAL;
2880 break;
2882 case SUCMD_SETVESAMODE:
2883 /* Gfx core must be initialized, SiS_Pr must exist */
2884 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2885 return -ENODEV;
2887 retval = 0;
2889 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2890 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2892 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2893 retval = -EINVAL;
2895 break;
2896 #endif
2898 default:
2899 retval = -EINVAL;
2902 if (retval > 0)
2903 retval = -EIO;
2905 return retval;
2908 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2910 struct sisusb_usb_data *sisusb;
2911 struct sisusb_info x;
2912 struct sisusb_command y;
2913 long retval = 0;
2914 u32 __user *argp = (u32 __user *)arg;
2916 sisusb = file->private_data;
2917 if (!sisusb)
2918 return -ENODEV;
2920 mutex_lock(&sisusb->lock);
2922 /* Sanity check */
2923 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2924 retval = -ENODEV;
2925 goto err_out;
2928 switch (cmd) {
2929 case SISUSB_GET_CONFIG_SIZE:
2931 if (put_user(sizeof(x), argp))
2932 retval = -EFAULT;
2934 break;
2936 case SISUSB_GET_CONFIG:
2938 x.sisusb_id = SISUSB_ID;
2939 x.sisusb_version = SISUSB_VERSION;
2940 x.sisusb_revision = SISUSB_REVISION;
2941 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2942 x.sisusb_gfxinit = sisusb->gfxinit;
2943 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2944 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2945 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2946 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2947 x.sisusb_vramsize = sisusb->vramsize;
2948 x.sisusb_minor = sisusb->minor;
2949 x.sisusb_fbdevactive = 0;
2950 #ifdef INCL_SISUSB_CON
2951 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
2952 #else
2953 x.sisusb_conactive = 0;
2954 #endif
2955 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2957 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2958 retval = -EFAULT;
2960 break;
2962 case SISUSB_COMMAND:
2964 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2965 retval = -EFAULT;
2966 else
2967 retval = sisusb_handle_command(sisusb, &y, arg);
2969 break;
2971 default:
2972 retval = -ENOTTY;
2973 break;
2976 err_out:
2977 mutex_unlock(&sisusb->lock);
2978 return retval;
2981 #ifdef SISUSB_NEW_CONFIG_COMPAT
2982 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2983 unsigned long arg)
2985 long retval;
2987 switch (cmd) {
2988 case SISUSB_GET_CONFIG_SIZE:
2989 case SISUSB_GET_CONFIG:
2990 case SISUSB_COMMAND:
2991 retval = sisusb_ioctl(f, cmd, arg);
2992 return retval;
2994 default:
2995 return -ENOIOCTLCMD;
2998 #endif
3000 static const struct file_operations usb_sisusb_fops = {
3001 .owner = THIS_MODULE,
3002 .open = sisusb_open,
3003 .release = sisusb_release,
3004 .read = sisusb_read,
3005 .write = sisusb_write,
3006 .llseek = sisusb_lseek,
3007 #ifdef SISUSB_NEW_CONFIG_COMPAT
3008 .compat_ioctl = sisusb_compat_ioctl,
3009 #endif
3010 .unlocked_ioctl = sisusb_ioctl
3013 static struct usb_class_driver usb_sisusb_class = {
3014 .name = "sisusbvga%d",
3015 .fops = &usb_sisusb_fops,
3016 .minor_base = SISUSB_MINOR
3019 static int sisusb_probe(struct usb_interface *intf,
3020 const struct usb_device_id *id)
3022 struct usb_device *dev = interface_to_usbdev(intf);
3023 struct sisusb_usb_data *sisusb;
3024 int retval = 0, i;
3026 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3027 dev->devnum);
3029 /* Allocate memory for our private */
3030 sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3031 if (!sisusb)
3032 return -ENOMEM;
3034 kref_init(&sisusb->kref);
3036 mutex_init(&(sisusb->lock));
3038 /* Register device */
3039 retval = usb_register_dev(intf, &usb_sisusb_class);
3040 if (retval) {
3041 dev_err(&sisusb->sisusb_dev->dev,
3042 "Failed to get a minor for device %d\n",
3043 dev->devnum);
3044 retval = -ENODEV;
3045 goto error_1;
3048 sisusb->sisusb_dev = dev;
3049 sisusb->minor = intf->minor;
3050 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3051 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3052 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3053 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3054 /* Everything else is zero */
3056 /* Allocate buffers */
3057 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3058 sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3059 if (!sisusb->ibuf) {
3060 retval = -ENOMEM;
3061 goto error_2;
3064 sisusb->numobufs = 0;
3065 sisusb->obufsize = SISUSB_OBUF_SIZE;
3066 for (i = 0; i < NUMOBUFS; i++) {
3067 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3068 if (!sisusb->obuf[i]) {
3069 if (i == 0) {
3070 retval = -ENOMEM;
3071 goto error_3;
3073 break;
3075 sisusb->numobufs++;
3078 /* Allocate URBs */
3079 sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3080 if (!sisusb->sisurbin) {
3081 retval = -ENOMEM;
3082 goto error_3;
3084 sisusb->completein = 1;
3086 for (i = 0; i < sisusb->numobufs; i++) {
3087 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3088 if (!sisusb->sisurbout[i]) {
3089 retval = -ENOMEM;
3090 goto error_4;
3092 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3093 sisusb->urbout_context[i].urbindex = i;
3094 sisusb->urbstatus[i] = 0;
3097 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3098 sisusb->numobufs);
3100 #ifdef INCL_SISUSB_CON
3101 /* Allocate our SiS_Pr */
3102 sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3103 if (!sisusb->SiS_Pr) {
3104 retval = -ENOMEM;
3105 goto error_4;
3107 #endif
3109 /* Do remaining init stuff */
3111 init_waitqueue_head(&sisusb->wait_q);
3113 usb_set_intfdata(intf, sisusb);
3115 usb_get_dev(sisusb->sisusb_dev);
3117 sisusb->present = 1;
3119 if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
3120 int initscreen = 1;
3121 #ifdef INCL_SISUSB_CON
3122 if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3123 sisusb_first_vc <= sisusb_last_vc &&
3124 sisusb_last_vc <= MAX_NR_CONSOLES)
3125 initscreen = 0;
3126 #endif
3127 if (sisusb_init_gfxdevice(sisusb, initscreen))
3128 dev_err(&sisusb->sisusb_dev->dev,
3129 "Failed to early initialize device\n");
3131 } else
3132 dev_info(&sisusb->sisusb_dev->dev,
3133 "Not attached to USB 2.0 hub, deferring init\n");
3135 sisusb->ready = 1;
3137 #ifdef SISUSBENDIANTEST
3138 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3139 sisusb_testreadwrite(sisusb);
3140 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3141 #endif
3143 #ifdef INCL_SISUSB_CON
3144 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3145 #endif
3147 return 0;
3149 error_4:
3150 sisusb_free_urbs(sisusb);
3151 error_3:
3152 sisusb_free_buffers(sisusb);
3153 error_2:
3154 usb_deregister_dev(intf, &usb_sisusb_class);
3155 error_1:
3156 kfree(sisusb);
3157 return retval;
3160 static void sisusb_disconnect(struct usb_interface *intf)
3162 struct sisusb_usb_data *sisusb;
3164 /* This should *not* happen */
3165 sisusb = usb_get_intfdata(intf);
3166 if (!sisusb)
3167 return;
3169 #ifdef INCL_SISUSB_CON
3170 sisusb_console_exit(sisusb);
3171 #endif
3173 usb_deregister_dev(intf, &usb_sisusb_class);
3175 mutex_lock(&sisusb->lock);
3177 /* Wait for all URBs to complete and kill them in case (MUST do) */
3178 if (!sisusb_wait_all_out_complete(sisusb))
3179 sisusb_kill_all_busy(sisusb);
3181 usb_set_intfdata(intf, NULL);
3183 sisusb->present = 0;
3184 sisusb->ready = 0;
3186 mutex_unlock(&sisusb->lock);
3188 /* decrement our usage count */
3189 kref_put(&sisusb->kref, sisusb_delete);
3192 static const struct usb_device_id sisusb_table[] = {
3193 { USB_DEVICE(0x0711, 0x0550) },
3194 { USB_DEVICE(0x0711, 0x0900) },
3195 { USB_DEVICE(0x0711, 0x0901) },
3196 { USB_DEVICE(0x0711, 0x0902) },
3197 { USB_DEVICE(0x0711, 0x0903) },
3198 { USB_DEVICE(0x0711, 0x0918) },
3199 { USB_DEVICE(0x0711, 0x0920) },
3200 { USB_DEVICE(0x0711, 0x0950) },
3201 { USB_DEVICE(0x0711, 0x5200) },
3202 { USB_DEVICE(0x182d, 0x021c) },
3203 { USB_DEVICE(0x182d, 0x0269) },
3207 MODULE_DEVICE_TABLE(usb, sisusb_table);
3209 static struct usb_driver sisusb_driver = {
3210 .name = "sisusb",
3211 .probe = sisusb_probe,
3212 .disconnect = sisusb_disconnect,
3213 .id_table = sisusb_table,
3216 static int __init usb_sisusb_init(void)
3219 #ifdef INCL_SISUSB_CON
3220 sisusb_init_concode();
3221 #endif
3223 return usb_register(&sisusb_driver);
3226 static void __exit usb_sisusb_exit(void)
3228 usb_deregister(&sisusb_driver);
3231 module_init(usb_sisusb_init);
3232 module_exit(usb_sisusb_exit);
3234 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3235 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3236 MODULE_LICENSE("GPL");