mmc: rtsx_pci: Enable MMC_CAP_ERASE to allow erase/discard/trim requests
[linux/fpc-iii.git] / drivers / usb / misc / sisusbvga / sisusb.c
blob15666ad7c772fe5a9b960e8e37f5bf93a150bcd1
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, size_t *bytes_written)
1290 return sisusb_write_mem_bulk(sisusb, dest, src, length,
1291 NULL, 0, bytes_written);
1294 #ifdef SISUSBENDIANTEST
1295 int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1296 u32 src, int length, size_t *bytes_written)
1298 return sisusb_read_mem_bulk(sisusb, src, dest, length,
1299 NULL, bytes_written);
1301 #endif
1302 #endif
1304 #ifdef SISUSBENDIANTEST
1305 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1307 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1308 char destbuffer[10];
1309 size_t dummy;
1310 int i, j;
1312 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1314 for (i = 1; i <= 7; i++) {
1315 dev_dbg(&sisusb->sisusb_dev->dev,
1316 "sisusb: rwtest %d bytes\n", i);
1317 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase,
1318 i, &dummy);
1319 for (j = 0; j < i; j++) {
1320 dev_dbg(&sisusb->sisusb_dev->dev,
1321 "rwtest read[%d] = %x\n",
1322 j, destbuffer[j]);
1326 #endif
1328 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1330 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1331 int regnum, u32 data)
1333 struct sisusb_packet packet;
1334 int ret;
1336 packet.header = 0x008f;
1337 packet.address = regnum | 0x10000;
1338 packet.data = data;
1339 ret = sisusb_send_packet(sisusb, 10, &packet);
1340 return ret;
1343 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1344 int regnum, u32 *data)
1346 struct sisusb_packet packet;
1347 int ret;
1349 packet.header = 0x008f;
1350 packet.address = (u32)regnum | 0x10000;
1351 ret = sisusb_send_packet(sisusb, 6, &packet);
1352 *data = packet.data;
1353 return ret;
1356 /* Clear video RAM */
1358 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1359 u32 address, int length)
1361 int ret, i;
1362 ssize_t j;
1364 if (address < sisusb->vrambase)
1365 return 1;
1367 if (address >= sisusb->vrambase + sisusb->vramsize)
1368 return 1;
1370 if (address + length > sisusb->vrambase + sisusb->vramsize)
1371 length = sisusb->vrambase + sisusb->vramsize - address;
1373 if (length <= 0)
1374 return 0;
1376 /* allocate free buffer/urb and clear the buffer */
1377 i = sisusb_alloc_outbuf(sisusb);
1378 if (i < 0)
1379 return -EBUSY;
1381 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1383 /* We can write a length > buffer size here. The buffer
1384 * data will simply be re-used (like a ring-buffer).
1386 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1388 /* Free the buffer/urb */
1389 sisusb_free_outbuf(sisusb, i);
1391 return ret;
1394 /* Initialize the graphics core (return 0 on success)
1395 * This resets the graphics hardware and puts it into
1396 * a defined mode (640x480@60Hz)
1399 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1400 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1401 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1402 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1403 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1404 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1405 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1406 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1408 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1409 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1411 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1413 int ret;
1414 u8 tmp8;
1416 ret = GETIREG(SISSR, 0x16, &tmp8);
1417 if (ramtype <= 1) {
1418 tmp8 &= 0x3f;
1419 ret |= SETIREG(SISSR, 0x16, tmp8);
1420 tmp8 |= 0x80;
1421 ret |= SETIREG(SISSR, 0x16, tmp8);
1422 } else {
1423 tmp8 |= 0xc0;
1424 ret |= SETIREG(SISSR, 0x16, tmp8);
1425 tmp8 &= 0x0f;
1426 ret |= SETIREG(SISSR, 0x16, tmp8);
1427 tmp8 |= 0x80;
1428 ret |= SETIREG(SISSR, 0x16, tmp8);
1429 tmp8 &= 0x0f;
1430 ret |= SETIREG(SISSR, 0x16, tmp8);
1431 tmp8 |= 0xd0;
1432 ret |= SETIREG(SISSR, 0x16, tmp8);
1433 tmp8 &= 0x0f;
1434 ret |= SETIREG(SISSR, 0x16, tmp8);
1435 tmp8 |= 0xa0;
1436 ret |= SETIREG(SISSR, 0x16, tmp8);
1438 return ret;
1441 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1442 int *bw, int *chab)
1444 int ret;
1445 u8 ramtype, done = 0;
1446 u32 t0, t1, t2, t3;
1447 u32 ramptr = SISUSB_PCI_MEMBASE;
1449 ret = GETIREG(SISSR, 0x3a, &ramtype);
1450 ramtype &= 3;
1452 ret |= SETIREG(SISSR, 0x13, 0x00);
1454 if (ramtype <= 1) {
1455 ret |= SETIREG(SISSR, 0x14, 0x12);
1456 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1457 } else {
1458 ret |= SETIREG(SISSR, 0x14, 0x02);
1461 ret |= sisusb_triggersr16(sisusb, ramtype);
1462 ret |= WRITEL(ramptr + 0, 0x01234567);
1463 ret |= WRITEL(ramptr + 4, 0x456789ab);
1464 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1465 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1466 ret |= WRITEL(ramptr + 16, 0x55555555);
1467 ret |= WRITEL(ramptr + 20, 0x55555555);
1468 ret |= WRITEL(ramptr + 24, 0xffffffff);
1469 ret |= WRITEL(ramptr + 28, 0xffffffff);
1470 ret |= READL(ramptr + 0, &t0);
1471 ret |= READL(ramptr + 4, &t1);
1472 ret |= READL(ramptr + 8, &t2);
1473 ret |= READL(ramptr + 12, &t3);
1475 if (ramtype <= 1) {
1477 *chab = 0; *bw = 64;
1479 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1480 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1481 *chab = 0; *bw = 64;
1482 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1485 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1486 *chab = 1; *bw = 64;
1487 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1489 ret |= sisusb_triggersr16(sisusb, ramtype);
1490 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1491 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1492 ret |= WRITEL(ramptr + 8, 0x55555555);
1493 ret |= WRITEL(ramptr + 12, 0x55555555);
1494 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1495 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1496 ret |= READL(ramptr + 4, &t1);
1498 if (t1 != 0xcdef0123) {
1499 *bw = 32;
1500 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1504 } else {
1506 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1508 done = 0;
1510 if (t1 == 0x456789ab) {
1511 if (t0 == 0x01234567) {
1512 *chab = 0; *bw = 64;
1513 done = 1;
1515 } else {
1516 if (t0 == 0x01234567) {
1517 *chab = 0; *bw = 32;
1518 ret |= SETIREG(SISSR, 0x14, 0x00);
1519 done = 1;
1523 if (!done) {
1524 ret |= SETIREG(SISSR, 0x14, 0x03);
1525 ret |= sisusb_triggersr16(sisusb, ramtype);
1527 ret |= WRITEL(ramptr + 0, 0x01234567);
1528 ret |= WRITEL(ramptr + 4, 0x456789ab);
1529 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1530 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1531 ret |= WRITEL(ramptr + 16, 0x55555555);
1532 ret |= WRITEL(ramptr + 20, 0x55555555);
1533 ret |= WRITEL(ramptr + 24, 0xffffffff);
1534 ret |= WRITEL(ramptr + 28, 0xffffffff);
1535 ret |= READL(ramptr + 0, &t0);
1536 ret |= READL(ramptr + 4, &t1);
1538 if (t1 == 0x456789ab) {
1539 if (t0 == 0x01234567) {
1540 *chab = 1; *bw = 64;
1541 return ret;
1542 } /* else error */
1543 } else {
1544 if (t0 == 0x01234567) {
1545 *chab = 1; *bw = 32;
1546 ret |= SETIREG(SISSR, 0x14, 0x01);
1547 } /* else error */
1551 return ret;
1554 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1556 int ret = 0;
1557 u32 ramptr = SISUSB_PCI_MEMBASE;
1558 u8 tmp1, tmp2, i, j;
1560 ret |= WRITEB(ramptr, 0xaa);
1561 ret |= WRITEB(ramptr + 16, 0x55);
1562 ret |= READB(ramptr, &tmp1);
1563 ret |= READB(ramptr + 16, &tmp2);
1564 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1565 for (i = 0, j = 16; i < 2; i++, j += 16) {
1566 ret |= GETIREG(SISSR, 0x21, &tmp1);
1567 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1568 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1569 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1570 ret |= SETIREG(SISSR, 0x21, tmp1);
1571 ret |= WRITEB(ramptr + 16 + j, j);
1572 ret |= READB(ramptr + 16 + j, &tmp1);
1573 if (tmp1 == j) {
1574 ret |= WRITEB(ramptr + j, j);
1575 break;
1579 return ret;
1582 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1583 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1585 int ret = 0, ranksize;
1586 u8 tmp;
1588 *iret = 0;
1590 if ((rankno == 2) && (dramtype[index][0] == 2))
1591 return ret;
1593 ranksize = dramtype[index][3] / 2 * bw / 32;
1595 if ((ranksize * rankno) > 128)
1596 return ret;
1598 tmp = 0;
1599 while ((ranksize >>= 1) > 0)
1600 tmp += 0x10;
1602 tmp |= ((rankno - 1) << 2);
1603 tmp |= ((bw / 64) & 0x02);
1604 tmp |= (chab & 0x01);
1606 ret = SETIREG(SISSR, 0x14, tmp);
1607 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1609 *iret = 1;
1611 return ret;
1614 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1615 u32 inc, int testn)
1617 int ret = 0, i;
1618 u32 j, tmp;
1620 *iret = 0;
1622 for (i = 0, j = 0; i < testn; i++) {
1623 ret |= WRITEL(sisusb->vrambase + j, j);
1624 j += inc;
1627 for (i = 0, j = 0; i < testn; i++) {
1628 ret |= READL(sisusb->vrambase + j, &tmp);
1629 if (tmp != j)
1630 return ret;
1632 j += inc;
1635 *iret = 1;
1636 return ret;
1639 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1640 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1642 int ret = 0, i, i2ret;
1643 u32 inc;
1645 *iret = 0;
1647 for (i = rankno; i >= 1; i--) {
1648 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1649 bw / 64 + i);
1650 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1651 if (!i2ret)
1652 return ret;
1655 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1656 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1657 if (!i2ret)
1658 return ret;
1660 inc = 1 << (10 + bw / 64);
1661 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1662 if (!i2ret)
1663 return ret;
1665 *iret = 1;
1666 return ret;
1669 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1670 int bw, int chab)
1672 int ret = 0, i2ret = 0, i, j;
1673 static const u8 sdramtype[13][5] = {
1674 { 2, 12, 9, 64, 0x35 },
1675 { 1, 13, 9, 64, 0x44 },
1676 { 2, 12, 8, 32, 0x31 },
1677 { 2, 11, 9, 32, 0x25 },
1678 { 1, 12, 9, 32, 0x34 },
1679 { 1, 13, 8, 32, 0x40 },
1680 { 2, 11, 8, 16, 0x21 },
1681 { 1, 12, 8, 16, 0x30 },
1682 { 1, 11, 9, 16, 0x24 },
1683 { 1, 11, 8, 8, 0x20 },
1684 { 2, 9, 8, 4, 0x01 },
1685 { 1, 10, 8, 4, 0x10 },
1686 { 1, 9, 8, 2, 0x00 }
1689 *iret = 1; /* error */
1691 for (i = 0; i < 13; i++) {
1692 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1693 for (j = 2; j > 0; j--) {
1694 ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1695 sdramtype, bw);
1696 if (!i2ret)
1697 continue;
1699 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1700 sdramtype);
1701 if (i2ret) {
1702 *iret = 0; /* ram size found */
1703 return ret;
1708 return ret;
1711 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1712 int clrall, int drwfr)
1714 int ret = 0;
1715 u32 address;
1716 int i, length, modex, modey, bpp;
1718 modex = 640; modey = 480; bpp = 2;
1720 address = sisusb->vrambase; /* Clear video ram */
1722 if (clrall)
1723 length = sisusb->vramsize;
1724 else
1725 length = modex * bpp * modey;
1727 ret = sisusb_clear_vram(sisusb, address, length);
1729 if (!ret && drwfr) {
1730 for (i = 0; i < modex; i++) {
1731 address = sisusb->vrambase + (i * bpp);
1732 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1733 address, 0xf100);
1734 address += (modex * (modey-1) * bpp);
1735 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1736 address, 0xf100);
1738 for (i = 0; i < modey; i++) {
1739 address = sisusb->vrambase + ((i * modex) * bpp);
1740 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1741 address, 0xf100);
1742 address += ((modex - 1) * bpp);
1743 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1744 address, 0xf100);
1748 return ret;
1751 static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1752 int touchengines)
1754 int ret = 0, i, j, modex, modey, bpp, du;
1755 u8 sr31, cr63, tmp8;
1756 static const char attrdata[] = {
1757 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1758 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1759 0x01, 0x00, 0x00, 0x00
1761 static const char crtcrdata[] = {
1762 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1763 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1764 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1765 0xff
1767 static const char grcdata[] = {
1768 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1769 0xff
1771 static const char crtcdata[] = {
1772 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1773 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1774 0x00
1777 modex = 640; modey = 480; bpp = 2;
1779 GETIREG(SISSR, 0x31, &sr31);
1780 GETIREG(SISCR, 0x63, &cr63);
1781 SETIREGOR(SISSR, 0x01, 0x20);
1782 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1783 SETIREGOR(SISCR, 0x17, 0x80);
1784 SETIREGOR(SISSR, 0x1f, 0x04);
1785 SETIREGAND(SISSR, 0x07, 0xfb);
1786 SETIREG(SISSR, 0x00, 0x03); /* seq */
1787 SETIREG(SISSR, 0x01, 0x21);
1788 SETIREG(SISSR, 0x02, 0x0f);
1789 SETIREG(SISSR, 0x03, 0x00);
1790 SETIREG(SISSR, 0x04, 0x0e);
1791 SETREG(SISMISCW, 0x23); /* misc */
1792 for (i = 0; i <= 0x18; i++) { /* crtc */
1793 SETIREG(SISCR, i, crtcrdata[i]);
1795 for (i = 0; i <= 0x13; i++) { /* att */
1796 GETREG(SISINPSTAT, &tmp8);
1797 SETREG(SISAR, i);
1798 SETREG(SISAR, attrdata[i]);
1800 GETREG(SISINPSTAT, &tmp8);
1801 SETREG(SISAR, 0x14);
1802 SETREG(SISAR, 0x00);
1803 GETREG(SISINPSTAT, &tmp8);
1804 SETREG(SISAR, 0x20);
1805 GETREG(SISINPSTAT, &tmp8);
1806 for (i = 0; i <= 0x08; i++) { /* grc */
1807 SETIREG(SISGR, i, grcdata[i]);
1809 SETIREGAND(SISGR, 0x05, 0xbf);
1810 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1811 SETIREG(SISSR, i, 0x00);
1813 SETIREGAND(SISSR, 0x37, 0xfe);
1814 SETREG(SISMISCW, 0xef); /* sync */
1815 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1816 for (j = 0x00, i = 0; i <= 7; i++, j++)
1817 SETIREG(SISCR, j, crtcdata[i]);
1819 for (j = 0x10; i <= 10; i++, j++)
1820 SETIREG(SISCR, j, crtcdata[i]);
1822 for (j = 0x15; i <= 12; i++, j++)
1823 SETIREG(SISCR, j, crtcdata[i]);
1825 for (j = 0x0A; i <= 15; i++, j++)
1826 SETIREG(SISSR, j, crtcdata[i]);
1828 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1829 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1830 SETIREG(SISCR, 0x14, 0x4f);
1831 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1832 if (modex % 16)
1833 du += bpp;
1835 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1836 SETIREG(SISCR, 0x13, (du & 0xff));
1837 du <<= 5;
1838 tmp8 = du >> 8;
1839 if (du & 0xff)
1840 tmp8++;
1842 SETIREG(SISSR, 0x10, tmp8);
1843 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1844 SETIREG(SISSR, 0x2b, 0x1b);
1845 SETIREG(SISSR, 0x2c, 0xe1);
1846 SETIREG(SISSR, 0x2d, 0x01);
1847 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1848 SETIREG(SISSR, 0x08, 0xae);
1849 SETIREGAND(SISSR, 0x09, 0xf0);
1850 SETIREG(SISSR, 0x08, 0x34);
1851 SETIREGOR(SISSR, 0x3d, 0x01);
1852 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1853 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1854 SETIREG(SISCR, 0x19, 0x00);
1855 SETIREGAND(SISCR, 0x1a, 0xfc);
1856 SETIREGAND(SISSR, 0x0f, 0xb7);
1857 SETIREGAND(SISSR, 0x31, 0xfb);
1858 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1859 SETIREGAND(SISSR, 0x32, 0xf3);
1860 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1861 SETIREG(SISCR, 0x52, 0x6c);
1863 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1864 SETIREG(SISCR, 0x0c, 0x00);
1865 SETIREG(SISSR, 0x0d, 0x00);
1866 SETIREGAND(SISSR, 0x37, 0xfe);
1868 SETIREG(SISCR, 0x32, 0x20);
1869 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1870 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1871 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1873 if (touchengines) {
1874 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1875 SETIREGOR(SISSR, 0x1e, 0x5a);
1877 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1878 SETIREG(SISSR, 0x27, 0x1f);
1879 SETIREG(SISSR, 0x26, 0x00);
1882 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1884 return ret;
1887 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1889 int ret = 0, i, j, bw, chab, iret, retry = 3;
1890 u8 tmp8, ramtype;
1891 u32 tmp32;
1892 static const char mclktable[] = {
1893 0x3b, 0x22, 0x01, 143,
1894 0x3b, 0x22, 0x01, 143,
1895 0x3b, 0x22, 0x01, 143,
1896 0x3b, 0x22, 0x01, 143
1898 static const char eclktable[] = {
1899 0x3b, 0x22, 0x01, 143,
1900 0x3b, 0x22, 0x01, 143,
1901 0x3b, 0x22, 0x01, 143,
1902 0x3b, 0x22, 0x01, 143
1904 static const char ramtypetable1[] = {
1905 0x00, 0x04, 0x60, 0x60,
1906 0x0f, 0x0f, 0x1f, 0x1f,
1907 0xba, 0xba, 0xba, 0xba,
1908 0xa9, 0xa9, 0xac, 0xac,
1909 0xa0, 0xa0, 0xa0, 0xa8,
1910 0x00, 0x00, 0x02, 0x02,
1911 0x30, 0x30, 0x40, 0x40
1913 static const char ramtypetable2[] = {
1914 0x77, 0x77, 0x44, 0x44,
1915 0x77, 0x77, 0x44, 0x44,
1916 0x00, 0x00, 0x00, 0x00,
1917 0x5b, 0x5b, 0xab, 0xab,
1918 0x00, 0x00, 0xf0, 0xf8
1921 while (retry--) {
1923 /* Enable VGA */
1924 ret = GETREG(SISVGAEN, &tmp8);
1925 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1927 /* Enable GPU access to VRAM */
1928 ret |= GETREG(SISMISCR, &tmp8);
1929 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1931 if (ret)
1932 continue;
1934 /* Reset registers */
1935 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1936 ret |= SETIREG(SISSR, 0x05, 0x86);
1937 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1939 ret |= SETREG(SISMISCW, 0x67);
1941 for (i = 0x06; i <= 0x1f; i++)
1942 ret |= SETIREG(SISSR, i, 0x00);
1944 for (i = 0x21; i <= 0x27; i++)
1945 ret |= SETIREG(SISSR, i, 0x00);
1947 for (i = 0x31; i <= 0x3d; i++)
1948 ret |= SETIREG(SISSR, i, 0x00);
1950 for (i = 0x12; i <= 0x1b; i++)
1951 ret |= SETIREG(SISSR, i, 0x00);
1953 for (i = 0x79; i <= 0x7c; i++)
1954 ret |= SETIREG(SISCR, i, 0x00);
1956 if (ret)
1957 continue;
1959 ret |= SETIREG(SISCR, 0x63, 0x80);
1961 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1962 ramtype &= 0x03;
1964 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1965 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1966 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1968 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1969 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1970 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1972 ret |= SETIREG(SISSR, 0x07, 0x18);
1973 ret |= SETIREG(SISSR, 0x11, 0x0f);
1975 if (ret)
1976 continue;
1978 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1979 ret |= SETIREG(SISSR, i,
1980 ramtypetable1[(j*4) + ramtype]);
1982 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1983 ret |= SETIREG(SISCR, i,
1984 ramtypetable2[(j*4) + ramtype]);
1987 ret |= SETIREG(SISCR, 0x49, 0xaa);
1989 ret |= SETIREG(SISSR, 0x1f, 0x00);
1990 ret |= SETIREG(SISSR, 0x20, 0xa0);
1991 ret |= SETIREG(SISSR, 0x23, 0xf6);
1992 ret |= SETIREG(SISSR, 0x24, 0x0d);
1993 ret |= SETIREG(SISSR, 0x25, 0x33);
1995 ret |= SETIREG(SISSR, 0x11, 0x0f);
1997 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1999 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2001 if (ret)
2002 continue;
2004 ret |= SETIREG(SISPART1, 0x00, 0x00);
2006 ret |= GETIREG(SISSR, 0x13, &tmp8);
2007 tmp8 >>= 4;
2009 ret |= SETIREG(SISPART1, 0x02, 0x00);
2010 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2012 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2013 tmp32 &= 0x00f00000;
2014 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2015 ret |= SETIREG(SISSR, 0x25, tmp8);
2016 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2017 ret |= SETIREG(SISCR, 0x49, tmp8);
2019 ret |= SETIREG(SISSR, 0x27, 0x1f);
2020 ret |= SETIREG(SISSR, 0x31, 0x00);
2021 ret |= SETIREG(SISSR, 0x32, 0x11);
2022 ret |= SETIREG(SISSR, 0x33, 0x00);
2024 if (ret)
2025 continue;
2027 ret |= SETIREG(SISCR, 0x83, 0x00);
2029 ret |= sisusb_set_default_mode(sisusb, 0);
2031 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2032 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2033 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2035 ret |= sisusb_triggersr16(sisusb, ramtype);
2037 /* Disable refresh */
2038 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2039 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2041 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2042 ret |= sisusb_verify_mclk(sisusb);
2044 if (ramtype <= 1) {
2045 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2046 if (iret) {
2047 dev_err(&sisusb->sisusb_dev->dev,
2048 "RAM size detection failed, assuming 8MB video RAM\n");
2049 ret |= SETIREG(SISSR, 0x14, 0x31);
2050 /* TODO */
2052 } else {
2053 dev_err(&sisusb->sisusb_dev->dev,
2054 "DDR RAM device found, assuming 8MB video RAM\n");
2055 ret |= SETIREG(SISSR, 0x14, 0x31);
2056 /* *** TODO *** */
2059 /* Enable refresh */
2060 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2061 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2062 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2064 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2066 ret |= SETIREG(SISSR, 0x22, 0xfb);
2067 ret |= SETIREG(SISSR, 0x21, 0xa5);
2069 if (ret == 0)
2070 break;
2073 return ret;
2076 #undef SETREG
2077 #undef GETREG
2078 #undef SETIREG
2079 #undef GETIREG
2080 #undef SETIREGOR
2081 #undef SETIREGAND
2082 #undef SETIREGANDOR
2083 #undef READL
2084 #undef WRITEL
2086 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2088 u8 tmp8, tmp82, ramtype;
2089 int bw = 0;
2090 char *ramtypetext1 = NULL;
2091 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2092 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2093 static const int busSDR[4] = {64, 64, 128, 128};
2094 static const int busDDR[4] = {32, 32, 64, 64};
2095 static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2097 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2098 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2099 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2100 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2101 ramtype &= 0x03;
2102 switch ((tmp8 >> 2) & 0x03) {
2103 case 0:
2104 ramtypetext1 = "1 ch/1 r";
2105 if (tmp82 & 0x10)
2106 bw = 32;
2107 else
2108 bw = busSDR[(tmp8 & 0x03)];
2110 break;
2111 case 1:
2112 ramtypetext1 = "1 ch/2 r";
2113 sisusb->vramsize <<= 1;
2114 bw = busSDR[(tmp8 & 0x03)];
2115 break;
2116 case 2:
2117 ramtypetext1 = "asymmeric";
2118 sisusb->vramsize += sisusb->vramsize/2;
2119 bw = busDDRA[(tmp8 & 0x03)];
2120 break;
2121 case 3:
2122 ramtypetext1 = "2 channel";
2123 sisusb->vramsize <<= 1;
2124 bw = busDDR[(tmp8 & 0x03)];
2125 break;
2128 dev_info(&sisusb->sisusb_dev->dev,
2129 "%dMB %s %cDR S%cRAM, bus width %d\n",
2130 sisusb->vramsize >> 20, ramtypetext1,
2131 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2134 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2136 struct sisusb_packet packet;
2137 int ret;
2138 u32 tmp32;
2140 /* Do some magic */
2141 packet.header = 0x001f;
2142 packet.address = 0x00000324;
2143 packet.data = 0x00000004;
2144 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2146 packet.header = 0x001f;
2147 packet.address = 0x00000364;
2148 packet.data = 0x00000004;
2149 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2151 packet.header = 0x001f;
2152 packet.address = 0x00000384;
2153 packet.data = 0x00000004;
2154 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2156 packet.header = 0x001f;
2157 packet.address = 0x00000100;
2158 packet.data = 0x00000700;
2159 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2161 packet.header = 0x000f;
2162 packet.address = 0x00000004;
2163 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2164 packet.data |= 0x17;
2165 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2167 /* Init BAR 0 (VRAM) */
2168 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2169 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2170 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2171 tmp32 &= 0x0f;
2172 tmp32 |= SISUSB_PCI_MEMBASE;
2173 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2175 /* Init BAR 1 (MMIO) */
2176 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2177 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2178 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2179 tmp32 &= 0x0f;
2180 tmp32 |= SISUSB_PCI_MMIOBASE;
2181 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2183 /* Init BAR 2 (i/o ports) */
2184 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2185 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2186 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2187 tmp32 &= 0x0f;
2188 tmp32 |= SISUSB_PCI_IOPORTBASE;
2189 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2191 /* Enable memory and i/o access */
2192 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2193 tmp32 |= 0x3;
2194 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2196 if (ret == 0) {
2197 /* Some further magic */
2198 packet.header = 0x001f;
2199 packet.address = 0x00000050;
2200 packet.data = 0x000000ff;
2201 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2204 return ret;
2207 /* Initialize the graphics device (return 0 on success)
2208 * This initializes the net2280 as well as the PCI registers
2209 * of the graphics board.
2212 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2214 int ret = 0, test = 0;
2215 u32 tmp32;
2217 if (sisusb->devinit == 1) {
2218 /* Read PCI BARs and see if they have been set up */
2219 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2220 if (ret)
2221 return ret;
2223 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2224 test++;
2226 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2227 if (ret)
2228 return ret;
2230 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2231 test++;
2233 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2234 if (ret)
2235 return ret;
2237 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2238 test++;
2241 /* No? So reset the device */
2242 if ((sisusb->devinit == 0) || (test != 3)) {
2244 ret |= sisusb_do_init_gfxdevice(sisusb);
2246 if (ret == 0)
2247 sisusb->devinit = 1;
2251 if (sisusb->devinit) {
2252 /* Initialize the graphics core */
2253 if (sisusb_init_gfxcore(sisusb) == 0) {
2254 sisusb->gfxinit = 1;
2255 sisusb_get_ramconfig(sisusb);
2256 ret |= sisusb_set_default_mode(sisusb, 1);
2257 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2261 return ret;
2265 #ifdef INCL_SISUSB_CON
2267 /* Set up default text mode:
2268 * - Set text mode (0x03)
2269 * - Upload default font
2270 * - Upload user font (if available)
2273 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2275 int ret = 0, slot = sisusb->font_slot, i;
2276 const struct font_desc *myfont;
2277 u8 *tempbuf;
2278 u16 *tempbufb;
2279 size_t written;
2280 static const char bootstring[] =
2281 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2282 static const char bootlogo[] = "(o_ //\\ V_/_";
2284 /* sisusb->lock is down */
2286 if (!sisusb->SiS_Pr)
2287 return 1;
2289 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2290 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2292 /* Set mode 0x03 */
2293 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2295 myfont = find_font("VGA8x16");
2296 if (!myfont)
2297 return 1;
2299 tempbuf = vmalloc(8192);
2300 if (!tempbuf)
2301 return 1;
2303 for (i = 0; i < 256; i++)
2304 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2306 /* Upload default font */
2307 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2308 0, 1, NULL, 16, 0);
2310 vfree(tempbuf);
2312 /* Upload user font (and reset current slot) */
2313 if (sisusb->font_backup) {
2314 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2315 8192, sisusb->font_backup_512, 1, NULL,
2316 sisusb->font_backup_height, 0);
2317 if (slot != 2)
2318 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2319 NULL, 16, 0);
2322 if (init && !sisusb->scrbuf) {
2324 tempbuf = vmalloc(8192);
2325 if (tempbuf) {
2327 i = 4096;
2328 tempbufb = (u16 *)tempbuf;
2329 while (i--)
2330 *(tempbufb++) = 0x0720;
2332 i = 0;
2333 tempbufb = (u16 *)tempbuf;
2334 while (bootlogo[i]) {
2335 *(tempbufb++) = 0x0700 | bootlogo[i++];
2336 if (!(i % 4))
2337 tempbufb += 76;
2340 i = 0;
2341 tempbufb = (u16 *)tempbuf + 6;
2342 while (bootstring[i])
2343 *(tempbufb++) = 0x0700 | bootstring[i++];
2345 ret |= sisusb_copy_memory(sisusb, tempbuf,
2346 sisusb->vrambase, 8192, &written);
2348 vfree(tempbuf);
2352 } else if (sisusb->scrbuf) {
2354 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2355 sisusb->vrambase, sisusb->scrbuf_size,
2356 &written);
2360 if (sisusb->sisusb_cursor_size_from >= 0 &&
2361 sisusb->sisusb_cursor_size_to >= 0) {
2362 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2363 sisusb->sisusb_cursor_size_from);
2364 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2365 sisusb->sisusb_cursor_size_to);
2366 } else {
2367 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2368 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2369 sisusb->sisusb_cursor_size_to = -1;
2372 slot = sisusb->sisusb_cursor_loc;
2373 if (slot < 0)
2374 slot = 0;
2376 sisusb->sisusb_cursor_loc = -1;
2377 sisusb->bad_cursor_pos = 1;
2379 sisusb_set_cursor(sisusb, slot);
2381 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2382 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2384 sisusb->textmodedestroyed = 0;
2386 /* sisusb->lock is down */
2388 return ret;
2391 #endif
2393 /* fops */
2395 static int sisusb_open(struct inode *inode, struct file *file)
2397 struct sisusb_usb_data *sisusb;
2398 struct usb_interface *interface;
2399 int subminor = iminor(inode);
2401 interface = usb_find_interface(&sisusb_driver, subminor);
2402 if (!interface)
2403 return -ENODEV;
2405 sisusb = usb_get_intfdata(interface);
2406 if (!sisusb)
2407 return -ENODEV;
2409 mutex_lock(&sisusb->lock);
2411 if (!sisusb->present || !sisusb->ready) {
2412 mutex_unlock(&sisusb->lock);
2413 return -ENODEV;
2416 if (sisusb->isopen) {
2417 mutex_unlock(&sisusb->lock);
2418 return -EBUSY;
2421 if (!sisusb->devinit) {
2422 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2423 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2424 if (sisusb_init_gfxdevice(sisusb, 0)) {
2425 mutex_unlock(&sisusb->lock);
2426 dev_err(&sisusb->sisusb_dev->dev,
2427 "Failed to initialize device\n");
2428 return -EIO;
2430 } else {
2431 mutex_unlock(&sisusb->lock);
2432 dev_err(&sisusb->sisusb_dev->dev,
2433 "Device not attached to USB 2.0 hub\n");
2434 return -EIO;
2438 /* Increment usage count for our sisusb */
2439 kref_get(&sisusb->kref);
2441 sisusb->isopen = 1;
2443 file->private_data = sisusb;
2445 mutex_unlock(&sisusb->lock);
2447 return 0;
2450 void sisusb_delete(struct kref *kref)
2452 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2454 if (!sisusb)
2455 return;
2457 usb_put_dev(sisusb->sisusb_dev);
2459 sisusb->sisusb_dev = NULL;
2460 sisusb_free_buffers(sisusb);
2461 sisusb_free_urbs(sisusb);
2462 #ifdef INCL_SISUSB_CON
2463 kfree(sisusb->SiS_Pr);
2464 #endif
2465 kfree(sisusb);
2468 static int sisusb_release(struct inode *inode, struct file *file)
2470 struct sisusb_usb_data *sisusb;
2472 sisusb = file->private_data;
2473 if (!sisusb)
2474 return -ENODEV;
2476 mutex_lock(&sisusb->lock);
2478 if (sisusb->present) {
2479 /* Wait for all URBs to finish if device still present */
2480 if (!sisusb_wait_all_out_complete(sisusb))
2481 sisusb_kill_all_busy(sisusb);
2484 sisusb->isopen = 0;
2485 file->private_data = NULL;
2487 mutex_unlock(&sisusb->lock);
2489 /* decrement the usage count on our device */
2490 kref_put(&sisusb->kref, sisusb_delete);
2492 return 0;
2495 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2496 size_t count, loff_t *ppos)
2498 struct sisusb_usb_data *sisusb;
2499 ssize_t bytes_read = 0;
2500 int errno = 0;
2501 u8 buf8;
2502 u16 buf16;
2503 u32 buf32, address;
2505 sisusb = file->private_data;
2506 if (!sisusb)
2507 return -ENODEV;
2509 mutex_lock(&sisusb->lock);
2511 /* Sanity check */
2512 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2513 mutex_unlock(&sisusb->lock);
2514 return -ENODEV;
2517 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2518 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2520 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2521 SISUSB_PCI_IOPORTBASE;
2523 /* Read i/o ports
2524 * Byte, word and long(32) can be read. As this
2525 * emulates inX instructions, the data returned is
2526 * in machine-endianness.
2528 switch (count) {
2529 case 1:
2530 if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2531 address, &buf8))
2532 errno = -EIO;
2533 else if (put_user(buf8, (u8 __user *)buffer))
2534 errno = -EFAULT;
2535 else
2536 bytes_read = 1;
2538 break;
2540 case 2:
2541 if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2542 address, &buf16))
2543 errno = -EIO;
2544 else if (put_user(buf16, (u16 __user *)buffer))
2545 errno = -EFAULT;
2546 else
2547 bytes_read = 2;
2549 break;
2551 case 4:
2552 if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2553 address, &buf32))
2554 errno = -EIO;
2555 else if (put_user(buf32, (u32 __user *)buffer))
2556 errno = -EFAULT;
2557 else
2558 bytes_read = 4;
2560 break;
2562 default:
2563 errno = -EIO;
2567 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2568 SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2570 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2571 SISUSB_PCI_MEMBASE;
2573 /* Read video ram
2574 * Remember: Data delivered is never endian-corrected
2576 errno = sisusb_read_mem_bulk(sisusb, address,
2577 NULL, count, buffer, &bytes_read);
2579 if (bytes_read)
2580 errno = bytes_read;
2582 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2583 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2584 SISUSB_PCI_MMIOSIZE) {
2586 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2587 SISUSB_PCI_MMIOBASE;
2589 /* Read MMIO
2590 * Remember: Data delivered is never endian-corrected
2592 errno = sisusb_read_mem_bulk(sisusb, address,
2593 NULL, count, buffer, &bytes_read);
2595 if (bytes_read)
2596 errno = bytes_read;
2598 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2599 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2601 if (count != 4) {
2602 mutex_unlock(&sisusb->lock);
2603 return -EINVAL;
2606 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2608 /* Read PCI config register
2609 * Return value delivered in machine endianness.
2611 if (sisusb_read_pci_config(sisusb, address, &buf32))
2612 errno = -EIO;
2613 else if (put_user(buf32, (u32 __user *)buffer))
2614 errno = -EFAULT;
2615 else
2616 bytes_read = 4;
2618 } else {
2620 errno = -EBADFD;
2624 (*ppos) += bytes_read;
2626 mutex_unlock(&sisusb->lock);
2628 return errno ? errno : bytes_read;
2631 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2632 size_t count, loff_t *ppos)
2634 struct sisusb_usb_data *sisusb;
2635 int errno = 0;
2636 ssize_t bytes_written = 0;
2637 u8 buf8;
2638 u16 buf16;
2639 u32 buf32, address;
2641 sisusb = file->private_data;
2642 if (!sisusb)
2643 return -ENODEV;
2645 mutex_lock(&sisusb->lock);
2647 /* Sanity check */
2648 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2649 mutex_unlock(&sisusb->lock);
2650 return -ENODEV;
2653 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2654 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2656 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2657 SISUSB_PCI_IOPORTBASE;
2659 /* Write i/o ports
2660 * Byte, word and long(32) can be written. As this
2661 * emulates outX instructions, the data is expected
2662 * in machine-endianness.
2664 switch (count) {
2665 case 1:
2666 if (get_user(buf8, (u8 __user *)buffer))
2667 errno = -EFAULT;
2668 else if (sisusb_write_memio_byte(sisusb,
2669 SISUSB_TYPE_IO, address, buf8))
2670 errno = -EIO;
2671 else
2672 bytes_written = 1;
2674 break;
2676 case 2:
2677 if (get_user(buf16, (u16 __user *)buffer))
2678 errno = -EFAULT;
2679 else if (sisusb_write_memio_word(sisusb,
2680 SISUSB_TYPE_IO, address, buf16))
2681 errno = -EIO;
2682 else
2683 bytes_written = 2;
2685 break;
2687 case 4:
2688 if (get_user(buf32, (u32 __user *)buffer))
2689 errno = -EFAULT;
2690 else if (sisusb_write_memio_long(sisusb,
2691 SISUSB_TYPE_IO, address, buf32))
2692 errno = -EIO;
2693 else
2694 bytes_written = 4;
2696 break;
2698 default:
2699 errno = -EIO;
2702 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2703 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE +
2704 sisusb->vramsize) {
2706 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2707 SISUSB_PCI_MEMBASE;
2709 /* Write video ram.
2710 * Buffer is copied 1:1, therefore, on big-endian
2711 * machines, the data must be swapped by userland
2712 * in advance (if applicable; no swapping in 8bpp
2713 * mode or if YUV data is being transferred).
2715 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2716 count, buffer, 0, &bytes_written);
2718 if (bytes_written)
2719 errno = bytes_written;
2721 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2722 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2723 SISUSB_PCI_MMIOSIZE) {
2725 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2726 SISUSB_PCI_MMIOBASE;
2728 /* Write MMIO.
2729 * Buffer is copied 1:1, therefore, on big-endian
2730 * machines, the data must be swapped by userland
2731 * in advance.
2733 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2734 count, buffer, 0, &bytes_written);
2736 if (bytes_written)
2737 errno = bytes_written;
2739 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2740 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2741 SISUSB_PCI_PCONFSIZE) {
2743 if (count != 4) {
2744 mutex_unlock(&sisusb->lock);
2745 return -EINVAL;
2748 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2750 /* Write PCI config register.
2751 * Given value expected in machine endianness.
2753 if (get_user(buf32, (u32 __user *)buffer))
2754 errno = -EFAULT;
2755 else if (sisusb_write_pci_config(sisusb, address, buf32))
2756 errno = -EIO;
2757 else
2758 bytes_written = 4;
2761 } else {
2763 /* Error */
2764 errno = -EBADFD;
2768 (*ppos) += bytes_written;
2770 mutex_unlock(&sisusb->lock);
2772 return errno ? errno : bytes_written;
2775 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2777 struct sisusb_usb_data *sisusb;
2778 loff_t ret;
2780 sisusb = file->private_data;
2781 if (!sisusb)
2782 return -ENODEV;
2784 mutex_lock(&sisusb->lock);
2786 /* Sanity check */
2787 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2788 mutex_unlock(&sisusb->lock);
2789 return -ENODEV;
2792 ret = no_seek_end_llseek(file, offset, orig);
2794 mutex_unlock(&sisusb->lock);
2795 return ret;
2798 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2799 struct sisusb_command *y, unsigned long arg)
2801 int retval, port, length;
2802 u32 address;
2804 /* All our commands require the device
2805 * to be initialized.
2807 if (!sisusb->devinit)
2808 return -ENODEV;
2810 port = y->data3 -
2811 SISUSB_PCI_PSEUDO_IOPORTBASE +
2812 SISUSB_PCI_IOPORTBASE;
2814 switch (y->operation) {
2815 case SUCMD_GET:
2816 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2817 if (!retval) {
2818 if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2819 retval = -EFAULT;
2821 break;
2823 case SUCMD_SET:
2824 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2825 break;
2827 case SUCMD_SETOR:
2828 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2829 break;
2831 case SUCMD_SETAND:
2832 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2833 break;
2835 case SUCMD_SETANDOR:
2836 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2837 y->data1, y->data2);
2838 break;
2840 case SUCMD_SETMASK:
2841 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2842 y->data1, y->data2);
2843 break;
2845 case SUCMD_CLRSCR:
2846 /* Gfx core must be initialized */
2847 if (!sisusb->gfxinit)
2848 return -ENODEV;
2850 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2851 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2852 SISUSB_PCI_MEMBASE;
2853 retval = sisusb_clear_vram(sisusb, address, length);
2854 break;
2856 case SUCMD_HANDLETEXTMODE:
2857 retval = 0;
2858 #ifdef INCL_SISUSB_CON
2859 /* Gfx core must be initialized, SiS_Pr must exist */
2860 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2861 return -ENODEV;
2863 switch (y->data0) {
2864 case 0:
2865 retval = sisusb_reset_text_mode(sisusb, 0);
2866 break;
2867 case 1:
2868 sisusb->textmodedestroyed = 1;
2869 break;
2871 #endif
2872 break;
2874 #ifdef INCL_SISUSB_CON
2875 case SUCMD_SETMODE:
2876 /* Gfx core must be initialized, SiS_Pr must exist */
2877 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2878 return -ENODEV;
2880 retval = 0;
2882 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2883 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2885 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2886 retval = -EINVAL;
2888 break;
2890 case SUCMD_SETVESAMODE:
2891 /* Gfx core must be initialized, SiS_Pr must exist */
2892 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2893 return -ENODEV;
2895 retval = 0;
2897 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2898 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2900 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2901 retval = -EINVAL;
2903 break;
2904 #endif
2906 default:
2907 retval = -EINVAL;
2910 if (retval > 0)
2911 retval = -EIO;
2913 return retval;
2916 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2918 struct sisusb_usb_data *sisusb;
2919 struct sisusb_info x;
2920 struct sisusb_command y;
2921 long retval = 0;
2922 u32 __user *argp = (u32 __user *)arg;
2924 sisusb = file->private_data;
2925 if (!sisusb)
2926 return -ENODEV;
2928 mutex_lock(&sisusb->lock);
2930 /* Sanity check */
2931 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2932 retval = -ENODEV;
2933 goto err_out;
2936 switch (cmd) {
2937 case SISUSB_GET_CONFIG_SIZE:
2939 if (put_user(sizeof(x), argp))
2940 retval = -EFAULT;
2942 break;
2944 case SISUSB_GET_CONFIG:
2946 x.sisusb_id = SISUSB_ID;
2947 x.sisusb_version = SISUSB_VERSION;
2948 x.sisusb_revision = SISUSB_REVISION;
2949 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2950 x.sisusb_gfxinit = sisusb->gfxinit;
2951 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2952 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2953 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2954 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2955 x.sisusb_vramsize = sisusb->vramsize;
2956 x.sisusb_minor = sisusb->minor;
2957 x.sisusb_fbdevactive = 0;
2958 #ifdef INCL_SISUSB_CON
2959 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
2960 #else
2961 x.sisusb_conactive = 0;
2962 #endif
2963 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2965 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2966 retval = -EFAULT;
2968 break;
2970 case SISUSB_COMMAND:
2972 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2973 retval = -EFAULT;
2974 else
2975 retval = sisusb_handle_command(sisusb, &y, arg);
2977 break;
2979 default:
2980 retval = -ENOTTY;
2981 break;
2984 err_out:
2985 mutex_unlock(&sisusb->lock);
2986 return retval;
2989 #ifdef SISUSB_NEW_CONFIG_COMPAT
2990 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2991 unsigned long arg)
2993 long retval;
2995 switch (cmd) {
2996 case SISUSB_GET_CONFIG_SIZE:
2997 case SISUSB_GET_CONFIG:
2998 case SISUSB_COMMAND:
2999 retval = sisusb_ioctl(f, cmd, arg);
3000 return retval;
3002 default:
3003 return -ENOIOCTLCMD;
3006 #endif
3008 static const struct file_operations usb_sisusb_fops = {
3009 .owner = THIS_MODULE,
3010 .open = sisusb_open,
3011 .release = sisusb_release,
3012 .read = sisusb_read,
3013 .write = sisusb_write,
3014 .llseek = sisusb_lseek,
3015 #ifdef SISUSB_NEW_CONFIG_COMPAT
3016 .compat_ioctl = sisusb_compat_ioctl,
3017 #endif
3018 .unlocked_ioctl = sisusb_ioctl
3021 static struct usb_class_driver usb_sisusb_class = {
3022 .name = "sisusbvga%d",
3023 .fops = &usb_sisusb_fops,
3024 .minor_base = SISUSB_MINOR
3027 static int sisusb_probe(struct usb_interface *intf,
3028 const struct usb_device_id *id)
3030 struct usb_device *dev = interface_to_usbdev(intf);
3031 struct sisusb_usb_data *sisusb;
3032 int retval = 0, i;
3034 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3035 dev->devnum);
3037 /* Allocate memory for our private */
3038 sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3039 if (!sisusb)
3040 return -ENOMEM;
3042 kref_init(&sisusb->kref);
3044 mutex_init(&(sisusb->lock));
3046 /* Register device */
3047 retval = usb_register_dev(intf, &usb_sisusb_class);
3048 if (retval) {
3049 dev_err(&sisusb->sisusb_dev->dev,
3050 "Failed to get a minor for device %d\n",
3051 dev->devnum);
3052 retval = -ENODEV;
3053 goto error_1;
3056 sisusb->sisusb_dev = dev;
3057 sisusb->minor = intf->minor;
3058 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3059 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3060 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3061 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3062 /* Everything else is zero */
3064 /* Allocate buffers */
3065 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3066 sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3067 if (!sisusb->ibuf) {
3068 retval = -ENOMEM;
3069 goto error_2;
3072 sisusb->numobufs = 0;
3073 sisusb->obufsize = SISUSB_OBUF_SIZE;
3074 for (i = 0; i < NUMOBUFS; i++) {
3075 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3076 if (!sisusb->obuf[i]) {
3077 if (i == 0) {
3078 retval = -ENOMEM;
3079 goto error_3;
3081 break;
3083 sisusb->numobufs++;
3086 /* Allocate URBs */
3087 sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3088 if (!sisusb->sisurbin) {
3089 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3090 retval = -ENOMEM;
3091 goto error_3;
3093 sisusb->completein = 1;
3095 for (i = 0; i < sisusb->numobufs; i++) {
3096 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3097 if (!sisusb->sisurbout[i]) {
3098 dev_err(&sisusb->sisusb_dev->dev,
3099 "Failed to allocate URBs\n");
3100 retval = -ENOMEM;
3101 goto error_4;
3103 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3104 sisusb->urbout_context[i].urbindex = i;
3105 sisusb->urbstatus[i] = 0;
3108 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3109 sisusb->numobufs);
3111 #ifdef INCL_SISUSB_CON
3112 /* Allocate our SiS_Pr */
3113 sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3114 if (!sisusb->SiS_Pr) {
3115 retval = -ENOMEM;
3116 goto error_4;
3118 #endif
3120 /* Do remaining init stuff */
3122 init_waitqueue_head(&sisusb->wait_q);
3124 usb_set_intfdata(intf, sisusb);
3126 usb_get_dev(sisusb->sisusb_dev);
3128 sisusb->present = 1;
3130 if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
3131 int initscreen = 1;
3132 #ifdef INCL_SISUSB_CON
3133 if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3134 sisusb_first_vc <= sisusb_last_vc &&
3135 sisusb_last_vc <= MAX_NR_CONSOLES)
3136 initscreen = 0;
3137 #endif
3138 if (sisusb_init_gfxdevice(sisusb, initscreen))
3139 dev_err(&sisusb->sisusb_dev->dev,
3140 "Failed to early initialize device\n");
3142 } else
3143 dev_info(&sisusb->sisusb_dev->dev,
3144 "Not attached to USB 2.0 hub, deferring init\n");
3146 sisusb->ready = 1;
3148 #ifdef SISUSBENDIANTEST
3149 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3150 sisusb_testreadwrite(sisusb);
3151 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3152 #endif
3154 #ifdef INCL_SISUSB_CON
3155 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3156 #endif
3158 return 0;
3160 error_4:
3161 sisusb_free_urbs(sisusb);
3162 error_3:
3163 sisusb_free_buffers(sisusb);
3164 error_2:
3165 usb_deregister_dev(intf, &usb_sisusb_class);
3166 error_1:
3167 kfree(sisusb);
3168 return retval;
3171 static void sisusb_disconnect(struct usb_interface *intf)
3173 struct sisusb_usb_data *sisusb;
3175 /* This should *not* happen */
3176 sisusb = usb_get_intfdata(intf);
3177 if (!sisusb)
3178 return;
3180 #ifdef INCL_SISUSB_CON
3181 sisusb_console_exit(sisusb);
3182 #endif
3184 usb_deregister_dev(intf, &usb_sisusb_class);
3186 mutex_lock(&sisusb->lock);
3188 /* Wait for all URBs to complete and kill them in case (MUST do) */
3189 if (!sisusb_wait_all_out_complete(sisusb))
3190 sisusb_kill_all_busy(sisusb);
3192 usb_set_intfdata(intf, NULL);
3194 sisusb->present = 0;
3195 sisusb->ready = 0;
3197 mutex_unlock(&sisusb->lock);
3199 /* decrement our usage count */
3200 kref_put(&sisusb->kref, sisusb_delete);
3203 static const struct usb_device_id sisusb_table[] = {
3204 { USB_DEVICE(0x0711, 0x0550) },
3205 { USB_DEVICE(0x0711, 0x0900) },
3206 { USB_DEVICE(0x0711, 0x0901) },
3207 { USB_DEVICE(0x0711, 0x0902) },
3208 { USB_DEVICE(0x0711, 0x0903) },
3209 { USB_DEVICE(0x0711, 0x0918) },
3210 { USB_DEVICE(0x0711, 0x0920) },
3211 { USB_DEVICE(0x0711, 0x0950) },
3212 { USB_DEVICE(0x0711, 0x5200) },
3213 { USB_DEVICE(0x182d, 0x021c) },
3214 { USB_DEVICE(0x182d, 0x0269) },
3218 MODULE_DEVICE_TABLE(usb, sisusb_table);
3220 static struct usb_driver sisusb_driver = {
3221 .name = "sisusb",
3222 .probe = sisusb_probe,
3223 .disconnect = sisusb_disconnect,
3224 .id_table = sisusb_table,
3227 static int __init usb_sisusb_init(void)
3230 #ifdef INCL_SISUSB_CON
3231 sisusb_init_concode();
3232 #endif
3234 return usb_register(&sisusb_driver);
3237 static void __exit usb_sisusb_exit(void)
3239 usb_deregister(&sisusb_driver);
3242 module_init(usb_sisusb_init);
3243 module_exit(usb_sisusb_exit);
3245 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3246 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3247 MODULE_LICENSE("GPL");