PCI: hotplug: Embed hotplug_slot
[linux/fpc-iii.git] / drivers / usb / misc / sisusbvga / sisusb.c
blob3198d0477cf85db84cd697f22dc6652bbcdf6e3c
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /*
3 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
5 * Main part
7 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
9 * If distributed as part of the Linux kernel, this code is licensed under the
10 * terms of the GPL v2.
12 * Otherwise, the following license terms apply:
14 * * Redistribution and use in source and binary forms, with or without
15 * * modification, are permitted provided that the following conditions
16 * * are met:
17 * * 1) Redistributions of source code must retain the above copyright
18 * * notice, this list of conditions and the following disclaimer.
19 * * 2) Redistributions in binary form must reproduce the above copyright
20 * * notice, this list of conditions and the following disclaimer in the
21 * * documentation and/or other materials provided with the distribution.
22 * * 3) The name of the author may not be used to endorse or promote products
23 * * derived from this software without specific psisusbr written permission.
24 * *
25 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
26 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Author: Thomas Winischhofer <thomas@winischhofer.net>
40 #include <linux/mutex.h>
41 #include <linux/module.h>
42 #include <linux/kernel.h>
43 #include <linux/signal.h>
44 #include <linux/errno.h>
45 #include <linux/poll.h>
46 #include <linux/init.h>
47 #include <linux/slab.h>
48 #include <linux/spinlock.h>
49 #include <linux/kref.h>
50 #include <linux/usb.h>
51 #include <linux/vmalloc.h>
53 #include "sisusb.h"
54 #include "sisusb_init.h"
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
58 #endif
60 #define SISUSB_DONTSYNC
62 /* Forward declarations / clean-up routines */
64 #ifdef INCL_SISUSB_CON
65 static int sisusb_first_vc;
66 static int sisusb_last_vc;
67 module_param_named(first, sisusb_first_vc, int, 0);
68 module_param_named(last, sisusb_last_vc, int, 0);
69 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
70 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
71 #endif
73 static struct usb_driver sisusb_driver;
75 static void sisusb_free_buffers(struct sisusb_usb_data *sisusb)
77 int i;
79 for (i = 0; i < NUMOBUFS; i++) {
80 kfree(sisusb->obuf[i]);
81 sisusb->obuf[i] = NULL;
83 kfree(sisusb->ibuf);
84 sisusb->ibuf = NULL;
87 static void sisusb_free_urbs(struct sisusb_usb_data *sisusb)
89 int i;
91 for (i = 0; i < NUMOBUFS; i++) {
92 usb_free_urb(sisusb->sisurbout[i]);
93 sisusb->sisurbout[i] = NULL;
95 usb_free_urb(sisusb->sisurbin);
96 sisusb->sisurbin = NULL;
99 /* Level 0: USB transport layer */
101 /* 1. out-bulks */
103 /* out-urb management */
105 /* Return 1 if all free, 0 otherwise */
106 static int sisusb_all_free(struct sisusb_usb_data *sisusb)
108 int i;
110 for (i = 0; i < sisusb->numobufs; i++) {
112 if (sisusb->urbstatus[i] & SU_URB_BUSY)
113 return 0;
117 return 1;
120 /* Kill all busy URBs */
121 static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
123 int i;
125 if (sisusb_all_free(sisusb))
126 return;
128 for (i = 0; i < sisusb->numobufs; i++) {
130 if (sisusb->urbstatus[i] & SU_URB_BUSY)
131 usb_kill_urb(sisusb->sisurbout[i]);
136 /* Return 1 if ok, 0 if error (not all complete within timeout) */
137 static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
139 int timeout = 5 * HZ, i = 1;
141 wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)),
142 timeout);
144 return i;
147 static int sisusb_outurb_available(struct sisusb_usb_data *sisusb)
149 int i;
151 for (i = 0; i < sisusb->numobufs; i++) {
153 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
154 return i;
158 return -1;
161 static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
163 int i, timeout = 5 * HZ;
165 wait_event_timeout(sisusb->wait_q,
166 ((i = sisusb_outurb_available(sisusb)) >= 0), timeout);
168 return i;
171 static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
173 int i;
175 i = sisusb_outurb_available(sisusb);
177 if (i >= 0)
178 sisusb->urbstatus[i] |= SU_URB_ALLOC;
180 return i;
183 static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
185 if ((index >= 0) && (index < sisusb->numobufs))
186 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
189 /* completion callback */
191 static void sisusb_bulk_completeout(struct urb *urb)
193 struct sisusb_urb_context *context = urb->context;
194 struct sisusb_usb_data *sisusb;
196 if (!context)
197 return;
199 sisusb = context->sisusb;
201 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
202 return;
204 #ifndef SISUSB_DONTSYNC
205 if (context->actual_length)
206 *(context->actual_length) += urb->actual_length;
207 #endif
209 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
210 wake_up(&sisusb->wait_q);
213 static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index,
214 unsigned int pipe, void *data, int len, int *actual_length,
215 int timeout, unsigned int tflags)
217 struct urb *urb = sisusb->sisurbout[index];
218 int retval, byteswritten = 0;
220 /* Set up URB */
221 urb->transfer_flags = 0;
223 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
224 sisusb_bulk_completeout,
225 &sisusb->urbout_context[index]);
227 urb->transfer_flags |= tflags;
228 urb->actual_length = 0;
230 /* Set up context */
231 sisusb->urbout_context[index].actual_length = (timeout) ?
232 NULL : actual_length;
234 /* Declare this urb/buffer in use */
235 sisusb->urbstatus[index] |= SU_URB_BUSY;
237 /* Submit URB */
238 retval = usb_submit_urb(urb, GFP_KERNEL);
240 /* If OK, and if timeout > 0, wait for completion */
241 if ((retval == 0) && timeout) {
242 wait_event_timeout(sisusb->wait_q,
243 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
244 timeout);
245 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
246 /* URB timed out... kill it and report error */
247 usb_kill_urb(urb);
248 retval = -ETIMEDOUT;
249 } else {
250 /* Otherwise, report urb status */
251 retval = urb->status;
252 byteswritten = urb->actual_length;
256 if (actual_length)
257 *actual_length = byteswritten;
259 return retval;
262 /* 2. in-bulks */
264 /* completion callback */
266 static void sisusb_bulk_completein(struct urb *urb)
268 struct sisusb_usb_data *sisusb = urb->context;
270 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
271 return;
273 sisusb->completein = 1;
274 wake_up(&sisusb->wait_q);
277 static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb,
278 unsigned int pipe, void *data, int len,
279 int *actual_length, int timeout, unsigned int tflags)
281 struct urb *urb = sisusb->sisurbin;
282 int retval, readbytes = 0;
284 urb->transfer_flags = 0;
286 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
287 sisusb_bulk_completein, sisusb);
289 urb->transfer_flags |= tflags;
290 urb->actual_length = 0;
292 sisusb->completein = 0;
293 retval = usb_submit_urb(urb, GFP_KERNEL);
294 if (retval == 0) {
295 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
296 if (!sisusb->completein) {
297 /* URB timed out... kill it and report error */
298 usb_kill_urb(urb);
299 retval = -ETIMEDOUT;
300 } else {
301 /* URB completed within timeout */
302 retval = urb->status;
303 readbytes = urb->actual_length;
307 if (actual_length)
308 *actual_length = readbytes;
310 return retval;
314 /* Level 1: */
316 /* Send a bulk message of variable size
318 * To copy the data from userspace, give pointer to "userbuffer",
319 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
320 * both of these are NULL, it is assumed, that the transfer
321 * buffer "sisusb->obuf[index]" is set up with the data to send.
322 * Index is ignored if either kernbuffer or userbuffer is set.
323 * If async is nonzero, URBs will be sent without waiting for
324 * completion of the previous URB.
326 * (return 0 on success)
329 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
330 char *kernbuffer, const char __user *userbuffer, int index,
331 ssize_t *bytes_written, unsigned int tflags, int async)
333 int result = 0, retry, count = len;
334 int passsize, thispass, transferred_len = 0;
335 int fromuser = (userbuffer != NULL) ? 1 : 0;
336 int fromkern = (kernbuffer != NULL) ? 1 : 0;
337 unsigned int pipe;
338 char *buffer;
340 (*bytes_written) = 0;
342 /* Sanity check */
343 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
344 return -ENODEV;
346 /* If we copy data from kernel or userspace, force the
347 * allocation of a buffer/urb. If we have the data in
348 * the transfer buffer[index] already, reuse the buffer/URB
349 * if the length is > buffer size. (So, transmitting
350 * large data amounts directly from the transfer buffer
351 * treats the buffer as a ring buffer. However, we need
352 * to sync in this case.)
354 if (fromuser || fromkern)
355 index = -1;
356 else if (len > sisusb->obufsize)
357 async = 0;
359 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
361 do {
362 passsize = thispass = (sisusb->obufsize < count) ?
363 sisusb->obufsize : count;
365 if (index < 0)
366 index = sisusb_get_free_outbuf(sisusb);
368 if (index < 0)
369 return -EIO;
371 buffer = sisusb->obuf[index];
373 if (fromuser) {
375 if (copy_from_user(buffer, userbuffer, passsize))
376 return -EFAULT;
378 userbuffer += passsize;
380 } else if (fromkern) {
382 memcpy(buffer, kernbuffer, passsize);
383 kernbuffer += passsize;
387 retry = 5;
388 while (thispass) {
390 if (!sisusb->sisusb_dev)
391 return -ENODEV;
393 result = sisusb_bulkout_msg(sisusb, index, pipe,
394 buffer, thispass, &transferred_len,
395 async ? 0 : 5 * HZ, tflags);
397 if (result == -ETIMEDOUT) {
399 /* Will not happen if async */
400 if (!retry--)
401 return -ETIME;
403 continue;
406 if ((result == 0) && !async && transferred_len) {
408 thispass -= transferred_len;
409 buffer += transferred_len;
411 } else
412 break;
415 if (result)
416 return result;
418 (*bytes_written) += passsize;
419 count -= passsize;
421 /* Force new allocation in next iteration */
422 if (fromuser || fromkern)
423 index = -1;
425 } while (count > 0);
427 if (async) {
428 #ifdef SISUSB_DONTSYNC
429 (*bytes_written) = len;
430 /* Some URBs/buffers might be busy */
431 #else
432 sisusb_wait_all_out_complete(sisusb);
433 (*bytes_written) = transferred_len;
434 /* All URBs and all buffers are available */
435 #endif
438 return ((*bytes_written) == len) ? 0 : -EIO;
441 /* Receive a bulk message of variable size
443 * To copy the data to userspace, give pointer to "userbuffer",
444 * to copy to kernel memory, give "kernbuffer". One of them
445 * MUST be set. (There is no technique for letting the caller
446 * read directly from the ibuf.)
450 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
451 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
452 unsigned int tflags)
454 int result = 0, retry, count = len;
455 int bufsize, thispass, transferred_len;
456 unsigned int pipe;
457 char *buffer;
459 (*bytes_read) = 0;
461 /* Sanity check */
462 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
463 return -ENODEV;
465 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
466 buffer = sisusb->ibuf;
467 bufsize = sisusb->ibufsize;
469 retry = 5;
471 #ifdef SISUSB_DONTSYNC
472 if (!(sisusb_wait_all_out_complete(sisusb)))
473 return -EIO;
474 #endif
476 while (count > 0) {
478 if (!sisusb->sisusb_dev)
479 return -ENODEV;
481 thispass = (bufsize < count) ? bufsize : count;
483 result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass,
484 &transferred_len, 5 * HZ, tflags);
486 if (transferred_len)
487 thispass = transferred_len;
489 else if (result == -ETIMEDOUT) {
491 if (!retry--)
492 return -ETIME;
494 continue;
496 } else
497 return -EIO;
500 if (thispass) {
502 (*bytes_read) += thispass;
503 count -= thispass;
505 if (userbuffer) {
507 if (copy_to_user(userbuffer, buffer, thispass))
508 return -EFAULT;
510 userbuffer += thispass;
512 } else {
514 memcpy(kernbuffer, buffer, thispass);
515 kernbuffer += thispass;
523 return ((*bytes_read) == len) ? 0 : -EIO;
526 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
527 struct sisusb_packet *packet)
529 int ret;
530 ssize_t bytes_transferred = 0;
531 __le32 tmp;
533 if (len == 6)
534 packet->data = 0;
536 #ifdef SISUSB_DONTSYNC
537 if (!(sisusb_wait_all_out_complete(sisusb)))
538 return 1;
539 #endif
541 /* Eventually correct endianness */
542 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
544 /* 1. send the packet */
545 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
546 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
548 if ((ret == 0) && (len == 6)) {
550 /* 2. if packet len == 6, it means we read, so wait for 32bit
551 * return value and write it to packet->data
553 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
554 (char *)&tmp, NULL, &bytes_transferred, 0);
556 packet->data = le32_to_cpu(tmp);
559 return ret;
562 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
563 struct sisusb_packet *packet, unsigned int tflags)
565 int ret;
566 ssize_t bytes_transferred = 0;
567 __le32 tmp;
569 if (len == 6)
570 packet->data = 0;
572 #ifdef SISUSB_DONTSYNC
573 if (!(sisusb_wait_all_out_complete(sisusb)))
574 return 1;
575 #endif
577 /* Eventually correct endianness */
578 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
580 /* 1. send the packet */
581 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
582 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
584 if ((ret == 0) && (len == 6)) {
586 /* 2. if packet len == 6, it means we read, so wait for 32bit
587 * return value and write it to packet->data
589 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
590 (char *)&tmp, NULL, &bytes_transferred, 0);
592 packet->data = le32_to_cpu(tmp);
595 return ret;
598 /* access video memory and mmio (return 0 on success) */
600 /* Low level */
602 /* The following routines assume being used to transfer byte, word,
603 * long etc.
604 * This means that
605 * - the write routines expect "data" in machine endianness format.
606 * The data will be converted to leXX in sisusb_xxx_packet.
607 * - the read routines can expect read data in machine-endianess.
610 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
611 u32 addr, u8 data)
613 struct sisusb_packet packet;
615 packet.header = (1 << (addr & 3)) | (type << 6);
616 packet.address = addr & ~3;
617 packet.data = data << ((addr & 3) << 3);
618 return sisusb_send_packet(sisusb, 10, &packet);
621 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
622 u32 addr, u16 data)
624 struct sisusb_packet packet;
625 int ret = 0;
627 packet.address = addr & ~3;
629 switch (addr & 3) {
630 case 0:
631 packet.header = (type << 6) | 0x0003;
632 packet.data = (u32)data;
633 ret = sisusb_send_packet(sisusb, 10, &packet);
634 break;
635 case 1:
636 packet.header = (type << 6) | 0x0006;
637 packet.data = (u32)data << 8;
638 ret = sisusb_send_packet(sisusb, 10, &packet);
639 break;
640 case 2:
641 packet.header = (type << 6) | 0x000c;
642 packet.data = (u32)data << 16;
643 ret = sisusb_send_packet(sisusb, 10, &packet);
644 break;
645 case 3:
646 packet.header = (type << 6) | 0x0008;
647 packet.data = (u32)data << 24;
648 ret = sisusb_send_packet(sisusb, 10, &packet);
649 packet.header = (type << 6) | 0x0001;
650 packet.address = (addr & ~3) + 4;
651 packet.data = (u32)data >> 8;
652 ret |= sisusb_send_packet(sisusb, 10, &packet);
655 return ret;
658 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
659 u32 addr, u32 data)
661 struct sisusb_packet packet;
662 int ret = 0;
664 packet.address = addr & ~3;
666 switch (addr & 3) {
667 case 0:
668 packet.header = (type << 6) | 0x0007;
669 packet.data = data & 0x00ffffff;
670 ret = sisusb_send_packet(sisusb, 10, &packet);
671 break;
672 case 1:
673 packet.header = (type << 6) | 0x000e;
674 packet.data = data << 8;
675 ret = sisusb_send_packet(sisusb, 10, &packet);
676 break;
677 case 2:
678 packet.header = (type << 6) | 0x000c;
679 packet.data = data << 16;
680 ret = sisusb_send_packet(sisusb, 10, &packet);
681 packet.header = (type << 6) | 0x0001;
682 packet.address = (addr & ~3) + 4;
683 packet.data = (data >> 16) & 0x00ff;
684 ret |= sisusb_send_packet(sisusb, 10, &packet);
685 break;
686 case 3:
687 packet.header = (type << 6) | 0x0008;
688 packet.data = data << 24;
689 ret = sisusb_send_packet(sisusb, 10, &packet);
690 packet.header = (type << 6) | 0x0003;
691 packet.address = (addr & ~3) + 4;
692 packet.data = (data >> 8) & 0xffff;
693 ret |= sisusb_send_packet(sisusb, 10, &packet);
696 return ret;
699 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
700 u32 addr, u32 data)
702 struct sisusb_packet packet;
703 int ret = 0;
705 packet.address = addr & ~3;
707 switch (addr & 3) {
708 case 0:
709 packet.header = (type << 6) | 0x000f;
710 packet.data = data;
711 ret = sisusb_send_packet(sisusb, 10, &packet);
712 break;
713 case 1:
714 packet.header = (type << 6) | 0x000e;
715 packet.data = data << 8;
716 ret = sisusb_send_packet(sisusb, 10, &packet);
717 packet.header = (type << 6) | 0x0001;
718 packet.address = (addr & ~3) + 4;
719 packet.data = data >> 24;
720 ret |= sisusb_send_packet(sisusb, 10, &packet);
721 break;
722 case 2:
723 packet.header = (type << 6) | 0x000c;
724 packet.data = data << 16;
725 ret = sisusb_send_packet(sisusb, 10, &packet);
726 packet.header = (type << 6) | 0x0003;
727 packet.address = (addr & ~3) + 4;
728 packet.data = data >> 16;
729 ret |= sisusb_send_packet(sisusb, 10, &packet);
730 break;
731 case 3:
732 packet.header = (type << 6) | 0x0008;
733 packet.data = data << 24;
734 ret = sisusb_send_packet(sisusb, 10, &packet);
735 packet.header = (type << 6) | 0x0007;
736 packet.address = (addr & ~3) + 4;
737 packet.data = data >> 8;
738 ret |= sisusb_send_packet(sisusb, 10, &packet);
741 return ret;
744 /* The xxx_bulk routines copy a buffer of variable size. They treat the
745 * buffer as chars, therefore lsb/msb has to be corrected if using the
746 * byte/word/long/etc routines for speed-up
748 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
749 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
750 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
751 * that the data already is in the transfer buffer "sisusb->obuf[index]".
754 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
755 char *kernbuffer, int length, const char __user *userbuffer,
756 int index, ssize_t *bytes_written)
758 struct sisusb_packet packet;
759 int ret = 0;
760 static int msgcount;
761 u8 swap8, fromkern = kernbuffer ? 1 : 0;
762 u16 swap16;
763 u32 swap32, flag = (length >> 28) & 1;
764 char buf[4];
766 /* if neither kernbuffer not userbuffer are given, assume
767 * data in obuf
769 if (!fromkern && !userbuffer)
770 kernbuffer = sisusb->obuf[index];
772 (*bytes_written = 0);
774 length &= 0x00ffffff;
776 while (length) {
777 switch (length) {
778 case 1:
779 if (userbuffer) {
780 if (get_user(swap8, (u8 __user *)userbuffer))
781 return -EFAULT;
782 } else
783 swap8 = kernbuffer[0];
785 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
786 addr, swap8);
788 if (!ret)
789 (*bytes_written)++;
791 return ret;
793 case 2:
794 if (userbuffer) {
795 if (get_user(swap16, (u16 __user *)userbuffer))
796 return -EFAULT;
797 } else
798 swap16 = *((u16 *)kernbuffer);
800 ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
801 addr, swap16);
803 if (!ret)
804 (*bytes_written) += 2;
806 return ret;
808 case 3:
809 if (userbuffer) {
810 if (copy_from_user(&buf, userbuffer, 3))
811 return -EFAULT;
812 #ifdef __BIG_ENDIAN
813 swap32 = (buf[0] << 16) |
814 (buf[1] << 8) |
815 buf[2];
816 #else
817 swap32 = (buf[2] << 16) |
818 (buf[1] << 8) |
819 buf[0];
820 #endif
821 } else
822 #ifdef __BIG_ENDIAN
823 swap32 = (kernbuffer[0] << 16) |
824 (kernbuffer[1] << 8) |
825 kernbuffer[2];
826 #else
827 swap32 = (kernbuffer[2] << 16) |
828 (kernbuffer[1] << 8) |
829 kernbuffer[0];
830 #endif
832 ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
833 addr, swap32);
835 if (!ret)
836 (*bytes_written) += 3;
838 return ret;
840 case 4:
841 if (userbuffer) {
842 if (get_user(swap32, (u32 __user *)userbuffer))
843 return -EFAULT;
844 } else
845 swap32 = *((u32 *)kernbuffer);
847 ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
848 addr, swap32);
849 if (!ret)
850 (*bytes_written) += 4;
852 return ret;
854 default:
855 if ((length & ~3) > 0x10000) {
857 packet.header = 0x001f;
858 packet.address = 0x000001d4;
859 packet.data = addr;
860 ret = sisusb_send_bridge_packet(sisusb, 10,
861 &packet, 0);
862 packet.header = 0x001f;
863 packet.address = 0x000001d0;
864 packet.data = (length & ~3);
865 ret |= sisusb_send_bridge_packet(sisusb, 10,
866 &packet, 0);
867 packet.header = 0x001f;
868 packet.address = 0x000001c0;
869 packet.data = flag | 0x16;
870 ret |= sisusb_send_bridge_packet(sisusb, 10,
871 &packet, 0);
872 if (userbuffer) {
873 ret |= sisusb_send_bulk_msg(sisusb,
874 SISUSB_EP_GFX_LBULK_OUT,
875 (length & ~3),
876 NULL, userbuffer, 0,
877 bytes_written, 0, 1);
878 userbuffer += (*bytes_written);
879 } else if (fromkern) {
880 ret |= sisusb_send_bulk_msg(sisusb,
881 SISUSB_EP_GFX_LBULK_OUT,
882 (length & ~3),
883 kernbuffer, NULL, 0,
884 bytes_written, 0, 1);
885 kernbuffer += (*bytes_written);
886 } else {
887 ret |= sisusb_send_bulk_msg(sisusb,
888 SISUSB_EP_GFX_LBULK_OUT,
889 (length & ~3),
890 NULL, NULL, index,
891 bytes_written, 0, 1);
892 kernbuffer += ((*bytes_written) &
893 (sisusb->obufsize-1));
896 } else {
898 packet.header = 0x001f;
899 packet.address = 0x00000194;
900 packet.data = addr;
901 ret = sisusb_send_bridge_packet(sisusb, 10,
902 &packet, 0);
903 packet.header = 0x001f;
904 packet.address = 0x00000190;
905 packet.data = (length & ~3);
906 ret |= sisusb_send_bridge_packet(sisusb, 10,
907 &packet, 0);
908 if (sisusb->flagb0 != 0x16) {
909 packet.header = 0x001f;
910 packet.address = 0x00000180;
911 packet.data = flag | 0x16;
912 ret |= sisusb_send_bridge_packet(sisusb,
913 10, &packet, 0);
914 sisusb->flagb0 = 0x16;
916 if (userbuffer) {
917 ret |= sisusb_send_bulk_msg(sisusb,
918 SISUSB_EP_GFX_BULK_OUT,
919 (length & ~3),
920 NULL, userbuffer, 0,
921 bytes_written, 0, 1);
922 userbuffer += (*bytes_written);
923 } else if (fromkern) {
924 ret |= sisusb_send_bulk_msg(sisusb,
925 SISUSB_EP_GFX_BULK_OUT,
926 (length & ~3),
927 kernbuffer, NULL, 0,
928 bytes_written, 0, 1);
929 kernbuffer += (*bytes_written);
930 } else {
931 ret |= sisusb_send_bulk_msg(sisusb,
932 SISUSB_EP_GFX_BULK_OUT,
933 (length & ~3),
934 NULL, NULL, index,
935 bytes_written, 0, 1);
936 kernbuffer += ((*bytes_written) &
937 (sisusb->obufsize-1));
940 if (ret) {
941 msgcount++;
942 if (msgcount < 500)
943 dev_err(&sisusb->sisusb_dev->dev,
944 "Wrote %zd of %d bytes, error %d\n",
945 *bytes_written, length,
946 ret);
947 else if (msgcount == 500)
948 dev_err(&sisusb->sisusb_dev->dev,
949 "Too many errors, logging stopped\n");
951 addr += (*bytes_written);
952 length -= (*bytes_written);
955 if (ret)
956 break;
960 return ret ? -EIO : 0;
963 /* Remember: Read data in packet is in machine-endianess! So for
964 * byte, word, 24bit, long no endian correction is necessary.
967 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
968 u32 addr, u8 *data)
970 struct sisusb_packet packet;
971 int ret;
973 CLEARPACKET(&packet);
974 packet.header = (1 << (addr & 3)) | (type << 6);
975 packet.address = addr & ~3;
976 ret = sisusb_send_packet(sisusb, 6, &packet);
977 *data = (u8)(packet.data >> ((addr & 3) << 3));
978 return ret;
981 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
982 u32 addr, u16 *data)
984 struct sisusb_packet packet;
985 int ret = 0;
987 CLEARPACKET(&packet);
989 packet.address = addr & ~3;
991 switch (addr & 3) {
992 case 0:
993 packet.header = (type << 6) | 0x0003;
994 ret = sisusb_send_packet(sisusb, 6, &packet);
995 *data = (u16)(packet.data);
996 break;
997 case 1:
998 packet.header = (type << 6) | 0x0006;
999 ret = sisusb_send_packet(sisusb, 6, &packet);
1000 *data = (u16)(packet.data >> 8);
1001 break;
1002 case 2:
1003 packet.header = (type << 6) | 0x000c;
1004 ret = sisusb_send_packet(sisusb, 6, &packet);
1005 *data = (u16)(packet.data >> 16);
1006 break;
1007 case 3:
1008 packet.header = (type << 6) | 0x0008;
1009 ret = sisusb_send_packet(sisusb, 6, &packet);
1010 *data = (u16)(packet.data >> 24);
1011 packet.header = (type << 6) | 0x0001;
1012 packet.address = (addr & ~3) + 4;
1013 ret |= sisusb_send_packet(sisusb, 6, &packet);
1014 *data |= (u16)(packet.data << 8);
1017 return ret;
1020 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1021 u32 addr, u32 *data)
1023 struct sisusb_packet packet;
1024 int ret = 0;
1026 packet.address = addr & ~3;
1028 switch (addr & 3) {
1029 case 0:
1030 packet.header = (type << 6) | 0x0007;
1031 ret = sisusb_send_packet(sisusb, 6, &packet);
1032 *data = packet.data & 0x00ffffff;
1033 break;
1034 case 1:
1035 packet.header = (type << 6) | 0x000e;
1036 ret = sisusb_send_packet(sisusb, 6, &packet);
1037 *data = packet.data >> 8;
1038 break;
1039 case 2:
1040 packet.header = (type << 6) | 0x000c;
1041 ret = sisusb_send_packet(sisusb, 6, &packet);
1042 *data = packet.data >> 16;
1043 packet.header = (type << 6) | 0x0001;
1044 packet.address = (addr & ~3) + 4;
1045 ret |= sisusb_send_packet(sisusb, 6, &packet);
1046 *data |= ((packet.data & 0xff) << 16);
1047 break;
1048 case 3:
1049 packet.header = (type << 6) | 0x0008;
1050 ret = sisusb_send_packet(sisusb, 6, &packet);
1051 *data = packet.data >> 24;
1052 packet.header = (type << 6) | 0x0003;
1053 packet.address = (addr & ~3) + 4;
1054 ret |= sisusb_send_packet(sisusb, 6, &packet);
1055 *data |= ((packet.data & 0xffff) << 8);
1058 return ret;
1061 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1062 u32 addr, u32 *data)
1064 struct sisusb_packet packet;
1065 int ret = 0;
1067 packet.address = addr & ~3;
1069 switch (addr & 3) {
1070 case 0:
1071 packet.header = (type << 6) | 0x000f;
1072 ret = sisusb_send_packet(sisusb, 6, &packet);
1073 *data = packet.data;
1074 break;
1075 case 1:
1076 packet.header = (type << 6) | 0x000e;
1077 ret = sisusb_send_packet(sisusb, 6, &packet);
1078 *data = packet.data >> 8;
1079 packet.header = (type << 6) | 0x0001;
1080 packet.address = (addr & ~3) + 4;
1081 ret |= sisusb_send_packet(sisusb, 6, &packet);
1082 *data |= (packet.data << 24);
1083 break;
1084 case 2:
1085 packet.header = (type << 6) | 0x000c;
1086 ret = sisusb_send_packet(sisusb, 6, &packet);
1087 *data = packet.data >> 16;
1088 packet.header = (type << 6) | 0x0003;
1089 packet.address = (addr & ~3) + 4;
1090 ret |= sisusb_send_packet(sisusb, 6, &packet);
1091 *data |= (packet.data << 16);
1092 break;
1093 case 3:
1094 packet.header = (type << 6) | 0x0008;
1095 ret = sisusb_send_packet(sisusb, 6, &packet);
1096 *data = packet.data >> 24;
1097 packet.header = (type << 6) | 0x0007;
1098 packet.address = (addr & ~3) + 4;
1099 ret |= sisusb_send_packet(sisusb, 6, &packet);
1100 *data |= (packet.data << 8);
1103 return ret;
1106 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1107 char *kernbuffer, int length, char __user *userbuffer,
1108 ssize_t *bytes_read)
1110 int ret = 0;
1111 char buf[4];
1112 u16 swap16;
1113 u32 swap32;
1115 (*bytes_read = 0);
1117 length &= 0x00ffffff;
1119 while (length) {
1120 switch (length) {
1121 case 1:
1122 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1123 addr, &buf[0]);
1124 if (!ret) {
1125 (*bytes_read)++;
1126 if (userbuffer) {
1127 if (put_user(buf[0], (u8 __user *)userbuffer))
1128 return -EFAULT;
1129 } else
1130 kernbuffer[0] = buf[0];
1132 return ret;
1134 case 2:
1135 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1136 addr, &swap16);
1137 if (!ret) {
1138 (*bytes_read) += 2;
1139 if (userbuffer) {
1140 if (put_user(swap16, (u16 __user *)userbuffer))
1141 return -EFAULT;
1142 } else {
1143 *((u16 *)kernbuffer) = swap16;
1146 return ret;
1148 case 3:
1149 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1150 addr, &swap32);
1151 if (!ret) {
1152 (*bytes_read) += 3;
1153 #ifdef __BIG_ENDIAN
1154 buf[0] = (swap32 >> 16) & 0xff;
1155 buf[1] = (swap32 >> 8) & 0xff;
1156 buf[2] = swap32 & 0xff;
1157 #else
1158 buf[2] = (swap32 >> 16) & 0xff;
1159 buf[1] = (swap32 >> 8) & 0xff;
1160 buf[0] = swap32 & 0xff;
1161 #endif
1162 if (userbuffer) {
1163 if (copy_to_user(userbuffer,
1164 &buf[0], 3))
1165 return -EFAULT;
1166 } else {
1167 kernbuffer[0] = buf[0];
1168 kernbuffer[1] = buf[1];
1169 kernbuffer[2] = buf[2];
1172 return ret;
1174 default:
1175 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1176 addr, &swap32);
1177 if (!ret) {
1178 (*bytes_read) += 4;
1179 if (userbuffer) {
1180 if (put_user(swap32, (u32 __user *)userbuffer))
1181 return -EFAULT;
1183 userbuffer += 4;
1184 } else {
1185 *((u32 *)kernbuffer) = swap32;
1186 kernbuffer += 4;
1188 addr += 4;
1189 length -= 4;
1192 if (ret)
1193 break;
1196 return ret;
1199 /* High level: Gfx (indexed) register access */
1201 #ifdef INCL_SISUSB_CON
1202 int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1204 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1207 int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1209 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1211 #endif
1213 int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
1214 u8 index, u8 data)
1216 int ret;
1218 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1219 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1220 return ret;
1223 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
1224 u8 index, u8 *data)
1226 int ret;
1228 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1229 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1230 return ret;
1233 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1234 u8 myand, u8 myor)
1236 int ret;
1237 u8 tmp;
1239 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1240 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1241 tmp &= myand;
1242 tmp |= myor;
1243 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1244 return ret;
1247 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1248 int port, u8 idx, u8 data, u8 mask)
1250 int ret;
1251 u8 tmp;
1253 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1254 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1255 tmp &= ~(mask);
1256 tmp |= (data & mask);
1257 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1258 return ret;
1261 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
1262 u8 index, u8 myor)
1264 return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1267 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
1268 u8 idx, u8 myand)
1270 return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1273 /* Write/read video ram */
1275 #ifdef INCL_SISUSB_CON
1276 int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1278 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1281 int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1283 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1286 int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1287 u32 dest, int length)
1289 size_t dummy;
1291 return sisusb_write_mem_bulk(sisusb, dest, src, length,
1292 NULL, 0, &dummy);
1295 #ifdef SISUSBENDIANTEST
1296 static int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1297 u32 src, int length)
1299 size_t dummy;
1301 return sisusb_read_mem_bulk(sisusb, src, dest, length,
1302 NULL, &dummy);
1304 #endif
1305 #endif
1307 #ifdef SISUSBENDIANTEST
1308 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1310 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1311 char destbuffer[10];
1312 int i, j;
1314 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
1316 for (i = 1; i <= 7; i++) {
1317 dev_dbg(&sisusb->sisusb_dev->dev,
1318 "sisusb: rwtest %d bytes\n", i);
1319 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
1320 for (j = 0; j < i; j++) {
1321 dev_dbg(&sisusb->sisusb_dev->dev,
1322 "rwtest read[%d] = %x\n",
1323 j, destbuffer[j]);
1327 #endif
1329 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1331 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1332 int regnum, u32 data)
1334 struct sisusb_packet packet;
1336 packet.header = 0x008f;
1337 packet.address = regnum | 0x10000;
1338 packet.data = data;
1339 return sisusb_send_packet(sisusb, 10, &packet);
1342 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1343 int regnum, u32 *data)
1345 struct sisusb_packet packet;
1346 int ret;
1348 packet.header = 0x008f;
1349 packet.address = (u32)regnum | 0x10000;
1350 ret = sisusb_send_packet(sisusb, 6, &packet);
1351 *data = packet.data;
1352 return ret;
1355 /* Clear video RAM */
1357 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1358 u32 address, int length)
1360 int ret, i;
1361 ssize_t j;
1363 if (address < sisusb->vrambase)
1364 return 1;
1366 if (address >= sisusb->vrambase + sisusb->vramsize)
1367 return 1;
1369 if (address + length > sisusb->vrambase + sisusb->vramsize)
1370 length = sisusb->vrambase + sisusb->vramsize - address;
1372 if (length <= 0)
1373 return 0;
1375 /* allocate free buffer/urb and clear the buffer */
1376 i = sisusb_alloc_outbuf(sisusb);
1377 if (i < 0)
1378 return -EBUSY;
1380 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1382 /* We can write a length > buffer size here. The buffer
1383 * data will simply be re-used (like a ring-buffer).
1385 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1387 /* Free the buffer/urb */
1388 sisusb_free_outbuf(sisusb, i);
1390 return ret;
1393 /* Initialize the graphics core (return 0 on success)
1394 * This resets the graphics hardware and puts it into
1395 * a defined mode (640x480@60Hz)
1398 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1399 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1400 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1401 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1402 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1403 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1404 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1405 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1406 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1408 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1410 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1412 int ret;
1413 u8 tmp8;
1415 ret = GETIREG(SISSR, 0x16, &tmp8);
1416 if (ramtype <= 1) {
1417 tmp8 &= 0x3f;
1418 ret |= SETIREG(SISSR, 0x16, tmp8);
1419 tmp8 |= 0x80;
1420 ret |= SETIREG(SISSR, 0x16, tmp8);
1421 } else {
1422 tmp8 |= 0xc0;
1423 ret |= SETIREG(SISSR, 0x16, tmp8);
1424 tmp8 &= 0x0f;
1425 ret |= SETIREG(SISSR, 0x16, tmp8);
1426 tmp8 |= 0x80;
1427 ret |= SETIREG(SISSR, 0x16, tmp8);
1428 tmp8 &= 0x0f;
1429 ret |= SETIREG(SISSR, 0x16, tmp8);
1430 tmp8 |= 0xd0;
1431 ret |= SETIREG(SISSR, 0x16, tmp8);
1432 tmp8 &= 0x0f;
1433 ret |= SETIREG(SISSR, 0x16, tmp8);
1434 tmp8 |= 0xa0;
1435 ret |= SETIREG(SISSR, 0x16, tmp8);
1437 return ret;
1440 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1441 int *bw, int *chab)
1443 int ret;
1444 u8 ramtype, done = 0;
1445 u32 t0, t1, t2, t3;
1446 u32 ramptr = SISUSB_PCI_MEMBASE;
1448 ret = GETIREG(SISSR, 0x3a, &ramtype);
1449 ramtype &= 3;
1451 ret |= SETIREG(SISSR, 0x13, 0x00);
1453 if (ramtype <= 1) {
1454 ret |= SETIREG(SISSR, 0x14, 0x12);
1455 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1456 } else {
1457 ret |= SETIREG(SISSR, 0x14, 0x02);
1460 ret |= sisusb_triggersr16(sisusb, ramtype);
1461 ret |= WRITEL(ramptr + 0, 0x01234567);
1462 ret |= WRITEL(ramptr + 4, 0x456789ab);
1463 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1464 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1465 ret |= WRITEL(ramptr + 16, 0x55555555);
1466 ret |= WRITEL(ramptr + 20, 0x55555555);
1467 ret |= WRITEL(ramptr + 24, 0xffffffff);
1468 ret |= WRITEL(ramptr + 28, 0xffffffff);
1469 ret |= READL(ramptr + 0, &t0);
1470 ret |= READL(ramptr + 4, &t1);
1471 ret |= READL(ramptr + 8, &t2);
1472 ret |= READL(ramptr + 12, &t3);
1474 if (ramtype <= 1) {
1476 *chab = 0; *bw = 64;
1478 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1479 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1480 *chab = 0; *bw = 64;
1481 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1484 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1485 *chab = 1; *bw = 64;
1486 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1488 ret |= sisusb_triggersr16(sisusb, ramtype);
1489 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1490 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1491 ret |= WRITEL(ramptr + 8, 0x55555555);
1492 ret |= WRITEL(ramptr + 12, 0x55555555);
1493 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1494 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1495 ret |= READL(ramptr + 4, &t1);
1497 if (t1 != 0xcdef0123) {
1498 *bw = 32;
1499 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1503 } else {
1505 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1507 done = 0;
1509 if (t1 == 0x456789ab) {
1510 if (t0 == 0x01234567) {
1511 *chab = 0; *bw = 64;
1512 done = 1;
1514 } else {
1515 if (t0 == 0x01234567) {
1516 *chab = 0; *bw = 32;
1517 ret |= SETIREG(SISSR, 0x14, 0x00);
1518 done = 1;
1522 if (!done) {
1523 ret |= SETIREG(SISSR, 0x14, 0x03);
1524 ret |= sisusb_triggersr16(sisusb, ramtype);
1526 ret |= WRITEL(ramptr + 0, 0x01234567);
1527 ret |= WRITEL(ramptr + 4, 0x456789ab);
1528 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1529 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1530 ret |= WRITEL(ramptr + 16, 0x55555555);
1531 ret |= WRITEL(ramptr + 20, 0x55555555);
1532 ret |= WRITEL(ramptr + 24, 0xffffffff);
1533 ret |= WRITEL(ramptr + 28, 0xffffffff);
1534 ret |= READL(ramptr + 0, &t0);
1535 ret |= READL(ramptr + 4, &t1);
1537 if (t1 == 0x456789ab) {
1538 if (t0 == 0x01234567) {
1539 *chab = 1; *bw = 64;
1540 return ret;
1541 } /* else error */
1542 } else {
1543 if (t0 == 0x01234567) {
1544 *chab = 1; *bw = 32;
1545 ret |= SETIREG(SISSR, 0x14, 0x01);
1546 } /* else error */
1550 return ret;
1553 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1555 int ret = 0;
1556 u32 ramptr = SISUSB_PCI_MEMBASE;
1557 u8 tmp1, tmp2, i, j;
1559 ret |= WRITEB(ramptr, 0xaa);
1560 ret |= WRITEB(ramptr + 16, 0x55);
1561 ret |= READB(ramptr, &tmp1);
1562 ret |= READB(ramptr + 16, &tmp2);
1563 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1564 for (i = 0, j = 16; i < 2; i++, j += 16) {
1565 ret |= GETIREG(SISSR, 0x21, &tmp1);
1566 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1567 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1568 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1569 ret |= SETIREG(SISSR, 0x21, tmp1);
1570 ret |= WRITEB(ramptr + 16 + j, j);
1571 ret |= READB(ramptr + 16 + j, &tmp1);
1572 if (tmp1 == j) {
1573 ret |= WRITEB(ramptr + j, j);
1574 break;
1578 return ret;
1581 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1582 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1584 int ret = 0, ranksize;
1585 u8 tmp;
1587 *iret = 0;
1589 if ((rankno == 2) && (dramtype[index][0] == 2))
1590 return ret;
1592 ranksize = dramtype[index][3] / 2 * bw / 32;
1594 if ((ranksize * rankno) > 128)
1595 return ret;
1597 tmp = 0;
1598 while ((ranksize >>= 1) > 0)
1599 tmp += 0x10;
1601 tmp |= ((rankno - 1) << 2);
1602 tmp |= ((bw / 64) & 0x02);
1603 tmp |= (chab & 0x01);
1605 ret = SETIREG(SISSR, 0x14, tmp);
1606 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1608 *iret = 1;
1610 return ret;
1613 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1614 u32 inc, int testn)
1616 int ret = 0, i;
1617 u32 j, tmp;
1619 *iret = 0;
1621 for (i = 0, j = 0; i < testn; i++) {
1622 ret |= WRITEL(sisusb->vrambase + j, j);
1623 j += inc;
1626 for (i = 0, j = 0; i < testn; i++) {
1627 ret |= READL(sisusb->vrambase + j, &tmp);
1628 if (tmp != j)
1629 return ret;
1631 j += inc;
1634 *iret = 1;
1635 return ret;
1638 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1639 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1641 int ret = 0, i, i2ret;
1642 u32 inc;
1644 *iret = 0;
1646 for (i = rankno; i >= 1; i--) {
1647 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1648 bw / 64 + i);
1649 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1650 if (!i2ret)
1651 return ret;
1654 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1655 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1656 if (!i2ret)
1657 return ret;
1659 inc = 1 << (10 + bw / 64);
1660 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1661 if (!i2ret)
1662 return ret;
1664 *iret = 1;
1665 return ret;
1668 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1669 int bw, int chab)
1671 int ret = 0, i2ret = 0, i, j;
1672 static const u8 sdramtype[13][5] = {
1673 { 2, 12, 9, 64, 0x35 },
1674 { 1, 13, 9, 64, 0x44 },
1675 { 2, 12, 8, 32, 0x31 },
1676 { 2, 11, 9, 32, 0x25 },
1677 { 1, 12, 9, 32, 0x34 },
1678 { 1, 13, 8, 32, 0x40 },
1679 { 2, 11, 8, 16, 0x21 },
1680 { 1, 12, 8, 16, 0x30 },
1681 { 1, 11, 9, 16, 0x24 },
1682 { 1, 11, 8, 8, 0x20 },
1683 { 2, 9, 8, 4, 0x01 },
1684 { 1, 10, 8, 4, 0x10 },
1685 { 1, 9, 8, 2, 0x00 }
1688 *iret = 1; /* error */
1690 for (i = 0; i < 13; i++) {
1691 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1692 for (j = 2; j > 0; j--) {
1693 ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1694 sdramtype, bw);
1695 if (!i2ret)
1696 continue;
1698 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1699 sdramtype);
1700 if (i2ret) {
1701 *iret = 0; /* ram size found */
1702 return ret;
1707 return ret;
1710 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1711 int clrall, int drwfr)
1713 int ret = 0;
1714 u32 address;
1715 int i, length, modex, modey, bpp;
1717 modex = 640; modey = 480; bpp = 2;
1719 address = sisusb->vrambase; /* Clear video ram */
1721 if (clrall)
1722 length = sisusb->vramsize;
1723 else
1724 length = modex * bpp * modey;
1726 ret = sisusb_clear_vram(sisusb, address, length);
1728 if (!ret && drwfr) {
1729 for (i = 0; i < modex; i++) {
1730 address = sisusb->vrambase + (i * bpp);
1731 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1732 address, 0xf100);
1733 address += (modex * (modey-1) * bpp);
1734 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1735 address, 0xf100);
1737 for (i = 0; i < modey; i++) {
1738 address = sisusb->vrambase + ((i * modex) * bpp);
1739 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1740 address, 0xf100);
1741 address += ((modex - 1) * bpp);
1742 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1743 address, 0xf100);
1747 return ret;
1750 static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1751 int touchengines)
1753 int ret = 0, i, j, modex, bpp, du;
1754 u8 sr31, cr63, tmp8;
1755 static const char attrdata[] = {
1756 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1757 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1758 0x01, 0x00, 0x00, 0x00
1760 static const char crtcrdata[] = {
1761 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1762 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1763 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1764 0xff
1766 static const char grcdata[] = {
1767 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1768 0xff
1770 static const char crtcdata[] = {
1771 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1772 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1773 0x00
1776 modex = 640; bpp = 2;
1778 GETIREG(SISSR, 0x31, &sr31);
1779 GETIREG(SISCR, 0x63, &cr63);
1780 SETIREGOR(SISSR, 0x01, 0x20);
1781 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1782 SETIREGOR(SISCR, 0x17, 0x80);
1783 SETIREGOR(SISSR, 0x1f, 0x04);
1784 SETIREGAND(SISSR, 0x07, 0xfb);
1785 SETIREG(SISSR, 0x00, 0x03); /* seq */
1786 SETIREG(SISSR, 0x01, 0x21);
1787 SETIREG(SISSR, 0x02, 0x0f);
1788 SETIREG(SISSR, 0x03, 0x00);
1789 SETIREG(SISSR, 0x04, 0x0e);
1790 SETREG(SISMISCW, 0x23); /* misc */
1791 for (i = 0; i <= 0x18; i++) { /* crtc */
1792 SETIREG(SISCR, i, crtcrdata[i]);
1794 for (i = 0; i <= 0x13; i++) { /* att */
1795 GETREG(SISINPSTAT, &tmp8);
1796 SETREG(SISAR, i);
1797 SETREG(SISAR, attrdata[i]);
1799 GETREG(SISINPSTAT, &tmp8);
1800 SETREG(SISAR, 0x14);
1801 SETREG(SISAR, 0x00);
1802 GETREG(SISINPSTAT, &tmp8);
1803 SETREG(SISAR, 0x20);
1804 GETREG(SISINPSTAT, &tmp8);
1805 for (i = 0; i <= 0x08; i++) { /* grc */
1806 SETIREG(SISGR, i, grcdata[i]);
1808 SETIREGAND(SISGR, 0x05, 0xbf);
1809 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1810 SETIREG(SISSR, i, 0x00);
1812 SETIREGAND(SISSR, 0x37, 0xfe);
1813 SETREG(SISMISCW, 0xef); /* sync */
1814 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1815 for (j = 0x00, i = 0; i <= 7; i++, j++)
1816 SETIREG(SISCR, j, crtcdata[i]);
1818 for (j = 0x10; i <= 10; i++, j++)
1819 SETIREG(SISCR, j, crtcdata[i]);
1821 for (j = 0x15; i <= 12; i++, j++)
1822 SETIREG(SISCR, j, crtcdata[i]);
1824 for (j = 0x0A; i <= 15; i++, j++)
1825 SETIREG(SISSR, j, crtcdata[i]);
1827 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1828 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1829 SETIREG(SISCR, 0x14, 0x4f);
1830 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1831 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1832 SETIREG(SISCR, 0x13, (du & 0xff));
1833 du <<= 5;
1834 tmp8 = du >> 8;
1835 SETIREG(SISSR, 0x10, tmp8);
1836 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1837 SETIREG(SISSR, 0x2b, 0x1b);
1838 SETIREG(SISSR, 0x2c, 0xe1);
1839 SETIREG(SISSR, 0x2d, 0x01);
1840 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1841 SETIREG(SISSR, 0x08, 0xae);
1842 SETIREGAND(SISSR, 0x09, 0xf0);
1843 SETIREG(SISSR, 0x08, 0x34);
1844 SETIREGOR(SISSR, 0x3d, 0x01);
1845 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1846 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1847 SETIREG(SISCR, 0x19, 0x00);
1848 SETIREGAND(SISCR, 0x1a, 0xfc);
1849 SETIREGAND(SISSR, 0x0f, 0xb7);
1850 SETIREGAND(SISSR, 0x31, 0xfb);
1851 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1852 SETIREGAND(SISSR, 0x32, 0xf3);
1853 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1854 SETIREG(SISCR, 0x52, 0x6c);
1856 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1857 SETIREG(SISCR, 0x0c, 0x00);
1858 SETIREG(SISSR, 0x0d, 0x00);
1859 SETIREGAND(SISSR, 0x37, 0xfe);
1861 SETIREG(SISCR, 0x32, 0x20);
1862 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1863 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1864 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1866 if (touchengines) {
1867 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1868 SETIREGOR(SISSR, 0x1e, 0x5a);
1870 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1871 SETIREG(SISSR, 0x27, 0x1f);
1872 SETIREG(SISSR, 0x26, 0x00);
1875 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1877 return ret;
1880 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1882 int ret = 0, i, j, bw, chab, iret, retry = 3;
1883 u8 tmp8, ramtype;
1884 u32 tmp32;
1885 static const char mclktable[] = {
1886 0x3b, 0x22, 0x01, 143,
1887 0x3b, 0x22, 0x01, 143,
1888 0x3b, 0x22, 0x01, 143,
1889 0x3b, 0x22, 0x01, 143
1891 static const char eclktable[] = {
1892 0x3b, 0x22, 0x01, 143,
1893 0x3b, 0x22, 0x01, 143,
1894 0x3b, 0x22, 0x01, 143,
1895 0x3b, 0x22, 0x01, 143
1897 static const char ramtypetable1[] = {
1898 0x00, 0x04, 0x60, 0x60,
1899 0x0f, 0x0f, 0x1f, 0x1f,
1900 0xba, 0xba, 0xba, 0xba,
1901 0xa9, 0xa9, 0xac, 0xac,
1902 0xa0, 0xa0, 0xa0, 0xa8,
1903 0x00, 0x00, 0x02, 0x02,
1904 0x30, 0x30, 0x40, 0x40
1906 static const char ramtypetable2[] = {
1907 0x77, 0x77, 0x44, 0x44,
1908 0x77, 0x77, 0x44, 0x44,
1909 0x00, 0x00, 0x00, 0x00,
1910 0x5b, 0x5b, 0xab, 0xab,
1911 0x00, 0x00, 0xf0, 0xf8
1914 while (retry--) {
1916 /* Enable VGA */
1917 ret = GETREG(SISVGAEN, &tmp8);
1918 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1920 /* Enable GPU access to VRAM */
1921 ret |= GETREG(SISMISCR, &tmp8);
1922 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1924 if (ret)
1925 continue;
1927 /* Reset registers */
1928 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1929 ret |= SETIREG(SISSR, 0x05, 0x86);
1930 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1932 ret |= SETREG(SISMISCW, 0x67);
1934 for (i = 0x06; i <= 0x1f; i++)
1935 ret |= SETIREG(SISSR, i, 0x00);
1937 for (i = 0x21; i <= 0x27; i++)
1938 ret |= SETIREG(SISSR, i, 0x00);
1940 for (i = 0x31; i <= 0x3d; i++)
1941 ret |= SETIREG(SISSR, i, 0x00);
1943 for (i = 0x12; i <= 0x1b; i++)
1944 ret |= SETIREG(SISSR, i, 0x00);
1946 for (i = 0x79; i <= 0x7c; i++)
1947 ret |= SETIREG(SISCR, i, 0x00);
1949 if (ret)
1950 continue;
1952 ret |= SETIREG(SISCR, 0x63, 0x80);
1954 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1955 ramtype &= 0x03;
1957 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1958 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1959 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1961 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1962 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1963 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1965 ret |= SETIREG(SISSR, 0x07, 0x18);
1966 ret |= SETIREG(SISSR, 0x11, 0x0f);
1968 if (ret)
1969 continue;
1971 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1972 ret |= SETIREG(SISSR, i,
1973 ramtypetable1[(j*4) + ramtype]);
1975 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1976 ret |= SETIREG(SISCR, i,
1977 ramtypetable2[(j*4) + ramtype]);
1980 ret |= SETIREG(SISCR, 0x49, 0xaa);
1982 ret |= SETIREG(SISSR, 0x1f, 0x00);
1983 ret |= SETIREG(SISSR, 0x20, 0xa0);
1984 ret |= SETIREG(SISSR, 0x23, 0xf6);
1985 ret |= SETIREG(SISSR, 0x24, 0x0d);
1986 ret |= SETIREG(SISSR, 0x25, 0x33);
1988 ret |= SETIREG(SISSR, 0x11, 0x0f);
1990 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1992 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
1994 if (ret)
1995 continue;
1997 ret |= SETIREG(SISPART1, 0x00, 0x00);
1999 ret |= GETIREG(SISSR, 0x13, &tmp8);
2000 tmp8 >>= 4;
2002 ret |= SETIREG(SISPART1, 0x02, 0x00);
2003 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2005 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2006 tmp32 &= 0x00f00000;
2007 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2008 ret |= SETIREG(SISSR, 0x25, tmp8);
2009 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2010 ret |= SETIREG(SISCR, 0x49, tmp8);
2012 ret |= SETIREG(SISSR, 0x27, 0x1f);
2013 ret |= SETIREG(SISSR, 0x31, 0x00);
2014 ret |= SETIREG(SISSR, 0x32, 0x11);
2015 ret |= SETIREG(SISSR, 0x33, 0x00);
2017 if (ret)
2018 continue;
2020 ret |= SETIREG(SISCR, 0x83, 0x00);
2022 ret |= sisusb_set_default_mode(sisusb, 0);
2024 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2025 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2026 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2028 ret |= sisusb_triggersr16(sisusb, ramtype);
2030 /* Disable refresh */
2031 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2032 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2034 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2035 ret |= sisusb_verify_mclk(sisusb);
2037 if (ramtype <= 1) {
2038 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2039 if (iret) {
2040 dev_err(&sisusb->sisusb_dev->dev,
2041 "RAM size detection failed, assuming 8MB video RAM\n");
2042 ret |= SETIREG(SISSR, 0x14, 0x31);
2043 /* TODO */
2045 } else {
2046 dev_err(&sisusb->sisusb_dev->dev,
2047 "DDR RAM device found, assuming 8MB video RAM\n");
2048 ret |= SETIREG(SISSR, 0x14, 0x31);
2049 /* *** TODO *** */
2052 /* Enable refresh */
2053 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2054 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2055 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2057 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2059 ret |= SETIREG(SISSR, 0x22, 0xfb);
2060 ret |= SETIREG(SISSR, 0x21, 0xa5);
2062 if (ret == 0)
2063 break;
2066 return ret;
2069 #undef SETREG
2070 #undef GETREG
2071 #undef SETIREG
2072 #undef GETIREG
2073 #undef SETIREGOR
2074 #undef SETIREGAND
2075 #undef SETIREGANDOR
2076 #undef READL
2077 #undef WRITEL
2079 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2081 u8 tmp8, tmp82, ramtype;
2082 int bw = 0;
2083 char *ramtypetext1 = NULL;
2084 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2085 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2086 static const int busSDR[4] = {64, 64, 128, 128};
2087 static const int busDDR[4] = {32, 32, 64, 64};
2088 static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2090 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2091 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2092 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2093 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2094 ramtype &= 0x03;
2095 switch ((tmp8 >> 2) & 0x03) {
2096 case 0:
2097 ramtypetext1 = "1 ch/1 r";
2098 if (tmp82 & 0x10)
2099 bw = 32;
2100 else
2101 bw = busSDR[(tmp8 & 0x03)];
2103 break;
2104 case 1:
2105 ramtypetext1 = "1 ch/2 r";
2106 sisusb->vramsize <<= 1;
2107 bw = busSDR[(tmp8 & 0x03)];
2108 break;
2109 case 2:
2110 ramtypetext1 = "asymmetric";
2111 sisusb->vramsize += sisusb->vramsize/2;
2112 bw = busDDRA[(tmp8 & 0x03)];
2113 break;
2114 case 3:
2115 ramtypetext1 = "2 channel";
2116 sisusb->vramsize <<= 1;
2117 bw = busDDR[(tmp8 & 0x03)];
2118 break;
2121 dev_info(&sisusb->sisusb_dev->dev,
2122 "%dMB %s %cDR S%cRAM, bus width %d\n",
2123 sisusb->vramsize >> 20, ramtypetext1,
2124 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2127 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2129 struct sisusb_packet packet;
2130 int ret;
2131 u32 tmp32;
2133 /* Do some magic */
2134 packet.header = 0x001f;
2135 packet.address = 0x00000324;
2136 packet.data = 0x00000004;
2137 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2139 packet.header = 0x001f;
2140 packet.address = 0x00000364;
2141 packet.data = 0x00000004;
2142 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2144 packet.header = 0x001f;
2145 packet.address = 0x00000384;
2146 packet.data = 0x00000004;
2147 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2149 packet.header = 0x001f;
2150 packet.address = 0x00000100;
2151 packet.data = 0x00000700;
2152 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2154 packet.header = 0x000f;
2155 packet.address = 0x00000004;
2156 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2157 packet.data |= 0x17;
2158 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2160 /* Init BAR 0 (VRAM) */
2161 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2162 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2163 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2164 tmp32 &= 0x0f;
2165 tmp32 |= SISUSB_PCI_MEMBASE;
2166 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2168 /* Init BAR 1 (MMIO) */
2169 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2170 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2171 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2172 tmp32 &= 0x0f;
2173 tmp32 |= SISUSB_PCI_MMIOBASE;
2174 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2176 /* Init BAR 2 (i/o ports) */
2177 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2178 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2179 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2180 tmp32 &= 0x0f;
2181 tmp32 |= SISUSB_PCI_IOPORTBASE;
2182 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2184 /* Enable memory and i/o access */
2185 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2186 tmp32 |= 0x3;
2187 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2189 if (ret == 0) {
2190 /* Some further magic */
2191 packet.header = 0x001f;
2192 packet.address = 0x00000050;
2193 packet.data = 0x000000ff;
2194 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2197 return ret;
2200 /* Initialize the graphics device (return 0 on success)
2201 * This initializes the net2280 as well as the PCI registers
2202 * of the graphics board.
2205 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2207 int ret = 0, test = 0;
2208 u32 tmp32;
2210 if (sisusb->devinit == 1) {
2211 /* Read PCI BARs and see if they have been set up */
2212 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2213 if (ret)
2214 return ret;
2216 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2217 test++;
2219 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2220 if (ret)
2221 return ret;
2223 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2224 test++;
2226 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2227 if (ret)
2228 return ret;
2230 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2231 test++;
2234 /* No? So reset the device */
2235 if ((sisusb->devinit == 0) || (test != 3)) {
2237 ret |= sisusb_do_init_gfxdevice(sisusb);
2239 if (ret == 0)
2240 sisusb->devinit = 1;
2244 if (sisusb->devinit) {
2245 /* Initialize the graphics core */
2246 if (sisusb_init_gfxcore(sisusb) == 0) {
2247 sisusb->gfxinit = 1;
2248 sisusb_get_ramconfig(sisusb);
2249 ret |= sisusb_set_default_mode(sisusb, 1);
2250 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2254 return ret;
2258 #ifdef INCL_SISUSB_CON
2260 /* Set up default text mode:
2261 * - Set text mode (0x03)
2262 * - Upload default font
2263 * - Upload user font (if available)
2266 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2268 int ret = 0, slot = sisusb->font_slot, i;
2269 const struct font_desc *myfont;
2270 u8 *tempbuf;
2271 u16 *tempbufb;
2272 static const char bootstring[] =
2273 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2274 static const char bootlogo[] = "(o_ //\\ V_/_";
2276 /* sisusb->lock is down */
2278 if (!sisusb->SiS_Pr)
2279 return 1;
2281 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2282 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2284 /* Set mode 0x03 */
2285 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2287 myfont = find_font("VGA8x16");
2288 if (!myfont)
2289 return 1;
2291 tempbuf = vmalloc(8192);
2292 if (!tempbuf)
2293 return 1;
2295 for (i = 0; i < 256; i++)
2296 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2298 /* Upload default font */
2299 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2300 0, 1, NULL, 16, 0);
2302 vfree(tempbuf);
2304 /* Upload user font (and reset current slot) */
2305 if (sisusb->font_backup) {
2306 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2307 8192, sisusb->font_backup_512, 1, NULL,
2308 sisusb->font_backup_height, 0);
2309 if (slot != 2)
2310 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2311 NULL, 16, 0);
2314 if (init && !sisusb->scrbuf) {
2316 tempbuf = vmalloc(8192);
2317 if (tempbuf) {
2319 i = 4096;
2320 tempbufb = (u16 *)tempbuf;
2321 while (i--)
2322 *(tempbufb++) = 0x0720;
2324 i = 0;
2325 tempbufb = (u16 *)tempbuf;
2326 while (bootlogo[i]) {
2327 *(tempbufb++) = 0x0700 | bootlogo[i++];
2328 if (!(i % 4))
2329 tempbufb += 76;
2332 i = 0;
2333 tempbufb = (u16 *)tempbuf + 6;
2334 while (bootstring[i])
2335 *(tempbufb++) = 0x0700 | bootstring[i++];
2337 ret |= sisusb_copy_memory(sisusb, tempbuf,
2338 sisusb->vrambase, 8192);
2340 vfree(tempbuf);
2344 } else if (sisusb->scrbuf) {
2345 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2346 sisusb->vrambase, sisusb->scrbuf_size);
2349 if (sisusb->sisusb_cursor_size_from >= 0 &&
2350 sisusb->sisusb_cursor_size_to >= 0) {
2351 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2352 sisusb->sisusb_cursor_size_from);
2353 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2354 sisusb->sisusb_cursor_size_to);
2355 } else {
2356 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2357 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2358 sisusb->sisusb_cursor_size_to = -1;
2361 slot = sisusb->sisusb_cursor_loc;
2362 if (slot < 0)
2363 slot = 0;
2365 sisusb->sisusb_cursor_loc = -1;
2366 sisusb->bad_cursor_pos = 1;
2368 sisusb_set_cursor(sisusb, slot);
2370 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2371 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2373 sisusb->textmodedestroyed = 0;
2375 /* sisusb->lock is down */
2377 return ret;
2380 #endif
2382 /* fops */
2384 static int sisusb_open(struct inode *inode, struct file *file)
2386 struct sisusb_usb_data *sisusb;
2387 struct usb_interface *interface;
2388 int subminor = iminor(inode);
2390 interface = usb_find_interface(&sisusb_driver, subminor);
2391 if (!interface)
2392 return -ENODEV;
2394 sisusb = usb_get_intfdata(interface);
2395 if (!sisusb)
2396 return -ENODEV;
2398 mutex_lock(&sisusb->lock);
2400 if (!sisusb->present || !sisusb->ready) {
2401 mutex_unlock(&sisusb->lock);
2402 return -ENODEV;
2405 if (sisusb->isopen) {
2406 mutex_unlock(&sisusb->lock);
2407 return -EBUSY;
2410 if (!sisusb->devinit) {
2411 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2412 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2413 if (sisusb_init_gfxdevice(sisusb, 0)) {
2414 mutex_unlock(&sisusb->lock);
2415 dev_err(&sisusb->sisusb_dev->dev,
2416 "Failed to initialize device\n");
2417 return -EIO;
2419 } else {
2420 mutex_unlock(&sisusb->lock);
2421 dev_err(&sisusb->sisusb_dev->dev,
2422 "Device not attached to USB 2.0 hub\n");
2423 return -EIO;
2427 /* Increment usage count for our sisusb */
2428 kref_get(&sisusb->kref);
2430 sisusb->isopen = 1;
2432 file->private_data = sisusb;
2434 mutex_unlock(&sisusb->lock);
2436 return 0;
2439 void sisusb_delete(struct kref *kref)
2441 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2443 if (!sisusb)
2444 return;
2446 usb_put_dev(sisusb->sisusb_dev);
2448 sisusb->sisusb_dev = NULL;
2449 sisusb_free_buffers(sisusb);
2450 sisusb_free_urbs(sisusb);
2451 #ifdef INCL_SISUSB_CON
2452 kfree(sisusb->SiS_Pr);
2453 #endif
2454 kfree(sisusb);
2457 static int sisusb_release(struct inode *inode, struct file *file)
2459 struct sisusb_usb_data *sisusb;
2461 sisusb = file->private_data;
2462 if (!sisusb)
2463 return -ENODEV;
2465 mutex_lock(&sisusb->lock);
2467 if (sisusb->present) {
2468 /* Wait for all URBs to finish if device still present */
2469 if (!sisusb_wait_all_out_complete(sisusb))
2470 sisusb_kill_all_busy(sisusb);
2473 sisusb->isopen = 0;
2474 file->private_data = NULL;
2476 mutex_unlock(&sisusb->lock);
2478 /* decrement the usage count on our device */
2479 kref_put(&sisusb->kref, sisusb_delete);
2481 return 0;
2484 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2485 size_t count, loff_t *ppos)
2487 struct sisusb_usb_data *sisusb;
2488 ssize_t bytes_read = 0;
2489 int errno = 0;
2490 u8 buf8;
2491 u16 buf16;
2492 u32 buf32, address;
2494 sisusb = file->private_data;
2495 if (!sisusb)
2496 return -ENODEV;
2498 mutex_lock(&sisusb->lock);
2500 /* Sanity check */
2501 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2502 mutex_unlock(&sisusb->lock);
2503 return -ENODEV;
2506 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2507 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2509 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2510 SISUSB_PCI_IOPORTBASE;
2512 /* Read i/o ports
2513 * Byte, word and long(32) can be read. As this
2514 * emulates inX instructions, the data returned is
2515 * in machine-endianness.
2517 switch (count) {
2518 case 1:
2519 if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2520 address, &buf8))
2521 errno = -EIO;
2522 else if (put_user(buf8, (u8 __user *)buffer))
2523 errno = -EFAULT;
2524 else
2525 bytes_read = 1;
2527 break;
2529 case 2:
2530 if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2531 address, &buf16))
2532 errno = -EIO;
2533 else if (put_user(buf16, (u16 __user *)buffer))
2534 errno = -EFAULT;
2535 else
2536 bytes_read = 2;
2538 break;
2540 case 4:
2541 if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2542 address, &buf32))
2543 errno = -EIO;
2544 else if (put_user(buf32, (u32 __user *)buffer))
2545 errno = -EFAULT;
2546 else
2547 bytes_read = 4;
2549 break;
2551 default:
2552 errno = -EIO;
2556 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2557 SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2559 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2560 SISUSB_PCI_MEMBASE;
2562 /* Read video ram
2563 * Remember: Data delivered is never endian-corrected
2565 errno = sisusb_read_mem_bulk(sisusb, address,
2566 NULL, count, buffer, &bytes_read);
2568 if (bytes_read)
2569 errno = bytes_read;
2571 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2572 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2573 SISUSB_PCI_MMIOSIZE) {
2575 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2576 SISUSB_PCI_MMIOBASE;
2578 /* Read MMIO
2579 * Remember: Data delivered is never endian-corrected
2581 errno = sisusb_read_mem_bulk(sisusb, address,
2582 NULL, count, buffer, &bytes_read);
2584 if (bytes_read)
2585 errno = bytes_read;
2587 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2588 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2590 if (count != 4) {
2591 mutex_unlock(&sisusb->lock);
2592 return -EINVAL;
2595 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2597 /* Read PCI config register
2598 * Return value delivered in machine endianness.
2600 if (sisusb_read_pci_config(sisusb, address, &buf32))
2601 errno = -EIO;
2602 else if (put_user(buf32, (u32 __user *)buffer))
2603 errno = -EFAULT;
2604 else
2605 bytes_read = 4;
2607 } else {
2609 errno = -EBADFD;
2613 (*ppos) += bytes_read;
2615 mutex_unlock(&sisusb->lock);
2617 return errno ? errno : bytes_read;
2620 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2621 size_t count, loff_t *ppos)
2623 struct sisusb_usb_data *sisusb;
2624 int errno = 0;
2625 ssize_t bytes_written = 0;
2626 u8 buf8;
2627 u16 buf16;
2628 u32 buf32, address;
2630 sisusb = file->private_data;
2631 if (!sisusb)
2632 return -ENODEV;
2634 mutex_lock(&sisusb->lock);
2636 /* Sanity check */
2637 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2638 mutex_unlock(&sisusb->lock);
2639 return -ENODEV;
2642 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2643 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2645 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2646 SISUSB_PCI_IOPORTBASE;
2648 /* Write i/o ports
2649 * Byte, word and long(32) can be written. As this
2650 * emulates outX instructions, the data is expected
2651 * in machine-endianness.
2653 switch (count) {
2654 case 1:
2655 if (get_user(buf8, (u8 __user *)buffer))
2656 errno = -EFAULT;
2657 else if (sisusb_write_memio_byte(sisusb,
2658 SISUSB_TYPE_IO, address, buf8))
2659 errno = -EIO;
2660 else
2661 bytes_written = 1;
2663 break;
2665 case 2:
2666 if (get_user(buf16, (u16 __user *)buffer))
2667 errno = -EFAULT;
2668 else if (sisusb_write_memio_word(sisusb,
2669 SISUSB_TYPE_IO, address, buf16))
2670 errno = -EIO;
2671 else
2672 bytes_written = 2;
2674 break;
2676 case 4:
2677 if (get_user(buf32, (u32 __user *)buffer))
2678 errno = -EFAULT;
2679 else if (sisusb_write_memio_long(sisusb,
2680 SISUSB_TYPE_IO, address, buf32))
2681 errno = -EIO;
2682 else
2683 bytes_written = 4;
2685 break;
2687 default:
2688 errno = -EIO;
2691 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2692 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE +
2693 sisusb->vramsize) {
2695 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2696 SISUSB_PCI_MEMBASE;
2698 /* Write video ram.
2699 * Buffer is copied 1:1, therefore, on big-endian
2700 * machines, the data must be swapped by userland
2701 * in advance (if applicable; no swapping in 8bpp
2702 * mode or if YUV data is being transferred).
2704 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2705 count, buffer, 0, &bytes_written);
2707 if (bytes_written)
2708 errno = bytes_written;
2710 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2711 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2712 SISUSB_PCI_MMIOSIZE) {
2714 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2715 SISUSB_PCI_MMIOBASE;
2717 /* Write MMIO.
2718 * Buffer is copied 1:1, therefore, on big-endian
2719 * machines, the data must be swapped by userland
2720 * in advance.
2722 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2723 count, buffer, 0, &bytes_written);
2725 if (bytes_written)
2726 errno = bytes_written;
2728 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2729 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2730 SISUSB_PCI_PCONFSIZE) {
2732 if (count != 4) {
2733 mutex_unlock(&sisusb->lock);
2734 return -EINVAL;
2737 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2739 /* Write PCI config register.
2740 * Given value expected in machine endianness.
2742 if (get_user(buf32, (u32 __user *)buffer))
2743 errno = -EFAULT;
2744 else if (sisusb_write_pci_config(sisusb, address, buf32))
2745 errno = -EIO;
2746 else
2747 bytes_written = 4;
2750 } else {
2752 /* Error */
2753 errno = -EBADFD;
2757 (*ppos) += bytes_written;
2759 mutex_unlock(&sisusb->lock);
2761 return errno ? errno : bytes_written;
2764 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2766 struct sisusb_usb_data *sisusb;
2767 loff_t ret;
2769 sisusb = file->private_data;
2770 if (!sisusb)
2771 return -ENODEV;
2773 mutex_lock(&sisusb->lock);
2775 /* Sanity check */
2776 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2777 mutex_unlock(&sisusb->lock);
2778 return -ENODEV;
2781 ret = no_seek_end_llseek(file, offset, orig);
2783 mutex_unlock(&sisusb->lock);
2784 return ret;
2787 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2788 struct sisusb_command *y, unsigned long arg)
2790 int retval, port, length;
2791 u32 address;
2793 /* All our commands require the device
2794 * to be initialized.
2796 if (!sisusb->devinit)
2797 return -ENODEV;
2799 port = y->data3 -
2800 SISUSB_PCI_PSEUDO_IOPORTBASE +
2801 SISUSB_PCI_IOPORTBASE;
2803 switch (y->operation) {
2804 case SUCMD_GET:
2805 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2806 if (!retval) {
2807 if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2808 retval = -EFAULT;
2810 break;
2812 case SUCMD_SET:
2813 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2814 break;
2816 case SUCMD_SETOR:
2817 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2818 break;
2820 case SUCMD_SETAND:
2821 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2822 break;
2824 case SUCMD_SETANDOR:
2825 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2826 y->data1, y->data2);
2827 break;
2829 case SUCMD_SETMASK:
2830 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2831 y->data1, y->data2);
2832 break;
2834 case SUCMD_CLRSCR:
2835 /* Gfx core must be initialized */
2836 if (!sisusb->gfxinit)
2837 return -ENODEV;
2839 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2840 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2841 SISUSB_PCI_MEMBASE;
2842 retval = sisusb_clear_vram(sisusb, address, length);
2843 break;
2845 case SUCMD_HANDLETEXTMODE:
2846 retval = 0;
2847 #ifdef INCL_SISUSB_CON
2848 /* Gfx core must be initialized, SiS_Pr must exist */
2849 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2850 return -ENODEV;
2852 switch (y->data0) {
2853 case 0:
2854 retval = sisusb_reset_text_mode(sisusb, 0);
2855 break;
2856 case 1:
2857 sisusb->textmodedestroyed = 1;
2858 break;
2860 #endif
2861 break;
2863 #ifdef INCL_SISUSB_CON
2864 case SUCMD_SETMODE:
2865 /* Gfx core must be initialized, SiS_Pr must exist */
2866 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2867 return -ENODEV;
2869 retval = 0;
2871 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2872 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2874 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2875 retval = -EINVAL;
2877 break;
2879 case SUCMD_SETVESAMODE:
2880 /* Gfx core must be initialized, SiS_Pr must exist */
2881 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2882 return -ENODEV;
2884 retval = 0;
2886 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2887 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2889 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2890 retval = -EINVAL;
2892 break;
2893 #endif
2895 default:
2896 retval = -EINVAL;
2899 if (retval > 0)
2900 retval = -EIO;
2902 return retval;
2905 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2907 struct sisusb_usb_data *sisusb;
2908 struct sisusb_info x;
2909 struct sisusb_command y;
2910 long retval = 0;
2911 u32 __user *argp = (u32 __user *)arg;
2913 sisusb = file->private_data;
2914 if (!sisusb)
2915 return -ENODEV;
2917 mutex_lock(&sisusb->lock);
2919 /* Sanity check */
2920 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2921 retval = -ENODEV;
2922 goto err_out;
2925 switch (cmd) {
2926 case SISUSB_GET_CONFIG_SIZE:
2928 if (put_user(sizeof(x), argp))
2929 retval = -EFAULT;
2931 break;
2933 case SISUSB_GET_CONFIG:
2935 x.sisusb_id = SISUSB_ID;
2936 x.sisusb_version = SISUSB_VERSION;
2937 x.sisusb_revision = SISUSB_REVISION;
2938 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2939 x.sisusb_gfxinit = sisusb->gfxinit;
2940 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2941 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2942 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2943 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2944 x.sisusb_vramsize = sisusb->vramsize;
2945 x.sisusb_minor = sisusb->minor;
2946 x.sisusb_fbdevactive = 0;
2947 #ifdef INCL_SISUSB_CON
2948 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
2949 #else
2950 x.sisusb_conactive = 0;
2951 #endif
2952 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2954 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2955 retval = -EFAULT;
2957 break;
2959 case SISUSB_COMMAND:
2961 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2962 retval = -EFAULT;
2963 else
2964 retval = sisusb_handle_command(sisusb, &y, arg);
2966 break;
2968 default:
2969 retval = -ENOTTY;
2970 break;
2973 err_out:
2974 mutex_unlock(&sisusb->lock);
2975 return retval;
2978 #ifdef SISUSB_NEW_CONFIG_COMPAT
2979 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2980 unsigned long arg)
2982 switch (cmd) {
2983 case SISUSB_GET_CONFIG_SIZE:
2984 case SISUSB_GET_CONFIG:
2985 case SISUSB_COMMAND:
2986 return sisusb_ioctl(f, cmd, arg);
2988 default:
2989 return -ENOIOCTLCMD;
2992 #endif
2994 static const struct file_operations usb_sisusb_fops = {
2995 .owner = THIS_MODULE,
2996 .open = sisusb_open,
2997 .release = sisusb_release,
2998 .read = sisusb_read,
2999 .write = sisusb_write,
3000 .llseek = sisusb_lseek,
3001 #ifdef SISUSB_NEW_CONFIG_COMPAT
3002 .compat_ioctl = sisusb_compat_ioctl,
3003 #endif
3004 .unlocked_ioctl = sisusb_ioctl
3007 static struct usb_class_driver usb_sisusb_class = {
3008 .name = "sisusbvga%d",
3009 .fops = &usb_sisusb_fops,
3010 .minor_base = SISUSB_MINOR
3013 static int sisusb_probe(struct usb_interface *intf,
3014 const struct usb_device_id *id)
3016 struct usb_device *dev = interface_to_usbdev(intf);
3017 struct sisusb_usb_data *sisusb;
3018 int retval = 0, i;
3020 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3021 dev->devnum);
3023 /* Allocate memory for our private */
3024 sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3025 if (!sisusb)
3026 return -ENOMEM;
3028 kref_init(&sisusb->kref);
3030 mutex_init(&(sisusb->lock));
3032 /* Register device */
3033 retval = usb_register_dev(intf, &usb_sisusb_class);
3034 if (retval) {
3035 dev_err(&sisusb->sisusb_dev->dev,
3036 "Failed to get a minor for device %d\n",
3037 dev->devnum);
3038 retval = -ENODEV;
3039 goto error_1;
3042 sisusb->sisusb_dev = dev;
3043 sisusb->minor = intf->minor;
3044 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3045 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3046 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3047 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3048 /* Everything else is zero */
3050 /* Allocate buffers */
3051 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3052 sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3053 if (!sisusb->ibuf) {
3054 retval = -ENOMEM;
3055 goto error_2;
3058 sisusb->numobufs = 0;
3059 sisusb->obufsize = SISUSB_OBUF_SIZE;
3060 for (i = 0; i < NUMOBUFS; i++) {
3061 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3062 if (!sisusb->obuf[i]) {
3063 if (i == 0) {
3064 retval = -ENOMEM;
3065 goto error_3;
3067 break;
3069 sisusb->numobufs++;
3072 /* Allocate URBs */
3073 sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3074 if (!sisusb->sisurbin) {
3075 retval = -ENOMEM;
3076 goto error_3;
3078 sisusb->completein = 1;
3080 for (i = 0; i < sisusb->numobufs; i++) {
3081 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3082 if (!sisusb->sisurbout[i]) {
3083 retval = -ENOMEM;
3084 goto error_4;
3086 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3087 sisusb->urbout_context[i].urbindex = i;
3088 sisusb->urbstatus[i] = 0;
3091 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3092 sisusb->numobufs);
3094 #ifdef INCL_SISUSB_CON
3095 /* Allocate our SiS_Pr */
3096 sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3097 if (!sisusb->SiS_Pr) {
3098 retval = -ENOMEM;
3099 goto error_4;
3101 #endif
3103 /* Do remaining init stuff */
3105 init_waitqueue_head(&sisusb->wait_q);
3107 usb_set_intfdata(intf, sisusb);
3109 usb_get_dev(sisusb->sisusb_dev);
3111 sisusb->present = 1;
3113 if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
3114 int initscreen = 1;
3115 #ifdef INCL_SISUSB_CON
3116 if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3117 sisusb_first_vc <= sisusb_last_vc &&
3118 sisusb_last_vc <= MAX_NR_CONSOLES)
3119 initscreen = 0;
3120 #endif
3121 if (sisusb_init_gfxdevice(sisusb, initscreen))
3122 dev_err(&sisusb->sisusb_dev->dev,
3123 "Failed to early initialize device\n");
3125 } else
3126 dev_info(&sisusb->sisusb_dev->dev,
3127 "Not attached to USB 2.0 hub, deferring init\n");
3129 sisusb->ready = 1;
3131 #ifdef SISUSBENDIANTEST
3132 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3133 sisusb_testreadwrite(sisusb);
3134 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3135 #endif
3137 #ifdef INCL_SISUSB_CON
3138 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3139 #endif
3141 return 0;
3143 error_4:
3144 sisusb_free_urbs(sisusb);
3145 error_3:
3146 sisusb_free_buffers(sisusb);
3147 error_2:
3148 usb_deregister_dev(intf, &usb_sisusb_class);
3149 error_1:
3150 kfree(sisusb);
3151 return retval;
3154 static void sisusb_disconnect(struct usb_interface *intf)
3156 struct sisusb_usb_data *sisusb;
3158 /* This should *not* happen */
3159 sisusb = usb_get_intfdata(intf);
3160 if (!sisusb)
3161 return;
3163 #ifdef INCL_SISUSB_CON
3164 sisusb_console_exit(sisusb);
3165 #endif
3167 usb_deregister_dev(intf, &usb_sisusb_class);
3169 mutex_lock(&sisusb->lock);
3171 /* Wait for all URBs to complete and kill them in case (MUST do) */
3172 if (!sisusb_wait_all_out_complete(sisusb))
3173 sisusb_kill_all_busy(sisusb);
3175 usb_set_intfdata(intf, NULL);
3177 sisusb->present = 0;
3178 sisusb->ready = 0;
3180 mutex_unlock(&sisusb->lock);
3182 /* decrement our usage count */
3183 kref_put(&sisusb->kref, sisusb_delete);
3186 static const struct usb_device_id sisusb_table[] = {
3187 { USB_DEVICE(0x0711, 0x0550) },
3188 { USB_DEVICE(0x0711, 0x0900) },
3189 { USB_DEVICE(0x0711, 0x0901) },
3190 { USB_DEVICE(0x0711, 0x0902) },
3191 { USB_DEVICE(0x0711, 0x0903) },
3192 { USB_DEVICE(0x0711, 0x0918) },
3193 { USB_DEVICE(0x0711, 0x0920) },
3194 { USB_DEVICE(0x0711, 0x0950) },
3195 { USB_DEVICE(0x0711, 0x5200) },
3196 { USB_DEVICE(0x182d, 0x021c) },
3197 { USB_DEVICE(0x182d, 0x0269) },
3201 MODULE_DEVICE_TABLE(usb, sisusb_table);
3203 static struct usb_driver sisusb_driver = {
3204 .name = "sisusb",
3205 .probe = sisusb_probe,
3206 .disconnect = sisusb_disconnect,
3207 .id_table = sisusb_table,
3210 static int __init usb_sisusb_init(void)
3213 #ifdef INCL_SISUSB_CON
3214 sisusb_init_concode();
3215 #endif
3217 return usb_register(&sisusb_driver);
3220 static void __exit usb_sisusb_exit(void)
3222 usb_deregister(&sisusb_driver);
3225 module_init(usb_sisusb_init);
3226 module_exit(usb_sisusb_exit);
3228 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3229 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3230 MODULE_LICENSE("GPL");